
  
  
  :root {
    color-scheme: dark;
    --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --mono: "SF Mono", ui-monospace, "JetBrains Mono", "Roboto Mono", Menlo, Consolas, monospace;
    --display: 'LSCond', Oswald, "Arial Narrow", "Segoe UI", sans-serif;
    /* Numbers only — lap times, deltas, prices. Never prose: --mono keeps
       the spec-sheet voice for the comparison table and legal lines. */
    --numeric: 'LSNum', "Roboto Condensed", ui-monospace, monospace;

    --bg: #12151A;
    --surface: #1B2029;
    --surface-2: #242A34;
    --surface-3: #2E3540;
    --ink: #EEF1F6;
    --muted: #8A93A8;
    --line: rgba(238,241,246,.09);
    --line-strong: rgba(238,241,246,.18);
    --accent: #38BDF8;
    --accent-ink: #062033;
    --energy: #F97316;
    --energy-ink: #221000;
    --good: #35C97C;
    --warn: #F5B942;
    --bad: #FF5B5B;
    --sp1: #38BDF8; --sp2: #35C97C; --sp3: #F5B942; --sp4: #FF5B5B;
    --shadow: 0 1px 0 rgba(0,0,0,.5), 0 24px 60px rgba(0,0,0,.4);
    --radius: 8px;
    --radius-md: 10px;
    --radius-lg: 12px;
    /* Type ladder, shared with the app (LapperType: micro/label/body/base).
       Four steps at least 2px apart — the site previously had twelve sizes
       inside a 6px range, which reads as one flat wash rather than a
       hierarchy. Display sizes stay on clamp() below. */
    --fs-micro: 11px;   /* uppercase meta: eyebrows, table heads, badges */
    --fs-label: 13px;   /* buttons, dense UI text */
    --fs-body:  15px;   /* card copy, lists, prose */
    --fs-base:  17px;   /* body */
    /* One tracking value for every uppercase label. Negative tracking on
       display sizes (h1/h2/.price) is an optical correction and stays. */
    --track-caps: .08em;
    --maxw: 1200px;
    /* Brand logo — LAPPER flips with the theme; track + SNAPPER cyan and the
       orange start dot stay constant */
    --logo-lapper:#e6ebf2;
  }
  html:lang(th) {
    --sans: 'LSThai', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --display: 'LSThai', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --track-caps: 0;
  }
  @media (prefers-color-scheme: light) {
    :root {
      color-scheme: light;
      --bg: #E0E0E0;
      --surface: #FFFFFF;
      --surface-2: #E9EDF5;
      --surface-3: #DCE2ED;
      --ink: #12151A;
      --muted: #4B5364;
      --line: rgba(18,21,26,.10);
      --line-strong: rgba(18,21,26,.20);
      --accent: #075985;
      --accent-ink: #FFFFFF;
      --energy: #B03B0B;
      --energy-ink: #FFFFFF;
      --good: #0B7141;
      --warn: #8A5200;
      --bad: #B4352A;
      --sp1: #075985; --sp2: #0B7141; --sp3: #8A5200; --sp4: #B4352A;
      --shadow: 0 1px 0 rgba(18,21,26,.05), 0 20px 50px rgba(18,21,26,.08);
      --logo-lapper:#333333;
    }
  }
  :root[data-theme="dark"] {
    color-scheme: dark;
    --bg:#12151A; --surface:#1B2029; --surface-2:#242A34; --surface-3:#2E3540;
    --ink:#EEF1F6; --muted:#8A93A8;
    --line:rgba(238,241,246,.09); --line-strong:rgba(238,241,246,.18);
    --accent:#38BDF8; --accent-ink:#062033; --energy:#F97316; --energy-ink:#221000;
    --good:#35C97C; --warn:#F5B942; --bad:#FF5B5B;
    --sp1:#38BDF8; --sp2:#35C97C; --sp3:#F5B942; --sp4:#FF5B5B;
    --shadow:0 1px 0 rgba(0,0,0,.5), 0 24px 60px rgba(0,0,0,.4);
    --logo-lapper:#e6ebf2;
  }
  :root[data-theme="light"] {
    color-scheme: light;
    --bg:#E0E0E0; --surface:#FFFFFF; --surface-2:#E9EDF5; --surface-3:#DCE2ED;
    --ink:#12151A; --muted:#4B5364;
    --line:rgba(18,21,26,.10); --line-strong:rgba(18,21,26,.20);
    --accent:#075985; --accent-ink:#FFFFFF; --energy:#B03B0B; --energy-ink:#FFFFFF;
    --good:#0B7141; --warn:#8A5200; --bad:#B4352A;
    --sp1:#075985; --sp2:#0B7141; --sp3:#8A5200; --sp4:#B4352A;
    --shadow:0 1px 0 rgba(18,21,26,.05), 0 20px 50px rgba(18,21,26,.08);
    --logo-lapper:#333333;
  }

  * { box-sizing: border-box; }
  html { scroll-behavior: smooth; }
  body {
    margin: 0; background: var(--bg); color: var(--ink);
    font-family: var(--sans); font-size: var(--fs-base); line-height: 1.6;
    -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  }
  @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

  .wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }
  .mono { font-family: var(--mono); }
  .eyebrow {
    font-family: var(--display); font-size: var(--fs-micro); letter-spacing: var(--track-caps);
    text-transform: uppercase; color: var(--accent); font-weight: 600;
  }
  /* Start-dot motif, echoing the logo's orange start dot. Orange (--energy) is
     deliberately scarce: this dot and the hero delta chip are the only places it
     appears. It is never an interactive color — interactive stays cyan. */
  .eyebrow::before {
    content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
    background: var(--energy); margin-right: 9px; vertical-align: 1px;
  }
  h1, h2, h3 { text-wrap: balance; line-height: 1.08; margin: 0; letter-spacing: -.01em; font-weight: 600;
    font-family: var(--display); }
  h1 { font-size: clamp(44px, 9vw, 96px); line-height: 1.04; letter-spacing: -.015em; }
  h2 { font-size: clamp(36px, 4.5vw, 56px); }
  h3 { font-size: 1.24rem; letter-spacing: 0; font-weight: 600; }
  p { margin: 0; }
  a { color: inherit; }
  .lead { font-size: clamp(1.05rem, 1.7vw, 1.28rem); color: var(--muted); max-width: 60ch; font-family: var(--sans); }
  .muted { color: var(--muted); }
  :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

  /* ---- header ---- */
  header {
    position: sticky; top: 0; z-index: 50;
    backdrop-filter: saturate(1.4) blur(12px);
    background: color-mix(in srgb, var(--bg) 84%, transparent);
    border-bottom: 1px solid var(--line);
  }
  .nav { display: flex; align-items: center; gap: 22px; height: 96px; }
  .brand { display: flex; align-items: center; gap: 10px; font-family: var(--display); font-weight: 700;
    letter-spacing: var(--track-caps); text-transform: uppercase; font-size: var(--fs-body); text-decoration: none; cursor: pointer; white-space: nowrap; }
  .brand .tick { width: 26px; height: 14px; border-radius: 2px; overflow: hidden; display: inline-flex; }
  .brand .tick i { flex: 1; }
  .brand .logo { height: 44px; width: auto; display: block; }
  /* Width-driven, not a fixed height: in the 1fr 1fr mobile footer grid a fixed
     30px height pins the intrinsic 229.5px width and overflows a 320px viewport.
     min(230px, 100%) keeps the desktop size and shrinks with the column. */
  .foot .brand .logo { width: min(230px, 100%); height: auto; }
  .logo .logo-lapper { fill: var(--logo-lapper); }
  .nav-links { display: flex; gap: 22px; margin-left: 8px; }
  .nav-links a {
    font-family: var(--display); font-size: var(--fs-label); letter-spacing: var(--track-caps); text-transform: uppercase; font-weight: 600;
    text-decoration: none; color: var(--muted); cursor: pointer; padding: 6px 0; border-bottom: 2px solid transparent;
    /* A two-line nav item reads as a broken menu, and the underline lands under half
       the label. Bulgarian's "За нас" wrapped at every desktop width, up to 1600px. */
    white-space: nowrap;
  }
  .nav-links a:hover { color: var(--ink); }
  .nav-links a.mobile-cta { display: none; }
  /* Menu-only nav items. Support lives here: the desktop row is capped at
     --maxw and cannot fit a sixth link (see the header comment below), but
     there is room to spare once the row collapses into the menu, and the
     link is worth keeping where people look for it. Same mechanism as
     .mobile-cta above, without the CTA's weight and accent colour. */
  .nav-links a.mobile-only { display: none; }
  .nav-links a.active { color: var(--ink); border-bottom-color: var(--accent); }
  .nav-spacer { flex: 1; }

  /* The header row cannot wrap and cannot scroll — .wrap caps it at --maxw, so above
     the menu-button breakpoint it has to fit its own content at every width. It did
     not: measured across the seven locales, the "Get the app" CTA hung off the right
     edge (and took page-level horizontal scroll with it) anywhere below 1020px in
     English and below 1200px in Bulgarian. The gaps and the 337px brand lockup
     therefore compress with the viewport. Scoped to the desktop row: below the
     breakpoint the links are gone, there is room to spare, and the lockup keeps its
     full size. */
  @media (min-width: 1101px) {
    .nav, .nav-links { gap: clamp(14px, 1.6vw, 22px); }
    header .brand .logo { height: clamp(34px, 3.1vw, 44px); }
  }
  .icon-btn { background: none; border: 1px solid var(--line); color: var(--ink); width: 44px; height: 44px;
    border-radius: var(--radius); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-body); }
  .icon-btn:hover { border-color: var(--line-strong); }

  /* Language switcher. One instance, beside the theme toggle, at every breakpoint —
     CSS cannot reparent a <details> into the mobile menu, and moving it with JS would
     break the disclosure's zero-JS promise. */
  .langswitch { position: relative; }
  .langswitch > summary { list-style: none; cursor: pointer; width: auto; padding: 0 10px; gap: 6px; }
  .langswitch > summary::-webkit-details-marker { display: none; }
  .langswitch .flag { width: 16px; height: 12px; border-radius: 2px; box-shadow: 0 0 0 1px var(--line); }
  .langswitch .globe { width: 16px; height: 16px; color: var(--muted); }
  .langswitch nav { position: absolute; right: 0; top: calc(100% + 8px); background: var(--bg);
    border: 1px solid var(--line); border-radius: var(--radius); padding: 6px; min-width: 168px; z-index: 30; }
  .langswitch ul { list-style: none; margin: 0; padding: 0; }
  .langswitch a { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
    border-radius: var(--radius); font-size: var(--fs-label); text-decoration: none; color: inherit; white-space: nowrap; }
  .langswitch a:hover { background: var(--line); }
  .langswitch a[aria-current] { font-weight: 700; }
  /* At the narrowest widths only the icon shows — which is why aria-label carries the
     meaning on the <summary>. */
  @media (max-width: 420px) { .langswitch > summary span { display: none; } }
  .btn {
    font-family: var(--display); font-size: var(--fs-label); letter-spacing: var(--track-caps); text-transform: uppercase; font-weight: 700;
    padding: 11px 18px; border-radius: var(--radius); border: 1px solid transparent; cursor: pointer; text-decoration: none;
    display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; transition: transform .08s ease, background .15s ease;
  }
  .btn:active { transform: translateY(1px); }
  /* Shown only above the layout breakpoint. Used by the "try it in your browser"
     CTA: on a phone the native app is strictly better AND one tap away in the
     store badge beside it, so offering the web build there would send a visitor
     to the worse of the two experiences. Not `visibility` — the link must be out
     of the tab order and out of the accessibility tree on mobile, not merely
     invisible. */
  @media (max-width: 900px) { a.btn.desktop-only { display: none; } }
  .btn-primary { background: var(--accent); color: var(--accent-ink); }
  .btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, #000); }
  .btn-ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
  .btn-ghost:hover { background: var(--surface-2); }
  .btn-lg { padding: 14px 24px; font-size: var(--fs-body); }
  .menu-btn { display: none; }

  /* ---- generic sections ---- */
  main { display: block; }
  /* There is no router and no stacking anymore — one page per document, and the build
     stamps it .active before writing the file, so .page.active (same specificity,
     declared next) always wins here. Kept as the .js-gated default every other
     pre-hidden state uses, in case that ever stops being true. */
  .js .page { display: none; }
  .page.active { display: block; animation: fade .3s ease; }
  @keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
  @media (prefers-reduced-motion: reduce) { .page.active { animation: none; } }
  section.band { padding: 84px 0; border-top: 1px solid var(--line); }
  section.band:first-child { border-top: none; }
  /* The answer and final-CTA bands sit a step above the page: a whisper of surface
     tint and more air. Restrained on purpose — the palette stays untouched. */
  section.band.elevated { background: color-mix(in srgb, var(--surface) 55%, var(--bg)); padding: 100px 0; }
  .center { text-align: center; }
  /* .btn's display:inline-flex would otherwise beat the UA's [hidden] rule. */
  [hidden] { display: none !important; }
  .stack-sm > * + * { margin-top: 14px; }
  .cta-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
  .cta-row.center { justify-content: center; }

  /* ---- hero ---- */
  .hero {
    position: relative; overflow: hidden; padding: 56px 0 88px; border-top: none;
    background:
      radial-gradient(680px 380px at 8% -10%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 65%),
      radial-gradient(620px 360px at 106% 106%, color-mix(in srgb, var(--energy) 14%, transparent), transparent 65%);
  }
  /* ---- photographic bands ----
     One treatment for every photo on the site, so the imagery reads as a set.
     A decorative plate fills the band; the section's own background doubles as
     the paint-before-load fallback. Every scrim mixes from var(--bg), which is
     what lets a single implementation grade correctly in both themes, and every
     one lands on solid var(--bg) at the bottom edge so the band blends into the
     page rather than ending on a hard seam. Each band then tunes its own
     gradient to suit how its copy is laid out. */
  .photo-bg { position: absolute; inset: 0; }
  .photo-bg img { width: 100%; height: 100%; object-fit: cover; }
  .photo-bg::after { content: ""; position: absolute; inset: 0; }
  /* Bands that carry a plate — or the schematic grid below — need to contain it and
     stack their copy above it. */
  .band.has-photo, .band.schematic { position: relative; overflow: hidden; }
  .band.has-photo > .wrap, .band.schematic > .wrap { position: relative; z-index: 1; }

  /* The privacy band is the only major section with no plate, and it should stay that
     way: a photograph behind a data-residency table would undercut a claim that is
     technical rather than emotional. But it sits between two plain bands on the same
     --bg, so three sections run flat through the middle of the page. It gets tone plus
     a faint schematic grid instead — its own eyebrow reads "Private by architecture"
     and its right column is already a mono diagram, so graph paper is the substrate the
     content implies. Pure CSS, so it adds no bytes and leaves photography special. The
     mask fades the grid out before the edges so it never reads as a hard-edged box. */
  .band.schematic { background: color-mix(in srgb, var(--surface) 62%, var(--bg)); }
  .band.schematic::before {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background:
      repeating-linear-gradient(90deg, var(--line) 0 1px, transparent 1px 56px),
      repeating-linear-gradient(180deg, var(--line) 0 1px, transparent 1px 56px);
    -webkit-mask-image: radial-gradient(125% 105% at 50% 50%, #000 35%, transparent 86%);
    mask-image: radial-gradient(125% 105% at 50% 50%, #000 35%, transparent 86%);
  }

  /* Hero: copy is left-aligned, so the veil is heaviest over the headline column
     and clears toward the top-right where the peaks sit. The art is far wider
     than the hero box, so cover scales it by height and trims the sides; biasing
     X past centre keeps those peaks behind the phone rather than losing them to
     that trim. Under 900px the copy spans the full width, so the veil evens out. */
  .hero-bg img { object-position: 64% 50%; }
  /* The two washes stack, so their effective opacity multiplies: the dark-theme values
     below come to ~77% over the headline column, which is why a light theme frosted the
     art over. The stops are named so a light theme can restate the five numbers rather
     than the whole gradient — light copy on this plate is all --ink or the darkened
     eyebrow, which leaves plenty of contrast headroom to spend on showing the photo. */
  .hero-bg::after {
    --v1: 62%; --v2: 28%; --v3: 10%;
    --w1: 32%; --w2: 52%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--v1), transparent), color-mix(in srgb, var(--bg) var(--v2), transparent) 62%, color-mix(in srgb, var(--bg) var(--v3), transparent)),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) var(--w1), transparent), color-mix(in srgb, var(--bg) var(--w2), transparent) 55%, var(--bg) 98%);
  }
  @media (prefers-color-scheme: light) { .hero-bg::after { --v1: 34%; --v2: 12%; --v3: 2%; --w1: 8%; --w2: 16%; } }
  :root[data-theme="light"] .hero-bg::after { --v1: 34%; --v2: 12%; --v3: 2%; --w1: 8%; --w2: 16%; }
  :root[data-theme="dark"] .hero-bg::after { --v1: 62%; --v2: 28%; --v3: 10%; --w1: 32%; --w2: 52%; }
  @media (max-width: 900px) {
    .hero-bg::after { background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) var(--m1), transparent), color-mix(in srgb, var(--bg) var(--m2), transparent) 55%, var(--bg) 98%);
      --m1: 64%; --m2: 76%;
    }
    /* Mobile cannot take the desktop lightening: at this crop the eyebrow lands on
       shadowed trees, and measured there 48% left it at 2.98:1. 66% is the floor. */
    @media (prefers-color-scheme: light) { .hero-bg::after { --m1: 54%; --m2: 60%; } }
    :root[data-theme="light"] .hero-bg::after { --m1: 54%; --m2: 60%; }
    :root[data-theme="dark"] .hero-bg::after { --m1: 64%; --m2: 76%; }
  }
  /* Answer band: copy is left-aligned like the hero's, so the veil is heaviest
     there and thins toward the windscreen on the right. It needs to be stronger
     than the hero's, because this plate's bright centre (sky and sunlit trees)
     sits directly behind the copy rather than beside it. Narrow screens drop the
     horizontal weighting — cover zooms in far enough that the copy can land on
     any part of the frame, so the veil has to be even and much deeper. */
  .answer-bg img { object-position: 50% 46%; }
  /* Same stacking, and the heaviest on the site: ~84% effective over the copy in a dark
     theme. Light themes restate the stops for the same reason as the hero. */
  .answer-bg::after {
    --v1: 74%; --v2: 42%; --v3: 24%;
    --w1: 34%; --w2: 52%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--v1), transparent), color-mix(in srgb, var(--bg) var(--v2), transparent) 60%, color-mix(in srgb, var(--bg) var(--v3), transparent)),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) var(--w1), transparent), color-mix(in srgb, var(--bg) var(--w2), transparent) 58%, var(--bg) 99%);
  }
  @media (prefers-color-scheme: light) { .answer-bg::after { --v1: 38%; --v2: 16%; --v3: 6%; --w1: 10%; --w2: 20%; } }
  :root[data-theme="light"] .answer-bg::after { --v1: 38%; --v2: 16%; --v3: 6%; --w1: 10%; --w2: 20%; }
  :root[data-theme="dark"] .answer-bg::after { --v1: 74%; --v2: 42%; --v3: 24%; --w1: 34%; --w2: 52%; }
  @media (max-width: 900px) {
    .answer-bg::after { background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) var(--m1), transparent), color-mix(in srgb, var(--bg) var(--m2), transparent) 55%, var(--bg) 99%);
      --m1: 80%; --m2: 87%;
    }
    @media (prefers-color-scheme: light) { .answer-bg::after { --m1: 46%; --m2: 58%; } }
    :root[data-theme="light"] .answer-bg::after { --m1: 46%; --m2: 58%; }
    :root[data-theme="dark"] .answer-bg::after { --m1: 80%; --m2: 87%; }
  }
  /* Chapters: ONE plate spans all four chapters, so scrolling the run follows a
     single unbroken ribbon of track. The continuity is structural — the four
     chapters already share a parent band — so this needs no scroll effect and no
     background-attachment: fixed, which janks on iOS. Copy alternates left and
     right from chapter to chapter, so the veil cannot favour either side: it
     stays even across the width and fades to solid --bg at the top and bottom
     edges so the run joins its neighbouring bands seamlessly. The plate is
     already near-monochrome, so a mid-strength veil is enough to keep it quiet
     while still letting the asphalt read behind the copy. */
  /* --veil has to be theme-aware here, unlike the other two plates. This one is a
     DARK photograph, so a light theme mixes it toward --bg and lifts it *toward*
     the ink colour instead of away from it. Measured against the plate's darkest
     pixels: at 60% the 12px accent eyebrow falls to 2.3:1, and only ~88% brings it
     back over the 4.5:1 floor. Dark themes are insensitive to the value (16:1 ink,
     8.5:1 eyebrow at any strength), so they keep the asphalt fully present. */
  .chapters-bg::after {
    --veil: 60%;
    background:
      linear-gradient(180deg, var(--bg), color-mix(in srgb, var(--bg) var(--veil), transparent) 5%, color-mix(in srgb, var(--bg) var(--veil), transparent) 95%, var(--bg));
  }
  /* This is the one plate delivered as a CSS background rather than a <picture>,
     because it is the one plate that must not reach phones at all. Below 900px the
     chapters stack, taking the band to ~11x taller than wide; cover then zooms ~5x
     into a narrow centre strip, the ribbon leaves the frame and only flat tone is
     left. Hiding an <img> does not stop the download — measured, Chrome still
     transferred the full 70KB with the wrapper at display:none — whereas a
     background-image whose URL is only ever declared above the breakpoint cannot
     be fetched below it. image-set() keeps the AVIF/JPEG choice and the 1x/1.5x
     step that srcset was giving us. */
  .chapters-bg { background-position: 50% 50%; background-size: cover; background-repeat: no-repeat; }
  @media (min-width: 901px) {
    .chapters-bg {
      background-image: image-set(
        url("/img/chapters-aerial-1408.avif") type("image/avif") 1x,
        url("/img/chapters-aerial-2112.avif") type("image/avif") 1.5x,
        url("/img/chapters-aerial-1408.jpg") type("image/jpeg") 1x);
    }
  }
  @media (prefers-color-scheme: light) { .chapters-bg::after { --veil: 55%; } }
  :root[data-theme="light"] .chapters-bg::after { --veil: 55%; }
  :root[data-theme="dark"] .chapters-bg::after { --veil: 60%; }

  /* Pricing: the plate is a banner across the TOP of the band, not the whole of it.
     The plan cards below are opaque --surface panels, so any image behind them would
     be paid for and never seen; the veil lands on solid --bg before they begin. Like
     the chapters plate this one is a dark photograph, so its veil is theme-aware for
     the same measured reason: against its darkest pixels the 12px accent eyebrow needs
     ~88% in a light theme to clear 4.5:1, while dark themes are fine at 58%. */
  .pricing-bg { bottom: auto; height: 920px; }
  .pricing-bg img { object-position: 50% 58%; }
  .pricing-bg::after {
    --veil: 58%;
    background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) var(--veil), transparent), color-mix(in srgb, var(--bg) calc(var(--veil) + 12%), transparent) 55%, var(--bg) 97%);
  }
  @media (prefers-color-scheme: light) { .pricing-bg::after { --veil: 55%; } }
  :root[data-theme="light"] .pricing-bg::after { --veil: 55%; }
  :root[data-theme="dark"] .pricing-bg::after { --veil: 58%; }
  @media (max-width: 900px) { .pricing-bg { height: 860px; } }

  /* --muted copy measures only ~4.5:1 against a bare light --bg, so ANY plate behind
     it drops it under the floor: measured, the hero lead lands at 3.7:1 and the
     answer lead at 3.2:1. Light themes therefore promote copy that sits on a plate
     to --ink, which measures 10:1 or better over the same veiled pixels. Dark themes
     need no change — --muted over a veiled plate still measures ~6:1 there — so the
     hierarchy they were designed with is left exactly as it is. */
  @media (prefers-color-scheme: light) {
    .hero .lead, .hero .qualify, .band.has-photo .lead { color: var(--ink); }
  }
  :root[data-theme="light"] .hero .lead,
  :root[data-theme="light"] .hero .qualify,
  :root[data-theme="light"] .band.has-photo .lead { color: var(--ink); }
  :root[data-theme="dark"] .hero .lead,
  :root[data-theme="dark"] .hero .qualify,
  :root[data-theme="dark"] .band.has-photo .lead { color: var(--muted); }

  /* Teaser: a wide, short banner. Copy sits in the left 45%, so the veil is heaviest
     there and clears toward the karts right of centre — the hero's arrangement. The
     plate needs no vertical fade to --bg because the band is short enough that the
     horizontal wash already carries it. */
  .teaser-bg::after {
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) 78%, transparent), color-mix(in srgb, var(--bg) 46%, transparent) 58%, color-mix(in srgb, var(--bg) 22%, transparent)),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) 30%, transparent), color-mix(in srgb, var(--bg) 44%, transparent) 70%, color-mix(in srgb, var(--bg) 68%, transparent));
  }
  @media (prefers-color-scheme: light) {
    .teaser-bg::after { background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) 58%, transparent), color-mix(in srgb, var(--bg) 30%, transparent) 58%, color-mix(in srgb, var(--bg) 12%, transparent)),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) 18%, transparent), color-mix(in srgb, var(--bg) 28%, transparent) 70%, color-mix(in srgb, var(--bg) 50%, transparent));
    }
  }
  :root[data-theme="light"] .teaser-bg::after { background:
    linear-gradient(90deg, color-mix(in srgb, var(--bg) 58%, transparent), color-mix(in srgb, var(--bg) 30%, transparent) 58%, color-mix(in srgb, var(--bg) 12%, transparent)),
    linear-gradient(180deg, color-mix(in srgb, var(--bg) 18%, transparent), color-mix(in srgb, var(--bg) 28%, transparent) 70%, color-mix(in srgb, var(--bg) 50%, transparent));
  }
  @media (max-width: 900px) {
    .teaser-bg::after { background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) 78%, transparent), color-mix(in srgb, var(--bg) 86%, transparent) 60%, var(--bg) 99%);
    }
    @media (prefers-color-scheme: light) {
      .teaser-bg::after { background:
        linear-gradient(180deg, color-mix(in srgb, var(--bg) 52%, transparent), color-mix(in srgb, var(--bg) 62%, transparent) 60%, var(--bg) 99%);
      }
    }
    :root[data-theme="light"] .teaser-bg::after { background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) 52%, transparent), color-mix(in srgb, var(--bg) 62%, transparent) 60%, var(--bg) 99%);
    }
  }

  /* About: atmosphere behind a page of reading, not a picture — and since the copy
     took the band's normal left gutter (see .about-copy) it now needs the same
     side-weighted layer Guides uses, heaviest over the left column and clear of the
     two mechanics right of centre. The eyebrow is what sets the strength: an 11px
     label sits at the top of the column, over the plate's brightest region, and
     measured against the composited pixels --accent landed at 2.9:1 there on the
     vertical veil alone. Light passes without it, so its side layer stays light and
     the plate survives. */
  .about-bg img { object-position: 50% 42%; }
  .about-bg::after {
    --veil: 74%;
    --side: 78%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 55%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 8%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 45%, color-mix(in srgb, var(--bg) calc(var(--veil) + 10%), transparent) 88%, var(--bg));
  }
  @media (prefers-color-scheme: light) { .about-bg::after { --veil: 58%; --side: 28%; } }
  :root[data-theme="light"] .about-bg::after { --veil: 58%; --side: 28%; }
  :root[data-theme="dark"] .about-bg::after { --veil: 74%; --side: 78%; }

  /* Guides: same job as About — atmosphere behind a page of reading, not a picture.
     The plate's one bright region (the low sun, upper-left) sits directly behind the
     copy column, so on top of the even vertical veil this band borrows the hero's
     side-weighted layer: heaviest over the left column, clear of the kart right of
     centre. Dark needs it at full strength (measured: the eyebrow landed at 3.1:1
     against the haze without it); light passes on the vertical veil alone, so its
     side layer is kept light to preserve the plate. Cards are opaque --surface. */
  .guides-bg img { object-position: 50% 40%; }
  .guides-bg::after {
    --veil: 74%;
    --side: 78%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 55%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 45%, color-mix(in srgb, var(--bg) calc(var(--veil) + 12%), transparent) 88%, var(--bg));
  }
  @media (prefers-color-scheme: light) { .guides-bg::after { --veil: 60%; --side: 28%; } }
  :root[data-theme="light"] .guides-bg::after { --veil: 60%; --side: 28%; }
  :root[data-theme="dark"] .guides-bg::after { --veil: 74%; --side: 78%; }

  /* Teams: the paddock plate is backlit, so its brightest area — blown-out haze and
     low sun above the awning — runs across the whole upper band, which is exactly
     where the headline and lead sit. Same shape of problem as Guides above, so it
     takes the same answer: an even vertical veil plus a side-weighted layer heaviest
     over the left copy column and clear of the karts right of centre.

     Unlike .pricing-bg this plate is deliberately NOT given a fixed height. The band
     carries a device lockup under the copy, so the obvious move is to stop the photo
     above it — but the gap between "copy ends" and "devices start" lands in a
     different place at every width (measured 2026-08-28: 596-636px at 1280, 523-563
     at 900, 593-633 at 390) and there is no single height inside all three. Worse,
     the headline wraps to different depths in eight locales, so any height tuned on
     English cuts mid-headline in German or Bulgarian. The plate therefore runs the
     full band and the veil closes to solid --bg at 92%, which puts the devices over
     the darkest, quietest part of the photograph rather than over a hard edge. */
  .teams-bg img { object-position: 50% 46%; }
  .teams-bg::after {
    --veil: 74%;
    --side: 78%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 55%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 42%, color-mix(in srgb, var(--bg) calc(var(--veil) + 14%), transparent) 74%, var(--bg) 92%);
  }
  @media (prefers-color-scheme: light) { .teams-bg::after { --veil: 60%; --side: 28%; } }
  :root[data-theme="light"] .teams-bg::after { --veil: 60%; --side: 28%; }
  :root[data-theme="dark"] .teams-bg::after { --veil: 74%; --side: 78%; }

  /* Teams / profile band: the third plate on that page, and deliberately a different
     register from the first — an 85mm two-shot at f/2 rather than a 35mm establishing
     wide, so the page does not read as two versions of the same paddock. Its tonal
     problem is the inverse of .teams-bg's: the copy column sits over the DARK half
     (shaded tyre stacks and the driver's back) while the blown highlights are far
     right, behind nothing. So the side-weighted layer is dropped — it would only
     darken what is already dark — and light mode instead carries a HEAVIER flat veil
     than any other band, because .plate-copy promotes this copy to near-black --ink
     and near-black over unlifted shadow is the one combination that fails. Measured
     both ways rather than reasoned. */
  .profile-bg img { object-position: 50% 40%; }
  .profile-bg::after {
    --veil: 66%;
    background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 45%, color-mix(in srgb, var(--bg) calc(var(--veil) + 16%), transparent) 78%, var(--bg) 95%);
  }
  @media (prefers-color-scheme: light) { .profile-bg::after { --veil: 64%; } }
  :root[data-theme="light"] .profile-bg::after { --veil: 64%; }
  :root[data-theme="dark"] .profile-bg::after { --veil: 66%; }

  /* Teams / Garage band: the fourth plate, placed immediately after the roles because
     the permissions explain who can act before this section explains what they manage.
     The generated workshop frame does the compositional work: quiet shadow and tools
     sit under the left-aligned heading, while the modern kart and mechanic occupy the
     right half. Cards stay opaque, so the plate can remain visible between them without
     asking body copy to fight mechanical detail. The vertical veil closes to --bg at
     the lower edge, keeping the stacked mobile cards readable after cover crops tightly
     around the engine. */
  .garage-bg img { object-position: 56% 50%; }
  .garage-bg::after {
    --veil: 68%;
    --side: 76%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 62%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 8%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 46%, color-mix(in srgb, var(--bg) calc(var(--veil) + 18%), transparent) 82%, var(--bg) 97%);
  }
  @media (prefers-color-scheme: light) { .garage-bg::after { --veil: 64%; --side: 32%; } }
  :root[data-theme="light"] .garage-bg::after { --veil: 64%; --side: 32%; }
  :root[data-theme="dark"] .garage-bg::after { --veil: 68%; --side: 76%; }

  /* Personal Garage hero: one kart and one pair of hands, rather than the fleet-scale
     scene used for Teams. The plate's left third is intentionally quiet workshop
     shadow for the headline; the kart, wet paddock and weather meter stay visible
     through the centre while the product capture occupies the right column. The
     bottom fade makes the tall phone feel seated in the page instead of pasted over
     a hard photographic edge. */
  .personal-garage-bg img { object-position: 54% 50%; }
  .personal-garage-bg::after {
    --veil: 68%;
    --side: 78%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 68%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 10%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 50%, color-mix(in srgb, var(--bg) calc(var(--veil) + 18%), transparent) 84%, var(--bg) 98%);
  }
  @media (prefers-color-scheme: light) { .personal-garage-bg::after { --veil: 68%; --side: 52%; } }
  :root[data-theme="light"] .personal-garage-bg::after { --veil: 68%; --side: 52%; }
  :root[data-theme="dark"] .personal-garage-bg::after { --veil: 68%; --side: 78%; }
  @media (max-width: 900px) {
    .personal-garage-bg img { object-position: 62% 50%; }
    .personal-garage-bg::after {
      background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 80%, transparent), color-mix(in srgb, var(--bg) 88%, transparent) 58%, var(--bg) 98%);
    }
    @media (prefers-color-scheme: light) {
      .personal-garage-bg::after {
        background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 72%, transparent), color-mix(in srgb, var(--bg) 82%, transparent) 58%, var(--bg) 98%);
      }
    }
    :root[data-theme="light"] .personal-garage-bg::after {
      background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 72%, transparent), color-mix(in srgb, var(--bg) 82%, transparent) 58%, var(--bg) 98%);
    }
  }

  /* Team Garage / vehicle-history band: a current kart, retired chassis and service
     parts make the section's promise tangible without turning the cards into labels
     on the photograph. The heading sits over the quiet workshop shadow at left; the
     machinery remains visible through the center and right gutters. A strong vertical
     veil gives all four cards a calm substrate and closes the photograph into --bg at
     the lower seam. Mobile keeps the current kart in frame after the cover crop. */
  .vehicle-history-bg img { object-position: 58% 50%; }
  .vehicle-history-bg::after {
    --veil: 72%;
    --side: 76%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 66%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 46%, color-mix(in srgb, var(--bg) calc(var(--veil) + 16%), transparent) 84%, var(--bg) 98%);
  }
  @media (prefers-color-scheme: light) { .vehicle-history-bg::after { --veil: 66%; --side: 42%; } }
  :root[data-theme="light"] .vehicle-history-bg::after { --veil: 66%; --side: 42%; }
  :root[data-theme="dark"] .vehicle-history-bg::after { --veil: 72%; --side: 76%; }
  @media (max-width: 620px) { .vehicle-history-bg img { object-position: 69% 50%; } }

  /* Home / Teams band: the squad walking out. Note the band DROPPED `elevated` to take
     this plate, and that is a fix rather than a side effect — inserting the Teams band
     after #engineer had put two elevated bands back to back, which flattened the
     page's tonal alternation right where a new section was trying to announce itself.
     Nearest plates are five bands up (chapters) and six down (teaser), so the home
     page's plate spacing still holds.

     The plate's bright region is the low sun dead centre, which the copy column to its
     left only clips — so this needs less veil than .teams-bg, and the side layer is
     kept modest so the walking figures do not get washed out of their own picture. */
  .squad-bg img { object-position: 50% 44%; }
  .squad-bg::after {
    --veil: 68%;
    --side: 62%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 62%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 8%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 45%, color-mix(in srgb, var(--bg) calc(var(--veil) + 16%), transparent) 80%, var(--bg) 96%);
  }
  @media (prefers-color-scheme: light) { .squad-bg::after { --veil: 62%; --side: 30%; } }
  :root[data-theme="light"] .squad-bg::after { --veil: 62%; --side: 30%; }
  :root[data-theme="dark"] .squad-bg::after { --veil: 68%; --side: 62%; }

  /* Teams / two-kinds band. Second plate on that page, so the run alternates
     plate / elevated / plate / elevated / plate rather than stacking photographs —
     but it is the densest page on the site and a fourth would be one too many.

     Its subject is a scale contrast (a small child beside an adult, both from
     behind), which is the one thing the section's heading is actually about. Note
     the master is CROPPED tighter than it was generated: at full width it read as a
     second wide backlit walk-away, too close to .squad-bg on the home page, and
     pulling in around the pair turned it back into its own picture. That was a crop,
     not a regeneration — the framing problem was mine, not the model's.

     Veil follows .teams-bg: the blown sky and track sit upper-centre behind the
     heading, so an even vertical veil carries a side-weighted layer over the left
     column and clears the pair right of centre. */
  .scale-bg img { object-position: 50% 42%; }
  .scale-bg::after {
    --veil: 72%;
    --side: 74%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 58%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 44%, color-mix(in srgb, var(--bg) calc(var(--veil) + 16%), transparent) 78%, var(--bg) 95%);
  }
  @media (prefers-color-scheme: light) { .scale-bg::after { --veil: 64%; --side: 30%; } }
  :root[data-theme="light"] .scale-bg::after { --veil: 64%; --side: 30%; }
  :root[data-theme="dark"] .scale-bg::after { --veil: 72%; --side: 74%; }

  /* Teams / pricing band. The fifth plate on this long page, kept deliberately quieter
     than Garage: a still life with no people, chosen because a price is the worst thing
     on the page to put a busy photograph behind. No two plates are adjacent; plain,
     elevated, or schematic sections continue to separate every photographic band.

     The subject carries the heading rather than decorating it — a row of identical
     helmets receding down one shelf is "fifteen drivers" and "one plan" in a single
     picture. The master is MIRRORED: the row recedes toward the awning's bright
     opening, which generated on the left, directly under the heading. Flipping put
     the deep shaded wall there instead. A still life has no handedness to break.

     The plan card is opaque --surface, so the veil only has to serve the heading and
     the muted line under the card. */
  .shelf-bg img { object-position: 50% 50%; }
  .shelf-bg::after {
    --veil: 70%;
    --side: 70%;
    background:
      linear-gradient(90deg, color-mix(in srgb, var(--bg) var(--side), transparent), transparent 60%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 42%, color-mix(in srgb, var(--bg) calc(var(--veil) + 18%), transparent) 76%, var(--bg) 94%);
  }
  @media (prefers-color-scheme: light) { .shelf-bg::after { --veil: 64%; --side: 30%; } }
  :root[data-theme="light"] .shelf-bg::after { --veil: 64%; --side: 30%; }
  :root[data-theme="dark"] .shelf-bg::after { --veil: 70%; --side: 70%; }

  /* Contact: the copy column is short and sits upper-left, and the form is an opaque
     --surface card over the right half — so the only place the plate is really seen is
     the empty lower-left quadrant. The veil is therefore weighted to the TOP, where
     the copy sits over near-black night sky, and eases off toward the bottom where the
     wet-tarmac reflections do the work. Theme-aware like the other dark plates. */
  .contact-bg img { object-position: 50% 55%; }
  .contact-bg::after {
    --veil: 58%;
    background:
      linear-gradient(180deg, color-mix(in srgb, var(--bg) calc(var(--veil) + 14%), transparent), color-mix(in srgb, var(--bg) var(--veil), transparent) 58%, color-mix(in srgb, var(--bg) calc(var(--veil) - 6%), transparent));
  }
  @media (prefers-color-scheme: light) { .contact-bg::after { --veil: 56%; } }
  :root[data-theme="light"] .contact-bg::after { --veil: 56%; }
  :root[data-theme="dark"] .contact-bg::after { --veil: 58%; }
  /* Was an inline color:var(--accent), which no rule could override — it has to be a
     class so it can darken over a plate in light themes, exactly like the eyebrow. */
  .contact-email { color: var(--accent); text-decoration: none; }

  /* The 12px accent eyebrow was what forced the light veils up to 86-88%, which read
     as too much frosting over the art. Darkening the label itself in light themes buys
     the same contrast far more cheaply: measured against a plate's darkest pixels,
     --accent needs a ~88% veil to clear 4.5:1, while this mix clears it at 70%. Only
     light themes need it — dark themes put a bright label on a dark plate and already
     measure 8:1+ — and only the label, since the surrounding copy is already --ink. */
  @media (prefers-color-scheme: light) {
    .hero .eyebrow, .band.has-photo .eyebrow, .band.has-photo .contact-email { color: color-mix(in srgb, var(--accent) 58%, #000); }
  }
  :root[data-theme="light"] .hero .eyebrow,
  :root[data-theme="light"] .band.has-photo .eyebrow,
  :root[data-theme="light"] .band.has-photo .contact-email { color: color-mix(in srgb, var(--accent) 58%, #000); }
  :root[data-theme="dark"] .hero .eyebrow,
  :root[data-theme="dark"] .band.has-photo .eyebrow,
  :root[data-theme="dark"] .band.has-photo .contact-email { color: var(--accent); }

  /* Bright plates are the exception to the rule above. The pricing plate carries
     bright specular metal and the teaser plate a sunlit left third, so --muted copy
     over either measures only ~2.5-3.7:1 even in a DARK theme, not just in light
     ones. Copy blocks marked .plate-copy therefore take --ink in both themes (8.7:1
     or better). Scoped this way so the .muted inside the opaque plan cards keeps its
     intended hierarchy; the .band.has-photo and :root[data-theme] parts are carried
     only to outrank the per-theme rules above. */
  .band.has-photo .plate-copy .lead,
  .band.has-photo .plate-copy .muted,
  :root[data-theme="light"] .band.has-photo .plate-copy .lead,
  :root[data-theme="light"] .band.has-photo .plate-copy .muted,
  :root[data-theme="dark"] .band.has-photo .plate-copy .lead,
  :root[data-theme="dark"] .band.has-photo .plate-copy .muted { color: var(--ink); }
  .hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: 48px; align-items: center; position: relative; z-index: 1; }
  .hero h1 { margin-top: 18px; }
  .hero .lead { margin-top: 20px; }
  .hero .cta-row { margin-top: 28px; }
  .qualify { margin-top: 18px; font-family: var(--display); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--muted); }
  .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

  /* ---- phone-frame figures + hero callout chips ---- */
  /* The bezel is a hardware object: near-black in both themes, drawn with padding on
     the <figure> itself so no wrapper element is needed. */
  figure.phone { margin: 0; position: relative; width: min(300px, 80vw);
    padding: 10px; border-radius: 40px; background: #171B22;
    border: 1px solid rgba(238,241,246,.16);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.07), var(--shadow); }
  figure.phone img { display: block; width: 100%; height: auto; border-radius: 30px;
    background: var(--surface); box-shadow: 0 0 0 1px rgba(0,0,0,.55); }
  figure.phone.hero-phone { margin: 0 auto; width: min(340px, 84vw); }
  figure.phone.answer-shot { margin: 40px auto 0; width: min(340px, 84vw); }
  @media (max-width: 480px) {
    figure.phone { padding: 8px; border-radius: 34px; }
    figure.phone img { border-radius: 26px; }
  }
  /* ---- tablet frame + the tablet/phone lockup ---- */
  /* Same hardware-object treatment as figure.phone, at iPad proportions. The
     bezel is proportionally thinner and the corner radius much shallower —
     reusing the phone's 40px reads as a giant phone rather than a tablet. */
  figure.tablet { margin: 0; position: relative; width: min(520px, 68vw);
    padding: 12px; border-radius: 22px; background: #171B22;
    border: 1px solid rgba(238,241,246,.16);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.07), var(--shadow); }
  figure.tablet img { display: block; width: 100%; height: auto; border-radius: 12px;
    background: var(--surface); box-shadow: 0 0 0 1px rgba(0,0,0,.55); }
  /* Held landscape. Wider than the portrait frame so the DEVICE reads as the same
     physical object turned on its side rather than a smaller tablet — at the
     portrait width a 4:3 shot renders barely 390px tall and looks like a different
     product. Shares the bezel and radius; only the width changes. */
  figure.tablet.landscape { width: min(760px, 88vw); }

  /* The two devices as one object — the coach's big screen with the paddock
     phone tucked against it. Flex with a negative margin rather than absolute
     positioning: the phone then still occupies layout, so the row cannot clip
     it at any width, and `align-items: flex-end` keeps both bezels sitting on
     one baseline however the two aspect ratios scale. */
  .device-pair { display: flex; align-items: flex-end; justify-content: center; }
  .device-pair figure.phone { width: min(150px, 20vw); margin-left: -48px;
    margin-bottom: -34px; z-index: 2; }
  @media (max-width: 700px) {
    figure.tablet { padding: 9px; border-radius: 18px; }
    figure.tablet img { border-radius: 10px; }
    .device-pair figure.phone { margin-left: -34px; margin-bottom: -8px; }
  }

  .spot-callout { position: absolute; font-family: var(--numeric);
    font-variant-numeric: tabular-nums; font-size: var(--fs-micro); font-weight: 700;
    font-variant-numeric: tabular-nums; white-space: nowrap; padding: 6px 10px; border-radius: var(--radius);
    background: var(--surface); border: 1px solid var(--line-strong); box-shadow: var(--shadow); color: var(--ink); }
  .spot-callout-1 { top: 78%; left: -22px; }
  .spot-callout-2 { top: 82%; right: -16px; color: var(--energy); }
  .spot-callout-3 { top: 85%; left: -30px; }

  /* ---- how-it-works step cards ---- */
  .card.step .step-shot { display: block; width: 100%; height: auto; border-radius: var(--radius-md);
    border: 1px solid var(--line); background: var(--surface-2); margin: 14px 0 16px; }

  /* ---- theme-aware responsive screenshots ---- */
  theme-shot, theme-shot > picture, theme-shot img { display: block; width: 100%; height: auto; }

  /* ---- capability chapters ---- */
  .chapter { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 64px; align-items: center;
    padding: 64px 0; border-top: 1px solid var(--line); }
  .chapter:first-child { border-top: none; padding-top: 0; }
  .chapter:last-child { padding-bottom: 0; }
  .chapter h3 { font-size: clamp(2rem, 3.75vw, 2.75rem); line-height: 1.1; }
  .chapter figure.phone { justify-self: center; }
  .chapter.flip figure.phone { order: -1; }

  /* ---- cards / grids ---- */
  .grid { display: grid; gap: 20px; }
  .g3 { grid-template-columns: repeat(3, 1fr); }
  .g2 { grid-template-columns: repeat(2, 1fr); }
  /* border-top after `border` so it overrides only the top edge. The 2px
     accent rule is the app SectionCard's signature, echoed here. */
  .card { background: var(--surface); border: 1px solid var(--line);
    border-top: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
    border-radius: var(--radius-lg); padding: 26px; }
  .card h3 { margin-bottom: 8px; }
  .card p { color: var(--muted); font-size: var(--fs-body); font-family: var(--sans); }
  .num { font-family: var(--display); font-size: var(--fs-label); color: var(--accent); font-weight: 700; letter-spacing: var(--track-caps); }

  /* Home / Teams: the profile screen is tall, so leaving it beneath three short,
     full-width cards made the section read as two unrelated layouts. Keep all four
     pieces, but treat them as one showcase: a compact benefits rail sits alongside
     the screen it describes. The card stack deliberately reaches the phone's visual
     height, and the CTA stays attached to the benefits rather than floating below a
     large empty gutter. */
  .teams-showcase { display: grid; grid-template-columns: minmax(0, 1fr) minmax(250px, 300px);
    gap: clamp(32px, 6vw, 76px); align-items: center; max-width: 1080px; }
  .teams-benefits { display: grid; gap: 14px; }
  .teams-benefits .card { padding: 22px 26px; }
  .teams-showcase figure.phone { width: min(270px, 100%); margin: 0; justify-self: center; }
  .teams-benefits .cta-row { margin-top: 10px; }

  /* ---- Personal Garage product stories ----
     The hero already proves the real app exists. These three panels then explain its
     workflow without repeating six marketing cards: baseline -> heat, conditions ->
     session, and a vehicle history that still belongs to one driver. They use the
     app's own visual grammar but stay responsive HTML, so their layout remains useful
     at widths where another tall phone capture would become too small to read. */
  .personal-feature { display: grid; grid-template-columns: minmax(0, .82fr) minmax(460px, 1.18fr);
    gap: clamp(44px, 7vw, 92px); align-items: center; }
  .personal-feature.reverse { grid-template-columns: minmax(460px, 1.18fr) minmax(0, .82fr); }
  .personal-feature.reverse .personal-feature-visual { order: -1; }
  .personal-feature-copy { max-width: 57ch; }
  .personal-feature-index { display: inline-flex; align-items: center; gap: 10px;
    color: var(--accent); font-family: var(--mono); font-size: var(--fs-micro);
    font-weight: 700; letter-spacing: var(--track-caps); }
  .personal-feature-index::after { content: ""; width: 42px; height: 1px; background: var(--accent); opacity: .55; }
  .personal-feature-copy h2 { font-size: clamp(2rem, 3.4vw, 3rem); line-height: 1.04; }
  .personal-feature-copy-block + .personal-feature-copy-block { margin-top: 38px; padding-top: 38px; border-top: 1px solid var(--line); }
  .personal-feature-copy p { color: var(--muted); font-size: var(--fs-body); line-height: 1.7; }
  .personal-feature-visual { min-width: 0; }
  .personal-ui { position: relative; overflow: hidden; border: 1px solid var(--line-strong);
    border-top: 2px solid color-mix(in srgb, var(--accent) 58%, transparent);
    border-radius: var(--radius-lg); background: color-mix(in srgb, var(--surface) 96%, transparent);
    box-shadow: var(--shadow); }
  .personal-ui::before { content: ""; position: absolute; width: 260px; height: 260px;
    right: -130px; top: -150px; border-radius: 50%; pointer-events: none;
    background: color-mix(in srgb, var(--accent) 10%, transparent); filter: blur(5px); }
  .pg-ui-bar { position: relative; display: flex; align-items: center; justify-content: space-between;
    gap: 18px; padding: 18px 22px; border-bottom: 1px solid var(--line); }
  .pg-ui-title { font-family: var(--display); font-size: var(--fs-base); font-weight: 650;
    letter-spacing: var(--track-caps); text-transform: uppercase; }
  .pg-ui-meta { color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); }
  .pg-ui-label { color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro);
    font-weight: 700; letter-spacing: var(--track-caps); text-transform: uppercase; }
  .pg-ui-pill { display: inline-flex; align-items: center; gap: 8px; min-height: 28px;
    padding: 6px 10px; border: 1px solid var(--line-strong); border-radius: 999px;
    background: var(--surface-2); color: var(--ink); font-family: var(--mono); font-size: var(--fs-micro); }
  .pg-ui-pill.accent { border-color: color-mix(in srgb, var(--accent) 36%, var(--line));
    background: color-mix(in srgb, var(--accent) 13%, var(--surface)); color: var(--accent); }

  /* Baseline -> heats */
  .pg-setup-body { position: relative; padding: 20px; }
  .pg-segmented { display: grid; grid-template-columns: 1fr 1fr; overflow: hidden;
    border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--bg); }
  .pg-segmented span { padding: 11px 14px; text-align: center; color: var(--muted);
    font-family: var(--display); font-size: var(--fs-label); letter-spacing: var(--track-caps); text-transform: uppercase; }
  .pg-segmented .active { background: color-mix(in srgb, var(--accent) 16%, var(--surface)); color: var(--accent); }
  .pg-setup-layout { display: grid; grid-template-columns: minmax(180px, .8fr) minmax(230px, 1.2fr);
    gap: 16px; margin-top: 16px; align-items: stretch; }
  .pg-baseline { display: flex; flex-direction: column; padding: 18px; border: 1px solid var(--line);
    border-radius: var(--radius-md); background: var(--surface-2); }
  .pg-baseline-name { margin-top: 24px; font-family: var(--display); font-size: 1.45rem; line-height: 1.08; }
  .pg-baseline-spec { margin-top: 10px; color: var(--muted); font-family: var(--mono);
    font-size: var(--fs-micro); line-height: 1.65; }
  .pg-baseline-action { margin-top: auto; padding-top: 24px; color: var(--accent);
    font-family: var(--mono); font-size: var(--fs-micro); font-weight: 700; letter-spacing: var(--track-caps); }
  .pg-runs { display: grid; gap: 12px; }
  .pg-run { position: relative; padding: 15px 16px 15px 38px; border: 1px solid var(--line);
    border-radius: var(--radius-md); background: var(--surface-2); }
  .pg-run::before { content: ""; position: absolute; left: 17px; top: 22px; width: 8px; height: 8px;
    border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 14%, transparent); }
  .pg-run + .pg-run::after { content: ""; position: absolute; left: 20px; bottom: calc(100% + 4px);
    width: 2px; height: 14px; background: color-mix(in srgb, var(--accent) 45%, var(--line)); }
  .pg-run-title { display: flex; justify-content: space-between; gap: 12px; font-family: var(--sans);
    font-size: var(--fs-label); font-weight: 700; }
  .pg-run-copy { margin-top: 7px; color: var(--muted); font-family: var(--mono);
    font-size: var(--fs-micro); line-height: 1.55; }
  .pg-check { color: var(--good); }

  /* Conditions -> linked session */
  .pg-evidence-body { position: relative; display: grid; grid-template-columns: 1.08fr 34px .92fr;
    gap: 14px; align-items: stretch; padding: 20px; }
  .pg-evidence-card { padding: 18px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-2); }
  .pg-weather-hero { display: flex; justify-content: space-between; gap: 14px; align-items: end; margin-top: 22px; }
  .pg-density { font-family: var(--display); font-size: clamp(2.4rem, 5vw, 3.5rem); line-height: .9; }
  .pg-density-note { display: block; margin-top: 7px; color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); }
  .pg-weather-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 18px; }
  .pg-weather-stats strong { display: block; margin-top: 4px; font-family: var(--mono); font-size: var(--fs-label); }
  .pg-paddock { display: flex; justify-content: space-between; gap: 12px; margin-top: 18px;
    padding-top: 15px; border-top: 1px solid var(--line); color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); }
  .pg-link { position: relative; display: flex; align-items: center; justify-content: center; color: var(--accent); }
  .pg-link::before { content: ""; width: 100%; height: 1px; background: color-mix(in srgb, var(--accent) 52%, var(--line)); }
  .pg-link span { display: grid; place-items: center; position: absolute; width: 30px; height: 30px;
    border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--line)); border-radius: 50%;
    background: var(--surface); font-family: var(--mono); font-size: var(--fs-label); }
  .pg-session-top { display: flex; justify-content: space-between; gap: 12px; align-items: start; }
  .pg-session-name { margin-top: 5px; font-family: var(--display); font-size: 1.35rem; }
  .pg-session-best { margin-top: 25px; }
  .pg-session-best strong { display: block; font-family: var(--display); font-size: 2.55rem; line-height: 1; }
  .pg-session-best span { display: block; margin-top: 5px; color: var(--good); font-family: var(--mono); font-size: var(--fs-micro); }
  .pg-trace { width: 100%; height: 64px; margin-top: 14px; color: var(--accent); overflow: visible; }
  .pg-trace .gridline { stroke: var(--line-strong); stroke-width: 1; }
  .pg-trace .line { fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
  .pg-session-foot { display: flex; justify-content: space-between; gap: 12px; margin-top: 10px;
    color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); }

  /* Vehicle history -> individual access */
  .pg-history-body { position: relative; padding: 4px 20px 20px; }
  .pg-history-row { display: grid; grid-template-columns: 76px 20px minmax(0, 1fr); gap: 12px; align-items: stretch; }
  .pg-history-date { padding-top: 21px; color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); text-align: right; }
  .pg-history-axis { position: relative; }
  .pg-history-axis::before { content: ""; position: absolute; left: 9px; top: 0; bottom: 0; width: 1px; background: var(--line-strong); }
  .pg-history-axis::after { content: ""; position: absolute; left: 5px; top: 25px; width: 9px; height: 9px;
    border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 13%, var(--surface)); }
  .pg-history-entry { display: grid; grid-template-columns: 1fr auto; gap: 12px; margin: 8px 0;
    padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-2); }
  .pg-history-track { font-family: var(--sans); font-size: var(--fs-label); font-weight: 700; }
  .pg-history-change { margin-top: 5px; color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); line-height: 1.5; }
  .pg-history-result { align-self: center; color: var(--ink); font-family: var(--display); font-size: 1.35rem; text-align: right; }
  .pg-history-result small { display: block; margin-top: 3px; color: var(--good); font-family: var(--mono); font-size: var(--fs-micro); }
  .pg-access { display: flex; align-items: center; justify-content: space-between; gap: 18px; margin-top: 16px;
    padding: 16px 18px; border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
    border-radius: var(--radius-md); background: color-mix(in srgb, var(--accent) 8%, var(--surface-2)); }
  .pg-access-person { display: flex; align-items: center; gap: 12px; }
  .pg-avatar { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
    background: color-mix(in srgb, var(--accent) 20%, var(--surface)); color: var(--accent);
    font-family: var(--display); font-size: var(--fs-base); }
  .pg-access strong { display: block; font-family: var(--sans); font-size: var(--fs-label); }
  .pg-access small { display: block; margin-top: 2px; color: var(--muted); font-family: var(--mono); font-size: var(--fs-micro); }

  @media (max-width: 900px) {
    .personal-feature, .personal-feature.reverse { grid-template-columns: minmax(0, 1fr); gap: 42px; }
    .personal-feature.reverse .personal-feature-visual { order: 0; }
    .personal-feature-copy { max-width: 64ch; }
  }
  @media (max-width: 620px) {
    .personal-feature-copy-block + .personal-feature-copy-block { margin-top: 30px; padding-top: 30px; }
    .pg-ui-bar, .pg-setup-body, .pg-evidence-body, .pg-history-body { padding-left: 14px; padding-right: 14px; }
    .pg-setup-layout, .pg-evidence-body { grid-template-columns: minmax(0, 1fr); }
    .pg-baseline-name { margin-top: 14px; }
    .pg-baseline-action { margin-top: 18px; padding-top: 0; }
    .pg-link { min-height: 28px; transform: rotate(90deg); }
    .pg-weather-hero { align-items: start; flex-direction: column; }
    .pg-history-row { grid-template-columns: 58px 18px minmax(0, 1fr); gap: 8px; }
    .pg-history-entry { grid-template-columns: minmax(0, 1fr); }
    .pg-history-result { text-align: left; }
    .pg-access { align-items: flex-start; flex-direction: column; }
  }

  /* ---- Team Garage feature page ----
     The product visual is HTML rather than a capture: the live Conditions card,
     fleet rows and heat list are the actual mechanic workflow, remain legible in
     every locale and cannot age into a misleading screenshot when the app moves. */
  .garage-hero { min-height: 620px; display: flex; align-items: flex-end; }
  .garage-hero > .wrap { width: 100%; }
  .garage-board { background: color-mix(in srgb, var(--surface) 92%, transparent);
    border: 1px solid var(--line-strong); border-radius: var(--radius-lg); padding: 20px;
    box-shadow: var(--shadow); backdrop-filter: blur(12px); }
  .garage-board-top { display: flex; justify-content: space-between; align-items: center;
    gap: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
  .garage-board-title { font-family: var(--display); font-size: var(--fs-base);
    letter-spacing: var(--track-caps); text-transform: uppercase; }
  .garage-board-count { color: var(--muted); font-family: var(--mono); font-size: var(--fs-label); }
  .garage-ops-layout { display: grid; grid-template-columns: minmax(280px, .82fr) minmax(0, 1.18fr);
    gap: 20px; align-items: start; }
  .garage-ops-stack { display: grid; gap: 20px; }
  .garage-conditions { position: relative; overflow: hidden; }
  .garage-conditions::after { content: ""; position: absolute; width: 180px; height: 180px;
    right: -72px; top: -92px; border-radius: 50%; pointer-events: none;
    background: color-mix(in srgb, var(--accent) 12%, transparent); filter: blur(4px); }
  .garage-condition-hero { display: flex; align-items: flex-end; justify-content: space-between;
    gap: 18px; padding: 20px 0 18px; border-bottom: 1px solid var(--line); }
  .garage-density { font-family: var(--numeric); font-size: clamp(2.6rem, 5vw, 4.5rem);
    font-weight: 700; line-height: .9; letter-spacing: -.04em; }
  .garage-density-label { display: block; margin-top: 8px; color: var(--muted);
    font-size: var(--fs-micro); letter-spacing: var(--track-caps); text-transform: uppercase; }
  .garage-sky { text-align: right; color: var(--muted); font-family: var(--sans);
    font-size: var(--fs-label); }
  .garage-condition-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px;
    padding-top: 18px; }
  .garage-condition-stat span { display: block; color: var(--muted); font-size: 10px;
    letter-spacing: var(--track-caps); text-transform: uppercase; }
  .garage-condition-stat strong { display: block; margin-top: 5px; font-family: var(--mono);
    font-size: var(--fs-label); white-space: nowrap; }
  .garage-condition-foot { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
    margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); color: var(--muted);
    font-size: var(--fs-micro); }
  .garage-fleet { display: grid; gap: 12px; margin-top: 16px; }
  .garage-vehicle { min-width: 0; background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--radius-md); padding: 15px 16px; }
  .garage-vehicle-top { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
  .garage-driver { font-family: var(--display); font-size: 19px; line-height: 1; }
  .garage-machine { margin-top: 7px; color: var(--muted); font-family: var(--sans);
    font-size: var(--fs-label); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .garage-status, .garage-setup-status { display: inline-flex; align-items: center; gap: 7px; flex: none;
    font-family: var(--sans); font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
    letter-spacing: var(--track-caps); padding: 6px 8px; border-radius: 999px;
    background: color-mix(in srgb, currentColor 10%, transparent); }
  .garage-status::before, .garage-setup-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
  .garage-status.ready, .garage-setup-status.ready { color: var(--good); }
  .garage-status.attention { color: var(--warn); }
  .garage-status.grounded { color: var(--bad); }
  .garage-setup-board { min-width: 0; }
  .garage-setup-context { display: flex; justify-content: space-between; align-items: flex-start;
    gap: 18px; padding-bottom: 16px; }
  .garage-setup-context strong { display: block; font-family: var(--display); font-size: 22px; }
  .garage-setup-context span { display: block; margin-top: 5px; color: var(--muted);
    font-family: var(--sans); font-size: var(--fs-label); }
  .garage-setup-tabs { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line); }
  .garage-setup-tabs span { padding: 11px 6px; text-align: center; color: var(--muted);
    font-family: var(--sans); font-size: var(--fs-micro); font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; }
  .garage-setup-tabs .active { color: var(--accent); box-shadow: inset 0 -2px var(--accent); }
  .garage-mode { display: inline-grid; grid-template-columns: 1fr 1fr; margin-top: 18px; padding: 4px;
    border: 1px solid var(--line); border-radius: var(--radius); }
  .garage-mode span { padding: 7px 14px; color: var(--muted); font-size: var(--fs-micro);
    font-weight: 700; text-align: center; }
  .garage-mode .active { color: var(--accent-ink); background: var(--accent); border-radius: calc(var(--radius) - 3px); }
  .garage-baseline-label { margin-top: 18px; color: var(--muted); font-family: var(--sans);
    font-size: 10px; letter-spacing: var(--track-caps); text-transform: uppercase; }
  .garage-baselines { display: flex; gap: 9px; margin-top: 8px; overflow: hidden; }
  .garage-baseline { flex: 0 1 auto; min-width: 0; padding: 9px 12px; border: 1px solid var(--line);
    border-radius: var(--radius); background: var(--surface-2); color: var(--ink); font-size: var(--fs-label);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .garage-heat-list { display: grid; gap: 10px; margin-top: 18px; }
  .garage-heat { padding: 16px; border: 1px solid var(--line); border-radius: var(--radius-md);
    background: var(--surface-2); }
  .garage-heat-top { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
  .garage-heat-name { font-family: var(--sans); font-size: var(--fs-body); font-weight: 700; }
  .garage-heat-session { color: var(--accent); font-family: var(--mono); font-size: var(--fs-micro);
    white-space: nowrap; }
  .garage-heat-change { margin-top: 8px; font-family: var(--mono); font-size: var(--fs-label); color: var(--ink); }
  .garage-heat-weather { margin-top: 6px; color: var(--muted); font-family: var(--sans);
    font-size: var(--fs-micro); line-height: 1.5; }
  .garage-workflow { counter-reset: garage-step; }
  .garage-workflow .card { position: relative; padding-top: 56px; }
  .garage-workflow .card::before { counter-increment: garage-step; content: "0" counter(garage-step);
    position: absolute; top: 22px; left: 26px; font-family: var(--mono); font-size: var(--fs-micro);
    color: var(--accent); letter-spacing: var(--track-caps); }
  .garage-workflow .card:not(:last-child)::after { content: "→"; position: absolute;
    right: -17px; top: 50%; z-index: 2; color: var(--accent); font-family: var(--display);
    font-size: 22px; transform: translateY(-50%); }
  .garage-support { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .garage-roles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .garage-role { display: flex; flex-direction: column; }
  .garage-role .garage-permission { margin-top: auto; padding-top: 18px; color: var(--accent);
    font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: var(--track-caps);
    text-transform: uppercase; }
  @media (max-width: 900px) {
    .garage-hero { min-height: 0; }
    .garage-ops-layout { grid-template-columns: minmax(0, 1fr); }
    .garage-workflow { grid-template-columns: minmax(0, 1fr) !important; }
    .garage-workflow .card:not(:last-child)::after { content: "↓"; right: auto; top: auto;
      left: 50%; bottom: -18px; transform: translateX(-50%); }
    .garage-support, .garage-roles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @media (max-width: 620px) {
    .garage-condition-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .garage-condition-hero { align-items: flex-start; flex-direction: column; }
    .garage-sky { text-align: left; }
    .garage-support, .garage-roles { grid-template-columns: minmax(0, 1fr); }
    .garage-setup-tabs span { font-size: 9px; }
  }
  /* ---- engineer sheet: the same language the app now speaks ----
     A finding reads top-down — what it is, what it means, why — with the number
     right-aligned in tabular figures so magnitudes stack down the card. The glyph
     rail is the scannable index: every mark is a fragment of a racing line plus a
     marker (identical geometry to the app's CustomPainter), drawn in currentColor
     so it inherits its row's colour and owns no palette of its own. */
  .lockup { display: flex; align-items: center; gap: 9px; padding-bottom: 18px; }
  .lockup-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--energy); flex: none; }
  .lockup-word { font-family: var(--display); font-size: 13px; font-weight: 800; letter-spacing: .2em; color: var(--ink); }
  .lockup-word + .lockup-word { margin-left: .45em; }
  .lockup-rule { flex: 1; height: 1px; background: var(--line); }
  .sheet-stats { display: flex; gap: 26px; flex-wrap: wrap; padding-bottom: 18px; border-bottom: 1px solid var(--line); }
  .sheet-stats > div { display: flex; flex-direction: column; gap: 3px; }
  .sheet-stat-label { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
  .sheet-stat-val { font-size: 21px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); line-height: 1.1; }
  .sheet-rows { list-style: none; margin: 0; padding: 0; }
  .sheet-rows li { display: grid; grid-template-columns: auto 1fr auto; gap: 0 14px;
    align-items: start; padding: 16px 0; border-bottom: 1px solid var(--line); }
  .sheet-rows li:last-child { border-bottom: none; padding-bottom: 0; }
  .glyph { fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round;
    stroke-linejoin: round; color: var(--muted); display: block; margin-top: 1px; }
  .is-focus .glyph { color: var(--bad); }
  .sheet-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .sheet-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted); }
  .is-focus .sheet-eyebrow { color: var(--bad); }
  .sheet-title { font-family: var(--sans); font-size: 16px; font-weight: 600; line-height: 1.2; color: var(--ink); }
  .is-focus .sheet-title { font-size: 18px; }
  .sheet-why { font-family: var(--sans); font-size: 13.5px; line-height: 1.45; color: var(--muted); }
  .sheet-metric { font-size: 18px; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; line-height: 1.15; }
  .is-focus .sheet-metric { font-size: 26px; }
  /* The one positive finding carries the good colour rather than sitting grey with
     the losses — a strength you can see at a glance is the point of ranking at all.
     Its own class, not the .is-good utility, so the colour lands on the glyph,
     eyebrow and title and does NOT inherit into the muted why-line. */
  .is-strength .glyph,
  .is-strength .sheet-eyebrow,
  .is-strength .sheet-title { color: var(--good); }
  .is-accent { color: var(--accent); } .is-good { color: var(--good); } .is-bad { color: var(--bad); }
  @media (max-width: 620px) {
    .sheet-rows li { grid-template-columns: auto 1fr; }
    .sheet-metric { grid-column: 2; text-align: left; margin-top: 2px; }
  }
  .flist { list-style: none; margin: 0; padding: 0; }
  .flist li { padding: 12px 0; border-top: 1px solid var(--line); font-size: var(--fs-body); display: flex; gap: 12px; align-items: baseline; font-family: var(--sans); }
  .flist li::before { content: "→"; color: var(--accent); font-family: var(--display); font-weight: 700; }

  /* devices */
  .devtiles { display: grid; grid-template-columns: repeat(4,1fr); gap: 16px; }
  .devtile { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 22px; text-align: center; }
  .devtile .ring { width: 54px; height: 54px; border-radius: 50%; margin: 0 auto 12px; display: flex; align-items: center; justify-content: center;
    border: 3px solid var(--ring-color, var(--accent)); background: var(--surface-2);
    font-family: var(--display); font-weight: 700; font-size: var(--fs-micro); letter-spacing: .02em; color: var(--ink); }
  .devtile h3 { font-weight: 700; font-size: var(--fs-base); letter-spacing: -.01em; font-family: var(--sans); }
  .devtile .devline { margin-top: 10px; font-size: var(--fs-body); line-height: 1.55; color: var(--muted); font-family: var(--sans); }

  /* export formats */
  .exportflow { display: flex; align-items: center; gap: 32px; }
  .exportflow .node { position: relative; flex: 0 1 auto; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 12px 18px; font-size: var(--fs-label); color: var(--ink); max-width: 100%; overflow-wrap: break-word; }
  .exportflow .node::after { content: ""; position: absolute; left: 100%; top: 50%; width: 32px; height: 1px; background: var(--line-strong); }
  .exportflow .lanes { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 20px; padding-left: 32px; }
  .exportflow .lanes::before { content: ""; position: absolute; left: 0; top: 12px; bottom: 12px; width: 1px; background: var(--line-strong); }
  .exportflow .lane { position: relative; border-top: 1px solid var(--line); padding-top: 16px; }
  .exportflow .lane:first-child { border-top: none; padding-top: 0; }
  .exportflow .lane-top { position: relative; display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px; }
  .exportflow .lane-top::before { content: ""; position: absolute; left: -32px; top: 0.6em; width: 32px; height: 1px; background: var(--line-strong); }
  .exportflow .lane .fmt { font-size: var(--fs-label); font-weight: 700; color: var(--fmt-color, var(--accent)); }
  .exportflow .lane .label { font-family: var(--sans); font-weight: 700; font-size: var(--fs-body); color: var(--ink); }
  .exportflow .lane .dest { font-family: var(--sans); font-size: var(--fs-body); }
  .exportflow .lane .desc { margin-top: 6px; font-size: var(--fs-body); line-height: 1.55; }

  /* csv lane's real-data preview reuses the page's shared thead th / tbody td
     rules (muted uppercase header, mono data cells) -- min-width and padding
     need overriding to undo the page-wide table { min-width:620px } and
     th,td { padding:14px 16px } rules that would otherwise force this compact
     table wider than the lane it sits in. Border/radius/stripe/font-size are
     new -- .card's own recipe (border: 1px solid var(--line); border-radius:
     var(--radius-lg)) plus a scannability stripe and an explicit body-cell
     size, since no existing table on this page has any of the three. */
  .exportflow .csvpreview { min-width: 0; margin-top: 10px; border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
  .exportflow .csvpreview th, .exportflow .csvpreview td { padding: 5px 10px; }
  .exportflow .csvpreview thead th { border-bottom-color: var(--fmt-color, var(--accent)); border-bottom-width: 2px; }
  .exportflow .csvpreview tbody td { font-size: var(--fs-label); }
  .exportflow .csvpreview tbody tr:nth-child(even) td { background: var(--surface-2); }

  /* comparison table */
  .tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-lg); }
  table { border-collapse: collapse; width: 100%; min-width: 620px; font-size: var(--fs-body); background: var(--surface); }
  th, td { text-align: left; padding: 14px 16px; border-bottom: 1px solid var(--line); }
  thead th { font-family: var(--display); font-size: var(--fs-micro); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--muted); font-weight: 700; background: var(--surface-2); }
  tbody th { color: var(--muted); font-family: var(--display); font-weight: 400; font-size: var(--fs-label); letter-spacing: .01em; }
  tbody td { font-family: var(--mono); }
  .yes { color: var(--good); font-weight: 700; } .no { color: var(--bad); } .part { color: var(--warn); }
  /* Colours a fragment of a heading. Blue already carries non-interactive meaning
     here (every .eyebrow uses it), and the two-tone split echoes the logo's own
     LAPPER/SNAPPER break, so the accent lands on the punchline rather than the
     whole line — a full heading in accent reads like an oversized link. */
  .accent { color: var(--accent); }
  .col-us { background: color-mix(in srgb, var(--accent) 9%, transparent); }

  /* pricing */
  .plans { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; align-items: start; }
  .plan { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 30px; position: relative; }
  .plan.pro { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow); }
  .plan .badge { position: absolute; top: -12px; right: 22px; background: var(--accent); color: var(--accent-ink);
    font-family: var(--display); font-size: var(--fs-micro); letter-spacing: var(--track-caps); text-transform: uppercase; padding: 5px 10px; border-radius: var(--radius); font-weight: 700; }
  .price { font-family: var(--numeric); font-variant-numeric: tabular-nums; font-size: 2.6rem; font-weight: 700; letter-spacing: -.02em; }
  .price small { font-size: .9rem; color: var(--muted); font-weight: 600; letter-spacing: 0; font-family: var(--display); text-transform: uppercase; }
  .toggle { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); padding: 4px; gap: 4px; font-family: var(--display); }
  .toggle button { background: none; border: none; color: var(--muted); font-family: var(--display); font-size: var(--fs-micro);
    text-transform: uppercase; letter-spacing: var(--track-caps); padding: 7px 13px; border-radius: var(--radius); cursor: pointer; font-weight: 600; }
  .toggle button.on { background: var(--accent); color: var(--accent-ink); font-weight: 700; }
  .plan ul { list-style: none; padding: 0; margin: 20px 0; }
  /* Not flex: a flex row would split each text run and mid-sentence <strong> into
     separate flex items, fragmenting the sentence into stacked columns on phones.
     The glyph hangs in the padding instead and the sentence flows naturally. */
  .plan li { padding: 9px 0 9px 26px; border-top: 1px solid var(--line); font-size: var(--fs-body); font-family: var(--sans); position: relative; }
  .plan li::before { content: "✓"; color: var(--good); font-weight: 700; position: absolute; left: 0; top: 9px; }
  .plan li.na { color: var(--muted); } .plan li.na::before { content: "—"; color: var(--muted); }
  /* Plan CTAs carry the longest strings on the site (localized trial copy); .btn's
     white-space:nowrap would set the card's min-content wider than a phone. */
  .plan .btn { white-space: normal; text-align: center; text-wrap: balance; }
  /* The Team band is one full-width .plan — same surface, price type and ✓ list as Free
     and Pro, laid out wide because it sits alone below the two-card grid rather than
     beside them. It replaced a .teamrow strip that predated the self-serve Team
     purchase. */
  .plan.team { margin-top: 24px; }
  /* The rail carries the whole offer — tier, price, both CTAs — and the ✓ list runs
     beside it. Price left and CTA right, with the list underneath, left a gutter of
     dead space down the middle of a 1100px card. Below 900px the rail's flex-basis
     stops fitting and the two wrap into the same stack the Free/Pro cards become. */
  .plan.team .teamhead { display: flex; align-items: flex-start; gap: 40px; flex-wrap: wrap; }
  .plan.team .teamhead-rail { flex: 0 1 30ch; min-width: 0; }
  .plan.team .teamhead-cta { margin-top: 22px; display: flex; flex-direction: column; gap: 10px; }
  .plan.team .teamhead-list { flex: 1 1 32ch; min-width: 0; }
  .plan.team ul { margin: 0; }

  /* prose (legal / about) */
  .prose { max-width: 68ch; }
  .prose h2 { font-size: 1.5rem; margin-top: 40px; }
  .prose > h2, .prose h3 { margin-top: 28px; margin-bottom: 6px; }
  .prose p, .prose li { color: var(--ink); font-size: var(--fs-body); font-family: var(--sans); }
  .prose .muted, .prose small { color: var(--muted); }
  .prose ul { padding-left: 20px; }

  /* About is the one .prose page that is a hero over a plate rather than a document,
     and it had .prose's measure on the .wrap itself. That shrinks the wrap to 68ch and
     .wrap's own margin:0 auto then centres it, so the copy floated mid-frame — 236px
     right of the 144px gutter every other band starts at, with the h1 boxed to 680px
     and wrapping five lines deep in Bulgarian. The wrap goes back to --maxw and the
     measure moves onto the copy, which is where .section-head has always kept it.

     The h1 measure is px, not ch, deliberately. The bundled condensed face is Latin-only
     (see lib/fonts.mjs), so Cyrillic and Greek fall back to a face whose "0" is 17%
     narrower — 18ch resolved to 938px in English and 788px in Bulgarian, handing the
     narrowest headline to the two locales whose strings are longest. */
  .about-copy { max-width: var(--maxw); }
  .about-copy > :not(h1) { max-width: 68ch; }
  .about-copy h1 { max-width: 940px; }
  .callout { background: var(--surface-2); border-left: 3px solid var(--accent); border-radius: var(--radius); padding: 14px 18px; font-size: var(--fs-body); font-family: var(--sans); }

  /* faq */
  .faq details { border-top: 1px solid var(--line); padding: 6px 0; }
  .faq summary { cursor: pointer; padding: 14px 0; font-weight: 600; list-style: none; display: flex; justify-content: space-between; font-family: var(--sans); }
  .faq summary::-webkit-details-marker { display: none; }
  .faq summary::after { content: "+"; color: var(--accent); font-family: var(--display); }
  .faq details[open] summary::after { content: "\2013"; }
  .faq p { color: var(--muted); padding-bottom: 14px; font-size: var(--fs-body); font-family: var(--sans); }

  /* form */
  .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
  .field label { font-family: var(--display); font-size: var(--fs-micro); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--muted); }
  .field input, .field select, .field textarea {
    background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 12px 14px;
    color: var(--ink); font-family: var(--sans); font-size: var(--fs-body);
  }

  /* footer */
  footer { border-top: 1px solid var(--line); background: var(--surface); margin-top: 20px; }
  .foot { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 32px; padding: 56px 24px 32px; }
  .foot .foot-label { font-family: var(--display); font-size: var(--fs-micro); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--muted); margin: 0 0 14px; font-weight: 700; }
  .foot a { display: block; text-decoration: none; color: var(--ink); font-size: var(--fs-body); padding: 5px 0; cursor: pointer; font-family: var(--sans); }
  .foot a:hover { color: var(--accent); }
  .footbar { border-top: 1px solid var(--line); padding: 20px 24px; display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
    font-size: var(--fs-label); color: var(--muted); font-family: var(--mono); }
  .disclaimer { font-size: var(--fs-micro); color: var(--muted); max-width: 70ch; line-height: 1.5; padding: 0 0 28px; font-family: var(--sans); }
  /* Footer rows define their vertical padding, so retain the shared 24px gutter
     explicitly. This keeps every footer row off the phone's screen edge. */
  .foot-disclaimer { padding-left: 24px; padding-right: 24px; }

  /* Injected by the build into Privacy and Terms on non-English pages only. */
  .english-only-notice { font-size: var(--fs-label); color: var(--muted); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 10px 12px; margin: 0 0 24px; }

  /* Suggests a locale; never redirects. Hidden until JS decides to show it. */
  .i18n-banner { display: flex; gap: 12px; align-items: center; justify-content: center;
    padding: 10px 16px; font-size: var(--fs-label); background: var(--line); }
  .i18n-banner[hidden] { display: none; }
  .i18n-banner a { color: var(--accent); font-weight: 700; }
  /* --ink, not --muted: against the banner tint (--line over --bg) muted was
     the marginal case that first exposed the light palette's contrast problem.
     The token itself is now darker (#4B5364, 5.85:1 on --bg), so this is no
     longer load-bearing — but --ink is still the right call for a control. */
  .i18n-banner button { background: none; border: 0; color: var(--ink); cursor: pointer; font: inherit; }

  .section-head { max-width: 60ch; }
  .section-head .lead { margin-top: 12px; }
  .mt-lg { margin-top: 40px; }
  .mt-md { margin-top: 24px; }

  /* Moment band: copy left, promo film right. The video ships poster-only
     (preload="none") so the band costs one 35 KB JPEG until someone presses play. */
  .moment-grid { display: grid; grid-template-columns: 1fr 1.05fr; gap: 48px; align-items: center; }
  .promo-video { margin: 0; }
  .promo-video video { display: block; width: 100%; height: auto; border: 1px solid var(--line-strong); background: #12151A; }

  @media (max-width: 900px) {
    /* Narrow screens stack the grid, so the copy sits alone under a band of empty
       sky — the same top padding reads as a bigger gap here than it does on desktop. */
    .hero { padding-top: 40px; }
    .hero-grid { grid-template-columns: 1fr; gap: 32px; }
    .moment-grid { grid-template-columns: 1fr; gap: 32px; }
    /* minmax(0,1fr), not 1fr: a grid item's min-width:auto would let one long
       no-wrap child (the Pro trial CTA, localized) widen the track past the
       viewport and force page-level horizontal scroll. */
    .g3, .g2, .plans, .devtiles { grid-template-columns: minmax(0, 1fr); }
    .teams-showcase { grid-template-columns: minmax(0, 1fr); gap: 32px; max-width: none; }
    .teams-benefits { gap: 16px; }
    .teams-showcase figure.phone { width: min(300px, 80vw); }
    .exportflow { flex-direction: column; align-items: stretch; gap: 16px; }
    .exportflow .node { align-self: flex-start; }
    .exportflow .node::after { display: none; }
    .exportflow .lanes { padding-left: 0; }
    .exportflow .lanes::before, .exportflow .lane-top::before { display: none; }
    /* repeat(2, minmax(0, 1fr)), not `1fr 1fr` — this override sits three rules
       below the one that explains why, and for four locales it silently undid it.
       A bare `1fr` track keeps min-width:auto, so the longest unbreakable word in
       a tile (Bulgarian's and French's device lines) widened the track past the
       viewport: measured 2026-08-28, fr overflowed to 328px and bg to 347px at a
       320px viewport, taking page-level horizontal scroll with them on the home
       page. Guarded now by test/tools/header-fit.mjs. */
    .devtiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .foot { grid-template-columns: 1fr 1fr; }
    .footbar { align-items: flex-start; }
    section.band { padding: 60px 0; }
    section.band.elevated { padding: 76px 0; }
    .chapter { grid-template-columns: 1fr; gap: 28px; padding: 40px 0; }
    /* Stacked chapters lead with the screen, then the copy — flip included. */
    .chapter figure.phone, .chapter.flip figure.phone { order: -1; }
    .spot-callout-1 { left: -8px; }
    .spot-callout-2 { right: -6px; }
    .spot-callout-3 { left: -12px; }
  }

  /* The menu button takes over at 1100px, not at the 900px the rest of the layout
     stacks at. Between the two the desktop row simply does not fit: even fully
     compressed, Bulgarian needs ~1090px of viewport for the brand, five links, the
     language switcher, the theme toggle and the CTA. Below that the links and the
     desktop CTA fold into the menu, where length costs nothing. */
  @media (max-width: 1100px) {
    .nav-links { display: none; }
    .menu-btn { display: inline-flex; }
    header .nav > a.btn-primary { display: none; }
    .nav-links.open { display: flex; position: absolute; top: 96px; left: 0; right: 0; flex-direction: column;
      background: var(--bg); border-bottom: 1px solid var(--line); padding: 16px 24px; gap: 4px; }
    .nav-links.open a { padding: 12px 0; font-size: var(--fs-body); }
    .nav-links.open a.mobile-cta { display: block; font-weight: 700; }
    .nav-links.open a.mobile-only { display: block; }
  }

  /* The brand lockup (337px at its 44px desktop height) forces horizontal overflow on
     narrow phones. Below 480px it turns fluid: the controls keep their tap size and the
     logo absorbs whatever width remains. Header-scoped — the footer logo keeps its own
     fixed 30px sizing and must not letterbox inside it. The vertical padding keeps the
     shrunken lockup a ≥24px-tall tap target. */
  @media (max-width: 480px) {
    .nav { gap: 12px; }
    .nav > .icon-btn, .langswitch { flex: none; }
    header .brand { flex: 1 1 auto; min-width: 0; padding: 10px 0; }
    .brand { min-width: 0; }
    header .brand .logo { width: 100%; max-width: 337px; height: auto; }
    /* Long localized CTAs ("Empieza la prueba gratuita de 14 días — sin tarjeta")
       must wrap on phones instead of forcing page-level horizontal scroll. */
    .btn { white-space: normal; text-align: center; }
    /* Keep legal contact details readable instead of squeezing two long strings
       into one line at phone widths. */
    .footbar { flex-direction: column; gap: 6px; }
  }

  /* ---- store badges ---- */
  /* Anchor targets scrolled to from a same-document link sit under the 96px sticky header. */
  #get, #how, #chapters { scroll-margin-top: 112px; }
  /* Social row. Sized for siblings — a second icon just drops in beside the first. */
  .social { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
  /* Overrides the `.foot a { display: block; padding: 5px 0 }` link rule so the icon
     box hugs the glyph instead of stretching across the column. */
  .foot a.social-link { display: inline-flex; padding: 0; line-height: 0; color: var(--muted); }
  .foot a.social-link:hover { color: var(--accent); }
  .social-link svg { display: block; }

  .store-badges { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
  a.store-badge { display: inline-flex; padding: 0; border-radius: var(--radius); line-height: 0; }
  a.store-badge:hover { opacity: .85; }
  a.store-badge svg { display: block; }

  /* ---- motion: scroll reveals + the hero callout showpiece ----
     Every pre-hidden state is double-gated: the boot script stamps .js on <html>, and
     the whole block sits inside prefers-reduced-motion: no-preference. Without JS, or
     with reduced motion, nothing is ever hidden and nothing moves. */
  @media (prefers-reduced-motion: no-preference) {
    .js .reveal { transition: opacity .6s ease, transform .6s ease; }
    .js .reveal:not(.in) { opacity: 0; transform: translateY(18px); }
    /* Sibling cards in a grid (the how-it-works steps) ripple in left to right. */
    .js .grid > .reveal:nth-child(2) { transition-delay: .12s; }
    .js .grid > .reveal:nth-child(3) { transition-delay: .24s; }

    /* The one set piece: the hero's corner-loss chips land on the screenshot shortly
       after load, 120ms apart; the orange delta chip gets a brief overshoot pop. */
    .js .hero-phone .spot-callout { opacity: 0; animation: chip-in .55s cubic-bezier(.2,.7,.3,1) forwards; }
    .js .hero-phone .spot-callout-1 { animation-delay: .40s; }
    .js .hero-phone .spot-callout-2 { animation-name: chip-in-pop; animation-duration: .7s; animation-delay: .52s; }
    .js .hero-phone .spot-callout-3 { animation-delay: .64s; }
  }
  @keyframes chip-in {
    from { opacity: 0; transform: translateY(12px); }
    to { opacity: 1; transform: none; }
  }
  @keyframes chip-in-pop {
    0% { opacity: 0; transform: translateY(12px) scale(.92); }
    72% { opacity: 1; transform: translateY(-2px) scale(1.07); }
    100% { opacity: 1; transform: none; }
  }
