/* ================================================================================================
   YPD ONE-APP SHELL, app.css, Phase B1
   Built 1:1 from the APPROVED mock: 050-Documents\YPD-SHELL-MOCKUP-V1A.html
   Rulebook: the machine-readable <script id="ypd-design-rules"> block inside that mock. LAW.

   ************************************************************************************************
   *  SHEET GEOMETRY IS TOKEN-OWNED.                                                              *
   *  Sheet height, min-height, flex sizing, insets and margins are set ONLY inside the block     *
   *  marked SHEET-GEOMETRY-START / SHEET-GEOMETRY-END below, and only through the design tokens  *
   *  (--sheet-inset, --sheet-top, --foot-h, --hd-h).                                             *
   *  NO screen rule may set a sheet's height, min-height, flex or margins. Why: min-height       *
   *  silently beats max-height, and one screen's private rule broke the 5 percent gap four       *
   *  times in the mock era (recorded in the rulebook). The build check rejects violations.       *
   ************************************************************************************************

   Format system (rulebook "formats"): TALL is the default token set (phones, folded).
   LONG (Z Fold open, about 1.2:1) is applied by the media query at the bottom,
   @media (min-aspect-ratio: 6/5), which swaps the token values and nothing else structural
   except the long-only rules the mock itself carried (.tools columns, narrow sheet width).
   ================================================================================================ */

/* ---- color tokens (mock kit, unchanged) -------------------------------------------------------- */
:root{
  --ink:#0A0A0A; --muted:#5A5A57; --orange:#FF3B00; --good:#1F9D57; --red:#E11900;
  --line:#DDDBD4; --paper:#F4F4F2; --bg:#EDEDEA; --lime:#B6FF3B;
  /* b563: the raw hex values the UI audit found (#19 to #25), named once here and used by name everywhere */
  --pax:#1650C7;          /* passenger blue (b367) */
  --good-tint:#E7F5EC; --good-ink:#0F5C2A; --good-deep:#0E7A42;   /* Online and Active fills and text */
  --red-tint:#FCE5E0; --red-wash:#FFF1EF; --red-ink:#C2170A;      /* Offline fills and text */
  --placeholder:#C9C5BE; --grab:#D3D0C9; --map-bg:#EFEDE7; --hint:#B9B6AE; --gmaps:#188038;

  /* ---- b106: THE --ypd-* FAMILY RESOLVES HERE. ypd-tokens.css is the OLD portal's sheet and
     app.html has never loaded it, so 40 var(--ypd-*) references written since b91 all computed
     to nothing, which is how an ADD button shipped as white text on a transparent background and
     Ahmed reported "no way to edit" on a button that hit-tested perfectly. Aliased to this file's
     own tokens where one exists, and to the canonical ypd-tokens.css hex where it does not, so
     the next rule written against either family just works. t90 asserts every var() in this file
     is defined in this file. ------------------------------------------------------------------ */
  --ypd-ink: var(--ink);        --ypd-orange: var(--orange);  --ypd-mist: var(--paper);
  --ypd-line: var(--line);      --ypd-steel: var(--muted);    --ypd-success: var(--good);
  --ypd-danger: var(--red);     --ypd-white: #FFFFFF;         --ypd-warn: #E0A400;
  --ypd-info: #2563EB;

  /* ---- TALL format token set, verbatim from the ypd-design-rules block -------------------------
     --navline is declared for the law's completeness; the route line itself lands in Phase C
     with the live Google map. */
  --act-h:60px;        /* Primary action button height */
  --act-fs:1.2rem;     /* Primary action font size */
  --row-h:64px;        /* List row height (sheets, menus, settings) */
  --car:48px;          /* Car marker size, tall gets the BIGGER marker (Ahmed) */
  --navline:12px;      /* Route line width, DOUBLED in tall (Ahmed) */
  --fs-label:var(--t-label);     /* Small mono labels. Lime on dark, grey on white, never the reverse */
  --foot-h:78px;       /* Footer height, five tabs, never fewer */
  --tap-min:48px;      /* Minimum tap target, ANY control, never smaller */
  --sheet-inset:5%;    /* Sheet side inset when risen, BOTH formats */
  --sheet-top:5%;      /* Sheet gap under the header when fully risen, BOTH formats */
  --hd-h:64px;         /* Header height. Header on EVERY screen except the landing */
  --title-fs:1.7rem;   /* Landing NAME line size, Space Grotesk 800 */
  --logo-fs:1.4rem;    /* Landing logo, tall: never wraps, never wider than GO ONLINE (law) */
  /* b578: THE GLANCE SIZE, a local role UI Engine has not got yet (listed for it). The one number read at arm's length
     while driving, once per screen: the distance to the next turn on the driving panel. Nothing else uses it. */
  --t-glance:44px;
}

*{box-sizing:border-box;margin:0;padding:0}

/* ---- the app root: the mock's .frame IS the viewport in the real app --------------------------- */
/* Android font boost off: our type scale is token-law, a system font bump must not wrap the logo */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
html,body{height:100%}
body{background:var(--bg);font-family:'Space Grotesk',-apple-system,'Segoe UI',Roboto,sans-serif;
  color:var(--ink);overflow:hidden}
/* ==================================================================================================
   A FRAME IS A DEVICE VIEWPORT AND IT NEVER SCROLLS (b37, 2026-08-15, from Ahmed's laptop).

   HIS REPORT: "the menu is off, the footer is moving up halfway across the screen", with the map
   carrying on BELOW the footer. Measured, fresh browser, one viewport each, unzoomed offsetHeight:

     430x900   zoom 1        frame scrollHeight 900 == clientHeight 900   over 0
     520x900   zoom 1        900 == 900                                   over 0
     768x1024  zoom 1.13778  935 vs 900                                   over 35   <-- his laptop
     900x800   zoom 1        800 == 800                                   over 0
     1280x800  zoom 1.11111  729 vs 720                                   over 9

   OVERFLOW APPEARS EXACTLY AND ONLY WHERE fitZoom() HAS SET body.style.zoom > 1.05, and the amount
   tracks the zoom. It is not the sheet: the in-flow children total 768 of the available 900. It is
   .map, which is position:absolute with bottom:var(--foot-h), being laid out against a zoom-scaled
   containing block, so its bottom edge lands past the frame's content box and becomes SCROLLABLE
   OVERFLOW on the frame.

   That overhang is the whole bug, and it has two faces that were logged as two findings:
     . "the ride-screen map overflows about 93 to 106px at 768" (b34 notes, left as a follow-up)
     . the footer jumping to mid-screen (this round)
   They are ONE defect. overflow:hidden suppresses the SCROLLBAR but still creates a scroll
   container, so scrollTop can be set programmatically. Every panel on these screens ends its open
   handler with scrollIntoView (the cancel confirm, Settings rows, Your rates), that call walks up
   to the nearest SCROLLABLE ancestor, finds the frame rather than the sheet, and scrolls the whole
   frame by the overhang, taking the header and footer with it. Measured after the cancel confirm
   opened at 768: frame.scrollTop 35, footer top 935 -> 895, and 40px of map left showing beneath it.
   That is his screenshot, produced on demand.

   THE FIX IS STRUCTURAL, NOT A TUNED NUMBER. overflow:clip clips identically but creates NO scroll
   container at all, so clipped overflow is not scrollable overflow: scrollHeight collapses to
   clientHeight, scrollTop cannot be set, and scrollIntoView walks past the frame to the sheet,
   which is the element that was always meant to scroll. Both declarations ship, so an engine
   without clip still gets hidden and the JS guard in app.html covers it.
   ================================================================================================== */
.frame{position:relative;width:100%;height:100%;background:var(--bg);
  overflow:hidden;              /* fallback for an engine with no overflow:clip */
  overflow:clip;overflow-clip-margin:content-box;
  display:flex;flex-direction:column}
/* Every screen is a state of the one shell (consolidation plan, decided). A hidden screen must
   actually hide: an explicit display on a component silently beats the UA's [hidden] rule
   (2026-07-31 lesson), so the shell pins it. */
.frame[hidden]{display:none!important}

/* ---- header, on EVERY screen except the landing (rulebook --hd-h) ------------------------------ */
.hd{flex:0 0 auto;height:var(--hd-h);display:flex;align-items:center;gap:var(--sp-2);background:var(--card);padding:0 var(--sp-3);
  border-bottom:1px solid var(--line)}
/* Rulebook: the logo is always ONE line, it scales down before it ever wraps */
.hd-logo{flex:1 1 auto;text-align:center;font-family:'Archivo Black',sans-serif;font-size:var(--t-body);
  letter-spacing:.01em;white-space:nowrap}
.hd-logo:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:.98rem}
.hd-logo em{font-style:normal;color:var(--orange)}
.icbtn{flex:0 0 auto;width:44px;height:44px;border:1px solid var(--line);border-radius:var(--r-input);
  background:var(--card);display:flex;align-items:center;justify-content:center;cursor:pointer}
.icbtn svg{width:22px;height:22px;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* Identity chip with status dot: red offline, yellow connecting, green connected (rulebook) */
.chip{flex:0 0 auto;display:flex;align-items:center;gap:7px;border:1px solid var(--line);
  border-radius:var(--r-pill);background:var(--card);padding:var(--sp-1) var(--sp-3) var(--sp-1) var(--sp-1);font-weight:700;font-size:var(--t-small)}
.chip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.9rem}
.chip .dot{width:10px;height:10px;border-radius:50%;flex:0 0 auto;margin-left:2px}
.chip .dot.on{background:var(--good)}
.chip .dot.off{background:var(--red)}
.chip .dot.mid{background:var(--ypd-warn)}   /* connecting, the yellow class exists per the rulebook */
.chip .av{flex:0 0 32px;width:32px;height:32px;border-radius:50%;   /* b186: never squeezed into an oval */background:var(--placeholder);display:flex;align-items:center;
  justify-content:center;color:var(--ink,#0A0A0A);font-weight:700;font-size:var(--t-small);overflow:hidden}
.chip .av:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:.85rem}   /* b308: ink initials, white on the grey disc measured 1.72:1 (UI Engine, 2026-09-12) */
.chip .chipnm{white-space:nowrap}
/* Below 520px the chip is COMPACT: avatar + status dot only, the name hides. Why: at 430 (fold
   cover screen) the full header ran 466px and the Settings button's tap center sat off-screen,
   unreachable, found by hit-test 2026-08-13. One rule fixes every header, including two-chip
   ride headers. The dot stays, status is never hidden. */
@media (max-width:520px){
  .hd .chip .chipnm{display:none}
  .hd .chip{padding:var(--sp-1) 10px var(--sp-1) var(--sp-1)}
}

/* ---- b104: once a ride is open, it rides along in EVERY driver header (Ahmed 2026-08-18:
   "YPD logo is not important once I clicked on my ride... each button is jumping to a different
   thing"). .hdride is the Ride screen's own fare pill + passenger chip, present in every driver
   header, hidden until body[data-hasride="1"], at which point the LOGO gives way instead, because
   the mockup MEASURED the naive both-at-once version overflowing 392px by 66px, which pushes the
   settings button off screen, the 2026-08-13 bug. Base rule first, overrides after, order is
   load-bearing (the b100c tie lesson). The narrow-width chip collapse above applies to this chip
   too, by inheritance, not by a copy. ---------------------------------------------------------- */
.hd .hdride{display:none}
body[data-hasride="1"] .frame[data-role="driver"] .hd .pill.hdride{display:inline-block}
body[data-hasride="1"] .frame[data-role="driver"] .hd .chip.hdride{display:flex}
body[data-hasride="1"] .frame[data-role="driver"] .hd .hd-logo{display:none}
/* offhd (2026-09-30): the OFFER header shows the lead being priced (offHdPaint), never the painted
   ride (Roger's booking wore Luisa's name and $100). And while pricing is docked over Home (b177) or
   Book a Ride is open (b401), another ride is in play, so the painted one steps aside for the logo. */
body[data-hasride] .frame[data-screen="offer"][data-role="driver"]:not([data-hdlead="1"]) .hd .hdride{display:none}
body[data-hasride] .frame[data-screen="offer"][data-role="driver"]:not([data-hdlead="1"]) .hd .hd-logo{display:block}
body .frame[data-screen="offer"][data-role="driver"][data-hdlead="1"] .hd .pill.hdride{display:inline-block}
body .frame[data-screen="offer"][data-role="driver"][data-hdlead="1"] .hd .chip.hdride{display:flex}
body .frame[data-screen="offer"][data-role="driver"][data-hdlead="1"] .hd .hd-logo{display:none}
body[data-hasride="1"] .frame[data-role="driver"]:is(.fx-pricing,.fx-bookopen) .hd .hdride{display:none}
body[data-hasride="1"] .frame[data-role="driver"]:is(.fx-pricing,.fx-bookopen) .hd .hd-logo{display:block}

/* ---- b105: one stage. While a ride is open the ONE live map sits behind every sheet screen,
   between its header and its sheet, the Ride screen's own layout. The menu's dimmed identity
   cards yield to it and return when the ride closes. The travelling map may shrink freely
   (min-height 0) so a tall sheet is never pushed off the frame by the .map base min-height. */
body[data-hasride="1"] .frame[data-screen="menu"][data-role="driver"] .fx-dim{display:none}
.fx-comms .map[data-map="live"], .fx-set .map[data-map="live"]{min-height:0;flex:1 1 120px}
/* b121: her travelling stage, the identical sizing law on the passenger side. Scoped to every
   screen EXCEPT her Ride screen, whose map keeps its full height. */
.frame[data-role="passenger"]:not([data-screen="ride"]) .map[data-map="paxlive"]{min-height:0;flex:1 1 120px}

/* ---- content scroll area ----------------------------------------------------------------------- */
.scr{flex:1 1 auto;overflow-y:auto;min-height:0;padding:14px 14px var(--sp-2);display:flex;flex-direction:column;gap:var(--sp-3)}

/* ---- big action, one button component everywhere it appears (rulebook --act-h / --act-fs) ------ */
.cta{display:block;width:100%;min-height:var(--act-h);border:none;border-radius:var(--r-ctl);background:var(--orange);
  color:#fff;font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:var(--act-fs);letter-spacing:.02em;
  cursor:pointer}
.cta.ghost{background:var(--card);color:var(--ink);border:1.5px solid var(--line);font-family:'Space Grotesk',sans-serif;font-weight:700}
.cta.dark{background:var(--ink)}
.ctasub{text-align:center;color:var(--muted);font-size:var(--t-small);margin-top:-4px}
.ctasub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem}

/* ---- cards ------------------------------------------------------------------------------------- */
.card{background:#fff;border:1px solid var(--line);border-radius:16px;padding:14px}
.cards2{display:flex;gap:var(--sp-3)}
.cards2 .card{flex:1 1 0;min-width:0}
/* b133: THE MIRRORED HOME TRIPTYCH, the approved mock. Three equal cards, content CENTERED
   (Ahmed: "I do like the fact that you have it centered... logically it makes sense"), and on a
   phone they stack full width, three slim columns were unreadable in the mock and he approved
   the stack. */
.cards3{display:flex;gap:var(--sp-3)}
.cards3 .card{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px}
.cards3 .card .fx-meta,.cards3 .card .mutline{text-align:center}
/* b134: OFFLINE wears the reddish pill, the mirror of .good, painted by presPaint */
.badge.off{background:var(--red-tint);color:var(--red-ink)}
/* b136: every Home avatar carries the landing photo's drop shadow, one rule for all
   four cards, both roles, "it separates elements from the background" */
.cards3 .avatar-lg{box-shadow:0 4px 14px rgba(10,10,10,.15)}
/* b144: A HOME CARD THAT NAMES THE RIDE IS A DOOR TO THE RIDE, so it has to READ like one.

   IT WEARS THE .tile TREATMENT, which is this app's existing "this panel is a door": a white
   surface with the same 1px --line border, a pointer, and it PRESSES. No new colour, no new
   shape, no badge, and the approved b133 triptych is not redrawn.

   AND IT DOES NOT WEAR A 1.5px BORDER, which is what this rule said first. MEASURED at dpr 3:
   border-width 1.5px computes to 1px, and .cta.ghost, which has declared 1.5px for months,
   computes to 1px too. So a border step would have been a claim in the stylesheet that renders
   nowhere. The PRESS is the affordance that actually reaches her thumb, and --paper against the
   card's #fff is a real difference she can see, which .shx and .tipstep already use for exactly
   this.

   THE WHOLE CARD IS THE TARGET, not the text inside it: the act sits on the card element and the
   shell's one delegated listener resolves through closest('[data-act]'). Verified by hit-testing
   five points across the card with elementFromPoint, never with el.click(), which bypasses hit
   testing entirely and passes on a control no finger can reach (the 2026-07-18 lesson). */
.card.tapcard{cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .12s ease}
.card.tapcard:active{background:var(--paper)}
/* b136/b137: screen-centering the fare pill was BUILT AND MEASURED at 375: pill 137-238,
   the second identity chip 128-190, a real overlap. It does not fit with two chips plus
   a two-amount pill, so the pill stays in flex flow (it shifts a little between roles,
   accepted as minor polish, Ahmed 2026-08-19). Do not re-add absolute centering without
   new geometry that removes a chip or shortens the pill. */
@media (max-width:560px){
  .cards3{flex-direction:column}
}
.badge{display:inline-block;border-radius:var(--r-pill);padding:3px 10px;font-size:var(--fs-label);font-weight:700;
  background:var(--paper);color:var(--muted)}
.badge.good{background:var(--good-tint);color:var(--good)}
.badge.warn{background:#FDEBE7;color:var(--red)}
/* b354: RETURN, a fact about the trip, not a warning. b576 (Ahmed 2026-10-25: "the return is supposed to have an orange
   color behind it, not black with white text. Do that for all the return trips"): the orange label chip, --label-bg with
   white text, 12px 800 caps. It was born ink in b354, and inside a My rides row the row's own `.row .tx span` (0,2,1) beat
   this rule's white (0,2,0), so it read grey on black. The frame and attribute in front make it (0,4,0), above that rule and
   the ride sheet's `.fx-ride .sheet h4 .badge` (0,3,1). */
.badge.retleg,.frame[data-role] .badge.retleg{background:var(--label-bg);color:var(--label-fg);font:800 var(--t-label)/1 var(--body);
  letter-spacing:.1em;text-transform:uppercase;padding:5px 8px;border-radius:6px;display:inline-flex;align-items:center;white-space:nowrap;flex:none}
.frame[data-role] .badge.retleg[hidden]{display:none!important}
/* b576: Home's passenger card says the booking's money, "$125 + $25", under the name, in the number type */
.fx-id .hm-fare{display:block;font:700 var(--t-data) var(--mono);color:var(--ink);margin:0 0 6px}
.fx-id .hm-fare[hidden]{display:none}
.fx-id .badge.retleg{margin:0 0 6px}
/* b355: a backup drives this booking. b588 (Ahmed 2026-10-26, bug-mvppm63d: "Catherine, Darlene driver, the text needs to
   be white. I can barely read it"): the same specificity trap RETURN fell into in b576, the row's own `.row .tx span`
   (0,2,1) beat this rule's white (0,2,0), so DARLENE DRIVES read grey on blue. Same fix, same chip type as RETURN. */
.badge.cvleg,.frame[data-role] .badge.cvleg{background:var(--pax);color:#fff;font:800 var(--t-label)/1 var(--body);
  letter-spacing:.1em;text-transform:uppercase;padding:5px 8px;border-radius:6px;display:inline-flex;align-items:center;white-space:nowrap;flex:none}
/* ---- b591: SHARE WITH TEAM, in the same hand-off box (guest ride piece 2, YPD-SHARE-ACCEPT-MOCKUP-V1A) ----
   the team driver chips stack one per line with the orange IN THE APP chip at the end, the pay line is locked to the fare
   (shown in the number type, nothing to type), and the hand-off chips keep their look below. */
.cvsec .cv-share{flex-direction:column}
.cvsec .cv-share .cv-chip{flex-direction:row;align-items:center;gap:8px;padding:4px 10px}
.cvsec .cv-share .cv-chip i{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cvsec .cv-chip .cv-inapp{font-size:11px;padding:5px 7px;flex:none}
/* on the picked (ink) chip the orange label keeps its white text: the selected-state rule paints every span white, and an
   orange chip reads on ink, a white one would not */
.frame[data-role="driver"] .cvsec .cv-chip.on .cv-inapp{background:var(--label-bg);color:var(--label-fg)}
.cvsec .cv-pay{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:6px}
.cvsec .cv-pay .fx-ml{margin:0;flex:0 0 auto}
.cvsec .cv-pay b{display:inline-flex;align-items:center;height:48px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r-input);background:var(--paper);font:700 var(--t-data)/1 var(--mono)}
.cvsec .cv-pay i{font-style:normal;font-size:var(--t-small);color:var(--muted);flex:1 1 100%}
/* the OFFER row under My rides, and the time left on it */
.fx-rides .ofrow .tx .ofends{display:block;font:700 var(--fs-label)/1.3 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-top:3px}
/* the offer sheet (C2 of the mock), docked like TRIP INFO */
.sheet.fx-ofr{padding:var(--sp-2) var(--sp-4) 14px}
.fx-ofr .of-facts{display:flex;flex-direction:column;margin-top:4px}
.fx-ofr .of-f{display:flex;gap:12px;align-items:baseline;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line)}
.fx-ofr .of-f:last-child{border-bottom:0}
.fx-ofr .of-k{font:700 var(--t-label)/1.2 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);flex:0 0 92px}
.fx-ofr .of-v{font:600 var(--t-body)/1.35 var(--body);text-align:right;min-width:0;color:var(--ink)}
.fx-ofr .of-v.data{font:700 var(--t-data)/1.35 var(--mono)}
.fx-ofr .of-lock{display:flex;align-items:center;gap:8px;background:var(--paper);border-radius:var(--r-input);padding:10px 12px;font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);margin-top:10px}
.fx-ofr .of-lock svg{width:18px;height:18px;flex:0 0 auto;fill:none;stroke:var(--muted);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.fx-ofr .of-btns{display:flex;gap:8px;margin-top:12px}
.fx-ofr .of-btns .cta{flex:1 1 0;min-width:0;margin:0}
.fx-ofr .of-btns .of-pass{flex:0 0 38%}
.fx-ofr .of-ends{font:700 var(--t-label)/1.2 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);text-align:center;margin-top:10px}
.fx-ofr .of-none{font-size:var(--t-body);line-height:1.5;color:var(--muted);padding:14px 0 6px}
.fx-ofr .setstat{margin-top:8px}
.frame.fx-ofopen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-ofopen > .map{filter:brightness(.72) saturate(.8)}
.frame.fx-ofopen > .sheet:not(.fx-ofr){visibility:hidden}
/* ---- b355: the hand-off row and its in-place panel on the Ride screen ---- */
.cvsec .cv-x{display:none}
/* b701: the one button that hands the ride off with nobody named, and what the calendar did, on the row */
.cvsec .fx-save[data-need]{background:var(--orange);color:#fff}
.cvsec [data-rd="coverbox"] button{scroll-margin-bottom:24px}
.cvsec [data-covercal]{margin:0 0 10px}
.cvsec [data-covercal][hidden],.cvsec [data-covercal] [hidden]{display:none}
.cvsec [data-covercal] .setstat{display:block;font-size:var(--t-small);font-weight:700;line-height:var(--lh-small)}
.cvsec [data-covercal] .fx-btns{margin-top:6px}
.cvsec[data-open="1"] .cv-x{display:block;background:var(--card);border:1.5px solid var(--ink);border-radius:var(--r-ctl);padding:var(--sp-1) var(--sp-3) var(--sp-3);margin:0 0 10px}
.cvsec .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:var(--sp-3) 0 var(--sp-2)}
.cvsec .fx-in{width:100%;height:48px;border:1px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);font:400 var(--t-body) "Space Grotesk",sans-serif;background:var(--card);box-sizing:border-box}
.cvsec .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 1rem "Space Grotesk",sans-serif}
.cvsec .fx-btns{display:flex;gap:10px;margin-top:10px}
.cvsec .fx-save{flex:1 1 0;min-height:48px;border:none;border-radius:var(--r-input);background:var(--good);color:#fff;font:700 var(--t-small) 'Space Grotesk',sans-serif;cursor:pointer}
.cvsec .fx-save:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .9rem 'Space Grotesk',sans-serif}
.cvsec .fx-cancel{flex:1 1 0;min-height:48px;border:1.5px solid var(--ink);border-radius:var(--r-input);background:var(--card);color:var(--ink);font:700 var(--t-small) 'Space Grotesk',sans-serif;cursor:pointer}
.cvsec .fx-cancel:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .9rem 'Space Grotesk',sans-serif}
.cvsec .setnote{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);margin:10px 0 0}
.cvsec .setnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.5}
.cv-chips{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.cv-chip{display:flex;flex-direction:column;min-height:48px;justify-content:center;padding:6px 14px;border:1.5px solid var(--line);border-radius:var(--r-input);background:var(--card);font-weight:800;cursor:pointer}
.cv-chip i{font-style:normal;font-weight:500;font-size:var(--fs-label);color:var(--muted)}
.cv-chip.on{border-color:var(--ink);background:var(--ink);color:#fff}
.cv-chip.on i{color:#E4E2DC}
.cv-chip.off{opacity:.5;text-decoration:line-through}
.paxcover{border-color:var(--pax);color:var(--pax);font-weight:600}
/* b357: undo a mis-started ride */
.rsundo{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:var(--sp-2) 0 0;padding:6px var(--sp-1) 6px var(--sp-3);
  border:1.5px dashed var(--line);border-radius:var(--r-input);font-size:var(--t-small);color:var(--muted);min-height:44px}
.rsundo:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}
.rsundo[hidden]{display:none!important}
/* b492: A HIDDEN ROW IS GONE, every row. .row carries display:flex, which beats the UA's [hidden] rule (the 2026-07-31
   law), so rsStopsPaint's hidden on .rsstops left a blank 64px card with a stops icon between the pickup and the drop-off
   on every ride without stops. One rule for the class, so no row set hidden can ever paint again. */
.row[hidden]{display:none!important}
.rsundo.far{border-color:var(--red);color:var(--red);font-weight:700}
.rsundo .aff{min-height:44px;min-width:72px;justify-content:center;display:inline-flex;align-items:center;cursor:pointer}
/* b486: the step it goes back to, on its own line under the question */
.rsundo .rsundo-to{display:block;margin-top:2px;color:var(--ink,inherit);font-weight:700}
.rsundo .aff[aria-disabled="true"]{opacity:.5;pointer-events:none}
.fx-carphoto{display:block;width:100%;max-height:120px;object-fit:cover;border-radius:10px;margin-top:var(--sp-2)}
.fx-carphoto[hidden], .fx-carsvg[hidden]{display:none!important}
/* b444: Settings > Vehicle, the photo of his car, the way the profile photo is set */
.vehpic{display:flex;flex-direction:column;gap:var(--sp-2);margin:var(--sp-3) 0 6px}
.vehpic .fx-carphoto.vehpic-img{max-height:180px;margin-top:0}
/* b674: the plate preview in Settings > Vehicle is a California plate too, 2:1, the whole photo inside it on white */
.vehpic .fx-carphoto.vehpic-img[data-platephoto]{width:min(100%,320px);max-height:none;aspect-ratio:2/1;object-fit:contain;background:#fff;
  border:2px solid var(--ink);border-radius:10px;box-sizing:border-box}
.vehpic .fx-carphoto.vehpic-img[data-platephoto][data-pfit="cover"]{object-fit:cover;border:0;border-radius:14px;background:transparent}   /* b684: the photo is the plate */
.vehpic-btn{display:flex;align-items:center;justify-content:center;min-height:48px;padding:0 14px;border:1.5px dashed var(--line);
  border-radius:var(--r-input);font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card);cursor:pointer;text-align:center}
.vehpic-btn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .95rem 'Space Grotesk',sans-serif}
.vehpic-rm{min-height:44px;border:none;background:none;color:var(--muted);font:500 var(--t-small) 'Space Grotesk',sans-serif;
  text-decoration:underline;text-underline-offset:3px;cursor:pointer;align-self:center;padding:0 14px}
.vehpic-rm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:500 .9rem 'Space Grotesk',sans-serif}
.vehpic-rm[hidden]{display:none!important}
.vnocolor{display:block;width:100%;color:var(--red)!important;font-size:var(--t-small);font-weight:700}
.vnocolor:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;font-weight:600}
/* ---- b356: the backup driver's profile editor, in place inside the hand-off panel ---- */
.cv-prof{border:1.5px dashed var(--line);border-radius:var(--r-input);padding:10px var(--sp-3);margin-top:var(--sp-3);background:var(--paper)}
.cv-prof .cv-pics{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px}
.cv-pic{display:flex;flex-direction:column;align-items:center;gap:6px;min-height:110px;justify-content:center;border:1px solid var(--line);border-radius:var(--r-input);background:var(--card);cursor:pointer;padding:var(--sp-2);text-align:center;font-weight:700;font-size:var(--t-small)}
.cv-pic:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.8rem}
.cv-pic img{width:72px;height:72px;object-fit:cover;border-radius:50%}
.cv-pic.car img{width:100%;height:72px;border-radius:8px}
.cv-pic i{font-style:normal;font-weight:500;color:var(--muted);font-size:var(--fs-label)}
.cv-prof .cv-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.cv-prof .cv-grid .wide{grid-column:1/-1}
.cv-prof input[type=file]{display:none}
.cv-link{display:inline-block;margin-top:10px;min-height:44px;line-height:44px;font-weight:700;font-size:var(--t-small);color:var(--pax);cursor:pointer}
.cv-link:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){line-height:44px;font-weight:800;font-size:.82rem}
.paxcover[hidden]{display:none!important}
/* THE MISSING-FLIGHT FLAG IS A FLAG, NOT A TINT (b42, Ahmed: he wants it to read as a big flag,
   matching the prominence of PUT IT BACK). A pale wash on a busy list row is the thing the eye
   skips; this is the one badge in the app that is asking him to pick up the phone before a ride
   he cannot otherwise drive to a terminal for, so it is FILLED in the shell's own accent, Forge
   Orange (--orange), white text.
   ITS OWN CLASS, USED BY BOTH RENDERERS. The My rides row and the New requests row write the same
   .flagflight span, so the two can never drift apart the way one styled instance would. It is a
   LABEL, not a control, so the 48px tap floor deliberately does not apply to it, which is why it
   is sized by its own padding here and not by --tap-min. */
.badge.warn.flagflight{background:var(--orange);color:#fff;letter-spacing:.02em;
  padding:var(--sp-1) 11px;box-shadow:0 1px 4px rgba(255,59,0,.35)}

/* WHOSE TRACKING LINK IS THIS (b42). Sits directly above the Copy button in Settings > Safety.
   The passenger chip only exists in the Ride screen's header, so copying a link from Settings had
   nothing on screen naming the passenger except a 12px caption, and the link is seeded from
   whatever booking the Ride screen last showed. Deliberately loud: an avatar disc, the name at
   body size in bold, the booking's date and time under it. */
.trackwho{display:flex;align-items:center;gap:11px;border:1.5px solid var(--ink);border-radius:var(--r-ctl);
  background:var(--paper);padding:10px var(--sp-3);margin:0 0 9px}
.trackwho[hidden]{display:none!important}
.trackwho .tw-av{flex:0 0 auto;width:38px;height:38px;border-radius:50%;background:var(--orange);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--t-small)}
.trackwho .tw-av:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:.9rem}
.trackwho .tw-tx{flex:1 1 auto;min-width:0}
.trackwho .tw-tx b{display:block;font-size:var(--t-body);font-weight:700;overflow-wrap:anywhere}
.trackwho .tw-tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem;font-weight:800}
.trackwho .tw-tx span{display:block;font-size:var(--t-small);color:var(--muted);font-weight:700}
.trackwho .tw-tx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;font-weight:700}
/* WARNING TEXT IS RED, global law (Ahmed 2026-08-13): any inline status needing attention */
.warntx{color:var(--red)!important;font-weight:700}
/* GREEN IS GOOD (global law): success + good-progress states */
.goodtx{color:var(--good)!important;font-weight:700}

/* ---- tool tiles -------------------------------------------------------------------------------- */
.tools{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.tools.two{grid-template-columns:repeat(2,1fr)}
.tools .tile.wide{grid-column:1/-1}   /* b307. b444: the passenger Share tile is a normal tile again, nothing wears this today */
/* b444: her shortcuts are all one size. "Share with a Friend" takes two lines on a phone, so every row takes the height
   of the tallest tile and Share sits in the grid exactly like Settings ("it needs to be just like settings and all the
   other tabs, they're shortcuts"). */
.frame[data-role="passenger"] .tools{grid-auto-rows:1fr}
.tile{position:relative;background:var(--card);border:1px solid var(--line);border-radius:var(--r-ctl);
  padding:var(--sp-3) 10px;display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:6px;justify-content:flex-start}
.tile .ic{width:44px;height:44px;border-radius:50%;border:1.6px solid var(--line);display:flex;
  align-items:center;justify-content:center}
.tile .ic svg{width:22px;height:22px;fill:none;stroke:var(--orange);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* b139: hints are gone (the fit-one-page round), the title is the only text, so no reserved
   lines and no min-height: circles and titles sit level and the row is as short as it can be */
.tile b{font-size:var(--t-small);line-height:var(--lh-small)}
.tile b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.88rem;line-height:1.15}
/* b314: THE WORDS COME FIRST (Ahmed 2026-09-16, Home screenshot: "Passenger Link" and "Sync Calendar" were cut
   off under the fold with only their circles showing, "the text should be on top and then the icon underneath,
   this will make it so when we have the second row I can still read what the icon is supposed to do"). One rule
   on the tile itself, so every quick link on both roles, and any tile added later, reads title first. */
.tile > b{order:-1}
/* b697: ONE LINE, ONE SIZE (Ahmed 2026-11-01, bug-mvy1nfl8-d0oe5, closed Fold 344x801: "where it says charging stop, we need to
   write it so it shows up in one row... maybe even changing the font size a little bit smaller"). MEASURED in Space Grotesk 700:
   the longest label, Sync Calendar, is 90.6px at 13px and the tile had 78.7px inside its 10px sides, so it wrapped and that row
   grew to 112. One size for every driver Home tile on both frames at every width, the 12px floor token (83.7px), with 4px sides
   so the words have 90.7px at 344. The line box stays the old 18.2px, so the tile keeps its 94px height. Her tiles are not touched,
   "Share with a Friend" takes two lines on purpose (b444). */
.frame[data-screen="home"][data-role="driver"] .tile{padding-inline:var(--sp-1)}
.frame[data-screen="home"][data-role="driver"] .tile b{font-size:var(--t-label);line-height:calc(var(--t-small)*var(--lh-small));white-space:nowrap}
.tile span{font-size:var(--fs-label);color:var(--muted);line-height:1.25}
/* b697: the count sits low in the right corner, beside the circle, same place on every tile (his words: "the one is showing up on
   the journal"). The old top right corner was the label's own row, and the label is as wide as the tile at 344. The words are on
   top and the 44px circle is centred, so this is the one corner both leave free: 27px to the right of the circle at 344. */
.tile .nbadge{position:absolute;bottom:6px;right:3px;min-width:20px;height:20px;border-radius:10px;
  background:var(--orange);color:#fff;font-size:var(--fs-label);font-weight:800;line-height:20px;text-align:center;padding:0 3px}
/* every badge carries its own [hidden] guard: these all set an explicit display, which beats the
   UA rule outright (the 2026-07-31 lesson, third time it has mattered in this file) */
.tile .nbadge[hidden]{display:none!important}
.row .aff[hidden]{display:none!important}
.card .badge[hidden]{display:none!important}

/* ---- ride card + fact strip. Labels grey on white per the lime/grey law ------------------------ */
.ridecard{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:14px}
.facts{display:flex;flex-wrap:wrap;row-gap:10px;border-top:1px solid var(--line);margin-top:10px;padding-top:10px;gap:0}
.facts>div{flex:1 1 30%;min-width:30%;padding:0 var(--sp-2);border-left:1px solid var(--line)}
.facts>div:first-child{border-left:none;padding-left:0}
.facts .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:var(--sp-1);margin-bottom:var(--sp-1)}
.facts .v{font-size:var(--t-small);font-weight:700;line-height:var(--lh-small);word-break:break-word}
.facts .v:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;font-weight:700;line-height:1.25}
.facts .v small{display:block;font-weight:500;color:var(--muted);font-size:var(--fs-label)}

/* ================================================================================================
   SHEET-GEOMETRY-START  (token-owned, the ONLY place sheet geometry may be set, see header law)
   Rulebook: sheets rise from the footer, 5 percent side insets, 5 percent gap under the header,
   the map always visible around them, a sheet NEVER reaches the header. Never a right-side docked
   panel, that is Uber's layout, not ours (Ahmed 2026-08-11).
   ================================================================================================ */
.sheet{position:relative;background:var(--card);border-radius:22px 22px 0 0;box-shadow:0 -8px 26px rgba(10,10,10,.18);
  padding:6px 14px var(--sp-3);margin-top:auto}
.frame > .sheet{z-index:2;
  margin:auto var(--sheet-inset) 0;                                        /* --sheet-inset, both sides */
  max-height:calc(100% - var(--foot-h) - var(--hd-h) - var(--sheet-top));  /* --sheet-top gap, never touches the header */
  overflow:auto;
  /* A sheet is NEVER flex-shrunk by an in-flow sibling (2026-08-14, the sign-in sheet opened
     half-cut: the default flex-shrink:1 let the landing's .fx-land compress the sheet below its
     own content, rows clipped, drivers won't scroll to discover a choice). A sheet sizes to its
     CONTENT up to the max-height cap above; a squeezed sibling yields instead (.fx-land already
     carries min-height:0 + overflow-y:auto for exactly that). Class rule, geometry-token-owned. */
  flex:0 0 auto;
  display:flex;flex-direction:column}    /* content layout for all sheets, owned here, not per screen */
/* SHEET-GEOMETRY-END ============================================================================= */

/* ==================================================================================================
   b63, EVERY SHEET OPENS AND CLOSES. Ahmed 2026-08-17, on the driver side and then the passenger
   side within a minute: "there's no way for me to hit an X in the top right to close the menu. And
   there's no way for me to click the handle on top... So you got to look at this as a global thing."

   He is right that it is global. There are EIGHTEEN sheets in this file, all eighteen draw the
   little grey dash, and not one of them was wired to anything. The dash has looked like a control
   and been decoration on every screen since the shell was built. Nobody noticed because until
   navigation there was nothing underneath worth uncovering.

   The bar and the X are INJECTED at runtime into every .sheet, once, rather than pasted into
   eighteen places where the nineteenth would be forgotten. Same reasoning as marking a container
   once instead of tagging every control inside it.
   ================================================================================================== */
.grab{width:44px;height:5px;border-radius:3px;background:var(--grab);flex:0 0 auto;cursor:pointer;
  /* A 48px TAP TARGET THAT STILL LOOKS LIKE A 5px DASH. Ahmed's standing rule is that nothing is
     ever a tiny control, and the padding grows the touch box while background-clip keeps the paint
     at 44x5. The negative margins give back exactly what the padding took, so no layout moves:
     5 + 44 = 49 tall, less 16 and 14 of margin, is the 19px the original 4/5/10 occupied. */
  box-sizing:content-box;padding:22px 40px;background-clip:content-box;margin:-16px auto -14px}
/* the sticky strip that carries the handle and the close button, so both stay reachable however
   far down a long sheet has been scrolled */
.shbar{position:sticky;top:0;z-index:3;background:#fff;flex:0 0 auto;cursor:pointer;
  display:flex;align-items:center;justify-content:center;margin:0 -14px;padding:0 14px;
  border-radius:22px 22px 0 0;
  /* b275: THE CAP. The bar sticks 6px below the sheet's true top (the sheet's own padding), and
     its rounded corners leave two notches, so scrolled rows showed through the gap and the
     corners, Ahmed's ride #23 "something still leaking through right above where the menu sheet
     is". The shadow paints a solid white strip above the bar, measured at the leak. */
  box-shadow:0 -14px 0 0 #fff}
.shbar::after{content:"";position:absolute;left:0;right:0;bottom:0;height:0}
/* b399: THE DRAG BELONGS TO THE BAR (Ahmed 2026-09-28: "when it goes down it works smooth. When it goes up, like a blue
   line shows up and it staggers and it barely goes up"). An upward drag on the bar was also a page scroll to the phone,
   so the browser panned, painted Android's blue overscroll glow and handed the finger over in bursts. The bar takes the
   whole gesture now, and a sheet never lets a scroll run on into the page behind it. */
.shbar{touch-action:none}
.frame > .sheet{overscroll-behavior:contain}
/* 48, not 44. Measured at 44 and corrected: his standing rule is that nothing ships as a tiny
   control, and "close this panel" is the one control on the screen he reaches for in a hurry. */
.shx{position:absolute;right:4px;top:50%;transform:translateY(-50%);
  width:48px;height:48px;min-width:48px;min-height:48px;border:none;background:transparent;
  display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;border-radius:50%}
.shx svg{width:19px;height:19px;fill:none;stroke:var(--muted);stroke-width:1.8;stroke-linecap:round}   /* b563: the one stroke, 1.8 (UI audit #30) */
.shx:active{background:#F1EFEA}
/* b536: THE X HAS ITS OWN CLEAR SPACE (Ahmed 2026-10-20, bug-mvgyt7fi-gkrh5, measured at 430 wide). The 48px X was
   centred on a 19px bar, so it hung 14px over the first row (I HAVE ARRIVED) and sat 6px under the map disc peeking over
   the sheet. A bar that carries the shared X is tall enough to hold it with 12px clear above (to the sheet's top edge)
   and 12px clear below (to the first control). The grab stays centred, the drag still belongs to the whole bar. */
.shbar:has(> .shx){min-height:62px}
.shbar > .shx{top:6px;transform:none}
/* b546: the ride sheet's sticky button row sits under the bar at --shbar-h, which phaseFold measures only when it
   folds. Unmeasured, it fell back to the old 19px bar, so on a scrolled sheet I HAVE ARRIVED stuck over the lower half
   of the X and a tap on the X pressed the button instead (t230, Trip Info's JOURNAL check). The fallback is the new bar. */
.fx-ride[data-role="driver"] > .sheet:has(> .shbar > .shx) > .fx-btnrow{top:var(--shbar-h,62px)}
/* b563: A SHEET'S OWN X GETS THE SAME CLEAR SPACE (UI audit #3, 2026-10-23). A sheet that moves its own .fin-x into the
   bar (Book a Ride on her side) gets the same 62px bar and the same 6px top as b536, 12px clear above and below. */
.shbar:has(> .fin-x){min-height:62px}
.frame > .sheet > .shbar > .fin-x{top:6px!important;transform:none!important}

/* b568: ONE SHEET TITLE BAR, every driver sheet (Ahmed 2026-10-24, option 1 of YPD-PANEL-TITLE-MOCKUP-V1A, UI audit E1).
   Built once by sheetTitleBuild in app.html. The grab handle above, then one row: the back chevron when the sheet has a
   parent, the title in Space Grotesk 19px, one orange chip, JOURNAL, the X, and a 1px line under it. It replaces the
   five shapes (the plain Archivo heading, the 79px Ride heading, Trip Info's chip line with its X above the edge, a
   sheet's own title beside a big times sign, and no title at all). The X sits 6px sheet padding, 19px grab and 7px of
   row under the sheet's top, 32px inside it, and the row's own 62px keeps the first card clear of it (b563). */
/* before the bar is built (a blink while the sheet is moved into its frame) the sheet's own X keeps its old corner */
:is(.fx-ti,.fx-owed,.fx-jrise,.fx-acode) > .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;
  justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;z-index:4;font-weight:600}
:is(.fx-ti,.fx-owed,.fx-jrise,.fx-acode) > .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.shbar.sttlbar{flex-direction:column;align-items:stretch;justify-content:flex-start;padding:0 10px 0 12px}
.shbar.sttlbar > .grab{align-self:center}
/* b596: THE ARROW SITS IN THE MIDDLE OF ITS SQUARE (Ahmed 2026-10-26, bug-mvptpvvm-7j71m, the Trip info back chevron:
   "this arrow can move down a little bit so it's in the center of this square... and it could be a little bit bigger").
   The row's padding was 2px above and 6px below, so every control in it, the chevron and the X, sat 2.5px above the
   row's middle, and on Trip info, where the title and the rider chip wrap to two lines, the row grows and the gap shows.
   The padding is now the same above and below (4 and 4, the row is still 62px), so flex centres the 44px square on the
   row's own middle whatever its height. The chevron and the X glyphs are 24px, a fifth bigger than b568's 20, the tap
   stays 44. t363 measures every arrow on the Ride sheet and Trip info at 390 wide. */
.sttl{display:flex;align-items:center;gap:6px;min-height:62px;padding:4px 0;margin:0 -10px 0 -12px;padding-left:12px;padding-right:10px;
  border-bottom:1px solid var(--line);box-sizing:border-box}
.sttl > .stt{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.frame > .sheet > .shbar .stt-t{display:block;margin:0;min-width:0;max-width:100%;font:600 var(--t-card)/1.25 var(--body);letter-spacing:0;
  color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-transform:none}
.sttl .stchip{display:inline-flex;align-items:center;max-width:100%;background:var(--label-bg);color:var(--label-fg);
  font:800 var(--t-label)/1 var(--body);letter-spacing:.1em;text-transform:uppercase;padding:6px 8px;border-radius:6px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box}
.sttl .stchip[hidden],.sttl .stchip:empty{display:none}
.sttl > .stact{position:static!important;transform:none!important;flex:0 0 auto;height:var(--tap);min-height:var(--tap);min-width:var(--tap);
  padding:0 10px;display:flex;align-items:center;box-sizing:border-box;border:1.5px solid var(--ink);border-radius:var(--r-input);
  background:var(--card);color:var(--ink);font:700 var(--t-label)/1 var(--mono);letter-spacing:.08em;cursor:pointer}
.frame > .sheet > .shbar > .sttl > :is(.shx,.fin-x),.sttl > .shback{position:static!important;transform:none!important;flex:0 0 auto;
  width:var(--tap);height:var(--tap);min-width:var(--tap);min-height:var(--tap);padding:0;margin:0;border:0;border-radius:12px;
  background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:0;color:var(--ink)}
.sttl > .shback{margin-left:-6px}
.sttl > .shback[hidden]{display:none!important}
.sttl > :is(.shx,.fin-x,.shback) svg{width:24px;height:24px;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}   /* b596: 24, was 20 */
.sttl > :is(.shx,.fin-x,.shback):active{background:var(--paper)}
/* the ride sheet's sticky button row sits under the taller bar (measured at --shbar-h once it folds) */
.fx-ride[data-role="driver"] > .sheet:has(> .shbar > .sttl) > .fx-btnrow{top:var(--shbar-h,82px)}
/* the Ride bar names the rider; at the close out the chip is the rider just dropped off */
.fx-ride[data-rsdone="1"] .sttl .stchip[data-rd="name"],.fx-ride:not([data-rsdone="1"]) .sttl .stchip.stdone{display:none}
/* what the bar now says, said once: the old in sheet labels it replaces */
.fx-ride[data-role="driver"] > .sheet > h4.rshead{justify-content:flex-start}
.fx-ti .ti-k[hidden]{display:none}
.fx-owed:has(> .shbar .sttl) .mo-head .mo-k,.fx-earn:has(> .shbar .sttl) .er-title,.fx-acode:has(> .shbar .sttl) .ypd-code h2{display:none}
.fx-jrise .jrs-head:not(:has(> :not([hidden]))){display:none}
.jr-head:not(:has(h4)){justify-content:flex-end}

/* THE COLLAPSED STATE. max-height so it ANIMATES, which is what he asked for ("it animates down"),
   rather than snapping out of existence. */
.frame > .sheet{transition:max-height .26s ease, padding .26s ease}
/* CLOSED MEANS GONE, NOT PEEKING (b64, Ahmed 2026-08-17 after testing b63).

   b63 left a 74px stub showing the handle, a "TAP TO OPEN" line and the top of the title, and he
   was right that it is clutter: "it basically shows Ride, Gabriel booked $125 plus 0. I didn't ask
   for that and that forces the menu to be opened a little bit. So let's get rid of that... I don't
   even think honestly it needs to have that bar and tap to open. It should just be the footer on
   the bottom."

   THE FOOTER IS THE WAY BACK. It is already on screen, it already has a button for every panel, and
   it is where his thumb already is. A second opener stubbed to the bottom of the map was a control
   competing with a control that was already there. His model, verbatim: "when I click on ride, the
   menu animates up. When I click inbox, the menu animates up... I hit the X it goes down."

   ONE VARIABLE, NO ARITHMETIC. An earlier cut used calc() with a term that multiplied by zero, and
   a calc() holding ONE unresolvable var drops the WHOLE declaration, so the clamp silently did not
   apply and the sheet measured TALLER closed than open. Caught by measuring, not by reading. */
.frame > .sheet.shmin{max-height:0;padding-top:0;padding-bottom:0;overflow:hidden;
  box-shadow:none;pointer-events:none}
/* the peek line and the handle exist for the OPEN sheet only; closed, there is nothing to peek at */
.sheet .shpeek{display:none}
@media (prefers-reduced-motion:reduce){ .frame > .sheet{transition:none} }
.sheet h4{font-family:var(--body);font-size:var(--t-card);margin:2px 2px 10px;font-weight:600}
.sheet h4:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:1.15rem}

/* ---- the one row component (rulebook --row-h): icon + bold + caption --------------------------- */
.row{display:flex;align-items:center;gap:12px;background:#fff;border:1px solid var(--line);
  border-radius:14px;padding:11px 13px;min-height:var(--row-h);margin-bottom:9px;flex:0 0 auto}
.row svg{width:24px;height:24px;flex:0 0 auto;fill:none;stroke:var(--ink);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.row .tx{flex:1 1 auto;min-width:0}
.row .tx b{display:block;font-size:var(--t-body)}
.row .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
.row .tx span{display:block;font-size:var(--t-small);line-height:var(--lh-small)}
/* b590: the muted colour is for a sub line, never for a status chip. This rule (0,2,1) beat every `.badge.<kind>` (0,2,0),
   so Confirmed, On the way, 2nd ride, EVERY WEEK (green) and Needs a price (red) all read grey inside a My rides, Past
   trips or New Requests row. RETURN (b576) and DARLENE DRIVES (b588) were each rescued one at a time with a longer
   selector; this takes the colour off chips once, for every kind, now and later. :where() keeps the specificity at
   (0,2,1), so .rwhen (0,3,0) and the passenger :where rules still win exactly as before. Display, size and line height
   stay on the chip as they were, so nothing moves, only the ink. */
.row .tx span:where(:not(.badge)){color:var(--muted)}
.row .tx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;line-height:1.3}
/* A span NESTED in a caption (the live data-name slot inside Your profile's caption) stays on
   the caption's own line: the block rule above is for the caption itself, not its parts
   (caught by pixels 2026-08-14, "Ahmed" broke onto its own line above ", photo, ...") */
.row .tx span span{display:inline}
/* Rulebook: a row that can be opened shows an OPEN tag, one that cannot shows it greyed (aff.lite) */
.row .aff{flex:0 0 auto;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.06em;background:var(--ink);color:#fff;border-radius:8px;padding:6px var(--sp-3)}
.row .aff.nav{background:var(--pax)}
.row .aff.lite{background:var(--paper);color:var(--ink)}
.row.warnrow .tx span{color:var(--red);font-weight:700}

/* ==================================================================================================
   b76, THE DESTINATION SEARCH PANEL. Approved by Ahmed 2026-08-17 off
   050-Documents/YPD-NAV-SEARCH-MOCKUP-V1A.html. Full-width saved-place rows over pills, and the
   tall sheet over the compact one, both his recommended options.
   ================================================================================================== */
/* A SHEET WITH AN EXPLICIT display BEATS THE UA'S [hidden] RULE. .frame > .sheet sets display:flex,
   so `hidden` on a sheet paints anyway. Fixed on the CLASS rather than on the one sheet that needs
   it today, because the next sheet that ships hidden would inherit the identical bug (2026-07-31,
   at real cost: a bar meant for one layout rendered on every one). No sheet in this file ships
   hidden today, so this changes nothing that exists and closes the door for everything that comes. */
.frame > .sheet[hidden]{display:none!important}

/* the field. 56px, bigger than the 48px floor, because it is the one control on this panel he aims
   at first and often while moving. */
.nsq-sheet .nsq-field{position:relative;margin:2px 0 var(--sp-3);flex:0 0 auto}
.nsq-sheet .nsq-in{display:block;width:100%;min-height:56px;border:1.5px solid var(--line);
  border-radius:var(--r-ctl);padding:0 56px 0 46px;background:var(--card);outline:none;
  font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;
  font-size:var(--t-body);color:var(--ink);text-overflow:ellipsis}
.nsq-sheet .nsq-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;font-size:1rem}
.nsq-sheet .nsq-in:focus{border-color:var(--orange);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--orange) 22%, transparent)}
.nsq-sheet .nsq-mag{position:absolute;left:14px;top:50%;transform:translateY(-50%);
  width:22px;height:22px;fill:none;stroke:var(--muted);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;pointer-events:none}
.nsq-sheet .nsq-clr{position:absolute;right:4px;top:50%;transform:translateY(-50%);
  width:48px;height:48px;min-width:48px;min-height:48px;border:none;background:transparent;
  display:flex;align-items:center;justify-content:center;padding:0;border-radius:50%;cursor:pointer}
.nsq-sheet .nsq-clr[hidden]{display:none!important}
.nsq-sheet .nsq-clr svg{width:19px;height:19px;fill:none;stroke:var(--muted);stroke-width:1.8;
  stroke-linecap:round}

/* the list scrolls, the field and the bar do not, so the thing he types into never leaves the screen */
.nsq-sheet .nsq-list{flex:1 1 auto;min-height:0;overflow-y:auto}

/* an unset saved place wears the app's own "this is not a live row yet" dressing */
.nsq-sheet .row.nsq-unset{border:1.5px dashed var(--line);background:var(--paper)}
.nsq-sheet .row.nsq-unset svg{stroke:var(--muted)}

/* change this address. 48, not 44. */
.nsq-sheet .nsq-ped{flex:0 0 auto;width:48px;height:48px;min-width:48px;min-height:48px;
  border:1px solid var(--line);border-radius:var(--r-input);background:var(--card);cursor:pointer;
  display:flex;align-items:center;justify-content:center;padding:0}
.nsq-sheet .nsq-ped svg{width:21px;height:21px;stroke:var(--muted)}

/* the greyed tail of a suggestion, so the eye lands on the part he already typed */
.nsq-sheet .row .tx b .nsq-rest{font-style:normal;font-weight:400;color:var(--muted)}

/* an empty list is a real sentence, never a blank panel */
.nsq-sheet .nsq-empty{color:var(--muted);font-size:var(--t-small);line-height:var(--lh-small);margin:6px 2px var(--sp-3)}
.nsq-sheet .nsq-empty:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.4}

/* EDIT IN PLACE, rule zero, no popup ever. Same class names as Settings so it is visibly the same
   control; scoped here because Settings' own copies live under .fx-set, which this screen is not. */
.nsq-sheet .row.nsq-open{display:block;border:1.5px solid var(--ink);cursor:default}
.nsq-sheet .fx-rowtop{display:flex;align-items:center;gap:var(--sp-3);flex:1 1 auto;min-width:0;
  min-height:var(--tap-min)}
.nsq-sheet .fx-rowtop svg{width:24px;height:24px;flex:0 0 auto}
.nsq-sheet .fx-rowtop .tx{flex:1 1 auto;min-width:0}
.nsq-sheet .fx-editor{display:block;margin:var(--sp-3) 2px var(--sp-1);padding-top:var(--sp-3);
  border-top:1px solid var(--line)}
.nsq-sheet .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.nsq-sheet .fx-in{display:block;width:100%;min-height:48px;border:1.5px solid var(--ink);
  border-radius:var(--r-input);padding:0 14px;background:var(--card);
  font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;
  font-size:var(--t-body);color:var(--ink)}
.nsq-sheet .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;font-size:1rem}
.nsq-sheet .fx-btns{display:flex;gap:10px;margin-top:var(--sp-3)}
.nsq-sheet .fx-save{flex:1 1 0;min-height:48px;border:none;border-radius:var(--r-input);background:var(--good);
  color:#fff;font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body);cursor:pointer}
.nsq-sheet .fx-save:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}
.nsq-sheet .fx-cancel{flex:1 1 0;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);
  background:var(--card);color:var(--ink);font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:var(--t-body);cursor:pointer}
.nsq-sheet .fx-cancel:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}
.nsq-sheet .fx-save.nsq-danger{background:var(--red)}

/* clearing the history, and the question it asks first */
.nsq-sheet .nsq-wipe,.nsq-sheet .nsq-forget{min-height:48px;font-size:var(--t-small);margin:var(--sp-1) 0 2px}
.nsq-sheet .nsq-wipe:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.nsq-sheet .nsq-forget:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.nsq-sheet .nsq-ask{border:1.5px solid var(--red);border-radius:var(--r-ctl);padding:var(--sp-3) 13px;
  margin:var(--sp-1) 0 2px;font-size:var(--t-body);font-weight:700;color:var(--ink)}
.nsq-sheet .nsq-ask:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.88rem;font-weight:700}

/* THE b50 COLUMN RULE IS FOR A ROW CARRYING THREE CONTROLS, AND THESE CARRY ONE.
   Under 560px `.fx-ride .sheet .row` wraps and gives .tx a line of its own, which is exactly right
   for the ride row that has to fit NAVIGATE, GOOGLE MAPS and EDIT beside an address, and exactly
   wrong here: it turned every 64px list item into a 200px stack, icon on one line, address on the
   next, the GO chip on a third, and pushed the recents off the bottom of the sheet.

   FOUND BY LOOKING, not by reading. The numbers all said 48px and passing; the screenshot at 430
   said the rows were three lines tall. Opted out BY NAME rather than by loosening the rule it opts
   out of, because the row that rule was written for still needs it. */
@media (max-width:560px){
  .fx-ride .sheet.nsq-sheet .row{flex-wrap:nowrap;row-gap:0}
  .fx-ride .sheet.nsq-sheet .row>.tx{flex:1 1 auto;min-width:0}
  /* except the editor, which is a block on purpose: it is a form, not a list item */
  .fx-ride .sheet.nsq-sheet .row.nsq-open{display:block}
}

/* ---- footer, five tabs on EVERY screen, never fewer (rulebook --foot-h) ------------------------ */
.foot{flex:0 0 auto;display:flex;background:var(--card);border-top:1px solid var(--line);padding:var(--sp-2) var(--sp-1) 14px;
  min-height:var(--foot-h)}
.tab{position:relative;flex:1 1 0;display:flex;flex-direction:column;align-items:center;gap:var(--sp-1);
  padding-top:6px;color:var(--muted);font-size:var(--fs-label);font-weight:700;min-width:var(--tap-min);cursor:pointer}
.tab svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.tab.on{color:var(--orange)}
.tab .bdg{position:absolute;top:0;right:calc(50% - 24px);min-width:18px;height:18px;border-radius:9px;
  background:var(--orange);color:#fff;font-size:var(--fs-label);font-weight:800;line-height:18px;text-align:center;padding:0 var(--sp-1)}

/* ---- map. Phase B1 stand-in grid; wherever this grid shows, the real app shows the live
        Google map (rulebook). Phase C swaps the background for the map canvas, nothing else. ----- */
/* Phase C: the facade adds map-live when the REAL Google map paints, replacing the grey grid */
.map.map-live{background:var(--map-bg)}
.map{position:relative;flex:1 1 auto;min-height:300px;overflow:hidden;
  background:
    linear-gradient(90deg,transparent 48%,#fff 48%,#fff 52%,transparent 52%),
    linear-gradient(0deg,transparent 47%,#fff 47%,#fff 53%,transparent 53%),
    repeating-linear-gradient(90deg,#E6E3DC 0 1px,transparent 1px 54px),
    repeating-linear-gradient(0deg,#E6E3DC 0 1px,transparent 1px 54px),var(--map-bg)}
.map .mpill{position:absolute;background:var(--orange);color:#fff;font-size:var(--fs-label);font-weight:800;
  border-radius:var(--r-pill);padding:var(--sp-1) 10px}
.map .mpill.red{background:var(--red)}
.map .mpill.blue{background:var(--pax)}
.map .car{position:absolute;width:var(--car);height:var(--car);border-radius:50%;background:var(--card);border:2px solid var(--ink);
  display:flex;align-items:center;justify-content:center;font-size:var(--t-body)}
.map .mbtn{position:absolute;width:46px;height:46px;border-radius:50%;background:var(--card);
  box-shadow:0 3px 10px rgba(10,10,10,.2);display:flex;align-items:center;justify-content:center;min-width:var(--tap-min)}
.map .mbtn svg{width:22px;height:22px;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* ==================================================================================================
   b62, IN-APP GOOGLE NAVIGATION. Values taken from the mockup Ahmed approved on 2026-08-17,
   050-Documents/YPD-ARRIVAL-CARD-MOCKUP-V1A.html, not re-invented here.

   THE ONE STRUCTURAL RULE, and it is his: the nav panel and the arrival card are EQUAL FLEX
   SIBLINGS. "Same size in the width, same size in the height, but it's going to be on the right
   hand side." Equal width and height therefore fall out of `flex:1 1 0` on both, and no future
   edit can drift them apart, because there is no second number to keep in step.

   The first version of this mockup was rejected, correctly, for painting the whole panel green.
   Google's panel is GREEN ON TOP AND WHITE UNDERNEATH: "the order is wrong. That's supposed to be
   white underneath."
   ================================================================================================== */
/* ON .frame, NOT .map. The panel is a sibling of the map now, because app-map.js empties the map
   container when Google mounts into it and took the whole panel with it. */
.frame{--navgreen:#15594A; --navgreen2:#0F4C40; --nav-inset:10px; --nav-dist:1.5rem;
  --nav-road:1.02rem; --nav-eta:0.56rem}
/* The fold, and any wide phone. The ETA strip can afford its full size once each panel is wider
   than about 260px; below that "1.2 mi" needs 54px in a 46px cell and gets cut, which is a real
   measurement off the approved mockup, not a guess. */
@media (min-width:700px){
  /* b85: --nav-eta was 0.88rem here and clipped every cell on a Fold. b81 fixed the
     PHONE token and never looked at this one. Rendered at 768, 884, 1000 and 1200:
     0.88rem clips 13 strings at 768, 0.70rem clips none at any width. */
  .frame{--nav-inset:14px; --nav-dist:1.35rem; --nav-road:0.98rem; --nav-eta:0.70rem}
}

/* Positioned against .frame and offset past the header, so it sits over the map exactly where it
   did before without living inside the container Google wipes. */
.navrow{position:absolute;top:calc(var(--hd-h) + var(--nav-inset));
  left:var(--nav-inset);right:var(--nav-inset);
  display:flex;gap:10px;align-items:flex-start;justify-content:space-between;
  z-index:4;pointer-events:none}
.navrow[hidden]{display:none!important}   /* an explicit display ALWAYS beats [hidden] (2026-07-31) */
/* b65: A QUARTER EACH, so three quarters of the map stays visible. On a PHONE a quarter of 430px
   is 107px, which cannot hold a street name, so the narrow case takes 44% and the fold takes 25%.
   b170: this block plus .navrow > * was DELETED BY ACCIDENT in the b167 index-math edit and
   restored from commit 4c63616; the guard now asserts it so it can never vanish silently. */
.frame{--nav-w:44%}
@media (min-width:700px){ .frame{--nav-w:25%} }
.navrow > *{flex:0 0 var(--nav-w);min-width:0;display:flex;flex-direction:column;
  position:relative;pointer-events:auto;transition:flex-basis .22s ease}

/* ---- Google's panel, green over white ---- */
.nvpanel{}
/* b75: 85% OPAQUE, TESLA-STYLE. Ahmed's photo of his own dash: "the Tesla navigation on the top
   left is transparent, I think it's 85% visible and 15% transparent... if something does
   accidentally go under the Google navigation panel and the padding isn't working, at least we
   can somewhat see it." A safety net for the padding, not a replacement for it. */
.nbtop{flex:1 1 auto;display:flex;align-items:center;gap:13px;background:rgba(21,89,74,.85);
  border-radius:16px 16px 0 0;padding:var(--sp-3) 14px;box-shadow:0 6px 18px rgba(10,10,10,.3)}
.nbtop .mn{flex:0 0 auto;width:34px;height:34px}
/* b74: 50% BOLDER. "the arrow that's going up needs to be a little bit bolder and stronger,
   I would say by 50%, it's too thin." */
.nbtop .mn svg{width:34px;height:34px;fill:none;stroke:#fff;stroke-width:3.2;stroke-linecap:round;stroke-linejoin:round}
.nbtx{min-width:0}
.nbtx .dist{display:block;font-family:'Archivo Black','Arial Black',sans-serif;font-size:var(--nav-dist);
  color:#fff;line-height:1.05}
/* b530 (bug-mv87t9me-vcj5l): THE TEXT CLEARS THE CLOSE ARROW. The arrow is a 30px strip on the panel's right edge and the
   distance and the road printed straight under it ("7.1 mi" ended 1px past the chevron's left edge). 34px on the right
   leaves 11px of clear green before the chevron. The distance never wraps, "7.1" over "mi" is not a distance; navFit in
   app.html steps the type down before anything can overflow, and the road gets one line the same way where it fits. */
.nbtop{padding-right:34px;gap:10px}
.nbtx{flex:1 1 auto}
.nbtx .dist{white-space:nowrap}
/* b70: TWO LINES, NOT AN ELLIPSIS. "stay on S Sepu..." is not a road he can act on. A street name
   is the one thing on this panel he actually needs, so it gets the room: two lines, a slightly
   smaller step of type, and it wraps on a space instead of being cut mid-word. */
.nbtx .road{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  color:#DCEFE8;font-size:calc(var(--nav-road) * 0.92);font-weight:600;line-height:1.2;
  overflow:hidden;white-space:normal;overflow-wrap:break-word}
.nbeta{flex:0 0 auto;display:flex;background:rgba(255,255,255,.88);border-radius:0 0 16px 16px;
  box-shadow:0 6px 18px rgba(10,10,10,.22);overflow:hidden}
/* b67: overflow:hidden, and it is the whole bug. Each cell had min-width:0 but nothing clipping it,
   so nowrap text spilled OUT of its own cell and printed over the next one. That is the
   "8:59 AM75 min 27 mi" Ahmed photographed mid-drive: three correct values, no space between them,
   because cell one was drawing on top of cell two. */
/* b74: CENTRED, not left. "11:19 needs to be centered in the white box that it's in and
   it's justified to the right and it's wasting space on the left. Then it says one
   minute, same situation." */
/* b81: THE DIVIDER MOVED RIGHT, his instruction: "maybe you need to move the divider after
   4:21 PM a little bit to the right, so there is more room for the PM to fit". The arrive
   cell holds the longest string of the three, so equal thirds sized all three cells to the
   one that did not fit. Swept at 360, 390, 412 and 430: past about a 1.4 share the minutes
   cell becomes the binding constraint instead, so 1.15 is where both fit at the largest
   readable font. Padding 7 to 4 buys 6px per cell, which at 149px of panel is not small. */
.nbeta span{flex:1 1 0;min-width:0;overflow:hidden;padding:9px var(--sp-1);
  border-left:1px solid var(--line);text-align:center}
.nbeta span:first-child{flex:1.15 1 0}
.nbeta i{text-overflow:ellipsis}
.nbeta span:first-child{border-left:none}
/* b75: sizes MEASURED against every string these cells can ever hold, at every frame width.
   Worst cases are "101 min" and "1234 mi" now that the AM/PM is gone. Tracking is tightened
   slightly, which buys a little more room without changing the size on screen. */
.nbeta i{display:block;font-style:normal;line-height:1.16;white-space:nowrap;
  letter-spacing:-.03em;font-family:'Archivo Black','Arial Black',sans-serif;font-size:var(--nav-eta)}
/* b85: 5px, not 14px. Fourteen pixels of padding each side of a cell, inside a panel that
   is a quarter of the screen, was spending 28px per cell to show nothing. The padding
   was a bigger lever here than the font size. */
@media (min-width:700px){ .nbeta span{padding:9px 5px} }

/* ---- b78, THE TESLA PROGRESS BAR ----
   Ahmed, with a photo of his own dash: "Tesla progress bar = start it and get this in the app".
   A grey line for the whole leg, a blue line for the part behind him, and his own accent marking
   where he is. It sits between the green panel and the white one, which is where he put it.

   b78-w, WHITE UNDER THE BAR. Ahmed: "I want white color under the progress bar, so it stands
   out more". The strip is white now, so the panel steps from green to white once instead of
   twice, and it is rgba(255,255,255,.88), THE SAME VALUE .nbeta USES, so the two whites are one
   piece.

   TRANSPARENCY IS THE DESIGN LANGUAGE HERE, NOT A DEFECT TO ENGINEER AWAY. Ahmed, choosing it
   over solid white and overruling a recommendation that had the better contrast number: "since
   the Google panel is transparent, then what you're building needs to follow the same
   transparency, so it feels like it's part of this, it's a part of the same family. If we make
   it all solid, that goes away from the visual look that I'm going for... this is the way Tesla
   does it, so I'm trying to take what Google does, take what Tesla does, and then come up with
   our own visual style." DO NOT raise this alpha toward opaque to win contrast back. The alpha
   is a decision. The contrast is solved on the MARKER instead, at .nbmark below.

   EVERY MARK WAS RE-MEASURED ON THE NEW GROUND rather than carried over, because a colour that
   read on dark green is making no promise at all on white. The old track was
   rgba(255,255,255,.32), which on white is white on white and would simply have vanished.
   From scratch/contrast-progress.mjs, against the green bar this replaces:
     blue fill vs its own track, WHICH IS WHERE THE PROGRESS IS READ   1.10:1 -> 3.25:1
     blue fill vs its ground                                           2.19:1 -> 4.51:1 light
                                                                              -> 3.43:1 dark
   The track goes 2.41:1 -> 1.39:1 over a light map and 1.05:1 over a dark one, and that is a
   real cost of the transparency, stated rather than hidden. It is also FORCED: on the dark-map
   ground the strip resolves to #E0E0E0, which is only 3.43:1 from the blue in total, so there
   is not enough range left to give the track 3.0 AND the blue edge 3.0. The range is spent on
   THE EDGE, because where the blue stops is the whole message and the track only ever says the
   leg continues past here. An opaque light track also holds its own colour on any ground, so
   the edge stays 3.25:1 whatever Google draws; a translucent dark track would have tracked the
   ground and dragged the edge down to 2.43:1 over a dark map. Measured, both ways, in that file.

   IT IS STILL 21px TALL including its border, measured at 360px, 430px, 884px and 1000px, not
   eyeballed. The hairline that used to sit on TOP of it was rgba(255,255,255,.14), right for
   dark green and invisible on white; it moved to the BOTTOM as var(--line), the hairline this
   panel already draws between the ETA strip's own cells, so the strip separates from the strip
   below it and the height did not move by a pixel. The panel is already as long as he will
   tolerate: "the negative space underneath should be less, and it's doing the opposite right
   now."

   --np is a plain number 0 to 1, written by navProgPaint. THE MARKER TRAVELS THE TRACK MINUS ITS
   OWN WIDTH, so it cannot hang off either end at 0% or 100%. That is structural, not a value
   somebody tuned: left:PCT% with a centring transform is the shape that overflows, and it is not
   used here. */
.nbprog{flex:0 0 auto;background:rgba(255,255,255,.88);padding:4px 12px 5px;
  border-bottom:1px solid var(--line)}
.nbprog[hidden]{display:none!important}   /* an explicit display ALWAYS beats [hidden] (2026-07-31) */
.nbtrack{position:relative;display:block;height:11px}
/* THE WHOLE ROUTE, GREY. var(--line) is not a new colour invented for this bar: it is the
   hairline this panel already draws on white, between the three ETA cells and under the arrival
   card's gate code, so the strip's grey and the greys around it are the same grey by
   construction and a palette change moves all of them together. Drawn as the track's own line
   so there is no second element that can drift out of step with the width the marker travels. */
.nbtrack::before{content:'';position:absolute;left:0;right:0;top:50%;margin-top:-2px;height:4px;
  border-radius:2px;background:var(--line)}
/* THE ROAD BEHIND HIM, in the SAME blue as the route line on the map (app-nav.js draws #1A73E8),
   so the bar and the map are telling him one story in one colour. It ends under the middle of
   the marker, which is why the 5.5px is half a marker and not a nudge. */
.nbfill{position:absolute;left:0;top:50%;margin-top:-2px;height:4px;border-radius:2px;
  background:#1A73E8;width:calc(5.5px + var(--np, 0) * (100% - 11px))}
/* ---- THE ARROW, TWO STACKED SHAPES ----
   HIS COLOUR, NOT AHMED'S. --orange is the DRIVER'S accent, written at runtime by applyAccent
   from their own profile, so a teal driver gets a teal arrow on their screen. There is no hex
   in either rule below; a hex here is the white-label bug t62-accent.mjs exists to catch.

   WHY IT IS TWO SHAPES AND NOT ONE. The strip is translucent by decision, so its ground is a
   RANGE: 88% white over a light road is #FFFFFF, over dark map content it is #E0E0E0. A bare
   accent arrow measured 3.57:1 on the light end and 2.72:1 on the dark end, and pale accents
   were far worse, 2.57:1 teal and 2.22:1 gold on the LIGHT end. That is a real readability
   problem and it is NOT solved by making the strip opaque, which was tried and rejected: the
   transparency is the visual language.

   So the arrow carries its own contrast. A slightly larger NEUTRAL arrow is drawn behind the
   accent one, which is exactly how Google and Tesla keep a coloured marker readable over a live
   map: the silhouette is delimited by something dark, so the shape reads no matter what colour
   is inside it or what the map is doing underneath. The ring measures 19.80:1 on a light map
   and 15.05:1 on a dark one, and it is the SAME number for every driver because it is neutral,
   which is what makes this accent-independent rather than tuned for Forge Orange. Every accent
   then clears 3.0:1 against the ring: orange 5.54, teal 7.71, gold 8.94, lime 16.36.

   An outline or a border cannot do this job: .nbmark is cut out with clip-path, and clip-path
   clips borders, outlines and box-shadows away with everything else. Changing the SHAPE
   technique is the fix; accepting a 2.2:1 arrow was not.

   THE OUTER BOX IS STILL EXACTLY 11px, and the ring is drawn INSIDE it rather than around it,
   so the marker's footprint has not grown by a pixel and every travel and overflow property
   below still holds unchanged. A ring drawn outward would hang past the end of the track at 0%
   and 100%, which is the exact overflow this shape exists to make impossible.

   EACH SHAPE IS DECLARED ONCE, as a token, and the layers reference them. Written as a shared
   `.nbmark::before,.nbmark::after` selector instead, the two layers would be one rule for
   anything reading this file by selector, and the accent layer would be unreadable to the
   white-label guard.

   AND THE RING IS A SOLID TRIANGLE WHILE THE ACCENT IS THE CHEVRON, which is not a style
   choice, it is the fix for something only a screenshot found. The blue fill runs to the
   arrow's CENTRE, so at 0% there are 5.5px of blue underneath the arrow. Through the chevron's
   notch that blue came out as a DETACHED BLUE DOT sitting to the left of the arrow, which
   reads as a rendering fault rather than as the start of the line, and it is on screen for the
   first seconds of every leg, which is exactly when he looks at the panel. A solid ring
   occludes the fill across the whole 11px, so the notch shows the ring's own dark instead. The
   arrow still looks like a chevron because the accent layer on top still is one. */
.nbmark{position:absolute;top:0;width:11px;height:11px;
  left:calc(var(--np, 0) * (100% - 11px));
  --nbarrow:polygon(6% 2%, 100% 50%, 6% 98%, 34% 50%);
  --nbring:polygon(0% 0%, 100% 50%, 0% 100%)}
/* the ring. var(--ink) is the panel's OWN near-black, already the text colour on these white
   panels, and it is neutral by construction so it can never become a second brand colour
   competing with the driver's own. */
.nbmark::before{content:'';position:absolute;inset:0;clip-path:var(--nbring);background:var(--ink)}
/* and the driver's colour, inside it */
.nbmark::after{content:'';position:absolute;inset:1.25px;clip-path:var(--nbarrow);background:var(--orange)}
/* THE NEXT-TURN ROW, BUILT AND SHIPPED OFF. Ahmed picked WITHOUT and said he may change his mind
   once he has driven with it, so this is a real row hidden by one attribute rather than an absence.
   Turning it on later is removing `hidden`, not a rebuild. */
.nbnext{display:flex;align-items:center;gap:var(--sp-2);background:var(--navgreen2);color:#CFE6DE;
  padding:6px 14px 7px;font-size:.78rem;font-weight:700;white-space:nowrap;
  border-top:1px solid rgba(255,255,255,.14)}
.nbnext[hidden]{display:none!important}
/* b554 (Ahmed 2026-10-20): THE ADDRESS UNDER THE TURN, the whole leg. The same dark green strip as the next turn row, white
   text, a pin, two lines at most and an ellipsis after that, so a long address can never make the panel eat the map.
   34px on the right like .nbtop (b530), the dock chevron is a full height strip on that edge. */
.nbdest{display:flex;align-items:flex-start;gap:6px;background:var(--navgreen2);color:#fff;
  padding:6px 34px 7px var(--sp-3);border-top:1px solid rgba(255,255,255,.14)}
.nbdest[hidden]{display:none!important}
.nbdest .mn3{flex:0 0 auto;width:15px;height:15px;margin-top:2px;display:block}
.nbdest .mn3 svg{width:15px;height:15px;fill:none;stroke:#CFE6DE;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.nbdest .desttx{flex:1 1 auto;min-width:0;font-size:calc(var(--nav-road) * 0.87);font-weight:700;line-height:1.22;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;white-space:normal;overflow-wrap:break-word}
.nbnext .mn2{width:15px;height:15px;flex:0 0 auto;display:block}
.nbnext .mn2 svg{width:15px;height:15px;fill:none;stroke:#CFE6DE;stroke-width:2.2;stroke-linecap:round}

/* ---- the arrival card ----
   b65, THE COLOUR. Ahmed on the black card: "it is black background with white text. It stands out
   too much." It now matches Google's own white strip directly under the turn, so the two panels
   read as one system instead of two competing objects, and the map behind stays the brightest thing
   on the screen. The gate code carries the DRIVER'S accent, which is the one place on this screen
   where their brand belongs and is white-label by construction. */
/* b82: CENTRED ON THE CONTAINER, NOT ROW BY ROW. Ahmed: "concord court needs to be centered
   under it... make sure the text for this whole Panel on the right hand side is similar. And is
   centered." Setting text-align here means .adr, .adrst, .gcode and anything added to this card
   later inherit it, so a new row cannot ship left aligned the way .adrst quietly did. */
.msgpanel{background:rgba(255,255,255,.88);border-radius:16px;box-shadow:0 6px 18px rgba(10,10,10,.22);
  overflow:hidden;justify-content:center;pointer-events:auto;text-align:center}
.msgpanel[hidden]{display:none!important}
.msgpanel .adr{padding:11px 14px 2px;font-family:'Archivo Black','Arial Black',sans-serif;
  color:var(--ink);font-size:var(--nav-dist);line-height:1.08;letter-spacing:-.02em}
/* b82: THE SAME SECONDARY SIZE AS THE ROAD ON THE LEFT, which is the whole of Ahmed's
   "they're the same size, same scale". calc(var(--nav-dist) * 0.52) was 12.48px and belonged to
   nothing; .nbtx .road is calc(var(--nav-road) * 0.92), so this is now the identical expression
   and the two panels cannot drift apart. MEASURED at 430px, both panels: primary 24px and 24px,
   secondary 15.01px and 15.01px, width 180.39px and 180.39px.
   TWO LINES, NOT AN ELLIPSIS, the same clamp .road already carries (b70). A street name is what
   he is reading at the kerb, so it gets a second line, and exactly one, so the card cannot grow
   tall enough to eat the map. */
.msgpanel .adrst{padding:0 14px 11px;font-weight:700;color:var(--ink);
  font-size:calc(var(--nav-road) * 0.92);line-height:1.15;letter-spacing:-.01em;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;white-space:normal;overflow-wrap:break-word}
/* an explicit display ALWAYS beats [hidden], so the guard is not optional (2026-07-31) */
.msgpanel .adrst[hidden]{display:none!important}
/* b438: the stop line over the address on a stop leg, "STOP 1 OF 2 · PICK UP JOSH", in the driver's accent at the
   label size, so the card is still one type system. Hidden on every other leg. */
.msgpanel .nvstop{padding:9px 26px 0;font-family:'Space Grotesk',-apple-system,'Segoe UI',Roboto,sans-serif;font-weight:800;
  font-size:calc(var(--nav-road) * 0.8);line-height:1.15;letter-spacing:.03em;color:var(--orange);text-transform:uppercase;overflow-wrap:break-word}
.msgpanel .nvstop[hidden]{display:none!important}
.dock .adrst{display:none}
/* b82: GATE CODE, NOT GATE. His words: "GATE = GATE CODE." The label sits at the panel's
   SECONDARY size and the code at its PRIMARY size, which is the same two step relationship the
   green panel uses, so the whole card is one type system rather than three. It cannot be one
   string: "GATE CODE 4471" measures 219.63px and the widest text box a phone gives this card is
   136.39px, so a single line could only ever wrap into three. The row's own padding drops from
   10/11 to 7/10 to pay back 4px of the 16.81px the label line costs.
   The colour stays var(--orange), the DRIVER'S accent, never a hex. This row is the one place on
   this screen where a driver's own brand belongs, and it is white label by construction. */
.msgpanel .gcode{padding:7px 14px 10px;border-top:1px solid var(--line);
  font-family:'Archivo Black','Arial Black',sans-serif;color:var(--orange);
  font-size:var(--nav-dist);line-height:1.08;overflow-wrap:break-word}
.msgpanel .gcode .glab{display:block;font-family:'Space Grotesk',-apple-system,'Segoe UI',Roboto,sans-serif;
  font-weight:800;font-size:calc(var(--nav-road) * 0.92);line-height:1.12;letter-spacing:.02em}
.msgpanel .gcode .gval{display:block}
/* b370: AT THE GATE, under the code, at the label's own size and the same accent, so "GATE CODE #4580 AT THE
   GATE" reads as one sentence (Ahmed 2026-09-19, bug-mu8cteg9). The row is also the one-tap save, so it
   carries the pointer. */
.msgpanel .gcode{cursor:pointer}
.msgpanel .gcode .gat{display:block;font-family:'Space Grotesk',-apple-system,'Segoe UI',Roboto,sans-serif;
  font-weight:800;font-size:calc(var(--nav-road) * 0.92);line-height:1.12;letter-spacing:.02em}
.msgpanel .gcode .gat[hidden]{display:none!important}
.msgpanel .gcode .glab[hidden], .msgpanel .gcode .gval[hidden]{display:none!important}
.msgpanel .gcode[hidden]{display:none!important}   /* no gate on file, no row, and it says nothing */

/* ---- b65, DOCK EITHER PANEL OUT OF THE WAY ----
   Ahmed: "We used to have an arrow on the right that I would click on it and it would hide the menu
   to the left... So right now we're just looking to be able to dock it to the left and then bring
   it back out." One arrow per panel, each folding towards its own edge, each leaving a tab wide
   enough to find and tap. The turn arrow stays visible on the docked nav tab so a glance still says
   which way the next turn goes. */
.navdock{position:absolute;top:0;height:100%;width:30px;min-height:48px;border:none;padding:0;
  background:transparent;display:flex;align-items:center;justify-content:center;
  cursor:pointer;z-index:3}
.nvpanel  .navdock{right:0}
.msgpanel .navdock{left:0}
.navdock svg{width:15px;height:15px;fill:none;stroke-width:2.8;stroke-linecap:round;stroke-linejoin:round}
.nvpanel  .navdock svg{stroke:#CFE6DE}
.msgpanel .navdock svg{stroke:var(--muted)}
/* b67: THE CARD'S CONTENT CLEARS ITS OWN ARROW. The dock button is absolute at left:0, and the
   address was printing underneath it, which is the chevron sitting on "lax airport" in his
   screenshot: "the arrow on that one is messed up".
   b82: ON BOTH SIDES, AND .adrst IS IN THE LIST NOW. b67 named the two rows that existed then,
   b74 added the street with 14px, and it has been printing straight through the chevron ever
   since, which is visible on his own screenshot. Symmetric padding is also what makes centred
   text actually centred, so the two fixes are one rule.
   26px, MEASURED, not chosen: the chevron is a 15px svg centred in a 30px strip, so it paints
   out to 22.5px; at the narrowest phone (360px) this leaves a 97.59px text box, which holds the
   widest single line the card can draw, a six digit gate code at 93.17px, with room to spare.
   It gives the house number 2px MORE than the 40px/14px it replaces. */
.msgpanel .adr, .msgpanel .adrst, .msgpanel .gcode{padding-left:26px;padding-right:26px}

/* b67: DOCKED, THE TAB IS THE BUTTON. It could fold away and never come back, "the arrow that makes
   him go to the left kind of worked, but can't bring it back", because the chevron was still a
   30px absolute strip beside a green header that had claimed the whole tab. Now everything else in
   the panel is hidden and the button IS the tab, so there is nothing left that can push it out of
   reach or cover it. */
.navrow > .dock{flex:0 0 52px}
.dock .nbtop, .dock .nbeta, .dock .nbnext, .dock .nbdest, .dock .nbprog, .dock .adr, .dock .gcode{display:none}
.dock .navdock{position:static;width:100%;height:auto;min-height:52px;border-radius:16px}
.dock .navdock svg{transform:scaleX(-1);width:18px;height:18px}
.nvpanel.dock  .navdock{background:var(--navgreen);box-shadow:0 6px 18px rgba(10,10,10,.3)}
.nvpanel.dock  .navdock svg{stroke:#fff}
.msgpanel.dock .navdock{background:var(--card);box-shadow:0 6px 18px rgba(10,10,10,.22)}
.msgpanel.dock{background:transparent;box-shadow:none;overflow:visible}

/* b67: THE PANELS NEVER FIGHT THE SHEET. Ahmed: "the Google navigation panels and the one that we
   have for the drop off is never supposed to fight with the menu. When the menu comes up, they're
   always supposed to be tucked away." An open sheet wins; closing it brings them back. `:has` is
   already load-bearing in this file, so this is not a new dependency. */
/* b84: A HIDDEN SHEET IS NOT AN OPEN SHEET. The destination search panel ships as
   <div class="sheet nsq-sheet" hidden>, a direct child of .frame, and `hidden` is not
   `.shmin`, so its mere PRESENCE satisfied every "is a sheet open" test in this file and
   held the navigation panel at opacity 0 for the whole drive. Ahmed photographed it: route,
   arrow and street label all correct, no panel at all. Fixed on the class, all nine
   selectors, so the next hidden panel inherits the right answer. */
.frame:has(> .sheet:not(.shmin):not([hidden])) > .navrow,
.frame:has(> .sheet:not(.shmin):not([hidden])) > .navctl{opacity:0;pointer-events:none}
.frame > .navrow, .frame > .navctl{transition:opacity .2s ease,top var(--safe-t) var(--safe-e),bottom var(--safe-t) var(--safe-e)}

/* ---- the controls. 48px minimum, his standing rule, and they exist only while navigating ---- */
/* Sits above the footer, not the bottom of the frame, because the footer is always there and the
   sheet is closed while navigating. */
.navctl{position:absolute;right:var(--nav-inset);bottom:calc(var(--foot-h) + var(--nav-inset));
  display:flex;flex-direction:column;gap:10px;z-index:4}
.navctl[hidden]{display:none!important}
/* b158: HER TWO BUTTONS LAND ON HIS SLOTS, his spec slot for slot: recenter on his recenter
   (top slot), sound on his sound (third slot), the search slot left empty between them. Her rail
   is one slot up from his base and her gap is one empty slot, so the two rails line up on any
   screen without a second geometry system. */
.frame[data-role="passenger"] > .navctl{
  bottom:calc(var(--foot-h) + var(--nav-inset) + 62px);
  gap:72px}
.navctl .mbtn{position:static;width:52px;height:52px;min-width:48px;min-height:48px;
  flex-direction:column;gap:1px;border:none;padding:0;cursor:pointer}
.navctl .mbtn .tag{font-style:normal;font-family:'JetBrains Mono',Consolas,monospace;
  font-size:var(--fs-label);letter-spacing:.06em;font-weight:800;color:var(--muted)}
.navctl .mbtn svg{width:21px;height:21px}
/* STOP is the one destructive control here, so it is the only one that wears the warning colour */
.navctl .mbtn.navx svg{stroke:var(--red)}
.navctl .mbtn.navx .tag{color:var(--red)}

/* ---- dark surfaces. Lime labels ONLY here, grey on white, never the reverse (rulebook) --------- */
.pill{display:inline-flex;align-items:center;gap:7px;background:var(--ink);color:#fff;border-radius:var(--r-pill);
  padding:var(--sp-2) var(--sp-4);font-family:'Archivo Black',sans-serif;font-size:var(--t-body);box-shadow:0 4px 12px rgba(10,10,10,.3)}
.pill:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:1.05rem}
.pill small{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;
  color:var(--lime);text-transform:uppercase}
.darkcard{background:var(--ink);color:#fff;border-radius:16px;padding:14px}
.darkcard .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--lime)}
.darkcard .big{font-family:var(--display);font-size:var(--t-big);color:var(--lime)}
.darkcard .big:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:1.5rem}

/* ---- misc -------------------------------------------------------------------------------------- */
.seclab{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--muted);margin:var(--sp-1) 2px -4px;flex:0 0 auto}
.avatar-lg{width:64px;height:64px;border-radius:50%;background:var(--placeholder);color:var(--ink,#0A0A0A);display:flex;   /* b308: ink initials, 11.5:1 on the grey */
  align-items:center;justify-content:center;font-weight:600;font-size:var(--t-card)}
.avatar-lg:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:1.3rem}
.hr{height:1px;background:var(--line);margin:10px 0}
.note{font-size:var(--t-small);color:var(--muted);line-height:var(--lh-small)}
.note:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;line-height:1.4}

/* ================================================================================================
   FRAGMENT STYLES, verbatim from the approved mock (prefixed per screen family).
   None of these touch sheet geometry, per the law at the top.
   ================================================================================================ */

/* fx-entry: landing + driver Home */
/* safe center: symmetric when it fits, scrolls instead of clipping on very short windows */
.fx-entry .fx-land{flex:1 1 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(16px,2.6dvh,28px);padding:26px;text-align:center;overflow-y:auto;min-height:0}
/* The logo NEVER wraps (law): nowrap enforced, tall size is its own smaller token */
.fx-entry .fx-logo{font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:var(--logo-fs);letter-spacing:.02em;white-space:nowrap}
/* TALL: the vehicle button stacks, name over plate, no middot (Ahmed 2026-08-13); LONG one line */
.fx-entry .fx-veh .vmain{display:flex;flex-direction:column;align-items:center;gap:2px}
.fx-entry .fx-veh .vsep{display:none}
.fx-entry .fx-logo em{font-style:normal;color:var(--orange)}
.fx-entry .fx-av{width:128px;height:128px;border-radius:50%;background:var(--placeholder);color:#fff;display:flex;align-items:center;justify-content:center;font-family:var(--display);font-size:var(--t-big);border:3px solid var(--orange);box-shadow:0 4px 14px rgba(10,10,10,.15)}
.fx-entry .fx-av:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:2.4rem}
.fx-entry .fx-name{font-family:'Space Grotesk',sans-serif;font-weight:800;font-size:var(--title-fs)}
.fx-entry .fx-avwrap{position:relative;cursor:pointer}
.fx-entry .fx-cam{position:absolute;bottom:0;right:0;width:36px;height:36px;border-radius:50%;background:var(--ink);border:2.5px solid #fff;display:flex;align-items:center;justify-content:center}
.fx-entry .fx-cam svg{width:18px;height:18px;fill:none;stroke:#fff;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.fx-entry .fx-vchev{width:16px;height:16px;stroke:var(--muted);fill:none;stroke-width:2;flex:0 0 auto}
.fx-crop{display:none;flex-direction:column;gap:10px;align-items:center;width:100%}
.fx-editor[data-stage="1"] .fx-crop{display:flex}
.fx-editor[data-stage="1"] .fx-phrow{display:none}
.cropbox{width:220px;height:220px;border-radius:50%;overflow:hidden;position:relative;background:#E5E3DD;touch-action:none;flex:0 0 auto}
.cropimg{position:absolute;max-width:none;user-select:none;-webkit-user-drag:none;pointer-events:none}
.cropzoom{width:220px;accent-color:var(--orange)}
/* Vehicle line, picker law LOCKED (Ahmed 2026-08-13): ONE line, name middot plate chevron, on a
   WHITE bordered button so it reads tappable. No tag, no hint text, both formats. */
.fx-entry .fx-veh{display:inline-flex;align-items:center;gap:var(--sp-2);color:var(--muted);font-size:var(--t-small);
  margin-top:-4px;background:var(--card);border:1.5px solid var(--line);border-radius:var(--r-ctl);padding:11px var(--sp-5);
  min-height:48px;cursor:pointer}
.fx-entry .fx-veh:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.fx-entry .fx-landcta{width:100%}
.fx-entry .fx-landghost{width:100%}
.fx-entry .vehlist{display:none;width:100%;max-width:520px}
.fx-entry .vehlist[data-open="1"]{display:flex;flex-direction:column;gap:10px}
.fx-entry .vrow{display:flex;align-items:center;gap:10px;min-height:var(--tap-min);border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);padding:10px 14px;cursor:pointer}
/* Row text is ONE line, identical format to the closed line (picker law) */
.fx-entry .vrow .vtx{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap;text-align:left}
.fx-entry .vrow b{font-size:var(--t-body)}
.fx-entry .vrow b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-entry .vrow span{color:var(--muted);font-size:var(--t-small)}
.fx-entry .vrow span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.fx-entry .vrow .vk{margin-left:auto;color:var(--orange);font-weight:800;font-size:var(--fs-label);letter-spacing:.06em}
.fx-phrow{display:flex;align-items:center;gap:var(--sp-3);margin:6px 0 var(--sp-1)}
.fx-phrow .pav{width:56px;height:56px;border-radius:50%;background:var(--placeholder);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;flex:0 0 auto}
.fx-phbtn{cursor:pointer}
.fx-entry .hd-logo{font-size:var(--t-label);white-space:nowrap;letter-spacing:.01em}
.fx-entry .hd-logo:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem}
.fx-entry .facts .v{font-size:var(--fs-label);word-break:normal;overflow-wrap:break-word}
.fx-entry .facts .v small{font-size:var(--fs-label)}
.fx-entry .chip{font-size:var(--t-small);gap:5px;padding-right:9px}
.fx-entry .chip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.fx-entry .fx-belldot{position:relative}
.fx-entry .fx-belldot i{display:none;position:absolute;top:8px;right:9px;width:9px;height:9px;
  border-radius:50%;background:var(--orange)}
/* (0,3,1) beats the rule above (0,2,1), so the dot appears only when the binding says so */
.fx-entry .fx-belldot[data-unread="1"] i{display:block}
.fx-entry .fx-chipoff{width:8px;height:8px;border-radius:50%;background:#B9B6AF;flex:0 0 auto}
.fx-entry .fx-id .nm{font-family:var(--body);font-size:var(--t-card);display:block;margin:var(--sp-2) 0 6px;font-weight:600}
.fx-entry .fx-id .nm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.1rem}
.fx-entry .fx-meta,.fx-pax .fx-meta{color:var(--muted);font-size:var(--fs-label);margin-top:var(--sp-2);line-height:1.35}
.fx-entry .fx-mono,.fx-pax .fx-mono{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.fx-entry .fx-vehname,.fx-pax .fx-vehname{font-weight:700;font-size:var(--t-body);line-height:var(--lh-body);margin-top:7px}
.fx-entry .fx-vehname:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-pax .fx-vehname:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.92rem;line-height:1.2}
.fx-entry .fx-plate,.fx-pax .fx-plate{display:inline-block;border:1.5px solid var(--ink);border-radius:6px;padding:2px var(--sp-2);font-family:'JetBrains Mono',monospace;font-weight:800;font-size:var(--t-num);letter-spacing:.06em;margin:7px 0 2px}
.fx-entry .fx-plate:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-pax .fx-plate:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-weight:700;font-size:.76rem}
.fx-entry .fx-carsvg,.fx-pax .fx-carsvg{width:100%;height:42px;margin-top:2px}
.fx-entry .fx-carsvg svg,.fx-pax .fx-carsvg svg{width:100%;height:100%;fill:none;stroke:var(--ink);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* b639: THE CAR SITS IN A FACE-SIZED CIRCLE (Ahmed 2026-10-28: "move it up to where it aligns with where my face is
   and where the passenger's picture is, so I can upload and put a picture of the car there"). The circle is .avatar-lg,
   so its size and place come from the same rule as the two face circles. A photo fills it, cropped; with no photo the
   grey circle carries the line drawing. Three-class selectors, they outrank .fx-entry/.fx-pax .fx-carsvg and .fx-carphoto. */
.cards3 .card .fx-carav{position:relative;overflow:hidden;flex:0 0 auto}
.cards3 .fx-carav .fx-carphoto{width:100%;height:100%;max-height:none;margin:0;border-radius:50%;object-fit:cover}
.cards3 .fx-carav .fx-carsvg{width:44px;height:18px;margin:0}
.cards3 .fx-carav .fx-carsvg svg{stroke-width:3.2}
/* and the card gives back most of the 20px the circle adds (64 circle in place of a 42 drawing): the plate sits
   tight under the name and the Home stack stays about as tall as it was (t221: the money owed panel above GO OFFLINE at 430x900) */
.cards3 .fx-carav ~ .fx-plate{margin:2px 0 0}

/* b653: THE DRIVER HOME'S THREE CARDS LINE UP (Ahmed 2026-10-28, HC645, the approved row layout). Same rows, same sizes,
   same order in every card: label, a 120px circle, the name, one 40px status line, one 44px button, then the card's
   own extra line under both. On a phone the circle sits left and the four rows right, so the three cards end above
   GO ONLINE at 430x900 (t377 measures it); wider than 560 the cards sit side by side and stack the rows centred.
   Driver frames only (.hc is only in their markup), her Home keeps b639. */
.cards3 .card.hc{gap:0;padding:16px 16px 18px}
.cards3 .card.hc > .fx-mono{margin:0 0 12px}
.cards3 .card.hc .hc-av{position:relative;width:120px;height:120px;flex:0 0 auto;cursor:pointer;-webkit-tap-highlight-color:transparent}
.cards3 .card.hc .hc-av > .avatar-lg{width:120px;height:120px;font-size:36px}
.cards3 .card.hc .fx-carav .fx-carsvg{width:74px;height:30px}
.cards3 .card.hc .fx-carav .fx-carsvg svg{stroke-width:2.6}
.cards3 .card.hc .hc-cam{position:absolute;right:-2px;bottom:-2px;width:34px;height:34px;border-radius:50%;background:var(--ink);
  border:3px solid #fff;display:flex;align-items:center;justify-content:center;box-sizing:border-box}
.cards3 .card.hc .hc-cam svg{width:16px;height:16px;fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* b670: YOUR PASSENGER's camera (bug-mvttmkth-11avs). The circle there opens the ride, so the camera is its own 44px button
   over the same corner; the 34px badge inside it sits exactly where the other two cards wear theirs. */
.cards3 .card.hc [data-act="home-paxphoto"]{position:absolute;right:-7px;bottom:-7px;width:44px;height:44px;margin:0;padding:0;border:0;border-radius:50%;
  background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;z-index:1}
.cards3 .card.hc [data-act="home-paxphoto"] > .hc-cam{position:static}
.cards3 .card.hc .hc-nm{display:block;margin:12px 0 0;height:30px;line-height:30px;font-family:var(--body);font-weight:600;font-size:24px;
  color:var(--ink);max-width:100%;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cards3 .card.hc .hc-l2{height:56px;margin:8px 0 0;display:flex;align-items:center;justify-content:center}   /* b674: 56, the California plate's height */
.cards3 .card.hc .hc-l2 .badge{font-size:15px;padding:0 16px;height:32px;line-height:32px;margin:0}
/* a licence plate: white, an ink frame with a thin inner rule, wide mono characters.
   b674 (Ahmed 2026-10-29, "make it fit California"): a California plate is 12 by 6 inches, so the frame is 2:1, 112 by 56, and
   the characters are sized to sit inside it; the photo over it is never cropped (contain, below). */
.cards3 .card.hc .hc-plate{display:inline-flex;align-items:center;justify-content:center;height:56px;width:112px;aspect-ratio:2/1;min-width:0;padding:0 6px;
  box-sizing:border-box;background:#fff;border:2.5px solid var(--ink);border-radius:8px;overflow:hidden;white-space:nowrap;
  box-shadow:inset 0 0 0 2px #fff,inset 0 0 0 3.5px rgba(10,10,10,.28);font:800 17px/1 'JetBrains Mono',monospace;letter-spacing:.08em;color:var(--ink);margin:0}
.cards3 .card.hc .hc-btnrow{display:flex;width:100%;min-height:44px;margin:14px 0 0}   /* the row keeps its height with no button (no ride), so the circles never move */
.cards3 .card.hc .hc-btnrow .ti-cardbtn{margin:0;width:100%}
.cards3 .card.hc .hc-extra{margin:12px 0 0;display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;gap:4px 12px}
.cards3 .card.hc .hc-extra:not(:has(> :not([hidden]))){display:none}
.cards3 .card.hc .hc-extra > *{margin:0}
/* b658: THE PLATE BOX (Ahmed 2026-10-28, bug-mvst785j). The drawn plate sets the size; his plate photo, when there is one, lies
   over it at exactly that size and frame. On his Homes the box is a door with a small camera badge.
   b674 (Ahmed 2026-10-29, "make it fit California and the bottom is getting cut off"): every plate box is a California plate,
   12 by 6 inches, a 2:1 rounded rectangle, and the photo shows WHOLE inside it (object-fit contain on white), never cropped
   top or bottom. The stored photo keeps its own shape (carPhotoShrink, no cropper), the box fits it. The text plate is centred. */
.hc-platebox{position:relative;display:inline-flex;vertical-align:middle;margin:2px 0 0;aspect-ratio:2/1}
.fx-entry .hc-platebox > .fx-plate,.fx-pax .hc-platebox > .fx-plate{margin:0;display:inline-flex;align-items:center;justify-content:center;
  height:56px;width:112px;aspect-ratio:2/1;box-sizing:border-box;padding:0 6px;overflow:hidden;white-space:nowrap;background:#fff}   /* the box carries the spacing, so the photo covers the plate exactly */
.cards3 .card.hc .hc-platebox{margin:0}
.hc-platebox .hc-plateimg{position:absolute;inset:0;width:100%;height:100%;box-sizing:border-box;object-fit:contain;background:#fff;
  border:1.5px solid var(--ink);border-radius:6px}
.hc-platebox .hc-plateimg[hidden]{display:none}
.cards3 .card.hc .hc-platebox{cursor:pointer;-webkit-tap-highlight-color:transparent}
.cards3 .card.hc .hc-platebox .hc-plateimg{border:2.5px solid var(--ink);border-radius:8px}
/* b684: THE PHOTO IS THE PLATE (Ahmed 2026-10-29 16:45, "your border doesn't match mine"). A 2:1 photo (data-pfit="cover", set
   by platePhotoFit once it loads) fills the box edge to edge with a real plate's small rounded corners, no drawn frame, no white
   under it, and the drawn text plate under it is hidden (it still holds the box's size). An older photo that is not 2:1 keeps
   the b674 framed contain look above. */
.hc-platebox[data-pfit="cover"] > [data-veh="plate"]{visibility:hidden}
.hc-platebox .hc-plateimg[data-pfit="cover"],.cards3 .card.hc .hc-platebox .hc-plateimg[data-pfit="cover"]{object-fit:cover;border:0;border-radius:5px;background:transparent}
.cards3 .card.hc .hc-platebox .hc-camsm{width:26px;height:26px;right:-11px;bottom:-11px;border-width:2px}
.cards3 .card.hc .hc-platebox .hc-camsm svg{width:13px;height:13px}
@media (max-width:560px){
  .cards3:has(> .card.hc){gap:14px}
  .cards3 .card.hc{display:grid;grid-template-columns:120px minmax(0,1fr);column-gap:16px;align-items:center;justify-items:start;
    text-align:left;padding:14px 16px}
  .cards3 .card.hc > .fx-mono{grid-column:2;grid-row:1;margin:0 0 2px}
  .cards3 .card.hc > .hc-av{grid-column:1;grid-row:1 / span 4}
  .cards3 .card.hc > .hc-nm{grid-column:2;grid-row:2;margin:6px 0 0}
  .cards3 .card.hc > .hc-l2{grid-column:2;grid-row:3;justify-content:flex-start;margin:6px 0 0}
  .cards3 .card.hc > .hc-btnrow{grid-column:2;grid-row:4;margin:10px 0 0}
  .cards3 .card.hc > .hc-extra{grid-column:1 / -1;grid-row:5;justify-content:flex-start;margin:12px 0 0;padding-top:10px;
    border-top:1px solid var(--line);width:100%}
}
/* b690: SHORTER CARDS, RETURN IN THE TITLE (Ahmed 2026-10-29, bug-mvu9ygm4-9fbri, Fold 829x612: "unnecessary extra line... I don't
   want the vertical cards to get any longer, in fact I want them to get a little bit shorter"). A return leg reads
   "YOUR PASSENGER · RETURN" in the one orange title chip (the RETURN word 800, the chip's own orange behind it), so it never
   takes a line under the button, and the gaps above and below the circle, name, status and button are trimmed. The circle
   stays 120, the status row stays 56 (the b674 plate), the buttons stay 44. tools/t394 measures it. */
.cards3 .card.hc [data-hcleg]{display:inline;background:#FF3B00;color:#FFFFFF;font-weight:800;font-size:inherit;letter-spacing:inherit;padding:0;margin:0}
.cards3 .card.hc [data-hcleg]::before{content:"\00A0\00B7\00A0";font-weight:700}
.cards3 .card.hc [data-hcleg][hidden]{display:none}
.cards3 .card.hc > [data-hcttl]{white-space:nowrap}
.cards3 .card.hc{padding:12px 16px}
.cards3 .card.hc > .fx-mono{margin:0 0 8px}
.cards3 .card.hc .hc-nm{margin:8px 0 0}
.cards3 .card.hc .hc-l2{margin:4px 0 0}
.cards3 .card.hc .hc-btnrow{margin:10px 0 0}
@media (max-width:560px){
  .cards3 .card.hc{padding:12px 14px}
  .cards3 .card.hc > .fx-mono{margin:0 0 2px}
  .cards3 .card.hc > .hc-nm{margin:4px 0 0}
  .cards3 .card.hc > .hc-l2{margin:4px 0 0}
  .cards3 .card.hc > .hc-btnrow{margin:8px 0 0}
}
/* a narrow phone (344, the Fold's cover screen): YOUR PASSENGER · RETURN is wider than the column beside the circle, so on every
   card the title runs across the top, the circle and the three rows under it, the cards still one height */
@media (max-width:380px){
  .cards3 .card.hc > .fx-mono{grid-column:1 / -1;grid-row:1;margin:0 0 8px}
  .cards3 .card.hc > .hc-av{grid-row:2 / span 3}
  .cards3 .card.hc > .hc-nm{grid-row:2;margin:0}
}
/* b692: THE PILL IS THE SWITCH (Ahmed 2026-10-29, approved HomeFold mock B: "when the pill is online it looks correct, but when it's
   offline it should be my branded orange color"). The driver card's status pill is a 44px switch: ONLINE green with the knob left,
   OFFLINE solid Forge Orange with the knob right, both white words at 19px 800 (large text, so white on --good 3.5:1 and on --orange
   3.6:1 pass). The first tap while online arms it, TAP AGAIN TO GO OFFLINE on --red-ink (6.1:1) for 3 seconds. The full-width
   GO ONLINE / GO OFFLINE row left Home. tools/t396 measures it. */
.cards3 .card.hc .hc-l2 [data-hctog]{display:inline-flex;align-items:center;justify-content:flex-start;gap:8px;height:44px;min-width:128px;max-width:100%;
  margin:0;padding:0 16px 0 6px;box-sizing:border-box;border:0;border-radius:var(--r-pill);font-family:var(--body);font-weight:800;font-size:19px;
  letter-spacing:.02em;line-height:1;white-space:nowrap;cursor:pointer;background:var(--good);color:var(--card);-webkit-tap-highlight-color:transparent}
.cards3 .card.hc .hc-l2 [data-hctog] > [data-hcknob]{flex:0 0 auto;width:32px;height:32px;border-radius:50%;background:var(--card);box-shadow:0 1px 3px rgba(10,10,10,.25)}
.cards3 .card.hc .hc-l2 [data-hctog="off"]{flex-direction:row-reverse;padding:0 6px 0 16px;background:var(--orange)}
.cards3 .card.hc .hc-l2 [data-hctog="arm"]{justify-content:center;padding:0 14px;background:var(--red-ink);font-size:13px;letter-spacing:.04em;line-height:1.1;
  white-space:normal;text-align:center}
.cards3 .card.hc .hc-l2 [data-hctog="arm"] > [data-hcknob]{display:none}

/* b692: THE FOLD (Ahmed 2026-10-29, approved HomeFold mock C). The header's double chevron (data-hcfoldall) sits in the free space
   just before the passenger chip; each card folds from its own title chip (a chevron after the words, the tap area grown to 44).
   A folded card is a slim bar: 32px circle, the name, its key status, its own 44px chevron. Folded bars sit together at the top,
   each open card under them in order, the tiles right after. hcFoldPaint sets the attributes. */
.frame[data-role="driver"][data-screen="home"] > .hd > [data-hchd]{grid-column:3;justify-self:end;display:flex;align-items:center;gap:var(--sp-2);
  min-width:0;max-width:100%}
[data-hcfoldall],.cards3 .card:is(.hc,[data-hm="lastride"]) > [data-hcchev]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 44px;width:44px;height:44px;margin:0;padding:0;
  box-sizing:border-box;border:1.5px solid var(--line);border-radius:50%;background:var(--card);color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent}
[data-hcfoldall] svg,.cards3 .card:is(.hc,[data-hm="lastride"]) > [data-hcchev] svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}
.cards3 .card:is(.hc,[data-hm="lastride"]) > [data-hcchev]{display:none;border-color:transparent;background:transparent}
/* b713 (Ahmed 2026-11-01, "I have it closed right now. And it should be up"): a closed card's arrow points up, an open card's points down, every folding card, so one row never disagrees */
.cards3 .card:is(.hc,[data-hm="lastride"]) > [data-hcchev] svg{transform:rotate(180deg)}
.cards3 .card:is(.hc,[data-hm="lastride"]) > .fx-mono[data-hcfoldby]{position:relative;cursor:pointer;-webkit-tap-highlight-color:transparent}
.cards3 .card:is(.hc,[data-hm="lastride"]) > .fx-mono[data-hcfoldby]::before{content:"";position:absolute;left:0;right:0;top:-18px;bottom:-8px}   /* 20 + 26 = 46 tall, never over the circle under it */
.cards3 .card:is(.hc,[data-hm="lastride"]) > .fx-mono[data-hcfoldby]::after{content:"";display:inline-block;width:6px;height:6px;margin:0 2px 0 8px;border:solid currentColor;
  border-width:2px 2px 0 0;transform:translateY(-1px) rotate(135deg)}

/* a folded card, one line */
.cards3 .card.hc[data-hcfold]{display:flex!important;flex-direction:row;align-items:center;justify-content:flex-start;gap:10px;padding:6px 4px 6px 10px!important;
  min-height:56px;height:auto;text-align:left}
.cards3 .card.hc[data-hcfold] > .fx-mono,
.cards3 .card.hc[data-hcfold] > .hc-btnrow,
.cards3 .card.hc[data-hcfold] > .hc-extra,
.cards3 .card.hc[data-hcfold] .hc-cam,
.cards3 .card.hc[data-hcfold] [data-act="home-paxphoto"],
.cards3 .card.hc[data-hcfold] [data-pres="pax"]{display:none!important}
.cards3 .card.hc[data-hcfold] > .hc-av{width:32px;height:32px;flex:0 0 32px;margin:0;order:0}
.cards3 .card.hc[data-hcfold] > .hc-av > .avatar-lg{width:32px;height:32px;font-size:12px;box-shadow:none}
.cards3 .card.hc[data-hcfold] .fx-carav .fx-carsvg{width:24px;height:10px}
.cards3 .card.hc[data-hcfold] > .hc-nm{flex:1 1 auto;min-width:0;margin:0!important;height:auto;line-height:1.2;font-size:17px;order:1}
.cards3 .card.hc[data-hcfold] > .hc-l2{flex:0 0 auto;height:auto;margin:0!important;order:2;gap:8px}
.cards3 .card.hc[data-hcfold] .hc-platebox{aspect-ratio:auto;width:auto;height:auto}
.cards3 .card.hc[data-hcfold] .hc-platebox > .hc-plate{height:32px!important;width:auto!important;min-width:0!important;aspect-ratio:auto!important;padding:0 10px!important;font-size:15px!important;overflow:visible}
.cards3 .card.hc[data-hcfold] .hc-plateimg{display:none!important}
.cards3 .card.hc[data-hcfold] .hc-platebox[data-pfit="cover"] > [data-veh="plate"]{visibility:visible}
.cards3 .card.hc[data-hcfold] .hc-l2 [data-hctog]{min-width:0;padding:0 12px 0 6px;gap:6px}
.cards3 .card.hc[data-hcfold] .hc-l2 [data-hctog="off"]{padding:0 6px 0 12px}
.cards3 .card.hc[data-hcfold] .hc-l2 [data-hctog="arm"]{padding:0 10px;max-width:150px}
.cards3 .card.hc[data-hcfold] .hc-l2 [data-hctog] > [data-hcknob]{width:28px;height:28px}
/* a return leg keeps its RETURN chip on the folded passenger bar: the title chip shows with only the RETURN word in it */
.cards3 .card.hc[data-hcfold] > [data-hcttl]:has(> [data-hcleg]:not([hidden])){display:inline-flex!important;align-items:center;order:2;margin:0;font-size:0;
  padding:4px 8px;flex:0 0 auto}
.cards3 .card.hc[data-hcfold] > [data-hcttl] > [data-hcleg]{font-size:12px;line-height:1}
.cards3 .card.hc[data-hcfold] > [data-hcttl] > [data-hcleg]::before,.cards3 .card.hc[data-hcfold] > [data-hcttl]::before,
.cards3 .card.hc[data-hcfold] > [data-hcttl]::after{content:none}
.cards3 .card.hc[data-hcfold] > [data-hcchev]{display:inline-flex;order:3}
/* b694 (bug-mvvhjric-we3eh): the fourth card folds too. RIDE FINISHED (or PAYS LATER) as a slim bar: the money, the rider, its button,
   the chevron. Wider than a phone it takes its own line under the other three, so their bars never stretch to a tall neighbour. */
/* b717 (bug-mvzh7abx-33vnt, Ahmed 2026-11-02: "the Roger one is supposed to go on top... next to here up here"): closed, it is a card in the top row like
   the hand off one: the money and a RECEIPT pill over the rider's whole name, the arrow, in the 58px of the other bars. The whole card is the RECEIPT
   door (the card carries the same act), so the pill is a label of the 58px target, and the name gets the card's width. */
.cards3 > .card[data-hm="lastride"][data-hcfold]:not([hidden]){display:grid!important;grid-template-columns:auto minmax(0,1fr) 44px;grid-template-rows:auto auto;
  align-items:center;justify-items:start;column-gap:8px;row-gap:2px;padding:4px 0 4px 10px!important;min-height:58px;height:auto;text-align:left}
.cards3 > .card[data-hm="lastride"][data-hcfold] > :is(.fx-mono,.fx-done-sub){display:none!important}
.cards3 > .card[data-hm="lastride"][data-hcfold] > .fx-done-big{grid-column:1;grid-row:1;margin:0;font-size:19px;line-height:1.1}
.cards3 > .card[data-hm="lastride"][data-hcfold] > .nm{grid-column:1 / span 2;grid-row:2;min-width:0;max-width:100%;margin:0;font-size:15px;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cards3 > .card[data-hm="lastride"][data-hcfold] > .fx-done-btns{grid-column:2;grid-row:1;width:auto;max-width:100%;margin:0;padding:0}
.cards3 > .card[data-hm="lastride"][data-hcfold] > .fx-done-btns .aff{height:24px;min-height:0;padding:0 8px;font-size:11px;letter-spacing:.04em}
.cards3 > .card[data-hm="lastride"][data-hcfold] > [data-hcchev]{display:inline-flex;grid-column:3;grid-row:1 / span 2;width:44px;flex:none;justify-self:end}
/* folded bars on top, each open card under them in its own order */
.cards3[data-hcfolds="some"] > .card.hc[data-hcfold]{order:0}
.cards3[data-hcfolds="some"] > .card:not([data-hcfold]){order:1}
/* wider than a phone the cards sit side by side: folded bars share the top line, an open card under them takes the full width in
   the phone's row layout (circle left, rows right); all three folded, his name is in the header chip and the plate is the car's
   key fact, so those two bars drop the name and the passenger bar keeps the passenger's name whole */
@media (min-width:561px){
  .cards3[data-hcfolds="some"],.cards3[data-hcfolds="all"]{flex-wrap:wrap;align-items:stretch}
  .cards3[data-hcfolds] > .card.hc[data-hcfold]{flex:1 1 0;min-width:0}
  .cards3[data-hcfolds] > .card[data-hm="lastride"][data-hcfold]{flex:1 1 168px;min-width:0;max-width:calc(50% - 6px)}   /* b717: in the row, never a row of its own */
  .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:nth-child(1),:nth-child(2)){flex:0 0 auto}
  .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:nth-child(1),:nth-child(2)) > .hc-nm{display:none}
  .cards3[data-hcfolds="some"] > .card:not([data-hcfold]){flex:1 1 100%}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]){display:grid;grid-template-columns:120px minmax(0,1fr);column-gap:16px;
    align-items:center;justify-items:start;text-align:left;padding:12px 16px}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]) > .fx-mono{grid-column:2;grid-row:1;margin:0 0 2px}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]) > .hc-av{grid-column:1;grid-row:1 / span 4}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]) > .hc-nm{grid-column:2;grid-row:2;margin:4px 0 0}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]) > .hc-l2{grid-column:2;grid-row:3;justify-content:flex-start;margin:4px 0 0}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]) > .hc-btnrow{grid-column:2;grid-row:4;margin:8px 0 0;max-width:320px}
  .cards3[data-hcfolds="some"] > .card.hc:not([data-hcfold]) > .hc-extra{grid-column:1 / -1;grid-row:5;justify-content:flex-start}
}

/* the SHARE MY RIDE sheet, the passenger link sheet's shape */
.sheet.fx-hs [data-hs="ride"]{margin:0 0 4px;color:var(--muted);font-size:var(--t-small)}
.sheet.fx-hs .hs-row{width:100%;margin:0 0 6px}
.sheet.fx-hs .hs-row .fx-in{display:block;width:100%;box-sizing:border-box;height:48px;border:1.5px solid var(--line);border-radius:10px;padding:0 14px;
  font:500 16px/1.2 var(--body);color:var(--ink);background:#fff}
.sheet.fx-hs .hs-row .fx-in:focus{outline:none;border-color:var(--ink)}
.sheet.fx-hs .fx-btns .fx-save{width:100%}
.sheet.fx-hs .fx-save[disabled]{opacity:.45;cursor:default}
/* b678: the EDIT / REPLACE / REMOVE PHOTO sheet on Home (peOpen), the share sheet's shape, found by data-pe, no class of its own */
.sheet[data-pe] > .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.sheet[data-pe] .pl-h{margin:var(--sp-1) 0 10px;font-size:var(--t-card);font-family:'Space Grotesk',sans-serif;font-weight:600}
.sheet[data-pe] .note{margin:0 0 4px}
.sheet[data-pe] .fx-btns{display:flex;flex-direction:column;gap:10px;margin-top:var(--sp-3)}
.sheet[data-pe] .fx-btns[hidden]{display:none}
.sheet[data-pe] .fx-btns > button{width:100%;margin:0;min-height:var(--tap-min)}
.fx-entry .fx-riderow{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.fx-entry .fx-riderow .nm{font-family:var(--body);font-size:var(--t-card);font-weight:600}
.fx-entry .fx-riderow .nm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.05rem}
.fx-entry .btnrow{display:flex;gap:10px;margin-top:var(--sp-3)}
.fx-entry .btnrow .cta{min-height:48px;font-size:var(--t-body);flex:1 1 0}
.fx-entry .btnrow .cta:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
.fx-entry .fx-swchip{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.06em;background:var(--ink);color:#fff;border-radius:8px;padding:6px 11px;cursor:pointer}
.fx-entry .fx-swalt{font-size:var(--fs-label);color:var(--muted)}
.fx-entry .fx-map-pill{position:absolute;top:14px;left:50%;transform:translateX(-50%)}
.fx-entry .fx-mp1{top:34%;left:15%}
.fx-entry .fx-mp2{top:57%;right:17%}
.fx-entry .fx-car{top:45%;left:50%;transform:translate(-50%,-50%)}
.fx-entry .fx-car svg{width:20px;height:20px;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linecap:round}
.fx-entry .fx-search{top:14px;right:12px}
.fx-entry .fx-shield{bottom:14px;left:12px}
.fx-entry .fx-go-off,.fx-pax .fx-go-off{background:var(--orange);margin-top:var(--sp-1)}
/* b563: GO ONLINE AND GO OFFLINE NEVER HIDE UNDER THE FOOTER (UI audit #4, 2026-10-23). At 390x844 the three Home cards
   pushed the one main action to 758, 8px under the footer top at 766, so it needed a scroll. It sticks to the bottom
   of Home's scroll area now: where it fits it sits where it always sat, where it does not it waits just above the
   footer. No card changes size. */
.frame[data-role="driver"][data-screen="home"] > .scr > .cta:is([data-act="go-online"],[data-act="go-offline"]){position:sticky;bottom:0;z-index:3;flex:0 0 auto}

/* fx-ride: the Ride screen */
.fx-ride .map{flex:1 1 210px;min-height:210px}
.fx-ride .map .car{left:150px;top:92px}
.fx-ride .map .mpill{left:194px;top:100px}
.fx-ride .sheet h4{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.fx-ride .sheet h4 .badge{font-family:'Space Grotesk',sans-serif;letter-spacing:0}
/* b492: 44px TAP HEIGHT (checklist rule). 11px padding rendered NAVIGATE 42, GOOGLE MAPS 40, EDIT 38 at 412 wide. The
   label centres in the taller box; gap matches .aff.gmaps so the YPD disc and the G sit the same way beside their words. */
.fx-ride .row .aff{padding:11px 14px;box-sizing:border-box;
  display:inline-flex;align-items:center;justify-content:center;gap:7px}
/* b492: TRIP INFO, a door on the sheet itself. The rail's INFO disc sits under the open sheet and the stops row only
   paints with stops, so a ride without stops had no door while the sheet was up. Ink chip, lime label (lime on dark,
   the rulebook), 44px tall, at the end of the title line. NOT .ti-pill: tiPlace docks that class in the rail (b484). */
.fx-ride .sheet h4 .rschip{margin-left:auto;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;padding:0 var(--sp-2);cursor:pointer;user-select:none}


.fx-ride .row .aff + .aff{margin-left:6px}
.fx-ride .fx-prow{min-height:52px;padding:var(--sp-2) 13px;margin-bottom:7px}
.fx-ride .fx-prow .tx b{font-size:var(--t-card);font-weight:600}
.fx-ride .fx-prow .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.88rem}
.fx-ride .fx-k{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:2px}
.fx-ride .fx-fact{border:1px dashed #C0BCB3;background:var(--paper)}
.fx-ride .fx-chev{width:18px !important;height:18px !important;stroke:var(--muted) !important}
.fx-ride .fx-btnrow{display:flex;gap:10px;margin-top:var(--sp-1);flex:0 0 auto}
.fx-ride .fx-btnrow .cta{flex:1 1 0;min-width:0}
/* b369: .cta sets display:block, which beats the browser's own [hidden]; the row's hidden buttons (the spent
   five minute notice, the retired Message button) must actually leave the row */
.fx-ride .fx-btnrow > .cta[hidden]{display:none!important}
/* b563: THE RIDE BUTTON KEEPS ITS WIDTH WITH NO SIGNAL (UI audit #1 and #2, 2026-10-23). The No signal line is a flex
   item in the same row, so at 412 and 390 it took 321 to 333 of 371px and squeezed I HAVE ARRIVED, START THE RIDE and
   COMPLETE THE RIDE to 0 to 2px. The row wraps now and the line takes its own full width line under the buttons. */
.fx-ride .fx-btnrow{flex-wrap:wrap}
.fx-ride .fx-btnrow > .setstat{flex:1 0 100%;order:2;margin:2px 0 0;text-align:center;font-size:var(--t-small);font-weight:700;color:var(--muted)}
.fx-ride .fx-btnrow > .setstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.85rem;font-weight:700}
.fx-ride .fx-btnrow > .setstat[hidden]{display:none!important}
/* b288: THE RIDE SHEET BY PHASE (Ahmed, pick 7-1). The sheet is a flex column, so the ORDER of its
   children is a style, not a DOM move: the phase button rides at the top under the grab bar and
   stays there while the sheet scrolls (sticky, offset by the bar's measured height, --shbar-h is
   written by phaseFold), the title follows it, and the rows the phase needs come next. The rest
   keeps its markup order below. The fold (how far the sheet opens) is an inline max-height,
   measured in app.html, never typed here. */
.frame > .sheet > .shbar{order:-40}
.fx-ride[data-role="driver"] > .sheet > .fx-btnrow{order:-30;position:sticky;top:var(--shbar-h,19px);z-index:3;
  background:var(--card);margin:0 -14px;padding:var(--sp-1) 14px var(--sp-2);box-shadow:0 -2px 0 0 #fff}
/* b707: what scrolls to a control stops below the bar and the sticky row, --shrow-h is measured in app.html */
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow){scroll-padding-top:calc(var(--shbar-h,82px) + var(--shrow-h,68px) + 6px)}
.fx-ride[data-role="driver"] > .sheet > h4{order:-29}
/* b380: THE FLIGHT LINE, RIGHT UNDER ON MY WAY (Ahmed 2026-09-25, bug-muhj441l, waiting at ONT for
   WN 853: "the most important thing for me is right underneath ON MY WAY... arrives 4:24 PM, 54
   minutes late, was 3:30 PM, Terminal 4, that needs to be red"). A direct child of the sheet, in the
   DOM straight after the button row and at the same order value, so it sits under the button on
   every phase and folds with it. Painted by flLinePaint() from the SERVER's stored verdict, never
   from anything decided here. Red is the feed saying late, green is the feed saying on time or
   landed, ink is a schedule not yet confirmed. 44px minimum, it opens the flight panel below. */
.fx-ride[data-role="driver"] > .sheet > .flline{order:-30;flex:0 0 auto;display:flex;align-items:center;gap:10px;min-height:44px;
  margin:0 0 var(--sp-2);padding:6px 10px;border:1.5px solid var(--line);border-radius:var(--r-input);background:var(--paper);cursor:pointer}
.fx-ride[data-role="driver"] > .sheet > .flline[hidden]{display:none!important}
.flline svg{width:22px;height:22px;flex:0 0 auto;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.flline .fl-tx{flex:1 1 auto;min-width:0;line-height:1.25}
.flline .fl-num{display:block;font-size:var(--t-data);font-weight:700;color:var(--ink);font-family:var(--mono)}
.flline .fl-num:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;font-weight:700}
.flline .fl-arr{display:inline;font-size:inherit;font-weight:700;color:var(--ink)}
/* b532 (bug-mvgx0jyz-lkd9i, Ahmed 2026-10-20 on Mobeen's parents to LAX, Qatar Airways QR740: "the formatting is off...
   it looks a little weird"). It painted "Qatar Airways QR 740" and "Departure time not on the feed yet" each across two
   or three lines beside a squeezed right column, "Terminal TOM BRADLEY". Now two lines, each ONE line: the flight on
   line 1, the time, a dot and the place on line 2, the place never broken in half. flFit in app.html steps the type
   down and then the wording shorter until each fits; only a line that fits no way at all wraps, at the dot. */
.flline .fl-num{white-space:nowrap;overflow:hidden}
.flline .fl-l2{display:block;font-size:var(--t-small);font-weight:700;color:var(--ink);white-space:nowrap;overflow:hidden}
.flline .fl-l2:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;font-weight:700}
.flline .fl-where{white-space:nowrap}
.flline .fl-where::before{content:"\00b7";padding:0 .3em;color:var(--muted)}
.fx-ride[data-role="driver"] > .sheet > .flline{gap:var(--sp-2)}
.flline .fl-l2[data-noplace] .fl-where{display:none}
.flline [data-wrap="1"]{white-space:normal;overflow:visible}
.flline .fl-l2[data-wrap="1"] .fl-where{display:block}
.flline .fl-l2[data-wrap="1"] .fl-where::before{content:none}
.flline .fl-arr.late{color:var(--red)}
.flline .fl-arr.ok{color:var(--good)}
.flline .fl-term{font-weight:700;color:var(--ink)}
.flline[data-checking="1"] .fl-arr{opacity:.55}
.flline[data-checking="1"] .fl-arr::after{content:" checking\2026";font-weight:400;color:var(--muted)}   /* b465: was a broken byte that read "checking6" */
.flline[data-tone="late"]{border-color:var(--red);background:#FFF6F4}
/* b530 (bug-mv8eclhz-g0ziw, Ahmed 2026-10-14: "I need to know what terminal to go to"). The line's tap opens its card
   IN PLACE, straight under it at the same order. b532 moved the terminal from its own right column onto line 2. */
.fx-ride[data-role="driver"] > .sheet > .flmore{order:-30;flex:0 0 auto;display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2) var(--sp-3);
  margin:0 0 var(--sp-2);padding:10px var(--sp-3);border:1.5px solid var(--line);border-top:none;border-radius:0 0 var(--r-input) var(--r-input);background:var(--card)}
.fx-ride[data-role="driver"] > .sheet > .flmore[hidden]{display:none!important}
.flmore > div{min-width:0}
.flmore .flm-k{display:block;margin-bottom:3px;font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase}   /* the b504/b510 orange chip through .fx-k */
.flmore b{display:block;font-size:var(--t-body);font-weight:700;color:var(--ink);overflow-wrap:anywhere}
.flmore b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:800}
.fx-ride[data-role="driver"] > .sheet > .flline[data-open="1"]{border-radius:var(--r-input) var(--r-input) 0 0;margin-bottom:0}
/* b465: AIRPORT WAIT, straight under the flight line, at the same order so it folds with it (app-airwait.js paints it).
   One sentence, then one wrapping row of pills: the wait (-5, the chip, +5), REFRESH, GOOGLE, Late (-5, the chip, +5),
   and GO at the leave time. Every pill 44px, ink on white; the chips are ink with lime labels; GO is the head-out orange
   with white words, his own ask for the head-out pills. LITE (no flight time yet, or he is on his way): REFRESH and
   GOOGLE only. data-tone go: leave now, the frame turns orange. */
.fx-ride[data-role="driver"] > .sheet > .awline{order:-30;flex:0 0 auto;display:flex;flex-direction:column;gap:6px;
  margin:-2px 0 var(--sp-2);padding:var(--sp-2) 10px;border:1.5px solid var(--line);border-radius:var(--r-input);background:var(--card)}
.fx-ride[data-role="driver"] > .sheet > .awline[hidden]{display:none!important}
.awline .aw-tx{display:block;font-size:var(--t-body);font-weight:700;color:var(--ink);line-height:var(--lh-body)}
/* b604 (bug-mvpxf3ai-m0yca): the top row is the FROM GOOGLE chip and the one line beside it; the button row is REFRESH,
   GOOGLE and PASTE FROM GOOGLE sharing the width, 44 tall, on one row at 390 */
.awline .aw-top{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.awline .aw-top .aw-tx{flex:1 1 160px;min-width:0}
.awline .aw-btns{flex-wrap:nowrap}
.awline .aw-btns .aw-pill{flex:1 1 0;min-width:0;padding:0 6px;white-space:nowrap}
.awline .aw-btns .aw-pastebtn{flex:2.2 1 0;padding:0 4px}
.awline .aw-tx:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.88rem;font-weight:800;line-height:1.3}
.awline .aw-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.awline .aw-grp{display:inline-flex;align-items:center;gap:var(--sp-1);flex:0 0 auto}
.awline [hidden]{display:none!important}
.awline .aw-pill{flex:0 0 auto;min-width:44px;padding:0 10px;
  display:inline-flex;align-items:center;justify-content:center;cursor:pointer;line-height:1}
.awline .aw-pill.aw-sq{padding:0 6px}
.awline .aw-go{min-width:64px}
.awline .aw-chip{flex:0 0 auto;min-height:44px;padding:var(--sp-1) 9px;border-radius:var(--r-input);background:var(--ink);color:#fff;
  display:inline-flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.1}
.awline .aw-chip i{font-style:normal;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;color:var(--lime)}
.awline .aw-chip b{font-size:var(--t-small);font-weight:700;color:#fff;white-space:nowrap}
.awline .aw-chip b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;font-weight:800}
.awline[data-tone="go"]{border-color:#FF3B00;background:#FFF6F2}
/* b468: LANDED (his tap), UNDO LANDED lit orange for 2 min; the terminal chip is a button; TEXT <NAME> green like COPY
   MESSAGE; the terminal box (every airport but LAX) is the chip's shape with a field in it */
.awline .aw-land[data-on="1"]{border-color:#FF3B00;color:#FF3B00}
.awline button.aw-chip{border:none;cursor:pointer;font-family:inherit;min-width:56px}

.awline .aw-termbox{flex:0 0 auto;min-height:44px;padding:3px var(--sp-2);border-radius:var(--r-input);background:var(--ink);display:inline-flex;
  flex-direction:column;justify-content:center;gap:2px;cursor:text}
.awline .aw-termbox i{font-style:normal;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;color:var(--lime)}
.awline .aw-termbox input{width:96px;min-height:24px;box-sizing:border-box;border:none;border-radius:6px;padding:0 6px;
  font:700 var(--t-small) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card)}
.awline .aw-termbox input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .82rem 'Space Grotesk',sans-serif}
/* b601: THE PASTE BOX, shown in place only when the phone refuses the clipboard read: one line, SAVE beside it */
.awline .aw-paste{display:flex;align-items:center;gap:6px;width:100%}
.awline .aw-paste input{flex:1 1 auto;min-width:0;min-height:44px;box-sizing:border-box;border:1.5px solid var(--ink);border-radius:var(--r-input);padding:0 10px;
  font:700 var(--t-small) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card)}
.fx-set .aw-pilllab{display:inline-flex;align-items:center;min-height:32px;margin:14px 0 var(--sp-2);padding:0 var(--sp-4);border-radius:var(--r-pill);
  background:#FF3B00;color:#fff;font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;font-size:var(--t-body);
  letter-spacing:.01em;line-height:1}
.fx-set .aw-pilllab:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:800;font-size:.95rem;line-height:1}
.fx-set .aw-steps > .aw-pilllab:first-child{margin-top:6px}
.fx-set .aw-steps .setnote{margin-top:var(--sp-1)}
.fx-ride[data-role="driver"] > .sheet[data-phase="enroute"] > [data-rrow="pickup"]{order:-28}
.fx-ride[data-role="driver"] > .sheet[data-phase="enroute"] > .paxsec{order:-27}
.fx-ride[data-role="driver"] > .sheet[data-phase="arrived"] > .paxsec{order:-28}
.fx-ride[data-role="driver"] > .sheet[data-phase="arrived"] > [data-rrow="pickup"]{order:-27}
.fx-ride[data-role="driver"] > .sheet[data-phase="trip"] > [data-rrow="dropoff"]{order:-28}
.fx-ride .fx-hint{margin:-3px var(--sp-1) 9px;text-align:center}

/* The Ride passenger section: ONE row that expands IN PLACE, never a popup (rule zero).
   data-open flips between the collapsed row and the expanded detail. The default state is
   Ahmed's pick at the first confirm-only review, see the data-default comment in app.html. */
.fx-ride .paxsec .pax-x{display:none}
.fx-ride .paxsec[data-open="1"] .pax-x{display:block}
.fx-ride .paxsec[data-open="1"] .fx-hint{display:none}
.fx-ride .paxsec[data-open="1"] .fx-chev{transform:rotate(90deg)}
.fx-ride .paxsec .sw-open{display:inline}
.fx-ride .paxsec .sw-close{display:none}
.fx-ride .paxsec[data-open="1"] .sw-open{display:none}
.fx-ride .paxsec[data-open="1"] .sw-close{display:inline}
.fx-ride .paxsec .seclab{margin-bottom:var(--sp-2)}

/* fx-comms: Inbox, Chat, Menu */
.fx-comms .fx-dot{width:10px;height:10px;border-radius:50%;background:var(--orange);flex:0 0 auto}
.fx-comms .cav{width:40px;height:40px;border-radius:50%;background:var(--placeholder);color:#fff;
  font-weight:700;font-size:var(--t-small);display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.fx-comms .cav:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:.9rem}
.fx-comms .aff.warn{background:var(--red)}
.fx-comms .fx-dim{opacity:.42;padding:14px 14px 0;display:flex;flex-direction:column;gap:var(--sp-3);pointer-events:none}
.fx-comms .fx-clear{margin-top:var(--sp-1);flex:0 0 auto}
.fx-comms .hd-logo{font-size:var(--t-small)}
.fx-comms .hd-logo:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}

/* Calendar sync REVIEW, expand-in-place inside Settings, Calendar sync (b695, it was a Menu row from b23).
   Same visual family as the Settings profile row (fx-rowtop + chevron + bordered open state). While it is
   open (data-rev on the row) the row shows the review and nothing else.
   .crow = one pending change, also the error card on the fx-comms lists; old value RED, new value GREEN
   (red is bad/old, green is good/new, standing law). Status lines centered, 0.95rem. */
.fx-comms .fx-rowtop{display:flex;align-items:center;gap:var(--sp-3);flex:1 1 auto;min-width:0;cursor:pointer}
.fx-comms .fx-rowtop svg{width:24px;height:24px;flex:0 0 auto}
.fx-comms .fx-chev{width:18px !important;height:18px !important;stroke:var(--muted) !important;flex:0 0 auto}
.fx-comms .row[data-open="1"]{display:block;border:1.5px solid var(--ink)}
.fx-comms .row[data-open="1"] > .fx-chev{display:none}
.fx-set .calrev{display:none}
.fx-set .row[data-rev="1"] .fx-editor > :not(.calrev){display:none}
.fx-set .row[data-rev="1"] .calrev{display:block}
.fx-set .calrev .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 10px}
:is(.fx-comms,.fx-set) .crow{display:flex;flex-wrap:wrap;align-items:center;gap:10px;border:1px solid var(--line);
  border-radius:var(--r-input);padding:10px var(--sp-3);margin-bottom:var(--sp-2);background:var(--paper)}
:is(.fx-comms,.fx-set) .crow .tx{flex:1 1 auto;min-width:0}
:is(.fx-comms,.fx-set) .crow .tx b{display:block;font-size:var(--t-small);margin-bottom:2px}
:is(.fx-comms,.fx-set) .crow .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem}
:is(.fx-comms,.fx-set) .crow .tx span{display:block;font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);word-break:break-word}
:is(.fx-comms,.fx-set) .crow .tx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;line-height:1.4}
/* CHANGE CARD labeled lines (b26): one field per line, small mono label + value. Selectors run
   through .tx because the generic `.crow .tx span` rule above is (0,3,1) and a bare
   `.crow .cfk` (0,3,0) silently LOSES to it, the exact specificity trap that muted b23's
   red/green (fixed below, same pass). */
:is(.fx-comms,.fx-set) .crow .tx .cfl{display:flex;align-items:baseline;gap:var(--sp-2);font-size:var(--t-small);line-height:var(--lh-small);
  margin-top:3px;color:var(--ink)}
:is(.fx-comms,.fx-set) .crow .tx .cfl:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;line-height:1.4}
:is(.fx-comms,.fx-set) .crow .tx .cfk{flex:0 0 58px;display:inline;font-family:'JetBrains Mono',monospace;
  font-size:var(--fs-label);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
:is(.fx-comms,.fx-set) .crow .tx .cfv{flex:1 1 auto;display:inline;min-width:0;word-break:break-word;color:var(--ink)}
:is(.fx-comms,.fx-set) .crow .tx .cfv b{display:inline;font-size:var(--t-small);margin:0}
:is(.fx-comms,.fx-set) .crow .tx .cfv b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
/* Old RED -> new GREEN. Through .tx (0,4,0) so they OUTRANK the generic span rule; the b23 bare
   .crow .cvold form lost that fight and the diff colors never actually rendered (found 2026-08-14). */
:is(.fx-comms,.fx-set) .crow .tx .cvold{display:inline;color:var(--red);font-weight:700}
:is(.fx-comms,.fx-set) .crow .tx .cvnew{display:inline;color:var(--good);font-weight:700}
:is(.fx-comms,.fx-set) .crow .aff{cursor:pointer;padding:9px 13px;font-size:var(--fs-label)}
:is(.fx-comms,.fx-set) .crow .aff.ok{background:var(--good);color:#fff}
/* ONE ACTION ROW FOR EVERY CARD TYPE (b28, Ahmed 2026-08-14, live: the New ride card put APPLY
   and SKIP side by side while the Update card threw APPLY out to the right edge and dropped SKIP
   onto its own line below). The buttons used to be loose flex children of .crow, so where they
   landed depended on how wide that card's text happened to be, which is a per-instance accident,
   not a layout. Every card now wraps its buttons in ONE .cacts row that is flex:1 1 100%, so it
   ALWAYS breaks to its own full-width line UNDER the fields with the buttons side by side and
   equal width, identically for update / new ride / error cards and any card type added later
   (class-level fix, not a patch on the update card). Buttons carry the 48px tap minimum here,
   which the old 9px-padding pills never met. */
:is(.fx-comms,.fx-set) .crow .cacts{flex:1 1 100%;display:flex;align-items:stretch;gap:10px;margin-top:10px}
/* the transparent border is load-bearing: with flex-basis 0 and border-box sizing, a border on
   ONE button makes that button wider than its neighbour, so both carry the same box and only the
   colour differs (measured, b28) */
:is(.fx-comms,.fx-set) .crow .cacts .aff{flex:1 1 0;min-width:0;min-height:var(--tap-min);display:flex;
  align-items:center;justify-content:center;text-align:center;border:1.5px solid transparent}
/* SKIP must LOOK like a button. .aff.lite paints itself --paper, which is the card's own
   background, so on a card it read as a label with nothing to press (seen in pixels, b28). Same
   green-filled + white-outlined pair the panel's own Apply all / Close already use, so the two
   levels of the panel match by construction. */
:is(.fx-comms,.fx-set) .crow .cacts .aff.lite{background:var(--card);border-color:var(--line)}
:is(.fx-comms,.fx-set) .calstat{flex:1 1 100%;display:block;text-align:center;font-size:var(--t-body);font-weight:700;margin:6px 0 2px}
:is(.fx-comms,.fx-set) .calstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
:is(.fx-comms,.fx-set) .calstat[hidden]{display:none}
.fx-set .calrev .fx-btns{display:flex;gap:10px;margin-top:var(--sp-3)}
.fx-set .calrev .fx-save{flex:1 1 0;min-height:48px;border:none;border-radius:var(--r-input);background:var(--good);
  color:#fff;font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body);cursor:pointer}
.fx-set .calrev .fx-save:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}
/* Apply all hides at 0/1 pending (b26 dead-button law); own [hidden] guard (07-31 lesson: an
   explicit display on a component silently beats the UA rule) */
.fx-set .calrev .fx-save[hidden]{display:none!important}
.fx-set .calrev .fx-cancel{flex:1 1 0;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);
  background:var(--card);color:var(--ink);font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:var(--t-body);cursor:pointer}
.fx-set .calrev .fx-cancel:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}

/* MY RIDES, the list screen (b28, Ahmed 2026-08-14: the Menu row promises "Every upcoming
   booking" and used to open the single Ride screen, which is one ride, not a list). One scrollable
   list of every current + upcoming booking, one .row per booking so it inherits the shell's row
   component (icon, text block, affordance, 64px min height) and nothing new is invented. The
   screen is an fx-comms screen, so the .crow card + .cacts action row above are reused verbatim
   for its error door. */
/* b320: HOW LONG A REQUEST HAS BEEN WAITING. Same steel as the trip line, one notch quieter,
   because it is context for the row and never the row's headline. */
/* b328: AND IT IS RED (Ahmed, 2026-09-17, bug-mu5yx4e9): "I can see where it shows came in four
   hours ago and that is awesome, but it's hard for me to see, so that needs to be the color red so
   it stands out, because that's important, how long that's been sitting there." Not italic grey
   furniture: the age of an unanswered request is the thing that costs him the client. */
.fx-rides .rrow .rtrip.rage{color:var(--red);font-weight:700;font-style:normal}
.fx-rides .rlist{display:flex;flex-direction:column;flex:0 0 auto}
.fx-rides .rrow{cursor:pointer;align-items:flex-start}
.fx-rides .rrow > svg{margin-top:3px}
/* name + status badge share the bold line; the block rule on .row .tx b is (0,2,1), this is (0,3,1) */
.fx-rides .rrow .tx b{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
/* WHEN is the line he scans for, so it reads at full ink weight; the trip line stays muted.
   (0,3,0) beats the generic `.row .tx span` (0,2,1). */
.fx-rides .rrow .rwhen{color:var(--ink);font-weight:700;font-size:var(--t-small)}
.fx-rides .rrow .rwhen:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.8rem}
.fx-rides .rrow .rtrip{color:var(--muted);word-break:break-word}
.fx-rides .rrow .aff{align-self:center}
/* b699: BACKUP BOOKING, as the mock. NEED DRIVER is the DRIVES chip in the brand orange, the money on the right is black once
   the fare is not his, and HANDED OFF on Home is a card of the same My rides rows. */
.badge.cvleg[data-need],.frame[data-role] .badge.cvleg[data-need]{background:var(--orange)}
.row .aff[data-zero]{background:var(--ink);color:#fff;white-space:nowrap}
/* b705: a handed off ride is one more Home card (Ahmed 2026-11-01): the box melts away so each card is a child of .cards3, and .card.hc gives it
   the folded bar, its height and its arrow (b692). Only what those rules cannot know is here. */
[data-handed]{display:contents}
[data-handed][hidden]{display:none!important}
/* b713 (Ahmed 2026-11-01, "Next to Roger. Next to the other three, but it's on its own row. And it's just a waste of that row right now"): closed, it is a pill IN the top row. Two lines
   in the 56px of the other bars so it fits beside them from 344 up: the name and HAND OFF, then who drives. Its circle stays for the open card. */
.cards3 [data-handcard][data-hcfold]{cursor:pointer}
.cards3 [data-handcard].card.hc[data-hcfold]{display:grid!important;grid-template-columns:minmax(0,1fr) 36px;grid-template-rows:auto auto;align-items:center;justify-items:start;column-gap:2px;row-gap:3px;padding:5px 0 5px 10px!important;min-height:58px}
.cards3 [data-handcard][data-hcfold] > .hc-av{display:none}
.cards3 [data-handcard].card.hc[data-hcfold] > .hc-nm{grid-column:1;grid-row:1;display:flex;align-items:baseline;gap:6px;width:100%;font-size:16px}
.cards3 [data-handcard].card.hc[data-hcfold] > .hc-l2{grid-column:1;grid-row:2;justify-content:flex-start;max-width:100%}
.cards3 [data-handcard].card.hc[data-hcfold] > [data-hcchev]{grid-column:2;grid-row:1 / span 2;width:36px;flex:none;justify-self:end}
.cards3 [data-handcard] > .hc-nm{height:auto;line-height:1.2;min-width:0;max-width:100%}
.cards3 [data-handcard] [data-handnm]{display:block;flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cards3 [data-handcard] [data-handword]{display:none;flex:0 0 auto;font:700 10.5px/1.2 'JetBrains Mono',monospace;letter-spacing:.04em;color:var(--ink);white-space:nowrap}
.cards3 [data-handcard][data-hcfold] [data-handword]{display:block}
.cards3 [data-handcard].card.hc .hc-l2 .badge{font-size:11px;height:22px;line-height:22px;padding:0 7px;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
/* open, its arrow stays on the card, top right, pointing down: that is how he closes it */
.cards3 [data-handcard]:not([data-hcfold]){position:relative}
.cards3 .card[data-handcard]:not([data-hcfold]) > [data-hcchev]{display:inline-flex;position:absolute;top:4px;right:4px}
.cards3 .card[data-handcard]:not([data-hcfold]) > [data-hcchev] svg{transform:none}
.cards3 .card[data-handcard] > .fx-mono[data-hcfoldby]::after{content:none}
.cards3 [data-handcard] > .hc-extra{display:flex;flex-direction:column;align-items:center;gap:var(--sp-1);width:100%;margin:var(--sp-2) 0 0;text-align:center}
.cards3 [data-handcard] .rwhen{color:var(--ink);font-weight:700;font-size:var(--t-small)}
.cards3 [data-handcard] .rtrip{color:var(--muted);word-break:break-word}
.cards3 [data-handcard] .aff[data-zero]{background:var(--ink);color:#fff;white-space:nowrap}
/* folded bars on top with the others, an open one under them, the same order the three keep */
.cards3 > [data-handed] > .card:not([data-hcfold]){order:1}
.cards3[data-hcfolds="none"] > [data-handed] > .card[data-hcfold]{order:-1}
/* b713: closed it shares the row. The passenger bar gives up its circle for the name, the two bars take the room the driver and plate bars leave. An open one, or a closed one with all
   three cards open under it, keeps a line of its own, the three never squeeze. On a phone the bars stack, so there it pairs with the passenger bar. */
/* b717 (bug-mvzh7abx-33vnt, Ahmed 2026-11-02: "all five of these are supposed to end up up here... and then the receipt one too... if you need to make two
   rows then make two rows up there, but they're just wasting space right now"). The closed RIDE FINISHED card, each closed hand off and RECEIPTS TO SEND
   are all cards of the top row, the same 58px, and wrap to a second row of the same cards when the row is full. None of them is ever a row of its own:
   a card alone on the second row stops at half the width. The rules below find the three through :has, so b713's passenger squeeze holds for any of
   them, not only a hand off. */
.cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold] > .hc-av{display:none!important}
/* RECEIPTS TO SEND as a top row card: the label over the first trip, the count on the right, the whole card the button */
.cards3 > .mo-panel[data-rc="panel"]{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto auto;align-items:center;justify-items:start;
  column-gap:8px;row-gap:2px;width:auto;min-width:0;min-height:58px;margin:0;padding:5px 14px 5px 10px;border-width:1.5px;border-radius:16px;align-self:stretch}
.cards3 > .mo-panel[data-rc="panel"] > .mo-l{display:contents}
.cards3 > .mo-panel[data-rc="panel"] .mo-k{grid-column:1;grid-row:1;max-width:100%;font-size:11px;letter-spacing:.06em;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cards3 > .mo-panel[data-rc="panel"] .mo-amt{grid-column:2;grid-row:1 / span 2;font:700 22px/1.1 var(--body)}
.cards3 > .mo-panel[data-rc="panel"] > .mo-who{grid-column:1;grid-row:2;max-width:100%;font-size:14px;line-height:1.25}
.cards3 > .mo-panel[data-rc="panel"] > .mo-who > span ~ span{display:none}
.cards3 > .mo-panel[data-rc="panel"] > .mo-go{display:none}
.cards3 > .mo-panel[data-rc="panel"][hidden]{display:none!important}
@media (min-width:561px){
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))){flex-wrap:wrap}
  .cards3 > [data-handed] > .card{flex:1 1 100%;min-width:0}
  .cards3[data-hcfolds]:not([data-hcfolds="none"]) > [data-handed] > .card[data-hcfold]{flex:1 1 168px;max-width:calc(50% - 6px)}
  .cards3[data-hcfolds="none"] > [data-handed] > .card[data-hcfold],.cards3 > .mo-panel[data-rc="panel"]{flex:1 1 168px;max-width:calc(50% - 6px)}
  .cards3[data-hcfolds]:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold]{flex:1 1 168px;min-width:0}
  /* all three open: the closed extras keep a row on top together, an empty full width break under them keeps the three open cards on their own row */
  .cards3[data-hcfolds="none"] > .mo-panel[data-rc="panel"]{order:-2}
  .cards3[data-hcfolds="none"] > [data-handed] > .card[data-hcfold]{order:-2}
  .cards3[data-hcfolds="none"]:has(> :is([data-handed]:not([hidden]),[data-rc="panel"]:not([hidden])))::before{content:"";flex:0 0 100%;height:0;order:-1;margin-top:calc(-1 * var(--sp-3))}
}
@media (max-width:560px){
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))){flex-direction:row;flex-wrap:wrap}
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card,.cards3 > [data-handed] > .card{flex:1 1 100%;min-width:0}
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold],
  .cards3 > [data-handed] > .card[data-hcfold],.cards3:has(> .card[data-hm="lastride"][data-hcfold]:not([hidden])) > .card[data-hm="lastride"][data-hcfold],.cards3 > .mo-panel[data-rc="panel"]{flex:1 1 calc(50% - 8px);max-width:calc(50% - 6px)}
  .cards3[data-hcfolds="none"] > .mo-panel[data-rc="panel"]{order:-1}
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold]{padding:6px 0 6px 10px!important;gap:2px}
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold] > .hc-nm{white-space:normal;max-height:2.4em;font-size:16px}
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold] > [data-hcchev]{flex:0 0 36px;width:36px}
}
@media (max-width:400px){
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-handed]:not([hidden]),[data-rc="panel"]:not([hidden]))) > .card.tapcard.hc[data-hcfold]{flex:1 1 calc(40% - 7px)}
  .cards3 > [data-handed] > .card[data-hcfold]{flex:1 1 calc(56% - 7px);max-width:none}   /* NEEDS A DRIVER needs the room at 344 (t408) */
  .cards3:has(> :is(.card[data-hm="lastride"][data-hcfold]:not([hidden]),[data-rc="panel"]:not([hidden]))) > [data-handed] > .card[data-hcfold],
  .cards3:has(> .card[data-hm="lastride"][data-hcfold]:not([hidden])) > .card[data-hm="lastride"][data-hcfold],.cards3 > .mo-panel[data-rc="panel"]{flex:1 1 calc(50% - 7px)}
  .cards3 [data-handcard].card.hc[data-hcfold] > .hc-nm{font-size:15px;gap:4px}
  .cards3 [data-handcard][data-hcfold] [data-handword]{font-size:9.5px}
}
.cards3 [data-handcard] .note,.fx-rides .rlist > .note{margin:var(--sp-1) 2px 0}
.fx-rides .rlist > .cta{margin-top:var(--sp-2)}
/* Empty / loading state, never a blank panel (the dock-era rule). Centered, .95rem, same family
   as .calstat. Own [hidden] guard: an explicit display silently beats the UA rule (07-31). */
.fx-rides .rstat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;color:var(--muted);
  margin:var(--sp-4) 0 var(--sp-1)}
.fx-rides .rstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-rides .rsub{display:block;text-align:center;font-size:var(--t-small);color:var(--muted);margin:0 0 var(--sp-3)}
.fx-rides .rsub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.fx-rides .rstat[hidden],.fx-rides .rsub[hidden]{display:none!important}

/* fx-set: Settings hub */
.fx-set .seclab{margin:10px 2px var(--sp-2)}
.fx-set .row{cursor:pointer}
.fx-set .fx-chev{width:18px !important;height:18px !important;stroke:var(--muted) !important;flex:0 0 auto}
/* b45: A 48px FLOOR ON THE ROW HEADER. This is the DOOR to every Settings screen and it was
   34px at 520px and wider, which is under Ahmed's standing hard rule (never a tiny control as
   the only way to do something). Found by measuring the new vehicle screen at four widths, and
   fixed on the CLASS rather than on the one row that was measured, because every other Settings
   row is the same control with the same problem. min-height only ever grows a row. */
.fx-set .fx-rowtop{display:flex;align-items:center;gap:var(--sp-3);flex:1 1 auto;min-width:0;
  min-height:var(--tap-min);cursor:pointer}
.fx-set .fx-rowtop svg{width:24px;height:24px;flex:0 0 auto}
.fx-set .fx-rowtop .tx{flex:1 1 auto;min-width:0}
/* Edit-in-place: the profile row expands inside the sheet, rule zero, no popup ever */
.fx-set .row .fx-editor{display:none}
.fx-set .row[data-open="1"]{display:block;border:1.5px solid var(--ink);cursor:default}
.fx-set .row[data-open="1"] .fx-editor{display:block}
.fx-set .row[data-open="1"] > .fx-chev{display:none}
.fx-set .fx-editor{margin:var(--sp-3) 2px var(--sp-1);padding-top:var(--sp-3);border-top:1px solid var(--line)}
.fx-set .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.fx-set .fx-in{display:block;width:100%;min-height:48px;border:1.5px solid var(--ink);border-radius:var(--r-input);
  padding:0 14px;font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;
  font-size:var(--t-body);color:var(--ink);background:var(--card)}
.fx-set .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;font-size:1rem}
:is(.fx-set,.fx-pl) .fx-btns{display:flex;gap:10px;margin-top:var(--sp-3)}
:is(.fx-set,.fx-pl) .fx-save{flex:1 1 0;min-height:48px;border:none;border-radius:var(--r-input);background:var(--good);
  color:#fff;font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body);cursor:pointer}
:is(.fx-set,.fx-pl) .fx-save:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}
:is(.fx-set,.fx-pl) .fx-cancel{flex:1 1 0;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);
  background:var(--card);color:var(--ink);font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:var(--t-body);cursor:pointer}
:is(.fx-set,.fx-pl) .fx-cancel:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}
/* PROFILE AUTOSAVE receipts (laws, Ahmed 2026-08-14): every save paints its status DIRECTLY
   UNDER the control that caused it, centered, .95rem+, green good red bad (goodtx/warntx carry
   the colors). The red line is itself the retry door (data-act="prof-retry"). Own [hidden]
   guard (07-31 lesson: an explicit display would beat the UA rule). */
.profstat{display:block;font-size:var(--t-body);font-weight:700;text-align:center;margin:10px 2px 2px}
.profstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.profstat.warntx{cursor:pointer}
.profstat[hidden]{display:none!important}
/* On the landing the receipt sits between the tapped photo and the name line */
.fx-land .profstat{margin:var(--sp-1) 0 0}
.fx-set .row.fx-danger b{color:var(--red)}
.fx-set .row.fx-danger svg{stroke:var(--red)}
.fx-set .row.fx-fact{border:1.5px dashed var(--line);background:var(--paper);cursor:default}
.fx-set .fx-tog{flex:0 0 auto;width:48px;height:28px;border-radius:var(--r-ctl);background:var(--orange);
  position:relative;display:inline-block}
.fx-set .fx-tog i{position:absolute;top:3px;right:3px;width:22px;height:22px;border-radius:50%;background:var(--card);
  box-shadow:0 1px 3px rgba(10,10,10,.25)}

/* ================================================================================================
   b34, SETTINGS THAT DO SOMETHING. Every row in the hub either works or says it is coming, and
   both states are visible BEFORE the tap: a working row carries the chevron, a coming one carries
   a SOON chip. Own [hidden] guards throughout (the 2026-07-31 lesson: an explicit display silently
   beats the UA's [hidden]{display:none}).
   ================================================================================================ */
/* the SOON chip. .aff.lite already paints it, this only stops it reading as an action. */
.fx-set .aff.fx-soon{opacity:.85;letter-spacing:.08em}
/* b695: a Settings row that rides to the top stops under the sticky title bar, its name stays on screen (t399 A6, measured) */
.fx-set .row{scroll-margin-top:calc(var(--shbar-h,82px) + var(--sp-2))}
/* b695: TIMING, a row in Notifications, the 11 steppers sit under it and open in place. aria-expanded carries the state */
.fx-set [data-timing="box"]{display:none;margin:0 0 var(--sp-3)}
.fx-set [data-timing="row"][aria-expanded="true"]{border-color:var(--ink)}
.fx-set [data-timing="row"][aria-expanded="true"] + [data-timing="box"]{display:block}
.fx-set [data-timing="row"][aria-expanded="true"] .fx-chev{transform:rotate(90deg)}
.fx-set [data-timing="box"] > .fx-ml{margin:var(--sp-3) 0 var(--sp-2)}
.fx-set [data-timing="box"] > .fx-ml:first-child{margin-top:var(--sp-1)}
/* the honest sentence a not-yet-built row opens */
.fx-set .setnote{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);margin:2px 2px var(--sp-1)}
.fx-set .setnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.5}
.fx-set .setnote.warntx{color:var(--red)}
/* A SWITCH ROW. The WHOLE ROW is the tap target, never the 28px pill (Ahmed's standing 07-19 rule:
   no tiny native-sized control is ever the only way to do something), so this carries the 48px
   floor and the pill is just what the state looks like. */
.fx-set .setrow{display:flex;align-items:center;gap:var(--sp-3);background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-input);padding:10px var(--sp-3);min-height:var(--tap-min);margin:0 0 var(--sp-2);cursor:pointer}
.fx-set .setrow .tx{flex:1 1 auto;min-width:0}
.fx-set .setrow .tx b{display:block;font-size:var(--t-body)}
.fx-set .setrow .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.fx-set .setrow .tx span{display:block;font-size:var(--t-small);color:var(--muted);line-height:var(--lh-small)}
.fx-set .setrow .tx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;line-height:1.35}
/* a FACT is not a door: it states something and cannot be tapped, so it never looks like a switch */
.fx-set .setrow.fx-fact{border-style:dashed;background:var(--paper);cursor:default}
.fx-set .setrow.fx-fact[hidden]{display:none}
/* the pill, and its OFF position. The knob moves, the track goes grey; colour alone would be
   invisible to anyone who cannot separate orange from grey, so the knob's side carries it too. */
.fx-set .setrow .fx-tog{transition:background .15s ease}
.fx-set .fx-tog.off{background:var(--line)}
.fx-set .fx-tog i{transition:left .15s ease, right .15s ease}
.fx-set .fx-tog.off i{right:auto;left:3px}
/* the receipt, same law and same look as .profstat: under its own control, centered, green good
   red bad, and the red line IS the retry door */
:is(.fx-set,.fx-pl) .setstat{display:block;font-size:var(--t-body);font-weight:700;text-align:center;margin:var(--sp-1) 2px 10px}
:is(.fx-set,.fx-pl) .setstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-set .setstat.warntx{cursor:pointer}
.fx-set .setstat[hidden]{display:none!important}
/* b432: THE HEAD-OUT REMINDER. The steppers reuse the rate steppers (.fx-off-ovr, 52px taps); the value is a read-only
   word, not an input, because a lead time is only ever stepped. With the switch off the rows dim but still work, so
   he can set the rule before turning it on. The Home line sits under the passenger's name in the ink of a fact. */
.fx-set .ho-val{flex:1 1 auto;min-width:0;text-align:right;font-family:var(--body);font-size:var(--t-body);color:var(--orange)}
.fx-set .ho-val:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.05rem}
.fx-set .setrow[data-on="0"][data-act="set-flag:headout"] ~ [data-timing="box"] .ho-steps{opacity:.5}
.fx-set .ho-steps .setnote{margin-top:var(--sp-1)}
/* b449: Near pickups, Far pickup mileage, Far pickup time as orange pills, white bold words, the stepper's own orange */
.fx-set .ho-pill{display:inline-flex;align-items:center;min-height:32px;margin:14px 0 var(--sp-2);padding:0 var(--sp-4);border-radius:var(--r-pill);
  background:#FF3B00;color:#fff;font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;font-size:var(--t-body);
  letter-spacing:.01em;line-height:1}
.fx-set .ho-pill:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:800;font-size:.95rem;line-height:1}
.fx-set .ho-steps > .ho-pill:first-child{margin-top:6px}
/* b449: Phone alarms. A fact row (it cannot be tapped), its state in words and colour, ALLOW only when the phone says no */
.fx-set .setrow.ho-alarms{cursor:default}
.fx-set .setrow.ho-alarms .tx .ho-alver{color:#FF3B00;font-weight:800;margin-top:2px}
.fx-set .setrow.ho-alarms .tx .ho-alver:empty{display:none}
.fx-set .ho-alst{display:block;font-style:normal;font-weight:700;font-size:var(--t-small);margin-top:var(--sp-1);line-height:var(--lh-small)}
.fx-set .ho-alst:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:.9rem;line-height:1.3}
.fx-set .ho-alarms[data-al="good"] .ho-alst{color:var(--good)}
.fx-set .ho-alarms[data-al="bad"] .ho-alst{color:var(--red)}
.fx-set .ho-alarms[data-al="none"] .ho-alst{color:#C24E00}
.fx-set .ho-alarms[data-al="wait"] .ho-alst{color:var(--muted)}
.fx-set .ho-alarms .ho-alpath[hidden]{display:none}
.fx-set .ho-alallow{flex:0 0 auto;min-height:48px;min-width:88px;padding:0 var(--sp-4);border:0;border-radius:var(--r-pill);background:#FF3B00;color:#fff;
  font:inherit;font-weight:700;font-size:var(--t-body);letter-spacing:.04em;cursor:pointer}
.fx-set .ho-alallow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:inherit;font-weight:800;font-size:.95rem}
.fx-set .ho-alallow[hidden]{display:none}
/* b460: OPEN THE ANDROID APP, the orange no-bridge row on an Android phone. A 48px orange pill, ink on the accent fill */
.fx-set .ho-openapp{margin-top:var(--sp-2)}
.fx-set .ho-openapp[hidden],.fx-set .ho-getapp[hidden]{display:none}
.fx-set .ho-openbtn{display:flex;align-items:center;justify-content:center;min-height:48px;padding:0 var(--sp-4);border-radius:var(--r-pill);
  background:#FF3B00;color:#fff;font-weight:700;font-size:var(--t-body);letter-spacing:.04em;text-decoration:none;text-align:center}
.fx-set .ho-openbtn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:.95rem}
.fx-set .ho-tell{margin-top:var(--sp-2)}
.fx-set .ho-tell p,.fx-set .ho-getapp p,.fx-set .ho-getapp li{margin:0 0 3px;font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink,var(--ink))}
.fx-set .ho-tell p:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-set .ho-getapp p:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-set .ho-getapp li:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.35}
.fx-set .ho-getapp{margin-top:var(--sp-2);padding:var(--sp-2) 10px;border-radius:10px;background:var(--card);border:1px solid var(--line)}
.fx-set .ho-getapp .ho-gethd{font-weight:800}
.fx-set .ho-getapp ol{margin:var(--sp-1) 0 0;padding-left:20px}
/* b454: THE BEDTIME REMINDER FOR EARLY RIDES. The same steppers and the same dimming with its own switch off; on the Ride
   screen the early ride's second line, "Bed by 9:00 PM, up at 3:00 AM", in the orange of the Home head-out line. */
.fx-set .setrow[data-on="0"][data-act="set-flag:bedtime"] ~ [data-timing="box"] .bt-steps{opacity:.5}
.fx-set .bt-steps .setnote{margin-top:var(--sp-1)}
.fx-set .bt-steps .ho-val{white-space:nowrap}
.fx-ride .row .tx .ho-bed{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.02em;color:var(--orange);margin-top:3px}
.fx-ride .row .tx .ho-bed[hidden]{display:none!important}
.fx-entry .fx-id .ho-home{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.04em;color:var(--orange);margin:-2px 0 6px}
.fx-entry .fx-id .ho-home[hidden]{display:none}
.fx-ride [data-rrow="headout"][hidden],.fx-ride [data-ho="ed"][hidden]{display:none!important}
.fx-ride [data-ho="ed"] .btns button{padding:0 6px}
/* a link the driver hands out. It wraps, because a link that runs off the edge cannot be read and
   cannot be pressed-and-held to copy either. */
.fx-set .linkrow{font-family:'JetBrains Mono',monospace;font-size:var(--t-label);line-height:var(--lh-label);
  word-break:break-all;background:var(--paper);border:1px solid var(--line);border-radius:10px;
  padding:11px var(--sp-3);margin:0 0 10px;color:var(--ink);-webkit-user-select:all;user-select:all}
.fx-set .linkrow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:.78rem;line-height:1.5}
.fx-set .linkrow.mutedlink{color:var(--muted);font-family:'Space Grotesk',sans-serif;
  font-size:var(--t-small);background:var(--card);border-style:dashed;user-select:auto}
.fx-set .linkrow.mutedlink:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-size:.84rem}

/* ================================================================================================
   b34, CANCEL THIS RIDE. Lives on the driver Ride screen under the money row, expands IN PLACE
   (rule zero, never a browser popup and never window.confirm), and the destructive button is the
   only red one on the screen so it cannot be confused with Keep it.
   ================================================================================================ */
.fx-ride .cxsec{flex:0 0 auto;margin-bottom:9px}
/* THE DESTRUCTIVE DOOR READS AS ONE BEFORE IT IS TAPPED. .fx-danger already means red in this
   codebase (Sign out), but the rules that paint it were scoped to .fx-set, so on the Ride screen
   the row rendered in ordinary black and the only warning was the words. Caught by pixels, which
   is the only thing that could have caught it (a class check would have passed: the class is
   there, the rule that colours it just was not). */
.fx-ride .cxsec .row.fx-danger b{color:var(--red)}
.fx-ride .cxsec .row.fx-danger svg{stroke:var(--red)}
.fx-ride .cxsec .cx-x{display:none}
.fx-ride .cxsec[data-open="1"] .cx-x{display:block;background:var(--card);border:1.5px solid var(--red);
  border-radius:var(--r-ctl);padding:13px;margin-top:-4px}
.fx-ride .cxsec[data-open="1"] .row.fx-danger{margin-bottom:6px}
.fx-ride .cxsec[data-open="1"] .fx-chev{transform:rotate(90deg)}
.fx-ride .cxsec .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.fx-ride .cxsec .cxwho{font-size:var(--t-body);font-weight:700;line-height:var(--lh-body);margin:0 0 var(--sp-2)}
.fx-ride .cxsec .cxwho:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:800;line-height:1.45}
.fx-ride .cxsec .setnote{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);margin:0 0 var(--sp-3)}
.fx-ride .cxsec .setnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;line-height:1.5}
.fx-ride .cxsec .fx-btns{display:flex;gap:10px;margin-top:10px}
.fx-ride .cxsec .fx-btns[hidden]{display:none!important}
.fx-ride .cxsec .fx-danger-btn{flex:1 1 0;cursor:pointer}
.fx-ride .cxsec .fx-cancel{flex:1 1 0;cursor:pointer}
.fx-ride .cxsec .setstat{display:block;font-size:var(--t-body);font-weight:700;text-align:center;
  margin:10px 2px 2px}
.fx-ride .cxsec .setstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-ride .cxsec .setstat[hidden]{display:none!important}
/* the decline confirm inside the New requests list reuses the calendar review's .crow shell, so it
   inherits that panel's already-proven 48px action buttons rather than inventing a second style */
.fx-leads .crow.cxrow{border-color:var(--red)}

/* ================================================================================================
   b37, THE CANCELLED STATE, and the record that outlives it.

   Ahmed cancelled a booking and reported "no way to undo it", and separately that the screen
   "should not go to the next ride, that should never happen". Both were true and both were this
   corner of the app. The Undo button lived inside .cx-x, which cxYes() collapses on success, so it
   was display:none exactly when it became relevant (measured at 430/520/768/900: rect 0x0, tap
   refused "zero size"). And cxRefresh() repainted the Ride screen onto the next booking.

   So the cancel now ENDS on a state of its own. .cxdone is a terminal card that names the booking
   that was cancelled and offers Put it back; data-cxdone on the frame hides the live ride rows, so
   no stale booking is left asserting itself behind it, which is the same rule cxEmptyRide follows.
   ================================================================================================ */
.fx-ride .cxdone{flex:0 0 auto}
.fx-ride .cxdone[hidden]{display:none!important}
/* the live ride yields to the terminal state, whole. A row still on screen under a card that says
   "cancelled" is the finished-rides bug in miniature: the screen asserting what the data denies. */
.fx-ride[data-cxdone="1"] > .sheet > h4,
.fx-ride[data-cxdone="1"] > .sheet > .row,
.fx-ride[data-cxdone="1"] > .sheet > .paxsec,
.fx-ride[data-cxdone="1"] > .sheet > .tipsec,
.fx-ride[data-cxdone="1"] > .sheet > .cxsec,
.fx-ride[data-cxdone="1"] > .sheet > .fx-btnrow{display:none!important}
/* THE DROPPED-OFF TERMINAL STATE (b41), the same rule for the same reason. A finished trip has left
   the feed, so the live ride rows underneath it describe nothing, and leaving them on screen under
   a card that says the trip is over is the screen asserting what the data denies. .rsdone reuses
   .cxdone's box so the tap targets and the 48px floor are the proven ones, and it gets its OWN
   [hidden] rule because .cxdone sets an explicit display and an explicit display silently beats
   [hidden]{display:none} (the 2026-07-31 lesson). The cancel card is deliberately excluded from the
   hide list below: a dropped-off ride is finished, not cancelled, and both cards must never be on
   screen at once. */
.fx-ride .rsdone[hidden]{display:none!important}
.fx-ride .rsdone{border-color:var(--good)}
.fx-ride[data-rsdone="1"] > .sheet > h4,
.fx-ride[data-rsdone="1"] > .sheet > .row,
.fx-ride[data-rsdone="1"] > .sheet > .paxsec,
.fx-ride[data-rsdone="1"] > .sheet > .tipsec,
.fx-ride[data-rsdone="1"] > .sheet > .flsec,
.fx-ride[data-rsdone="1"] > .sheet > .cxsec,
/* :not(.rsdone) IS LOAD BEARING. The finished-trip card IS a .cxdone (it reuses that box on
   purpose), so a bare `.cxdone` here hid the card by its own rule: it stayed [hidden]-free and
   "visible" to any check reading the attribute, while computing to display:none and zero size. The
   harness caught it as "Review and save trip is a real tap target -> zero size", which is why the
   tap test is hit-tested rather than el.click(): a synthetic click would have "worked" on a control
   the driver could never have pressed. */
.fx-ride[data-rsdone="1"] > .sheet > .cxdone:not(.rsdone),
.fx-ride[data-rsdone="1"] > .sheet > .fx-btnrow{display:none!important}
.fx-ride .cxdone-card{background:var(--card);border:1.5px solid var(--red);border-radius:var(--r-ctl);
  padding:13px;margin:0 0 var(--sp-3)}
.fx-ride .cxdone-card b{display:block;font-size:var(--t-body);font-weight:700;line-height:var(--lh-body);
  margin:0 0 6px}
.fx-ride .cxdone-card b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:800;line-height:1.45}
.fx-ride .cxdone-card span{display:block;font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.fx-ride .cxdone-card span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;line-height:1.5}
.fx-ride .cxdone .fx-btns{display:flex;gap:10px;margin:0 0 10px}
/* b236: THE MISSING [hidden] GUARD, and it is the whole "See my trips twice" bug (Ahmed
   2026-08-23). The rule above sets an explicit display, which BEATS the browser's own
   [hidden]{display:none}, so the after-save row was never hidden and both rows rendered at once.
   The class rule this codebase already writes for every component that sets a display. */
.fx-ride .cxdone .fx-btns[hidden]{display:none!important}
/* b236: WHILE THE CLOSE-OUT IS OPEN, the card above it says nothing more. "Review and save trip"
   would only reopen the panel he is already in, and the card's own header is the line that gets
   cut in half under the top of the sheet. Both stand down until he is out of the panel. */
.fx-ride .cxdone .clsec[data-open="1"] ~ .fx-btns[data-cl="beforebtns"]{display:none!important}
.fx-ride .cxdone:has(.clsec[data-open="1"]) > .cxwho{display:none}
.fx-ride .cxdone .fx-save{flex:1 1 0;cursor:pointer}
.fx-ride .cxdone .fx-cancel{flex:1 1 0;cursor:pointer}
.fx-ride .cxdone .setstat{display:block;font-size:var(--t-body);font-weight:700;text-align:center;
  margin:0 2px 10px}
.fx-ride .cxdone .setstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-ride .cxdone .setstat[hidden]{display:none!important}

/* RECENTLY CANCELLED, on My rides. The durable half: this is what makes an undo survive a repaint,
   a tab change and a reload, which a button on the screen where the act happened cannot. */
.fx-rides .cxlog{flex:0 0 auto;margin-top:6px}
.fx-rides .cxlog[hidden]{display:none!important}
.fx-rides .cxlog .cxlogrow{border-color:var(--line);background:var(--paper)}
.fx-rides .cxlog .cxlogrow b{color:var(--muted);text-decoration:line-through}
.fx-rides .cxlog .cxlogrow svg{stroke:var(--red)}
/* PUT IT BACK is the one action on the row, so it is a real tap target, never a small tag
   (Ahmed's standing rule about tiny controls). */
.fx-rides .cxlog .cxlogrow .aff{min-height:var(--tap-min);display:flex;align-items:center;
  padding:6px 14px;background:var(--red);color:#fff}
.fx-rides .cxlog .setstat{display:block;font-size:var(--t-small);font-weight:700;text-align:center;
  margin:var(--sp-2) 2px 2px}
.fx-rides .cxlog .setstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;font-weight:700}
.fx-rides .cxlog .setstat[hidden]{display:none!important}

/* fx-pax: passenger-role screens */
.fx-pax .map.slim{flex:1 1 auto;min-height:230px}
.fx-pax .hd{gap:6px;padding:10px 10px}
.fx-pax .hd-logo{font-size:var(--fs-label);letter-spacing:0;min-width:0}
.fx-pax .chip{padding:var(--sp-1) 9px var(--sp-1) var(--sp-1);font-size:var(--t-small)}
.fx-pax .chip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}
.fx-pax .chip .av{width:28px;height:28px;font-size:var(--t-small)}
.fx-pax .chip .av:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem}
.fx-pax .carchip{position:absolute;background:var(--card);border:1px solid var(--line);border-radius:var(--r-pill);
  padding:2px 9px;font-size:var(--fs-label);font-weight:800;box-shadow:0 2px 6px rgba(10,10,10,.15)}
.fx-pax .mono-k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.fx-pax .idname{display:block;font-size:var(--t-card);font-weight:600;margin:var(--sp-2) 0 6px}
.fx-pax .idname:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.05rem;font-weight:800}
.fx-pax .plate{display:inline-block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;border:1px solid var(--line);border-radius:6px;padding:2px 7px;background:var(--paper)}
.fx-pax .mutline{font-size:var(--t-small);color:var(--muted);line-height:var(--lh-small);margin-top:6px}
.fx-pax .mutline:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;line-height:1.4}
.fx-pax .namebadges{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.fx-pax .avrow{width:36px;height:36px;border-radius:50%;background:var(--placeholder);color:#fff;display:flex;
  align-items:center;justify-content:center;font-weight:700;font-size:var(--t-small);flex:0 0 auto}
.fx-pax .avrow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:.9rem}
.fx-pax .avrow.ink{background:var(--ink)}
.fx-pax .btnrow{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-3)}
.fx-pax .btnrow2{display:flex;gap:10px;flex:0 0 auto}
.fx-pax .btnrow2 .cta{flex:1 1 0;min-width:0;font-size:var(--t-body)}
.fx-pax .btnrow2 .cta:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem}
/* b513: her yes to the two ride texts, under Message your driver */
.fx-pax .paxtexts{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:10px;padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--r-input);flex:0 0 auto}
.fx-pax .paxtexts[hidden],.fx-pax .paxtexts [hidden]{display:none!important}
.fx-pax .paxtexts .pt-q{font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink)}
.fx-pax .paxtexts .pt-q:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .98rem 'Space Grotesk',sans-serif}
.fx-pax .paxtexts .cta{width:100%;min-height:44px;font-size:var(--t-body)}
.fx-pax .paxtexts .cta:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-pax .paxtexts .pt-fine{font-size:var(--fs-label);line-height:1.35;color:var(--muted)}
.fx-pax .paxridehead{display:flex;align-items:center;gap:10px;margin:2px 2px 10px;flex:0 0 auto}
.fx-pax .paxridehead h4{margin:0}
/* b639 (PF641, approved from mock PF639): HER FLIGHT LINE under "Your ride", the driver's .flline in a white box like her
   other rows (same edge, corner and fill as .row), red edged on pink when the flight is late, a grey line under it */
.fx-pax > .sheet > .flline.paxfl{display:flex;align-items:center;gap:12px;min-height:44px;flex:0 0 auto;margin:0 0 9px;
  padding:10px 14px;background:#fff;border:1px solid var(--line);border-radius:14px}
.fx-pax > .sheet > .flline.paxfl[hidden]{display:none!important}
.fx-pax > .sheet > .flline.paxfl[data-tone="late"]{border-color:var(--red);background:#FFF6F4}
.flline.paxfl .fl-sub{display:block;font-size:.74rem;font-weight:600;color:var(--muted);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.flline.paxfl .fl-sub[hidden]{display:none}
.fx-pax .dim{display:flex;flex-direction:column;flex:1 1 auto;overflow:hidden;opacity:.4;
  filter:saturate(.7);pointer-events:none}
.fx-pax .avatar-lg.ink{background:var(--ink);color:#fff}   /* b308: the ink disc keeps white initials */

/* ================================================================================================
   SHEET STACKING, from the mock. Map and dimmed layers sit BEHIND the risen sheet so the map
   stays visible around it (rulebook behavior). Subjects here are the map/dim layers, not sheets.
   ================================================================================================ */
.frame > .hd{position:relative;z-index:3}
.frame > .foot{position:relative;z-index:3;background:var(--card)}
.frame:has(> .sheet) > .map,
.frame:has(> .sheet) > .fx-dim,
.frame:has(> .sheet) > .dim{position:absolute;top:0;left:0;right:0;bottom:var(--foot-h);
  min-height:0;height:auto;z-index:0}
/* Screens whose sheet has no live map behind it still show the street grid around the sheet */
.frame:has(> .sheet):not(:has(> .map)):not(:has(> .fx-dim)):not(:has(> .dim)){background:
  linear-gradient(90deg,transparent 48%,#fff 48%,#fff 52%,transparent 52%),
  linear-gradient(0deg,transparent 47%,#fff 47%,#fff 53%,transparent 53%),
  repeating-linear-gradient(90deg,#E6E3DC 0 1px,transparent 1px 54px),
  repeating-linear-gradient(0deg,#E6E3DC 0 1px,transparent 1px 54px),var(--map-bg)}

/* ================================================================================================
   LONG FORMAT, Z Fold open, about 1.2:1 and wider. THE format switch is this media query:
   it swaps the token set (verbatim long column of the ypd-design-rules block) plus the mock's
   own long-only structural rules. Everything else reads the tokens and obeys automatically.
   ================================================================================================ */
@media (min-aspect-ratio: 6/5){
  :root{
    --act-h:52px; --act-fs:1.05rem; --row-h:56px; --car:34px; --navline:6px; --fs-label:var(--t-label);   /* b563: 12px on the fold too, nothing under 12 (UI audit #5) */
    --foot-h:64px; --tap-min:48px; --sheet-top:5%; --hd-h:56px;
    --sheet-inset:5%;
    --title-fs:1.7rem;
    --logo-fs:1.7rem;     /* long has the width, logo matches the name size */
  }
  /* b704: ONE WIDTH, CLEAR OF THE CIRCLES AND THE RAIL (Ahmed 2026-11-01, 2:39 PM on the open Fold: "our menu should never be wider
     than the overlay and the icons on the right hand side, and these all should open the same width"). Android's bubbles (YPD, Your
     Circle, Uber) sit on the left edge, 78px wide at 829, and ran over Leaving home's title; the map rail is 63px on the right.
     84px each side, a number not a percent, because neither of them grows with the window. Every sheet already reads this token, so
     the old 50 and 60 percent narrow widths are gone with it. Wide windows only: a phone whose keyboard cuts it under 6/5 is still a
     phone, 84px a side would leave it a strip, so it keeps 5 percent. */
  @media (min-width:640px){:root{--sheet-inset:84px}}
  .tools{grid-template-columns:repeat(6,1fr)}
  .tools.two{grid-template-columns:repeat(3,1fr)}
  .facts>div{flex:1 1 0;min-width:0}

  /* Long footer padding trimmed so the footer's REAL height equals its 64px token.
     Found by MEASUREMENT: with the tall padding the footer's content ran ~71px, the sheet
     max-height calc trusts --foot-h, and the 5 percent header gap lost 7px on tall-content
     sheets, the exact failure class the rulebook records (gap failed four times). Footer
     rule, not a sheet rule, so sheet geometry stays token-owned. */
  .foot{padding:6px var(--sp-1) var(--sp-2)}

  /* LONG: vehicle button back to one line, name middot plate (law) */
  .fx-entry .fx-veh .vmain{flex-direction:row;gap:6px}
  .fx-entry .fx-veh .vsep{display:inline}

}

/* ================================================================================================
   SIGN-IN FRONT DOOR (Option 2, PICKED by Ahmed 2026-08-14 from YPD-SIGNIN-MOCK-V1A). The
   signed-out landing IS the sign-in screen: logo, Driver Sign In, three methods visible at ZERO
   taps, footnote. Same .fx-land component as the landing, so the landing rhythm law (centered
   column, one gap, symmetric) applies by construction. Kit components only, NO sheet involved.
   ================================================================================================ */
/* The land swap, CSS-owned, DRIVER-SCOPED: signed-out is the DEFAULT first paint, and auth is a
   driver-only concept (passengers are link-first, NO login, sign-in law), so a keyless passenger
   device must keep its normal landing. Both lands ship in the markup, the attribute picks one,
   zero flash in either direction (the head script flips keyed devices synchronously).
   Specificity note (07-30 lesson, measured by the b19 probe): the hidden default must OUTRANK
   the kit's `.fx-entry .fx-land{display:flex}` (0,2,0), a bare `.fx-authland` silently loses
   and both lands render on a keyed device. Hence the full compound. */
.fx-entry .fx-land.fx-authland{display:none}
body[data-role="driver"][data-auth="out"] .fx-land:not(.fx-authland){display:none}
body[data-role="driver"][data-auth="out"] .fx-land.fx-authland{display:flex}
/* b719: the new sign-in screen (signin-screen.js) is clear over the map, so the old door under it steps out of sight
   while it is up; after a tap the old door shows only the door that was picked, its second step */
body[data-sis="on"] .fx-land.fx-authland{visibility:hidden}
.fx-authland[data-sis-pick="google"] .authsec:not([data-authrow="google"]),
.fx-authland[data-sis-pick="phone"] .authsec:not([data-authrow="phone"]),
.fx-authland[data-sis-pick="email"] .authsec:not([data-authrow="email"]){display:none}
/* b721: the phone step now runs ON the new screen, so it sits just under Google's reCAPTCHA challenge (z-index
   2000000000) in case Google asks for a picture check, and still over everything else in the app */
.sis[data-sis="driver"]{z-index:1999999000}
/* Driver Sign In line: the landing name-line component (Space Grotesk 800, --title-fs) */
.auth-title{font-family:'Space Grotesk',sans-serif;font-weight:800;font-size:var(--title-fs)}
/* Method buttons fill the column like every landing CTA */
.fx-authland .authsec{width:100%}
.fx-authland .authsec .cta{width:100%}
/* Google primary: the orange .cta carrying the white-tile 4-color G mark (mock geometry) */
.auth-gbtn{display:flex;align-items:center;justify-content:center;gap:var(--sp-3);font-size:var(--t-body)}
.auth-gbtn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.02rem}
.auth-gbadge{flex:0 0 auto;width:34px;height:34px;border-radius:9px;background:var(--card);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center}
.auth-gbadge svg{width:20px;height:20px}
/* Inline expansion under the tapped method button, never a popup (rule zero) */
.authsec .auth-x{display:none;padding:10px 2px 0}
.authsec[data-open="1"] .auth-x{display:block}
/* Inputs: same look as the Settings editor field (48px tap law) */
.auth-x .auth-in{display:block;width:100%;min-height:48px;border:1.5px solid var(--ink);
  border-radius:var(--r-input);padding:0 14px;font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;
  font-weight:700;font-size:var(--t-body);color:var(--ink);background:var(--card);margin-bottom:10px}
.auth-x .auth-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',sans-serif;font-weight:700;font-size:1rem}
.auth-x .auth-cta{min-height:48px;font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body)}
.auth-x .auth-cta:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.95rem}
/* Stage 1 = sent: the form swaps for the inline confirmation (email) or the code field (phone) */
.authsec .auth-sent{display:none}
.authsec .auth-code{display:none}
.authsec[data-stage="1"] .auth-form{display:none}
/* Link-sent confirmation: CENTERED and stacked, the sent line reads like every other status
   (status-under-its-button law, Ahmed 2026-08-14 called out its left-justification live) */
.authsec[data-stage="1"] .auth-sent{display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:10px;min-height:48px}
.authsec[data-stage="1"] .auth-code{display:block}
.auth-sent .goodtx{font-size:var(--t-body);text-align:center}
.auth-sent .goodtx:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.auth-sent .aff{cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.06em;background:var(--ink);color:#fff;border-radius:8px;padding:var(--sp-3) 14px}
/* STATUS-UNDER-ITS-BUTTON LAW (Ahmed 2026-08-14, live): a status message renders DIRECTLY UNDER
   the button that caused it, centered, large enough to notice (.95rem+), green for good red for
   bad, the driver's eye goes to the button they just pressed. .authstat is each method's own
   status line; .autherr shares the exact same geometry in red. Own [hidden] guard (07-31 lesson:
   an explicit display would beat the UA rule; here display is default but the guard is kept for
   the class's future). */
.authsec .authstat{font-size:var(--t-body);text-align:center;margin:10px 2px 0}
.authsec .authstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.authsec .authstat[hidden]{display:none!important}
.authsec .autherr{font-size:var(--t-body);text-align:center;margin:10px 2px 0}
.authsec .autherr:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
/* reCAPTCHA disclosure, small + muted inside the phone section. REQUIRED PAIR with the badge
   rule below: Google permits hiding the floating badge only when this attribution shows in
   the flow (Ahmed 2026-08-14, the grey badge arrows lingered bottom-right after phone sign-in). */
.auth-recap{color:var(--muted);font-size:var(--fs-label);margin:var(--sp-2) var(--sp-1) 0;text-align:left}
.grecaptcha-badge{visibility:hidden!important}
/* Land-level green progress line, now ONLY the boot-time email-link landing (no button pressed
   yet); button-caused statuses live in each method's .authstat above. Same noticeable size.
   Its own [hidden] guard: an explicit display would otherwise beat the UA rule (07-31 lesson). */
.auth-prog{font-size:var(--t-body);text-align:center}
.auth-prog:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.auth-prog[hidden]{display:none!important}
/* Footnote, the mock's tagline component */
.auth-note{color:var(--muted);font-size:var(--t-small)}
.auth-note:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem}
/* Soft retry chip: signed in, key exchange pending (linked:false), tap retries */
.auth-retry{display:none;align-items:center;justify-content:center;gap:var(--sp-2);min-height:48px;
  width:100%;border:1.5px dashed var(--line);border-radius:var(--r-ctl);background:var(--card);color:var(--muted);
  font-size:var(--t-small);font-weight:700;cursor:pointer;padding:0 14px}
.auth-retry:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;font-weight:700}
body[data-role="driver"][data-auth="retry"] .auth-retry{display:flex}

/* ================================================================================================
   b30 · THE TIP, THE MONEY PILL, AND THE IDENTITY PLATE
   ================================================================================================ */

/* THE FARE PILL. It carries the tip now ("$160 + $65"), so it is a longer string than the "$95"
   the inline style was sized for, and it sits between TWO identity chips on the Ride header.
   It never wraps and never pushes a chip off the header (the 08-13 hit-test lesson: at 430 the
   header ran 466px and the Settings button's tap centre was unreachable). */
/* b295: the one line on the driver sign-in for a passenger who landed there by a broken link */
.authpax{margin:-4px auto 14px;max-width:320px;text-align:center;font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.authpax:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.35}
/* b289: the fare pill hides while the painted ride is the finished one (body[data-ridedone], set by
   rsDonePaint, cleared by paintRideFields on the next booking). Own rule because .pill carries an
   explicit display, the 2026-07-31 law. */
/* b530 (bug-mv8bidxc-mv0sr, Ahmed 2026-10-14 at the drop-off close-out of Lelani's parents: "the money pill is missing"):
   THE PILL STAYS WITH ITS RIDE. b289's rule hid it the moment the painted ride was the dropped one, which is exactly the
   close-out, when the money is what he is settling, and with the pill gone the passenger plate slid left beside his own.
   His new standing call is the header on every screen: his plate left, the money centre, the passenger right. The pill
   now leaves with the passenger plate, when another booking is painted (paintRideFields), never on its own.
   body[data-ridedone] is still stamped for anything else that reads it. */
.pill.fx-farepill{margin:0 auto;font-size:var(--t-body);padding:6px 14px;white-space:nowrap;
  flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
.pill.fx-farepill:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
/* b492: THE HEADER FARE PILL TAPS AT 44px WITHOUT GROWING. The painted pill stays 31px (fare-flip is a tap, the
   checklist wants 44). A transparent border above and below carries the hit area, background-clip keeps the ink off
   it, and the shadow follows the painted pixels (drop-shadow) rather than the border box, so no halo. overflow:hidden
   for the ellipsis is untouched, a border is inside the box. */
.hd .pill.fx-farepill{box-sizing:border-box;border:solid transparent;border-width:7px 0;background-clip:padding-box;min-height:45px;
  box-shadow:none;filter:drop-shadow(0 3px 5px rgba(10,10,10,.28))}
.frame[data-role="passenger"] .hd .pill.fx-farepill.pxbooked{box-shadow:none;filter:drop-shadow(0 3px 5px rgba(31,157,87,.35))}
/* b668 (bug-mvtskwnd-9s2aj, Ahmed 2026-10-29: "you click on it, it shows $100. You click on it, it shows $120"): the driver's
   pill steps "$100 + $20", "$100", "$120". farePillPaint holds the first face's width as an inline min-width on the shorter
   faces, and the shorter text sits in the middle of it. */
.frame[data-role="driver"] .pill.fx-farepill[data-fstep]{justify-content:center}
/* b444: HER BOOKED PRICE IS GREEN. Her header fare pill once a price is agreed, and her Ride badge, which reads
   "Booked $70" with the price in heavier type. The app's green (--good) and white, the same pair as WORKS. */
.frame[data-role="passenger"] .pill.fx-farepill.pxbooked{background:var(--good);color:#fff;box-shadow:0 4px 12px rgba(31,157,87,.35)}
.badge.pxbooked{background:var(--good);color:#fff;font-size:var(--t-body);font-weight:700;padding:6px 14px;letter-spacing:.01em;
  box-shadow:0 3px 10px rgba(31,157,87,.25)}
.badge.pxbooked:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.badge.pxbooked b{font-family:var(--body);font-weight:600;font-size:var(--t-card);margin-left:2px}
.badge.pxbooked b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-weight:400;font-size:1.15rem}

/* THE IDENTITY PLATE shows the profile name VERBATIM (b30 law), so it must survive a long name
   without breaking the header. It never wraps; past its cap it ellipsises, which is a rendering
   limit, not a truncation of the record. Below 520px the whole name is hidden by the existing
   compact-chip rule above, so this only governs the wide formats. */
/* b128: THE NAME SHOWS FULL WHEN THERE IS ROOM. The fixed ch caps clipped "Yuma Test Ride 3" to
   "Yuma Test..." on a wide laptop with half a header of empty space (Ahmed's screenshot). The
   chips are flex items that SHRINK under real pressure (min-width:0 + ellipsis) and otherwise
   render the whole name, so a phone still never overflows and a laptop never truncates early. */
.hd .chip{min-width:0;flex:0 1 auto}
.hd .chip .chipnm{overflow:hidden;text-overflow:ellipsis;max-width:30ch}
/* b530 (bug-mv8bidxc-mv0sr, Ahmed 2026-10-14: "my name is missing and I'm to the left, and it shows LP which is
   supposed to be on the right, and the money pill is missing"). EVERY DRIVER HEADER THAT CARRIES THE RIDE IS THREE
   COLUMNS: his plate left, the money centre, the passenger right. Two equal side columns put the pill on the true centre
   whatever the two plates hold, and the passenger plate keeps the right edge even if the pill is ever hidden. A header
   with the logo instead (no ride, pricing, Book a Ride) puts the logo in the centre column, as before.
   HIS NAME SHOWS ON A PHONE. The 520px rule below hid every chip name for the 2026-08-13 Settings button, which b314
   took out of every header; his own name comes back, the passenger keeps initials (LP), and a long name ellipsises at
   its column, never off the header. */
.frame[data-role="driver"] > .hd:has(> .pill.fx-farepill){display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
  align-items:center;column-gap:var(--sp-2)}
.frame[data-role="driver"] > .hd:has(> .pill.fx-farepill) > .chip:has([data-name="plate"]){justify-self:start;max-width:100%}
.frame[data-role="driver"] > .hd:has(> .pill.fx-farepill) > .chip:has([data-rd="chipname"]){justify-self:end;grid-column:3;max-width:100%}
.frame[data-role="driver"] > .hd:has(> .pill.fx-farepill) > .pill.fx-farepill{grid-column:2;margin:0}
.frame[data-role="driver"] > .hd:has(> .pill.fx-farepill) > .hd-logo{grid-column:2}
@media (max-width:520px){
  .frame[data-role="driver"] > .hd .chip .chipnm[data-name="plate"]{display:block;min-width:0;font-size:var(--t-small);letter-spacing:-.01em}
  .frame[data-role="driver"] > .hd .chip:has([data-name="plate"]){gap:5px;padding-right:9px}
}

/* THE TIP EDITOR. Expands in place under the money row (rule zero), same shape as the Settings
   profile editor. Own [hidden]-equivalent guard by data-open (07-31: an explicit display beats
   the UA rule, so the closed state is stated, never assumed). */
.fx-ride .tipsec{display:block}
.fx-ride .tipsec .tip-x{display:none}
.fx-ride .tipsec[data-open="1"] .tip-x{display:block;margin:-4px 2px 10px;padding:var(--sp-3) var(--sp-3) var(--sp-1);
  border:1.5px solid var(--ink);border-radius:var(--r-ctl);background:var(--card)}
.fx-ride .tipsec .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 var(--sp-2)}
/* The money row's own EDIT is a control this round TOUCHES, so it meets --tap-min in full. The
   other NAVIGATE/EDIT chips on this screen are a separate queued task and are left alone. */
.fx-ride .row .aff.tipedit{min-height:var(--tap-min);display:inline-flex;align-items:center;
  justify-content:center;min-width:64px;cursor:pointer}
/* NEVER a native number spinner (HARD standing rule, Ahmed 2026-07-19: he cannot click them).
   Big − / + buttons, well over the 48px floor, with the field between them. */
.fx-ride .tiprow{display:flex;align-items:center;gap:10px}
.fx-ride .tipstep{flex:0 0 auto;width:56px;height:56px;min-width:var(--tap-min);line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center}
.fx-ride .tipstep:active{background:var(--paper)}
.fx-ride .tipin{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--sp-1);
  border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);padding:0 var(--sp-3);min-height:56px}
.fx-ride .tipcur{font-family:'Space Grotesk',sans-serif;font-size:var(--t-card);font-weight:600;color:var(--muted)}
.fx-ride .tipcur:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-size:1.3rem;font-weight:700}
/* THE TAP TARGET IS THE FIELD, NOT ITS BOX (b33, measured at 26px inside a 56px row while the b33
   tip work was being probed). The container met the 48px law and the only thing you can actually
   tap to focus did not, which is the identical defect b31 found on the offer sheet's price input.
   align-self:stretch makes the field fill the row it already sits in, so the number and the target
   are the same object. */
.fx-ride .tipin .fx-in{flex:1 1 auto;min-width:0;width:100%;border:none;outline:none;background:transparent;
  align-self:stretch;min-height:48px;
  font-family:'Space Grotesk',sans-serif;font-size:var(--t-card);font-weight:600;color:var(--ink);padding:0}
.fx-ride .tipin .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-size:1.3rem;font-weight:700}
/* kill the native spinners outright, both engines */
.fx-ride .tipin .fx-in::-webkit-outer-spin-button,
.fx-ride .tipin .fx-in::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.fx-ride .tipin .fx-in{-moz-appearance:textfield;appearance:textfield}
.fx-ride .tipsec .fx-btns{display:flex;gap:10px;margin-top:var(--sp-3)}
.fx-ride .tipsec .fx-save{flex:1 1 0;cursor:pointer}
.fx-ride .tipsec .fx-cancel{flex:1 1 0;cursor:pointer}
/* the receipt, under the control that caused it (status-under-its-button law) */
.fx-ride .tipsec .profstat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;
  margin:10px 0 var(--sp-1);cursor:pointer}
.fx-ride .tipsec .profstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-ride .tipsec .profstat[hidden]{display:none!important}
/* THE MISSING-FLIGHT SECTION (b40). It reuses .tipsec's layout on purpose, so the tap targets,
   the 48px --tap-min buttons and the in-place expander are the SAME ones that are already
   proven, rather than a second set that can drift. Only what differs is written here.
   ITS OWN [hidden] RULE IS MANDATORY (the 2026-07-31 lesson): .fx-ride .tipsec sets an explicit
   display, and an explicit display silently BEATS the browser's [hidden]{display:none}. Without
   this line the warning would render on every ride, airport or not. */
.fx-ride .tipsec.flsec[hidden]{display:none!important}
.fx-ride .tipsec.flsec{border-top:1.5px solid var(--line)}
.fx-ride .flrow b{color:var(--red)}
/* A REAL TAP TARGET (b40, caught by the harness at 70x36). Ahmed's standing rule: never ship a
   control smaller than a thumb can hit. A bare .aff pill is 36px tall, so this one states its
   own minimum rather than inheriting a size that has never been measured.
   Its own [hidden] rule for the same reason .flsec has one: an explicit display beats [hidden]. */
.fx-ride .flrow .aff.fledit{min-height:var(--tap-min);display:inline-flex;align-items:center;
  justify-content:center;padding:0 14px}
.fx-ride .flrow .aff.fledit[hidden]{display:none!important}
.fx-ride .flin{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--sp-1)}
.fx-ride .flin .fx-in{flex:1 1 auto;min-width:0;width:100%;min-height:var(--tap-min);
  border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);outline:none;
  background:var(--card);font:inherit;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.fx-ride .flin .fx-in:focus{border-color:var(--ink)}

/* ---- THE FLIGHT THAT IS ON FILE (b42) ---------------------------------------------------------
   Same .tipsec layout again, for the same reason the warning above reuses it: the tap targets and
   the in-place expander are already proven. Its own [hidden] rule is MANDATORY (the 2026-07-31
   lesson): .fx-ride .tipsec sets an explicit display, which silently beats [hidden]{display:none},
   so without this line the panel renders on every ride including ones with no flight at all. */
/* THE SHEET KEEPS A LAST INCH (b42). Its scroll viewport ends exactly at the pinned footer, so a
   control sitting flush against that edge has its centre ON the boundary and hit-tests to the
   FOOTER, not to itself. That is how the flight editor's SAVE became untappable at 430x900.
   revealPanel() in app.html does the scrolling; this is the belt to its braces, so a control is
   never flush against the clip even when he scrolls the sheet by hand. */
.fx-ride .sheet{padding-bottom:20px}
.fx-ride .tipsec.floksec[hidden]{display:none!important}
.fx-ride .tipsec.floksec{border-top:1.5px solid var(--line)}
/* GREEN WHEN IT CHECKS OUT, RED WHEN THE FEED DISAGREES WITH THE BOOKING. data-flok is written by
   flightOkPaint() from the SERVER's verdict state, never from anything the browser decided. */
.fx-ride .floksec[data-flok="ok"] .flokrow b{color:var(--good)}
.fx-ride .floksec[data-flok="warn"] .flokrow b{color:var(--red)}
.fx-ride .floksec[data-flok="warn"] .flokrow span{color:var(--red);font-weight:700}
.fx-ride .floksec[data-flok="warn"] .flokrow{border-color:var(--red);background:#FFF6F4}
/* A REAL TAP TARGET, the same floor the ADD IT pill states for itself: a bare .aff is 36px and
   Ahmed's standing rule is that nothing ships smaller than a thumb can hit. */
.fx-ride .flokrow .aff.flokedit{min-height:var(--tap-min);display:inline-flex;align-items:center;
  justify-content:center;padding:0 14px}
.fx-ride .flokrow .aff.flokedit[hidden]{display:none!important}
.fx-ride .flokgrid{display:grid;grid-template-columns:1fr 1fr;gap:10px var(--sp-3);margin:2px 0 var(--sp-1)}
.fx-ride .flokgrid > div{min-width:0}
.fx-ride .flokgrid b{display:block;font-size:var(--t-body);font-weight:700;overflow-wrap:anywhere}
.fx-ride .flokgrid b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}

/* CHAT is a RENDERED list now (b30), same empty-state law as My rides: never a blank panel, and
   no demo rows in the markup. Reuses .rstat/.rsub, which until now were scoped to .fx-rides. */
.fx-comms .clist{display:flex;flex-direction:column;flex:0 0 auto}
.fx-comms .rstat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;color:var(--muted);
  margin:var(--sp-4) 0 var(--sp-1)}
.fx-comms .rstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-comms .rsub{display:block;text-align:center;font-size:var(--t-small);color:var(--muted);margin:0 0 var(--sp-3)}
.fx-comms .rsub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.fx-comms .rstat[hidden],.fx-comms .rsub[hidden]{display:none!important}


/* ================================================================================================
   THE OFFER FLOW, VERSION A (b31). Ported from the approved mock fragment (fx-off), which Ahmed
   picked from a rendered screenshot on 2026-08-14. One component, one definition: the price cards,
   the steppers and the check line are the SAME components on the driver's sheet, on the passenger's
   answer screen and inside Settings > Your rates.

   NOTHING HERE TOUCHES SHEET GEOMETRY (the law at the top of this file): no height, min-height,
   flex or margin is set on a .sheet. The one size this block does set is the LEAD PANE's own
   max-height, which is an inner scroll region, and it exists for a measured reason. A 430x900
   phone sheet gives about 713px, the pricing tool alone needs roughly 340 of it, and the full lead
   runs about 780px on its own, so on a phone SOMETHING has to give. Version A's answer: the lead
   detail takes one short swipe, and the money block below it never moves and never clips.
   ================================================================================================ */

/* The map yields, always. flex:1 1 auto with min-height:0 means the sheet sizes to its content up
   to the geometry cap and the map takes whatever is left, which at the cap is exactly the 5 percent
   gap the law reserves under the header. A fixed map min-height here would force the frame to
   overflow on a dense sheet, which is the failure this one line makes impossible. */
.fx-off .map{flex:1 1 auto;min-height:0}
.fx-off .hd-logo{font-size:var(--t-small)}
.fx-off .hd-logo:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}

/* the two ways out share one row (Version A). Stacked they cost about 116px, which is exactly what
   the dense layout does not have; side by side both stay full height and both stay visible. */
:is(.fx-off,.fx-pricing) .cta.go{background:var(--good)}
:is(.fx-off,.fx-pricing) .cta.bad{background:var(--red)}
:is(.fx-off,.fx-pricing) .cta.sm{min-height:50px;font-size:var(--t-body)}
:is(.fx-off,.fx-pricing) .cta.sm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem}
:is(.fx-off,.fx-pricing) .fx-off-acts2{display:flex;gap:9px;margin-bottom:2px;flex:0 0 auto}
:is(.fx-off,.fx-pricing) .fx-off-acts2 .cta{flex:1 1 0;min-width:0;font-size:var(--t-body)}
:is(.fx-off,.fx-pricing) .fx-off-acts2 .cta:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem}
:is(.fx-off,.fx-pricing) .fx-off-acts2 .cta.go{flex:0 0 41%}
/* STATUS UNDER ITS BUTTON: the receipt row mirrors the button row cell for cell, so each message
   lands under the exact control that caused it rather than under whichever one it drifts to. */
:is(.fx-off,.fx-pricing) .fx-off-stats{margin-bottom:0}
:is(.fx-off,.fx-pricing) .fx-off-stats .fx-off-st{flex:1 1 0;min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-stats .fx-off-st:last-child{flex:0 0 41%}

/* THE LEAD, IN HIS PRIORITY ORDER: name, then WHAT KIND OF RIDE, then pick-up, then drop-off, then
   date, time and passengers with REAL weight, never the muted sub-line they used to be. */
/* THE MONEY BLOCK NEVER MOVES. Measured at 430x900: the sheet caps at 713px, and with the whole
   surface in one scroll the action buttons landed at y=1277, off screen, so the one control the
   screen exists for needed a scroll to reach. The fix is structural, not a tuned pane height: the
   2col FILLS the sheet, the LEAD column takes what is left and scrolls, and the MONEY column is
   flex:0 0 auto so it can never be shrunk or pushed out, whatever a client wrote in their notes. */
:is(.fx-off,.fx-pricing) .fx-off-2col{display:flex;flex-direction:column;gap:0;flex:1 1 auto;min-height:0}
:is(.fx-off,.fx-pricing) .fx-off-2col > div{min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-2col > div:first-child{flex:1 1 auto;min-height:0;overflow-y:auto}
:is(.fx-off,.fx-pricing) .fx-off-2col > div:last-child{flex:0 0 auto}
:is(.fx-off,.fx-pricing) .fx-off-name{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);
  margin:2px 2px 9px;flex-wrap:wrap;flex:0 0 auto}
:is(.fx-off,.fx-pricing) .fx-off-name .nm{font-family:var(--body);font-size:var(--t-card);line-height:1.1;font-weight:600}
:is(.fx-off,.fx-pricing) .fx-off-name .nm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.45rem;line-height:1.1}
:is(.fx-off,.fx-pricing) .fx-off-name .bset{display:flex;gap:6px;flex-wrap:wrap}
:is(.fx-off,.fx-pricing) .fx-off-name .badge[hidden]{display:none!important}

/* an explicit display silently BEATS the UA's [hidden] rule, so every component in this family
   pins its own hidden state (the 2026-07-31 lesson; found again here by measuring a "hidden"
   decline banner that was rendering 64px tall) */
:is(.fx-off,.fx-pricing) .row[hidden],:is(.fx-off,.fx-pricing) .fx-off-type[hidden],:is(.fx-off,.fx-pricing) .fx-off-ab[hidden],
:is(.fx-off,.fx-pricing) .fx-off-when[hidden],:is(.fx-off,.fx-pricing) .fx-off-more[hidden],:is(.fx-off,.fx-pricing) .fx-off-prices[hidden],
:is(.fx-off,.fx-pricing) .fx-off-basis[hidden],:is(.fx-off,.fx-pricing) .fx-off-bseg[hidden],
:is(.fx-off,.fx-pricing) .fx-off-ovr[hidden],:is(.fx-off,.fx-pricing) .fx-off-acts2[hidden],:is(.fx-off,.fx-pricing) .fx-off-chip[hidden],
:is(.fx-off,.fx-pricing) .fx-off-quote[hidden],:is(.fx-off,.fx-pricing) .fx-off-okcard[hidden],:is(.fx-off,.fx-pricing) .fx-off-why[hidden],
:is(.fx-off,.fx-pricing) .fx-off-trip[hidden],:is(.fx-off,.fx-pricing) .fx-off-pane[hidden],.fx-set .fx-off-ovr[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-type{display:flex;align-items:center;gap:10px;background:#FFF1EC;border:1.5px solid var(--orange);
  border-radius:13px;padding:var(--sp-2) var(--sp-3);min-height:var(--tap-min);margin-bottom:var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-type svg{width:23px;height:23px;flex:0 0 auto;fill:none;stroke:var(--orange);
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
:is(.fx-off,.fx-pricing) .fx-off-type b{font-size:var(--t-body);line-height:var(--lh-body);display:block}
:is(.fx-off,.fx-pricing) .fx-off-type b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.02rem;line-height:1.15}
:is(.fx-off,.fx-pricing) .fx-off-type span{font-size:var(--t-small);color:var(--muted);display:block;line-height:var(--lh-small)}
:is(.fx-off,.fx-pricing) .fx-off-type span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;line-height:1.25}

/* PICK-UP AND DROP-OFF SHARE ONE CARD (measured: two cards spend about 36px on two borders, two
   paddings and two margins to say one thing, and 36px is what the priority strip needs). */
:is(.fx-off,.fx-pricing) .fx-off-ab{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:2px var(--sp-3);margin-bottom:var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-ab .ln{display:flex;align-items:center;gap:10px;min-height:var(--tap-min);
  border-bottom:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-ab .ln:last-child{border-bottom:none}
:is(.fx-off,.fx-pricing) .fx-off-ab .pin{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:var(--ink);color:#fff;
  display:flex;align-items:center;justify-content:center;font-family:var(--body);font-size:var(--t-small)}
:is(.fx-off,.fx-pricing) .fx-off-ab .pin:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:.76rem}
:is(.fx-off,.fx-pricing) .fx-off-ab .pin.b{background:var(--orange)}
:is(.fx-off,.fx-pricing) .fx-off-ab .tx{flex:1 1 auto;min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-ab .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--muted);display:block}
:is(.fx-off,.fx-pricing) .fx-off-ab b{display:block;font-size:var(--t-body);line-height:var(--lh-body);word-break:break-word}
:is(.fx-off,.fx-pricing) .fx-off-ab b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.94rem;line-height:1.15}
:is(.fx-off,.fx-pricing) .fx-off-ab .s{display:block;font-size:var(--fs-label);color:var(--muted);line-height:1.2;word-break:break-word}
:is(.fx-off,.fx-pricing) .fx-off-ab .tag{flex:0 0 auto;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.06em;background:var(--paper);color:var(--ink);border-radius:8px;padding:5px 9px}
:is(.fx-off,.fx-pricing) .fx-off-ab .tag[hidden]{display:none!important}

/* DATE, TIME, PASSENGERS read too quietly as a sub-line, so they get their own loud strip.
   Lime labels on the dark surface, grey on white, never the reverse (the standing law). */
:is(.fx-off,.fx-pricing) .fx-off-when{display:flex;background:var(--ink);border-radius:13px;padding:7px var(--sp-1);margin-bottom:var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-when > div{flex:1 1 0;min-width:0;padding:0 9px;border-left:1px solid #33322F}
:is(.fx-off,.fx-pricing) .fx-off-when > div:first-child{border-left:none}
:is(.fx-off,.fx-pricing) .fx-off-when .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--lime);display:block;margin-bottom:2px}
:is(.fx-off,.fx-pricing) .fx-off-when b{display:block;color:#fff;font-family:var(--body);
  font-size:var(--t-body);line-height:var(--lh-body);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
:is(.fx-off,.fx-pricing) .fx-off-when b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:.96rem;line-height:1.15}
:is(.fx-off,.fx-pricing) .fx-off-when .s{display:block;color:#C6C3BC;font-size:var(--fs-label);line-height:1.2}

/* EVERYTHING ELSE THEY SENT, dense two-up so all of it is on screen at once once opened */
:is(.fx-off,.fx-pricing) .fx-off-grid{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:9px}
:is(.fx-off,.fx-pricing) .fx-off-grid[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-grid > div{background:var(--paper);border:1px solid var(--line);border-radius:11px;
  padding:7px 10px;min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-grid > div.wide{grid-column:1 / -1}
:is(.fx-off,.fx-pricing) .fx-off-grid .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--muted);display:block;margin-bottom:1px}
:is(.fx-off,.fx-pricing) .fx-off-grid b{display:block;font-size:var(--t-small);line-height:var(--lh-small);word-break:break-word}
:is(.fx-off,.fx-pricing) .fx-off-grid b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.2}
:is(.fx-off,.fx-pricing) .fx-off-grid .s{display:block;font-size:var(--fs-label);color:var(--muted);line-height:1.25}

/* ONE row that NAMES exactly what is inside it, expands IN PLACE, and never hides the fact that
   there is more. An affordance reading "flight, bags, stops, notes, contact" is not a hidden field. */
:is(.fx-off,.fx-pricing) .fx-off-more{display:flex;align-items:center;gap:10px;background:var(--card);border:1.5px dashed var(--line);
  border-radius:13px;padding:var(--sp-2) var(--sp-3);min-height:var(--tap-min);margin-bottom:var(--sp-2);cursor:pointer}
:is(.fx-off,.fx-pricing) .fx-off-more svg{width:22px;height:22px;flex:0 0 auto;fill:none;stroke:var(--ink);
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
:is(.fx-off,.fx-pricing) .fx-off-more .tx{flex:1 1 auto;min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-more b{display:block;font-size:var(--t-small)}
:is(.fx-off,.fx-pricing) .fx-off-more b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
:is(.fx-off,.fx-pricing) .fx-off-more span{display:block;font-size:var(--fs-label);color:var(--muted);line-height:1.25}
:is(.fx-off,.fx-pricing) .fx-off-more .aff{flex:0 0 auto;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.06em;background:var(--ink);color:#fff;border-radius:8px;padding:6px var(--sp-3)}

/* WHERE THE SCROLL GOES. Version A collapses everything past priority five behind the row above,
   so the open part takes one short swipe on a phone while the money block below never moves. */
/* the lead column above IS the scroll region now, so this inner cap would only add a second
   scrollbar inside the first */
:is(.fx-off,.fx-pricing) .fx-off-pane{overflow:visible}

/* THE MEASURED DRIVE, sitting directly on top of the two prices. Ahmed does the arithmetic himself
   ("21.4 miles, so in my mind I already know it needs to be around $42"), so the two numbers he
   multiplies are never on another screen and never in small print. */
:is(.fx-off,.fx-pricing) .fx-off-meas{display:flex;background:var(--card);border:2px solid var(--ink);border-radius:13px;
  padding:6px var(--sp-1);margin-bottom:var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-meas[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-meas > div{flex:1 1 0;min-width:0;padding:0 9px;border-left:1px solid var(--line);
  display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
:is(.fx-off,.fx-pricing) .fx-off-meas > div:first-child{border-left:none}
:is(.fx-off,.fx-pricing) .fx-off-meas .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--muted);flex:1 0 100%}
:is(.fx-off,.fx-pricing) .fx-off-meas b{font-family:var(--body);font-size:var(--t-card);line-height:1.1;font-weight:600}
:is(.fx-off,.fx-pricing) .fx-off-meas b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.32rem;line-height:1.1}
:is(.fx-off,.fx-pricing) .fx-off-meas .u{font-size:var(--t-small);color:var(--muted);font-weight:700}
:is(.fx-off,.fx-pricing) .fx-off-meas .u:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;font-weight:700}

/* OFFER WITHOUT A DISTANCE STILL WORKS: the route came back empty, so the same place carries two
   fields he types into and both prices compute from what he entered. */
:is(.fx-off,.fx-pricing) .fx-off-man{display:flex;gap:9px;margin-bottom:9px}
:is(.fx-off,.fx-pricing) .fx-off-man[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-man > div{flex:1 1 0;min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-man .lb{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.07em;text-transform:uppercase;color:var(--muted);display:block;margin-bottom:var(--sp-1)}
:is(.fx-off,.fx-pricing) .fx-off-man .bx{min-height:52px;border:1.5px solid var(--red);border-radius:var(--r-input);background:var(--card);
  display:flex;align-items:center;padding:0 13px}
/* the quiet note: a rough drive time, or the address that failed. Warning text is RED (global law). */
:is(.fx-off,.fx-pricing) .fx-off-rnote{display:block;font-size:var(--t-small);font-weight:700;color:var(--red);line-height:var(--lh-small);
  margin:-2px 2px var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-rnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;font-weight:700;line-height:1.3}
:is(.fx-off,.fx-pricing) .fx-off-rnote[hidden]{display:none!important}

/* THE TWO NUMBERS, side by side, never behind a toggle, never more than zero taps away. The dark
   instrument block with lime labels is the highest contrast pairing in the app, on purpose, because
   Ahmed's own words are "this is critical, it needs to stand out, be vibrant and very easy for me
   to see, I click on this every single time I make an offer". The one in use carries the orange ring. */
:is(.fx-off,.fx-pricing) .fx-off-prices{display:flex;gap:9px;margin-bottom:7px}
:is(.fx-off,.fx-pricing) .fx-off-p{flex:1 1 0;min-width:0;background:var(--ink);color:#fff;border:2px solid var(--ink);
  border-radius:var(--r-ctl);padding:var(--sp-2) 10px;display:flex;flex-direction:column;gap:1px;min-height:80px;
  cursor:pointer;text-align:left;font-family:inherit}
:is(.fx-off,.fx-pricing) .fx-off-p .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--lime)}
:is(.fx-off,.fx-pricing) .fx-off-p .amt{font-family:var(--display);font-size:var(--t-big);line-height:1.05}
:is(.fx-off,.fx-pricing) .fx-off-p .amt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.85rem;line-height:1.05}
:is(.fx-off,.fx-pricing) .fx-off-p .s{font-size:var(--t-small);color:var(--lime);font-weight:700;line-height:var(--lh-small)}
:is(.fx-off,.fx-pricing) .fx-off-p .s:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;font-weight:700;line-height:1.25}
/* THE CHOSEN CARD IS GREEN, WHOLE CARD, NOT A RING (b32, Ahmed's first live run 2026-08-14: "I
   couldn't tell which one I'd picked"). An orange 2px border on an almost-black card is a 2px
   difference on a phone held at arm's length, and the quiet grey "TAP TO USE" line that was the
   other half of the affordance was, in his words, too subtle on a left side that is already
   congested. GREEN IS GOOD is the app's standing colour law, and choosing a price is the good
   outcome, so the selected card takes the good-green token as its entire background. That is a
   change of the loudest property the card has, unmissable at a glance, and it costs no space.
   The label and the sub-line go WHITE here: lime on green is the one pairing in this palette with
   no contrast left, and the lime rule is about labels on the DARK surface. The pill stays as a
   named state so the choice is never carried by colour alone. */


:is(.fx-off,.fx-pricing) .fx-off-p .pick{margin-top:auto;align-self:flex-start;background:var(--card);color:var(--good);border-radius:var(--r-pill);
  padding:3px 9px;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.07em}
:is(.fx-off,.fx-pricing) .fx-off-p .pick[hidden]{display:none!important}

/* ONE CONTROL, TWO WORDS (b32). Which drive is he pricing: the passenger's leg, or his whole
   outing from home and back. Flipping it re-reads the distance, the drive time, both price cards
   and the earnings line from that basis. Ahmed's constraint, verbatim: keep it simple, drivers are
   not that smart, the old offer page failed by being cumbersome. So it is ONE segmented control on
   the surface he is already looking at, no second screen and no explanation paragraph.
   It sits directly ABOVE the measured drive because that is the number it changes. */
:is(.fx-off,.fx-pricing) .fx-off-basis{display:flex;gap:0;background:var(--paper);border:1.5px solid var(--ink);
  border-radius:13px;padding:3px;margin-bottom:var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-basis[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-bseg{flex:1 1 0;min-width:0;min-height:var(--tap-min);cursor:pointer;display:flex;align-items:center;justify-content:center;
  padding:0 6px;text-align:center;line-height:1.15}

:is(.fx-off,.fx-pricing) .fx-off-bseg[disabled]{opacity:.42;cursor:default}
/* why the other half is unavailable, said plainly, in red, exactly where it applies */
:is(.fx-off,.fx-pricing) .fx-off-bnote{display:block;font-size:var(--t-small);font-weight:700;color:var(--red);line-height:var(--lh-small);
  margin:-4px 2px var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-bnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;font-weight:700;line-height:1.3}
:is(.fx-off,.fx-pricing) .fx-off-bnote[hidden]{display:none!important}

/* HIS OWN NUMBER. Big steppers, NEVER a native spinner (Ahmed's standing rule, 2026-07-19: he
   cannot hit the arrows, so any increment gets a real 48px+ target). Typing is always allowed. */
:is(.fx-off,.fx-pricing) .fx-off-ovr,.fx-set .fx-off-ovr{display:flex;align-items:center;gap:var(--sp-2);margin-bottom:7px}
:is(.fx-off,.fx-pricing) .fx-off-step,.fx-set .fx-off-step{flex:0 0 auto;min-width:var(--tap-min);
  min-height:var(--tap-min);display:flex;
  align-items:center;justify-content:center;cursor:pointer;color:var(--ink)}
:is(.fx-off,.fx-pricing) .fx-off-in,.fx-set .fx-off-in{flex:1 1 auto;min-width:0;min-height:52px;border:1.5px solid var(--ink);
  border-radius:13px;background:var(--card);display:flex;align-items:center;justify-content:center;gap:6px;padding:0 10px}
:is(.fx-off,.fx-pricing) .fx-off-in .lb,.fx-set .fx-off-in .lb{flex:0 0 auto;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
:is(.fx-off,.fx-pricing) .fx-off-in .cur,.fx-set .fx-off-in .cur{flex:0 0 auto;font-family:var(--body);
  font-size:var(--t-page);line-height:1;font-weight:600}
:is(.fx-off,.fx-pricing) .fx-off-in .cur:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-set .fx-off-in .cur:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.45rem;line-height:1}
:is(.fx-off,.fx-pricing) .fx-off-in.warnbox{border-color:var(--red)}
/* the field itself. NO native spinner in either engine, and the box never grows past its row. */
/* THE FIELD IS THE TAP TARGET, not the box around it (measured: the input rendered 31px inside a
   52px row, so the 48px law was met by the container and missed by the only thing you can tap to
   focus). align-self:stretch makes the whole row focus the field. */
:is(.fx-off,.fx-pricing) .fx-off-num,.fx-set .fx-off-num{flex:1 1 auto;min-width:0;width:100%;border:none;outline:none;
  background:transparent;font-family:var(--body);font-size:var(--t-page);
  color:var(--ink);padding:0;align-self:stretch;min-height:48px;
  -moz-appearance:textfield;appearance:textfield;font-weight:600}
:is(.fx-off,.fx-pricing) .fx-off-num:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-set .fx-off-num:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.45rem}
:is(.fx-off,.fx-pricing) .fx-off-num::-webkit-outer-spin-button,:is(.fx-off,.fx-pricing) .fx-off-num::-webkit-inner-spin-button,
.fx-set .fx-off-num::-webkit-outer-spin-button,.fx-set .fx-off-num::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
:is(.fx-off,.fx-pricing) .fx-off-man .fx-off-num{font-size:var(--t-body);font-family:'Space Grotesk',sans-serif;font-weight:700;min-height:48px}
:is(.fx-off,.fx-pricing) .fx-off-man .fx-off-num:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.05rem;font-family:'Space Grotesk',sans-serif;font-weight:700}

/* ONE LINE saying whether the number he landed on is healthy. Green good, red bad, global law. */
:is(.fx-off,.fx-pricing) .fx-off-chk{text-align:center;font-size:var(--t-small);font-weight:700;margin:0 0 6px;line-height:var(--lh-small);
  color:var(--muted)}
:is(.fx-off,.fx-pricing) .fx-off-chk:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;font-weight:700;line-height:1.3}
:is(.fx-off,.fx-pricing) .fx-off-chk.good{color:var(--good)}
:is(.fx-off,.fx-pricing) .fx-off-chk.bad{color:var(--red)}

/* STATUS UNDER ITS BUTTON, centered, large enough to notice (0.95rem+), green good red bad */
:is(.fx-off,.fx-pricing) .fx-off-st{text-align:center;font-size:var(--t-body);font-weight:700;margin:5px 0 2px;line-height:var(--lh-body);
  color:var(--muted)}
:is(.fx-off,.fx-pricing) .fx-off-st:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700;line-height:1.3}
:is(.fx-off,.fx-pricing) .fx-off-st.good{color:var(--good)}
:is(.fx-off,.fx-pricing) .fx-off-st.bad{color:var(--red)}
:is(.fx-off,.fx-pricing) .fx-off-st.neu{color:var(--muted)}
:is(.fx-off,.fx-pricing) .fx-off-st[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-gap{height:6px}

/* ---- passenger surfaces ------------------------------------------------------------------- */
:is(.fx-off,.fx-pricing) .fx-off-quote{background:var(--ink);color:#fff;border-radius:16px;padding:15px 14px;text-align:center;margin-bottom:9px}
:is(.fx-off,.fx-pricing) .fx-off-quote .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--lime)}
:is(.fx-off,.fx-pricing) .fx-off-quote .big{font-family:var(--display);font-size:var(--t-big);
  line-height:1.05;margin:3px 0 2px}
:is(.fx-off,.fx-pricing) .fx-off-quote .big:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:2.9rem;line-height:1.05}
:is(.fx-off,.fx-pricing) .fx-off-quote .sub{color:#C6C3BC;font-size:var(--t-small);line-height:var(--lh-small)}
:is(.fx-off,.fx-pricing) .fx-off-quote .sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;line-height:1.35}
:is(.fx-off,.fx-pricing) .fx-off-okcard{background:var(--good-tint);border:1.5px solid var(--good);border-radius:15px;padding:13px;
  text-align:center;margin-bottom:9px}
:is(.fx-off,.fx-pricing) .fx-off-okcard .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--good)}
:is(.fx-off,.fx-pricing) .fx-off-okcard .big{font-family:var(--display);font-size:var(--t-big);
  color:var(--ink);margin:3px 0 2px}
:is(.fx-off,.fx-pricing) .fx-off-okcard .big:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:2rem}
:is(.fx-off,.fx-pricing) .fx-off-okcard .sub{font-size:var(--t-small);color:var(--muted);line-height:var(--lh-small)}
:is(.fx-off,.fx-pricing) .fx-off-okcard .sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.35}

/* telling the driver why, expands IN PLACE on the same sheet, never a popup, never another page */
:is(.fx-off,.fx-pricing) .fx-off-why{border:1.5px solid var(--red);border-radius:var(--r-ctl);padding:var(--sp-3);background:#FDEBE7;margin-bottom:9px}
:is(.fx-off,.fx-pricing) .fx-off-why .ttl{font-weight:700;font-size:var(--t-body);margin-bottom:2px}
:is(.fx-off,.fx-pricing) .fx-off-why .ttl:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.92rem}
:is(.fx-off,.fx-pricing) .fx-off-why .sub{font-size:var(--t-small);color:var(--muted);line-height:var(--lh-small)}
:is(.fx-off,.fx-pricing) .fx-off-why .sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;line-height:1.3}
:is(.fx-off,.fx-pricing) .fx-off-chips{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin:9px 0 var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-chip{min-height:var(--tap-min);display:flex;align-items:center;padding:0 15px;border-radius:var(--r-input);
  background:var(--card);border:1.5px solid var(--line);font-family:inherit;font-weight:700;font-size:var(--t-small);
  color:var(--ink);cursor:pointer}
:is(.fx-off,.fx-pricing) .fx-off-chip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:inherit;font-weight:700;font-size:.85rem}
:is(.fx-off,.fx-pricing) .fx-off-chip.on{border-color:var(--red);color:var(--red)}
:is(.fx-off,.fx-pricing) .fx-off-note{display:block;width:100%;min-height:52px;border:1.5px solid var(--line);border-radius:var(--r-input);
  background:var(--card);padding:10px 13px;font-family:'Space Grotesk',sans-serif;font-size:var(--t-small);color:var(--ink);
  margin-bottom:9px;resize:none}
:is(.fx-off,.fx-pricing) .fx-off-note:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-size:.85rem}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln{display:flex;align-items:center;gap:11px;min-height:52px;border-bottom:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln:last-child{border-bottom:none}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln svg{width:21px;height:21px;flex:0 0 auto;fill:none;stroke:var(--ink);
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln .tx{flex:1 1 auto;min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln .tx b{display:block;font-size:var(--t-small)}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln .tx span{display:block;font-size:var(--t-small);color:var(--muted)}
:is(.fx-off,.fx-pricing) .fx-off-trip .ln .tx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.75rem}
/* the empty states, the same components My rides already uses, never a blank panel */
:is(.fx-off,.fx-pricing) .rstat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;color:var(--muted);margin:var(--sp-4) 0 var(--sp-1)}
:is(.fx-off,.fx-pricing) .rstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
:is(.fx-off,.fx-pricing) .rsub{display:block;text-align:center;font-size:var(--t-small);color:var(--muted);margin:0 0 var(--sp-3)}
:is(.fx-off,.fx-pricing) .rsub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
/* b33: the empty state carries TWO doors out now (a deep link that could not be honoured reports
   here, and one door is not a choice), and .cta is display:block so they stack and need the gap. */
:is(.fx-off,.fx-pricing) [data-ost="empty"] .cta + .cta{margin-top:9px}
/* a deep link that FAILED says so in red, on the line that normally says "nothing to price": the
   difference between "no work waiting" and "that ride could not be opened" is the whole message */
:is(.fx-off,.fx-pricing) [data-ost="empty"] .rstat.bad{color:var(--red)}
:is(.fx-off,.fx-pricing) [data-ost][hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .pill[hidden]{display:none!important}

/* ---- NEW REQUESTS, the lead list. Reuses My rides' list component whole ---------------------- */
.fx-leads .rrow{cursor:pointer;align-items:flex-start}
.fx-leads .aff.warn{background:var(--red);color:#fff}

/* ---- SETTINGS > YOUR RATES, the same stepper component the offer sheet uses ------------------ */
.fx-set .fx-rates .fx-ml{margin-top:10px}
.fx-set .fx-rates .fx-ml:first-child{margin-top:0}
.fx-set .ratestat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;margin:2px 0 var(--sp-2);cursor:pointer}
.fx-set .ratestat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-set .ratestat[hidden]{display:none!important}
/* THE BASIS GROUP HEADING (b33). Four rates in two pairs need the pairs NAMED, in the same two
   words the offer sheet's toggle uses, or "A mile" appears twice with nothing saying which drive
   it prices. Its own component rather than a reused .fx-ml: this is a heading over a group, not a
   caption on a field, and giving it .fx-ml's small grey caps would make it read as one. */
.fx-set .fx-rates .fx-rgrp{margin:20px 0 10px;padding-top:var(--sp-3);border-top:1.5px solid var(--ink)}
.fx-set .fx-rates .fx-rgrp:first-child{margin-top:0;padding-top:0;border-top:none}
.fx-set .fx-rates .fx-rgrp b{display:block;font-family:var(--body);
  font-size:var(--t-body);line-height:var(--lh-body);color:var(--ink)}
.fx-set .fx-rates .fx-rgrp b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black','Space Grotesk',sans-serif;font-size:1.05rem;line-height:1.2}
.fx-set .fx-rates .fx-rgrp span{display:block;margin-top:3px;font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.fx-set .fx-rates .fx-rgrp span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;line-height:1.3}
.fx-set .fx-rates .fx-rgrp[hidden]{display:none!important}


/* ================================================================================================
   THE OFFER, LONG FORMAT (Z Fold open). Long is wider than it is tall, so the column that stacks in
   tall sits SIDE BY SIDE here instead, lead on the left and money on the right, and the dense detail
   grid opens out to three across. Same components, same tokens, only the arrangement moves.

   THIS BLOCK LIVES AT THE END OF THE FILE ON PURPOSE. Its first version was inserted inside the
   shared format media query at line 526, which is BEFORE the tall rules above; at equal specificity
   the later rule wins, so the tall single-column rule quietly beat this grid and 900x720 rendered
   the wrong layout. Measured, not read.
   ================================================================================================ */
@media (min-aspect-ratio: 6/5){
  :is(.fx-off,.fx-pricing) .fx-off-2col{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-4);
    align-items:stretch;flex:1 1 auto;min-height:0}
  /* both columns own their own scroll, so neither can push the other's controls off the sheet */
  :is(.fx-off,.fx-pricing) .fx-off-2col > div:first-child,
  :is(.fx-off,.fx-pricing) .fx-off-2col > div:last-child{min-height:0;overflow-y:auto;flex:initial}
  :is(.fx-off,.fx-pricing) .fx-off-grid{grid-template-columns:1fr 1fr 1fr}
  :is(.fx-off,.fx-pricing) .fx-off-name .nm{font-size:var(--t-card);font-weight:600}
:is(.fx-off,.fx-pricing) .fx-off-name .nm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.3rem}
  .fx-set .fx-rates .fx-off-ovr{max-width:520px}
}


/* ==================================================================================================
   b39, 2026-08-16. HOME'S QUICK TOOLS, MY TRIPS, AND THE QUOTE SHEET.
   ================================================================================================== */

/* THE SOON CHIP ON A TILE. Same component as the Settings hub's SOON chip (b34), positioned like
   the request badge it shares a corner convention with, so a driver reads "not yet" before tapping
   rather than after. .aff.lite already paints it; this only places it and stops it reading as an
   action. */
/* SOON IS TOO EASY TO MISS IN GREY (Ahmed, after testing b39). It was muted text on paper inside a
   hairline border, at .58rem and 85% opacity, which is the styling of something you are meant to
   ignore, and he tapped tiles expecting them to work. It now uses the shell's existing accent token
   (Forge Orange, --orange, no new colour) as a SOLID fill, which is the same treatment the request
   and inbox badges already use for "look here" in this file. Full opacity, because a badge whose
   job is to be noticed must not be faded. */
.tile .fx-soon{position:absolute;top:8px;right:10px;opacity:1;letter-spacing:.08em;
  font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:800;padding:3px 7px;
  border-radius:7px;border:1px solid var(--orange);background:var(--orange);color:#fff}
/* a SOON tile is still a full tap target, it just says less will happen. The tile no longer dims:
   dimming the whole tile is what made the badge fade with it. */
.tile[data-act^="soon"]{opacity:1}

/* THE HONEST SENTENCE, under the grid or the button row that was pressed (the status-under-its-
   button law, adapted: a line inside one cell of a six-cell grid reflows the other five). */
.toolnote{display:block;margin:2px 2px var(--sp-2);padding:11px 13px;border:1px solid var(--line);
  border-left:3px solid var(--orange);border-radius:var(--r-input);background:var(--card);color:var(--ink);
  font-size:var(--t-small);line-height:var(--lh-small)}
.toolnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.4}
.toolnote[hidden]{display:none!important}
.toolnote p{margin:0 0 var(--sp-2)}
.toolnote p:last-child{margin:0}

/* MY TRIPS. It is an .fx-rides screen, so the list rows, the empty state and the error card are the
   SAME components My rides uses; one family, nothing new invented. Only what differs is here. */
.fx-trips .trow{cursor:default}
/* AMOUNT NOT SAVED is the one thing on this screen that must never read as a price. It is the
   warn colour, not a dollar sign, and its row is excluded from the total below it. */
.fx-trips .rrow .aff.warn{background:var(--red);color:#fff;font-size:var(--fs-label);letter-spacing:.06em;
  text-align:center;line-height:1.15;max-width:96px;white-space:normal}
.fx-trips .ttotal{background:var(--paper);border-color:var(--line)}
.fx-trips .ttotal .tx b{font-family:'JetBrains Mono',monospace;letter-spacing:.08em;font-size:var(--fs-label);
  color:var(--muted)}
.fx-trips .ttotal .aff{background:var(--ink);color:#fff;font-size:var(--t-label)}
.fx-trips .ttotal .aff:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem}
.fx-trips .tripnote{display:block;margin:10px 2px 2px;padding:11px 13px;border:1px solid var(--line);
  border-left:3px solid var(--orange);border-radius:var(--r-input);background:var(--card);color:var(--muted);
  font-size:var(--t-small);line-height:var(--lh-small)}
.fx-trips .tripnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.45}
.fx-trips .tripnote[hidden]{display:none!important}
.fx-trips .tripnote p{margin:0 0 var(--sp-2);color:var(--muted)}
.fx-trips .tripnote p:last-child{margin:0}

/* THE VEHICLE PICKER'S honest second row: it names where a car is added, it is not a car. */
.fx-entry .vehlist .vrow.fx-vnote{color:var(--muted);font-size:var(--t-small);cursor:default}
.fx-entry .vehlist .vrow.fx-vnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem}
.fx-entry .vehlist .vrow.fx-vnote .vtx{color:var(--muted)}

/* THE QUOTE SHEET's own line, where the two commit buttons sit on a real lead. Same width, same
   place, so the sheet does not jump between the two modes. */
:is(.fx-off,.fx-pricing) .fx-off-quote{display:block;margin:10px 0 0;padding:11px 13px;border:1px solid var(--line);
  border-left:3px solid var(--orange);border-radius:var(--r-input);background:var(--card);color:var(--ink);
  font-size:var(--t-small);line-height:var(--lh-small)}
:is(.fx-off,.fx-pricing) .fx-off-quote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.4}
:is(.fx-off,.fx-pricing) .fx-off-quote[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-acts2[hidden]{display:none!important}

/* ================================================================================================
   b43, THE CLOSE-OUT AND THE PAYMENT HANDLES.

   The close-out review lives INSIDE the finished-trip card (.rsdone), not beside it, which is why
   none of the [data-rsdone="1"] hide rules above can reach it: they hide direct children of the
   sheet, and this is two levels deeper. It reuses .tiprow / .tipstep / .tipin from the tip editor
   ON PURPOSE, so the 56px steppers and the 48px field target are the ones already measured and
   proven rather than a second set that can drift.
   ================================================================================================ */
.fx-ride .clsec{display:block;margin:0 0 var(--sp-3)}
.fx-ride .clsec .cl-x{display:none}
/* its own closed state is STATED, never assumed: an explicit display beats [hidden] (2026-07-31) */
/* b293: THE CLOSE-OUT DECIDES AT THE TOP (Ahmed 2026-09-09, report 9: "paid now, pays later, and
   save this trip could be right there on the third row, that way I only go down when I need to").
   The box is a flex column so the ORDER is a style: the Payment label, the PAID NOW / PAYS LATER
   pair, then Save this trip and its status line, then everything he only sometimes touches. */
.fx-ride .clsec[data-open="1"] .cl-x{display:flex;flex-direction:column;background:var(--card);border:1.5px solid var(--ink);
  border-radius:var(--r-ctl);padding:var(--sp-3) var(--sp-3) var(--sp-1);margin:0 0 var(--sp-1)}
.fx-ride .clsec[data-open="1"] .cl-x > .fx-ml:first-child{order:-4}
.fx-ride .clsec[data-open="1"] .cl-x > .clpaid{order:-3}
.fx-ride .clsec[data-open="1"] .cl-x > .fx-btns:has([data-cl="savebtn"]){order:-2;margin-bottom:var(--sp-3)}
.fx-ride .clsec[data-open="1"] .cl-x > [data-prof="clstat"]{order:-1}

/* WHAT WAS AGREED IS A FACT, NOT A CONTROL. Dashed, unpressable, and it reads before the boxes,
   because "we said $100" is the thing every number under it is measured against. */
.fx-ride .clsec .clfact{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  border:1.5px dashed var(--line);border-radius:var(--r-input);background:var(--paper);
  padding:10px var(--sp-3);margin:0 0 10px;min-height:var(--tap-min)}
.fx-ride .clsec .clfact .fx-k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.fx-ride .clsec .clfact b{font-size:var(--t-card);font-weight:600}
.fx-ride .clsec .clfact b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.15rem;font-weight:800}
.fx-ride .clsec .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:10px 0 var(--sp-2)}
.fx-ride .clsec .setnote{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);margin:10px 0 0}
.fx-ride .clsec .setnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.5}
.fx-ride .clsec .fx-btns{display:flex;gap:10px;margin-top:var(--sp-3)}
.fx-ride .clsec .fx-btns[hidden]{display:none!important}
.fx-ride .clsec .fx-save{flex:1 1 0;cursor:pointer}
.fx-ride .clsec .fx-save[disabled]{opacity:.55;cursor:default}
.fx-ride .clsec .fx-cancel{flex:1 1 0;cursor:pointer}
.fx-ride .clsec .profstat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;
  margin:10px 0 var(--sp-1);cursor:pointer}
.fx-ride .clsec .profstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-ride .clsec .profstat[hidden]{display:none!important}
/* THE RUNNING TOTAL. Three rows, the last one loud, because the number he is about to charge is
   the one thing on this panel he must not be able to misread. */
.fx-ride .cllines{margin:var(--sp-3) 0 0;border-top:1px solid var(--line)}
.fx-ride .clrow{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:9px 0;border-bottom:1px solid var(--line);font-size:var(--t-body)}
.fx-ride .clrow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
.fx-ride .clrow[hidden]{display:none!important}
.fx-ride .clrow span{color:var(--muted)}
.fx-ride .clrow b{font-weight:700;text-align:right;overflow-wrap:anywhere}
.fx-ride .clrow.cltot{border-bottom:none;padding-top:var(--sp-3)}
.fx-ride .clrow.cltot span{color:var(--ink);font-weight:800}
.fx-ride .clrow.cltot b{font-size:var(--t-page);font-weight:600}
.fx-ride .clrow.cltot b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.35rem;font-weight:800}
/* THE SAVED RECEIPT, the same document the passenger is reading, on the screen he saved it from. */
.fx-ride .clrcpt{background:var(--card);border:1.5px solid var(--good);border-radius:var(--r-ctl);
  padding:var(--sp-3) 13px;margin:0 0 var(--sp-3)}
.fx-ride .clrcpt[hidden]{display:none!important}
.fx-ride .clrcpt-top{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);
  margin:0 0 var(--sp-2)}
.fx-ride .clrcpt-top span{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.fx-ride .clrcpt-top b{font-size:var(--t-big);font-weight:800;color:var(--good)}
.fx-ride .clrcpt-top b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem;font-weight:800}
.fx-ride .clrcpt-lnk{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);line-height:1.5;
  word-break:break-all;color:var(--muted);margin-top:10px;-webkit-user-select:all;user-select:all}

/* ---- SETTINGS > PAYMENT HANDLES ---------------------------------------------------------------
   One row per method: a label, the handle, and a switch big enough to press. The switch is a real
   button with a WORD on it, not a coloured dot: colour alone is invisible to anyone who cannot
   separate orange from grey, and this row decides whether a stranger is shown an account number. */
.fx-set .payrow{display:flex;align-items:center;gap:10px;margin:0 0 var(--sp-2)}
.fx-set .payrow .paylab{flex:0 0 78px;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);line-height:1.25}
.fx-set .payrow .fx-in{flex:1 1 auto;min-width:0;width:100%;min-height:var(--tap-min);
  border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);outline:none;background:var(--card);
  font:inherit;font-weight:700;font-size:var(--t-body);color:var(--ink)}
.fx-set .payrow .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:inherit;font-weight:700;font-size:.92rem}
.fx-set .payrow .fx-in:focus{border-color:var(--ink)}
.fx-set .payrow .paytg{flex:0 0 auto;min-width:64px;min-height:var(--tap-min);
  border:1.5px solid var(--ink);border-radius:var(--r-input);background:var(--ink);color:#fff;
  font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;
  cursor:pointer}
.fx-set .payrow .paytg.off{background:var(--card);color:var(--muted);border-color:var(--line)}
/* the receipt sits under the row that caused it, same law as every other control in this hub */
.fx-set .fx-editor .profstat{display:block;text-align:center;font-size:var(--t-small);font-weight:700;
  margin:0 2px 10px;cursor:pointer}
.fx-set .fx-editor .profstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;font-weight:700}
.fx-set .fx-editor .profstat[hidden]{display:none!important}

/* NARROW PHONES. At 430 the 78px label column plus a 64px switch leaves a handle box too small to
   read an email address in, so the label goes above the field and the row wraps. Measured, not
   guessed: this is the same class as the b39 label-column bug where a fixed flex basis ate a
   third of the screen and broke addresses one character per line. */
@media (max-width:440px){
  .fx-set .payrow{flex-wrap:wrap}
  .fx-set .payrow .paylab{flex:1 1 100%;margin-bottom:-2px}
  .fx-set .payrow .fx-in{flex:1 1 auto;min-width:0}
}


/* ================================================================================================
   THE TRIP DETAIL (b44, 2026-08-16). My trips, one trip open.

   It reuses .tiprow / .tipstep / .tipin from the tip editor and .cllines / .clrow from the
   close-out, because these are the same three controls doing the same three jobs and a fourth
   visual language for "type a number with a big minus and a big plus" would be a fourth thing to
   keep in step. What is NEW here is only the header, the rate block and the two confirms.

   EVERY COMPONENT WITH AN EXPLICIT display GETS ITS OWN [hidden] RULE (the 2026-07-31 lesson: an
   explicit display silently BEATS the browser's [hidden]{display:none}, and a bar meant for one
   layout rendered across every screen in Layout Radar because of exactly this).

   EVERY TAP TARGET IS var(--tap-min) OR MORE. Ahmed's standing rule, and it is a hard one: never a
   tiny native control as the only way to do something, and never a number spinner.
   ================================================================================================ */
.fx-trips .tdsec{display:block;margin:2px 0 var(--sp-3)}
.fx-trips .tdsec[hidden]{display:none!important}
.fx-trips .tdsec .cl-x{display:none}
.fx-trips .tdsec[data-open="1"] .cl-x{display:block;background:var(--card);border:1.5px solid var(--ink);
  border-radius:16px;padding:14px;margin:0}

.fx-trips .tdhead{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  padding:2px 2px var(--sp-2)}
.fx-trips .tdhead .tx{min-width:0;display:flex;flex-direction:column;gap:2px}
.fx-trips .tdhead b{font-size:var(--t-card);font-weight:600;overflow-wrap:anywhere}
.fx-trips .tdhead b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.15rem;font-weight:800}
.fx-trips .tdhead span{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.fx-trips .tdhead .badge[hidden]{display:none!important}
.fx-trips .tdtrip{font-size:var(--t-body);line-height:var(--lh-body);color:var(--muted);padding:0 2px 10px;
  overflow-wrap:anywhere}
.fx-trips .tdtrip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;line-height:1.5}

.fx-trips .tdsec .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);
  margin:14px 0 6px}
.fx-trips .tdsec .fx-ml:first-child{margin-top:0}
.fx-trips .tdsec .tiprow{display:flex;align-items:center;gap:10px}
.fx-trips .tdsec .tipstep{flex:0 0 auto;width:56px;height:56px;min-width:var(--tap-min);
  min-height:var(--tap-min);border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);
  font-size:var(--t-card);font-weight:600;line-height:1;color:var(--ink);cursor:pointer}
.fx-trips .tdsec .tipstep:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.5rem;font-weight:800;line-height:1}
.fx-trips .tdsec .tipstep:active{background:var(--paper)}
.fx-trips .tdsec .tipin{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--sp-1);
  min-height:var(--tap-min);border:1.5px solid var(--line);border-radius:var(--r-ctl);padding:0 var(--sp-3);
  background:var(--card)}
.fx-trips .tdsec .tipin.wide{width:100%}
.fx-trips .tdsec .tipin .tipcur{flex:0 0 auto;font-weight:800;color:var(--muted)}
/* THE INPUT IS THE TAP TARGET, NOT ITS WRAPPER. The box was var(--tap-min) and the field inside
   it was 22px, so the thing a thumb has to hit to start typing was under half the minimum. The rule
   is about the control. */
.fx-trips .tdsec .tipin{align-items:stretch}
.fx-trips .tdsec .tipin .tipcur{display:flex;align-items:center}
.fx-trips .tdsec .tipin .fx-in{flex:1 1 auto;min-width:0;width:100%;min-height:var(--tap-min);
  border:none;outline:none;background:transparent;font:inherit;font-weight:600;font-size:var(--t-card);
  color:var(--ink)}
.fx-trips .tdsec .tipin .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:inherit;font-weight:800;font-size:1.05rem}
/* NO NATIVE SPINNERS, ANYWHERE. He cannot hit them, and the boxes above are the tap targets. */
.fx-trips .tdsec .tipin .fx-in::-webkit-outer-spin-button,
.fx-trips .tdsec .tipin .fx-in::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.fx-trips .tdsec .tipin .fx-in{-moz-appearance:textfield;appearance:textfield}

.fx-trips .tdsec .cllines{margin:14px 0 0;border-top:1px solid var(--line)}
.fx-trips .tdsec .clrow{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:10px 0;border-bottom:1px solid var(--line);font-size:var(--t-body)}
.fx-trips .tdsec .clrow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-trips .tdsec .clrow[hidden]{display:none!important}
.fx-trips .tdsec .clrow span{color:var(--muted)}
.fx-trips .tdsec .clrow b{font-weight:700;text-align:right;overflow-wrap:anywhere}
.fx-trips .tdsec .clrow.cltot{border-bottom:none;padding-top:var(--sp-3)}
.fx-trips .tdsec .clrow.cltot span{color:var(--ink);font-weight:800}
.fx-trips .tdsec .clrow.cltot b{font-size:var(--t-page);font-weight:600}
.fx-trips .tdsec .clrow.cltot b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.35rem;font-weight:800}
/* THE RATE BLOCK is the driver's own question, not the passenger's, so it reads quieter than the
   money above it and never leaves this screen. */
.fx-trips .tdsec .cllines.tdrates{margin-top:6px;border-top:1px dashed var(--line)}
.fx-trips .tdsec .cllines.tdrates .clrow{font-size:var(--t-body);padding:var(--sp-2) 0}
.fx-trips .tdsec .cllines.tdrates .clrow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.88rem}
.fx-trips .tdsec .cllines.tdrates b{font-family:'JetBrains Mono',monospace;font-size:var(--t-small)}
.fx-trips .tdsec .cllines.tdrates b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:.86rem}

.fx-trips .tdsec .setnote{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted);margin:10px 0 0}
.fx-trips .tdsec .setnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.5}
.fx-trips .tdsec .profstat{display:block;text-align:center;font-size:var(--t-body);font-weight:700;
  margin:10px 2px 0;cursor:pointer;line-height:var(--lh-body)}
.fx-trips .tdsec .profstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700;line-height:1.45}
.fx-trips .tdsec .profstat[hidden]{display:none!important}
.fx-trips .tdsec .fx-btns{display:flex;gap:10px;margin-top:var(--sp-3)}
.fx-trips .tdsec .fx-btns[hidden]{display:none!important}
.fx-trips .tdsec .fx-save{flex:1 1 0;min-height:var(--tap-min);border:none;border-radius:var(--r-input);
  background:var(--ink);color:#fff;font:inherit;font-weight:700;font-size:var(--t-body);cursor:pointer}
.fx-trips .tdsec .fx-save:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:inherit;font-weight:800;font-size:.95rem}
.fx-trips .tdsec .fx-save[disabled]{opacity:.55;cursor:default}
.fx-trips .tdsec .fx-cancel{flex:1 1 0;min-height:var(--tap-min);border:1.5px solid var(--line);
  border-radius:var(--r-input);background:var(--card);color:var(--ink);font:inherit;font-weight:700;font-size:var(--t-body);
  cursor:pointer}
.fx-trips .tdsec .fx-cancel:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:inherit;font-weight:800;font-size:.95rem}
/* REMOVE reads as the serious one it is, without ever being the only red thing on a screen full of
   ordinary edits: an outline, not a filled red button, because it opens a confirm rather than
   firing. */
.fx-trips .tdsec .fx-cancel.tddanger{border-color:var(--red);color:var(--red)}

.fx-trips .tdsec .tdmore{margin-top:var(--sp-4);padding-top:14px;border-top:1px solid var(--line)}
.fx-trips .tdsec .tdconfirm{display:flex;align-items:flex-start;gap:10px;flex-wrap:wrap;
  margin-top:10px;padding:var(--sp-3);border:1.5px solid var(--ink);border-radius:var(--r-ctl);background:var(--paper)}
.fx-trips .tdsec .tdconfirm[hidden]{display:none!important}
.fx-trips .tdsec .tdconfirm .tx{flex:1 1 200px;min-width:0;display:flex;flex-direction:column;gap:var(--sp-1)}
.fx-trips .tdsec .tdconfirm b{font-size:var(--t-body);font-weight:700;overflow-wrap:anywhere}
.fx-trips .tdsec .tdconfirm b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.98rem;font-weight:800}
.fx-trips .tdsec .tdconfirm span{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.fx-trips .tdsec .tdconfirm span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.85rem;line-height:1.5}
.fx-trips .tdsec .tdconfirm .cacts{flex:1 1 100%;display:flex;gap:10px}
.fx-trips .tdsec .tdconfirm .aff{flex:1 1 0;min-height:var(--tap-min);display:flex;
  align-items:center;justify-content:center;cursor:pointer;border-radius:var(--r-input);
  border:1.5px solid var(--line);background:var(--card)}
.fx-trips .tdsec .tdconfirm .aff.warn{border-color:var(--red);color:var(--red)}

/* THE ROW IS A DOOR, so it says so and it is big enough to hit. */
.fx-trips .trow{cursor:pointer}
.fx-trips .trow .aff.lite{min-height:var(--tap-min);display:flex;align-items:center;
  justify-content:center;padding:0 10px;cursor:pointer}
/* RECENTLY REMOVED, styled as Recently cancelled already is on My rides: one idea, one look. */
.fx-trips .cxlogrow{border-color:var(--line);background:var(--paper)}
.fx-trips .cxlogrow b{color:var(--muted);text-decoration:line-through}
.fx-trips .cxlogrow svg{stroke:var(--red)}
.fx-trips .cxlogrow .aff{min-height:var(--tap-min);display:flex;align-items:center;
  justify-content:center;padding:0 10px;cursor:pointer}
.fx-trips .rlist[hidden]{display:none!important}
.fx-trips .setstat[hidden]{display:none!important}

/* THE CANCELLATION FLAG, on the New Requests row, on the pricing sheet and on a trip row. Same
   badge in all three places, because it is one fact and a driver should recognise it instantly. */
.badge.warn.flagcx{background:var(--red);color:#fff;letter-spacing:.02em}

/* NARROW PHONES. At 430 a 56px stepper each side of a box leaves the number about 150px, which is
   enough; what is not enough is the confirm's two buttons beside its text, so the actions take a
   full row of their own. Measured at 430 / 520 / 768 / 900, not guessed. */
@media (max-width:440px){
  .fx-trips .tdsec .tipstep{width:52px;height:52px}
  .fx-trips .tdhead{flex-wrap:wrap}
  .fx-trips .tdsec .cllines.tdrates .clrow{gap:var(--sp-2)}
}


/* ================================================================================================
   VERSION B, WHAT YOU SEE (b44, Ahmed picked it 2026-08-16 from YPD-SHELL-MOCKUP-V1A.html).

   The driver's own copy: the earnings card with his three rates and the verdict against his own
   floors, the money group, and the meter group with the red line for the wait he did not charge.

   LIME LABELS ONLY ON THE DARK SURFACE, grey on white, never the reverse. That is the rulebook and
   it has been re-reported four times; .darkcard already carries it, which is exactly why this card
   IS a .darkcard rather than a new component that would have to remember.
   ================================================================================================ */
.fx-trips .tdearn{margin:0 0 14px}
.fx-trips .tdearn .earn{font-family:var(--display);font-size:var(--t-big);line-height:1.05;
  color:var(--lime);margin:var(--sp-1) 0 var(--sp-3)}
.fx-trips .tdearn .earn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:2.1rem;line-height:1.05}
.fx-trips .tdearn .rates{display:flex;gap:10px;flex-wrap:wrap;border-top:1px solid rgba(255,255,255,.16);
  padding-top:var(--sp-3)}
.fx-trips .tdearn .rates > div{flex:1 1 90px;min-width:0;display:flex;flex-direction:column;gap:3px}
.fx-trips .tdearn .rates b{font-family:'JetBrains Mono',monospace;font-size:var(--t-body);font-weight:700;
  color:#fff;overflow-wrap:anywhere}
.fx-trips .tdearn .rates b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:1.05rem;font-weight:800}
/* THE VERDICT. Green when it clears both floors, red when it does not, and ABSENT when either rate
   could not be computed, because a verdict from a missing number is a claim nobody measured. */
.fx-trips .tdearn .verdict{display:flex;align-items:flex-start;gap:var(--sp-2);margin-top:var(--sp-3);
  padding-top:var(--sp-3);border-top:1px solid rgba(255,255,255,.16);font-size:var(--t-small);line-height:var(--lh-small);
  color:var(--lime)}
.fx-trips .tdearn .verdict:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.45}
.fx-trips .tdearn .verdict.bad{color:#FF8B6B}
.fx-trips .tdearn .verdict[hidden]{display:none!important}

.fx-trips .tdsec .cllines .seclab{margin:0 0 6px;padding:0}
/* THE RED LINE. Money he chose not to take, priced at his own wait rate. It is the "did I charge
   under" signal, which is why it is coloured and not just another grey row. */
.fx-trips .tdsec .clrow.tdunder span,
.fx-trips .tdsec .clrow.tdunder b{color:var(--red)}
.fx-trips .tdsec .clrow.tdunder[hidden]{display:none!important}

/* ================================================================================================
   IT RISES FROM THE FOOTER (b44). Ahmed remembered the old end-of-ride screen coming "from the
   bottom and up", and the old DRIVER closeout never did: it was a plain card below a full-height
   map that he had to scroll past, and his own bug report about being stuck there is still sitting
   in driver.html at 4739. So this is a fix, not a flourish.

   HEIGHT, NOT translateY, matching the dock panel the rider portal already uses (lab-render.js
   812-820), so both sides of the app rise the same way.
   ================================================================================================ */
@keyframes ypdRise{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:none}}
.fx-trips .tdsec[data-open="1"] .cl-x{animation:ypdRise .30s cubic-bezier(.2,1.1,.35,1) both}
.fx-ride .clrcpt{animation:ypdRise .30s cubic-bezier(.2,1.1,.35,1) both}
.fx-ride .clrcpt[hidden]{display:none!important;animation:none}
@media (prefers-reduced-motion:reduce){
  .fx-trips .tdsec[data-open="1"] .cl-x,
  .fx-ride .clrcpt{animation:none}
}



/* THREE CONTROLS DO NOT FIT BESIDE AN ADDRESS ON A PHONE (b50). Adding GOOGLE MAPS squeezed the
   address column until "Drop-off to be confirmed" wrapped one word per line, which is the same
   defect as the 3x scale round: the row had room for two controls and was given three. Below the
   Z Fold width the row becomes a COLUMN, address first then the controls together on their own
   line, which is the shape Ahmed already approved for the vehicle rows. Wide screens keep the
   single line, because there it genuinely fits. */
@media (max-width:560px){
  .fx-ride .sheet .row, .fx-pax .sheet .row{flex-wrap:wrap;row-gap:var(--sp-2)}
  .fx-ride .sheet .row>.tx, .fx-pax .sheet .row>.tx{flex:1 1 100%;min-width:0}
  .fx-ride .sheet .row>.aff, .fx-pax .sheet .row>.aff{flex:0 0 auto}
}

/* NAVIGATE IS OURS, GOOGLE MAPS IS GOOGLE'S, AND THE COLOUR SAYS WHICH (b51, Ahmed 2026-08-16:
   "the driver will know that the navigation is in our app or the navigation is in Google, and
   that is going to solve a lot of issues for us"). Forge Orange for ours against Google's green,
   each with its own mark, so at a glance on a kerb the two are never confused. The blue was a
   default nobody chose. Its own [hidden] rule, same law as every other explicit display. */
.aff.ypdnav{gap:7px;
  display:inline-flex;align-items:center;justify-content:center}
.aff.ypdnav[hidden]{display:none!important}
/* b52: the REAL mark, not a letter. Ahmed: the icon is orange and the button is orange, so an
   orange icon disappears, which is why this is the INK version with white YPD. Master files:
   024-IMAGES-THUMBNAILS/YPD-LOGO/ (svg plus 192, 512 and 1024 png, orange AND ink). */
/* b53: a WHITE CIRCLE with BLACK letters, so ours and Google's read as the same kind of
   object on the same row (Ahmed 2026-08-16: "make the black box underneath white, make the
   text black, and since the Google logo is in a circle just make ours a circle also"). */
.aff.ypdnav .yicon{width:20px;height:20px;flex:0 0 20px;stroke:none;border-radius:50%}
.row .aff.ypdnav .yicon path, .row .aff.ypdnav .yicon rect{stroke:none}
/* the plate on the passenger's landing, so she knows which car to walk to */
.platechip{margin-left:6px;padding:2px 7px;border:1.5px solid var(--ink);border-radius:7px;
  font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:800;letter-spacing:.04em}

/* ==================================================================================================
   b50 — THE GOOGLE MAPS BUTTON, Ahmed 2026-08-16: "make it the green button as google maps is
   green, also can you add the google icon, that would make it very easy to know its google."

   It is the one control on the Ride screen that leaves the app, and it is the one he reaches for
   when our own navigation is not trusted, so it is the one that must be identifiable without
   reading. Google's own green, the real four-colour G on a white disc, and its own [hidden] rule
   because an explicit display beats [hidden] (the 2026-07-31 law).
   ================================================================================================== */
.aff.gmaps{gap:7px;
  display:inline-flex;align-items:center;justify-content:center}
.aff.gmaps[hidden]{display:none!important}
.aff.gmaps .gicon{width:20px;height:20px;flex:0 0 20px;background:var(--card);border-radius:50%;padding:2px;
  box-sizing:border-box;stroke:none}
/* the row's own svg rule strokes every child svg, which would outline the G in ink and destroy it */
.row .aff.gmaps .gicon path{stroke:none}

/* ==================================================================================================
   b48 — THE PASSENGER'S PAY SCREEN (approved Version A) AND HER INBOX LIST.

   .paywrap CARRIES ITS OWN [hidden] RULE. An explicit `display` silently BEATS the browser's
   [hidden]{display:none}, which on 2026-07-31 put a bar meant for one layout across every screen
   in Ahmed's tool with no way back. Any new component with an explicit display gets its own
   [hidden] in the SAME edit, not the next one.
   ================================================================================================== */
.fx-pax .paywrap{display:block;margin-top:10px;border-top:1px solid var(--line);padding-top:10px}
.fx-pax .paywrap[hidden]{display:none!important}
.fx-pax .paysheet{display:flex;flex-direction:column;gap:var(--sp-2)}
.fx-pax .paytotal{text-align:center;padding:var(--sp-5) 14px}
/* the total is the one number she is acting on, so it gets the size. AMOUNT NOT SAVED is longer
   than a fare and must not clip, so it wraps down a step instead of overflowing. */
.fx-pax .paybig{font-family:var(--display);font-size:var(--t-big);line-height:1.1;
  margin:6px 0 2px;overflow-wrap:anywhere}
.fx-pax .paybig:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-size:2.4rem;line-height:1.1}
.fx-pax .paytotal .mutline{margin-top:0}
.fx-pax .payrow{display:flex;align-items:center;gap:10px;min-height:var(--tap-min);
  border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);padding:10px var(--sp-3)}
.fx-pax .payrow>svg{flex:0 0 22px;width:22px;height:22px;fill:none;stroke:var(--ink);stroke-width:1.7}
.fx-pax .payrow .tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto;text-align:left}
.fx-pax .payrow .tx b{font-size:var(--t-body)}
.fx-pax .payrow .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
/* a handle is the thing she copies, so it is monospace and it never truncates */
.fx-pax .payrow .tx span{color:var(--muted);font-size:var(--t-small);
  font-family:'JetBrains Mono',monospace;overflow-wrap:anywhere}
.fx-pax .payrow .tx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;font-family:'JetBrains Mono',monospace}
.fx-pax .payrow .aff{min-height:var(--tap-min);display:flex;align-items:center;padding:0 var(--sp-4);
  flex:0 0 auto;cursor:pointer;border-radius:var(--r-input);border:1.5px solid var(--ink);background:var(--ink);
  color:#fff;font-weight:800;font-size:var(--fs-label);letter-spacing:.04em}
/* the ONE thing in the app that leaves it, marked as leaving */
.fx-pax .payleave{color:var(--muted);font-size:var(--fs-label);margin:-2px 0 2px}
.fx-pax .paysheet .setstat[hidden]{display:none!important}
.fx-pax .ilist{display:flex;flex-direction:column;gap:var(--sp-2);width:100%}

/* ==================================================================================================
   b45 — THE VEHICLE LIST, THE CANCELLATION FEE, AND RECENTLY REMOVED AT THE BOTTOM.
   ================================================================================================== */

/* ---- the landing picker: a SELECTED row reads as selected, and every row is a 48px target ------ */
.fx-entry .vrow.vsel{border-color:var(--orange);background:var(--paper)}
.fx-entry .vrow .vk{flex:0 0 auto}

/* ---- Settings > Vehicle, the manager -------------------------------------------------------- */
.fx-set .vehmgr{display:flex;flex-direction:column;gap:10px;width:100%;margin:2px 0 10px}
/* b46: a COLUMN, not a wrapping row. The car identifies itself first, then every control sits
   together on its own line, so a selected row and an unselected row are the same shape. */
.fx-set .vehmgr .vrow{display:flex;flex-direction:column;align-items:stretch;gap:var(--sp-2);
  border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);padding:var(--sp-3) var(--sp-3)}
.fx-set .vehmgr .vrow.vsel{border-color:var(--orange);background:var(--paper)}
/* b46: flex:0 0 auto, not the old 1 1 140px. In the column layout a grow factor made the text
   block eat the row's spare height and pushed the controls to the bottom of a tall empty box. */
.fx-set .vehmgr .vtx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:0 0 auto;text-align:left}
.fx-set .vehmgr .vtx b{font-size:var(--t-body);overflow-wrap:anywhere}
.fx-set .vehmgr .vtx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
.fx-set .vehmgr .vtx span{color:var(--muted);font-size:var(--t-small);overflow-wrap:anywhere}
.fx-set .vehmgr .vtx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem}
.fx-set .vehmgr .vk{color:var(--orange);font-weight:800;font-size:var(--fs-label);letter-spacing:.06em;flex:0 0 auto}
/* EVERY affordance on a row is a real tap target. Ahmed's standing rule: never a tiny control as
   the only way to do something. */
.fx-set .vehmgr .vacts{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
/* EVERY affordance on a row is a real tap target AND looks like one. Before b46 these were bare
   text on a selected row, because .vsel paints the row the same colour the pill was borrowing. */
.fx-set .vehmgr .aff{min-height:var(--tap-min);display:flex;align-items:center;padding:0 var(--sp-4);
  flex:0 0 auto;cursor:pointer;border-radius:var(--r-input);border:1.5px solid var(--ink);background:var(--ink);
  color:#fff;font-weight:800;font-size:var(--fs-label);letter-spacing:.04em}
.fx-set .vehmgr .aff.lite{background:var(--card);color:var(--ink);border-color:var(--line)}
.fx-set .vehmgr .vacts .vk{min-height:var(--tap-min);display:flex;align-items:center;padding:0 var(--sp-1)}
.fx-set .vehform{width:100%;border-top:1px solid var(--line);padding-top:10px;margin-top:var(--sp-1)}
.fx-set .vehform[hidden]{display:none!important}
.fx-set .vehicons{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin:var(--sp-1) 0 10px}
.fx-set .vehopt{min-height:var(--tap-min);padding:0 var(--sp-4);border:1.5px solid var(--line);
  border-radius:var(--r-input);background:var(--card);font:inherit;font-size:var(--t-small);cursor:pointer;flex:1 1 auto}
.fx-set .vehopt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:inherit;font-size:.82rem}
.fx-set .vehopt.on{border-color:var(--orange);background:var(--paper);font-weight:800}

/* ---- My trips: the cancellation line, and Recently removed folded at the bottom -------------- */
/* A cancelled block must never read like earnings, so it is the warn edge and never the ink pill. */
.fx-trips .ttotal.tcx{border-color:var(--red)}
.fx-trips .ttotal.tcx .tx b{color:var(--red)}
.fx-trips .ttotal.tcx .aff{background:var(--red);color:#fff;font-size:var(--fs-label)}
.fx-trips .ttotal.tcx .aff.lite{background:transparent;color:var(--muted)}
/* THE WHOLE HEADER IS THE DOOR, and it states its count, so a folded section can never hide the
   fact that there is something inside it. */
.fx-trips .trmhead{margin-top:14px;cursor:pointer;background:var(--paper);border-color:var(--line)}
.fx-trips .trmhead b{color:var(--muted);text-decoration:none}
.fx-trips .trmhead svg{stroke:var(--muted)}
.fx-trips .trmhead .aff{min-height:var(--tap-min);display:flex;align-items:center;padding:0 10px}

/* THE GATE CODE CHIP (b45). It sits at the PICKUP, on the ride card and the Ride screen, because
   the moment it matters is at a locked gate. In the warn colour it is a QUESTION he still has to
   ask, never a code: "?" typed in a calendar is not an answer. */
.gatechip{display:inline-block;margin-top:var(--sp-1);padding:3px var(--sp-2);border-radius:8px;background:var(--paper);
  border:1px solid var(--line);font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);
  letter-spacing:.06em;font-weight:800;overflow-wrap:anywhere}
.gatechip.warntx{background:var(--red);border-color:var(--red);color:#fff}
.gatechip[hidden]{display:none!important}

/* ==================================================================================================
   b75, THE FOUR NAV CONTROLS GET THEIR REAL ICONS.

   Ahmed, 2026-08-17: "its time to put in the correct icons vs a dot and close with a grey box" and
   "Proper icons = create these and add them." The dot was the recenter crosshair, the grey box was
   the CLOSE / OVERVIEW / RECENTER text tag under it.

   And the order, from the same day: "Order now will be [ recenter on top, then under it, search,
   then sound, then safe ] all four in order on the right side." The rail is a flex COLUMN, so that
   order is the source order of the four buttons and nothing here has to restate it.

   Every value below is off the mockup he approved, YPD-NAV-MOCKUP-V1A.html, section "THE ARROW AND
   THE FOUR CONTROLS". WHITE LABEL: the only colour token here is var(--orange), which applyAccent()
   rewrites per driver, so a teal driver gets teal controls and a teal badge.
   ================================================================================================== */

/* THE DISC ITSELF, WHICH THIS RAIL NEVER ACTUALLY HAD, and it is half of what Ahmed is pointing at.
   The white circle, the shadow and the ink glyph all live on `.map .mbtn`, and .navctl is a SIBLING
   of .map rather than a child of it, so none of that has ever reached these buttons. What has been
   shipping is a bare user-agent button: a pale grey rounded rectangle with a crosshair on it and a
   grey text box under it, which is his sentence almost word for word. Found by rendering the rail
   and looking at it, not by reading the stylesheet, where it is invisible.

   position:relative in the same rule because the badge needs a containing block. It was static, set
   to beat .map .mbtn's absolute, so an absolutely positioned badge would have anchored to .navctl
   and stacked all three in one corner of the rail. relative flows in the flex column identically.

   AND display:flex, from the same hole. .navctl .mbtn already asks for flex-direction:column, but
   display:flex lives on .map .mbtn too, so the column never applied: a button is inline-block by
   default and flex-direction is inert on it. That is why the word sat BESIDE the glyph instead of
   under it, on every one of these buttons, in the shipped app. */
.navctl .mbtn{position:relative;border-radius:50%;background:var(--card);color:var(--ink);
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 3px 10px rgba(10,10,10,.28);-webkit-appearance:none;appearance:none}
.navctl .mbtn svg{fill:none;stroke:var(--ink);stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}

/* ON IS A FILLED DISC, OFF IS A WHITE ONE. Three things change at once, the fill, the glyph and the
   word, because a subtle tint is not a state you can read at a glance from behind a wheel. */
.navctl .mbtn.act{background:var(--orange)}
.navctl .mbtn.act svg{stroke:#fff}
.navctl .mbtn.act .tag,.navctl .mbtn.act .big{color:#fff}
.navctl .mbtn .big{font-style:normal;font-family:'JetBrains Mono',Consolas,monospace;
  font-size:var(--fs-label);letter-spacing:.06em;font-weight:800;color:var(--ink);line-height:1.1}
/* An explicit display ALWAYS beats [hidden] (2026-07-31), so the swapped glyph pins its own rule
   rather than trusting that nothing above ever gives an svg a display. */
.navctl .mbtn svg[hidden]{display:none!important}

/* SEARCH CARRIES NO WORD UNDER IT, which is his art exactly: the approved card draws the magnifier
   alone. It is the only glyph on this rail with nothing stacked under it, so it gets one pixel more
   room rather than sitting a hair high against the three that do. Nothing else changes: it is the
   same 52x52 disc as its neighbours, which is what keeps the column even. */
.navctl .mbtn[data-nv="srch"] svg{width:23px;height:23px}

/* THE CYCLE NUMBER, in place of the grey box. A 20px badge with a white ring, so it reads on a
   light grey map tile and on a dark one, and it sits on the corner rather than stealing height
   from the glyph the way the text tag did. */
.navctl .mbtn .pip{position:absolute;top:-4px;right:-4px;width:20px;height:20px;border-radius:50%;
  background:var(--orange);color:#fff;font-style:normal;
  font-family:'JetBrains Mono',Consolas,monospace;font-size:var(--fs-label);font-weight:800;
  display:flex;align-items:center;justify-content:center;border:2px solid #fff;
  box-shadow:0 1px 3px rgba(10,10,10,.3)}

/* SAFE ON: THE HEADER LEAVES BY THE TOP AND THE FOOTER LEAVES BY THE BOTTOM, AND HE WATCHES THEM GO.
   Ahmed, b85, on what shipped in b84: "On top where the header is hidden is a black line and a
   orange line I didn't ask for. And then on the bottom the footer is just Gray. It's supposed to
   move down... It also feels like it just the header pops off. And the footer just turns off.
   That's not how I want it to function. When we click safe on, the header on top slowly moves to
   the top. And animates. So we see it going to the top. And the same thing with the footer."

   THREE THINGS WERE WRONG AND ALL THREE CAME FROM ONE IDEA. b84 collapsed --hd-h to 10px and
   --foot-h to 12px, which is a way of making a bar SMALL, not a way of making a bar LEAVE. A 10px
   bar is still a bar, so it needed a fill and a rule to look deliberate, which is where the ink
   strip and the orange line came from, and neither was ever asked for. Nothing travelled, because
   nothing moved: a token flipped and the frame relaid out in one frame.

   THE EDGES NOW MOVE, and the map takes the room in the same instant. On the ride screen the map
   is already position:absolute at top:0 (`.frame:has(> .sheet) > .map`), so it has ALWAYS run the
   full height behind the header. A header that transforms out of view therefore uncovers real map
   with no relayout at all, which is why the motion is a transform and not a height: transform runs
   on the compositor, and a driver is looking at this while moving.

   THE FOOTER IS THE ONE THAT NEEDS CARE, because the map stops at bottom:var(--foot-h), so unless
   the map claims that strip the footer would slide down off a band of empty frame background.
   Going IN, the map's bottom snaps to 0 with no delay and the footer slides down OVER map that is
   already painted. Coming OUT, the same snap-back would leave a 78px grey band under the map for
   the whole 240ms the footer spends climbing, so the base rule below delays the snap by exactly
   the duration of the slide. Zero frames of layout animation on the Google map either way.

   Measured, 430x900 and 884x900 (his fold, both leaves), unobstructed map, chrome excluded:
       SAFE off   758px      SAFE on   900px      +142px, +18.7%
   b84 reached 878 and paid for the last 22px with two coloured strips.

   AN OPEN SHEET UN-TUCKS BOTH EDGES, and that is an escape hatch, not a nicety. The rule near the
   top of this file fades .navctl out whenever a sheet is open, so without this a driver in SAFE ON
   who opened a sheet would have no header, no footer and no controls, and no way back. */
.frame > .hd, .frame > .foot{transition:transform var(--safe-t) var(--safe-e)}
.frame{--safe-t:.24s; --safe-e:cubic-bezier(.4,0,.2,1)}
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .hd{transform:translateY(-100%)}
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .foot{transform:translateY(100%)}
/* The map claims the footer strip the moment SAFE goes on, and gives it back only once the footer
   has finished climbing back into place. A 0s duration with a delay is a STEP at the end of the
   delay, which is exactly the handover wanted here. */
.frame > .map{transition:bottom 0s linear var(--safe-t)}
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .map{bottom:0;transition:bottom 0s linear 0s}
/* b212: THE MAP TAKES THE FOOTER'S ROW. Since the one-stage map (b105) the map is a FLEX item, not
   absolute, so bottom:0 above does nothing and a translated footer still keeps its row: the grey
   band under the map in SAFE (Ahmed 08-22, his red circle). In SAFE the header and footer leave the
   flow, so the map grows to the frame's full height. */
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .hd{position:absolute;top:0;left:0;right:0;z-index:7}
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .foot{position:absolute;bottom:0;left:0;right:0;z-index:7}
/* The overlays ride with the edges they were positioned against, rather than jumping to meet them.
   Both already offset off --hd-h and --foot-h, so SAFE only has to name the tucked value.

   AND THE WAY OUT OF SAFE LIVES ON THAT RAIL, so nothing on it may end up closer to a screen edge
   than the chrome that just left was keeping it. Measured at 430x900 with a bare var(--nav-inset):
   the rail's lowest pixel landed at y=890, ten pixels off the bottom, while the footer holds its
   own tabs at 886 and b84's tucked rail sat at 878. Four pixels lower than any control this app
   has ever placed, on the one button that turns SAFE back off. --safe-edge is the footer's own
   bottom padding, borrowed rather than guessed, and env() adds whatever the device says is
   unusable on top. app.html already ships viewport-fit=cover, and with the footer gone there is
   nothing else left standing between this rail and the gesture bar. */
.frame{--safe-edge:14px}
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .navrow{
  top:calc(var(--nav-inset) + env(safe-area-inset-top,0px))}
.frame.safe:not(:has(> .sheet:not(.shmin):not([hidden]))) > .navctl{
  bottom:calc(var(--nav-inset) + var(--safe-edge) + env(safe-area-inset-bottom,0px))}
/* HE ASKED FOR THE MOTION, so someone who has asked their phone for less of it gets the same
   result without it. Placed after the rules above and at their own specificity for the base pair,
   and the SAFE map rule is already a 0s step, so nothing here can animate. */
@media (prefers-reduced-motion:reduce){
  .frame > .hd, .frame > .foot, .frame > .map,
  .frame > .navrow, .frame > .navctl{transition:none}
}

/* ==== b87, THE MESSAGE BAR ==== =============================================================
   IT COVERS THE HEADER. Ahmed, 2026-08-17: "It's going to animate from the top and it's going to
   cover the header. And then I believe it stays for 5 seconds and then it goes away. But I can
   click on it. Or swipe it. Up, down, left, right."

   Anchored to the frame at top 0, full width, and it SLIDES IN over the header rather than pushing
   anything, so nothing he was about to tap moves under his thumb. One line is exactly the header's
   height; a longer sentence grows DOWNWARD, which is his own answer to the two line case.

   IT IS NOT A .sheet AND MUST NEVER BECOME ONE. Nine selectors read
   :has(> .sheet:not(.shmin):not([hidden])) to mean "a sheet is open", and a sheet-classed bar would
   satisfy all nine every time a message played, fading the turn panel out mid-drive. That is the
   b83 defect t72-sheetvis.mjs exists for, and t79-msgbar.mjs asserts this element never joins it. */
.frame > .msgbar{position:absolute;left:0;right:0;top:0;z-index:60;
  display:flex;align-items:center;gap:11px;
  min-height:var(--hd-h);            /* one line is exactly the header. two lines grow DOWN */
  padding:9px var(--sp-3);color:#fff;
  background:var(--ink);                /* b271: header messages are OPAQUE, his ride #22 call */
  box-shadow:0 6px 18px rgba(10,10,10,.34);
  transform:translateY(-100%);
  transition:transform .34s cubic-bezier(.2,.8,.2,1);
  touch-action:none;                 /* the flick belongs to the bar, not to the page */
  cursor:pointer}
.frame > .msgbar.in{transform:translateY(0)}

/* THE HEADER STEPS OUT OF THE WAY UNDERNEATH, AND THIS IS NOT A COSMETIC CHOICE.
   At 88 percent over a WHITE header with black type, the wordmark and the chip read straight
   through the bar and it looks like a rendering fault. Two ways out: make the bar solid, which
   leaves the 88 percent family, or take the header away while the bar is over it, which keeps one
   opacity value everywhere and makes "it covers the header" literally true. This is the second one.
   Found by rendering it and looking, not by reading the CSS. */
.frame.msgon > .hd{opacity:0;transition:opacity .16s linear}
@media (prefers-reduced-motion:reduce){ .frame.msgon > .hd{transition:none} }
/* an explicit display ALWAYS beats [hidden], and this component has one (2026-07-31) */
.frame > .msgbar[hidden]{display:none!important}

/* THE COLOUR LAW. Ink is ordinary, green is good, a red ring is a warning, solid red stops the ride
   working, and the accent state is the DRIVER'S colour, never a hex. */
.frame > .msgbar.good{background:var(--good)}   /* b271: opaque */
.frame > .msgbar.warn{outline:3px solid #C0392B;outline-offset:-3px}
.frame > .msgbar.urgent{background:#C0392B}   /* b271: opaque */
.frame > .msgbar.accent{background:var(--orange)}   /* b271: opaque */

.msgbar .mi{flex:0 0 auto;width:26px;height:26px}
.msgbar .mi svg{width:26px;height:26px;fill:none;stroke:#B6FF3B;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.msgbar.good .mi svg,.msgbar.urgent .mi svg{stroke:#fff}
.msgbar .mt{flex:1 1 auto;min-width:0;font-size:var(--t-body);font-weight:400;line-height:var(--lh-body);text-align:center;   /* b271: every header message is centered */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.msgbar .mt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.02rem;font-weight:600;line-height:1.25}   /* b189: two lines, never four */
/* LIME, never grey, on every small label on a dark surface (the standing lime-labels rule) */
.msgbar .mlab{display:block;font-family:'JetBrains Mono',Consolas,monospace;font-size:var(--fs-label);
  letter-spacing:.09em;text-transform:uppercase;color:#B6FF3B;font-weight:800;margin-bottom:2px}
.msgbar.good .mlab,.msgbar.urgent .mlab{color:rgba(255,255,255,.88)}
/* the queue depth, so two messages back to back never read as a glitch */
.msgbar .mq{flex:0 0 auto;font-family:'JetBrains Mono',Consolas,monospace;font-size:var(--fs-label);
  font-weight:800;letter-spacing:.08em;background:rgba(255,255,255,.18);border-radius:6px;padding:3px 7px}
/* A MESSAGE THAT PERFORMS THE ACTION SAYS SO. The whole bar is still the target, this only tells
   him the tap DOES the thing rather than opening the screen where the thing lives. */
.msgbar .mdo{flex:0 0 auto;font-family:'JetBrains Mono',Consolas,monospace;font-size:var(--fs-label);
  font-weight:800;letter-spacing:.08em;background:#B6FF3B;color:var(--ink);border-radius:6px;padding:5px 9px}
.msgbar.good .mdo,.msgbar.urgent .mdo{background:var(--card);color:var(--ink)}
/* the gate code is the one message whose CONTENT is the point, so it gets the room */
.msgbar .gcode{display:block;font-family:'JetBrains Mono',Consolas,monospace;font-size:var(--t-page);
  font-weight:600;letter-spacing:.12em;line-height:1.1}
.msgbar .gcode:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',Consolas,monospace;font-size:1.7rem;font-weight:800;line-height:1.1}

/* THE PROBLEM STRIP, the one exception to the 5 second rule. At 5s a problem shrinks to this and
   stays until it is tapped, flicked or replaced.
   48px, NOT the old portal's 36px. The strip is the one message that parks itself on screen, which
   makes it the one message he has to be able to hit while driving, and 36px fails the 48px minimum.
   Caught by measuring the rendered panel, not by reading the old CSS. */
.frame > .msgbar.strip{min-height:48px;padding:6px var(--sp-3)}
.msgbar.strip .mt{font-size:var(--t-small);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.msgbar.strip .mt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem}
.msgbar.strip .mlab{display:none}

/* HE ASKED FOR THE MOTION, so someone who asked their phone for less of it still gets the message,
   it just arrives instead of sliding. */
@media (prefers-reduced-motion:reduce){ .frame > .msgbar{transition:none} }

/* IN NAVIGATION THE TURN PANEL MOVES, IT IS NEVER COVERED. In SAFE the nav row sits at the top of
   the screen, so the band pushes it down for the life of the message. Only a HIGH gets here at all,
   a MEDIUM waits until the instruction is off screen (the engine holds it, app-msg.js pick()). */
.frame.msgon > .navrow{transform:translateY(var(--msgh,0px));
  transition:transform .34s cubic-bezier(.2,.8,.2,1)}
@media (prefers-reduced-motion:reduce){ .frame.msgon > .navrow{transition:none} }
/* ==== end b87 ==== */

/* ==== b87b, THE ASK's TWO CONTROLS ==== ==========================================
   TWO CONTROLS, BOTH AT THE 48px FLOOR, and the floor is not decoration here: this is a question
   answered at the wheel, and 48px is the minimum any control in this app may be (the standing rule,
   Ahmed 2026-07-19, "never ship a tiny native control as the only way to do something").

   THEY SIT AT THE END OF THE BAR, in the reading order NO then SEND, so the destructive-sounding one
   is not the one under a thumb travelling in from the right edge. Neither is actually destructive,
   which is why there is no confirm step behind either.

   NO HEX FOR THE YES. It carries var(--orange), the DRIVER'S own accent, so a teal driver's Send
   button is teal. The NO is neutral by construction and is the same on every driver's phone. */
.msgbar .mask{flex:0 0 auto;display:flex;gap:var(--sp-2);align-items:center}
.msgbar .mbtn{min-height:48px;min-width:48px;padding:0 14px;border-radius:var(--r-input);
  font-family:'Space Grotesk',-apple-system,'Segoe UI',Roboto,sans-serif;font-weight:700;
  font-size:var(--t-small);line-height:1.1;cursor:pointer;white-space:nowrap}
.msgbar .mbtn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',-apple-system,'Segoe UI',Roboto,sans-serif;font-weight:800;font-size:.86rem;line-height:1.1}
.msgbar .mbtn.no{background:transparent;color:#fff;border:1.5px solid rgba(255,255,255,.55)}
.msgbar .mbtn.yes{background:var(--orange);color:#fff;border:none}
/* b468: an ask's third answer (SEND TEXT on the landed notice), outlined like NO, white words */
.msgbar .mbtn.alt{background:transparent;color:#fff;border:1.5px solid #fff}
/* three answers: the words take the first row whole, the buttons share the row under them, 48px each */
.frame > .msgbar:has(.mbtn.alt){flex-wrap:wrap;row-gap:var(--sp-2)}
.msgbar:has(.mbtn.alt) .mt{flex:1 1 calc(100% - 40px);-webkit-line-clamp:3}   /* the label and two lines of words */
.msgbar:has(.mbtn.alt) .mask{flex:1 1 100%}
.msgbar:has(.mbtn.alt) .mask .mbtn{flex:1 1 0;min-width:0}
/* On the two coloured states the accent would fight the ground it sits on, so YES goes neutral
   white there and stays the loudest thing on the bar either way. */
.msgbar.good .mbtn.yes,.msgbar.urgent .mbtn.yes{background:var(--card);color:var(--ink)}
/* The strip is the docked PROBLEM state and a problem is never a question, so if the two ever meet
   the buttons are not drawn at half size, they are not drawn at all. */
.msgbar.strip .mask{display:none}
/* A question that has to share the bar with a long sentence keeps its controls: the text gives way
   first, which is the opposite of the usual flex default and is deliberate. */
.msgbar .mask{min-width:0}
/* ==== end b87b ==== */



/* ================= b91: NO GPS ON THIS DEVICE, Option A, approved 2026-08-17 =================
   The ask card and the quiet chip. Translucent white over the map per the standing rule (the
   Google panel is transparent, Tesla does the same, ours follows). Buttons 48px, the tap law. */
.gpsask{position:absolute;left:12px;right:12px;bottom:150px;z-index:60;
  background:rgba(255,255,255,.88);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  border-radius:16px;padding:var(--sp-4) 15px 14px;box-shadow:0 10px 30px rgba(0,0,0,.24)}
.gpsask[hidden]{display:none}
.gpsask .gaic{width:34px;height:34px;border-radius:9px;background:#FDF3DA;color:#8A5200;
  display:flex;align-items:center;justify-content:center;font-size:var(--t-card);margin-bottom:9px;font-weight:600}
.gpsask .gaic:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:18px}
.gpsask h4{margin:0 0 5px;color:var(--ypd-ink);font-size:var(--t-card);font-weight:600}
.gpsask h4:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:16px;font-weight:600}
.gpsask p{margin:0 0 13px;color:var(--ypd-steel);font-size:var(--t-small);line-height:var(--lh-small)}
.gpsask p:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:12.7px;line-height:1.5}
.gpsask .gabtns{display:flex;gap:var(--sp-2)}
.gpsask button{flex:1;min-height:48px;border-radius:11px;border:0;cursor:pointer;
  font:700 var(--t-small)/var(--lh-small) "Space Grotesk",sans-serif}
.gpsask button:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 13.5px/1.2 "Space Grotesk",sans-serif}
.gpsask .gago{background:var(--ypd-orange);color:#fff}
.gpsask .gasec{background:var(--ypd-mist);color:var(--ypd-ink);border:1px solid var(--ypd-line)}
.gpschip{position:absolute;top:calc(var(--hdr-h,62px) + 10px);left:12px;z-index:55;
  display:flex;align-items:center;gap:6px;background:rgba(255,255,255,.88);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border-radius:20px;
  padding:6px 11px 6px 8px;box-shadow:0 3px 10px rgba(0,0,0,.16);pointer-events:none;
  color:var(--ypd-ink);font:600 var(--fs-label)/1.2 "Space Grotesk",sans-serif}
.gpschip[hidden]{display:none}
.gpschip s{width:8px;height:8px;border-radius:50%;background:var(--ypd-warn);display:block;
  text-decoration:none}

/* ================== b99: the Passenger panel's rows are editable in place ==================
   Option C phase 1. The row becomes the field, nothing pops up. 48px everywhere, his tap law. */
.fx-prow .aff.lite[data-act]{min-height:44px;min-width:62px;padding:0 13px;border-radius:9px;
  border:1px solid var(--ypd-line);background:var(--ypd-mist);color:var(--ypd-ink);
  display:flex;align-items:center;justify-content:center;font:600 var(--t-label)/1 "Space Grotesk",sans-serif;
  cursor:pointer}
.fx-prow .aff.lite[data-act].add{background:var(--ypd-orange);color:#fff;border-color:var(--ypd-orange)}
.paxed{background:var(--ypd-mist);padding:13px 15px;border-bottom:1px solid var(--ypd-line)}
.paxed[hidden]{display:none}
.paxed label{display:block;font:700 var(--fs-label)/1.2 "Space Grotesk",sans-serif;letter-spacing:.6px;
  color:var(--ypd-steel);margin-bottom:6px}
.paxed input{width:100%;height:48px;border-radius:10px;border:1px solid var(--ypd-line);
  background:var(--ypd-white);padding:0 var(--sp-3);color:var(--ypd-ink);
  font:500 var(--t-body) "Space Grotesk",sans-serif}
.paxed .btns{display:flex;gap:var(--sp-2);margin-top:10px}
.paxed button{flex:1;min-height:48px;border-radius:10px;border:0;cursor:pointer;
  font:700 var(--t-small)/var(--lh-small) "Space Grotesk",sans-serif}
.paxed button:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 13.5px/1.2 "Space Grotesk",sans-serif}
.paxed .save{background:var(--ypd-orange);color:#fff}
.paxed .cxl{background:var(--ypd-white);color:var(--ypd-ink);border:1px solid var(--ypd-line)}
.paxed .hint{font-size:var(--fs-label);color:var(--ypd-steel);margin-top:var(--sp-2);line-height:1.45}
.paxed .hint.err{color:var(--ypd-danger);font-weight:600}

/* ================== b100: the full passenger screen (Option C phase 2) ====================
   The photo, and every field saving itself. Same 48px law as everything else he taps. */
.fx-pax .paxhero{display:flex;flex-direction:column;align-items:center;gap:6px;padding:6px 0 14px}
.fx-pax .paxav{width:88px;height:88px;border-radius:50%;background:var(--ypd-mist);
  border:1px solid var(--ypd-line);object-fit:cover;display:block}
.fx-pax .paxav.ph{display:flex;align-items:center;justify-content:center;color:#A9A9A6;font-size:var(--t-page);font-weight:600}
.fx-pax .paxav.ph:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:30px}
/* [hidden] LAST, and it has to be last. Both circles carry .paxav, so .fx-pax .paxav[hidden] and
   .fx-pax .paxav.ph are BOTH 0,3,0 and the tie is broken by source order alone. Placed above
   .paxav.ph it silently failed to hide the placeholder, so a passenger WITH a photo got two
   circles just as one without a photo did. Order, not !important, and not a longer selector.
   Anything else added to .paxav goes ABOVE this line. */
.fx-pax .paxav[hidden]{display:none}
.fx-pax .paxphotobtn{padding:0 var(--sp-4);cursor:pointer}
.fx-pax .paxfield{padding:var(--sp-3) 15px;border-bottom:1px solid var(--ypd-line)}
.fx-pax .paxfield label{display:block;font:700 var(--fs-label)/1.2 "Space Grotesk",sans-serif;letter-spacing:.6px;
  color:var(--ypd-steel);margin-bottom:6px}
.fx-pax .paxfield .fr{display:flex;gap:var(--sp-2)}
.fx-pax .paxfield input{flex:1;min-width:0;height:48px;border-radius:10px;border:1px solid var(--ypd-line);
  background:var(--ypd-white);padding:0 var(--sp-3);color:var(--ypd-ink);
  font:500 var(--t-body) "Space Grotesk",sans-serif}
.fx-pax .paxfield button{min-width:78px;cursor:pointer}
.fx-pax .paxfield .fnote{font-size:var(--fs-label);color:var(--ypd-steel);margin-top:7px;line-height:1.45}
.fx-pax .paxfield .fnote.err{color:var(--ypd-danger);font-weight:600}
.fx-pax .paxfield .fnote.ok{color:var(--ypd-success);font-weight:600}

/* ---- b113: THE UPDATE BAR. Fixed over every screen, because a stale tab is stale everywhere.
   Forge Orange, the accent that means "act now", and its [hidden] rule sits LAST among its own
   rules per the b100c source-order law. ---------------------------------------------------------- */
/* b159: ONE LINE, ALL CAPS, the message bar's own scale. The two-line card overlapped the
   header on his fold; this sits where a bar belongs and truncates rather than wraps if a tiny
   screen cannot fit it. */
/* b227: retired, kept only so an old cached page cannot paint an unstyled bar */
.updbar{display:none!important;position:fixed;left:12px;right:12px;top:12px;z-index:9999;background:var(--orange);color:#fff;
  border-radius:var(--r-input);padding:0 var(--sp-4);height:48px;display:flex;align-items:center;justify-content:center;
  font:700 var(--t-small)/1 "Space Grotesk",sans-serif;letter-spacing:.04em;text-align:center;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;cursor:pointer;box-shadow:0 6px 24px rgba(10,10,10,.28)}
.updbar[hidden]{display:none}

/* ==================================================================================================
   b144: HER NAVIGATION PANEL AND HER RAIL.

   IDENTICAL TO HIS BY REUSE, NOT BY COPY. Everything visual (.navrow, .nvpanel, .nbtop, .nbeta,
   .navdock, the .dock collapse, .navctl, .mbtn, .pip, .tag) is the SAME rule set his panel uses,
   so a change to the driver's look reaches hers in the same pass and the two cannot drift. Only
   the ANCHORING is redefined here, and only because her nodes live INSIDE the map element rather
   than beside it: her map is the travelling stage (b121) and the panel has to travel with it.

   Positioned against .map rather than .frame, so his offset past the header and his offset above
   the footer would push these two a header's height down and a footer's height up inside a box
   that has neither. The inset is the same --nav-inset token, so his spacing and hers are one
   number, not two.
   ================================================================================================== */
/* SHE GETS HIS .navrow POSITIONING UNTOUCHED: top under the header, left and right at the inset.
   Only the RAIL moves, and only because HER SHEET IS NOT AN OVERLAY. His sheet closes while he
   navigates; hers IS her Ride screen and is always open, and MEASURED on a 375px phone it covers
   the bottom 577px of her 734px map. His rail sits above the footer, which on her side lands
   inside that: document.elementFromPoint at the middle of the recenter button came back with a
   row of the sheet, so the button looked tappable and was not. Both controls therefore live in
   the strip of map she can actually see, panel left and rail right, on the same inset token. */
/* b153: THE OVERRIDE THAT PUT HER RAIL TOP-RIGHT IS GONE, his explicit call: "there is a
   recenter button and a sound off button but it is not located where it is for the driver.
   That is where ours need to be." She now inherits .navctl unchanged, bottom-right above
   the footer, and the sheet makes room instead, the rule below. */

/* AND THE SHEET DOES NOT FADE THEM OUT. The rule above this one exists because an open sheet on
   the DRIVER's screen is a panel covering his map, so his nav chrome tucks away under it. Her
   sheet is not a panel over a map, it is the bottom half of her screen and it is open for the
   whole ride, so inheriting his rule would hold her navigation at opacity 0 forever, which is
   the exact b84 symptom in a new place. Scoped to the passenger, his behaviour is unchanged. */
/* b165: THE ROW IS NEVER A TAP SHIELD. This override used to set pointer-events:auto on
   the whole .navrow, and the row is an invisible full-width strip that crosses the sheet's
   X on every screen the chrome travels to, so every real tap on the X and the drag handle
   died on it, his red-marker video. Proven by elementFromPoint returning `navrow` at the
   X's centre. The row gets its OPACITY back only; .navrow{pointer-events:none} stands and
   .navrow > * keeps the panel itself tappable. The rail is real controls, it keeps both. */
/* b173/b174: AND HIS SCREENS FOLLOW HER RULES, the Ride sheet included (Ahmed 08-21: the ride
   sheet showed no nav or icons while the menus were right). One behaviour everywhere: with a
   sheet open the chrome stays, the sheet narrows, the expanded panel reserves headroom.
   Passenger selector stays last in each group. */
.frame[data-role="driver"]:has(> .sheet:not(.shmin):not([hidden])) > .navrow,
.frame[data-role="passenger"]:has(> .sheet:not(.shmin):not([hidden])) > .navrow{opacity:1}
.frame[data-role="driver"]:has(> .sheet:not(.shmin):not([hidden])) > .navctl,
.frame[data-role="passenger"]:has(> .sheet:not(.shmin):not([hidden])) > .navctl{opacity:1;pointer-events:auto}
/* b153: WHILE NAVIGATION IS LIVE THE SHEET IS NOT AS WIDE, his words. The docked panel tab
   gets a real column on the left and the rail gets one on the right, 52px chrome plus the
   inset each side, so the sheet X is under neither and every control hit-tests to itself.
   Keyed on the nav row being visible, so a ride with no live navigation keeps the
   full-width sheet. */
/* b154: EVERY passenger stage frame, not only the ride screen, because the chrome travels
   now and the law is the same wherever it lands: live navigation gets its columns, the
   sheet is not as wide, and nothing sits over anything. One rule, four menus, his point. */
.frame[data-role="driver"]:has(> .navrow:not([hidden])) > .sheet,
.frame[data-role="passenger"]:has(> .navrow:not([hidden])) > .sheet{
  margin-left:calc(52px + var(--nav-inset)*2);
  margin-right:calc(52px + var(--nav-inset)*2)}
/* b165: THE PANEL AND THE SHEET STOP FIGHTING, his marker over the overlapped title. While
   her panel is EXPANDED its full green card needs the top of the map, so the sheet's
   ceiling drops below it and the two never overlap; docked back to the tab, the sheet gets
   its full height back. :not(.shmin) so the closed state's max-height:0 still wins. */
.frame[data-role="driver"]:has(> .navrow:not([hidden]) .nvpanel:not(.dock)) > .sheet:not(.shmin):not([hidden]),
.frame[data-role="passenger"]:has(> .navrow:not([hidden]) .nvpanel:not(.dock)) > .sheet:not(.shmin):not([hidden]){
  max-height:calc(100% - var(--foot-h) - var(--hd-h) - var(--sheet-top) - 118px)}
.frame[data-role="passenger"] > .navrow{pointer-events:none}   /* the row itself stays click-through, its children do not */

/* HIS GLYPH, TURNED. The shared node carries the maneuver KIND, so rather than drawing a second
   set of arrow paths that could disagree with the driver's, the one straight arrow he already
   draws is rotated. straight and arrive are 0 degrees, which is his arrow exactly as it ships, so
   an unknown or missing kind degrades to the picture his panel paints today rather than to a
   blank. */
[data-pv="mn"]{transition:transform .18s ease}
[data-pv="mn"][data-arrow="left"]{transform:rotate(-90deg)}
[data-pv="mn"][data-arrow="right"]{transform:rotate(90deg)}
[data-pv="mn"][data-arrow="sleft"]{transform:rotate(-45deg)}
[data-pv="mn"][data-arrow="sright"]{transform:rotate(45deg)}
[data-pv="mn"][data-arrow="uturn"]{transform:rotate(180deg)}
@media (prefers-reduced-motion:reduce){ [data-pv="mn"]{transition:none} }

/* ==================================================================================================
   b177: PRICE A RIDE OPENS OVER HOME (Ahmed 08-21, approved from the shell mockup slot f-price).
   The driver offer SHEET is docked into the visible Home frame while pricing (the map-mover
   pattern): Home dims behind it, the sheet rises from the footer, the X returns it. Every
   .fx-off descendant rule above was widened to :is(.fx-off,.fx-pricing) so the sheet is styled
   identically in both homes; only the offer frame's own .map and .hd-logo rules stay behind.
   ================================================================================================== */
/* b219: THE FINISH SHEET docks into Home through the SAME two rules Price a Ride uses (the
   class is widened, never copied). .fx-finish is set on the Home frame while the TRIP COMPLETED
   sheet is up, on either role. */
:is(.frame.fx-pricing,.frame.fx-finish) > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
:is(.frame.fx-pricing,.frame.fx-finish) > .sheet{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;   /* b184: the same side inset as every risen sheet, Ahmed */
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch}
/* b177: the offer sheet scrolls from the FIRST paint, in its own frame too (his Long screenshot
   only scrolled after a toggle forced a relayout) */
.fx-off > .sheet{overflow-y:auto;min-height:0}
/* b177: LOAD A BOOKING, the quote-mode picker. Rows are real taps, 48px floor. */
.fx-off-pick{border:1px solid var(--line);border-radius:var(--r-ctl);overflow:hidden;margin:0 0 10px;background:var(--card)}
.fx-off-pick .ph{display:flex;justify-content:space-between;align-items:center;padding:9px 13px;background:#FAFAF8;border-bottom:1px solid var(--line)}
.fx-off-pick .ph .k{color:var(--ink)}
.fx-off-pick .opt{display:flex;justify-content:space-between;align-items:center;gap:10px;min-height:48px;padding:9px 13px;
  border-bottom:1px solid var(--line);font-weight:700;font-size:var(--t-body);cursor:pointer}
.fx-off-pick .opt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.92rem}
.fx-off-pick .opt:last-child{border-bottom:0}
.fx-off-pick .opt.on{background:#FFF1EC}
.fx-off-pick .opt i{display:block;font-style:normal;font-weight:500;font-size:var(--t-small);color:var(--muted)}
.fx-off-pick .opt i:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:500;font-size:.76rem}
.fx-off-pick .opt em{font:700 var(--fs-label)/1 "JetBrains Mono",monospace;background:var(--ink);color:#B6FF3B;padding:6px var(--sp-2);border-radius:6px;font-style:normal;flex:0 0 auto}
.fx-off-pick[hidden]{display:none!important}
/* b182: the list scrolls INSIDE the picker (about three rows), so six calendar legs never swallow
   the address card below; and the calendar commit is one full-width button */
.fx-off-pick [data-off="picklist"]{max-height:174px;overflow-y:auto;-webkit-overflow-scrolling:touch}
.fx-off-pick [data-off="picklist"][hidden]{display:none}
.fx-off-pick .ph{cursor:pointer;min-height:44px}
.fx-off-pick .ph [data-off="pickcap"]{color:var(--orange,#FF3B00)}
:is(.fx-off,.fx-pricing) .fx-off-acts2[data-off="calacts"] .cta.go{flex:1 1 100%}

/* ==================================================================================================
   b186: THE TALL FORMAT, ITS OWN BLOCK (Ahmed 08-21, his five screenshots). Long has owned a token
   block since the mock; tall was "the default", so every width rule written with long in mind
   leaked into it: the 44% nav column that wrapped "170 ft" onto three lines, the 52px chrome column
   that narrowed every sheet, the 118px headroom guess that put the sheet inside the panel, the rail
   stranded bottom-right. This block is the exact complement of the long switch, so long is
   untouched by construction (proved by pixel diff before shipping).
   ================================================================================================== */
/* b435 (bug-mum4yh55): the phone's band gap, 5% of the TALL DESIGN WIDTH at most (430, fitZoom's number). Under 430
   wide it is exactly the old 5vw. Read by the tall band and rail below and by the short long screen further down. */
.frame{--tall-w:430px; --band-gap:min(5vw, calc(var(--tall-w) * .05))}
@media not all and (min-aspect-ratio: 6/5){
  /* 2. THE NAV BAND. The row spans the top at the sheet insets; the rail takes the right end. */
  /* b190: the band's top gap is the SAME 5% as its sides (5% of the width, not of the height) */
  /* b435 (bug-mum4yh55, Ahmed 2026-09-28, the Z Fold in SPLIT SCREEN and open in portrait): THE BAND AND THE RAIL ARE
     PHONE SIZED AT EVERY WIDTH. 5vw and 5% grew with the screen, so on the open fold (904 wide, 753 after the design-
     width zoom) the rail hung 46px under the header instead of 21 and the green bar stretched 542px across the map.
     The gap is now 5% of the TALL DESIGN WIDTH at most (430, the same number fitZoom uses), the band can never be
     wider than it is on that phone and is centred in the lane left of the rail, and the band's own tokens are the
     phone's (the min-width:700px set was written for the long fold's 25% panels and leaked into wide tall). At or
     under 430 wide every value below equals the old one, so the phone does not move. Measured by t264. */
  .frame{--nav-inset:10px; --nav-dist:1.5rem; --nav-road:1.02rem; --nav-eta:0.56rem; --nav-w:44%}
  .frame > .navrow{left:var(--band-gap);right:calc(var(--band-gap) + 52px + 10px);top:calc(var(--hd-h) + var(--band-gap));
    max-width:calc(var(--tall-w) - 2 * var(--band-gap) - 52px - 10px);margin-left:auto;margin-right:auto}
  .frame > .navrow > .nvpanel{flex:1 1 auto}
  .frame > .navrow > .nvpanel.dock{flex:0 0 52px}
  .frame > .navctl{right:var(--band-gap);bottom:auto;top:calc(var(--hd-h) + var(--band-gap))}
  /* b190: HER RAIL, restated at the b158 selector strength. That rule pins her rail to the footer
     with an empty 72px slot; in tall the rail hangs from the band instead, sound right under
     recenter. Without this the rail stretched band-to-footer, the measured chrome height swallowed
     the frame and no sheet could rise while navigation was live (his 12:50 screenshot). */
  .frame[data-role="passenger"] > .navctl{bottom:auto;gap:10px}
  /* the row-opacity law (b173) already keeps the chrome visible under an open sheet; the rail too */
  .frame:has(> .sheet:not(.shmin):not([hidden])) > .navctl{opacity:1;pointer-events:auto}

  /* 3. THE SHEETS. Inset each side, ceiling measured from the chrome, never guessed. */
  .frame[data-role="driver"]:has(> .navrow:not([hidden])) > .sheet,
  .frame[data-role="passenger"]:has(> .navrow:not([hidden])) > .sheet{
    margin-left:var(--sheet-inset);margin-right:var(--sheet-inset)}
  .frame[data-role="driver"]:has(> .navrow:not([hidden])) > .sheet:not(.shmin):not([hidden]),
  .frame[data-role="passenger"]:has(> .navrow:not([hidden])) > .sheet:not(.shmin):not([hidden]){
    max-height:calc(100% - var(--foot-h) - var(--hd-h) - var(--sheet-top) - var(--nav-chrome-h, 0px) - var(--sheet-top))}
  /* the b165 expanded-panel rule carries one more class in its selector, so it is restated here
     with the measured value, otherwise its 118px guess outranks the line above */
  .frame[data-role="driver"]:has(> .navrow:not([hidden]) .nvpanel:not(.dock)) > .sheet:not(.shmin):not([hidden]),
  .frame[data-role="passenger"]:has(> .navrow:not([hidden]) .nvpanel:not(.dock)) > .sheet:not(.shmin):not([hidden]){
    max-height:calc(100% - var(--foot-h) - var(--hd-h) - var(--sheet-top) - var(--nav-chrome-h, 0px) - var(--sheet-top))}
  /* b189: the message bar reads a touch smaller in tall, the header's height plus one line at most */
  .frame > .msgbar .mt{font-size:var(--t-body);line-height:var(--lh-body)}
.frame > .msgbar .mt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem;line-height:1.2}
  .frame > .msgbar{padding:7px var(--sp-3)}
  /* a sheet that must go higher than its ceiling wins the stack; the chrome comes back when it drops */
  .frame > .sheet:not(.shmin):not([hidden]){z-index:5}
}

/* b194: EDIT ON A LEAD. The affordance sits at the right end of the address line and the strip
   cells are tappable; the editor block is the Ride screen's .paxed, reused. */
:is(.fx-off,.fx-pricing) .fx-off-ab .ln{position:relative}
:is(.fx-off,.fx-pricing) .fx-off-ab .ln .fx-leadedit{flex:0 0 auto;margin-left:auto;align-self:center}
:is(.fx-off,.fx-pricing) .fx-leadedit[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-when > div[data-act]{cursor:pointer}
:is(.fx-off,.fx-pricing) .fx-leaded{margin:0 0 10px;border-radius:var(--r-input);border:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-leaded[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-leaded input[type="time"]{margin-top:6px}
:is(.fx-off,.fx-pricing) .fx-off-who[hidden]{display:none!important}
.rlhead{font:700 var(--fs-label)/1 "JetBrains Mono",monospace;letter-spacing:.1em;color:var(--muted);padding:10px 14px var(--sp-1)}

/* b205: the four typed boxes at close-out, a two by two grid above the tip, both formats */
.clmet{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:0 0 var(--sp-3)}
.clmet label{display:block}
.clmet .fx-ml{display:block;margin-bottom:var(--sp-1)}
.clmet .fx-in{width:100%;height:48px;border:1px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);font:700 var(--t-body) "Space Grotesk",sans-serif;background:var(--card)}
.clmet .fx-in:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 1.05rem "Space Grotesk",sans-serif}
.clmet .fx-in:focus{border-color:var(--ink);outline:none}

/* b206: THE GPS CHIP IS A CHILD OF THE NAV PANEL, centred under it by the layout engine, every state,
   both formats. The old JS placement measured the panel once per fix and went wrong in a state the
   harness could not reproduce; a child cannot be anywhere but under its parent. */
.nvpanel > .gpschip{position:absolute;top:calc(100% + 10px);left:50%;right:auto;transform:translateX(-50%);white-space:nowrap}
.nvpanel.dock > .gpschip{display:none}

/* b209: THE CLOSURE CARDS, his LAST RIDE and her RIDE COMPLETE. Same card box as the triptych. */
.card.fx-done{border:2px solid var(--good);background:#EEF8F1}
.card.fx-done .fx-mono,.card.fx-done .mono-k{color:var(--good-deep)}
.card.fx-done .fx-done-big{font:900 var(--t-big)/1 var(--display);margin:6px 0 2px;color:var(--ink)}
.card.fx-done .fx-done-big:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.45rem/1 "Archivo Black","Arial Black",sans-serif}   /* b230: the mock's scale */
.card.fx-done .fx-done-sub{font-size:var(--t-small);color:var(--muted);text-align:center;line-height:var(--lh-small);white-space:pre-line}
.card.fx-done .fx-done-sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;line-height:1.3}
.card.fx-done .fx-done-btns{display:flex;gap:var(--sp-2);margin-top:10px;width:100%}
.card.fx-done .fx-done-btns .aff{flex:1;height:40px;border-radius:10px;display:grid;place-items:center;background:var(--ink);color:#fff;font:700 var(--fs-label) "JetBrains Mono",monospace;letter-spacing:.08em;cursor:pointer}
.card.fx-done .fx-done-btns .aff.hot{background:var(--orange);color:#fff}
.card.fx-done[hidden]{display:none!important}
/* b584: a ride still owed wears MONEY OWED's red, never the paid green (bug-mvpfwtgg-9bkt8) */
.card.fx-done.owed{border-color:var(--red);background:#FFF5F3}
.card.fx-done.owed .fx-mono,.card.fx-done.owed .mono-k{color:var(--red-ink)}
.card.fx-done.owed .fx-done-btns .aff.hot{background:var(--ink);color:#fff}

/* b219: TRIP COMPLETED, the sheet itself. Brand colours only: Forge Orange for the line, the
   check, DONE and PAY; ink for the A pin and RECEIPT. No green, no stars. */
.sheet.fx-fin{padding:var(--sp-2) var(--sp-4) 14px}
.sheet.fx-fin[hidden]{display:none!important}
.fx-fin .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.fx-fin .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.fx-fin .fin-head{text-align:center;padding:2px 0 6px}
.fx-fin .fin-route{max-width:320px;margin:0 auto var(--sp-1)}
.fx-fin .fin-route svg{width:100%;height:auto;display:block}
.fx-fin .fin-tag{display:block;color:var(--orange);font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:3px;margin:2px 0}
.fx-fin h4{margin:0 0 10px;font-size:var(--t-page);text-align:center;font-family:'Space Grotesk',sans-serif;font-weight:600}
.fx-fin h4:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem;font-family:'Space Grotesk',sans-serif;font-weight:800}
.fx-fin .fin-who{border:1px solid var(--line);border-radius:var(--r-ctl);padding:var(--sp-3) 14px;margin:0 0 10px;text-align:left}
.fx-fin .fin-who .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:2px;color:var(--muted)}
.fx-fin .fin-who b{display:block;font-size:var(--t-card);margin:2px 0;font-weight:600}
.fx-fin .fin-who b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.35rem}
.fx-fin .fin-who .leg{color:#555;font-size:var(--t-small)}
.fx-fin .fin-who .leg:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem}
.fx-fin .fin-money > div{display:flex;justify-content:space-between;padding:var(--sp-2) 2px;border-bottom:1px solid var(--line);font-size:var(--t-body)}
.fx-fin .fin-money > div:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-fin .fin-money > div.tot{border:0;font-weight:600;font-size:var(--t-card)}
.fx-fin .fin-money > div.tot:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:800;font-size:1.2rem}
.fx-fin .fin-sms{background:var(--red-wash);color:var(--red-ink);border-radius:10px;padding:7px 10px;font-size:var(--t-small);text-align:center;margin:6px 0 10px}
.fx-fin .fin-sms:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem}
.fx-fin .fin-sms[hidden]{display:none!important}
.fx-fin .fin-line{background:var(--paper);border-radius:var(--r-input);padding:var(--sp-3) 14px;font-size:var(--t-body);color:#222;margin:6px 0 var(--sp-3);text-align:left}
.fx-fin .fin-line:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.fx-fin .fin-btns{display:grid;grid-template-columns:1fr;gap:10px}
.fx-fin .fin-btns.two{grid-template-columns:1fr 1fr}
.fx-fin .fin-btns .cta{margin:0;min-height:var(--act-h)}
.fx-fin .fin-btns .cta.k{background:var(--ink)}
.fx-fin .fin-cols{display:grid;grid-template-columns:1fr;gap:0}
@media (min-aspect-ratio: 6/5){
  .fx-fin .fin-cols{grid-template-columns:1fr 1.2fr;gap:22px;align-items:start}
}

/* b220: the Passenger Link sheet over Home, the Safety block's own classes do the rest */
.sheet.fx-pl{padding:var(--sp-2) var(--sp-4) 14px}
.sheet.fx-pl[hidden]{display:none!important}
.fx-pl .pl-h{margin:var(--sp-1) 0 10px;font-size:var(--t-card);font-family:'Space Grotesk',sans-serif;font-weight:600}
.fx-pl .pl-h:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.3rem;font-family:'Space Grotesk',sans-serif;font-weight:800}
.fx-pl .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.fx-pl .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.fx-pl .linkrow{margin:var(--sp-2) 0 10px}
/* b221: a box the ride measured wears a thin orange edge until he types in it */
.clfield[data-measured="1"]{border-color:var(--orange)}

/* b226: MONEY DUE. The switch (close-out and the trip editor) and the pill in the money slot. */
.clpaid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2);margin:var(--sp-1) 0 var(--sp-3)}
.clpaid-b{cursor:pointer}


/* b353: PAID NOW / PAYS LATER / SAVE TRIP, one row, one size (Ahmed, Monique's close-out 09-18). The save
   is the third cell; its green comes from the rule t145 pins, the size from here. */
.clpaid.clpaid3{grid-template-columns:repeat(3,minmax(0,1fr))}
.clpaid3 .clpaid-b{padding:0 var(--sp-1);min-width:0}
.fx-ride .clsec .clpaid3 .clsave{flex:none}
/* b353: the unit sits inside the box, bold, so MILES and MIN can never be mistaken for each other */
.clunit{display:flex;align-items:center;height:48px;border:1px solid var(--line);border-radius:var(--r-input);background:var(--card);padding:0 var(--sp-3) 0 0;gap:6px}
.clunit:focus-within{border-color:var(--ink)}
.clmet .clunit .fx-in{border:0;height:46px;flex:1 1 auto;min-width:0;border-radius:var(--r-input)}
.clunit u{text-decoration:none;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:800;letter-spacing:.06em;color:var(--ink);flex:0 0 auto}
.aff.warn.due{background:var(--red);color:#fff;font-weight:800;white-space:nowrap}
.tdpaid{margin-bottom:10px}
.tdmark{margin:0 0 var(--sp-2)}
.tdmark[hidden]{display:none!important}
/* b372: HOW THEY PAID (Ahmed 2026-09-19, bug-mu8tygsm-7555a, #f-due option 3). One row for both MARK PAID doors, the
   trip editor and Home's MONEY OWED sheet: seven ways, a note only he sees, CONFIRM. Picked is green (the checklist
   row: the selected state is green), 44px taps, a 16px note so a phone does not zoom. */
.tdhow{display:block;width:100%;margin:0 0 var(--sp-2);cursor:pointer}
.phow{display:flex;flex-direction:column;gap:var(--sp-2);border:1px solid var(--line);border-radius:var(--r-ctl);padding:10px var(--sp-3);background:var(--card);margin:0 0 var(--sp-2);min-width:0}
.phow-k{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.phow-chips{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}
.phow-c{min-width:0;padding:0 var(--sp-1);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.phow-note{display:block;min-height:44px;width:100%;box-sizing:border-box;border:1.5px solid var(--line);border-radius:10px;padding:0 var(--sp-3);font:400 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card)}
.phow-note:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:500 16px 'Space Grotesk',sans-serif}
.phow-when{font-size:var(--t-small);color:var(--muted)}
.phow-when:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem}
.phow-btns{display:flex;gap:var(--sp-2)}
.phow-btns button{flex:1 1 0;cursor:pointer}


.phow-btns button[disabled]{opacity:.6;cursor:default}
.badge.good.flagpaid{background:var(--good);color:#fff;letter-spacing:.02em}
.tdhow[hidden], .tdhowbox[hidden]{display:none!important}

/* b227: the update sheet over Home */
.sheet.fx-upd{text-align:center;padding:var(--sp-2) var(--sp-4) 14px}
.sheet.fx-upd[hidden]{display:none!important}
.fx-upd .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.fx-upd .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.fx-upd .upd-icon{width:72px;margin:6px auto var(--sp-2)}
.fx-upd .upd-icon svg{width:100%;height:auto;display:block}
.fx-upd h4{margin:0 0 6px;font-size:var(--t-page);font-family:'Space Grotesk',sans-serif;font-weight:600}
.fx-upd h4:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.5rem;font-family:'Space Grotesk',sans-serif;font-weight:800}
.fx-upd .upd-p{margin:0 0 10px;color:#222;font-size:var(--t-body)}
.fx-upd .upd-p:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-upd .upd-ver{display:flex;flex-direction:column;gap:var(--sp-1);font-family:'JetBrains Mono',monospace;font-size:var(--t-small);letter-spacing:1px;color:var(--muted);margin:0 0 14px}
.fx-upd .upd-ver:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:.8rem}
.fx-upd .upd-ver b{color:var(--ink)}
.fx-upd .fin-btns{display:grid;grid-template-columns:1fr;gap:10px;margin-bottom:10px}
.fx-upd .fin-btns .cta{margin:0;min-height:var(--act-h)}
.fx-upd .fin-btns .cta.k{background:var(--card);color:var(--ink);border:1.5px solid var(--ink)}

/* b230: four cards stay (Ahmed 2026-08-22, "I like the four cards"), the b229 hide rule is gone */
/* b229: the finish sheet in LONG: title and buttons left, the figures right, one screen, DONE never hidden */
.sheet.fx-fin .fin-btns{margin-top:var(--sp-1)}
@media (min-aspect-ratio: 6/5){
  .sheet.fx-fin{display:grid;grid-template-columns:1fr 1.2fr;grid-template-areas:"grab grab" "head body" "btns body";column-gap:22px;align-items:start}
  .sheet.fx-fin > .grab{grid-area:grab;justify-self:center}
  .sheet.fx-fin > .fin-x{grid-area:body;justify-self:end;align-self:start;position:relative;top:0;right:0}
  .sheet.fx-fin > .fin-head{grid-area:head}
  .sheet.fx-fin > .fin-body{grid-area:body}
  .sheet.fx-fin > .fin-btns{grid-area:btns;align-self:start}
  /* b584, RIDE FINISHED ON THE FOLD (Ahmed 2026-10-26, bug-mvpfvlpe-9uppf, 921 x 680: "this screen I can't see the whole
     thing... on the left is a lot of negative space... the X should always be on the top right corner"). The b568 title
     bar was auto placed into the left column, so its X sat in the middle of the sheet, and the receipt block (b381, never
     given a place) took the right column's first row, which pushed the trip and DONE under it, off the screen, and left
     the left column empty. Now: the bar across the whole top, X at the right; left, the trip, the money and DONE, on
     screen; right, the receipt, scrolling with the sheet. */
  .frame[data-role="driver"] > .sheet.fx-fin{grid-template-areas:"bar bar" "head rxr" "body rxr" "btns rxr" ". rxr";grid-template-rows:auto auto auto auto 1fr;align-content:start}
  .frame[data-role="driver"] > .sheet.fx-fin > .shbar{grid-area:bar}
  .frame[data-role="driver"] > .sheet.fx-fin > .shpeek{display:none}
  .frame[data-role="driver"] > .sheet.fx-fin > .rxrhost{grid-area:rxr;min-width:0}
}

/* b230: RIDE FINISHED keeps the height of its neighbours (the approved closure mock, fit one page).
   The name is one line, the sub two, the two doors share one row. Nothing in it may grow the row. */
.card.fx-done .nm{font-size:var(--t-card);line-height:var(--lh-card);max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600}
.card.fx-done .nm:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem;line-height:1.2}
.card.fx-done .fx-done-sub{font-size:var(--fs-label);line-height:1.25;max-height:2.6em;overflow:hidden}
.card.fx-done .fx-done-btns{margin-top:auto;padding-top:var(--sp-2)}
.card.fx-done .fx-done-btns .aff{height:38px;font-size:var(--fs-label);letter-spacing:.05em;padding:0 var(--sp-1);white-space:nowrap}

/* b235: the passenger landing's one waiting line, under GO ONLINE */
.fx-land .landnote{margin:10px auto 0;max-width:26em;text-align:center;font-size:var(--t-body);color:var(--muted);line-height:var(--lh-body)}
.fx-land .landnote:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;line-height:1.35}
.fx-land .landnote[hidden]{display:none!important}
/* b502: the rider landing's CAN'T REACH line (audit finding 9). One calm muted sentence in the
   landnote's own measure, and a ghost RETRY under it at the 44px tap the audit asked for, narrow,
   so it reads as a second thought under GO ONLINE and never competes with it. */
.fx-land .landreach{width:100%;max-width:26em;margin:var(--sp-1) auto 0;display:flex;flex-direction:column;align-items:center;gap:var(--sp-3);text-align:center}
.fx-land .landreach[hidden]{display:none!important}
.fx-land .landreach-tx{font-size:var(--t-body);color:var(--muted);line-height:var(--lh-body)}
.fx-land .landreach-tx:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;line-height:1.35}
.fx-land .landreach-btn{width:auto;min-width:160px;min-height:44px;height:44px;padding:0 28px;font-size:var(--t-body)}
.fx-land .landreach-btn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}

/* b238: her "no next ride" sheet, the update sheet's frame */
.sheet.fx-nxt{text-align:center;padding:var(--sp-2) var(--sp-4) 14px}
.sheet.fx-nxt[hidden]{display:none!important}
.fx-nxt .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.fx-nxt .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.fx-nxt h4{margin:10px 0 6px;font-size:var(--t-page);font-family:'Space Grotesk',sans-serif;font-weight:600}
.fx-nxt h4:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.4rem;font-family:'Space Grotesk',sans-serif;font-weight:800}
.fx-nxt .nxt-p{margin:0 0 14px;color:#222;font-size:var(--t-body)}
.fx-nxt .nxt-p:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-nxt .fin-btns{display:grid;grid-template-columns:1fr;gap:10px;margin-bottom:10px}
.fx-nxt .fin-btns .cta{margin:0;min-height:var(--act-h)}
.fx-nxt .fin-btns .cta.k{background:var(--card);color:var(--ink);border:1.5px solid var(--ink)}

/* b239: her booking sheet. Same frame as the "no next ride" sheet, with the money card the driver
   side has carried since b37, so both people are reading the same confirmation. */
.sheet.fx-bkd{text-align:center;padding:var(--sp-2) var(--sp-4) 14px}
.sheet.fx-bkd[hidden]{display:none!important}
.fx-bkd .fin-x{position:absolute;top:8px;right:10px;width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.fx-bkd .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.fx-bkd h4{margin:10px 0 10px;font-size:var(--t-page);font-family:'Space Grotesk',sans-serif;font-weight:600}
.fx-bkd h4:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.4rem;font-family:'Space Grotesk',sans-serif;font-weight:800}
/* b444 (Ahmed 2026-10-01: "the dark green that we use, the normal one, with white text... this is how much you're
   paying, this is what you booked, nice and green, and it needs to feel peaceful"). Her BOOKED AT card is the app's
   green (--good, the WORKS green) with white type, soft edges, no hard border. */
.fx-bkd .bkd-card{border:none;background:var(--good,var(--good));color:#fff;border-radius:16px;padding:14px var(--sp-3) var(--sp-4);margin:0 0 var(--sp-3);
  box-shadow:0 6px 18px rgba(31,157,87,.28)}
.fx-bkd .bkd-card .k{font-family:'Space Grotesk',sans-serif;font-weight:800;font-size:var(--t-label);letter-spacing:.14em;color:#fff}
.fx-bkd .bkd-card .k:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:.78rem}
.fx-bkd .bkd-card .big{font-family:var(--display);font-weight:800;font-size:var(--t-big);line-height:1.1;color:#fff}
.fx-bkd .bkd-card .big:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:800;font-size:2.8rem;line-height:1.1}
.fx-bkd .bkd-card .sub{font-size:var(--t-body);color:#fff}
.fx-bkd .bkd-card .sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-bkd .nxt-p{margin:0 0 14px;color:#222;font-size:var(--t-body)}
.fx-bkd .nxt-p:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.fx-bkd .fin-btns{display:grid;grid-template-columns:1fr;gap:10px;margin-bottom:10px}
.fx-bkd .fin-btns .cta{margin:0;min-height:var(--act-h)}
.fx-bkd .fin-btns .cta.k{background:var(--card);color:var(--ink);border:1.5px solid var(--ink)}

/* b242: the stage label under the recenter badge, both rails. The button is a 52px circle; the
   label sits just outside its bottom edge so the glyph stays centred and the word reads in lime
   on the rail's own ground. */
.navctl .mbtn .rclab{position:absolute;left:50%;top:-16px;transform:translateX(-50%);white-space:nowrap;   /* ABOVE, his words: "small overview text right above it" */
  font-size:var(--fs-label);letter-spacing:.08em;color:var(--ink);background:var(--card);padding:0 var(--sp-1);border-radius:6px;line-height:12px}

/* b248: THE LADYBUG, Option C off the approved mockup. Injected by app-ladybug.js into every
   footer before Menu; CSS shows it on the DRIVER only (v1 is Ahmed's build, his Q1 answer).
   Idle: the brand ladybug. Recording: the slot becomes a blinking elapsed clock. */
.foot .tab.lbug{display:none}
/* b262: the passenger reports too (his ask 2026-08-24), same button, same loop */
body[data-role="driver"] .foot .tab.lbug,
body[data-role="passenger"] .foot .tab.lbug{display:flex}
.foot .tab.lbug .lbugsvg{width:24px;height:24px}   /* b563: 24 like the other five tabs (UI audit #31) */
.foot .tab.lbug .lbtimer{display:none;font-style:normal;font-size:.78rem;font-weight:800;color:#C0392B;height:22px;align-items:center;animation:lbblink 1.2s infinite}
.foot .tab.lbug.rec .lbugsvg{display:none}
.foot .tab.lbug.rec .lbtimer{display:flex}
.foot .tab.lbug.rec .lblab{color:#C0392B}
/* b449: REPORT A BUG under GO ONLINE, the owner's own door to the ladybug before he is online (no footer on the landing).
   The ladybug's red, a ghost button so GO ONLINE stays the one big action, 48px tall. */
.lb-ownbtn{display:flex;align-items:center;justify-content:center;gap:var(--sp-2);margin:var(--sp-3) auto 0;min-height:48px;min-width:200px;
  padding:0 22px;border-radius:var(--r-pill);border:2px solid #FF3B00;background:var(--card);color:#FF3B00;font:inherit;font-weight:800;
  font-size:.95rem;letter-spacing:.04em;cursor:pointer;-webkit-tap-highlight-color:transparent}
.lb-ownbtn[hidden]{display:none}
.lb-ownbtn.rec{background:#FF3B00;color:#fff}
@keyframes lbblink{0%,100%{opacity:1}50%{opacity:.45}}

/* ================================================================================================
   b253: THE OFFER SHEET DENSITY, Ahmed's tuned spec approved off the f-offerdensity v5 mockup
   (ticket bug-mt6ppf1q-yhnlq). Rates one centered line, the price centered, the meas strip
   centered, and on the WIDE layout the left rows share their right partner's height rhythm.
   ================================================================================================ */
:is(.fx-off,.fx-pricing) .fx-off-p{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:var(--sp-2);text-align:center;padding:11px var(--sp-2)}
:is(.fx-off,.fx-pricing) .fx-off-p .s{display:none}
:is(.fx-off,.fx-pricing) .fx-off-p .k{order:2;margin:0}
:is(.fx-off,.fx-pricing) .fx-off-p .amt{order:1;margin:0}
:is(.fx-off,.fx-pricing) .fx-off-p{position:relative}
/* the pill rides the corner so the line stays "$19 PER MILE", one line, centered (his rule) */
:is(.fx-off,.fx-pricing) .fx-off-p .pick{position:absolute;top:-7px;right:8px;margin:0;font-size:var(--fs-label);padding:2px 7px}
:is(.fx-off,.fx-pricing) .fx-off-p .pick[hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-in{justify-content:center;text-align:center}
:is(.fx-off,.fx-pricing) .fx-off-meas{text-align:center}
:is(.fx-off,.fx-pricing) .fx-off-meas .k{display:block}
:is(.fx-off,.fx-pricing) .fx-off-chk{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-ab{margin-bottom:var(--sp-2)}
/* b255: the b253 static guesses are gone; offAlignPairs MEASURES each left/right pair after
   every paint and sets both to the larger height (Ahmed: "everything needs to be measured").
   These rules only make a stretched box center its content and share one 8px margin rhythm,
   so equal heights also mean equal row tops. */
:is(.fx-off,.fx-pricing) [data-pair]{margin:0 0 var(--sp-2)}
:is(.fx-off,.fx-pricing) [data-pair][hidden]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-when[data-pair],
:is(.fx-off,.fx-pricing) .fx-off-meas[data-pair]{align-items:center}
:is(.fx-off,.fx-pricing) .fx-off-type[data-pair]{align-items:center}
:is(.fx-off,.fx-pricing) .fx-off-ab[data-pair]{display:flex;flex-direction:column;justify-content:center}
:is(.fx-off,.fx-pricing) .fx-off-basis[data-pair]{align-items:stretch}
:is(.fx-off,.fx-pricing) .fx-off-prices[data-pair]{align-items:stretch}
:is(.fx-off,.fx-pricing) .fx-off-ovr[data-pair]{align-items:center}
:is(.fx-off,.fx-pricing) .fx-off-acts2[data-pair]{align-items:stretch}
:is(.fx-off,.fx-pricing) .fx-off-acts2[data-pair] .cta{height:auto}

/* b254: THE OFFER SHEET MATCHES THE MOCKUP (Ahmed's screenshot review of b253).
   The title row is retired: the passenger row carries the name, so the block collapses. The
   decline/cancel-history badges it hosted (b44) keep painting; with no badge showing the row is
   zero height, with one it stands alone as its own small line, the fact survives. */
:is(.fx-off,.fx-pricing) .fx-off-name .nm{display:none}
:is(.fx-off,.fx-pricing) .fx-off-name [data-off="nth"]{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-name{margin:0}
:is(.fx-off,.fx-pricing) .fx-off-name:not(:has(.badge:not([hidden]))){display:none}
/* the "Everything else they sent" row is retired; its descriptive facts moved into the flag
   card's own line (typeSub), his call. The grid goes with it. */
:is(.fx-off,.fx-pricing) .fx-off-more{display:none!important}
:is(.fx-off,.fx-pricing) .fx-off-grid[data-off="moregrid"]{display:none!important}
/* the when strip never shows a sub word ("small") under a value */
:is(.fx-off,.fx-pricing) .fx-off-when .s{display:none}

/* b255b: THE RIGHT SIDE SHOUTS (Ahmed 2026-08-24). The whole money column is uppercase so it
   stands apart from the left; the meas strip holds one line per cell at one size, never wraps. */
:is(.fx-off,.fx-pricing) .fx-off-rightcol{text-transform:uppercase}
:is(.fx-off,.fx-pricing) .fx-off-rightcol .fx-off-bseg,
:is(.fx-off,.fx-pricing) .fx-off-rightcol .cta{text-transform:uppercase}
:is(.fx-off,.fx-pricing) .fx-off-meas > div{min-width:0}
:is(.fx-off,.fx-pricing) .fx-off-meas b{white-space:nowrap;font-size:var(--t-body)}
:is(.fx-off,.fx-pricing) .fx-off-meas b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
:is(.fx-off,.fx-pricing) .fx-off-meas .k{white-space:nowrap}

/* b256: CENTERED FOR REAL (Ahmed's live screenshot, 2026-08-24). The trip strip's values center
   under their labels; the estimate box centers YOUR ESTIMATE IS $18 as one phrase with no gap
   inside $18. Scoped to the offer's own boxes, the Settings fields keep their layout. */
:is(.fx-off,.fx-pricing) .fx-off-meas > div{justify-content:center}
:is(.fx-off,.fx-pricing) .fx-off-ovr .fx-off-in{gap:0}
:is(.fx-off,.fx-pricing) .fx-off-ovr .fx-off-in .lb{margin-right:10px}
:is(.fx-off,.fx-pricing) .fx-off-ovr .fx-off-num{flex:0 1 auto;width:2ch;min-width:1ch;field-sizing:content;text-align:left}

/* ================================================================================================
   b257: THE PICKED SKIN (Ahmed 2026-08-24, off the f-offercolors mockups). One law: SELECTED =
   GREEN. White cards, ONE hairline outline and soft shadow on every box (his B pick), the black
   date strip retired (his screenshot), the flag and B pin lose their orange, the active basis's
   numbers green in the trip strip, the estimate money the sheet's one orange, both CTAs neutral
   until hover or press turns them green. Red stays reserved for the floor warning.
   NOTE on the lime-labels law: it applies to labels ON THE DARK SURFACE; this sheet no longer
   has a dark surface, so its labels are the standard grey-on-white, his explicit call.
   ================================================================================================ */
:is(.fx-off,.fx-pricing) :is(.fx-off-when,.fx-off-type,.fx-off-ab,.fx-off-basis,.fx-off-meas,.fx-off-in,.fx-off-step,.fx-off-p){
  box-shadow:0 1px 4px rgba(10,10,10,.05)}
/* the date strip goes white, his screenshot */
:is(.fx-off,.fx-pricing) .fx-off-when{background:#fff;border:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-when > div{border-left:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-when > div:first-child{border-left:none}
:is(.fx-off,.fx-pricing) .fx-off-when .k{color:var(--muted)}
:is(.fx-off,.fx-pricing) .fx-off-when b{color:var(--ink)}
/* the flag card joins the family: white, hairline, ink icon */
:is(.fx-off,.fx-pricing) .fx-off-type{background:var(--card);border:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-type svg{stroke:var(--ink)}
/* the B pin loses its orange, both pins ink */
:is(.fx-off,.fx-pricing) .fx-off-ab .pin.b{background:var(--ink)}
/* the toggle: hairline box, the chosen side GREEN (was ink) */
:is(.fx-off,.fx-pricing) .fx-off-basis{border:1px solid var(--line);background:var(--card)}

/* the trip strip: hairline, and the live basis's numbers go green with the toggle */
:is(.fx-off,.fx-pricing) .fx-off-meas{border:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-meas[data-on="trip"] > div:first-child b,
:is(.fx-off,.fx-pricing) .fx-off-meas[data-on="whole"] > div:last-child b,
:is(.fx-off,.fx-pricing) .fx-off-meas[data-on="all"] b{color:var(--good)}
/* the rate cards: unselected is white like every other off control (was ink with lime); the
   chosen card is the one selected look, ink with white (b569, was the green fill) */
:is(.fx-off,.fx-pricing) .fx-off-p{background:var(--card);color:var(--ink);border:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-p .k{color:var(--muted)}


/* the estimate: hairline box, the label and the money ORANGE, the sheet's one orange, it is
   the offer amount; the red warnbox ring still wins when a floor is broken */
:is(.fx-off,.fx-pricing) .fx-off-in{border:1px solid var(--line)}
:is(.fx-off,.fx-pricing) .fx-off-in .lb,:is(.fx-off,.fx-pricing) .fx-off-in .cur{color:var(--orange)}
:is(.fx-off,.fx-pricing) .fx-off-ovr .fx-off-num{color:var(--orange)}

/* the CTAs: b569 gave them the button system, SEND OFFER the one orange, BOOK IT white. The green hover and press
   (b258, b262) went with it, green is for states only. */


/* ================================================================================================
   b258: THE OFFER SCREEN JOINS THE SHELL (ticket bug-mt7hp3dd-yeolu, plan approved).
   ================================================================================================ */
/* the grey facade map yields while the LIVE map is in the frame, and returns when it leaves */
.fx-off .map[data-map="live"] ~ .map{display:none}
/* the trip strip cells are TAPPABLE doors to the basis choice, never a text selection */
:is(.fx-off,.fx-pricing) .fx-off-meas > div{cursor:pointer;-webkit-user-select:none;user-select:none}
/* the ACTIVE cell's texts go ORANGE, matching YOUR ESTIMATE IS: one orange chain from the
   numbers to the money they produce (replaces the b257 green). The toggle stays green. */
:is(.fx-off,.fx-pricing) .fx-off-meas[data-on="trip"] > div:first-child :is(.k,b),
:is(.fx-off,.fx-pricing) .fx-off-meas[data-on="whole"] > div:last-child :is(.k,b),
:is(.fx-off,.fx-pricing) .fx-off-meas[data-on="all"] :is(.k,b){color:var(--orange)}

/* b259: a stale lead's date strip says so in the warning color; red stays reserved for warnings */
:is(.fx-off,.fx-pricing) .fx-off-when.past :is(.k,b){color:var(--red)}

/* b260: the success state of the estimate box, his reversed colors: orange fill, white text,
   same box, same size, no extra line anywhere */
:is(.fx-off,.fx-pricing) .fx-off-in.booked{background:var(--orange);border-color:var(--orange)}
:is(.fx-off,.fx-pricing) .fx-off-in.booked :is(.lb,.cur){color:#fff}
:is(.fx-off,.fx-pricing) .fx-off-ovr .fx-off-in.booked .fx-off-num{color:#fff}

/* b262: BOOKED AT $15 is ONE line in the booked card, the big font kept (his ticket) */
:is(.fx-off,.fx-pricing) .fx-off-okcard{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;column-gap:10px}
:is(.fx-off,.fx-pricing) .fx-off-okcard .sub{flex:1 0 100%}
/* b267's green SAVE THIS TRIP became the orange PRIMARY in b569 (the one button system, green is for states only) */

/* b271: THE LANDING KEEPS THE SHELL. The live map slides behind it (same mechanism as every
   other shell screen); the veil keeps the logo, name and GO ONLINE readable on top of it. When
   no map exists yet (nothing to show), the landing looks exactly as before. */
.fx-entry .fx-land{position:relative;z-index:2}
/* b274: BEHIND means BEHIND. The landing's map joined the frame as a flex SIBLING, so on a
   phone it took its flex share of the column and shoved GO ONLINE off the screen (Ahmed's
   11:37 screenshot, "I can't even click this button"). On the landing the map is an absolute
   backdrop filling the frame; the content column lays out exactly as it did with no map. */
.fx-entry .map{position:absolute;inset:0;min-height:0;z-index:0}
/* and the nav chrome that rides with the map stays out of sight on a landing: it belongs to
   driving screens, not to the offline doorway */
.fx-entry :is([data-nv="row"],[data-nv="ctl"],[data-nv="panel"],[data-pv="row"],[data-pv="ctl"]){display:none}
.fx-entry:has(.map) .fx-land{background:linear-gradient(rgba(244,244,242,.86),rgba(244,244,242,.86))}
/* b297: HOME KEEPS THE SHELL TOO, both roles. Ahmed 2026-09-09 1:08 PM: the landing with the map
   behind it "looks really cool", Home on plain grey "doesn't look that good", and after a ride
   "we never see this bland grey background anymore". Same backdrop, same veil, the header and the
   footer stay opaque above it. The map is a backdrop (absolute, z 0), the dashboard column sits
   on the veil (z 2), the chrome bars above both (z 3). */
.fx-entry:has(.map) > .scr{position:relative;z-index:2;background:linear-gradient(rgba(244,244,242,.86),rgba(244,244,242,.86))}
.fx-entry > .hd, .fx-entry > .foot{position:relative;z-index:3}
.frame[data-role="passenger"][data-screen="home"] > .map[data-map="paxlive"]{position:absolute;inset:0;min-height:0;flex:none;z-index:0}
.frame[data-role="passenger"][data-screen="home"]:has(.map) > .scr{position:relative;z-index:2;background:linear-gradient(rgba(244,244,242,.86),rgba(244,244,242,.86))}
.frame[data-role="passenger"][data-screen="home"] > .hd, .frame[data-role="passenger"][data-screen="home"] > .foot{position:relative;z-index:3}
.frame[data-role="passenger"][data-screen="home"] :is([data-pv="row"],[data-pv="ctl"]){display:none}

/* b272: THE WARM DOCK. Full-size and laid out (the map keeps its viewport and its tiles),
   paint-hidden (visibility) and behind every opaque screen, never interactive. The column flex
   matches the frame the map normally lives in, so parking is a same-size reparent. */
.mapdock{position:fixed;inset:0;z-index:0;pointer-events:none;visibility:hidden;
  display:flex;flex-direction:column}

/* b275: .cta AND .aff GET THEIR [hidden] RULES. Both carry an explicit display, which silently
   BEATS the browser's [hidden] (the 2026-07-31 law, found AGAIN by ride #23's DOM replay: the
   retired I-paid button had its [hidden] attribute set and kept rendering anyway, and Ahmed
   paid twice). Every other component family in this file already carries its rule. */
.cta[hidden]{display:none!important}
.aff[hidden]{display:none!important}

/* b282: THE OVERRIDE RING. While a temporary close-up (the last 1000 ft, or a ramp) sits on top of
   the stage he picked, the stage badge keeps its number and grows an orange ring around it, with a
   white gap so it reads on the map. Ahmed's pick, 2026-09-05: "keep your stage, and see the app is
   temporarily zoomed in." A RING and not a dot: the red count pip already owns the top-right corner
   of this button (measured 09-05, a dot there sat on the pip). A ring is drawn by box-shadow, so it
   never moves the badge text or the pip. */
.navctl .mbtn.ovr{box-shadow:0 0 0 2px #fff, 0 0 0 5px var(--orange)}

/* b287: THE NO-PHONE FLAG. A booking with no number turns its passenger row orange on the ride
   sheet and on the Home card, so the gap is seen days before the pickup, not at the curb. */
/* b713: he could barely read it (Ahmed 2026-11-01), orange on white is 3.4 to 1. 15px and the dark red, 7 to 1 */
.row.nophone .tx span, .row.nophone b[data-rd="paxphone"]{color:#A12A1B;font-weight:800;font-size:15px}
.row.nophone .tx > b::after{content:" \26A0";color:#A12A1B}
/* b304: a stylesheet stamp bump with no rule change, so Ahmed's phone (still on the b301 checker, which watched this file's stamp alone) offers the update sheet; from b303 on the checker reads the newest stamp on the page. 2026-09-09 7:35 PM */
/* b306: stamp only. Every build moves this stamp now, so the update prompt (which reads the newest stamp on the page) sees a change even when only app.html changed. */
/* b309: stamp only, the calendar event links (rider app link, Google flight tracker) live in functions/api/_calfmt.js */
/* b310: the no-phone warning on the driver Home, one red row per upcoming booking with no phone */
/* b713 (Ahmed 2026-11-01, "I can barely see that. That's important"): it left the bottom of Home for the row under the top pills, a full width child of .cards3, in its own solid
   fill so it reads over the map. White on #A12A1B is 7.5 to 1, a fixed colour so a driver's brand colour cannot fade it. */
.nophone-alert{display:grid;gap:var(--sp-2);margin:0}
.nophone-alert[hidden]{display:none}
.cards3 > .nophone-alert{flex:1 1 100%;width:100%;min-width:0}
.cards3[data-hcfolds="none"] > .nophone-alert{order:-1}
.cards3:has(> .nophone-alert:not([hidden])){flex-wrap:wrap}
.nophone-row{display:block;width:100%;min-height:52px;text-align:left;cursor:pointer;font:inherit;
  background:#A12A1B;color:#FFFFFF;border:0;border-radius:var(--r-input);padding:10px 14px}
.nophone-row b{display:block;color:#FFFFFF;font-size:17px;line-height:1.25;font-weight:800}
.nophone-row b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:800}
.nophone-row span{display:block;color:#FFFFFF;font-size:15px;font-weight:600;line-height:1.3;margin-top:2px}
.nophone-row span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.85rem}
/* b311: stamp only, the fixes are the map polyline vertices, the turn lead and the follow hold */
/* b312: stamp only, the fixes are the recenter stage zoom and the five minute button */
/* b313: stamp only, the fix is the Google call floors in app-nav.js */
/* b314: tiles read title first, the header icon buttons are gone from the markup */

/* ---- b315: MAPS COST, owner only -------------------------------------------------------------------
   The tile is INK, not white (Ahmed 2026-09-16: "this button needs to look different because it's only on
   my end"), with an OWNER tag, so it can never be mistaken for a tool every driver has. */
.tile[hidden]{display:none!important}
/* b353: ORANGE, WHITE TEXT, WHITE ICON (Ahmed, Home after Monique 09-18: "I want the background to be orange
   and I want map cost to be white text and I want the logo to be white... and where it says [the tag] find
   another place to put it... maybe just a little D on the top right corner"). The word tag becomes a small
   white corner mark; the orange fill is now what says "only mine". */
.tile.owner{background:var(--orange);border-color:var(--orange);color:#fff}
.tile.owner b{color:#fff}
.tile.owner .ic{border-color:#fff;background:transparent;color:#fff}
.tile.owner .ic svg{stroke:#fff}
/* b697: the D corner mark is gone (Ahmed 2026-11-01), Uber Offers was its last wearer and is becoming a free tool. */
/* b704: THE PAID TILES (Ahmed 2026-11-01): "All the paid stuff will be a different background color... Stick to the white text on orange because
   that's what our branding is." A typed #FF3B00, never var(--orange), which a driver's brand colour replaces (applyAccent). White words, icon
   and ring; the count badge goes ink so it does not vanish on the orange. Every role, so Ahmed sees what they see. */
.tile[data-paid]{background:#FF3B00;border-color:#FF3B00;color:#FFFFFF}
.tile[data-paid] b{color:#FFFFFF}
.tile[data-paid] .ic{border-color:#FFFFFF;background:transparent;color:#FFFFFF}
.tile[data-paid] .ic svg{stroke:#FFFFFF}
.tile[data-logo] .ic svg{width:30px;height:30px}   /* b712, b713: the free tiles wear real colour pictures (Ahmed 2026-11-01), the colours sit on the shapes, one attribute for all five */
.tile[data-paid] .nbadge{background:#0A0A0A;color:#FFFFFF}
/* b704: THE FREE PLAN'S HOME: no Google map behind it, a still drawing of streets, so it is not the grey he rejected in b297 */
:root[data-plan="free"] .frame[data-role="driver"]{background-color:#E9E7E0;
  background-image:linear-gradient(112deg,transparent 47%,#D7D4CA 47.3%,#D7D4CA 48.6%,transparent 49%),linear-gradient(24deg,transparent 62%,#DAD7CE 62.3%,#DAD7CE 63.2%,transparent 63.6%),linear-gradient(0deg,rgba(244,244,242,.72),rgba(244,244,242,.72))}
/* b704: THE SIGN UP SHEET, app-freeplan.js, docked over whichever frame he is on */
.frame[data-suopen] > .sheet:not([data-kind="signup"]){visibility:hidden}
.sheet[data-kind="signup"]{gap:var(--sp-2);z-index:30}
.sheet[data-kind="signup"] [data-su="name"]{margin:0;font:700 22px/1.25 var(--body);color:var(--ink)}
.sheet[data-kind="signup"] [data-su="line"]{margin:var(--sp-1) 0 0;font-size:16px;line-height:1.4;color:var(--ink)}
.sheet[data-kind="signup"] [data-su="video"]{margin:var(--sp-2) 0 0;width:100%;aspect-ratio:16/9;max-height:21vh;border:1.5px dashed var(--line);border-radius:var(--r-ctl);background:var(--card)}
.sheet[data-kind="signup"] [data-su="price"]{margin:var(--sp-2) 0;font-size:14px;color:var(--muted)}
.sheet[data-kind="signup"] [data-su="price"] b{font-size:28px;line-height:1.2;color:var(--ink)}
.sheet[data-kind="signup"] [data-su="yes"]{display:block;width:100%;min-height:52px;background:#FF3B00;color:#FFFFFF;border:0;border-radius:var(--r-ctl);font:800 16px var(--body);letter-spacing:.3px}
.sheet[data-kind="signup"] [data-su="say"]{margin:var(--sp-1) 0 0;font-size:14px;color:var(--red-ink)}
.sheet[data-kind="signup"] [data-su="no"]{display:block;width:100%;min-height:44px;margin:var(--sp-1) 0 0;background:transparent;border:0;color:var(--ink);font:600 15px var(--body)}
.fx-mapscost .sheet{display:flex;flex-direction:column;gap:10px}
/* ---- b656: YOUR DEVICES (DV652). The Maps Cost mc-card pieces, each device the Menu's own .row, opened downward so the
   version line, Old version tag, the update hint and RENAME / FORGET sit inside one card. Buttons are the fx-set pair, 48px. */
.frame[data-screen="devices"] .sheet{display:flex;flex-direction:column;gap:10px}
.frame[data-screen="devices"] .row{flex-wrap:wrap;align-items:flex-start;margin:10px 0 0}
.frame[data-screen="devices"] .row > .tx{flex:1 1 0}
.frame[data-screen="devices"] .row[data-old="1"]{border-color:var(--red)}
.frame[data-screen="devices"] .row[data-old="1"] > svg{stroke:var(--red)}
.frame[data-screen="devices"] .row .tx span:first-of-type{font-family:'JetBrains Mono',monospace;font-variant-numeric:tabular-nums;margin-top:2px}
.frame[data-screen="devices"] .row[data-old="1"] .tx span:first-of-type{color:var(--red);font-weight:700}
.frame[data-screen="devices"] .row .tx .mc-pill{display:inline-block;margin-top:8px;font-size:var(--fs-label);line-height:1.3}
.row > [data-dv="rowtag"]{flex:0 0 auto;white-space:nowrap}
.frame[data-screen="devices"] .row > .toolnote{flex:1 1 100%;margin:0}
.frame[data-screen="devices"] .row > input{flex:1 1 100%;min-height:48px;border:1.5px solid var(--ink);border-radius:var(--r-input);padding:0 12px;font:inherit;font-size:var(--t-body);background:var(--card);color:var(--ink)}
.frame[data-screen="devices"] .row > .fx-btns{flex:1 1 100%;display:flex;gap:10px}
.frame[data-screen="devices"] .fx-save{flex:1 1 0;min-height:48px;border:none;border-radius:var(--r-input);background:var(--good);color:#fff;font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body);cursor:pointer}
.frame[data-screen="devices"] .fx-cancel{flex:1 1 0;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);background:var(--card);color:var(--ink);font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body);cursor:pointer}
.frame[data-screen="devices"] .row .tx .mc-pill.warn{color:var(--red)}
.frame[data-screen="devices"] .row .tx .mc-pill.ok{color:var(--good)}
.mc-card{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:14px}
.mc-lbl{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:700;margin-bottom:6px}
.mc-toprow{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.mc-big{font-family:var(--display);font-size:var(--t-big);line-height:1;font-variant-numeric:tabular-nums}
.mc-big:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',Arial,sans-serif;font-size:2.4rem;line-height:1}
.mc-pill{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:3px 9px;border-radius:var(--r-input);border:1.5px solid var(--line);color:var(--muted)}
.mc-pill.ok{color:var(--good);border-color:var(--good)}
.mc-pill.warn{color:var(--red);border-color:var(--red)}
.mc-sub{color:var(--muted);font-size:var(--t-small);margin-top:6px}
.mc-sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem}

/* ---- b349: THE JOURNAL, four moments (Ahmed's pick 1 of the mock, 2026-09-18). Reuses the
   mc-card shell; everything jr- is this screen's own. Lime labels rule: every small label is a
   JetBrains Mono uppercase label like mc-lbl, never grey prose. ---- */
/* MEASURED, not eyeballed (b349, wip at 375 wide): a bare 1fr column takes the widest unbreakable child as
   its minimum, and the day pill made that 349px inside a 338px sheet, so every card overflowed the frame.
   minmax(0,1fr) and min-width:0 make the column the container's width, whatever the children say. */
.fx-journal .sheet{display:grid;grid-template-columns:minmax(0,1fr);gap:10px;align-content:start}
.fx-journal .sheet > *{min-width:0}
.jr-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);min-width:0}
.jr-head h4{margin:0;flex:0 0 auto}
.jr-daynav{display:flex;align-items:center;gap:var(--sp-1);flex:1 1 auto;min-width:0;justify-content:flex-end}
/* b374: 44px, not 36. These two arrows now walk a WEEK and a MONTH back as well as a day, so they are the
   history control for the whole costs view and they have to be hittable with a thumb in a parked car. */
.jr-daynav .aff{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;font-size:var(--t-card);padding:0;flex:0 0 auto;font-weight:600}
.jr-daynav .aff:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.1rem}
.jr-day{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:0;text-transform:uppercase;background:var(--ink);color:#fff;border-radius:var(--r-pill);padding:6px var(--sp-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
/* b699: on the closed Fold the title bar leaves the pill 52px, so it wraps and tightens instead of cutting the date to OCT .. */
@media (max-width:400px){.jr-day{white-space:normal;overflow:visible;text-overflow:clip;text-align:center;line-height:1.15;padding:4px;border-radius:12px}}
.jr-nag{border-color:#B07600;color:#B07600;font-weight:600}
.jr-moments{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px}
.jr-mo{min-width:0}
.jr-mo{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:14px var(--sp-3);min-height:104px;display:flex;flex-direction:column;justify-content:space-between;gap:6px;cursor:pointer}
.jr-mo .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:700}
.jr-mo b{font-family:var(--body);font-weight:400;font-size:var(--t-body);line-height:1.1;display:block}
.jr-mo b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-weight:400;font-size:1.02rem;line-height:1.1}
.jr-mo .v{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-variant-numeric:tabular-nums;color:var(--ink)}
.jr-mo .v.none{color:var(--hint)}
/* b361: DONE IS GREEN, TO DO IS RED (Ahmed 2026-09-18, bug-mu7puns9, at the charger): "leaving home, I'm
   done, that could be green card and white text, so now I know it's done. And then the other two or three
   should still be red... with the red outline." The next one to do also gets a pale red wash. */
.jr-mo:not(.done){border:2px solid var(--red)}
.jr-mo.now{background:var(--red-wash)}
.jr-mo.done{background:#1F9D57;border:2px solid var(--good)}
.jr-mo.done .k,.jr-mo.done b,.jr-mo.done .v{color:#fff}
.jr-fields{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.jr-fld{display:block}
.jr-fld-wide{grid-column:1/-1}
.jr-fld small{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:700;margin-bottom:var(--sp-1)}
.jr-in{height:48px;border:1px solid var(--line);border-radius:10px;background:var(--paper);display:flex;align-items:center;padding:0 var(--sp-3);gap:var(--sp-2)}
.jr-in input{flex:1 1 auto;min-width:0;border:0;background:transparent;font-family:'JetBrains Mono',monospace;font-size:var(--t-card);font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink);outline:none;height:100%}
.jr-in input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:1.02rem;font-weight:700}
.jr-in input::placeholder{color:var(--hint);font-weight:400}
.jr-in u{text-decoration:none;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);color:var(--muted);font-weight:700;flex:0 0 auto}
.jr-in:focus-within{border-color:var(--orange);box-shadow:0 0 0 2px rgba(255,59,0,.15)}
.jr-seg{display:flex}
.jr-seg span{flex:1;text-align:center;padding:12px 0;cursor:pointer}

.jr-btns{display:flex;gap:var(--sp-2);margin-top:10px}
.jr-btns .cta{margin:0}
.cta.ghost{background:var(--card);color:var(--ink);border:1.5px solid var(--ink)}
.jr-remove{display:block;width:100%;margin-top:var(--sp-2);min-height:44px;border:0;background:transparent;color:var(--bad);font-weight:700;font-size:var(--t-small);cursor:pointer}
.jr-remove:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.86rem}
.jr-remove[hidden]{display:none}
.jr-hint.err{color:var(--bad);font-weight:600}
.jr-lbl{display:flex;justify-content:space-between;align-items:center}
.jr-lbl .mono{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);text-transform:none;letter-spacing:0;color:var(--ink)}
.jr-list{display:grid;gap:2px;margin-bottom:var(--sp-2)}
.jr-ride{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:10px 0;border-bottom:1px solid var(--line);cursor:pointer;min-height:44px}
.jr-ride:last-child{border-bottom:0}
.jr-ride b{display:block;font-size:var(--t-body)}
.jr-ride b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.jr-ride span{display:block;font-size:var(--t-small);color:var(--muted);line-height:var(--lh-small)}
.jr-ride span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;line-height:1.3}
.jr-pill{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:3px 9px;border-radius:var(--r-input);border:1.5px solid;flex:0 0 auto}
.jr-pill.ok{color:var(--good);border-color:var(--good)}
.jr-pill.warn{color:#B07600;border-color:#B07600}
/* b562: FOLDED DONE SECTIONS (Ahmed approved, from Your Circle's foldHead). One DONE (N) row per section under the
   items still open: a 44px button, the house orange chip with white text and the count, a chevron that turns when
   open. The moments grid moves its done cards below the row with order and hides them while it is shut. */
.jr-fold{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;box-sizing:border-box;
  margin:var(--sp-1) 0 0;padding:0 14px;cursor:pointer;text-align:left}
.jr-fold-chip{font-family:'JetBrains Mono',monospace;font-size:var(--t-label);line-height:var(--lh-label);font-weight:800;letter-spacing:.12em;text-transform:uppercase;
  background:#FF3B00;color:#FFFFFF;border-radius:4px;padding:3px var(--sp-2);white-space:nowrap}
.jr-fold-chip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:12px;line-height:1.3;font-weight:700}
.jr-fold-chev{font-size:var(--t-body);line-height:1;color:var(--ink);transition:transform .18s ease;flex:0 0 auto}
.jr-fold-chev:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:16px;line-height:1}
.jr-fold[aria-expanded="true"] .jr-fold-chev{transform:rotate(180deg)}
.jr-foldbody{display:grid;gap:2px}
.jr-foldbody[hidden]{display:none}
.jr-list > .jr-fold + .jr-foldbody{margin-top:2px}
.jr-moments > .jr-fold{grid-column:1/-1;order:1;margin:0}
.jr-moments > .jr-mo.done{order:2}
.jr-moments.jr-shut > .jr-mo.done{display:none}
.jr-sub{color:var(--muted);font-size:var(--t-small);padding:6px 0}
.jr-sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem}
.jr-tot{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.jr-tot div{background:var(--paper);border-radius:10px;padding:var(--sp-2) 10px}
.jr-tot small{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:700}
.jr-tot b{font-family:var(--body);font-weight:600;font-size:var(--t-card);font-variant-numeric:tabular-nums}
.jr-tot b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-weight:400;font-size:1.2rem}
/* b374: WHAT THE DAY, WEEK AND MONTH REALLY COST AND EARNED (Ahmed 2026-09-19, #f-costs option 1). Built on the
   Journal's own look, paper tiles with JetBrains Mono labels and Archivo Black numbers, so the costs read as the
   same screen rather than a second design. Selected is GREEN and red is kept for the one warning, the Panels and
   branding law; every tap target is 44px or more; every number is tabular so a column of money lines up. */
/* MEASURED, not eyeballed. .jr-seg carries overflow:hidden for its rounded corners, which makes it a SCROLL
   CONTAINER, and a scroll container contributes ZERO to intrinsic sizing in the scrolled axis. Everywhere else
   in this app .jr-seg sits inside a plain block (.jr-fld), where height:auto reads its content and the rule
   never bites. As a direct GRID ITEM of .fx-journal .sheet its auto row sized itself from that zero, so the
   switch rendered as a 2px hairline with three invisible 44px buttons overflowing it, and a tap at their own
   centre landed on the hairline instead. An explicit min-height is not an intrinsic contribution, so the row
   has a size again. Caught by a headless probe reading the grid's own track list, never by reading the CSS. */
.cx-sw{min-height:44px}   /* b569: the keys stand apart now (no overflow:hidden frame), 44 keeps the row its size */
/* REAL BUTTONS, not spans. A control he taps with a thumb in a parked car is a button: it takes the tap, it
   takes the keyboard, and it cannot be missed by a hit test the way a bare flex-item span can. The three
   share .jr-seg's frame, so the switch looks like every other segmented choice in the Journal. */
.cx-sw button{flex:1;min-width:0;padding:var(--sp-3) 0;cursor:pointer;text-align:center}
/* b569: picked is the one selected look of the button system (ink, white text), the same as .jr-seg span.on */

.cx-when{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:.04em;color:var(--muted);text-align:center;margin-top:-4px}
.cx-body{display:flex;flex-direction:column;gap:10px;min-width:0}
.cx-body[hidden]{display:none}
.cx-tiles{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.cx-t{background:var(--paper);border-radius:10px;padding:7px 10px;min-width:0}
.cx-t small{display:flex;align-items:center;gap:5px;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);white-space:nowrap;overflow:hidden}
.cx-t b{display:block;font-family:var(--body);font-weight:600;font-size:var(--t-card);font-variant-numeric:tabular-nums;white-space:nowrap;line-height:var(--lh-card)}
.cx-t b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-weight:400;font-size:1.18rem;line-height:1.25}
.cx-t .s{display:block;font-size:var(--fs-label);color:#4A4A47;line-height:1.25;font-variant-numeric:tabular-nums}
.cx-t .s em{font-style:normal;color:var(--red-ink);font-weight:700}
.cx-tag{display:inline-block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:800;letter-spacing:.06em;border-radius:5px;padding:2px 5px;background:#E8F5EC;color:var(--good-deep);flex:0 0 auto}
.cx-tag.est{background:#FFF4D6;color:#8A5A00}
.cx-t.cx-wide{grid-column:1 / -1}
.cx-kinds{display:flex;gap:6px;flex-wrap:wrap;margin-top:3px}
.cx-kinds span{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;background:var(--card);border:1px solid var(--line);border-radius:var(--r-pill);padding:3px var(--sp-2);font-variant-numeric:tabular-nums;white-space:nowrap}
.cx-net{border:2px solid var(--good);border-radius:var(--r-ctl);padding:9px var(--sp-3);background:var(--card)}
.cx-net .top{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-2)}
.cx-net small{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:800;letter-spacing:.12em;color:var(--good)}
.cx-net b{font-family:var(--display);font-weight:400;font-size:var(--t-big);color:var(--good);font-variant-numeric:tabular-nums;white-space:nowrap}
.cx-net b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-weight:400;font-size:1.7rem}
.cx-net .s{display:block;font-size:var(--fs-label);color:#4A4A47;line-height:1.3;font-variant-numeric:tabular-nums}
.cx-gas{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--paper);border-radius:var(--r-input);padding:6px 6px 6px var(--sp-3);min-height:44px}
.cx-gas[hidden]{display:none}
.cx-gas .tx{min-width:0;line-height:1.25}
.cx-gas .tx b{display:block;font-size:var(--t-small);font-variant-numeric:tabular-nums}
.cx-gas .tx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}
.cx-gas .tx span{display:block;font-size:var(--fs-label);color:var(--muted);font-variant-numeric:tabular-nums}
.cx-gas .tx span i{font-style:normal;color:var(--good);font-weight:800}
/* an edit affordance is a real button with a visible label, sized in pixels, not in --rfs */
.cx-edit{flex:0 0 auto;min-height:52px;min-width:72px;padding:0 14px;border:1.5px solid var(--ink);border-radius:var(--r-input);background:var(--card);display:flex;align-items:center;justify-content:center;font-family:'Space Grotesk',sans-serif;font-size:var(--t-small);font-weight:700;color:var(--ink);cursor:pointer}
.cx-edit:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-size:.82rem;font-weight:800}
.cx-gasbox[hidden]{display:none}
.cx-fields{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.cx-btns{display:flex;gap:var(--sp-2)}
.cx-btns .cta{margin:0;flex:1 1 0;min-width:0;min-height:52px;font-size:var(--t-body)}
.cx-btns .cta:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem}
.cx-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-ctl);padding:var(--sp-2) var(--sp-3)}
.cx-card[hidden]{display:none}
.cx-lbl{display:flex;justify-content:space-between;gap:var(--sp-2);font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:2px}
.cx-lbl span + span{letter-spacing:.04em;color:var(--ink)}
.cx-r{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:48px;border-top:1px solid var(--line);padding:var(--sp-1) 0}
.cx-r:first-child{border-top:0}
.cx-r .l{min-width:0;line-height:1.25}
.cx-r .l b{display:block;font-size:var(--t-small);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cx-r .l b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem}
.cx-r .l span{display:block;font-size:var(--fs-label);color:#4A4A47;font-variant-numeric:tabular-nums}
.cx-r .r{flex:0 0 auto;text-align:right;line-height:1.15}
.cx-r .r b{display:block;font-family:var(--mono);font-weight:700;font-size:var(--t-data);font-variant-numeric:tabular-nums;color:var(--good)}
.cx-r .r b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Archivo Black',sans-serif;font-weight:400;font-size:1rem}
.cx-r .r small{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.1em;color:var(--muted)}
.cx-r.empty .r b{color:#4A4A47}
.cx-foot{font-size:var(--fs-label);color:var(--muted);line-height:1.35}
.cx-foot:empty{display:none}
.cx-days{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:var(--sp-1);align-items:end}
.cx-d{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:3px;min-height:44px;min-width:0;cursor:pointer;background:none;border:0;padding:2px 0}
.cx-d .bar{width:70%;max-width:26px;background:var(--good);border-radius:4px 4px 0 0}
.cx-d.off .bar{background:#E4E1DA}
.cx-d.on .bar{background:var(--ink)}
.cx-d.soon .bar{background:repeating-linear-gradient(45deg,#E4E1DA 0 4px,#fff 4px 8px);border:1px dashed var(--placeholder)}
.cx-d small{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.06em;color:var(--muted)}
.cx-d span{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
/* WEEK and MONTH are the costs alone: the four moments, the charging stops, the rides and the editor belong to
   ONE day, so the same panel simply stops showing them. This is the switch NAVIGATING, not a second screen. */
.fx-journal .sheet.cx-period .jr-moments,
.fx-journal .sheet.cx-period .jr-nag,
.fx-journal .sheet.cx-period .jr-edit,
.fx-journal .sheet.cx-period .jr-dayonly{display:none}
.mc-meter{margin-top:12px}
.mc-mrow{display:flex;justify-content:space-between;gap:var(--sp-2);flex-wrap:wrap}
.mc-mrow span{font-family:'JetBrains Mono',monospace;font-size:var(--t-label);color:var(--muted);font-variant-numeric:tabular-nums}
.mc-mrow span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:.78rem}
.mc-bar{position:relative;height:12px;background:var(--paper);border:1px solid var(--line);border-radius:6px;margin-top:6px}
.mc-bar i{position:absolute;left:0;top:0;bottom:0;border-radius:6px;display:block;background:var(--good)}
.mc-bar i.warn{background:#E0A400} .mc-bar i.bad{background:var(--red)}
.mc-bar em{position:absolute;top:-4px;bottom:-4px;width:2px;background:var(--ink)}
.mc-drow{display:grid;grid-template-columns:1fr auto 7em;gap:10px;padding:7px 0;border-top:1px solid var(--line);font-size:var(--t-body);align-items:center}
.mc-drow:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
.mc-drow span:nth-child(2),.mc-drow span:nth-child(3){text-align:right;font-family:'JetBrains Mono',monospace;font-variant-numeric:tabular-nums}
.mc-dhead{border-top:0;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:700}
.mc-dtot{font-weight:700}
.mc-spark{display:flex;align-items:flex-end;gap:6px;height:70px;margin-top:var(--sp-2)}
.mc-spark div{flex:1;background:var(--orange);border-radius:3px 3px 0 0}
.mc-spark div.zero{background:var(--line)}
.mc-days{display:flex;gap:6px;margin-top:var(--sp-1)}
.mc-days span{flex:1;text-align:center;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);color:var(--muted)}
.mc-updbar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.mc-updbar .mc-sub{margin-top:0}
.mc-updbar .cta{width:auto;margin:0;padding-inline:var(--sp-5)}
/* b650: THE GOOGLE BILL on the same screen (bug-mvsover3-4psuu). The split bar and keys, the month list that opens in
   place (52px rows, a real button each), the note box, the biggest days, the budget alert, the enter-a-month form. */
.gb-split{display:flex;height:12px;border-radius:6px;overflow:hidden;border:1px solid var(--line);margin-top:12px;background:var(--paper)}
.gb-split[hidden]{display:none}
.gb-split i{display:block;height:100%}
.gb-k{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:8px;vertical-align:-1px}
.gb-maps{background:var(--good)} .gb-fb{background:var(--orange)} .gb-oth{background:#8A8A8A}
.gb-rows{margin-top:8px}
.gb-rows .mc-drow,.gb-days .mc-drow{grid-template-columns:1fr auto}
.gb-mo{border-top:1px solid var(--line)}
.gb-mo:first-child{border-top:0}
.gb-mh{display:grid;grid-template-columns:1fr auto 18px;gap:10px;align-items:center;width:100%;min-height:52px;padding:6px 0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}
.gb-mh b{font-size:var(--t-body)}
.gb-amt{text-align:right;font-family:'JetBrains Mono',monospace;font-variant-numeric:tabular-nums;font-weight:700}
.gb-amt small{display:block;font-weight:400;color:var(--muted);font-size:var(--fs-label);letter-spacing:.04em}
.gb-mh svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2.2;transition:transform .15s}
.gb-mo.open .gb-mh svg{transform:rotate(90deg)}
.gb-mb{display:none;padding:0 0 12px}
.gb-mo.open .gb-mb{display:block}
.gb-note{margin-top:10px;padding:10px 12px;border-radius:12px;background:var(--paper);border:1px solid var(--line);font-size:var(--t-small);line-height:1.4}
.gb-note .mc-lbl{margin-bottom:4px}
.gb-days{margin-top:10px}
.gb-days .mc-drow{padding:5px 0}
.gb-days .mc-drow span:nth-child(2){font-family:'JetBrains Mono',monospace}
.gb-alert{display:flex;gap:10px;align-items:flex-start}
.gb-alert .mc-sub{margin-top:2px}
.gb-alert svg{flex:0 0 22px;width:22px;height:22px;fill:none;stroke:var(--orange);stroke-width:2}
.gb-enter{margin-top:10px;border-top:1px solid var(--line);padding-top:6px}
.gb-enter summary{min-height:44px;display:flex;align-items:center;cursor:pointer;font-weight:700}
.gb-in{display:block;width:100%;box-sizing:border-box;height:44px;margin:0 0 8px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r-input);background:var(--card);color:var(--ink);font:inherit}
.gb-enter .cta{width:auto;margin:0}
/* b315: stamp, owner-only Maps Cost tile and screen */
/* b316: stamp only, arrival keeps the card and rail, pill clearance, parked heading */

/* b322: A SHORT SCREEN CANNOT AFFORD A PERCENTAGE GAP. Ahmed prices on a fold held wide, 921 by
   573, where the 5% gap plus the header and the footer leave the pricing sheet about 400px for a
   sheet whose content is 580, so it scrolls from the first paint and he reads it as wasted room
   ("it looks like the menu can open up more because there is room on top"). Under 700px tall the
   gap becomes a fixed 16px: the sheet still never reaches the header (the law), and it gains the
   difference. Measured on his own viewport, 29px of gap to 16px, 13px back to the content.
   TALL PHONES ARE UNTOUCHED, 5% of 812 is 41px and the content already fits. */
@media (max-height: 700px){ :root{ --sheet-top:16px } }

/* ================================================================================================
   b323 . SHARE A RIDE WITH A BACKUP DRIVER. The panel takes the row's place, like the decline
   confirm beside it, because rule zero says never a popup. Every control clears the tap floor.
   ================================================================================================ */
.shrow .shwhos{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin:10px 0 0}
.crow.shrow .tx .shwhos .shwho{display:inline-flex;flex-direction:column;justify-content:center;min-height:var(--tap-min);
  padding:6px var(--sp-3);border:1px solid var(--line);border-radius:10px;background:var(--card);cursor:pointer;
  font-weight:700;font-size:var(--t-body);line-height:var(--lh-body)}
.crow.shrow .tx .shwhos .shwho:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.95rem;line-height:1.15}
.shrow .shwho i{font-style:normal;font-weight:500;font-size:var(--t-small);color:var(--muted)}
.shrow .shwho i:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:500;font-size:.78rem}
.shrow .shwho em{font-style:normal;font-size:var(--fs-label);letter-spacing:.06em;text-transform:uppercase}
.shrow .shwho em.yes{color:#147135}
.shrow .shwho em.no{color:#C0392B}
.shrow .shwho.on{border-color:var(--orange,#FF3B00);box-shadow:inset 0 0 0 1px var(--orange,#FF3B00)}
.shrow .shpay{display:flex;align-items:center;gap:var(--sp-2);margin:10px 0 0}
.shrow .shpay .k{font-size:var(--t-label);letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.shrow .shpay .k:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.shrow .shpay .cur{font-weight:800}
.shrow .shcopytop{display:flex;justify-content:flex-end;margin:var(--sp-3) 0 0}
/* b328: the amount is read at arm's length, so it is not a 5ch box. He could not read $120. */
.shrow .shamt{width:7ch;min-height:56px;font-size:var(--t-card);border:1px solid var(--line);border-radius:10px;
  padding:0 10px;font-weight:600;text-align:center}
.shrow .shamt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.35rem;font-weight:800}
.shrow .shmsg{white-space:pre-wrap;background:#F7F7F5;border:1px solid var(--line);border-radius:10px;
  padding:10px var(--sp-3);margin:10px 0 0;font-size:var(--t-body);line-height:var(--lh-body);max-height:220px;overflow:auto}
.shrow .shmsg:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem;line-height:1.45}
.shrow .shsaid{display:block;margin-top:var(--sp-2);font-size:var(--t-small);font-weight:700;color:#147135}
.shrow .shsaid:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;font-weight:700}
.rrow .rshared{color:#8A5C00;font-weight:600}

/* b324: adding a backup driver from the share panel */
.crow.shrow .tx .shwhos .shwho.add{border-style:dashed;color:var(--muted)}
.crow.shrow .tx .shwhos .shwho.off{opacity:.55}
/* b589: the team seat on a roster chip. IN THE APP is the orange label chip (the b576 .badge.retleg type); INVITE is the
   white secondary of the b569 button system, small, inside the chip under the car; the link box sits under the chips. */
.shrow .shwho .shinapp,.frame[data-role] .shrow .shwho .badge.retleg{margin:6px 0 0;align-self:flex-start}
.shrow .shwho .shinv{display:inline-flex;align-items:center;justify-content:center;min-height:var(--btn-h-sm,44px);margin:6px 0 0;padding:0 12px;
  border:1px solid var(--btn-edge,var(--ink));border-radius:var(--btn-r,12px);background:var(--paper);color:var(--ink);
  font:var(--btn-fw,700) var(--btn-fs-sm,var(--t-label)) var(--body);letter-spacing:var(--btn-ls,.08em);text-transform:var(--btn-case,uppercase);align-self:flex-start}
.shrow .shinvbox{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:center;margin:10px 0 0}
.shrow .shinvbox .k{flex:1 1 100%;font:700 var(--t-label) var(--body);letter-spacing:.08em;text-transform:uppercase;color:var(--label-bg)}
.shrow .shinvbox .shin{flex:1 1 200px;font:500 var(--t-small) var(--mono);color:var(--ink)}
.ypd-teamnote{display:block;margin:6px auto 0;text-align:center;font-weight:700;font-size:var(--t-small);letter-spacing:.02em;color:var(--muted);line-height:var(--lh-small)}
.ypd-teamnote[hidden]{display:none}
.shrow .shadd{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:center;margin:10px 0 0}
.shrow .shin{flex:1 1 140px;min-height:var(--tap-min);border:1px solid var(--line);border-radius:10px;padding:0 10px;font:inherit}
.shrow .shbig{display:inline-flex;align-items:center;min-height:var(--tap-min);padding:0 var(--sp-3);border:1px solid var(--line);
  border-radius:10px;font-size:var(--t-small);font-weight:700;cursor:pointer}
.shrow .shbig:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;font-weight:700}
.shrow .shbig.on{border-color:var(--orange,#FF3B00);color:var(--orange,#FF3B00)}

/* b325: a field the client left blank is shown, not hidden, because a missing return flight is
   exactly what stops him pricing. It reads as missing and carries its own ADD door. */
.fx-off-grid > div.blank b{color:#8A5C00;font-style:italic}
.fx-off-grid > div{position:relative}
.fx-off-grid > div .fx-leadedit{margin-left:var(--sp-2)}

/* b332: an address the client left half finished, said before the message is sent */
.shrow .shwarn{border-left:4px solid var(--red);background:#FFF4F2;border-radius:0 8px 8px 0;
  padding:10px var(--sp-3);margin:var(--sp-3) 0 0;font-size:var(--t-small);font-weight:700;color:#8A2010}
.shrow .shwarn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem;font-weight:600}

/* b367: THE PASSENGER SIDE IS BLUE (Ahmed 2026-09-18, bug-mu7qrvz7, picked option 1 of #f-paxside in the
   shell mockup): he opened the passenger side by mistake, it showed a TEST ride with Darlene driving, and he
   nearly drove to the wrong address. "The driver's side is my branding colors like white and orange... just
   make it like a blue color for both male or female on the passenger side, and the driver's side is going to
   stay the way it is." One token does it: every accent on her side reads --orange, so her body redefines it.
   Green (selected, Online), red (warnings) and the black fare pill stay as they are. Deep blue var(--pax), white
   on it reads 7.0:1. The band names the side in words, under the header of every passenger screen. */
body[data-role="passenger"]{--orange:var(--pax);--pb:var(--pax)}
.frame[data-role="passenger"] > .hd{margin-bottom:28px}
.frame[data-role="passenger"] > .hd > .pb-band{position:absolute;top:calc(100% + 1px);left:0;right:0;height:28px;background:var(--pb,var(--pax));
  color:#fff;display:flex;align-items:center;justify-content:center;gap:10px;pointer-events:none;
  font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.14em;white-space:nowrap;overflow:hidden}
.frame[data-role="passenger"] > .hd > .pb-band em{font:700 var(--fs-label) 'Space Grotesk',sans-serif;letter-spacing:.02em;font-style:normal;
  overflow:hidden;text-overflow:ellipsis}
.frame[data-role="passenger"] > .hd > .chip:first-child{border:2px solid var(--pb,var(--pax));box-shadow:0 0 0 2px rgba(22,80,199,.14)}

/* b368: TRIP INFO, WHAT HE NEEDS TO KNOW IN ONE TAP (Ahmed 2026-09-18, bug-mu7r3v7q, driving to LAX: "I need
   to be able to click and see that information... on the right right here, or in the home... when I come
   back here I always have to hit X and I don't mind that"). Option 1 of #f-ridebrief: two doors, one WHITE
   sheet. Door 1 is a map control top right on Ride (a control like recenter, never a card on the map), door
   2 is a button on Home's YOUR PASSENGER card. The orange number on both counts her lines he has not seen.
   The sheet rises from the footer over the screen he is on (rule zero, it opens in place) and the X puts
   him back. Passengers and the gate code are the biggest type on it, because he reads it at speed.
   --ti-top is MEASURED at runtime (tiPlace), under the navigation row whenever that row is up. */
/* b384: DOOR 1 IS A RAIL BUTTON (Ahmed 2026-09-25 22:46, bug-muhyvyb4: "the icon needs to look like the other four
   icons that are on the right-hand side"). While he navigates it is the first child of .navctl and every .navctl .mbtn
   rule dresses it, so it cannot drift from its neighbours. With no drive it stands alone in the rail's bottom slot, and
   this rule is the SAME disc written for a button outside the rail: 52px, white, the rail's shadow, the ink stroke. */
.frame > .ti-pill{position:absolute;right:var(--nav-inset);bottom:calc(var(--foot-h) + var(--nav-inset));top:auto;z-index:4;
  width:52px;height:52px;min-width:48px;min-height:48px;margin:0;padding:0;border:none;border-radius:50%;
  background:var(--card);color:var(--ink);box-shadow:0 3px 10px rgba(10,10,10,.28);-webkit-appearance:none;appearance:none;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;cursor:pointer}
.frame > .ti-pill svg{width:21px;height:21px;fill:none;stroke:var(--ink);stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
/* b392: the big i, a filled dot and a thick stem, no circle, in the rail and alone */
.ti-pill svg.ti-i{stroke-width:3.6}
.ti-pill svg.ti-i circle{fill:var(--ink);stroke:none}
.frame > .ti-pill .tag{font-style:normal;font-family:'JetBrains Mono',Consolas,monospace;
  font-size:var(--fs-label);letter-spacing:.06em;font-weight:800;color:var(--muted)}
/* the unseen count sits on the disc's corner, where recenter wears its stage number */
.ti-pill .ti-new{position:absolute;top:-4px;right:-4px;min-width:20px;height:20px;padding:0 5px;border-radius:10px;
  border:2px solid #fff;font-size:var(--fs-label);box-shadow:0 1px 3px rgba(10,10,10,.3)}
.navctl > .ti-pill[hidden]{display:none!important}
/* WHERE IN THE RAIL. His four keep the exact slots he set (b75: recenter, search, sound, SAFE), and INFO has ONE slot
   whether a drive is on or not, so it never jumps when navigation starts or ends (bug-muhzirmc, "this jump thing").
     long format (his phone, 921 x 573): the rail stands on the footer and five discs do not fit under the arrival card
       (measured in t220: card bottom 208, a fifth disc on top at 195), so INFO sits BESIDE SAFE, the rail's gap to its
       left, bottom edges level. The rail itself stays four tall.
     tall format (b186): the rail hangs from the nav band, and INFO is the fifth disc under SAFE (order 99).
   248px is four discs and four gaps (4 x 52 + 4 x 10), the rail's own numbers; the fold's frame scale applies to it too. */
/* b392 (Ahmed 2026-09-26: "underneath it is the info button... right now it's to the left of the safe off button and that's
   incorrect"): INFO is the fifth disc UNDER SAFE in both formats. In the long format the rail stands on the footer, so the
   five discs close the rail's gap from 10px to 6px while INFO is in it (5 x 52 + 4 x 6 = 284, the four were 238), which
   keeps the top disc clear of the arrival card; alone, INFO keeps the rail's bottom slot, the same place, no jump. */
.navctl > .mbtn.ti-pill{position:relative;right:auto;bottom:auto;order:99}
/* b452 (bug-mur6fxj9): THE COMPASS IS THE DISC UNDER INFO, the same disc, a big glyph like INFO's big i: the arrow for UP, the
   letter for NORTH (N) and ALL (A). It is the last child of the rail by order, so his four and INFO keep their slots. */
.navctl > .mbtn.cmpbtn{order:100}
/* b452: SIX DISCS IN THE LONG FORMATS (his four, INFO, the compass). Measured, t264 and t220: at 52px and a 6px gap (342px) the
   rail's top rode into the arrival card on his long phone (921x573, the fullest card ends at 208) and its foot sat 53px into
   the footer at 767x430. So a long window shrinks every disc alike, the order never changes:
     628 tall and up       52px, 6px gap (342), as before
     573 to 627            44px, 4px gap (284, the 44px tap floor), the rail stands on the footer under the card
     460 to 572            48px, 6px gap (318), the rail hangs from the header and the card steps left of it (b435)
     under 460             44px, 4px gap (284)
   INFO alone is the same disc in the same slot in each tier, so it never jumps when a drive starts. His rail only; hers
   keeps the b158 slots. */
@media (min-aspect-ratio: 6/5){
  .frame > .ti-pill.ti-pill{bottom:calc(var(--foot-h) + var(--nav-inset) + 58px)}   /* 52 + 6 */
}
@media (min-aspect-ratio: 6/5) and (max-height: 627px){
  .frame:not([data-role="passenger"]) > .navctl > .mbtn{width:44px;height:44px;min-width:44px;min-height:44px}
  .frame:not([data-role="passenger"]) > .navctl.navctl{gap:var(--sp-1)}   /* over the INFO gap rule further down */
  .frame > .ti-pill.ti-pill{width:44px;height:44px;min-width:44px;min-height:44px;bottom:calc(var(--foot-h) + var(--nav-inset) + 48px)}   /* 44 + 4 */
}
@media (min-aspect-ratio: 6/5) and (min-height: 460px) and (max-height: 572px){
  .frame:not([data-role="passenger"]) > .navctl > .mbtn{width:48px;height:48px}
  .frame:not([data-role="passenger"]) > .navctl.navctl{gap:6px}
  .frame > .ti-pill.ti-pill{width:48px;height:48px;bottom:auto;top:calc(var(--hd-h) + var(--band-gap) + 216px)}   /* 4 x 48 + 4 x 6 */
}
@media (min-aspect-ratio: 6/5) and (max-height: 459px){
  .frame > .ti-pill.ti-pill{bottom:auto;top:calc(var(--hd-h) + var(--band-gap) + 192px)}   /* 4 x 44 + 4 x 4 */
}
.navctl .mbtn.cmpbtn svg.cmp-up{stroke-width:3.2}
.navctl .mbtn .cmp-l{font:400 21px/21px 'Archivo Black',sans-serif;color:var(--ink);height:21px;display:block}
.navctl .mbtn .cmp-l[hidden]{display:none!important}
@media (min-aspect-ratio: 6/5){
  .navctl:has(> .ti-pill:not([hidden])){gap:6px}
}
@media not all and (min-aspect-ratio: 6/5){
  .frame > .ti-pill{right:var(--band-gap);bottom:auto;top:calc(var(--hd-h) + var(--band-gap) + 248px)}   /* b435: the rail's own gap */
}
/* b435 (bug-mum4yh55): A SHORT LONG SCREEN, the fold split top and bottom, or any long window under 573 tall. The rail
   stands on the footer in long, and five discs (284px) under the fullest arrival card (138px, t220) only fit from his
   own phone's 573 up; below that the rail rode up the screen into the card and toward the header (767x430: the
   OVERVIEW label on top of the address). Here the card steps left of the rail column, as the tall band does, and the
   rail hangs from the header by the phone's band gap (room for the OVERVIEW label over the top disc), so the two can
   never meet whatever the card holds. INFO alone keeps its fifth slot (4 x 52 + 4 x 6 = 232), the same place as in
   the rail, no jump. Her rail is restated at the b158 strength, otherwise its footer anchor plus this top would
   stretch it (the b190 lesson). */
@media (min-aspect-ratio: 6/5) and (max-height: 572px){
  .frame > .navrow{right:calc(var(--nav-inset) + 52px + 10px)}
  .frame > .navctl{bottom:auto;top:calc(var(--hd-h) + var(--band-gap))}
  .frame[data-role="passenger"] > .navctl{bottom:auto}
  .frame > .ti-pill{bottom:auto;top:calc(var(--hd-h) + var(--band-gap) + 216px)}   /* b452: 4 x 48 + 4 x 6 */
}
/* THE GATE BAND (bug-muhxr5uu: "colored nice and bold and stand out, maybe the background is orange and the text is
   white"). Forge Orange, white type, the code in the biggest type on the sheet, full width over the facts. */
.fx-ti .ti-gate{display:flex;align-items:center;gap:var(--sp-3);min-height:56px;padding:var(--sp-2) 14px;border-radius:var(--r-input);
  background:#FF3B00;color:#fff;flex-wrap:wrap}
.fx-ti .ti-gate i{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.12em;font-style:normal;color:#fff}
.fx-ti .ti-gate b{font:900 var(--t-big) var(--display);letter-spacing:.06em;line-height:1.1;color:#fff;overflow-wrap:anywhere}
.fx-ti .ti-gate b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.9rem 'Archivo Black',sans-serif;line-height:1.1}
.fx-ti .ti-gate s{text-decoration:none;font:700 var(--fs-label) 'Space Grotesk',sans-serif;color:#fff;opacity:.9;margin-left:auto}
.fx-ti .ti-gate.ti-ask{background:var(--card);border:2px solid #FF3B00}
.fx-ti .ti-gate.ti-ask i,.fx-ti .ti-gate.ti-ask s{color:#FF3B00}
.fx-ti .ti-gate.ti-ask b{color:#FF3B00;font:600 var(--t-card) 'Space Grotesk',sans-serif}
.fx-ti .ti-gate.ti-ask b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.2rem 'Space Grotesk',sans-serif}
.fx-ti .ti-gate[hidden],.fx-ti .ti-chips button[hidden]{display:none!important}
.fx-ti .ti-f.ti-wide{grid-column:1 / -1}
.fx-ti .ti-f.ti-wide b{font-size:var(--t-body)}
.fx-ti .ti-f.ti-wide b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.98rem}
.ti-new{min-width:24px;height:24px;border-radius:var(--r-input);background:var(--orange);color:#fff;
  font:800 var(--fs-label) 'JetBrains Mono',monospace;font-style:normal;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;flex:0 0 auto}
/* door 2, on the passenger card. It sits INSIDE the card's own door (open-nextride); the delegated
   listener takes the nearest data-act, so this button answers for itself. */
.card .ti-cardbtn{display:flex;align-items:center;justify-content:center;gap:var(--sp-2);width:100%;margin-top:var(--sp-2);cursor:pointer;padding:0 10px}
/* the sheet */
.sheet.fx-ti{padding:var(--sp-2) var(--sp-4) 14px;gap:var(--sp-2)}
.fx-ti .ti-head{display:flex;flex-direction:column;gap:2px;margin-top:2px}
.fx-ti .ti-k{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted);text-transform:uppercase}
.fx-ti .ti-head b{font:600 var(--t-card) 'Space Grotesk',sans-serif;line-height:1.2;color:var(--ink)}
.fx-ti .ti-head b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.25rem 'Space Grotesk',sans-serif;line-height:1.2}
/* b452: the name and the passenger pill share one line */
.fx-ti .ti-name{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.fx-ti .ti-name b{font-size:var(--t-page);overflow-wrap:anywhere;font-weight:600}
.fx-ti .ti-name b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.5rem}
.fx-ti .ti-paxpill{display:inline-flex;align-items:center;min-height:28px;padding:0 var(--sp-3);border-radius:var(--r-pill);background:var(--ink);color:#fff;
  font:700 var(--t-small) 'Space Grotesk',sans-serif;letter-spacing:.02em;white-space:nowrap}
.fx-ti .ti-paxpill:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .8rem 'Space Grotesk',sans-serif}
/* b452: TEXT <NAME>, the message box and its three buttons, 48px each */
.fx-ti .ti-text{display:flex;flex-direction:column;gap:6px;border:1px solid var(--line);border-radius:var(--r-input);padding:var(--sp-2) 10px 10px}
.fx-ti .ti-text textarea{width:100%;box-sizing:border-box;min-height:118px;resize:vertical;border:1.5px solid var(--line);border-radius:10px;
  padding:var(--sp-2) 10px;font:400 var(--t-body)/var(--lh-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card);field-sizing:content;max-height:300px}
.fx-ti .ti-text textarea:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 .95rem/1.35 'Space Grotesk',sans-serif}
.fx-ti .ti-text textarea:focus{border-color:var(--ink);outline:none}
.fx-ti .ti-trow{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.fx-ti .ti-trow button{padding:0 14px;cursor:pointer}
.fx-ti .ti-tcopy{flex:1 1 140px}
.fx-ti .ti-tsms{flex:1 1 120px}
.fx-ti .ti-talt{flex:0 1 auto}
.fx-ti .ti-trow button[hidden]{display:none!important}
/* b468: THE ARRIVAL CARD UNDER THE TURN PANEL, ON THE LEFT (bug-murfh86w, Ahmed 2026-10-02 13:41 by LAX, heading up:
   the "LAX" card at the top right "is fighting with where my pencil is... I want the LAX to be underneath where it says
   Google navigation... it can now easily come on the left hand side, it doesn't need to be on the top right"). The
   driver's row is a column: the panel, then the card at the panel's width under it, so the rail's column on the right
   has nothing beside it. Docked, either one is its 52px arrow. Her screen keeps its row. Measured by t264 and t285. */
.frame[data-role="driver"] > .navrow{flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:var(--sp-2)}
.frame[data-role="driver"] > .navrow > .nvpanel,
.frame[data-role="driver"] > .navrow > .msgpanel{flex:0 0 auto;width:var(--nav-w);max-width:100%}
@media not all and (min-aspect-ratio: 6/5){
  /* tall: the panel keeps the width it had beside the card (the band less the card's 44% and the gap) */
  /* b530 (bug-mv87t9me-vcj5l, Ahmed 2026-10-14 on b513: "7.1 and then the miles goes underneath... route 210 east the
     east is coming in another line... the panel is going to get a little bit bigger"). Since b468 the card sits UNDER
     the panel, so the old 56% (the width it had beside the card) left the band's right third empty map. 72% of the band,
     both panels, still clear of the rail: 222px at 412 and 208px at 390 (was 163 and 152). Measured by t333. */
  .frame[data-role="driver"] > .navrow > .nvpanel,
  .frame[data-role="driver"] > .navrow > .msgpanel{width:72%}
  /* b554 (bug-mvgxt0nw-jw7ms): out to the icons, the same gap on both sides. navWideFit in app.html measures the icon
     column as drawn and writes --nvp-w; with no measurement the 72% above stands. */
  .frame[data-role="driver"] > .navrow[data-wide] > .nvpanel:not(.dock),
  .frame[data-role="driver"] > .navrow[data-wide] > .msgpanel:not(.dock){width:var(--nvp-w,72%)}
}
.frame[data-role="driver"] > .navrow > :is(.nvpanel,.msgpanel).dock{width:52px}
/* b468: ON THE WAY, LANDED, CURB, the text that is due lit in ink */
.fx-ti .ti-stg{display:flex;gap:6px;flex-wrap:wrap}
.fx-ti .ti-stg[hidden]{display:none!important}
.fx-ti .ti-stg button{flex:1 1 0;min-width:0;padding:0 var(--sp-2);cursor:pointer;white-space:nowrap}
/* b580: STAGE and the orange chip above the text, Confirmation, On my way or Arrived */
.fx-ti .ti-stline{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}

.fx-ti .ti-facts{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
@media (min-width:700px){ .fx-ti .ti-facts{grid-template-columns:repeat(3,1fr)} }
.fx-ti .ti-f{border:1px solid var(--line);border-radius:var(--r-input);padding:7px 10px;min-height:62px;display:flex;flex-direction:column;justify-content:center;min-width:0}
.fx-ti .ti-f i{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted);font-style:normal}
.fx-ti .ti-f b{font:600 var(--t-card) 'Space Grotesk',sans-serif;line-height:1.2;color:var(--ink);overflow-wrap:anywhere}
.fx-ti .ti-f b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.05rem 'Space Grotesk',sans-serif;line-height:1.2}
.fx-ti .ti-f.ti-big b{font:600 var(--t-page) var(--body);letter-spacing:.04em}
.fx-ti .ti-f.ti-big b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.6rem 'Archivo Black',sans-serif}
.fx-ti .ti-f s{text-decoration:none;font-size:var(--fs-label);color:var(--muted)}
.fx-ti .ti-f.ti-none b{color:var(--muted);font:700 var(--t-body) 'Space Grotesk',sans-serif;letter-spacing:0}
.fx-ti .ti-f.ti-none b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .95rem 'Space Grotesk',sans-serif}
.fx-ti .ti-notes{display:flex;flex-direction:column;gap:var(--sp-2)}
.fx-ti .ti-note{position:relative;border:1px solid var(--line);border-radius:var(--r-input);padding:var(--sp-2) var(--sp-3);min-height:52px}
.fx-ti .ti-note b{display:block;font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);padding-right:52px;overflow-wrap:anywhere}
.fx-ti .ti-note b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1rem 'Space Grotesk',sans-serif}
.fx-ti .ti-note span{display:block;font-size:var(--fs-label);color:var(--muted)}
.fx-ti .ti-note em{position:absolute;top:9px;right:10px;font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.08em;font-style:normal;
  background:var(--orange);color:#fff;border-radius:6px;padding:3px 7px}
.fx-ti .ti-note.new{border:2px solid var(--orange)}
.fx-ti .ti-note.bk{background:var(--paper)}
.fx-ti .ti-empty{font-size:var(--t-body);color:var(--muted);padding:var(--sp-1) 2px}
.fx-ti .ti-empty:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.fx-ti .ti-add{display:flex;gap:var(--sp-2)}
.fx-ti .ti-add input{flex:1 1 auto;min-width:0;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);font:400 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card)}
.fx-ti .ti-add input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 1rem 'Space Grotesk',sans-serif}
.fx-ti .ti-add input:focus{border-color:var(--ink);outline:none}
.fx-ti .ti-save{flex:0 0 96px;cursor:pointer}
.fx-ti .ti-chips{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.fx-ti .ti-chips button{display:flex;align-items:center;padding:0 14px;cursor:pointer}
/* it docks the way every risen sheet docks (b177's rule, same numbers): from the footer, the side inset,
   the gap under the header. While it is up the screen behind it steps back and the Ride sheet stands
   aside, so two sheets are never read as one. */
.frame > .sheet.fx-ti{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch}
.frame.fx-tiopen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-tiopen > .map{filter:brightness(.72) saturate(.8)}
.frame.fx-tiopen > .sheet:not(.fx-ti){visibility:hidden}
/* door 1 is a MAP control, so it follows the map controls' own law (the recenter rail, line ~872): while a
   sheet is up over the map it steps aside, and the sheet's X brings the map and the door back. Measured
   in t220: the Ride sheet rises to 45px under the header on a phone, and the door would sit on its X. */
.frame > .ti-pill{transition:opacity .2s ease}
.frame:has(> .sheet:not(.shmin):not([hidden])) > .ti-pill{opacity:0;pointer-events:none}
/* the X and the b380 JOURNAL shortcut (bug-muhjtqyq) ride in the one title bar (b568, .sttl), so they stay under his
   thumb after the sheet has scrolled to the note box */
/* b438: STOPS, IN ORDER, at the end of TRIP INFO. Every control 44px or more. */
.fx-ti .ti-stops{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-1)}
.fx-ti .ti-stoplist{display:flex;flex-direction:column;gap:var(--sp-2)}
.fx-ti .ti-stop{display:grid;grid-template-columns:32px 1fr;gap:6px 10px;border:1px solid var(--line);border-radius:var(--r-input);padding:var(--sp-2) 10px;align-items:center}
.fx-ti .ti-stop.done{background:var(--paper)}
.fx-ti .ti-stop.done .ti-stx b{color:var(--muted)}
.fx-ti .ti-sn{width:32px;height:32px;border-radius:16px;background:var(--ink);color:#fff;display:flex;align-items:center;justify-content:center;font:700 var(--t-small) 'Space Grotesk',sans-serif}
.fx-ti .ti-sn:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .9rem 'Space Grotesk',sans-serif}
.fx-ti .ti-stx{min-width:0}
.fx-ti .ti-stx b{display:block;font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);overflow-wrap:anywhere}
.fx-ti .ti-stx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1rem 'Space Grotesk',sans-serif}
.fx-ti .ti-stx span{display:block;font-size:var(--t-small);color:var(--muted);overflow-wrap:anywhere}
.fx-ti .ti-stx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.fx-ti .ti-sbtns{grid-column:1 / -1;display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.fx-ti .ti-sbtns button, .fx-ti .ti-skind button, .fx-ti .ti-srow button{cursor:pointer;padding:0 var(--sp-2)}
.fx-ti .ti-sbtns button:disabled, .fx-ti .ti-srow button:disabled{opacity:.4;cursor:default}
.fx-ti .ti-sform{display:flex;flex-direction:column;gap:var(--sp-2);border:2px solid var(--ink);border-radius:var(--r-input);padding:10px}
.fx-ti .ti-sform[hidden], .fx-ti .ti-best[hidden]{display:none!important}
.fx-ti .ti-sform input{min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);font:400 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card);min-width:0}
.fx-ti .ti-sform input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 1rem 'Space Grotesk',sans-serif}
.fx-ti .ti-sform input:focus{border-color:var(--ink);outline:none}
.fx-ti .ti-skind{display:grid;grid-template-columns:1fr 1fr;gap:6px}

.fx-ti .ti-srow{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
.fx-ti .ti-srow .ti-sgo{background:var(--good);color:#fff;border-color:var(--good)}
.fx-ti .ti-best{display:flex;flex-direction:column;gap:6px;border:2px solid var(--orange);border-radius:var(--r-input);padding:10px}
.fx-ti .ti-best b{font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink)}
.fx-ti .ti-best b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .95rem 'Space Grotesk',sans-serif}
.fx-ti .ti-best span{font-size:var(--t-small);color:var(--muted)}
.fx-ti .ti-best span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem}
/* b440: PRESS AND DRAG, the whole trip as one list (Ahmed 2026-10-01: "you know how in Google Maps you can hold it and
   edit and then move the positioning?"). START is fixed, every stop and END carry a 44px handle; a lifted row follows
   his finger and the others reflow. Rows are 44px or taller. */
.fx-ti .ti-stop, .fx-ti .ti-tend{grid-template-columns:44px 32px 1fr;min-height:44px;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.fx-ti .ti-tend{display:grid;gap:6px 10px;border:1.5px dashed var(--line);border-radius:var(--r-input);padding:var(--sp-2) 10px;align-items:center;background:var(--card)}
.fx-ti .ti-tend.ti-tstart{background:var(--paper)}
.fx-ti .ti-tend .ti-sn{background:var(--paper);color:var(--ink);border:1.5px solid var(--ink)}
.fx-ti .ti-drag, .fx-ti .ti-dragx{width:44px;min-height:44px;display:flex;align-items:center;justify-content:center}
.fx-ti .ti-drag{border-radius:10px;font:600 var(--t-page)/1 'Space Grotesk',sans-serif;color:var(--ink);cursor:grab;touch-action:none;background:var(--paper)}
.fx-ti .ti-drag:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.5rem/1 'Space Grotesk',sans-serif}
.fx-ti .ti-sorting .ti-drag{cursor:grabbing}
.fx-ti .ti-dragging{position:relative;z-index:5;box-shadow:0 10px 24px rgba(10,10,10,.22);border-color:var(--ink);background:var(--card);transition:none}
.fx-ti .ti-sorting .ti-stop:not(.ti-dragging), .fx-ti .ti-sorting .ti-tend:not(.ti-dragging){transition:transform .12s}
.fx-ti .ti-willend .ti-sn{background:var(--paper);color:var(--ink);border:1.5px solid var(--ink)}
.fx-ti .ti-sbtns.ti-sbtns2{grid-template-columns:repeat(2,1fr)}
/* LAST, so nothing above can beat it (the explicit-display law, 2026-07-31) */
.frame > .ti-pill[hidden], .card .ti-cardbtn[hidden], .ti-new[hidden], .frame > .sheet.fx-ti[hidden]{display:none!important}

/* ==== b369: MONEY OWED ON HOME (Ahmed 2026-09-18, option 1 of #f-moneyowed): "just another panel with money that's
   owed... when there's no money owed it just stays clear just the way it is right now". The panel is the approved
   mock's .mo-panel: a red edge because money owed is a warning, one whole-panel tap target, gone when nothing is
   owed. Her copy wears her accent, --orange is her blue under body[data-role=passenger] (b367). */
.mo-panel{display:flex;align-items:center;gap:var(--sp-3);width:100%;min-height:64px;margin:0;padding:var(--sp-2) 10px var(--sp-2) 14px;
  border:2px solid var(--red);border-radius:var(--r-ctl);background:#FFF5F3;color:var(--ink);text-align:left;cursor:pointer;font:inherit}
.mo-panel .mo-l{flex:0 0 auto;display:flex;flex-direction:column}
.mo-panel .mo-k{display:block;font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--red-ink)}
.mo-panel .mo-amt{display:block;font:600 var(--t-page) var(--body);line-height:1.1;color:var(--ink)}
.mo-panel .mo-amt:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.5rem 'Archivo Black',sans-serif;line-height:1.1}
.mo-panel .mo-who{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;font-size:var(--t-small);line-height:var(--lh-small);color:#3A3A37}
.mo-panel .mo-who:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.35}
.mo-panel .mo-who > span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mo-panel .mo-go{flex:0 0 auto;min-height:48px;min-width:72px;padding:0 var(--sp-3);border-radius:var(--r-input);background:var(--ink);color:#fff;
  display:flex;align-items:center;justify-content:center;font:800 var(--t-num) 'JetBrains Mono',monospace;letter-spacing:.08em}
.mo-panel .mo-go:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .76rem 'JetBrains Mono',monospace}
.mo-panel.pax{border-color:var(--orange);background:#F1F5FD}
.mo-panel.pax .mo-k{color:var(--orange)}
.mo-panel.pax .mo-go{background:var(--orange)}
/* the sheet: the TRIP INFO dock law, same tokens (from the footer, the side inset, the gap under the header) */
.sheet.fx-owed{padding:var(--sp-2) var(--sp-4) 14px;gap:var(--sp-2)}
.fx-owed .mo-head{display:flex;flex-direction:column;gap:2px;margin:2px 0 var(--sp-2)}
.fx-owed .mo-k{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted)}
.fx-owed .mo-head b{font:600 var(--t-card) var(--body);line-height:1.2;color:var(--ink)}
.fx-owed .mo-head b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.12rem 'Archivo Black',sans-serif;line-height:1.2}
.fx-owed .mo-list{display:flex;flex-direction:column;gap:var(--sp-2)}
.fx-owed .mo-row{border:1px solid var(--line);border-radius:var(--r-ctl);padding:10px var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-2);background:var(--card)}
.fx-owed .mo-row.done{border:2px solid var(--good);background:#EEF8F1}
.fx-owed .mo-top{display:flex;align-items:center;justify-content:space-between;gap:10px}
.fx-owed .mo-top > div{min-width:0}
.fx-owed .mo-top b{display:block;font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);overflow-wrap:anywhere}
.fx-owed .mo-top b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.02rem 'Space Grotesk',sans-serif}
.fx-owed .mo-top .s{display:block;font-size:var(--t-small);color:var(--muted)}
.fx-owed .mo-top .s:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem}
.fx-owed .mo-pill{flex:0 0 auto;font:800 var(--fs-label) ui-monospace,monospace;letter-spacing:1px;color:#fff;background:var(--red);border-radius:var(--r-pill);padding:var(--sp-1) 10px;white-space:nowrap}
.fx-owed .mo-row.done .mo-pill{background:var(--good)}
.fx-owed .mo-btns{display:flex;gap:var(--sp-2)}
.fx-owed .mo-btns button{flex:1 1 0;cursor:pointer}


.fx-owed .mo-paid[disabled]{opacity:.6;cursor:default}
.fx-owed .mo-done{font:700 var(--t-small) 'Space Grotesk',sans-serif;color:var(--good-deep)}
.fx-owed .mo-done:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .8rem 'Space Grotesk',sans-serif}
.fx-owed .mo-rule{font-size:var(--fs-label);color:var(--muted);line-height:1.4;margin-top:var(--sp-2)}
@media (min-aspect-ratio: 6/5){ .fx-owed .mo-list{display:grid;grid-template-columns:1fr 1fr} }
.frame > .sheet.fx-owed{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch}
.frame.fx-owedopen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-owedopen > .map{filter:brightness(.72) saturate(.8)}
/* LAST, so nothing above can beat it (the explicit-display law) */
.mo-panel[hidden], .frame > .sheet.fx-owed[hidden]{display:none!important}

/* ==== b611: THE ONE PAID SHEET (Ahmed 2026-10-26, bug-mvpwzivw-jsahh, option 1 of YPD-MARK-PAID-MOCKUP-V1A). The Money
   owed sheet's own look (fx-owed, data-kind="pay"), with: who and which ride on top, the lime PAID and HOW labels (lime on
   ink, the checklist row), the big amount box (orange edge while it is live), four 48px chips (selected is ink on white
   flipped, the b569 choice), the money lines in columns with the dollar signs stacked (Ahmed 10-23), one orange PAID
   at the --act-h size. Every tap target is 44 or more and the sheet fits 390 wide with no sideways scroll. ---- */
.sheet.fx-pay{gap:0}
.sttl .stchip.pay-chip.due{background:var(--red);color:#fff}
.sttl .stchip.pay-chip:not(.due){background:var(--good);color:#fff}
.fx-pay .pay-whom{display:flex;align-items:center;gap:12px;padding:4px 0 8px}
.fx-pay .pay-av{width:48px;height:48px;border-radius:50%;background:var(--ink);color:#fff;display:flex;align-items:center;justify-content:center;font:700 15px/1 'Space Grotesk',sans-serif;flex:0 0 auto}
.fx-pay .pay-whom .tx{min-width:0}
.fx-pay .pay-whom b{display:block;font:600 var(--t-card) var(--body);line-height:1.25;color:var(--ink)}
.fx-pay .pay-whom span{display:block;font:700 var(--t-small) 'JetBrains Mono',monospace;line-height:1.4;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fx-pay .pay-ml{display:inline-block;font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase;background:var(--ink);color:var(--lime);padding:4px 7px;border-radius:5px;margin:8px 0 6px}
.fx-pay .pay-amt{display:flex;align-items:center;gap:6px;border:2px solid var(--ink);border-radius:var(--r-ctl);background:var(--card);min-height:76px;padding:0 16px;font:400 var(--t-big) 'Archivo Black','Space Grotesk',sans-serif;line-height:1}
.fx-pay .pay-amt.live{border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,59,0,.18)}
.fx-pay .pay-cur{color:var(--muted);font:700 24px/1 'JetBrains Mono',monospace;flex:0 0 auto}
.fx-pay .pay-in{flex:1 1 auto;min-width:0;width:100%;border:0;outline:0;background:transparent;font:400 var(--t-big) 'Archivo Black','Space Grotesk',sans-serif;line-height:1;color:var(--ink);padding:0;height:60px;caret-color:var(--orange)}
.fx-pay .pay-hows{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
.fx-pay .pay-c{min-width:0;min-height:48px;display:flex;align-items:center;justify-content:center;border:1.5px solid #BDBAB2;border-radius:var(--r-input);background:var(--card);color:var(--ink);font:800 var(--t-small) 'Space Grotesk',sans-serif;letter-spacing:.08em;cursor:pointer;padding:0 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fx-pay .pay-c.on{background:var(--ink);color:#fff;border-color:var(--ink)}
.fx-pay .pay-money{display:grid;grid-template-columns:1fr 104px;margin-top:10px;border:1px solid var(--line);border-radius:var(--r-input);overflow:hidden}
.fx-pay .pay-money > *{padding:0 12px;min-height:44px;display:flex;align-items:center;border-top:1px solid var(--line);box-sizing:border-box}
.fx-pay .pay-money > :nth-child(-n+2){border-top:0}
.fx-pay .pay-money .w{font:600 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);flex-direction:column;align-items:flex-start;justify-content:center;gap:0;padding-top:6px;padding-bottom:6px}
.fx-pay .pay-money .w small{display:block;font:500 var(--t-small) 'Space Grotesk',sans-serif;color:var(--muted);line-height:1.3}
.fx-pay .pay-money .a{font:700 var(--t-data) 'JetBrains Mono',monospace;justify-content:flex-start;border-left:1px solid var(--line);background:var(--paper);color:var(--ink);width:100%;text-align:left;gap:4px}
.fx-pay .pay-money .a.pos{color:var(--good)}
.fx-pay .pay-money .a.short{color:var(--red)}
.fx-pay .pay-money button.a.edit{cursor:pointer;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:4px;color:var(--orange);font:700 var(--t-data) 'JetBrains Mono',monospace}
.fx-pay .pay-money .a.edit .pay-cur{font:700 var(--t-data) 'JetBrains Mono',monospace}
.fx-pay .pay-tipin{flex:1 1 auto;min-width:0;width:100%;border:0;outline:0;background:transparent;font:700 var(--t-data) 'JetBrains Mono',monospace;color:var(--ink);padding:0;height:40px}
.fx-pay .pay-btns{display:flex;gap:8px;margin-top:12px}
.fx-pay .pay-go{flex:1 1 0;min-width:0;min-height:var(--act-h);border:none;border-radius:var(--r-ctl);background:var(--orange);color:#fff;font:700 var(--t-body) 'Space Grotesk',sans-serif;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;padding:0 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fx-pay .pay-go[disabled]{opacity:.6;cursor:default}
.fx-pay .pay-stat{margin-top:8px;font-size:var(--t-small);line-height:1.4;color:var(--muted)}
.fx-pay .pay-stat.warn{color:var(--red-ink);font-weight:700}
.fx-pay .pay-stat[hidden]{display:none!important}
/* ==== b666: PAID AHEAD (Ahmed 2026-10-29, "paidahead: 1"). The PAID sheet's own look (fx-pay, data-kind="paidahead"), its
   children never shrink (the mock's note), three and two across rows, the payer's name box; the TRIP INFO PAYMENT row; the
   Rides list's green PAID badge and line. ---- */
.sheet.fx-pay[data-kind="paidahead"] > *{flex-shrink:0}
/* the round initials: the whom line's span rule (grey mono, block) was winning over .pay-av, so they read dark on ink */
.fx-pay .pay-whom .pay-av{display:flex;color:#fff;font:700 15px/1 'Space Grotesk',sans-serif;white-space:nowrap;overflow:visible}
.fx-pay .pay-hows[data-pa="cols3"]{grid-template-columns:repeat(3,minmax(0,1fr))}
.fx-pay .pay-hows[data-pa="cols2"]{grid-template-columns:repeat(2,minmax(0,1fr))}
.fx-pay input[data-pa="name"],.fx-pay input[data-pa="date"]{display:block;width:100%;box-sizing:border-box;margin-top:8px;min-height:48px;border:1.5px solid var(--ink);border-radius:var(--r-input);background:var(--card);padding:0 14px;font:600 var(--t-body) var(--body);color:var(--ink)}
.fx-pay input[data-pa="name"][hidden],.fx-pay input[data-pa="date"][hidden],.fx-pay [data-pa="clear"][hidden]{display:none!important}
/* ==== b718: THE CANCEL SHEET (Ahmed 2026-11-02, option B of YPD-CANCEL-FEE-MOCK-V1A). The PAID sheet's own look (fx-pay,
   data-kind="cancel"), no new class: the three steps are data-cxf blocks, the why chips (64px) and the move chips two
   across, the amount box carries its own 48px minus and plus, the new day and time side by side, BACK beside the one
   orange button. ---- */
.sheet.fx-pay[data-kind="cancel"] > *{flex-shrink:0}
.fx-pay [data-cxf][hidden]{display:none!important}
.fx-pay .pay-hows[data-cxf="cols2"]{grid-template-columns:repeat(2,minmax(0,1fr))}
.fx-pay [data-cxf="s1"] .pay-c{min-height:64px}
.fx-pay [data-cxf="amtbox"]{padding:0 8px}
.fx-pay [data-cxf="minus"],.fx-pay [data-cxf="plus"]{flex:0 0 auto;width:48px;height:48px;border:1.5px solid var(--ink);border-radius:var(--r-input);background:var(--card);color:var(--ink);font:700 26px/1 'Space Grotesk',sans-serif;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
.fx-pay [data-cxf="dt"]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:8px}
.fx-pay [data-cxf="dt"] input{display:block;width:100%;min-width:0;box-sizing:border-box;min-height:48px;border:1.5px solid var(--ink);border-radius:var(--r-input);background:var(--card);padding:0 12px;font:600 var(--t-body) var(--body);color:var(--ink)}
.fx-pay [data-cxf="back"]{flex:0 0 auto;min-height:var(--act-h);border:1.5px solid var(--ink);border-radius:var(--r-ctl);background:var(--card);color:var(--ink);font:700 var(--t-small) 'Space Grotesk',sans-serif;letter-spacing:.08em;padding:0 18px;cursor:pointer}
.fx-pay [data-cxf="same"]{color:var(--ink)}
.fx-pay [data-pa="clear"]{flex:0 0 auto;min-height:var(--act-h);border:1.5px solid var(--ink);border-radius:var(--r-ctl);background:var(--card);color:var(--ink);font:700 var(--t-small) 'Space Grotesk',sans-serif;letter-spacing:.08em;padding:0 14px;cursor:pointer}
.fx-ti [data-tif="payahead"] [data-ti="parow"]{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:4px}
.fx-ti [data-tif="payahead"].paid b{color:var(--good)}
.fx-ti [data-tif="payahead"] .ti-chips{flex:0 0 auto}
.fx-ti [data-tif="payahead"] .ti-chips button{min-height:44px}
.fx-ti [data-tif="payahead"] .ti-chips button[data-pen]{width:44px;padding:0;justify-content:center}
.fx-rides .rrow .rtrip[data-pa="line"]{color:var(--good);font-weight:700}
/* ==== b669: PAID AHEAD STANDS OUT (Ahmed 2026-10-29, bug-mvtu1r3c-k7d0o: "it should stand out more, it kind of looks like
   the other stuff"). The NET tile's solid green (#147135) with white type, 6:1, everywhere paid ahead shows: TRIP INFO's
   PAYMENT card, the Rides list badge and line, the RIDE FINISHED line, the drop-off sheet's Paid line. Data attributes
   only. Not paid stays as it was. ---- */
.frame .fx-ti .ti-f[data-tif="payahead"][data-pa="ahead"]{background:#147135;border-color:#147135;color:#fff;padding:12px 14px}
.frame[data-role="driver"] .fx-ti .ti-f[data-tif="payahead"][data-pa="ahead"] > i[data-ti="pahead"]{display:flex;align-items:center;gap:6px;background:transparent;padding:0;color:#fff;
  font:800 var(--t-small) 'JetBrains Mono',monospace;letter-spacing:.1em}
.frame .fx-ti .ti-f[data-tif="payahead"][data-pa="ahead"] > i[data-ti="pahead"] svg{flex:0 0 auto;background:#fff;color:#147135;border-radius:50%;padding:2px;box-sizing:content-box}
.frame .fx-ti .ti-f[data-tif="payahead"][data-pa="ahead"] [data-ti="patx"]{min-width:0}
.frame .fx-ti .ti-f[data-tif="payahead"][data-pa="ahead"] b[data-ti="payahead"]{display:block;color:#fff;font:400 var(--t-big)/1.1 var(--display);overflow-wrap:anywhere}
.frame .fx-ti .ti-f[data-tif="payahead"][data-pa="ahead"] s[data-ti="pasub"]{display:block;margin-top:2px;color:#fff;font:600 var(--t-small) 'Space Grotesk',sans-serif;overflow-wrap:anywhere}
.fx-ti [data-tif="payahead"] s[data-ti="pasub"][hidden]{display:none!important}
.fx-rides .rrow .badge.flagpaid[data-pa="badge"]{background:#147135;color:#fff;font-weight:800;letter-spacing:.06em}
.fx-rides .rrow .rtrip.rtrip[data-pa="line"]{color:var(--good-deep);font-weight:800}
.card.fx-done .fx-done-sub[data-pa="ahead"]{background:#147135;color:#fff;font-weight:800;border-radius:8px;padding:4px 10px;max-height:none;line-height:1.3}
.fx-jrise [data-jr="paidahead"] > b{display:block;background:#147135;color:#fff;font-weight:800;border-radius:var(--r-input);padding:10px 14px}
/* dropone (b680): the seven ways on the one drop-off sheet wrap, four chips then three, each 44 tall and never cut */
.fx-jrise [data-jr="oneways"] .jr-seg{flex-wrap:wrap}
.fx-jrise [data-jr="oneways"] .jr-seg > span{flex:1 1 calc(25% - 6px);min-width:calc(25% - 6px);white-space:nowrap;padding:0 var(--sp-1)}
.fx-jrise [data-jr="tiprow"] [data-jr="onetotal"] b{color:var(--good-deep)}
/* the trip editor's money line (the mock's C1), one tap, columns, dollar signs stacked */
.fx-trips .tdsec .tdmoney{display:grid;grid-template-columns:1fr 112px;width:100%;margin:0 0 var(--sp-2);padding:0;border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);color:var(--ink);text-align:left;cursor:pointer;font:inherit;overflow:hidden}
.fx-trips .tdsec .tdmoney > span{padding:0 12px;min-height:44px;display:flex;align-items:center;border-top:1px solid var(--line);box-sizing:border-box}
.fx-trips .tdsec .tdmoney > span:nth-child(-n+2){border-top:0}
.fx-trips .tdsec .tdmoney .w{font:600 var(--t-body) 'Space Grotesk',sans-serif}
.fx-trips .tdsec .tdmoney .a{font:700 var(--t-data) 'JetBrains Mono',monospace;border-left:1px solid var(--line);background:var(--paper);letter-spacing:.04em}
.fx-trips .tdsec .tdmoney .due{color:var(--red);font-weight:800}
.fx-trips .tdsec .tdmoney .a.due{background:var(--red);color:#fff;justify-content:center}
.fx-trips .tdsec .tdmoney .good{color:var(--good-deep);font-weight:700}
.fx-trips .tdsec .tdmoney .a.good{background:var(--ink);color:#fff;justify-content:center}
.fx-trips .tdsec .tdmoney.due{border-color:var(--red)}
.fx-trips .tdsec .tdmoney.paid{border-color:var(--good)}
.fx-trips .tdsec .tdlater{display:block;width:100%;min-height:44px;margin:0 0 var(--sp-2)}
.fx-trips .tdsec .tdlater[hidden], .fx-trips .tdsec [data-td="moneyinputs"][hidden]{display:none!important}
/* ==== b371: THE JOURNAL ASKS AT THE RIGHT MOMENT (Ahmed 2026-09-19, #f-journalrise, pick 1; bug-mu8cxl8z, bug-mu8f0egy,
   bug-mu80p9mb). START THE RIDE raises AT PICKUP, COMPLETE THE RIDE raises AT DROP-OFF over the Ride screen, LOG IT on
   the message bar raises HOME. ONE white sheet from the footer, the TRIP INFO dock law (same inset, same gap under the
   header), the screen behind steps back. Inside it is the Journal's own editor (jr-), so these rules only add what the
   risen sheet needs: the thousands in the odometer box, the green "filled in" border, the line under a box saying where
   its number came from, the one optional row, and the home totals. Selected is green (the checklist row), on every
   Journal choice, the Journal screen's too. ---- */

.jr-in.known{background:var(--card);border:1.5px solid var(--good)}
.jr-pre{flex:0 0 auto;font-family:'JetBrains Mono',monospace;font-size:var(--t-card);font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink);margin-right:-6px}
.jr-pre:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'JetBrains Mono',monospace;font-size:1.02rem;font-weight:700}
.jr-fhint{display:block;font-size:var(--fs-label);color:var(--muted);margin-top:3px;line-height:1.3}
.jr-fhint b{color:var(--good-deep);font-weight:800}
.sheet.fx-jrise{padding:var(--sp-2) var(--sp-4) 14px}
.fx-jrise .jrs-head{display:flex;flex-direction:column;gap:2px;margin:2px 0 6px}
.fx-jrise .jrs-k{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted);text-transform:uppercase;display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.fx-jrise .jrs-auto{font:800 var(--fs-label) 'JetBrains Mono',monospace;font-style:normal;letter-spacing:.08em;background:#E8F5EC;color:var(--good-deep);border-radius:6px;padding:3px 6px}
.fx-jrise .jrs-head b{font:600 var(--t-card) 'Space Grotesk',sans-serif;line-height:1.2;color:var(--ink)}
.fx-jrise .jrs-head b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.25rem 'Space Grotesk',sans-serif;line-height:1.2}
.fx-jrise .jrs-sub{font-size:var(--t-small);color:#3A3A37;line-height:var(--lh-small);margin:0 0 var(--sp-2)}
.fx-jrise .jrs-sub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.35}
.fx-jrise .jr-fields{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-2)}
.fx-jrise .jr-fld{min-width:0}
.fx-jrise .jrs-btns{display:flex;gap:var(--sp-2);margin-top:var(--sp-3)}
.fx-jrise .jrs-btns .cta{flex:1 1 0;min-width:0;margin:0}
.fx-jrise .jrs-btns .cta.ghost{flex:0 0 38%}
.fx-jrise .jrs-foot{font-size:var(--fs-label);color:var(--muted);line-height:1.35;margin-top:var(--sp-2)}
.fx-jrise .jrs-foot.err{color:var(--bad);font-weight:600}
.jr-more{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);width:100%;margin:0;padding:0 var(--sp-3);text-align:left;cursor:pointer}
.jr-more em{font:800 var(--fs-label) 'JetBrains Mono',monospace;font-style:normal;letter-spacing:.08em;color:var(--muted);flex:0 0 auto}
.jr-more.open{border-style:solid}
.jr-morebox{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--sp-2)}
.jr-rt{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-2)}
.jr-rt div{background:var(--paper);border-radius:10px;padding:7px 10px;min-width:0}
.jr-rt small{display:block;font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
.jr-rt b{display:block;font:600 var(--t-card) var(--body);font-variant-numeric:tabular-nums;white-space:nowrap}
.jr-rt b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:400 1.15rem 'Archivo Black',sans-serif}
/* Long (the Z Fold open): four columns, the choices two wide, the words the whole row, as the mock */
@media (min-aspect-ratio: 6/5){
  .fx-jrise .jr-fields{grid-template-columns:repeat(4,minmax(0,1fr))}
  .fx-jrise .jr-fields > div.jr-fld-wide, .fx-jrise .jr-fields > label.jr-fld:has([data-jr="f-earnings"]){grid-column:span 2}
  .fx-jrise .jr-fields > label.jr-fld-wide, .fx-jrise .jr-more, .fx-jrise .jr-morebox, .fx-jrise .jr-rt{grid-column:1/-1}
  /* dropone (b680): on the wide pane the one sheet is two by two, Paid beside Tip, Odometer beside Battery, so it fits 829 x 612 with no scroll (measured, 37 px over as four rows) */
  .fx-jrise [data-jr="edit"][data-one="1"] .jr-fields > .jr-fld-wide[data-jr="oneways"], .fx-jrise [data-jr="edit"][data-one="1"] .jr-fields > .jr-fld-wide[data-jr="paidahead"],
  .fx-jrise [data-jr="edit"][data-one="1"] .jr-fields > label.jr-fld-wide[data-jr="tiprow"], .fx-jrise [data-jr="edit"][data-one="1"] .jr-fields > label.jr-dash{grid-column:span 2}
}
/* the red count on the Journal tile: what he put off, today */
.tile .nbadge.jr-cnt{background:var(--red);box-shadow:0 0 0 2px #fff}
/* b697: the red edge is drawn inside the 1px border, so a due Journal tile keeps its size, its row its height, and the count its place */
.tile.jr-due{border-color:var(--red);box-shadow:inset 0 0 0 1px var(--red)}
.frame > .sheet.fx-jrise{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch}
.frame.fx-jropen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-jropen > .map{filter:brightness(.72) saturate(.8)}
.frame.fx-jropen > .sheet:not(.fx-jrise){visibility:hidden}
/* ---- b386: THE DAY IS MADE OF OUTINGS (Ahmed 2026-09-25, #f-outings, his pick 1). The mockup's ot- look, built on
   the Journal's own tokens: paper tiles, JetBrains Mono labels, Archivo Black numbers, done is green and running
   is red, the day card is ink with lime labels, every tap target 44px. Scoped to the Journal. ---- */
.fx-journal .ot-body{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0}
.fx-journal .ot-list{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0}
.fx-journal .ot-card{background:var(--card);border:2px solid var(--good);border-radius:16px;padding:9px 11px;display:flex;flex-direction:column;gap:6px;min-width:0}
.fx-journal .ot-card.run{border-color:var(--red)}
.fx-journal .ot-card.ot-wait,.fx-journal .ot-card.ot-empty{border:1.5px dashed var(--line);min-height:64px;justify-content:center}
.fx-journal .ot-card.ot-wait b,.fx-journal .ot-card.ot-empty b{font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--muted)}
.fx-journal .ot-card.ot-wait b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-journal .ot-card.ot-empty b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .9rem 'Space Grotesk',sans-serif}
.fx-journal .ot-card.ot-empty .s{font-size:var(--fs-label);color:var(--muted);line-height:1.35}
.fx-journal .ot-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);min-width:0}
.fx-journal .ot-head > div{min-width:0}
.fx-journal .ot-head b{display:block;font:400 var(--t-body) var(--body);line-height:1.15}
.fx-journal .ot-head b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:400 .96rem 'Archivo Black',sans-serif;line-height:1.15}
.fx-journal .ot-head span.s{display:block;font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.06em;color:var(--muted)}
.fx-journal .ot-pill{flex:0 0 auto;font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.08em;border-radius:var(--r-pill);padding:var(--sp-1) 9px;white-space:nowrap;background:var(--good);color:#fff}
.fx-journal .ot-pill.run{background:var(--red)}
.fx-journal .ot-tl{display:flex;flex-direction:column;border-left:2px solid var(--line);margin-left:7px;padding-left:var(--sp-3);min-width:0}
.fx-journal .ot-e{position:relative;display:flex;justify-content:space-between;align-items:center;gap:var(--sp-2);min-height:26px;font-size:var(--t-small);line-height:var(--lh-small);min-width:0}
.fx-journal .ot-e:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.2}
.fx-journal .ot-e[data-act]{min-height:44px;cursor:pointer}
.fx-journal .ot-e:before{content:'';position:absolute;left:-19px;top:50%;margin-top:-6px;width:12px;height:12px;border-radius:50%;background:var(--good);box-shadow:0 0 0 2px #fff}
.fx-journal .ot-e.now:before{background:var(--card);border:2.5px solid var(--red);width:8px;height:8px;margin-top:-6.5px}
.fx-journal .ot-e.later:before{background:var(--line)}
.fx-journal .ot-e .l{min-width:0}
.fx-journal .ot-e .l b{font-weight:700}
.fx-journal .ot-e .l span{color:var(--muted);font-size:var(--fs-label)}
.fx-journal .ot-e .r{flex:0 0 auto;font:700 var(--fs-label) 'JetBrains Mono',monospace;font-variant-numeric:tabular-nums;color:#3A3A37;text-align:right}
.fx-journal .ot-e.now .l b,.fx-journal .ot-e.now .r{color:var(--red-ink)}
.fx-journal .ot-e.later .l b,.fx-journal .ot-e.later .r{color:#9A9A95}
.fx-journal .ot-ride{position:relative;margin:3px 0;border:1.5px solid var(--ink);border-radius:var(--r-input);padding:0 10px 5px;display:flex;flex-direction:column;background:#FAFAF8;min-width:0}
.fx-journal .ot-ride:before{content:'';position:absolute;left:-21px;top:16px;width:12px;height:12px;border-radius:3px;background:var(--ink);box-shadow:0 0 0 2px #fff}
.fx-journal .ot-ride .rt{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-2);min-height:44px;cursor:pointer;min-width:0}
.fx-journal .ot-ride .rt b{font:700 var(--t-small) 'Space Grotesk',sans-serif;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fx-journal .ot-ride .rt b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .86rem 'Space Grotesk',sans-serif}
.fx-journal .ot-ride .go{flex:0 0 auto;min-height:32px;display:flex;align-items:center;font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.08em;background:var(--ink);color:#B6FF3B;border-radius:8px;padding:0 var(--sp-2)}
.fx-journal .ot-ride .ot-e{min-height:22px}
.fx-journal .ot-ride .ot-e:before{display:none}
.fx-journal .ot-tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px}
.fx-journal .ot-t{background:var(--paper);border-radius:10px;padding:5px var(--sp-2);min-width:0}
.fx-journal .ot-t small{display:block;font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fx-journal .ot-t b{display:block;font:400 var(--t-body) var(--body);font-variant-numeric:tabular-nums;white-space:nowrap;line-height:1.25;overflow:hidden;text-overflow:ellipsis}
.fx-journal .ot-t b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:400 .98rem 'Archivo Black',sans-serif;line-height:1.25}
.fx-journal .ot-t .s{display:block;font-size:var(--fs-label);color:#4A4A47;line-height:1.2;overflow-wrap:anywhere}
.fx-journal .ot-t.net{background:var(--card);border:2px solid #147135}
.fx-journal .ot-t.net small,.fx-journal .ot-t.net b{color:var(--good-deep)}
.fx-journal .ot-t.wait b{color:#9A9A95}
.fx-journal .ot-day{background:var(--ink);color:#fff;border-radius:16px;padding:9px 11px;display:flex;flex-direction:column;gap:6px}
.fx-journal .ot-day .k{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.12em;color:#B6FF3B}
.fx-journal .ot-day .ot-t{background:#1E1E1C}
.fx-journal .ot-day .ot-t small{color:#B6FF3B}
.fx-journal .ot-day .ot-t b{color:#fff}
.fx-journal .ot-day .ot-t .s{color:var(--placeholder)}
.fx-journal .ot-day .ot-t.net{background:#147135;border-color:#147135}
.fx-journal .ot-day .ot-t.net b,.fx-journal .ot-day .ot-t.net small{color:#fff}
/* b698: at 344 wide TIME OUT and CHARGING were cut with dots in every tile, here and on the outing cards: the tracking gives way */
.fx-journal .ot-t small{letter-spacing:.02em}
/* b698: a day number is never cut with dots; it fits on one line down to 344, and past that it wraps inside its tile */
.fx-journal .ot-day .ot-t b{white-space:normal;overflow:visible}
@media (max-width:360px){.fx-journal .ot-t{padding-left:4px;padding-right:4px}.fx-journal .ot-day .ot-t{padding-left:6px;padding-right:6px}.fx-journal .ot-day .ot-t b{letter-spacing:-.02em}}
/* b698: NET on its own full width line inside the one day card (JR617-DAY-MOCK-V1B, option 1) */
.fx-journal .ot-day .ot-t.net{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:0 var(--sp-2);min-height:52px;padding:8px 11px;border-radius:12px}
.fx-journal .ot-day .ot-t.net small{letter-spacing:.12em}
.fx-journal .ot-day .ot-t.net b{font-family:var(--display);font-size:28px;line-height:1.15;overflow:visible}
.fx-journal .ot-day .ot-t.net .s{flex:1 1 100%;color:#DDF5E4;line-height:1.3}
.fx-journal .ot-note{font-size:var(--fs-label);color:var(--muted);line-height:1.35}
.fx-journal .ot-note:empty{display:none}
/* Long (the Z Fold open): two outings side by side, the day card the full row under them */
@media (min-aspect-ratio: 6/5){
  .fx-journal .ot-list{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-3);align-items:start}
  .fx-journal .ot-list > .ot-wait,.fx-journal .ot-list > .ot-empty{grid-column:1/-1}
}
/* WEEK and MONTH are the costs alone, the outings belong to ONE day (the b374 switch navigating) */
.fx-journal .sheet.cx-period .ot-body{display:none}
/* THE RIDE BREAKDOWN, over the Journal from the footer, never past the header: the same geometry tokens the risen
   Journal sheet uses. Not a .sheet, so the shell's bar and drag leave it alone. */
.frame.fx-journal > .jr-brk{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);z-index:6;margin:0;
  background:var(--card);border-radius:22px 22px 0 0;box-shadow:0 -8px 26px rgba(10,10,10,.18);padding:var(--sp-2) 14px 14px;
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch;
  display:flex;flex-direction:column;gap:10px}
.frame.fx-journal.fx-brkopen > .sheet{visibility:hidden}
.fx-journal .brk-bar{display:flex;align-items:center;gap:var(--sp-2);min-height:48px}
.fx-journal .brk-back,.fx-journal .brk-x{flex:0 0 48px;width:48px;height:48px;border:0;border-radius:50%;background:var(--paper);display:flex;align-items:center;justify-content:center;font:600 var(--t-page) 'Space Grotesk',sans-serif;color:var(--ink);cursor:pointer;padding:0}
.fx-journal .brk-back:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-journal .brk-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.4rem 'Space Grotesk',sans-serif}
.fx-journal .brk-tt{flex:1 1 auto;min-width:0;line-height:1.2}
.fx-journal .brk-tt small{display:block;font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted)}
.fx-journal .brk-tt b{display:block;font:600 var(--t-card) 'Space Grotesk',sans-serif;color:var(--ink);overflow-wrap:anywhere}
.fx-journal .brk-tt b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.08rem 'Space Grotesk',sans-serif}
.fx-journal .ot-legs{background:var(--card);border:1px solid var(--line);border-radius:var(--r-ctl);padding:2px 11px}
.fx-journal .ot-leg{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);min-height:44px;border-top:1px solid var(--line);font-size:var(--t-small)}
.fx-journal .ot-leg:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}
.fx-journal .ot-leg:first-child{border-top:0}
.fx-journal .ot-leg .l{min-width:0;line-height:1.2}
.fx-journal .ot-leg .l span{display:block;font-size:var(--fs-label);color:var(--muted)}
.fx-journal .ot-leg .r{flex:0 0 auto;display:flex;gap:10px;font:700 var(--fs-label) 'JetBrains Mono',monospace;font-variant-numeric:tabular-nums}
.fx-journal .ot-leg .r i{font-style:normal;color:var(--muted);min-width:44px;text-align:right}
.fx-journal .ot-leg.tot{font-weight:800}
.fx-journal .ot-leg.tot .r i{color:var(--ink)}
.fx-journal .ot-money{background:var(--card);border:1px solid var(--line);border-radius:var(--r-ctl);padding:2px 11px}
.fx-journal .ot-m{display:flex;justify-content:space-between;align-items:center;gap:10px;min-height:36px;font-size:var(--t-small);line-height:var(--lh-small);border-top:1px solid var(--line)}
.fx-journal .ot-m:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.2}
.fx-journal .ot-m:first-child{border-top:0}
.fx-journal .ot-m > span{min-width:0}
.fx-journal .ot-m span.s{display:block;font-size:var(--fs-label);color:var(--muted)}
.fx-journal .ot-m b{font-variant-numeric:tabular-nums;white-space:nowrap}
.fx-journal .ot-m.minus > b{color:var(--red-ink)}
.fx-journal .ot-m.net{border-top:1.5px solid var(--ink);margin-top:2px;min-height:44px;font:400 var(--t-body) var(--body)}
.fx-journal .ot-m.net:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:400 1rem 'Archivo Black',sans-serif}
.fx-journal .ot-m.net b{color:var(--good-deep);font-size:var(--t-card);font-weight:600}
.fx-journal .ot-m.net b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.3rem}
.frame.fx-journal > .jr-brk[hidden],.fx-journal .ot-day[hidden],.fx-journal .mc-card.jr-dayonly[hidden]{display:none!important}

/* LAST, so nothing above can beat it (the explicit-display law) */
.frame > .sheet.fx-jrise[hidden], .jr-morebox[hidden], .fx-jrise .jrs-sub[hidden], .fx-jrise .jrs-auto[hidden], .tile .nbadge.jr-cnt[hidden]{display:none!important}

/* ==== b391: CODE FOR THE ANDROID APP, docked the TRIP INFO way (from the footer, the side inset, the gap under the
   header, the screen behind it stepping back), and the owner's Where is everyone row. */
.frame > .sheet.fx-acode{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;
  padding:var(--sp-2) var(--sp-4) var(--sp-4);max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch}
.frame.fx-acopen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-acopen > .sheet:not(.fx-acode){visibility:hidden}
.fx-acode .acode-body{padding:var(--sp-1) 2px 0}
/* the module's own .row is a button column, not the shell's row card: the card's border, fill and padding stay off it */
.ypd-code .row{border:0;background:none;padding:0;min-height:0;border-radius:0;margin-bottom:0;align-items:stretch}
/* LAST, the explicit-display law: .row sets display:flex, so hidden must win outright */
.frame > .sheet.fx-acode[hidden], .fx-authland .authsec[hidden], .row[data-wi-owner][hidden]{display:none!important}

/* ==== b396: THE INBOX FOR THE PASSENGER HE IS DRIVING (Ahmed 2026-09-28, option 1 of YPD-INBOX-PER-PASSENGER-MOCKUP-V1A).
   Who it is for, with ALL RIDERS beside it, then the texts her phone got stacked in one blue card, counted, each SENT or
   NOT SENT, then the in-app rows as before. Blue is the text colour because a text is not an app message. */
.ypdib-who,.ypdib-stack{box-sizing:border-box;max-width:100%;width:100%}
.ypdib-who{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--card);border:1.5px solid var(--ink);
  border-radius:var(--r-ctl);padding:var(--sp-2) var(--sp-2) var(--sp-2) 14px;margin:0 0 10px}
.ypdib-who > div{display:flex;flex-direction:column;min-width:0}
.ypdib-who > div[data-act],.ypdib-stack[data-act]{cursor:pointer}
.ypdib-who b{font:600 var(--t-card) var(--body);color:var(--ink);overflow-wrap:anywhere}
.ypdib-who b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.05rem 'Archivo Black',sans-serif}
.ypdib-k,.ypdib-sec{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted);text-transform:uppercase}
.ypdib-sw{flex:0 0 auto;min-height:44px;padding:0 var(--sp-3);border-radius:var(--r-input);border:1.5px solid var(--ink);background:var(--card);color:var(--ink);
  font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.06em;cursor:pointer}
.ypdib-sec{display:block;margin:var(--sp-1) 2px 6px}
.ypdib-stack{background:var(--card);border:2px solid var(--pax);border-radius:var(--r-ctl);padding:10px var(--sp-3);display:flex;flex-direction:column;gap:6px;margin:0 0 var(--sp-3)}
.ypdib-top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.ypdib-top b{font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--pax)}
.ypdib-top b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .92rem 'Space Grotesk',sans-serif}
.ypdib-cnt{min-width:26px;height:26px;border-radius:13px;background:var(--pax);color:#fff;display:inline-flex;align-items:center;justify-content:center;
  font:800 var(--fs-label) 'JetBrains Mono',monospace;padding:0 7px}
.ypdib-li{display:flex;justify-content:space-between;align-items:baseline;gap:10px;border-top:1px solid #E8EDF8;padding-top:6px;font-size:var(--t-small);line-height:var(--lh-small)}
.ypdib-li:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.35}
.ypdib-li > span{color:#2A2A27;min-width:0;overflow-wrap:anywhere}
.ypdib-li i{flex:0 0 auto;font-style:normal;font:700 var(--fs-label) 'JetBrains Mono',monospace;color:var(--muted);white-space:nowrap}
.ypdib-li em{font-style:normal;font-weight:800;margin-left:var(--sp-1)}
.ypdib-li em.ok{color:var(--good-deep)}
.ypdib-li em.bad{color:var(--red-ink)}

/* ==== b396: RECEIPTS TO SEND, MONEY OWED's shape with a black edge (a to-do, not a warning), and its sheet rows */
.mo-panel.rc{border-color:var(--ink);background:var(--card);margin-top:var(--sp-2)}
.mo-panel.rc .mo-k{color:var(--ink)}
.fx-owed .mo-pill.rc{background:var(--ink)}
.fx-owed .mo-row.done .mo-pill.rc{background:var(--good)}

.fx-owed .rc-never{width:100%;cursor:pointer}
.fx-owed .mo-done[data-rc="ask"]{color:var(--ink)}   /* b717: the RIDE FINISHED choice's question, ink, not the done green */
.fx-owed .rc-never[disabled]{opacity:.6}
.mo-panel.rc[hidden]{display:none!important}
/* ==== b442: PRICE TO CHECK on Home and the PRICE CHECK card in TRIP INFO (Ahmed 2026-10-01, Lelani's ride: "something
   changed, now that needs to be a badge that pops up for me like a notification"). The panel is the MONEY OWED panel in
   orange, money to look at, not money owed. The card sits at the top of STOPS, IN ORDER. Every tap 44px or more. */
.mo-panel.pc{border-color:var(--orange);background:#FFF7F0;margin-top:var(--sp-2)}
.mo-panel.pc .mo-k{color:#B23A00}
.mo-panel.pc .mo-go{background:var(--orange)}
.mo-panel.pc[hidden]{display:none!important}
.fx-ti .ti-pc[hidden]{display:none!important}
.fx-ti .ti-pc{display:flex;flex-direction:column;gap:var(--sp-2)}
.fx-ti .pc-card{display:flex;flex-direction:column;gap:var(--sp-2);border:2px solid var(--orange);border-radius:var(--r-input);padding:10px var(--sp-3);background:#FFF7F0}
.fx-ti .pc-card.pc-letgo, .fx-ti .pc-card.pc-shorter{border-color:var(--line);background:var(--card)}
.fx-ti .pc-card.pc-done{border-color:var(--good);background:#EEF8F1}
.fx-ti .pc-card.pc-pick, .fx-ti .pc-card.pc-err{border-color:var(--ink);background:var(--card)}
.fx-ti .pc-k{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:#B23A00}
.fx-ti .pc-done .pc-k{color:#1F7A3A}
.fx-ti .pc-pick .pc-k, .fx-ti .pc-err .pc-k{color:var(--ink)}
.fx-ti .pc-head{font:600 var(--t-card) 'Space Grotesk',sans-serif;color:var(--ink);line-height:1.25}
.fx-ti .pc-head:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1.02rem 'Space Grotesk',sans-serif;line-height:1.25}
.fx-ti .pc-say{margin:0;font:400 var(--t-body)/var(--lh-body) 'Space Grotesk',sans-serif;color:var(--ink)}
.fx-ti .pc-say:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 .95rem/1.4 'Space Grotesk',sans-serif}
.fx-ti .pc-tier{margin:0;font:700 var(--t-body)/var(--lh-body) 'Space Grotesk',sans-serif;color:#B23A00}
.fx-ti .pc-tier:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .9rem/1.35 'Space Grotesk',sans-serif}
.fx-ti .pc-letgo .pc-tier, .fx-ti .pc-shorter .pc-tier{color:var(--muted)}
.fx-ti .pc-math{margin:0;font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.fx-ti .pc-math:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;line-height:1.4}
.fx-ti .pc-steps{margin:0;padding-left:20px;font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink)}
.fx-ti .pc-steps:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.45}
.fx-ti .pc-stepper{display:grid;grid-template-columns:72px 1fr 72px;gap:var(--sp-2);align-items:stretch}
.fx-ti .pc-stepper button, .fx-ti .pc-row button, .fx-ti .pc-quiet button{min-height:48px;border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--ink);
  font:700 var(--t-small) 'Space Grotesk',sans-serif;letter-spacing:.04em;cursor:pointer;padding:0 var(--sp-2)}
.fx-ti .pc-stepper button:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-ti .pc-row button:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-ti .pc-quiet button:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .8rem 'Space Grotesk',sans-serif}
.fx-ti .pc-tot{display:flex;align-items:center;gap:var(--sp-1);border:2px solid var(--ink);border-radius:10px;padding:0 10px;background:var(--card);min-height:48px;min-width:0;box-sizing:border-box}
.fx-ti .pc-tot span{font:600 var(--t-card) var(--body);color:var(--ink)}
.fx-ti .pc-tot span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.3rem 'Archivo Black',sans-serif}
.fx-ti .pc-tot input{flex:1 1 auto;width:100%;min-width:0;border:0;outline:none;background:transparent;font:600 var(--t-card) var(--body);color:var(--ink);text-align:center;min-height:44px}
.fx-ti .pc-tot input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.3rem 'Archivo Black',sans-serif}
.fx-ti .pc-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
.fx-ti .pc-row .pc-go{background:var(--orange);color:#fff;border-color:var(--orange)}
.fx-ti .pc-row .pc-copy{background:var(--good);color:#fff;border-color:var(--good)}
.fx-ti .pc-row button:disabled{opacity:.4;cursor:default}
.fx-ti .pc-msg{width:100%;box-sizing:border-box;min-height:132px;border:1.5px solid var(--line);border-radius:10px;padding:10px;font:400 var(--t-body)/var(--lh-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card);resize:vertical}
.fx-ti .pc-msg:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:500 .92rem/1.4 'Space Grotesk',sans-serif}
.fx-ti .pc-pickrow{display:flex;align-items:center;gap:10px;min-height:52px;border:1px solid var(--line);border-radius:10px;padding:6px 10px;background:var(--card);cursor:pointer}
.fx-ti .pc-pickrow input{width:24px;height:24px;flex:0 0 auto;margin:0}
.fx-ti .pc-pickrow span{min-width:0;display:flex;flex-direction:column}
.fx-ti .pc-pickrow b{font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink)}
.fx-ti .pc-pickrow b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .92rem 'Space Grotesk',sans-serif}
.fx-ti .pc-pickrow s{text-decoration:none;font-size:var(--t-small);color:var(--muted);overflow-wrap:anywhere}
.fx-ti .pc-pickrow s:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem}
.fx-ti .pc-quiet{display:flex;flex-direction:column;gap:6px;border:1px dashed var(--line);border-radius:var(--r-input);padding:var(--sp-2) 10px}
.fx-ti .pc-quiet span{font-size:var(--t-small);color:var(--muted)}
.fx-ti .pc-quiet span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem}

/* ==== b434 FIXED, PLEASE TEST, b439 folded under the tiles, b441 BUG REPORT with FROM OTHER DRIVERS AND RIDERS.
   b607 (Ahmed 2026-10-26, bug-mvpxlyxn-baid9: "these menus and these cards and these colors, they don't match the rest of the
   app, they need to match the branding of the app"): the whole panel is drawn from the tokens now. A white Home card with the
   tile's thin line and corner. Every section label is the orange label chip (the .badge.retleg look, --label-bg on --label-fg,
   12px 800 caps). Counts and the build in the number type (--t-num, the mono face). Buttons from the b569 system: WORKS and
   SEND NOT YET the orange primary, NOT YET and BACK the secondary, OPEN / CLOSE, the arrows, SHOW ALL, ONE AT A TIME and PLAY THE
   RECORDING the small secondary. No lime edge, no lime chips (lime is for ink chrome, never on white), no teal box, no green
   fill (green is for states only). FROM OTHER DRIVERS AND RIDERS is the same white card under a hairline, a RIDER chip in
   orange or a DRIVER chip in ink, so the two still read apart (his b441 ask). Nothing in the panel's behaviour changed. */
.bf-panel{display:flex;flex-direction:column;gap:var(--sp-2);width:100%;margin:var(--sp-3) 0 0;padding:var(--sp-2) 14px var(--sp-3);
  border:1px solid var(--line);border-radius:var(--r-ctl);background:var(--card);color:var(--ink);text-align:left;font:inherit;box-sizing:border-box}
.bf-panel .bf-toggle{width:100%;min-height:var(--btn-h-sm);border:0;background:none;padding:0;cursor:pointer;text-align:left;color:inherit;font:inherit}
.bf-panel .bf-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.bf-panel .bf-right{display:flex;align-items:center;justify-content:flex-end;gap:10px;min-width:0;flex:1 1 auto}
/* the label chip: the title, YOURS TO TEST, FROM OTHER DRIVERS AND RIDERS, every WHAT label */
.bf-panel :is(.bf-title,.bf-minehd,.bf-otitle,.bf-k){display:inline-flex;align-items:center;align-self:flex-start;margin:0;
  font:800 var(--t-label)/1 var(--body);letter-spacing:.1em;text-transform:uppercase;background:var(--label-bg);color:var(--label-fg);
  padding:5px 8px;border-radius:6px;white-space:nowrap;flex:none}
.bf-panel .bf-k{margin-top:var(--sp-1);white-space:normal}
/* the counts and the build line, in the number type */
.bf-panel :is(.bf-amt,.bf-split,.bf-oamt,.bf-pos,.bf-build){font:var(--w-num) var(--t-num)/1.3 var(--mono);letter-spacing:.02em;color:var(--ink);text-transform:none}
.bf-panel .bf-amt::after{content:' to test'}
.bf-panel .bf-split{white-space:normal;text-align:right;min-width:0}
.bf-panel .bf-split[hidden], .bf-panel .bf-amt[hidden], .bf-panel .bf-minehd[hidden]{display:none!important}
/* the small secondary of the b569 system */
.bf-panel :is(.bf-chev,.bf-nb,.bf-notyet,.bf-cancel,.bf-play){display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;
  min-height:var(--btn-h-sm);padding:0 12px;border:var(--btn-edge) solid var(--ink);border-radius:var(--btn-r);background:var(--card);color:var(--ink);
  font:var(--btn-fw) var(--btn-fs-sm)/1.15 var(--body);letter-spacing:var(--btn-ls);text-transform:var(--btn-case);cursor:pointer;box-shadow:none;flex:none}
.bf-panel .bf-nb{min-width:48px}
.bf-panel .bf-nb[disabled]{opacity:.35}
.bf-panel .bf-body{display:flex;flex-direction:column;gap:var(--sp-2)}
.bf-panel .bf-body[hidden]{display:none!important}
.bf-panel .bf-navrow{display:flex;align-items:center;gap:var(--sp-2)}
.bf-panel .bf-pos{flex:1;text-align:center}
.bf-panel .bf-list,.bf-panel .bf-olist{display:flex;flex-direction:column;gap:var(--sp-2)}
/* a fix card and a report card: the Home tile's own look */
.bf-panel .bf-row,.bf-panel .bf-orow{border:1px solid var(--line);border-radius:var(--r-ctl);padding:var(--sp-3) 14px;display:flex;flex-direction:column;gap:var(--sp-1);background:var(--card);min-width:0}
.bf-panel .bf-build{color:var(--muted)}
.bf-panel .bf-t{font:600 var(--t-body)/var(--lh-small) var(--body);color:var(--ink);overflow-wrap:anywhere}
.bf-panel :is(.bf-when,.bf-owho){font:var(--w-small) var(--t-small)/var(--lh-small) var(--body);color:var(--muted);overflow-wrap:anywhere}
.bf-panel .bf-esc{font:800 var(--t-small)/1.2 var(--body);color:#FFFFFF;background:var(--bad);border-radius:6px;padding:6px 10px;align-self:flex-start}
.bf-panel .bf-back{font:800 var(--t-small)/1.3 var(--body);color:var(--bad-ink)}
.bf-panel .bf-btns{display:flex;gap:var(--sp-2);margin-top:6px}
.bf-panel .bf-btns button{flex:1 1 0}
/* WORKS and SEND NOT YET: the primary, the one next thing on the card */
.bf-panel :is(.bf-works,.bf-send){display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-height:var(--btn-h);padding:0 12px;
  border:var(--btn-edge) solid var(--accent);border-radius:var(--btn-r);background:var(--accent);color:var(--on-accent);
  font:var(--btn-fw) var(--btn-fs)/1.15 var(--body);letter-spacing:var(--btn-ls);text-transform:var(--btn-case);cursor:pointer;box-shadow:none}
.bf-panel :is(.bf-notyet,.bf-cancel){min-height:var(--btn-h);font-size:var(--btn-fs)}
.bf-panel .bf-btns button[disabled]{opacity:.6;cursor:default}
.bf-panel .bf-note{min-height:var(--btn-h);width:100%;box-sizing:border-box;border:var(--rule) solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);
  font:500 var(--t-body) var(--body);background:var(--card);color:var(--ink)}
.bf-panel .bf-err{font:700 var(--t-small)/1.3 var(--body);color:var(--bad-ink)}
/* FROM OTHER DRIVERS AND RIDERS, under a hairline, read only */
.bf-panel .bf-others{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-1);padding:var(--sp-3) 0 0;border-top:1px solid var(--line)}
.bf-panel .bf-others[hidden]{display:none!important}
.bf-panel .bf-ohd{display:flex;align-items:center;justify-content:space-between;gap:10px}
.bf-panel .bf-ohead{display:flex;align-items:center;gap:var(--sp-2);min-width:0}
.bf-panel .bf-badge{display:inline-flex;align-items:center;font:800 var(--t-label)/1 var(--body);letter-spacing:.1em;text-transform:uppercase;padding:5px 8px;border-radius:6px;flex:none}
.bf-panel .bf-badge.rider{background:var(--accent);color:var(--on-accent)}
.bf-panel .bf-badge.driver{background:var(--ink);color:#FFFFFF}
.bf-panel .bf-oname{font:700 var(--t-body)/1.3 var(--body);color:var(--ink);overflow-wrap:anywhere;min-width:0}
.bf-panel .bf-ostate{align-self:flex-start;font:var(--w-num) var(--t-num)/1 var(--mono);letter-spacing:.06em;padding:5px var(--sp-2);border-radius:6px;border:1px solid var(--line);color:var(--ink);background:var(--card)}
.bf-panel .bf-ostate.st-new{background:var(--warn-tint);border-color:var(--warn)}
.bf-panel .bf-ostate.st-works{background:var(--good-tint);border-color:var(--good);color:var(--good-ink)}
.bf-panel .bf-ostate.st-notyet{background:var(--bad-tint);border-color:var(--bad);color:var(--bad-ink)}
.bf-panel .bf-none{color:var(--muted);font-weight:500}
.bf-panel .bf-media{width:100%;max-height:220px;border-radius:var(--r-input);background:var(--ink)}
@media (min-aspect-ratio: 6/5){ .bf-panel .bf-list,.bf-panel .bf-olist{display:grid;grid-template-columns:1fr 1fr} }
/* LAST, so nothing above can beat it (the explicit-display law) */
.bf-panel[hidden]{display:none!important}

/* ==== b397: A CHARGE IN PROGRESS SAYS IT IS SAVED (bug-mulk7efr): the green band on the reopened stop, the two boxes left */
.jr-chg{display:flex;flex-direction:column;gap:3px;padding:10px var(--sp-3);border-radius:var(--r-input);background:#EEF8F1;border:2px solid var(--good)}
.jr-chg b{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.08em;color:var(--good-deep)}
.jr-chg span{font-size:var(--t-small);line-height:var(--lh-small);color:#1F3B2A}
.jr-chg span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.35}
/* b481: the charge shortcut's "Add to home screen" help line, under the charging form's header, dismissible */
.jr-sclhelp{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-2) var(--sp-2) 10px var(--sp-3);border-radius:var(--r-input);background:#FFF8E1;border:1.5px solid #E0A400}
.jr-sclhelp-top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.jr-sclhelp b{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.08em;color:#8A5A00}
.jr-sclhelp span{font-size:var(--t-small);line-height:var(--lh-small);color:#3A2A00}
.jr-sclhelp span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.35}
.jr-sclhelp ol{margin:2px 0 0;padding:0 0 0 20px;font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink)}
.jr-sclhelp ol:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.45}
.jr-sclx{flex:0 0 auto;width:44px;height:44px;margin:-6px 0;border:0;border-radius:22px;background:transparent;color:#8A5A00;font:600 var(--t-page)/1 sans-serif;cursor:pointer}
.jr-sclx:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 1.4rem/1 sans-serif}
/* b571: .jr-in.jr-todo (the red edge on the two boxes a charge still needs) is gone, see the b571 block at the end */
/* b398: what the Journal tile's red count is counting, in words */
.jr-duebar{display:flex;flex-direction:column;gap:2px;margin:0 0 var(--sp-2);padding:9px var(--sp-3);border-radius:var(--r-input);background:var(--red-wash);border:1.5px solid var(--orange)}
.jr-duebar b{font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--red-ink)}
.jr-duebar span{font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink)}
.jr-duebar span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;line-height:1.35}
.jr-duebar[hidden]{display:none!important}
/* b467: parked during an outing, the stop one tap away near the top; his charging places as he types, the star, the chips */
.jr-park{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;min-height:52px;margin:0 0 var(--sp-2);padding:9px 14px;border-radius:var(--r-input);
  background:var(--red-wash);border:1.5px solid var(--orange);color:var(--ink);text-align:left;cursor:pointer}
.jr-park b{font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--red-ink)}
.jr-park b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .95rem 'Space Grotesk',sans-serif}
.jr-park span{font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink)}
.jr-park span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.3}
.jr-park[hidden]{display:none!important}
.fx-journal .sheet.cx-period .jr-park{display:none!important}   /* b469: DAY only, without being one of the .jr-dayonly cards */
/* b469: a personal charge says so, small, beside its place */
.jr-tag{display:inline-block;margin-left:var(--sp-2);padding:2px 6px;border-radius:6px;background:#EEF0F6;color:#3A3F55;font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.08em;vertical-align:middle}
/* b480: another business's charge, the same chip in the Website builder gold the places chips already wear */
.jr-tag.jr-tag-ob{background:#FFF8E1;color:#7A5A00}
/* b480: three choices in one row at phone width, the words wrap rather than clip */
.jr-seg span[data-act^="jr-seg:personal:"]{padding:var(--sp-2) var(--sp-1);line-height:1.2;display:flex;align-items:center;justify-content:center}
.jr-chips{display:flex;flex-wrap:wrap;gap:6px}
.jr-chips[hidden]{display:none!important}
.jr-chip{min-height:44px;max-width:100%;padding:0 14px;border-radius:22px;border:1.5px solid #E0A400;background:#FFF8E1;color:var(--ink);
  font:700 var(--t-small) 'Space Grotesk',sans-serif;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.jr-chip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .84rem 'Space Grotesk',sans-serif}
.jr-sugg{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--card);margin-top:-4px}
.jr-sugg[hidden]{display:none!important}
.jr-sug{display:flex;flex-direction:column;align-items:flex-start;gap:1px;width:100%;min-height:52px;padding:var(--sp-2) var(--sp-3);border:0;border-bottom:1px solid var(--line);
  background:var(--card);color:var(--ink);text-align:left;cursor:pointer}
.jr-sug:last-child{border-bottom:0}
.jr-sug b{font:700 var(--t-body) 'Space Grotesk',sans-serif}
.jr-sug b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .92rem 'Space Grotesk',sans-serif}
.jr-sug span{font-size:var(--fs-label);color:var(--muted)}
.jr-sug em{font-size:var(--t-small);font-style:normal;font-weight:700;color:var(--red-ink)}
.jr-sug em:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.76rem;font-weight:700}
.jr-star{width:100%;min-height:48px;padding:0 var(--sp-3);border:1.5px solid var(--line);border-radius:10px;background:var(--card);color:var(--ink);
  font:700 var(--t-small) 'Space Grotesk',sans-serif;text-align:left;cursor:pointer}
.jr-star:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .88rem 'Space Grotesk',sans-serif}
.jr-star.on{background:#FFF8E1;border-color:#E0A400}
/* b400: RESET THE FLAG, full width under the chips, quiet until he needs it */
.fx-ti .ti-reset{width:100%;min-height:48px;margin-top:10px;border:1.5px solid var(--orange);border-radius:var(--r-input);background:var(--card);color:var(--red-ink);
  font:800 var(--t-num) 'JetBrains Mono',monospace;letter-spacing:.06em;cursor:pointer}
.fx-ti .ti-reset:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .76rem 'JetBrains Mono',monospace}
.fx-ti .ti-reset[hidden]{display:none!important}

/* ==== b401: BOOK A RIDE IN THE APP (Ahmed 2026-09-28, #f-bookapp option 2, "simple and easy... in steps, like a tutorial").
   The dock sheet every other panel is: white, from the footer, the TRIP INFO dock law. One question per screen, the step
   and a progress bar on top, NEXT and BACK at the bottom. var(--orange) is his orange on his side and her blue on hers
   (b367), so the sheet wears whoever is booking. Small labels mono and upper case, 44px and taller taps. */
.frame > .sheet.fx-book{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch;padding:var(--sp-2) var(--sp-4) var(--sp-4)}
.frame.fx-bookopen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-bookopen > .map{filter:brightness(.72) saturate(.8)}
.fx-book > .shbar > .fin-x{position:absolute;top:50%;right:0;transform:translateY(-50%);width:48px;height:48px;display:flex;align-items:center;justify-content:center;font-size:var(--t-page);color:var(--ink);cursor:pointer;font-weight:600}
.fx-book > .shbar > .fin-x:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.6rem}
.fx-book .bk-body{display:flex;flex-direction:column;gap:var(--sp-3);padding-top:var(--sp-1)}
.fx-book .bk-k{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--orange);text-transform:uppercase;padding-right:52px}
.fx-book .bk-bar{height:6px;border-radius:3px;background:#EEECE7;overflow:hidden}
.fx-book .bk-bar i{display:block;height:100%;background:var(--orange);border-radius:3px}
.fx-book .bk-q{font:600 var(--t-card) var(--body);line-height:1.25;color:var(--ink);text-wrap:balance}
.fx-book .bk-q:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.15rem 'Archivo Black',sans-serif;line-height:1.25}
.fx-book .bk-f{display:flex;flex-direction:column;gap:5px}
.fx-book .bk-f.bad input,.fx-book .bk-f.bad select,.fx-book .bk-f.bad textarea,.fx-book .bk-f.bad .bk-seg{border-color:var(--red)!important;box-shadow:0 0 0 2px rgba(212,45,30,.15)}
.fx-book .bk-lb{font:700 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.1em;color:var(--muted);text-transform:uppercase}
.fx-book .bk-lb i{font-style:normal;text-transform:none;letter-spacing:0;font-family:'Space Grotesk',sans-serif;font-weight:500}
.fx-book input[type=text],.fx-book input[type=tel],.fx-book input[type=email],.fx-book input[type=date],.fx-book input[type=number],.fx-book select,.fx-book textarea{
  width:100%;box-sizing:border-box;min-height:52px;border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);background:var(--card);color:var(--ink);font:400 var(--t-body) 'Space Grotesk',system-ui,sans-serif}
.fx-book input[type=text]:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-book input[type=tel]:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-book input[type=email]:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-book input[type=date]:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-book input[type=number]:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-book select:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-book textarea:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:500 16px 'Space Grotesk',system-ui,sans-serif}
.fx-book textarea{padding:var(--sp-3);min-height:88px;resize:vertical}
.fx-book input:focus,.fx-book select:focus,.fx-book textarea:focus{outline:none;border-color:var(--orange)}
.fx-book .bk-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--sp-2)}
.fx-book .bk-hint{font-style:normal;font-size:var(--t-small);line-height:var(--lh-small)}
.fx-book .bk-hint:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.35}
.fx-book .bk-hint.ok{color:var(--good-deep)}
.fx-book .bk-hint.warn{color:#B07600}
.fx-book .bk-choices{display:flex;flex-direction:column;gap:10px}
.fx-book .bk-choice{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;min-height:64px;padding:var(--sp-3) 14px;border:1.5px solid var(--line);border-radius:var(--r-ctl);background:var(--card);color:var(--ink);cursor:pointer;font:inherit}
.fx-book .bk-choice b{font:700 var(--t-body) 'Space Grotesk',sans-serif}
.fx-book .bk-choice b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 1rem 'Space Grotesk',sans-serif}
.fx-book .bk-choice span{font-size:var(--t-small);color:var(--muted)}
.fx-book .bk-choice span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem}

.fx-book .bk-seg{display:flex}
.fx-book .bk-seg button{flex:1 1 0;min-width:0;cursor:pointer;padding:0 var(--sp-1)}


.fx-book .bk-step{display:grid;grid-template-columns:52px 1fr 52px;gap:var(--sp-2)}
.fx-book .bk-step button{cursor:pointer}
.fx-book .bk-step input{text-align:center}
.fx-book .bk-note{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.fx-book .bk-note:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.82rem;line-height:1.4}
.fx-book .bk-note.warn{color:#B07600;font-weight:600}
.fx-book .bk-consent{display:flex;gap:10px;align-items:flex-start;font-size:var(--t-small);line-height:var(--lh-small);color:#3A3A37}
.fx-book .bk-consent:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.78rem;line-height:1.45}
.fx-book .bk-consent input{width:24px;height:24px;flex:0 0 24px;margin-top:2px;accent-color:var(--orange)}
.fx-book .bk-consent a{color:var(--orange)}
.fx-book .bk-err{padding:10px var(--sp-3);border-radius:var(--r-input);background:var(--red-wash);border:1.5px solid var(--red);color:#8E1B10;font-size:var(--t-small);line-height:var(--lh-small);font-weight:700}
.fx-book .bk-err:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.4;font-weight:600}
.fx-book .bk-nav{display:grid;grid-template-columns:1fr 2fr;gap:10px;margin-top:var(--sp-1)}
.fx-book .bk-cta{cursor:pointer}
.fx-book .bk-cta[disabled]{opacity:.6}
.fx-book .bk-ghost{min-height:54px;border:1.5px solid var(--ink);border-radius:var(--r-ctl);background:var(--card);color:var(--ink);font:700 var(--t-small) 'Space Grotesk',sans-serif;letter-spacing:.04em;cursor:pointer}
.fx-book .bk-ghost:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .86rem 'Space Grotesk',sans-serif}
.fx-book .bk-done{font:600 var(--t-page) var(--body);color:var(--good-deep)}
.fx-book .bk-done:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:900 1.4rem 'Archivo Black',sans-serif}
.fx-book .bk-body > .bk-cta,.fx-book .bk-body > .bk-ghost{width:100%}
.fx-book .bk-rv{border:1px solid var(--line);border-radius:var(--r-input);padding:var(--sp-2) var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-1)}
.fx-book .bk-rvh{display:flex;justify-content:space-between;align-items:center}
.fx-book .bk-rvh button{min-height:40px;min-width:64px;border:1.5px solid var(--ink);border-radius:10px;background:var(--card);font:800 var(--fs-label) 'JetBrains Mono',monospace;letter-spacing:.06em;cursor:pointer}
.fx-book .bk-rl{display:flex;justify-content:space-between;gap:10px;font-size:var(--t-small);line-height:var(--lh-small)}
.fx-book .bk-rl:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;line-height:1.35}
.fx-book .bk-rl span{color:var(--muted);flex:0 0 auto}
.fx-book .bk-rl b{text-align:right;overflow-wrap:anywhere;font-weight:700}
.tile.tile-old b{color:var(--muted)}
.fin-btns .cta.ghost.fin-old{background:var(--card);color:var(--ink);border:1.5px solid var(--ink)}
.frame > .sheet.fx-book[hidden]{display:none!important}

/* b407: SEND THE CONFIRMATION on the Booked screen. Outline buttons: SEND OFFER stays the only orange on this sheet. */
:is(.fx-off,.fx-pricing) .fx-cf{display:flex;flex-direction:column;gap:9px;margin-bottom:10px}
:is(.fx-off,.fx-pricing) .fx-cf[hidden],:is(.fx-off,.fx-pricing) .fx-cf-msg[hidden]{display:none}
:is(.fx-off,.fx-pricing) .fx-cf .k{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--good)}
:is(.fx-off,.fx-pricing) .fx-cf-msg{display:flex;flex-direction:column;gap:var(--sp-2);border:1.5px solid var(--line, #d9d9d4);border-radius:15px;padding:11px}
:is(.fx-off,.fx-pricing) .fx-cf-bub{white-space:pre-wrap;word-break:break-word;background:#DCF8C6;color:#111;border-radius:var(--r-input) var(--r-input) 3px var(--r-input);padding:10px var(--sp-3);font-size:var(--t-body);line-height:var(--lh-body);user-select:text;-webkit-user-select:text}
:is(.fx-off,.fx-pricing) .fx-cf-bub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem;line-height:1.4}
:is(.fx-off,.fx-pricing) .fx-cf .cta{min-height:48px;margin:0}

/* b418 CALENDAR SYNC, OLD ABOVE NEW (#calsync option 1, Ahmed 2026-09-30). Each change is its own row: its name on the
   left, the app's value on top crossed out in red, the calendar's value underneath in green. Applied cards turn green. */
:is(.fx-comms,.fx-set) .crow.calcard .tx .calhead{display:flex;justify-content:space-between;align-items:baseline;gap:var(--sp-2);margin-bottom:var(--sp-1)}
:is(.fx-comms,.fx-set) .crow.calcard .tx .calhead b{display:inline;font-size:var(--t-body);margin:0;color:var(--ink)}
:is(.fx-comms,.fx-set) .crow.calcard .tx .calhead b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
:is(.fx-comms,.fx-set) .crow.calcard .tx .calkind{font-style:normal;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted);flex:0 0 auto}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cchg{display:grid;grid-template-columns:78px 1fr;gap:2px 10px;align-items:start;
  border-top:1px solid rgba(0,0,0,.07);padding-top:7px;margin-top:7px}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cchg .cfk{padding-top:2px}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cvals{display:flex;flex-direction:column;gap:2px}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cvold{display:block;color:var(--red);font-weight:500;text-decoration:line-through;text-decoration-thickness:1.5px}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cvnew{display:block;color:var(--good);font-weight:700;font-size:var(--t-small)}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cvnew:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.84rem}
:is(.fx-comms,.fx-set) .crow.calcard[data-done]{background:var(--good-tint);border-color:var(--good)}
:is(.fx-comms,.fx-set) .crow.calcard .caldone{flex:1 1 100%;display:flex;align-items:center;justify-content:center;min-height:46px;
  border-radius:var(--r-input);background:var(--good);color:#fff;font-weight:700;font-size:var(--t-small);margin-top:var(--sp-2)}
:is(.fx-comms,.fx-set) .crow.calcard .caldone:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:700;font-size:.9rem}
/* b498: THE CANCEL CARD. A "Canceled" title or a deleted event proposes cancelling one booking: red label, red edge,
   the booking's own facts in ink (nothing old, nothing new), the same APPLY and SKIP. "Not on the calendar" is the
   read-only list of bookings the sync could not pair with any event, under the cards. */
:is(.fx-comms,.fx-set) .crow.calcard .tx .calkind.cx{color:var(--red)}
:is(.fx-comms,.fx-set) .crow.calcard[data-cx]{border-color:var(--red)}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cvcx{display:block;color:var(--ink);font-weight:700;font-size:var(--t-small)}
:is(.fx-comms,.fx-set) .crow.calcard .tx .cvcx:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-weight:600;font-size:.84rem}
:is(.fx-comms,.fx-set) .calunm{display:flex;flex-direction:column;gap:3px;padding:10px var(--sp-1) 2px}
:is(.fx-comms,.fx-set) .calunm .calunmh{font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:2px}
:is(.fx-comms,.fx-set) .calunm .calunml{font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink)}
:is(.fx-comms,.fx-set) .calunm .calunml:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;line-height:1.4}
:is(.fx-comms,.fx-set) .calunm .calunml i{font-style:normal;color:var(--muted);font-size:var(--fs-label)}

/* b424: NEXT REQUEST on the Booked screen, two lines */
.fx-off [data-off="next"]{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;line-height:1.2;padding-top:var(--sp-2);padding-bottom:var(--sp-2)}
.fx-off [data-off="next"][hidden]{display:none!important}
.fx-off [data-off="next"] .nx-s{font:500 var(--fs-label) 'Space Grotesk',sans-serif;letter-spacing:0;text-transform:none;opacity:.95;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

/* b428: A NEW REQUEST'S DOORS GET THEIR OWN LINE, AND 44px. Measured on a 430 phone while building the weekly series:
   a lead with a phone carries four doors (PRICE IT or BOOK IT $85, SHARE, TEXT THEM, DECLINE or SKIP WEEK) in one
   no-wrap flex row, and they squeezed the request itself into a 30px column, one letter per line, with every door
   25px tall. The request now takes the full width and the doors wrap underneath it, each at least the tap minimum. */
.row.lrow{flex-wrap:wrap}
.row.lrow > .tx{flex:1 1 calc(100% - 40px)}
.row.lrow > .aff{min-height:var(--tap-min);display:inline-flex;align-items:center;justify-content:center;flex:1 1 auto;align-self:auto}

/* b431: THE FIRST-TIME WELCOME ON HER RIDE LINK (Ahmed 2026-09-30, option 1). Roger: "We are not seeing how to set up
   the app". One white card over her dimmed screen, between the header and the footer so the shell stays, large type and
   one big button because it is written for a rider who does not use apps. Her accent is var(--orange), the driver's. */
.frame > .wc-dim{position:absolute;left:0;right:0;top:var(--hd-h);bottom:var(--foot-h);z-index:60;
  background:rgba(10,10,10,.55);display:flex;align-items:center;justify-content:center;padding:var(--sp-3) var(--sp-4);overflow-y:auto}
.frame.fx-entry > .wc-dim{top:0;bottom:0}
.frame > .wc-dim[hidden]{display:none!important}
.wc-card{background:var(--card);color:var(--ink);border-radius:20px;box-shadow:0 10px 30px rgba(0,0,0,.35);padding:var(--sp-5) var(--sp-3) var(--sp-4);
  width:100%;max-width:420px;margin:auto 0;display:flex;flex-direction:column;gap:var(--sp-3)}
/* b444 (Ahmed 2026-10-01: "make this pop-up width-wise a little bit bigger"): the phone's width less a 16px gutter each
   side, up to 420px, and a little less padding inside so each of the three lines holds one line at 412 wide (t270). */
.wc-hello{font:600 var(--t-page)/var(--lh-page) var(--body)}
.wc-hello:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:400 1.5rem/1.15 'Archivo Black','Space Grotesk',sans-serif}
.wc-drv{display:flex;align-items:center;gap:var(--sp-3);border:1.5px solid var(--line);border-radius:var(--r-ctl);padding:10px}
.wc-photo{flex:0 0 auto;width:58px;height:58px;border-radius:50%;background:var(--ink);color:#fff;border:2px solid var(--orange);
  display:flex;align-items:center;justify-content:center;font:600 var(--t-card) 'Space Grotesk',sans-serif;background-size:cover;background-position:center}
.wc-photo:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 1.1rem 'Space Grotesk',sans-serif}
.wc-dtx{display:flex;flex-direction:column;min-width:0}
.wc-dtx b{font:600 var(--t-card)/var(--lh-card) 'Space Grotesk',sans-serif}
.wc-dtx b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 1.2rem/1.2 'Space Grotesk',sans-serif}
.wc-dtx span{font-size:var(--t-body);color:var(--muted)}
.wc-dtx span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.wc-dtx span[hidden]{display:none}
/* b444: the plate on its own row under the car, and the car's picture under the driver row */
.wc-plate{display:flex;align-items:baseline;gap:6px;font-size:var(--t-data);color:var(--muted);font-family:var(--mono)}
.wc-plate:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.9rem}
.wc-plate b{font:700 var(--t-data) var(--mono);letter-spacing:.06em;color:var(--ink)}
.wc-plate b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 1rem 'JetBrains Mono',monospace}
.wc-carpic{display:block;width:100%;height:150px;object-fit:cover;border-radius:var(--r-ctl);background:#F4F4F0}
.wc-carpic[hidden]{display:none!important}
.wc-trip{background:#F4F4F0;border-radius:var(--r-ctl);padding:10px var(--sp-3);font-size:var(--t-body);line-height:var(--lh-body);display:flex;flex-direction:column}
.wc-trip:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.06rem;line-height:1.35}
.wc-trip b{font-weight:700}
.wc-trip span{color:var(--muted);font-size:var(--t-body)}
.wc-trip span:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.wc-does{display:flex;flex-direction:column;gap:var(--sp-2);margin:0;padding:0;list-style:none}
.wc-does li{display:flex;gap:var(--sp-2);align-items:flex-start;font-size:var(--t-body);line-height:var(--lh-body)}
.wc-does li:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.96rem;line-height:1.3}   /* b444: one line each at 412, the longest with ~15px to spare (t270 prints it) */
.wc-n{flex:0 0 auto;width:24px;height:24px;border-radius:50%;background:var(--ink);color:#fff;display:flex;align-items:center;
  justify-content:center;font:700 var(--t-data) var(--mono)}
.wc-n:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 .88rem 'JetBrains Mono',monospace}
.wc-free{display:flex;gap:var(--sp-2);align-items:center;font-size:var(--t-body);font-weight:700;color:var(--good)}
.wc-free:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1rem;font-weight:700}
.wc-ok{display:flex;align-items:center;justify-content:center;width:100%;min-height:60px;border:none;border-radius:var(--r-ctl);
  background:var(--orange);color:#fff;font:600 var(--t-card) 'Space Grotesk',sans-serif;letter-spacing:.04em;cursor:pointer}
.wc-ok:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:700 1.15rem 'Space Grotesk',sans-serif}
.wc-what{display:block;margin:10px auto var(--sp-1);min-height:44px;padding:0 14px;border:none;background:none;color:var(--muted);
  font:400 var(--t-body) 'Space Grotesk',sans-serif;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.wc-what:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:500 .9rem 'Space Grotesk',sans-serif}

/* b489: THE GUEST RIDER (Waqar books and pays, Hammad rides). Her welcome card's quiet "Booked by Waqar" under the
   greeting; the driver's Home card "for Waqar" under the guest's name; TRIP INFO's booked-by line, the guest's own TEXT
   and CALL, and the GUEST RIDER fields. Every button 48px. */
.wc-by{margin-top:-8px;font-size:var(--t-body);color:var(--muted)}
.wc-by:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem}
.wc-by[hidden]{display:none!important}
.fx-id .rc-for{display:block;font-size:var(--t-small);font-weight:700;color:var(--muted);margin:-4px 0 6px}
.fx-id .rc-for:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem;font-weight:600}
.fx-id .rc-for[hidden]{display:none!important}
.fx-ti .ti-for{font-size:var(--t-small);font-weight:700;color:var(--muted)}
.fx-ti .ti-for:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem;font-weight:600}
.fx-ti .ti-for[hidden]{display:none!important}
.fx-ti .ti-gtrow[hidden]{display:none!important}
.fx-ti .ti-gsms{flex:1 1 120px;border:none;background:var(--ink);color:#fff}
.fx-ti .ti-gcall{flex:1 1 120px;border:1.5px solid var(--ink);background:var(--card);color:var(--ink)}
.fx-ti .ti-guested{display:flex;flex-wrap:wrap;gap:var(--sp-2);border:1px solid var(--line);border-radius:var(--r-input);padding:var(--sp-2) 10px 10px}
.fx-ti .ti-guested .ti-k{flex:1 1 100%}
.fx-ti .ti-guested input{flex:1 1 160px;min-width:0;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);
  font:400 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);background:var(--card);box-sizing:border-box}
.fx-ti .ti-guested input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:600 1rem 'Space Grotesk',sans-serif}
.fx-ti .ti-guested input:focus{border-color:var(--ink);outline:none}
.fx-ti .ti-gsave{flex:1 1 100%;cursor:pointer}
/* b553: SHARE WITH, the switch (ink with lime when on) and TEXT THE LINK, both 48px, side by side when they fit */
.fx-ti .ti-shon,.fx-ti .ti-shtxt{flex:1 1 140px;cursor:pointer}



.fx-ti .ti-shtxt[hidden]{display:none!important}
.fx-ti .ti-shsub{flex:1 1 100%;font-size:var(--t-small);font-weight:700;color:var(--muted)}
.fx-ti .ti-shsub:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.84rem;font-weight:600}
.fx-ti .ti-shsub:empty{display:none}
.fx-ti .ti-match{color:var(--ink)}   /* b560: Matched your client <name> */
/* b560: HIM, HER, THEM for the share text, 44px, the pressed one ink */
.fx-ti .ti-pron{display:flex;gap:6px;flex:1 1 160px}
.fx-ti .ti-pron button{flex:1 1 0;cursor:pointer}

/* b560: SHARE RIDE beside TRIP INFO, the Ride sheet title line and the Home card */
.fx-ride .sheet h4 .rschip.rsshare{margin-left:6px}
.card .ti-cardrow{display:flex;gap:var(--sp-2);width:100%}
.card .ti-cardrow > .ti-cardbtn{flex:1 1 0;min-width:0}

/* b439 and b441 bug panel rules: folded into the b607 block above */
/* b482: THE STOPS ON THE RIDE SHEET (bug-muy10nub-nh0lu), between the pickup and the drop-off, the next one in orange */
.rsstops .tx{display:flex;flex-direction:column;gap:var(--sp-2)}
.rsstops .rsst b{font-size:var(--t-body)}
.rsstops .rsst b:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.92rem}
.rsstops .rsst.nx b{color:var(--orange)}
.rsstops .rsst.done{opacity:.55}
/* b482: HOW THEY PAID, THE TIP'S QUICK AMOUNTS AND DONE, ALL GOOD (bug-muy48vd1-k183e), every tap 44px or more */
.clhow,.cltipq{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin:2px 0 10px}
.clhow-c,.cltipq-c{min-width:64px;padding:0 var(--sp-3);cursor:pointer}

.clallgood{display:block;width:100%;margin:var(--sp-3) 0 var(--sp-1);cursor:pointer}
.clallgood-sub{text-align:center}
/* b529: what they paid over the fare, offered as the tip in one tap ("$12 TIP?"), ink on the brand orange, 48px */
.cltipover{display:block;width:100%;min-height:48px;margin:2px 0 10px;border:0;border-radius:var(--r-input);background:var(--orange);color:var(--ink);font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:var(--t-body);letter-spacing:.03em;cursor:pointer}
.cltipover:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-family:'Space Grotesk',sans-serif;font-weight:800;font-size:1rem}
.cltipover[hidden]{display:none}
.tipstep[data-hold]{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;touch-action:manipulation}
/* b529 (bug-mv8bidxc-mv0sr, Lelani's parents: "odometer and battery, it needs to be bigger... the stuff underneath it is
   the same size, it's just too tiny"). The dash numbers on every Journal moment and charging stop: the box, the number,
   the thousands, the label over it and the line under it, all larger. The other boxes keep their size. */
.jr-fld.jr-dash small{font-size:var(--t-small)}
.jr-fld.jr-dash small:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.jr-fld.jr-dash .jr-in{height:60px}
.jr-fld.jr-dash .jr-in input,.jr-fld.jr-dash .jr-pre{font-size:var(--t-card);font-weight:600}
.jr-fld.jr-dash .jr-in input:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.jr-fld.jr-dash .jr-pre:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:1.5rem}
.jr-fld.jr-dash .jr-in u{font-size:var(--t-small)}
.jr-fld.jr-dash .jr-in u:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.8rem}
.jr-fld.jr-dash .jr-fhint{font-size:var(--t-small)}
.jr-fld.jr-dash .jr-fhint:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.86rem}
/* b529: the risen sheet's title is one line, "Drop off Lelani's parents" */
.fx-jrise .jrs-head b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.fx-jrise .jrs-k[hidden],.jr-fld[hidden]{display:none}
/* b529: NEXT RIDE on the HOME sheet, a full width button over the dash boxes */
.jr-nextride .cta{display:block;width:100%;min-height:52px;margin:0}
/* b504: EVERY SMALL LABEL LIME, ON AN INK CHIP WHERE THE CARD IS WHITE (audit round 1 finding 10, Ahmed's standing rule,
   Brand Kit: "Every small label, eyebrow and field name is --lime, never grey"). The driver frames still carried grey
   (#5A5A57) mono eyebrows on white cards: YOUR DRIVER / YOUR VEHICLE / YOUR PASSENGER on Home, the Journal's moment
   labels (1 · LEAVING HOME), RIDES TODAY, CHARGING TODAY, the tile names (MILES DRIVEN, the TODAY SO FAR grid), TRIP INFO's field names (BAGS,
   STOPS, NOTES ON THIS BOOKING), Settings' section labels, the ride sheet's field names (.fx-ml, .fx-k) and the rail's tags. Lime text cannot be read on white, so the
   label wears its own ink chip, lime inside, same mono face and size, hugging its words (fit-content, so a block label
   never becomes a full-width bar). This supersedes the old "grey on white, lime only on dark" line above. Labels already
   on ink (TRIP INFO's .rschip, the dark cards) keep lime text with no chip. Driver frames only, the rider's are untouched.
   STOP (.navx, red) and a lit rail button (.act) keep their state colours. tools/t313 measures it. */
.frame[data-role="driver"] :is(.fx-mono,.mc-lbl,.jr-mo .k,.cx-t small,.jr-tot small,.jr-fld small,.jr-rt small,.brk-tt small,.seclab,.fx-ml,.fx-k,
  .fx-ti .ti-k,.fx-ti .ti-f i,.fx-off-in .lb,.fx-off-man .lb,.bk-lb,.paylab,.rlhead,.ti-pill .tag,.navctl .mbtn:not(.act):not(.navx) .tag,
  .fx-off-when .k,.fx-off-ab .ln .tx .k,.svlab > .svlabt){
  background:#FF3B00;color:#FFFFFF;border-radius:4px;padding:2px 6px;width:fit-content;max-width:100%;box-sizing:border-box}
/* b510 (bug-mv4lewfb-cxwn2, Ahmed 2026-10-11, on the Journal): "instead of black background and green text, make it orange
   background and white text, and then do that wherever you're doing that... that'll stand out." So every b504 chip above is
   Forge Orange #FF3B00 with white #FFFFFF text, and TRIP INFO's .rschip on the Ride sheet matches. Labels that sit on ink
   and were lime before b504 keep their lime. White on #FF3B00 is 3.6:1. tools/t313 measures it. */
.frame[data-role="driver"] :is(.fx-ti .ti-k){display:inline-block}
/* the rail discs are 52px wide: the chip keeps its words inside the disc */
.frame[data-role="driver"] :is(.ti-pill .tag,.navctl .mbtn .tag){padding:1px var(--sp-1);border-radius:3px}
/* CHARGING TODAY carries its stop sum on the same line: white inside the chip */
.frame[data-role="driver"] .jr-lbl{gap:var(--sp-2)}
.frame[data-role="driver"] .jr-lbl .mono{color:#fff}
.frame[data-role="driver"] .jr-lbl .mono:empty{display:none}
/* GUEST RIDER sat on flex-basis 100% to take its own line; the chip hugs its words and an empty full-width item after
   it does the line break instead (order puts the label first, the break second, the -8px eats the empty row's gap) */
.frame[data-role="driver"] .fx-ti .ti-guested .ti-k{flex:0 0 auto;order:-2}
.frame[data-role="driver"] .fx-ti .ti-guested::before{content:'';flex:0 0 100%;height:0;order:-1;margin-top:-8px}

/* ==== b534, MAP BUTTONS (Ahmed 2026-10-20, live on b531) ====================================================================
   1. AT THE TOP, EVERY LAYOUT: "they should always be at the top the way they are here, that's the new rule". The long layout
      (the open fold, sideways) still stood his rail on the footer, a b392/b452 anchor written while the arrival card owned the
      top right. Since b468 the card sits under the turn panel on the left, so the right column is free and his rail hangs from
      the header on every layout, the same as tall. Her rail keeps its b158 slots.
   2. AN OFF BUTTON LEAVES NO GAP: data-railoff (railPaint) is display:none, the rest stack from the top in the same order.
   3. INFO ALONE (no drive) waits in the slot it takes in the rail: --rail-pre discs of --rail-d plus --rail-g each, the same
      disc and gap numbers each tier already uses. */
.navctl > .mbtn[data-railoff], .frame > .ti-pill[data-railoff]{display:none!important}
.frame:not([data-role="passenger"]){--rail-d:52px; --rail-g:10px}
@media (min-aspect-ratio: 6/5){
  .frame:not([data-role="passenger"]) > .navctl{bottom:auto;top:calc(var(--hd-h) + var(--band-gap))}
  .frame:not([data-role="passenger"]){--rail-g:6px}
}
@media (min-aspect-ratio: 6/5) and (max-height: 627px){ .frame:not([data-role="passenger"]){--rail-d:44px; --rail-g:4px} }
@media (min-aspect-ratio: 6/5) and (min-height: 460px) and (max-height: 572px){ .frame:not([data-role="passenger"]){--rail-d:48px; --rail-g:6px} }
.frame:not([data-role="passenger"]) > .ti-pill.ti-pill{bottom:auto;
  top:calc(var(--hd-h) + var(--band-gap) + var(--rail-pre, 1) * (var(--rail-d) + var(--rail-g)))}
/* b695: a Settings row now, opens in place, each line a 48px NAME and a 48px SWITCH */
.fx-set .mbrow .mbx{display:none}
.fx-set .mbrow[data-open="1"] .mbx{display:block;margin:var(--sp-3) 2px var(--sp-1);padding-top:var(--sp-3);border-top:1px solid var(--line)}
.fx-set .mbx > .fx-ml{display:block;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;margin:0 0 10px}
.fx-set .mbl{display:flex;align-items:center;gap:10px;margin:0 0 var(--sp-2)}
.fx-set .mbl .mbuse,.fx-set .mbl .mbname{flex:1 1 auto;min-width:0;min-height:48px;display:flex;align-items:center;padding:0 14px;
  border-radius:var(--r-input);font:700 var(--t-body) 'Space Grotesk',sans-serif;color:var(--ink);text-align:left}
.fx-set .mbl .mbuse:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *),.fx-set .mbl .mbname:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font:800 .95rem 'Space Grotesk',sans-serif}
.fx-set .mbl .mbuse{cursor:pointer}
.fx-set .mbl .mbname{border:1.5px dashed var(--line);background:var(--paper)}
.fx-set .mbl .mbsw{flex:0 0 auto;min-width:104px;display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2);
  padding:0 10px;cursor:pointer}
.fx-set .mbl .mbk{margin:0;font-family:'JetBrains Mono',monospace;font-size:var(--fs-label);font-weight:800;letter-spacing:.08em;text-transform:uppercase}
.fx-set .mbl.mbfix .mbk{flex:0 0 auto;min-width:112px;text-align:center;box-sizing:border-box}
.fx-set .mbl .mbsw{min-width:112px}
.fx-set .mbl .mbsw .mbk{min-width:2.4em;text-align:center;box-sizing:border-box}
.fx-set .mbtog{flex:0 0 auto;width:48px;height:28px;border-radius:var(--r-ctl);position:relative;display:inline-block;transition:background .15s ease}
.fx-set .mbtog i{position:absolute;top:3px;right:3px;width:22px;height:22px;border-radius:50%;background:var(--card);box-shadow:0 1px 3px rgba(10,10,10,.25)}

.fx-set .mbtog.off i{right:auto;left:3px}
.fx-set .mbstat{display:block;font-size:var(--t-body);font-weight:700;text-align:center;margin:var(--sp-1) 2px 6px}
.fx-set .mbstat:where(.frame[data-role="passenger"],.frame[data-role="passenger"] *){font-size:.95rem;font-weight:700}
.fx-set .mbstat[hidden]{display:none!important}
.fx-set .mbstat.goodtx{color:var(--good)}
.fx-set .mbstat.warntx{color:var(--red)}

/* b563: UI AUDIT, CLEAR MISTAKES (YPD-UI-AUDIT-V1A, 2026-10-23). Every control 44px or more, every label legible.
   Measured by the audit harness at 412, 390 and 921 before and after. */
/* #14 Add the car you drive: the whole line taps, 44px tall */
.fx-entry .fx-swalt{display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box;cursor:pointer}
/* #12 Map buttons and Sync from calendar: the row that toggles is 44px tall, on every Menu and Settings row */
:is(.nsq-sheet,.fx-comms,.fx-set) .fx-rowtop{min-height:44px;box-sizing:border-box}
/* the request sheet: Date, Pickup time, Passengers and the EDIT doors tap at 44px, the estimate box is 44px wide */
:is(.fx-off,.fx-pricing) .fx-off-when > [data-act]{min-height:44px;box-sizing:border-box}
:is(.fx-off,.fx-pricing) .fx-leadedit{min-height:44px;min-width:44px;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center}
:is(.fx-off,.fx-pricing) .fx-off-ovr .fx-off-num{min-width:44px}
/* #35 THE KEYBOARD RING, YPD's own (b565, replaces the b564 outline:revert pin). The first Tab shows where you are.
   Every data-act control keeps b563's orange ring. Every other focusable control gets a 2px ring in the app accent
   with a 2px gap, so a rider's chosen colour or a white label driver's colour carries through. !important because
   several inputs say outline:none for the mouse; :focus-visible only fires for the keyboard (and for text fields,
   which is when a ring helps most), so a tap never paints it on a button. */
[data-act]:focus-visible{outline:2px solid var(--orange) !important;outline-offset:2px !important}
:is(a[href],button,input,select,textarea,summary,[tabindex]:not([tabindex="-1"]),[contenteditable]:not([contenteditable="false"])):not([data-act]):focus-visible{
  outline:2px solid var(--accent) !important;outline-offset:2px !important}
/* #34 the Inbox TRY AGAIN door under its no signal line */
.di-retry{margin-top:10px}
/* at 12px the narrow chips keep to one line: PICKUP TIME on the request sheet, 3 · AT DROP-OFF in the Journal */
.frame[data-role="driver"] :is(.fx-off-when .k,.jr-mo .k){letter-spacing:.02em}
/* #23 the sheet back arrow paints in the token colours, not the system grey and black. Its size and place are unchanged. */
.shbar > .shback{border-color:var(--ink);background-color:var(--paper)}

/* ================================================================================================
   b569: ONE BUTTON SYSTEM FOR THE WHOLE DRIVER APP (Ahmed's pick, option 1 of 050-Documents\YPD-BUTTONS-MOCKUP-V1A.html,
   UI audit E2 to E6, E9). Before this the app had 7 corner shapes, 5 heights, 2 kinds of capitals, green used as a
   button and 3 colours for selected. Now there are four looks and one selected state, all read from the tokens:

     PRIMARY   orange fill, white text. Exactly one per screen or sheet, the next thing he taps.
     SECONDARY white fill, 1.5px ink edge, ink text. Every other action.
     QUIET     text with an underline, 44px tall. The way out or the other way.
     DANGER    red edge, red text. Filled red only on the final confirm, Yes, cancel this ride.
     CHOICE    a segmented pick. White with a grey edge, the picked one ink with white text, everywhere.

   Corners 14 on every button and every choice. Heights 56 for the main action, 48 normal, 44 small. Labels in
   capitals, Space Grotesk 700, .08em apart, 13px (15 on 56, 12 on 44). Green is for states only, never an action.

   ONE PLACE WINS. Every rule below is .frame[data-role="driver"] :where(the list):not(#ypd-btn), so every one weighs
   the same, one id and two classes. That beats the per screen rules it replaced without a single !important, and
   inside the block the ORDER decides: shape, then size, then role, then the selected state, then the few exceptions.
   The old colour, corner and font lines on those buttons are deleted.
   Only the driver's frames take it, the passenger's look is untouched. The chat pieces and the Android code door
   are UI Engine's shared pieces; since b570 their masters read the same names (chat-driver.css, app-authcode.js).
   b570: the --btn-* names live in style-driver.css (UI Engine's layer), not here. Same values, same computed look. */
/* ---- every button and choice: shape, type, size ---- */
.frame[data-role="driver"] :where(.cta, .fx-save, .fx-cancel, .fx-danger-btn, .rschip, .ti-cardbtn, .fx-ride .row .aff:not(.warn),
  .fx-pax .row > .aff, .aff.ypdnav, .aff.gmaps, :is(.fx-comms,.fx-set) .crow .aff, .fx-prow .aff.lite[data-act], .ti-trow button, .ti-gsave, .ti-save,
  .ti-shon, .ti-shtxt, .ti-sbtns button, .ti-skind button, .ti-srow button, .ti-chips button, .ti-stg button, .ti-pron button,
  .clpaid-b, .clhow-c, .cltipq-c, .clallgood, .tipstep, .fx-off-step, .fx-off-bseg, .jr-seg > span, .jr-seg > button, .jr-more,
  .jr-fold, .mo-btns button, .rc-never, .mbuse, .mbsw, .paxphotobtn, .ypd-wn-btn, .mp-btn, .fr > button[data-act^="pax-set:"],
  .awline .aw-pill, .phow-c, .phow-btns button, .tdhow, .bk-cta, .bk-seg button, .bk-step button, .fx-leadedit,
  .fx-entry .fx-swalt):not(#ypd-btn){
  box-sizing:border-box;border-radius:var(--btn-r);border-width:var(--btn-edge);border-style:solid;box-shadow:none;
  font-family:var(--body);font-weight:var(--btn-fw);font-size:var(--btn-fs);font-style:normal;line-height:1.15;
  letter-spacing:var(--btn-ls);text-transform:var(--btn-case);min-height:var(--btn-h);height:auto;cursor:pointer}
/* 56, the main action and its row partner */
.frame[data-role="driver"] :where(.cta:not(.sm), .clallgood, .tipstep, .bk-cta, .mp-btn.pri):not(#ypd-btn){
  min-height:var(--btn-h-lg);font-size:var(--btn-fs-lg)}
/* 44, the small ones and every choice */
.frame[data-role="driver"] :where(.rschip, .ti-cardbtn, .fx-ride .row .aff:not(.warn), .fx-pax .row > .aff, .aff.ypdnav, .aff.gmaps,
  :is(.fx-comms,.fx-set) .crow .aff, .fx-prow .aff.lite[data-act], .ti-sbtns button, .ti-srow button, .ti-chips button, .jr-fold, .paxphotobtn,
  .ypd-wn-btn, .mp-btn.sec, .mp-btn.dgr, .awline .aw-pill, .rc-never, .fx-leadedit, .fx-entry .fx-swalt,
  .ti-stg button, .ti-pron button, .ti-skind button, .clpaid-b:not(.clsave), .clhow-c, .cltipq-c, .phow-c, .jr-seg > span,
  .jr-seg > button, .bk-seg button, .fx-off-bseg):not(#ypd-btn){
  min-height:var(--btn-h-sm);font-size:var(--btn-fs-sm)}
/* .ti-shon, .ti-shtxt and the Map buttons switch stay 48, the height of the field or the name beside them */

/* ---- PRIMARY, orange, one per screen ---- */
.frame[data-role="driver"] :where(.cta:not(.ghost, .go, .bad, .k, .dark, .good, .fx-go-off, [data-rs="btn5"]), .fx-ride .fx-btnrow .cta[data-rs="btn"],
  .fx-off-acts2 .cta[data-act="cal-price-save"], .fx-save, .ti-tsms, .clpaid-b.clsave, .bk-cta, .mp-btn.pri):not(#ypd-btn){
  background:var(--accent);color:var(--on-accent);border-color:var(--accent)}
/* ---- SECONDARY, white with an ink edge ---- */
.frame[data-role="driver"] :where(.cta:is(.ghost, .go, .k, .dark, .good, .fx-go-off):not([data-act="cal-price-save"], [data-rs="btn"]),
  .fx-ride .fx-btnrow .cta[data-rs="btn5"], .fx-cancel, .rschip, .ti-cardbtn, .fx-ride .row .aff:not(.warn), .fx-pax .row > .aff,
  .aff.ypdnav, .aff.gmaps, :is(.fx-comms,.fx-set) .crow .aff, .fx-prow .aff.lite[data-act], .ti-tcopy, .ti-gsave, .ti-save, .ti-shtxt,
  .ti-sbtns button, .ti-srow button, .ti-chips button, .clallgood, .tipstep, .fx-off-step, .jr-more, .jr-fold, .mo-btns button,
  .mbuse, .paxphotobtn, .ypd-wn-btn, .mp-btn.sec, .fr > button[data-act^="pax-set:"], .awline .aw-pill, .phow-btns button,
  .tdhow, .bk-step button):not(#ypd-btn){
  background:var(--card);color:var(--ink);border-color:var(--ink)}
/* ---- QUIET, underlined text ---- */
.frame[data-role="driver"] :where(.ti-talt, .rc-never, .fx-leadedit, .fx-entry .fx-swalt):not(#ypd-btn){
  background:transparent;color:var(--ink);border-color:transparent;text-decoration:underline;text-underline-offset:4px;
  text-decoration-thickness:1.5px;padding-inline:var(--sp-2);min-height:var(--btn-h-sm);font-size:var(--btn-fs-sm)}
/* ---- DANGER, a red edge; filled red only on the final confirm ---- */
.frame[data-role="driver"] :where(.cta.bad, .fx-save.nsq-danger, .fx-cancel.tddanger, .mp-btn.dgr):not(#ypd-btn){
  background:var(--card);color:var(--bad);border-color:var(--bad)}
.frame[data-role="driver"] .fx-danger-btn:not(#ypd-btn){background:var(--bad);color:#FFFFFF;border-color:var(--bad)}
/* ---- CHOICE, white with a grey edge ---- */
.frame[data-role="driver"] :where(.ti-stg button, .ti-pron button, .ti-skind button, .ti-shon, .clpaid-b:not(.clsave), .clhow-c,
  .cltipq-c, .phow-c, .jr-seg > span, .jr-seg > button, .bk-seg button, .fx-off-bseg, .mbsw):not(#ypd-btn){
  background:var(--card);color:var(--ink);border-color:var(--btn-choice-edge)}
/* ---- THE ONE SELECTED STATE, ink with white text, on every choice and every choice card ---- */
.frame[data-role="driver"] :where(.ti-stg button, .ti-pron button, .ti-skind button, .ti-shon, .clpaid-b:not(.clsave), .clhow-c,
  .cltipq-c, .phow-c, .jr-seg > span, .jr-seg > button, .bk-seg button, .fx-off-bseg, .mbsw, .fx-off-p, .bk-choice, .cv-chip,
  .vehopt, .fx-off-pick .opt):is(.on, [aria-pressed="true"], [aria-checked="true"]):not(#ypd-btn){
  background:var(--btn-sel-bg);color:var(--btn-sel-fg);border-color:var(--btn-sel-bg)}
.frame[data-role="driver"] :is(.fx-off-p, .bk-choice, .cv-chip, .vehopt, .fx-off-pick .opt):is(.on, [aria-pressed="true"]) :is(.k, .s, span, i, b):not(.pick){
  color:var(--btn-sel-fg)}

/* ---- the segmented rows: separate keys with a gap, no shared frame (the mockup's .seg) ---- */
.frame[data-role="driver"] :is(.jr-seg, .bk-seg, .fx-off-basis){border:0;border-radius:0;background:none;padding:0;overflow:visible;gap:6px}
.frame[data-role="driver"] :is(.jr-seg > span, .jr-seg > button){display:flex;align-items:center;justify-content:center;padding:0 var(--sp-1)}
.frame[data-role="driver"] :where(.bk-seg button + button):not(#ypd-btn){border-left-width:var(--btn-edge)}
/* the close out's PAID NOW / PAYS LATER / SAVE TRIP row keeps its three columns, so the keys stay narrow */
.frame[data-role="driver"] :where(.clpaid3 .clpaid-b):not(#ypd-btn){padding-inline:var(--sp-1)}

/* ---- Map buttons in Menu (audit E9): OFF is a neutral outline, ON is the picked ink. No orange on either ---- */
.frame[data-role="driver"] :where(.fx-set .mbl .mbsw .mbk):not(#ypd-btn){background:none;color:inherit;padding:0;border-radius:0}
.frame[data-role="driver"] :where(.fx-set .mbsw .mbtog):not(#ypd-btn){background:var(--card)}
.frame[data-role="driver"] :where(.fx-set .mbsw .mbtog i):not(#ypd-btn){background:var(--ink)}
.frame[data-role="driver"] :where(.fx-set .mbsw .mbtog.off):not(#ypd-btn){background:var(--line)}
.frame[data-role="driver"] :where(.fx-set .mbsw .mbtog.off i):not(#ypd-btn){background:var(--card)}

/* ---- the Ride sheet's two big keys share the row the way the mockup draws it: 5 MIN AWAY narrow, the next step wide ---- */
.frame[data-role="driver"] :is(.fx-ride .fx-btnrow > .cta[data-rs="btn5"]):not([hidden]){flex:0 0 38%}
/* the steppers: the off screen ones line up with the 48 field beside them. A stepper's label is a glyph, not a word,
   so its minus and plus keep a readable size */
.frame[data-role="driver"] :where(.fx-off-step):not(#ypd-btn):not(#ypd-btn-x){width:var(--btn-h);min-width:var(--btn-h)}
.frame[data-role="driver"] :where(.tipstep, .fx-off-step, .bk-step button):not(#ypd-btn):not(#ypd-btn-x){font-size:var(--t-card);letter-spacing:0}
/* on the open fold the request sheet's rows are paired across its two columns and the pair can be a little taller than
   56; SEND OFFER and BOOK IT sit in the middle of it at their own 56 instead of stretching to 58 */
.frame[data-role="driver"] :is(.fx-off-acts2[data-pair]){align-items:center}
/* the YPD disc on NAVIGATE is white with ink letters; on the white key a hairline ink ring keeps it a disc, the way the G
   keeps its tile on GOOGLE MAPS */
.frame[data-role="driver"] :is(.aff.ypdnav .yicon){box-shadow:0 0 0 1px var(--ink)}

/* ==== b571, THE JOURNAL'S BOXES, ONE SIZE, AND NO RED BOX (Ahmed 2026-10-24 on b570, filling a charging stop) ====================
   1. bug-mvmzlb04-c7puo: "the battery before is a different size versus price per kilowatt. They should match, they should fit
      in one row... it's doing it all over." b529 drew the dash readings (odometer, battery) 60 tall at 24px and left every other
      box 48 at 16px, with a bigger label that wrapped to two lines on his 383 wide phone, so a pair never shared a row. Now every
      box on every Journal form (the moments, the risen sheets, the charging stop, the gas car) is one size: 48 tall, the number
      at 19px, 12px inside, the unit and the label at 12px, the line under it at 13px. A label that still wraps cannot push its
      box down: a field in a pair takes three rows of the form's own grid (label, box, line under it), so both boxes start on
      the same line whatever the words over them.
   2. bug-mvmz0ao1-tai3h: "there's like a new red box that's coming in and it doesn't even fit inside... get rid of that red box".
      b565's keyboard ring (2px, a 2px gap, !important) lands on the INPUT inside the rounded box on every tap, so an orange
      rectangle stood outside the box's own edge. The box already shows where you are (its orange edge), so the input inside it
      draws no ring. The close-out's miles and minutes boxes (.clunit) carried the same ring and lose it too. The two boxes a
      charge in progress still needs lose their red edge as well; a plain line under each says "When you unplug". */
.frame :is(.jr-in,.clunit) input:not([data-act]):focus-visible{outline:none !important}
.frame .jr-fld small{font-size:var(--t-label);letter-spacing:.08em}
.frame .jr-fld .jr-in{height:var(--ctl);padding:0 var(--sp-3);box-sizing:border-box}
.frame .jr-fld .jr-in input,.frame .jr-fld .jr-in .jr-pre{font-size:var(--t-card)}
.frame .jr-fld .jr-in u{font-size:var(--t-label)}
.frame .jr-fld .jr-fhint{font-size:var(--t-small)}
.frame :is(.jr-fields,.cx-fields) > label.jr-fld:not(.jr-fld-wide):not([hidden]){display:grid;grid-row:span 3;grid-template-rows:subgrid;grid-template-columns:minmax(0,1fr);row-gap:0;align-content:start;min-width:0}
.frame :is(.jr-fields,.cx-fields) > label.jr-fld:not(.jr-fld-wide) > small{align-self:end}
.frame :is(.jr-fields,.cx-fields) > label.jr-fld:not(.jr-fld-wide) > .jr-fhint{align-self:start}

/* ==== b573, ONE TEXT SIZE SCALE (Ahmed 2026-10-25, option 1 of YPD-TEXT-SCALE-MOCKUP-V1A) ================================
   Every size in this file is now one of the shared token roles in tokens.css, picked by what the words MEAN: page title 24,
   card or sheet title 19 (Space Grotesk 600), body 15, small 13 for addresses and sub lines, label 12 caps (the orange chip),
   number 12, data 14 mono for flights, fares and times, big money 34 in Archivo Black (with the fare pill, the only Archivo).
   The audit counted 29 sizes showing in the driver's frames; the role set is 9. Left raw on purpose: the turn by turn banner
   (its sizes scale from --nav-road and were measured against clipping), the map rail's compass letter, the bug reporter's
   FIXED, PLEASE TEST panel and the ladybug's own words (shared pieces), and .cta's --act-fs, which the passenger still reads.
   1. The frame's own size is body. Text with no size of its own took the browser's 16px (the Maps cost meter's names, the
      share link sheet's line), so it now inherits body like everything else. The landing's name line and logo take the page
      size (they were 27 and 22 to 27). Driver frames only, so her landing keeps its own. */
.frame[data-role="driver"]{font-size:var(--t-body);--title-fs:var(--t-page);--logo-fs:var(--t-page)}
/* 2. the share link sheet's SEND TO line is a label and its link the mono label line, as on every other sheet */
.frame[data-role="driver"] .fx-pl .fx-ml{font-size:var(--t-label)}
.frame[data-role="driver"] .fx-pl .linkrow{font-size:var(--t-label)}
/* 3. the Inbox's empty and loading line: since b574 app-paxchat.js sets it for the driver's frame itself */
/* 4. THE PASSENGER'S SIDE DOES NOT MOVE. Every rule this pass changed is followed by the same selector with a zero
   specificity :where(.frame[data-role="passenger"], ... *) carrying the rule's ORIGINAL font lines, so inside her frame
   the cascade is exactly b572's (measured: the rider and track screens, before and after, no size moved). UI Engine and
   the passenger side can move her frames to the scale later by deleting those lines.
   5. the mockup's first clash: on the Ride sheet the place name read smaller than the flight under it. The pickup and the
   drop-off names are card titles now (19, 600), their address lines small (13), the flight data (14 mono). The other rows
   of the sheet keep body at 15 bold, the passenger's row among them. */
.frame[data-role="driver"] .row:is([data-rrow="pickup"],[data-rrow="dropoff"]) > .tx > b{font-size:var(--t-card);font-weight:600;line-height:var(--lh-card)}
/* 6. the third clash, Home's passenger card: the name is a card title (19), HEAD OUT and its time are data (14 mono) */
.frame[data-role="driver"] .fx-id .ho-home{font-size:var(--t-data)}
/* 7. a status chip inside a row's title (BOOKED in My rides) is a label, 12; .row .tx span (a sub line, small 13) caught it */
.frame[data-role="driver"] .row .tx .badge{font-size:var(--t-label)}

/* ==== b574: THE LAST DRIVER TEXTS ONTO THE SCALE (finishing b573 with UI Engine's masters). b573 left the ladybug's footer
   timer, REPORT A BUG under Go Online and the bug panel alone as shared pieces; they are app.css rules, so they move here.
   Driver frames only, the passenger's footer timer and her bug panel keep their sizes. The timer is a count (12, 800);
   REPORT A BUG is body (15); the panel's title is a card title (19, Space Grotesk 600) in its lime chip, its buttons
   control (14, the b569 look kept: same corner, edge, weight and fill), its fix lines body, its counts page and card,
   the came back line a label, the error line small. */
.frame[data-role="driver"] .foot .tab.lbug .lbtimer{font-size:var(--t-num);font-weight:var(--w-num)}
.frame[data-role="driver"] .lb-ownbtn{font-size:var(--t-body)}
/* b607: the bug panel's b574 sizes (title 19, buttons 14, counts 24 and 19) are gone, the b607 block carries the panel's whole
   look from the tokens: the title is the 12px label chip like every other label on Home, the buttons the b569 sizes (13, 12 on
   the small ones), the counts the number type. Nothing here any more, so that block is the one place that paints it. */

/* ==================================================================================================
   b578, THE DRIVING SCREEN, OPTION 1, THE GLANCE HIERARCHY (Ahmed 2026-10-25, picked off
   050-Documents/YPD-DRIVING-SCREEN-MOCKUP-V1A.html: "the glance hierarchy (44 distance, 24 road, 14 ETA, dark green
   panel). Build it in the app."). The mockup's .o1 CSS and its size table are the spec; these are its values.

   Distance first, the arrow second, the road third, everything else smaller but never under 13. The sizes are the size
   at 412 and do not scale with the panel any more (navWideFit sets the width only); navFit steps the distance (to 76%)
   and the road (to 87%) down where a narrower panel needs it, the b530 way.

   DRIVER ONLY: every rule is scoped to [data-nv="panel"] / [data-nv="card"] / the driver rail, so the passenger's panel
   (data-pv, the same classes) is untouched. A docked panel keeps the b67 tab: display rules carry :not(.dock).

   DARK GREEN WITH WHITE TYPE, NOT A WHITE PANEL. The mockup measured the green at 6.9 to 1 against a light map, white type
   on it 8.1 to 1 over a light map and 10.0 to 1 over a dark one; b75's 85% green with pale road text was 4.9 to 1. The
   transparency stays the design language (b78), it is only a little less see-through.
   ================================================================================================== */
[data-nv="panel"]{--navtop:rgba(15,76,64,.92); --navrow2:rgba(10,58,49,.94)}
[data-nv="panel"] .nbtop{background:var(--navtop);padding:12px 34px 12px 14px}
/* the arrow and the distance on the first line, the road under both on its own line, the panel's full width */
[data-nv="panel"]:not(.dock) .nbtop{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:12px;row-gap:6px;align-items:center}
[data-nv="panel"] .nbtop .mn{width:48px;height:48px}
[data-nv="panel"] .nbtop .mn svg{width:48px;height:48px;stroke-width:3.6}
[data-nv="panel"] .nbtop .nbtx{display:contents}
[data-nv="panel"] .nbtx .dist{min-width:0;font-size:var(--t-glance);line-height:1;letter-spacing:-.01em}
/* the unit at 24 against 44, an em so navFit's steps take it down with the number */
[data-nv="panel"] .nbtx .dist u{text-decoration:none;font-size:.54545em}
/* the road: white, 24 / 600, two lines at most (b70's clamp), the road only, never "Turn right onto" (2026-08-11) */
[data-nv="panel"] .nbtx .road{grid-column:1 / -1;min-width:0;color:#fff;font-size:var(--t-page);font-weight:600;line-height:1.2}
/* the rows under the turn: then next (it ships off, NAV_NEXT_ON) and the address (b554), in that order, the darker green */
[data-nv="panel"] > .nbnext{order:1}
[data-nv="panel"] > .nbdest{order:2}
[data-nv="panel"] > .nbprog{order:3}
[data-nv="panel"] > .nbeta{order:4}
[data-nv="panel"] :is(.nbnext,.nbdest){background:var(--navrow2);border-top:1px solid rgba(255,255,255,.16);gap:var(--sp-2);line-height:1.25}
[data-nv="panel"] .nbnext{padding:var(--sp-2) 14px;font-size:var(--t-body);font-weight:700;color:#E4F2EC}
[data-nv="panel"] .nbdest{padding:var(--sp-2) 34px var(--sp-2) 14px;color:#fff}
[data-nv="panel"] :is(.nbnext .mn2,.nbdest .mn3),
[data-nv="panel"] :is(.nbnext .mn2,.nbdest .mn3) svg{width:18px;height:18px;stroke-width:2.4}
[data-nv="panel"] .nbdest .mn3{margin-top:0}
/* the address, the street 15 / 700 then the city 13 / 500, still two lines at most */
[data-nv="panel"] .nbdest .desttx{font-size:var(--t-body);font-weight:700;line-height:1.25}
[data-nv="panel"] .nbdest .dcity{font-size:var(--t-small);font-weight:500;color:#CFE6DE}
/* b631 (bug-mvs3baih-wa1nc, Ahmed 2026-10-28 5:28 AM on b629): THE CITY ON ITS OWN LINE. "I like the address 9462 Brewer
   Way, then Villa Park should go in the next row. That way it's nice and clean, easier to read." navDestPaint puts a line
   break between the street and the city, and here each of the two lines is one line: a street too long for its line ends
   in an ellipsis rather than pushing the city to a third, so the row is still b554's two lines at most. The city keeps the
   b578 smaller lighter type. Both legs, and the airport leg the same way: the airport, then its kerb (b583's .dterm is a
   .dcity too). A line with no city stays b554's two line clamp. */
[data-nv="panel"] .nbdest .desttx:has(> .dcity){display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* b664 (bug-mvtq6jqh-l6093, Ahmed 2026-10-29, the Fold in landscape: "it needs to be one line... get rid of this icon... make it
   a little bit longer if you need to. The height, we can leave it alone"). The pin is gone from the markup, and the street is
   ONE line with or without a city: navDestFit (app.html) steps its type down to 12px, then a wide window's card grows (to
   min(320px, 40%), --nvd-w on the row), and only then this ellipsis. A cell of the ETA strip that would cut "12:45 pm" makes
   the strip's cells content sized (data-etafit), so the time takes the room the minutes do not need. */
[data-nv="panel"] .nbdest .desttx{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
[data-nv="panel"][data-etafit] .nbeta span,
[data-nv="panel"][data-etafit] .nbeta span:first-child{flex:1 1 auto}
@media (min-aspect-ratio: 6/5){
  .frame[data-role="driver"] > .navrow[data-dfit] > .nvpanel:not(.dock){width:var(--nvd-w,var(--nav-w))}
}
/* b665 (Ahmed 2026-10-29, "splitnav: B", the B Compact mock). ANDROID SPLIT SCREEN, THE COMPACT CARD. app.html's
   navCompactSync sets data-nvc on the panel while the window matches NAV_COMPACT_Q (a tall pane no taller than 700, or one
   under 360 wide). The same card, smaller: never past 60% of the window, the arrow 30, the distance 28 (navFit steps it from
   there), the road 15 on ONE line (navFit steps it, then this ellipsis), the address 13 and its city 11 (navDestFit fits the
   street from 13 to its 12 floor), the ETA 12 in tighter cells. Full screen never carries the attribute, so nothing here
   touches it. */
.frame[data-role="driver"] > .navrow > .nvpanel[data-nvc]:not(.dock){max-width:60vw}
[data-nv="panel"][data-nvc]:not(.dock) .nbtop{padding:8px 30px 8px 10px;column-gap:8px;row-gap:3px}
[data-nv="panel"][data-nvc] .nbtop .mn,
[data-nv="panel"][data-nvc] .nbtop .mn svg{width:30px;height:30px}
[data-nv="panel"][data-nvc] .nbtx .dist{font-size:28px}
[data-nv="panel"][data-nvc] .nbtx .road{font-size:15px;line-height:18px;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-line-clamp:unset}   /* b694: the line is held, navFit's steps never move the card */
[data-nv="panel"][data-nvc] .nbdest{padding:5px 30px 5px 10px}
[data-nv="panel"][data-nvc] .nbdest .desttx{font-size:13px}
[data-nv="panel"][data-nvc] .nbdest .dcity{font-size:11px}
[data-nv="panel"][data-nvc] .nbeta span{padding:6px 2px}
[data-nv="panel"][data-nvc] .nbeta i{font-size:12px}
/* b631 (bug-mvs4ucvi-oi6qj, Ahmed 2026-10-28 6:10 AM, parked at the pickup: "the address should be up here, then the street and
   then the city... we don't need it twice"). AT THE END OF THE LEG (navEndPaint sets data-atend) the turn's place holds the
   address, the street at the road's 24 / 700 on line one, two lines at most, the city 15 / 500 soft green on line two, one
   line. The arrow and the empty turn step out, and so does the address row under it, so the address is said once. */
[data-nv="panel"][data-atend] .nbtop :is(.mn, .nbtx){display:none}
[data-nv="panel"][data-atend] > .nbdest{display:none}
[data-nv="panel"] .nbtop [data-nv="endadr"]{grid-column:1 / -1;min-width:0;color:#fff}
[data-nv="panel"] .nbtop [data-nv="endadr"][hidden]{display:none!important}
[data-nv="panel"] .nbtop [data-nv="endadr"] br{display:none}   /* the street and the city are blocks up here */
[data-nv="panel"] .nbtop [data-nv="endadr"] .dst{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  overflow-wrap:break-word;font-size:var(--t-page);font-weight:700;line-height:1.2}
[data-nv="panel"] .nbtop [data-nv="endadr"] .dcity{display:block;margin-top:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:var(--t-body);font-weight:500;line-height:1.25;color:#CFE6DE}
[data-nv="panel"] .nbtop [data-nv="endadr"] .dterm{font-weight:700;color:#fff}
/* THE ETA STRIP IN THE DATA FACE. b75's 9px Archivo Black was the smallest type on the whole driving screen; now
   JetBrains Mono 14, the arrival time in ink 800 behind the driver's accent dot, the minutes and the miles 600 grey.
   The arrival cell keeps the wider share (b81), 1.25 now. */
[data-nv="panel"] .nbeta span{padding:10px var(--sp-1)}
[data-nv="panel"] .nbeta span:first-child{flex:1.25 1 0}
[data-nv="panel"] .nbeta i{font-family:'JetBrains Mono',Consolas,monospace;font-size:var(--t-data);font-weight:600;line-height:1.2;
  letter-spacing:0;color:var(--muted)}
[data-nv="panel"] .nbeta span:first-child i{font-weight:800;color:var(--ink)}
/* b670: NO DOT BEFORE THE ARRIVAL TIME (Ahmed 2026-10-29, bug-mvttqhpv-fiz7w: "There's a dot next to it, orange. We don't
   need that... it's not important"). The accent dot's rule is gone, on every panel shape (full, compact, docked), so the
   time has its 14px back and navDestFit measures the bare value. */
/* THE RULE: when the arrival card is up, the then next row and the address row step out of the panel, because the card
   carries the address now. That is what keeps the arrival stack clear of the car. A docked card gives them back. */
[data-nv="row"]:has(> [data-nv="card"]:not([hidden]):not(.dock)) [data-nv="panel"] :is(.nbnext,.nbdest){display:none}
/* the rail's stage words, OVERVIEW and UP, 13 while navigating (the rail only exists while navigating) */
.navctl[data-nv="ctl"] .mbtn .tag:is([data-nv="rclab"],[data-nv="cmptag"]){font-size:var(--t-small)}
/* the chip holds its whole word: the b504 chip's max-width:100% capped OVERVIEW at the 52px disc and the word ran out of
   its chip and off the screen at 412 (seen on the b577 screenshot too, at 12). About 80px at 13, so it ends at the disc's
   right edge (the mockup's tag sits on the disc's right) and grows to the left, on screen at every width. */
.frame[data-role="driver"] .navctl[data-nv="ctl"] .mbtn .tag[data-nv="rclab"]{max-width:none;left:auto;right:0;transform:none}

/* THE ARRIVAL CARD: the house number 34 Archivo and the street 19 / 700 on one line, the city 13 / 500 under them, then
   GATE CODE 13 / 800 and the code 24 Archivo in the driver's accent on one line. A name with no house number (an
   airport, a place) is the whole line at 24, so "Ontario International Airport" never stacks three lines of 34. */
[data-nv="card"]:not(.dock) .adrln{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;column-gap:var(--sp-2);
  padding:9px 26px 0}
[data-nv="card"] .adrln .adr{padding:0;font-size:var(--t-big);line-height:1.05;letter-spacing:-.01em;min-width:0;overflow-wrap:break-word}
[data-nv="card"] .adrln:not([data-num]) .adr{font-size:var(--t-page);line-height:1.2}   /* 1.2: Archivo's ink fits its line box, so b519's overflow test does not cut a name that fits */
[data-nv="card"] .adrln .adrst{padding:0;font-size:var(--t-card);font-weight:700;line-height:1.2;letter-spacing:0;min-width:0}
[data-nv="card"] .adrcity{padding:0 26px 7px;font-size:var(--t-small);font-weight:500;line-height:1.3;color:var(--muted)}
[data-nv="card"] .adrcity[hidden]{display:none!important}   /* an explicit display ALWAYS beats [hidden] (2026-07-31) */
[data-nv="card"] .adrln:has(+ .adrcity[hidden]){padding-bottom:7px}   /* no city: the line keeps the city's breathing room */
.dock .adrln, .dock .adrcity{display:none}
[data-nv="card"]:not(.dock) .gcode:not([hidden]){display:flex;flex-wrap:wrap;align-items:center;justify-content:center;column-gap:10px;
  padding:6px 26px 7px}
[data-nv="card"] .gcode .glab{display:inline;font-size:var(--t-small);font-weight:800;line-height:1.2;letter-spacing:.04em;color:var(--ink)}
[data-nv="card"] .gcode .gval{display:inline;font-size:var(--t-page);line-height:1.08}
[data-nv="card"] .gcode .gat{flex-basis:100%;font-size:var(--t-small)}

/* ==================================================================================================
   b581, THE RAIL, THE RISEN JOURNAL GRID AND THE ROAD BESIDE THE ARROW (Ahmed 2026-10-26, on b578, driving)
   1. bug-mvpaktf3-oofr5: "the 17 and the 3 are competing, fighting for the same spot... maybe the 17 goes on the left and
      the 3 goes on the right and they're the same size". The stage word (OVERVIEW, 14, 17) and the stage number sat on
      the same corner. Now they are one row over the recenter disc, the word on the left, the number on the right, both
      20 tall, 13px, white on orange with the same white ring, and they never touch (2px apart).
   2. Same report: "the three icons... too close together vertically, they need a little bit more spacing". The rail's
      gap is one number, --rail-g, now on the rail itself too: 16 tall, 14 long, 10 on the shorter long tiers (6 under 460).
   3. "the info should just be the letter I... North just make it the letter N". INFO is a big I, the compass a big N (A
      for the overview), no chip under either; in heading up the N turns so it always points at north.
   4. "the recenter, make the circle and the four lines a little bit bigger": the glyph is about half the disc (27 in 52),
      stroke 2.4.
   5. bug-mvpai59e-ttd5c: "this menu is off, it's not lined up" (Leaving home risen over Ride, his long phone). In the
      four column layout CAR took two columns of the first row and LEFT AT and ODOMETER shared its rows, so their labels
      sank and BATTERY and TEMP started a row lower under CAR. The first field after a wide one now starts its own row, so
      the four boxes sit on one row, one label line, one box line, every left edge on the grid.
   6. bug-mvpaua2q-699d7: "I want the arrow to be right here, and then where it says California 71, I want that to be a
      little to the side and aligned with the 2 miles on top". The road sits in the distance's column, under it, left
      edges equal; the arrow keeps its own column.
   ================================================================================================== */
.frame:not([data-role="passenger"]){--rail-g:16px}
@media (min-aspect-ratio: 6/5){ .frame:not([data-role="passenger"]){--rail-g:14px} }
@media (min-aspect-ratio: 6/5) and (max-height: 627px){ .frame:not([data-role="passenger"]){--rail-g:10px} }
@media (min-aspect-ratio: 6/5) and (max-height: 459px){ .frame:not([data-role="passenger"]){--rail-g:4px} }
.frame:not([data-role="passenger"]) > .navctl.navctl.navctl{gap:var(--rail-g)}
.frame:not([data-role="passenger"]) > .navctl > .mbtn[data-nv="rc"] svg{width:calc(var(--rail-d) * .52);height:calc(var(--rail-d) * .52);stroke-width:2.4}
/* b595 (Ahmed 2026-10-26 15:18, bug-mvptiif1-zc39a, on b591): THREE DISCS, ONE ANATOMY. "We don't need the A... instead of
   the N, it'll be north, and a little arrow on top of it... I liked it when you had an orange button there that said
   info... where it says overview, it'll come across in the middle, so all three icons are the same." The rail is NORTH,
   OVERVIEW, INFO, top down. Every disc is the same white disc (--rail-d) with a glyph in it (the compass arrow, the
   recenter cross, the i) and its name in ONE orange chip, white caps, the b581 chip, centred on the disc's bottom edge:
   NORTH, the stage word (OVERVIEW, 14, 17), INFO. The stage number keeps the top right corner of OVERVIEW (b284's ring
   and b292's taps read it). NORTH filled orange is north up, the arrow straight up; white is heading up, the arrow turned
   to point at north on the screen. The big letters (b581's I and N, A) are gone with their rules. The chip hangs 8px
   under the disc, so the gap between discs is never under 10px (the 4px tier is 10 now). */
.frame[data-role="driver"] .navctl[data-nv="ctl"] .mbtn .pip,
.frame:not([data-role="passenger"]) :is(.navctl[data-nv="ctl"] .mbtn, .ti-pill) .tag.rtag,
.frame[data-role="driver"] .navctl[data-nv="ctl"] .mbtn[data-nv="rc"] .tag[data-nv="rclab"]{position:absolute;
  height:20px;min-width:20px;box-sizing:border-box;padding:0 5px;border:2px solid #fff;border-radius:10px;
  background:var(--orange);color:#fff;font:800 var(--t-small)/16px 'JetBrains Mono',Consolas,monospace;letter-spacing:0;
  display:flex;align-items:center;justify-content:center;white-space:nowrap;box-shadow:0 1px 3px rgba(10,10,10,.3);max-width:none;width:auto}
.frame:not([data-role="passenger"]) :is(.navctl[data-nv="ctl"] .mbtn, .ti-pill) .tag.rtag,
.frame[data-role="driver"] .navctl[data-nv="ctl"] .mbtn[data-nv="rc"] .tag[data-nv="rclab"]{left:50%;right:auto;top:auto;bottom:-8px;transform:translateX(-50%);z-index:1}
.frame[data-role="driver"] .navctl[data-nv="ctl"] .mbtn .pip{top:-6px;right:-6px;left:auto;bottom:auto;transform:none}
.frame:not([data-role="passenger"]) .ti-pill .ti-new{top:-6px;right:-6px}
/* the glyphs, the same share of the disc as the recenter cross (b581, .52), so the three read as one set */
.frame:not([data-role="passenger"]) > .navctl > .mbtn.cmpbtn svg.cmp-up,
.frame:not([data-role="passenger"]) .ti-pill svg.ti-i{width:calc(var(--rail-d) * .5);height:calc(var(--rail-d) * .5);display:block}
.frame:not([data-role="passenger"]) > .navctl > .mbtn.cmpbtn svg.cmp-up{stroke-width:2.6;transform-origin:50% 50%}
.frame:not([data-role="passenger"]) .ti-pill svg.ti-i{stroke-width:3.2}
.frame:not([data-role="passenger"]) .ti-pill svg.ti-i circle{fill:var(--ink);stroke:none}
.frame:not([data-role="passenger"]) .ti-pill.act svg.ti-i circle{fill:#fff}
/* the glyph sits a little high in the disc so the chip on the bottom edge does not crowd it */
.frame:not([data-role="passenger"]) :is(.navctl[data-nv="ctl"] > .mbtn, .ti-pill):has(> .tag.rtag) > svg,
.frame:not([data-role="passenger"]) .navctl[data-nv="ctl"] > .mbtn[data-nv="rc"] > svg{margin-top:-6px}
/* NORTH is the first disc, over OVERVIEW; INFO keeps the end (order 99) */
.navctl > .mbtn.cmpbtn{order:-1}
/* ON is the filled disc, the rail's own law (sound, SAFE): the arrow goes white, the chip keeps its ring */
.navctl .mbtn.cmpbtn.act svg.cmp-up{stroke:#fff}
/* b631 (bug-mvs3cgah-uaom4, Ahmed 2026-10-28 5:28 AM on b629): THE RAIL SPANS THE PANEL. "The north one aligns with the top,
   and the info one aligns with the bottom... And then the recenter will automatically be in the middle." navRailFit
   (app.html) MEASURES the panel and writes the rail's top and height, then sets data-railfit; space-between does the rest,
   so NORTH's top is the green's top edge, INFO's bottom the ETA strip's bottom edge, recenter between them. The gap stays
   the minimum. No measurement (wide screens, no panel): no attribute, the rail is exactly as before. */
.frame[data-role="driver"] > .navctl[data-nv="ctl"][data-railfit]{justify-content:space-between;box-sizing:border-box}
/* b631 (bug-mvs4wnui-axfz0): MOVE FLAG, one pill over the map under the panel, centred, his 44 tap target; orange when it moves
   the flag, ink when it only says why not */
.frame[data-role="driver"] > [data-nv="flagmove"]{position:absolute;left:50%;top:52%;transform:translateX(-50%);z-index:5;
  min-height:44px;padding:0 var(--sp-4, 20px);border:2px solid #fff;font:800 var(--t-body)/1 'JetBrains Mono',Consolas,monospace;
  letter-spacing:.04em;white-space:nowrap;box-shadow:0 3px 10px rgba(10,10,10,.3);cursor:pointer}
.frame[data-role="driver"] > [data-nv="flagmove"][data-mode="move"]{background:var(--orange);color:#fff}
.frame[data-role="driver"] > [data-nv="flagmove"][hidden]{display:none!important}
/* a panel shorter than the rail (the "--" before the route answers): navRailFit writes --rf-d, the discs give a little,
   44 at the least, his tap target */
.frame[data-role="driver"] > .navctl[data-nv="ctl"][data-railfit="tight"] > :is(.mbtn, .ti-pill){width:var(--rf-d);height:var(--rf-d);
  min-width:var(--rf-d);min-height:var(--rf-d)}
@media (min-aspect-ratio: 6/5) and (max-height: 459px){ .frame:not([data-role="passenger"]){--rail-g:10px} }
@media (min-aspect-ratio: 6/5){
  .fx-jrise .jr-fields > div.jr-fld-wide + label.jr-fld:not([hidden]){grid-column-start:1}
}
/* b595: nothing rides over the top disc any more (the chips hang under their discs), so the nav band keeps its own top in
   the tall layout too; b581's 12px step is retired. */
[data-nv="panel"]:not(.dock) .nbtop .mn{grid-row:1;align-self:center}
/* b694 (bug-mvvdfstt-i98la, "N Victoria" cut off at 829x612): the road takes the whole card width, under the arrow as well as
   under the distance. The row was already there, only the arrow's column stood empty. navFit keeps it on one line. */
[data-nv="panel"] .nbtx .road{grid-column:1 / -1}

/* ==================================================================================================
   b582, THE ARRIVAL CARD RETIRED, THE ARRIVED SHEET AT THE FLIGHT, THE RIDE TITLE CENTRED (Ahmed 2026-10-26, on b578)
   1. bug-mvpd5bed-83ftn: the white arrival card is off the driving screen (NAV_CARD_RETIRED in app.html). The panel keeps
      its address row the whole leg, and the two rows only the card had now sit in the panel, the same dark green rows:
      the stop line over the address, and GATE CODE under it inside b370's mile (data-near), the row still the gate save.
   2. bug-mvpd8m3h-8n0il: "there's some artifact left right here, I don't need that", circled on the top right corner of
      the Ride sheet where the sheet's scroll bar was drawn. The driver's sheets still scroll by hand, no bar is drawn.
   3. Same report: "this, I think it should be centered right over here, and then START THE RIDE". The Ride sheet's title
      and the rider's chip sit in the middle of the bar, over the button; the X keeps its corner. The other sheets keep
      b568's bar as it was.
   ================================================================================================== */
[data-nv="panel"] > .nvstop, [data-nv="panel"] > .gcode{order:2;background:var(--navrow2);border-top:1px solid rgba(255,255,255,.16);
  padding:var(--sp-2) 34px var(--sp-2) 14px;color:#fff}
[data-nv="panel"] > .nvstop{font-size:var(--t-body);font-weight:800;line-height:1.25}
[data-nv="panel"] > .nvstop[hidden]{display:none!important}
[data-nv="panel"]:not(.dock) > .gcode:not([hidden]){display:flex;flex-wrap:wrap;align-items:center;column-gap:10px;row-gap:2px;
  min-height:var(--tap);box-sizing:border-box;cursor:pointer}
[data-nv="panel"]:not([data-near]) > .gcode, [data-nv="panel"] > .gcode[hidden]{display:none!important}
[data-nv="panel"] > .gcode .glab{font:800 var(--t-small)/1.2 var(--body);letter-spacing:.04em;color:var(--lime)}
[data-nv="panel"] > .gcode .gval{font-family:'Archivo Black','Arial Black',sans-serif;font-size:var(--t-page);line-height:1.08;color:#fff}
[data-nv="panel"] > .gcode .gat{flex-basis:100%;font:800 var(--t-small)/1.2 var(--body);letter-spacing:.04em;color:var(--lime)}
[data-nv="panel"] > .gcode .gat[hidden]{display:none!important}
.dock > .nvstop{display:none!important}
.frame[data-role="driver"] > .sheet{scrollbar-width:none}
.frame[data-role="driver"] > .sheet::-webkit-scrollbar{display:none;width:0;height:0}
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl > .stt{justify-content:center}
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl:has(> .shback[hidden]) > .stt{padding-left:calc(var(--tap) + 6px)}

/* ==================================================================================================
   b583, THE RIDE SHEET ON THE OPEN FOLD (Ahmed 2026-10-26, bug-mvpdpic0-70psd, on b578, Sultana's SNA drop-off, his fold open
   and sideways, 921 x 680)
   1. "With the phone open both sides and horizontal, these three could be in one row. Like this one down here from SNA doesn't
      need to be on its own. One in the middle, one on the right." The flight line's facts (AIRLINE, FLIGHT, FROM, and DEPARTS
      when the feed has it) sit in one row across the sheet from 800 wide. The tall layout keeps its two columns. The Flight
      on file card's four facts do the same.
   2. "We don't need this here anymore, TEXT SULTANA yourself, because we do that from the Info." The row is off the driver's
      Ride sheet; texting her lives in TRIP INFO, and pressing and holding a status button still copies the text.
   3. b582 drew GATE CODE (and AT THE GATE) in lime on the green panel. YPD labels are the orange chip with white text (b510).
   The fare left the Booked badge in app.html ("it's down here, just right here is fine"); the travel card's places sit on
   one line each in travel-host.js.
   ================================================================================================== */
@media (min-width:800px){
  .fx-ride[data-role="driver"] > .sheet > .flmore{grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}
  .fx-ride[data-role="driver"] .flokgrid{grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}
}
.frame[data-role="driver"] [data-rrow="textpax"]{display:none!important}
[data-nv="panel"] > .gcode .glab, [data-nv="panel"] > .gcode .gat{background:#FF3B00;color:#FFFFFF;border-radius:4px;padding:2px 6px;
  width:fit-content;max-width:100%;box-sizing:border-box}
/* AT THE GATE keeps its own line under the code, as a chip that hugs its words: an empty full-width item breaks the line */
[data-nv="panel"] > .gcode .gat{flex:0 0 auto;order:2}
[data-nv="panel"] > .gcode:has(> .gat:not([hidden]))::after{content:'';flex:0 0 100%;height:0;order:1}
/* 4. "I don't think I got a notification to leave at 7:15... we need to check that I never got that notification." Once the
      head-out time has passed, the row says what happened (app-headout.js outcome): sent at what minute, or why none went
      out, so he can see it on the sheet instead of wondering. Ink, the row's body size, under the rule line. */
.fx-ride .row .tx .ho-out{margin-top:3px;font-weight:700;color:var(--ink)}
.fx-ride .row .tx .ho-out[hidden]{display:none!important}
/* 5. bug-mvpfim25-bv27z: "it should tell me what terminal I'm going to". An airport leg's line under the turn is the airport
      and its kerb (navDestAir in app.html), the kerb as strong as the name, white, not the city's soft green. */
[data-nv="panel"] .nbdest .dterm{font-weight:700;color:#fff}

/* ==================================================================================================
   b600, THE DOORS BESIDE THE NAME, THE ANSWERS IN ORANGE, THE MONEY IN GREEN (Ahmed 2026-10-26, bug-mvpujpia-puggj, on b591,
   the Ride screen before Yasmeen's LAX ride)
   1. "Right here where it says TRIP INFO and SHARE, let's put those buttons right next to her name. That frees up this whole
      thing. I don't need to read Booked, I already know they're booked." TRIP INFO and SHARE are title bar pieces now
      (data-stchip in app.html, sheetTitleBuild moves them into the bar beside her name), the b569 small button, 44 tall,
      white with the ink edge, pushed to the right of her line. The Booked badge and the row it sat on are gone from the sheet.
      The bar's words sit left, with the doors, so the title is no longer centred on this one sheet.
   2. "The answers should stand out, they should be with the orange background: terminal 3, passenger, the drop-off, the time."
      .fact-hot, one rule: the orange chip with white text, hugging its words, on the pickup line, the drop-off line, the time
      and the passenger's name. The small labels stay lime (b510). "Heading out is not that important so it can stay white.
      You're driving this, hand off, that doesn't need it." Those rows carry no class and are untouched.
   3. "The money could be green, because that's how money would be." .fact-good on the fare line, --good, the PAID green.
   ================================================================================================== */
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl > .stt{justify-content:flex-start;gap:6px}
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl:has(> .shback[hidden]) > .stt{padding-left:0}
/* the pair is one title bar piece (data-stchip), so a long name moves both doors to the next line together, still on the right */
.fx-ride[data-role="driver"] .sttl .stchip.rsdoors{display:inline-flex;gap:6px;margin-left:auto;background:transparent;color:inherit;
  padding:0;overflow:visible;text-overflow:clip;max-width:100%;flex:0 0 auto}
.fx-ride[data-role="driver"] .sttl .rsdoors .rschip{background:var(--card);color:var(--ink);border:var(--btn-edge) solid var(--ink);
  border-radius:var(--btn-r);min-height:var(--btn-h-sm);padding:0 6px;font:var(--btn-fw) var(--btn-fs-sm)/1.15 var(--body);
  letter-spacing:var(--btn-ls);text-transform:var(--btn-case);display:inline-flex;align-items:center;justify-content:center;
  box-sizing:border-box;cursor:pointer;user-select:none;flex:0 0 auto}
.fx-ride[data-role="driver"] .fact-hot{display:inline-block;width:fit-content;max-width:100%;box-sizing:border-box;background:var(--accent);
  color:#FFFFFF;border-radius:6px;padding:3px 8px;line-height:1.25}
.fx-ride[data-role="driver"] .row .tx > b.fact-hot + span{margin-top:4px}
.fx-ride[data-role="driver"] .fact-good{color:var(--good)}

/* ==================================================================================================
   b622, THE CHARGING STOP: FILLED IS GREEN, AND SAVE FITS ON ONE ROW (Ahmed 2026-10-27, bug-mvr37u45-z6mx4, on b611, the
   stop opened from the Home tile)
   1. "Everything filled out should be green background with white text, and underneath green, and only the part that is
      not done, session cost and session kWh, should stay the way it is." On this one form (the editor carries
      data-kind="stop", app-journal.js b622) a box with a number in it (.known, the app's or his) is the done state: the
      --good fill, the number, its unit and the thousands in white, the line under it in the good ink. An empty box keeps the
      plain look. The box he is typing in keeps its orange edge so he can see where he is. The chosen key of "This charge is
      for" wears the same green: on this form a choice made is a thing done, the same state as a filled box (b569's ink
      selected look stays on every other choice in the app).
   2. "Where it says SAVE COST AND KWH make it fit in one row." The save key keeps its words on one line and takes the room,
      Cancel takes only what it needs; measured at 412 (t372-cs620).
   ================================================================================================== */
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known{background:var(--good);border-color:var(--good)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known :is(input,u,.jr-pre){color:var(--on-accent)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known input::placeholder{color:var(--on-accent)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known:focus-within{border-color:var(--orange)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known + .jr-fhint{color:var(--good-ink)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-seg > span.on:not(#ypd-btn){background:var(--good);color:var(--on-accent);border-color:var(--good)}
.frame[data-role="driver"] .jr-btns > .cta:not(#ypd-btn){width:auto;flex:1 1 auto;min-width:0;white-space:nowrap;padding-inline:var(--sp-3)}
.frame[data-role="driver"] .jr-btns > .cta.ghost:not(#ypd-btn){flex:0 0 auto}

/* ==================================================================================================
   b626: UBER OFFERS, owner only (app-uber.js). The Your earnings dock's shape, from the tokens. The cards are .card, the
   labels the orange label chip (.badge.retleg), the buttons the b569 system (.cta, .cta.sm.ghost, a .bk-seg key for
   each rule's ON / OFF). The ONE new look is the verdict, GigU's card from his recording of 2026-10-27: the newest
   offer's card OUTLINED in the state colour, green (--good) when it meets every rule, yellow (--warn) when one money
   number is under his goal, red (--bad) when both are or a hard rule breaks, and $ a mile, $ an hour and the rating
   each with its own small bar in its own state colour. A state, never decoration. The history rows carry the colour
   as a dot. The colour is data-ubcol (the bars data-ubg), set from the score the phone made.
   ================================================================================================== */
.frame > .sheet.fx-uber{position:absolute;left:var(--sheet-inset);right:var(--sheet-inset);bottom:var(--foot-h);top:auto;margin:0;z-index:6;
  max-height:calc(100% - var(--hd-h) - var(--foot-h) - var(--sheet-top));overflow-y:auto;-webkit-overflow-scrolling:touch;padding:var(--sp-2) var(--sp-4) var(--sp-4)}
.frame.fx-uberopen > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame.fx-uberopen > .map{filter:brightness(.72) saturate(.8)}
/* b679: CLIENT TEXTS (app-texts.js), the text reader's consent card. The Uber sheet's look, no new class names, the plain
   .sheet and .card marked by data attributes: [data-txsheet] the sheet, [data-txopen] the dimmed frame, data-txp=
   note the muted small line, line body text, row the switch row (name and line left, the ON / OFF key right, a 44px
   tap), kv the three WHAT IT READS / KEEPS / DROPS blocks, k their ink labels (lime until b684). */
.frame[data-txopen] > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame[data-txopen] > .map{filter:brightness(.72) saturate(.8)}
.sheet[data-txsheet] [data-txp="body"]{display:grid;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3) var(--sp-4)}
.sheet[data-txsheet] .card[data-txp="sec"]{display:grid;gap:var(--sp-2)}
.sheet[data-txsheet] [data-txp="note"]{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
/* b713: a line on the new texts card is a door to that client's conversation, the whole row is the target */
.sheet[data-txsheet] [data-tx="open"]{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--sp-2);width:100%;min-height:var(--tap-min);margin:0;padding:var(--sp-2) 0;
  border:0;border-bottom:1px solid var(--line);background:transparent;text-align:left;color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent}
.sheet[data-txsheet] [data-tx="open"]:last-child{border-bottom:0;padding-bottom:0}
.sheet[data-txsheet] [data-txp="line"]{font:var(--f-body);color:var(--ink)}
.sheet[data-txsheet] [data-txp="row"]{display:grid;grid-template-columns:1fr auto;align-items:center;gap:var(--sp-2);min-height:var(--tap)}
.sheet[data-txsheet] [data-txp="row"] > div{display:grid;gap:2px;min-width:0}
.sheet[data-txsheet] [data-txp="rl"] b{font:var(--f-card);color:var(--ink)}
.sheet[data-txsheet] [data-txp="row"] .bk-seg{display:flex}
.sheet[data-txsheet] [data-txp="row"] .bk-seg button{min-width:64px;min-height:var(--tap)}
.sheet[data-txsheet] [data-txp="kv"]{display:grid;gap:2px}
/* b684 (Ahmed 2026-10-29, on his phone: "it's in a color that's not following my brand and I can't read it. At least make it
   black"): the three WHAT IT labels were lime on the white card, 1.21:1. Lime is for labels on ink only; on a light card the
   label is ink, 19.8:1 on white (the orange chip with white is 3.6:1, under 4.5). tools/t390 measures every text node. */
.sheet[data-txsheet] [data-txp="k"]{font:800 var(--t-label)/1.2 var(--body);letter-spacing:var(--ls-label);text-transform:uppercase;color:var(--ink)}
.fx-uber .ub-body{display:flex;flex-direction:column;gap:var(--sp-3);padding-top:2px}
.fx-uber .card{display:flex;flex-direction:column;gap:var(--sp-2);border-radius:var(--r-ctl)}
.fx-uber .badge.retleg{align-self:flex-start}
.fx-uber .ub-k{font:800 var(--t-label)/1.2 var(--body);letter-spacing:var(--ls-label);text-transform:uppercase;color:var(--muted)}
.fx-uber .ub-note{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
.fx-uber .ub-line{font:var(--f-body);color:var(--ink)}
/* b635: ONE BIG UBER READER ON / OFF, the app's GO ONLINE / GO OFFLINE button (.cta .fx-go-off): off it is GO OFFLINE's
   white with the ink edge, on it is filled green. :not(#ypd-btn) matches the driver button rules' weight. */
/* b691 (Ahmed's recording 2026-10-29 19:08): UBER READER ON and READ UBER AND SEND TO CLAUDE side by side, equal, the
   status line under BOTH. The row is a grid; the READ UBER block (data-ub diagtop, inside it) spans the whole grid as a
   subgrid, so its button takes the second cell and its line the row under. Rows: 1 the buttons, 2 the line, 3 the power
   note, 4 a send failure. Under 360 wide the buttons stack. */
.fx-uber [data-ub="power"]{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto auto auto auto;column-gap:var(--sp-2);row-gap:0}
.fx-uber [data-ub="power"] > .cta{grid-area:1/1/2/2;position:relative;z-index:1;min-width:0}
.fx-uber [data-ub="power"][data-ubtwo="0"] > .cta{grid-column:1/-1}
.fx-uber [data-ub="power"] > [data-ub="powernote"]{grid-area:3/1/4/-1;margin-top:var(--sp-1)}
.fx-uber [data-ub="diagtop"]{grid-area:1/1/-1/-1;display:grid;grid-template-columns:subgrid;grid-template-rows:subgrid;min-width:0}
.fx-uber [data-ub="diagtop"] > [data-act="uber:readnow"]{grid-area:1/2/2/3;min-width:0}
.fx-uber [data-ub="diagtop"] > [data-ub="diagline"]{grid-area:2/1/3/-1;margin-top:var(--sp-2)}
.fx-uber [data-ub="diagtop"] > [data-ub="readnote"]{grid-area:4/1/5/-1;margin-top:var(--sp-1)}
.frame[data-role="driver"] .fx-uber [data-ub="power"][data-ubtwo="1"] .cta:not(#ypd-btn){min-height:var(--act-h);font-size:var(--t-body);line-height:1.2;padding-left:var(--sp-2);padding-right:var(--sp-2);white-space:normal;margin:0}
@media (max-width:359px){
  .fx-uber [data-ub="power"]{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto auto auto auto}
  .fx-uber [data-ub="power"] > .cta{grid-column:1/-1}
  .fx-uber [data-ub="diagtop"] > [data-act="uber:readnow"]{grid-area:2/1/3/-1}
  .frame[data-role="driver"] .fx-uber [data-ub="power"][data-ubtwo="1"] [data-ub="diagtop"] > .cta:not(#ypd-btn){margin-top:var(--sp-2)}
  .fx-uber [data-ub="diagtop"] > [data-ub="diagline"]{grid-area:3/1/4/-1}
  .fx-uber [data-ub="power"] > [data-ub="powernote"]{grid-area:4/1/5/-1}
  .fx-uber [data-ub="diagtop"] > [data-ub="readnote"]{grid-area:5/1/6/-1}
}
/* b691: OFFERS, five compact rows: the colour, the time over the place, the pay, $ an hour, $ a mile */
/* b709: the time keeps its width on the 344 cover screen, it clipped to "5." beside a "not read"; $ an hour and $ a mile give way instead */
.fx-uber [data-ub="offers"] .ub-row{grid-template-columns:14px minmax(64px,1fr) auto minmax(0,auto) minmax(0,auto);min-height:var(--tap)}
@media (max-width:360px){.fx-uber [data-ub="offers"] .ub-row{column-gap:var(--sp-1)}}
.fx-uber [data-ubc="tp"]{display:flex;flex-direction:column;min-width:0}
.fx-uber [data-ubc="tp"] > span + span{font-size:var(--t-small);line-height:var(--lh-small);color:var(--muted)}
/* b709: the pay with the score under it, PASS 59 */
.fx-uber .ub-row [data-ubc="pay"]{display:flex;flex-direction:column;align-items:flex-start;overflow:visible}
.fx-uber [data-ubc="score"]{font-size:var(--t-small);line-height:var(--lh-small);font-weight:700}
.fx-uber [data-ub="offers"] > .cta{align-self:stretch}
/* b691: FREQUENCY, offers an hour, one scale, the green part the GOOD ones, the counts and hours in text tokens */
.fx-uber [data-ub="freqchart"]{display:block;width:100%;overflow:visible}
.fx-uber [data-ub="freqchart"] rect[data-fz="good"]{fill:var(--good)}
.fx-uber [data-ub="freqchart"] rect[data-fz="rest"]{fill:var(--line-mid)}
.fx-uber [data-ub="freqchart"] line[data-fz="base"]{stroke:var(--line);stroke-width:1}
.fx-uber [data-ub="freqchart"] text{font:700 var(--t-small)/1 var(--body);font-variant-numeric:tabular-nums;fill:var(--ink)}
.fx-uber [data-ub="freqchart"] text[data-fz="h"]{font-weight:600;fill:var(--muted)}
.fx-uber [data-ub="freqchart"] [data-ubnow="1"] text[data-fz="h"]{fill:var(--ink);font-weight:800}
.fx-uber .ub-top[data-ub="freqlegend"]{justify-content:flex-start;gap:var(--sp-4)}
.fx-uber [data-ub="freqlegend"] .ub-rl{display:inline-flex;align-items:center;gap:var(--sp-1)}
.fx-uber [data-ub="freqword"]{color:var(--ink);font-size:var(--t-body)}
.frame[data-role="driver"] .fx-uber .cta[data-act="uber:power"]:not(#ypd-btn){width:100%;min-height:var(--act-h);font-size:var(--act-fs)}
.frame[data-role="driver"] .fx-uber .cta[data-act="uber:power"][data-ubon="1"]:not(#ypd-btn){background:var(--good);border-color:var(--good);color:#fff}
/* b685 (Ahmed bug-mvu7pk7x-2hjzp: "Read Uber now to be the green button, just like above where it says Uber reader on"):
   his tap turns READ UBER NOW the same green for about 4 seconds, SENT TO CLAUDE with a tick, then back to orange */
.frame[data-role="driver"] .fx-uber .cta[data-act="uber:readnow"][data-ubsent="1"]:not(#ypd-btn){background:var(--good);border-color:var(--good);color:#fff;opacity:1}
/* b633: what the reader sees, the first line of the sheet, at card size so he reads it at a glance */
.fx-uber [data-ub="diagtop"] [data-ub="diagline"]{font:var(--f-card);color:var(--ink)}
/* the live card, GigU's shape (his recording, 2026-10-27): white, the OUTLINE is the grade */
.fx-uber .ub-live{border:4px solid var(--line-mid);padding:var(--card-pad);color:var(--ink);background:var(--card)}
.fx-uber .ub-live[data-ubcol="green"]{border-color:var(--good)}
.fx-uber .ub-live[data-ubcol="red"]{border-color:var(--bad)}
/* b716 (Ahmed 2026-11-02: "the yellow makes me not want to take a ride"): THE MIDDLE GRADE IS A LIGHT GREEN, two greens for
   good and okay, red stays red. Offer grading only, every other yellow in the app (warnings, connecting) keeps --warn.
   --ub-ok #8FD6A3 is the light green (dark ink on it 11.6:1, beside --good #1F9D57 2.05:1 so the two read apart), --ub-ok-ink
   #3D6E4B its word on the white card (5.95:1). The Android shell 1.5.8 uses the same hex. The data value stays "yellow". */
.fx-uber{--ub-ok:#8FD6A3;--ub-ok-ink:#3D6E4B}
.fx-uber .ub-live[data-ubcol="yellow"]{border-color:var(--ub-ok)}
.fx-uber .ub-live[data-ubcol="green"] .ub-word{color:var(--good-ink)}
.fx-uber .ub-live[data-ubcol="red"] .ub-word{color:var(--bad-ink)}
.fx-uber .ub-live[data-ubcol="yellow"] .ub-word{color:var(--ub-ok-ink)}
.fx-uber .ub-top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.fx-uber .ub-word{font:800 var(--t-label)/1 var(--body);letter-spacing:var(--ls-label);text-transform:uppercase}
/* the three numbers, each with its own pass or fail bar (the .ub-dot, drawn tall) */
.fx-uber .ub-grid.ub-three{grid-template-columns:1fr 1fr 1fr}
.fx-uber .ub-three b{display:flex;align-items:center;gap:6px;font:var(--f-card);font-variant-numeric:tabular-nums}
.fx-uber .ub-three .ub-dot{width:5px;height:24px;border-radius:3px;flex:none}
.fx-uber .ub-dot[data-ubg="pass"]{background:var(--good)}
.fx-uber .ub-dot[data-ubg="close"]{background:var(--ub-ok)}
.fx-uber .ub-dot[data-ubg="low"]{background:var(--bad)}
.fx-uber .ub-live .ub-top .badge.retleg{flex:none}
/* the first run: the three colours, no login, one switch */
.fx-uber .ub-legend{grid-template-columns:auto 1fr}
.fx-uber .ub-legend > .ub-dot{width:16px;height:16px}
.fx-uber .ub-when{font:var(--f-data);opacity:.9}
.fx-uber .ub-fare{font:var(--f-big);line-height:1;font-variant-numeric:tabular-nums}
.fx-uber .ub-why{font:700 var(--t-body)/var(--lh-body) var(--body)}
.fx-uber .ub-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2) var(--sp-3)}
.fx-uber .ub-grid > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.fx-uber .ub-grid b{font:var(--f-data);overflow-wrap:anywhere}
.fx-uber .ub-live > .cta{align-self:stretch}
/* the rules */
.fx-uber .ub-rule{display:grid;grid-template-columns:auto 1fr 96px;align-items:center;gap:var(--sp-2);min-height:var(--tap)}
.fx-uber .ub-rule .bk-seg{display:flex}
.fx-uber .ub-rule .bk-seg button{min-width:64px;min-height:var(--tap)}
.fx-uber .ub-rl{font:var(--f-small);color:var(--ink)}
.fx-uber .ub-in{width:100%;box-sizing:border-box;min-height:var(--tap);border-radius:var(--r-input);border:1.5px solid var(--btn-choice-edge);background:var(--card);
  padding:0 var(--sp-2);font:var(--f-data);color:var(--ink);text-align:right}
.fx-uber .ub-in:disabled{opacity:.45}
.fx-uber .ub-in:focus{outline:none;border-color:var(--ink)}
.fx-uber .ub-types{display:flex;flex-wrap:wrap}
.fx-uber .ub-types button{min-height:var(--tap);padding:0 var(--sp-3)}
/* the history */
.fx-uber .ub-list{display:flex;flex-direction:column}
.fx-uber .ub-row{display:grid;grid-template-columns:14px 1.2fr 1fr 1fr 1fr;align-items:center;gap:var(--sp-2);min-height:var(--row);padding:0 var(--sp-1);
  border:0;border-bottom:1px solid var(--line);background:none;color:var(--ink);text-align:left;font:var(--f-small);cursor:pointer}
.fx-uber .ub-row b{font:var(--f-data)}
.fx-uber .ub-row span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fx-uber .ub-dot{width:14px;height:14px;border-radius:50%;background:var(--line-mid)}
.fx-uber .ub-row[data-ubcol="green"] .ub-dot{background:var(--good)}
.fx-uber .ub-row[data-ubcol="red"] .ub-dot{background:var(--bad)}
.fx-uber .ub-row[data-ubcol="yellow"] .ub-dot{background:var(--ub-ok)}
/* the picture, full screen */
.fx-uber .ub-view{position:fixed;inset:0;z-index:60;overflow-y:auto;background:var(--ink);color:var(--paper);padding:var(--sp-3) var(--gutter) var(--sp-6);
  display:flex;flex-direction:column;gap:var(--sp-3)}
.fx-uber .ub-vbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);position:sticky;top:0;background:var(--ink);padding:var(--sp-1) 0}
.fx-uber .ub-vbar .cta{width:auto;padding:0 var(--sp-4)}
.fx-uber .ub-view[data-ubcol="green"] .ub-vbar .ub-word{color:var(--good)}
.fx-uber .ub-view[data-ubcol="red"] .ub-vbar .ub-word{color:var(--bad)}
.fx-uber .ub-view[data-ubcol="yellow"] .ub-vbar .ub-word{color:var(--ub-ok)}
.fx-uber .ub-view .ub-word{font-size:var(--t-card)}
.fx-uber .ub-img{display:block;width:100%;height:auto;border-radius:var(--r-input);background:#000}
.fx-uber .ub-view .ub-why{color:var(--paper)}
/* b709: THE BURST, BACK and NEXT ride in the sticky bar, so a tall picture never pushes them off screen and they never move as he flips */
.fx-uber .ub-vbar{flex-wrap:wrap}
.fx-uber [data-ub="burstnav"]{flex:1 0 100%;display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:var(--sp-2)}
.fx-uber [data-ub="burstnav"] .cta{width:100%;min-height:var(--tap);padding:0 var(--sp-2);margin:0}
.fx-uber [data-ub="burstnav"] .cta:disabled{opacity:.4;cursor:default}
.fx-uber [data-ub="burstlabel"]{display:flex;flex-direction:column;align-items:center;min-width:72px;color:var(--paper);font:var(--f-small);line-height:var(--lh-small)}
.fx-uber [data-ub="burstlabel"] b{font:var(--f-data);font-size:var(--t-card)}
.fx-uber [data-ub="burstlabel"] span{color:var(--lime)}
.fx-uber .ub-img[data-ubburst]{max-height:70vh;object-fit:contain}
.fx-uber .ub-kv{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2) var(--sp-3)}
.fx-uber .ub-kv > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.fx-uber .ub-kv b{font:var(--f-small);font-weight:700;overflow-wrap:anywhere}
.fx-uber .ub-view .ub-k{color:var(--lime)}   /* b709: small labels are lime on a dark panel, the Panels and branding row */
/* ==================================================================================================
   b627: THE UBER RIDE LOG, his Speechnotes note written for him (app-uber.js). The b626 family, nothing new: the ride is a
   .card.ub-live outlined in the offer's grade, his fields are .ub-k over .ub-in, the choices .bk-seg. Two looks are added
   to existing names: a box he or the app has filled is GREEN (.ub-in.known, b622's done look on the charging stop), and the
   words boxes (data-urt) read left to right with a dictation textarea three lines tall. The Journal's own card carries
   .fx-uber so the same rules paint it there.
   ================================================================================================== */
.fx-uber .ub-in[data-urt]{text-align:left}
.fx-uber textarea.ub-in{min-height:96px;padding:var(--sp-2);resize:vertical;font:var(--f-body);line-height:var(--lh-body)}
.fx-uber .ub-in.known{background:var(--good);border-color:var(--good);color:var(--on-accent)}
.fx-uber .ub-in.known::placeholder{color:var(--on-accent)}
.fx-uber [data-ub="ride"] > div > .ub-k,.fx-uber [data-ub="ride"] .ub-grid .ub-k{display:block;margin-bottom:2px}
.fx-uber [data-ub="ride"] > .ub-k{margin-top:var(--sp-2)}
.fx-uber [data-ub="ride"] .ub-legend{grid-template-columns:1fr auto}
.fx-uber [data-ub="ride"] .ub-legend .bk-seg button{min-width:72px}
.fx-uber [data-ub="ride"] .ub-types button{flex:1 1 auto}
.fx-uber [data-ub="ride"] > .cta{align-self:stretch}
.mc-card.fx-uber > .ub-body{padding-top:var(--sp-2)}
.mc-card.fx-uber > .cta{margin-top:var(--sp-3)}
.mc-card.fx-uber .ub-row{grid-template-columns:14px 1fr 1.3fr 1fr 1fr}
/* b629: ONE CARD, THREE ROWS at the top (GigU's home): name over a one-line status, a gear, the ON / OFF switch.
   The rows are .ub-rule laid out by their data-ubrow3, the gear is a .cta.sm.ghost icon button, no new class. */
.fx-uber [data-ub="home3"]{gap:0;padding-top:var(--sp-1);padding-bottom:var(--sp-1)}
.fx-uber [data-ub="home3"] > div + div{border-top:1px solid var(--line)}
.fx-uber [data-ubrow3]{grid-template-columns:1fr 44px 64px;padding:var(--sp-2) 0}
.fx-uber [data-ubrow3] > div:first-child{display:flex;flex-direction:column;gap:2px;min-width:0}
.fx-uber [data-ubrow3] .ub-rl b{font:var(--f-card)}
.fx-uber [data-ubgear]{width:44px;min-width:44px;min-height:44px;padding:0;display:flex;align-items:center;justify-content:center}
.fx-uber [data-ub="camera"]{opacity:.45}
/* b629: TWO LINES A GOAL (GigU's Cherry Picker). One slider, two handles: the red Bad handle and the green Good handle,
   two native range inputs laid over one SVG track (red, yellow, green between the handles) with each handle's value in
   a tag above it. No new class: the pieces are found by their data attributes. The SVG sits inside the handles' half
   width on each side, so its 0% and 100% are exactly the handle centres. Handles are 44 across (a 28 dot inside). */
.fx-uber [data-ubdual]{position:relative;height:80px;padding:0 22px;margin:0 0 var(--sp-2)}
.fx-uber [data-ubdual][data-ubon="0"]{opacity:.45}
.fx-uber [data-ubdual] > svg{display:block;width:100%;height:58px;overflow:visible}
.fx-uber [data-ubdual] rect[data-z="bad"]{fill:var(--bad)}
.fx-uber [data-ubdual] rect[data-z="mid"]{fill:var(--ub-ok)}
.fx-uber [data-ubdual] rect[data-z="good"]{fill:var(--good)}
.fx-uber [data-ubdual] [data-ubtag="bad"] rect{fill:var(--bad)}
.fx-uber [data-ubdual] [data-ubtag="good"] rect{fill:var(--good)}
.fx-uber [data-ubdual] text{fill:#FFFFFF;font:800 13px/1 var(--body);font-variant-numeric:tabular-nums}
.fx-uber [data-ubdual] input[type="range"]{position:absolute;left:0;top:27px;width:100%;height:44px;margin:0;padding:0;
  -webkit-appearance:none;appearance:none;background:transparent;pointer-events:none;z-index:1}
.fx-uber [data-ubdual] input[type="range"]:focus{outline:none}
.fx-uber [data-ubdual][data-ubtop="bad"] input[data-ubend="bad"]{z-index:2}
.fx-uber [data-ubdual] input[type="range"]::-webkit-slider-runnable-track{height:44px;background:transparent;border:0}
.fx-uber [data-ubdual] input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:44px;height:44px;border-radius:50%;
  border:8px solid transparent;background-clip:padding-box;box-shadow:inset 0 0 0 3px var(--card);pointer-events:auto;cursor:pointer}
.fx-uber [data-ubdual] input[type="range"]::-moz-range-thumb{width:28px;height:28px;border-radius:50%;border:3px solid var(--card);pointer-events:auto;cursor:pointer}
.fx-uber [data-ubdual] input[data-ubend="bad"]::-webkit-slider-thumb{background-color:var(--bad)}
.fx-uber [data-ubdual] input[data-ubend="good"]::-webkit-slider-thumb{background-color:var(--good)}
.fx-uber [data-ubdual] input[data-ubend="bad"]::-moz-range-thumb{background:var(--bad)}
.fx-uber [data-ubdual] input[data-ubend="good"]::-moz-range-thumb{background:var(--good)}
.fx-uber [data-ubdual] input[type="range"]:focus-visible::-webkit-slider-thumb{box-shadow:inset 0 0 0 3px var(--card),0 0 0 3px var(--ink)}

/* ==================================================================================================
   b632, THE RIDE SHEET'S TOP (Ahmed 2026-10-28, John's pickup, b631)
   1. bug-mvs51ub7-3mubq: "This right here should all kind of be aligned... RIDER is John and it should be right here, and then
      Trip and Share, if it needs to be a little bit smaller it's fine, so it all fits right here nice and easy." The title, the
      rider's chip and the two doors are ONE line: the line never wraps, the doors stay whole (their 44 px tap kept) and a
      little smaller, and a long name gives way with an ellipsis instead of pushing them under it.
   2. bug-mvs53zqb-zf9l9 (b): "it needs to be underneath where it says START THE RIDE, right underneath it, because that's
      when I'm going to use it." The undo row rides directly under the one button (order -30, after it in the markup), at
      every stage it shows.
   ================================================================================================== */
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl > .stt{flex-wrap:nowrap;min-width:0}
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl > .stt > .stt-t{flex:0 0 auto}
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl > .stt > .stchip[data-rd="name"]{flex:0 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.fx-ride[data-role="driver"] .sttl .stchip.rsdoors{flex:0 0 auto;gap:4px}
/* b694 (bug-mvvdrinw-7ivt7): on the Ride sheet the rider's name and RETURN sit in the header already and crowded the action buttons.
   Only here: Inbox, Chat, Trip info and the rest keep their chips. rsHeadPlace reads a chip of no width as fitting. */
.fx-ride[data-role="driver"] > .sheet:has(> .fx-btnrow) > .shbar > .sttl > .stt > .stchip:is([data-rd="name"],[data-rd="ret"]){display:none!important}
.fx-ride[data-role="driver"] .sttl .rsdoors .rschip{min-height:44px;padding:0 5px;font-size:calc(var(--btn-fs-sm) * .92);letter-spacing:.02em}
.fx-ride[data-role="driver"] > .sheet > .rsundo{order:-30;flex:0 0 auto;margin-top:6px}
/* (a) one sentence: "Tapped by mistake, back to (I have arrived)", the step in bold on the same line */
.fx-ride[data-role="driver"] .rsundo .rsundo-to{display:inline;margin-top:0}

/* ==================================================================================================
   b634 (bug-mvs8eo1x-v3un1, Ahmed 2026-10-28 7:50 AM on b629, the Fold in SPLIT SCREEN with Uber, the YPD pane 573x612):
   THE PHONE LAYOUT IN A SPLIT PANE. "because I added this split on the left it gets messed up... It should not be out like
   that right in the middle on the top. I can't even function." b435 kept the band phone sized but CENTRED it in the lane
   left of a rail pinned to the right edge, so a 450 to 800 wide pane showed the green card floating in the middle and the
   rail far off on its own. Now a tall pane under 800 wide is the phone pinned to the left: the band starts the phone's gap
   from the left edge at the phone's width, and the rail stands right beside it, exactly where a 430 phone has it (the
   rail's right edge is the tall column's width less the gap). Under 430 nothing moves, max() keeps the old right gap.
   The open fold, full screen (880 to 904 wide, t264 and t220), keeps b435's centred band. navRailFit (app.html) runs in
   the same range, so NORTH meets the card's top and INFO its bottom, as on the phone. Measured by t372-sp634.
   ================================================================================================== */
@media (aspect-ratio < 6/5) and (width < 800px){
  .frame[data-role="driver"] > .navrow{margin-left:0;margin-right:auto}
  .frame[data-role="driver"] > .navctl,
  .frame[data-role="driver"] > .ti-pill{right:max(var(--band-gap), calc(100% + var(--band-gap) + var(--tall-w) * -1))}
}

/* ==================================================================================================
   b636, THE CHARGING STOP ON ITS OWN SCREEN: THE BOX HE IS FILLING IS WHITE, A FILLED ONE GREEN, AND WHAT IS DONE ROLLS UP
   (Ahmed 2026-10-28, bug-mvsccnuh-0m8yg, on b633 at the charger)
   1. "this should be white color as I'm filling it out"; "this 80% after should be white in color, [it's] black". The box
      the cursor is in took the plain box's --paper fill, #121212 on a phone in dark mode, and a filled box he went back into
      kept its green with the number selected over it. Now the box being filled is white with the dark number, on every
      Journal moment and the stop, whatever the phone's theme, and leaving it gives the b622 state back: green once it holds a
      number, plain while empty. The hex is fixed on purpose, the --card and --ink tokens turn dark with the phone.
   2. The done boxes of a charge in progress sit in one folded box under a .jr-more row (app-journal.js rollUp); the box is a
      .jr-fields grid, so it keeps the form's two columns, and it is gone while folded.
   ================================================================================================== */
.frame[data-role="driver"] [data-jr="edit"][data-kind] .jr-in:focus-within{background:#FFFFFF;border-color:var(--orange)}
.frame[data-role="driver"] [data-jr="edit"][data-kind] .jr-in:focus-within :is(input,u,.jr-pre){color:#0A0A0A}
.frame[data-role="driver"] [data-jr="edit"][data-kind] .jr-in:focus-within input::selection{background:rgba(255,59,0,.28);color:#0A0A0A}
.frame[data-role="driver"] [data-jr="rollbox"][hidden]{display:none!important}
.frame[data-role="driver"] [data-jr="rollrow"] [data-jr="rolltxt"]{font-family:'JetBrains Mono',monospace;font-weight:700;font-variant-numeric:tabular-nums;min-width:0;overflow-wrap:anywhere}
/* b644: THE JOURNAL DAY, OPEN AND IN ORDER (Ahmed 2026-10-28, JR643 round 3 approved). The date rides in the title bar beside
   Journal, the Ride sheet's pattern: arrows 44 tall, the pill shrinks before the row ever wraps (360 and 430 measured by
   t372-jr643). The day's steps in time order, each with EDIT, the step he is on in orange with white text. The outing's NET
   green with white. The next outing's moments behind one button. Charging stops are off this screen. */
.fx-journal .sttl > .stt:has(> .jr-daynav){flex-wrap:nowrap}
.fx-journal .sttl > .stt > .stt-t{flex:0 0 auto}
.fx-journal .sttl .stchip.jr-daynav{background:transparent;color:var(--ink);padding:0;margin-left:auto;gap:0;flex:0 1 auto;min-width:0;
  overflow:visible;font:inherit;letter-spacing:0;text-transform:none;border-radius:0}
.fx-journal .sttl .jr-daynav .aff{min-width:32px;width:32px;height:44px;min-height:44px;padding:0;background:transparent;border:0;
  font-size:24px;line-height:1;color:var(--ink)}
.fx-journal .sttl .jr-daynav .jr-day{flex:0 1 auto;min-width:0}
.fx-journal .cx-when:empty{display:none}
.fx-journal .jr-steps .jr-step{align-items:center}
.fx-journal .jr-steps .jr-step b{display:block}
.fx-journal .jr-steps .jr-stepwhen{display:inline;font-style:normal;font-weight:600;color:var(--muted);margin-left:8px;font-size:.86em}
.fx-journal .jr-steps .jr-stepin{margin-left:18px;border-left:3px solid var(--accent,#FF3B00);padding-left:12px}
.fx-journal .jr-steps .jr-stephd{margin:10px 0 2px;font-weight:800;font-size:var(--t-body);color:var(--ink)}
.fx-journal .jr-steps .jr-step .jr-stepedit{min-height:44px;min-width:76px;padding:0 16px;border:0;border-radius:var(--r-input);
  background:var(--paper);color:var(--good);font-weight:800;letter-spacing:.06em;cursor:pointer}
.fx-journal .jr-steps .jr-step.jr-now{background:#FF3B00;border:0;border-radius:12px;padding:10px 12px;margin:4px 0}
.fx-journal .jr-steps .jr-step.jr-now.jr-stepin{margin-left:18px}
.fx-journal .jr-steps .jr-step.jr-now :is(b,span,.jr-stepwhen){color:#FFFFFF;opacity:1}
.fx-journal .jr-steps > .jr-edit{margin:6px 0 10px 18px}
/* b665: the day grouped by outing. The open outing's fold row, its passenger line, and each finished outing as one row that opens */
.fx-journal .jr-steps > .jr-fold[data-of]{margin:2px 0 4px}
.fx-journal .jr-steps .jr-foldbody[data-fold^="o-"] > .jr-edit{margin:6px 0 10px 18px}
.fx-journal .jr-steps .mc-sub[data-jr-pax]{margin:0 0 6px}
.fx-journal .jr-steps > .ot-card{margin-top:8px}
.fx-journal .jr-steps .jr-foldbody[data-fold^="o-"] > .ot-card{margin-top:8px}
.fx-journal .jr-steps .ot-card > .ot-head[data-of]{min-height:44px;cursor:pointer}
.fx-journal .jr-steps .ot-card > .ot-head[data-of] > div b{margin-top:2px}
.fx-journal .jr-steps .ot-card > .ot-head[data-of][aria-expanded="true"] .jr-fold-chev{transform:rotate(180deg)}
.fx-journal .jr-steps .ot-card > .jr-foldbody[data-fold^="o-"]{gap:6px}
.fx-journal .ot-card .ot-t.net{background:#147135;border-color:#147135}
.fx-journal .ot-card .ot-t.net :is(small,b,.s){color:#FFFFFF}
.fx-journal .ot-t .s:empty{display:none}
.fx-journal .jr-nextcard .jr-nextsub{margin-top:8px}
.fx-journal .jr-nextcard .jr-nextsub:empty{display:none}
.fx-journal .jr-nextcard .jr-moments{margin-top:10px}

/* mv644: THE MENU TITLE BAR CARRIES THE VERSION (Ahmed 2026-10-28, "look at the Ride, the way Ride and Sam looks, Trip info,
   Share, X"). The same pieces as the Ride bar: B641 in the orange name chip, ANDROID 1.4.4 in the white TRIP INFO pill,
   pushed right against the X, one line. */
.fx-comms[data-screen="menu"] > .sheet > .shbar > .sttl > .stt{flex-wrap:nowrap;justify-content:flex-start;gap:6px;min-width:0}
.fx-comms[data-screen="menu"] > .sheet > .shbar > .sttl > .stt > .stt-t{flex:0 0 auto}
.fx-comms[data-screen="menu"] .sttl .stchip[data-ver="chip"]{flex:0 0 auto}
.fx-comms[data-screen="menu"] .sttl .stchip[data-ver="shell"]{display:inline-flex;margin-left:auto;background:transparent;color:inherit;
  padding:0;overflow:visible;text-overflow:clip;max-width:100%;flex:0 0 auto}
.fx-comms[data-screen="menu"] .sttl [data-ver="shell"] .rschip{background:var(--card);color:var(--ink);border:var(--btn-edge) solid var(--ink);
  border-radius:var(--btn-r);min-height:44px;padding:0 5px;font:var(--btn-fw) calc(var(--btn-fs-sm) * .92)/1.15 var(--body);
  letter-spacing:.02em;text-transform:var(--btn-case);display:inline-flex;align-items:center;justify-content:center;
  box-sizing:border-box;cursor:default;user-select:none;flex:0 0 auto;white-space:nowrap}
.fx-comms[data-screen="menu"] .sttl .stchip[data-ver="shell"]:empty{display:none}

/* ==================================================================================================
   b655, THE CHARGING STOP, SIMPLER (Ahmed 2026-10-28, bug-mvsp0qwq-d8eap, on b644)
   1. "at least the row that I'm clicking on should be there so I can click on it". Now every sheet, b704, app-keyboard.js.
   2. "Charging stop location, I don't know why it's two different rows". Location and its box on one line; the card's own
      CHARGING STOP label is gone here, the title bar already says it.
   3. "it's too much color when it's filled out. Make it less obvious but it needs to be obvious that we filled it out". The
      Your Circle Money tab's Money in panel (Your Circle standard.css b787, .xpnin): a
      faint green tint, 8 percent of --good over the card, a green edge, 55 percent of --good, the number in the normal ink,
      and a small green check at the end of the box. The chosen YPD or Personal key wears the same. Replaces b622's solid fill.
   4. The title bar is the Ride sheet's (b600, b632): the title, and + NEW STOP on the right of the same line, the door's look.
   ================================================================================================== */
/* b704: ROOM TO TYPE (Ahmed 2026-11-01, bug-mvyethma-6smek, the open Fold at 829x331: "I don't think we need the header right now").
   Replaces b655's Charging stop only rule (item 1 above): every frame now, set once by app-keyboard.js, and the footer stays, he
   needs it to stop the recording and hit enter. The two tokens go to 0 rather than a second max-height, because some twenty sheets
   carry their own calc() on them and all of them grow by the header this way. The handle goes too, nothing is dragged while typing. */
.frame[data-kb]{--hd-h:0px;--sheet-top:0px}
.frame[data-kb] > .hd{display:none!important}
.frame[data-kb] > .sheet{transition:none}
.frame[data-kb] > .sheet > .grab,.frame[data-kb] > .sheet > .shbar > .grab{display:none}
.frame[data-kb="over"]{top:var(--kb-top,0px);height:var(--kb-h,100%)}
.frame[data-screen="charge"] [data-jr="edit"] > [data-jr="edlab"]{display:none}
.frame[data-screen="charge"] [data-jr="edit"] .jr-hint:empty{display:none}
.frame[data-screen="charge"] .jr-fld:has(> .jr-in > [data-jr="f-where"]){display:flex;align-items:center;flex-wrap:wrap;gap:6px var(--sp-2)}
.frame[data-screen="charge"] .jr-fld:has(> .jr-in > [data-jr="f-where"]) > small{flex:0 0 auto;margin:0}
.frame[data-screen="charge"] .jr-fld:has(> .jr-in > [data-jr="f-where"]) > .jr-in{flex:1 1 0;min-width:0}
.frame[data-screen="charge"] .jr-fld:has(> .jr-in > [data-jr="f-where"]) > .jr-fhint{flex:1 0 100%}
.frame[data-screen="charge"] .jr-in > [data-jr="f-where"]{font-size:16px;min-width:0;text-overflow:ellipsis}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known:not(:focus-within){background:color-mix(in srgb, var(--good) 8%, var(--card));
  border-color:color-mix(in srgb, var(--good) 55%, var(--line))}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known:not(:focus-within) :is(input,.jr-pre){color:var(--ink)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known:not(:focus-within) u{color:var(--good-ink)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known input::placeholder{color:var(--muted)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-in.known:not(:focus-within)::after{content:"\2713";flex:0 0 auto;font:800 15px/1 var(--body);color:var(--good)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-seg > span.on:not(#ypd-btn){background:color-mix(in srgb, var(--good) 8%, var(--card));
  color:var(--ink);border-color:color-mix(in srgb, var(--good) 55%, var(--line));box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--good) 55%, var(--line))}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-seg > span.on:not(#ypd-btn)::after{content:"\2713";margin-left:6px;color:var(--good)}
.frame[data-screen="charge"] .sttl > .stt{flex-wrap:nowrap;min-width:0}
.frame[data-screen="charge"] .sttl > .stt > .stt-t{flex:0 0 auto}
.frame[data-screen="charge"] .sttl .stchip.rsdoors{display:inline-flex;gap:4px;margin-left:auto;background:transparent;color:inherit;padding:0;
  overflow:visible;text-overflow:clip;max-width:100%;flex:0 0 auto}
.frame[data-screen="charge"] .sttl .rsdoors .rschip{background:var(--card);color:var(--ink);border:var(--btn-edge) solid var(--ink);
  border-radius:var(--btn-r);min-height:44px;padding:0 8px;font:var(--btn-fw) calc(var(--btn-fs-sm) * .92)/1.15 var(--body);
  letter-spacing:.02em;text-transform:var(--btn-case);display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;
  box-sizing:border-box;cursor:pointer;user-select:none;flex:0 0 auto}

/* ==================================================================================================
   b668, THE CHARGING STOP, ONE ROW AT A TIME (Ahmed 2026-10-29, bug-mvtrm1zk-69njk at 344 wide in a split screen, and
   bug-mvtshy57-clj9o at 829 wide)
   1. "it should be one row at a time because we're putting temperature and odometer together, I can't read the whole
      odometer". Under 600 wide every box on the stop has its own row, the odometer and the temperature too; wider, the pairs
      stay side by side, each wide enough for 63,285 and its MI.
   2. "Up here where it says saved 9:35 in the morning charging, that's all I need". The green SAVED line is one row and the
      OPEN for what is done (app-journal.js rollUp), 44 tall, OPEN at its end.
   3. "Put the save cost above favorites". Favorites sits under the save row, with a little air above it.
   ================================================================================================== */
@media (max-width:599px){
  .frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-fields{grid-template-columns:minmax(0,1fr)}
}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] [data-jr="charging"]{flex-direction:row;align-items:center;justify-content:space-between;
  gap:var(--sp-2);width:100%;min-height:44px;box-sizing:border-box;text-align:left;cursor:pointer;font:inherit;color:var(--good-deep);margin:0}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] [data-jr="charging"] > em{flex:0 0 auto;font:800 var(--fs-label) 'JetBrains Mono',monospace;
  font-style:normal;letter-spacing:.08em;color:var(--good-deep)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] > [data-jr="favrow"]{margin-top:var(--sp-3)}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] > [data-jr="sugg"]{margin-top:var(--sp-2)}
/* the longer SAVE (COST AND KWH) is never cut: where it and Cancel do not fit side by side, Cancel takes the next row */
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-btns{flex-wrap:wrap}
.frame[data-role="driver"] [data-jr="edit"][data-kind="stop"] .jr-btns > .cta:not(#ypd-btn){flex:1 0 auto;min-width:max-content;max-width:100%}

/* ==================================================================================================
   b677, THE KEY IN THE TITLE BAR ON A WIDE SHEET (Ahmed 2026-10-29, bug-mvtu6bs9-58w9t, the Fold open 829 x 612, approved
   mock 20261029-YPD-RideHead-Compare): "start the ride should be above and then next to it the name and then next to it
   trip info and share info, because there's enough room for it... that will free us some space."
   rsHeadPlace (app.html) moves 5 MIN AWAY and the ride key into .rshead-act at the front of the title row when the sheet
   is 600 or wider and the row still fits; .rshead-on on the sheet says it did. Then the "Ride" word goes (the key names the
   moment), and the full width button row goes unless its No signal line is showing. The keys are 48 high and as wide as
   their words, the orange primary and the white secondary as before (the colour rules read .cta and .ghost, not the row).
   Narrow phones never get the class, so 412 and 383 keep today's row. */
.fx-ride[data-role="driver"] .sttl > .stt > .rshead-act{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;min-width:0}
.frame[data-role="driver"] .rshead-act > .cta:not(#ypd-btn){flex:0 0 auto;width:auto;min-width:0;min-height:48px;height:48px;
  padding:0 16px;margin:0;white-space:nowrap;font-size:var(--btn-fs);line-height:1}
.rshead-act > .cta[hidden]{display:none!important}
.fx-ride[data-role="driver"] > .sheet.rshead-on > .shbar .stt-t{display:none!important}
.fx-ride[data-role="driver"] > .sheet.rshead-on > .fx-btnrow:not(:has(> .setstat:not([hidden]))){display:none!important}
/* the undo row sits straight under the bar then; one line, 44 tall, the UNDO keeps its 44 px tap (Ahmed: "I like that one,
   it just needs to be worded a little bit better", the words are rsPaint's "You tapped <step>") */
.fx-ride[data-role="driver"] > .sheet > .rsundo{padding-top:0;padding-bottom:0;min-height:44px}

/* ==================================================================================================
   b709, THE FIRST RUN TUTORIAL (app-tutorial.js, the approved YPD-TUTORIAL-MOCK-V1A). No new class, every piece found by its data
   attribute. The sheet sits between the header and the footer, the main button pinned under the words at the same height on every
   step. Buttons are the app's .cta, white on orange. The coach mark's spot is placed by the script from the real tile's rect.
   ================================================================================================== */
.frame > .sheet[data-kind="tutorial"]{position:absolute;left:0;right:0;top:calc(var(--hd-h) + 10px);bottom:var(--foot-h);margin:0;padding:0;max-height:none;z-index:30;
  display:flex;flex-direction:column;overflow:hidden}
.frame > .sheet[data-kind="tutorial"][hidden]{display:none!important}
@media (min-width:640px){ .frame > .sheet[data-kind="tutorial"]{left:var(--sheet-inset);right:var(--sheet-inset);top:calc(var(--hd-h) + var(--sheet-top))} }
.frame[data-tutopen] > .sheet:not([data-kind="tutorial"]){visibility:hidden}
.frame[data-tutopen] > .scr{filter:brightness(.62) saturate(.7);pointer-events:none}
.frame[data-tutopen] > .map{filter:brightness(.72) saturate(.8)}
.frame[data-tutopen] > .hd{pointer-events:none}
.frame[data-tutopen] > .foot .tab:not(.lbug){opacity:.45;pointer-events:none}
[data-tut="top"]{flex:0 0 auto;display:grid;grid-template-columns:44px 1fr auto;align-items:center;gap:4px;min-height:48px;padding:2px 6px 0}
[data-tut="back"]{width:44px;height:44px;border:0;background:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--ink)}
[data-tut="back"] svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
[data-tut="skip"]{min-height:44px;min-width:44px;border:0;background:none;padding:0 var(--sp-2);font:700 14px var(--body);color:#B82B00;cursor:pointer;white-space:nowrap}
[data-tut="dots"]{display:flex;gap:6px;justify-content:center;align-items:center;min-width:0}
[data-tut="dots"] i{display:block;flex:0 0 auto;width:8px;height:8px;border-radius:50%;background:var(--line)}
[data-tut="dots"] i[data-d="done"]{background:var(--ink)}
[data-tut="dots"] i[data-d="skip"]{background:transparent;box-shadow:inset 0 0 0 2px var(--orange)}
[data-tut="dots"] i[data-d="cur"]{width:20px;border-radius:4px;background:var(--orange)}
[data-tut="body"]{flex:1 1 auto;min-height:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding:6px 18px 10px;display:flex;flex-direction:column;gap:10px}
[data-tut="body"] > *{flex:0 0 auto;min-width:0}
[data-tut="body"] > .badge{align-self:flex-start}
[data-tut="btns"]{flex:0 0 auto;padding:var(--sp-2) 18px 14px;display:grid;gap:var(--sp-2);background:var(--card);border-top:1px solid var(--line)}
[data-tut="btns"] .cta{min-height:52px;font-size:16px}
[data-tut="btns"] .cta.ghost{min-height:44px;font-size:14px}
.sheet [data-tut="title"]{margin:0;font:700 24px/1.2 var(--body);color:var(--ink)}
[data-tut="line"]{margin:0;font-size:15px;line-height:1.4;color:var(--ink)}
[data-tut="quiet"]{margin:0;font-size:14px;line-height:1.35;color:var(--muted)}
[data-tut="say"]{margin:0;font-size:14px;font-weight:700;color:var(--red-ink)}
[data-tut="wrow"]{display:flex;gap:11px;align-items:flex-start}
[data-tut="wic"]{flex:0 0 38px;width:38px;height:38px;border-radius:50%;border:1.6px solid var(--line);display:flex;align-items:center;justify-content:center}
[data-tut="wic"] svg{width:19px;height:19px;fill:none;stroke:var(--orange);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
[data-tut="wrow"] b{display:block;font-size:15px}
[data-tut="wrow"] > div > span{display:block;font-size:14px;line-height:1.35;color:var(--muted)}
[data-tut="fld"]{display:grid;gap:4px}
[data-tut="fld"] label{font-size:13px;font-weight:700;color:var(--ink)}
[data-tut="homein"]{width:100%;min-height:52px;border:1.5px solid var(--line);border-radius:var(--r-input);padding:0 var(--sp-3);font:400 16px var(--body);color:var(--ink);background:var(--card);box-sizing:border-box}
[data-tut="list"]{border:1px solid var(--line);border-radius:var(--r-input);overflow:hidden}
[data-tut="list"] > div{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:44px;padding:0 var(--sp-3);font-size:14.5px;color:var(--ink)}
[data-tut="list"] > div + div{border-top:1px solid var(--line)}
[data-tut="tag"]{flex:0 0 auto;border-radius:var(--r-pill);padding:3px 10px;font-size:12px;font-weight:800;color:#FFFFFF;white-space:nowrap}
[data-tut="tag"][data-tone="good"]{background:var(--good-ink)}
[data-tut="tag"][data-tone="bad"]{background:var(--red-ink)}
[data-tut="tag"][data-tone="wait"]{background:var(--paper);color:var(--ink);border:1px solid var(--line)}
[data-tut="granted"]{display:flex;align-items:center;justify-content:center;min-height:44px;border-radius:var(--r-input);background:var(--good-ink);color:#FFFFFF;font-weight:800;font-size:15px}
[data-tut="disc"]{display:grid;gap:8px}
[data-tut="disc"] > div{font-size:14.5px;line-height:1.36;color:var(--ink)}
[data-tut="disc"] b{font-weight:700}
@media (max-width:380px){ .sheet [data-tut="title"]{font-size:22px} [data-tut="disc"]{gap:6px} [data-tut="disc"] > div{font-size:13.5px;line-height:1.32} }
/* wide and short, the open Fold: the two buttons side by side, the words get the height */
@media (min-aspect-ratio:6/5){ [data-tut="btns"]:has(> .cta + .cta){grid-template-columns:1fr 1fr;align-items:stretch} [data-tut="btns"] .cta.ghost{min-height:52px} }
/* the pictured Android steps, Android's own light look because they show Android and not YPD */
[data-tut="pics"]{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
[data-tut="pic"]{min-width:0}
[data-tut="pic"] > b{display:block;font-size:13px;line-height:1.25;margin:0 0 4px;color:var(--ink)}
[data-tut="pic"] > b i{font-style:normal;display:inline-block;width:19px;height:19px;border-radius:50%;background:var(--orange);color:#FFFFFF;text-align:center;line-height:19px;font-size:12px;margin-right:4px}
[data-an]{position:relative;height:96px;border-radius:9px;border:1px solid #E2E2E6;background:#F2F2F7;color:#1C1C1E;overflow:hidden;font-size:11px;line-height:1.25;padding:5px}
[data-anh]{font-weight:700;font-size:10.5px;color:#6B6B70;padding:0 2px 3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
[data-anr]{display:flex;align-items:center;justify-content:space-between;gap:5px;background:#FFFFFF;min-height:23px;padding:0 6px;border-bottom:1px solid #E2E2E6}
[data-anr="hot"]{outline:2px solid var(--orange);outline-offset:-2px;border-radius:5px;font-weight:700}
[data-antog]{flex:0 0 auto;position:relative;width:24px;height:14px;border-radius:7px;background:#3478F6}
[data-antog]::after{content:"";position:absolute;left:12px;top:2px;width:10px;height:10px;border-radius:50%;background:#FFFFFF}
[data-andlg]{position:absolute;left:6px;right:6px;bottom:5px;background:#FFFFFF;border-radius:8px;padding:5px 7px;box-shadow:0 1px 6px rgba(0,0,0,.28)}
[data-anacts]{display:flex;justify-content:flex-end;gap:var(--sp-2);margin-top:3px;font-weight:700;color:#6B6B70}
[data-anacts] u{text-decoration:none;color:#1C1C1E;outline:2px solid var(--orange);border-radius:4px;padding:0 5px}
/* the Uber scene, the sample card and a picture of an Uber offer under it */
[data-tut="scene"]{position:relative;border-radius:var(--r-input);border:1px solid var(--line);background:#E3E1DA;padding:10px 10px 10px 40px;display:grid;gap:var(--sp-2);overflow:hidden}
[data-tut="bub"]{position:absolute;left:0;top:18px;width:34px;height:40px;border-radius:0 18px 18px 0;background:var(--orange);color:#FFFFFF;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:800}
[data-tut="ucard"]{background:#FFFFFF;border-radius:10px;padding:7px 10px;font-size:13px;color:#0A0A0A}
[data-tut="ucard"] em{font-style:normal;background:#0A0A0A;color:#FFFFFF;font-size:11px;font-weight:700;padding:1px 6px;border-radius:4px}
[data-tut="ucard"] b{display:block;font-size:19px;line-height:1.2;margin-top:2px}
[data-tut="ucard"] i{display:block;margin-top:5px;height:22px;border-radius:6px;background:#0A0A0A}
/* the sliders are the Uber sheet's own, here without their ON / OFF, one job per screen */
[data-tut="uberbox"] .ub-live{padding:var(--sp-2) 10px;min-width:0}
[data-tut="uberbox"] [data-ubrow] .bk-seg{display:none}
[data-tut="uberbox"] [data-ubrow]{display:block;margin:0;padding:0;border:0}
[data-tut="uberbox"] [data-ubrow] .ub-rl{font-weight:700;font-size:14px;line-height:18px;color:var(--ink)}
.fx-uber[data-tut="uberbox"] [data-ubdual]{height:71px;margin:-6px 0 0}
[data-step="mins"]{gap:6px}
[data-step="mins"] .ub-live .ub-line{display:none}
[data-step="mins"] [data-tut="sample"]{margin-top:var(--sp-1)}
/* coach marks: the scrim is the spot's own shadow, the frame clips it, the taps stop at the cover */
.frame > [data-tut="coach"]{position:absolute;inset:0;z-index:40;overflow:hidden}
.frame[data-tutopen]:has(> [data-tut="coach"]) > .scr{filter:none}   /* the lit tile is its real self, the scrim does the dimming */
[data-tut="spot"]{position:absolute;border-radius:16px;box-shadow:0 0 0 3px var(--orange),0 0 0 2400px rgba(10,10,10,.74);pointer-events:none}
[data-tut="ccard"]{position:absolute;box-sizing:border-box;margin:0;background:var(--card);border-radius:18px;padding:var(--sp-3) 14px;display:grid;gap:7px;box-shadow:0 8px 26px rgba(10,10,10,.34)}
[data-tut="ccard"] .badge{justify-self:start}
[data-tut="ccard"] .cta{min-height:52px;font-size:16px}
[data-tut="ctop"]{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);min-height:44px;margin:-6px -6px -4px 0}
[data-tut="ctitle"]{margin:0;font:700 19px/1.2 var(--body);color:var(--ink)}
/* Finish setup, last in the grid, an orange edge on a white tile */
.tile[data-tut-tile]{border:2px solid var(--orange);cursor:pointer}
.tile[data-tut-tile][hidden]{display:none!important}
/* the Home card, under the tiles, and the line that says where it went */
[data-tut="homecard"]{display:grid;grid-template-columns:minmax(0,1fr) auto 44px;align-items:center;gap:6px;padding:6px 4px 6px var(--sp-3);margin:0}
[data-tut="homecard"][hidden],[data-tut="homesay"][hidden]{display:none!important}
[data-tut="homecard"] b{display:block;font-size:15px;color:var(--ink)}
[data-tut="homecard"] > div > span{display:block;font-size:13px;color:var(--muted)}
[data-tut="open"]{width:auto;min-height:44px;padding:0 13px;font:800 14px var(--body)}
[data-tut="hx"]{width:44px;height:44px;border:0;background:none;padding:0;font-size:20px;line-height:1;color:var(--ink);cursor:pointer}
[data-tut="homesay"]{font-size:14px;font-weight:700;color:var(--good-ink);text-align:center}
/* the Settings row that carries the switch */
.fx-set [data-tutrow="card"] .mbl{flex:0 0 auto;margin:0}
.fx-set [data-tutrow="card"] .mbl .mbsw{min-width:96px;min-height:44px;padding:0}
/* ==============================================================================================
   b720: DRIVER HOME V2 (Ahmed 2026-11-02, option 1 of DRIVER-HOME-V2-MOCKUP-V1A, "Build as shown"). Only the two driver Home frames
   carry data-hv2, every other screen keeps the full shell.
   1. The header keeps the fare pill alone in the centre: his own pill top left goes (the Online card already says he is on), the
      rider's pill top right goes (the rider card already shows them). The fold-all button stays on the right, it is how the cards open.
   2. All cards closed, the top row is four equal cards: Online, the car, the rider (his photo and live dot, PICKUP under the name), the
      hand off. A missing card lets the others share the row, no gap. RIDE FINISHED and RECEIPTS TO SEND (b717) are cards of the same
      size after them, wrapping to a second row, never wider than half. No arrows on the closed cards, as the mock: each card's own
      tap still does what it did (the rider opens the ride, the hand off opens itself, RIDE FINISHED and RECEIPTS open the receipt).
   3. The tiles in two labelled rows, Free (bigger) then With your plan (smaller, orange), each row sharing its width.
   ============================================================================================== */
.frame[data-hv2][data-screen="home"][data-role="driver"] > .hd > .chip,
.frame[data-hv2][data-screen="home"][data-role="driver"] > .hd > [data-hchd] > .chip{display:none!important}

/* the top row, all closed */
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"]{display:flex;flex-direction:row;flex-wrap:wrap;align-items:stretch;gap:12px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > :is(.card,.mo-panel[data-rc="panel"]),
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-handed] > .card{flex:1 1 calc(25% - 9px);min-width:0;max-width:none;margin:0;order:0;box-sizing:border-box;min-height:58px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > :is(.card[data-hm="lastride"],.mo-panel[data-rc="panel"]),
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-handed] > .card[data-hcfold]{max-width:calc(50% - 6px)}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-handed] > .card[data-hcfold]{order:1}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card[data-hm="lastride"]{order:2}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .mo-panel[data-rc="panel"]{order:3}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-nophone]{order:4;flex:1 1 100%}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-handed] > .card:not([data-hcfold]){order:5;flex:1 1 100%;max-width:none}
/* no ride painted, no rider card */
body:not([data-hasride="1"]) .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc{display:none!important}
/* no arrows drawn on the three, as the mock, and each still opens on its own (b692): its arrow is a 44px target laid over the picture,
   so a tap on the face, the car or the rider's photo opens that card, the pill and the rest of the rider card do what they did.
   The hand off and RIDE FINISHED keep their drawn arrows (b713, b717), they have the room. */
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]{position:relative}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] > [data-hcchev]{display:block!important;position:absolute;left:8px;top:calc(50% - 22px);
  width:44px;height:44px;flex:none;margin:0;padding:0;border:0;border-radius:50%;background:transparent;opacity:0;z-index:1}
/* Online and the car: the picture and the pill or the plate, no name */
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:nth-child(1),:nth-child(2)){flex:1 1 calc(25% - 9px);gap:10px;padding:6px 10px!important}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:nth-child(1),:nth-child(2)) > .hc-nm{display:none!important}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] > .hc-av{display:block!important;position:relative;width:40px;height:40px;flex:0 0 40px;pointer-events:none}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] > .hc-av > .avatar-lg{width:40px;height:40px;font-size:14px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] .hc-platebox{pointer-events:none}
/* TAP AGAIN TO GO OFFLINE (b692) is the longest the pill gets: for its three seconds it takes the picture's room and wraps inside the card */
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:has([data-hctog="arm"]) > :is(.hc-av,[data-hcchev]){display:none!important}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] > .hc-l2{min-width:0;max-width:100%}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] .hc-l2 [data-hctog="arm"]{max-width:100%;white-space:normal}
/* the live dot on the driver's and the rider's picture */
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:has([data-pres="self"]),.tapcard) > .hc-av::after{content:"";position:absolute;right:-2px;bottom:-2px;
  width:13px;height:13px;box-sizing:border-box;border-radius:50%;border:2px solid var(--card);background:var(--red)}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:has([data-hctog="on"],[data-hctog="arm"]) > .hc-av::after,
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]:has([data-pres="pax"].good) > .hc-av::after{background:var(--good)}
/* the rider: picture, name, PICKUP 3:40 under it, a RETURN chip on the right when it is one */
[data-hcpick]{display:none}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]{display:grid!important;grid-template-columns:40px minmax(0,1fr) auto;grid-template-rows:auto auto;
  column-gap:10px;row-gap:1px;align-items:center;align-content:center;padding:6px 10px!important;flex:1 1 calc(25% - 9px);min-width:0}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > .hc-av{grid-column:1;grid-row:1 / span 2}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > .hc-nm{grid-column:2;grid-row:1;align-self:end;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:16px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]:not(:has(> [data-hcpick]:not([hidden]))) > .hc-nm{grid-row:1 / span 2;align-self:center}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > [data-hcpick]:not([hidden]){display:block;grid-column:2;grid-row:2;align-self:start;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:700 11px/1.2 'JetBrains Mono',monospace;letter-spacing:.02em;color:var(--muted)}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > [data-hcttl]{grid-column:3;grid-row:1 / span 2}
.frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > .hc-l2{display:none!important}

/* the two tile rows */
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools{display:flex;flex-wrap:wrap;align-items:stretch;gap:8px}
/* the label: a full width line so the row breaks there, the driver frames' own label chip inside it (b504, b510) */
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > [data-tgrp]{flex:0 0 100%;display:block;margin:2px 0 -2px;line-height:1}
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > [data-tgrp] > .fx-mono{display:inline-block;letter-spacing:.1em}
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile{flex:1 1 0;min-width:0;margin:0;justify-content:center;box-sizing:border-box}
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile:not([data-paid]){min-height:104px;gap:8px}
/* one label size on every tile, b697's 12px; bigger and smaller is the tile and its picture */
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile:not([data-paid]) .ic{width:52px;height:52px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile[data-paid]{min-height:84px;gap:6px;padding-block:8px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile[data-paid] .ic{width:38px;height:38px}
.frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile[data-paid] .ic svg{width:19px;height:19px}
@media (max-width:560px){
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > :is(.card,.mo-panel[data-rc="panel"]),
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-handed] > .card,
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:nth-child(1),:nth-child(2)),
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]{flex-basis:calc(50% - 6px)}
  /* half a phone is 175 wide: the picture and the pill a little tighter, so ONLINE fits whole */
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold]:is(:nth-child(1),:nth-child(2)){gap:8px;padding:6px 8px!important}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] > .hc-av,
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] > .hc-av > .avatar-lg{width:36px;height:36px;flex-basis:36px}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]{grid-template-columns:36px minmax(0,1fr) auto}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] .hc-l2 [data-hctog]{font-size:14px;gap:5px;padding:0 10px 0 5px}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] .hc-l2 [data-hctog="off"]{padding:0 5px 0 10px}
  /* a phone: three a row in both, every label on one line at the 12px floor (b697, the closed Fold at 344); the free ones stay the taller */
  .frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile{flex:0 0 calc((100% - 16px) / 3)}
}
/* the closed Fold's cover screen, 344 wide: the rider card gives its picture to the name, as b713 did, so the name stays whole */
@media (max-width:380px){
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]{grid-template-columns:0 minmax(0,1fr) auto;column-gap:0;padding:6px 8px!important}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > .hc-nm{font-size:15px}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold] > .hc-av{display:none!important}
  /* the hand off needs NEEDS A DRIVER and its arrow whole, so beside the rider it keeps b713's 176 and the rider takes the rest */
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > [data-handed] > .card[data-hcfold]{flex:1 0 176px;max-width:none}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.tapcard.hc[data-hcfold]{flex:1 1 112px}
  /* and the switch drops its knob, so OFFLINE fits beside his picture in a 152px card */
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] .hc-l2 [data-hctog] > [data-hcknob]{display:none}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .cards3[data-hcfolds="all"] > .card.hc[data-hcfold] .hc-l2 [data-hctog]{padding:0 12px!important}
}
/* the unfolded Fold, 1298 by 1080: fitZoom already scales the whole page there, the tiles only take some of the height it has to spare, as the mock */
@media (min-width:561px) and (min-height:900px){
  .frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile:not([data-paid]){min-height:124px}
  .frame[data-hv2][data-screen="home"][data-role="driver"] .tools > .tile[data-paid]{min-height:100px}
}
