diff --git a/.cursor/rules/70-phone.mdc b/.cursor/rules/70-phone.mdc new file mode 100644 index 0000000..f2d3fca --- /dev/null +++ b/.cursor/rules/70-phone.mdc @@ -0,0 +1,18 @@ +--- +description: Phone layout for DETRO. Phones are the primary screen. +alwaysApply: true +--- + +# Phone + +Phones are the primary screen. A layout that only fits at 960px is unfinished. Laptop layout at 960px and above stays as it is. + +Check 320, 390, and 430 CSS pixels. The page does not scroll sideways. + +- One column. Touch targets stay at least 44px. Padding and type around them are tighter than on a laptop. +- The route strip keeps one colored line. Station names wrap underneath it and do not overlap. +- A station name stays on one line. A title wraps at the arrow between the two stations. +- A pair of actions may sit side by side. If a label needs three lines, stack that row. +- The header is the mark plus four tabs. It stays on screen, clears the safe area, and does not cover the first line of the page. +- On City, the map is visible without scrolling. The trip sheet is the part that scrolls. +- Do not add a banner, a tutorial, or extra chrome to fix spacing. diff --git a/src/index.css b/src/index.css index 296b333..e0d4940 100644 --- a/src/index.css +++ b/src/index.css @@ -189,7 +189,7 @@ summary:active { flex-direction: column; align-items: stretch; gap: 6px; - padding: 8px 12px; + padding: max(8px, env(safe-area-inset-top)) 12px 8px; background: #fff; border-bottom: 1px solid var(--line); } @@ -914,6 +914,17 @@ ul[role="listbox"] li { margin: 0; } overflow-wrap: break-word; } +.board-names { + display: none; + margin: 0.55rem 0 0; + padding: 0; + list-style: none; +} + +.place-name { + white-space: nowrap; +} + .trip-row { display: flex; flex-wrap: wrap; @@ -1971,6 +1982,129 @@ summary { } } +@media (max-width: 719px) { + .sheet { + gap: 12px; + padding: 12px; + } + + .pane, + .planner, + .map-intro, + .map-list, + .itinerary, + .ticket { + padding: 12px; + } + + .choices { + grid-template-columns: 1fr; + gap: 6px; + } + + .choices button { + min-height: 44px; + padding: 0.35rem 0.5rem; + font-size: 0.92rem; + } + + .choice-detail { + font-size: 0.78rem; + line-height: 1.25; + } + + .board { + padding: 0.7rem 0.75rem; + } + + .board-line { + min-width: 0; + align-items: center; + } + + .board-joint { + width: auto; + } + + .board-name { + display: none; + } + + .board-seg::before { + left: -9px; + right: -9px; + } + + .board-names { + display: flex; + flex-wrap: wrap; + gap: 0.15rem 0.35rem; + font-size: 0.78rem; + font-weight: 700; + line-height: 1.3; + } + + .board-names li:not(:last-child)::after { + content: " ·"; + font-weight: 600; + color: var(--muted); + } + + .itinerary h2, + .city-route-bar h2, + .map-route-title { + font-size: 1.15rem; + } + + .stats { + gap: 8px; + } + + .stats div { + padding: 10px; + } + + .stats dd, + .depart-clock { + font-size: 1.35rem; + } + + .city-route-bar { + padding: 0.75rem 0.75rem 0.15rem; + } + + .city-route-body { + gap: 10px; + padding: 0.55rem 0.75rem 1rem; + } + + .city-split { + grid-template-rows: minmax(14rem, 0.85fr) minmax(0, 1.15fr); + } + + .result .zoom-row { + display: grid; + grid-template-columns: 1fr 1fr; + } + + .result .zoom-row button { + white-space: normal; + min-height: 44px; + } +} + +@media (max-width: 359px) { + .mark-tag { + display: none; + } + + .tabbar a { + gap: 0.2rem; + padding: 0 4px; + font-size: 0.78rem; + } +} + @keyframes city-pane-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } diff --git a/src/ui/CityMap.tsx b/src/ui/CityMap.tsx index b5f08c2..0b66553 100644 --- a/src/ui/CityMap.tsx +++ b/src/ui/CityMap.tsx @@ -434,9 +434,9 @@ export function CityMap({

{shown ? ( <> - {shown.originName} + {shown.originName} - {shown.destinationName} + {shown.destinationName} ) : ( copy.loadingRoute diff --git a/src/ui/MapView.tsx b/src/ui/MapView.tsx index e504733..5e366ad 100644 --- a/src/ui/MapView.tsx +++ b/src/ui/MapView.tsx @@ -115,7 +115,9 @@ export function MapView({ {journey && journey.legs.length > 0 ? (

- {journey.originName} → {journey.destinationName} + {journey.originName} + + {journey.destinationName}

diff --git a/src/ui/PlanView.tsx b/src/ui/PlanView.tsx index e94efda..637747f 100644 --- a/src/ui/PlanView.tsx +++ b/src/ui/PlanView.tsx @@ -477,10 +477,10 @@ export function JourneyCard({

{copy.from} - {journey.originName} + {journey.originName} {copy.to} - {journey.destinationName} + {journey.destinationName}

diff --git a/src/ui/RouteBoard.tsx b/src/ui/RouteBoard.tsx index c88cae8..e228c16 100644 --- a/src/ui/RouteBoard.tsx +++ b/src/ui/RouteBoard.tsx @@ -40,6 +40,11 @@ export function RouteBoard({
))}
+
    + {names.map((name, index) => ( +
  1. {name}
  2. + ))} +
) }