/* =============================================================================
   EXPRESS THEME — 4-step booking funnel (wizard_layout = express-4-step)
   =============================================================================

   Same approach as meridian.css: a value-level reskin of
   resources/css/atelier.css with every selector rescoped from .atelier-root
   to .express-root, so the copied Atelier step Blades (same .gv-* DOM
   contract, same bindings) render unchanged. The token block takes the
   palette and type from the visual reference
   gvbooking-specs/four-step-wizard/prototype.html (light only — no dark
   mode): navy ink and action colour, yellow highlight. Type comes from the
   tenant's font preset (Phase 2i, see "Font presets" below).

   Token roles keep Atelier's meaning so the tenant Branding colour lands the
   same way (ThemeColorTokens maps accent => ['--accent']): --accent is the
   action colour (CTA, selected, focus) and defaults to the prototype's navy
   CTA. The prototype's yellow is --hl, the tenant's second Branding colour
   (ThemeColorTokens maps primary => ['--hl']). It is used only for the trip
   pass header and the completed-step marks (desktop pills, mobile segments).
   Decorative amber elsewhere uses the fixed --xp-amber.

   --accent-ink / --hl-ink are the readable text colours on --accent / --hl.
   The express shell Blade computes both (WCAG relative luminance: dark ink
   or white, whichever contrasts more) and sets them inline on .express-root,
   so they track the tenant colours; the values below are fallbacks.

   --xp-canvas is the page canvas, the tenant's third Branding colour
   (ThemeColorTokens maps background => ['--xp-canvas'], Phase 2e). It is
   separate from --bg so the fills that read --bg (mobile trip sheet,
   vehicle art) keep their colour. --page-ink / --page-ink-muted are the
   text colours for everything that sits directly on the canvas; the shell
   computes them from the effective canvas (see the Phase 2e block at the
   bottom of this file).

   The 4-step chrome (stepper, trip pass, mobile total bar, step-specific
   overrides) is appended at the bottom of this file under "Express 4-step
   chrome".
   ============================================================================= */

/* Phase 2i: fonts are no longer imported here. The express shell Blade
   loads only the tenant's chosen font preset (booking_site_settings.
   font_style) with one Google Fonts <link>, and sets data-font on
   .express-root; the preset blocks below map it to the --xp-font-* vars. */

/* -----------------------------------------------------------------------------
   Font presets (Phase 2i). One block per BookingSiteSettings::FONT_STYLES key.
   Also matched on <body> so elements outside .express-root (payment modal,
   powered-by line) read the same vars.
     --xp-font-body      everything else
     --xp-font-display   step headings, brand name + mark, vehicle names,
                         section titles
     --xp-font-price     card prices, trip pass amounts, fare total, mobile
                         bar total, numeric trip stats
     --xp-display-scale / --xp-price-scale multiply the sizes that were set
     for the old condensed display serif.
   -------------------------------------------------------------------------- */
.express-root[data-font="modern"],
body:has(.express-root[data-font="modern"]) {
    --xp-font-body: 'Plus Jakarta Sans', system-ui, sans-serif;
    --xp-font-display: 'Plus Jakarta Sans', system-ui, sans-serif;
    --xp-font-price: 'Plus Jakarta Sans', system-ui, sans-serif;
    --xp-display-weight: 800;
    --xp-display-track: -0.025em;
    --xp-price-weight: 800;
    --xp-price-track: -0.02em;
    --xp-display-scale: 0.78;
    --xp-price-scale: 0.76;
}
.express-root[data-font="executive"],
body:has(.express-root[data-font="executive"]) {
    --xp-font-body: 'Manrope', system-ui, sans-serif;
    --xp-font-display: 'Manrope', system-ui, sans-serif;
    --xp-font-price: 'Manrope', system-ui, sans-serif;
    --xp-display-weight: 800;
    --xp-display-track: -0.03em;
    --xp-price-weight: 800;
    --xp-price-track: -0.02em;
    --xp-display-scale: 0.78;
    --xp-price-scale: 0.76;
}
.express-root[data-font="classic"],
body:has(.express-root[data-font="classic"]) {
    --xp-font-body: 'DM Sans', system-ui, sans-serif;
    --xp-font-display: 'Lora', Georgia, serif;
    --xp-font-price: 'Lora', Georgia, serif;
    --xp-display-weight: 600;
    --xp-display-track: -0.01em;
    --xp-price-weight: 600;
    --xp-price-track: 0;
    --xp-display-scale: 0.80;
    --xp-price-scale: 0.78;
}
.express-root[data-font="luxury"],
body:has(.express-root[data-font="luxury"]) {
    --xp-font-body: 'Montserrat', system-ui, sans-serif;
    --xp-font-display: 'Cormorant Garamond', Georgia, serif;
    --xp-font-price: 'Montserrat', system-ui, sans-serif;
    --xp-display-weight: 700;
    --xp-display-track: 0;
    --xp-price-weight: 600;
    --xp-price-track: -0.01em;
    --xp-display-scale: 0.94;
    --xp-price-scale: 0.68;
}
/* Phase 4a: the Atelier style's default preset (any style may pick it). */
.express-root[data-font="atelier"],
body:has(.express-root[data-font="atelier"]) {
    --xp-font-body: 'Geist', system-ui, sans-serif;
    --xp-font-display: 'Fraunces', Georgia, serif;
    --xp-font-price: 'Fraunces', Georgia, serif;
    --xp-display-weight: 500;
    --xp-display-track: -0.01em;
    --xp-price-weight: 500;
    --xp-price-track: -0.02em;
    --xp-display-scale: 0.86;
    --xp-price-scale: 0.86;
}
/* Shared Atelier partials rendered inside express (receipt, thank-you,
   payment modal) still read --serif / --sans; point them at the preset. */
.express-root,
body:has(.express-root) {
    --serif: var(--xp-font-display, Georgia, serif);
    --sans: var(--xp-font-body, system-ui, sans-serif);
}

/* -----------------------------------------------------------------------------
   Tokens (CSS custom properties)
   -------------------------------------------------------------------------- */
:root {
    --bg: #F4F5F7;
    --surface: #ffffff;
    --surface-soft: #F4F5F7;
    --ink: #0F1B2D;
    --ink-soft: #465263;
    --ink-muted: #6B7686;
    --line: #DCE0E5;
    --line-2: #C3CAD3;
    --accent: #0F1B2D;
    --accent-soft: #FCF1C9;
    --accent-bg: #FCF1C9;
    --gold: #9A7404;
    --green: #17663F;
    --err: #B42318;
    --hl: #F2B705;
    --hl-ink: #0F1B2D;
    --hl-soft: #FCF1C9;
    --accent-ink: #FFFFFF;
    --xp-amber: #F2B705;
    --page: #E6E9EC;
    --xp-canvas: #F4F5F7;
    --page-ink: #0F1B2D;
    --page-ink-muted: #465263;
    --page-ink-inverse: #FFFFFF;
    --page-line: #C3CAD3;
    --page-line-soft: #DCE0E5;
    --shadow-sm: 0 1px 2px rgba(15, 27, 45, 0.05), 0 0 0 1px rgba(15, 27, 45, 0.04);
    --shadow-md: 0 4px 16px rgba(15, 27, 45, 0.07), 0 0 0 1px rgba(15, 27, 45, 0.04);
    --shadow-lg: 0 1px 0 rgba(15, 27, 45, 0.05), 0 20px 44px -26px rgba(15, 27, 45, 0.45);
    --shadow-card-hover: 0 16px 48px rgba(15, 27, 45, 0.14), 0 0 0 1px rgba(15, 27, 45, 0.06);
    --shadow-focus: 0 0 0 4px rgba(15, 27, 45, 0.12), 0 0 0 1px var(--accent);
    --radius: 12px;
    --radius-sm: 10px;
    --radius-lg: 18px;

    /* Same single-source pay-CTA token as Atelier. */
    --gv-pay-cta-bg: var(--ink);

    /* Payment modal tokens (unchanged roles from Atelier). */
    --gv-modal-backdrop: rgba(15, 27, 45, 0.55);
    --gv-z-modal: 100;

    color-scheme: light;
}

/* -----------------------------------------------------------------------------
   Panel tokens (Phase 3a). booking_site_settings.panel_style sets
   data-panels="light|dark" on .express-root (the shell Blade); also matched
   on <body> so the payment modal and the other unscoped pieces read them.
   Every panel fill, panel border and text-on-panel colour in this file
   reads one of these. Light values are exactly the values the light
   panels used before Phase 3a; dark values come from the approved dark
   palette. Text placed directly on the canvas keeps --page-ink*.
     --xp-panel / -2 / -line / -line-2   card fill, raised fill, hairlines
     --xp-panel-ink / -ink-2 / -muted    text on panels
     --xp-panel-hover / -glass           hover fill, translucent overlay fill
     --xp-hover-tint                     icon-button hover wash
     --xp-field-*                        input fill, border, placeholder
     --xp-tile / -tile-2 / -tile-ink     vehicle image tiles (light in both
     --xp-tile-glass                     finishes; silhouettes stay dark)
     --xp-header-* / --xp-bar-*          header band, mobile bottom bar
     --xp-seg-idle                       inactive mobile step segments
     --xp-badge-* / --xp-error / -success
     --xp-vcard-*                        Step 2 vehicle card border + text
     --xp-inverse-*                      ink-filled buttons (Done, Pay with
                                         card, brand mark, Edit trip)
     --xp-strip-*                        trust strip (dark in both finishes)
     --xp-on-status / --xp-iframe-bg     text on green fills, hosted-page
                                         iframe backdrop (white in both)
     --xp-amber-ink                      text on the fixed amber
     --xp-promo-ok / -err                promo code feedback
     --xp-map-art-1 / -2 / --xp-map-solid  map placeholder behind the map
   The dark block also points the legacy Atelier tokens (--surface, --ink,
   --line, ...) at the panel tokens, so shared partials rendered inside
   express (fare breakdown, custom fields) follow the panel finish.
   --xp-panel-ref, --xp-focus and --xp-link are computed in the shell
   (contrast against the panel colour) and set inline on .express-root.
   -------------------------------------------------------------------------- */
.express-root[data-panels="light"],
body:has(.express-root[data-panels="light"]) {
    --xp-panel-ref: #FFFFFF;
    --xp-panel: #FFFFFF;
    --xp-panel-2: #F4F5F7;
    --xp-panel-line: #DCE0E5;
    --xp-panel-line-2: #C3CAD3;
    --xp-panel-ink: #0F1B2D;
    --xp-panel-ink-2: #465263;
    --xp-panel-muted: #6B7686;
    --xp-panel-hover: #F6F3EC;
    --xp-panel-glass: rgba(255, 255, 255, 0.94);
    --xp-hover-tint: rgba(0, 0, 0, 0.05);
    --xp-field-bg: #FFFFFF;
    --xp-field-bg-hover: #FAFBFC;
    --xp-field-border: #7A8596;
    --xp-field-border-hover: #465263;
    --xp-field-placeholder: #5F6B7A;
    --xp-tile: #EEF1F5;
    --xp-tile-2: #F4F5F7;
    --xp-tile-ink: #0F1B2D;
    --xp-tile-glass: rgba(255, 255, 255, 0.95);
    --xp-header-bg: #FFFFFF;
    --xp-header-line: #DCE0E5;
    --xp-bar-bg: #FFFFFF;
    --xp-bar-line: #DCE0E5;
    --xp-seg-idle: var(--page-line-soft);
    --xp-badge-best-bg: #E3F1E8;
    --xp-badge-best-ink: #17663F;
    --xp-badge-space-bg: #EAF0F7;
    --xp-badge-space-ink: #24456E;
    --xp-error: #B42318;
    --xp-success: #17663F;
    --xp-vcard-line: #D5DAE1;
    --xp-vcard-line-hover: #8A94A3;
    --xp-vcard-desc: #5F6B7A;
    --xp-vcard-cap: #2B3646;
    --xp-inverse-bg: #0F1B2D;
    --xp-inverse-bg-hover: #000000;
    --xp-inverse-ink: #F4F5F7;
    --xp-inverse-ink-soft: rgba(245, 243, 238, 0.6);
    --xp-strip-solid: #0F1B2D;
    --xp-strip-ink: #F4F5F7;
    --xp-on-status: #FFFFFF;
    --xp-iframe-bg: #FFFFFF;
    --xp-amber-ink: #0F1B2D;
    --xp-badge-info-ink: #4A6DA7;
    --xp-badge-warn-ink: #9C7726;
    --xp-attention-ink: #6F5A1D;
    --xp-promo-ok: #1A7F37;
    --xp-promo-err: #C0362C;
    --xp-map-art-1: #E8DDD0;
    --xp-map-art-2: #D4C4B0;
    --xp-map-solid: #0F1B2D;
}
.express-root[data-panels="dark"],
body:has(.express-root[data-panels="dark"]) {
    --xp-panel-ref: #17191E;
    --xp-panel: #17191E;
    --xp-panel-2: #1F2229;
    --xp-panel-line: #2C3038;
    --xp-panel-line-2: #3A3F49;
    --xp-panel-ink: #F3F1EC;
    --xp-panel-ink-2: #C8CBD1;
    --xp-panel-muted: #A9ADB6;
    --xp-panel-hover: #23262D;
    --xp-panel-glass: rgba(23, 25, 30, 0.94);
    --xp-hover-tint: rgba(255, 255, 255, 0.08);
    --xp-field-bg: #0F1114;
    --xp-field-bg-hover: #13161A;
    --xp-field-border: #4A505B;
    --xp-field-border-hover: #6B7280;
    --xp-field-placeholder: #8A8F99;
    --xp-tile: #E4E0D8;
    --xp-tile-2: #E4E0D8;
    --xp-tile-ink: #0F1B2D;
    --xp-tile-glass: rgba(255, 255, 255, 0.95);
    --xp-header-bg: #0E0F12;
    --xp-header-line: #23262D;
    --xp-bar-bg: #17191E;
    --xp-bar-line: #2C3038;
    --xp-seg-idle: #2C3038;
    --xp-badge-best-bg: rgba(74, 190, 120, 0.16);
    --xp-badge-best-ink: #8EE0AE;
    --xp-badge-space-bg: rgba(120, 160, 230, 0.18);
    --xp-badge-space-ink: #B4CCF5;
    --xp-error: #FF8A80;
    --xp-success: #8EE0AE;
    --xp-vcard-line: #2C3038;
    --xp-vcard-line-hover: #4A505B;
    --xp-vcard-desc: #A9ADB6;
    --xp-vcard-cap: #C8CBD1;
    --xp-inverse-bg: #F3F1EC;
    --xp-inverse-bg-hover: #FFFFFF;
    --xp-inverse-ink: #17191E;
    --xp-inverse-ink-soft: rgba(23, 25, 30, 0.6);
    --xp-strip-solid: #0F1B2D;
    --xp-strip-ink: #F4F5F7;
    --xp-on-status: #FFFFFF;
    --xp-iframe-bg: #FFFFFF;
    --xp-amber-ink: #0F1B2D;
    --xp-badge-info-ink: #B4CCF5;
    --xp-badge-warn-ink: #E8C77A;
    --xp-attention-ink: #E8C77A;
    --xp-promo-ok: #8EE0AE;
    --xp-promo-err: #FF8A80;
    --xp-map-art-1: #1F2229;
    --xp-map-art-2: #17191E;
    --xp-map-solid: #0E0F12;

    /* Legacy Atelier tokens follow the dark panels (shared partials). */
    --surface: var(--xp-panel);
    --surface-soft: var(--xp-panel-2);
    --ink: var(--xp-panel-ink);
    --ink-soft: var(--xp-panel-ink-2);
    --ink-muted: var(--xp-panel-muted);
    --line: var(--xp-panel-line);
    --line-2: var(--xp-panel-line-2);
    --err: var(--xp-error);
}

/* -----------------------------------------------------------------------------
   Atelier style tokens (Phase 4a). booking_site_settings.wizard_style sets
   data-style="express|atelier" on .express-root (the shell Blade); also
   matched on <body> like data-font / data-panels. Declared AFTER the font
   and panel blocks so it wins at equal specificity. These values replace
   the light panel values; with dark panels the Atelier dark block below
   (Phase 4b) replaces them in turn. The shell also sets the Atelier default
   --accent / --hl / --xp-canvas inline (a tenant colour replaces them) and
   computes --accent-ink, --page-ink*, --xp-focus, --xp-link and
   --xp-link-canvas against those defaults.
     --xp-panel-muted #6E6C66   Atelier's #9A9A96 darkened to reach 4.5:1
                                on #FFFFFF (5.25), #FAF8F3 (4.95) and the
                                #F5F3EE canvas (4.73); Phase 4b
     --xp-field-border #958E82  3.25:1 on white, so fields stay visible
     --xp-rcpt-head-*           trip summary header band (Phase 4b)
   The legacy Atelier tokens (--ink, --line, ...) follow, for the shared
   partials rendered inside express (fare breakdown, custom fields).
   -------------------------------------------------------------------------- */
.express-root[data-style="atelier"],
body:has(.express-root[data-style="atelier"]) {
    --xp-canvas: #F5F3EE;
    --bg: #F5F3EE;
    --xp-panel: #FFFFFF;
    --xp-panel-2: #FAF8F3;
    --xp-panel-line: #E8E4DC;
    --xp-panel-line-2: #D9D3C7;
    --xp-panel-ink: #1A1A1A;
    --xp-panel-ink-2: #5A5A58;
    --xp-panel-muted: #6E6C66;
    --xp-panel-hover: #F6F3EC;
    --xp-hover-tint: rgba(26, 26, 26, 0.05);
    --xp-field-bg: #FAF8F3;
    --xp-field-bg-hover: #F6F3EC;
    --xp-field-border: #958E82;
    --xp-field-border-hover: #77756F;
    --xp-field-placeholder: #6E6C66;
    --xp-tile: #F0EBE0;
    --xp-tile-2: #F0EBE0;
    --xp-header-bg: #FFFFFF;
    --xp-header-line: #E8E4DC;
    --xp-bar-bg: #FFFFFF;
    --xp-bar-line: #E8E4DC;
    --xp-seg-idle: #E8E4DC;
    --xp-badge-best-bg: rgba(74, 122, 77, 0.12);
    --xp-badge-best-ink: #3F6B42;
    --xp-badge-space-bg: rgba(176, 138, 62, 0.14);
    --xp-badge-space-ink: #8A6A2B;
    --xp-success: #4A7A4D;
    --green: #4A7A4D;
    --gold: #B08A3E;
    --xp-amber: var(--accent);
    --xp-vcard-desc: #5A5A58;
    --xp-vcard-cap: #3A3936;
    --xp-inverse-bg: #1A1A1A;
    --xp-inverse-ink: #F5F3EE;
    --xp-inverse-ink-soft: rgba(245, 243, 238, 0.6);
    --xp-rcpt-head-bg: #1A1A1A;
    --xp-rcpt-head-ink: #F5F3EE;
    --page-line: #D9D3C7;
    --page-line-soft: #E8E4DC;
    --radius: 14px;
    --radius-lg: 20px;
    --radius-sm: 10px;
    --shadow-sm: 0 1px 2px rgba(26, 26, 26, 0.04), 0 0 0 1px rgba(26, 26, 26, 0.04);
    --shadow-md: 0 4px 16px rgba(26, 26, 26, 0.06), 0 0 0 1px rgba(26, 26, 26, 0.04);
    --shadow-lg: 0 12px 48px rgba(26, 26, 26, 0.10), 0 0 0 1px rgba(26, 26, 26, 0.04);
    --shadow-card-hover: 0 16px 48px rgba(26, 26, 26, 0.14), 0 0 0 1px rgba(26, 26, 26, 0.06);
    --gv-modal-backdrop: rgba(26, 26, 26, 0.55);

    --surface: var(--xp-panel);
    --surface-soft: var(--xp-panel-2);
    --ink: var(--xp-panel-ink);
    --ink-soft: var(--xp-panel-ink-2);
    --ink-muted: var(--xp-panel-muted);
    --line: var(--xp-panel-line);
    --line-2: var(--xp-panel-line-2);
}

/* -----------------------------------------------------------------------------
   Atelier style + dark panels (Phase 4b): warm near-black. Matches both
   attributes, so it wins over the Atelier block above and the dark panel
   block (which it otherwise follows: tokens not set here keep the Atelier
   or dark panel value). The shell sets the matching inline values: canvas
   #13110F when no tenant background, panel ref #1C1916, focus fallback
   #F5F3EE, link / canvas-link fallback #E58A6F, done-step --hl #6FA373.
     vehicle tiles stay light (#EDE7DC -> #D8CFBE) and the glass badges
     keep their light values; --xp-on-status is near-black because white
     on #6FA373 is only 2.93:1 (#13110F on it is 6.42:1).
   -------------------------------------------------------------------------- */
.express-root[data-style="atelier"][data-panels="dark"],
body:has(.express-root[data-style="atelier"][data-panels="dark"]) {
    --xp-canvas: #13110F;
    --bg: #13110F;
    --xp-header-bg: #13110F;
    --xp-header-line: #2A2622;
    --xp-panel: #1C1916;
    --xp-panel-2: #24201C;
    --xp-panel-line: #34302A;
    --xp-panel-line-2: #443E36;
    --xp-panel-ink: #F5F3EE;
    --xp-panel-ink-2: #CFC8BC;
    --xp-panel-muted: #A39C90;
    --xp-panel-hover: #2A2622;
    --xp-panel-glass: rgba(28, 25, 22, 0.94);
    --xp-hover-tint: rgba(245, 243, 238, 0.08);
    --xp-field-bg: #15130F;
    --xp-field-bg-hover: #1A1814;
    --xp-field-border: #746D61;
    --xp-field-border-hover: #8A8276;
    --xp-field-placeholder: #A39C90;
    --xp-tile: #EDE7DC;
    --xp-tile-2: #EDE7DC;
    --xp-tile-ink: #1A1A1A;
    --xp-bar-bg: #1C1916;
    --xp-bar-line: #34302A;
    --xp-seg-idle: #34302A;
    --xp-success: #6FA373;
    --green: #6FA373;
    --xp-on-status: #13110F;
    --xp-vcard-desc: #A39C90;
    --xp-vcard-cap: #CFC8BC;
    --xp-inverse-bg: #F5F3EE;
    --xp-inverse-bg-hover: #FFFFFF;
    --xp-inverse-ink: #1A1A1A;
    --xp-inverse-ink-soft: rgba(26, 26, 26, 0.6);
    --xp-rcpt-head-bg: #2A2622;
    --xp-rcpt-head-ink: #F5F3EE;
    --xp-error: #FF8A80;
    --xp-promo-ok: #9FD0A2;
    --xp-promo-err: #FF8A80;
    --xp-map-art-1: #24201C;
    --xp-map-art-2: #1C1916;
    --xp-map-solid: #13110F;
}

/* Phase C — mobile sheet handle. Declaration only; the payment modal's
   sheet variant on max-width: 768px consumes this. */
.gv-sheet-handle {
    width: 36px;
    height: 4px;
    background: var(--xp-panel-muted);
    border-radius: 999px;
    margin: 12px auto 8px;
}

/* -----------------------------------------------------------------------------
   Booking layout component overrides (Classic chrome neutralized for Atelier)
   -------------------------------------------------------------------------- */
/* Session 15.1.6 Fix C — reset the UA body margin for Atelier.
   The classic-only reset `html, body { margin: 0; padding: 0 }` lives
   inside the `@unless($isAtelier)` block in
   resources/views/components/layouts/booking.blade.php, so Atelier
   tenants retain UA Chrome/Safari default body { margin: 8px }.
   Effect: every "full-bleed" Atelier surface (.gv-form-card border-
   radius:0 box-shadow:none, .gv-trip-summary margin:14 14, .gv-vehicle-
   list padding:0 14, .gv-section-card margin:0 14, etc.) ends 8px in
   from the device edge on each side instead of at the device edge
   proper. This is a polish bug independent of the Step 2 overflow.
   The `:has` selector is fine: every supported browser (Safari 15.4+
   = iOS 15.4+ shipped Mar 2022) supports it. */
html:has(.express-root),
body:has(.express-root) {
    margin: 0;
    padding: 0;
}

body:has(.express-root) {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--xp-font-body);
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Session 15.1.1 Polish Fix 1 — defensive horizontal overflow clip.
       Step 3's inline `grid-template-columns: minmax(0, 1fr) 380px;` can
       widen the body past the viewport on iPhone (the fixed 380px column
       beats the 980px mobile collapse rule because inline styles trump
       non-!important CSS), which then stretches the no-max-width
       `.gv-header` flex container off-screen and pushes the "24/7" chip
       outside the visible viewport — exactly the "half-width header"
       symptom Mike reported on Steps 2/3/Thank-You. Clipping here keeps
       the header visually pinned to the viewport on every step
       regardless of any future inline-style or content-width oversight. */
    overflow-x: clip;
}

body:has(.express-root) .gv-topbar { display: none; }
body:has(.express-root) .gv-shell { max-width: none; margin: 0; padding: 0; }

.express-root,
.express-root *,
.express-root *::before,
.express-root *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}
.express-root { min-height: 100vh; overflow-x: clip; }

/* -----------------------------------------------------------------------------
   Header (brand bar + dispatch info)
   -------------------------------------------------------------------------- */
.express-root .gv-header {
    background: var(--xp-header-bg);
    border-bottom: 1px solid var(--xp-header-line);
    padding: 18px 40px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.express-root .gv-brand { display: flex; align-items: center; gap: 12px; }

.express-root .gv-brand-mark {
    width: 36px; height: 36px;
    background: var(--xp-inverse-bg); color: var(--xp-inverse-ink);
    border-radius: 8px;
    display: grid; place-items: center;
    font-family: var(--xp-font-display);
    font-weight: var(--xp-display-weight); font-size: calc(18px * var(--xp-display-scale));
    letter-spacing: var(--xp-display-track);
}

.express-root .gv-brand-name {
    font-family: var(--xp-font-display);
    font-size: calc(20px * var(--xp-display-scale)); font-weight: var(--xp-display-weight);
    letter-spacing: var(--xp-display-track);
}

.express-root .gv-brand-tag {
    font-size: 12px; color: var(--xp-panel-muted);
    letter-spacing: 0.08em; text-transform: uppercase;
    margin-top: 2px;
}

.express-root .gv-header-meta {
    display: flex; align-items: center; gap: 24px;
    font-size: 13px; color: var(--xp-panel-ink-2);
}

.express-root .gv-header-meta-item { display: flex; align-items: center; gap: 6px; }
.express-root .gv-header-meta-item svg { width: 14px; height: 14px; opacity: 0.6; }

/* -----------------------------------------------------------------------------
   Step indicator (3 steps)
   -------------------------------------------------------------------------- */
.express-root .gv-steps {
    display: flex; align-items: center; justify-content: center;
    gap: 0; padding: 28px 40px 20px;
    max-width: 1400px; margin: 0 auto;
}

.express-root .gv-step {
    display: flex; align-items: center; gap: 12px;
    padding: 0 28px;
    color: var(--xp-panel-muted);
    font-size: 13px; letter-spacing: 0.04em;
    text-transform: uppercase; font-weight: 500;
    /* Session 15.2 (Bug #2): pills became <button>s. Strip the UA chrome so
       they look identical to the previous <div> rendering, then layer in the
       interactivity cues. min-height enforces the 44×44 tap target the
       Phase A audit established (44px is the Apple HIG / WCAG 2.5.5
       minimum). Backward nav is always allowed; the disabled state below
       only applies to forward jumps beyond maxStepReached. */
    background: transparent;
    border: 0;
    font-family: inherit;
    cursor: pointer;
    min-height: 44px;
    -webkit-tap-highlight-color: transparent;
}

.express-root .gv-step:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Disabled = forward-skip blocked. Visually subtle: reduced opacity + the
   built-in disabled cursor. Active / complete state classes still apply
   to disabled buttons; the customer can see the path ahead but can't
   leap-frog into it. */
.express-root .gv-step:disabled,
.express-root .gv-step.is-disabled {
    cursor: not-allowed;
    opacity: 0.5;
}
.express-root .gv-step:disabled .gv-step-num,
.express-root .gv-step.is-disabled .gv-step-num {
    opacity: 0.7;
}

/* Hover on reachable pills hints they're clickable, without competing with
   the .is-active solid-ink state. */
.express-root .gv-step:not(:disabled):not(.is-active):hover {
    color: var(--xp-panel-ink);
}
.express-root .gv-step:not(:disabled):not(.is-active):hover .gv-step-num {
    border-color: var(--xp-panel-ink-2);
}

.express-root .gv-step-num {
    width: 26px; height: 26px;
    border-radius: 50%; border: 1px solid var(--xp-panel-line);
    display: grid; place-items: center;
    font-family: var(--xp-font-body);
    font-size: 13px; font-weight: 500;
    background: var(--xp-panel);
}

.express-root .gv-step.is-active { color: var(--xp-panel-ink); }
.express-root .gv-step.is-active .gv-step-num {
    background: var(--accent); color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}

.express-root .gv-step.is-complete { color: var(--xp-panel-ink-2); }
.express-root .gv-step.is-complete .gv-step-num {
    background: var(--green); color: var(--bg);
    border-color: var(--green);
}

.express-root .gv-step-divider { width: 60px; height: 1px; background: var(--xp-panel-line); }
.express-root .gv-step-divider.is-complete { background: var(--green); }

/* -----------------------------------------------------------------------------
   Main grid (Step 1: form / map)
   -------------------------------------------------------------------------- */
.express-root .gv-main {
    max-width: 1400px; margin: 0 auto;
    padding: 32px 40px 60px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: 36px;
    align-items: start;
}

/* -----------------------------------------------------------------------------
   Form card + headline block
   -------------------------------------------------------------------------- */
.express-root .gv-form-card {
    background: var(--xp-panel);
    border-radius: var(--radius-lg);
    padding: 36px 36px 32px;
    box-shadow: var(--shadow-md);
    position: relative;
}

.express-root .gv-eyebrow {
    color: var(--accent);
    font-size: 12px; letter-spacing: 0.14em;
    text-transform: uppercase; font-weight: 500;
    display: flex; align-items: center; gap: 8px;
    margin-bottom: 14px;
}

.express-root .gv-eyebrow::before {
    content: ''; width: 24px; height: 1px; background: var(--accent);
}

.express-root .gv-headline {
    font-family: var(--xp-font-display);
    font-size: calc(36px * var(--xp-display-scale)); font-weight: var(--xp-display-weight);
    line-height: 1.1; letter-spacing: var(--xp-display-track);
    color: var(--xp-panel-ink); margin-bottom: 8px;
}

.express-root .gv-headline em { font-style: italic; color: var(--accent); }

.express-root .gv-subheadline {
    color: var(--xp-panel-ink-2);
    font-size: 14px; margin-bottom: 28px;
}

/* -----------------------------------------------------------------------------
   Service-type segmented control (Step 1)
   -------------------------------------------------------------------------- */
.express-root .gv-service-types {
    /* D.1.3 — adapt to 1/2/3 tabs without left-anchoring. Each tab gets
       an equal share of the row regardless of count. Tab count is
       written as --gv-tabs by step-1.blade so the grid stays
       deterministic on browsers without flex-grow rounding quirks. */
    display: grid;
    grid-template-columns: repeat(var(--gv-tabs, 3), minmax(0, 1fr));
    gap: 6px;
    background: var(--xp-panel-2);
    padding: 4px;
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius-sm);
    margin-bottom: 28px;
}

/* Solo-tab variant: render as a static header rather than a clickable
   pill — there's nowhere else to switch to. Keeps the row's visual
   anchoring but suppresses the hover affordance. */
.express-root .gv-service-types[data-tab-count="1"] .gv-service-type {
    cursor: default;
    pointer-events: none;
}

.express-root .gv-service-type {
    padding: 12px 14px;
    text-align: center;
    background: transparent;
    border: none;
    border-radius: 7px;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink-2);
    cursor: pointer;
    transition: all 0.18s ease;
    letter-spacing: 0.02em;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.express-root .gv-service-type svg { width: 16px; height: 16px; opacity: 0.7; }

.express-root .gv-service-type:hover { color: var(--xp-panel-ink); }
.express-root .gv-service-type:hover svg { opacity: 1; }

.express-root .gv-service-type.is-active {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
}
.express-root .gv-service-type.is-active svg { opacity: 1; color: var(--accent-ink); }

/* -----------------------------------------------------------------------------
   Form fields, route thread
   -------------------------------------------------------------------------- */
.express-root .gv-field-group { display: grid; gap: 14px; margin-bottom: 14px; }
.express-root .gv-field-group-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

.express-root .gv-field {
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 12px 16px 12px 50px;
    position: relative;
    transition: all 0.18s ease;
    cursor: text;
    display: block;
}

.express-root .gv-field:hover { background: var(--xp-panel-hover); }
.express-root .gv-field:focus-within {
    background: var(--xp-panel);
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

.express-root .gv-field-icon {
    position: absolute;
    left: 18px; bottom: 12px;
    width: 20px; height: 20px;
    color: var(--xp-panel-muted);
    pointer-events: none;
}
.express-root .gv-field:focus-within .gv-field-icon { color: var(--accent); }

.express-root .gv-field-label {
    display: block;
    font-size: 11px; font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em; text-transform: uppercase;
    margin-bottom: 2px;
}

/* Native date/time pickers (iOS Safari, Chrome mobile) render their own
   placeholder text inside the input — "Date" / "mm/dd/yyyy" / etc. — which
   visually collides with our own .gv-field-label rendered above. Hide our
   label on these inputs and grow the field padding so the native chrome
   doesn't feel cramped. Toggle the class in the Blade partial; do NOT
   target input[type="date"] directly here because Atelier's input layout
   depends on the label still controlling vertical rhythm for non-picker
   fields. */
.express-root .gv-field--native-picker .gv-field-label {
    display: none;
}
.express-root .gv-field--native-picker {
    padding-top: 16px;
    padding-bottom: 16px;
}

.express-root .gv-field input,
.express-root .gv-field textarea {
    width: 100%; background: transparent;
    border: none; outline: none;
    font-family: var(--xp-font-body);
    font-size: 15px; color: var(--xp-panel-ink);
    font-weight: 400; padding: 0;
    resize: none;
}
.express-root .gv-field textarea { min-height: 48px; line-height: 1.4; }
.express-root .gv-field input::placeholder,
.express-root .gv-field textarea::placeholder { color: var(--xp-panel-muted); }

.express-root .gv-route-thread { position: relative; }
.express-root .gv-route-thread::before {
    content: '';
    position: absolute;
    left: 27px; top: 60px; bottom: 60px;
    width: 1.5px;
    background: repeating-linear-gradient(to bottom, var(--xp-panel-muted) 0 3px, transparent 3px 6px);
    opacity: 0.5;
    pointer-events: none;
}

/* -----------------------------------------------------------------------------
   Steppers (passengers / luggage) + option pills + return toggle
   -------------------------------------------------------------------------- */
.express-root .gv-stepper-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px;
    margin-bottom: 24px;
}

.express-root .gv-stepper {
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 14px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.express-root .gv-stepper-info { display: flex; align-items: center; gap: 10px; }

.express-root .gv-stepper-icon {
    width: 32px; height: 32px;
    border-radius: 8px;
    background: var(--xp-panel);
    display: grid; place-items: center;
    color: var(--xp-panel-ink-2);
}
.express-root .gv-stepper-icon svg { width: 16px; height: 16px; }

.express-root .gv-stepper-label {
    font-size: 12px; color: var(--xp-panel-muted);
    letter-spacing: 0.04em; text-transform: uppercase;
    font-weight: 500;
}

/* Stepper label desktop/mobile spans — default state: show the long label
   ("Passengers"/"Luggage"), hide the short one ("Pax"/"Bags"). The mobile
   block at 768px below flips these. Replaces the previous font-size:0 +
   ::after swap-trick which could flash during a Livewire morph. */
.express-root .gv-stepper-label .gv-label-desktop {
    display: inline;
}
.express-root .gv-stepper-label .gv-label-mobile {
    display: none;
}

.express-root .gv-stepper-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(20px * var(--xp-price-scale)); font-weight: var(--xp-price-weight);
    line-height: 1; color: var(--xp-panel-ink);
}

.express-root .gv-stepper-controls { display: flex; gap: 4px; }

.express-root .gv-stepper-btn {
    min-width: 36px; min-height: 36px;
    border-radius: 8px;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    color: var(--xp-panel-ink-2);
    cursor: pointer;
    display: grid; place-items: center;
    transition: all 0.15s ease;
    font-size: 14px; font-weight: 500;
}

.express-root .gv-stepper-btn:hover {
    background: var(--xp-inverse-bg); color: var(--xp-inverse-ink);
    border-color: var(--xp-panel-ink);
}

/* D.1.2 — pill-styled native selects for the Passenger / Luggage / Child-seat
   dropdowns. Matches the gv-stepper-btn aesthetic (rounded, surface bg,
   subtle border, dark hover) plus a custom chevron SVG positioned right.
   Native chevron is suppressed via appearance:none + a transparent
   background-image trick that keeps the SVG crisp on retina. */
.express-root .gv-stepper-select,
.express-root .gv-childseat-select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    min-height: 36px;
    padding: 0 28px 0 12px;
    border-radius: 8px;
    background-color: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    color: var(--xp-panel-ink);
    cursor: pointer;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    transition: all 0.15s ease;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2358514a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px 12px;
}

.express-root .gv-stepper-select:hover,
.express-root .gv-childseat-select:hover {
    border-color: var(--xp-panel-ink);
    color: var(--xp-panel-ink);
}

.express-root .gv-stepper-select:focus,
.express-root .gv-childseat-select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

/* Drop the inner padding for child-seat selects so they fit the 3-up
   row with the narrower per-column width. */
.express-root .gv-childseat-select {
    width: 100%;
    padding: 6px 26px 6px 10px;
    font-size: 13px;
}

/* Child-seat sub-picker — frame the 3-up select row to match the
   pill-card aesthetic the rest of Step 1 uses. */
.express-root .gv-childseat-picker {
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 16px;
}

.express-root .gv-childseat-heading {
    font-size: 11px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 10px;
}

.express-root .gv-childseat-picker .gv-field-select {
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 8px 10px;
    cursor: default;
}

.express-root .gv-childseat-picker .gv-field-label {
    margin-bottom: 4px;
}

.express-root .gv-childseat-note {
    margin-top: 10px;
    font-size: 12px;
    color: var(--xp-panel-muted);
    line-height: 1.4;
}

/* Spec C — ✕ collapse button on the revealed hourly drop-off field.
   Sibling of the wire:ignore wrapper, absolute-positioned in the top-right
   corner of the dropoff field. The wrapper carries position:relative. */
.express-root .gv-field-collapse-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--xp-panel-ink-2);
    cursor: pointer;
    border-radius: 50%;
    transition: background 0.15s ease, color 0.15s ease;
    padding: 0;
    z-index: 2;
}

.express-root .gv-field-collapse-btn:hover {
    background: var(--xp-hover-tint);
    color: var(--xp-link);
}

/* Spec C — three-up compact picker grid for booster / infant / child seats.
   Replaces the previous .gv-field-group-3 class (which never had a CSS rule
   and therefore stacked vertically). Stays inside .gv-childseat-picker's
   framed container. */
.express-root .gv-child-seats-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
}

@media (max-width: 480px) {
    .express-root .gv-child-seats-grid {
        grid-template-columns: 1fr;
    }
}

.express-root .gv-options-label {
    font-size: 11px; font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em; text-transform: uppercase;
    margin-bottom: 12px;
}

.express-root .gv-options-row {
    display: flex; flex-wrap: wrap;
    gap: 8px; margin-bottom: 24px;
}

.express-root .gv-pill {
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 999px;
    padding: 8px 14px 8px 12px;
    font-size: 13px; color: var(--xp-panel-ink-2);
    cursor: pointer;
    transition: all 0.15s ease;
    display: inline-flex;
    align-items: center; gap: 6px;
    font-weight: 400;
}

.express-root .gv-pill:hover { border-color: var(--xp-panel-ink); color: var(--xp-panel-ink); }
.express-root .gv-pill.is-active {
    background: var(--accent); color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}
.express-root .gv-pill svg { width: 14px; height: 14px; }

.express-root .gv-return {
    display: flex; align-items: center;
    justify-content: space-between;
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 28px;
}

.express-root .gv-return-text { font-size: 14px; color: var(--xp-panel-ink); }

.express-root .gv-toggle-group {
    display: flex;
    background: var(--xp-panel);
    border-radius: 8px;
    padding: 3px;
    box-shadow: var(--shadow-sm);
}

.express-root .gv-toggle {
    background: transparent; border: none;
    padding: 6px 16px;
    font-family: var(--xp-font-body);
    font-size: 13px; font-weight: 500;
    color: var(--xp-panel-muted);
    cursor: pointer;
    border-radius: 6px;
    transition: all 0.15s ease;
}

.express-root .gv-toggle.is-active {
    background: var(--accent); color: var(--accent-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
}

/* -----------------------------------------------------------------------------
   Pay CTA button — shared between the existing sticky CTA (.gv-cta, used on
   Step 1 "See pricing" and Step 3 "Continue to payment") and the new Step 3
   trip-summary pay button (.gv-pay-cta, Session 15.2.2). One rule block, two
   class names: structurally incapable of drifting apart. Background sourced
   from `--gv-pay-cta-bg` — single declaration of the black color value lives
   at :root above.
   -------------------------------------------------------------------------- */
.express-root .gv-cta,
.express-root .gv-pay-cta {
    width: 100%;
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
    border: none;
    border-radius: var(--radius);
    padding: 18px 24px;
    font-family: var(--xp-font-body);
    font-size: 15px; font-weight: 500;
    letter-spacing: 0.02em;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: all 0.2s ease;
    margin-bottom: 14px;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}

.express-root .gv-cta:hover,
.express-root .gv-pay-cta:hover {
    background: var(--green);
    /* Fixed green hover, so white text whatever --accent-ink is. */
    color: var(--xp-on-status);
    transform: translateY(-1px);
    box-shadow: 0 8px 24px rgba(74, 122, 77, 0.32);
}

.express-root .gv-pay-cta:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.express-root .gv-cta-arrow { transition: transform 0.2s ease; }
.express-root .gv-cta:hover .gv-cta-arrow,
.express-root .gv-pay-cta:hover .gv-cta-arrow { transform: translateX(4px); }

/* Positional modifier — when the shared pay button sits flush at the bottom
   of the Step 3 receipt sidebar, drop the 14px margin-bottom (the sidebar
   already terminates the visual flow). Appearance unchanged. */
.express-root .gv-pay-cta.gv-pay-cta--in-receipt {
    margin-bottom: 0;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

.express-root .gv-cta-secondary-text {
    text-align: center;
    font-size: 12px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.02em;
}
.express-root .gv-cta-secondary-text span { color: var(--xp-panel-ink-2); }

/* -----------------------------------------------------------------------------
   Map canvas + overlay cards (Step 1 right column)
   -------------------------------------------------------------------------- */
.express-root .gv-map-canvas {
    /* 2026-05-25 — Fixed-height map. Same behavior standalone + iframed.
       No sticky, no viewport units, no align-items stretch. Map is a
       decorative location indicator at a fixed scale. Form column scrolls
       past it independently if it grows taller. */
    position: relative;
    height: 640px;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-lg);
    background: linear-gradient(135deg, var(--xp-map-art-1) 0%, var(--xp-map-art-2) 100%);
}

.express-root .gv-map-img {
    width: 100%; height: 100%;
    object-fit: cover; display: block;
}

.express-root .gv-trip-card {
    position: absolute;
    top: 24px; left: 24px; right: 24px;
    background: var(--xp-panel-glass);
    backdrop-filter: blur(20px) saturate(140%);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    border-radius: var(--radius);
    padding: 18px 20px;
    box-shadow: 0 4px 20px rgba(26, 26, 26, 0.10);
    display: flex; align-items: center; gap: 16px;
}

.express-root .gv-trip-pins {
    display: flex; flex-direction: column;
    align-items: center; gap: 4px;
    padding-top: 4px;
}

.express-root .gv-pin {
    width: 12px; height: 12px;
    border-radius: 50%;
    border: 2px solid var(--xp-panel);
}

.express-root .gv-pin.is-pickup {
    background: var(--xp-inverse-bg);
    box-shadow: 0 0 0 1px var(--xp-panel-ink);
}

.express-root .gv-pin.is-dropoff {
    background: var(--accent);
    box-shadow: 0 0 0 1px var(--accent);
}

.express-root .gv-pin-line {
    width: 1.5px; height: 16px;
    background: repeating-linear-gradient(to bottom, var(--xp-panel-muted) 0 2px, transparent 2px 4px);
}

.express-root .gv-trip-addresses { flex: 1; min-width: 0; }

.express-root .gv-trip-address {
    font-size: 13px; color: var(--xp-panel-ink);
    font-weight: 500;
    white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.4;
}
.express-root .gv-trip-address:first-child { margin-bottom: 6px; }

.express-root .gv-trip-stats {
    text-align: right;
    border-left: 1px solid var(--xp-panel-line);
    padding-left: 16px;
}

.express-root .gv-trip-stat-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(20px * var(--xp-price-scale)); font-weight: var(--xp-price-weight);
    line-height: 1; color: var(--xp-panel-ink);
}

.express-root .gv-trip-stat-label {
    font-size: 11px; color: var(--xp-panel-muted);
    letter-spacing: 0.08em; text-transform: uppercase;
    margin-top: 4px;
}

.express-root .gv-trust-strip {
    position: absolute;
    bottom: 24px; left: 24px; right: 24px;
    background: rgba(26, 26, 26, 0.92);
    backdrop-filter: blur(20px) saturate(140%);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    color: var(--xp-strip-ink);
    border-radius: var(--radius);
    padding: 14px 20px;
    display: flex; align-items: center;
    justify-content: space-between; gap: 16px;
}

.express-root .gv-trust-item {
    display: flex; align-items: center; gap: 8px;
    font-size: 12px;
    color: rgba(245, 243, 238, 0.85);
    flex: 1; min-width: 0;
}

.express-root .gv-trust-item strong {
    color: var(--xp-strip-ink); font-weight: 500;
}

.express-root .gv-trust-item svg {
    width: 14px; height: 14px;
    color: var(--gold);
    flex-shrink: 0;
}

.express-root .gv-trust-divider {
    width: 1px; height: 16px;
    background: rgba(245, 243, 238, 0.15);
    flex-shrink: 0;
}

.express-root .gv-map-badge {
    position: absolute;
    top: 50%; right: 24px;
    transform: translateY(-50%);
    background: var(--xp-panel);
    border-radius: var(--radius);
    padding: 16px 20px;
    box-shadow: var(--shadow-md);
    text-align: center;
    min-width: 120px;
}

.express-root .gv-map-badge-eyebrow {
    font-size: 10px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 6px;
}

.express-root .gv-map-badge-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(28px * var(--xp-price-scale)); font-weight: var(--xp-price-weight);
    color: var(--xp-panel-ink); line-height: 1;
}

.express-root .gv-map-badge-sub {
    font-size: 12px; color: var(--xp-panel-ink-2);
    margin-top: 4px;
}

/* -----------------------------------------------------------------------------
   Page heading + trip summary (Step 2)
   -------------------------------------------------------------------------- */
.express-root .gv-page-heading { margin-bottom: 24px; }

.express-root .gv-trip-summary {
    background: var(--xp-panel);
    border-radius: var(--radius);
    padding: 16px 20px;
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 28px;
}

.express-root .gv-trip-summary-pins {
    display: flex; flex-direction: column;
    align-items: center; gap: 4px;
    padding-top: 4px;
}

.express-root .gv-trip-summary-pins .gv-pin { width: 10px; height: 10px; }
.express-root .gv-trip-summary-pins .gv-pin-line { height: 14px; }

.express-root .gv-trip-summary-text { flex: 1; min-width: 0; }

.express-root .gv-trip-summary-row {
    font-size: 13px; color: var(--xp-panel-ink);
    line-height: 1.5;
}
.express-root .gv-trip-summary-row:first-child { margin-bottom: 4px; }

.express-root .gv-trip-summary-meta {
    display: flex; gap: 16px;
    font-size: 12px; color: var(--xp-panel-muted);
    border-left: 1px solid var(--xp-panel-line);
    padding-left: 18px;
}

.express-root .gv-trip-summary-meta-item {
    display: flex; align-items: center; gap: 6px;
}

.express-root .gv-trip-summary-meta-item svg { width: 13px; height: 13px; }

.express-root .gv-trip-summary-meta strong {
    color: var(--xp-panel-ink); font-weight: 500;
}

.express-root .gv-edit-link {
    color: var(--xp-link);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    background: none;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 10px;
    border-radius: 6px;
    transition: background 0.15s;
}

.express-root .gv-edit-link:hover { background: var(--accent-bg); }
.express-root .gv-edit-link svg { width: 12px; height: 12px; }

/* -----------------------------------------------------------------------------
   Section label + sort control (Step 2)
   -------------------------------------------------------------------------- */
.express-root .gv-section-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.express-root .gv-sort-control {
    display: flex; gap: 4px;
    background: var(--xp-panel);
    border-radius: 8px;
    padding: 3px;
    box-shadow: var(--shadow-sm);
}

.express-root .gv-sort-btn {
    background: transparent;
    border: none;
    padding: 6px 12px;
    font-family: var(--xp-font-body);
    font-size: 12px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    cursor: pointer;
    border-radius: 6px;
    text-transform: none;
    letter-spacing: 0;
    transition: all 0.15s;
}

.express-root .gv-sort-btn.is-active {
    background: var(--accent); color: var(--accent-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
}

/* -----------------------------------------------------------------------------
   Vehicle cards (Step 2)
   -------------------------------------------------------------------------- */
.express-root .gv-vehicle-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
    /* Self-query note: container-type sits on the list (parent of every card),
       NOT on the card itself. CSS container queries can only style descendants
       of the container element — the container element is not its own
       descendant. Putting container-type on the card and then trying to switch
       its own grid-template-columns inside container is a silent no-op. Hosting
       the container on the list lets the container query restyle the card itself
       (the card is a descendant of the list) while still measuring card width
       (cards span the list inline-size). Same contract as taxibooking themes. */
    container-type: inline-size;
    container-name: gv-vehicle-card;
}

.express-root .gv-vehicle-card {
    background: var(--xp-panel);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    overflow: hidden;
    cursor: pointer;
    transition: all 0.25s ease;
    display: grid;
    /* Photo column wrapped in minmax(0, 280px) so it can shrink if the
       container is narrower than the sum of fixed tracks — prevents the
       photo grid item from blowing past its track when embedded in
       narrow iframe widths. */
    grid-template-columns: minmax(0, 280px) minmax(0, 1fr) auto;
    align-items: stretch;
    position: relative;
}

.express-root .gv-vehicle-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-card-hover);
}


.express-root .gv-vehicle-photo {
    background: linear-gradient(135deg, #f0ebe0 0%, #d8cfbe 100%);
    position: relative;
    overflow: hidden;
    aspect-ratio: 4/3;
    /* Hard width bounds so the photo zone never escapes its grid track
       under any container width (standalone OR iframe). Belt-and-
       suspenders against intrinsic-content sizing surprises that have
       been observed in embedded contexts. */
    display: block;
    width: 100%;
    min-width: 0;
    max-width: 100%;
}

.express-root .gv-vehicle-photo img,
.express-root .gv-vehicle-photo svg {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    object-fit: cover;
    object-position: center;
    transition: transform 0.4s cubic-bezier(.2,.7,.2,1);
}

.express-root .gv-vehicle-card:hover .gv-vehicle-photo svg,
.express-root .gv-vehicle-card:hover .gv-vehicle-photo img {
    transform: scale(1.05);
}

.express-root .gv-vehicle-tag {
    position: absolute;
    top: 12px; right: 12px;
    background: var(--xp-tile-glass);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    color: var(--xp-tile-ink);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 5px 10px;
    border-radius: 6px;
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: center;
    gap: 5px;
    z-index: 1;
}

.express-root .gv-vehicle-tag svg { width: 11px; height: 11px; }

.express-root .gv-vehicle-tag.is-popular { color: var(--accent); }
.express-root .gv-vehicle-tag.is-popular svg { color: var(--accent); }

.express-root .gv-vehicle-tag.is-value { color: var(--green); }
.express-root .gv-vehicle-tag.is-value svg { color: var(--green); }

.express-root .gv-vehicle-tag.is-premium { color: var(--gold); }
.express-root .gv-vehicle-tag.is-premium svg { color: var(--gold); }

.express-root .gv-vehicle-body {
    padding: 22px 24px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-width: 0;
}

.express-root .gv-vehicle-class {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 4px;
}

.express-root .gv-vehicle-name {
    font-family: var(--xp-font-display);
    font-size: calc(24px * var(--xp-display-scale));
    font-weight: var(--xp-display-weight);
    letter-spacing: var(--xp-display-track);
    line-height: 1.15;
    color: var(--xp-panel-ink);
    margin-bottom: 6px;
}

.express-root .gv-vehicle-examples {
    font-size: 12px;
    color: var(--xp-panel-muted);
    margin-bottom: 14px;
    font-style: italic;
}

.express-root .gv-vehicle-specs {
    display: flex;
    gap: 18px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}

.express-root .gv-spec {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--xp-panel-ink-2);
}

.express-root .gv-spec svg {
    width: 14px; height: 14px;
    color: var(--xp-panel-muted);
}

.express-root .gv-spec strong {
    color: var(--xp-panel-ink);
    font-weight: 500;
}

.express-root .gv-vehicle-amenities {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.express-root .gv-amenity {
    font-size: 11px;
    color: var(--xp-panel-ink-2);
    background: var(--xp-panel-2);
    padding: 4px 10px;
    border-radius: 999px;
    letter-spacing: 0.02em;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.express-root .gv-amenity svg {
    width: 10px;
    height: 10px;
    color: var(--xp-success);
}

.express-root .gv-vehicle-aside {
    background: var(--xp-panel-2);
    border-left: 1px solid var(--xp-panel-line);
    padding: 22px 24px;
    display: flex;
    flex-direction: column;
    /* Spec C — center the price column so the eyebrow ("FOR X HOURS" /
       "FROM") and the price amount sit visually centered above the
       full-width Select button below. Was flex-end (right-aligned),
       which created visual asymmetry against the centered button text. */
    align-items: center;
    justify-content: center;
    gap: 16px;
    min-width: 200px;
}

.express-root .gv-price-block { text-align: center; }

.express-root .gv-price-row {
    font-size: 12px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 4px;
}

.express-root .gv-price-amount {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(36px * var(--xp-price-scale));
    font-weight: var(--xp-price-weight);
    line-height: 1;
    letter-spacing: var(--xp-price-track);
    color: var(--xp-panel-ink);
}

.express-root .gv-price-amount sup {
    font-size: 18px;
    font-weight: 400;
    vertical-align: top;
    margin-right: 1px;
    margin-top: 6px;
    display: inline-block;
}

/* STEP2-VEHICLE-SELECT-2026-05-24 */
/* Vehicle Select button — three-state visual signal:
   - Default:               black (passive, but visible) "you can pick this"
   - Card hover:             terracotta (engagement) "you're about to pick"
   - Card .is-selected:      accent + --xp-focus ring, "Selected" + check
   The icon swap (arrow → check) is handled in the Blade conditional;
   here we only own color. */
.express-root .gv-vehicle-select {
    width: 100%;
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    border: 1px solid var(--xp-panel-ink);
    border-radius: var(--radius);
    padding: 14px 20px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.18s, border-color 0.18s, color 0.18s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 48px;
}

.express-root .gv-vehicle-select svg {
    transition: transform 0.18s ease;
}

.express-root .gv-vehicle-card:hover .gv-vehicle-select {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--accent);
}
.express-root .gv-vehicle-card:hover .gv-vehicle-select svg {
    transform: translateX(3px);
}


.express-root .gv-vehicle-select svg { width: 14px; height: 14px; }

/* -----------------------------------------------------------------------------
   Right sidebar: mini-map + trust card (Step 2)
   -------------------------------------------------------------------------- */
.express-root .gv-aside-stack {
    position: sticky;
    top: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.express-root .gv-mini-map {
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    background: linear-gradient(135deg, var(--xp-map-art-1) 0%, var(--xp-map-art-2) 100%);
    height: 260px;
    position: relative;
}

.express-root .gv-mini-map svg {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}

.express-root .gv-mini-map-stat {
    position: absolute;
    bottom: 16px; left: 16px; right: 16px;
    background: var(--xp-panel-glass);
    backdrop-filter: blur(20px) saturate(140%);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    border-radius: 12px;
    padding: 12px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.express-root .gv-mini-map-stat-label {
    font-size: 10px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.express-root .gv-mini-map-stat-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(18px * var(--xp-price-scale));
    font-weight: var(--xp-price-weight);
    color: var(--xp-panel-ink);
}

.express-root .gv-mini-map-stat-divider {
    width: 1px;
    height: 28px;
    background: var(--xp-panel-line);
}

.express-root .gv-trust-card {
    background: var(--xp-panel);
    border-radius: var(--radius-lg);
    padding: 20px 22px;
    box-shadow: var(--shadow-sm);
}

.express-root .gv-trust-eyebrow {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 14px;
}

.express-root .gv-trust-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--xp-panel-line);
}
.express-root .gv-trust-row:last-child { border-bottom: none; }
.express-root .gv-trust-row:first-child { padding-top: 0; }

.express-root .gv-trust-icon {
    width: 32px; height: 32px;
    border-radius: 8px;
    background: var(--xp-panel-2);
    display: grid; place-items: center;
    color: var(--xp-link);
    flex-shrink: 0;
}

.express-root .gv-trust-icon svg { width: 16px; height: 16px; }

.express-root .gv-trust-text {
    font-size: 13px;
    color: var(--xp-panel-ink);
    line-height: 1.5;
}

.express-root .gv-trust-text strong { font-weight: 500; }
.express-root .gv-trust-text em {
    font-style: normal;
    color: var(--xp-panel-muted);
    font-size: 12px;
    display: block;
    margin-top: 2px;
}

/* -----------------------------------------------------------------------------
   Sticky action bar (Step 2 footer)
   -------------------------------------------------------------------------- */
.express-root .gv-action-bar {
    position: sticky;
    bottom: 0;
    background: var(--xp-panel);
    border-top: 1px solid var(--xp-panel-line);
    padding: 16px 40px;
    margin-top: 32px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    box-shadow: 0 -4px 20px rgba(26,26,26,0.05);
    z-index: 10;
}

.express-root .gv-action-bar-summary {
    display: flex;
    align-items: center;
    gap: 16px;
}

.express-root .gv-action-bar-vehicle {
    display: flex;
    align-items: center;
    gap: 12px;
}

.express-root .gv-action-bar-vehicle-thumb {
    width: 50px; height: 38px;
    border-radius: 8px;
    background: linear-gradient(135deg, #f0ebe0 0%, #d8cfbe 100%);
    overflow: hidden;
}

.express-root .gv-action-bar-vehicle-thumb svg,
.express-root .gv-action-bar-vehicle-thumb img { width: 100%; height: 100%; }

.express-root .gv-action-bar-vehicle-info {
    font-size: 13px;
}

.express-root .gv-action-bar-vehicle-info strong {
    display: block;
    color: var(--xp-panel-ink);
    font-weight: 500;
    margin-bottom: 2px;
}

.express-root .gv-action-bar-vehicle-info span {
    color: var(--xp-panel-muted);
    font-size: 12px;
}

.express-root .gv-action-bar-divider {
    width: 1px;
    height: 36px;
    background: var(--xp-panel-line);
}

.express-root .gv-action-bar-price {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.express-root .gv-action-bar-price-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.express-root .gv-action-bar-price-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(24px * var(--xp-price-scale));
    font-weight: var(--xp-price-weight);
    color: var(--xp-panel-ink);
    line-height: 1;
    margin-top: 4px;
}

.express-root .gv-action-cta {
    background: var(--accent);
    color: var(--accent-ink);
    border: none;
    border-radius: var(--radius);
    padding: 14px 28px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.02em;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
    transition: all 0.2s;
}

.express-root .gv-action-cta:hover {
    background: var(--green);
    transform: translateY(-1px);
    box-shadow: 0 8px 24px rgba(74,122,77,0.32);
}

.express-root .gv-action-cta svg { width: 16px; height: 16px; }

/* -----------------------------------------------------------------------------
   Section cards (Step 3 — numbered sections)
   -------------------------------------------------------------------------- */
.express-root .gv-section-card {
    background: var(--xp-panel);
    border-radius: var(--radius-lg);
    padding: 28px 30px;
    box-shadow: var(--shadow-md);
    margin-bottom: 16px;
}

.express-root .gv-section-title {
    font-family: var(--xp-font-display);
    font-size: calc(20px * var(--xp-display-scale)); font-weight: var(--xp-display-weight);
    letter-spacing: var(--xp-display-track);
    color: var(--xp-panel-ink);
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.express-root .gv-section-num {
    width: 24px; height: 24px;
    border-radius: 50%;
    background: var(--xp-panel-2);
    color: var(--xp-panel-ink);
    font-family: var(--xp-font-body);
    font-size: 13px;
    display: grid; place-items: center;
    font-weight: 500;
}

.express-root .gv-section-sub {
    font-size: 13px;
    color: var(--xp-panel-muted);
    margin-bottom: 22px;
    margin-left: 34px;
}

.express-root .gv-field-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
}

.express-root .gv-field-grid.is-full { grid-template-columns: minmax(0, 1fr); }

/* -----------------------------------------------------------------------------
   Payment methods + card grid + security strip (Step 3)
   -------------------------------------------------------------------------- */
.express-root .gv-payment-methods {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px;
    margin-bottom: 18px;
}

.express-root .gv-payment-method {
    background: var(--xp-panel-2);
    border: 1.5px solid transparent;
    border-radius: var(--radius);
    padding: 14px 16px;
    cursor: pointer;
    transition: all 0.18s;
    display: flex;
    align-items: center;
    gap: 12px;
}

.express-root .gv-payment-method:hover {
    background: var(--xp-panel-hover);
}

.express-root .gv-payment-method.is-selected {
    background: var(--xp-panel);
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

.express-root .gv-payment-radio {
    width: 18px; height: 18px;
    border-radius: 50%;
    border: 1.5px solid var(--xp-panel-line);
    background: var(--xp-panel);
    flex-shrink: 0;
    position: relative;
    transition: all 0.18s;
}

.express-root .gv-payment-method.is-selected .gv-payment-radio {
    border-color: var(--accent);
}

.express-root .gv-payment-method.is-selected .gv-payment-radio::after {
    content: '';
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--accent);
}

.express-root .gv-payment-method-info {
    flex: 1;
    min-width: 0;
}

.express-root .gv-payment-method-label {
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
}

.express-root .gv-payment-method-sub {
    font-size: 12px;
    color: var(--xp-panel-muted);
    margin-top: 2px;
}

.express-root .gv-payment-icons {
    display: flex;
    gap: 4px;
}

.express-root .gv-payment-icon {
    width: 28px;
    height: 18px;
    border-radius: 3px;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    display: grid;
    place-items: center;
    font-size: 9px;
    font-weight: 700;
    color: var(--xp-panel-ink-2);
    letter-spacing: -0.02em;
}

.express-root .gv-card-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 90px 90px;
    gap: 12px;
}

.express-root .gv-security-strip {
    margin-top: 18px;
    padding-top: 18px;
    border-top: 1px solid var(--xp-panel-line);
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 12px;
    color: var(--xp-panel-muted);
}

.express-root .gv-security-strip svg {
    width: 14px; height: 14px;
    color: var(--xp-success);
    flex-shrink: 0;
}

.express-root .gv-security-strip strong {
    color: var(--xp-panel-ink-2);
    font-weight: 500;
}

/* -----------------------------------------------------------------------------
   Checkboxes (Step 3)
   -------------------------------------------------------------------------- */
.express-root .gv-checkbox-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 0;
    cursor: pointer;
}

.express-root .gv-checkbox {
    width: 20px; height: 20px;
    border-radius: 6px;
    border: 1.5px solid var(--xp-panel-line);
    background: var(--xp-panel);
    flex-shrink: 0;
    margin-top: 1px;
    transition: all 0.15s;
    position: relative;
}

.express-root .gv-checkbox-row.is-checked .gv-checkbox {
    background: var(--xp-inverse-bg);
    border-color: var(--xp-panel-ink);
}

.express-root .gv-checkbox-row.is-checked .gv-checkbox::after {
    content: '';
    position: absolute;
    left: 5px; top: 2px;
    width: 6px; height: 10px;
    border: solid var(--xp-inverse-ink);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.express-root .gv-checkbox-text {
    font-size: 13px;
    color: var(--xp-panel-ink);
    line-height: 1.5;
}

.express-root .gv-checkbox-text em {
    font-style: normal;
    color: var(--xp-panel-muted);
    display: block;
    font-size: 12px;
    margin-top: 2px;
}

.express-root .gv-cta-block { margin-top: 4px; }

/* -----------------------------------------------------------------------------
   Receipt sidebar (Step 3 right column)
   -------------------------------------------------------------------------- */
.express-root .gv-receipt {
    position: sticky;
    top: 24px;
    background: var(--xp-panel);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    overflow: hidden;
}

.express-root .gv-receipt-header {
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    padding: 22px 26px;
}

.express-root .gv-receipt-eyebrow {
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--xp-inverse-ink-soft);
    margin-bottom: 4px;
    font-weight: 500;
}

.express-root .gv-receipt-title {
    font-family: var(--xp-font-display);
    font-size: calc(22px * var(--xp-display-scale));
    font-weight: var(--xp-display-weight);
    letter-spacing: var(--xp-display-track);
}

.express-root .gv-receipt-vehicle {
    background: var(--xp-panel-2);
    padding: 18px 26px;
    border-bottom: 1px solid var(--xp-panel-line);
    display: flex;
    align-items: center;
    gap: 14px;
}

.express-root .gv-receipt-vehicle-img {
    width: 80px; height: 56px;
    border-radius: 10px;
    background: linear-gradient(135deg, #f0ebe0 0%, #d8cfbe 100%);
    overflow: hidden;
    flex-shrink: 0;
}

.express-root .gv-receipt-vehicle-info { flex: 1; }

.express-root .gv-receipt-vehicle-name {
    font-family: var(--xp-font-display);
    font-size: calc(16px * var(--xp-display-scale));
    font-weight: var(--xp-display-weight);
    color: var(--xp-panel-ink);
    margin-bottom: 2px;
}

.express-root .gv-receipt-vehicle-meta {
    font-size: 12px;
    color: var(--xp-panel-muted);
}

.express-root .gv-receipt-body { padding: 22px 26px; }

.express-root .gv-receipt-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 0;
}

.express-root .gv-receipt-row + .gv-receipt-row {
    border-top: 1px solid var(--xp-panel-line);
}

.express-root .gv-receipt-icon {
    width: 28px; height: 28px;
    border-radius: 8px;
    background: var(--xp-panel-2);
    color: var(--xp-panel-ink-2);
    display: grid; place-items: center;
    flex-shrink: 0;
    margin-top: 2px;
}
.express-root .gv-receipt-icon svg { width: 14px; height: 14px; }

.express-root .gv-receipt-text-block {
    flex: 1;
    min-width: 0;
}

.express-root .gv-receipt-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 2px;
}

.express-root .gv-receipt-value {
    font-size: 13px;
    color: var(--xp-panel-ink);
    font-weight: 500;
    line-height: 1.4;
    word-wrap: break-word;
}

/* -----------------------------------------------------------------------------
   Promo + fare breakdown + total (Step 3 receipt)
   -------------------------------------------------------------------------- */
.express-root .gv-fare-breakdown {
    padding: 0 26px;
    border-top: 1px solid var(--xp-panel-line);
}

.express-root .gv-fare-breakdown summary {
    list-style: none;
    cursor: pointer;
    padding: 14px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    font-weight: 500;
}

.express-root .gv-fare-breakdown summary::-webkit-details-marker { display: none; }

.express-root .gv-fare-breakdown summary::after {
    content: '';
    width: 8px; height: 8px;
    border-right: 1.5px solid var(--xp-panel-muted);
    border-bottom: 1.5px solid var(--xp-panel-muted);
    transform: rotate(45deg);
    transition: transform 0.2s;
    margin-right: 4px;
}

.express-root .gv-fare-breakdown[open] summary::after { transform: rotate(-135deg); }

.express-root .gv-fare-row {
    display: flex;
    justify-content: space-between;
    padding: 6px 0;
    font-size: 13px;
    color: var(--xp-panel-ink-2);
}

.express-root .gv-fare-row.is-discount { color: var(--xp-success); }

.express-root .gv-fare-row strong { color: var(--xp-panel-ink); font-weight: 500; }

.express-root .gv-fare-row:last-child { padding-bottom: 14px; }

.express-root .gv-receipt-total {
    background: var(--xp-panel-2);
    padding: 20px 26px;
    border-top: 1px solid var(--xp-panel-line);
    display: flex;
    align-items: center;
    justify-content: space-between;
}

/* Session 15.2.2 — the previous 15.2.1 `.gv-receipt-total.is-interactive`
   subtle-hover affordance has been REMOVED. The Step 3 trip-summary pay
   surface in the `details` substate is now rendered with the shared
   `.gv-pay-cta` class above (same visual as the sticky CTA). The bare
   `.gv-receipt-total` rule (just below) still renders the plain non-
   interactive totals in every non-`details` substate. */

.express-root .gv-receipt-total-label {
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    font-weight: 500;
}

.express-root .gv-receipt-total-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(28px * var(--xp-price-scale));
    font-weight: var(--xp-price-weight);
    color: var(--xp-panel-ink);
    line-height: 1;
    letter-spacing: var(--xp-price-track);
}

.express-root .gv-promo-row {
    padding: 14px 26px;
    border-top: 1px solid var(--xp-panel-line);
    border-bottom: 1px solid var(--xp-panel-line);
    background: var(--xp-panel-2);
}

.express-root .gv-promo-input-row {
    display: flex;
    gap: 8px;
}

.express-root .gv-promo-input {
    flex: 1;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 10px;
    padding: 10px 14px;
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--xp-panel-ink);
    outline: none;
    transition: border-color 0.15s;
}

.express-root .gv-promo-input:focus { border-color: var(--accent); }

.express-root .gv-promo-btn {
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 10px;
    padding: 10px 16px;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    transition: all 0.15s;
}

.express-root .gv-promo-btn:hover {
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    border-color: var(--xp-panel-ink);
}

/* -----------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1100px) {
    .express-root .gv-vehicle-card {
        grid-template-columns: 220px minmax(0, 1fr) auto;
    }
    .express-root .gv-vehicle-aside { min-width: 180px; }
}

@media (max-width: 1000px) {
    /* Session 15.1.3 Polish Fix 9 — drop the `order: -1` that previously
       flipped .gv-receipt above the section on mobile. Customer arrives at
       Step 3 already committed (vehicle chosen, price seen); the next
       conversion ask is contact info. Letting the source DOM order render
       (section.Your-Details → aside.gv-receipt) means the form is at the
       top of the screen on mobile, with the trip summary card below as
       reference. Just resets sticky→relative since the desktop rule's
       position: sticky relies on the right column being its own grid track. */
    .express-root .gv-receipt { position: relative; top: 0; }
    .express-root .gv-section-card { padding: 22px; }
    .express-root .gv-card-grid { grid-template-columns: minmax(0, 1fr); }
    .express-root .gv-payment-methods { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 980px) {
    .express-root .gv-main { grid-template-columns: minmax(0, 1fr); padding: 20px 16px 40px; }
    .express-root .gv-map-canvas {
        position: relative; top: 0;
        height: 320px; min-height: 320px;
        order: -1;
    }
    .express-root .gv-form-card { padding: 24px 22px; }
    .express-root .gv-headline { font-size: calc(28px * var(--xp-display-scale)); }
    .express-root .gv-header { padding: 14px 20px; }
    .express-root .gv-steps { padding: 16px 20px 14px; }
    .express-root .gv-step-divider { width: 24px; }
    .express-root .gv-trip-card { padding: 14px 16px; }
    .express-root .gv-trust-strip { padding: 10px 14px; flex-wrap: wrap; }
    .express-root .gv-field-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
    .express-root .gv-aside-stack { position: relative; top: 0; }
    /* Card sub-element reflow rules (photo aspect-ratio, aside flex direction,
       select width) removed from this block. The @container gv-vehicle-card
       block at end of file is now the sole driver of every card sub-element
       layout shift, matching the taxibooking themes. Mixing viewport and
       container drivers caused a split where, under iframe embedding with
       viewport < 900px but card container >= 600px, sub-elements stacked
       while the grid stayed wide. The remaining rules in this block are
       genuinely page-level (sidebar sticky-off, action-bar chrome). */
    .express-root .gv-action-bar { padding: 12px 16px; flex-wrap: wrap; }
}

/* Step 2 override — vehicle cards need substantially more room than the
   map/trust sidebar. Step 1 keeps the near-50/50 ratio (form vs big map). */
.express-root .gv-main.gv-main-step2 {
    grid-template-columns: minmax(0, 2.4fr) minmax(0, 1fr);
}
@media (max-width: 980px) {
    .express-root .gv-main.gv-main-step2 {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Session 15.1.1 Polish Fix 3 — Step 3 grid moved out of inline style.
   The previous `<main style="grid-template-columns: minmax(0, 1fr) 380px;">`
   couldn't be overridden by mobile breakpoints (inline style specificity
   trumps non-!important CSS), so the 380px receipt column survived the
   980px collapse and forced body width past the iPhone viewport. Now
   the desktop ratio lives here and the 980px breakpoint cleanly collapses
   it to a single column — matching the existing Step 2 contract. */
.express-root .gv-main.gv-main--step3 {
    grid-template-columns: minmax(0, 1fr) 380px;
}
@media (max-width: 980px) {
    .express-root .gv-main.gv-main--step3 {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* -----------------------------------------------------------------------------
   Mobile pass — iPhone 12 Safari (390px) and similar narrow viewports.
   Refines the layout the 980/900/1000 rules collapse to: tightens chrome,
   replaces too-long labels with short equivalents (via font-size:0 + ::after
   since the labels live in Blade text nodes we cannot edit), reorders Step 1
   so the form shows above the trust strip and map, makes the trust strip a
   vertical solid-ink stack, flips Step 2 vehicle cards to photo-on-top, makes
   Step 3's gv-cta-block sticky, hides Step 2's mini-map sidebar element.

   Visual contract: /home/mike/gvbooking/atelier-mockups/gvbooking-mobile-step{1,2,3}.html
   -------------------------------------------------------------------------- */
@media (max-width: 768px) {

    /* Header — brand on left, single 24/7 chip on right.
       Dispatch phone meta-item is hidden when present (pre-existing
       :first-child:not(:last-child) targets it without needing :has).
       The "24/7 dispatch" label is replaced with "24/7" via font-size:0 +
       ::after on the last meta-item, since the literal text is a Blade
       text node we cannot edit. */
    .express-root .gv-header {
        padding: 12px 14px;
        gap: 10px;
    }
    .express-root .gv-brand {
        gap: 10px;
        min-width: 0;
        flex: 1;
    }
    .express-root .gv-brand-mark {
        width: 32px; height: 32px;
        font-size: calc(16px * var(--xp-display-scale));
        flex-shrink: 0;
    }
    /* Name + tag column only: the brand mark is also a div, and a plain
       `> div` here gave it flex: 1 (the wide dark bar, Phase 2i). */
    .express-root .gv-brand > div:not(.gv-brand-mark) {
        min-width: 0;
        flex: 1;
    }
    .express-root .gv-brand-name {
        font-size: calc(17px * var(--xp-display-scale));
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .express-root .gv-brand-tag {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size: 10px;
    }
    .express-root .gv-header-meta {
        gap: 0;
        flex-shrink: 0;
    }
    .express-root .gv-header-meta-item:first-child:not(:last-child) {
        display: none;
    }
    .express-root .gv-header-meta-item:last-child {
        font-size: 0;
        gap: 6px;
    }
    .express-root .gv-header-meta-item:last-child::after {
        content: "24/7";
        font-size: 12px;
        font-weight: 500;
        color: var(--xp-panel-ink-2);
    }
    .express-root .gv-header-meta-item:last-child svg {
        width: 14px; height: 14px;
    }

    /* Step indicator — circles + short labels ("Trip" / "Vehicle" / "Confirm").
       Source labels in atelier-3-step.blade.php are "Trip details" / "Vehicle"
       / "Confirm", living as text nodes adjacent to .gv-step-num — we can't
       wrap or rename them via CSS, so we hide them with font-size:0 on the
       parent and re-introduce short labels via ::after on each .gv-step. */
    .express-root .gv-steps {
        padding: 12px 14px 12px;
        gap: 6px;
        font-size: 0;
        flex-wrap: nowrap;
    }
    .express-root .gv-step {
        padding: 0;
        gap: 6px;
        font-size: 0;
    }
    .express-root .gv-step-num {
        width: 22px; height: 22px;
        font-size: 12px;
    }
    .express-root .gv-step::after {
        font-size: 10px;
        font-weight: 500;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: inherit;
        white-space: nowrap;
    }
    .express-root .gv-step:nth-child(1)::after { content: "Trip"; }
    .express-root .gv-step:nth-child(3)::after { content: "Vehicle"; }
    .express-root .gv-step:nth-child(5)::after { content: "Confirm"; }
    .express-root .gv-step-divider {
        width: 12px;
    }

    /* Main grid — single column with 0 outer padding so cards bleed to edges
       (matches mockup). Step 1: form above trust strip above map. Override
       the 980px `gv-map-canvas { order: -1 }` so the form (DOM order: first)
       leads the visual flow. */
    .express-root .gv-main {
        padding: 0 0 24px;
        gap: 0;
    }

    /* Form card — full bleed, smaller padding, mobile headline scale */
    .express-root .gv-form-card {
        border-radius: 0;
        box-shadow: none;
        padding: 20px 16px 24px;
        margin: 0;
    }
    .express-root .gv-headline {
        font-size: calc(26px * var(--xp-display-scale));
        margin-bottom: 8px;
    }
    .express-root .gv-subheadline {
        font-size: 13px;
        margin-bottom: 20px;
        padding-right: 4px;
        word-break: break-word;
    }
    .express-root .gv-eyebrow {
        font-size: 11px;
        margin-bottom: 12px;
    }

    /* Service-type segmented control — three flex tabs with vertical
       icon-above-label stacking so all three labels (Flat rate / Hourly /
       Shuttle) fit at 390px without horizontal overflow. */
    .express-root .gv-service-types {
        gap: 4px;
        margin-bottom: 18px;
    }
    .express-root .gv-service-type {
        flex-direction: column;
        padding: 10px 4px;
        gap: 4px;
        font-size: 12px;
        min-width: 0;
    }
    .express-root .gv-service-type svg {
        width: 16px; height: 16px;
    }

    /* Date / Time row — 2-up but minmax(0, 1fr) so text/icon never push the
       grid wider than the viewport. */
    .express-root .gv-field-group-2 {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 10px;
    }
    .express-root .gv-field {
        min-width: 0;
        padding: 10px 14px 10px 44px;
    }
    .express-root .gv-field-icon {
        left: 14px;
        bottom: 10px;
        width: 18px; height: 18px;
    }
    .express-root .gv-field-label {
        font-size: 10px;
    }
    .express-root .gv-field input,
    .express-root .gv-field textarea {
        font-size: 14px;
    }
    .express-root .gv-route-thread::before {
        left: 23px;
        top: 56px;
        bottom: 56px;
    }

    /* Passengers / Luggage — keep 2-up but tighten and replace the long
       "Passengers" / "Luggage" labels with "Pax" / "Bags" (via font-size:0
       + ::after, since the literals are Blade text nodes). */
    .express-root .gv-stepper-row {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 10px;
        margin-bottom: 18px;
    }
    .express-root .gv-stepper {
        padding: 12px;
        gap: 8px;
    }
    .express-root .gv-stepper-info {
        gap: 8px;
        min-width: 0;
    }
    .express-root .gv-stepper-icon {
        width: 30px; height: 30px;
        flex-shrink: 0;
    }
    .express-root .gv-stepper-value {
        font-size: calc(20px * var(--xp-price-scale));
    }
    /* Stepper label desktop/mobile swap — both spans are rendered in the
       Blade partial; CSS shows the right one per breakpoint. This replaces
       the previous `font-size: 0 + ::after { content: "Pax" }` trick which
       could flash the original "Passengers"/"Luggage" text for one frame
       during a Livewire morph before the mobile cascade applied. */
    .express-root .gv-stepper-label .gv-label-desktop {
        display: none;
    }
    .express-root .gv-stepper-label .gv-label-mobile {
        display: inline;
    }
    .express-root .gv-stepper-controls {
        gap: 4px;
        flex-shrink: 0;
    }
    .express-root .gv-stepper-btn {
        min-width: 44px; min-height: 44px;
    }

    /* Add-to-trip pills — 2 per row, never overflow horizontally. */
    .express-root .gv-options-row {
        gap: 6px;
        margin-bottom: 20px;
    }
    .express-root .gv-pill {
        flex: 1 1 calc(50% - 4px);
        min-width: 0;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 9px 10px;
        font-size: 12px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Return-trip card — title above, Yes/No grid below (mockup). */
    .express-root .gv-return {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
        padding: 14px 16px;
        margin-bottom: 20px;
    }
    .express-root .gv-return-text {
        font-size: 14px;
    }
    .express-root .gv-toggle-group {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 4px;
        padding: 4px;
    }
    .express-root .gv-toggle {
        padding: 8px;
        text-align: center;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* CTA + confidence block. Shared between .gv-cta and .gv-pay-cta. */
    .express-root .gv-cta,
    .express-root .gv-pay-cta {
        padding: 14px 16px;
        font-size: 15px;
        margin-bottom: 12px;
    }
    .express-root .gv-pay-cta.gv-pay-cta--in-receipt {
        margin-bottom: 0;
    }
    .express-root .gv-cta-secondary-text {
        font-size: 11px;
    }

    /* ===== Step 1 — flow order: form → trust strip → map at bottom =====
       The trust strip lives inside .gv-map-canvas in the existing markup, so
       we can't reorder it as a direct child of .gv-main. Instead: keep
       gv-map-canvas as a single grid item but flip its INTERNAL layout to
       flex-direction: column-reverse. DOM order inside gv-map-canvas is:
       map (svg/iframe/img), trip-card?, map-badge?, trust-strip — so reversed
       it becomes: trust-strip first, then the absolute-positioned overlays
       (which we display:none below to avoid them stacking awkwardly above the
       map content), then the map itself last. */
    .express-root .gv-map-canvas {
        order: 0;
        position: relative;
        top: 0;
        height: auto;
        min-height: 0;
        border-radius: 0;
        box-shadow: none;
        background: var(--xp-map-solid);
        display: flex;
        flex-direction: column-reverse;
    }
    .express-root .gv-map-canvas .gv-map-img {
        height: 200px;
        flex-shrink: 0;
    }
    /* Trip-card and map-badge are decorative overlays on the desktop map
       (absolute positioning). On the 200px mobile map they would cover most
       of it, and column-reverse strips their absolute positioning context.
       Hide them on mobile — the same trip data is in the form above and on
       Step 2's trip-summary banner. */
    .express-root .gv-map-canvas .gv-trip-card,
    .express-root .gv-map-canvas .gv-map-badge {
        display: none;
    }
    /* Trust strip — un-absolute, full-bleed solid ink, vertical stack. */
    .express-root .gv-trust-strip {
        position: relative;
        top: auto; bottom: auto; left: auto; right: auto;
        background: var(--xp-strip-solid);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border-radius: 0;
        padding: 14px 16px;
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        flex-wrap: nowrap;
    }
    .express-root .gv-trust-divider {
        display: none;
    }
    .express-root .gv-trust-item {
        flex: none;
        font-size: 13px;
    }

    /* ===== Step 2 — trip summary banner ===== */
    /* Inline horizontal banner: pickup/dropoff rows truncate with ellipsis
       on a single line each; meta wraps to a second line below them; the
       Edit pill anchors to the right. We use flex-wrap + order to flow the
       sibling .gv-trip-summary-meta onto its own row without restructuring
       HTML. */
    .express-root .gv-trip-summary {
        flex-wrap: wrap;
        gap: 10px;
        margin: 14px 14px 18px;
        padding: 12px 14px;
    }
    .express-root .gv-trip-summary-pins {
        order: 1;
        flex-shrink: 0;
        padding-top: 0;
    }
    .express-root .gv-trip-summary-pins .gv-pin { width: 8px; height: 8px; }
    .express-root .gv-trip-summary-pins .gv-pin-line { height: 10px; }
    .express-root .gv-trip-summary-text {
        order: 2;
        flex: 1;
        min-width: 0;
    }
    .express-root .gv-trip-summary-row {
        font-size: 13px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .express-root .gv-edit-link {
        order: 3;
        flex-shrink: 0;
        padding: 6px 12px;
        font-size: 11px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
    .express-root .gv-trip-summary-meta {
        order: 4;
        flex-basis: 100%;
        border-left: none;
        padding-left: 0;
        gap: 8px;
        flex-wrap: wrap;
        font-size: 11px;
    }
    .express-root .gv-trip-summary-meta-item svg {
        width: 11px; height: 11px;
    }

    /* ===== Step 2 — page heading + section label tighten ===== */
    .express-root .gv-page-heading {
        padding: 0 14px;
        margin-bottom: 14px;
    }
    .express-root .gv-section-label {
        padding: 0 14px;
        font-size: 10px;
        margin-bottom: 10px;
    }

    /* ===== Step 2 — vehicle cards (vertical: photo on top) ===== */
    /* The 900px breakpoint already collapses to 1 column. Refine sizing,
       padding and the price+select row to match the mockup at 390px. */
    .express-root .gv-vehicle-list {
        padding: 0 14px;
        gap: 14px;
    }
    .express-root .gv-vehicle-card {
        grid-template-columns: minmax(0, 1fr);
        border-radius: var(--radius-lg);
    }
    .express-root .gv-vehicle-photo {
        aspect-ratio: 16 / 10;
    }
    .express-root .gv-vehicle-tag {
        top: 12px; right: 12px;
        max-width: calc(100% - 24px);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .express-root .gv-vehicle-body {
        padding: 16px;
        min-width: 0;
    }
    .express-root .gv-vehicle-name {
        font-size: calc(20px * var(--xp-display-scale));
    }
    .express-root .gv-vehicle-examples {
        font-size: 12px;
        margin-bottom: 12px;
    }
    .express-root .gv-vehicle-specs {
        gap: 12px;
        font-size: 12px;
        margin-bottom: 12px;
    }
    .express-root .gv-vehicle-amenities {
        gap: 6px;
    }
    .express-root .gv-vehicle-aside {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 14px 16px;
        background: transparent;
        border-left: none;
        border-top: 1px solid var(--xp-panel-line);
        min-width: 0;
    }
    .express-root .gv-price-block {
        text-align: left;
        min-width: 0;
    }
    .express-root .gv-price-row {
        font-size: 10px;
    }
    .express-root .gv-price-amount {
        font-size: calc(24px * var(--xp-price-scale));
    }
    .express-root .gv-price-amount sup {
        font-size: 14px;
        margin-top: 2px;
    }
    /* Session 15.1.1 Polish Fix 6 — make Select the unmistakable primary
       action on mobile. Phase A left this button as a soft surface-color
       chip on the right side of the aside row; Mike's iPhone screenshot
       made clear it didn't read as THE thing to tap. Inverting to the
       ink token gives it the highest contrast on the card and matches
       the desktop hover/selected states. Width: auto keeps it sitting
       right of the price block (the photo-on-top mobile card layout is
       the Phase A contract, not changed here). */
    .express-root .gv-vehicle-select {
        width: auto;
        flex-shrink: 0;
        padding: 14px 22px;
        font-size: 14px;
        font-weight: 600;
        min-height: 48px;
        background: var(--xp-inverse-bg);
        color: var(--xp-inverse-ink);
        border-color: var(--xp-panel-ink);
    }
    .express-root .gv-vehicle-select svg {
        width: 16px;
        height: 16px;
    }

    /* ===== Step 2 — sidebar collapses below list ===== */
    /* The aside-stack is already a 2nd grid row at 980px. Hide the mini-map
       at mobile (decorative; the trip-summary banner already shows the route)
       and turn the trust card into a 2x2 grid like the mockup. */
    .express-root .gv-aside-stack {
        padding: 18px 14px 0;
        gap: 0;
    }
    .express-root .gv-mini-map {
        display: none; /* decorative on mobile; route is in trip-summary banner above */
    }
    .express-root .gv-trust-card {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        column-gap: 14px;
        row-gap: 12px;
        padding: 18px 16px;
    }
    .express-root .gv-trust-eyebrow {
        grid-column: 1 / -1;
        margin-bottom: 0;
    }
    .express-root .gv-trust-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
        padding: 0;
        border-bottom: none;
    }
    .express-root .gv-trust-row + .gv-trust-row {
        border-top: none;
    }
    .express-root .gv-trust-icon {
        width: 28px; height: 28px;
        margin-bottom: 2px;
    }
    .express-root .gv-trust-text {
        font-size: 12px;
    }
    .express-root .gv-trust-text em {
        font-size: 11px;
    }

    /* ===== Step 2 — sticky bottom action bar ===== */
    .express-root .gv-action-bar {
        padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
        gap: 10px;
        margin-top: 16px;
    }
    .express-root .gv-action-bar-summary {
        gap: 10px;
        flex: 1;
        min-width: 0;
    }
    .express-root .gv-action-bar-vehicle-thumb {
        width: 40px; height: 30px;
    }
    .express-root .gv-action-bar-vehicle-info {
        font-size: 12px;
        min-width: 0;
        overflow: hidden;
    }
    .express-root .gv-action-bar-vehicle-info strong {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .express-root .gv-action-bar-vehicle-info span {
        font-size: 11px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
    }
    .express-root .gv-action-bar-divider {
        display: none;
    }
    .express-root .gv-action-bar-price-value {
        font-size: calc(18px * var(--xp-price-scale));
    }
    .express-root .gv-action-cta {
        padding: 12px 14px;
        font-size: 13px;
        gap: 6px;
        flex-shrink: 0;
    }

    /* ===== Step 3 — full-bleed form sections + sticky confirm CTA =====
       Source DOM order (section first, aside second) renders straight
       through on mobile after Polish Fix 9 dropped the prior order:-1
       on .gv-receipt — Your Details now leads, Trip Summary follows.
       Here we tighten paddings and add a sticky confirm CTA at the bottom. */
    .express-root .gv-receipt {
        margin: 14px 14px 18px !important;
    }
    .express-root .gv-receipt-header {
        padding: 16px 18px;
    }
    .express-root .gv-receipt-title {
        font-size: calc(18px * var(--xp-display-scale));
    }
    .express-root .gv-receipt-vehicle {
        padding: 14px 18px;
        gap: 12px;
    }
    .express-root .gv-receipt-vehicle-img {
        width: 60px; height: 42px;
    }
    .express-root .gv-receipt-body {
        padding: 16px 18px;
    }
    .express-root .gv-promo-row {
        padding: 12px 18px;
    }
    .express-root .gv-fare-breakdown {
        padding: 0 18px;
    }
    .express-root .gv-receipt-total {
        padding: 16px 18px;
    }
    .express-root .gv-receipt-total-value {
        font-size: calc(24px * var(--xp-price-scale));
    }
    .express-root .gv-section-card {
        margin: 0 14px 12px;
        padding: 18px 16px;
        border-radius: var(--radius-lg);
    }
    .express-root .gv-section-title {
        font-size: calc(18px * var(--xp-display-scale));
    }
    .express-root .gv-section-num {
        width: 26px; height: 26px;
    }
    .express-root .gv-section-sub {
        font-size: 12px;
        margin-left: 36px;
        margin-bottom: 16px;
    }
    /* Card grid (number / exp / cvc) — at mobile, stack all three vertically.
       The desktop rule is `1fr 90px 90px`; the 1000px rule already overrides
       to `1fr` (single column). Verify it sticks. */
    .express-root .gv-card-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 10px;
    }
    .express-root .gv-payment-methods {
        grid-template-columns: minmax(0, 1fr);
    }
    .express-root .gv-payment-method {
        padding: 12px 14px;
    }
    /* Sticky bottom Confirm CTA — sits at viewport bottom on mobile so the
       customer always sees the price + confirm button while scrolling
       through the form. */
    .express-root .gv-cta-block {
        position: sticky;
        bottom: 0;
        background: var(--xp-panel);
        border-top: 1px solid var(--xp-panel-line);
        padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
        margin: 16px -14px 0;
        box-shadow: 0 -4px 20px rgba(26,26,26,0.05);
        z-index: 10;
    }
    .express-root .gv-cta-block .gv-cta {
        margin-bottom: 6px;
        padding: 14px 16px;
    }

    /* Booking complete card — full-bleed on mobile. */
    .express-root .gv-form-card[style*="max-width: 640px"] {
        margin: 0 !important;
        border-radius: 0 !important;
    }
}

/* Narrow phones (iPhone 14 390px, iPhone SE 375px) — collapse 2-up field
   groups to single column so date+time, return-date+return-time pairs each
   own a full row. Below 480px there isn't enough horizontal space for the
   44px icon-padding + native iOS date/time chrome inside half the viewport. */
@media (max-width: 480px) {
    .express-root .gv-field-group-2 {
        grid-template-columns: minmax(0, 1fr);
        gap: 12px;
    }

    /* Session 15.1.3 Polish Fix 7 — Step 2 vehicle-card price+select row
       collapses to a vertical stack at narrow phones. The 768 mobile rule
       set .gv-vehicle-aside to flex-direction: row with the Select button
       pinned via flex-shrink: 0 (Polish Fix 6's prominence boost). On
       iPhone SE 375px the row's intrinsic min-content (price block + gap
       + non-shrinking Select) summed past the available card-inner width,
       forcing .gv-main-step2's `grid-template-columns: 1fr` (resolved to
       minmax(auto, 1fr)) wider than the viewport because grid `auto` min
       picks the largest min-content of any track item. body:has(.express-root)
       overflow-x: clip from polish Fix 1 silently clipped the right edge,
       so trip-summary, hero copy, AND the Select button all chopped at the
       same viewport boundary. Stacking the aside vertically here means
       each child sets the row's min-content individually instead of
       summing — the column track resolves to viewport width and nothing
       overflows. The overflow-x: clip stays as defensive backstop and is
       now a no-op for this case. */
    .express-root .gv-vehicle-aside {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }
    .express-root .gv-vehicle-aside .gv-price-block {
        text-align: left;
        width: 100%;
    }
    .express-root .gv-vehicle-aside .gv-vehicle-select {
        width: 100%;
        justify-content: center;
    }
}

/* Narrow phones (e.g. iPhone SE 375px and below) — minor tightening only. */
@media (max-width: 420px) {
    .express-root .gv-headline {
        font-size: calc(22px * var(--xp-display-scale));
    }
    .express-root .gv-form-card,
    .express-root .gv-section-card {
        padding-left: 14px;
        padding-right: 14px;
    }
    .express-root .gv-section-card {
        margin-left: 12px;
        margin-right: 12px;
    }
    .express-root .gv-receipt {
        margin-left: 12px !important;
        margin-right: 12px !important;
    }
    .express-root .gv-vehicle-list {
        padding: 0 12px;
    }
    .express-root .gv-trip-summary {
        margin: 12px 12px 16px;
    }
    .express-root .gv-vehicle-name {
        font-size: calc(18px * var(--xp-display-scale));
    }
    .express-root .gv-price-amount {
        font-size: calc(22px * var(--xp-price-scale));
    }

    /* Session 15.1.1 Polish Fix 2 — stepper count visibility regression.
       Phase A bumped `.gv-stepper-btn` to 44×44 for the Apple-HIG tap
       target. On iPhone SE (375px) and iPhone 14 (390px) the stepper
       cell inner width is only ~120-128px, but the desktop layout
       (icon + gap + label/value block + space-between + 44 + gap + 44)
       totals ~160px — the "−" button overlapped the count number,
       hiding the "2" / "1" digit Mike reported in the iPhone SE screenshot.
       Fix: hide the decorative icon (the "Pax"/"Bags" mobile label is
       already the primary field affordance) and tighten the stepper
       padding + control gap. The +/− buttons keep their 44×44 tap
       target — only the icon and the surrounding chrome shrink. */
    .express-root .gv-stepper {
        padding: 10px;
        gap: 4px;
    }
    .express-root .gv-stepper-icon {
        display: none;
    }
    .express-root .gv-stepper-info {
        gap: 0;
        min-width: 0;
        flex: 1;
    }
    .express-root .gv-stepper-controls {
        gap: 2px;
        flex-shrink: 0;
    }
}

/* =============================================================================
   Session 7.1 — Embed-mode safety net (iframe resize feedback fix)
   =============================================================================
   When the wizard is loaded inside the embed iframe, embed-emitter.js stamps
   `[data-gvbooking-embedded]` on <html> at boot. These overrides neutralize the
   viewport-driven heights that would otherwise feed an infinite resize loop
   (parent grows iframe -> 100vh grows -> map/root grow -> measurement grows ->
   parent grows iframe again). Standalone /book/{slug} pages are not affected
   because the attribute is only set inside an iframe.
   ============================================================================= */

[data-gvbooking-embedded] .express-root {
    min-height: 0;
}

/* Embedded-only: force the map media element (iframe or static IMG) to fill
   the .gv-map-canvas container. Without this it falls back to a short
   intrinsic height (~150px) and leaves brown background visible below. */
[data-gvbooking-embedded] .express-root .gv-map-canvas .gv-map-img {
    width: 100%;
    height: 100%;
    min-height: 480px;
    object-fit: cover;
}

/* The measurement marker is on the layout wrapper, so body itself should
   size to its content rather than fill the iframe viewport. */
body:has([data-gvbooking-measure]) {
    height: auto;
    min-height: 0;
}

/* =============================================================================
   SESSION 10 — STEP 3 PAYMENT STAGE
   =============================================================================

   The payment-iframe surface from §6.5 of the design spec. The GHL invoice
   page (Nuxt SPA loaded from link.fastpaydirect.com) is rendered inside an
   iframe sized by the --gv-iframe-clip-viewport-h variable below. The
   native Atelier "Amount to pay" summary lives above the iframe; when the
   customer clicks the green "Pay $X.XX" button inside the iframe, GHL
   opens its hosted payment modal which overlays the entire viewport.

   Step-3 payment-stage tunables:

   --gv-iframe-clip-offset — translateY applied to the GHL invoice iframe
       to land the green "Pay" button in the visible viewport strip.

       Current value: 0px.

       Historical note: a value of -380px was used during a May 11, 2026
       live test against AtlantaAirport.Cab and the comment that lived here
       previously claimed that value was the verified magic number. The
       value was reset to 0 at some point and the comment was not updated.
       As of May 15, 2026, Mike confirmed the payment surface renders
       correctly with 0 offset.

       P3 followup: verify on a real production booking that the green Pay
       button is fully visible at the current 0 offset, and consider
       tightening the clip strip if dead-space is visible above/below the
       button.

   --gv-iframe-clip-viewport-h — visible height of the iframe in px.
       Current value: 600px. Mobile keeps the same value via the
       max-width: 768px rules near line 2587.
   ============================================================================= */

.express-root {
    --gv-iframe-clip-offset: 0;
    --gv-iframe-clip-viewport-h: 600px;
}

.express-root .gv-payment-stage {
    margin-top: 20px;
    border-top: 1px solid var(--xp-panel-line);
    background: var(--xp-panel);
}

.express-root .gv-payment-stage__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 18px 24px;
    background: linear-gradient(180deg, var(--xp-panel) 0%, var(--xp-panel-2) 100%);
    border-bottom: 1px solid var(--xp-panel-line);
    flex-wrap: wrap;
    gap: 8px;
}

.express-root .gv-payment-stage__secure {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--xp-success);
    font-weight: 600;
    font-size: 13px;
}

.express-root .gv-payment-stage__secure svg {
    width: 16px;
    height: 16px;
}

.express-root .gv-payment-stage__meta {
    font-size: 12px;
    color: var(--xp-panel-muted);
}

.express-root .gv-payment-stage__summary {
    padding: 28px 24px 24px;
    text-align: center;
    background: var(--xp-panel);
}

.express-root .gv-payment-stage__summary-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--xp-panel-muted);
    margin-bottom: 8px;
}

.express-root .gv-payment-stage__summary-amount {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-weight: var(--xp-price-weight);
    font-size: calc(48px * var(--xp-price-scale));
    color: var(--xp-panel-ink);
    line-height: 1;
}

.express-root .gv-payment-stage__summary-sub {
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    margin-top: 10px;
}

/* THE CLIP. overflow:hidden + position:absolute + top:negative is what
   hides the GHL invoice header/billing/line-items and lands the Pay
   button in the visible region. */
.express-root .gv-iframe-viewport {
    position: relative;
    height: var(--gv-iframe-clip-viewport-h);
    overflow: hidden;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
    border-bottom: 1px solid var(--xp-panel-line);
}

.express-root .gv-iframe-viewport iframe {
    position: absolute;
    top: var(--gv-iframe-clip-offset);
    left: 0;
    width: 100%;
    height: 600px;
    border: none;
    background: var(--xp-iframe-bg);
}

.express-root .gv-payment-stage__cta-hint {
    padding: 14px 24px 18px;
    text-align: center;
    font-size: 13px;
    color: var(--xp-panel-muted);
}

.express-root .gv-payment-stage__footer {
    padding: 14px 24px;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
    text-align: center;
    font-size: 12px;
    color: var(--xp-panel-muted);
    line-height: 1.5;
}

.express-root .gv-payment-stage__footer strong {
    color: var(--xp-panel-ink-2);
}

/* Mobile — drop the iframe viewport height slightly; the Pay button is
   still landed inside the strip because GHL's mobile breakpoint
   collapses the right rail too. */
@media (max-width: 768px) {
    .express-root {
        --gv-iframe-clip-viewport-h: 600px;
    }
    .express-root .gv-payment-stage__summary-amount {
        font-size: calc(40px * var(--xp-price-scale));
    }
}

/* Spinner — used by step3_substate='creating_invoice'. */
.express-root .gv-spinner {
    width: 44px;
    height: 44px;
    border: 3px solid var(--xp-panel-2);
    border-top-color: var(--xp-panel-ink);
    border-radius: 50%;
    margin: 0 auto 20px;
    animation: gvSpin 0.8s linear infinite;
}

@keyframes gvSpin {
    to { transform: rotate(360deg); }
}

.express-root .gv-spinner-title {
    font-family: var(--xp-font-display);
    font-weight: var(--xp-display-weight);
    font-size: calc(22px * var(--xp-display-scale));
    color: var(--xp-panel-ink);
    margin: 0 0 6px;
}

.express-root .gv-spinner-sub {
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    margin: 0;
}

/* Success mark — used by step3_substate='payment_succeeded'. */
.express-root .gv-success-mark {
    width: 72px;
    height: 72px;
    margin: 0 auto 18px;
    background: var(--green);
    color: var(--xp-on-status);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 36px;
    font-weight: 700;
}

.express-root .gv-success-title {
    font-family: var(--xp-font-display);
    font-weight: var(--xp-display-weight);
    font-size: calc(28px * var(--xp-display-scale));
    color: var(--xp-panel-ink);
    margin: 0 0 8px;
}

.express-root .gv-success-sub {
    color: var(--xp-panel-ink-2);
    font-size: 14px;
    margin: 0;
}

/* Invoice-error panel — used by step3_substate='invoice_error'. */
.express-root .gv-error-panel {
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: 18px 22px;
    margin-top: 12px;
}

/* Session 14 — neutral variant for the payment-wait timeout panel.
   Same cream surface but no terracotta accent — this state is calm-
   waiting, not error. Title gets a small animated dot to communicate
   ongoing activity. */
.express-root .gv-error-panel--neutral {
    border-left: 1px solid var(--xp-panel-line);
}

.express-root .gv-error-panel--neutral .gv-error-panel-title::before {
    content: "";
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--xp-panel-ink-2);
    margin-right: 10px;
    vertical-align: middle;
    animation: gv-calm-pulse 1.6s ease-in-out infinite;
}

@keyframes gv-calm-pulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
}

.express-root .gv-error-panel-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.express-root .gv-error-panel-icon {
    font-size: 22px;
    color: var(--xp-link);
}

.express-root .gv-error-panel-title {
    font-family: var(--xp-font-display);
    font-weight: var(--xp-display-weight);
    font-size: calc(18px * var(--xp-display-scale));
    color: var(--xp-panel-ink);
    margin: 0;
}

.express-root .gv-error-panel-body {
    color: var(--xp-panel-ink-2);
    font-size: 14px;
    line-height: 1.5;
    margin: 0 0 16px;
}

.express-root .gv-error-panel-actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.express-root .gv-error-panel-ref {
    margin: 14px 0 0;
    font-size: 11px;
    color: var(--xp-panel-muted);
    text-align: right;
}

.express-root .gv-error-panel-ref strong {
    color: var(--xp-panel-ink-2);
    font-family: var(--xp-font-body);
    letter-spacing: 0.04em;
}

/* Primary/secondary buttons inside the error panel. */
.express-root .gv-btn-primary {
    background: var(--xp-inverse-bg);
    color: var(--xp-panel);
    border: none;
    border-radius: var(--radius-sm);
    padding: 12px 22px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.express-root .gv-btn-primary:hover {
    background: var(--xp-inverse-bg-hover);
}

.express-root .gv-btn-primary:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.express-root .gv-btn-secondary {
    background: var(--xp-panel);
    color: var(--xp-panel-ink);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius-sm);
    padding: 11px 20px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}

.express-root .gv-btn-secondary:hover {
    border-color: var(--xp-panel-ink);
}

/* =============================================================================
   Session 15.1.6 Fix D — defense-in-depth containment on the Step 2 chain.
   =============================================================================
   Even after Fix B hardens every grid track to minmax(0, 1fr), defense in
   depth keeps any future regression localized: if a descendant ends up with
   intrinsic min-content > track width (e.g. an explicit width:N on a span,
   a long unbreakable city name in a customer-edited form field, a font that
   loads late and changes word widths), the overflow stops at the card edge
   instead of propagating up to .gv-main-step2 and then visually clipping at
   the device boundary.

   Pattern: min-width: 0 (so flex/grid items can shrink below their min-content)
   and max-width: 100% (so block elements never exceed their container). The
   vehicle-photo media gets max-width 100% + height: auto so a large photo
   never widens its own box.

   Scoped to @media (max-width: 980px) — same breakpoint where Step 2's main
   grid collapses to a single column. Desktop keeps its existing aside
   `min-width: 200px` and per-track sizing untouched.
   ============================================================================= */
@media (max-width: 980px) {
    .express-root .gv-vehicle-list {
        min-width: 0;
        max-width: 100%;
    }
    .express-root .gv-vehicle-card {
        /* `overflow: hidden` already on the base rule (line ~818). */
        max-width: 100%;
        min-width: 0;
    }
    .express-root .gv-vehicle-photo {
        min-width: 0;
        max-width: 100%;
    }
    .express-root .gv-vehicle-photo img,
    .express-root .gv-vehicle-photo svg {
        /* Preserve the base-rule sizing (position: absolute; inset: 0;
           width/height: 100%; object-fit: cover) even at narrow widths.
           Earlier `height: auto` here released the absolutely-positioned
           image to its natural intrinsic height, which let the photo
           bleed past its zone when the card collapsed in embedded
           contexts. */
        max-width: 100%;
        max-height: 100%;
        height: 100%;
    }
    .express-root .gv-vehicle-body {
        /* `min-width: 0` already on the base rule (line ~893). */
        max-width: 100%;
    }
    .express-root .gv-vehicle-aside {
        min-width: 0;
        max-width: 100%;
    }
    .express-root .gv-aside-stack {
        min-width: 0;
        max-width: 100%;
    }
}

/* -----------------------------------------------------------------------------
   Phase C — Payment modal shell.
   Hosts whatever payment surface the selected payment method needs
   (today: the GHL invoice iframe; later: the Stripe Payment Element).
   Live tokens consumed: --gv-modal-backdrop, --gv-z-modal, --surface,
   --surface-soft, --line, --ink, --ink-soft, --ink-muted, --radius-lg,
   --shadow-lg, --serif, --sans. The modal lives on the page root, NOT
   inside .express-root, so styles below are selector-global; Classic
   theme can adopt the same shell when Phase F lands.
   -------------------------------------------------------------------------- */
[x-cloak] { display: none !important; }

.gv-modal-backdrop {
    position: fixed;
    inset: 0;
    background: var(--gv-modal-backdrop, rgba(26, 26, 26, 0.55));
    backdrop-filter: blur(8px) saturate(120%);
    -webkit-backdrop-filter: blur(8px) saturate(120%);
    z-index: var(--gv-z-modal, 100);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    overflow-y: auto;
}

.gv-modal-card {
    background: var(--xp-panel);
    border-radius: var(--radius-lg, 20px);
    box-shadow: var(--shadow-lg, 0 12px 48px rgba(26, 26, 26, 0.10));
    width: 100%;
    max-width: 560px;
    max-height: min(90vh, 720px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    font-family: var(--xp-font-body);
    color: var(--xp-panel-ink);
}

.gv-modal-card .gv-sheet-handle {
    display: none;
}

.gv-modal-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 18px 24px 12px;
    border-bottom: 1px solid var(--xp-panel-line);
}

.gv-modal-card__title {
    font-family: var(--xp-font-display);
    font-weight: var(--xp-display-weight);
    font-size: calc(22px * var(--xp-display-scale));
    line-height: 1.2;
    color: var(--xp-panel-ink);
    margin: 0;
}

.gv-modal-card__close {
    background: transparent;
    border: 0;
    padding: 6px;
    color: var(--xp-panel-muted);
    cursor: pointer;
    border-radius: 999px;
    line-height: 0;
    transition: color 0.18s, background 0.18s;
}
.gv-modal-card__close:hover,
.gv-modal-card__close:focus-visible {
    color: var(--xp-panel-ink);
    background: var(--xp-panel-2);
    outline: none;
}
.gv-modal-card__close:focus-visible {
    box-shadow: var(--shadow-focus, 0 0 0 4px rgba(15, 27, 45, 0.12));
}

.gv-modal-card__body {
    padding: 16px 24px 24px;
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.gv-modal-card__footer {
    padding: 14px 24px;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
    text-align: center;
    font-size: 12px;
    color: var(--xp-panel-muted);
    line-height: 1.5;
}

.gv-modal-card-enter-start {
    opacity: 0;
    transform: scale(0.96);
}
.gv-modal-card-enter-end {
    opacity: 1;
    transform: scale(1);
}
.gv-modal-card-enter {
    transition: opacity 200ms cubic-bezier(.2,.7,.2,1),
                transform 200ms cubic-bezier(.2,.7,.2,1);
}

/* Phase C — payment-stage variant for the modal-hosted GHL iframe.
   The inline clip (--gv-iframe-clip-offset / --gv-iframe-clip-viewport-h)
   stayed declared for back-compat (per RECON implication #8) but is
   intentionally NOT applied here: the modal hosts a clean ~520px iframe
   with no clipping. */
.gv-payment-stage--modal {
    margin: 0;
    border-top: 0;
    background: var(--xp-panel);
}
.gv-payment-stage--modal .gv-payment-stage__summary {
    padding: 8px 0 20px;
}
.gv-payment-stage--modal .gv-payment-stage__summary-amount {
    font-size: calc(40px * var(--xp-price-scale));
}
.gv-iframe-host {
    position: relative;
    width: 100%;
    min-height: 720px;
    background: var(--xp-panel-2);
    border-radius: var(--radius-sm);
    overflow: hidden;
    border: 1px solid var(--xp-panel-line);
}
.gv-iframe-host iframe {
    width: 100%;
    height: 720px;
    border: 0;
    background: var(--xp-iframe-bg);
    display: block;
}

@media (max-width: 768px) {
    .gv-iframe-host {
        min-height: 640px;
    }
    .gv-iframe-host iframe {
        height: 640px;
    }
}

@media (max-width: 768px) {
    .gv-modal-backdrop {
        padding: 0;
        align-items: flex-end;
    }
    .gv-modal-card {
        max-width: 100%;
        width: 100%;
        max-height: 92vh;
        border-radius: var(--radius-lg, 20px) var(--radius-lg, 20px) 0 0;
    }
    .gv-modal-card .gv-sheet-handle {
        display: block;
    }
    .gv-modal-card-enter-start {
        opacity: 0;
        transform: translateY(16px);
    }
    .gv-modal-card-enter-end {
        opacity: 1;
        transform: translateY(0);
    }
}


/* ============================================================
   Phase D6 — Thank-you page.
   Mobile-first (375px viewport) layout for the post-booking
   confirmation surface. Replaces the inline block at
   atelier-3-step.blade.php lines 62-82 (Session 15.1 Bug 9).
   ============================================================ */

.express-root .gv-thank-you-main {
    padding: 24px 16px 48px;
}

.express-root .gv-thank-you-card {
    max-width: 640px;
    margin: 0 auto;
    background: var(--xp-panel);
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(26, 26, 26, 0.04), 0 1px 12px rgba(26, 26, 26, 0.04);
}

/* Hero / opener */
.express-root .gv-thank-you-hero {
    padding: 32px 20px 24px;
    text-align: center;
    background: var(--xp-panel-2);
    border-bottom: 1px solid var(--xp-panel-line);
}
.express-root .gv-thank-you-eyebrow {
    font-family: var(--xp-font-body);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.18em;
    color: var(--xp-link);
    margin-bottom: 12px;
}
.express-root .gv-thank-you-headline {
    font-family: var(--xp-font-display);
    font-size: calc(32px * var(--xp-display-scale));
    line-height: 1.1;
    color: var(--xp-panel-ink);
    margin: 0 0 12px;
    letter-spacing: var(--xp-display-track);
}
.express-root .gv-thank-you-headline em {
    font-style: italic;
    color: var(--xp-link);
    font-weight: 400;
}
.express-root .gv-thank-you-sub {
    font-family: var(--xp-font-body);
    font-size: 15px;
    line-height: 1.55;
    color: var(--xp-panel-ink-2);
    margin: 0;
    max-width: 460px;
    margin-left: auto;
    margin-right: auto;
}

/* Confirmation reference card */
.express-root .gv-thank-you-reference {
    padding: 20px;
    text-align: center;
    border-bottom: 1px solid var(--xp-panel-line);
    background: var(--xp-panel);
}
.express-root .gv-thank-you-reference-label {
    font-family: var(--xp-font-body);
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.16em;
    color: var(--xp-panel-muted);
    margin-bottom: 6px;
}
.express-root .gv-thank-you-reference-value {
    font-family: ui-monospace, monospace;
    font-size: 18px;
    letter-spacing: 0.04em;
    color: var(--xp-panel-ink);
    font-weight: 500;
}
.express-root .gv-thank-you-reference-email {
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--xp-panel-muted);
    margin-top: 10px;
}
.express-root .gv-thank-you-reference-email strong {
    color: var(--xp-panel-ink-2);
    font-weight: 500;
}

/* Section blocks */
.express-root .gv-thank-you-section {
    padding: 24px 20px;
    border-bottom: 1px solid var(--xp-panel-line);
}
.express-root .gv-thank-you-section:last-of-type {
    border-bottom: none;
}
.express-root .gv-thank-you-section-title {
    font-family: var(--xp-font-display);
    font-size: calc(16px * var(--xp-display-scale));
    color: var(--xp-panel-ink);
    margin: 0 0 16px;
    font-weight: var(--xp-display-weight);
    letter-spacing: var(--xp-display-track);
}

/* Detail list (Your trip) */
.express-root .gv-thank-you-detail-list {
    margin: 0;
    font-family: var(--xp-font-body);
}
.express-root .gv-thank-you-detail-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 0;
    border-bottom: 1px dotted var(--xp-panel-line);
}
.express-root .gv-thank-you-detail-row:last-child {
    border-bottom: none;
}
.express-root .gv-thank-you-detail-row dt {
    font-family: var(--xp-font-body);
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.14em;
    color: var(--xp-panel-muted);
}
.express-root .gv-thank-you-detail-row dd {
    margin: 0;
    font-size: 14px;
    color: var(--xp-panel-ink);
    line-height: 1.4;
}

/* Payment block */
.express-root .gv-thank-you-payment {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.express-root .gv-thank-you-payment-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    font-family: var(--xp-font-body);
}
.express-root .gv-thank-you-payment-label {
    font-size: 13px;
    color: var(--xp-panel-ink-2);
}
.express-root .gv-thank-you-payment-value {
    font-family: var(--xp-font-price);
    font-variant-numeric: lining-nums tabular-nums;
    font-size: calc(22px * var(--xp-price-scale));
    color: var(--xp-panel-ink);
    font-weight: var(--xp-price-weight);
    letter-spacing: var(--xp-price-track);
}
.express-root .gv-thank-you-payment-method {
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--xp-panel-muted);
    margin-top: -4px;
}
.express-root .gv-thank-you-payment-sub {
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    margin: 8px 0 0;
    line-height: 1.5;
}

/* Badges */
.express-root .gv-thank-you-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    font-family: var(--xp-font-body);
    font-size: 12px;
    font-weight: 500;
    align-self: flex-start;
    margin-top: 4px;
}
.express-root .gv-thank-you-badge svg {
    width: 14px;
    height: 14px;
}
.express-root .gv-thank-you-badge--paid {
    background: rgba(74, 122, 77, 0.12);
    color: var(--xp-success);
}
.express-root .gv-thank-you-badge--authorized {
    /* Distinct neutral blue — not green (paid), not yellow (pending). */
    background: rgba(74, 109, 167, 0.12);
    color: var(--xp-badge-info-ink);
}
.express-root .gv-thank-you-badge--pending {
    background: rgba(204, 159, 51, 0.14);
    color: var(--xp-badge-warn-ink);
}
.express-root .gv-thank-you-badge--voided {
    background: rgba(154, 154, 150, 0.18);
    color: var(--xp-panel-muted);
}

/* Attention block (offline methods) */
.express-root .gv-thank-you-attention {
    margin-top: 12px;
    padding: 14px 16px;
    background: rgba(204, 159, 51, 0.10);
    border: 1px solid rgba(204, 159, 51, 0.30);
    border-radius: 10px;
    font-family: var(--xp-font-body);
    font-size: 13px;
    line-height: 1.55;
    color: var(--xp-attention-ink);
}

/* What happens next */
.express-root .gv-thank-you-next-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.express-root .gv-thank-you-next-list li {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    font-family: var(--xp-font-body);
    font-size: 14px;
    color: var(--xp-panel-ink-2);
    line-height: 1.5;
}
.express-root .gv-thank-you-next-step {
    flex: 0 0 24px;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--xp-panel-line);
    border-radius: 50%;
    background: var(--xp-panel);
    color: var(--xp-link);
    font-family: var(--xp-font-body);
    font-size: 12px;
    font-weight: 500;
}

/* Policy + footnote */
.express-root .gv-thank-you-policy {
    padding: 20px;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
    font-family: var(--xp-font-body);
    font-size: 13px;
    line-height: 1.55;
    color: var(--xp-panel-ink-2);
}
.express-root .gv-thank-you-policy p {
    margin: 0 0 8px;
}
.express-root .gv-thank-you-policy p:last-child {
    margin-bottom: 0;
}
.express-root .gv-thank-you-policy-extra {
    color: var(--xp-panel-muted);
    font-size: 12px;
}
.express-root .gv-thank-you-policy-phone {
    color: var(--xp-link);
    text-decoration: none;
    font-weight: 500;
}
.express-root .gv-thank-you-footnote {
    padding: 16px 20px 24px;
    text-align: center;
    font-family: var(--xp-font-body);
    font-size: 11px;
    color: var(--xp-panel-muted);
    margin: 0;
    line-height: 1.5;
}

/* Desktop (≥769px) — softer presentation, slightly bigger headline */
@media (min-width: 769px) {
    .express-root .gv-thank-you-main {
        padding: 48px 24px 64px;
    }
    .express-root .gv-thank-you-hero {
        padding: 48px 32px 32px;
    }
    .express-root .gv-thank-you-headline {
        font-size: calc(42px * var(--xp-display-scale));
    }
    .express-root .gv-thank-you-sub {
        font-size: 16px;
    }
    .express-root .gv-thank-you-section {
        padding: 28px 32px;
    }
    .express-root .gv-thank-you-reference {
        padding: 24px 32px;
    }
    .express-root .gv-thank-you-detail-row {
        flex-direction: row;
        align-items: baseline;
        gap: 16px;
    }
    .express-root .gv-thank-you-detail-row dt {
        flex: 0 0 100px;
    }
    .express-root .gv-thank-you-policy,
    .express-root .gv-thank-you-footnote {
        padding-left: 32px;
        padding-right: 32px;
    }
}

/* ============================================================
   Step-1 polish additions (2026-05-23)
   ============================================================
   These rules are APPENDED to atelier.css. They:
   - Rebalance .gv-stepper-select so the dropdown fills the
     value-side real estate (the original min-width: 36px chip
     left a long empty stretch next to the label)
   - Style the new .gv-field--time-picker three-segment cluster
     that replaces native <input type="time"> on Step 1
   - Style the per-stop "×" remove button to match Atelier pills
   ============================================================ */

/* --- Stepper-select rebalance --- */
/* The wide pill-card has two regions: gv-stepper-info (label) on the
   left, gv-stepper-controls (select) on the right. The previous CSS
   sized the select at min-height 36px with auto width — fine on a
   320px mobile but visually anemic on a 600px desktop card. The fix
   gives gv-stepper-controls a minimum width so the select reads as a
   real control, and grows the select font slightly to anchor weight. */
.express-root .gv-stepper--select .gv-stepper-controls {
    min-width: 120px;
    display: flex;
    justify-content: flex-end;
}

.express-root .gv-stepper--select .gv-stepper-select {
    flex: 0 0 auto;
    min-width: 96px;
    height: 40px;
    padding: 0 36px 0 16px;
    font-size: 15px;
    text-align: left;
    text-align-last: left;
}

/* Mobile keeps the chip compact — at narrow widths even the rebalanced
   control needs to fit a 320px viewport without crowding the label. */
@media (max-width: 768px) {
    .express-root .gv-stepper--select .gv-stepper-controls {
        min-width: 88px;
    }
    .express-root .gv-stepper--select .gv-stepper-select {
        min-width: 72px;
        height: 36px;
        padding: 0 28px 0 12px;
        font-size: 14px;
    }
}

/* --- Time picker: three-segment cluster --- */
/* Sits inside a gv-field card. The label runs above; the row of three
   selects (hour : minute period) sits below, aligned right against
   the inner padding. Each segment is a pill-shaped select reusing the
   gv-time-picker-segment styling. */
.express-root .gv-field--time-picker {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 10px 16px 10px 56px;
    position: relative;
    min-height: 64px;
    background: var(--xp-panel-2);
    border-radius: var(--radius);
}

.express-root .gv-field--time-picker .gv-field-icon {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--xp-panel-ink-2);
}

.express-root .gv-field--time-picker .gv-field-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 4px;
    line-height: 1;
}

.express-root .gv-time-picker-row {
    display: flex;
    align-items: center;
    gap: 4px;
}

.express-root .gv-time-picker-segment {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    height: 34px;
    padding: 0 24px 0 10px;
    border-radius: 8px;
    background-color: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    color: var(--xp-panel-ink);
    cursor: pointer;
    font-family: var(--xp-font-body);
    font-size: 15px;
    font-weight: 500;
    line-height: 1;
    transition: all 0.15s ease;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2358514a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 6px center;
    background-size: 10px 10px;
}

.express-root .gv-time-picker-segment:hover {
    border-color: var(--xp-panel-ink);
    color: var(--xp-panel-ink);
}

.express-root .gv-time-picker-segment:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

.express-root .gv-time-picker-period {
    min-width: 64px;
    margin-left: 6px;
}

.express-root .gv-time-picker-sep {
    color: var(--xp-panel-muted);
    font-weight: 600;
    font-size: 16px;
    line-height: 1;
    user-select: none;
    padding: 0 2px;
}

@media (max-width: 768px) {
    .express-root .gv-field--time-picker {
        padding: 10px 14px 10px 50px;
        min-height: 60px;
    }
    .express-root .gv-time-picker-segment {
        height: 32px;
        font-size: 14px;
        padding: 0 22px 0 8px;
    }
    .express-root .gv-time-picker-period {
        min-width: 56px;
    }
}

/* --- Stop-remove pill: × button to dismiss an extra stop --- */
/* Visually clean cross button aligned with the stop-row's vertical
   midpoint. Smaller than the standard gv-pill so it reads as a
   secondary affordance. */
.express-root .gv-pill.gv-stop-remove {
    width: 32px;
    height: 32px;
    min-width: 32px;
    padding: 0;
    display: grid;
    place-items: center;
    font-size: 18px;
    line-height: 1;
    color: var(--xp-panel-muted);
}

.express-root .gv-pill.gv-stop-remove:hover {
    color: var(--xp-link);
    border-color: var(--accent);
    background: transparent;
}

/* Phones: the add-to-trip pill rule (max-width 768px, flex: 1 1 50%)
   also matched this button and stretched it to half the stop row,
   squeezing the stop address. Keep it a fixed 44px round tap target. */
@media (max-width: 768px) {
    .express-root .gv-pill.gv-stop-remove {
        flex: 0 0 44px;
        width: 44px;
        height: 44px;
        min-width: 44px;
    }
}

/* --- Optionlist & extra custom-field selects on Step 3 ---
   The custom-field component's optionlist / extra branches render a
   native <select> inside a .gv-field-select label. Previously only
   styled inside .gv-childseat-picker; we extend the same pill
   aesthetic globally so e.g. the Meet & Greet question on Step 3
   matches the rest of the wizard's controls. */
.express-root .gv-field-select {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 16px;
    background: var(--xp-panel-2);
    border-radius: var(--radius);
    margin-bottom: 12px;
}

.express-root .gv-field-select > .gv-field-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 500;
    line-height: 1;
}

.express-root .gv-field-select > select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    height: 40px;
    padding: 0 36px 0 14px;
    border-radius: 10px;
    background-color: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    color: var(--xp-panel-ink);
    cursor: pointer;
    font-family: var(--xp-font-body);
    font-size: 15px;
    font-weight: 500;
    line-height: 1;
    transition: all 0.15s ease;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2358514a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px 12px;
    width: 100%;
}

.express-root .gv-field-select > select:hover {
    border-color: var(--xp-panel-ink);
}

.express-root .gv-field-select > select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

/* The child-seat picker has its own narrower select rule (see
   line ~580 of the base atelier.css); the more specific selector
   .gv-childseat-picker .gv-field-select keeps it scoped. The
   global rule above is the fallback for any other .gv-field-select
   that doesn't have a more-specific override. */

/* ============================================================
   Step-1 polish FOLLOW-UP (2026-05-23 — second pass)
   ============================================================
   Appended to atelier.css after the initial step-1-polish block.
   Fixes the date-input alignment regression caused by the
   .gv-field--time-picker being taller than its sibling .gv-field
   inside the same .gv-field-group-2 row.

   The problem: .gv-field-group-2 is a 2-column grid with
   `align-items: stretch` (default), so both children stretch to
   the height of the tallest. The time picker's stacked layout
   (label above, 3 selects below) makes it ~64px tall, which
   stretches the date input vertically — the date column then
   shows extra padding above/below its single line of text.

   Fix: tighten the time picker's vertical rhythm so it matches
   the date input's natural height (~52px including padding),
   and explicitly align-items: stretch the row so both children
   share the same height predictably. The date field's label
   stays in the upper-left position via its existing
   .gv-field--native-picker rule.
   ============================================================ */

/* Match the time-picker card's height to the date field's height. */
.express-root .gv-field--time-picker {
    padding: 8px 16px 8px 56px;
    min-height: 52px;
    justify-content: center;
}

.express-root .gv-field--time-picker .gv-field-label {
    margin-bottom: 3px;
}

.express-root .gv-time-picker-row {
    gap: 3px;
}

/* Slightly shorter pills so the whole cluster fits the 52px card
   without crowding the label above. */
.express-root .gv-time-picker-segment {
    height: 28px;
    padding: 0 22px 0 8px;
    font-size: 14px;
    background-size: 9px 9px;
    background-position: right 5px center;
}

.express-root .gv-time-picker-period {
    min-width: 56px;
}

.express-root .gv-time-picker-sep {
    font-size: 14px;
}

/* Belt-and-braces — explicitly equal-height row. The grid default
   is `stretch` but some flexbox fallback paths inherit `start`,
   so be explicit. */
.express-root .gv-field-group-2 {
    align-items: stretch;
}

/* Mobile keeps the same proportions, just smaller pills. */
@media (max-width: 768px) {
    .express-root .gv-field--time-picker {
        padding: 8px 14px 8px 50px;
        min-height: 50px;
    }
    .express-root .gv-time-picker-segment {
        height: 26px;
        font-size: 13px;
        padding: 0 20px 0 7px;
    }
    .express-root .gv-time-picker-period {
        min-width: 50px;
    }
}


/* Step-1 polish — show the eyebrow label on native date/time pickers
   so the date card reads "PICKUP DATE" above its value, symmetrical
   with the time card's "PICKUP TIME" eyebrow. The original
   .gv-field--native-picker rule (line 408) hides this label as a
   hedge against native-browser placeholder collision; date inputs
   with real values don't have that collision, so the label is safe
   to show. */
.express-root .gv-field--native-picker .gv-field-label {
    display: block;
    margin-bottom: 2px;
}

/* Step-1 polish — match the date card's layout to the time card.
   The .gv-field--time-picker rule uses flex column + centered to
   group its eyebrow + value pills as a vertically-centered cluster.
   The date card was using default block layout, so its eyebrow sat
   at the top and its input sat below in normal flow — visually
   misaligned with the time card. This makes both cards use the
   same flex layout. Icon repositioned from bottom-anchored to
   center-anchored to match the time card's centered icon. */
.express-root .gv-field--native-picker {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-top: 8px;
    padding-bottom: 8px;
}

.express-root .gv-field--native-picker .gv-field-icon {
    bottom: auto;
    top: 50%;
    transform: translateY(-50%);
}

/* ============================================================
   Phase D.1.1 — per-stop "Wait time" dropdown
   ============================================================
   Lives inside each .gv-stop-row alongside the address input. The
   dropdown reuses the .gv-field-select visual vocabulary (eyebrow +
   native <select> on a soft surface) but at a tighter width so two
   columns fit comfortably on desktop. On narrow phones the row wraps
   and the dropdown drops below the address — the .gv-stop-row card
   rule below sets flex-wrap: wrap.
   ============================================================ */

/* The stop row itself is the self-contained card grouping the address
   field, the wait-time control, and the × remove button. Phase 2c: the
   flex layout (display/align/gap/margin) moved here from the inline style,
   because rows are now shown with x-show, which clears an inline display
   value when it shows an element. No overflow:hidden — the wait-time
   popover opens an absolutely-positioned dropdown that must not be
   clipped. */
.express-root .gv-stop-row {
    display: flex;
    align-items: stretch;
    gap: 8px;
    margin-bottom: 8px;
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 12px 14px;
    background: var(--xp-panel-2);
    flex-wrap: wrap;
}

/* Flattened to transparent so the .gv-stop-row card is the only visible
   container (no box-in-box). Label + select control unchanged. */
.express-root .gv-stop-wait {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 2px 0;
    background: transparent;
    border-radius: var(--radius);
    min-width: 130px;
    align-self: stretch;
    justify-content: center;
}

.express-root .gv-stop-wait-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 500;
    line-height: 1;
}

.express-root .gv-stop-wait-select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    height: 32px;
    padding: 0 28px 0 10px;
    border-radius: 8px;
    background-color: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    color: var(--xp-panel-ink);
    cursor: pointer;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2358514a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 10px 10px;
    width: 100%;
}

.express-root .gv-stop-wait-select:hover { border-color: var(--xp-panel-ink); }

.express-root .gv-stop-wait-select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

/* Phase D.1.1 — per-vehicle price-block sub-line.
   Renders under the "From $XX.XX" total on Step 2 vehicle cards when
   the wait-time charge contributes to the price. Right-aligned to match
   the existing .gv-price-block (text-align: right) so it stays inside
   the same column without breaking layout. */
.express-root .gv-price-breakdown {
    margin-top: 4px;
    font-size: 12px;
    color: var(--xp-panel-muted);
    line-height: 1.3;
}

.express-root .gv-price-breakdown-line {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

.express-root .gv-price-breakdown-line span:last-child {
    font-variant-numeric: tabular-nums;
}

/* === datetime-stepper polish (2026-05-24) === */
/* Step 1 Date / Time / Passenger / Luggage row — visual consistency fixes.

   Problems addressed:
   - Native date input's ::-webkit-calendar-picker-indicator rendered as a
     tiny dim chevron-calendar squished to the right edge. Browser-default
     chrome that looked unfinished against the otherwise-polished field.
     Hidden here; the entire .gv-field--native-picker label still routes
     clicks to the underlying input which opens the picker.
   - .gv-stepper--select .gv-stepper-select used min-width:96px which let
     Firefox auto-grow based on option-list width — passenger select with
     max=8 rendered at one width, luggage select with max=9 at another.
     Locked to fixed width here.
   - Value text was left-aligned at padding-left:16px which made single-
     digit values (1) feel awkwardly offset against the chevron, while
     double-digit values (12) read fine. Centered so any digit count
     reads balanced.
*/

/* Hide the native date picker chrome (WebKit/Blink). The entire field
   label remains the click target; tapping anywhere on the cream surface
   opens the picker via the native <input type="date"> default behavior. */
.express-root .gv-field--native-picker input[type="date"]::-webkit-calendar-picker-indicator {
    opacity: 0;
    width: 100%;
    height: 100%;
    position: absolute;
    inset: 0;
    cursor: pointer;
}

/* Make the date input fill the field so the click target is the whole
   cream rectangle, not just the small text area. */
.express-root .gv-field--native-picker input[type="date"] {
    width: 100%;
    cursor: pointer;
}

/* The field is position:relative already (.gv-field sets position:
   relative for the absolute-positioned icon). Adding pointer cursor to
   the whole label so the affordance is obvious on hover. */
.express-root .gv-field--native-picker {
    cursor: pointer;
}

/* Stepper select: fixed dimensions so passenger + luggage are pixel-
   identical regardless of option-list contents, with centered text so
   any digit count balances visually around the chevron. */
.express-root .gv-stepper--select .gv-stepper-select {
    width: 96px;
    min-width: 96px;
    height: 40px;
    padding: 0 32px 0 16px;
    font-size: 15px;
    font-weight: 500;
    text-align: center;
    text-align-last: center;
}

/* Tighten the controls column so both steppers reserve the same right-
   side footprint. Was min-width:120px; lock it. */
.express-root .gv-stepper--select .gv-stepper-controls {
    min-width: 96px;
    width: 96px;
}
/* === end datetime-stepper polish === */



/* === Universal select popover (2026-05-24) ===
   Powers <x-booking.select-popover>. Two variants:
     - card    — full .gv-trip-control shell (uses existing rules)
     - compact — inline field for custom fields, child seats, wait time
   The popover and rows are SHARED by both variants. */

/* --- Compact trigger field --- */
.express-root .gv-select-compact {
    position: relative;
    display: block;
    margin-bottom: 8px;
}
.express-root .gv-select-compact-label {
    display: block;
    font-size: 11px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 4px;
}
.express-root .gv-select-compact-trigger {
    appearance: none;
    width: 100%;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 10px 14px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 44px;
    transition: border-color 0.15s ease;
}
.express-root .gv-select-compact-trigger:hover,
.express-root .gv-select-compact-trigger:focus-visible {
    border-color: var(--xp-panel-ink);
    outline: none;
}
.express-root .gv-select-compact-trigger[aria-expanded="true"] {
    border-color: var(--accent);
}
.express-root .gv-select-compact-value {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.express-root .gv-select-compact-chevron {
    width: 10px;
    height: 10px;
    color: var(--xp-panel-muted);
    flex-shrink: 0;
}

/* --- The popover surface (shared by both variants) --- */
.express-root .gv-select-popover {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 30;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    box-shadow: 0 12px 32px rgba(26, 26, 26, 0.12), 0 2px 8px rgba(26, 26, 26, 0.06);
    padding: 6px;
}
.express-root .gv-select-popover--scroll {
    max-height: 260px; /* ~6 rows × 40px + padding + a hint of the 7th */
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--xp-panel-line) transparent;
}
.express-root .gv-select-popover::-webkit-scrollbar {
    width: 8px;
}
.express-root .gv-select-popover::-webkit-scrollbar-track {
    background: transparent;
}
.express-root .gv-select-popover::-webkit-scrollbar-thumb {
    background: var(--xp-panel-line);
    border-radius: 4px;
    border: 2px solid var(--xp-panel);
}
.express-root .gv-select-popover::-webkit-scrollbar-thumb:hover {
    background: var(--xp-panel-muted);
}

/* --- A row inside the popover. Three-state color signal matches the
       platform rule: passive (ink) / hover (cream surface-soft) /
       selected (terracotta is-active). Price suffix uses ink-muted to
       de-emphasize relative to the label. --- */
.express-root .gv-select-popover-row {
    appearance: none;
    width: 100%;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    padding: 10px 14px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: left;
    line-height: 1.2;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.express-root .gv-select-popover-row + .gv-select-popover-row,
.express-root .gv-select-popover-row--placeholder + .gv-select-popover-row {
    margin-top: 2px;
}
.express-root .gv-select-popover-row:hover:not(.is-active) {
    background: var(--xp-panel-2);
    border-color: var(--xp-panel-line);
}
.express-root .gv-select-popover-row.is-active {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}
.express-root .gv-select-popover-row.is-active .gv-select-popover-row-price {
    color: var(--accent-ink);
    opacity: 0.85;
}
.express-root .gv-select-popover-row--placeholder {
    color: var(--xp-panel-muted);
    font-style: italic;
}
.express-root .gv-select-popover-row-price {
    font-size: 12px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}


/* === Universal select popover (2026-05-24) ===
   Powers <x-booking.select-popover>. Two variants:
     - card    — full .gv-trip-control shell (uses existing rules)
     - compact — inline field for custom fields, child seats, wait time
   The popover and rows are SHARED by both variants. */

/* --- Compact trigger field --- */
.express-root .gv-select-compact {
    position: relative;
    display: block;
    margin-bottom: 8px;
}
.express-root .gv-select-compact-label {
    display: block;
    font-size: 11px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 4px;
}
.express-root .gv-select-compact-trigger {
    appearance: none;
    width: 100%;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 10px 14px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 44px;
    transition: border-color 0.15s ease;
}
.express-root .gv-select-compact-trigger:hover,
.express-root .gv-select-compact-trigger:focus-visible {
    border-color: var(--xp-panel-ink);
    outline: none;
}
.express-root .gv-select-compact-trigger[aria-expanded="true"] {
    border-color: var(--accent);
}
.express-root .gv-select-compact-value {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.express-root .gv-select-compact-chevron {
    width: 10px;
    height: 10px;
    color: var(--xp-panel-muted);
    flex-shrink: 0;
}



/* === Universal select popover (2026-05-24) ===
   Powers <x-booking.select-popover>. Two variants:
     - card    — full .gv-trip-control shell (uses existing rules)
     - compact — inline field for custom fields, child seats, wait time
   The popover and rows are SHARED by both variants. */

/* --- Compact trigger field --- */
.express-root .gv-select-compact {
    position: relative;
    display: block;
    margin-bottom: 8px;
}
.express-root .gv-select-compact-label {
    display: block;
    font-size: 11px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 4px;
}
.express-root .gv-select-compact-trigger {
    appearance: none;
    width: 100%;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 10px 14px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 44px;
    transition: border-color 0.15s ease;
}
.express-root .gv-select-compact-trigger:hover,
.express-root .gv-select-compact-trigger:focus-visible {
    border-color: var(--xp-panel-ink);
    outline: none;
}
.express-root .gv-select-compact-trigger[aria-expanded="true"] {
    border-color: var(--accent);
}
.express-root .gv-select-compact-value {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.express-root .gv-select-compact-chevron {
    width: 10px;
    height: 10px;
    color: var(--xp-panel-muted);
    flex-shrink: 0;
}



/* === Universal select popover (2026-05-24) ===
   Powers <x-booking.select-popover>. Two variants:
     - card    — full .gv-trip-control shell (uses existing rules)
     - compact — inline field for custom fields, child seats, wait time
   The popover and rows are SHARED by both variants. */

/* --- Compact trigger field --- */
.express-root .gv-select-compact {
    position: relative;
    display: block;
    margin-bottom: 8px;
}
.express-root .gv-select-compact-label {
    display: block;
    font-size: 11px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 4px;
}
.express-root .gv-select-compact-trigger {
    appearance: none;
    width: 100%;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 10px 14px;
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 44px;
    transition: border-color 0.15s ease;
}
.express-root .gv-select-compact-trigger:hover,
.express-root .gv-select-compact-trigger:focus-visible {
    border-color: var(--xp-panel-ink);
    outline: none;
}
.express-root .gv-select-compact-trigger[aria-expanded="true"] {
    border-color: var(--accent);
}
.express-root .gv-select-compact-value {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.express-root .gv-select-compact-chevron {
    width: 10px;
    height: 10px;
    color: var(--xp-panel-muted);
    flex-shrink: 0;
}


/* Smart-placement modifiers: --below is a no-op marker for symmetry;
   --above flips the popover anchor upward so it doesn't get clipped
   when the trigger sits near the iframe bottom edge. Same pattern
   ships inline on .gv-date-popover and .gv-time-popover. */
.express-root .gv-select-popover.gv-select-popover--below {
    /* No override — inherits default downward positioning */
}
.express-root .gv-select-popover.gv-select-popover--above {
    top: auto;
    bottom: calc(100% + 6px);
}

/* =============================================================================
   VEHICLE-CARD-RESPONSIVE-V1 — container-query-driven reflow (Step 2 card).

   Single source of truth for the Atelier vehicle card's responsive behavior.
   The card reflows on its OWN inline-size (not the viewport), so embedded-
   iframe contexts work regardless of the client column's width.

   Two states:
     - Wide  (card >= 600px): the existing 3-column [photo | body | aside]
                               layout — standalone look preserved.
     - Stacked (card < 600px): photo on top (16:9), body middle, footer with
                               horizontal [price | Select] aside. A second
                               sub-threshold at 380px stacks the aside
                               vertically so Select stays a comfortable tap
                               target.
   Amenities are non-wrapping inline chips that wrap as a group.

   Identical behavior contract is replicated in taxibooking-classic.css and
   taxibooking-polished.css with each theme's own prefix and visual tokens.
   Follow-up: factor the structural skeleton into a shared partial all three
   themes import.

   Source-order note: this block lives at the end of the file so it wins over
   the legacy @media-based card collapse rules above (same selector specificity).
   ============================================================================= */

/* container-type/container-name now live on .gv-vehicle-list (see Vehicle cards
   section, ~line 1042). Hosting on the card itself is a silent no-op because a
   container query cannot restyle its own container element. */

.express-root .gv-amenity {
    white-space: nowrap;
}

@container gv-vehicle-card (max-width: 600px) {
    .express-root .gv-vehicle-card {
        grid-template-columns: minmax(0, 1fr);
    }
    .express-root .gv-vehicle-photo {
        aspect-ratio: 16 / 9;
    }
    .express-root .gv-vehicle-body {
        padding: 18px 20px;
    }
    .express-root .gv-vehicle-amenities {
        gap: 6px;
    }
    .express-root .gv-vehicle-aside {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        gap: 12px;
        padding: 14px 20px;
        background: var(--xp-panel-2);
        border-left: none;
        border-top: 1px solid var(--xp-panel-line);
        min-width: 0;
    }
    .express-root .gv-price-block {
        text-align: left;
        flex: 1 1 auto;
        min-width: 0;
    }
    .express-root .gv-vehicle-select {
        width: auto;
        min-width: 160px;
        flex: 0 1 auto;
    }
}

@container gv-vehicle-card (max-width: 380px) {
    .express-root .gv-vehicle-aside {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }
    .express-root .gv-price-block {
        text-align: center;
    }
    .express-root .gv-vehicle-select {
        width: 100%;
        min-width: 0;
    }
}

/* MOBILE-PRICE-CENTERED-2026-07-08 — Fix 1.
   The mobile @media(768) override (row layout, text-align:left, 24px) plus the
   @container(600px) row/left rule shrank + left-aligned the vehicle price on
   phones. This authoritative block is placed LAST in source so it out-ranks
   both (equal specificity 0,2,0 → source order wins) at every phone width,
   restoring the desktop intent: a centered, large, prominent "FROM $X" price
   stacked above a full-width Select button. */
@media (max-width: 768px) {
    .express-root .gv-vehicle-aside {
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 14px;
    }
    .express-root .gv-price-block {
        text-align: center;
        min-width: 0;
    }
    .express-root .gv-price-amount {
        font-size: calc(34px * var(--xp-price-scale));
        font-weight: var(--xp-price-weight);
    }
    .express-root .gv-price-amount sup {
        font-size: 17px;
        margin-top: 5px;
    }
    .express-root .gv-vehicle-select {
        width: 100%;
        min-width: 0;
    }
}

/* MOBILE-PRICE-CENTERED-2026-07-08b — Fix 1 CORRECTION (on top of 6f384c6).
   6f384c6's block targeted `.gv-price-block` / `.gv-price-amount` at specificity
   0,2,0. At <=480px the rule `.express-root .gv-vehicle-aside .gv-price-block
   { text-align:left; width:100% }` (atelier.css:~2790, specificity 0,3,0)
   OUT-RANKS it, so on a 375px phone the price stayed LEFT-aligned. (The 34px
   size was already winning — the last 0,2,0 `.gv-price-amount` rule in source
   set it — but this block also pins the size at 0,3,0 so it can never regress.)
   The @container(600) rule at ~:4736 is only 0,2,0 and precedes 6f384c6 in
   source, so it never competed: specificity, NOT the container/media cascade
   boundary, is the arbiter here. This authoritative block raises the selectors
   to 0,3,0 (aside-scoped, equal to the :2790 rule) AND sits LAST in source, so
   it wins in every phone context — a centered, large "FROM $X" above a
   full-width Select. */
@media (max-width: 768px) {
    .express-root .gv-vehicle-aside .gv-price-block {
        text-align: center;
        width: 100%;
        min-width: 0;
    }
    .express-root .gv-vehicle-aside .gv-price-amount {
        font-size: calc(34px * var(--xp-price-scale));
        font-weight: var(--xp-price-weight);
    }
    .express-root .gv-vehicle-aside .gv-price-amount sup {
        font-size: 17px;
        margin-top: 5px;
    }
}

/* Per-tenant "Hide map on mobile devices" (extra_settings.map.hide_on_mobile).
   <body data-hide-map-mobile="1"> is set in components/layouts/booking.blade.php.
   Hides Step-1 (.gv-map-canvas) and Step-2 (.gv-mini-map) map units on phones.
   !important + attribute-scoped selector beats the theme's plain
   `.<theme>-root .gv-map-canvas` mobile rules (specificity 0,0,2,0, no !important). */
@media (max-width: 768px) {
    [data-hide-map-mobile="1"] .gv-map-canvas,
    [data-hide-map-mobile="1"] .gv-mini-map {
        display: none !important;
    }
}

/* =============================================================================
   Express 4-step chrome
   -----------------------------------------------------------------------------
   Everything below is new for express-4-step: the 4-pill stepper, the mobile
   step header, the main + trip-pass rail grid, the trip pass, the mobile
   total bar, the child-seat disclosure, and the overrides that move Atelier's
   receipt-sidebar widgets (gratuity, promo, fare breakdown, total) into the
   Step 4 main column. Visual reference: prototype.html. Breakpoint: the rail
   and stepper appear at >= 820px; below that the mobile header + bar take over.
   ============================================================================= */

body:has(.express-root) { background: var(--bg); }

/* Phase 2i: display and price weights come from the font preset
   (.express-root[data-font] blocks at the top of this file). */
.express-root .gv-headline,
.express-root .gv-spinner-title,
.express-root .gv-success-title,
.express-root .gv-thank-you-headline,
.express-root .gv-brand-name,
.express-root .gv-vehicle-name {
    font-weight: var(--xp-display-weight);
}
.express-root .gv-price-amount,
.express-root .gv-receipt-total-value,
.express-root .gv-payment-stage__summary-amount {
    font-weight: var(--xp-price-weight);
}

.express-root .gv-headline {
    font-size: calc(42px * var(--xp-display-scale));
    line-height: 1.05;
    letter-spacing: var(--xp-display-track);
}
.express-root .gv-headline em { font-style: italic; color: var(--xp-panel-ink); }
.express-root .gv-eyebrow { color: var(--xp-panel-ink-2); }
.express-root .gv-eyebrow::before { background: var(--xp-amber); }
.express-root .gv-subheadline { color: var(--xp-panel-ink-2); }

/* Section headings: display font at the UI size (Phase 2i). */
.express-root .gv-section-title {
    font-family: var(--xp-font-display);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0;
}
.express-root .gv-section-num {
    font-family: var(--xp-font-body);
    font-weight: 700;
}

/* ---- Head: desktop stepper + mobile step header ---- */
.express-root .xp-head {
    max-width: 1120px;
    margin: 0 auto;
    padding: 16px 18px 2px;
}

.express-root .xp-stepper { display: none; }
.express-root .xp-stepper ol {
    list-style: none;
    display: flex;
    width: 100%;
}
.express-root .xp-stepper li {
    display: flex;
    align-items: center;
    flex: 1;
}
.express-root .xp-stepper li:last-child { flex: 0 0 auto; }
.express-root .xp-stepper li:not(:last-child)::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--xp-panel-line-2);
    margin: 0 14px;
}
.express-root .xp-sbtn {
    display: flex;
    align-items: center;
    gap: 10px;
    background: none;
    border: 0;
    padding: 4px 2px;
    color: var(--xp-panel-muted);
    cursor: default;
    font-family: var(--xp-font-body);
    font-weight: 600;
    font-size: 14px;
    white-space: nowrap;
    border-radius: 8px;
}
.express-root .xp-sbtn .xp-n {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1.5px solid var(--xp-panel-line-2);
    display: grid;
    place-items: center;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}
.express-root .xp-sbtn[aria-current="step"] { color: var(--xp-panel-ink); }
.express-root .xp-sbtn[aria-current="step"] .xp-n {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}
.express-root .xp-sbtn.is-done { color: var(--xp-panel-ink); }
.express-root .xp-sbtn.is-done .xp-n {
    background: var(--hl);
    border-color: var(--hl);
    color: var(--hl-ink);
}
/* Phase 4f: only completed steps are buttons (.is-link); the current and
   future steps are inert spans. */
.express-root .xp-sbtn.is-link { cursor: pointer; }
@media (hover: hover) {
    .express-root .xp-sbtn.is-link:hover .xp-sl {
        text-decoration: underline;
        text-underline-offset: 3px;
    }
}
.express-root .xp-sbtn.is-link:focus-visible {
    outline: 2px solid var(--xp-focus);
    outline-offset: 2px;
}

.express-root .xp-mstep {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 8px 12px;
    align-items: center;
}
.express-root .xp-back {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    min-height: 44px;
    background: none;
    border: 0;
    border-radius: 8px;
    color: var(--page-ink);
    padding: 0 8px 0 0;
    cursor: pointer;
    font-family: var(--xp-font-body);
    font-weight: 600;
    font-size: 15px;
}
.express-root .xp-back:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--xp-focus);
}
/* Phase 4d — Step 4 Back while money may be moving: disabled, with the
   "Payment in progress" note under the step header. */
.express-root .xp-back:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.express-root .xp-pay-lock {
    margin: 6px 0 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--page-ink-muted);
}
/* Phase 4d — "Change payment method" above the card form. Same build as
   the Back button (Phase 2i), on the panel ink so it reads on light and
   dark panels. */
.express-root .xp-change-method {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 44px;
    margin: -6px 0 4px;
    background: none;
    border: 0;
    border-radius: 8px;
    color: var(--xp-panel-ink);
    padding: 0 8px 0 0;
    cursor: pointer;
    font-family: var(--xp-font-body);
    font-weight: 600;
    font-size: 14px;
}
.express-root .xp-change-method:hover { text-decoration: underline; }
.express-root .xp-change-method:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--xp-focus);
}
.express-root .xp-change-method:disabled { opacity: 0.6; cursor: wait; }
.express-root .xp-change-method.is-xp-busy {
    opacity: 0.72;
    transform: scale(0.985);
    transition: opacity 0.08s ease, transform 0.08s ease;
}
.express-root .xp-mtxt {
    text-align: right;
    font-size: 13px;
    color: var(--xp-panel-muted);
}
.express-root .xp-mtxt strong {
    color: var(--xp-panel-ink);
    font-size: 14px;
    margin-left: 6px;
}
.express-root .xp-msegs {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
}
.express-root .xp-msegs i {
    height: 4px;
    border-radius: 2px;
    background: var(--xp-panel-line);
}
.express-root .xp-msegs i.is-on { background: var(--hl); }
/* Current segment: accent, covered by a 2px inset --xp-focus ring. On a
   4px bar the ring fills it, so it reads as the accent when that reaches
   3:1 and as the dark ink when it does not. No size change. */
.express-root .xp-msegs i.is-cur {
    background: var(--accent);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
}

/* ---- Main + rail grid ---- */
.express-root .xp-layout {
    max-width: 1120px;
    margin: 0 auto;
    padding: 10px 18px 28px;
}
.express-root .xp-main { min-width: 0; }
.express-root .xp-rail { display: none; }

/* The copied Atelier step bodies were built for Atelier's own 2-column
   .gv-main grid; inside the express main column they are single-column. */
.express-root .xp-step > section,
.express-root .xp-step > .gv-form-card { min-width: 0; }
.express-root .xp-step .gv-form-card {
    background: transparent;
    box-shadow: none;
    padding: 0;
    border-radius: 0;
}
.express-root .xp-step .gv-page-heading { margin-bottom: 18px; }

/* Desktop-only CTAs inside the step (the mobile bar carries them below
   820px). */
.express-root .xp-desk-cta { display: none; }

.express-root .xp-step2-continue { margin-top: 18px; }

.express-root .xp-trust-strip {
    position: static;
    margin-top: 18px;
    transform: none;
}

/* ---- Child seat disclosure (Step 1) ---- */
.express-root .xp-disclosure {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 0 14px;
    padding: 14px 16px;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line-2);
    border-radius: var(--radius-sm);
    color: var(--xp-panel-ink);
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    text-align: left;
}
.express-root .xp-disclosure > span:first-child { flex: 1; }
.express-root .xp-disclosure-count {
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--xp-amber);
    color: var(--xp-amber-ink);
    font-size: 12px;
    font-weight: 700;
    display: inline-grid;
    place-items: center;
}
.express-root .xp-disclosure-chev { transition: transform 0.15s ease; color: var(--xp-panel-ink-2); }
.express-root .xp-disclosure.is-open .xp-disclosure-chev { transform: rotate(180deg); }
.express-root .xp-disclosure:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Seat count on the "Add child seats" pill (Step 1). */
.express-root .xp-pill-count {
    flex: none;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--xp-amber);
    color: var(--xp-amber-ink);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    display: inline-grid;
    place-items: center;
}

/* ---- Step 4: Atelier receipt-sidebar widgets in the main column ---- */
.express-root .xp-step-4 .gv-gratuity-row {
    padding: 0;
    border-top: 0;
}
.express-root .xp-step-4 .gv-promo-row {
    padding: 0 0 12px;
    border: 0;
    background: none;
}
.express-root .xp-step-4 .gv-fare-breakdown { padding: 0; }
.express-root .xp-step-4 .gv-receipt-total {
    background: none;
    padding: 14px 0 0;
}
.express-root .xp-step-4 .gv-receipt-total-value { font-size: calc(36px * var(--xp-price-scale)); }
.express-root .xp-step-4 .gv-pay-cta { margin-top: 18px; }

/* ---- Trip pass ---- */
.express-root .xp-pass {
    position: relative;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 18px;
    box-shadow: var(--shadow-lg);
}
.express-root .xp-pass-top {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 18px;
    background: var(--hl);
    color: var(--hl-ink);
    border-radius: 17px 17px 0 0;
    font-size: 13px;
    font-weight: 700;
}
.express-root .xp-pass-type { font-weight: 600; }
.express-root .xp-pass-body { padding: 16px 18px 18px; }
.express-root .xp-ps-h {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    min-height: 22px;
}
.express-root .xp-ps-k {
    font-size: 12.5px;
    color: var(--xp-panel-muted);
    font-weight: 600;
}
.express-root .xp-edit {
    background: none;
    border: 0;
    padding: 2px 0;
    color: var(--xp-panel-ink);
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    cursor: pointer;
}
.express-root .xp-pass-route {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(22px, 1fr) minmax(0, auto);
    align-items: center;
    gap: 10px;
    margin: 4px 0 12px;
}
.express-root .xp-code {
    font-family: var(--xp-font-display);
    font-size: calc(28px * var(--xp-display-scale));
    line-height: 1.05;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.express-root .xp-code.is-dim { color: var(--xp-panel-muted); }
.express-root .xp-pass-line {
    position: relative;
    border-top: 2px dotted var(--xp-panel-line-2);
}
.express-root .xp-pass-line::after {
    content: "";
    position: absolute;
    left: 50%;
    top: -5px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--xp-amber);
    transform: translateX(-50%);
}
.express-root .xp-pass-empty {
    margin-top: 6px;
    color: var(--xp-panel-muted);
    font-size: 14px;
}
.express-root .xp-pass-dl {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 5px 14px;
    font-size: 13.5px;
}
.express-root .xp-pass-dl dt { color: var(--xp-panel-muted); }
.express-root .xp-pass-dl dd { overflow-wrap: anywhere; }
.express-root .xp-perf {
    position: relative;
    border-top: 2px dashed var(--xp-panel-line);
    margin: 0 14px;
}
.express-root .xp-pass-veh {
    display: grid;
    grid-template-columns: 76px minmax(0, 1fr);
    gap: 12px;
    align-items: center;
    margin-top: 4px;
}
.express-root .xp-pv-art {
    display: block;
    height: 48px;
    color: var(--xp-tile-ink);
    background: var(--xp-tile-2);
    border-radius: 10px;
    overflow: hidden;
}
.express-root .xp-pv-art img,
.express-root .xp-pv-art svg {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.express-root .xp-pv-name { display: block; font-weight: 700; }
.express-root .xp-pv-eg { display: block; font-size: 12.5px; color: var(--xp-panel-muted); }
.express-root .xp-pass-muted {
    margin-top: 4px;
    color: var(--xp-panel-muted);
    font-size: 13.5px;
}
.express-root .xp-pass-sec {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--xp-panel-line);
}
.express-root .xp-ps-v { margin-top: 2px; font-weight: 600; }
.express-root .xp-ps-x { margin-top: 2px; font-size: 13px; color: var(--xp-panel-ink-2); overflow-wrap: anywhere; }
.express-root .xp-pass-total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--xp-panel-line);
}
.express-root .xp-pass-total > span:first-child { font-weight: 600; font-size: 14px; }
.express-root .xp-pt-amt {
    font-family: var(--xp-font-price);
    font-size: calc(34px * var(--xp-price-scale));
    line-height: 1;
    font-variant-numeric: lining-nums tabular-nums;
}

/* ---- Phase 4g / 4i: fare breakdown in the Step 3 summary ----
   Shared by the trip pass and the Atelier trip receipt. Panel tokens only,
   so it follows both styles and light / dark panels. Phase 4i: it sits ABOVE
   the "Trip price" line and is always open (rail and mobile sheet): Base
   price first and slightly emphasised, then each itemized line, then the
   Trip price line (with its own divider) as the last line. */
.express-root .xp-tfare {
    margin-top: 14px;
    padding-top: 10px;
    border-top: 1px solid var(--xp-panel-line);
}
.express-root .xp-tfare-row {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 3px 0;
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    font-variant-numeric: tabular-nums;
}
.express-root .xp-tfare-row > span:first-child { min-width: 0; overflow-wrap: anywhere; }
.express-root .xp-tfare-row > span:last-child { white-space: nowrap; color: var(--xp-panel-ink); }
.express-root .xp-tfare-row.is-base {
    color: var(--xp-panel-ink);
    font-weight: 600;
}
.express-root .xp-tfare-row.is-discount,
.express-root .xp-tfare-row.is-discount > span:last-child { color: var(--xp-success); }
.express-root[data-style="atelier"] .xp-rcpt-fare {
    padding: 14px 22px 12px;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
}
.express-root[data-style="atelier"] .xp-rcpt-fare .xp-tfare {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

/* ---- Mobile total bar ---- */
.express-root .xp-mbar {
    position: sticky;
    bottom: 0;
    z-index: 10;
    background: var(--xp-bar-bg);
    border-top: 1px solid var(--xp-bar-line);
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
}
.express-root .xp-msheet {
    max-height: min(62vh, 560px);
    overflow: auto;
    margin: -10px -14px 10px;
    padding: 14px 16px 6px;
    background: var(--xp-panel-2);
    border-bottom: 1px solid var(--xp-panel-line);
}
.express-root .xp-mbar-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 12px;
    align-items: center;
}
.express-root .xp-mtotal {
    background: none;
    border: 0;
    padding: 2px 0;
    text-align: left;
    color: var(--xp-panel-ink);
    cursor: pointer;
    display: grid;
    min-width: 0;
    border-radius: 8px;
    font-family: var(--xp-font-body);
}
.express-root .xp-mtotal .xp-lbl {
    font-size: 12px;
    font-weight: 500;
    color: var(--xp-panel-muted);
}
.express-root .xp-mtotal .xp-amt {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: var(--xp-font-price);
    font-size: calc(27px * var(--xp-price-scale));
    line-height: 1.05;
    font-variant-numeric: lining-nums tabular-nums;
}
.express-root .xp-mtotal .xp-chev {
    transition: transform 0.15s;
    color: var(--xp-panel-ink-2);
}
.express-root .xp-mbar.is-open .xp-mtotal .xp-chev { transform: rotate(180deg); }
.express-root .xp-mbar .xp-mcta {
    width: auto;
    min-height: 50px;
    margin: 0;
    padding: 12px 18px;
    font-size: 15px;
    gap: 10px;
}
.express-root .xp-mbar .xp-mcta .gv-cta-arrow { display: none; }
/* Phase 4j: Step 1 bar holds the button only (no trip summary): full width. */
.express-root .xp-mbar-row.is-cta-only { grid-template-columns: minmax(0, 1fr); }
.express-root .xp-mbar-row.is-cta-only .xp-mcta { width: 100%; justify-content: center; }

[x-cloak] { display: none !important; }

/* ---- Wide layout (>= 820px): stepper + sticky rail, no mobile bar ---- */
@media (min-width: 820px) {
    .express-root .xp-head { padding: 28px 40px 6px; }
    .express-root .xp-stepper { display: flex; }
    .express-root .xp-mstep { display: none; }
    .express-root .xp-layout {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 340px;
        gap: 48px;
        align-items: start;
        padding: 22px 40px 44px;
    }
    .express-root .xp-rail {
        display: block;
        position: sticky;
        top: 20px;
    }
    .express-root .xp-mbar { display: none; }
    .express-root .xp-desk-cta { display: flex; }
}

@media (max-width: 819px) {
    .express-root .gv-headline { font-size: calc(32px * var(--xp-display-scale)); }
}

@media (prefers-reduced-motion: reduce) {
    .express-root .xp-disclosure-chev,
    .express-root .xp-mtotal .xp-chev { transition: none; }
}


/* ==========================================================================
   Moved from inline \3c style> blocks in the express step Blades (speed phase 2).
   They used to be re-sent in every Livewire response. Appended last so they
   keep the same cascade position they had (after the rest of this file).
   ========================================================================== */

/* --- Step 1 trip controls (moved from express-4-step/step-1.blade.php) --- */
/* === Trip controls — Date / Time / Passengers / Luggage ===
   One unified component family. No modifier classes fighting
   for control of borders/padding/sizing. Same visual contract
   as the rest of Atelier: cream surface, hairline line border,
   accent focus state. */

.express-root .gv-trip-controls {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px;
    margin-bottom: 24px;
}

.express-root .gv-trip-control {
    position: relative;
    display: block;
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    padding: 10px 14px 10px 50px;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
    min-height: 64px;
}
.express-root .gv-trip-control:hover {
    background: var(--xp-panel-hover);
}
.express-root .gv-trip-control:focus-within {
    background: var(--xp-panel);
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
}

.express-root .gv-trip-control-icon {
    position: absolute;
    left: 18px;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    color: var(--xp-panel-muted);
    pointer-events: none;
}
.express-root .gv-trip-control:focus-within .gv-trip-control-icon {
    color: var(--accent);
}

.express-root .gv-trip-control-label {
    display: block;
    font-size: 11px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 4px;
}

/* Date trigger reuses the time-trigger button class structure
   for visual parity. .gv-trip-control--date is a marker class
   only; it inherits all styling from .gv-trip-control and the
   trigger button styling rules below. */

/* Select (passenger / luggage) — borderless, transparent, with
   inline chevron SVG. Single rule, no per-modifier overrides. */
.express-root .gv-trip-control-select {
    width: 100%;
    background: transparent;
    border: none;
    outline: none;
    font-family: var(--xp-font-body);
    font-size: 15px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    padding: 0;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 22px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2358514a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
    background-size: 12px 12px;
}

/* === Popover-trigger controls (time / date / count) ===
   All use the same .gv-trip-control-time-trigger button to
   carry their padding, so the wrapper itself contributes zero
   padding. This was originally introduced for the time control
   and is now shared by date, passenger count, and luggage count. */
.express-root .gv-trip-control--time,
.express-root .gv-trip-control--date,
.express-root .gv-trip-control--count {
    cursor: pointer;
    padding: 0;
}
.express-root .gv-trip-control--time:focus-within,
.express-root .gv-trip-control--date:focus-within,
.express-root .gv-trip-control--count:focus-within {
    /* focus styles handled by the trigger button itself */
}
.express-root .gv-trip-control-time-trigger {
    width: 100%;
    background: transparent;
    border: none;
    outline: none;
    padding: 10px 14px 10px 50px;
    min-height: 64px;
    font-family: var(--xp-font-body);
    cursor: pointer;
    text-align: left;
    position: relative;
    display: block;
}
.express-root .gv-trip-control-time-trigger:focus-visible {
    outline: none;
}
.express-root .gv-trip-control-time-display {
    display: flex;
    align-items: baseline;
    gap: 8px;
}
.express-root .gv-trip-control-time-value {
    font-size: 15px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    font-variant-numeric: tabular-nums;
}
.express-root .gv-trip-control-time-period {
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink-2);
    letter-spacing: 0.04em;
}
.express-root .gv-trip-control-time-chevron {
    width: 10px;
    height: 10px;
    color: var(--xp-panel-muted);
    margin-left: auto;
    align-self: center;
}

/* Popover container — absolute, anchored below the time trigger */
.express-root .gv-time-popover {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 30;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    box-shadow: 0 12px 32px rgba(26, 26, 26, 0.12), 0 2px 8px rgba(26, 26, 26, 0.06);
    padding: 18px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
}

/* Smart placement (2026-05-27 — iframe clipping fix).
   Default downward anchor stays on .gv-time-popover above.
   --below is a no-op marker for symmetry; --above flips the
   anchor so the popover renders upward from the trigger's
   top edge. 6px matches the existing default gap. */
.express-root .gv-time-popover.gv-time-popover--below {
    /* No override — inherits default downward positioning */
}
.express-root .gv-time-popover.gv-time-popover--above {
    top: auto;
    bottom: calc(100% + 6px);
}
[x-cloak] { display: none !important; }

.express-root .gv-time-popover-section {
    min-width: 0;
}
.express-root .gv-time-popover-section-label {
    font-size: 10px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: 8px;
}

.express-root .gv-time-popover-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
}
.express-root .gv-time-cell {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    padding: 8px 0;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: center;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.express-root .gv-time-cell:hover {
    background: var(--xp-panel-2);
    border-color: var(--xp-panel-line);
}
.express-root .gv-time-cell.is-active,
.express-root .gv-time-cell.is-active:hover {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}

/* Period (AM/PM) section spans both columns under the grids */
.express-root .gv-time-popover-section--period {
    grid-column: 1 / -1;
    border-top: 1px solid var(--xp-panel-line);
    padding-top: 14px;
    margin-top: 2px;
}
.express-root .gv-time-popover-period {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}
.express-root .gv-time-period-btn {
    appearance: none;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 999px;
    padding: 9px 0;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink-2);
    cursor: pointer;
    text-align: center;
    line-height: 1;
    letter-spacing: 0.04em;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.express-root .gv-time-period-btn:hover {
    border-color: var(--xp-panel-ink);
    color: var(--xp-panel-ink);
}
.express-root .gv-time-period-btn.is-active,
.express-root .gv-time-period-btn.is-active:hover {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}

.express-root .gv-time-popover-done {
    grid-column: 1 / -1;
    appearance: none;
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    border: none;
    border-radius: var(--radius);
    padding: 10px 0;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.04em;
    cursor: pointer;
    margin-top: 4px;
    transition: background 0.12s ease;
}
.express-root .gv-time-popover-done:hover {
    background: var(--accent);
    color: var(--accent-ink);
}

/* Count popover CSS retired 2026-05-24 — superseded by
   .gv-select-popover and .gv-select-popover-row in atelier.css.
   Both passenger and luggage controls now use the universal
   select-popover component. */

/* === Date popover ===
   Mirrors .gv-time-popover's visual contract (surface, line
   border, shadow, padding) but with a month-grid layout. Selected
   and today states use the same is-active terracotta fill as the
   time cells. Disabled (past) cells are visually quiet and
   non-interactive. */
.express-root .gv-date-popover {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 30;
    width: 320px;
    max-width: calc(100vw - 32px);
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: var(--radius);
    box-shadow: 0 12px 32px rgba(26, 26, 26, 0.12), 0 2px 8px rgba(26, 26, 26, 0.06);
    padding: 16px;
}

/* Smart placement (2026-05-27 — iframe clipping fix).
   Default downward anchor stays on .gv-date-popover above.
   --below is a no-op marker for symmetry; --above flips the
   anchor so the popover renders upward from the trigger's
   top edge. 6px matches the existing default gap. */
.express-root .gv-date-popover.gv-date-popover--below {
    /* No override — inherits default downward positioning */
}
.express-root .gv-date-popover.gv-date-popover--above {
    top: auto;
    bottom: calc(100% + 6px);
}

.express-root .gv-date-popover-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.express-root .gv-date-popover-nav-title {
    font-family: var(--xp-font-body);
    font-size: 16px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    letter-spacing: -0.01em;
}
.express-root .gv-date-popover-nav-btn {
    appearance: none;
    background: transparent;
    border: 1px solid var(--xp-panel-line);
    border-radius: 8px;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--xp-panel-ink-2);
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.express-root .gv-date-popover-nav-btn svg {
    width: 14px;
    height: 14px;
}
.express-root .gv-date-popover-nav-btn:hover:not(:disabled) {
    background: var(--xp-panel-2);
    color: var(--xp-panel-ink);
    border-color: var(--xp-panel-ink);
}
.express-root .gv-date-popover-nav-btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.express-root .gv-date-popover-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    margin-bottom: 6px;
}
.express-root .gv-date-popover-weekdays > div {
    font-size: 10px;
    font-weight: 500;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    padding: 4px 0;
}

.express-root .gv-date-popover-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    margin-bottom: 12px;
}

.express-root .gv-date-cell {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    justify-self: stretch;
    width: 100%;
    aspect-ratio: 1 / 1;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    cursor: pointer;
    text-align: center;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
    display: grid;
    place-items: center;
}
.express-root .gv-date-cell:hover:not(:disabled):not(.is-active) {
    background: var(--xp-panel-2);
    border-color: var(--xp-panel-line);
}
.express-root .gv-date-cell.is-empty {
    background: transparent;
    border-color: transparent;
    cursor: default;
    pointer-events: none;
}
.express-root .gv-date-cell.is-past {
    color: var(--xp-panel-muted);
    opacity: 0.4;
    cursor: not-allowed;
}
.express-root .gv-date-cell.is-today:not(.is-active) {
    border-color: var(--accent);
    color: var(--xp-link);
}
.express-root .gv-date-cell.is-active {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--xp-focus);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}

/* Date popover Done button — reuse .gv-time-popover-done styling */
.express-root .gv-date-popover .gv-time-popover-done {
    width: 100%;
    margin-top: 0;
}

/* Mobile — stack 1 column, slightly tighter padding */
@media (max-width: 768px) {
    .express-root .gv-trip-controls {
        grid-template-columns: minmax(0, 1fr);
        gap: 10px;
        margin-bottom: 18px;
    }
    .express-root .gv-trip-control {
        padding: 10px 14px 10px 44px;
        min-height: 58px;
    }
    .express-root .gv-trip-control-icon {
        left: 14px;
    }
    .express-root .gv-date-popover {
        width: calc(100vw - 60px);
        max-width: 320px;
    }
}

/* --- Step 2 edit-trip button (moved from express-4-step/step-2.blade.php) --- */
/* STEP2-EDIT-BTN-2026-05-24 */
/* Edit-trip button — black default → terracotta hover.
   Matches the platform's primary-action color rule
   established for Step 3 pay CTA and Step 2 advance CTA. */
.gv-edit-trip-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    border: 1.5px solid var(--xp-panel-ink);
    border-radius: 999px;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
    white-space: nowrap;
    flex-shrink: 0;
}
.gv-edit-trip-btn svg {
    width: 15px;
    height: 15px;
    color: var(--xp-inverse-ink);
    transition: transform 0.15s ease;
}
.gv-edit-trip-btn:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}
.gv-edit-trip-btn:hover svg {
    color: var(--accent-ink);
    transform: rotate(-6deg);
}
.gv-edit-trip-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* --- Step 4 gratuity widget (moved from express-4-step/step-4.blade.php) --- */
/* ---- Driver-gratuity sidebar widget ----
   Matches the sidebar's canonical inset & typography rhythm.
   Scoped under .express-root so it loses to nothing on
   specificity within the Atelier theme. */
.express-root .gv-gratuity-row {
    padding: 16px 26px 18px;
    border-top: 1px solid var(--xp-panel-line);
}
.express-root .gv-gratuity-label {
    font-size: 11px;
    color: var(--xp-panel-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 10px;
    display: flex;
    align-items: baseline;
    gap: 6px;
}
.express-root .gv-gratuity-optional {
    font-size: 10px;
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--xp-panel-muted);
    opacity: 0.7;
    font-weight: 400;
}
.express-root .gv-gratuity-pills {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-bottom: 8px;
}
.express-root .gv-gratuity-pill {
    appearance: none;
    -webkit-appearance: none;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 999px;
    padding: 9px 0;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink-2);
    cursor: pointer;
    text-align: center;
    line-height: 1;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.express-root .gv-gratuity-pill:hover {
    border-color: var(--xp-panel-ink);
    color: var(--xp-panel-ink);
}
.express-root .gv-gratuity-pill:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.express-root .gv-gratuity-pill.is-active,
.express-root .gv-gratuity-pill.is-active:hover {
    background: var(--accent);
    border-color: var(--xp-focus);
    color: var(--accent-ink);
    box-shadow: inset 0 0 0 1px var(--xp-focus);
}
.express-root .gv-gratuity-custom {
    position: relative;
    display: flex;
    align-items: center;
}
.express-root .gv-gratuity-custom-prefix {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--xp-panel-muted);
    pointer-events: none;
    line-height: 1;
}
.express-root .gv-gratuity-custom-input {
    width: 100%;
    background: var(--xp-panel);
    border: 1px solid var(--xp-panel-line);
    border-radius: 10px;
    padding: 10px 14px 10px 26px;
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--xp-panel-ink);
    outline: none;
    transition: border-color 0.15s ease;
    -moz-appearance: textfield;
}
.express-root .gv-gratuity-custom-input:focus {
    border-color: var(--accent);
}
.express-root .gv-gratuity-custom-input::placeholder {
    color: var(--xp-panel-muted);
    opacity: 0.85;
}
.express-root .gv-gratuity-custom-input::-webkit-outer-spin-button,
.express-root .gv-gratuity-custom-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
@media (max-width: 860px) {
    .express-root .gv-gratuity-row {
        padding: 14px 18px 16px;
    }
}

/* ==========================================================================
   Phase 2b — Step 1 trip-type variants + rail map
   ========================================================================== */

/* Custom-field wrappers only carry x-show (per trip type); they add no box. */
.express-root .xp-cf-wrap { display: contents; }

/* Room for the hourly drop-off collapse button. Used to be an inline style
   on the input, which now sits inside a wire:ignore region that is never
   re-rendered, so the class lives on the wrapper outside it. */
.express-root .gv-dropoff-wrapper.xp-has-collapse .gv-field input { padding-right: 36px; }

/* Step 1 map at the top of the rail (the rail itself only shows >= 820px).
   Overrides the Atelier column-map sizing (640px, 320px at <= 980px). */
.express-root .xp-rail .xp-map { margin-bottom: 16px; }
.express-root .xp-rail .xp-map .gv-map-canvas {
    position: relative;
    top: 0;
    order: 0;
    height: 300px;
    min-height: 300px;
    border-radius: 18px;
    box-shadow: var(--shadow-lg);
}
/* min-height: 0 also beats the embedded-mode 480px map rule (same
   specificity, later in the file). */
.express-root .xp-rail .xp-map .gv-map-img { width: 100%; height: 100%; min-height: 0; }
.express-root .xp-rail .xp-map .gv-trip-card {
    top: 12px; left: 12px; right: 12px;
    padding: 10px 12px;
    gap: 10px;
}
.express-root .xp-rail .xp-map .gv-trip-address { font-size: 12px; }
.express-root .xp-rail .xp-map .gv-trip-stats { padding-left: 10px; }
.express-root .xp-rail .xp-map .gv-trip-stat-value { font-size: calc(16px * var(--xp-price-scale)); }
.express-root .xp-rail .xp-map .gv-map-badge {
    top: auto; bottom: 12px; right: 12px;
    transform: none;
    padding: 10px 14px;
    min-width: 0;
}
.express-root .xp-rail .xp-map .gv-map-badge-value { font-size: calc(22px * var(--xp-price-scale)); }

/* ============================================================
   Phase 2c — pressed / busy state for actions that wait for the server
   (xpPress in resources/js/express.js, [data-xp-press]). Added in the
   same frame as the tap; removed when the request has answered.
   ============================================================ */
.express-root .is-xp-busy {
    cursor: progress;
}
.express-root .gv-cta.is-xp-busy,
.express-root .gv-pay-cta.is-xp-busy,
.express-root .gv-btn-primary.is-xp-busy,
.express-root .gv-vehicle-select.is-xp-busy,
.express-root .gv-promo-btn.is-xp-busy,
.express-root .gv-edit-trip-btn.is-xp-busy,
.express-root .xp-sbtn.is-xp-busy,
.express-root .xp-back.is-xp-busy,
.express-root .xp-edit.is-xp-busy {
    opacity: 0.72;
    transform: scale(0.985);
    transition: opacity 0.08s ease, transform 0.08s ease;
}
.express-root .gv-vehicle-card.is-xp-busy {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent);
}
.express-root .gv-promo-input.is-xp-busy {
    opacity: 0.72;
}

/* ============================================================
   Phase 2d — visible inputs
   Every input-like control on Steps 1-4 reads from the --field-* tokens:
   white fill on the #F4F5F7 page, a border at >= 3:1 against both the
   fill and the page (WCAG 1.4.11), darker border on hover, and a focus
   ring (border + 2px ring) in --xp-focus: the tenant accent when it
   reaches 3:1 on the white fill, else the dark ink (Phase 2e; the shell
   computes it). Declared on .express-root rather than :root so the vars
   resolve after the tenant's inline override. --shadow-focus is
   redefined here too, so every older focus shadow in this file follows
   the same focus colour instead of resolving var(--accent) at :root.
   Borders stay 1px and no padding changes, so nothing moves.
     --field-border       #7A8596  3.73:1 on #FFFFFF, 3.42:1 on #F4F5F7
     --field-border-hover #465263  7.93:1 on #FFFFFF, 7.27:1 on #F4F5F7
     --field-label        #465263  7.93:1 on the field fill
     --field-placeholder  #5F6B7A  5.43:1 on the field fill
   ============================================================ */
.express-root {
    --field-bg: var(--xp-field-bg);
    --field-bg-hover: var(--xp-field-bg-hover);
    --field-border: var(--xp-field-border);
    --field-border-hover: var(--xp-field-border-hover);
    --field-label: var(--xp-panel-ink-2);
    --field-placeholder: var(--xp-field-placeholder);
    --xp-focus: var(--accent);
    --xp-link: var(--accent);
    --field-focus-ring: 0 0 0 2px var(--xp-focus);
    --shadow-focus: 0 0 0 4px rgba(15, 27, 45, 0.12), 0 0 0 1px var(--xp-focus);
}

/* Fill + border: address / stop / Step 3 text fields and textarea, custom
   fields, date / time / passenger / luggage / hours triggers, compact
   selects (child seats, custom-field option lists), native selects,
   stop wait-time select, promo input, custom tip. */
.express-root .gv-field,
.express-root .gv-trip-control,
.express-root .gv-select-compact-trigger,
.express-root .gv-field-select > select,
.express-root .gv-stop-wait-select,
.express-root .gv-promo-input,
.express-root .gv-gratuity-custom-input {
    background-color: var(--field-bg);
    border-color: var(--field-border);
}

/* The stop row is a card around a field + wait select; give its frame the
   stronger hairline so it reads as a group without competing with the
   inputs inside it. */
.express-root .gv-stop-row { border-color: var(--xp-panel-line-2); }

/* Hover */
.express-root .gv-field:hover,
.express-root .gv-trip-control:hover,
.express-root .gv-select-compact-trigger:hover,
.express-root .gv-field-select > select:hover,
.express-root .gv-stop-wait-select:hover,
.express-root .gv-promo-input:hover,
.express-root .gv-gratuity-custom-input:hover {
    background-color: var(--field-bg-hover);
    border-color: var(--field-border-hover);
}

/* Focus: --xp-focus border + 2px ring (box-shadow, no layout shift). */
.express-root .gv-field:focus-within,
.express-root .gv-trip-control:focus-within,
.express-root .gv-select-compact-trigger:focus-visible,
.express-root .gv-select-compact-trigger[aria-expanded="true"],
.express-root .gv-field-select > select:focus,
.express-root .gv-stop-wait-select:focus,
.express-root .gv-promo-input:focus,
.express-root .gv-gratuity-custom-input:focus {
    background-color: var(--field-bg);
    border-color: var(--xp-focus);
    box-shadow: var(--field-focus-ring);
    outline: none;
}

/* Labels */
.express-root .gv-field-label,
.express-root .gv-trip-control-label,
.express-root .gv-select-compact-label,
.express-root .gv-field-select > .gv-field-label,
.express-root .gv-stop-wait-label {
    color: var(--field-label);
}

/* Placeholders */
.express-root .gv-field input::placeholder,
.express-root .gv-field textarea::placeholder,
.express-root .gv-promo-input::placeholder,
.express-root .gv-gratuity-custom-input::placeholder {
    color: var(--field-placeholder);
    opacity: 1;
}

/* ============================================================
   Phase 2e — tenant background + readable canvas text
   The tenant background (--xp-canvas, set inline on .express-root by
   themeColorStyle()) paints the express root; the shell paints <body>
   with the same value, so there is no strip of the old colour standalone
   or in the embed iframe. Cards, fields, vehicle cards, the trip pass,
   the map and the mobile bar keep their own fills.
   Everything that sits directly on the canvas reads --page-ink (dark ink
   or white, whichever contrasts more with the canvas) or
   --page-ink-muted (>= 4.5:1 on the canvas); lines on the canvas read
   --page-line / --page-line-soft. All are computed by the shell; the
   :root values reproduce the previous colours when no tenant background
   is set (muted text that was #6B7686 is now #465263, 4.2:1 -> 7.3:1).
   ============================================================ */
.express-root { background: var(--xp-canvas); }

/* Page headings (all steps, incl. the "online booking unavailable" state) */
.express-root .gv-headline,
.express-root .gv-headline em { color: var(--page-ink); }
.express-root .gv-eyebrow,
.express-root .gv-subheadline { color: var(--page-ink-muted); }

/* Desktop stepper: labels, number rings, connector lines */
.express-root .xp-sbtn { color: var(--page-ink-muted); }
.express-root .xp-sbtn[aria-current="step"],
.express-root .xp-sbtn.is-done { color: var(--page-ink); }
.express-root .xp-sbtn .xp-n { border-color: var(--page-line); }
.express-root .xp-stepper li:not(:last-child)::after { background: var(--page-line); }

/* Mobile step header: Back, "Step n of 4", segments */
.express-root .xp-back { color: var(--page-ink); }
.express-root .xp-mtxt { color: var(--page-ink-muted); }
.express-root .xp-mtxt strong { color: var(--page-ink); }
.express-root .xp-msegs i { background: var(--xp-seg-idle); }

/* Section labels and fine print outside cards */
.express-root .gv-options-label,
.express-root .gv-section-label,
.express-root .gv-cta-secondary-text { color: var(--page-ink-muted); }
.express-root .gv-cta-secondary-text span { color: var(--page-ink); }

/* Step 1 route thread: the dotted line runs through the canvas between
   the pickup / drop-off fields. */
.express-root .gv-route-thread::before {
    background: repeating-linear-gradient(to bottom, var(--page-ink-muted) 0 3px, transparent 3px 6px);
}

/* Step 3 add-ons box: was an unfilled outline with ink text straight on
   the canvas; give it the card fill so its text stays readable on any
   background. */
.express-root .gv-addons { background: var(--xp-panel); }

/* Trip control icon follows the field focus colour. */
.express-root .gv-trip-control:focus-within .gv-trip-control-icon { color: var(--xp-focus); }

/* ============================================================
   Phase 2f — selected states use the brand (accent) colour
   Fill states (trip-type tabs, return Yes/No, Add a stop, AM/PM, time /
   date cells, select-popover rows incl. child seats and custom fields,
   tip pills, the selected vehicle's Select button, the current step disc
   and mobile segment) paint var(--accent) with var(--accent-ink) text.
   Ring states (selected vehicle card, payment method card) use
   var(--accent). Every one also carries 2px of --xp-focus (border +
   inset ring, or an outer ring; never a size change), so a light accent
   under 3:1 on white still stands apart from the unselected items; on a
   dark accent --xp-focus is the accent and the ring matches the fill.
   The rules sit in place above; the payment card ring is here because
   its 1px accent border is set inline in step-4.
   ============================================================ */
.express-root .gv-vehicle-card.gv-vehicle-card--selected,
.express-root .gv-vehicle-card.gv-vehicle-card--selected:hover {
    box-shadow: 0 0 0 1px var(--accent), 0 0 0 3px var(--xp-focus), var(--shadow-md);
}

/* ============================================================
   Phase 2g — Step 2 vehicle cards (express-4-step/step-2.blade.php)
   Each vehicle is one <button class="xp-vcard"> (whole card = tap
   target; the Select pill is a span). Cards stay white with dark text
   on any tenant background. The pressed state is the existing
   data-xp-press mechanism (.is-xp-busy, resources/js/express.js); the
   selected card (the vehicle already on the form) carries
   aria-pressed="true". The previous .gv-vehicle-card.is-selected rules
   were step-2 only and are removed; .gv-vehicle-card stays for the
   Step 4 payment method cards.
   ============================================================ */
.express-root .xp-vlist-count {
    margin: 0 0 12px;
    font-size: 14px;
    font-weight: 600;
    color: var(--page-ink);
}
.express-root .xp-vcard {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 18px;
    background: var(--xp-panel);
    border: 1px solid var(--xp-vcard-line);
    border-radius: 16px;
    padding: 14px 18px 14px 14px;
    color: var(--xp-panel-ink);
    font-family: var(--xp-font-body);
    font-size: 14px;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.express-root .xp-vcard:disabled { cursor: not-allowed; opacity: 0.6; }
.express-root .xp-vc-img {
    flex: none;
    width: 148px;
    height: 98px;
    border-radius: 11px;
    background: var(--xp-tile);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--xp-tile-ink);
}
.express-root .xp-vc-img img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.express-root .xp-vc-img svg { display: block; width: 88%; height: 88%; }
.express-root .xp-vc-info {
    flex: 1 1 220px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}
.express-root .xp-vc-badge {
    display: inline-block;
    margin-bottom: 2px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
}
.express-root .xp-vc-badge.is-price { background: var(--xp-badge-best-bg); color: var(--xp-badge-best-ink); }
.express-root .xp-vc-badge.is-space { background: var(--xp-badge-space-bg); color: var(--xp-badge-space-ink); }
.express-root .xp-vc-name {
    display: block;
    max-width: 100%;
    font-family: var(--xp-font-display);
    font-weight: var(--xp-display-weight);
    font-size: calc(27px * var(--xp-display-scale));
    line-height: 1.1;
    color: var(--xp-panel-ink);
}
.express-root .xp-vc-desc {
    display: block;
    max-width: 100%;
    font-size: 14px;
    color: var(--xp-vcard-desc);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.express-root .xp-vc-cap {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 18px;
    margin-top: 4px;
    font-size: 14px;
    color: var(--xp-vcard-cap);
}
.express-root .xp-vc-capi {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.express-root .xp-vc-capi svg { width: 16px; height: 16px; flex: none; }
.express-root .xp-vc-side {
    flex: none;
    margin-left: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    text-align: right;
}
.express-root .xp-vc-price {
    display: flex;
    align-items: flex-start;
    font-family: var(--xp-font-price);
    font-weight: var(--xp-price-weight);
    line-height: 1;
    color: var(--xp-panel-ink);
    font-variant-numeric: lining-nums tabular-nums;
}
.express-root .xp-vc-cur,
.express-root .xp-vc-cts { font-size: calc(21px * var(--xp-price-scale)); line-height: 1; margin-top: 4px; }
.express-root .xp-vc-dol { font-size: calc(42px * var(--xp-price-scale)); line-height: 1; }
.express-root .xp-vc-cap-label { font-size: 12px; color: var(--xp-vcard-desc); }
.express-root .xp-vc-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 8px;
    min-height: 44px;
    padding: 0 18px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
}
.express-root .xp-vc-idle,
.express-root .xp-vc-busy { display: inline-flex; align-items: center; gap: 8px; }
.express-root .xp-vc-busy { display: none; }
.express-root .xp-vc-pill svg { width: 16px; height: 16px; flex: none; }
.express-root .xp-vc-spin {
    display: inline-block;
    flex: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid currentColor;
    border-right-color: transparent;
    animation: gvSpin 0.7s linear infinite;
}
.express-root .xp-vc-chev { display: none; }

/* Hover (not selected): never drops a selected card back to default.
   Phase 4c: every card :hover rule sits in a hover-capable, fine-pointer
   query, so a tap on a touch screen never leaves a card stuck hovered. */
@media (hover: hover) and (pointer: fine) {
    .express-root .xp-vcard:not([aria-pressed="true"]):not(:disabled):hover {
        border-color: var(--xp-vcard-line-hover);
        transform: translateY(-1px);
        box-shadow: 0 6px 18px rgba(15, 27, 45, 0.10);
    }
}
.express-root .xp-vcard:focus-visible {
    outline: 3px solid var(--xp-focus);
    outline-offset: 3px;
}
/* Pressed, waiting for Step 3. */
.express-root .xp-vcard.is-xp-busy { border-color: var(--xp-focus); }
.express-root .xp-vcard.is-xp-busy .xp-vc-idle { display: none; }
.express-root .xp-vcard.is-xp-busy .xp-vc-busy { display: inline-flex; }
/* Selected: the vehicle already on the form when the rider returns. */
.express-root .xp-vcard[aria-pressed="true"] {
    border-color: var(--xp-focus);
    box-shadow: 0 0 0 1px var(--xp-focus), 0 0 0 5px color-mix(in srgb, var(--xp-focus) 22%, transparent);
    transform: none;
}
@media (hover: hover) and (pointer: fine) {
    .express-root .xp-vcard[aria-pressed="true"]:hover {
        border-color: var(--xp-focus);
        box-shadow: 0 0 0 1px var(--xp-focus), 0 0 0 5px color-mix(in srgb, var(--xp-focus) 22%, transparent);
        transform: none;
    }
}
.express-root .xp-vcard[aria-pressed="true"] .xp-vc-pill {
    background: var(--xp-panel);
    color: var(--xp-panel-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
}
.express-root .xp-vcard[aria-pressed="true"] .xp-vc-idle svg,
.express-root .xp-vc-chev.is-on svg { color: var(--xp-focus); }

/* Mobile: compact row. Info and price column dissolve into one grid:
     image | name ............ price
     image | badge description
     image | capacity ........ chevron */
@media (max-width: 639px) {
    .express-root .xp-vcard {
        display: grid;
        grid-template-columns: 84px auto minmax(0, 1fr) auto;
        grid-template-areas:
            "img name  name price"
            "img badge desc desc"
            "img cap   cap  chev";
        column-gap: 0;
        row-gap: 4px;
        align-items: center;
        padding: 12px;
    }
    .express-root .xp-vc-info,
    .express-root .xp-vc-side { display: contents; }
    .express-root .xp-vc-img {
        grid-area: img;
        width: 84px;
        height: 72px;
        margin-right: 12px;
        border-radius: 9px;
    }
    .express-root .xp-vc-name {
        grid-area: name;
        min-width: 0;
        font-size: calc(21px * var(--xp-display-scale));
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .express-root .xp-vc-price { grid-area: price; justify-self: end; margin-left: 10px; }
    .express-root .xp-vc-dol { font-size: calc(27px * var(--xp-price-scale)); }
    .express-root .xp-vc-cur,
    .express-root .xp-vc-cts { font-size: calc(14px * var(--xp-price-scale)); margin-top: 3px; }
    .express-root .xp-vc-badge {
        grid-area: badge;
        justify-self: start;
        margin: 0 8px 0 0;
        font-size: 11px;
    }
    .express-root .xp-vc-desc { grid-area: desc; min-width: 0; font-size: 13px; }
    .express-root .xp-vc-cap { grid-area: cap; gap: 4px 14px; margin-top: 2px; font-size: 13px; }
    .express-root .xp-vc-capi svg { width: 14px; height: 14px; }
    .express-root .xp-vc-cap-label,
    .express-root .xp-vc-pill { display: none; }
    .express-root .xp-vcard:disabled .xp-vc-cap-label { display: block; grid-area: price; }
    .express-root .xp-vc-chev {
        grid-area: chev;
        justify-self: end;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 5px;
        width: 26px;
        height: 26px;
        margin-left: 10px;
        border-radius: 999px;
        background: var(--accent);
        color: var(--accent-ink);
        box-shadow: inset 0 0 0 2px var(--xp-focus);
    }
    .express-root .xp-vc-chev svg { width: 14px; height: 14px; flex: none; }
    .express-root .xp-vc-chev .xp-vc-spin { display: none; width: 12px; height: 12px; }
    .express-root .xp-vcard.is-xp-busy .xp-vc-chev-i { display: none; }
    .express-root .xp-vcard.is-xp-busy .xp-vc-chev .xp-vc-spin { display: inline-block; }
    .express-root .xp-vc-chev.is-on {
        width: auto;
        padding: 0 10px;
        background: var(--xp-panel);
        color: var(--xp-panel-ink);
        font-size: 13px;
        font-weight: 600;
        white-space: nowrap;
    }
}

@media (prefers-reduced-motion: reduce) {
    .express-root .xp-vcard {
        transform: none;
        transition: none;
    }
    .express-root .xp-vc-spin { animation: none; }
}
@media (prefers-reduced-motion: reduce) and (hover: hover) and (pointer: fine) {
    .express-root .xp-vcard:not([aria-pressed="true"]):not(:disabled):hover {
        transform: none;
        transition: none;
    }
}

/* ============================================================
   Phase 2h — text on white surfaces over any tenant background
   Text placed directly on the canvas reads --page-ink /
   --page-ink-muted / --page-line (Phase 2e). Every element that paints
   its own fill (a panel, var(--xp-panel*)) sets color:
   var(--xp-panel-ink) on itself (Phase 3a; was var(--ink)), so its text
   never inherits page ink from the canvas; its muted text reads
   --xp-panel-muted / --xp-panel-ink-2, never --page-ink-muted.
   :where() keeps this at the specificity of one class, so every
   existing per-element colour (muted pills, labels, accent-ink fills,
   selected states) still wins; on a light canvas --page-ink is the same
   #0F1B2D as --ink, so nothing changes visually there.
   Inventory, by surface:
     shell      .gv-header, .xp-pass (trip pass), .xp-mbar, .xp-msheet,
                .gv-modal-card (payment modal)
     step 1     .gv-field, .gv-trip-control, .gv-select-compact-trigger,
                .gv-field-select, .gv-service-types, .gv-return,
                .gv-toggle-group, .gv-stop-row, .gv-childseat-picker,
                .gv-pill, .xp-disclosure, .gv-trip-card, .gv-map-badge
                (the step-1 map card's overlays)
     popovers   .gv-select-popover, .gv-time-popover, .gv-date-popover
     step 2     .gv-trip-summary (pickup / drop-off box), .xp-vcard
     step 3     .gv-section-card (details panels), .gv-addons
     step 4     .gv-section-card (tip, fare, payment panels),
                .gv-vehicle-card (payment method cards), .gv-promo-input,
                .gv-promo-btn, .gv-gratuity-pill, .gv-gratuity-custom-input,
                .gv-payment-stage, .gv-error-panel, .gv-btn-secondary
                (Phase 5a: tip, payment options and promo moved to step 3;
                step 4 adds .xp-final, the review card)
     done       .gv-thank-you-card
   The Step 1 form panel (.xp-step .gv-form-card) is transparent, so it
   is canvas, not a surface.
   ============================================================ */
.express-root :where(
    .gv-header,
    .xp-pass,
    .xp-mbar,
    .xp-msheet,
    .gv-modal-card,
    .gv-field,
    .gv-trip-control,
    .gv-select-compact-trigger,
    .gv-field-select,
    .gv-service-types,
    .gv-return,
    .gv-toggle-group,
    .gv-stop-row,
    .gv-childseat-picker,
    .gv-pill,
    .xp-disclosure,
    .gv-trip-card,
    .gv-map-badge,
    .gv-select-popover,
    .gv-time-popover,
    .gv-date-popover,
    .gv-trip-summary,
    .xp-vcard,
    .gv-section-card,
    .gv-addons,
    .gv-vehicle-card,
    .gv-promo-input,
    .gv-promo-btn,
    .gv-gratuity-pill,
    .gv-gratuity-custom-input,
    .gv-payment-stage,
    .gv-error-panel,
    .gv-btn-secondary,
    .xp-final,
    .gv-thank-you-card
) {
    color: var(--xp-panel-ink);
}

/* Step 2 pickup / drop-off box: the trip pass rail (>= 820px, same
   breakpoint as .xp-rail) already shows the route with an Edit link, so
   the box only shows where the rail is hidden (mobile). */
@media (min-width: 820px) {
    .express-root .xp-hide-with-rail { display: none; }
}

/* Header band: the brand mark is a fixed square (36px desktop, 34px
   below 820px; no flex grow or shrink against a long brand name) and
   centres its letter on one line box; the band centres the mark with
   equal top and bottom padding. A tenant logo replaces the mark and keeps
   its aspect ratio inside a 140px x 36px (34px mobile) box (Phase 2i). */
.express-root .gv-header { align-items: center; }
.express-root .gv-brand { align-items: center; }
.express-root .gv-brand > .gv-brand-mark {
    flex: none;
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    line-height: 1;
    text-align: center;
}
.express-root .gv-brand > .gv-brand-logo {
    display: block;
    flex: none;
    width: auto;
    height: auto;
    max-width: 140px;
    max-height: 36px;
    object-fit: contain;
}
@media (max-width: 819px) {
    .express-root .gv-brand > .gv-brand-mark {
        width: 34px;
        height: 34px;
    }
    .express-root .gv-brand > .gv-brand-logo { max-height: 34px; }
}

/* ============================================================
   Phase 3a — dark panels: dark-only pieces
   Everything else follows the panel tokens at the top of this file.
   Native controls inside dark panels get the dark UA rendering
   (select option lists, date / time pickers, scrollbars). Set on the
   controls only, not the root, so third-party iframes (Stripe, hosted
   invoice) keep their own scheme and backdrop.
   ============================================================ */
.express-root[data-panels="dark"] :is(input, select, textarea) { color-scheme: dark; }
/* The light-yellow accent wash behind the trip summary Edit link would sit
   under light link text; use the neutral hover wash instead. */
.express-root[data-panels="dark"] .gv-edit-link:hover { background: var(--xp-hover-tint); }

/* ============================================================
   Phase 4a — Stripe "Pay $X" button (both styles)
   The card-entry stage's pay button (data-gv-stripe-pay-cta in
   express-4-step/step-4) is the step's primary action: accent fill,
   --accent-ink text and the 2px --xp-focus inset ring, like the other
   primary CTAs. The other .gv-btn-primary buttons (retry, open payment
   window, call us) keep the inverse fill.
   ============================================================ */
.express-root .gv-btn-primary[data-gv-stripe-pay-cta],
.express-root .gv-btn-primary[data-gv-stripe-pay-cta]:hover {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: inset 0 0 0 2px var(--xp-focus);
    justify-content: center;
}
.express-root .gv-btn-primary[data-gv-stripe-pay-cta]:focus-visible {
    outline: 2px solid var(--xp-focus);
    outline-offset: 2px;
}

/* ============================================================
   Phase 4a — Atelier style: selector styling
   Everything below is scoped to .express-root[data-style="atelier"] and
   restyles the existing express markup only (Round 2 changes markup).
   Tokens live in the Atelier token block at the top of this file. The
   extra attribute selector puts every rule here above the Express rule
   it replaces, whatever the order or media query.
   ============================================================ */

/* Headings: regular-weight display font; the accent italic em and the
   eyebrow use --xp-link (the accent when it reaches 4.5:1 on white). */
.express-root[data-style="atelier"] .gv-headline { font-weight: 400; }
.express-root[data-style="atelier"] .gv-headline em {
    font-style: italic;
    color: var(--xp-link);
}
.express-root[data-style="atelier"] .gv-eyebrow {
    color: var(--xp-link);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    gap: 8px;
}
.express-root[data-style="atelier"] .gv-eyebrow::before {
    content: "";
    flex: none;
    width: 24px;
    height: 1px;
    background: var(--accent);
}

/* Step 1: the white form card is back (Express makes it transparent).
   Text inside it is on a panel, so it reads the panel inks rather than
   the canvas inks. */
.express-root[data-style="atelier"] .xp-step .gv-form-card {
    background: var(--xp-panel);
    border-radius: 20px;
    padding: 36px 36px 32px;
    box-shadow: var(--shadow-md);
    color: var(--xp-panel-ink);
}
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-headline { color: var(--xp-panel-ink); }
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-subheadline,
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-options-label,
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-section-label,
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-cta-secondary-text { color: var(--xp-panel-ink-2); }
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-cta-secondary-text span { color: var(--xp-panel-ink); }
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-route-thread::before {
    background: repeating-linear-gradient(to bottom, var(--xp-panel-muted) 0 3px, transparent 3px 6px);
}
@media (max-width: 639px) {
    .express-root[data-style="atelier"] .xp-step .gv-form-card { padding: 24px 20px 22px; }
}

/* Desktop stepper: centred and compact. Uppercase labels, 26px discs with
   a display-font numeral, 60px hairline connectors. Current = ink disc,
   done = --hl disc with a check (and a --hl connector after it), future =
   white disc with a hairline border. */
.express-root[data-style="atelier"] .xp-stepper ol { justify-content: center; }
.express-root[data-style="atelier"] .xp-stepper li,
.express-root[data-style="atelier"] .xp-stepper li:last-child { flex: 0 0 auto; }
.express-root[data-style="atelier"] .xp-stepper li:not(:last-child)::after {
    flex: none;
    width: 60px;
    height: 1px;
    background: var(--xp-panel-line);
    margin: 0 18px;
}
.express-root[data-style="atelier"] .xp-stepper li:has(.xp-sbtn.is-done):not(:last-child)::after { background: var(--hl); }
.express-root[data-style="atelier"] .xp-sbtn {
    gap: 12px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.express-root[data-style="atelier"] .xp-sbtn .xp-n {
    width: 26px;
    height: 26px;
    border: 1px solid var(--xp-panel-line);
    background: var(--xp-panel);
    color: var(--xp-panel-ink);
    font-family: var(--xp-font-display);
    font-weight: 500;
    font-size: 13px;
    letter-spacing: 0;
    box-shadow: none;
}
.express-root[data-style="atelier"] .xp-sbtn[aria-current="step"] .xp-n {
    background: var(--xp-inverse-bg);
    border-color: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    box-shadow: none;
}
.express-root[data-style="atelier"] .xp-sbtn.is-done .xp-n {
    background: var(--hl);
    border-color: var(--hl);
    color: var(--hl-ink);
}

/* Mobile step row. */
.express-root[data-style="atelier"] .xp-mtxt,
.express-root[data-style="atelier"] .xp-mtxt strong {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.express-root[data-style="atelier"] .xp-msegs i { background: var(--xp-seg-idle); }
.express-root[data-style="atelier"] .xp-msegs i.is-on { background: var(--hl); }
.express-root[data-style="atelier"] .xp-msegs i.is-cur {
    background: var(--xp-inverse-bg);
    box-shadow: none;
}

/* Selected choice controls: ink fill, cream text, no inset ring. Date /
   time cells and select-popover rows keep the accent fill. */
.express-root[data-style="atelier"] .gv-service-type.is-active,
.express-root[data-style="atelier"] .gv-toggle.is-active,
.express-root[data-style="atelier"] .gv-pill.is-active,
.express-root[data-style="atelier"] .gv-time-period-btn.is-active,
.express-root[data-style="atelier"] .gv-time-period-btn.is-active:hover,
.express-root[data-style="atelier"] .gv-gratuity-pill.is-active,
.express-root[data-style="atelier"] .gv-gratuity-pill.is-active:hover {
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    border-color: var(--xp-inverse-bg);
    box-shadow: none;
}
.express-root[data-style="atelier"] .gv-service-type.is-active svg { color: var(--xp-inverse-ink); }

/* Section titles: display font 500 at 20px, with the numbered circle
   (Express pins them to 16px / 700). */
.express-root[data-style="atelier"] .gv-section-title {
    font-family: var(--xp-font-display);
    font-size: 20px;
    font-weight: 500;
    letter-spacing: -0.01em;
}
.express-root[data-style="atelier"] .gv-section-num {
    font-family: var(--xp-font-display);
    font-weight: 500;
}

/* Primary CTAs (See prices, Continue, Continue to payment, Pay): accent
   fill, label left and arrow right; hover = green fill, 1px lift, green
   shadow and the arrow nudges 4px. The mobile bar keeps its own size. */
.express-root[data-style="atelier"] .gv-cta,
.express-root[data-style="atelier"] .gv-pay-cta {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: none;
    border-radius: 14px;
    justify-content: space-between;
    transition: background 0.2s ease, color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.express-root[data-style="atelier"] .gv-cta:not(.xp-mcta),
.express-root[data-style="atelier"] .gv-pay-cta:not(.xp-mcta) { padding: 18px 24px; }
.express-root[data-style="atelier"] .gv-cta:hover,
.express-root[data-style="atelier"] .gv-pay-cta:hover {
    background: var(--green);
    color: var(--xp-on-status);
    transform: translateY(-1px);
    box-shadow: 0 8px 24px rgba(74, 122, 77, 0.32);
}
.express-root[data-style="atelier"] .gv-cta-arrow { transition: transform 0.2s ease; }
.express-root[data-style="atelier"] .gv-cta:hover .gv-cta-arrow,
.express-root[data-style="atelier"] .gv-pay-cta:hover .gv-cta-arrow { transform: translateX(4px); }

/* Step 2 vehicle card (current markup): radius 20, no border, warm shadow,
   lift on hover; warm image bed; display-font name, price-font price;
   the Select pill becomes a rectangle: ink -> accent on card hover ->
   green "Selected". Badges take the glass tag look. */
.express-root[data-style="atelier"] .xp-vcard {
    border: 0;
    border-radius: 20px;
    box-shadow: var(--shadow-md);
    transition: box-shadow 0.25s ease, transform 0.25s ease;
}
@media (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-vcard:not([aria-pressed="true"]):not(:disabled):hover {
        transform: translateY(-2px);
        box-shadow: var(--shadow-card-hover);
    }
}
.express-root[data-style="atelier"] .xp-vcard[aria-pressed="true"] {
    box-shadow: 0 0 0 2px var(--green), var(--shadow-md);
    transform: none;
}
@media (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-vcard[aria-pressed="true"]:hover {
        box-shadow: 0 0 0 2px var(--green), var(--shadow-md);
        transform: none;
    }
}
.express-root[data-style="atelier"] .xp-vcard.is-xp-busy { box-shadow: 0 0 0 2px var(--xp-focus), var(--shadow-md); }
.express-root[data-style="atelier"] .xp-vc-img { background: linear-gradient(135deg, var(--xp-tile), #D8CFBE); }
.express-root[data-style="atelier"] .xp-vc-name {
    font-family: var(--xp-font-display);
    font-weight: 500;
}
.express-root[data-style="atelier"] .xp-vc-price {
    font-family: var(--xp-font-price);
    font-weight: 500;
}
.express-root[data-style="atelier"] .xp-vc-pill {
    border-radius: 14px;
    font-size: 14px;
    font-weight: 600;
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    box-shadow: none;
    transition: background 0.2s ease, color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-vcard:not([aria-pressed="true"]):not(:disabled):hover .xp-vc-pill {
        background: var(--accent);
        color: var(--accent-ink);
    }
}
.express-root[data-style="atelier"] .xp-vcard[aria-pressed="true"] .xp-vc-pill {
    background: var(--green);
    color: var(--xp-on-status);
    box-shadow: none;
}
.express-root[data-style="atelier"] .xp-vcard[aria-pressed="true"] .xp-vc-idle svg { color: var(--xp-on-status); }
.express-root[data-style="atelier"] .xp-vc-chev {
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    box-shadow: none;
}
.express-root[data-style="atelier"] .xp-vc-chev.is-on {
    background: var(--green);
    color: var(--xp-on-status);
}
.express-root[data-style="atelier"] .xp-vc-chev.is-on svg { color: var(--xp-on-status); }
.express-root[data-style="atelier"] .xp-vc-badge {
    background: var(--xp-tile-glass);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border-radius: 6px;
    padding: 5px 10px;
    box-shadow: var(--shadow-sm);
}
.express-root[data-style="atelier"] .xp-vc-badge.is-price { color: var(--xp-badge-best-ink); }
.express-root[data-style="atelier"] .xp-vc-badge.is-space { color: var(--xp-badge-space-ink); }

/* Trip pass: ink header band with cream text (instead of --hl), display-
   font place codes, accent route dot, hairline perforation. */
.express-root[data-style="atelier"] .xp-pass-top {
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
}
.express-root[data-style="atelier"] .xp-code {
    font-family: var(--xp-font-display);
    font-weight: 500;
}
.express-root[data-style="atelier"] .xp-pass-line::after { background: var(--accent); }
.express-root[data-style="atelier"] .xp-perf { border-top: 1px dashed var(--xp-panel-line-2); }

/* Focus: 2px --xp-focus outline, 2px offset. */
.express-root[data-style="atelier"] :is(button, a, [role="button"], .xp-vcard, .xp-sbtn, .gv-cta, .gv-pay-cta, .gv-gratuity-pill):focus-visible {
    outline: 2px solid var(--xp-focus);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .express-root[data-style="atelier"] .gv-cta,
    .express-root[data-style="atelier"] .gv-pay-cta,
    .express-root[data-style="atelier"] .gv-cta:hover,
    .express-root[data-style="atelier"] .gv-pay-cta:hover,
    .express-root[data-style="atelier"] .xp-vcard {
        transform: none;
        transition: none;
    }
    .express-root[data-style="atelier"] .gv-cta:hover .gv-cta-arrow,
    .express-root[data-style="atelier"] .gv-pay-cta:hover .gv-cta-arrow { transform: none; }
}
@media (prefers-reduced-motion: reduce) and (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-vcard:not([aria-pressed="true"]):not(:disabled):hover {
        transform: none;
        transition: none;
    }
}

/* ============================================================
   Phase 4b — Atelier style, round 2: markup branches.
   Everything below is scoped to .express-root[data-style="atelier"] and
   styles markup that only the Atelier style renders (the 3-part vehicle
   card, the Step 1 map column, the receipt-style trip summary), plus the
   canvas-checked accent for text on the canvas. Colours come from the
   Atelier token blocks (light and dark) near the top of this file.
   ============================================================ */

/* Accent text placed directly on the canvas (the Step 2-4 page headings)
   reads --xp-link-canvas (the shell checks it against the effective
   canvas); inside the Step 1 form card it stays --xp-link (checked
   against the panel). */
.express-root[data-style="atelier"] .gv-eyebrow,
.express-root[data-style="atelier"] .gv-headline em { color: var(--xp-link-canvas, var(--xp-link)); }
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-eyebrow,
.express-root[data-style="atelier"] .xp-step .gv-form-card .gv-headline em { color: var(--xp-link); }

/* ---- Step 2 vehicle card (.xp-vcard.xp-acard) ----
   One button, three parts: photo 220px | body | aside 200px. The round 1
   .xp-vcard rules still give it radius 20, shadow-md, the hover lift and
   the selected / busy rings; the rules here replace the Express layout
   (also its < 640px grid). */
.express-root[data-style="atelier"] .xp-acard {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr) 200px;
    grid-template-areas: none;
    gap: 0;
    align-items: stretch;
    padding: 0;
    overflow: hidden;
    background: var(--xp-panel);
    color: var(--xp-panel-ink);
}
.express-root[data-style="atelier"] .xp-ac-photo {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 165px; /* 220px x 4:3 */
    overflow: hidden;
    background: linear-gradient(135deg, var(--xp-tile), #D8CFBE);
    color: var(--xp-tile-ink);
}
.express-root[data-style="atelier"] .xp-ac-photo img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    padding: 12px;
    box-sizing: border-box;
    object-fit: contain;
    transition: transform 0.4s ease;
}
.express-root[data-style="atelier"] .xp-ac-photo svg {
    display: block;
    width: 82%;
    height: auto;
    max-height: 80%;
    transition: transform 0.4s ease;
}
@media (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-acard:not([aria-pressed="true"]):not(:disabled):hover .xp-ac-photo img,
    .express-root[data-style="atelier"] .xp-acard:not([aria-pressed="true"]):not(:disabled):hover .xp-ac-photo > svg { transform: scale(1.05); }
}
.express-root[data-style="atelier"] .xp-ac-tag {
    position: absolute;
    top: 12px;
    right: 12px;
    margin: 0;
    z-index: 1;
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
}
.express-root[data-style="atelier"] .xp-ac-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: 4px;
    padding: 22px 24px;
}
.express-root[data-style="atelier"] .xp-ac-class {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--xp-panel-muted);
}
.express-root[data-style="atelier"] .xp-ac-name {
    display: block;
    max-width: 100%;
    font-family: var(--xp-font-display);
    font-weight: 500;
    font-size: calc(24px * var(--xp-display-scale));
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--xp-panel-ink);
}
.express-root[data-style="atelier"] .xp-ac-desc {
    display: block;
    max-width: 100%;
    font-size: 12px;
    font-style: italic;
    color: var(--xp-panel-muted);
}
.express-root[data-style="atelier"] .xp-ac-specs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    margin-top: 8px;
    font-size: 13px;
    color: var(--xp-panel-ink-2);
}
.express-root[data-style="atelier"] .xp-ac-spec {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.express-root[data-style="atelier"] .xp-ac-spec svg { width: 15px; height: 15px; flex: none; color: var(--xp-panel-muted); }
.express-root[data-style="atelier"] .xp-ac-aside {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 22px 20px;
    background: var(--xp-panel-2);
    border-left: 1px solid var(--xp-panel-line);
    text-align: center;
}
.express-root[data-style="atelier"] .xp-ac-label {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--xp-panel-muted);
}
.express-root[data-style="atelier"] .xp-ac-price {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    font-family: var(--xp-font-price);
    font-weight: 500;
    font-size: calc(36px * var(--xp-price-scale));
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--xp-panel-ink);
    font-variant-numeric: lining-nums tabular-nums;
}
.express-root[data-style="atelier"] .xp-ac-cur,
.express-root[data-style="atelier"] .xp-ac-cts {
    font-size: 0.5em;
    line-height: 1;
    margin-top: 0.15em;
}
.express-root[data-style="atelier"] .xp-ac-cts { opacity: 0.55; }
.express-root[data-style="atelier"] .xp-ac-select {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 48px;
    padding: 0 16px;
    border-radius: 14px;
    background: var(--xp-inverse-bg);
    color: var(--xp-inverse-ink);
    font-family: var(--xp-font-body);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    transition: background 0.2s ease, color 0.2s ease;
}
.express-root[data-style="atelier"] .xp-ac-select svg { width: 16px; height: 16px; flex: none; }
@media (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-acard:not([aria-pressed="true"]):not(:disabled):hover .xp-ac-select {
        background: var(--accent);
        color: var(--accent-ink);
    }
}
.express-root[data-style="atelier"] .xp-acard[aria-pressed="true"] .xp-ac-select {
    background: var(--green);
    color: var(--xp-on-status);
}
.express-root[data-style="atelier"] .xp-acard[aria-pressed="true"] .xp-vc-idle svg { color: var(--xp-on-status); }

/* Phone: photo band on top (full width, 180px tall), body, then the aside
   with a top border. Phase 4c: a fixed height instead of 16:10 + max-height,
   which sized the band from the capped height (narrower than the card) and
   collapsed to 0 on iOS Safari, as the only content is the absolute <img>. */
@media (max-width: 639px) {
    .express-root[data-style="atelier"] .xp-acard { grid-template-columns: minmax(0, 1fr); }
    .express-root[data-style="atelier"] .xp-ac-photo {
        justify-self: stretch;
        width: 100%;
        aspect-ratio: auto;
        height: 180px;
        min-height: 0;
        max-height: none;
    }
    .express-root[data-style="atelier"] .xp-ac-body { padding: 18px 20px 16px; }
    .express-root[data-style="atelier"] .xp-ac-aside {
        border-left: 0;
        border-top: 1px solid var(--xp-panel-line);
        padding: 18px 20px 20px;
        gap: 14px;
    }
    .express-root[data-style="atelier"] .xp-ac-price {
        font-weight: 600;
        font-size: calc(32px * var(--xp-price-scale));
    }
}

/* ---- Step 1 map column (Atelier, .xp-layout-amap) ----
   The rail is not rendered on this step. Below 820px the column is hidden
   and express.js keeps booking-map.js from drawing into it (as with the
   rail map). 820-979px: the map sits under the form, 420px tall. From
   980px: form card | map column, 1fr / 1.1fr. */
.express-root[data-style="atelier"] .xp-amap-col { display: none; }
@media (min-width: 820px) {
    .express-root[data-style="atelier"] .xp-layout-amap { display: block; }
    .express-root[data-style="atelier"] .xp-amap-col { display: block; margin-top: 24px; }
    .express-root[data-style="atelier"] .xp-amap .gv-map-canvas {
        position: relative;
        top: 0;
        order: 0;
        display: block;
        height: 420px;
        min-height: 420px;
        border-radius: 20px;
        box-shadow: var(--shadow-lg);
        background: linear-gradient(135deg, var(--xp-map-art-1) 0%, var(--xp-map-art-2) 100%);
    }
    .express-root[data-style="atelier"] .xp-amap .gv-map-img { width: 100%; height: 100%; min-height: 0; }
    .express-root[data-style="atelier"] .xp-amap .gv-trip-card {
        display: flex;
        top: 20px;
        left: 20px;
        right: auto;
        max-width: min(440px, calc(100% - 40px));
    }
    .express-root[data-style="atelier"] .xp-amap .gv-map-badge { display: block; }
    .express-root[data-style="atelier"] .xp-amap-trust { display: none; }
}
@media (min-width: 980px) {
    .express-root[data-style="atelier"] .xp-layout-amap {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
        gap: 32px;
        align-items: stretch;
        max-width: 1280px;
    }
    .express-root[data-style="atelier"] .xp-amap-col { margin-top: 0; }
    .express-root[data-style="atelier"] .xp-amap,
    .express-root[data-style="atelier"] .xp-amap .gv-map-canvas { height: 100%; }
    .express-root[data-style="atelier"] .xp-amap .gv-map-canvas { min-height: 640px; }
    .express-root[data-style="atelier"] .xp-amap .gv-trip-card { top: 24px; left: 24px; }
    /* The trust strip moves from under the CTA into the map. */
    .express-root[data-style="atelier"] .xp-layout-amap .xp-step-1 .xp-trust-strip { display: none; }
    .express-root[data-style="atelier"] .xp-amap-trust {
        display: flex;
        position: absolute;
        top: auto;
        bottom: 24px;
        left: 24px;
        right: 24px;
        flex-direction: row;
        align-items: center;
        gap: 16px;
        padding: 14px 20px;
        border-radius: 14px;
        background: rgba(26, 26, 26, 0.88);
        -webkit-backdrop-filter: blur(20px) saturate(140%);
        backdrop-filter: blur(20px) saturate(140%);
        color: var(--xp-strip-ink);
    }
    .express-root[data-style="atelier"] .xp-amap-trust .gv-trust-divider { display: block; }
    .express-root[data-style="atelier"] .xp-amap-trust .gv-trust-item { flex: 1; font-size: 12px; }
    .express-root[data-style="atelier"] .xp-amap-trust .gv-trust-item svg { color: var(--gold); }
    /* The price badge sits above the strip. */
    .express-root[data-style="atelier"] .xp-amap .gv-map-badge { top: auto; bottom: 96px; transform: none; }
}

/* ---- Receipt-style trip summary (.xp-rcpt, Steps 2-4) ---- */
.express-root[data-style="atelier"] .xp-rcpt {
    background: var(--xp-panel);
    color: var(--xp-panel-ink);
    border-radius: 20px;
    box-shadow: var(--shadow-md);
    overflow: hidden;
}
.express-root[data-style="atelier"] .xp-rcpt-head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 18px 22px;
    background: var(--xp-rcpt-head-bg);
    color: var(--xp-rcpt-head-ink);
}
.express-root[data-style="atelier"] .xp-rcpt-eyebrow {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.6;
}
.express-root[data-style="atelier"] .xp-rcpt-title {
    font-family: var(--xp-font-display);
    font-weight: 500;
    font-size: 22px;
    line-height: 1.15;
    letter-spacing: -0.01em;
}
.express-root[data-style="atelier"] .xp-rcpt-veh {
    display: grid;
    grid-template-columns: 80px minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px;
    padding: 16px 22px;
    background: var(--xp-panel-2);
    border-bottom: 1px solid var(--xp-panel-line);
}
.express-root[data-style="atelier"] .xp-rcpt-thumb {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 80px;
    height: 56px;
    border-radius: 10px;
    overflow: hidden;
    background: linear-gradient(135deg, var(--xp-tile), #D8CFBE);
    color: var(--xp-tile-ink);
}
.express-root[data-style="atelier"] .xp-rcpt-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.express-root[data-style="atelier"] .xp-rcpt-thumb svg { display: block; width: 88%; height: 88%; }
.express-root[data-style="atelier"] .xp-rcpt-vtext { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.express-root[data-style="atelier"] .xp-rcpt-vname {
    font-family: var(--xp-font-display);
    font-weight: 500;
    font-size: 16px;
    line-height: 1.2;
}
.express-root[data-style="atelier"] .xp-rcpt-vmeta { font-size: 12px; color: var(--xp-panel-muted); }
.express-root[data-style="atelier"] .xp-rcpt-body { padding: 14px 22px 18px; }
.express-root[data-style="atelier"] .xp-rcpt-sec {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    min-height: 22px;
}
.express-root[data-style="atelier"] .xp-rcpt-rows + .xp-rcpt-sec {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--xp-panel-line);
}
.express-root[data-style="atelier"] .xp-rcpt-k,
.express-root[data-style="atelier"] .xp-rcpt-label {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--xp-panel-muted);
}
.express-root[data-style="atelier"] .xp-rcpt-rows {
    list-style: none;
    margin: 6px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.express-root[data-style="atelier"] .xp-rcpt-row {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr);
    gap: 12px;
    align-items: start;
}
.express-root[data-style="atelier"] .xp-rcpt-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: var(--xp-panel-2);
    border: 1px solid var(--xp-panel-line);
    color: var(--xp-panel-ink-2);
}
.express-root[data-style="atelier"] .xp-rcpt-ico svg { width: 14px; height: 14px; }
.express-root[data-style="atelier"] .xp-rcpt-rtext { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.express-root[data-style="atelier"] .xp-rcpt-value {
    font-size: 13px;
    font-weight: 500;
    color: var(--xp-panel-ink);
    overflow-wrap: anywhere;
}
.express-root[data-style="atelier"] .xp-rcpt-rider { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
.express-root[data-style="atelier"] .xp-rcpt-sub { font-size: 12px; color: var(--xp-panel-muted); overflow-wrap: anywhere; }
.express-root[data-style="atelier"] .xp-rcpt-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 16px 22px;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
}
.express-root[data-style="atelier"] .xp-rcpt-ttext { display: flex; flex-direction: column; gap: 2px; }
.express-root[data-style="atelier"] .xp-rcpt-tlabel { font-size: 13px; font-weight: 600; }
.express-root[data-style="atelier"] .xp-rcpt-amt {
    font-family: var(--xp-font-price);
    font-weight: 500;
    font-size: calc(28px * var(--xp-price-scale));
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: lining-nums tabular-nums;
}
/* In the mobile sheet the bar already frames it. */
.express-root[data-style="atelier"] .xp-msheet .xp-rcpt { box-shadow: none; border-radius: 0; }

@media (prefers-reduced-motion: reduce) {
    .express-root[data-style="atelier"] .xp-ac-photo img,
    .express-root[data-style="atelier"] .xp-ac-photo svg,
    .express-root[data-style="atelier"] .xp-ac-select { transition: none; }
}
@media (prefers-reduced-motion: reduce) and (hover: hover) and (pointer: fine) {
    .express-root[data-style="atelier"] .xp-acard:not([aria-pressed="true"]):not(:disabled):hover .xp-ac-photo img,
    .express-root[data-style="atelier"] .xp-acard:not([aria-pressed="true"]):not(:disabled):hover .xp-ac-photo > svg { transform: none; }
}

/* ============================================================
   Phase 4e — white band behind real vehicle photos
   Fleet photos are often white-background JPGs; on the tinted tile they
   showed as a white box. When a real photo is shown the Blade adds
   .has-photo to its container and the band is plain white. A fixed
   #FFFFFF, not a token, so it stays white with dark panels too. A 1px
   line (#E8E4DC, #3A362F on dark panels) keeps the band from running
   into the card body, on the side that touches it. Placeholder SVGs keep
   the tinted band.
   ============================================================ */

/* Express Step 2 card: photo left of the text at every width. */
.express-root .xp-vc-img.has-photo {
    box-sizing: border-box;
    background: #FFFFFF;
    border-right: 1px solid #E8E4DC;
}

/* Atelier Step 2 card: photo column left of the body; band on top < 640px. */
.express-root[data-style="atelier"] .xp-ac-photo.has-photo {
    box-sizing: border-box;
    background: #FFFFFF;
    border-right: 1px solid #E8E4DC;
}
.express-root[data-style="atelier"] .xp-ac-photo.has-photo .xp-ac-tag {
    box-shadow: 0 0 0 1px #E8E4DC, var(--shadow-sm);
}
@media (max-width: 639px) {
    .express-root[data-style="atelier"] .xp-ac-photo.has-photo {
        border-right: 0;
        border-bottom: 1px solid #E8E4DC;
    }
}

/* Trip receipt (Atelier) and trip pass (Express) thumbnails: inset tiles,
   so the line goes all round. */
.express-root .xp-pv-art.has-photo,
.express-root[data-style="atelier"] .xp-rcpt-thumb.has-photo {
    box-sizing: border-box;
    background: #FFFFFF;
    border: 1px solid #E8E4DC;
}

/* Dark panels: the band stays white; only the line darkens. */
.express-root[data-panels="dark"] .xp-vc-img.has-photo,
.express-root[data-panels="dark"] .xp-pv-art.has-photo,
.express-root[data-style="atelier"][data-panels="dark"] .xp-ac-photo.has-photo,
.express-root[data-style="atelier"][data-panels="dark"] .xp-rcpt-thumb.has-photo {
    border-color: #3A362F;
}

/* ============================================================
   Phase 4h — Step 2 renders no trip summary rail (the summary starts at
   Step 3), so the layout is one column there and the vehicle list is
   centred at a readable width instead of leaving the rail column empty.
   ============================================================ */
@media (min-width: 820px) {
    .express-root .xp-layout.xp-layout-norail { grid-template-columns: minmax(0, 1fr); }
    .express-root .xp-layout-norail > .xp-main {
        width: 100%;
        max-width: 880px;
        margin: 0 auto;
    }
}


/* ==========================================================================
   Phase 5a — Step 3 holds every price choice; Step 4 is a one-column review.
   ========================================================================== */

/* Step 3 payment options: title / label / subtitle on the left, the total
   with that option on the right. */
.express-root .xp-method-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 4px;
}
.express-root .xp-method-card { width: 100%; }
.express-root .xp-method-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    width: 100%;
}
.express-root .xp-method-text { flex: 1; min-width: 0; }
.express-root .xp-method-price {
    flex: none;
    font-family: var(--xp-font-display);
    font-weight: 600;
    font-size: calc(17px * var(--xp-price-scale));
    color: var(--xp-panel-ink);
    font-variant-numeric: tabular-nums;
}
/* The promo row and the tip row sat in Step 4's receipt column before; on
   Step 3 they live inside a section card, so they drop that column's band. */
.express-root .xp-pay-options .xp-promo-row {
    margin-top: 14px;
    padding: 0;
    border: 0;
    background: none;
}
.express-root .xp-pay-options .gv-promo-input { min-width: 0; }
.express-root .xp-tip-card .gv-gratuity-row {
    padding: 0;
    border-top: 0;
}

/* Step 4: a narrower centred column (the layout is already one column). */
.express-root .xp-step-4 > section {
    max-width: 640px;
    margin: 0 auto;
}

/* Step 4 summary card. */
.express-root .xp-final {
    background: var(--xp-panel);
    color: var(--xp-panel-ink);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    padding: 22px 24px 0;
    margin-bottom: 16px;
    overflow: hidden;
}
.express-root .xp-final-head {
    display: flex;
    align-items: center;
    gap: 14px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--xp-panel-line);
}
.express-root .xp-final-veh {
    flex: none;
    width: 76px;
    height: 44px;
    border-radius: 10px;
    background: var(--xp-panel-2);
    display: grid;
    place-items: center;
    overflow: hidden;
}
.express-root .xp-final-veh svg { width: 64px; height: auto; }
.express-root .xp-final-veh-name {
    font-family: var(--xp-font-display);
    font-weight: 600;
    font-size: 17px;
    color: var(--xp-panel-ink);
}
.express-root .xp-final-sub { font-size: 12px; color: var(--xp-panel-muted); margin-top: 2px; }

.express-root .xp-final-route {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 0 4px;
}
.express-root .xp-final-stop {
    position: relative;
    display: flex;
    gap: 12px;
    align-items: flex-start;
}
.express-root .xp-final-stop:not(:last-child)::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 14px;
    bottom: -14px;
    border-left: 2px dotted var(--xp-panel-line-2);
}
.express-root .xp-final-dot {
    flex: none;
    width: 10px;
    height: 10px;
    margin-top: 4px;
    border-radius: 50%;
    border: 2px solid var(--xp-panel-ink);
    background: var(--xp-panel);
}
.express-root .xp-final-stop.is-dropoff .xp-final-dot { background: var(--xp-panel-ink); }
.express-root .xp-final-stop.is-stop .xp-final-dot { width: 8px; height: 8px; margin-left: 1px; }
.express-root .xp-final-k {
    display: block;
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--xp-panel-muted);
}
.express-root .xp-final-v {
    display: block;
    font-size: 14px;
    color: var(--xp-panel-ink);
    overflow-wrap: anywhere;
}
.express-root .xp-final-when {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 0 2px;
    font-size: 14px;
    font-weight: 500;
    color: var(--xp-panel-ink);
}
.express-root .xp-final-when svg { color: var(--xp-panel-muted); flex: none; }

.express-root .xp-final-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 12px 0 4px;
    padding: 6px 0;
    background: none;
    border: none;
    font-family: var(--xp-font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--xp-link);
    cursor: pointer;
}
.express-root .xp-final-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.express-root .xp-final-chev { transition: transform 0.15s ease; }
.express-root .xp-final-chev.is-open { transform: rotate(180deg); }

.express-root .xp-final-more { padding: 6px 0 4px; }
.express-root .xp-final-rows { margin: 0; }
.express-root .xp-final-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 7px 0;
    border-bottom: 1px solid var(--xp-panel-line);
    font-size: 13px;
}
.express-root .xp-final-row dt { color: var(--xp-panel-muted); flex: none; }
.express-root .xp-final-row dd {
    margin: 0;
    color: var(--xp-panel-ink);
    text-align: right;
    overflow-wrap: anywhere;
}
.express-root .xp-final-fare { padding-top: 12px; }
.express-root .xp-final-fare-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 4px 0;
    font-size: 13px;
    color: var(--xp-panel-ink-2);
    font-variant-numeric: tabular-nums;
}
.express-root .xp-final-fare-row.is-base { color: var(--xp-panel-ink); font-weight: 600; }
.express-root .xp-final-fare-row.is-discount { color: var(--xp-promo-ok); }

.express-root .xp-final-total {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin: 12px -24px 0;
    padding: 16px 24px;
    background: var(--xp-panel-2);
    border-top: 1px solid var(--xp-panel-line);
}
.express-root .xp-final-total-label {
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--xp-panel-ink);
}
.express-root .xp-final-total-amt {
    font-family: var(--xp-font-display);
    font-weight: 600;
    font-size: calc(28px * var(--xp-price-scale));
    color: var(--xp-panel-ink);
    font-variant-numeric: tabular-nums;
}

/* Step 4 finish card: instructions + ONE button (offline), or the card form. */
/* Its title carries no section number, so the subtitle is not indented. */
.express-root .xp-finish .gv-section-sub { margin-left: 0; margin-bottom: 12px; }
.express-root .xp-finish-due { margin: 4px 0 16px; font-size: 14px; color: var(--xp-panel-ink); }
.express-root .xp-finish-cta { margin-bottom: 0; }
.express-root .xp-finish-note {
    margin: 10px 0 0;
    font-size: 12px;
    text-align: center;
    color: var(--xp-panel-muted);
    overflow-wrap: anywhere;
}

/* Back to Step 3: a text link, not a second button. */
.express-root .xp-final-back {
    display: block;
    margin: 6px auto 0;
    padding: 8px 4px;
    background: none;
    border: none;
    font-family: var(--xp-font-body);
    font-size: 13px;
    color: var(--page-ink-muted);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.express-root .xp-final-back:hover { color: var(--page-ink); }

@media (max-width: 819px) {
    .express-root .xp-final { padding: 18px 18px 0; }
    .express-root .xp-final-total { margin: 12px -18px 0; padding: 14px 18px; }
    .express-root .xp-method-row { padding: 12px 14px; gap: 12px; }
}
/* On phones the summary card lines up with the section cards below it
   (same side margins as .gv-section-card at these widths). */
@media (max-width: 768px) {
    .express-root .xp-final { margin: 0 14px 12px; }
    .express-root .xp-final { padding: 18px 16px 0; }
    .express-root .xp-final-total { margin: 12px -16px 0; padding: 14px 16px; }
}
@media (max-width: 420px) {
    .express-root .xp-final { margin-left: 12px; margin-right: 12px; padding-left: 14px; padding-right: 14px; }
    .express-root .xp-final-total { margin-left: -14px; margin-right: -14px; padding-left: 14px; padding-right: 14px; }
}

/* Oct 2026 — Step 3's button with an offline payment option (pay the driver /
   by phone) books the ride: "Confirm booking" instead of "Continue". Both
   labels (and the line under the button) are in the markup; the root's
   data-xp-pay (server value, switched by xpMethodCards on tap) shows one. */
.express-root[data-xp-pay="offline"] .xp-if-online,
.express-root:not([data-xp-pay="offline"]) .xp-if-offline { display: none; }
