/* Radar toggle. Reads as off until it is on, because the byte cost is opt-in and the
   button is the only place a rider learns that. */
.mrp-radar-ctrl button{font:700 10px/1 var(--gothic,system-ui);letter-spacing:.08em;
  width:29px;height:29px;color:var(--steel);background:transparent;border:0;cursor:pointer}
.mrp-radar-ctrl button.is-on{color:var(--white);background:var(--orange)}
.mrp-radar-ctrl button[disabled]{opacity:.45;cursor:progress}

/* =============================================================================
   HERITAGE — trip planner
   Same idiom as the rest: black / white / one signal orange, square corners,
   heavy uppercase gothic. Builder column on the left, map on the right, the
   same split the Discover page already teaches.
   ========================================================================== */
.pln{display:grid;grid-template-columns:390px minmax(0,1fr);
  height:calc(100vh - 106px);min-height:520px}
@media(max-width:900px){
  .pln{grid-template-columns:1fr;height:auto}
  .pln-map{height:52vh;min-height:320px;order:-1}
}

.pln-side{border-right:1px solid var(--rule);display:flex;flex-direction:column;
  min-width:0;min-height:0;overflow:auto;background:var(--surface)}
.pln-map{position:relative;min-width:0;min-height:0;background:var(--chrome)}
.pln-map #pmap{position:absolute;inset:0}
.pmap-readiness{position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;
  gap:12px;padding:24px 24px calc(38dvh + 24px);box-sizing:border-box;
  background:linear-gradient(145deg,var(--chrome),var(--panel));color:var(--ink);text-align:left}
.pmap-readiness[hidden]{display:none}
.pmap-readiness-spin{width:24px;height:24px;flex:0 0 24px;border:3px solid var(--rule);border-top-color:var(--orange);
  border-radius:50%;animation:pmap-ready-spin .8s linear infinite}
.pmap-readiness-copy{display:flex;flex-direction:column;gap:2px;max-width:240px}
.pmap-readiness-copy b{font-size:16px}.pmap-readiness-copy span{color:var(--steel);font-size:13px;line-height:1.35}
.pmap-readiness button{min-height:44px;padding:0 16px;border:0;border-radius:12px;background:var(--orange);color:#181b1a;font-weight:750}
.pmap-readiness[data-state="failed"] .pmap-readiness-spin{display:none}
@keyframes pmap-ready-spin{to{transform:rotate(360deg)}}

.pbar{padding:15px 17px;border-bottom:1px solid var(--rule);background:var(--panel)}
.pbar h1{margin:0 0 3px;font-size:16px;font-weight:900;letter-spacing:-.01em;
  text-transform:uppercase;color:var(--text-strong)}
.pbar p{margin:0;font-size:11.5px;line-height:1.45;color:var(--steel)}

.psearch-wrap{position:relative;padding:14px 17px 0}
.psearch-wrap input{width:100%;border:1px solid var(--ink);padding:11px 12px;
  font:inherit;font-size:14px;background:var(--surface);color:var(--ink)}
.psearch-wrap input::placeholder{color:var(--smoke)}
#presults{position:absolute;left:17px;right:17px;top:100%;z-index:9;background:var(--surface);overflow-y:auto;
  border:1px solid var(--ink);border-top:0;max-height:310px;overflow:auto;
  box-shadow:0 12px 28px rgba(0,0,0,.18)}
.pres{display:block;width:100%;text-align:left;border:0;border-bottom:1px solid var(--rule);
  background:var(--surface);padding:10px 12px;cursor:pointer;font:inherit}
.pres:hover{background:var(--panel)}
.pres:last-child{border-bottom:0}
.pres b{display:block;font-size:13.5px;font-weight:700;letter-spacing:-.005em;line-height:1.25}
.pres span{display:block;font-size:11px;color:var(--steel);margin-top:2px}
.pres--place{background:var(--panel)}

.plist{list-style:none;margin:0;padding:14px 17px 0;display:flex;flex-direction:column;gap:8px}
.pempty{margin:16px 17px;font-size:12.5px;line-height:1.55;color:var(--steel)}
/* Screen 04 restyle (2026-10-08): numbered orange pins, matching mock-013-014.png.
   The mock also draws a connecting rail between pins — skipped here, deliberately:
   a row's height varies with its content (surface chip, per-leg select, date), so a
   line fixed to a pin's vertical offset would drift off-centre on anything but the
   shortest row. A rail that is right on some rows and visibly wrong on others is
   worse than no rail. */
.pstop{display:grid;grid-template-columns:minmax(26px,auto) 1fr auto;gap:10px;align-items:center;
  border:1px solid var(--rule);padding:9px 10px;background:var(--surface)}
.pno{width:26px;height:26px;background:var(--orange);color:#fff;border-radius:50%;display:grid;
  place-items:center;font-size:12px;font-weight:800}
/* P0-EDT-02 (mock-013): start is a hollow ring, finish is a flag - neither is "stop N". */
.pno--start{background:none;border:2.5px solid var(--orange);box-sizing:border-box}
.pno--finish{background:none;color:var(--orange);font-size:16px;line-height:1}
.pname{min-width:0}
.pname b{display:block;font-size:13px;font-weight:700;line-height:1.25;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pname span{display:block;font-size:10.5px;color:var(--steel);margin-top:2px}
/* CORNERS PER MILE, at the size of the decision it drives.
   The leg list opened with a sequence number - which tells a rider nothing - and
   buried a raw curve COUNT in the sub-line. 340 curves means opposite things on a
   12 mile road and on a 200 mile one. This is the designed leg card: the figure that
   actually decides whether a leg is worth riding, first and biggest. */
.pcpm{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;
  min-width:3rem;line-height:1}
.pcpm b{font-size:21px;font-weight:800;font-variant-numeric:tabular-nums}
.pcpm u{text-decoration:none;font-size:8.5px;letter-spacing:.11em;opacity:.6;
  text-transform:uppercase;margin-top:2px}
/* THE SURFACE CHIP. Amber, on its own line, impossible to skim past - it is the one
   thing in this list that is a warning rather than a measurement.
   There is deliberately NO "paved" chip beside it: pv is 1 on all 85,984 rows, so it
   is a default and not a measurement, and a green PAVED badge would assert something
   nobody has ever checked. No chip means OSM recorded something. Nothing more. */
.pchip{display:inline-block;margin-top:5px;padding:3px 8px;border-radius:5px;
  font-size:9px;font-weight:700;letter-spacing:.07em;text-transform:uppercase}
.pchip--unk{background:#3A2808;color:#F0CF7A;border:1px solid #6B5518}
/* Stronger than "unknown", because it is a different statement: OSM explicitly maps
   this road as gravel, dirt or sand. 44 of these got past the promotion gate and were
   shipping as paved with nothing said at all. */
.pchip--bad{background:#2C1614;color:#F0A49A;border:1px solid #6B2A22}
@media (prefers-color-scheme:light){
  .pchip--unk{background:#FBF1D8;color:#6B5518;border-color:#D4B55E}
  .pchip--bad{background:#FBE5E2;color:#73221A;border-color:#D79A92}}
.pacts{display:flex;gap:3px}
.pacts button{width:26px;height:26px;border:1px solid var(--rule);background:var(--surface);
  cursor:pointer;font-size:13px;line-height:1;color:var(--ink)}
.pacts button:hover:not([disabled]){background:var(--chrome);color:var(--white);
  border-color:var(--black)}
.pacts button[disabled]{opacity:.32;cursor:default}

.popts{display:flex;gap:16px;flex-wrap:wrap;align-items:center;padding:14px 17px 0;
  font-size:11.5px;color:var(--steel)}
.popts label{display:flex;gap:6px;align-items:center;cursor:pointer}
.popts input[type=number]{width:62px;border:1px solid var(--rule);padding:5px 6px;
  font:inherit;font-size:12px}
.popts accent-color{accent-color:var(--orange)}
.popts input[type=checkbox]{accent-color:var(--orange);width:15px;height:15px}

#pout{padding:16px 17px 0}
.psum{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--rule);
  border:1px solid var(--rule)}
.psum div{background:var(--surface);padding:11px 9px;text-align:center}
.psum b{display:block;font-size:17px;font-weight:900;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;line-height:1.05;white-space:nowrap}
@media(min-width:1200px){.psum b{font-size:19px}}
.psum span{display:block;font-size:8.5px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--steel);margin-top:4px}
.pdays{list-style:none;margin:12px 0 0;padding:0;border:1px solid var(--rule)}
.pdays li{display:flex;justify-content:space-between;gap:10px;padding:9px 12px;
  border-bottom:1px solid var(--rule);font-size:12.5px}
.pdays li:last-child{border-bottom:0}
.pdays b{font-weight:800}
.pdays span{color:var(--steel);font-variant-numeric:tabular-nums}
.pnote{margin:11px 0 0;font-size:11px;line-height:1.5;color:var(--steel)}

.pexp{display:flex;gap:8px;flex-wrap:wrap;padding:16px 17px 20px;margin-top:auto}
/* `a` as well as `button`: "Ride there now" is a link, because it goes somewhere
   rather than doing something, and a rider should be able to long-press it. It has to
   sit in the row looking like its neighbours all the same. */
.pexp button,.pexp a{border:1px solid var(--ink);background:var(--surface);color:var(--ink);
  font:inherit;font-size:10.5px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
  padding:11px 13px;cursor:pointer;text-decoration:none;display:inline-flex;
  align-items:center}
/* shared 2026-10-29 (gap/P1-continuity.md sec.6, P1-SHR-01-web): this used to pair
   var(--chrome2) with var(--white) text. --chrome2 is near-white in the LIGHT theme
   (#F0EEEA), so hovering Share there painted white text on a near-white chip -
   contrast ratio ~1.07:1, unreadable (measured, shots/light-13-after-share-click.png).
   --ink already inverts correctly with --chrome2 in both themes (dark text on the
   light chrome2 of light mode, light text on the dark chrome2 of dark mode). */
.pexp button:hover:not([disabled]),.pexp a:hover{background:var(--chrome2);color:var(--ink)}
.pgpx-note{flex:1 1 100%;margin:0;padding:2px 2px 4px;font-size:11px;line-height:1.45;
  color:var(--steel)}
/* The one control on this row that is never disabled: you do not have to plan a trip
   to go and ride. It only reads as THE primary action once a route exists to ride
   (WBH-4490) - html.has-route is set by summary() in js/plan.js. Before that, "Find me
   a ride" above is the one accent on the sheet; this row has none. */
html.has-route .pexp a#pridenow{background:var(--orange);border-color:var(--orange);color:#fff}
html.has-route .pexp a#pridenow:hover{background:var(--orange-dk);border-color:var(--orange-dk);
  color:#fff}
.pexp button[disabled]{opacity:.4;cursor:default}
#pstatus{padding:0 17px;font-size:11.5px;color:var(--orange);font-weight:600;min-height:17px}

/* ---------------------- lodging at each overnight stop --------------------
   Scoped to where a day actually ends, not the whole route: a rider wants a bed
   where they will stop, not a list of every hotel across 800 miles. */
.pdays li{flex-direction:column;align-items:stretch;gap:3px}
.pdays li>b{font-weight:800}
.pdays li>span{color:var(--steel);font-variant-numeric:tabular-nums}
/* Rain on the day, under the miles. Hidden until it has something to say, so a plan for a
   rider outside the US or past the forecast horizon does not carry an empty grey bar. */
.pwx:empty{display:none}
.pwx{margin:6px 0 0;font-size:12px;color:var(--steel);
     display:flex;align-items:baseline;gap:6px}
.pwx::before{content:"";width:7px;height:7px;border-radius:50%;
             background:var(--steel);opacity:.55;flex:none}
/* Rain is a caution, not a failure, so it takes the brand orange rather than the
   red reserved for a missed deadline. */
.pwx--wet{color:var(--orange);font-weight:600}
.pwx--wet::before{background:currentColor;opacity:1}
.pwx--far{font-style:italic;opacity:.75}

.pbeds:empty{display:none}
.pbeds{margin:8px 0 2px;border-top:1px solid var(--rule);padding-top:8px}
.pbeds>b{display:block;font-size:9.5px;font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;color:var(--orange);margin:0 0 6px}
.pbeds>i{display:block;font-style:normal;font-size:11.5px;color:var(--steel);
  line-height:1.5}
.pbeds ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.pbeds li{display:flex;justify-content:space-between;gap:10px;font-size:12px;
  border:0;padding:0}
.pbeds li span{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.pbeds li i{font-style:normal;color:var(--steel);white-space:nowrap;
  font-variant-numeric:tabular-nums}
.phw-warn{display:block;margin:9px 17px 0;font-style:normal;font-size:11px;
  line-height:1.45;color:var(--orange);font-weight:600}
.phw-warn:empty{display:none}
.popts label:has(input:disabled){opacity:.5}

/* --------------------------- routing style dial --------------------------
   Direct / Curvy / Supercurvy instead of one checkbox. "Avoid interstates" was
   a yes/no answer to a question that has degrees. */
.pstyle{--c-gap:6px;padding:14px 17px 0}
/* the shape is .c-chip; this is the one part that is only a style-row concern */
.pstyle .tbtn--alt{flex:0 0 auto;min-width:0;border-color:var(--rule);color:var(--steel)}
.pstyle .tbtn--alt:hover{background:var(--chrome2);color:var(--ink);border-color:var(--ink)}
.phint{margin:7px 0 0;font-size:11px;color:var(--steel)}

/* ------------------------------ drag to reorder ---------------------------
   Pointer Events, not HTML5 drag-and-drop (2026-10-08): dragstart/dragover/drop
   never fire from a touch on iOS Safari, so the mouse-only version shipped here
   until now could not be used on the phone this app mostly runs on. touch-action:
   none stops the browser treating the drag gesture as a page scroll. */
.pstop{cursor:default}
.pgrip{color:var(--rule);font-size:13px;letter-spacing:-2px;cursor:grab;
  padding:0 2px;user-select:none;touch-action:none}
.pgrip:active{cursor:grabbing}
.pstop.dragging{opacity:.45}
.pstop.over{box-shadow:inset 0 3px 0 var(--orange)}

/* "+ Add a stop" row, below the list (screen 04). Same visual family as .pacts
   buttons — border, no fill — so it reads as part of the list rather than a new
   kind of control. */
.padd-stop{display:flex;align-items:center;justify-content:center;gap:6px;
  width:calc(100% - 34px);margin:0 17px;border:1px dashed var(--rule);
  background:transparent;color:var(--steel);font:inherit;font-size:12.5px;
  font-weight:700;letter-spacing:.04em;padding:10px;cursor:pointer}
.padd-stop:hover{border-color:var(--orange);color:var(--orange)}
.padd-stop span{font-size:15px;line-height:1}

/* Staged recalculate (screen 04, mock-013) + one-level undo. Column, not the old
   row: "Changes apply after recalculating" / Recalculate route (primary, full width) /
   Restore version N stack top to bottom, same order the mock draws them in. */
.precalc{display:flex;flex-direction:column;align-items:stretch;gap:8px;
  margin:10px 17px 0;padding:10px;border:1px solid var(--rule);
  background:var(--panel)}
.pedit-pending-note{margin:0;font-size:12px;color:var(--steel);text-align:center}
#pedit-recalc{width:100%}
.precalc-ver{margin:0;font-size:10.5px;font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--steel);text-align:center}
.precalc-ver b{color:var(--orange)}
.precalc-undo{border:1px solid var(--ink);background:var(--surface);color:var(--ink);
  font:inherit;font-size:10.5px;font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;padding:7px 10px;cursor:pointer;align-self:center}
.precalc-undo:hover{background:var(--chrome2);color:var(--ink)}
/* Back to three columns for good: number, name, and ONE cell holding every control.
   The column count grew with each new control and the row silently wrapped when it ran
   out — which is how the delete button ended up underneath the date picker. */
.pstop{grid-template-columns:26px 1fr auto}
.pctl{display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
@media (max-width:560px){
  /* On a phone the controls get their own full-width row rather than fighting the name
     for forty pixels. Everything stays tappable with gloves on. */
  .pstop{grid-template-columns:26px 1fr}
  .pctl{grid-column:1 / -1;justify-content:flex-start;gap:8px;
        padding-top:8px;border-top:1px solid var(--rule)}
  .pacts button{width:38px;height:38px}
  .pby label{white-space:nowrap}
}

/* --------------------------- share screen with QR --------------------------
   A six-character short link in a version-1 QR, because the thing being
   scanned is a phone screen at a petrol stop, in gloves, in daylight.

   P1-SHR-01-web (scope board 06 "Share this ride" / gap/P1-continuity.md sec.6):
   this used to render in-flow, ~7 screens down a long form, with nothing to bring
   it on screen (measured -527px/-157px off the top of the viewport after the
   click -- the rider saw no visible change). It is now a real dedicated
   full-screen screen (position:fixed, covers the whole viewport, its own header
   with a back control) matching the mockup, not a sheet buried in a scroll
   position nobody could find. */
.pshare-sheet{position:fixed;inset:0;z-index:70;background:var(--surface);
  display:flex;flex-direction:column;overflow-y:auto;-webkit-overflow-scrolling:touch}
.pshare-sheet[hidden]{display:none}
body.pshare-open{overflow:hidden}
.pshare-head{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:10px;
  padding:14px 15px;background:var(--surface);border-bottom:1px solid var(--rule)}
.pshare-back{background:none;border:0;color:var(--ink);font-size:20px;line-height:1;
  cursor:pointer;padding:4px 6px;margin:-4px 0}
.pshare-back:hover{color:var(--orange)}
.pshare-head b{flex:1 1 auto;font-size:15px;font-weight:800;color:var(--ink);
  text-align:center}
/* Balances .pshare-back on the opposite side so the centered title in the flex row
   between them stays visually centered now that the header has three children, not
   two (the mockup's own header dots: back, title, overflow). */
.pshare-more{background:none;border:0;color:var(--ink);font-size:20px;line-height:1;
  cursor:pointer;padding:4px 6px;margin:-4px 0;flex:0 0 auto}
.pshare-more:hover{color:var(--orange)}
/* The "Specific riders" overflow reuses Home's exact .paccount/.paccount-row sheet
   (already loaded on this page) instead of a second menu component; these two rules
   only adapt the row to carry a two-line label+description like .pshare-invite used
   to, since every other .paccount-row on this page is a single plain link line. */
#pshare-more-sheet .paccount-row{flex-direction:column;align-items:flex-start;
  gap:3px;min-height:auto;padding:12px 4px}
#pshare-more-sheet .paccount-row::after{display:none}
#pshare-more-sheet .paccount-row i{font-style:normal;color:var(--steel);font-size:12px;
  line-height:1.4}
/* The resting screen has three visual groups (hero, route identity, actions). Give
   those groups the viewport's spare height instead of leaving one ~250px hole below
   an in-flow CTA. When a QR/link panel opens, this same flex body grows and the sheet
   scrolls normally; the footer remains the reachable viewport anchor. */
.pshare-body{padding:0 17px;flex:1 0 auto;display:flex;flex-direction:column;
  justify-content:space-evenly;gap:12px;min-height:0}
.pshare-map{position:relative;margin:0;border-radius:14px;overflow:hidden;
  border:1px solid var(--rule);background:var(--chrome2);height:250px;flex:0 0 250px}
.pshare-map canvas.pshare-map-canvas{display:block;width:100%;height:250px}
/* REDESIGN S12: the live MapLibre hero (js/route-preview-canvas.js mountHero)
   layers over the flat canvas fallback underneath, same box, same corners. */
.pshare-map-host{position:absolute;inset:0}
.pshare-map-host[hidden]{display:none}
.pshare-map-host .maplibregl-ctrl-bottom-right,
.pshare-map-host .maplibregl-ctrl-bottom-left{display:none}
.pshare-name{margin:0 0 3px;font-size:19px;font-weight:800;color:var(--ink)}
.pshare-meta{margin:0;font-size:12.5px;color:var(--steel)}
.pshare-status{margin:4px 0 0;font-size:12px;color:var(--orange);font-weight:600;min-height:15px}
.pshare-rows{border:0;border-top:1px solid var(--rule);border-radius:0;overflow:visible;margin:0}
.pshare-rows .pshare-row{display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  background:transparent;border:0;border-bottom:1px solid var(--rule);padding:13px 0;
  cursor:pointer;font:inherit}
.pshare-rows .pshare-row:hover{background:transparent}
/* REDESIGN S12 (round 3, REDESIGN-AUDIT-3 #2): the tile leads each row with an orange
   "+" bullet; this build had the text and chevron but dropped that leading glyph. */
.pshare-row-icon{flex:0 0 auto;width:16px;font-size:15px;line-height:1;font-weight:800;
  color:var(--orange);text-align:center}
.pshare-row-t{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}
.pshare-row-t b{font-size:13.5px;color:var(--ink)}
.pshare-row-t i{font-size:11.5px;font-style:normal;color:var(--steel)}
.pshare-row-chev{color:var(--steel);font-size:18px}
.pshare-link-panel{border:1px solid var(--rule);border-radius:12px;overflow:hidden;
  margin-bottom:14px;background:var(--panel)}
.pshare-link-panel[hidden]{display:none}
.pshare-invite{display:block;padding:13px 14px;border:1px solid var(--rule);
  border-radius:12px;background:var(--panel);color:var(--ink);text-decoration:none;
  font-size:12.5px}
.pshare-invite:hover{background:var(--chrome2)}
.pshare-invite b{display:block;font-size:13.5px;margin-bottom:2px}
.pshare-invite i{font-style:normal;color:var(--steel);font-size:11.5px;line-height:1.4}
/* Viewport anchor in the resting state; sticky keeps the same real action reachable
   after either disclosure panel makes the dedicated screen scroll. */
.pshare-foot{position:sticky;bottom:0;padding:14px 17px calc(14px + env(safe-area-inset-bottom));
  background:var(--surface);border-top:1px solid var(--rule)}
.pshare-primary{width:100%;border:0;border-radius:12px;background:var(--orange);
  color:#181B1A;font:inherit;font-size:14.5px;font-weight:800;padding:14px;cursor:pointer}
.pshare-primary:hover{background:var(--orange-dk)}
@media (max-height:700px){
  .pshare-body{gap:8px}
  .pshare-map{height:190px;flex-basis:190px}
  .pshare-map canvas.pshare-map-canvas{height:190px}
}
.pshare-expiry{display:flex;align-items:center;gap:8px;padding:11px 13px;
  border-top:1px solid var(--rule);font-size:12px;color:var(--steel);flex-wrap:wrap}
.pshare-expiry select{font:inherit;font-size:12px;border:1px solid var(--rule);
  background:var(--surface);color:var(--ink);padding:5px 6px}
.pshare-revoke{border:1px solid var(--rule);background:var(--surface);color:var(--ink);
  font:inherit;font-size:11px;font-weight:700;padding:7px 10px;cursor:pointer;
  white-space:nowrap;margin-left:auto}
.pshare-revoke:hover{background:var(--ink);color:var(--surface)}
.pqr{display:grid;place-items:center;padding:16px 0 10px;background:#FFFFFF}
.pqr img,.pqr canvas{display:block}
.pqr-fail{margin:0;padding:18px;font-size:12px;color:var(--steel);text-align:center}
.pqr-url{margin:0;padding:0 13px 10px}
.pqr-url input{width:100%;border:1px solid var(--rule);background:var(--panel);
  color:var(--ink);font:inherit;font-size:12.5px;padding:8px 9px;text-align:center}
.pqr-note{margin:0;padding:0 13px 10px;font-size:11px;line-height:1.45;color:var(--steel)}
.pqr-acts{display:flex;gap:7px;flex-wrap:wrap;padding:0 13px 13px}
.pqr-acts a,.pqr-acts button{flex:1 1 auto;text-align:center;border:1px solid var(--ink);
  background:var(--surface);color:var(--ink);font:inherit;font-size:10.5px;font-weight:800;
  letter-spacing:.09em;text-transform:uppercase;padding:10px 8px;cursor:pointer;
  white-space:nowrap}
.pqr-acts a:hover,.pqr-acts button:hover{background:var(--ink);color:var(--surface)}

/* ---------------------------------------------------------------------------
   "Give me a ride" — the front door of the planner (2026-09-15)
   Sits above the manual stop list because it is what most riders want most of
   the time: they know the destination and the time they have, not the roads.
   --------------------------------------------------------------------------- */
.pauto{
  background:var(--panel);
  border:1px solid var(--rule);
  border-left:3px solid var(--orange);
  padding:16px 16px 14px;
  margin:0 0 18px;
}
.pauto h2{
  font-size:17px; line-height:1.15; margin:0 0 4px;
  letter-spacing:.01em; color:var(--text-strong);
}
.pauto-lead{ font-size:12.5px; line-height:1.45; color:var(--steel); margin:0 0 12px; }
.pauto-grid{
  display:grid; grid-template-columns:auto 1fr; gap:8px 10px; align-items:center;
  margin-bottom:12px;
}
/* Wrapped number cells: on the website they keep the label-above-input shape and
   sit three to a row rather than one per line. */
.pauto-num{display:flex;flex-direction:column;gap:3px;min-width:0}
.pauto-num > label{font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;color:var(--smoke)}
.pauto-grid label{
  font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--smoke);
}
.pauto-grid input{
  width:100%; box-sizing:border-box;
  background:var(--surface); color:var(--ink);
  border:1px solid var(--rule); border-radius:2px;
  padding:9px 10px; font-size:14px;
  font-family:"Libre Franklin",system-ui,-apple-system,sans-serif;
}
.pauto-grid input:focus-visible{ outline:2px solid var(--orange); outline-offset:1px; }
.pauto-grid input[type=number]{ max-width:110px; font-variant-numeric:tabular-nums; }
#pa-go{ width:100%; }
#pa-go:disabled{ opacity:.6; cursor:progress; }
.pauto-note{
  font-size:13px; line-height:1.5; color:var(--ink);
  margin:12px 0 0; min-height:1em;
}
/* When the note has something to say it is the ONLY feedback the button gives, so it
   has to read as a result rather than as fine print. Dean could not tell a working
   planner from a dead button because the answer arrived as small grey text. */
.pauto-note:not(:empty){
  background:var(--surface);
  border-left:3px solid var(--orange);
  padding:10px 12px;
}
/* P0-HOM-06: a single small CENTERED line, never the loudest thing on Home (mock-003:
   "Sponsored · MotoHaus · Built for the long way" reads as one line, not a two-line
   left-aligned block). Plain block + text-align so it wraps and centers as one unit
   instead of a flex row whose items only center as a group. The Sponsored kicker
   (.pauto-sponsor-k) is hidden by js/plan.js's homeSponsorLine() whenever this renders
   house copy - it only has a reason to show next to an actual verified sponsor. */
.pauto-sponsor{
  display:block; text-align:center;
  margin:10px 0 0; font-size:12px; line-height:1.4; color:var(--steel);
}
.pauto-sponsor-k{
  font-weight:700; letter-spacing:.04em; text-transform:uppercase; font-size:10.5px;
  color:var(--steel); margin-right:6px;
}
@media (min-width:700px){
  .pauto-grid{ grid-template-columns:auto 1fr auto auto; }
  .pauto-grid input[type=number]{ max-width:88px; }
}

/* Autocomplete + "use my location" for the ride planner (2026-09-15).
   Dean, first run on the phone: "it should give my location as a option, and have
   auto fill for typed cities." Both were fair — a blank From field meaning "here" is
   not a feature anyone can see. */
.pauto-field{ position:relative; display:flex; gap:6px; align-items:stretch; }
.pauto-field input{ flex:1 1 auto; min-width:0; }
.pauto-here{
  flex:0 0 auto; white-space:nowrap;
  font:600 11px/1 "Libre Franklin",system-ui,-apple-system,sans-serif;
  letter-spacing:.03em; text-transform:uppercase;
  color:var(--orange); background:transparent;
  border:1px solid var(--rule); border-radius:2px;
  padding:0 10px; cursor:pointer;
}
.pauto-here:hover{ border-color:var(--orange); }
.pauto-here:disabled{ opacity:.55; cursor:progress; }
.pauto-here:focus-visible{ outline:2px solid var(--orange); outline-offset:2px; }

.pauto-sug{
  position:absolute; top:calc(100% + 4px); left:0; right:0; z-index:40;
  background:var(--surface); border:1px solid var(--rule); border-radius:2px;
  max-height:240px; overflow-y:auto;
  box-shadow:0 8px 28px rgba(0,0,0,.45);
}
.pauto-sug button{
  display:block; width:100%; text-align:left; cursor:pointer;
  background:transparent; border:0; border-bottom:1px solid var(--rule);
  padding:9px 11px; color:var(--ink);
  font:400 13px/1.35 "Libre Franklin",system-ui,-apple-system,sans-serif;
}
.pauto-sug button:last-child{ border-bottom:0; }
.pauto-sug button:hover,
.pauto-sug button[aria-selected="true"]{ background:var(--panel); color:var(--orange); }
.pauto-sug b{ display:block; font-weight:600; grid-column:1; min-width:0; }
.pauto-sug span{ display:block; font-size:11.5px; color:var(--steel); margin-top:1px;
  grid-column:1; min-width:0; }
/* THE DISTANCE, BESIDE THE NAME AND NOT UNDER IT.
   The brief asks every search row to carry a distance, and a third line would have cost
   the row that carries it: eight results already end at y771 against a visible limit of
   788, so one more line per row pushes the last result back off the screen this list was
   fixed to get it onto. A two-column grid puts the distance to the right of both existing
   lines and leaves the row exactly as tall as it was, which the 52px min-height above
   was already setting anyway. Tabular figures so the column of numbers lines up. */
.pauto-sug button{ display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:10px;
  align-items:center; }
.pauto-sug .pauto-away{ grid-column:2; grid-row:1 / -1; justify-self:end;
  font-style:normal; font-size:11.5px; color:var(--steel); white-space:nowrap;
  font-variant-numeric:tabular-nums; }
@media (min-width:700px){
  .pauto-grid .pauto-field{ grid-column:auto; }
}

/* Round trip. Dean: "We need a round trip too." Most rides are a loop from home and
   back, not a one-way delivery — the planner assumed a destination because that is how
   navigation apps think, not how a Sunday works. */
.pauto-loop{
  display:flex; align-items:center; gap:8px;
  font:500 13px/1.3 "Libre Franklin",system-ui,-apple-system,sans-serif;
  color:var(--ink); margin:0 0 12px; cursor:pointer;
}
.pauto-loop input{ width:16px; height:16px; accent-color:var(--orange); flex:0 0 auto; }

/* Destination demoted to an optional disclosure. Dean: "most guys just want a quick 2-3
   ride." Asking for a destination first made the ordinary ride the hard path. */
.pauto-more{ margin-top:14px; border-top:1px solid var(--rule); padding-top:10px; }
.pauto-more summary{
  cursor:pointer; list-style:none;
  font:600 11px/1 "Libre Franklin",system-ui,-apple-system,sans-serif;
  letter-spacing:.06em; text-transform:uppercase; color:var(--steel);
  padding:2px 0;
}
.pauto-more summary::-webkit-details-marker{ display:none; }
.pauto-more summary::before{ content:"+ "; color:var(--orange); font-weight:700; }
.pauto-more[open] summary::before{ content:"− "; }
.pauto-more summary:hover{ color:var(--orange); }
.pauto-grid--to{ margin-top:10px; }
.pauto-hint{ font-size:11.5px; color:var(--smoke); margin:8px 0 0; line-height:1.4; }
/* =========================================================================
   [HIDDEN] ONCE, FOR THE WHOLE PLANNER

   An author `display` beats the browser's own [hidden] rule, so every element
   here that is laid out with flex or grid stayed on screen when JS hid it - and
   each one was found the hard way, as a panel nobody could see that swallowed
   every tap underneath it. Five separate !important repairs had accumulated
   (.pauto-grid label, .pauto-append, .pauto-mode--trip, #pa-trip-hint, .proutes)
   plus two quieter ones. This is the rule they were all approximating. Anything
   added later gets it for free, which is the point: the next one of these should
   not be a bug first.
   ========================================================================= */
[hidden]{display:none !important}

/* =========================================================================
   COMPONENTS

   Four shapes carry this app: a card, a segmented control, the chip inside it,
   and the primary action. Each was re-described wherever it appeared - .tbtn
   alone had seven definitions - and the comment on the third one says what that
   cost: "reusing the class elsewhere inherited the shape and none of the
   meaning, both buttons rendered identically and a rider could not tell which
   kind of ride they were about to get." The fix at the time was a fourth block.

   This is the component instead. One declaration list per shape; every selector
   that IS that shape is grouped onto it; the sizes sit behind tokens. A new
   screen joins a group rather than restating it.

   Type scales with --ts and boxes do not. Scaling the chrome with the text
   control is what filled Dean's screen mid-ride.
   ========================================================================= */
:root{
  --c-tap:48px;          /* Apple's 44pt floor, with a glove's margin */
  --c-tap-sm:44px;
  --c-gap:8px;
  --c-radius:2px;        /* this site's chrome is square-ish, not pill */
  --c-radius-card:10px;
  --c-pad-card:12px;
}

/* SEGMENTED CONTROL - a row of mutually exclusive choices. The container owns
   the track only; where it sits on the sheet stays with the context. */
.c-seg,
.pauto-mode,
.pstyle{display:flex;gap:var(--c-gap);flex-wrap:wrap}
.c-seg > *,
.pauto-mode .tbtn{flex:1 1 0;min-width:0}

/* THE CHIP inside it. One shape, one pressed state, everywhere. */
.c-chip,
.pauto-mode .tbtn,
.pstyle .tbtn{
  min-height:var(--c-tap);
  border:1px solid var(--rule);
  background:var(--surface);
  color:var(--steel);
  font:inherit;font-weight:600;letter-spacing:.02em;
  border-radius:var(--c-radius);
  cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:background .12s ease, color .12s ease, border-color .12s ease;
}
.c-chip:hover,
.pauto-mode .tbtn:hover,
.pstyle .tbtn:hover{background:var(--panel);color:var(--ink);border-color:var(--ink)}
.c-chip:focus-visible,
.pauto-mode .tbtn:focus-visible,
.pstyle .tbtn:focus-visible{outline:2px solid var(--orange);outline-offset:2px}
/* Pressed is near-black on orange, not white. The two chips disagreed - the mode row
   used #0A0A0A and the style row #fff - and white on var(--orange) measures about
   2.4:1, which fails at any size. This is the kind of thing a component settles once. */
.c-chip[aria-pressed="true"],
.pauto-mode .tbtn[aria-pressed="true"],
.pstyle .tbtn[aria-pressed="true"]{
  background:var(--orange);border-color:var(--orange);color:#0A0A0A}

/* THE STYLE ROW is the same chip, smaller and shouting: it names a routing tradeoff
   rather than a mode, so it reads as a tag. Only what differs lives here. */
.pstyle .tbtn{flex:1 1 auto;border-color:var(--ink);font-weight:800;
  letter-spacing:.04em;text-transform:uppercase}

/* CARD - a panel that holds other things. Deliberately NOT retrofitted onto
   .pauto-more or .pauto-budget: on the website the first is a hairline disclosure
   and the second carries its own surface, and quietly turning either into a box is
   a redesign of a screen nobody asked me to touch. They join this when their own
   context is next opened. Border, fill and radius each say "separate object", so
   they are spent on the blocks that are one. */
.c-card{
  background:var(--panel);
  border:1px solid var(--rule);
  border-radius:var(--c-radius-card);
  padding:var(--c-pad-card);
}

/* PRIMARY ACTION - the one thing on a screen that commits. Full width, tallest
   target, heaviest weight; there is never more than one per screen. */
.c-act,
#pa-go{
  width:100%;
  min-height:54px;
  font:inherit;font-size:calc(16px * var(--ts, 1));
  font-weight:700;letter-spacing:.02em;
  cursor:pointer;
}

#pa-go{ width:100%; padding:13px 14px; font-size:14px; }

/* Loop vs point-to-point. Both first class — Dean rides both ways, so neither is
   hidden behind a disclosure and neither is forced. */
/* placement only - the shape is .c-seg above */
.pauto-mode{ margin:0 0 10px; }

/* ---------------------------------------------------------------------------
   PHONE SIZING (2026-09-16)

   Dean: "We need to fix the buttons sizing too, it's hard on a phone."

   Apple's own guidance is a 44pt minimum touch target and most of these were well
   under it — the Hours box was 88px wide, "Use my location" was a 24px-tall strip of
   text, and the routing style buttons were sized for a mouse. This is a thing people
   use at a petrol station wearing gloves, so everything you can tap is now at least
   48px tall and the text is 16px, which also stops iOS zooming the page when a field
   takes focus.
   --------------------------------------------------------------------------- */
.pauto input[type=text],
.pauto input[type=number],
.pauto input[type=search]{
  min-height:48px;
  font-size:16px;            /* below 16px iOS zooms the whole page on focus */
  padding:12px 12px;
}
.pauto-grid input[type=number]{ max-width:100%; width:110px; }

.pauto-here{
  min-height:48px; padding:0 14px; font-size:12px;
}

.pauto-mode .tbtn{ font-size:14px; padding:12px 10px; }

.pauto-sug button{
  min-height:52px; padding:11px 12px; font-size:14px;
}

/* the routing-style row below the planner had the same problem */
.pstyle .tbtn{ font-size:13px; padding:11px 8px; }
/* WBH-4489: #pridenow is the <a>, not a <button>, so this rule never reached it - the
   one place the pending-trip handoff now lives tested 37px tall, under a thumb's target. */
.pexp button, .pexp a{ min-height:48px; font-size:14px; padding:12px 14px; }
.mrp-save-offline{ min-height:48px; font-size:13px; }

/* Stack the label above the field on a narrow screen: a two-column grid with a
   fixed label column squeezes every input to nothing on a 390px phone. */
@media (max-width:560px){
  .pauto-grid{ grid-template-columns:1fr; gap:4px 0; }
  .pauto-grid label{ margin-top:10px; }
  .pauto-grid input[type=number]{ width:100%; max-width:140px; }
  .pauto-field{ flex-wrap:wrap; }
  .pauto-here{ flex:1 1 100%; margin-top:6px; }
}

/* The mode buttons had no selected state at all, and the fix at the time was a fourth
   copy of the chip. It is now .c-chip and the hover is the only thing left that is
   particular to this row - an orange edge, because a mode is a commitment. */
.pauto-mode .tbtn:hover{ border-color:var(--orange); color:var(--ink); background:var(--surface) }

/* `display:flex` on .pauto-field beat the browser's own [hidden]{display:none}, so the
   destination box stayed on screen in Loop mode with its label correctly hidden — an
   orphaned input asking for somewhere to go on a ride that comes back. Any rule that
   sets display has to concede to [hidden]. */
.pauto-field[hidden],


/* "Find me a ride" is the whole point of the panel and it was rendering grey, which on a
   dark UI reads as disabled. The one thing a rider is meant to press should be the most
   obvious thing on the screen. */
#pa-go{
  background:var(--orange);
  border:1px solid var(--orange);
  color:#0A0A0A;
  border-radius:2px;
  cursor:pointer;
}
#pa-go:hover:not(:disabled){ background:var(--orange-dk); border-color:var(--orange-dk); }
#pa-go:disabled{ background:var(--panel); border-color:var(--rule); color:var(--smoke); }
#pa-go:focus-visible{ outline:2px solid var(--orange); outline-offset:3px; }

/* Days and hours-a-day sit side by side on a wide screen and stack on a phone. */
@media (min-width:560px){
  .pauto-grid{ grid-template-columns:auto 1fr auto auto; }
}
#pa-days{ width:90px; }
#pa-budget:not(:empty){ margin-top:10px; color:var(--steel); }

/* "Carry on from my last stop" — only shown when there IS a trip to carry on from. */
.pauto-append{
  display:flex; align-items:center; gap:8px; margin:0 0 12px;
  font:500 13px/1.3 "Libre Franklin",system-ui,-apple-system,sans-serif;
  color:var(--ink); cursor:pointer;
}

.pauto-append input{ width:18px; height:18px; accent-color:var(--orange); flex:0 0 auto; }

/* Fill-in vs carry-on, shown only when there is a trip to act on. */
.pauto-mode--trip{ margin-top:2px; }



/* Ways round — alternate routes, offered rather than chosen for the rider.
   WBH-4490: a card per alternative, not a pill of miles and minutes. Duration and
   distance are always shown; the tradeoff line only appears when js/plan.js decided the
   difference was worth saying (see routeTradeoff) - no card ever claims a surface or
   corner-count advantage, because that data is not trustworthy yet. */
.proutes{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin:14px 0 4px; }

.proutes-lab{
  font:700 11px/1 "Libre Franklin",system-ui,-apple-system,sans-serif;
  letter-spacing:.06em; text-transform:uppercase; color:var(--smoke);
  flex:0 0 100%;
}
.proute-card{
  flex:1 1 auto; min-width:92px; display:flex; flex-direction:column; gap:3px;
  min-height:46px; padding:9px 10px;
  border:1px solid var(--rule); background:var(--surface); color:var(--steel);
  border-radius:2px; cursor:pointer; text-align:left; font:inherit;
}
.proute-card-top{ display:flex; flex-wrap:wrap; align-items:baseline; gap:6px; }
.proute-card-kind{display:block;flex:1 0 100%;font-size:11px;font-weight:700;color:var(--steel)}
.proute-card-mi{ font-size:13px; font-weight:700; color:var(--ink);
  font-variant-numeric:tabular-nums; }
.proute-card-h{ font-size:12px; color:var(--steel); font-variant-numeric:tabular-nums; }
.proute-card-trade{ font-size:10.5px; letter-spacing:.03em; color:var(--smoke); }
.proute-card[aria-pressed="true"]{ background:var(--orange); border-color:var(--orange); }
.proute-card[aria-pressed="true"] .proute-card-mi,
.proute-card[aria-pressed="true"] .proute-card-h{ color:#0A0A0A; font-weight:700; }
.proute-card[aria-pressed="true"] .proute-card-trade{ color:#0A0A0A; }

/* Per-leg routing style. A long trip is slab to get there and twisty once you arrive;
   one setting for the whole thing was never going to fit. */
.pleg{ flex:0 0 auto; }
.pleg select{
  background:var(--surface); color:var(--ink);
  border:1px solid var(--rule); border-radius:2px;
  font:600 11px/1 "Libre Franklin",system-ui,-apple-system,sans-serif;
  padding:8px 6px; min-height:40px; max-width:86px;
}
.pleg select:focus-visible{ outline:2px solid var(--orange); outline-offset:2px; }

/* ---------------------------------------------------------------------------
   TEXT SIZE — planner controls.

   These live here, not in heritage.css, because plan.css loads AFTER it and was
   overriding every scaled size with its own fixed px. The body text grew and the
   buttons did not, which is the half-done version of an accessibility feature and
   arguably worse than none: the labels get bigger while the thing you have to hit
   stays the same.

   --ts is defined in heritage.css; large is the default (Dean: "A++ should be the
   base, I have great vision and a lot of these guys don't").
   --------------------------------------------------------------------------- */
.pauto input[type=text],
.pauto input[type=number],
.pauto input[type=search]{
  font-size: calc(16px * var(--ts));
  min-height: calc(48px * var(--ts));
}
.pauto-here{ font-size: calc(12px * var(--ts)); min-height: calc(48px * var(--ts)); }
.pauto-mode .tbtn{ font-size: calc(14px * var(--ts)); min-height: calc(48px * var(--ts)); }
#pa-go{ font-size: calc(16px * var(--ts)); min-height: calc(54px * var(--ts)); }
.pauto-sug button{ font-size: calc(14px * var(--ts)); min-height: calc(52px * var(--ts)); }
.pauto h2{ font-size: calc(17px * var(--ts)); }
.pauto-lead{ font-size: calc(12.5px * var(--ts)); }
.pauto-grid label{ font-size: calc(11px * var(--ts)); }
.pauto-note{ font-size: calc(13px * var(--ts)); }
.pauto-hint, #pa-budget{ font-size: calc(12.5px * var(--ts)); }
.pauto-append{ font-size: calc(13px * var(--ts)); }
.pauto-append input{ width: calc(18px * var(--ts)); height: calc(18px * var(--ts)); }
.pleg select{ font-size: calc(12.5px * var(--ts)); min-height: calc(40px * var(--ts)); }
.pstyle .tbtn{ font-size: calc(13px * var(--ts)); min-height: calc(46px * var(--ts)); }
.pexp button, .pexp a{ font-size: calc(14px * var(--ts)); min-height: calc(48px * var(--ts)); }
.proute-card{ min-height: calc(46px * var(--ts)); }
.proute-card-mi{ font-size: calc(13px * var(--ts)); }
.proute-card-h{ font-size: calc(12px * var(--ts)); }
.proute-card-trade{ font-size: calc(10.5px * var(--ts)); }
.mrp-save-offline{ font-size: calc(13px * var(--ts)); min-height: calc(48px * var(--ts)); }

/* ROAD TYPE IN THE SETUP PANEL (2026-09-16)
   Dean: "I should be able to answer back roads / highways / interstate."
   Three across on a phone, scaled by --ts like every other control here, because a
   control that does not grow with the text is the half-done version of the feature. */
.pauto-ask{ margin: 14px 0 6px; font-weight: 600;
            font-size: calc(12.5px * var(--ts)); }
.pauto-mode--style{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.pauto-mode--style .tbtn{ font-size: calc(13px * var(--ts));
                          min-height: calc(48px * var(--ts));
                          padding-left: 4px; padding-right: 4px; }
#pa-style-hint{ margin: 6px 0 2px; }

/* DATES ON THE TRIP (2026-09-16)
   Dean: "I have to make it to Millville on the 25th for the race and then I need to make
   it to Bangor on Monday. In between, that is what I want to fill." */
.pby{ display: inline-flex; align-items: center; }
.pby label{ display: inline-flex; align-items: center; gap: 4px;
            font-size: calc(11px * var(--ts)); opacity: .8; }
.pby input[type="date"]{ font: inherit; font-size: calc(11.5px * var(--ts));
                         min-height: calc(34px * var(--ts)); padding: 2px 4px; }
.pdate{ opacity: .75; }
.pflag{ display: inline-block; margin-top: 3px; padding: 2px 7px; border-radius: 3px;
        font-size: calc(11px * var(--ts)); background: rgba(255,255,255,.09); }
.pflag--late{ background: #8c2f2f; color: #fff; }
.pdeadline{ margin: 10px 0; padding: 10px 12px; border-left: 3px solid var(--rule, #555);
            font-size: calc(13px * var(--ts)); line-height: 1.5; }
/* Late is the one state that has to be unmissable: it is the difference between a plan
   and a plan that does not work. */
.pdeadline--late{ border-left-color: #b63c3c; background: rgba(182,60,60,.12); }

/* WORTH STOPPING FOR (2026-09-16)
   Dean: "hey on your route there's a waterfall 1 mile off the road, it's a good stopping
   point, would you like to add that as a waypoint." */
.pnearby{ margin: 18px 17px 0; }
.pnearby h3{ margin: 0 0 4px; font-size: calc(15px * var(--ts)); }
.pnearby-lead{ margin: 0 0 10px; opacity: .75; font-size: calc(12px * var(--ts)); }
.pnearby-list{ list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.pnearby-list li{
  display: grid;
  /* label, name, distance, button — the name takes the slack so a long one wraps
     inside its own column instead of pushing the Add button off a phone screen */
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center; gap: 8px;
  padding: 8px 10px; border: 1px solid var(--rule, #3a3a3a); border-radius: 4px;
}
.pnear-t{ font-size: calc(10px * var(--ts)); text-transform: uppercase;
          letter-spacing: .05em; padding: 3px 7px; border-radius: 3px;
          background: rgba(255,255,255,.08); white-space: nowrap; }
.pnear-t[data-t="waterfall"]{ background: rgba(90,150,200,.22); }
.pnear-t[data-t="viewpoint"]{ background: rgba(120,170,110,.22); }
.pnear-t[data-t="bbq"]{ background: rgba(200,120,70,.22); }
.pnear-n{ font-size: calc(13px * var(--ts)); min-width: 0; overflow-wrap: anywhere; }
.pnear-d{ font-size: calc(11.5px * var(--ts)); opacity: .7; white-space: nowrap; }
.pnearby-list .tbtn{ font-size: calc(12px * var(--ts));
                     min-height: calc(40px * var(--ts)); padding: 0 12px; }
@media (max-width: 560px){
  /* Two rows on a phone: label + distance above, name and Add below. Four columns on a
     390px screen leaves the name about forty pixels, which is not a name. */
  .pnearby-list li{ grid-template-columns: auto 1fr auto; }
  .pnear-n{ grid-column: 1 / -1; order: 3; }
  .pnearby-list .tbtn{ order: 4; grid-column: 1 / -1; justify-self: start; }
}
/* The curated note — "Motorcycle-only campground", "Non-ethanol 90-octane pump" — is the
   reason a rider spot is worth more than a pin on a map, so it is shown, not hidden. */
.pnear-n em{ display:block; font-style:normal; opacity:.7;
             font-size: calc(11px * var(--ts)); margin-top:2px; line-height:1.35; }
.pnear-t[data-t="rider"]{ background: rgba(214,138,42,.28); font-weight:700; }
.pnear-t[data-t="shop"]{ background: rgba(140,140,160,.2); }

/* MAP CONTROLS, SIZED FOR A GLOVE (2026-09-16)
   MapLibre ships 29px buttons. That is fine for a mouse and wrong for a cold thumb on a
   phone clamped to a bar, which is where this map is actually used. Found by measuring
   every tap target on the page rather than the ones I had just changed. */
.maplibregl-ctrl button{ width: 44px; height: 44px; }
.maplibregl-ctrl button .maplibregl-ctrl-icon{ background-size: 22px 22px; }
/* MapLibre draws the (i) as a 24px background image that repeats by default; grown to 34px
   it tiled a half (i) beside and below the real one once Home opened collapsed. */
.maplibregl-ctrl-attrib-button{ width: 34px; height: 34px;
  background-repeat: no-repeat; background-position: center; background-size: 22px 22px; }
/* Collapsed, the box and the button are one 34px circle; tapped open, MapLibre's own layout. */
.maplibregl-ctrl-attrib.maplibregl-compact:not(.maplibregl-compact-show){
  width: 34px; height: 34px; min-height: 34px; padding: 0; border-radius: 50%;
  background: transparent; box-shadow: none; }
.maplibregl-ctrl-attrib.maplibregl-compact:not(.maplibregl-compact-show) .maplibregl-ctrl-attrib-button{
  top: 0; left: 0; right: auto; border-radius: 50%; background-color: var(--surface, #fff);
  box-shadow: 0 1px 4px rgba(0,0,0,.18); }
/* The library's (i) is a black image; inverting a light circle gives a dark one with a light (i). */
html[data-theme="dark"] .maplibregl-ctrl-attrib.maplibregl-compact:not(.maplibregl-compact-show) .maplibregl-ctrl-attrib-button{
  background-color: #EEEAE2; filter: invert(1); }

/* WBH-4489: squared white boxes next to screen 11's round controls read as two different
   products. Round them to match ride.html's control language, but theme-aware - this
   screen, unlike the riding one, is used in daylight too and carries a light theme. */
.pln-map .maplibregl-ctrl-group{
  background: transparent; box-shadow: none; border-radius: 0;
  display: flex; flex-direction: column; gap: 10px;
}
.pln-map .maplibregl-ctrl-group button{
  border-radius: 50%;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 6px 18px rgba(0,0,0,.25);
  border: 1px solid var(--rule);
}
.pln-map .maplibregl-ctrl-group button + button{ border-top: 0; }

/* WHAT YOU RIDE FOR (2026-09-16)
   Dean: "we talked about curvy is a metric for Sport." Same scale as every other control
   in this panel, because a selector that does not grow with the text is the half-done
   version of the accessibility work. */
.pauto-sel{ width: 100%; font: inherit; font-size: calc(13.5px * var(--ts));
            min-height: calc(48px * var(--ts)); padding: 0 10px;
            border: 1px solid var(--rule, #3a3a3a); background: var(--surface);
            color: inherit; }
#pa-rider-hint{ margin: 6px 0 2px; }

/* THE DIAL (2026-09-16) — making time against doing the ride.
   The slider itself is deliberately tall: this gets adjusted with gloves on, at a petrol
   station, by somebody who has just decided they have an extra afternoon. */
.pauto-dial{ display: grid; grid-template-columns: auto 1fr auto; align-items: center;
             gap: 10px; }
.pauto-dial span{ font-size: calc(11px * var(--ts)); opacity: .7; white-space: nowrap; }
.pauto-dial input[type="range"]{ width: 100%; height: calc(34px * var(--ts));
                                 accent-color: var(--orange, #d68a2a); }

/* ------------------------------------------------------------------ the dial
   Dean asked for an actual amplifier knob and sent a brass one. Built in brass, he
   said "pretty blah" - and he was right, because brass is nobody's brand colour here.

   The approved identity (WBH-4269, logo-set-imagegen-v3) settles what it should be:
   WARM BRUSHED SILVER with the route accent in orange. That is the logo's own
   material - brushed metal letters with an orange road carved through them - so the
   one skeuomorphic control on this site now speaks the identity instead of a stock
   amp photo. mrp-brand-colors.json names it "warm brushed silver" and
   orange_on_dark #FF5B12, which is var(--orange); this pulls the variable rather
   than the hex so it cannot drift from the palette.

   The range input underneath stays focusable and keyboard-operable. It is moved
   off-screen rather than display:none, because display:none removes it from the tab
   order and takes the arrow keys with it. */
.pauto-dial.knob{display:flex;align-items:center;justify-content:center;gap:14px;
  flex-wrap:wrap;margin:10px 0 2px}
.knob .knob-end{font-size:calc(12px * var(--ts));color:var(--steel);
  text-transform:uppercase;letter-spacing:.07em;font-weight:700;white-space:nowrap}
.knob-stage{position:relative;width:140px;height:140px;flex:none}
.knob-ticks{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
/* Unlit ticks are dark steel. Lit ones take the colour and weight computed per tick
   in plan.js - orange at the bottom of the sweep, hot red by eleven, and getting
   heavier as they climb. */
.knob-ticks line{stroke:#4a4a4a;stroke-width:2;stroke-linecap:round;
  transition:stroke .12s linear, stroke-width .12s linear}
.knob-ticks line.on{stroke:var(--lit, var(--orange));stroke-width:var(--w, 3)}

/* ELEVEN. Dean: "turned up to 11 should be EXTREME!!!"
   The rim runs hot, the pointer goes red, and the 11 on the face lights up. This is
   the only element on the site that glows, which is what makes it mean something.
   The pulse is motion, so it is removed for anyone who asked for less of it. */
.knob.maxed .knob-body{box-shadow:0 7px 18px rgba(0,0,0,.6),
  inset 0 0 0 1px rgba(255,255,255,.28), inset 0 2px 3px rgba(255,255,255,.35),
  0 0 0 3px rgba(255,32,10,.55), 0 0 26px 6px rgba(255,32,10,.45);
  animation:knob-hot 1.5s ease-in-out infinite}
.knob.maxed .knob-pointer{background:#ff2410;
  box-shadow:0 0 12px rgba(255,36,16,.95), 0 1px 1px rgba(0,0,0,.6)}
.knob.maxed .knob-pointer::after{background:#ff2410;
  box-shadow:0 0 14px rgba(255,36,16,1)}
.knob.maxed .knob-max{color:#ff2410;text-shadow:0 0 10px rgba(255,36,16,.8);
  transform:scale(1.35);transform-origin:right bottom}
@keyframes knob-hot{
  0%,100%{box-shadow:0 7px 18px rgba(0,0,0,.6),
    inset 0 0 0 1px rgba(255,255,255,.28), inset 0 2px 3px rgba(255,255,255,.35),
    0 0 0 3px rgba(255,32,10,.45), 0 0 22px 4px rgba(255,32,10,.35)}
  50%{box-shadow:0 7px 18px rgba(0,0,0,.6),
    inset 0 0 0 1px rgba(255,255,255,.28), inset 0 2px 3px rgba(255,255,255,.35),
    0 0 0 4px rgba(255,32,10,.75), 0 0 34px 9px rgba(255,32,10,.6)}}
.knob-max{transition:color .15s linear, transform .15s ease-out, text-shadow .15s linear}
@media (prefers-reduced-motion:reduce){.knob.maxed .knob-body{animation:none}}

/* Brushed silver: fine radial striations, a soft dome highlight over them, and a
   machined rim. The striations are one repeating-conic-gradient rather than
   sixty elements. */
.knob-body{position:absolute;left:14px;top:14px;width:112px;height:112px;
  border-radius:50%;cursor:grab;touch-action:none;
  background:
    radial-gradient(circle at 36% 28%, rgba(255,255,255,.55) 0%,
                                       rgba(255,255,255,.10) 34%,
                                       rgba(0,0,0,.30) 78%,
                                       rgba(0,0,0,.50) 100%),
    repeating-conic-gradient(from 0deg,
      #d5d1cb 0deg 1.6deg, #b3aea7 1.6deg 3.2deg,
      #c8c3bc 3.2deg 4.8deg, #a49f98 4.8deg 6.4deg),
    repeating-conic-gradient(#2e2b28 0deg 3deg, #171514 3deg 6deg);
  background-clip:content-box, content-box, border-box;
  border:8px solid transparent;
  box-shadow:0 7px 18px rgba(0,0,0,.6),
             inset 0 0 0 1px rgba(255,255,255,.28),
             inset 0 2px 3px rgba(255,255,255,.35);}
.knob-body:active{cursor:grabbing}

/* The pointer is the road accent from the logo: orange, running out from the centre. */
.knob-pointer{position:absolute;left:50%;top:9%;width:6px;height:37%;
  margin-left:-3px;border-radius:3px;background:var(--orange);
  box-shadow:0 0 7px rgba(255,91,18,.75), 0 1px 1px rgba(0,0,0,.6)}
.knob-pointer::after{content:"";position:absolute;left:50%;bottom:-9px;width:7px;
  height:7px;margin-left:-3.5px;border-radius:50%;background:var(--orange);
  box-shadow:0 0 8px rgba(255,91,18,.85)}

.knob-min,.knob-max{position:absolute;bottom:-2px;font-size:13px;font-weight:800;
  color:var(--steel);font-family:var(--gothic);letter-spacing:.04em}
.knob-min{left:0}.knob-max{right:0}

.knob:has(input[type=range]:focus-visible) .knob-body{outline:3px solid var(--orange);
  outline-offset:5px}
.knob input[type=range]{position:absolute;left:-9999px;width:10px;height:10px;opacity:0}
@media (prefers-reduced-motion:reduce){.knob-ticks line{transition:none}}


/* THE RIDER MARKER (2026-09-17).
   Dean: "Can we make the icon for the rider different? Maybe based on the bike in the
   garage?" MapLibre draws a blue dot and a pulsing ring; both are replaced here by the
   bike silhouette that plan.js builds from the garage segment. The ring goes because a
   pulse under a vehicle icon reads as an alert rather than as a position. */
.maplibregl-user-location-dot.mrp-rider,
.maplibregl-user-location-dot.mrp-rider::before {
  background-color: transparent;
  box-shadow: none;
  animation: none;
}
.maplibregl-user-location-dot.mrp-rider {
  width: 44px; height: 44px;
  background-repeat: no-repeat;
  background-size: 44px 44px;
  border-radius: 0;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.55));
}
.maplibregl-user-location-dot.mrp-rider::after { display: none; }


/* Surface doubt, in the trip list. Amber and not red: this says WE DO NOT KNOW, not that
   the road is bad. 13,558 roads carry su:'assumed' - OSM has no surface tag and we let
   them through because they are classified routes, which is usually right and sometimes
   gravel. The marker existed since the promotion pass and reached no screen until now. */
.pstop-surf { color: #b8860b; font-style: normal; }
@media (prefers-color-scheme: dark) { .pstop-surf { color: #eab308; } }

/* The time budget, said at the size of the decision it drives. */
.pauto-budget { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  margin: .35rem 0 1rem; padding: .7rem .9rem; border-radius: 10px;
  background: rgba(255,122,26,.10); border: 1px solid rgba(255,122,26,.30); }
.pauto-budget-lab, .pauto-budget-sub { opacity: .8; font-size: .95rem; }
.pauto-budget-big { font-size: 2.1rem; line-height: 1; font-weight: 700; letter-spacing: .01em; }
.pauto-hint--soft { opacity: .78; font-size: .92em; line-height: 1.4; margin-top: 4px; }

/* THE WAY TO NAVIGATION.
   The app opens on this page, so the first frame has to carry the one thing a rider
   opened it for. WBH-4489: it used to be a full-width "Ride there now" bar; the brief
   draws one pill here instead - a back arrow and the screen's name - so that is what
   this now styles. Hidden on the website, which already has a masthead; shown fixed
   over the map in the app only, in the APP SCREEN block below. */
.pln-topbar { display: none; align-items: center; gap: .6rem; }
.pln-back { display: grid; place-items: center; flex: 0 0 auto; color: inherit; }
/* An author `display` beats the browser's own [hidden] rule, so .pln-back above was
   rendering the arrow on the app's home screen even with the attribute set: a control
   that looked live and did nothing, since js/plan.js only wires the click when there is
   somewhere to go back to. Same cascade trap as the .pauto-more <details> controls. */

.pln-topbar-t { font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; }

/* IN THE APP, THE SALES PITCH IS NOISE.
   "86,282 roads measured, free GPX on every one" is for a stranger deciding whether to
   try this. The man with it installed on his phone has decided. It also sat directly
   above the navigation bar in the same orange, so the first frame showed two accent
   blocks and the one that was actually a button did not read as one. */
body.in-app .promo { display: none; }

/* ALREADY RIDDEN. A quiet fact beside the name, not a warning and not a strikethrough:
   he may well want to ride it again, and the one thing this must not do is look like
   the road is unavailable. */
.pres-rid { display: inline-block; margin-left: .5rem; padding: .08em .45em;
  border-radius: 999px; font-style: normal; font-size: .68em; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; vertical-align: middle;
  background: rgba(255,122,26,.16); border: 1px solid rgba(255,122,26,.38);
  color: inherit; opacity: .9; white-space: nowrap; }

/* HELMET LAW STRIP. Dean's design: hair means ride free, hair with an asterisk means
   free with a catch, a full face means no way out. Two icons and an asterisk rather
   than three icons, because the rider wants to know what to DO, not which legal
   bucket a state sits in. */
.phel { margin: 0 0 1rem; }
.phel-row { display: flex; flex-wrap: wrap; gap: .45rem; }
.phel-s { display: inline-flex; align-items: center; gap: .35rem; position: relative;
  padding: .3rem .6rem .3rem .45rem; border-radius: 999px; font-size: .9rem;
  border: 1px solid rgba(128,128,128,.35); }
.phel-s svg { width: 20px; height: 20px; fill: currentColor; flex: 0 0 auto; }
.phel-s b { font-weight: 700; letter-spacing: .02em; }
.phel-s i { font-style: normal; opacity: .78; font-size: .86em; }
/* The asterisk rides on the icon, not in the text, so it reads at a glance. */
.phel-s u { position: absolute; left: 1.45rem; top: .12rem; text-decoration: none;
  font-weight: 800; line-height: 1; font-size: .95rem; color: #ff7a1a; }
/* Required is the one that costs you if you get it wrong, so it is the one with colour. */
.phel-s--universal { background: rgba(255,122,26,.14); border-color: rgba(255,122,26,.45); }
.phel-s--none, .phel-s--partial { background: rgba(128,128,128,.10); }
.phel-note { margin: .4rem 0 0; font-size: .8rem; opacity: .7; line-height: 1.4; }
/* It is a button now, so it must not look like one of the page's buttons. */
.phel-s { font: inherit; cursor: pointer; text-align: left; color: inherit; }
/* On a phone the condition is hidden to keep the strip glanceable, and revealed on tap.
   `title` is hover-only, so without this the asterisk promises a catch the rider on the
   actual device can never read. */
@media (max-width: 430px) {
  .phel-s i { display: none; }
  .phel-s--open { flex: 1 1 100%; border-radius: 12px; }
  .phel-s--open i { display: block; }
}


/* ========================= THE APP SCREEN =========================
   Dean, 2026-10-07, with two videos side by side: ours and Google Maps.
   "Look at the difference between these two." "It is clunky and hard to navigate."

   He was right and the diagnosis was not what I expected. Nothing was missing. The
   app-shape fix had already removed the website chrome and put the four-verb bar at the
   bottom. What was left underneath was still a PAGE: a tracking banner, then a Ride
   There bar, then a map squeezed into a 52vh band, then a paragraph explaining that your
   trip is saved in the web address, then "Give me a ride" - and only two screens down,
   the thing the product exists for: "You have 3 HOURS of riding, about 126 miles".

   Google gives the map the whole screen and floats one search bar, two round buttons and
   a draggable sheet on top of it. Nothing stacks. Nothing scrolls past the thing you came
   for. That is the entire difference, and it is layout, not features.

   So on a phone IN THE APP ONLY - the website and the desktop grid are untouched, because
   they work and Dean uses them - the same components are recomposed:
     the map owns the screen
     the prose goes
     everything else becomes a sheet resting on the bottom, one thumb from the top of it
   ================================================================= */
@media (max-width:900px){
  html[data-app] .pln{display:block;height:auto}

  /* The map IS the screen, not a band in a stack. Fixed, behind everything, under the
     floating controls it already has - rain, locate, layers - which keep working because
     they were already absolutely positioned over it. */
  html[data-app] .pln-map{position:fixed;inset:0;height:auto;min-height:0;order:0;z-index:0}

  /* The sheet. Rests at the bottom showing its handle and the first control, and is
     dragged or scrolled up to the full height. 58vh is deliberate: it leaves the map
     readable above it, which is the whole reason the map is full-bleed. */
  html[data-app] .pln-side{
    position:fixed;left:0;right:0;z-index:4;
    bottom:calc(56px + env(safe-area-inset-bottom,0px));
    max-height:58vh;border-right:0;border-top:1px solid var(--rule);
    border-radius:16px 16px 0 0;overflow:auto;-webkit-overflow-scrolling:touch;
    box-shadow:0 -14px 34px rgba(0,0,0,.55);
    background:color-mix(in srgb, var(--surface) 96%, transparent)}

  /* The grab handle, so it reads as a sheet before anyone touches it. */
  html[data-app] .pln-side::before{
    content:"";position:sticky;top:0;display:block;width:38px;height:4px;
    margin:8px auto 2px;border-radius:2px;background:var(--steel);opacity:.55}

  /* THE PARAGRAPH GOES. "Your trip is saved in the web address, so bookmark it to keep
     it" is website copy explaining a web mechanic to someone holding an app. It sat
     between the map and the product. */
  html[data-app] .pbar p{display:none}
  html[data-app] .pbar{padding:2px 17px 10px;border-bottom:0;background:none}
  html[data-app] .pbar h1{font-size:13px;letter-spacing:.08em;text-transform:uppercase;
    color:var(--steel);font-weight:800}

  /* WBH-4489: the brief draws one pill over the map here - a back arrow and the screen's
     name - replacing the full-width "Ride There Now" bar that used to run this strip. It
     gets its own surface so it reads over any terrain color underneath it. The right inset
     clears MapLibre's own zoom column, which lives top-right - the lesson the old banner
     taught when it ran straight under the + and - buttons. */
  html[data-app] .pln-topbar{display:flex;position:fixed;left:12px;right:70px;z-index:5;
    top:calc(10px + env(safe-area-inset-top,0px));
    padding:.55rem .9rem;border-radius:14px;
    background:color-mix(in srgb, var(--surface) 90%, transparent);
    backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
    box-shadow:0 10px 26px rgba(0,0,0,.4);border:1px solid var(--rule)}

  /* WBH-4489: Recentre has no equivalent in the brief, so it is docked rather than removed -
     it only appears when the rider has panned away while tracking, and losing the way back
     to themselves would be worse than the clutter. It used to float across the top and
     print over the Ride There pill; docked above the sheet's handle instead, by the thumb,
     like a map app's own recentre control, it never contests the top bar for the same strip. */
  html[data-app] .precentre{position:fixed;left:auto;right:12px;transform:none;
    bottom:calc(120px + env(safe-area-inset-bottom,0px));
    width:auto;margin:0;padding:0 16px;min-height:40px;z-index:5;
    border-radius:20px;box-shadow:0 8px 20px rgba(0,0,0,.45);font-size:13px}

  /* The product goes first inside the sheet, not after a heading and a lead line. */
  html[data-app] .pauto{padding-top:4px}
  html[data-app] .pauto-lead{display:none}
}

/* ---------------- APP DENSITY ----------------
   Dean, 2026-10-07, after the sheet landed: "This still looks like huge check boxes from
   the Internet. It does not look like a mobile app at all."

   Measured on a 390x844 phone before this block, and he is being generous:

     --ts                1.5          the site's rider text scale
     Loop / Ride to      72 px each
     Give me a ride      81 px
     Start field         72 px
     Use my location     72 px
     time budget         85 px
     sheet content     2723 px        inside a 490 px window

   Apple's minimum tap target is 44. Ours are 64 to 93 PER CENT bigger than the minimum,
   full width, stacked - which is exactly what a web form looks like, because that is what
   it is. The sheet fixed where the controls sit; it did nothing about how big they are.

   THE SIZE IS NOT AN ACCIDENT AND MOST OF IT STAYS. --ts is 1.5 because Dean reads this
   through a visor and large text is this product's default, which is right. But --ts was
   being multiplied into the BOX as well as the type: every min-height is calc(48px * --ts).
   Type scales for the eyes; chrome should not scale with it. So the type keeps --ts and
   the boxes get native heights.

   The riding screen is deliberately untouched - that one is read at 60 mph and is the one
   place these sizes earn themselves. Planning happens stopped. */
@media (max-width:900px){
  html[data-app] .pauto-mode{display:grid;grid-template-columns:1fr 1fr;gap:6px}
  html[data-app] .pauto-mode .tbtn{min-height:44px;font-size:calc(13px * var(--ts, 1));
    padding:0 10px}
  html[data-app] #pa-go{min-height:50px;font-size:calc(14px * var(--ts, 1))}
  html[data-app] .pauto-field input,
  html[data-app] #pa-start,
  html[data-app] #pa-dest{min-height:46px;font-size:calc(13.5px * var(--ts, 1))}
  html[data-app] .pauto-here{min-height:40px;font-size:calc(11px * var(--ts, 1))}
  html[data-app] .pauto-sug button{min-height:42px;font-size:calc(12.5px * var(--ts, 1))}

  /* The budget is the product and keeps its size; it just stops carrying a block of
     padding that belongs on a desktop card. */
  html[data-app] .pauto-budget{padding:8px 12px}

  /* Section labels were full-size headings between every control. In an app they are
     captions on the thing below them. */
  html[data-app] .pauto h2{font-size:calc(15px * var(--ts, 1));margin:0 0 6px}
  html[data-app] .pauto > *{margin-top:8px}
  html[data-app] .pauto{padding-left:12px;padding-right:12px}
}

@media (max-width:900px){
  /* The disclosure that holds the dials. Reads as one row until it is wanted. */
  html[data-app] .pauto-more{border:1px solid var(--rule);border-radius:10px;
    background:var(--panel);margin-top:8px}
  html[data-app] .pauto-more > summary{list-style:none;cursor:pointer;
    min-height:44px;display:flex;align-items:center;padding:0 12px;
    font-size:calc(12.5px * var(--ts, 1));font-weight:800;letter-spacing:.06em;
    text-transform:uppercase;color:var(--steel)}
  html[data-app] .pauto-more > summary::-webkit-details-marker{display:none}
  html[data-app] .pauto-more > summary::after{content:"+";margin-left:auto;font-size:17px;
    font-weight:700;color:var(--orange)}
  html[data-app] .pauto-more[open] > summary::after{content:"\2212"}
  html[data-app] .pauto-more > *:not(summary){margin:0 12px 10px}
  /* The shape and style rows were wrapping to 94px because two long labels will not sit
     side by side at this width. In the disclosure they get the room to stack. */
  html[data-app] .pauto-mode--shape,
  html[data-app] .pauto-mode--style,
  html[data-app] .pauto-mode--scenery{display:grid;grid-template-columns:1fr 1fr;gap:6px}
}

@media (max-width:900px){
  /* DAYS, HOURS, MILES ARE ONE QUESTION, NOT THREE SCREENS.
     Measured: each was a full-width 72 px field with its own 20 px label above it, so
     "how long have you got" cost 276 px of a 490 px sheet and pushed Go off the bottom.

     The first attempt put them in a three-column grid and let the labels auto-place. The
     DOM order is label, input, label, input, label, input, so they interleaved and the
     render came back with DAYS on one side, a bare 1 in the middle and HOURS A DAY
     wrapping to two lines - worse than what it replaced. Caught by looking at it.

     So the captions go into the fields instead of above them. One row, three numbers,
     each saying what it is. Fewer elements to place and nothing to interleave. */
  html[data-app] .pauto-grid{display:grid;grid-template-columns:1fr 1fr 1fr;
    gap:4px 8px;align-items:end}
  html[data-app] .pauto-grid > label{grid-column:1/-1;margin:4px 0 0;
    font-size:calc(10.5px * var(--ts, 1));letter-spacing:.07em;text-transform:uppercase;
    color:var(--steel)}
  html[data-app] .pauto-grid > .pauto-field,
  html[data-app] .pauto-grid > #pa-start{grid-column:1/-1}
  /* The three numbers each sit in their own cell with their caption above, instead of
     the caption being hidden. See the comment on .pauto-num in build-heritage.py: the
     old rule removed the labels from the screen AND from the accessibility tree. */
  html[data-app] .pauto-grid > .pauto-num{grid-column:auto;display:flex;
    flex-direction:column;gap:3px;min-width:0}
  /* No letter-spacing and a hair smaller: "HOURS A DAY" is the longest of the three and
     at 10px + .06em it ellipsised to "HOURS A D..." in a 112px column. A caption that
     truncates is most of the way back to having no caption. */
  html[data-app] .pauto-grid > .pauto-num > label{grid-column:auto;margin:0;
    font-size:calc(9.5px * var(--ts, 1));letter-spacing:0;text-transform:uppercase;
    color:var(--steel);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  html[data-app] #pa-days,
  html[data-app] #pa-hours,
  html[data-app] #pa-miles{grid-column:auto;min-height:46px;width:100%;max-width:none;
    font-size:calc(14px * var(--ts, 1));text-align:center;padding:0 4px}
}

/* ---------------- STOP DRAWING BOXES ----------------
   Dean, 2026-10-07, third pass: "You're still using big ugly check boxes when the UI
   doesn't need to be that way."

   He is right and shrinking them was answering the wrong question. The problem is not
   that the controls are large, it is that they are BORDERED FORM FIELDS at all. Every
   value on this screen sat in its own outlined rectangle because that is what a web form
   is made of. No app on this phone looks like that: iOS groups settings into one card and
   separates the rows with hairlines, with the label on the left and the value on the
   right. The box around each value is the thing that says "website", not its height.

   So in app mode the fields stop being boxes and become rows of a grouped list:
   no per-field border, no per-field background, one surrounding card, hairline dividers,
   values right-aligned. Same inputs, same JS, same behaviour - different vocabulary.

   [data-app] on phones only. The website keeps its form; it is a form, on a desktop,
   and it works. */
@media (max-width:900px){
  html[data-app] .pauto-grid{
    background:var(--surface);border:1px solid var(--rule);border-radius:12px;
    padding:2px 12px;gap:0;overflow:hidden}

  /* A row, not a field. The hairline is on the row, so the last one has none. */
  html[data-app] .pauto-grid > .pauto-field,
  html[data-app] .pauto-grid > input{
    background:none;border:0;border-bottom:1px solid var(--rule);border-radius:0;
    padding:0;min-height:48px}
  html[data-app] .pauto-grid > input{text-align:right;padding-right:2px}
  html[data-app] .pauto-grid > .pauto-field input{
    background:none;border:0;border-radius:0;min-height:48px;padding:0;text-align:right}
  html[data-app] .pauto-grid > *:last-child{border-bottom:0}

  /* The three numbers keep their own row but lose their outlines too. */
  html[data-app] #pa-days,
  html[data-app] #pa-hours,
  html[data-app] #pa-miles{
    background:none;border:0;border-bottom:1px solid var(--rule);border-radius:0;
    text-align:center;min-height:48px}

  /* Use my location becomes the action inside the row it belongs to, the way a maps app
     puts a locate glyph in the search field, rather than a full-width outlined slab. */
  html[data-app] .pauto-here{
    background:none;border:0;min-height:44px;padding:0 2px;
    color:var(--orange);font-size:calc(11.5px * var(--ts, 1));
    letter-spacing:.06em;text-transform:uppercase;width:auto;margin:0}

  /* The one button that SHOULD look like a button is the one that does the thing. */
  html[data-app] #pa-go{border-radius:10px;margin-top:10px}

  /* Section captions sit above their card, quiet, like a settings group header. */
  html[data-app] .pauto-grid + label,
  html[data-app] .pauto > label{font-size:calc(10.5px * var(--ts, 1));
    letter-spacing:.08em;text-transform:uppercase;color:var(--steel);
    margin:12px 2px 5px;display:block}
}

@media (max-width:900px){
  /* The grab handle is a real button, full width, 34 px tall, so it is hit with a glove
     without aiming. The ::before pseudo-handle from the first sheet is retired - a
     decoration that looks draggable and is not is worse than no affordance at all. */
  html[data-app] .pln-side::before{content:none}
  html[data-app] .pln-grab{display:block;width:100%;min-height:34px;border:0;padding:0;
    background:none;cursor:pointer;position:sticky;top:0;z-index:2}
  html[data-app] .pln-grab i{display:block;width:40px;height:4px;margin:11px auto;
    border-radius:2px;background:var(--steel);opacity:.7}
  html[data-app] .pln-grab:focus-visible{outline:2px solid var(--orange);outline-offset:-2px}

  /* Peek: the handle and a sliver, so the map gets the screen back. */
  html[data-app] .pln-side.is-peek{max-height:52px;overflow:hidden}

  /* The "Not tracking / Start ride" strip at the very top is NOT ours - it is native
     SwiftUI chrome from ContentView, above the web view. CSS cannot reach it and the two
     rules I first wrote here targeted classes that do not exist on this page. Shrinking it
     is a Swift change and a new build. Noted, not faked. */
}



/* ================= SCREENS 01/02, RESTYLED IN PLACE =================
   Design brief, 8 October 2026 (Ray/Astra), supersedes "Ride Setup Before Navigation"
   (27 September) per that brief's own authority clause. The 27-Sept pass built a second
   sheet that floated ON TOP of this one and hid it (.d1, body.d1-on) - a fifth screen,
   not the four already rendered above it. This restyle does not repeat that: there is no
   second sheet. The existing .pln-side / .pln-grab / .pauto-grid / .pauto-more IS screen
   01/02, with the deltas the new brief actually asks for added directly to it below -
   ride-time steppers on the existing budget hero, and a full-screen take on the existing
   #presults. Nothing here is a new screen; everything targets an id or class that was
   already live on this page. */

/* Ride-time steppers. Hidden on the desktop/website row - same markup, only the
   buttons differ - and shown only where the brief asked for them: app, phone width. */
.pauto-budget-row{display:inline-flex;align-items:baseline;gap:.4rem}
.pauto-step{display:none}
@media (max-width:900px){
  html[data-app] .pauto-budget-row{gap:.6rem}
  html[data-app] .pauto-step{display:inline-flex;align-items:center;justify-content:center;
    width:44px;height:44px;min-width:44px;min-height:44px;border-radius:50%;
    border:1px solid var(--rule);background:var(--panel);color:var(--orange);
    font-size:20px;font-weight:700;line-height:1;cursor:pointer;flex:0 0 auto}
  html[data-app] .pauto-step:active{background:var(--orange);color:var(--white)}
}

/* Units override pill (mi/km). The locale default in js/plan.js already serves the
   desktop page correctly, so the override control itself is app+phone only, same as
   the steppers above - see js/app-first.js and WBH-4474/4477. */
.pauto-unit{display:none}
@media (max-width:900px){
  html[data-app] .pauto-unit{display:flex;gap:8px;margin:8px 0 0}
  html[data-app] .pauto-unit .tbtn{flex:0 0 64px;min-height:44px}
}

/* A circular glyph per result row, plus a badge for what is already known about the
   road: "Guide available" when a guide page exists (r.u), "Road details" when the road
   is in the catalogue but has no guide page yet (r.kn and not r.u). Runs everywhere -
   it is a small, additive mark on an existing row, not a layout change - so the plain
   dropdown on desktop gets it too. */
.pres{display:flex;align-items:flex-start;gap:10px}
.pres-glyph{width:28px;height:28px;border-radius:50%;flex:0 0 auto;margin-top:1px;
  border:1px solid var(--rule)}
/* Fill/icon now come from the shared .poi-glyph/.poi-glyph--road classes
   (css/poi-markers.css, P0-THM-09-web) added alongside these in the markup. */
.pres-body{flex:1;min-width:0}
.pres-badge{display:inline-block;margin-top:4px;padding:.12em .55em;border-radius:999px;
  font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  background:rgba(255,91,18,.14);border:1px solid rgba(255,91,18,.4);color:var(--orange)}
.pres-badge--known{background:rgba(128,128,128,.14);border-color:var(--rule);color:var(--steel)}

/* SEARCH RESULT PINS (P0-SRC-04, mock-009): one small pin per result while the list is
   open, white with the same category glyph as its row's icon until selected, then
   orange like the single destination pin. A real button (not a div) so it is reachable
   and labelled, not just a decoration riders cannot actually tap.
   Shape/colour/icon come from the shared .poi-marker/.poi-marker--CAT classes
   (css/poi-markers.css, P0-THM-09-web) added alongside .pres-pin in the markup; the
   pointed pin shape itself (c1106 repair, REDESIGN-AUDIT-10 S04) is defined there too,
   under .pres-pin, because it has to win against .poi-marker's own circle at equal
   specificity and this file loads first. .pres-pin here only sets cursor. */
.pres-pin{cursor:pointer}

/* Cancel sits beside the search field and only shows when there is a full-screen list
   to leave. Wired in js/app-first.js, which also owns the steppers above. */
.psearch-row{display:flex;align-items:center;gap:8px}
.psearch-row input{flex:1;min-width:0}
.psearch-cancel{display:none;flex:0 0 auto;border:0;background:none;font:inherit;
  color:var(--orange);font-weight:700;cursor:pointer;padding:0 2px}

/* Website keeps its plain dropdown; the heading belongs to the app's results sheet. */
.presults-head{display:none}

@media (max-width:900px){
  /* SEARCH RESULTS (brief, mock-009): the list is the bottom sheet, the map stays above
     it and the query stays in the search bar.

     This used to be a full-screen takeover that nobody ever saw: the Home allow-list
     hid .psearch-wrap with !important and the takeover had none, so typing a road on
     Home dropped pins on the map and showed nothing else (gap audit, 2026-10-28). The
     allow-lists now exempt .psearch-wrap, and these rules own it. :has() watches
     #presults' own hidden attribute, so every path that fills or empties the list
     already drives this; no JS state. While the list shows it IS the sheet, in every
     state: on Home a row opens the destination card, with a route or in Edit stops a
     row is added as a stop (js/plan.js). */
  html[data-app] .pln-side > .psearch-wrap:not(:has(#presults:not([hidden]))):not(:is(.show-dials:not([data-psheet]) *)){
    display:none !important}
  html[data-app]:has(#presults:not([hidden])) .pln-side > *:not(.pln-grab):not(.psearch-wrap){
    display:none !important}
  /* R2 (c1106/ios-reach, S04): `top:61dvh;bottom:0` sized this sheet against the FULL
     viewport. `dvh` tracks browser-chrome changes (Safari's URL bar); it does not shrink
     for the on-screen keyboard inside a native app's WKWebView, which has no browser
     chrome of its own to resize -- so with the keyboard open this fixed box sat almost
     entirely behind it (keyboard ~39-45% of screen height, same as the 39dvh this left
     for the sheet), and the list never visibly rendered. js/planner-sheet.js already
     measures the real keyboard height every resize via visualViewport and now publishes
     it as --mrp-kb; anchoring from the bottom with that inset (instead of a fixed 0) and
     giving the sheet its own max-height (instead of pinning its top) keeps the same
     ~39dvh of sheet both with and without a keyboard, always above it. */
  html[data-app]:has(#presults:not([hidden])) .pln-side{
    position:fixed!important;left:0!important;right:0!important;top:auto!important;
    bottom:var(--mrp-kb,0px)!important;
    height:39dvh!important;min-height:0!important;max-height:39dvh!important;overflow:hidden!important}
  html[data-app]:has(#presults:not([hidden])) .pln-side > .psearch-wrap{
    display:block !important;position:static;flex:1 1 auto;min-height:0;overflow-y:auto;
    overscroll-behavior:contain;padding:0 16px 16px;background:var(--surface)}
  html[data-app]:has(#presults:not([hidden])) .psearch-wrap > :not(#presults-head):not(#presults){
    display:none !important}
  html[data-app] #presults-head{display:flex;align-items:baseline;justify-content:space-between;
    gap:12px;margin:0 0 8px}
  html[data-app] #presults-head h2{margin:0;font-family:system-ui,-apple-system,"Segoe UI",sans-serif;
    font-size:calc(23px * var(--home-scale, 1));line-height:1.15;font-weight:800;letter-spacing:-.02em;
    color:var(--ink);text-transform:none}
  html[data-app] #presults-count{font-size:calc(15px * var(--home-scale, 1));color:var(--steel);white-space:nowrap}
  html[data-app] .psearch-wrap #presults{position:static;display:flex;flex-direction:column;gap:8px;
    max-height:none !important;overflow:visible;margin:0;padding:0;border:0;
    border-radius:0;box-shadow:none;background:none}
  html[data-app] .psearch-wrap #presults .pres{display:flex;align-items:center;gap:14px;width:100%;
    min-height:52px;margin:0;padding:6px 38px 6px 8px;position:relative;box-sizing:border-box;
    background:var(--panel);border:1px solid var(--rule);border-radius:12px;color:var(--ink);
    text-align:left;font-family:system-ui,-apple-system,"Segoe UI",sans-serif;cursor:pointer}
  html[data-app] .psearch-wrap #presults .pres::after{content:"\203A";position:absolute;right:14px;top:50%;
    transform:translateY(-50%);font-size:24px;line-height:1;color:var(--steel)}
  html[data-app] .psearch-wrap #presults .pres-glyph{width:36px;height:36px;margin:0;
    background:var(--chrome2);border:0}
  html[data-app] .psearch-wrap #presults .pres-glyph--road{background:var(--orange)}
  html[data-app] .psearch-wrap #presults .pres-body b{display:block;font-size:calc(14px * var(--home-scale, 1));
    line-height:1.25;font-weight:700;color:var(--ink)}
  html[data-app] .psearch-wrap #presults .pres-body > span{display:block;margin-top:2px;
    font-size:calc(11px * var(--home-scale, 1));line-height:1.2;color:var(--steel)}
  html[data-app] .psearch-wrap #presults .pres-badge{font-size:9px;line-height:1.2;letter-spacing:0;text-transform:none;
    font-weight:600;padding:1px 6px;border-radius:5px;color:#181B1A;background:color-mix(in srgb, var(--orange) 22%, var(--panel));
    border:0}
  html[data-app] .psearch-wrap #presults .pres-badge--known{color:var(--ink);background:var(--chrome2)}

  /* SELECTED ROW (P0-SRC-04, mock-009): tapping a row or its map pin highlights one at
     a time, orange-tinted border and background as drawn, never more than one lit. */
  html[data-app] .psearch-wrap #presults .pres.is-sel{border-color:var(--orange);
    background:color-mix(in srgb, var(--orange) 10%, var(--panel))}
  html[data-app] .psearch-wrap #presults .pres.is-sel .pres-badge{color:#181B1A;
    background:color-mix(in srgb, var(--orange) 34%, var(--panel))}

  /* LOADING / EMPTY / ERROR (P0-SRC-05). One quiet status line under the rows that are
     already there, never a claim that something succeeded. */
  html[data-app] .psearch-wrap #presults-status,
  html[data-app] .psearch-wrap .pres-status{display:block;margin:2px 0 4px;padding:0 2px;
    font-size:calc(13px * var(--home-scale, 1));line-height:1.35;color:var(--steel)}
  html[data-app] .psearch-wrap .pres-status--error{color:#B23A2A}
  html[data-app] .psearch-wrap .pres-retry{display:inline-flex;align-items:center;min-height:32px;
    margin-left:6px;padding:2px 10px;border:1px solid var(--rule);border-radius:8px;
    background:var(--panel);color:var(--ink);font-weight:600;font-size:inherit;cursor:pointer}

  /* The bar's back arrow (#psearch-cancel, moved there by js/plan.js) replaces the
     magnifier while there is a list or a picked place to go back from - OR (mock-009,
     redesign-audit-1) the moment the field itself is focused, which is how Home's own
     Destination tap opens this bar now: the rider should see "I am in search, here is
     the way back" before a single character lands in #presults. */
  html[data-app] .pln-searchtop .psearch-cancel{display:none}
  html[data-app]:is(:has(#presults:not([hidden])),[data-psheet="place"],:has(#psearch:focus)) .pln-searchtop .psearch-cancel{
    display:flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;
    margin-left:-10px;padding:0;color:var(--ink)}
  html[data-app]:is(:has(#presults:not([hidden])),[data-psheet="place"],:has(#psearch:focus)) .pln-searchtop .pln-mag{display:none}
  /* redesign-audit-3 (S04, mock-009): the same full-screen search state hides the
     trailing "MRP" account badge too - the mockup's search bar is back-arrow, query,
     clear (x), nothing else on the right. The account sheet it opens is still reachable
     the instant the rider backs out (the badge returns with the magnifier). */
  html[data-app]:is(:has(#presults:not([hidden])),[data-psheet="place"],:has(#psearch:focus)) .pln-searchtop .paccount-btn{
    display:none !important}
}

/* ===================================================================================
   SCREEN 02, THE BRIEF'S SHEET SHAPE — "a compact, draggable bottom sheet"
   ===================================================================================
   Dean, 2026-10-08, looking at a screenshot of what we had: "Second doesn't look like
   the brief... we are back to the old style again." He was right. What was on screen was
   eight controls stacked flat with uppercase labels — the same information as the brief
   and a completely different thing to look at.

   The brief's screen 02 is four bordered rows, one decision each: an icon on the left, a
   small grey label, the value in bold, a chevron on the right. Everything else lives
   behind "Customize preferences", which the brief says must stay "easy to find" — found,
   not surfaced.

   Nothing here removes a control or rewires one. Every id is the id plan.js already
   drives; this is the same sheet wearing the shape the brief drew. Outside [data-app] it
   does not apply at all, so the website is untouched.
   =================================================================================== */
@media(max-width:900px){
  /* The brief's heading replaces the page h2 inside the app sheet. */
  html[data-app] .pauto > h2{display:none}
  html[data-app] .pln-head{display:block;margin:2px 0 14px}
  html[data-app] .pln-head-t{display:block;font-size:calc(26px * var(--ts, 1));
    font-weight:800;letter-spacing:-.02em;line-height:1.1;color:var(--ink)}
  html[data-app] .pln-head-s{display:block;margin-top:4px;
    font-size:calc(13px * var(--ts, 1));line-height:1.4;color:var(--steel)}

  /* ---- the row, which is the whole look ---- */
  html[data-app] .pauto-budget,
  html[data-app] .pauto-more > summary{
    display:flex;align-items:center;gap:12px;width:100%;box-sizing:border-box;
    min-height:62px;margin:0 0 9px;padding:10px 14px;
    border:1px solid var(--rule);border-radius:14px;background:var(--surface)}

  /* RIDE TIME. The steppers were already here and already correct - the brief draws the
     same control. It just needed to stop being a banner and become a row. */
  html[data-app] .pauto-budget{background:var(--surface);border-color:var(--rule)}
  /* Two lines, not three. The first attempt let the derived distance share the row with
     the label and the stepper, and at 390px the three together overflowed and wrapped
     into a mess. The brief's row is one line; ours keeps a second for "about 126 mi",
     because that number is the answer to the question the control is asking and the
     brief had no equivalent to drop. It sits under the value, quiet. */
  html[data-app] .pauto-budget{flex-wrap:wrap;align-content:center;padding:11px 14px}
  html[data-app] .pauto-budget-lab{flex:0 0 auto;order:1;
    font-size:calc(12.5px * var(--ts, 1));font-weight:700;letter-spacing:0;
    color:var(--ink)}
  html[data-app] .pauto-budget-row{order:2;margin-left:auto;display:flex;
    align-items:center;gap:6px}
  html[data-app] .pauto-budget-big{font-size:calc(15.5px * var(--ts, 1));font-weight:800;
    min-width:4.1em;text-align:center;font-variant-numeric:tabular-nums}
  html[data-app] .pauto-budget-sub{order:3;flex:0 0 100%;min-width:0;margin-top:5px;
    font-size:calc(11px * var(--ts, 1));color:var(--steel);
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* FROM — the brief's first row. The field, its label and the Use-my-location button
     were three stacked things; they are one card now, with the label small above the
     value, the same shape as every other row on the sheet. */
  /* The grid itself was already drawn as a card in app mode. Now that each decision
     carries its own border, that outer card is the box around the boxes - it is what
     made Start render as a card inside a card even after the label and field were
     joined. Only the top-level grid loses it; the one inside Customize keeps its own
     grouping. Traced by walking the ancestors of #pa-from and reading the computed
     border at each level, rather than by looking at the screenshot a third time. */
  /* AND IT MUST NOT CLIP ITS OWN DROPDOWN. Measured: .pauto-grid computes overflow-y:hidden
     and ends at y386; the suggestion list starts at y380. Six pixels of eight results were
     visible and the rest were cut off by the grid - not covered by the install card, not
     pushed below the fold. Two probes blamed the wrong thing before one read the clip. */
  html[data-app] .pauto-grid:has(#pa-from){border:0;background:none;padding:0;
    border-radius:0;margin-bottom:0;overflow:visible}

  /* THE DROPDOWN PAINTS ABOVE THE ROWS BELOW IT. .pauto-sug is z-index:40 inside the
     From field, but a later sibling row won at the same stacking level: elementFromPoint
     at the list's top returned the Ride style <summary>. A stacking context on the field
     itself settles it. */
  html[data-app] .pauto-grid > .pauto-field:has(#pa-from){position:relative;z-index:45}
  /* "Ride there now" used to be demoted here unconditionally, to stop it reading as a
     second accent beside "Find me a ride" above. WBH-4490 replaces that with the
     html.has-route gate in the base .pexp rule: no accent on this row until a route
     exists, then it is the route preview's one primary ("Start ride") - in the app too,
     not just on the website. Download GPX lost its own .primary class the same ticket,
     so it needs no app-only override either. */

  /* ONE CARD, NOT A CARD INSIDE A CARD. The label and the field are siblings in the
     grid, so bordering the field alone left "START" sitting outside a second box. Each
     takes half the border instead - the label the top, the field the bottom - and the
     pair reads as the single row the brief draws, with no markup change. */
  html[data-app] .pauto-grid > label[for=pa-from]{grid-column:1/-1;margin:0;
    padding:9px 14px 0;font-size:calc(10.5px * var(--ts, 1));letter-spacing:.05em;
    text-transform:uppercase;color:var(--steel);
    border:1px solid var(--rule);border-bottom:0;
    border-radius:14px 14px 0 0;background:var(--surface)}
  html[data-app] .pauto-grid > .pauto-field:has(#pa-from){
    border:1px solid var(--rule);border-top:0;border-radius:0 0 14px 14px;
    background:var(--surface);padding:0 14px 8px;margin-bottom:9px}
  html[data-app] .pauto-grid > .pauto-field:has(#pa-from) #pa-from{
    border:0;background:none;padding:2px 0;min-height:30px;
    font-size:calc(14.5px * var(--ts, 1));font-weight:700;text-align:left}
  html[data-app] .pauto-here{margin-top:2px;padding:0;min-height:30px;
    background:none;border:0;text-align:left;
    font-size:calc(11.5px * var(--ts, 1));letter-spacing:.04em}
  html[data-app] .pauto-step{width:40px;height:40px;border-radius:50%;flex:0 0 auto}

  /* CUSTOMIZE PREFERENCES — a row that opens, not a wall of controls. */
  html[data-app] .pauto-more{margin:0 0 14px}
  /* The suggestion list draws its own border while it is EMPTY, which is what put a
     second rounded box inside the Start card. It only has anything to say once the
     rider is typing. */
  /* :empty was wrong - the element holds whitespace text nodes, so it is never :empty
     and the rule never applied. :not(:has(*)) asks the question that was actually meant:
     does it contain any ELEMENT. Verified by measuring the rendered border, not by
     looking at the screenshot again. */
  html[data-app] .pauto-sug:not(:has(*)){display:none;border:0}

  /* A CLOSED <details> DOES NOT RELIABLY HIDE ITS CHILDREN HERE.
     The browser hides them through its own stylesheet, and an author rule that sets
     `display` on a child beats it - .pauto-mode{display:grid} and friends do exactly
     that. Measured: with both disclosures reporting open=false, #pa-hours still had a
     104x48 box and #pa-rider 362x72, so the rows were "collapsed" and their contents
     were on screen underneath. Say it explicitly. */
  html[data-app] .pauto-more:not([open]) > *:not(summary){display:none !important}

  /* An older .pauto-more existed before this brief, with its own uppercase grey summary
     and an orange "+" on the right, and the site-wide rule at the top of this file adds
     another "+" on the LEFT. Two marker systems and a shouting label, stacked: the row
     rendered as "+ ~ RIDE STYLE MIXED > +". These three rules retire the old treatment
     rather than leaving both to fight. */
  html[data-app] .pauto-more{border:0;background:none;margin:0 0 9px;padding:0}
  html[data-app] .pauto-more > summary::before,
  html[data-app] .pauto-more > summary::after{content:none !important}
  html[data-app] .pauto-more > summary{cursor:pointer;list-style:none;
    text-transform:none;letter-spacing:0;color:var(--ink);
    font-size:calc(14.5px * var(--ts, 1));font-weight:700}
  html[data-app] .pauto-more > summary::-webkit-details-marker{display:none}
  /* Label above, value below - the brief's row, not an inline run-on. */
  html[data-app] .pauto-more-t{display:flex;flex-direction:column;gap:1px;
    font-size:calc(11px * var(--ts, 1));font-weight:600;letter-spacing:.03em;
    color:var(--steel)}
  html[data-app] .pauto-more-v{font-size:calc(14.5px * var(--ts, 1));font-weight:800;
    color:var(--ink);letter-spacing:0}
  /* P0-HOM-03 (mock-003): Ride style's row loses its visible "Ride style" line the same
     way Ride time does (css/plan.css's #pa-duration-more rule above) - clipped, not
     display:none, so the accessible name survives for anyone not reading the icon. */
  html[data-app] #pa-style-more .pmt-label{position:absolute;width:1px;height:1px;
    padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
  html[data-app] .pauto-more--style > summary .pauto-more-t{gap:1px}
  /* What the disclosure holds sits inside the card's width, not flush to the screen. */
  html[data-app] .pauto-more[open] > *:not(summary){margin:0 2px 10px}
  html[data-app] .pauto-more-ico{flex:0 0 auto;font-size:15px;color:var(--steel)}
  html[data-app] .pauto-more-t{flex:1 1 auto;min-width:0}
  html[data-app] .pauto-more-ch{flex:0 0 auto;font-size:21px;color:var(--steel);
    line-height:1;transition:transform .18s ease}
  html[data-app] .pauto-more[open] > summary .pauto-more-ch{transform:rotate(90deg)}
  html[data-app] .pauto-more[open] > summary{margin-bottom:4px;
    border-bottom-left-radius:0;border-bottom-right-radius:0}
  /* What opens sits in a quiet well, so an open disclosure still reads as one block
     rather than the flat stack this replaced. */
  html[data-app] .pauto-more[open] > :not(summary):first-of-type{margin-top:0}
  html[data-app] .pauto-more[open]{padding:0 0 2px}

  /* FIND ROUTES. The brief's single primary action, full width, at the foot of the
     sheet. It was already #pa-go and already orange; it was not already the last thing
     your eye reaches. */

  /* #pa-budget repeats the distance the ride-time row already shows one line above it
     ("of riding time, about 126 mi" / "3h a day is about 126 mi."). One of them is
     enough, and the one inside the control it describes is the useful one. */
  html[data-app] #pa-budget{display:none}
  html[data-app] #pa-go{width:100%;min-height:54px;margin-top:4px;border-radius:14px;
    font-size:calc(15px * var(--ts, 1));font-weight:800}
}

/* =================================================================
   THE 8 OCTOBER DESIGN, IN THE APP.  (Ray/Astra mockups, docs/design-2026-10-08)

   Dean, 2026-10-09: "MRP looks the same as the old version... this is weeks at this
   point." He was right, and the count says why. His home screen has FOUR things in the
   sheet: Where to ride?, Loop/Destination, a time card, a style card, and one orange
   button. The live sheet had eleven controls and 1,753px of scroll inside a 490px
   window. The night before this I ADDED two more, scenery and surface, because a
   conformance check said a control must exist - making the form longer while the design
   is about making it shorter.

   So this block is subtraction, not styling. Everything that is not one of the four
   decisions is hidden until there is a route to talk about, at which point the planner's
   full apparatus comes back (html.has-route). The website and desktop are untouched.
   ================================================================= */
@media (max-width:900px){

  /* 1. THE GROUND IS CREAM, NOT BLACK. The mockups are a warm off-white with near-black
        type; ours was #121212. This re-points the tokens for app mode only, so every
        component that already reads them follows without being touched individually.
        Dark remains the website default and the riding screen's own business. */

  html[data-app] body{background:var(--surface)}
  html[data-app] .pln-side{
    background:var(--surface);border-top:0;
    border-radius:20px 20px 0 0;
    box-shadow:0 -12px 34px rgba(20,18,15,.14);
  }

  /* 2. ONE HEADLINE, AT THE SIZE IT IS DRAWN. "Where to ride?" is the largest thing on
        the sheet in the mockup; ours was 13px uppercase furniture above a 43px line. */
  html[data-app] .pbar{display:none}
  html[data-app] .pln-head{margin:2px 0 10px}
  html[data-app] #pa-head-t{
    font-size:calc(30px * var(--ts, 1));line-height:1.04;font-weight:800;
    letter-spacing:-.025em;color:var(--ink);display:block}
  html[data-app] #pa-head-s{
    font-size:calc(12.5px * var(--ts, 1));color:var(--steel);margin-top:4px}

  /* 3. LOOP / DESTINATION IS ONE SEGMENTED CONTROL, not two buttons with a gap. */
  html[data-app] .pauto-mode--trip,
  html[data-app] .pauto-mode:has(#pa-mode-loop){
    background:var(--chrome2);border-radius:13px;padding:4px;gap:4px}
  html[data-app] .pauto-mode:has(#pa-mode-loop) .tbtn{
    border:0;background:transparent;border-radius:10px;font-weight:700;
    color:var(--steel);min-height:42px}
  html[data-app] .pauto-mode:has(#pa-mode-loop) .tbtn[aria-pressed="true"]{
    background:var(--orange);color:#181B1A;box-shadow:0 1px 3px rgba(20,18,15,.18)}
  /* P0-HOM mock-003: Loop carries a circular-arrow icon, Destination a pin, each beside
     its own label - not text alone. Scoped to this exact segmented control (:has) so the
     Ride-style/curviness row's plain text buttons, which share the .tbtn class, are
     untouched. */
  html[data-app] .pauto-mode:has(#pa-mode-loop) .tbtn{
    display:inline-flex;align-items:center;justify-content:center;gap:6px}
  html[data-app] .pauto-mode:has(#pa-mode-loop) .tbtn-ico{flex:0 0 auto;display:inline-flex}
  html[data-app] .pauto-mode:has(#pa-mode-loop) .tbtn-label{
    min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* 4. THE TIME CARD. Drawn as a rounded white card, not a labelled row. */
  html[data-app] #pa-budget-head{
    background:var(--panel);border:1px solid var(--rule);border-radius:13px;
    padding:10px 12px}
  html[data-app] #pa-budget-head .pauto-budget-lab{
    font-size:calc(11px * var(--ts, 1));letter-spacing:.06em;text-transform:uppercase;
    color:var(--steel)}

  /* 5. ONE PRIMARY ACTION, ORANGE, FULL WIDTH, AT THE FOOT. */
  html[data-app] #pa-go.primary{
    background:var(--orange);color:#fff;border:0;border-radius:14px;
    min-height:56px;font-size:calc(16px * var(--ts, 1));font-weight:800;
    letter-spacing:-.01em;box-shadow:0 6px 18px rgba(255,91,18,.28)}
  /* dr-gate-reds (2026-11-08): ONE primary action (test-brief.js "02 plan a loop")
     broke the moment html.pridenow-live made #pridenow a second accent-filled button
     on this same Home screen (WBH-4489 fix, above) - a rider with a pushed trip saw
     "Ready to navigate" AND an equally orange "Find routes" side by side, neither
     reading as the one thing to do. Ready-to-navigate IS the one primary action in
     that state; Find Routes (a real, still-live way to plan something new instead)
     demotes to the same bordered-neutral look .pexp's own secondary buttons use,
     exactly as Download GPX already reads as secondary in the app despite literally
     carrying .primary - "primary" is the colour the rider sees, not a class name. */
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) #pa-go.primary{
    background:var(--chrome2)!important;color:var(--ink)!important;
    border:1px solid var(--rule)!important;box-shadow:none!important;font-weight:700}

  /* 6. SUBTRACTION. Until there is a route, the sheet shows only the decision. These are
        not deleted - every one of them reappears the moment a route exists, which is the
        screen they were designed for. The from-field goes because the app knows where
        you are and the mockup puts search over the map instead.

        Written as "everything except" rather than a list of things to hide. I hid them one
     at a time first and shipped two leaks in two passes - the style row at y=699, then
     the miles-a-day box - because a sheet this old has children I did not know about.
     An allow-list cannot leak: anything added to the sheet in future is hidden here
     until someone decides it belongs on the home screen. */
  html[data-app]:not(.has-route):not(.show-dials):not([data-psheet]) .pln-side > *:not(.pauto):not(.pln-customize):not(.pln-grab):not(.preview-heading):not(.home-scroll-body):not(.home-action-footer):not(.psearch-wrap):not(.pexp){
    display:none !important}
  /* dr-gate-reds (2026-11-08): WBH-4489's one-tap "way to navigation" (#pridenow,
     js/plan.js wayToNav()) lives inside .pexp, which the allow-list above used to hide
     outright on Home with no exception - correct for a plain cold open with nothing to
     ride, wrong for the two cases js/plan.js now marks html.pridenow-live for (in the
     app; a confirmed pending trip with stops to ride). .pexp is exempted from the
     allow-list above (":not(.pexp)") and these two rules take over its display instead,
     same specificity, mutually exclusive on the one class that toggles between them -
     default hidden, shown and restyled as the one button only when pridenow-live. Not
     routed through the has-route-only #pridenow rules elsewhere in this file: Home has
     no route to style a summary row around, just the one button. test-navbar.js caught
     it at 0x0 - in the app, a trip waiting, the exact cold-launch case this exists for. */
  html[data-app]:not(.pridenow-live):not(.has-route):not(.show-dials):not([data-psheet]) .pln-side > .pexp{
    display:none !important}
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) .pln-side > .pexp{
    display:flex !important;flex-direction:column;margin:0 16px 16px;padding:0}
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) .pexp > *:not(#pridenow){
    display:none !important}
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) .pexp #pridenow{
    display:flex !important;align-items:center;justify-content:center;width:100%;min-height:50px;
    box-sizing:border-box;border-radius:14px;background:var(--orange);border-color:var(--orange);
    color:#181B1A;font-weight:700}
  /* Classes, not ids, inside :not(). An id in a :not() still counts toward
     specificity, so the first version of this line carried two ids and outranked
     the .show-dials rule that Customize depends on - the button appeared to do
     nothing because the hide kept winning. #pa-go is .primary and #pa-note is
     .pauto-note, so naming the classes keeps this at zero ids. */
  /* P0-HOM-06: .pauto-sponsor (#pa-sponsor, the house/ad line under Find routes,
     mock-003) added to the allow-list - this is the higher-specificity rule
     (":not([data-psheet])") that actually wins on Home, so the earlier, lower-specificity
     copy of this allow-list further down this file was fixed for nothing until this one
     was too. js/plan.js's homeSponsorLine() already un-hides the element; the CSS was
     hiding it again regardless. */
  html[data-app]:not(.has-route):not(.show-dials):not([data-psheet]) .pauto > *:not(.pln-head):not(.pauto-mode):not(.pln-cards):not(.primary):not(.pauto-note):not(.pauto-sponsor){
    display:none !important}
  /* #pa-style-more is NOT hidden any more: it is the second card in .pln-cards, which is
     how the mockup draws style, and how the brief check finds the ride_style decision. */
  html[data-app]:not(.has-route):not(.show-dials):not([data-psheet]) .pauto-grid,
  html[data-app]:not(.has-route):not(.show-dials):not([data-psheet]) #pa-more{display:none !important}

  /* 7. CUSTOMIZE, where the mockup puts it: a quiet link on the headline's right, which
        is the door to everything hidden above. */
  html[data-app] .pln-customize{
    position:absolute;top:14px;right:16px;z-index:2;
    display:inline-flex;align-items:center;gap:5px;
    background:none;border:0;padding:6px 2px;cursor:pointer;
    font-size:calc(12.5px * var(--ts, 1));font-weight:700;color:var(--steel)}
  /* P0-HOM-05 (mock-003): a sliders icon, not the hamburger lines this replaced - the
     SVG is a real child (js/plan.js designCustomize()), so no ::before content here. */
  html[data-app] .pln-customize svg{flex:0 0 auto;width:14px;height:14px}

  /* 8. SEARCH FLOATS OVER THE MAP, as drawn: a white pill at the top, not a field buried
        in the sheet. js/plan.js moves the existing input into this shell so there is one
        search in the DOM, not two that can disagree. */
  html[data-app] .pln-searchtop{
    position:fixed;top:calc(10px + env(safe-area-inset-top,0px));left:12px;right:12px;
    z-index:6;background:var(--panel);border:1px solid var(--rule);border-radius:15px;
    box-shadow:0 8px 22px rgba(20,18,15,.14);display:flex;align-items:center;
    gap:9px;padding:0 13px;min-height:50px}
  html[data-app] .pln-searchtop input{
    flex:1;border:0;background:none;outline:none;min-height:48px;
    font-size:calc(15px * var(--ts, 1));color:var(--ink)}
  html[data-app] .pln-searchtop .pln-mag{color:var(--steel);flex:0 0 auto;display:flex}
  /* The pill and the search bar cannot both own the top of the screen. */
  html[data-app] .pln-topbar{display:none}
}

@media (max-width:900px){
  /* Customize re-opens the dials on the home screen. The hides above use !important to
     beat the base layout rules, so the door back in has to be at least as specific. */
  html[data-app].show-dials #pa-style-more,
  html[data-app].show-dials #pa-more{display:block !important}
}

@media (max-width:900px){
  /* The two cards the mockup draws side by side: time and style. */
  html[data-app] .pln-cards{display:grid;grid-template-columns:1fr 1fr;gap:8px;
    align-items:stretch;margin-top:8px}
  html[data-app] .pln-cards > *{margin:0 !important;min-width:0}
  html[data-app] .pln-cards #pa-style-more{border:1px solid var(--rule);border-radius:13px;
    background:var(--panel);display:flex !important;flex-direction:column;justify-content:center}
  html[data-app] .pln-cards #pa-style-more > summary{padding:0 12px;min-height:0;
    height:100%;white-space:normal;text-transform:none;letter-spacing:0;
    font-size:calc(12.5px * var(--ts, 1));color:var(--ink)}
  html[data-app] .pln-cards #pa-budget-head{height:100%}
}

@media (max-width:900px){
  /* The time card is half the width it used to be, and its contents were sized for the
     full sheet. My first attempt at shrinking them overflowed the card in both
     directions - "AVE" and "3 hours" clipped off the left edge - because the label, the
     big number, two steppers and a sub-line will not fit in 175px however small you set
     them. So the card carries what the mockup's card carries: the figure and the way to
     change it. The explanatory sub-line goes; it said "of riding time, about 126 mi",
     and the miles are already on the result. */
  html[data-app] .pln-cards #pa-budget-head{
    display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:2px;padding:10px 8px;overflow:hidden}
  html[data-app] .pln-cards .pauto-budget-lab{
    font-size:calc(10px * var(--ts, 1));letter-spacing:.08em;text-transform:uppercase;
    opacity:1;color:var(--steel);white-space:nowrap}
  html[data-app] .pln-cards .pauto-budget-sub{display:none}
  html[data-app] .pln-cards .pauto-budget-row{
    display:flex;align-items:center;justify-content:center;gap:8px;
    width:100%;min-width:0;flex-wrap:nowrap}
  html[data-app] .pln-cards .pauto-budget-big{
    font-size:calc(19px * var(--ts, 1));font-weight:800;letter-spacing:-.02em;
    white-space:nowrap;min-width:0}
  html[data-app] .pln-cards .pauto-budget-row button{
    width:28px;min-width:28px;height:28px;min-height:28px;padding:0;flex:0 0 auto;
    display:grid;place-items:center;font-size:15px}

}

@media (max-width:900px){
  /* "RIDE TO" HAD NOWHERE TO TYPE. Dean, 2026-10-09, with a screen recording:
     "Functionality broken." He tapped Ride to, tapped Plan my ride, and got "Where are
     you heading?" - the app demanding a destination it gave him no field for.

     setMode('ab') un-hides #pa-to-label and #pa-to-field, but both live inside
     .pauto-grid, which the home-screen allow-list had already set to display:none. The
     field dutifully revealed itself inside a hidden parent. A loop starts where the
     rider is and needs no fields, which is why hiding the grid looked safe; a
     destination ride is the half I did not try before shipping.

     So the grid comes back the moment Ride to is pressed, carrying only the destination:
     start stays implicit, as the mockup has it. The :has() carries an id, so it outranks
     the allow-list's !important hide. */
  html[data-app]:not(.has-route) .pauto:has(#pa-mode-ab[aria-pressed="true"]) .pauto-grid{
    display:block !important;margin-top:8px}
  html[data-app]:not(.has-route):not(.show-dials):not([data-psheet]) .pauto:has(#pa-mode-ab[aria-pressed="true"]) .pauto-grid > label[for="pa-from"],
  html[data-app]:not(.has-route):not(.show-dials):not([data-psheet]) .pauto:has(#pa-mode-ab[aria-pressed="true"]) .pauto-grid > .pauto-field:not(#pa-to-field){
    display:none !important}
  html[data-app] .pauto-grid > #pa-to-label{
    font-size:calc(10.5px * var(--ts, 1));letter-spacing:.07em;text-transform:uppercase;
    color:var(--steel);display:block;margin-bottom:4px}

  /* The tracking banner was still dark over a cream screen - the one slab of the old
     theme left in the shot Dean sent. */
  html[data-app] .mrp-track-banner,
  html[data-app] #track-banner,
  html[data-app] .trk-banner{
    background:var(--panel) !important;color:var(--ink) !important;
    border-bottom:1px solid var(--rule) !important}
}

@media (max-width:900px){
  /* The destination hint is four lines of prose about town centres and bed addresses.
     True, and it belongs on the website: in the app it pushed the field itself to the
     bottom of the sheet and left the suggestion list nowhere to open but upward over
     the headline. The mockups carry no prose on this screen. */
  html[data-app] #pa-to-hint{display:none}
}

/* =================================================================
   4/9 ROUTE PREVIEW. After a plan, the rider gets a decision, not a document.

   Measured before touching it: once a route exists the sheet holds twelve visible
   blocks and 5,197px of scroll inside a 490px window - the nearby list alone is 1,958px
   and the stop list another 1,104. That is the same wall the home screen had, and the
   screen it buries is the one Ray/Astra drew most precisely: a route name, a line of
   facts, the alternatives as cards, and one orange Start ride.

   The alternatives already exist. js/plan.js renderRoutes() builds .proute-card buttons
   with miles, hours and a trade-off, and clicking one switches the route. They were
   never the problem; they were just somewhere down a five-thousand-pixel scroll.

   Same allow-list shape as the home screen, for the same reason: I hid things one at a
   time there and leaked twice. Everything not on the list comes back behind Customize.
   ================================================================= */
@media (max-width:900px){
  /* Gated on :not(.show-dials) rather than answered by a louder rule. Three times
     today I wrote an override to beat one of these hides and lost on specificity.
     A hide that knows when it should not apply needs no counter-rule. */
  /* #proutes and #pout are siblings of .pauto in the generated page, not children of
     it. Keep them in this outer allow-list; the inner rule below only governs the
     planning controls that really do live inside .pauto. */
  /* #pshare-sheet (r4-ios-mirror-b, 2026-10-30): also a sibling of .pauto, same as
     #proutes/#pout, and missing from this allow-list the same way they would have
     been missing before this comment existed. Share opens from the Preview screen
     with no data-psheet set (it is a full-viewport overlay, not a named sheet state),
     so without this exemption this "hide everything else once a route exists" rule
     forced display:none!important on the real, already-built P1-SHR-01 screen the
     instant a route existed in app mode -- hidden=false on #pshare-sheet itself, but
     overridden here. Found driving Share inside the production WebPlanner (not a
     website tab, where this app-mode-gated rule never applies, which is why
     P1-SHR-01-web's own Playwright test never caught it). */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-side > *:not(.pauto):not(.pexp):not(.pln-customize):not(.pln-grab):not(#proutes):not(#pout):not(.proute-recenter):not(.preview-heading):not(#pstatus):not(#phwwarn):not(#pwx-alt):not(#condition-review-notice):not(.psearch-wrap):not(#pshare-sheet){
    display:none !important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pauto > *:not(.pln-head):not(#proutes):not(#pout):not(.pauto-note):not(#pa-trip-wrap):not(#pa-trip-hint):not(.primary){
    display:none !important}
  /* dr-gate-reds (2026-11-08): #pa-trip-wrap (Start fresh / Fill in my trip / Carry
     on, js/plan.js paAppendUI()) only un-hides itself once stops already exist - the
     exact case a route loaded from a share link or pending-trip push produces. That
     route finishes drawing (has-route) within a few seconds of the page opening,
     which is before this "hide everything but the summary" rule had an exemption for
     it, so the three-way choice vanished out from under a rider who had not even had
     time to read it yet - test-dates.js caught it: the DOM settles with #pa-fill at
     0x0 a few seconds after load, every run, not a timing flake. Exempted above and
     given its own spacing here, same as the summary rows next to it. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) #pa-trip-wrap{
    margin:10px 0 0}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) #pa-trip-hint{
    margin:6px 0 0;font-size:calc(13px * var(--ts, 1));opacity:.8}

  /* The route's name at the size the mockup draws it, with its facts under it. */
  html[data-app].has-route #pa-head-t{
    font-size:calc(27px * var(--ts, 1));line-height:1.05;font-weight:800;letter-spacing:-.025em}

  /* The alternatives, as cards in a row rather than a scrolling strip. */
  html[data-app].has-route #proutes{display:flex;gap:8px;margin-top:10px}
  html[data-app].has-route .proutes-lab{display:none}
  html[data-app].has-route .proute-card{
    flex:1 1 0;min-width:0;background:var(--panel);border:1px solid var(--rule);
    border-radius:13px;padding:10px 9px;text-align:left;cursor:pointer}
  html[data-app].has-route .proute-card[aria-pressed="true"]{
    border-color:var(--orange);background:color-mix(in srgb, var(--orange) 9%, var(--panel))}
  html[data-app].has-route .proute-card-mi{
    font-size:calc(17px * var(--ts, 1));font-weight:800;letter-spacing:-.02em;display:block}
  html[data-app].has-route .proute-card-kind{
    font-size:calc(10.5px * var(--ts, 1));line-height:1.15;color:var(--steel);display:block;margin-bottom:3px}
  html[data-app].has-route .proute-card-h{
    font-size:calc(11px * var(--ts, 1));color:var(--steel);display:block}
  html[data-app].has-route .proute-card-trade{
    font-size:calc(10.5px * var(--ts, 1));color:var(--orange);display:block;margin-top:3px}

  /* ONE primary action. The mockup's Start ride is our #pridenow; Download GPX is a
     website action and Navigate this is the same verb twice, so both go quiet. */
  /* `flex-wrap:nowrap` (r5-ios-mirror-d, 2026-10-30): the base `.pexp` rule (line 122,
     a plain-web/desktop rule outside app mode) sets `flex-wrap:wrap`, meant for a
     context where these buttons sit in a horizontal row that wraps. This app-mode
     override already turns `.pexp` into a vertical column stack but never cancelled
     the inherited `wrap` - with ~11 real children (Start ride, Edit route, Save,
     Share, GPX download/import, Google Maps, Clear, Save offline, the "more" door,
     the recalculate note) once all are revealed, `flex-direction:column` +
     `flex-wrap:wrap` does not just overflow and scroll (the intended behavior, and
     what this row's acceptance explicitly allows - "reachable...by scroll if
     needed") - it WRAPS into multiple side-by-side columns, scattering buttons
     (including `#psave`) off to the right at ~626px in a 390px-wide viewport,
     genuinely off-screen, not just below the fold. Confirmed via Playwright: before
     this fix, `#psave`'s `left` was 626 (`window.innerWidth` 390); `#pgpx-note`
     alone became an 1127px-tall second column from an ordinary-length string
     wrapping into a near-single-character column width. `nowrap` restores the
     single vertical list the design (and the row's own "without crowding Start
     ride" / "by scroll if needed" wording) describes. */
  html[data-app].has-route .pexp{display:flex;flex-direction:column;flex-wrap:nowrap;gap:8px;margin-top:10px}
  html[data-app].has-route .pexp #pridenow{
    order:-1;background:var(--orange);border-color:var(--orange);color:#181B1A;
    border-radius:14px;min-height:56px;font-size:calc(16px * var(--ts, 1));font-weight:800;
    display:flex;align-items:center;justify-content:center;
    box-shadow:0 6px 18px rgba(255,91,18,.28)}
  /* Everything except Start ride. Download GPX, Google Maps, Save, Share, Clear and
     Save-offline are six more 72px buttons under the one the rider came for - 360px of
     secondary action below the primary. They are all real and all stay one tap away
     behind Customize; none of them is the decision this screen exists to make. */
  /* The edit link is named here rather than fought with specificity: :not(#pridenow)
     carries an id, so any class-only override loses to it. Second time today I hit
     that - an id inside :not() still counts. Name the exception, do not out-shout it. */
  /* `.show-actions` (r5-ios-mirror-d, 2026-10-30): the quiet "Save, share, GPX
     and more" door now toggles its OWN class, not `.show-dials` - it must reveal
     only these buttons, never Customize's unrelated `.pauto` preference dials
     (destination mode/budget/bike style) or the catch-all rule above, both of
     which `.show-dials` also reverts and which otherwise push `#psave` ~2400px
     down the sheet, past "reachable without a long scroll" (this row's own
     acceptance). See js/plan.js designEditLink() for the matching JS change. */
  html[data-app].has-route:not(.show-dials):not(.show-actions):not([data-psheet]) .pexp > *:not(#pridenow):not(.pln-editlink):not(.pln-morelink){display:none !important}
  html[data-app].has-route.show-dials .pexp > *,
  html[data-app].has-route.show-actions .pexp > *{display:revert !important}

  /* Customize is the way back to the stops, the nearby list and the dials. */
}

@media (max-width:900px){
  /* The mockup's primary reads "Start ride" in sentence case, not shouted. */
  html[data-app].has-route .pexp #pridenow{text-transform:none;letter-spacing:-.01em}

  /* The summary was a 196px paragraph where the mockup has one quiet line of facts.
     It is NOT deleted: it carries the roads by name, the corner count, and the caveat
     that a car-fallback route may not avoid interstates - that last one is exactly the
     kind of thing a rider should be told rather than protected from. It just stops
     being the biggest thing on the screen. */
  html[data-app].has-route #pa-note{
    font-size:calc(12px * var(--ts, 1));line-height:1.4;color:var(--steel);
    background:none;border-left:0;padding:0;margin-top:6px}
}

@media (max-width:900px){
  /* The mockup's quiet link under the primary. Visible only once there is a route to
     edit, and it is deliberately NOT another orange button - this screen has one. */
  html[data-app] .pln-editlink{display:none}
  html[data-app].has-route .pexp .pln-editlink{
    display:block !important;background:none;border:0;cursor:pointer;
    padding:10px 4px 2px;width:100%;
    font-size:calc(16px * var(--ts, 1));font-weight:600;color:var(--steel);
    text-transform:none;letter-spacing:normal;min-height:44px}
  html[data-app].has-route.show-dials .pexp .pln-editlink{display:none !important}
}

/* Planner appearance: preference resolution is shared by chrome and base map. */
:root, :root[data-theme="dark"] {
 --surface:#111515;--panel:#202222;--chrome:#111515;--chrome2:#2A2D2C;
 --rule:#434844;--ink:#F8F5EF;--steel:#B8BDB8;--smoke:#B8BDB8;
 --text-strong:#F8F5EF;--orange:#FF7A1A;--orange-dk:#E3650C;color-scheme:dark;
}
:root[data-theme="light"] {
 --surface:#F8F5EF;--panel:#FFFFFF;--chrome:#F8F5EF;--chrome2:#F0EEEA;
 --rule:#D8D9D4;--ink:#181B1A;--steel:#606661;--smoke:#606661;
 --text-strong:#181B1A;--orange:#FF7A1A;--orange-dk:#E3650C;color-scheme:light;
}
.planner-theme { position:absolute;left:12px;top:72px;z-index:5;
 background:var(--panel);color:var(--ink);border:1px solid var(--rule);
 border-radius:12px;padding:2px 10px;font-size:16px;max-width:calc(100% - 80px); }
.planner-theme select { min-height:44px;background:var(--panel);color:var(--ink);border:0;font:inherit; }
.planner-theme select:focus-visible { outline:2px solid var(--orange);outline-offset:2px; }
#planner-theme-status:not(:empty) {display:block;max-width:220px;}
html[data-app] #pa-go.primary,html[data-app] .pauto-mode .tbtn[aria-pressed="true"],
.primary,.mrp-radar-ctrl button.on { color:#181B1A; }

/* Home layout: duration stays readable between accessible controls, without clipping. */
@media (max-width:900px){
 html[data-app] #pa-head-t{font-size:calc(20px * var(--ts, 1));line-height:1.15}
 html[data-app] .pln-cards #pa-budget-head{overflow:visible}
 html[data-app] .pln-cards .pauto-budget-row{
  display:grid;grid-template-columns:1fr 1fr;gap:4px 8px;justify-items:center}
 html[data-app] .pln-cards .pauto-budget-big{
  grid-column:1 / -1;grid-row:1;font-size:calc(16px * var(--ts, 1));white-space:normal;text-align:center}
 html[data-app] .pln-cards .pauto-budget-row button{
  grid-row:2;width:44px;min-width:44px;height:44px;min-height:44px}
}
/* Active navigation uses theme ink at every viewport width. */
html[data-app] .appbar__t.is-on{color:var(--ink)}

/* Preview must remain readable when only one genuine route is available. */
.proutes-availability { flex: 1 0 100%; margin: 0 0 4px; font-size: calc(16px * var(--ts, 1)); line-height: 1.4; color: var(--steel); }
@media (max-width:900px) {
  html[data-app].has-route #proutes { flex-wrap: wrap; }
  html[data-app].has-route .proute-card { flex: 1 1 150px; min-height: 44px; }
  html[data-app].has-route .proute-card-top { flex-wrap: wrap; min-width: 0; }
  html[data-app].has-route .proute-card-top > * { max-width: 100%; overflow-wrap: anywhere; }
  html[data-app].has-route .proute-card-h,
  html[data-app].has-route .proute-card-trade { font-size: calc(16px * var(--ts, 1)); line-height: 1.4; }
}

/* Accepted Preview is a route, not the setup introduction. Customize retains setup. */
@media (max-width:900px) {
 html[data-app].has-route:not(.show-dials) .pauto > .pln-head { display:none !important; }
 html[data-app].has-route:not(.show-dials) .pexp { margin-top:8px; }
 html[data-app].has-route #pridenow { color:#181B1A; min-height:56px; }
 html[data-app].has-route #proutes .proutes-availability { order:1; }
}

/* Preview keeps live notices but needs no empty setup-card chrome. Setup returns
   unchanged through Customize; populated notes keep their natural height. */
@media (max-width:900px) {
 html[data-app].has-route:not(.show-dials) .pauto {
  padding:0;margin:0;border:0;background:none;
 }
 html[data-app].has-route:not(.show-dials) #pa-note:empty,
 html[data-app].has-route:not(.show-dials) #pstatus:empty {
  min-height:0;margin:0;padding:0;
 }
 html[data-app].has-route:not(.show-dials) #pstatus,
 html[data-app].has-route:not(.show-dials) #phwwarn,
 html[data-app].has-route:not(.show-dials) #condition-review-notice {
  font-size:calc(16px * var(--ts, 1));line-height:1.4;
 }
}

/* Selected-route hierarchy. Facts come from the displayed route; all notices and
   detailed itinerary remain in the sheet's scroll flow. No text truncation. */
.preview-heading { display:contents; }
.preview-heading h2, .preview-heading p { display:none; }
@media (max-width:900px) {
 html[data-app].has-route:not(.show-dials) .preview-heading { display:flex;flex-wrap:wrap;align-items:center;gap:4px 12px;margin:0 0 12px;min-width:0; }
 html[data-app] .preview-heading h2 { display:none;flex:1 1 180px;min-width:0;margin:0;color:var(--ink);font-size:calc(24px * var(--ts, 1));line-height:1.2;overflow-wrap:anywhere; }
 html[data-app] .preview-heading p { display:none;flex:1 0 100%;order:2;margin:0;color:var(--steel);font-size:calc(16px * var(--ts, 1));line-height:1.4;overflow-wrap:anywhere; }
 html[data-app].has-route:not(.show-dials) .preview-heading h2,
 html[data-app].has-route:not(.show-dials) .preview-heading p { display:block; }
 html[data-app] .pln-customize { min-height:44px;min-width:44px;font-size:calc(16px * var(--ts, 1)); }
 html[data-app].has-route:not(.show-dials) .preview-heading .pln-customize { position:static;min-width:44px;min-height:44px;padding:8px 10px;margin-left:auto;border:1px solid var(--steel);border-radius:12px;font-size:calc(16px * var(--ts, 1));line-height:1.4;color:var(--ink); }
 html[data-app]:not(.has-route) .pln-side > .preview-heading { display:contents !important; }
 html[data-app].has-route:not(.show-dials) #pstatus { color:var(--steel);margin:6px 0; }
 html[data-app].has-route:not(.show-dials) #pa-note { font-size:calc(16px * var(--ts, 1));line-height:1.4; }
 html[data-app].has-route .proute-card-h { font-size:calc(22px * var(--ts, 1));font-weight:800; }
 html[data-app].has-route .proutes-availability { margin:4px 0;font-size:calc(16px * var(--ts, 1));line-height:1.4; }
}

/* Keep Preview content inside the approved sheet gutter; the grab handle retains
   its existing full-width hit area. Padding belongs to content, not the map. */
@media (max-width:900px) {
 html[data-app].has-route:not(.show-dials) .pln-side > .preview-heading,
 html[data-app].has-route:not(.show-dials) .pln-side > #proutes,
 html[data-app].has-route:not(.show-dials) .pln-side > .pexp,
 html[data-app].has-route:not(.show-dials) .pln-side > #pout,
 html[data-app].has-route:not(.show-dials) .pln-side > #pstatus,
 html[data-app].has-route:not(.show-dials) .pln-side > #phwwarn,
 html[data-app].has-route:not(.show-dials) .pln-side > #pwx-alt,
 html[data-app].has-route:not(.show-dials) .pln-side > #condition-review-notice {
   margin-left:16px;margin-right:16px;max-width:calc(100% - 32px);box-sizing:border-box;
 }
}

/* Compact decision state: fields belong to Customize; primary action follows route facts. */
@media (max-width:900px) {
 html[data-app].show-dials .pauto > .pauto-grid { display:block !important; }
 html[data-app].has-route:not(.show-dials) #proutes.proutes-single-summary .proute-card { display:flex; }
 html[data-app] .ppreview-more .proutes-availability { margin:8px 0 0; }
 html[data-app].has-route:not(.show-dials) .preview-heading { margin-bottom:0; }
 html[data-app].has-route:not(.show-dials) .pexp { margin-top:8px;margin-bottom:8px; }
}

/* Route title owns its row; metadata and Customize wrap below at larger text sizes. */
@media (max-width:900px) {
 html[data-app].has-route:not(.show-dials) .preview-heading h2 { flex:1 0 100%;order:0; }
 html[data-app].has-route:not(.show-dials) .preview-heading p { flex:1 1 140px;order:1; }
 html[data-app].has-route:not(.show-dials) .preview-heading .pln-customize { order:2;max-width:100%;box-sizing:border-box;white-space:normal;overflow-wrap:anywhere; }
}

/* ACTIVE CONSTRAINT CHIPS (P0-CUS-08). A flex item alongside the title/metadata inside
   .preview-heading (display:contents on that header otherwise, display:flex once a
   route is on screen - see the rules above), so the chips wrap onto their own row under
   the title and metadata without any layout of their own. */
.pcz-chips { display:none;list-style:none;margin:0;padding:0;gap:6px;flex-wrap:wrap; }
@media (max-width:900px) {
 html[data-app].has-route:not(.show-dials) .pcz-chips:not([hidden]) { display:flex;order:3;flex:1 0 100%; }
}
.pcz-chip { min-height:30px;padding:4px 12px;border-radius:999px;border:1px solid var(--rule);
  background:var(--raised);color:var(--ink);font-size:12.5px;font-weight:650;cursor:pointer; }
.pcz-chip--hard { border-color:var(--orange);background:var(--orange);color:var(--black); }

/* Home design conformance: one sheet surface, with retained accessible controls.
   Accepted Preview and expanded Customize intentionally retain their existing rules. */
@media (max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pauto{background:transparent;border:0;padding:0;margin:12px 16px 20px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-head{padding-right:132px;min-height:44px;margin:0 0 14px;}
 html[data-app]:not(.has-route):not(.show-dials) #pa-head-t{font-size:calc(22px * var(--ts, 1));line-height:1.2;letter-spacing:-.025em;overflow-wrap:normal;}
 html[data-app]:not(.has-route):not(.show-dials) #pa-head-s{display:block;font-size:calc(13px * var(--ts, 1));line-height:1.4;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-customize{top:56px;right:16px;min-height:44px;min-width:44px;padding:8px 0 8px 8px;font-size:calc(16px * var(--ts, 1));line-height:1.25;max-width:132px;white-space:normal;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode{margin:0 0 12px;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode .tbtn{min-height:44px;font-size:calc(16px * var(--ts, 1));}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards{gap:12px;margin:0 0 14px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-budget-head{background:var(--chrome2);border-radius:14px;padding:10px 8px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-style-more{background:var(--chrome2);border-radius:14px;}
 html[data-app]:not(.has-route):not(.show-dials) #pa-go.primary{margin-top:0;min-height:52px;border-radius:14px;font-size:calc(17px * var(--ts, 1));}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-note:not(:empty){margin-top:12px;}
}

/* Home scalable text: keep the action in sheet flow; never reserve fixed label width.
   The separate action row preserves one existing button and all state transitions. */
@media (max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pln-customize{position:static;align-self:flex-end;box-sizing:border-box;max-width:calc(100% - 32px);margin:4px 16px 0;padding:8px;white-space:normal;overflow-wrap:anywhere;text-align:right;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-head{padding-right:0;min-width:0;}
 html[data-app]:not(.has-route):not(.show-dials) #pa-head-t,
 html[data-app]:not(.has-route):not(.show-dials) #pa-head-s{overflow-wrap:anywhere;}
}

/* Home action is a non-shrinking content row. Large text and its icon may wrap. */
@media (max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pln-customize{flex:0 0 auto;height:auto;min-height:44px;line-height:1.4;}
}

/* Approved Home composition: one intrinsic wrapping title/action row. */
.planner-appearance{position:absolute;left:12px;top:72px;z-index:5;max-width:calc(100% - 24px);box-sizing:border-box;background:var(--panel);color:var(--ink);border:1px solid var(--chrome2);border-radius:12px;}
.planner-appearance summary{min-height:44px;min-width:44px;box-sizing:border-box;padding:10px 12px;font:inherit;line-height:1.5;cursor:pointer;overflow-wrap:anywhere;}
.planner-appearance summary:focus-visible{outline:2px solid var(--orange);outline-offset:2px;}
.planner-appearance .planner-theme{position:static;display:block;box-shadow:none;border:0;max-width:100%;}
.preview-heading .pln-head{display:none;}
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pln-side > .preview-heading{display:flex !important;flex-wrap:wrap;align-items:center;gap:8px 12px;margin:8px 16px 0;min-width:0;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-head{display:block;flex:1 1 11rem;min-width:0;margin:0;padding:0;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading #pa-head-t{display:block;margin:0;font-size:calc(22px * var(--ts,1));line-height:1.25;overflow-wrap:anywhere;}
 /* Brief, 8 October: there is no start FIELD on this sheet any more - "Start and
    finish at your location" is how the screen states where the ride begins instead
    (ride-04/test-brief.js "the four decisions, by name"). #pa-head-s carries exactly
    that sentence, and it is the only copy of it in the page - so hiding it here, where
    the only #pa-head-s actually lives (inside .preview-heading, same as #pa-head-t
    right above), meant the rider never saw it at all: the brief's "start" decision had
    no visible representation anywhere on the default sheet. Show it like its sibling. */
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading #pa-head-s{display:block;margin:0;font-size:calc(13px * var(--ts,1));line-height:1.4;overflow-wrap:anywhere;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-customize{flex:0 1 auto;align-self:center;position:static;margin:0 0 0 auto;max-width:100%;height:auto;min-height:44px;padding:8px;line-height:1.4;text-align:start;}
}

/* Home mode labels size their track intrinsically. Wrap whole choices before
   wrapping text; never ellipsise the chosen destination mode at larger text. */
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop):not([hidden]){display:flex;flex-wrap:wrap;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop) .tbtn{flex:1 1 max-content;box-sizing:border-box;min-width:0;max-width:100%;height:auto;min-height:44px;line-height:1.4;white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere;}
}

/* Compact Home composition. Text continues to honor the rider's scale; rows
   grow/wrap instead of clipping. Existing duration steppers remain functional. */
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pln-side > .preview-heading{gap:4px 8px;margin-top:4px;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-head{flex:1 1 max-content;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading #pa-head-t{font-size:calc(20px * var(--ts,1));line-height:1.2;overflow-wrap:normal;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-customize{font-size:calc(16px * var(--ts,1));padding:4px;min-height:44px;line-height:1.3;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto{margin-top:8px;margin-bottom:12px;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop):not([hidden]){display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop) .tbtn{padding:6px 4px;min-height:44px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards{gap:8px;align-items:start;margin-bottom:10px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-budget-head{height:auto;padding:6px 4px;gap:0;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-lab{font-size:calc(11px * var(--ts,1));line-height:1.2;letter-spacing:0;text-transform:none;white-space:normal;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-row{gap:0 4px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-big{font-size:calc(16px * var(--ts,1));line-height:1.3;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more{height:auto;min-height:44px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more > summary{height:auto;min-height:44px;padding:8px;gap:4px;font-size:calc(14px * var(--ts,1));line-height:1.3;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-now{font-size:calc(16px * var(--ts,1));line-height:1.3;}
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance > summary{font-size:calc(16px * var(--ts,1));line-height:1.3;padding:6px 8px;min-height:44px;}
}

/* Home composition: the real action remains visible while setup scrolls.
   Node slots are restored by planner-sheet before all non-Home compositions. */
@media(max-width:900px){
 /* P0-HOM mock-003: the sheet runs to the bottom edge. The generic .pln-side rule
    above reserves 56px below it for the bottom tab bar (.appbar) - correct on every
    OTHER app state, which still shows that bar - but Home hides the bar outright
    (P0-HOM-02) and never gave the sheet its space back, so the map (and its
    attribution/scale controls) showed through a 56px gap under the sheet that the
    mockup does not have. Still honors the home-indicator safe area, just not a tab
    bar that is not there.
    MUST match the appbar-hide selector below (:not(.has-route):not([data-psheet])
    :not(.show-dials)) exactly, not just the has-route/show-dials part of it: without
    the [data-psheet] exclusion this also matched Setup/Destination/Customize (every
    one of them has data-psheet set, none has has-route or show-dials), stripping
    their real 56px tab-bar reservation while their appbar stayed visible - the
    destination card's "Find routes" button ended up sitting under the still-visible,
    fixed, z-index:900 appbar, eating its own clicks. */
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side{bottom:env(safe-area-inset-bottom,0px);}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side{max-height:38dvh;}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side{display:flex;flex-direction:column;overflow:hidden !important;padding-bottom:0;}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side > .home-scroll-body{display:block !important;flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;scroll-padding-block:8px;}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .home-scroll-body > .preview-heading{display:flex !important;flex-wrap:wrap;align-items:center;gap:4px 8px;margin:4px 16px 0;min-width:0;}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side > .home-action-footer{display:block !important;flex:0 0 auto;padding:8px 16px;box-sizing:border-box;background:var(--surface);}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .home-action-footer #pa-go{display:block;width:100%;box-sizing:border-box;margin:0;min-height:44px;height:auto;white-space:normal;overflow-wrap:anywhere;}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .home-action-footer #pa-note:empty{display:none;margin:0;min-height:0;}
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side[data-sheet-detent="collapsed"] > .home-scroll-body,
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .pln-side[data-sheet-detent="collapsed"] > .home-action-footer{display:none !important;}
}

/* Preview owns the secondary route-actions disclosure. It is created once for that
   later state, but must not consume a row in Home's four-decision composition. */
@media(max-width:900px){
 html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) .preview-heading .ppreview-more{display:none!important}
}

/* Setup copy belongs to Home/Customize, never the accepted route heading.
   The original node is now nested inside preview-heading. */
html[data-app].has-route:not(.show-dials) .preview-heading .pln-head{display:none !important;}

/* Compact only Home's base hierarchy; preserve the rider's text multiplier. */
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading #pa-head-t{font-size:calc(18px * var(--ts,1));line-height:1.2;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-customize{font-size:calc(16px * var(--ts,1));line-height:1.3;min-height:44px;}
 html[data-app]:not(.has-route):not(.show-dials) .home-scroll-body > .preview-heading{gap:2px 6px;}
}

/* Home: allocate width to the actual words before allocating equal decoration.
   A long heading wraps beside Customize; neither action nor text scale is lost. */
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .home-scroll-body > .preview-heading{display:flex !important;flex-wrap:wrap;align-items:center;column-gap:6px;row-gap:0;margin-top:0;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-head{flex:1 1 min-content;min-width:min-content;margin:0;padding:0;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading #pa-head-t{margin:0;overflow-wrap:normal;word-break:normal;}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-customize{margin:0;min-height:44px;max-width:100%;white-space:normal;overflow-wrap:normal;word-break:normal;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto{margin-top:4px;margin-bottom:4px;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop):not([hidden]){display:flex;flex-wrap:wrap;gap:4px;}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop) .tbtn{flex:1 1 max-content;min-width:min-content;max-width:100%;overflow-wrap:normal;word-break:normal;min-height:44px;}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards{margin-top:4px;margin-bottom:4px;}
 /* Keep the disclosure named. Remove ornamental padding, not its accessible
    text, selector, status, or the rider's text multiplier. */
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance > summary{min-width:44px;min-height:44px;padding:2px 6px;font-size:calc(14px * var(--ts,1));line-height:1.3;}
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance[open] > summary{font-size:calc(16px * var(--ts,1));padding:6px 8px;}
}

/* Customize retains the same minimum touch target as Home. */
@media (max-width:900px){
 html[data-app].show-dials .pauto-mode:has(#pa-mode-loop) .tbtn{min-height:44px;}
}

/* Home closed Appearance is a compact, named native disclosure. The original
   location is provisional; open controls and other planner modes keep text. */
.planner-appearance-icon{display:none;}
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance:not([open]) > summary{display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:44px;min-width:44px;min-height:44px;padding:0;list-style:none;}
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance:not([open]) > summary::-webkit-details-marker{display:none;}
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance:not([open]) .planner-appearance-icon{display:block;width:24px;height:24px;flex:none;}
 html[data-app]:not(.has-route):not(.show-dials) .planner-appearance:not([open]) .planner-appearance-name{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}
}

/* Appearance is a planner overlay, outside the map stacking context. */
.pln{position:relative;}
.pln > .planner-appearance{left:402px;max-width:calc(100% - 414px);}
@media(max-width:900px){
 .pln > .planner-appearance{left:12px;max-width:calc(100% - 24px);}
 html[data-app] .pln > .planner-appearance{position:fixed;z-index:6;}
}

/* Mobile Home: one equal-weight frame per decision; retain real duration semantics. */
@media (max-width:900px) {
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards { align-items:stretch; }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-budget-head,
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more {
  box-sizing:border-box; height:auto; min-width:0; margin:0;
  border:1px solid var(--rule); border-radius:14px; background:var(--chrome2);
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-budget-head {
  padding:6px; justify-content:flex-start; gap:2px;
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-sub {
  display:block; width:100%; min-width:0; margin:0;
  font-size:calc(11px * var(--ts, 1)); line-height:1.35;
  color:var(--steel); white-space:normal; overflow-wrap:anywhere; text-align:center;
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more {
  padding:0; justify-content:flex-start;
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more > summary {
  box-sizing:border-box; min-height:44px; margin:0; padding:8px;
  border:0; border-radius:13px; background:transparent;
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more:not([open]) > summary {
  flex:1 0 auto;
 }
}

/* Reset inherited wrap/basis before restoring the full explanatory line.
   The complete explanation stays in the Home scroll body, after its controls. */
@media (max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-budget-head {
  flex-direction:column;flex-wrap:nowrap;align-content:normal;gap:0;
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-row {
  box-sizing:border-box;flex:0 0 auto;width:100%;max-width:100%;margin-left:0;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-sub {
  flex:0 0 auto;overflow:visible;text-overflow:clip;
 }
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more:not([open]) > summary {
  flex:0 0 auto;height:auto;
 }
}

/* Native/manual origin entry keeps its existing typography with a full touch target. */
@media (max-width:900px){
 html[data-app] .pauto-grid > .pauto-field:has(#pa-from) #pa-from{min-height:44px}
}

/* Desktop app hierarchy: same real controls, independent of phone detents. */
@media (min-width:901px){
  html[data-app] .pln{grid-template-columns:minmax(340px,390px) minmax(0,1fr);min-height:0;height:calc(100dvh - 106px)}
  html[data-app] .pln-side{position:relative;min-height:0;overflow:auto;box-sizing:border-box;padding-bottom:16px}
  html[data-app] .pln-grab{display:none!important}
  html[data-app] .pln-topbar{display:none}
  html[data-app] .pln-searchtop{position:fixed;left:414px;right:80px;top:118px;z-index:6;display:flex;align-items:center;gap:8px;padding:0 12px;min-height:44px;border:1px solid var(--rule);border-radius:14px;background:var(--panel);color:var(--ink)}
  html[data-app] .pln-searchtop input{flex:1;min-width:0;width:100%;min-height:44px;border:0;background:transparent;color:var(--ink);font-size:calc(16px * var(--ts,1))}
  html[data-app] .pln-searchtop #presults{left:0;right:0}
  html[data-app] .pln > .planner-appearance{position:fixed;left:auto;right:16px;top:118px;max-width:min(360px,calc(100vw - 430px));z-index:7}
  html[data-app] .planner-appearance:not([open]) summary{width:44px;height:44px;min-width:44px;box-sizing:border-box;padding:10px;font-size:0}
  html[data-app] .planner-appearance:not([open]) .planner-appearance-name{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  html[data-app] .planner-appearance-icon{display:block;width:24px;height:24px}
  html[data-app] .planner-appearance select{min-height:44px;max-width:100%;font-size:calc(16px * var(--ts,1))}
  html[data-app] .preview-heading{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:16px;min-width:0}
  html[data-app] .preview-heading .pln-head{flex:1 1 170px;margin:0;font-size:calc(20px * var(--ts,1));line-height:1.2;overflow-wrap:normal}
  html[data-app] .pln-customize{position:static;flex:0 0 auto;min-height:44px;padding:8px;border:0;background:transparent;color:var(--ink);font-size:calc(14px * var(--ts,1));white-space:normal}
  html[data-app] .pauto{margin:0;padding:12px 16px;border:0;background:transparent}
  html[data-app] .pauto-mode:has(#pa-mode-loop){display:flex;flex-wrap:wrap;gap:4px}
  html[data-app] .pauto-mode:has(#pa-mode-loop) .tbtn{flex:1 1 min-content;min-height:44px;white-space:normal;font-size:calc(16px * var(--ts,1));padding:8px}
  html[data-app] .pln-cards{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;margin-top:12px}
  html[data-app] .pln-cards > *{min-width:0;margin:0;padding:10px;border:1px solid var(--rule);border-radius:14px;background:var(--panel);box-sizing:border-box}
  html[data-app] #pa-budget-head{display:flex;flex-direction:column;flex-wrap:nowrap;gap:8px}
  html[data-app] #pa-budget-head .pauto-budget-row{display:flex;flex-wrap:wrap;width:100%;justify-content:center;align-items:center;gap:4px}
  html[data-app] #pa-budget-head button,html[data-app] #pa-style-more > summary{min-width:44px;min-height:44px;box-sizing:border-box}
  html[data-app] #pa-style-more > summary{white-space:normal;overflow-wrap:anywhere}
  html[data-app]:not(.has-route):not(.show-dials) .pln-side{display:flex;flex-direction:column;overflow:hidden;padding-bottom:0}
  html[data-app]:not(.has-route):not(.show-dials) .pln-side > .home-scroll-body{display:block;flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;scroll-padding:8px}
  html[data-app]:not(.has-route):not(.show-dials) .pln-side > .home-action-footer{display:block;flex:0 0 auto;padding:12px 16px;background:var(--surface);border-top:1px solid var(--rule)}
  html[data-app]:not(.has-route):not(.show-dials) .home-action-footer #pa-go{display:block;width:100%;min-height:44px;height:auto;margin:0;padding:10px;white-space:normal;font-size:calc(16px * var(--ts,1));box-sizing:border-box}
 /* P0-HOM-06 (mock-003): the house/sponsor line sits centered under Find routes, in the
    fixed footer so it is always on screen with the button it is about - never scrolled
    away with the rest of the form (js/planner-sheet.js homeOrder()). */
 html[data-app]:not(.has-route):not(.show-dials) .home-action-footer #pa-sponsor{justify-content:center;text-align:center;margin:8px 0 0}
 html[data-app]:not(.has-route):not(.show-dials) .home-action-footer #pa-note:not(:empty){margin:8px 0 0}
  html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-head{display:block!important}
  html[data-app]:not(.has-route):not(.show-dials) .pln-side > *:not(.home-scroll-body):not(.home-action-footer):not(.pexp){display:none!important}
  /* dr-gate-reds (2026-11-08): same exempt-and-split fix as the phone block above
     (css/plan.css, @media max-width:900px) for the wide/data-app window - WBH-4489's
     one-tap "way to navigation" (#pridenow, js/plan.js wayToNav()) lives inside .pexp,
     which the Home rule directly above used to hide outright. Shown here, not through
     the has-route-only rules elsewhere in this file (2010-2060, 3241-3248), because
     Home has no route to style a summary row around - just the one button. */
  html[data-app]:not(.pridenow-live):not(.has-route):not(.show-dials) .pln-side > .pexp{display:none!important}
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) .pln-side > .pexp{
    display:flex!important;flex-direction:column;margin:0 16px 16px;padding:0}
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) .pexp > *:not(#pridenow){
    display:none!important}
  html[data-app].pridenow-live:not(.has-route):not(.show-dials):not([data-psheet]) .pexp #pridenow{
    display:flex!important;align-items:center;justify-content:center;width:100%;min-height:50px;
    box-sizing:border-box;border-radius:14px;background:var(--orange);border-color:var(--orange);
    color:#181B1A;font-weight:700}
  /* P0-HOM-06: .pauto-sponsor (#pa-sponsor, the house/ad line under Find routes,
     mock-003) was missing from this allow-list, so Home hid it unconditionally - the
     opposite of what js/plan.js's homeSponsorLine() paints it for. Added, not a new
     exception class: it is the same mechanism every other Home-only control already
     uses. */
  html[data-app]:not(.has-route):not(.show-dials) .pauto > *:not(.pauto-mode):not(.pln-cards):not(.pauto-note):not(.pauto-sponsor){display:none!important}
  html[data-app].show-dials .pauto-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}
  html[data-app].show-dials .pauto-grid input{max-width:100%;min-width:0;min-height:44px;box-sizing:border-box}
  html[data-app].has-route:not(.show-dials) .pexp{flex-shrink:0;margin:0 16px 12px}
  html[data-app].has-route:not(.show-dials) .pexp button{min-height:44px;white-space:normal}
}

/* Desktop disclosure opens below the independent search row; destination keeps its real field. */
@media (min-width:901px){
 html[data-app] .pln > .planner-appearance[open]{top:174px;max-height:calc(100dvh - 190px);overflow:auto;box-sizing:border-box}
 html[data-app]:not(.has-route):not(.show-dials) .pauto:has(#pa-mode-ab[aria-pressed="true"]) > .pauto-grid:not([hidden]){display:block!important;margin-top:12px}
 html[data-app]:not(.has-route):not(.show-dials) .pauto:has(#pa-mode-ab[aria-pressed="true"]) > .pauto-grid > label[for="pa-from"],
 html[data-app]:not(.has-route):not(.show-dials) .pauto:has(#pa-mode-ab[aria-pressed="true"]) > .pauto-grid > .pauto-field:not(#pa-to-field){display:none!important}
 html[data-app] .pauto-grid > [hidden]{display:none!important}
}

/* Desktop Home: semantic heading and destination precede secondary preferences.
   The destination hint is explanatory content, never a horizontal input sibling. */
@media(min-width:901px){
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-head-t{display:block!important;margin:0;font-size:calc(20px * var(--ts,1));line-height:1.2;font-weight:800;color:var(--ink)}
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-head-s{display:block;margin-top:4px;font-size:calc(13px * var(--ts,1));line-height:1.4;color:var(--steel)}
 html[data-app]:not(.has-route):not(.show-dials) .pauto{display:flex;flex-direction:column}
 html[data-app]:not(.has-route):not(.show-dials) .pauto > .pauto-mode{order:0}
 html[data-app]:not(.has-route):not(.show-dials) .pauto > .pauto-grid{order:1}
 html[data-app]:not(.has-route):not(.show-dials) .pauto > .pln-cards{order:2}
 html[data-app]:not(.has-route):not(.show-dials) .pauto > .pauto-note{order:3}
 html[data-app] #pa-to-field:not([hidden]){display:flex;flex-direction:column;align-items:stretch;min-width:0;width:100%;height:auto;box-sizing:border-box}
 html[data-app] #pa-to-field > #pa-to{flex:0 0 auto;width:100%;max-width:100%;min-width:0;height:auto;min-height:44px;box-sizing:border-box;line-height:1.4}
 html[data-app] #pa-to-field > #pa-to-hint{flex:0 0 auto;width:100%;margin:6px 0 0;box-sizing:border-box}
}

/* Desktop app cards: existing duration controls and readable disclosed choices.
   Mobile rules and the underlying duration/style model remain unchanged. */
@media (min-width:901px){
 html[data-app] .pln-cards{align-items:start}
 html[data-app] #pa-budget-head .pauto-budget-row{display:grid;grid-template-columns:1fr 1fr;justify-items:center;gap:8px;width:100%}
 html[data-app] #pa-budget-head .pauto-budget-big{grid-column:1 / -1;grid-row:1;white-space:normal;text-align:center;max-width:100%}
 html[data-app] #pa-budget-head .pauto-step{display:inline-flex;align-items:center;justify-content:center;grid-row:2;flex:none;width:44px;height:44px;min-width:44px;min-height:44px;padding:0;border:1px solid var(--rule);border-radius:50%;background:var(--panel);color:var(--ink);font-size:calc(20px * var(--ts,1));line-height:1;cursor:pointer}
 html[data-app] #pa-budget-head .pauto-step:focus-visible{outline:2px solid var(--orange);outline-offset:2px}
 html[data-app] #pa-style-more .pauto-mode--shape{display:grid;grid-template-columns:minmax(0,1fr);gap:4px;padding:4px;max-width:100%;box-sizing:border-box}
 html[data-app] #pa-style-more .pauto-mode--shape .tbtn{width:100%;min-width:0;min-height:44px;height:auto;padding:8px 4px;white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:normal;word-break:normal;line-height:1.4;font-size:calc(16px * var(--ts,1));box-sizing:border-box}
 html[data-app] #pa-style-more .pauto-more-t{min-width:0;white-space:normal;overflow-wrap:normal}
}

/* Disclosed desktop choices use the full card row at enlarged text sizes.
   Closed cards retain equal weight; the existing scroll body owns overflow. */
@media (min-width:901px){
 html[data-app] .pln-cards > #pa-style-more[open]{grid-column:1 / -1}
}

/* Mobile Home composition. Heritage's normal phone scale is 1.5; retain its
   Large/XL ratios while using the approved 17px system control baseline. */
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials){--home-scale:calc(var(--ts,1.5) / 1.5)}
 html[data-app]:not(.has-route):not(.show-dials) .pln-side,
 html[data-app]:not(.has-route):not(.show-dials) .pln-side button,
 html[data-app]:not(.has-route):not(.show-dials) .pln-searchtop input{font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
 html[data-app]:not(.has-route):not(.show-dials) #pa-head-t{font-size:calc(24px * var(--home-scale));font-weight:700;line-height:1.2;letter-spacing:-.025em}
 html[data-app]:not(.has-route):not(.show-dials) .pln-customize{font-size:calc(16px * var(--home-scale));max-width:100%;padding:8px 0;min-height:44px}
 html[data-app]:not(.has-route):not(.show-dials) .pauto-mode:has(#pa-mode-loop) .tbtn{font-size:calc(17px * var(--home-scale));font-weight:600;min-height:44px;padding:8px}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards{gap:8px;align-items:stretch;margin:8px 0 0}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-budget-head{padding:8px 4px;display:flex;flex-direction:column;gap:0;justify-content:center;background:var(--panel)}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-lab,
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-sub{display:block;position:static;width:auto;height:auto;clip-path:none;margin:0;overflow:visible;white-space:normal;font-size:calc(13px * var(--home-scale));line-height:1.3;text-align:center}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-row{display:grid;grid-template-columns:44px minmax(0,1fr) 44px;gap:0;align-items:center;width:100%}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-big{font-family:inherit;font-size:calc(17px * var(--home-scale));line-height:1.25;font-weight:650;min-width:0;white-space:normal;text-align:center;overflow-wrap:normal}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-step{width:44px;height:44px;min-width:44px;min-height:44px;padding:0;font-size:22px}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more{background:var(--panel);justify-content:center}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-more > summary{font-family:inherit;font-size:calc(13px * var(--home-scale));line-height:1.3;min-height:44px;padding:8px;gap:4px}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards #pa-style-now{font-family:inherit;font-size:calc(17px * var(--home-scale));line-height:1.3;font-weight:650}
 html[data-app]:not(.has-route):not(.show-dials) .home-action-footer #pa-go.primary{font-size:calc(17px * var(--home-scale));min-height:52px;font-weight:650}
 html[data-app]:not(.has-route):not(.show-dials) .pln-searchtop input{font-size:calc(17px * var(--home-scale))}
}
@media(max-width:900px){
 html[data-app]:not(.has-route):not(.show-dials) .preview-heading .pln-customize{font-size:calc(16px * var(--home-scale))}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-big{grid-column:2;grid-row:1}
 html[data-app]:not(.has-route):not(.show-dials) .pln-cards .pauto-budget-row button{grid-row:1}
 html[data-app]:not(.has-route):not(.show-dials) #pa-budget-head .pauto-budget-lab{font-size:calc(13px * var(--home-scale));text-transform:none;letter-spacing:0}
}

/* Compact duration disclosure: original value remains the planner's update target. */
html[data-app="1"] .pln-cards #pa-budget-head { padding: 0; }
html[data-app="1"] #pa-duration-more { width: 100%; }
html[data-app="1"] #pa-duration-more > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 44px; padding: 8px 12px; box-sizing: border-box; cursor: pointer;
  list-style: none;
}
html[data-app="1"] #pa-duration-more > summary::-webkit-details-marker { display: none; }
html[data-app="1"] #pa-duration-more > summary::after { content: '⌄'; flex: 0 0 auto; font-size: 17px; color: var(--steel); }
html[data-app="1"] #pa-duration-more[open] > summary::after { content: '⌃'; }
/* P0-HOM mock-003: both pickers end in the SAME small down chevron at the same spot.
   Ride style's own chevron (.pauto-more-ch) ships as a literal "rsaquo" character that
   only becomes a down-chevron by rotating 90deg on open (css/plan.css's generic
   .pauto-more[open] rule, the right behaviour for a plain disclosure elsewhere on this
   page) - but Home's two pickers sit side by side and read as one matched pair, and on
   Home this row starts (and stays, until tapped) closed, so it showed a bare ">" next to
   Ride time's "⌄" forever. Swap the glyph to match Ride time's exactly, in this one
   scope, without touching the shared .pauto-more component other screens still use. */
html[data-app="1"] .pln-cards #pa-style-more > summary .pauto-more-ch {
  font-size: 0; transform: none;
}
html[data-app="1"] .pln-cards #pa-style-more > summary .pauto-more-ch::after {
  content: '⌄'; font-size: 17px; color: var(--steel);
}
html[data-app="1"] .pln-cards #pa-style-more[open] > summary .pauto-more-ch::after {
  content: '⌃';
}
html[data-app="1"] #pa-duration-more > summary:focus-visible { outline: 2px solid var(--accent, #e65f25); outline-offset: -3px; border-radius: 12px; }
html[data-app="1"] #pa-duration-more .pauto-budget-lab { margin: 0; }
html[data-app="1"] #pa-duration-more .pauto-budget-big { margin-left: auto; font-size: calc(17px * var(--home-scale, 1)); }
html[data-app="1"] #pa-duration-more .pauto-budget-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 0 12px;
}
html[data-app="1"] #pa-duration-more .pauto-step { display: block; width: 100%; min-height: 44px; }
html[data-app="1"] #pa-duration-more .pauto-budget-sub { display: block; padding: 5px 12px 10px; text-align: center; }
/* P0-HOM-03 (mock-003): clock icon + value + chevron, no visible label line - the same
   shape #pa-style-more already draws for Ride style right beside it. budgetLabel stays
   in the DOM (accessible name) but moves off-screen with the standard clip technique,
   never display:none, so it never leaves the accessibility tree. */
html[data-app="1"] #pa-budget-head #pa-duration-more > summary {
  display: grid; grid-template-columns: 17px minmax(0,1fr) 16px; align-items: center;
  gap: 2px 8px;
}
html[data-app="1"] #pa-budget-head #pa-duration-more > summary .pmt-ico {
  grid-column: 1; grid-row: 1; display: flex; align-items: center; justify-content: center;
  color: var(--steel);
}
html[data-app="1"] #pa-budget-head #pa-duration-more > summary .pauto-budget-lab.pmt-label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
html[data-app="1"] #pa-budget-head #pa-duration-more > summary .pauto-budget-big {
  grid-column: 2; grid-row: 1; order: 0; margin: 0; text-align: left;
}
html[data-app="1"] #pa-budget-head #pa-duration-more > summary::after {
  grid-column: 3; grid-row: 1; order: 0;
}

/* ===================================================================================
   NO PLAN.HTML APP-MODE SCREEN HAS A TAB BAR (P0-HOM-02, mock-003; redesign-audit-1,
   2026-10-31). js/app-shell.js's .appbar (Ride/Roads/Plan/Garage) is shared chrome
   across every app page. This USED to be scoped to the exact Home state only (no
   route, no focused sheet), on the theory that Preview/Setup/Edit/Customize keep it
   until their own screens are redesigned - but none of those screens' mockups (004,
   010, 011, 012, 013) draws a tab bar either, and the audit caught it reappearing,
   V1 and all, the moment a rider tapped Destination (data-psheet="setup"). So this is
   unconditional for the whole of plan.html's app mode: every data-psheet state and
   Preview (has-route, no sheet) alike. Outside app mode (the website, or the desktop
   app's .show-dials layout) this file never loads at all, so nothing here touches it.
   Every destination the bar held is still reachable, through the account/overflow sheet
   (js/plan.js's accountSheet + the rows added for this screen) opened by the avatar at
   the right of the search pill - never removed, only relocated.
   The map's own Layers button follows the narrower, original rule: Home's rail is N /
   3D / Locate only (mock-003); Preview's rail keeps Layers (mock-004), so only Home
   hides it, and only from the rail - the panel it opens is unchanged and reachable from
   the "Map layers" row in that same overflow sheet (js/plan.js accountLayersRow()). */
html[data-app] .appbar{display:none}
html[data-app]:not(.has-route):not([data-psheet]):not(.show-dials) #pmap-layers{display:none}

/* ===================================================================================
   FOCUSED SHEETS - Loop/Destination setup, the destination card, Customize and Edit
   stops as the brief draws them (mock-010 to mock-013). js/plan.js focusedSheets() sets
   html[data-psheet] to setup | place | customize | edit; the Home and Preview allow-lists
   above stand down while it is set (":not([data-psheet])"), and each state below names
   exactly what its sheet shows. Same controls as before, never a second copy: every
   element named here already existed or is a header/footer for one of these sheets.
   Phone app only; the website and the desktop app keep the long form.
   =================================================================================== */
@media (max-width:900px){
  html[data-app] .pfocus-head:not([hidden]){display:flex;align-items:flex-start;gap:12px;margin:0 0 12px}
  html[data-app] .pfocus-head-t{flex:1 1 auto;min-width:0}
  html[data-app] .pfocus-title{margin:0;font-family:system-ui,-apple-system,"Segoe UI",sans-serif;
    font-size:calc(26px * var(--home-scale, 1));line-height:1.15;font-weight:800;letter-spacing:-.02em;
    color:var(--ink);text-transform:none}
  html[data-app] .pfocus-sub{margin:4px 0 0;font-size:calc(15px * var(--home-scale, 1));line-height:1.35;color:var(--steel)}
  /* BUG-pcz-close (round 3, iOS mirror builder): the iOS WKWebView mirror caught this
     control at 0x0 after a destination-mode route. Not reproducible here as a
     persistent state across many Chromium-driven flows (inline Setup destination,
     destination-card search, both themes, both sizes) - every read settled at 44x44
     once the sheet-opening transition (dropMarker()'s easeTo + the detent re-measure,
     same ~300-900ms window scripts/test-planner-design.js's openDestCard() already
     retries past) finished. min-width/min-height give this control an explicit floor
     so it can never render below the 44pt target even if a future ancestor change
     reintroduces a transient collapse, on top of the flex:0 0 auto that already
     refuses to shrink it. */
  html[data-app] .pfocus-x{flex:0 0 auto;width:44px;height:44px;min-width:44px;min-height:44px;
    border-radius:50%;border:0;padding:0;
    background:var(--chrome2);color:var(--ink);font-size:24px;line-height:1;cursor:pointer;
    display:inline-flex;align-items:center;justify-content:center}
  html[data-app] .pfocus-ver{flex:0 0 auto;align-self:center;font-size:calc(14px * var(--home-scale, 1));color:var(--steel)}
  html[data-app] .pfocus-foot:not([hidden]){display:block;margin-top:12px}
  html[data-app] .pfocus-foot .primary,
  html[data-app] #pedit-recalc,
  html[data-app] .pdest-go{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;
    min-height:56px;margin:0;border:0;border-radius:14px;background:var(--orange);color:#181B1A;
    font-family:system-ui,-apple-system,"Segoe UI",sans-serif;font-size:calc(17px * var(--home-scale, 1));
    font-weight:700;letter-spacing:-.01em;text-transform:none;cursor:pointer;box-shadow:none}
  html[data-app] .pfocus-note{margin:0 0 8px;text-align:center;font-size:calc(13px * var(--home-scale, 1));color:var(--steel)}

  /* ------------------------------ the top bar ------------------------------ */
  /* Setup draws "< Plan a loop" where the search pill sits; the pill comes back on Back.
     P0-PRV-01 (mock-004): Preview draws the SAME floating pill - "< Loop from your
     location   90 min" - for the same reason: a persistent search field is not what
     mock-004 shows over a route already on the map, and "Edit route or add a stop"
     (below the Start ride button) is Preview's own, already-built door back to search. */
  html[data-app][data-psheet="setup"] .pln-searchtop,
  html[data-app][data-psheet="edit"] .pln-searchtop,
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-searchtop{display:none !important}
  html[data-app][data-psheet="setup"] .pln-topbar,
  html[data-app][data-psheet="edit"] .pln-topbar,
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar{display:flex !important;align-items:center;gap:6px;
    position:fixed;top:calc(10px + env(safe-area-inset-top,0px));left:12px;right:12px;z-index:6;
    min-height:50px;padding:0 13px 0 4px;background:var(--panel);border:1px solid var(--rule);
    border-radius:15px;box-shadow:0 8px 22px rgba(20,18,15,.14);color:var(--ink)}
  html[data-app][data-psheet="setup"] .pln-topbar .pfocus-back:not([hidden]),
  html[data-app][data-psheet="edit"] .pln-topbar .pfocus-back:not([hidden]),
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar .pfocus-back:not([hidden]){display:inline-flex;
    align-items:center;justify-content:center;width:44px;height:44px;border:0;background:none;
    color:var(--ink);font-size:22px;cursor:pointer;padding:0}
  /* A5 (c1106): single-line `white-space:nowrap` + `text-overflow:ellipsis` clips mid-word
     on any real route name longer than the demo text ("Loop from Blue Ridge Parkway, North
     Carolina" measured 350px in a 312px pill -> "Loop from Blue Ridge Parkw..."). Wrapping
     to up to 2 lines (this pill's `min-height`, not a fixed `height`, already lets it grow)
     fits a realistic name in full in almost every case; `-webkit-line-clamp` only falls back
     to an ellipsis - always after a full word, never mid-word, because the line break itself
     is a normal word-wrap break - on the rare name still too long for 2 lines. */
  html[data-app][data-psheet="setup"] .pln-topbar-t,
  html[data-app][data-psheet="edit"] .pln-topbar-t,
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar-t{font-size:calc(17px * var(--home-scale, 1));font-weight:700;
    flex:1 1 auto;min-width:0;white-space:normal;overflow-wrap:break-word;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-overflow:ellipsis;line-height:1.2}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar-dur,
  html[data-app][data-psheet="edit"] .pln-topbar-dur{flex:0 0 auto;
    font-size:calc(14px * var(--home-scale, 1));font-weight:700;color:var(--steel);padding-left:6px}
  /* mock-013: the floating pill owns Back + "Edit route" + "Version N" now; #pedit-head
     (still real, still inside the sheet) keeps the fuller "Stops & waypoints" heading and
     its own back/version chip hides so the two do not say the same thing twice. */
  html[data-app][data-psheet="edit"] #pedit-head .pfocus-x,
  html[data-app][data-psheet="edit"] #pedit-head .pfocus-ver{display:none}

  /* --------------------------- the sheet, per state --------------------------- */
  html[data-app][data-psheet="place"] .pln-side > *:not(.pln-grab):not(#pdest),
  html[data-app][data-psheet="setup"] .pln-side > *:not(.pln-grab):not(.home-scroll-body):not(.home-action-footer),
  html[data-app][data-psheet="customize"] .pln-side > *:not(.pln-grab):not(.home-scroll-body):not(.pauto),
  html[data-app][data-psheet="nearby"] .pln-side > *:not(.pln-grab):not(#pnearby-head):not(#pnearby),
  html[data-app][data-psheet="edit"] .pln-side > *:not(.pln-grab):not(#pedit-head):not(#plist):not(.padd-row):not(#ptapadd-hint):not(#precalc):not(#editor-revision-history):not(#pedit-foot){
    display:none !important}
  html[data-app][data-psheet="place"] .pln-side > #pdest,
  html[data-app][data-psheet="nearby"] .pln-side > #pnearby{display:block !important;flex:1 1 auto;min-height:0;
    overflow-y:auto;padding:0 16px 16px}
  /* #pnearby-head already carries "Worth stopping for" as the sheet's real heading;
     showNearby()'s own innerHTML (js/plan.js) repeats it as an <h3> for the places it
     used to render inline elsewhere, which would otherwise read as the same words
     twice in a row on this sheet. */
  html[data-app][data-psheet="nearby"] #pnearby h3{display:none}
  html[data-app][data-psheet] .pln-side > .home-scroll-body{display:block !important;flex:1 1 auto;min-height:0;overflow-y:auto}
  html[data-app][data-psheet="setup"] .pln-side > .home-action-footer{display:block !important}
  html[data-app][data-psheet] .preview-heading .pln-customize{display:none !important}
  html[data-app][data-psheet="customize"] .preview-heading{display:none !important}
  /* redesign-audit-1 (2026-10-31): Setup's own "Your ride"/"Your loop" heading
     (#pa-head-t/#pa-head-s, inside .preview-heading) sat flush against the screen edge
     - every OTHER rule that gives .preview-heading its 16px inset is scoped
     ":not([data-psheet])" (Home only, further up this file) or ":not(.has-route)"
     (desktop, @media min-width:901px), so Setup - reached from Home's own Destination
     tap, or from Loop's "Plan a loop" - never inherited any inset at phone width at
     all. place/customize/edit do not need the same fix: place pads #pdest directly,
     customize hides .preview-heading outright (just above), and edit never shows it
     either (css/plan.css's edit allow-list omits .home-scroll-body's heading). */
  html[data-app][data-psheet="setup"] .home-scroll-body > .preview-heading{
    display:flex !important;flex-wrap:wrap;align-items:center;gap:4px 8px;margin:4px 16px 0;min-width:0}
  html[data-app][data-psheet="edit"] .pln-side > :is(#pedit-head, #plist, .padd-row, #ptapadd-hint, #precalc, #editor-revision-history, #pedit-foot){
    margin-left:16px;margin-right:16px}
  html[data-app][data-psheet="nearby"] .pln-side > #pnearby-head{margin-left:16px;margin-right:16px}
  html[data-app][data-psheet="edit"] .padd-row{display:flex;gap:8px}
  html[data-app][data-psheet="edit"] .padd-row .padd-stop{flex:1 1 0;min-width:0;width:auto;margin:0}
  html[data-app][data-psheet="edit"] #ptapadd[aria-pressed="true"]{background:var(--orange);border-color:var(--orange);color:var(--black)}

  /* Setup: start, (destination), ride time, style, then Customize as a row (mock-011). */
  html[data-app][data-psheet="setup"] .pauto > :not(.pauto-grid):not(.pln-cards):not(#pa-more):not(.pauto-note):not(.primary){
    display:none !important}
  html[data-app][data-psheet="setup"] .pauto > .pauto-grid{display:block !important;margin-top:4px}
  html[data-app][data-psheet="setup"] .pauto-grid > :is(label[for="pa-from"], #pa-to-label):not([hidden]){display:block;
    margin:12px 0 4px;font-size:calc(13px * var(--home-scale, 1));letter-spacing:0;text-transform:none;color:var(--steel)}
  html[data-app][data-psheet="setup"] .pauto-grid > .pauto-field:not([hidden]){display:flex !important;align-items:center;
    gap:6px;flex-wrap:wrap;padding:4px 4px 4px 12px;border:1px solid var(--rule);border-radius:14px;background:var(--panel)}
  html[data-app][data-psheet="setup"] .pauto-grid > .pauto-field > input{flex:1 1 140px;min-width:0;min-height:44px;
    border:0;background:none;color:var(--ink);font-size:calc(16px * var(--home-scale, 1));padding:0}
  html[data-app][data-psheet="setup"] .pauto-grid .pauto-here{min-height:44px;border:0;border-radius:10px;
    background:var(--chrome2);color:var(--ink);padding:0 12px;font-size:calc(14px * var(--home-scale, 1))}
  html[data-app][data-psheet="setup"] .pauto-grid .pauto-sug:not([hidden]){flex-basis:100%}
  html[data-app][data-psheet="setup"] #pa-to-hint{display:none !important}
  html[data-app][data-psheet="setup"] .pauto > #pa-more{display:block !important;margin-top:10px;
    border:1px solid var(--rule);border-radius:14px;background:var(--panel)}
  html[data-app][data-psheet="setup"] #pa-more > :not(summary){display:none !important}
  html[data-app][data-psheet="setup"] #pa-more > summary{display:flex;align-items:center;gap:10px;
    min-height:52px;padding:0 14px;list-style:none;cursor:pointer;color:var(--ink);
    font-size:calc(16px * var(--home-scale, 1));font-weight:600;text-transform:none;letter-spacing:0}

  /* Customize: "Make it your ride" (mock-012). Road character, scenery, surface,
     avoidances, the rider; units/dates/return time folded into one closed row. */
  html[data-app][data-psheet="customize"] .pln-side > :is(.home-scroll-body, .pauto){padding:0 16px 16px}
  html[data-app][data-psheet="customize"] .pauto > :not(#pcz-head):not(.pln-cards):not(#pa-more):not(#pa-stage):not(#pcz-foot){
    display:none !important}
  html[data-app][data-psheet="customize"] .pauto > .pln-cards{display:block !important;margin:0}
  html[data-app][data-psheet="customize"] .pln-cards > :not(#pa-style-more){display:none !important}
  html[data-app][data-psheet="customize"] .pln-cards > #pa-style-more,
  html[data-app][data-psheet="customize"] .pauto > #pa-more{display:block !important;border:0 !important;
    background:none !important;padding:0 !important;margin:0 !important}
  html[data-app][data-psheet="customize"] :is(#pa-style-more, #pa-more) > summary{display:none !important}
  html[data-app][data-psheet="customize"] .pauto-ask{display:flex;flex-direction:column;gap:2px;margin:16px 0 8px;
    font-size:calc(17px * var(--home-scale, 1));font-weight:700;letter-spacing:0;text-transform:none;color:var(--ink)}
  html[data-app][data-psheet="customize"] :is(.pauto-ask-q,.pauto-hint){display:none !important}
  /* rd-plansetup draws the real controls as tracks and supplies their end captions.
     Keep its geometry while correcting the words to the approved mockup copy. */
  html[data-app][data-psheet="customize"] .pauto .tbtn[data-shape="sweepers"]::before{content:"Relaxed" !important}
  html[data-app][data-psheet="customize"] .pauto .tbtn[data-shape="twisty"]::before{content:"Technical" !important}
  html[data-app][data-psheet="customize"] .pauto .tbtn[data-scenery="direct"]::before{content:"Direct" !important}
  html[data-app][data-psheet="customize"] .pauto .tbtn[data-scenery="scenic"]::before{content:"More scenic" !important}
  html[data-app][data-psheet="customize"] #pa-more-adv{margin-top:16px;border-top:1px solid var(--rule);padding-top:4px}
  html[data-app][data-psheet="customize"] #pa-more-adv > summary{min-height:44px;display:flex;align-items:center;
    color:var(--ink);font-size:calc(15px * var(--home-scale, 1));font-weight:600;cursor:pointer}
  /* c1106 fix round 1, F1-rework: #pa-stage now nests INSIDE #pcz-foot (docs/
     _plan_page.html) instead of sitting between #pa-more and #pcz-foot as its own
     flex row - that mid-list placement is what ate scroll height from #pa-more and
     covered "Avoid highways", and showed a second, functionally-identical "Update
     routes" button next to #pcz-done (#pcz-done already forwards to #pa-stage-update
     when dirty - see js/plan.js). Only the hint line renders now; the nested button
     stays in the DOM for that forwarding click() call but is never shown. */
  html[data-app][data-psheet="customize"] #pcz-foot > #pa-stage:not([hidden]){display:block !important}
  html[data-app][data-psheet="customize"] #pcz-foot > #pa-stage > .pauto-mode{display:none !important}

  /* Destination card (mock-010). */
  html[data-app] .pdest-top{display:flex;align-items:center;justify-content:space-between;gap:12px}
  html[data-app] .pfocus-kicker{margin:0;font-size:calc(12px * var(--home-scale, 1));font-weight:700;
    letter-spacing:.08em;text-transform:uppercase;color:var(--steel)}
  html[data-app] #pdest .pfocus-title{font-size:calc(28px * var(--home-scale, 1))}
  html[data-app] .pfocus-row{display:flex;align-items:center;gap:12px;width:100%;min-height:56px;margin-top:10px;
    padding:6px 14px 6px 8px;box-sizing:border-box;border:1px solid var(--rule);border-radius:14px;
    background:var(--panel);color:var(--ink);text-align:left;font:inherit;cursor:pointer}
  html[data-app] .pfocus-ico{flex:0 0 auto;width:40px;height:40px;border-radius:50%;background:var(--chrome2);
    display:inline-flex;align-items:center;justify-content:center;color:var(--ink)}
  html[data-app] .pfocus-row-t{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
  html[data-app] .pfocus-row-t small{font-size:calc(13px * var(--home-scale, 1));color:var(--steel)}
  html[data-app] .pfocus-row-t b{font-size:calc(16px * var(--home-scale, 1));font-weight:600}
  html[data-app] .pfocus-ch{flex:0 0 auto;font-size:24px;color:var(--steel)}
  html[data-app] .pfocus-line{margin-top:14px}
  html[data-app] .pfocus-line-t{display:block;margin-bottom:6px;font-size:calc(15px * var(--home-scale, 1));color:var(--ink)}
  html[data-app] .pdest-styles{display:grid !important;grid-template-columns:repeat(4,minmax(0,1fr));gap:4px;
    padding:4px;border-radius:14px;background:var(--chrome2)}
  html[data-app] .pdest-styles .tbtn{min-height:44px;min-width:0;padding:4px 2px;border:0;border-radius:10px;
    white-space:normal;line-height:1.15;font-size:calc(14px * var(--home-scale, 1));background:none;color:var(--ink)}
  html[data-app] .pdest-styles .tbtn[aria-pressed="true"]{background:var(--orange);color:#181B1A}
  html[data-app] .pdest-acts{display:flex;flex-wrap:wrap;gap:4px 16px;margin:8px 0 4px}
  html[data-app] .pfocus-sec:not([hidden]){display:inline-flex;align-items:center;min-height:44px;border:0;
    background:none;padding:0;cursor:pointer;font-size:calc(15px * var(--home-scale, 1));font-weight:600;
    color:var(--ink);text-decoration:underline;text-underline-offset:3px}
  html[data-app] .pdest-go{margin-top:8px}

  /* mock-010 keeps "From your location" on one baseline. The existing swap action is
     moved into More options by focusedSheets(), so this wrapper has one full-width row. */
  html[data-app] .pdest-from-wrap{display:block;margin-top:10px}
  html[data-app] .pdest-from-wrap .pfocus-row{flex:1 1 auto;width:100%;margin-top:0}
  html[data-app] #pdest .pdest-from-wrap .pfocus-row-t{flex-direction:row;align-items:baseline;
    gap:.28em;white-space:nowrap}
  html[data-app] #pdest .pdest-from-wrap .pfocus-row-t small{font-size:calc(16px * var(--home-scale, 1));
    color:var(--ink)}
  html[data-app] .pdest-swap{min-height:44px;border:0;background:none;color:var(--ink);cursor:pointer;
    display:inline-flex;align-items:center;gap:10px;padding:0;font:inherit}
  html[data-app] .pdest-swap-label{font-size:calc(15px * var(--home-scale, 1));font-weight:600;
    text-decoration:underline;text-underline-offset:3px}
  html[data-app] .pdest-swap:active{background:var(--chrome2)}
  html[data-app] #pdest .pdest-go{position:relative}
  html[data-app] #pdest .pdest-go>span{position:absolute;right:16px;top:50%;transform:translateY(-50%)}

  /* P0-DST-01: the place stays PINNED AND LABELLED on the map (mock-010), not a bare dot.
     redesign-audit-3 (S05): a one-line, fixed-width, ellipsis-truncated pill cut real
     road names mid-word ("Blue Ridge Parkway (S..."). The mockup's own example name is
     short enough to never hit this, so the fix is not "make the mockup's pill" - it is
     "never truncate mid-word": wrap onto a second line at a WORD boundary instead of
     clipping with an ellipsis, with a wider cap so most names still fit on one line. */
  html[data-app] .pdest-pin-wrap{display:flex;flex-direction:column;align-items:center;gap:4px}
  html[data-app] .pdest-pin-label{max-width:min(78vw,260px);padding:5px 12px;border-radius:14px;
    background:var(--panel);color:var(--ink);font-size:calc(13px * var(--home-scale, 1));
    font-weight:600;line-height:1.25;white-space:normal;overflow:visible;overflow-wrap:normal;
    word-break:normal;text-align:center;box-shadow:0 2px 6px rgba(0,0,0,.35)}
  html[data-app] .pdest-pin{display:block;width:26px;height:34px;background:var(--orange);border:3px solid #fff;
    border-radius:50% 50% 50% 0;transform:rotate(-45deg);box-shadow:0 2px 6px rgba(0,0,0,.35)}
}

@media (max-width:900px){
  /* A focused sheet's middle detent fits what it carries (planner-sheet.js sizes Home to
     the bottom of the two cards, which would cut setup off after them). Capped so a band
     of map stays visible above it; collapsed and expanded keep their measured heights. */
  html[data-app][data-psheet] .pln-side[data-sheet-detent="intermediate"]{
    height:auto !important;max-height:calc(100dvh - 190px) !important}

  /* Setup: Start first, as drawn; the heading's subtitle says what the loop does. */
  html[data-app][data-psheet="setup"] .pauto{display:flex !important;flex-direction:column}
  html[data-app][data-psheet="setup"] .pauto > .pauto-grid{order:-1}
  html[data-app][data-psheet="setup"] #pa-head-s{display:block !important;margin-top:4px;
    font-size:calc(15px * var(--home-scale, 1));color:var(--steel)}
  html[data-app][data-psheet="setup"] #pa-head-t{font-size:calc(26px * var(--home-scale, 1));font-weight:800}

  /* Customize: the Home heading gives way to "Make it your ride". */
  html[data-app][data-psheet="customize"] .pln-side .home-scroll-body > .preview-heading{display:none !important}
  html[data-app][data-psheet="customize"] .pauto .pauto-mode{display:grid !important;grid-auto-flow:column;
    grid-auto-columns:minmax(0,1fr);gap:4px;margin:0;padding:4px;border:0;border-radius:14px;background:var(--chrome2)}
  html[data-app][data-psheet="customize"] .pauto .pauto-mode .tbtn{min-height:44px;min-width:0;margin:0;
    padding:4px 6px;border:0 !important;border-radius:10px;background:none;color:var(--ink);box-shadow:none;
    font-family:system-ui,-apple-system,"Segoe UI",sans-serif;font-size:calc(15px * var(--home-scale, 1));
    font-weight:600;line-height:1.15;white-space:normal;text-transform:none;letter-spacing:0}
  html[data-app][data-psheet="customize"] .pauto .pauto-mode .tbtn[aria-pressed="true"]{background:var(--orange);color:#181B1A}
  html[data-app][data-psheet="customize"] #pa-avoid-wrap{display:flex;align-items:center;gap:10px;min-height:44px;
    margin-top:14px;font-size:calc(16px * var(--home-scale, 1));color:var(--ink)}
  html[data-app][data-psheet="customize"] #pa-rider{min-height:44px;width:100%;border-radius:12px;
    border:1px solid var(--rule);background:var(--panel);color:var(--ink);font-size:calc(16px * var(--home-scale, 1))}

  /* Destination card: the primary stays on screen while the card scrolls. Keep the
     surface backstop beside/below the sticky footer without painting over the picker. */
  html[data-app] #pdest .pdest-go{position:sticky;bottom:0;z-index:1;box-shadow:0 10px 0 10px var(--surface)}

  /* Edit stops (mock-013): number, name, then reorder and remove. Up/down stay as the
     accessible alternative to dragging; leg style, arrive-by and shaping fold behind
     #pedit-opts (class .pstop-more on the list). */
  html[data-app][data-psheet="edit"] #plist{list-style:none;padding:0}
  html[data-app][data-psheet="edit"] #plist .pstop{display:grid !important;grid-template-columns:32px minmax(0,1fr);
    grid-template-areas:"n name" "n ctl";align-items:center;gap:2px 12px;margin:0;padding:10px 0;
    border:0;border-bottom:1px solid var(--rule);border-radius:0;background:none;box-shadow:none;min-height:56px;
    position:relative}
  /* mock-013's dashed rail between consecutive pins. Every row's badge sits in the
     32px "n" column, vertically CENTRED by this rule's own align-items:center
     regardless of how tall the row's text makes it - so a row's badge is always at
     50% of THAT row's own height, a constant this can anchor to without knowing any
     row's actual pixel height up front (rows range 56-122px here, real road names
     and multi-fact meta lines, not the mock's short illustrative ones). Starting
     the line at the badge's own vertical centre (not its bottom edge) and letting it
     run UNDER the badge is deliberate, not a misalignment: the badge's own solid
     background (or, for Start/Finish, the ring/flag glyph painted over it) covers
     the segment behind it, which is the standard "line passes through each marker"
     timeline look the mock itself draws. Bleeding 20px past this row's own bottom
     border means the dash reaches well into whatever the next row's own height
     turns out to be; the next row's own background/badge (painted later in DOM
     order, so on top) covers the overshoot the same way. Omitted on the last row
     (nothing below Finish to connect to) and never drawn over #pcpm's circles
     dropped for app mode (this selector is #plist-scoped to the app's own badge
     rules already; a lone 2-point edit, start+finish only, draws exactly one
     segment connecting the two, matching the mockup's own worked example). */
  html[data-app][data-psheet="edit"] #plist .pstop:not(:last-child)::before{
    content:"";position:absolute;left:14px;top:50%;bottom:-20px;width:0;
    border-left:2px dashed var(--rule);pointer-events:none;z-index:0}
  /* Only the BADGE (column "n") ever shares horizontal space with the connector -
     .pname starts at column 2, past the 32px "n" track, so it never paints over the
     line regardless of z-index and does not need to be touched (unlike an earlier
     version of this fix, which gave .pname position:relative too and, as a side
     effect, moved the containing block for .pacts' absolutely-positioned up/down
     buttons deeper into this row - confirmed directly that is what sent their
     "static position" fallback to the wrong place; see the up/down rule in
     css/rd-preview.css for the real fix for that). */
  html[data-app][data-psheet="edit"] #plist .pstop > :is(.pno, .pcpm){position:relative;z-index:1}
  html[data-app][data-psheet="edit"] #plist:not(.pstop-more) .pstop{grid-template-columns:32px minmax(0,1fr) auto;
    grid-template-areas:"n name ctl"}
  /* P0-EDT-02/mock-013: a 28px circle, not the leg card's own 48px (3rem) min-width
     badge - the base .pcpm/.pno rules were written for the long desktop list and never
     scoped down for this phone sheet, so min-width kept winning over the width set here
     (min-width floors the used value regardless of which rule has higher specificity).
     Reset it explicitly rather than relying on this rule's width alone to beat it. */
  html[data-app][data-psheet="edit"] #plist .pstop > :is(.pno, .pcpm){grid-area:n;width:28px;height:28px;min-width:28px;border-radius:50%;
    display:inline-flex;align-items:center;justify-content:center;
    font-size:13px;font-weight:700;line-height:1}
  /* Start/finish are the hollow ring and flag mock-013 draws, not "stop N" - the plain
     rule above must not force them solid, or Start loses its ring (confirmed: it was
     rendering as a filled orange disk before this exclusion). */
  html[data-app][data-psheet="edit"] #plist .pstop > :is(.pno, .pcpm):not(.pno--start):not(.pno--finish){background:var(--orange);color:#181B1A}
  html[data-app][data-psheet="edit"] #plist .pstop > .pno--start{background:none;border:2.5px solid var(--orange);box-sizing:border-box}
  html[data-app][data-psheet="edit"] #plist .pstop > .pno--finish{background:none;color:var(--orange);font-size:16px}
  html[data-app][data-psheet="edit"] #plist .pcpm u{display:none}
  html[data-app][data-psheet="edit"] #plist .pcpm b{font-size:11px}
  /* round 4: .pstop's own "n name ctl" areas (above) only ever had TWO real direct
     children (the badge and .pname) - renderTrip() (js/plan.js) nests .pctl INSIDE
     .pname, deliberately, per that function's own comment ("ALL the trailing controls
     live in ONE grid cell... one cell means the next control cannot [grow a column]
     again"), so the "ctl" column has never had an item placed in it and sits at 0 width
     (confirmed directly: getComputedStyle(.pstop).gridTemplateColumns reported
     "32px 302px 0px"). Nothing upstream of here is wrong; only this file assumed a
     sibling that was never going to exist. Making a grid of .pname ITSELF - text
     children in column 1, .pctl in column 2 spanning every row text uses - reads
     name+meta (however many lines: plain meta, or meta plus the unpaved/assumed
     .pchip, each its own child span) as one stacked block on the left and keeps
     handle+trash a single, vertically-centred column on the right, without moving
     .pctl out of .pname (which would reopen the exact "6 children, 4 columns, Remove
     hit the date picker" bug that comment is warning against). This is the fix for
     round 3's own screenshot showing only "Where I am"/Start with the rest of the
     list unreachable: every OTHER row's true height was 95-142px (name, then meta on
     its own line, then the controls row BELOW both, all block-stacked because "ctl"
     was never real) against #plist's 128px floor, so one tall row filled the whole
     visible box and the other 5 real rows (confirmed present in the DOM throughout,
     never a stops-array/timing bug) sat entirely inside #plist's own un-scrolled
     overflow. */
  html[data-app][data-psheet="edit"] #plist .pname{grid-area:name;min-width:0;
    display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:8px;align-items:center}
  html[data-app][data-psheet="edit"] #plist .pname > :not(.pctl){grid-column:1}
  html[data-app][data-psheet="edit"] #plist .pname > .pctl{grid-column:2;grid-row:1/-1;align-self:center}
  html[data-app][data-psheet="edit"] #plist .pname b{display:block;font-size:calc(16px * var(--home-scale, 1));
    line-height:1.25;font-weight:700;color:var(--ink)}
  /* ":not(.pctl)" matters: .pctl is ALSO a direct child <span> of .pname in the real
     markup (js/plan.js renderTrip()), so "any direct-child span" caught it too and its
     extra type-selector (span) out-specified the plain ".pctl{display:flex}" rule below,
     collapsing the whole control row to display:block - confirmed directly (computed
     style was "block", not "flex") and is why every row's controls used to stack into
     their own full-width lines instead of sitting in one trailing cell. */
  html[data-app][data-psheet="edit"] #plist .pname > span:not(.pctl){display:block;font-size:calc(13px * var(--home-scale, 1));color:var(--steel)}
  html[data-app][data-psheet="edit"] #plist .pctl{grid-area:ctl;display:flex;flex-wrap:wrap;align-items:center;gap:4px;justify-content:flex-end}
  /* mock-013: Start ("Where I am") and Finish ("Back to start" / the destination) are
     where the ride begins and ends, not a row you drag or trash - dragging the origin
     or deleting the destination from this list was never a sane action (there is no
     guard on data-a="rm" splicing index 0 today; hiding the control is the guard, not
     a feature removed - changing either end belongs to the "To"/"From" fields this
     list does not own). :has() keys off the badge classes renderTrip() already stamps
     (.pno--start/.pno--finish) rather than a new class, so no js/plan.js change is
     needed here either. */
  html[data-app][data-psheet="edit"] #plist .pstop:has(.pno--start) .pctl,
  html[data-app][data-psheet="edit"] #plist .pstop:has(.pno--finish) .pctl{display:none}
  html[data-app][data-psheet="edit"] #plist:not(.pstop-more) :is(.pleg, .pby, [data-a="role"], .pacts > [disabled][aria-label="Verified road pin unavailable"]){display:none !important}
  html[data-app][data-psheet="edit"] #plist .pgrip{display:inline-flex;align-items:center;justify-content:center;
    width:32px;min-height:44px;color:var(--ink);cursor:grab;font-size:22px;letter-spacing:-2px}
  html[data-app][data-psheet="edit"] #plist .pacts{display:inline-flex;gap:2px}
  html[data-app][data-psheet="edit"] #plist .pacts button{width:44px;height:44px;min-width:44px;min-height:44px;
    padding:0;border:0;border-radius:10px;background:none;color:var(--ink);font-size:18px;line-height:1}
  html[data-app][data-psheet="edit"] #plist .pacts button[disabled]{opacity:.35}
  html[data-app][data-psheet="edit"] #plist.pstop-more :is(.pleg select, .pby input, .pacts [data-a="role"]){
    min-height:44px;border-radius:10px;border:1px solid var(--rule);background:var(--panel);color:var(--ink);font-size:15px}
  html[data-app][data-psheet="edit"] #plist.pstop-more .pacts [data-a="role"]{width:auto;padding:0 10px}
  html[data-app][data-psheet="edit"] #paddstop{min-height:44px;color:var(--orange);font-weight:700;
    background:none;border:0;font-size:calc(16px * var(--home-scale, 1))}
  html[data-app][data-psheet="edit"] #pedit-opts{display:flex;margin:0 auto 4px;font-size:calc(14px * var(--home-scale, 1));color:var(--steel)}

  /* Preview's door to Save / Share / GPX / nearby (the full view). */
  html[data-app] .pln-morelink{display:none}
  html[data-app] .pln-nearbylink{display:none}
  html[data-app].has-route .pexp .pln-morelink{display:block !important;width:100%;min-height:44px;
    padding:4px;border:0;background:none;cursor:pointer;text-transform:none;letter-spacing:normal;
    font-size:calc(15px * var(--ts, 1) / 1.5);font-weight:600;color:var(--steel);text-decoration:underline;
    text-underline-offset:3px}

  /* Result glyphs: a road mark on roads, a pin on places (mock-009). */
  html[data-app] .psearch-wrap #presults .pres-glyph{position:relative}
  html[data-app] .psearch-wrap #presults .pres-glyph::before{content:"";position:absolute;inset:10px;
    background:var(--ink);-webkit-mask:var(--pres-ico) center/contain no-repeat;mask:var(--pres-ico) center/contain no-repeat;
    --pres-ico:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s-6-5.4-6-10a6 6 0 1 1 12 0c0 4.6-6 10-6 10z'/%3E%3Ccircle cx='12' cy='11' r='2'/%3E%3C/svg%3E")}
  /* c1106 repair (REDESIGN-AUDIT-11 S04 "F2"): a SECOND, independent copy of the road
     glyph, not a reference to css/poi-markers.css's own --poi-ico - this app-mode
     result-row rule's higher specificity (html[data-app] .psearch-wrap #presults
     .pres-glyph--road::before) always wins over that shared file's plain
     .poi-glyph--road::before, so editing poi-markers.css alone left every search row
     in the native app shell still drawing the old one-bend curve that reads as a ">"
     chevron at this size - confirmed live (getComputedStyle on the actual row kept
     returning this path, unchanged, after poi-markers.css's own value had already
     been fixed). Kept byte-identical to poi-markers.css's --poi-ico for .road rather
     than consolidated into one reference, to stay inside this fix's own scope. */
  html[data-app] .psearch-wrap #presults .pres-glyph--road::before{background:#181B1A;
    --pres-ico:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round'%3E%3Cpath d='M15 22C15 19.5 6 19.5 6 17C6 14.5 15 14.5 15 12C15 9.5 6 9.5 6 7C6 4.5 15 4.5 15 2'/%3E%3C/svg%3E")}
}

/* ===================================================================================
   BRIEF MAP CONTROLS, NOTICE, ACCOUNT (2026-10-29) - js/plan.js briefMapControls(),
   statusNotice(), accountSheet(). Every width, app and website: one control language.
   =================================================================================== */
.pmapctl{display:flex;flex-direction:column;gap:10px;margin:10px 10px 0 0;pointer-events:auto;clear:both;float:right}
.pmapctl--low{margin:0 10px 10px 0}
.pmapctl.is-squeezed{visibility:hidden}
.pmapbtn,.pmapctl .maplibregl-ctrl-geolocate{
  position:relative;width:44px;height:44px;min-width:44px;min-height:44px;padding:0;border-radius:50% !important;
  border:1px solid var(--rule) !important;background:var(--panel) !important;color:var(--ink);
  box-shadow:0 6px 18px rgba(0,0,0,.22);display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;font:700 14px/1 system-ui,-apple-system,"Segoe UI",sans-serif}
.pmapctl .maplibregl-ctrl-group{background:transparent;box-shadow:none;border:0;margin:0 !important}
.pmapbtn:focus-visible,.pmapctl .maplibregl-ctrl-geolocate:focus-visible{outline:3px solid var(--orange);outline-offset:2px}
/* P0-HOM mock-003: the Locate control's own default MapLibre icon is a grey/blue
   crosshair target - the mockup draws a navigation-arrow glyph (same shape family as
   the compass needle above) in orange on the white/dark rail circle, in every control
   state (default, pressed/active while tracking, error), so override the icon in all of
   them rather than only the resting state. */
.pmapctl .maplibregl-ctrl-geolocate .maplibregl-ctrl-icon,
.pmapctl .maplibregl-ctrl-geolocate:disabled .maplibregl-ctrl-icon,
.pmapctl .maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-active .maplibregl-ctrl-icon,
.pmapctl .maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-active-error .maplibregl-ctrl-icon,
.pmapctl .maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-background .maplibregl-ctrl-icon,
.pmapctl .maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-background-error .maplibregl-ctrl-icon{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FF7A1A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 19 20 12 16 5 20Z'/%3E%3C/svg%3E") !important;
  background-size:22px 22px;background-repeat:no-repeat;background-position:center}
.pmap-needle{position:absolute;left:50%;top:6px;width:0;height:0;margin-left:-6px;
  border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:11px solid var(--orange);
  transform-origin:6px 16px;transform:rotate(var(--bearing,0deg))}
.pmap-n{position:absolute;bottom:7px;left:0;right:0;text-align:center;font-size:11px;font-weight:800;color:var(--ink)}
/* P0-HOM mock-003: the button text is always "3D" (plan.js paint3d()); mock-003 draws
   it active - orange text on the same neutral white/dark rail circle every other button
   uses, not a solid-orange fill (that treatment is reserved for the segmented control
   and Find routes, the screen's one dominant action). Plain/off is the ordinary muted
   icon color every other inactive rail glyph already uses. */
#pmap-3d .pmap-3d-t{color:var(--steel)}
#pmap-3d[aria-pressed="true"] .pmap-3d-t{color:var(--orange)}
.pmap-layers-panel{position:absolute;right:66px;bottom:80px;z-index:7;min-width:230px;max-width:calc(100% - 90px);
  padding:12px 14px;border-radius:16px;background:var(--panel);color:var(--ink);border:1px solid var(--rule);
  box-shadow:0 12px 30px rgba(0,0,0,.28);font:15px/1.3 system-ui,-apple-system,"Segoe UI",sans-serif}
.pmap-layers-panel[hidden]{display:none}
.pmap-layers-h{margin:0 0 6px;font-weight:700;font-size:16px}
.pmap-layer{display:flex;align-items:center;gap:10px;min-height:44px;cursor:pointer}
.pmap-layer input{width:22px;height:22px;accent-color:var(--orange);margin:0}
.pmap-layer small{color:var(--steel);font-size:12px;margin-left:4px}
.pmap-layers-s{margin:4px 0 0;font-size:13px;color:var(--steel)}
.pmap-layers-s:empty{display:none}
/* Zoom buttons: mouse and keyboard keep them; a phone pinches, as drawn. */
@media (max-width:900px){
  .pln-map .maplibregl-ctrl-top-right > .maplibregl-ctrl-group:not(.pmapctl){display:none}
}
/* P0-HOM mock-003: the sheet now runs to the bottom edge; the scale bar carries no
   legal requirement (unlike attribution, which stays - compact, lifted above the
   sheet by briefMapControls()'s place(), js/plan.js), so on Home it is simply hidden
   rather than given a second floating corner the mockup does not draw. */
html[data-app]:not(.has-route):not(.show-dials) .maplibregl-ctrl-scale{display:none}
html[data-app].has-route .maplibregl-ctrl-scale{display:none}
.proute-bubble{padding:6px 12px;border-radius:12px;background:var(--panel);color:var(--ink);
  border:1px solid var(--rule);box-shadow:0 4px 14px rgba(0,0,0,.25);white-space:nowrap;pointer-events:none;
  font:700 15px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif}
.proute-bubble[hidden]{display:none}

/* The one notice style (P0-STA-01): under the top bar, above the map, never over the sheet. */
.pnotice{position:fixed;left:12px;right:12px;top:calc(70px + env(safe-area-inset-top,0px));z-index:8;
  display:flex;align-items:center;gap:8px;max-width:560px;margin:0 auto;padding:8px 8px 8px 14px;
  border-radius:14px;background:var(--panel);color:var(--ink);border:1px solid var(--rule);
  border-left:4px solid var(--steel);box-shadow:0 8px 22px rgba(0,0,0,.2);
  font:15px/1.35 system-ui,-apple-system,"Segoe UI",sans-serif}
.pnotice[hidden]{display:none}
/* P0-STA-01/P0-MAP-02: in the app, "under the top bar" still left this centered banner
   spanning the full width behind the N/3D rail at the same height - never exercised
   before Home opened tilted by default, because nothing showed a notice this early with
   3D off. The rail is a fixed 44px column at the right (briefMapControls()); give the
   notice room to clear it instead of passing behind it. */
html[data-app] .pnotice{right:68px}
.pnotice[data-kind="warn"]{border-left-color:#D99A00}
.pnotice[data-kind="error"]{border-left-color:#D14B3A}
.pnotice-t{flex:1 1 auto;min-width:0}
.pnotice-act{min-height:44px;padding:0 12px;border-radius:10px;border:1px solid var(--rule);background:var(--chrome2);
  color:var(--ink);font:600 15px system-ui,-apple-system,sans-serif;cursor:pointer}
.pnotice-act[hidden]{display:none}
.pnotice-x{flex:0 0 auto;width:44px;height:44px;border:0;background:none;color:var(--steel);font-size:22px;cursor:pointer}
@media (min-width:901px){ .pnotice{left:414px;top:12px} }
html:not([data-app]) .pnotice{top:12px}

/* Account button and sheet (P0-SHL-07). */
/* P0-HOM-01 (mock-003): "MRP" in orange on a tinted-orange circle by default; signed-in
   initials flip to the solid-orange/dark-text treatment (.is-in) the same way the rest of
   this app marks a selected/primary state. */
.paccount-btn{flex:0 0 auto;width:44px;height:44px;min-width:44px;margin-right:-8px;border-radius:50%;
  border:0;background:color-mix(in srgb, var(--orange) 22%, var(--panel));color:var(--orange);cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  font:800 11px/1 system-ui,-apple-system,sans-serif;letter-spacing:.02em}
.paccount-btn.is-in{background:var(--orange);color:#181B1A;font-size:14px;letter-spacing:0}
.paccount-btn--float{position:absolute;left:12px;top:12px;z-index:5;box-shadow:0 6px 18px rgba(0,0,0,.22);margin:0}
.paccount{position:fixed;inset:0;z-index:30;background:rgba(0,0,0,.35);display:flex;align-items:flex-end;justify-content:center}
.paccount[hidden]{display:none}
.paccount-card{width:100%;max-width:520px;box-sizing:border-box;padding:16px 16px calc(16px + env(safe-area-inset-bottom,0px));
  border-radius:20px 20px 0 0;background:var(--panel);color:var(--ink);max-height:85dvh;overflow:auto;
  font:16px/1.35 system-ui,-apple-system,"Segoe UI",sans-serif}
@media (min-width:901px){ .paccount{align-items:center} .paccount-card{border-radius:20px} }
.paccount-head{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.paccount-head-t{flex:1 1 auto;min-width:0}
.paccount-head h2{margin:0;font-size:24px;font-weight:800;letter-spacing:-.01em;text-transform:none;color:var(--ink)}
.paccount-head p{margin:2px 0 0;color:var(--steel);font-size:15px}
.paccount-av{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;
  background:color-mix(in srgb, var(--orange) 22%, var(--panel));color:var(--orange);font-weight:800}
.paccount-av--lg{width:48px;height:48px;flex:0 0 auto;font-size:15px;letter-spacing:.02em}
.paccount-row{display:flex;align-items:center;min-height:48px;padding:0 4px;border-bottom:1px solid var(--rule);
  color:var(--ink);text-decoration:none;font-weight:600}
.paccount-row::after{content:"\203A";margin-left:auto;color:var(--steel);font-size:22px}
/* The Layers row (button, not a link) reuses .paccount-row's look with a plain-button
   reset underneath it - same row, same chevron, no navigation. */
button.paccount-row--btn{width:100%;background:none;border:0;border-bottom:1px solid var(--rule);
  text-align:left;font:inherit;cursor:pointer}
.paccount .pfocus-x{width:44px;height:44px;border-radius:50%;border:0;background:var(--chrome2);color:var(--ink);font-size:24px;cursor:pointer}
.paccount .planner-appearance{margin-top:12px}
.paccount .planner-theme{position:static;display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:48px;padding:0 4px;border:0;border-radius:0;box-shadow:none;max-width:none;background:none;font-weight:600}
.paccount .planner-theme select{min-height:44px;border:1px solid var(--rule);border-radius:12px;padding:0 10px;background:var(--chrome2)}

/* Search bar clear (x), the brief's own instead of the browser's blue one. */
.pln-searchtop input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;display:none}
.psearch-clear{flex:0 0 auto;width:44px;height:44px;border:0;border-radius:50%;padding:0;cursor:pointer;
  background:none;color:var(--steel);display:inline-flex;align-items:center;justify-content:center}
.psearch-clear > svg{width:26px;height:26px;padding:5px;box-sizing:border-box;border-radius:50%;background:var(--chrome2)}
.psearch-clear[hidden]{display:none}
.pmapctl--corner{position:absolute;right:0;bottom:12px;z-index:3;margin:0 10px 0 0;float:none}
.pln-map .maplibregl-ctrl-top-right{transition:none}

/* R5 planner follow-up: the phone sheets are decisions, not long desktop forms. */
@media (max-width:900px){
  /* Setup follows its compact content instead of stretching a viewport percentage.
     Expanded choices scroll above the fixed action without consuming the map. */
  html[data-app][data-psheet="setup"] .pln-side[data-sheet-detent]{
    position:fixed!important;left:0!important;right:0!important;top:auto!important;bottom:0!important;
    height:auto!important;min-height:0!important;max-height:calc(100dvh - 190px)!important;padding-bottom:0!important;
    overflow:hidden!important;display:flex!important;flex-direction:column!important}
  html[data-app][data-psheet="setup"] .pln-side>.home-scroll-body{
    display:block!important;flex:0 1 auto!important;min-height:0!important;overflow-y:auto!important;overscroll-behavior:contain!important}
  /* TWO MORE LAYERS, SAME DROPDOWN. css/rd-plansetup.css already lifts #pa-from-more's
     own overflow:hidden while a result list is open ("THIS overflow:hidden ... ALSO
     CLIPS ITS OWN DROPDOWN") - .pauto-grid got the same treatment above in this file
     ("AND IT MUST NOT CLIP ITS OWN DROPDOWN"). Measured directly: even with both of
     those lifted, #pa-from-sug (ending y827) was still clipped by THIS sheet's own
     overflow:hidden (.pln-side[data-sheet-detent]) and by .home-scroll-body's
     overflow-y:auto (ending y781) - elementFromPoint inside the overlap kept returning
     #pa-go, a static element that should never have painted over an absolutely
     positioned, z-indexed dropdown; it only could because the dropdown was being
     clipped out of existence before z-index was ever compared. Same fix, two more
     ancestors: exempt both, only while the dropdown actually has rows in it. */
  html[data-app][data-psheet="setup"] .pln-side[data-sheet-detent]:has(#pa-from-sug:not([hidden])){
    overflow:visible!important}
  html[data-app][data-psheet="setup"] .pln-side>.home-scroll-body:has(#pa-from-sug:not([hidden])){
    overflow-y:visible!important}
  html[data-app][data-psheet="setup"] .pln-side>.home-action-footer{
    flex:0 0 auto!important;padding:8px 16px calc(10px + env(safe-area-inset-bottom,0px))!important;
    background:var(--surface)!important;border-top:1px solid var(--rule)!important}

  /* Preview: one compact, bottom-anchored decision panel. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-side{
    position:fixed!important;left:0!important;right:0!important;bottom:0!important;
    height:325px!important;max-height:min(325px,calc(100dvh - 190px))!important;
    padding-bottom:8px!important;overflow:hidden!important;display:flex!important;flex-direction:column!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-side>.pln-grab{
    display:block!important;flex:0 0 44px!important;min-height:44px!important;margin:0!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .preview-heading{
    flex:0 0 auto!important;margin:0 16px 4px!important;gap:1px 8px!important;overflow:visible!important;
    display:grid!important;grid-template-columns:minmax(0,1fr) 44px 44px!important;grid-template-rows:auto auto!important}
  /* A5 (c1106): same mid-word-ellipsis defect as .pln-topbar-t above, on the big sheet
     title directly below the pill - this grid cell's own nowrap+ellipsis was clipping
     "Loop from Blue Ridge Parkway, North Carolina" to "Loop from Blue Ridge Par...".
     grid-template-rows:auto auto (set just above) already grows row 1 to fit a taller
     cell, so letting this wrap up to 2 lines costs nothing else in the layout. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .preview-heading h2{
    grid-column:1!important;grid-row:1!important;min-width:0!important;
    font-size:19px!important;line-height:1.2!important;white-space:normal!important;overflow-wrap:break-word!important;
    display:-webkit-box!important;-webkit-box-orient:vertical!important;-webkit-line-clamp:2!important;
    overflow:hidden!important;text-overflow:ellipsis!important}
  /* DEAN ROUND 2026-11-08 (item 3, "cards and font are cutting off text"): this facts
     line ("59 mi · 1h 22m · Back roads, Curvy · surface: paved (confirmed)") sits right
     at the fixed 343px content width on a 375px phone - a real route with a surface
     caveat measured 343.75px of text against a 343px box, 0.75px over, enough for nowrap
     + ellipsis to clip "surface: paved (confirme...)" even though scrollWidth read only
     1px over clientWidth. Same A5 fix as the h2 title two rules up: grid-template-rows
     is already `auto auto`, so letting this row wrap to 2 lines (floor, not fixed
     height) costs nothing else in the 325px sheet budget - measured slack there is
     ~50px, one extra 15px line fits with room to spare. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .preview-heading p{
    grid-column:1/-1!important;grid-row:2!important;
    font-size:12px!important;line-height:1.25!important;white-space:normal!important;overflow:hidden!important;
    display:-webkit-box!important;-webkit-box-orient:vertical!important;-webkit-line-clamp:2!important;
    text-overflow:ellipsis!important;overflow-wrap:break-word!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .preview-heading .pcz-chips{display:none!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .preview-heading .pln-customize{
    grid-column:2!important;grid-row:1!important;
    display:flex!important;flex:0 0 44px!important;width:44px!important;min-width:44px!important;min-height:44px!important;
    padding:0!important;align-items:center!important;justify-content:center!important;font-size:0!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .preview-heading .pln-customize::before{
    display:none!important;content:none!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more{
    grid-column:3!important;grid-row:1!important;
    position:relative!important;flex:0 0 44px!important;width:44px!important;min-width:44px!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more>summary{
    display:flex!important;align-items:center!important;justify-content:center!important;width:44px!important;height:44px!important;
    list-style:none!important;font-size:0!important;color:var(--steel)!important;cursor:pointer!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more>summary::after{
    content:'•••';font-size:18px!important;letter-spacing:2px!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more:not([open])>.pln-morelink{display:none!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more:not([open])>.pln-nearbylink{display:none!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more[open]{z-index:8!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more[open]>.pln-morelink{
    display:block!important;position:absolute!important;right:0!important;top:44px!important;width:226px!important;min-height:44px!important;
    padding:9px 12px!important;border:1px solid var(--rule)!important;border-radius:12px!important;background:var(--panel)!important;
    box-shadow:0 8px 24px rgba(20,18,15,.2)!important;color:var(--ink)!important;font-size:13px!important;text-align:left!important}
  /* dr-fix-3 (2026-11-08): "Worth stopping for" (#pnearby) joins the same "..." menu as
     a second real entry, stacked 8px under "Save, share, GPX and more" rather than
     inside its toggled .pexp reveal - it is its OWN focused sub-sheet (data-psheet=
     "nearby", js/plan.js planFocus.open('nearby')), not part of that reveal-in-place
     panel. Hidden via [hidden] (not just display) whenever showNearby()/clearRoute()
     say there is nothing to suggest, so the menu never offers an empty sheet. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .ppreview-more[open]>.pln-nearbylink:not([hidden]){
    display:block!important;position:absolute!important;right:0!important;top:94px!important;width:226px!important;min-height:44px!important;
    padding:9px 12px!important;border:1px solid var(--rule)!important;border-radius:12px!important;background:var(--panel)!important;
    box-shadow:0 8px 24px rgba(20,18,15,.2)!important;color:var(--ink)!important;font-size:13px!important;text-align:left!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) #proutes{
    display:flex!important;flex:0 0 80px!important;flex-wrap:nowrap!important;gap:7px!important;
    margin:4px 16px!important;max-width:calc(100% - 32px)!important;overflow:hidden!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .proute-card{
    flex:1 1 0!important;min-width:0!important;width:auto!important;height:80px!important;min-height:80px!important;
    padding:6px 7px!important;gap:1px!important;border-radius:12px!important;overflow:hidden!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .proute-card-top{display:block!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .proute-card-kind{
    font-size:10px!important;line-height:1.05!important;margin:0!important;white-space:nowrap!important;
    overflow:hidden!important;text-overflow:ellipsis!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .proute-card-h{
    font-size:15px!important;line-height:1.1!important;margin-top:2px!important;white-space:nowrap!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .proute-card-trade{
    font-size:9px!important;line-height:1.05!important;margin-top:2px!important;white-space:nowrap!important;
    overflow:hidden!important;text-overflow:ellipsis!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .proute-card-mi{
    font-size:11px!important;line-height:1.05!important;margin-top:2px!important;white-space:nowrap!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pexp{
    flex:0 0 auto!important;gap:2px!important;margin:4px 16px 0!important;padding:0!important;
    max-width:calc(100% - 32px)!important;overflow:hidden!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pexp #pridenow{
    min-height:46px!important;border-radius:13px!important;font-size:16px!important;line-height:1!important;
    box-shadow:0 3px 10px rgba(255,91,18,.2)!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pexp .pln-editlink{
    min-height:36px!important;padding:5px 4px 0!important;font-size:14px!important}
  /* The full desktop itinerary remains in the model/export views, but it must not
     trail beneath the phone preview sheet. The accepted route is represented here
     by its map, compact metadata, alternatives and rider actions. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) :is(#pstatus,#pwx-alt,#pout,#pnearby){
    display:none!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-side>.pauto:not(:has(#pa-trip-wrap:not([hidden]))){
    display:none!important}
  /* dr-gate-reds (2026-11-08): the rule above hides the whole Home sheet once a route
     exists - right for the ordinary case, wrong for #pa-trip-wrap (Start fresh / Fill
     in my trip / Carry on), which js/plan.js's paAppendUI() un-hides whenever any stop
     exists - which includes a route loaded from a share link or a pending-trip push,
     one that draws its own naive first pass and flips has-route within a couple of
     seconds, before a rider has had any chance to ask for the enhanced "Fill" pass.
     :has() carves out exactly that case rather than widening the blanket hide; .pauto's
     OTHER children stay hidden via the exemption already added a few lines up
     (.pauto > *:not(...):not(#pa-trip-wrap):not(#pa-trip-hint)). test-dates.js caught
     it: #pa-fill settles at 0x0 a few seconds after load, every run - not a timing
     flake, has-route flipping true is what does it. (The add-a-waypoint regression this
     first appeared to cause in test-poi.js was a different, pre-existing gap in that
     test - it never opened Edit before reaching for #pnearby's Add button after
     #pnearby moved there; fixed in test-poi.js directly, confirmed by reverting this
     rule to prove it was not the cause.) */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-side>.pauto:has(#pa-trip-wrap:not([hidden])){
    display:block!important;padding:0!important;margin:0 16px 12px!important;border:0!important;background:none!important}

  /* Preview and Edit share the mockup's separate back circle and title pill. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar,
  html[data-app][data-psheet="edit"] .pln-topbar{
    left:12px!important;right:12px!important;padding:0!important;gap:8px!important;background:none!important;
    border:0!important;box-shadow:none!important;border-radius:0!important}
  /* Android's native overflow occupies the top-right edge above the WebView. */
  html[data-app][data-psheet="edit"] .pln-topbar{right:64px!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar .pfocus-back,
  html[data-app][data-psheet="edit"] .pln-topbar .pfocus-back{
    flex:0 0 44px!important;width:44px!important;height:44px!important;border-radius:50%!important;
    background:var(--panel)!important;border:1px solid var(--rule)!important;box-shadow:0 4px 14px rgba(0,0,0,.2)!important}
  /* A5 (c1106): this rule (not the earlier, lower-specificity .pln-topbar-t block above -
     confirmed live which one actually paints) is what rendered "Loop from Blue Ridge
     Parkw..." clipped mid-word: a fixed line-height:42px plus nowrap+ellipsis forces
     exactly one line no matter the real route name's length. Letting it wrap up to 2
     lines (min-height floor, not a fixed line-height, so the pill can grow) fits a
     realistic name in full in almost every case; line-clamp's own ellipsis fallback only
     ever lands after a whole word, same reasoning as the other .pln-topbar-t rule. */
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar-t,
  html[data-app][data-psheet="edit"] .pln-topbar-t{
    flex:1 1 auto!important;min-width:0!important;min-height:44px!important;box-sizing:border-box!important;
    padding:7px 76px 7px 14px!important;border-radius:15px!important;
    background:var(--panel)!important;border:1px solid var(--rule)!important;box-shadow:0 4px 14px rgba(0,0,0,.2)!important;
    white-space:normal!important;overflow-wrap:break-word!important;line-height:1.25!important;
    display:-webkit-box!important;-webkit-box-orient:vertical!important;-webkit-line-clamp:2!important;
    overflow:hidden!important;text-overflow:ellipsis!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar-dur,
  html[data-app][data-psheet="edit"] .pln-topbar-dur{position:absolute!important;right:12px!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar-t{font-size:12px!important}
  html[data-app].has-route:not(.show-dials):not([data-psheet]) .pln-topbar-dur{
    right:4px!important;z-index:2!important;min-width:46px!important;padding-left:7px!important;background:var(--panel)!important;
    font-size:11px!important;text-align:right!important}

  /* Destination keeps its main card clean; secondary paths remain one disclosure away. */
  html[data-app][data-psheet="place"] .pln-side{
    position:fixed!important;left:0!important;right:0!important;top:61dvh!important;bottom:0!important;height:auto!important;
    min-height:0!important;max-height:none!important;padding:0!important;overflow:hidden!important}
  html[data-app][data-psheet="place"] .pln-side>#pdest{position:relative;padding:0 16px 8px!important;overflow-y:auto!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-title{
    font-size:21px!important;line-height:1.08!important;display:-webkit-box!important;-webkit-line-clamp:2!important;
    -webkit-box-orient:vertical!important;overflow:hidden!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-row{min-height:46px!important;margin-top:6px!important;padding-top:3px!important;padding-bottom:3px!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-ico{width:32px!important;height:32px!important}
  html[data-app][data-psheet="place"] #pdest .pdest-style-line{margin-top:5px!important}
  html[data-app][data-psheet="place"] #pdest .pdest-go{min-height:48px!important;margin-top:5px!important}
  html[data-app][data-psheet="place"] .pdest-more{position:absolute!important;z-index:4!important;top:0!important;right:12px!important;
    width:44px!important;height:0!important;margin:0!important;border:0!important;overflow:visible!important}
  html[data-app][data-psheet="place"] .pdest-more>summary{position:absolute!important;top:0!important;right:0!important;
    width:44px!important;min-height:44px;display:flex;align-items:center;justify-content:center;color:var(--steel);
    font-size:0;font-weight:650;cursor:pointer;list-style:none}
  html[data-app][data-psheet="place"] .pdest-more>summary::after{content:"\2022\2022\2022";font-size:18px;letter-spacing:2px}
  html[data-app][data-psheet="place"] .pdest-more[open]{left:16px!important;right:16px!important;top:44px!important;
    width:auto!important;height:auto!important;padding:8px 12px!important;border-radius:12px!important;
    background:var(--panel)!important;box-shadow:0 8px 24px rgba(20,18,15,.2)!important}
  html[data-app][data-psheet="place"] .pdest-more[open]>summary{top:-44px!important;right:-4px!important}
  html[data-app][data-psheet="place"] .pdest-more:not([open])>.pdest-acts{display:none!important}
  html[data-app][data-psheet="place"] .pdest-acts{display:flex!important;flex-direction:column!important;margin:0!important}

  /* Customize: scroll only the choices; keep one honest Update action fixed below. */
  html[data-app][data-psheet="customize"] .pln-side[data-sheet-detent]{
    position:fixed!important;left:0!important;right:0!important;top:auto!important;bottom:0!important;
    height:516px!important;min-height:0!important;max-height:calc(100dvh - 190px)!important;padding:0!important;overflow:hidden!important;
    display:flex!important;flex-direction:column!important}
  html[data-app][data-psheet="customize"] .pln-side>.pln-grab{
    flex:0 0 14px!important;height:14px!important;min-height:14px!important}
  html[data-app][data-psheet="customize"] .pln-searchtop{right:64px!important}
  html[data-app][data-psheet="customize"] .pln-side>.home-scroll-body{
    display:flex!important;flex:1 1 auto!important;min-height:0!important;padding:0!important;overflow:hidden!important}
  html[data-app][data-psheet="customize"] .pln-side>.home-scroll-body>.preview-heading{display:none!important}
  html[data-app][data-psheet="customize"] .pln-side>.pauto,
  html[data-app][data-psheet="customize"] .pln-side>.home-scroll-body>.pauto{
    display:flex!important;flex:1 1 auto!important;min-height:0!important;flex-direction:column!important;
    padding:0!important;margin:0!important;overflow:hidden!important}
  /* dr-fix-1 item 3 (mock-012 S07): the grab handle (14px box, bar centred within it)
     sat 2px above "Make it your ride" - read as touching in the gate composite. #pa-more
     (below) already scrolls its own overflow (overflow-y:auto, confirmed independently
     taller than its box at both phone sizes), so this padding-top does not compete with
     any fixed, must-fit-above-the-footer budget - it only grows the always-visible
     header, same as the mockup's own clearer gap there. */
  html[data-app][data-psheet="customize"] #pcz-head{flex:0 0 auto!important;margin:0 16px 4px!important;padding-top:5px}
  html[data-app][data-psheet="customize"] .pauto>.pln-cards,
  html[data-app][data-psheet="customize"] .pauto>#pa-more{flex:0 0 auto!important;margin-left:16px!important;margin-right:16px!important}
  html[data-app][data-psheet="customize"] .pauto>#pa-more{
    flex:1 1 auto!important;min-height:0!important;overflow-y:auto!important;overscroll-behavior:contain!important;
    padding-bottom:8px!important;scroll-padding-bottom:8px!important}
  html[data-app][data-psheet="customize"] .pauto-ask{margin:7px 0 4px!important;font-size:14px!important}
  /* VERTICAL RHYTHM (coordinator web review, 2026-11-06, c1106 R4): Surface's own
     control row got NO bottom margin at all (falling back to the general
     .pauto-mode{margin:0} rule above), so it crowded "Avoid highways" right under it -
     measured directly (Playwright, 390x844): .pauto-mode--surface-primary bottom=635,
     #pa-avoid-wrap top=639, a 4px gap. 8px is a real, deliberately modest bump (not
     matched to Scenery's margin, which also has to absorb an overflowing caption
     Surface does not carry - see css/rd-plansetup.css): #pa-more must still fit entirely
     above the pinned Update footer with no scroll (P0-CUZ-DENSITY), and at 375x667 that
     budget is only ~2px at baseline, so every pixel added here is a pixel Suggested
     stops loses; 8px doubles the old 4px gap without spending more of that tight budget
     than the fix can afford. */
  html[data-app][data-psheet="customize"] .pauto .pauto-mode.pauto-mode--surface-primary{margin-bottom:8px!important}
  html[data-app][data-psheet="customize"] .pauto :is(.pauto-mode.pauto-mode--shape,.pauto-mode.pauto-mode--scenery) .tbtn::after{
    display:none!important}
  html[data-app][data-psheet="customize"] .pauto :is(.pauto-mode.pauto-mode--shape,.pauto-mode.pauto-mode--scenery) .tbtn[aria-pressed="true"]::after{
    display:block!important}
  html[data-app][data-psheet="customize"] .pauto-routing-advanced,
  html[data-app][data-psheet="customize"] .pauto-advanced-ride,
  html[data-app][data-psheet="customize"] #pa-more-adv{margin-top:8px!important;border-top:1px solid var(--rule)!important}
  html[data-app][data-psheet="customize"] .pauto-mode--surface-primary{grid-template-columns:repeat(2,minmax(0,1fr))!important}
  html[data-app][data-psheet="customize"] .pauto-mode--surface-primary .tbtn[aria-pressed="true"]{
    background:var(--orange)!important;color:#181b1a!important;border-color:var(--orange)!important}
  html[data-app][data-psheet="customize"] .pcz-switch-row{
    display:flex!important;align-items:center!important;justify-content:space-between!important;gap:16px!important;
    /* Same rhythm as the group above it: Surface's control row now carries its own
       13px margin-bottom (c1106 R4), so this only needs to clear that, not replace it -
       4px measured as crowding (surfaceMode bottom=635, avoidWrap top=639) before. */
    min-height:44px!important;margin-top:4px!important;color:var(--ink)!important;font-size:16px!important;font-weight:650!important}
  html[data-app][data-psheet="customize"] .pcz-switch-row input{
    appearance:none!important;position:relative!important;flex:0 0 48px!important;width:48px!important;height:28px!important;
    min-width:48px!important;max-width:48px!important;min-height:28px!important;max-height:28px!important;
    margin:0!important;border:1px solid var(--rule)!important;border-radius:999px!important;background:var(--chrome2)!important;
    cursor:pointer!important}
  html[data-app][data-psheet="customize"] .pcz-switch-row input::after{
    content:""!important;position:absolute!important;left:3px!important;top:3px!important;width:20px!important;height:20px!important;
    border-radius:50%!important;background:#fff!important;box-shadow:0 1px 3px rgba(0,0,0,.3)!important;transition:transform .12s ease!important}
  html[data-app][data-psheet="customize"] .pcz-switch-row input:checked{background:var(--orange)!important;border-color:var(--orange)!important}
  html[data-app][data-psheet="customize"] .pcz-switch-row input:checked::after{
    background:#fff!important;transform:translateX(20px)!important}
  html[data-app][data-psheet="customize"] .pauto-suggested-main{
    display:block!important;position:relative!important;height:auto!important;min-height:68px!important;margin-top:2px!important;
    padding-top:7px!important;border-top:1px solid var(--rule)!important}
  html[data-app][data-psheet="customize"] .pauto-suggested-main .pauto-ask{
    margin:0!important;color:var(--steel)!important;font-size:12px!important;font-weight:500!important;line-height:16px!important}
  html[data-app][data-psheet="customize"] .pauto-suggested-main .pauto-sel{
    display:block!important;width:100%!important;height:44px!important;min-height:44px!important;max-width:none!important;margin:0!important;
    padding:0 28px 0 0!important;border:0!important;background-color:transparent!important;color:var(--ink)!important;
    text-align:left!important;font-size:15px!important;font-weight:650!important}
  html[data-app][data-psheet="customize"] .pmapctl--low{display:none!important}
  html[data-app][data-psheet="customize"] .pauto-routing-advanced>summary,
  html[data-app][data-psheet="customize"] .pauto-advanced-ride>summary,
  html[data-app][data-psheet="customize"] #pa-more-adv>summary,
  html[data-app][data-psheet="customize"] .pauto-stage-more>summary{
    display:flex!important;align-items:center!important;min-height:44px!important;list-style:none!important;
    color:var(--steel)!important;font-size:14px!important;font-weight:650!important;cursor:pointer!important}
  /* DEAN ROUND 2026-11-08: Suggested stops (docs/_plan_page.html, now the same
     label-above-value .pauto-more row as Ride style) inherited the GENERIC
     min-height:62px/padding:10px 14px summary row (built for a top-level toggle like
     "Customize preferences"); P0-CUZ-DENSITY (scripts/test-plansetup-redesign.js)
     measured the row below it landing 1.125px under the pinned Update footer at
     390x844 as a direct result. min-height alone does not fix it - the label+value
     text itself needs ~59px, more than even the 44px every sibling row below uses - so
     this trims the row's own padding instead, the actual slack P0-CUZ-DENSITY needs. */
  html[data-app][data-psheet="customize"] #pa-suggested-stops>summary{
    min-height:0!important;padding:7px 14px!important}
  html[data-app][data-psheet="customize"] .pauto-routing-advanced:not([open])>:not(summary),
  html[data-app][data-psheet="customize"] .pauto-advanced-ride:not([open])>:not(summary),
  html[data-app][data-psheet="customize"] .pauto-stage-more:not([open])>:not(summary){display:none!important}
  html[data-app][data-psheet="customize"] .pauto-stage-more{display:none!important}
  html[data-app][data-psheet="customize"] .pauto:has(#pa-stage:not([hidden])) #pa-more>.pauto-stage-more{
    display:block!important}
  /* c1106 fix round 1, F1-rework (coordinator, looking at the F1 shots): the previous
     pass gave #pa-stage its own sizing but left it a separate flex row between
     #pa-more and #pcz-foot - that ate height straight out of #pa-more's scroll area
     (covering "Avoid highways" at the smaller viewports) and showed its own "Update
     routes" button stacked right above #pcz-done's identical one. #pa-stage now nests
     INSIDE #pcz-foot (docs/_plan_page.html), which was always its own fixed-height
     footer row outside #pa-more's scroll area, so nothing else loses height when it
     appears. Only its hint line renders (#pcz-foot>#pa-stage>.pauto-mode above stays
     display:none) - #pcz-done is the one visible action, and already forwards to
     #pa-stage-update when dirty (js/plan.js), so behavior is unchanged. */
  html[data-app][data-psheet="customize"] #pcz-foot>#pa-stage>.pauto-hint{
    display:block!important;margin:0!important;color:var(--ink)!important;font-size:13px!important;
    font-weight:600!important;line-height:1.3!important}
  html[data-app][data-psheet="customize"] #pcz-foot{
    display:flex!important;flex-direction:column!important;gap:8px!important;flex:0 0 auto!important;
    margin:0!important;padding:8px 16px calc(10px + env(safe-area-inset-bottom,0px))!important;
    background:var(--surface)!important;border-top:1px solid var(--rule)!important}
  html[data-app][data-psheet="customize"] #pcz-done{width:100%!important;min-height:52px!important;border-radius:14px!important}
  /* c1106 W1 (REDESIGN-AUDIT-7 S07): #pcz-done is never disabled any more (js/plan.js
     syncCustomizeStage()) - this opacity rule used to be the pale/"broken-looking"
     primary CTA the audit flagged on all 3 platforms. Removed rather than left dead. */

  /* Edit: the list owns the flexible middle; note/action/restore stay in view. */
  html[data-app][data-psheet="edit"] .pln-side[data-sheet-detent]{
    position:fixed!important;left:0!important;right:0!important;
    /* Complementary viewport top/height keeps the full four-row edit visible.
       Include the detent attribute below to override the generic focused-sheet
       rule; rd-preview.css no longer caps Edit at 100dvh minus 345px. */
    top:min(53dvh, calc(100dvh - 397px))!important;bottom:auto!important;
    height:max(47dvh, 397px)!important;
    min-height:0!important;max-height:none!important;
    padding:0!important;overflow:hidden!important;display:flex!important;flex-direction:column!important}
  html[data-app][data-psheet="edit"] .pln-side>.pln-grab{
    flex:0 0 14px!important;min-height:14px!important;height:14px!important}
  /* Edit deliberately leaves a shorter map band than Preview. Put the two lower
     controls side-by-side there so 3D, Layers and Locate all remain usable without
     overlapping the header or forcing the placement guard to hide the lower rail. */
  html[data-app][data-psheet="edit"] .pmapctl--low{
    flex-direction:row!important;visibility:visible!important}
  html[data-app][data-psheet="edit"] #pedit-head{flex:0 0 48px!important;margin:0 16px!important;padding-right:60px!important;align-items:center!important}
  html[data-app][data-psheet="edit"] #pedit-head .pfocus-title{font-size:20px!important;line-height:1.05!important}
  html[data-app][data-psheet="edit"] #pedit-sub{font-size:13px!important;line-height:1.15!important;
    white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important}
  html[data-app][data-psheet="edit"] #plist{
    display:block!important;flex:1 1 auto!important;min-height:0!important;overflow-y:auto!important;
    overscroll-behavior:contain!important;margin:0 16px!important}
  html[data-app][data-psheet="edit"] #plist .pstop{
    min-height:44px!important;padding:0!important;border-bottom:0!important;box-sizing:border-box!important}
  /* Up/down remain keyboard-reachable but are absolutely positioned by
     rd-preview.css. Prevent their control wrapper from retaining a second flex
     line: ordinary road-name rows then use the same 44px allocation as their real
     Remove action, while Start/Finish keep their readable two-line labels. */
  html[data-app][data-psheet="edit"] #plist .pstop:not(:has(.pno--start)):not(:has(.pno--finish)){
    height:44px!important}
  html[data-app][data-psheet="edit"] #plist .pctl{flex-wrap:nowrap!important;margin-top:0!important}
  html[data-app][data-psheet="edit"] #plist .pstop:not(:last-child)::before{border-left:1px solid var(--rule)!important}
  html[data-app][data-psheet="edit"] #plist .pname b{font-size:14px!important;line-height:1.05!important;
    white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important}
  html[data-app][data-psheet="edit"] #plist .pname>span:not(.pctl){display:block!important;margin-top:1px!important;font-size:10px!important}
  /* The sheet header already carries the route-wide time/distance/surface summary.
     Repeating per-leg curve metrics makes a real two-stop ride taller than the S08
     viewport and pushes Finish behind the fixed action footer. Keep the meaningful
     endpoint sublabels, but let numbered stops be the compact road-name rows drawn
     in the reference; their full leg data remains available in editing tools. */
  html[data-app][data-psheet="edit"] #plist .pstop:not(:has(.pno--start)):not(:has(.pno--finish)) .pname>span:not(.pctl){
    display:none!important}
  html[data-app][data-psheet="edit"] .padd-row{flex:0 0 44px!important;margin:0 16px!important}
  html[data-app][data-psheet="edit"] .padd-row .padd-stop{justify-content:flex-start!important;border:0!important;padding:0 0 0 2px!important}
  html[data-app][data-psheet="edit"] #pedit-foot{
    display:flex!important;flex:0 0 auto!important;flex-direction:column!important;margin:0!important;
    padding:3px 16px calc(4px + env(safe-area-inset-bottom,0px))!important;background:var(--surface)!important;
    border-top:1px solid var(--rule)!important}
  html[data-app][data-psheet="edit"] #precalc{
    display:grid!important;grid-template-columns:1fr auto!important;align-items:center!important;gap:2px 10px!important;
    margin:0!important;padding:0!important;border:0!important;background:none!important;box-shadow:none!important}
  html[data-app][data-psheet="edit"] #pedit-pending-note{display:block!important;grid-column:1/-1!important;margin:0!important;
    font-size:12px!important;color:var(--steel)!important}
  html[data-app][data-psheet="edit"] #pedit-recalc{grid-column:1/-1!important;width:100%!important;min-height:44px!important;border-radius:13px!important}
  html[data-app][data-psheet="edit"] .precalc-ver{display:none!important}
  html[data-app][data-psheet="edit"] #precalc-undo{justify-self:center!important;grid-column:1/-1!important;min-height:44px!important;border:0!important;
    padding:0 12px!important;background:none!important;color:var(--steel)!important;text-decoration:underline!important;font-size:12px!important;
    font-weight:500!important;text-transform:none!important;letter-spacing:0!important}
  html[data-app][data-psheet="edit"] .pedit-more{
    position:absolute!important;z-index:4!important;top:14px!important;right:16px!important;width:46px!important;
    margin:0!important;border:1px solid var(--rule)!important;border-radius:12px!important;background:var(--panel)!important}
  html[data-app][data-psheet="edit"] .pedit-more[open]{left:16px!important;right:16px!important;width:auto!important;
    padding:6px 12px 12px!important;box-shadow:0 8px 24px rgba(20,18,15,.2)!important}
  html[data-app][data-psheet="edit"] .pedit-more>summary{min-height:44px;display:flex;align-items:center;justify-content:center;list-style:none;
    color:var(--steel);font-size:0;font-weight:650;cursor:pointer}
  html[data-app][data-psheet="edit"] .pedit-more>summary::after{content:"•••";font-size:18px;letter-spacing:2px}
  html[data-app][data-psheet="edit"] .pedit-more:not([open])>:not(summary){display:none!important}
  html[data-app][data-psheet="edit"] #pedit-done{display:none!important}
}

/* Short phones retain the same map clearance and scrollable choice region. */
@media (max-width:900px) and (max-height:700px){
  html[data-app][data-psheet="customize"] #pcz-head{margin-bottom:0!important;padding-top:0!important}
  html[data-app][data-psheet="customize"] .pauto-ask{margin:3px 0 2px!important}
  html[data-app][data-psheet="customize"] .pauto-mode--surface-primary{padding:0!important}
  html[data-app][data-psheet="customize"] .pauto :is(.pauto-mode.pauto-mode--shape,.pauto-mode.pauto-mode--scenery){margin-top:2px!important}
  /* dr-fix-1 item 3: the taller-phone Curviness/Suggested-stops fixes live in
     css/rd-plansetup.css, which loads AFTER this file (docs/_plan_page.html) and so
     wins any tie at equal specificity - the actual short-phone reverts for both are
     there, in this same media query, not here. */
  html[data-app][data-psheet="customize"] .pauto-suggested-main{
    min-height:63px!important;margin-top:0!important;padding-top:2px!important}
  /* Same P0-CUZ-DENSITY fit as the 390x844 padding trim above, with more of it: the
     short 375x667/700-tall phone measured 4.375px of overflow even after that first
     trim (label+value content height is fixed; only the row's own padding can give). */
  html[data-app][data-psheet="customize"] #pa-suggested-stops>summary{
    padding:3px 14px!important}
  html[data-app][data-psheet="place"] .pln-side{
    top:58.5dvh!important;height:auto!important;min-height:0!important;max-height:none!important}
  html[data-app][data-psheet="place"] .pln-side>#pdest{padding-bottom:4px!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-kicker{font-size:10px!important;line-height:1!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-title{font-size:18px!important;line-height:1.02!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-sub{margin-top:2px!important;font-size:13px!important;line-height:1.15!important}
  html[data-app][data-psheet="place"] #pdest .pdest-from-wrap{margin-top:4px!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-row{min-height:44px!important}
  html[data-app][data-psheet="place"] #pdest .pfocus-ico{width:30px!important;height:30px!important}
  html[data-app][data-psheet="place"] #pdest .pdest-style-line{margin-top:3px!important}
  html[data-app][data-psheet="place"] #pdest .pdest-style-more>summary{
    min-height:44px!important;padding:3px 9px!important;box-sizing:border-box!important}
  html[data-app][data-psheet="place"] #pdest .pdest-go{
    position:relative!important;min-height:44px!important;margin-top:3px!important;box-shadow:none!important}
  html[data-app][data-psheet="edit"] .pln-side{
    top:min(53dvh, calc(100dvh - 397px))!important;height:max(47dvh, 397px)!important;
    min-height:0!important;max-height:none!important}
}

/* P1-SAV-01-web: quick Save/Share/GPX proxy for plain web (see designQuickSaveShareGpx
   in js/plan.js). App mode never creates this row — it already shows the real
   controls up top via "Save, share, GPX and more" once a route exists. Pinned at the
   very top of the sheet (appended into .preview-heading, which lays its children out
   in-flow via display:contents) so it is visible the instant a route comes back, with
   no scroll past the destination/shape/budget/bike form that follows it on this
   layout. Buttons, not links: these forward clicks to the real #psave/#pshare/#pgpx
   and mirror their own text, so the status text IS #psave's, never a second copy. */
/* One row, never stacked: on the shortest supported viewport (375x667) this sits
   right under a 52vh map, so three full-width stacked buttons pushed "Download GPX"
   past the fold — exactly the long-scroll problem this exists to remove. Equal
   thirds with ellipsis keeps all three on-screen, untouched, at every supported
   width (measured: fits 375x667 with ~30px to spare). */
.pln-quicksave{display:flex;gap:6px;flex-wrap:nowrap;width:100%;order:-1;margin:12px 16px 0;padding:8px 10px;
  background:var(--panel);border:1px solid var(--rule);border-radius:12px;box-sizing:border-box}
.pln-quicksave[hidden]{display:none}
.pln-quicksave button{flex:1 1 0;min-width:0;min-height:44px;padding:6px 4px;border-radius:9px;
  border:1px solid var(--ink);background:var(--surface);color:var(--ink);font:600 12px/1.2 "Libre Franklin",
  system-ui,-apple-system,sans-serif;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-align:center}
.pln-quicksave button:disabled{opacity:.5;cursor:default}
.pln-quicksave button.pln-quicksave-save{background:var(--orange);border-color:var(--orange);color:#181B1A;font-weight:800}
