/* Aircrate — design system
 *
 * Aesthetic: editorial cargo manifest in Apple's palette. Pricing math is
 * the product, so the interface treats numbers like a shipping declaration —
 * tabular figures, dotted leaders, hairline rules, monospace for refs.
 * Asymmetric editorial layouts; binary light-gray / pure-black sections;
 * single Apple Blue accent reserved for interactive elements + the route line.
 *
 * Type pairing: Bricolage Grotesque (display, optical-sized variable) + Geist
 * (body) + Geist Mono (numerals + refs). Loaded via Google Fonts.
 */

@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wdth,wght@12..96,75..100,300..800&family=Geist:wght@300..700&family=Geist+Mono:wght@300..600&display=swap');

/* Marketing-site baseline zoom. The design reads best at ~110% browser
 * zoom (the rendering scale the user prefers); baking that in here means
 * fresh visitors see the calibrated scale by default and can still
 * Ctrl/Cmd-Plus further if they want — zoom composes with the user's
 * own browser zoom rather than overriding it.
 *
 * Scoped to desktop+ (tablet phones already have their own calibrated
 * clamps in the media queries below) and to non-PWA mode (the installed
 * app sets html.is-pwa via the head-script and renders at 1x because
 * the PWA layouts are already calibrated to native device pixels).
 *
 * `zoom` was non-standard until 2024 (Firefox 126+); evergreen Safari
 * + Chrome + Edge all support it. Older Firefox simply gets the 100%
 * render, which is the previous shipping baseline — graceful degrade. */
@media (min-width: 768px) {
  html:not(.is-pwa) { zoom: 1.1; }
}

:root {
  /* ── color (Apple's exact palette from apple.md) ────────────────────── */
  --page:        #f5f5f7;                   /* Apple's signature light gray */
  --surface:     #ffffff;                   /* elevated card */
  --surface-2:   #ededf0;                   /* recessed (input fills) */
  --ink:         #1d1d1f;                   /* near-black */
  --ink-soft:    rgba(0, 0, 0, 0.80);
  --ink-muted:   rgba(0, 0, 0, 0.56);
  --hairline:    rgba(0, 0, 0, 0.12);
  --hairline-strong: rgba(0, 0, 0, 0.22);

  --accent:      #0071e3;                   /* Apple Blue */
  --accent-deep: #0066cc;                   /* link blue on light */
  --accent-soft: rgba(0, 113, 227, 0.10);

  --dark-page:   #000000;                   /* pure black, Apple cinema */
  --dark-ink:    #ffffff;
  --dark-ink-soft: rgba(255, 255, 255, 0.92);
  --dark-ink-muted: rgba(255, 255, 255, 0.56);
  --dark-hairline: rgba(255, 255, 255, 0.16);
  --dark-accent: #2997ff;                   /* link blue on dark */

  --focus:       #0071e3;                   /* Apple Blue doubles as focus */

  /* ── spacing (4pt scale, semantic names) ────────────────────────────── */
  --s-1:   4px;
  --s-2:   8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  24px;
  --s-6:  32px;
  --s-7:  48px;
  --s-8:  64px;
  --s-9:  96px;
  --s-10: 144px;

  /* ── radius ─────────────────────────────────────────────────────────── */
  --r-1:   4px;
  --r-2:   8px;
  --r-3:  12px;
  --r-pill: 999px;

  /* ── type ──────────────────────────────────────────────────────────── */
  --font-display: 'Bricolage Grotesque', 'Bricolage-fallback', Georgia, serif;
  --font-body:    'Geist', 'Geist-fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono:    'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* fluid display sizes — clamp(min, fluid, max). Display max kept tight
     (76px not 92px) so the hero headline fits in 2–3 lines on a 1280px
     viewport instead of wrapping into 4 stubby lines. */
  --t-display:   clamp(40px, 5.2vw + 8px, 76px);
  --t-section:   clamp(28px, 3.0vw + 8px, 48px);
  --t-feature:   clamp(22px, 1.6vw + 14px, 32px);
  --t-lead:      clamp(17px, 0.6vw + 14px, 21px);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.04), 0 0 0 1px rgba(0, 0, 0, 0.04);
  --shadow-2: rgba(0, 0, 0, 0.22) 3px 5px 30px 0px;   /* Apple's signature card shadow */
}

/* fallback that matches Geist's metrics so swap doesn't shift layout */
@font-face {
  font-family: 'Geist-fallback';
  src: local('Helvetica Neue'), local('Helvetica'), local('Arial');
  ascent-override: 92%;
  descent-override: 22%;
  size-adjust: 100%;
}
@font-face {
  font-family: 'Bricolage-fallback';
  src: local('Georgia');
  ascent-override: 96%;
  descent-override: 22%;
  size-adjust: 102%;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Defensive: never let a stray wide descendant (long translated copy
   with white-space:nowrap, an oversized inline SVG, etc.) push the
   document past viewport width and force horizontal scroll on mobile.
   `overflow-x: clip` cuts the overflow without establishing a scroll
   container, so `position: sticky` on the header keeps working. */
html, body { overflow-x: clip; }
/* Kill the default iOS / Android Chrome tap-highlight everywhere. Our
   hover / focus styles already convey interactivity; the gray-blue
   flash on press just looks broken on a dark or accent-coloured button.
   Per-element overrides we had on .brand and nav.site a were left in
   place but are now redundant. */
a, button, [role="button"], input, select, textarea, summary, label,
.btn, .price-track, details, .clickable,
tr, td, .dash-tile, .activity li, .activity .ref {
  -webkit-tap-highlight-color: transparent;
}
/* Reserve scrollbar space at all times. Without this, the macOS / Chrome
   trackpad scrollbar appears/disappears during scroll and shifts every
   right-aligned element in the page (including the nav inside the sticky
   header) by ~15px — reads as horizontal jitter. */
html { scrollbar-gutter: stable; }

body {
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-kerning: normal;
}

/* tabular numerals everywhere a number can appear */
.num, .mono, td, .price, .ledger dd, .ledger dt .qty, time {
  font-variant-numeric: tabular-nums;
}

/* ── layout primitives ──────────────────────────────────────────────── */

.wrap     { max-width: 1120px; margin: 0 auto; padding: 0 var(--s-5); }
.wrap-mid { max-width: 880px; margin: 0 auto; padding: 0 var(--s-5); }
.wrap-narrow { max-width: 640px; margin: 0 auto; padding: 0 var(--s-5); }

section { padding: var(--s-9) 0; }
section.tight { padding: var(--s-7) 0; }

/* ── hero (marketing) ─────────────────────────────────────────────────
   Full-bleed map background + overlaid text column. The .hero-map div
   positions absolute and fills the hero; the SVG inside sizes 100% wide
   with auto height (preserving aspect — will overflow vertically on
   wide viewports, clipped by overflow:hidden). A soft white-to-
   transparent gradient via .hero::before sits between map (z:0) and
   text (z:2) at z:1 so the headline reads cleanly without dimming the
   route + Paramaribo on the right. */
.hero {
  position: relative;
  /* overflow:hidden was here to clip the SVG, but on shorter (16:9)
     desktops it also clipped the fineprint at the bottom edge.
     Moved to .hero-map below so the map gets clipped but the text
     column never can. */
  isolation: isolate;
}
/* Desktop: hero fills the viewport below the sticky header so the
   next section doesn't peek in at the bottom on tall monitors. Flex
   centers the .wrap vertically within the now-taller hero so the
   text column doesn't anchor to the top of the section padding.
   100vh (not calc(100vh - 48px)) on purpose — the html:not(.is-pwa)
   zoom: 1.1 makes the literal "100vh" measure slightly under the
   visible viewport after the zoom-scale, so dropping the header
   subtraction lets the hero exactly fill what the user sees. The
   sticky header overlays the top 48px transparently so this is
   visually clean either way. */
@media (min-width: 768px) {
  .hero {
    min-height: 100vh;
    display: flex;
    align-items: center;
    /* Trim the section padding so on 16:9 desktops (1080px tall) the
       text column still has breathing room from the hero floor and
       the fineprint doesn't kiss the bottom edge. */
    padding-block: var(--s-6);
  }
  .hero > .wrap { width: 100%; }
}
.hero-map {
  position: absolute;
  inset: 0;
  /* Owns the overflow-clipping now (moved off .hero). The SVG is wider
     and taller than the hero on most viewports — this keeps the
     overflow contained without ever clipping the text column above. */
  overflow: hidden;
  display: flex;
  /* Anchor the SVG to the bottom of the hero instead of centering it.
     The SVG aspect (1.38:1) is narrower than a viewport-tall hero, so
     it always overflows vertically. With bottom anchor the overflow
     crops from the top (which is mostly empty USA/Canada / open ocean
     above the route) so Suriname's outline always lands in view at the
     bottom edge — the destination should never feel half-cut. */
  align-items: flex-end;
  justify-content: center;
  /* Lift the bottom-anchored SVG off the hero floor — gives SURINAME
     a comfortable margin and lets the route arc sit near optical
     centre instead of grazing the bottom. */
  padding-bottom: var(--s-9);
  z-index: 0;
  /* Let the cursor reach the SVG inside so parallax mousemove fires
     in the open ocean area. Text overlay above still catches its own
     events because it sits at a higher z-index. */
  pointer-events: none;
}
.hero-map > figure {
  width: 100%;
  height: auto;
  /* Centered vertically; SVG natural aspect (480:347 = 1.38:1) is
     narrower than typical hero aspect (~2:1) so it fills width and
     overflows top/bottom slightly — clipped by .hero overflow:hidden. */
}
.hero-map .route-svg {
  width: 100%;
  height: auto;
  display: block;
  pointer-events: auto;
}
/* Gradient mask between map and text. Full surface color on the left
   third so the H1 sits on a clean reading plane, fading to transparent
   by 70% so the route arc + Paramaribo on the right stay full opacity. */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to right,
    var(--surface) 0%,
    var(--surface) 32%,
    rgba(255, 255, 255, 0) 70%
  );
  z-index: 1;
  pointer-events: none;
}
.hero > .wrap {
  position: relative;
  z-index: 2;
}
/* Text column constrains the headline so it doesn't run into the
   route arc on the right side of the underlying map. */
.hero-text { max-width: 56ch; }

/* Fineprint row under the CTAs ("72-hour quote validity · PayPal &
   card accepted"). Inline-flex with a wide gap on desktop; on mobile
   the gap tightens + font shrinks slightly so the whole row stays on
   one line at ~360px viewports instead of wrapping into two. */
.hero-fineprint {
  margin-top: var(--s-7);
  color: var(--ink-muted);
  display: flex;
  align-items: baseline;
  gap: var(--s-5);
  flex-wrap: wrap;
}
@media (max-width: 720px) {
  .hero-fineprint {
    gap: var(--s-2);
    font-size: 10px;
    /* Wrap freely — Dutch ("Offerte 72 uur geldig · PayPal & creditcard
       geaccepteerd") is ~30% longer than the English copy and nowrap
       used to push the row past 100vw, dragging every block ancestor
       wider than the viewport (the H1, lead, and header nav all
       clipped on the right edge as a side-effect). Two lines of tiny
       fineprint reads fine. */
    flex-wrap: wrap;
    white-space: normal;
  }
}

/* Mobile: the full-bleed map + text overlay is a desktop-only treatment.
   On phones (visitors arriving in mobile Safari / Chrome — PWA users
   never see this hero because .marketing-landing is hidden in app
   mode) restore the original stacked layout: text on top, smaller
   map below at its natural aspect. No overlay, no gradient mask, no
   absolute positioning — just normal flow. */
@media (max-width: 720px) {
  .hero {
    overflow: visible;
    isolation: auto;
    display: flex;
    flex-direction: column;
  }
  .hero::before { display: none; }
  .hero > .wrap {
    position: static;
    z-index: auto;
    order: 1;
  }
  .hero-map {
    position: static;
    inset: auto;
    display: block;
    order: 2;
    max-width: 480px;
    margin: var(--s-6) auto 0;
    padding: 0 var(--s-5);
    pointer-events: auto;
  }
  .hero-map > figure {
    width: 100%;
    margin: 0;
  }
  .hero-text { max-width: 100%; }
}
section.dark {
  background: var(--dark-page);
  color: var(--dark-ink);
}

@media (max-width: 720px) {
  section { padding: var(--s-7) 0; }
}

/* ── header ─────────────────────────────────────────────────────────── */

header.site {
  position: sticky; top: 0; z-index: 30;
  background: rgba(0, 0, 0, 0.80);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  /* Isolate the header's paint so backdrop-filter doesn't pull half-pixel
     samples from a still-painting page below it. `contain: paint` cuts
     the repaint region to the header itself; `will-change: backdrop-filter`
     hints to the compositor to keep the blur layer stable across frames.
     Setting `transform: translateZ(0)` here would create a stacking
     context that breaks the blur — that's why it isn't here. */
  contain: layout paint;
  will-change: backdrop-filter;
}
header.site .row {
  display: flex; align-items: center; justify-content: space-between;
  height: 48px; gap: var(--s-5);
}
/* Push the wordmark closer to the screen edge on desktop without affecting
   mobile, where the brand is centered (width:100%; justify-content:center)
   and the wrap's symmetric padding keeps the centering true. */
@media (min-width: 721px) {
  header.site .wrap { padding-left: var(--s-2); }
}
/* Brand wordmark — design 03a "tight wordmark": Helvetica 800 with negative
   tracking and a signal-blue accent period. The period is rendered as a
   span so we can colour it independently of the rest of the word. */
.brand {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: #fff;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 800; font-size: 19px;
  letter-spacing: -0.045em;
  line-height: 1;
  transition: color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.brand:hover,
.brand:active,
.brand:focus-visible { color: rgba(255, 255, 255, 0.7); }
/* Keep the signal-blue dot blue across all states. .brand:hover is more
   specific than .brand-dot alone, so without this rule the dot would turn
   grey along with the wordmark on hover. */
.brand:hover .brand-dot,
.brand:active .brand-dot,
.brand:focus-visible .brand-dot { color: var(--accent); }
/* Wordmark + dot share one flex item so the dot stays kerned tight against
   the final "e"; without this wrapper the dot becomes its own flex child
   and inherits the 10px gap. */
.brand-word { display: inline-block; line-height: 1; }
.brand-dot { color: var(--accent); margin-left: 0.02em; }
/* Stencil-cut monogram from the design canvas: a black chip with a cut-out
   "A" + arc "C". Inline SVG so it scales crisply and tints with currentColor.
   The SVG's own viewBox carries the rx=6 corner; no CSS border-radius needed. */
.brand-mark {
  width: 26px; height: 26px;
  display: block;
  flex-shrink: 0;
  /* Used to be inline <svg>, but Chrome's "Force dark mode for web
     contents" flag (Pixel / dev option) inverts inline SVG content
     regardless of forced-color-adjust or color-scheme hints — turning
     the dark chip white and erasing the AC cutout. Switching to <img
     src="favicon.svg"> bypasses the inversion entirely because Chrome's
     force-dark explicitly preserves <img> tags as content. */
}
nav.site {
  display: flex; gap: var(--s-5);
  font-family: var(--font-body);
  font-size: 12px; font-weight: 400;
}
nav.site a {
  color: rgba(255, 255, 255, 0.88);
  text-decoration: none;
  transition: color 0.15s;
  letter-spacing: -0.01em;
  /* Suppress the default blue tap-highlight on iOS / Android Chrome —
     it makes the nav links flash on every press, which clashes with our
     custom hover/focus styling. */
  -webkit-tap-highlight-color: transparent;
}
nav.site a:hover { color: #fff; }

/* ── typography ─────────────────────────────────────────────────────── */

h1, h2, h3, .display, .display-section, .display-feature {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.022em;
  margin: 0;
  text-wrap: balance;
}
.display {
  font-size: var(--t-display);
  line-height: 0.96;
  font-variation-settings: 'opsz' 96, 'wdth' 100;
}
h2, .display-section {
  font-size: var(--t-section);
  line-height: 1.04;
  font-variation-settings: 'opsz' 64, 'wdth' 100;
}
h3, .display-feature {
  font-size: var(--t-feature);
  line-height: 1.12;
  font-variation-settings: 'opsz' 32, 'wdth' 100;
}
p { margin: 0; }
.lead {
  font-family: var(--font-body);
  font-size: var(--t-lead);
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: 56ch;
  text-wrap: pretty;
}
section.dark .lead { color: var(--dark-ink-soft); }

.eyebrow {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-deep);
}
.eyebrow::before {
  content: '';
  display: inline-block;
  width: 18px; height: 1px;
  background: currentColor;
}
/* On pure black we need the brighter Apple link blue (#2997ff) for readable contrast — Apple's own rule. */
section.dark .eyebrow { color: var(--dark-accent); }

a { color: var(--accent-deep); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--ink); }
section.dark a { color: var(--dark-accent); }
section.dark a:hover { color: var(--dark-ink); }

.muted        { color: var(--ink-muted); }
section.dark .muted { color: var(--dark-ink-muted); }

/* ── buttons ────────────────────────────────────────────────────────── */

.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--page);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  padding: 14px 22px;
  font-family: var(--font-body);
  font-size: 15px; font-weight: 500;
  letter-spacing: -0.01em;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-bg);
  border-radius: var(--r-2);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.06s ease, background 0.18s, border-color 0.18s, color 0.18s;
  -webkit-appearance: none; appearance: none;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Apple's primary CTA spec: #0071e3 fill, pure white text. 7:1 contrast.
   We set color: explicitly (not just --btn-fg) so any cascade-level surprise
   from section.dark or printer-ink mode can't override the white. */
.btn.primary {
  --btn-bg: var(--accent);
  --btn-fg: #ffffff;
  background: var(--accent) !important;
  color: #ffffff !important;
  border-color: var(--accent) !important;
}
.btn.primary:hover {
  --btn-bg: #0077ed;
  background: #0077ed !important;
}
section.dark .btn.primary,
section.dark .btn.primary:visited {
  color: #ffffff !important;
  background: var(--accent) !important;
  border-color: var(--accent) !important;
}
section.dark .btn.primary:hover { background: #0077ed !important; }

.btn.dark { --btn-bg: var(--ink); --btn-fg: #ffffff; }
.btn.dark:hover { --btn-bg: #2a2a2c; }
section.dark .btn.dark { --btn-bg: #ffffff; --btn-fg: var(--ink); }
section.dark .btn.dark:hover { --btn-bg: #ededf0; }

/* Pill — Apple's signature "Learn more" CTA shape */
.btn.pill {
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--accent-deep);
  border-color: var(--accent-deep);
}
.btn.pill:hover { background: var(--accent-deep); color: #fff; }
section.dark .btn.pill { color: var(--dark-accent); border-color: var(--dark-accent); }
section.dark .btn.pill:hover { background: var(--dark-accent); color: #000; }

.btn.ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border-color: var(--hairline-strong);
}
.btn.ghost:hover { --btn-bg: rgba(0, 0, 0, 0.04); }
section.dark .btn.ghost {
  --btn-fg: var(--dark-ink);
  border-color: var(--dark-hairline);
}
section.dark .btn.ghost:hover { --btn-bg: rgba(255, 255, 255, 0.06); }

.btn .arrow { transition: transform 0.22s cubic-bezier(0.34, 1.4, 0.64, 1); display: inline-block; }
.btn:hover .arrow,
.btn:focus-visible .arrow { transform: translateX(5px); }

/* ── ledger (the signature pricing pattern) ─────────────────────────── */

.ledger {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 14px;
}
.ledger dt, .ledger dd {
  margin: 0;
  padding: 12px 0;
  border-bottom: 1px solid var(--hairline);
}
.ledger dt {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--s-3);
  color: var(--ink-soft);
}
.ledger dt::after {
  content: '';
  align-self: end;
  margin-bottom: 4px;
  border-bottom: 1px dotted var(--hairline-strong);
  height: 1px;
}
.ledger dt > span:first-child { white-space: nowrap; }
.ledger dt .qty { color: var(--ink-muted); margin-left: var(--s-2); }
.ledger dd {
  text-align: right;
  font-weight: 600;
  color: var(--ink);
  padding-left: var(--s-4);
  font-variant-numeric: tabular-nums;
}
.ledger .total-row dt,
.ledger .total-row dd {
  padding-top: var(--s-4);
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  border-bottom: none;
  border-top: 2px solid var(--ink);
}
.ledger .total-row dt::after { display: none; }

section.dark .ledger dt { color: var(--dark-ink-soft); }
/* The qty span (e.g. "5 lb × $4.35", "15%") inherits ink-muted from light-bg
   rules — override on dark surfaces or it's invisible on the black card. */
section.dark .ledger dt .qty { color: var(--dark-ink-muted); }
section.dark .ledger dt::after { border-bottom-color: var(--dark-hairline); }
section.dark .ledger dt, section.dark .ledger dd { border-bottom-color: var(--dark-hairline); }
section.dark .ledger dd { color: var(--dark-ink); }
section.dark .ledger .total-row dt,
section.dark .ledger .total-row dd { color: var(--dark-ink); border-top-color: var(--dark-ink); }

/* ── forms ──────────────────────────────────────────────────────────── */

label {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--s-2);
}
section.dark label { color: var(--dark-ink-muted); }

input, textarea, select {
  width: 100%;
  font-family: var(--font-body);
  font-size: 17px; font-weight: 400;
  letter-spacing: -0.01em;
  padding: 12px 14px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-2);
  transition: border-color 0.15s, box-shadow 0.15s;
}
input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--accent-deep);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
section.dark input, section.dark textarea, section.dark select {
  background: #1d1d1f;
  color: var(--dark-ink);
  border-color: var(--dark-hairline);
}

.field { margin-bottom: var(--s-5); }
.field-help {
  font-size: 14px; line-height: 1.45;
  color: var(--ink-muted);
  margin-top: var(--s-2);
}
section.dark .field-help { color: var(--dark-ink-muted); }

/* ── flow toggle (stamp-style tabs) ─────────────────────────────────── */

.flow-toggle {
  display: grid; gap: 0; grid-template-columns: 1fr 1fr;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-2);
  background: var(--surface);
  overflow: hidden;
}
.flow-toggle label {
  margin: 0; padding: var(--s-4) var(--s-5);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 15px; font-weight: 500;
  letter-spacing: -0.005em;
  text-transform: none;
  color: var(--ink-soft);
  text-align: center;
  transition: background 0.15s, color 0.15s;
  border-right: 1px solid var(--hairline);
}
.flow-toggle label:last-child { border-right: none; }
.flow-toggle input[type="radio"] { display: none; }
.flow-toggle label:has(input:checked) {
  background: var(--ink);
  color: var(--page);
}
.flow-toggle label .sub {
  display: block;
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.flow-toggle label:has(input:checked) .sub { color: rgba(255, 255, 255, 0.64); }

/* Delivery zone variant has 3 options: top row stays 2-up, the third
   option (outside-GP) spans both columns and centers itself on the
   second row — looks tidier than leaving a half-empty row. */
.delivery-zones label:nth-child(3) {
  grid-column: 1 / -1;
  border-right: none;
  border-top: 1px solid var(--hairline);
}

/* ── flow cards (homepage two options) ─────────────────────────────── */

.flow-card {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s-4);
  padding: var(--s-7) var(--s-6) var(--s-6);
  background: var(--surface);
  border-radius: var(--r-3);
  border: 1px solid var(--hairline);
  position: relative;
  transition: border-color 0.18s, transform 0.18s;
}
.flow-card:hover { border-color: var(--ink); }
.flow-card .stamp {
  position: absolute;
  top: var(--s-5); right: var(--s-5);
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 4px 8px;
  border: 1px solid var(--hairline-strong);
  border-radius: 2px;
}
.flow-card .price-line {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-soft);
}
.flow-card .price-line .amount {
  color: var(--ink);
  font-weight: 600;
}

/* ── FAQ section with sticky cobe globe behind the column ──────────────
   Section becomes a tall scroll container. Inside, a sticky wrapper
   pins the globe behind the FAQ items as the user scrolls through.
   Globe rotation is driven from JS (faq-globe.js) based on scroll
   progress through the section. */

/* Wrapper that contains BOTH the FAQ section and the Trust section
   so the sticky globe pin stays visible across both — the globe
   spans from the first FAQ row down through the end of "Hands on,
   every package." */
.faq-trust-globed {
  position: relative;
  overflow: clip;        /* Trim any globe halo bleed at edges. */
}

/* Sticky pin holds the globe.gl mount. globe.gl auto-sizes its
   WebGL canvas to the mount's clientWidth/clientHeight, so the mount
   fills the entire pinned viewport — no fixed pixel canvas =
   no edge cutoff at any zoom altitude. */
.faq-globe-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  pointer-events: none;
  z-index: 0;
  /* Top fade only — gentle dissolve at the very top so the globe
     enters the section softly. Bottom kept solid since the user
     wants the globe to extend all the way to the footer without
     fading. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 8%, black 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, black 8%, black 100%);
}
.faq-globe-pin #faq-globe-mount {
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.faq-globe-pin canvas { display: block; }

#faq.faq-globed {
  position: relative;
  padding-top: var(--s-7);
  padding-bottom: var(--s-7);
}

/* Floating-grid layout: 12-col grid, cards staggered across the
   width so the globe peeks between them. Header sits centred at top
   of the grid; each FAQ card occupies 5 columns at alternating
   positions. */
.faq-floating-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--s-4);
  max-width: 1240px;
  margin: 0 auto;
  /* Pull the grid up over the sticky pin so the content floats in
     front of the globe instead of sitting under it. */
  margin-top: calc(-100vh + var(--s-5));
  padding: 0 var(--s-5);
}

/* Section header lives ABOVE the sticky globe pin so users see what
   section they're entering before the visual takes over the viewport.
   Previously sat inside the floating grid (centered over the globe);
   that worked on desktop but on mobile (where the grid pull-up is
   disabled) the title got buried below the globe. Promoting it to a
   normal section header in front of the pin fixes both contexts. */
.faq-section-header {
  position: relative;
  z-index: 2;
  text-align: center;
  max-width: 1240px;
  margin: 0 auto;
  padding: var(--s-7) var(--s-5) var(--s-4);
}
.faq-section-header .display-section {
  margin-top: var(--s-3);
  font-size: clamp(28px, 3vw + 8px, 44px);
}

/* Default — every card spans 5 columns on the right. Each nth-child
   places it in a specific column slot for the staggered effect.
   Pattern: alternating left / right with a slight extra indent on
   every fourth row for visual rhythm. */
.faq-floating-grid .faq-item {
  background: rgba(255, 255, 255, 0.78);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(0, 113, 227, 0.12);
  border-radius: var(--r-2);
  box-shadow: 0 4px 24px rgba(0, 66, 153, 0.08);
  transition: transform 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
  align-self: start;
}
.faq-floating-grid .faq-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 32px rgba(0, 66, 153, 0.12);
}
.faq-floating-grid .faq-item[open] {
  background: rgba(255, 255, 255, 0.96);
}
.faq-floating-grid .faq-item summary,
.faq-floating-grid .faq-item .faq-body {
  padding-left: var(--s-4);
  padding-right: var(--s-4);
}

/* Stagger positions — left / right / left-indent / right-indent.
   The faq-header was previously the first grid child (which pushed
   nth-child counts up by one); it has been promoted out of the grid,
   so the items are now nth-child(1..8). */
.faq-floating-grid .faq-item:nth-child(1)  { grid-column: 1 / span 5; }   /* Q1 left */
.faq-floating-grid .faq-item:nth-child(2)  { grid-column: 8 / span 5; }   /* Q2 right */
.faq-floating-grid .faq-item:nth-child(3)  { grid-column: 2 / span 5; }   /* Q3 left-indent */
.faq-floating-grid .faq-item:nth-child(4)  { grid-column: 7 / span 5; }   /* Q4 right-indent */
.faq-floating-grid .faq-item:nth-child(5)  { grid-column: 1 / span 5; }   /* Q5 left */
.faq-floating-grid .faq-item:nth-child(6)  { grid-column: 8 / span 5; }   /* Q6 right */
.faq-floating-grid .faq-item:nth-child(7)  { grid-column: 2 / span 5; }   /* Q7 left-indent */
.faq-floating-grid .faq-item:nth-child(8)  { grid-column: 7 / span 5; }   /* Q8 right-indent */

.faq-globed .display-section,
.faq-globed .eyebrow {
  text-shadow: 0 2px 12px rgba(255, 255, 255, 0.6);
}

/* Trust section sits AFTER FAQ inside the same wrapper. Pull its
   content over the pin so "Hands on, every package" floats in front
   of the globe for its final beat. */
.faq-trust-globed > section:not(#faq) {
  position: relative;
  z-index: 1;
}

/* Trust block: "Stamped paper artifacts" tariff card.
   Ivory document with a blue washi-tape strip, a slight rotation
   (pinned-to-a-board feel), a solid black rule under the header,
   dashed dividers between sections, and a blue rubber stamp on the
   signature row. */
.tariff-card {
  position: relative;
  max-width: 880px;
  margin: 32px auto 8px;
  padding: clamp(28px, 4.5vw, 56px) clamp(28px, 5vw, 64px);
  background: #fbf6e7;                  /* ivory paper */
  color: #14171f;
  border-radius: 4px;
  box-shadow:
    0 22px 50px rgba(40, 30, 10, 0.20),
    0 4px 10px rgba(40, 30, 10, 0.08);
  /* Subtle pinned-to-board tilt. */
  transform: rotate(-0.6deg);
}

/* Washi tape strip pinning the top-left corner. Semi-transparent
   brand blue so it reads as tape, not solid paint. */
.tc-tape {
  position: absolute;
  top: -18px;
  left: 7%;
  width: 150px;
  height: 34px;
  background: rgba(76, 124, 232, 0.55);
  transform: rotate(-4deg);
  box-shadow:
    0 2px 4px rgba(40, 30, 10, 0.12),
    inset 0 0 12px rgba(255, 255, 255, 0.15);
  pointer-events: none;
}

.tc-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s-5);
  margin-bottom: var(--s-4);
}

.tc-eyebrow {
  font-family: var(--font-mono, monospace);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #14171f;
}

.tc-route {
  font-family: var(--font-mono, monospace);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #14171f;
  text-align: right;
  line-height: 1.45;
}

.tc-rule {
  border: 0;
  margin: 0 0 var(--s-5);
  height: 0;
}
.tc-rule-solid {
  border-top: 1.5px solid #14171f;
}
.tc-rule-dashed {
  border-top: 1px dashed rgba(20, 23, 31, 0.32);
  margin: var(--s-5) 0;
}

.tc-title {
  margin: 0 0 var(--s-4);
  font: 800 clamp(40px, 5vw + 8px, 64px) / 1.0
        var(--font-display, "Helvetica Neue"), Helvetica, Arial, sans-serif;
  letter-spacing: -0.03em;
  color: #14171f;
}

.tc-lead {
  margin: 0;
  font-size: clamp(15px, 0.9vw + 10px, 19px);
  line-height: 1.55;
  color: #14171f;
  max-width: 60ch;
}

.tc-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-5);
  flex-wrap: wrap;
}

/* Footer right cluster — stamp sits next to the CTA pill so the
   "Authentic / Ops · 01" mark feels like it was applied next to the
   document's outgoing action. */
.tc-footer-right {
  display: flex;
  align-items: center;
  gap: var(--s-4);
}

/* Blue rubber stamp — clean rectangular border, brand blue ink,
   slight rotation. Matches the design's "FORWARDED / OPS · 04" mark. */
.tc-stamp {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 12px 22px;
  border: 2.5px solid var(--accent-deep, #0066cc);
  background: transparent;
  color: var(--accent-deep, #0066cc);
  font-family: var(--font-mono, monospace);
  transform: rotate(-3deg);
  /* Faint inner highlight so the stamp reads as ink-on-paper. */
  box-shadow: inset 0 0 0 1px rgba(0, 102, 204, 0.25);
}
.tc-stamp-title {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.tc-stamp-sub {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.20em;
  text-transform: uppercase;
}

.tc-ref {
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: rgba(20, 23, 31, 0.55);
}

/* Outlined rectangular CTA — bold black border, transparent fill,
   inverts on hover. */
.tc-cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 22px;
  border: 1.5px solid #14171f;
  border-radius: 4px;
  background: transparent;
  color: #14171f;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  transition: background 0.18s, color 0.18s, transform 0.18s;
}
.tc-cta:hover {
  background: #14171f;
  color: #fbf6e7;
  transform: translateY(-1px);
}
.tc-arrow { transition: transform 0.18s; }
.tc-cta:hover .tc-arrow { transform: translateX(3px); }

@media (max-width: 720px) {
  .tariff-card {
    transform: rotate(-0.3deg);
    padding: var(--s-6) var(--s-5);
    margin-top: 28px;
  }
  .tc-tape { left: 6%; width: 110px; height: 26px; top: -14px; }
  .tc-header { flex-direction: column; gap: var(--s-2); }
  .tc-route { text-align: left; }
  .tc-row { gap: var(--s-4); }
  .tc-footer-row { align-items: flex-start; }
  .tc-footer-right { width: 100%; justify-content: space-between; }
  .tc-cta { flex: 1; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .tariff-card { transform: none; }
  .tc-tape { transform: none; }
  .tc-stamp { transform: none; }
  .tc-cta { transition: none; }
}

/* Extend the wrapper past the Trust section so the sticky globe pin
   stays alive (and the scroll-driven zoom keeps progressing) for an
   extra beat before releasing. With the aggressive ALT_NEAR (0.6)
   in faq-globe.js, the globe fills the screen by the end of this
   padding — only ~half the sphere is visible, the rest clips off
   the top and bottom of the sticky 100vh pin, then the pin releases
   exactly as the footer arrives. */
/* No extra padding — wrapper now includes the PWA-home shell and
   footer (see index.html), so the sticky pin stays alive naturally
   right through to the end of the page. */

/* Footer sits inside the wrapper on top of the sticky globe. Give
   it a translucent backdrop so the text + links stay readable
   against any dots behind. */
.faq-trust-globed > footer.site {
  position: relative;
  z-index: 1;
  background: rgba(245, 245, 247, 0.85);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
}

/* Mobile (≤720px): collapse to single column, full width per card,
   more opaque background since the globe behind is smaller. */
@media (max-width: 720px) {
  .faq-floating-grid {
    grid-template-columns: 1fr;
    gap: var(--s-3);
    margin-top: 0;            /* Don't pull up — let globe + cards stack naturally. */
    padding: 0 var(--s-4);
  }
  .faq-floating-grid .faq-item,
  .faq-floating-grid .faq-item:nth-child(n) {
    grid-column: 1 / -1;
    background: rgba(255, 255, 255, 0.94);
  }
  .faq-globe-pin {
    /* Smaller globe presence on mobile so cards have room to breathe. */
    height: 70vh;
  }
  .faq-globe-pin #faq-globe-mount {
    opacity: 0.7 !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .faq-globe-pin #faq-globe-mount { opacity: 0.7; }
  .faq-floating-grid .faq-item { transition: none; }
  .faq-floating-grid .faq-item:hover { transform: none; }
}

/* ── Two Ways layout (Option A / Option B side-by-side) ────────────────
   Desktop: two equal columns side-by-side via auto-fit grid. Mobile:
   horizontal scroll-snap carousel — cards sit side-by-side at ~88vw
   each so the next one peeks in from the right edge as a scroll
   affordance. Stacking the boarding-pass cards vertically on phones
   was burying Option B below the fold and reading as "there's only
   one option here" until you scrolled. The carousel keeps both options
   one swipe apart. */
.two-ways-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: var(--s-5);
}

@media (max-width: 720px) {
  .two-ways-cards {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: var(--s-3);
    /* Explicit all-sides padding. The first card sits at s5 from
       the screen edge so it lines up with every other .wrap-bound
       element below ("Already a customer?", member upsell, FAQ).
       Padding-block adds breathing room above + below. */
    padding-top: var(--s-2);
    padding-bottom: var(--s-4);
    padding-left: var(--s-5);
    padding-right: var(--s-5);
    /* Full-bleed only on the right: extend past .wrap's content
       area so the second card can peek in from outside the wrap. */
    margin-right: calc(-1 * var(--s-5));
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    overscroll-behavior-inline: contain;
    scroll-padding-inline-start: var(--s-5);
  }
  .two-ways-cards::-webkit-scrollbar { display: none; }
  .two-ways-cards > .boarding-pass {
    flex: 0 0 82vw;
    max-width: 360px;
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
}

/* ── boarding-pass cards (homepage two-options) ────────────────────────
   Replaces the flat flow-card with a boarding-pass artefact: main panel,
   perforated divider (dashed line with notched circle cut-outs that
   match the section background to look like real perforation), and a
   tear-off stub on the trailing edge with rate + stamp. */

.boarding-pass {
  --bp-surface: var(--surface);
  --bp-ink: var(--ink);
  --bp-muted: var(--ink-muted);
  --bp-soft: var(--ink-soft);
  --bp-accent: var(--accent-deep);
  --bp-rule: var(--hairline-strong);
  /* Notch background = the section colour BEHIND the card, so the
     cutouts visually punch through to the page. */
  --bp-notch-bg: var(--surface-2);

  display: grid;
  grid-template-columns: 1fr 22px 168px;
  background: var(--bp-surface);
  color: var(--bp-ink);
  border-radius: var(--r-3);
  overflow: hidden;
  box-shadow: 0 18px 40px rgba(14,17,22,0.10);
  min-height: 340px;
  position: relative;
  isolation: isolate;
}

.boarding-pass.dark {
  --bp-surface: var(--ink);
  --bp-ink: #ffffff;
  --bp-muted: rgba(255,255,255,0.55);
  --bp-soft: rgba(255,255,255,0.78);
  --bp-accent: #7db1ff;
  --bp-rule: rgba(255,255,255,0.18);
}

.bp-main {
  padding: var(--s-5) var(--s-6);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-5);
  min-width: 0;
}

.bp-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s-4);
}

.bp-option {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bp-accent);
  line-height: 1.3;
}

.bp-route {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bp-muted);
  text-align: right;
  line-height: 1.3;
}

.bp-title {
  margin: 0;
  font: 800 38px/1.0 var(--font-display, "Helvetica Neue"), Helvetica, Arial, sans-serif;
  letter-spacing: -0.03em;
  color: var(--bp-ink);
}

.bp-paragraph {
  margin: var(--s-3) 0 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--bp-soft);
  max-width: 38ch;
}

.bp-footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--s-4);
  flex-wrap: wrap;
}

.bp-price {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.10em;
  color: var(--bp-muted);
  line-height: 1.5;
}
.bp-price .amount { color: var(--bp-ink); font-weight: 600; }

.bp-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.005em;
  background: var(--bp-ink);
  color: var(--bp-surface);
  text-decoration: none;
  transition: transform 0.18s, opacity 0.18s;
}
.bp-cta:hover { transform: translateX(2px); color: var(--bp-surface); }

/* Blue pill button — same geometry as bp-cta but filled with brand
   accent. Used for the primary hero CTA so the page's loudest button
   matches the boarding-pass language and lands in brand blue. */
.btn.pill-blue {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 22px;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  background: var(--accent-deep);
  color: #ffffff;
  border: 0;
  text-decoration: none;
  transition: transform 0.18s, background 0.18s, box-shadow 0.18s;
  box-shadow: 0 8px 20px rgba(0, 102, 204, 0.18);
}
.btn.pill-blue:hover {
  background: #0a4fa5;
  color: #ffffff;
  transform: translateX(2px);
  box-shadow: 0 10px 24px rgba(0, 102, 204, 0.26);
}
.btn.pill-blue .arrow { transition: transform 0.18s; }
.btn.pill-blue:hover .arrow { transform: translateX(2px); }

/* Perforated divider: a dashed line with two circular cut-outs at top
   and bottom that match the page background, so the card looks like
   it was actually torn along the perforation. */
.bp-perforation {
  position: relative;
  border-left: 1.5px dashed var(--bp-rule);
}
.bp-perforation::before,
.bp-perforation::after {
  content: "";
  position: absolute;
  left: -11px;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: var(--bp-notch-bg);
}
.bp-perforation::before { top: -11px; }
.bp-perforation::after  { bottom: -11px; }

.bp-stub {
  padding: var(--s-5) var(--s-4);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-3);
}

.bp-stub-eyebrow {
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bp-muted);
  line-height: 1.3;
}

.bp-stub-rate {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.bp-stub-rate-label {
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bp-muted);
  line-height: 1;
}
.bp-stub-rate-value {
  font: 800 26px/1 var(--font-display, "Helvetica Neue"), Helvetica, Arial, sans-serif;
  letter-spacing: -0.025em;
  color: var(--bp-ink);
}

.bp-stamp {
  align-self: flex-end;
  display: inline-block;
  padding: 8px 12px;
  border: 2.4px solid var(--bp-accent);
  color: var(--bp-accent);
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  line-height: 1;
  transform: rotate(2deg);
}

/* Mobile: stack main + stub vertically, perforation becomes a
   horizontal tear. Stub goes below. */
@media (max-width: 720px) {
  .boarding-pass {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr 22px auto;
    min-height: 0;
  }
  .bp-main { padding: var(--s-5); }
  .bp-perforation {
    border-left: 0;
    border-top: 1.5px dashed var(--bp-rule);
  }
  .bp-perforation::before,
  .bp-perforation::after {
    top: -11px;
    bottom: auto;
  }
  .bp-perforation::before { left: -11px; }
  .bp-perforation::after  { left: auto; right: -11px; }
  .bp-stub {
    padding: var(--s-5);
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--s-4);
  }
  .bp-stamp { transform: rotate(0deg); }
}

/* ── multi-item input rows ─────────────────────────────────────────── */

.items-list { display: flex; flex-direction: column; gap: var(--s-3); }

.item-row {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: var(--s-3);
  align-items: center;
}
.item-row .seq {
  font-family: var(--font-mono);
  font-size: 12px; color: var(--ink-muted);
  text-align: right;
  letter-spacing: 0.04em;
}
.item-row .row-input { width: 100%; }
.item-row .remove {
  background: transparent;
  border: 1px solid var(--hairline-strong);
  color: var(--ink-muted);
  border-radius: var(--r-2);
  width: 36px; height: 44px;
  font-size: 18px; line-height: 1;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 0.15s, border-color 0.15s;
}
.item-row .remove:hover { color: #b00020; border-color: #b00020; }
.item-row .remove[disabled] { opacity: 0.3; cursor: not-allowed; }

.add-item-btn {
  align-self: flex-start;
  background: transparent;
  border: 1px dashed var(--hairline-strong);
  color: var(--ink-soft);
  padding: 10px 16px;
  border-radius: var(--r-2);
  font-family: var(--font-body);
  font-size: 14px; font-weight: 500;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.add-item-btn:hover {
  color: var(--ink);
  border-color: var(--ink);
  border-style: solid;
}

/* ── manual entry per-item card ─────────────────────────────────────── */

.manual-item {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  padding: var(--s-5);
}
.manual-item .head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-3); margin-bottom: var(--s-3);
}
.manual-item .seq-tag {
  font-family: var(--font-mono);
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.10em;
  color: var(--ink-muted);
}
.manual-item .pill {
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 8px; border-radius: var(--r-pill);
  border: 1px solid var(--hairline-strong);
  color: var(--ink-muted);
}
.manual-item .pill.detected {
  color: #2a8a5e; border-color: rgba(42, 138, 94, 0.4);
  background: rgba(42, 138, 94, 0.06);
}
.manual-item .pill.needs-input {
  color: #875a05; border-color: rgba(135, 90, 5, 0.4);
  background: rgba(135, 90, 5, 0.06);
}
.manual-item .title {
  font-family: var(--font-display);
  font-size: 17px; font-weight: 600;
  letter-spacing: -0.012em;
  margin-bottom: var(--s-3);
}
.manual-item .url {
  font-family: var(--font-mono);
  font-size: 12px; color: var(--ink-muted);
  word-break: break-all;
  margin-bottom: var(--s-4);
}
.manual-item .inputs {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.manual-item .inputs .field { margin: 0; }
.manual-item .inputs .field-help {
  font-size: 11px; line-height: 1.4;
  color: var(--ink-muted); margin-top: 4px;
}
@media (max-width: 600px) {
  .manual-item .inputs { grid-template-columns: 1fr; }
}

/* ── timeline (status journey) ──────────────────────────────────────── */

.journey {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  position: relative;
  list-style: none;
  padding: 0;
  margin: 0;
}
.journey li {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  align-items: start;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--hairline);
  /* Anchor for the connector line drawn below — sits between this dot
     and the next, colored accent for completed segments so the customer
     reads it as a filled-in timeline as their shipment progresses. */
  position: relative;
}
.journey li:last-child { border-bottom: none; }
.journey li::after {
  content: "";
  position: absolute;
  /* Center under the 10px dot (column starts at li's left:0, dot
     occupies 0–10px → center at 5px; 2px line at left:4 lands on it). */
  left: 4px;
  top: 26px;        /* just below the dot (padding 16 + dot top 8 + dot 10 - 8 fudge) */
  bottom: -8px;     /* bridge across the row gap into the next dot */
  width: 2px;
  background: var(--hairline);
  z-index: 0;
}
.journey li.done::after { background: var(--accent-deep); }
.journey li:last-child::after { display: none; }
.journey .dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  margin-top: 8px;
  background: var(--surface);
  border: 2px solid var(--hairline-strong);
  /* Sit above the connector line so the dot's border isn't bisected. */
  position: relative;
  z-index: 1;
}
.journey li.done .dot { background: var(--accent-deep); border-color: var(--accent-deep); }
.journey li.current .dot {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.journey .label {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.journey li:not(.done):not(.current) .label { color: var(--ink-muted); }
.journey .sub {
  font-family: var(--font-body);
  font-size: 14px; color: var(--ink-soft);
  margin-top: 2px;
}
.journey time {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-muted);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* ── alerts ─────────────────────────────────────────────────────────── */

.alert {
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-2);
  font-size: 14px; line-height: 1.5;
  border: 1px solid var(--hairline-strong);
  background: var(--surface);
  color: var(--ink-soft);
}
.alert.bad { color: #b00020; border-color: rgba(176, 0, 32, 0.3); background: rgba(176, 0, 32, 0.06); }

/* ── meta strip (FF-XXXXXX + status) ────────────────────────────────── */

.meta-strip {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--hairline);
  margin-bottom: var(--s-5);
  font-family: var(--font-mono);
  font-size: 13px;
}
.meta-strip .ref { color: var(--ink); font-weight: 600; letter-spacing: 0.04em; }
.meta-strip .status {
  text-transform: uppercase;
  letter-spacing: 0.10em;
  color: var(--ink-soft);
  font-size: 11px;
}
.meta-strip .status.paid,
.meta-strip .status.delivered { color: #2a8a5e; }
.meta-strip .status.cancelled { color: #b00020; }

/* ── Member+ badge ─────────────────────────────────────────────────────
   Inline pill + larger chip used to mark subscriber accounts on /account.
   Clipped bottom-right corner reads as a shipping chip rather than a
   gold-foil luxury seal — same vocabulary as the rest of the brand
   (signal blue, Helvetica). The leading dot is a small status indicator,
   not decoration. */
.member-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 10px;
  background: var(--accent);
  color: #fff;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  vertical-align: middle;
  text-transform: none;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%);
}
.member-pill::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  background: #fff;
  border-radius: 999px;
  flex: none;
}
.member-pill.lg { height: 28px; font-size: 12px; padding: 0 12px; gap: 6px; }
.member-pill.lg::before { width: 7px; height: 7px; }
.member-pill.sm { height: 18px; font-size: 9px; padding: 0 7px; gap: 4px; }
.member-pill.sm::before { width: 5px; height: 5px; }
/* Outline variant — for surfaces where solid blue would be too loud
   (e.g. sitting next to a primary CTA). */
.member-pill.outline {
  background: transparent;
  color: var(--accent-deep);
  box-shadow: inset 0 0 0 1.5px var(--accent-deep);
}
.member-pill.outline::before { background: var(--accent-deep); }

/* Premium subscriber card. Two variants:
   .founder = ink (black) with a gold foil-feel "M+" plate; reserved for
              comped accounts (is_member=1, member_until NULL).
   default  = signal-blue with a paper-white "M+" plate; for paid members.
   Aspect ratio 460:290 = standard credit-card 1.586:1, so the card scales
   naturally without distorting on mobile. */
.member-card {
  position: relative;
  width: 100%;
  max-width: 460px;
  aspect-ratio: 460 / 290;
  background: var(--accent);
  background-image: repeating-linear-gradient(90deg, transparent 0 5px, rgba(255,255,255,0.10) 5px 6px);
  color: #fff;
  border-radius: 12px;
  padding: 22px 24px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  box-shadow: 0 18px 38px rgba(0, 113, 227, 0.22), inset 0 1px 0 rgba(255,255,255,0.10);
}
.member-card.founder {
  background: #0E1116;
  background-image: repeating-linear-gradient(90deg, transparent 0 5px, rgba(255,255,255,0.045) 5px 6px);
  box-shadow: 0 18px 38px rgba(14, 17, 22, 0.32), inset 0 1px 0 rgba(255,255,255,0.05);
}
.member-card-plate {
  position: absolute;
  top: 18px; right: 18px;
  width: 54px; height: 36px;
  background: #fff;
  color: var(--accent-deep);
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 800;
  font-size: 17px;
  letter-spacing: -0.02em;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.10);
}
/* Restrained gold foil for founders only — reads as embossed plate, not bling. */
.member-card.founder .member-card-plate {
  background: linear-gradient(135deg, #B8893A 0%, #E0BD78 45%, #B8893A 100%);
  color: #0E1116;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.20);
}
.member-card-brand {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -0.035em;
  color: #fff;
}
.member-card-brand .dot { color: rgba(255,255,255,0.55); }
.member-card.founder .member-card-brand .dot { color: var(--accent); }
.member-card-tag {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.65);
  margin-top: 6px;
}
.member-card.founder .member-card-tag { color: rgba(255,255,255,0.5); }
.member-card-name {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700;
  font-size: 22px;
  letter-spacing: -0.025em;
  line-height: 1.05;
}
.member-card-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-top: 12px;
}
.member-card-label {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.65);
}
.member-card.founder .member-card-label { color: rgba(255,255,255,0.5); }
.member-card-value {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.22em;
  margin-top: 5px;
  color: #fff;
}
.member-card-value.thru {
  font-size: 13px;
  letter-spacing: 0.18em;
}
.member-card-value .sep { color: rgba(255,255,255,0.55); }
.member-card.founder .member-card-value .sep { color: var(--accent); }
@media (max-width: 480px) {
  .member-card { padding: 18px 20px; }
  .member-card-name { font-size: 19px; }
  .member-card-value { font-size: 14px; letter-spacing: 0.18em; }
  .member-card-plate { width: 46px; height: 30px; font-size: 14px; top: 16px; right: 16px; }
}

/* ── route SVG (homepage hero) ──────────────────────────────────────── */

.route-svg {
  width: 100%; height: auto;
  display: block;
}
.route-svg .land {
  fill: rgba(0, 0, 0, 0.05);
  stroke: rgba(0, 0, 0, 0.20);
  stroke-width: 0.6;
  stroke-linejoin: round;
}
.route-svg .land-context {
  fill: rgba(0, 0, 0, 0.025);
  stroke: rgba(0, 0, 0, 0.10);
  stroke-width: 0.5;
  stroke-linejoin: round;
}
.route-svg .land-highlight {
  fill: rgba(0, 113, 227, 0.08);
  stroke: var(--accent-deep);
  stroke-width: 0.7;
  stroke-linejoin: round;
}
.route-svg .route-line {
  fill: none;
  stroke: var(--accent-deep);
  stroke-width: 1.4;
  stroke-dasharray: 4 4;
  stroke-linecap: round;
  /* March the dashes from Miami → Paramaribo. One full cycle equals the
     dash + gap (8 units), so the loop seams perfectly. Negative offset
     to push dashes toward the destination end. */
  animation: route-march 1.4s linear infinite;
}
@keyframes route-march {
  to { stroke-dashoffset: -8; }
}
@media (prefers-reduced-motion: reduce) {
  .route-svg .route-line { animation: none; }
}
.route-svg .anchor {
  fill: var(--accent);
  stroke: #fff;
  stroke-width: 2;
}
.route-svg .anchor-ring {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1;
  opacity: 0.32;
}
/* Pulse rings — separate circles so the static halo above stays put.
   Stagger Paramaribo by half a cycle so the two anchors breathe in
   opposite phase. The `r` CSS property animates SVG circle radius
   in all evergreen browsers. */
.route-svg .anchor-pulse {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.2;
  animation: anchor-pulse 2.4s ease-out infinite;
}
.route-svg .anchor-pulse.delayed { animation-delay: 1.2s; }
@keyframes anchor-pulse {
  0%   { r: 6;  opacity: 0.55; }
  100% { r: 28; opacity: 0;    }
}
@media (prefers-reduced-motion: reduce) {
  .route-svg .anchor-pulse { animation: none; opacity: 0; }
}
.route-svg .label {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  fill: var(--ink-soft);
}
.route-svg .label-major {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.012em;
  fill: var(--ink);
  text-transform: none;
}
.route-svg .ship-mark {
  font-family: var(--font-mono);
  font-size: 12px;
  fill: var(--accent-deep);
  font-weight: 500;
}
/* In-transit marker glide. animateMotion moves the element along the
   route path; CSS fades it in at Miami and out at Paramaribo so the
   loop snap-back is invisible. Match the cycle length to the SMIL
   `dur` on the element so they stay in phase. */
.route-svg .ship-mark.in-transit-glide {
  animation: ship-fade 11s linear infinite;
}
/* Multi-packet flow: 4 gliders share an 11s cycle but are staggered by
   2.75s each so there's always 1-2 in flight. CSS animation-delay
   matches the SMIL begin= attribute on each glider's animateMotion so
   the opacity fade syncs to position. */
.route-svg .ship-mark.in-transit-glide.glide-2 { animation-delay: 2.75s; }
.route-svg .ship-mark.in-transit-glide.glide-3 { animation-delay: 5.5s; }
.route-svg .ship-mark.in-transit-glide.glide-4 { animation-delay: 8.25s; }
@keyframes ship-fade {
  0%   { opacity: 0; }
  8%   { opacity: 1; }
  90%  { opacity: 1; }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .route-svg .ship-mark.in-transit-glide { animation: none; opacity: 1; }
}

/* ── extended hero motion (editorial-cinematic layers) ─────────────────
   Stack added 2026-05-18 to give the hero more sense of depth + flow
   without abandoning the editorial tone. Every effect respects the
   reduced-motion block at the bottom. */

/* Hairline ocean grid behind the land paths — faint blueprint plate. */
.route-svg .ocean-grid line {
  stroke: var(--accent-deep);
  stroke-width: 0.3;
  opacity: 0.06;
}
.route-svg .ocean-grid {
  animation: grid-drift 40s linear infinite;
  transform-origin: center;
}
@keyframes grid-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(6px); }
}

/* Route draw-on for first paint. JS adds .is-drawing immediately, the
   keyframe runs once with `forwards`, then JS strips the class so the
   existing route-march animation resumes seamlessly (route-march
   continues from stroke-dashoffset: 0 → -8 every 1.4s as before). */
.route-svg .route-line.is-drawing {
  animation: route-draw 1.4s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
}
@keyframes route-draw {
  from { stroke-dashoffset: 280; }
  to   { stroke-dashoffset: 0; }
}

/* Anchor radar — inner halo (faster, smaller) and outer echo (slower,
   wider) stacked with the existing .anchor-pulse for a 3-layer breath.
   Paramaribo gets .delayed on each so the two anchors stay out of phase
   (same convention as .anchor-pulse.delayed). */
.route-svg .anchor-halo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1;
  animation: anchor-halo 1.8s ease-out infinite;
}
.route-svg .anchor-halo.delayed { animation-delay: 0.9s; }
@keyframes anchor-halo {
  0%   { r: 4;  opacity: 0.55; }
  100% { r: 14; opacity: 0;    }
}
.route-svg .anchor-echo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 0.9;
  animation: anchor-echo 3.2s ease-out infinite;
}
.route-svg .anchor-echo.delayed { animation-delay: 1.6s; }
@keyframes anchor-echo {
  0%   { r: 10; opacity: 0.25; }
  100% { r: 36; opacity: 0;    }
}

/* Ghost waypoints — static low-opacity context dots along the implied
   route. No animation — they're geographic scaffolding, not action. */
.route-svg .waypoint {
  fill: var(--accent-deep);
  opacity: 0.12;
}

/* Suriname "you are here" breath — a 1.2s alpha swell tucked into a
   10s cycle, so 88% of the time it sits at its base accent-soft alpha
   and you only notice the breath subconsciously. */
.route-svg .land-highlight.suriname-breath {
  animation: suriname-breath 10s ease-in-out infinite;
}
@keyframes suriname-breath {
  0%, 86%, 100% { fill: rgba(0, 113, 227, 0.08); }
  93%           { fill: rgba(0, 113, 227, 0.14); }
}

/* Parallax layer wrapper. hero-motion.js sets --px / --py on each
   .parallax-layer based on cursor offset × data-depth. Clamped at ±5px
   in JS. transition smooths the trail so it doesn't feel jittery. */
.route-svg .parallax-layer {
  transform: translate3d(calc(var(--px, 0px)), calc(var(--py, 0px)), 0);
  transition: transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}

/* Hero text reveal — staggered drop-in from above driven by
   hero-motion.js. JS flips .is-revealed across .hero-reveal children
   with 80ms stagger on DOMContentLoaded. One-shot; never re-runs. */
.hero-reveal {
  opacity: 0;
  transform: translateY(-28px);
  transition: opacity 700ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.hero-reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* Reduced-motion: kill all new hero animations, render final state. */
@media (prefers-reduced-motion: reduce) {
  .route-svg .ocean-grid { animation: none; }
  .route-svg .route-line.is-drawing { animation: none; stroke-dashoffset: 0; }
  .route-svg .anchor-halo,
  .route-svg .anchor-echo { animation: none; opacity: 0; }
  .route-svg .land-highlight.suriname-breath { animation: none; }
  .route-svg .parallax-layer { transform: none; transition: none; }
  .hero-reveal { opacity: 1; transform: none; transition: none; }
}

/* ── footer ─────────────────────────────────────────────────────────── */

footer.site {
  border-top: 1px solid var(--hairline);
  padding: var(--s-7) 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
}
footer.site a { color: var(--ink-muted); }
footer.site a:hover { color: var(--ink); }

/* ── admin table ────────────────────────────────────────────────────── */

table.orders { width: 100%; border-collapse: collapse; font-size: 14px; font-family: var(--font-body); }
table.orders th, table.orders td {
  text-align: left; padding: 12px 10px;
  border-bottom: 1px solid var(--hairline);
}
table.orders th {
  font-family: var(--font-mono);
  font-weight: 500; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-muted);
}
table.orders td.mono { font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.04em; }
table.orders tr:hover td { background: var(--accent-soft); }

/* ── utility ────────────────────────────────────────────────────────── */

.mono { font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.04em; }
.divider {
  height: 1px; background: var(--hairline);
  margin: var(--s-7) 0;
}

@media (max-width: 720px) {
  .flow-toggle { grid-template-columns: 1fr; }
  .flow-toggle label { border-right: none; border-bottom: 1px solid var(--hairline); }
  .flow-toggle label:last-child { border-bottom: none; }
}

/* ── Mobile (≤720px): collapse two-column inline grids, undo stickies ──
 *
 * Layout pages use inline `style="display:grid; grid-template-columns: ..."`
 * for the marketing 2-col hero / explainer / pricing-dark sections and for
 * form rows. Inline styles outrank external CSS, so the overrides below
 * use !important. We target by attribute selector instead of refactoring
 * eight HTML files to classes.
 *
 * Auto-fit grids (`repeat(auto-fit, minmax(Npx, 1fr))`) are intentionally
 * skipped — they already collapse on their own.
 */
@media (max-width: 720px) {

  /* Two-column marketing grids (hero, three-steps, pricing-dark, quote
     main-vs-sidebar) — single column. */
  [style*="grid-template-columns: minmax(0, 1.35fr)"],
  [style*="grid-template-columns: minmax(0, 1.4fr)"],
  [style*="grid-template-columns: minmax(0, 1.1fr)"],
  [style*="grid-template-columns: minmax(0, 1fr) minmax"] {
    grid-template-columns: 1fr !important;
    gap: var(--s-5) !important;
  }

  /* Form-row two-up (e.g. name+email, phone+address). */
  [style*="grid-template-columns: 1fr 1fr"] {
    grid-template-columns: 1fr !important;
    gap: var(--s-4) !important;
  }

  /* Sticky right-sidebars (pricing explainer on /quote, etc) become
     ordinary blocks below the form they used to sit beside. */
  aside[style*="position: sticky"] {
    position: static !important;
    top: auto !important;
  }

  /* Tighter page padding so card edges aren't clipped by viewport. */
  .wrap, .wrap-mid, .wrap-narrow {
    padding-left: var(--s-4);
    padding-right: var(--s-4);
  }

  /* Hero display headlines clamp() to a smaller floor on phones —
     "$4.35 a pound" stays one line instead of forcing 36px+ rendering. */
  .display { font-size: clamp(34px, 9vw, 56px) !important; line-height: 1.05; }

  /* Header on mobile: brand centered on its own row, then nav centered
     below it and wrapping so no item gets clipped off either edge. The
     base justify-content: space-between is what pushed the nav off the
     right side and clipped "How it works" off the left. */
  header.site .row {
    flex-wrap: wrap;
    height: auto;
    padding: 8px 0;
    row-gap: 4px;
  }
  .brand {
    width: 100%;
    justify-content: center;
  }
  nav.site {
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--s-4);
    font-size: 13px;
    row-gap: 4px;
  }

  /* Account/status order-row grids: stack ref + status into two lines
     instead of a 4-column cramped row that pushes price off-screen. */
  [style*="grid-template-columns: 110px 1fr auto auto"],
  [style*="grid-template-columns: 28px 1fr auto auto"] {
    grid-template-columns: auto 1fr !important;
    row-gap: 6px !important;
  }
}

/* ── Tiny phones (≤420px): even more aggressive overrides for the
 *    homepage hero numerals and a few inline display heads. */
@media (max-width: 420px) {
  .display { font-size: 36px !important; }
  .display-section { font-size: 28px !important; }
}

/* ── Mobile header scroll behavior + ledger overflow fixes ──────── */
@media (max-width: 720px) {

  /* Ledger rows on a 5-col-tall card overflow narrow viewports because the
     dt label is `white-space: nowrap`. On mobile let labels wrap, drop the
     dotted-leader line (it visually collapses anyway), and tighten the
     padding-left on the dd column so the price doesn't push past the card. */
  .ledger { font-size: 13px; }
  .ledger dt > span:first-child { white-space: normal !important; }
  .ledger dt::after { display: none; }
  .ledger dd { padding-left: var(--s-3); }

  /* Header collapse-on-scroll: smoothly shrink the brand row to zero so
     only the nav stays sticky, then tighten the row padding so the
     whole header is compact (~48px) instead of a same-height shell with
     an invisible brand sitting in it.
     The earlier opacity-only version preserved the brand's space which
     looked broken ("logo disappears but nav doesn't shrink"). The even
     earlier display:none version was abrupt — the ~32px instant
     collapse jumped content under the sticky upward, and on iOS slow
     scrollers reacted, scrollY re-crossed the threshold, and the
     header flapped. A max-height + opacity transition splits the
     difference: layout *does* shrink (so the header feels compact)
     but does so over 240ms, slow enough that the user perceives it as
     header behavior rather than a jolt — no reflexive counter-scroll,
     no flap. The 80/20 hysteresis in header.js gives a 60px buffer
     around the threshold for extra safety. */
  header.site .brand {
    overflow: hidden;
    max-height: 60px;
    transition: max-height 240ms cubic-bezier(0.22, 0.61, 0.36, 1),
                opacity 180ms ease-out;
  }
  header.site.scrolled .brand {
    max-height: 0;
    opacity: 0;
    pointer-events: none;
  }
  header.site.scrolled .row {
    row-gap: 0;
    padding: 4px 0;
  }
}

/* ── Scroll-reveal ─────────────────────────────────────────────────────
   Elements marked with .reveal fade + slide up 10px when they enter
   the viewport, once. Toggled by a small IntersectionObserver in
   reveal.js so we don't ship a whole animation library. The
   stagger-N classes add a 60ms-per-step delay for sibling lists like
   the FAQ accordion and the three-step ol so the items cascade
   instead of all popping at once. */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.55s ease-out, transform 0.55s ease-out;
}
.reveal.in-view {
  opacity: 1;
  transform: translateY(0);
}
.reveal.stagger-1 { transition-delay: 0.06s; }
.reveal.stagger-2 { transition-delay: 0.12s; }
.reveal.stagger-3 { transition-delay: 0.18s; }
.reveal.stagger-4 { transition-delay: 0.24s; }
.reveal.stagger-5 { transition-delay: 0.30s; }
.reveal.stagger-6 { transition-delay: 0.36s; }
.reveal.stagger-7 { transition-delay: 0.42s; }
.reveal.stagger-8 { transition-delay: 0.48s; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ── "Three steps" / how-it-works section ─────────────────────────────
   Desktop: 2-col grid where the header sticks to the top of the
   viewport while the right column scrolls through steps.
   Mobile: collapses to a normal stack (the sticky header would float
   over the steps on a single-column layout). */
.three-steps {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: var(--s-9);
  align-items: start;
}
.three-steps-header { position: sticky; top: 96px; }

@media (max-width: 720px) {
  .three-steps {
    grid-template-columns: 1fr;
    gap: var(--s-6);
  }
  .three-steps-header {
    position: static;
    /* Add a visual divider so the heading reads as a section header
       above the steps instead of crowding them. */
    padding-bottom: var(--s-3);
  }
}

/* ── Pricing-examples marquee ──────────────────────────────────────────
   Desktop renders the 4 example pounds as a static 4-up grid. Mobile
   converts the same markup to a horizontal auto-scrolling marquee so
   the section doesn't eat 4 full screens of vertical space. The HTML
   includes 4 duplicate cards (aria-hidden) that only show on mobile to
   make the loop seamless. */
.price-marquee {
  margin-top: var(--s-8);
  padding-top: var(--s-6);
  border-top: 1px solid var(--dark-hairline);
}
.price-track {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5);
}
/* Hide the duplicates on desktop — they only exist to seam-loop the marquee. */
.price-track > [aria-hidden="true"] { display: none; }

@media (max-width: 720px) {
  .price-marquee {
    overflow: hidden;
    /* Soft fade at both edges so cards appear to slide in/out instead
       of hard-clipping at the viewport edge. mask works in all evergreen
       browsers via the -webkit- prefix on Safari. */
    -webkit-mask-image: linear-gradient(
      90deg,
      transparent 0,
      #000 28px,
      #000 calc(100% - 28px),
      transparent 100%
    );
            mask-image: linear-gradient(
      90deg,
      transparent 0,
      #000 28px,
      #000 calc(100% - 28px),
      transparent 100%
    );
  }
  .price-track {
    display: flex;
    grid-template-columns: none;
    gap: 0;
    width: max-content;
    animation: price-marquee 28s linear infinite;
  }
  /* Show duplicates so the loop seams correctly. */
  .price-track > [aria-hidden="true"] { display: block; }
  .price-track > div {
    flex: 0 0 200px;
    margin-right: var(--s-5);
  }
}
@keyframes price-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* ── FAQ accordions ────────────────────────────────────────────────────
   Stack of <details> elements styled to match the rest of the site.
   Native expand/collapse — no JS, no scroll layout shift on toggle. */
.faq-item {
  border-top: 1px solid var(--hairline);
  padding: var(--s-4) 0;
}
.faq-item:last-child { border-bottom: 1px solid var(--hairline); }
.faq-item > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(16px, 1.2vw + 8px, 19px);
  letter-spacing: -0.018em;
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}
.faq-item > summary::-webkit-details-marker { display: none; }
/* Chevron — flips when the item is open. */
.faq-item > summary::after {
  content: "+";
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 24px;
  line-height: 1;
  color: var(--ink-muted);
  transition: transform 0.2s ease, color 0.2s ease;
}
.faq-item[open] > summary::after {
  content: "−";
  color: var(--ink);
}
.faq-body {
  margin-top: var(--s-3);
  color: var(--ink-soft);
  line-height: 1.65;
  font-size: 15px;
}

/* ── Admin command-center dashboard ────────────────────────────────────
   Compact card grid sitting above the orders table. Queue tiles are
   clickable: clicking one sets the status filter and scrolls to the
   orders table. Money tiles are display-only. Activity is a tight feed
   of the latest order_events. */
.dash-section { margin: 16px 0; }
.dash-section-title {
  font: 600 11px/1.4 var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.10em;
  color: var(--ink-muted);
  margin: 0 0 8px;
}
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
}
.dash-tile {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-2);
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 4px;
  min-height: 72px;
  transition: border-color 0.15s, transform 0.05s;
}
.dash-tile.clickable { cursor: pointer; }
.dash-tile.clickable:hover { border-color: var(--accent); }
.dash-tile.clickable:active { transform: translateY(1px); }
.dash-tile.alert { border-color: #d4361b; background: #fff5f3; }
.dash-tile.alert .v { color: #c13017; }
.dash-tile .k {
  font: 600 11px/1.4 var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-muted);
}
.dash-tile .v {
  font-family: var(--font-display);
  font-size: 26px; font-weight: 700;
  letter-spacing: -0.02em; line-height: 1.1;
}
.dash-tile .sub {
  font-size: 12px; color: var(--ink-muted);
  margin-top: 2px;
}
.activity { list-style: none; padding: 0; margin: 0; }
.activity li {
  display: grid;
  /* The kind column was 70px — too narrow for QUOTE_FINALIZED, which
     overflowed and ran on top of the desc cell because grid items default
     to min-width:auto (won't shrink below content). Widened the column to
     fit the longest kind plus buffer; also clip + ellipsis-truncate any
     future longer name so we never bleed across cells again. */
  grid-template-columns: 90px 130px 1fr 110px;
  gap: 12px; align-items: center;
  padding: 8px 4px;
  border-top: 1px solid var(--hairline);
  font-size: 13px;
}
.activity li > * { min-width: 0; }
.activity li:first-child { border-top: 0; }
.activity .ref { font-family: var(--font-mono); font-size: 12px; }
.activity .kind {
  font: 600 10px/1 var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.activity .desc { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.activity .ts { color: var(--ink-muted); font-size: 12px; text-align: right; }

/* ── Card surface (admin login + modal + dashboard wrappers) ───────────
   Was missing from the global stylesheet, which is why the admin detail
   modal rendered transparent and the underlying page bled through.
   Plain white surface + hairline + tiny shadow, matches the rest of
   the site's editorial-card aesthetic. */
.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  padding: var(--s-5);
  box-shadow: var(--shadow-1);
}

/* Detail modal scrolls when content is taller than the viewport. */
#detail-modal { overflow-y: auto; }
#detail-modal .wrap-narrow { padding-bottom: 5vh; }

/* ── Admin mobile (≤720px): card-stack tables + flexible activity rows ─ */
@media (max-width: 720px) {

  /* Orders table: collapse 7-col layout into a card stack. Each row
     becomes a labeled block; column headers hide off-screen. Ref +
     status sit on the top line, customer fills the middle, flow/total
     anchor the bottom. */
  table.orders, table.orders thead, table.orders tbody,
  table.orders tr, table.orders th, table.orders td {
    display: block;
  }
  table.orders thead {
    position: absolute;
    left: -9999px;
    top: -9999px;
  }
  table.orders tr {
    border: 1px solid var(--hairline);
    border-radius: var(--r-2);
    padding: 10px 12px;
    margin: 8px 0;
    background: var(--surface);
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 4px 12px;
    align-items: center;
  }
  table.orders tr:hover td { background: transparent; }
  table.orders td {
    border: 0;
    padding: 0;
    font-size: 13px;
  }
  /* Cell order: ref · created · customer · flow · total · status · arrow */
  table.orders td:nth-child(1) { /* ref */
    grid-column: 1; grid-row: 1;
    font-weight: 600;
  }
  table.orders td:nth-child(2) { /* created */
    grid-column: 2; grid-row: 1;
    text-align: right; font-size: 11px;
  }
  table.orders td:nth-child(3) { /* customer */
    grid-column: 1 / -1; grid-row: 2;
    padding: 4px 0;
  }
  table.orders td:nth-child(4) { /* flow */
    grid-column: 1; grid-row: 3;
    font-size: 12px; color: var(--ink-muted);
  }
  table.orders td:nth-child(5) { /* total */
    grid-column: 1; grid-row: 3;
    justify-self: end;
    font-weight: 600;
  }
  table.orders td:nth-child(6) { /* status */
    grid-column: 1 / -1; grid-row: 4;
    padding-top: 4px;
  }
  table.orders td:nth-child(7) { /* arrow */
    display: none;
  }

  /* Activity rows: stop forcing fixed 90+70+1fr+110 columns. Stack ref+kind
     on row 1, description on row 2, timestamp aligns right next to ref. */
  .activity li {
    grid-template-columns: auto auto 1fr;
    grid-template-areas:
      "ref kind ts"
      "desc desc desc";
    gap: 4px 10px;
    padding: 10px 4px;
  }
  .activity .ref { grid-area: ref; }
  .activity .kind { grid-area: kind; }
  .activity .ts { grid-area: ts; text-align: right; }
  .activity .desc { grid-area: desc; }

  /* Activity modal: tighten outer padding so the card uses full width. */
  #activity-modal { padding: 16px 8px !important; }
  #activity-modal .card { padding: var(--s-4); }

  /* Detail modal: hug the viewport edges and use full height. */
  #detail-modal .wrap-narrow {
    margin-top: 2vh !important;
    padding-left: var(--s-3);
    padding-right: var(--s-3);
  }
  #detail-modal .card { padding: var(--s-4); }

  /* Dashboard tile grid: smaller min-width so 2 tiles fit per row. */
  .dash-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
  .dash-tile .v { font-size: 22px; }

  /* Filter forms on admin: ensure inputs span full width when wrapping. */
  #filter-form .field,
  #activity-modal .field { flex: 1 1 100%; min-width: 0 !important; }

  /* Admin main wrap: tighter padding so cards have breathing room. */
  main.wrap { padding-left: var(--s-3); padding-right: var(--s-3); }
}
