/* Self-hosted variable subsets. Paths are ABSOLUTE so the fingerprinting
   pass in build.py can rewrite them with one consistent rule — a relative
   ../fonts/ URL would slip past it and 404 after hashing.
   latin-ext carries Turkish (ğ İ ş) and
   loads only when those characters appear on the page. */
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:400 600;
  font-display:swap;
  src:url('/assets/fonts/inter-latin.c9407645.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:400 600;
  font-display:swap;
  src:url('/assets/fonts/inter-latin-ext.a28eb6d3.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Sora';
  font-style:normal;
  font-weight:600 700;
  font-display:swap;
  src:url('/assets/fonts/sora-latin.3902474d.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Sora';
  font-style:normal;
  font-weight:600 700;
  font-display:swap;
  src:url('/assets/fonts/sora-latin-ext.8d9b4a41.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ==========================================================================
   Cantonly — design system
   --------------------------------------------------------------------------
   "Precision Trade": deep navy foundation for authority, the original brand
   blue/indigo (#3884d4 → #45499e) retained for brand moments, and a warm
   amber signal colour so calls to action finally out-rank everything else.
   The old site painted the same gradient on every element, which flattened
   all hierarchy.
   ========================================================================== */

/* ------------------------------------------------------------------ tokens */
:root {
  /* brand — carried over from the original site */
  --brand: #2e6fbd;          /* deepened for AA contrast on white */
  --brand-bright: #3884d4;   /* the original blue */
  --indigo: #45499e;         /* the original gradient partner */
  --accent: #a46010;         /* amber, WCAG AA on white and --surface */
  --accent-bright: #e0921f;  /* amber for dark backgrounds */

  /* neutrals */
  --ink: #0c1a2e;
  --ink-soft: #24384f;
  --body: #4c5c72;
  --muted: #637185;          /* WCAG AA at small sizes on --surface */
  --line: #dce4f0;
  --line-soft: #eaf0f8;
  --surface: #f6f9fd;
  --surface-2: #edf3fb;
  --bg: #ffffff;
  --on-dark: #eaf1fb;
  --on-dark-muted: #a5b8d0;

  /* navy palette: the hero, bands and footer in dark mode; buttons and
     logo tiles in both */
  --navy: #0b1830;
  --navy-2: #102542;

  /* Feature sections: the home hero, the .band call-to-action strips and
     the footer. Light by default; the dark-mode block below turns them
     navy. Text values are checked against the darkest point of each
     background (where the glows overlap): all pass WCAG AA. */
  --sec-ink: var(--ink);          /* headings */
  --sec-text: var(--ink-soft);    /* body copy */
  --sec-muted: var(--body);       /* secondary text, footer links */
  --sec-faint: var(--body);       /* fine print */
  --sec-eyebrow: #8a500c;         /* amber deepened for AA on the blue tint */
  --sec-rule: var(--line);
  --sec-grid: rgba(12, 26, 46, .05);
  --sec-chip-bg: rgba(255, 255, 255, .7);
  --sec-chip-line: var(--line);
  --hero-bg:
    radial-gradient(1100px 520px at 12% -10%, rgba(56, 132, 212, .08), transparent 62%),
    radial-gradient(760px 460px at 88% 8%, rgba(69, 73, 158, .08), transparent 60%),
    linear-gradient(168deg, #f7faff 0%, #eef3fb 100%);
  --band-bg: linear-gradient(150deg, #eef4fd, #e7eff9);
  --band-glow: rgba(56, 132, 212, .08);
  --band-line: var(--line);       /* separates the tinted band from white */
  --footer-bg: var(--surface);
  --footer-line: var(--line);
  /* Metallic rim around the phone's bezel, so the frame reads against the
     hero: >= 3:1 against the hero background (WCAG non-text contrast). */
  --phone-rim: #7d8da3;
  --phone-shadow: 0 24px 48px rgba(12, 26, 46, .22);

  /* High-contrast pair for filled buttons and the skip link. Must flip
     together, so they cannot be derived from --ink (which inverts to a
     light value in dark mode and would put white text on white). */
  --invert-bg: #0c1a2e;
  --invert-fg: #ffffff;

  /* Logo tile. Cannot just be --navy: in dark mode --navy is darker than
     the page background, so the mark would vanish into it. */
  --mark-tile: #0b1830;
  --mark-dot: #e0921f;

  /* type */
  --font-display: 'Sora', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;

  --fs-display: clamp(2.5rem, 5.6vw, 4.25rem);
  --fs-h1: clamp(2.1rem, 4.4vw, 3.25rem);
  --fs-h2: clamp(1.7rem, 3vw, 2.4rem);
  --fs-h3: clamp(1.15rem, 1.5vw, 1.35rem);
  --fs-lead: clamp(1.05rem, 1.5vw, 1.25rem);
  --fs-body: 1.0625rem;
  --fs-sm: 0.9375rem;
  --fs-xs: 0.8125rem;

  /* space & shape */
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --section-y: clamp(3.5rem, 8vw, 7rem);
  --max: 1200px;
  --prose: 70ch;
  --r-sm: 8px;
  --r: 14px;
  --r-lg: 22px;

  --shadow-sm: 0 1px 2px rgba(12, 26, 46, .06), 0 2px 8px rgba(12, 26, 46, .04);
  --shadow: 0 2px 6px rgba(12, 26, 46, .06), 0 12px 32px rgba(12, 26, 46, .08);
  --shadow-lg: 0 8px 24px rgba(12, 26, 46, .1), 0 32px 64px rgba(12, 26, 46, .12);

  --ease: cubic-bezier(.22, .61, .36, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --brand: #7db4ee;
    --brand-bright: #93c4f5;
    --indigo: #8d92e0;
    --accent: #e8a63f;
    --accent-bright: #f0b455;

    --ink: #eef4fd;
    --ink-soft: #d3e0f0;
    --body: #a9bbd2;
    --muted: #8b9db5;
    --line: #22344f;
    --line-soft: #1a2942;
    --surface: #0e1c30;
    --surface-2: #142640;
    --bg: #08111f;
    --navy: #050d18;
    --navy-2: #0c1b30;

    --sec-ink: #fff;
    --sec-text: var(--on-dark);
    --sec-muted: var(--on-dark-muted);
    --sec-faint: var(--muted);
    --sec-eyebrow: var(--accent-bright);
    --sec-rule: rgba(255, 255, 255, .1);
    --sec-grid: rgba(255, 255, 255, .05);
    --sec-chip-bg: rgba(255, 255, 255, .07);
    --sec-chip-line: rgba(255, 255, 255, .14);
    --hero-bg:
      radial-gradient(1100px 520px at 12% -10%, rgba(56, 132, 212, .34), transparent 62%),
      radial-gradient(760px 460px at 88% 8%, rgba(69, 73, 158, .42), transparent 60%),
      linear-gradient(168deg, var(--navy-2) 0%, var(--navy) 100%);
    --band-bg: linear-gradient(150deg, var(--navy-2), var(--navy));
    --band-glow: rgba(56, 132, 212, .3);
    --band-line: transparent;
    --footer-bg: var(--navy);
    --footer-line: transparent;
    --phone-rim: #8a9bb4;           /* >= 4:1 on the navy hero, glow included */
    --phone-shadow: 0 28px 60px rgba(0, 0, 0, .45);

    --invert-bg: #eef4fd;
    --invert-fg: #08111f;

    /* Inverted, not a lifted navy: a dark tile on a dark page measured
       1.64:1, well under the 3:1 WCAG needs for a non-text graphic, and the
       mark all but vanished. White reads at ~19:1 and matches the footer. */
    --mark-tile: #ffffff;
    /* Deeper amber: the bright brand amber on a white tile is washed out.
       (WCAG 1.4.11 exempts logos from contrast minimums — this is a
       legibility choice, not a compliance one.) */
    --mark-dot: #bd7b15;
  }
}

/* ------------------------------------------------------------------ reset */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; height: auto; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  line-height: 1.15;
  letter-spacing: -0.025em;
  margin: 0 0 .6em;
  font-weight: 700;
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); letter-spacing: -0.015em; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { color: var(--indigo); }

ul, ol { margin: 0 0 1.1em; padding-left: 1.2em; }
li { margin-bottom: .4em; }

strong { color: var(--ink-soft); font-weight: 600; }

:focus-visible {
  outline: 3px solid var(--brand-bright);
  outline-offset: 3px;
  border-radius: 3px;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ------------------------------------------------------------------ layout */
.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }
.section--surface { background: var(--surface); }
.section--line { border-top: 1px solid var(--line-soft); }

.prose-narrow { max-width: var(--prose); }
.center { text-align: center; }
.center .prose-narrow { margin-inline: auto; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--invert-bg);
  color: var(--invert-fg);
  padding: .75rem 1.25rem;
  border-radius: 0 0 var(--r-sm) 0;
  font-weight: 600;
}
.skip-link:focus { left: 0; color: var(--invert-fg); }

.icon { width: 1.25em; height: 1.25em; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.sprite-host { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ------------------------------------------------------------------ eyebrow */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1rem;
}
.eyebrow::before {
  content: "";
  width: 1.75rem;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}
.eyebrow--center { justify-content: center; }
/* .on-dark marks the feature sections (hero, bands). The name predates the
   light theme: they are only dark in dark mode now. Colours come from the
   --sec-* tokens, so the class works in both themes. */
.on-dark .eyebrow { color: var(--sec-eyebrow); }
.on-dark .eyebrow::before { background: var(--sec-eyebrow); }

.lead { font-size: var(--fs-lead); line-height: 1.6; color: var(--ink-soft); }
.on-dark .lead { color: var(--sec-text); }

/* ------------------------------------------------------------------ buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1;
  padding: .95rem 1.5rem;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: transform .18s var(--ease), background-color .18s var(--ease),
              border-color .18s var(--ease), color .18s var(--ease), box-shadow .18s var(--ease);
}
.btn:hover { transform: translateY(-2px); }
.btn .icon { width: 1.1em; height: 1.1em; }

.btn--primary { background: var(--invert-bg); color: var(--invert-fg); box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: var(--brand); color: var(--invert-fg); box-shadow: var(--shadow); }

.btn--accent { background: var(--accent-bright); color: #2a1a04; }
.btn--accent:hover { background: #f2ad3f; color: #2a1a04; }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { background: var(--surface-2); color: var(--ink); border-color: var(--brand); }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }
.btn-row--center { justify-content: center; }

/* ------------------------------------------------------------------ header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.site-header.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: 0 1px 12px rgba(12, 26, 46, .06);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 72px;
}

.brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; flex: none; }
/* Inline SVG, not an <img>: sharp at any DPI, no extra request, and the
   tile recolours per theme via currentColor. */
.brand__mark {
  width: 30px;
  height: 30px;
  flex: none;
  color: var(--mark-tile);
}
.brand__text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.3rem;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.brand__group {
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  border-left: 1px solid var(--line);
  padding-left: .6rem;
  margin-left: .2rem;
  line-height: 1.25;
  font-weight: 600;
}

.nav { margin-left: auto; }
.nav ul {
  display: flex;
  align-items: center;
  gap: .25rem;
  list-style: none;
  margin: 0;
  padding: 0;
  /* Wrap rather than spill. .nav has min-width:0 so it is the item that
     gives way, but its content is nowrap, so without this the links
     overflow their own box and paint on top of the language pill and the
     CTA button instead of reflowing.

     The case that surfaced it was not a language we ship: a reader viewing
     the Chinese page with the browser's own translation turned on. Chrome
     replaced 4-character labels with English ones six times longer, far
     past anything the six shipped languages need. We cannot size a header
     for arbitrary machine translation, but it must degrade by growing a
     second row, not by becoming unreadable. */
  flex-wrap: wrap;
  justify-content: flex-end;
  row-gap: .15rem;
}
.nav li { margin: 0; }
.nav a:not(.btn) {
  display: block;
  padding: .5rem .7rem;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  border-radius: var(--r-sm);
  white-space: nowrap;
  transition: background-color .16s var(--ease), color .16s var(--ease);
}
.nav a:not(.btn):hover { background: var(--surface-2); color: var(--ink); }
.nav a.is-active { color: var(--brand); font-weight: 600; }

/* The drawer CTA and language pill duplicate .header-cta; both are for the
   mobile menu only, since .header-cta itself is hidden below 1200px. */
.nav__cta, .nav__lang { display: none; }

/* MUST be flex. <details> is a block element, so in a plain block container
   the language pill takes its own line and shoves the CTA button below it —
   out of the 72px header and onto the hero. */
.header-cta {
  display: flex;
  align-items: center;
  gap: .55rem;
  flex: none;
}
.header-cta .btn { white-space: nowrap; }
/* Let the nav be the element that gives way, not the CTA. */
.nav { min-width: 0; }
/* Never let the header grow a second row, whatever the language. */
.header-inner { flex-wrap: nowrap; }

/* ------------------------------------------------------------- theme switch */
/* Moon in light mode (click for dark), sun in dark mode. The icon swap is
   pure CSS (see the dark-mode block), so it is right before main.js runs;
   main.js only keeps aria-pressed and the saved choice in step. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Same height as the language pill beside it. */
  width: 34px;
  height: 34px;
  flex: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background-color .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}
.theme-toggle:hover { background: var(--surface-2); border-color: var(--brand); color: var(--ink); }
.theme-toggle .icon { width: 1.05rem; height: 1.05rem; }
/* Measured: with the switch in the header, German needed 7px more than the
   1200px row had, and Turkish fitted with 0px spare. Tighter gaps between
   brand, nav and actions on the one-row layout give both room again (German
   ~15px, Turkish ~22px). The drawer layout below 1200px keeps 1.5rem. */
@media (min-width: 1200px) {
  .header-inner { gap: 1rem; }
}
.theme-toggle__sun { display: none; }
/* Without JavaScript the switch cannot work; the site still follows the
   device setting. */
.no-js .theme-toggle { display: none; }
/* The header actions are hidden in the drawer layout, so a second switch
   sits beside the menu button there. */
.theme-toggle--mobile { display: none; }

.nav-toggle {
  display: none;
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: .55rem;
  color: var(--ink);
  cursor: pointer;
}

/* Applied at every width, not just narrow ones: the nav has to hold seven
   items in languages whose labels run much longer than English, inside a
   1200px container that also carries the brand, the language flag and the CTA.
   At full padding German and Turkish overflowed and the flag pill landed on
   top of the last nav item. */
.nav a:not(.btn) { padding: .5rem .55rem; font-size: .875rem; }

/* .brand__group is no longer rendered in the header — .wrap caps at 1200px,
   so the row never gains room at wider viewports and the line could not fit
   beside a seven-item nav in German, Turkish or Swedish. The Wexpom
   affiliation lives in the footer instead. The styles stay for the footer. */

/* 1199px: measured. Originally 1180px (between 1100 and 1170 the German
   nav did not fit beside the brand, the language pill and the CTA inside
   the 1200px container). The theme switch added 34px, after which German
   needed 1185px for one row and every other language 1181px; 1199px gives
   German ~15px to spare. Narrower widths get the drawer, which keeps every
   shipped language on one clean row. */
@media (max-width: 1199px) {
  .nav-toggle { display: block; margin-left: 0; }
  .header-cta { display: none; }
  /* Square-ish here, to pair with the menu button beside it. */
  .theme-toggle--mobile { display: inline-flex; margin-left: auto; margin-right: -.75rem; border-radius: var(--r-sm); }
  .no-js .theme-toggle--mobile { display: none; }
  .no-js .nav-toggle { margin-left: auto; }
  .nav {
    position: fixed;
    inset: 72px 0 auto;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow);
    padding: 1rem var(--gutter) 1.5rem;
    margin: 0;
    display: none;
  }
  .nav[data-open="true"] { display: block; }
  .nav ul { flex-direction: column; align-items: stretch; gap: 0; }
  .nav a:not(.btn) { padding: .85rem .5rem; border-bottom: 1px solid var(--line-soft); border-radius: 0; font-size: 1rem; }
  .nav__cta, .nav__lang { display: block; }
  .nav .nav__cta { margin-top: 1rem; }
  /* Full-width pill, not a square grey row: .btn carries its own padding,
     radius and colours now that .nav a no longer matches it. */
  .nav .nav__cta .btn { display: flex; width: 100%; }
}

/* ------------------------------------------------------------------ hero */
.hero {
  position: relative;
  overflow: hidden;
  background: var(--hero-bg);
  color: var(--sec-text);
  padding-block: clamp(3.5rem, 8vw, 6.5rem) clamp(3.5rem, 8vw, 6rem);
}
.hero h1 { color: var(--sec-ink); font-size: var(--fs-display); }
.hero p { color: var(--sec-text); }

/* faint route-line motif — echoes shipping lanes */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--sec-grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--sec-grid) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(circle at 70% 30%, #000 0%, transparent 72%);
  pointer-events: none;
}
.hero > * { position: relative; z-index: 1; }

.hero-grid {
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-visual { order: -1; max-width: 300px; margin-inline: auto; }
}

.hero__route {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--sec-muted);
  background: var(--sec-chip-bg);
  border: 1px solid var(--sec-chip-line);
  padding: .45rem .9rem;
  border-radius: 999px;
  margin-bottom: 1.5rem;
}
.hero__route .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent-bright); flex: none; }

.hero__note {
  margin-top: 1.5rem;
  font-size: var(--fs-sm);
  color: var(--sec-muted);
}

.hero-visual { position: relative; }
.hero-visual picture { display: block; }
/* A flat app screenshot, framed as a phone: dark bezel, a metallic rim so
   the frame stands out in either theme, and a drop shadow. The rim is a
   shadow ring, not a border, so it adds no layout size. */
.hero-visual img {
  /* The screenshot is taller than the old mockup (1.9:1 vs 1.68:1); 88%
     keeps the hero the height it was, so the app's tab bar stays in view. */
  display: block;
  max-width: 88%;
  margin-inline: auto;
  border: 8px solid #05070c;
  border-radius: 2rem;
  box-shadow: 0 0 0 3px var(--phone-rim), var(--phone-shadow);
}

/* ------------------------------------------------------------------ stats */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.stat { background: var(--bg); padding: 1.6rem 1.5rem; }
.stat__num {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.03em;
  line-height: 1.1;
  margin: 0 0 .3rem;
}
.stat__num .unit { font-size: .6em; color: var(--accent); margin-left: .15em; }
.stat__label { font-size: var(--fs-sm); color: var(--muted); margin: 0; }

/* ------------------------------------------------------------------ cards */
.grid {
  display: grid;
  gap: clamp(1rem, 2.2vw, 1.75rem);
}
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(1.5rem, 2.5vw, 2rem);
  transition: transform .2s var(--ease), box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--brand) 35%, var(--line)); }
.card h3 { margin-bottom: .5rem; }
.card p:last-child { margin-bottom: 0; }
.card--flat:hover { transform: none; box-shadow: none; border-color: var(--line); }
.card--surface { background: var(--surface); }

.card__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  background: linear-gradient(140deg, var(--brand-bright), var(--indigo));
  color: #fff;
  margin-bottom: 1.1rem;
}
.card__icon .icon { width: 22px; height: 22px; stroke-width: 1.7; }

.card__link {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  margin-top: 1rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
}
.card__link .icon { width: 1em; height: 1em; transition: transform .18s var(--ease); }
.card__link:hover .icon { transform: translateX(3px); }

/* ------------------------------------------------------------------ steps */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.step {
  position: relative;
  display: grid;
  grid-template-columns: 3.25rem 1fr;
  gap: 1.25rem;
  padding-bottom: 2.25rem;
  margin: 0;
}
.step:last-child { padding-bottom: 0; }
.step::before {
  content: "";
  position: absolute;
  left: 1.6rem;
  top: 3.25rem;
  bottom: .5rem;
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--line) 0 6px, transparent 6px 12px);
}
.step:last-child::before { display: none; }
.step__num {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--bg);
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--brand);
  font-size: 1.1rem;
  position: relative;
  z-index: 1;
}
.step h3 { margin: .55rem 0 .4rem; }

/* ------------------------------------------------------------------ compare table */
.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r); }
table.compare {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  font-size: var(--fs-sm);
  background: var(--bg);
}
table.compare th, table.compare td {
  text-align: left;
  padding: .95rem 1.15rem;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
table.compare thead th {
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.compare tbody th { font-weight: 600; color: var(--ink); font-family: var(--font-body); width: 30%; }
table.compare tr:last-child td, table.compare tr:last-child th { border-bottom: 0; }
table.compare td.is-strong { color: var(--ink); font-weight: 500; }

/* ------------------------------------------------------------------ accordion */
.faq-list { display: grid; gap: .75rem; }
.faq-item {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--bg);
  overflow: hidden;
}
.faq-item[open] { border-color: color-mix(in srgb, var(--brand) 40%, var(--line)); box-shadow: var(--shadow-sm); }
.faq-item summary {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.15rem 1.35rem;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.03rem;
  color: var(--ink);
  line-height: 1.4;
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "";
  margin-left: auto;
  flex: none;
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  transform: rotate(45deg);
  transition: transform .22s var(--ease);
}
.faq-item[open] summary::after { transform: rotate(-135deg); }
.faq-item summary:hover { background: var(--surface); }
.faq-item .faq-body { padding: 0 1.35rem 1.35rem; }
.faq-item .faq-body > :first-child { margin-top: 0; }

/* ------------------------------------------------------------------ offices */
.offices { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(1rem, 2.2vw, 1.75rem); }
.office {
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(1.5rem, 2.5vw, 2rem);
  background: var(--bg);
}
.office--pending { background: var(--surface); border-style: dashed; }
.office__flag {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 .4rem;
}
.office h3 { margin-bottom: 1.25rem; }
.office__pending-note { font-size: var(--fs-sm); color: var(--body); margin-bottom: 1.25rem; }
.office__rows { margin: 0; display: grid; gap: .8rem; }
.office__rows > div { display: grid; grid-template-columns: 6.5rem 1fr; gap: 1rem; align-items: start; }
.office__rows dt {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: .15rem;
}
.office__rows dd { margin: 0; font-size: var(--fs-sm); color: var(--ink-soft); }
.office__rows dd.is-tbc { color: var(--muted); font-style: italic; }

/* ------------------------------------------------------------------ team */
/* Nine people = a clean 3x3. The old version used
   `auto-fill, minmax(150px, 1fr)`, which yields ~7 columns at desktop and
   left two orphans hanging on a second row.

   Symmetry here comes from three things working together:
     1. a fixed 3-column track, so the count divides evenly
     2. grid-auto-rows: 1fr, so every row is exactly the same height
     3. each card is a flex column with `margin-top:auto` on the tag, so the
        pills line up along a single baseline even when a title wraps
   Without (3), one two-line title knocks that card's pill out of line with
   its neighbours and the whole row reads as crooked. */
.team-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1fr;
  gap: clamp(.9rem, 1.8vw, 1.4rem);
}

/* If the roster stops being a multiple of three, a lone final card centres
   rather than hanging against the left edge. Inert at 9. */
.team-grid > :last-child:nth-child(3n + 1) { grid-column: 2; }

@media (max-width: 860px) {
  .team-grid { grid-template-columns: repeat(2, 1fr); }
  .team-grid > :last-child:nth-child(3n + 1) { grid-column: auto; }
  /* 9 is odd, so at two columns the last card is always alone: centre it. */
  .team-grid > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
    justify-self: center;
    width: min(100%, 22rem);
  }
}

@media (max-width: 460px) {
  .team-grid { grid-template-columns: 1fr; }
  /* justify-self must be reset as well as width — left at `center` the last
     card shrink-wraps its content while its neighbours fill the column. */
  .team-grid > :last-child:nth-child(odd) {
    grid-column: auto;
    width: auto;
    justify-self: stretch;
  }
}

.member {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(1.4rem, 2.4vw, 1.9rem) 1.15rem clamp(1.2rem, 2vw, 1.5rem);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: transform .2s var(--ease), box-shadow .2s var(--ease),
              border-color .2s var(--ease);
}
.member:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
}

/* The wrapper is the ring: 3px of padding showing a gradient behind a circular
   image. Neutral at rest so nine of them do not shout; brand gradient on hover. */
.member__photo {
  display: block;
  width: clamp(88px, 8vw, 108px);
  aspect-ratio: 1;
  padding: 3px;
  border-radius: 50%;
  background: var(--line);
  margin-bottom: 1rem;
  transition: background .25s var(--ease), transform .25s var(--ease);
}
.member:hover .member__photo {
  background: linear-gradient(140deg, var(--brand-bright), var(--indigo));
  transform: scale(1.04);
}
.member__photo img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  /* The source portraits are inconsistently framed; bias the crop upward so
     faces stay centred rather than drifting toward the chin. */
  object-position: 50% 22%;
  background: var(--surface-2);
}

.member__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0 0 .15rem;
}
.member__title {
  font-size: var(--fs-sm);
  color: var(--body);
  margin: 0 0 1rem;
  line-height: 1.4;
}

/* margin-top:auto is what pins every pill to the same baseline. */
.member__tag {
  margin: auto 0 0;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .32rem .7rem;
  white-space: nowrap;
}
.member__tag .icon {
  width: .95rem;
  height: .95rem;
  color: var(--brand);
  stroke-width: 1.9;
}

/* ------------------------------------------------------------------ checklist */
.ticks { list-style: none; margin: 0 0 1.1em; padding: 0; display: grid; gap: .7rem; }
.ticks li { display: grid; grid-template-columns: 1.4rem 1fr; gap: .7rem; margin: 0; align-items: start; }
.ticks .icon { width: 1.15rem; height: 1.15rem; color: var(--brand); margin-top: .28rem; stroke-width: 2.2; }

/* ------------------------------------------------------------------ band */
/* A tinted strip in light mode, navy in dark mode (see --band-* tokens). */
.band {
  background: var(--band-bg);
  /* Drawn as inset shadows, not borders, so the band is the same height in
     both themes (a transparent border would still take 1px in dark mode). */
  box-shadow: inset 0 1px 0 var(--band-line), inset 0 -1px 0 var(--band-line);
  color: var(--sec-text);
  position: relative;
  overflow: hidden;
}
.band h2, .band h3 { color: var(--sec-ink); }
.band p { color: var(--sec-text); }
.band .stat__num { color: var(--sec-ink); }
.band::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(700px 340px at 85% 15%, var(--band-glow), transparent 65%);
  pointer-events: none;
}
.band > * { position: relative; z-index: 1; }

.cta-band { text-align: center; }
.cta-band .prose-narrow { margin-inline: auto; }

/* ------------------------------------------------------------------ notice */
.notice {
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  background: var(--surface);
  border-radius: var(--r-sm);
  padding: 1.1rem 1.35rem;
  font-size: var(--fs-sm);
}
.notice p:last-child { margin-bottom: 0; }
.notice strong { color: var(--ink); }

/* ------------------------------------------------------------------ form */
.form-grid { display: grid; gap: 1rem; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 620px) { .form-row { grid-template-columns: 1fr; } }

.field { display: grid; gap: .4rem; }
.field label { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-soft); }
.field .hint { font-size: var(--fs-xs); color: var(--muted); }
.field .req { color: var(--accent); }

.field input, .field select, .field textarea {
  font-family: inherit;
  font-size: var(--fs-body);
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: .8rem 1rem;
  width: 100%;
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease);
}
.field textarea { min-height: 150px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}
.field input::placeholder, .field textarea::placeholder { color: var(--muted); }

.form-consent { display: grid; grid-template-columns: 1.25rem 1fr; gap: .7rem; align-items: start; font-size: var(--fs-sm); }
.form-consent input { width: 1.1rem; height: 1.1rem; margin-top: .35rem; }

/* ------------------------------------------------------------------ prose (guides) */
.prose { max-width: var(--prose); }
.prose h2 { margin-top: 2.5em; }
.prose h3 { margin-top: 2em; }
.prose > :first-child { margin-top: 0; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li { margin-bottom: .55em; }
.prose blockquote {
  margin: 1.75em 0;
  padding: 0 0 0 1.35rem;
  border-left: 3px solid var(--brand);
  color: var(--ink-soft);
  font-size: var(--fs-lead);
  line-height: 1.55;
}
.prose .table-scroll { margin: 1.75em 0; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 2.5em 0; }

.toc {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1.35rem 1.5rem;
  margin-bottom: 2.5rem;
}
.toc h2 {
  font-size: var(--fs-xs) !important;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 .8rem !important;
  font-family: var(--font-body);
  font-weight: 700;
}
.toc ol { margin: 0; padding-left: 1.2em; font-size: var(--fs-sm); }
.toc li { margin-bottom: .35em; }

.article-head { border-bottom: 1px solid var(--line); padding-bottom: 2rem; margin-bottom: 2.5rem; }
.article-meta { font-size: var(--fs-xs); color: var(--muted); letter-spacing: .04em; text-transform: uppercase; font-weight: 600; }

/* ------------------------------------------------------------------ breadcrumb */
.crumbs { font-size: var(--fs-xs); color: var(--muted); margin-bottom: 1.25rem; }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: .45rem; margin: 0; padding: 0; }
.crumbs li { margin: 0; display: flex; align-items: center; gap: .45rem; }
.crumbs li + li::before { content: "/"; color: var(--line); }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--brand); text-decoration: underline; }

/* ------------------------------------------------------------------ page head */
.page-head {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(2.5rem, 5vw, 4.25rem);
}
.page-head h1 { margin-bottom: .7rem; }
.page-head .lead { max-width: var(--prose); }

/* ------------------------------------------------------------------ footer */
.site-footer {
  background: var(--footer-bg);
  box-shadow: inset 0 1px 0 var(--footer-line);   /* no layout space; see .band */
  color: var(--sec-muted);
  padding-block: clamp(3rem, 6vw, 4.5rem) 1.75rem;
  font-size: var(--fs-sm);
}
.footer-top {
  display: grid;
  grid-template-columns: minmax(220px, 1.3fr) repeat(auto-fit, minmax(140px, 1fr));
  gap: clamp(1.75rem, 4vw, 3rem);
  padding-bottom: 2.5rem;
  border-bottom: 1px solid var(--sec-rule);
}
.footer-brand .brand__text { color: var(--sec-ink); }
.footer-brand p { margin-top: .9rem; max-width: 32ch; color: var(--sec-muted); }
/* The logo tile needs no override: the global --mark-tile is navy in light
   mode and white in dark mode, which is right for the footer in both. */
.footer-brand .brand { gap: .6rem; }

.f-col h2 {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--sec-ink);
  margin-bottom: .9rem;
}
.f-col ul { list-style: none; margin: 0; padding: 0; }
.f-col li { margin-bottom: .55rem; }
.f-col a { color: var(--sec-muted); text-decoration: none; }
.f-col a:hover { color: var(--sec-ink); text-decoration: underline; }

.footer-contact {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1.5rem;
  padding-block: 2rem;
  border-bottom: 1px solid var(--sec-rule);
}
.footer-contact h2 { color: var(--sec-ink); font-family: var(--font-body); font-size: var(--fs-xs); letter-spacing: .12em; text-transform: uppercase; margin-bottom: .6rem; }
.footer-contact a { color: var(--sec-text); }
.footer-contact p { margin-bottom: .3rem; }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
  justify-content: space-between;
  align-items: center;
  padding-top: 1.75rem;
  font-size: var(--fs-xs);
  color: var(--sec-muted);
}
.footer-bottom p { margin: 0; }
.footer-bottom a { color: var(--sec-muted); }

/* ------------------------------------------------------------------ reveal */
/* Visible by DEFAULT. The hidden state is applied only once main.js has
   confirmed it can animate (it sets .js-reveal on <html>), so a blocked or
   failed script can never leave sections invisible. */
.js-reveal .reveal { opacity: 0; transform: translateY(14px); }
.js-reveal .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .js-reveal .reveal { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------------ print */
@media print {
  .site-header, .site-footer, .nav-toggle, .cta-band { display: none; }
  body { color: #000; font-size: 11pt; }
  .hero { background: none; color: #000; }
  .hero h1 { color: #000; }
}

/* ------------------------------------------------------------------ video */
/* Click-to-load: nothing is requested from YouTube until the user presses
   play. Saves ~1MB of third-party JS on load and avoids setting cookies
   before consent. */
.video-embed { max-width: 900px; margin-inline: auto; }
.video-embed__btn {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--surface);
  cursor: pointer;
  line-height: 0;
}
.video-embed__btn img { width: 100%; aspect-ratio: 1280 / 634; object-fit: cover; }
.video-embed__btn::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(11,24,48,.15), rgba(11,24,48,.5));
  transition: background .2s var(--ease);
}
.video-embed__btn:hover::after { background: linear-gradient(180deg, rgba(11,24,48,.05), rgba(11,24,48,.35)); }
.video-embed__play {
  position: absolute;
  z-index: 1;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 76px; height: 76px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: #fff;
  color: var(--navy);
  box-shadow: var(--shadow-lg);
  padding-left: 4px;
  transition: transform .2s var(--ease), background-color .2s var(--ease);
}
.video-embed__btn:hover .video-embed__play { transform: translate(-50%, -50%) scale(1.07); background: var(--accent-bright); }
.video-embed__frame { position: relative; aspect-ratio: 16 / 9; border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--line); }
.video-embed__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* In dark mode --brand is a light blue, so the primary hover state needs
   dark text rather than the light --invert-fg. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn--primary:hover { color: #08111f; }
  :root:not([data-theme="light"]) .theme-toggle__moon { display: none; }
  :root:not([data-theme="light"]) .theme-toggle__sun { display: block; }

  /* Feature sections are navy in dark mode, so their buttons invert. (In
     light mode they are light, and the normal buttons apply.) */
  :root:not([data-theme="light"]) .on-dark .btn--primary { background: #fff; color: var(--navy); }
  :root:not([data-theme="light"]) .on-dark .btn--primary:hover { background: var(--accent-bright); color: #08111f; }
  :root:not([data-theme="light"]) .on-dark .btn--ghost { color: #fff; border-color: rgba(255,255,255,.28); }
  :root:not([data-theme="light"]) .on-dark .btn--ghost:hover { background: rgba(255,255,255,.1); color: #fff; border-color: rgba(255,255,255,.5); }
}

/* --------------------------------------------------------------- utilities */
/* Visible to screen readers only — the flag alone carries no accessible name. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ language */
/* A <details> dropdown: no JavaScript, and every option is a real <a> so
   crawlers can follow it. A JS-only switcher would hide five sixths of the
   site from search engines. */
.langpick { position: relative; flex: none; }

.langpick summary {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .6rem .8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-soft);
  list-style: none;
  transition: background-color .16s var(--ease), border-color .16s var(--ease);
}
.langpick summary::-webkit-details-marker { display: none; }
.langpick summary::after {
  content: "";
  width: 6px; height: 6px;
  margin-left: .1rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
}
.langpick[open] summary::after { transform: rotate(-135deg) translateY(-2px); }
.langpick summary:hover { background: var(--surface-2); border-color: var(--brand); }
.langpick summary { padding: .5rem .7rem; }

.langpick ul {
  position: absolute;
  right: 0;
  top: calc(100% + .5rem);
  z-index: 60;
  min-width: 12rem;
  margin: 0;
  padding: .4rem;
  list-style: none;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
}
.langpick li { margin: 0; }
.langpick ul a {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem .65rem;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  text-decoration: none;
}
.langpick ul a:hover { background: var(--surface-2); color: var(--ink); }
.langpick ul a.is-current { color: var(--brand); font-weight: 600; }
.langpick__flag {
  width: 21px;
  height: 14px;
  flex: none;
  border-radius: 2.4px;
  /* A hairline ring so light flags (Germany's gold band, Sweden's yellow)
     do not bleed into the surface behind them. */
  box-shadow: 0 0 0 1px rgba(12, 26, 46, .16);
}
.langpick summary .langpick__flag { width: 23px; height: 15.5px; }
.langpick ul a.is-current { background: var(--surface-2); }

/* On mobile the header CTA is hidden, so the switcher moves into the drawer. */
@media (max-width: 1199px) {
  .nav .langpick { display: block; margin-top: 1rem; }
  .nav .langpick summary { width: 100%; justify-content: center; }
  .nav .langpick ul { position: static; box-shadow: none; margin-top: .5rem; }
  /* .nav a:not(.btn) out-specifies .langpick ul a, so restate the row layout:
     without this the flag stacks above its language name. */
  .nav .langpick ul a {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .65rem;
    border-bottom: 0;
    border-radius: var(--r-sm);
  }
}

/* ------------------------------------------------------------------ CJK */
/* Sora and Inter carry no Chinese glyphs, so zh would fall back to whatever
   the OS picked — usually with mismatched metrics. Name the platform CJK faces
   explicitly instead. Downloading a webfont is not an option: a subset covering
   common Simplified Chinese is several megabytes.
   CJK also needs no negative tracking (it hurts glyph spacing) and a little
   more leading, since the glyphs are dense and full-height. */
.lang-zh {
  --font-display: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
                  "Noto Sans SC", "Source Han Sans SC", sans-serif;
  --font-body: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
               "Noto Sans SC", "Source Han Sans SC", sans-serif;
}
.lang-zh body, .lang-zh { line-height: 1.85; }
.lang-zh h1, .lang-zh h2, .lang-zh h3, .lang-zh h4 {
  letter-spacing: 0;
  line-height: 1.35;
  text-wrap: initial;
}
.lang-zh .eyebrow { letter-spacing: .08em; }
.lang-zh .member__tag, .lang-zh .btn { white-space: normal; }

/* ------------------------------------------------------------------ touch targets */
/* 48px minimum hit area wherever the primary pointer is a finger (Google's
   mobile guideline). Scoped to coarse pointers so the desktop layout keeps
   its tighter rhythm. Links inside running prose are exempt by design. */
@media (pointer: coarse) {
  .btn,
  .brand,
  .card__link { min-height: 48px; }
  .nav-toggle { min-width: 48px; min-height: 48px; }
  .theme-toggle { width: 48px; height: 48px; }
  .form-grid input:not([type="checkbox"]),
  .form-grid select { min-height: 48px; }
  .crumbs a,
  .toc a,
  .site-footer li a,
  dd a {
    display: inline-flex;
    align-items: center;
    min-height: 48px;
  }
  /* The label beside it is the real target (for="consent"); this just makes
     the box itself easier to hit. */
  .form-consent input { width: 1.5rem; height: 1.5rem; margin-top: .1rem; }
}


/* Generated by build.py from the dark-mode blocks above: the same rules, applied when the visitor picks dark with the header switch. */

  :root[data-theme="dark"] {
    --brand: #7db4ee;
    --brand-bright: #93c4f5;
    --indigo: #8d92e0;
    --accent: #e8a63f;
    --accent-bright: #f0b455;

    --ink: #eef4fd;
    --ink-soft: #d3e0f0;
    --body: #a9bbd2;
    --muted: #8b9db5;
    --line: #22344f;
    --line-soft: #1a2942;
    --surface: #0e1c30;
    --surface-2: #142640;
    --bg: #08111f;
    --navy: #050d18;
    --navy-2: #0c1b30;

    --sec-ink: #fff;
    --sec-text: var(--on-dark);
    --sec-muted: var(--on-dark-muted);
    --sec-faint: var(--muted);
    --sec-eyebrow: var(--accent-bright);
    --sec-rule: rgba(255, 255, 255, .1);
    --sec-grid: rgba(255, 255, 255, .05);
    --sec-chip-bg: rgba(255, 255, 255, .07);
    --sec-chip-line: rgba(255, 255, 255, .14);
    --hero-bg:
      radial-gradient(1100px 520px at 12% -10%, rgba(56, 132, 212, .34), transparent 62%),
      radial-gradient(760px 460px at 88% 8%, rgba(69, 73, 158, .42), transparent 60%),
      linear-gradient(168deg, var(--navy-2) 0%, var(--navy) 100%);
    --band-bg: linear-gradient(150deg, var(--navy-2), var(--navy));
    --band-glow: rgba(56, 132, 212, .3);
    --band-line: transparent;
    --footer-bg: var(--navy);
    --footer-line: transparent;
    --phone-rim: #8a9bb4;           /* >= 4:1 on the navy hero, glow included */
    --phone-shadow: 0 28px 60px rgba(0, 0, 0, .45);

    --invert-bg: #eef4fd;
    --invert-fg: #08111f;

    /* Inverted, not a lifted navy: a dark tile on a dark page measured
       1.64:1, well under the 3:1 WCAG needs for a non-text graphic, and the
       mark all but vanished. White reads at ~19:1 and matches the footer. */
    --mark-tile: #ffffff;
    /* Deeper amber: the bright brand amber on a white tile is washed out.
       (WCAG 1.4.11 exempts logos from contrast minimums — this is a
       legibility choice, not a compliance one.) */
    --mark-dot: #bd7b15;
  }


  :root[data-theme="dark"] .btn--primary:hover { color: #08111f; }
  :root[data-theme="dark"] .theme-toggle__moon { display: none; }
  :root[data-theme="dark"] .theme-toggle__sun { display: block; }

  /* Feature sections are navy in dark mode, so their buttons invert. (In
     light mode they are light, and the normal buttons apply.) */
  :root[data-theme="dark"] .on-dark .btn--primary { background: #fff; color: var(--navy); }
  :root[data-theme="dark"] .on-dark .btn--primary:hover { background: var(--accent-bright); color: #08111f; }
  :root[data-theme="dark"] .on-dark .btn--ghost { color: #fff; border-color: rgba(255,255,255,.28); }
  :root[data-theme="dark"] .on-dark .btn--ghost:hover { background: rgba(255,255,255,.1); color: #fff; border-color: rgba(255,255,255,.5); }
