/* =========================================================================
   Zeetius Federation
   -------------------------------------------------------------------------
   1  Reset and base
   2  Typography
   3  Layout
   4  Header and navigation
   5  Buttons, links, chips
   6  Section furniture
   7  Artefacts   (the product's own records, drawn in HTML and SVG)
   8  Accordion and tabs
   9  Forms
   10 Footer
   11 Motion

   Physical direction properties are not used anywhere in this file. Arabic is
   half the traffic this site is built for, so `margin-left` is a bug, not a
   style choice — everything is written with inline/block logical properties
   and mirrors for free.
   ========================================================================= */

/* ---------- 1  Reset and base ------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The sticky header would otherwise cover whatever an in-page link lands on. */
  scroll-padding-block-start: calc(var(--header-h) + var(--s-5));
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  /* 17px. Never below 16: iOS Safari zooms the viewport when a smaller input
     takes focus, which on the demo form is a real, reproducible bug. */
  font-size: var(--t-base);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

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

:where(a) { color: inherit; }

/* One visible, generous focus ring everywhere. Never removed. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r-1);
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--cyan); color: var(--ink-950); }

.skip-link {
  position: absolute;
  inset-block-start: -100%;
  inset-inline-start: var(--s-4);
  z-index: var(--z-panel-layer);
  padding: var(--s-3) var(--s-5);
  background: var(--cyan);
  color: var(--ink-950);
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 var(--r-2) var(--r-2);
}
.skip-link:focus { inset-block-start: 0; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- 2  Typography ------------------------------------------------ */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--lh-heading);
  letter-spacing: var(--track-display);
  color: var(--fg-strong);
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: var(--t-4xl); line-height: var(--lh-display); font-weight: 700; }
h2 { font-size: var(--t-3xl); line-height: var(--lh-display); font-weight: 700; }
h3 { font-size: var(--t-xl); }
h4 { font-size: var(--t-lg); }

p { margin: 0; text-wrap: pretty; }
p + p { margin-block-start: var(--s-4); }

.lede {
  font-size: var(--t-md);
  line-height: var(--lh-loose);
  color: var(--fg-muted);
  max-inline-size: var(--w-prose);
}

.prose { max-inline-size: var(--w-prose); }
.prose-narrow { max-inline-size: var(--w-narrow); }

/* Tabular figures wherever digits stack in a column: ranks, points, scores,
   seeds, IDs, dates, money. Opt-in, because tabular figures are wrong in
   running prose — the gaps around a "1" look like broken kerning. */
.tnum { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }

.num {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  letter-spacing: var(--track-display);
  line-height: 1;
  color: var(--fg-strong);
}

/* The one label style on the site. It appears inside artefacts as a column
   or field name — never stacked above a section heading as decoration. */
.field-label {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
:root:lang(ar) .field-label { text-transform: none; letter-spacing: 0; }

/* ---------- 3  Layout ---------------------------------------------------- */

.shell {
  inline-size: 100%;
  max-inline-size: var(--w-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.shell--wide { max-inline-size: var(--w-wide); }

.band {
  background: var(--bg);
  color: var(--fg);
  padding-block: var(--band);
  position: relative;
}
.band--lg { padding-block: var(--band-lg); }
.band--sm { padding-block: var(--band-sm); }
.band--flush-top { padding-block-start: 0; }

/* The seam between the two worlds. A hard 1px edge, never a gradient: the
   change of ground carries meaning and a fade would blur it into decoration. */
.band.on-ink + .band.on-paper,
.band.on-paper + .band.on-ink { border-block-start: 1px solid var(--ink-700); }

.stack { display: flex; flex-direction: column; gap: var(--s-5); }
.stack--tight { gap: var(--s-3); }
.stack--loose { gap: var(--s-7); }

.row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-4); }

.split {
  display: grid;
  gap: clamp(var(--s-6), 5vw, var(--s-9));
  align-items: start;
}
@media (min-width: 62rem) {
  .split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: center; }
  .split--even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .split--text-end { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  .split__figure-first { order: -1; }
}

.section-head {
  display: grid;
  gap: var(--s-4);
  max-inline-size: 54ch;
  margin-block-end: var(--s-8);
}
.section-head--wide { max-inline-size: 72ch; }

/* ---------- 4  Header and navigation ------------------------------------ */

.masthead {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  background: var(--ink-950);
  color: var(--ink-fg);
  border-block-end: 1px solid var(--ink-800);
  transition: border-color var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out);
}
.masthead.is-stuck {
  background: rgb(4 12 18 / 0.86);
  backdrop-filter: blur(14px) saturate(1.4);
  border-block-end-color: var(--ink-700);
}

.masthead__inner {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  block-size: var(--header-h);
}

.brand { display: inline-flex; align-items: center; gap: var(--s-3); text-decoration: none; flex-shrink: 0; }

/* The lockup carries its own "for FEDERATIONS", so the header no longer sets a
   product word beside it. That tagline is a sixth of the mark's height, which
   is the proportion the mark was drawn at — 34px is where it stops reading as
   a smear and still leaves air inside a 68px header. */
.brand__mark { block-size: 34px; inline-size: auto; }
.footer .brand__mark { block-size: 42px; }

.nav { display: none; margin-inline-start: auto; }
.nav__list { display: flex; align-items: center; gap: var(--s-2); list-style: none; margin: 0; padding: 0; }
.nav__link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--ink-300);
  text-decoration: none;
  border-radius: var(--r-2);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
  white-space: nowrap;
}
.nav__link:hover { color: var(--ink-050); background: var(--ink-800); }
.nav__link[aria-current="page"] { color: var(--ink-050); }
.nav__link[aria-current="page"]::before {
  content: '';
  inline-size: 5px; block-size: 5px;
  border-radius: 50%;
  background: var(--cyan);
}

/* Menu button for the platform pages. Uses the popover-free details/summary
   pattern so it works with JS off and cannot be clipped by an ancestor. */
.menu { position: relative; }
.menu__panel {
  position: absolute;
  inset-block-start: calc(100% + var(--s-2));
  inset-inline-start: 0;
  inline-size: max-content;
  max-inline-size: min(92vw, 30rem);
  background: var(--ink-900);
  border: 1px solid var(--ink-700);
  border-radius: var(--r-3);
  padding: var(--s-3);
  display: grid;
  gap: 2px;
  box-shadow: 0 24px 48px -24px rgb(0 0 0 / 0.9);
}
.menu[open] .menu__caret { transform: rotate(180deg); }
.menu__caret { transition: transform var(--dur-2) var(--ease-out); }
.menu__item {
  display: grid;
  gap: 2px;
  padding: var(--s-3);
  border-radius: var(--r-2);
  text-decoration: none;
  color: var(--ink-100);
  transition: background-color var(--dur-1) var(--ease-out);
}
.menu__item:hover { background: var(--ink-800); }
.menu__item strong { font-family: var(--font-display); font-size: var(--t-md); font-weight: 600; color: var(--ink-050); }
.menu__item span { font-size: var(--t-sm); color: var(--ink-400); line-height: 1.45; }
summary { cursor: pointer; list-style: none; }
summary::-webkit-details-marker { display: none; }

.masthead__actions { display: flex; align-items: center; gap: var(--s-2); margin-inline-start: auto; }
.nav + .masthead__actions { margin-inline-start: var(--s-4); }

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink-200);
  text-decoration: none;
  border: 1px solid var(--ink-700);
  border-radius: var(--r-2);
  transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.lang-switch:hover { color: var(--ink-050); border-color: var(--ink-500); }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px; block-size: 44px;
  background: none;
  border: 1px solid var(--ink-700);
  border-radius: var(--r-2);
  color: var(--ink-100);
  cursor: pointer;
}
.nav-toggle:hover { border-color: var(--ink-500); }

.nav-drawer {
  display: none;
  border-block-start: 1px solid var(--ink-800);
  background: var(--ink-950);
  padding-block: var(--s-5) var(--s-7);
}
.nav-drawer.is-open { display: block; }
.nav-drawer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.nav-drawer__link {
  display: grid;
  gap: 2px;
  padding: var(--s-4) 0;
  border-block-end: 1px solid var(--ink-800);
  text-decoration: none;
  color: var(--ink-050);
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 600;
}
.nav-drawer__link span { font-family: var(--font-body); font-size: var(--t-sm); font-weight: 400; color: var(--ink-400); }

@media (min-width: 68rem) {
  .nav { display: block; }
  .nav-toggle, .nav-drawer { display: none !important; }
}

/* ---------- 5  Buttons, links, chips ------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-block-size: 46px;
  padding: var(--s-3) var(--s-5);
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: var(--track-tight);
  line-height: 1;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--r-2);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out),
              border-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out),
              transform var(--dur-1) var(--ease-out);
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--cyan); color: var(--ink-950); }
.btn--primary:hover { background: #3FBDE4; }

.btn--outline { border-color: var(--border); color: var(--fg-strong); background: transparent; }
.btn--outline:hover { border-color: var(--accent); color: var(--accent); }

.btn--quiet { padding-inline: 0; color: var(--accent); background: none; min-block-size: 0; }

.btn--sm { min-block-size: 40px; padding: var(--s-2) var(--s-4); font-size: var(--t-sm); }

/* Detail-page links. No arrow glyph appended to the text — the rule under the
   label grows instead, which reads as the record opening rather than as chrome. */
.go {
  display: inline-flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
  text-decoration: none;
  color: var(--accent);
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 600;
  inline-size: fit-content;
}
.go::after {
  content: '';
  display: block;
  block-size: 2px;
  inline-size: 1.75rem;
  background: currentColor;
  transition: inline-size var(--dur-2) var(--ease-out);
}
.go:hover::after { inline-size: 100%; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px var(--s-2);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1.4;
  border-radius: var(--r-1);
  border: 1px solid currentColor;
  white-space: nowrap;
}
.chip::before { content: ''; inline-size: 6px; block-size: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.chip--ok { color: var(--state-ok); }
.chip--pending { color: var(--attention); }
.chip--stop { color: var(--state-stop); }
.chip--live { color: var(--accent); }
.chip--muted { color: var(--fg-muted); }

.dot-live {
  inline-size: 7px; block-size: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  box-shadow: 0 0 0 0 var(--cyan-glow);
  animation: pulse 2.4s var(--ease-in-out) infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgb(16 166 214 / 0.5); }
  60% { box-shadow: 0 0 0 8px rgb(16 166 214 / 0); }
}

/* ---------- 6  Section furniture ---------------------------------------- */

.hero { padding-block: clamp(3rem, 7vw, 5.5rem) clamp(3.5rem, 8vw, 6rem); }
.hero__grid { display: grid; gap: clamp(var(--s-7), 6vw, var(--s-9)); align-items: center; }
@media (min-width: 68rem) {
  .hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
}
.hero h1 { max-inline-size: 15ch; }
.hero .lede { margin-block-start: var(--s-5); }
.hero__actions { margin-block-start: var(--s-7); display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* Page hero for the six detail pages: one ink band, tighter than home. */
.pagehead { padding-block: clamp(2.75rem, 6vw, 4.5rem) clamp(3rem, 6vw, 5rem); }
.pagehead h1 { max-inline-size: 18ch; }
.pagehead__crumb { display: flex; gap: var(--s-2); align-items: center; font-size: var(--t-sm); color: var(--ink-400); margin-block-end: var(--s-5); }
.pagehead__crumb a { text-decoration: none; color: var(--ink-300); }
.pagehead__crumb a:hover { color: var(--cyan); }

/* Counters. The number is the content, so it is set in the display face at a
   size that lets a federation read it across a boardroom table. */
.counters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: 1px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  overflow: hidden;
}
/* Four counters in an auto-fit grid land as three-plus-one and leave a hole
   the hairline draws attention to. Two-up is the only honest arrangement. */
.counters--pairs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.counter { background: var(--bg); padding: var(--s-5); box-shadow: 0 0 0 1px var(--hairline); }
.counter__value { font-size: var(--t-2xl); display: block; }
.counter__value { font-family: var(--font-display); font-weight: 700; color: var(--fg-strong); font-variant-numeric: tabular-nums; line-height: 1; }
.counter__label { display: block; margin-block-start: var(--s-2); font-size: var(--t-sm); color: var(--fg-muted); line-height: 1.45; }

/* Client logos. A marquee only because there are more federations than fit;
   it pauses on hover and on focus, and does not move at all under
   prefers-reduced-motion, where it becomes a plain wrapped row. */
.rail { overflow: hidden; mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent); }
.rail__track { display: flex; gap: clamp(var(--s-6), 5vw, var(--s-9)); inline-size: max-content; animation: rail 46s linear infinite; }
.rail:hover .rail__track, .rail:focus-within .rail__track,
.rail:has(.is-lit) .rail__track { animation-play-state: paused; }
@keyframes rail { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.rail__item { display: flex; align-items: center; gap: var(--s-3); flex-shrink: 0; }
/* Federation crests are dark line art on white. Tinting them for the dark
   ground erases them, so each sits on its own light plate instead — which is
   also how they appear on a federation's own letterhead. Desaturating keeps
   eleven different palettes from reading as confetti; hover restores colour. */
.rail__item img {
  block-size: 58px; inline-size: 58px;
  object-fit: contain;
  padding: 7px;
  border-radius: var(--r-2);
  background: var(--ink-050);
  filter: grayscale(1) contrast(0.9);
  opacity: 0.8;
  transition: filter var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out);
}
/* Colour comes back on hover, on keyboard focus, and on a tap — a touch
   device has no hover, so without the last one half the audience never sees
   a crest in its own colours. site.js sets .is-lit on tap. */
.rail__item:hover img,
.rail__item:focus-visible img,
.rail__item.is-lit img { filter: none; opacity: 1; }
.rail__item:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--r-2); }
a.rail__item { display: flex; }

/* ---------- 7  Artefacts ------------------------------------------------- */

/* Shared shell. Every artefact is a framed record: one hairline border, one
   header strip naming what you are looking at, and tabular content inside. */
.artefact {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  overflow: hidden;
}
.on-ink .artefact { box-shadow: 0 32px 64px -40px rgb(0 0 0 / 0.9); }
.on-paper .artefact { box-shadow: 0 24px 48px -36px rgb(10 21 28 / 0.28); }

.artefact__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-block-end: 1px solid var(--hairline);
  background: var(--bg);
}
.artefact__title {
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
:root:lang(ar) .artefact__title { text-transform: none; letter-spacing: 0; font-size: var(--t-base); }
.artefact__head .chip, .artefact__head .dot-live { margin-inline-start: auto; }
.artefact__body { padding: var(--s-4); }
.artefact__foot {
  padding: var(--s-3) var(--s-4);
  border-block-start: 1px solid var(--hairline);
  font-size: var(--t-xs);
  color: var(--fg-muted);
  background: var(--bg);
}

/* --- Ledger: the hero. An append-only stream of what the federation did
   today. It is the product's audit log, which is a real aggregate and not a
   marketing invention — that is the whole reason it earns the hero slot. */
.ledger__rows { list-style: none; margin: 0; padding: 0; display: grid; }
.ledger__row {
  display: grid;
  grid-template-columns: auto auto 1fr;
  grid-template-areas: 'time mark what' '.  .   meta';
  gap: 2px var(--s-3);
  align-items: baseline;
  padding: var(--s-3) var(--s-4);
  border-block-end: 1px solid var(--hairline);
  font-size: var(--t-sm);
}
.ledger__row:last-child { border-block-end: none; }
.ledger__time { grid-area: time; font-variant-numeric: tabular-nums; color: var(--fg-muted); font-size: var(--t-xs); }
.ledger__mark { grid-area: mark; inline-size: 7px; block-size: 7px; border-radius: 50%; align-self: center; }
.ledger__mark[data-state="ok"] { background: var(--state-ok); }
.ledger__mark[data-state="pending"] { background: var(--attention); }
.ledger__mark[data-state="live"] { background: var(--accent); }
.ledger__what { grid-area: what; color: var(--fg-strong); font-weight: 500; }
.ledger__meta { grid-area: meta; color: var(--fg-muted); font-size: var(--t-xs); display: flex; gap: var(--s-3); flex-wrap: wrap; }
.ledger__ref { font-variant-numeric: tabular-nums; }
@media (min-width: 34rem) {
  .ledger__row { grid-template-columns: auto auto minmax(0, 1fr) auto; grid-template-areas: 'time mark what meta'; align-items: center; }
  .ledger__meta { justify-content: flex-end; text-align: end; }
}

/* --- Approval chain. Click a preset and the chain re-renders: this is the
   single claim the whole product rests on, so the page demonstrates it
   rather than asserting it. */
.chain__presets { display: flex; flex-wrap: wrap; gap: var(--s-2); padding: var(--s-4); border-block-end: 1px solid var(--hairline); }
.preset {
  padding: var(--s-2) var(--s-3);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--fg-muted);
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.preset:hover { color: var(--fg-strong); border-color: var(--border); }
.preset[aria-selected="true"] { color: var(--accent-contrast); background: var(--accent); border-color: var(--accent); }

.chain__track { list-style: none; margin: 0; padding: var(--s-6) var(--s-4); display: grid; gap: 0; }
.chain__node {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: var(--s-4);
  padding-block-end: var(--s-5);
  position: relative;
}
.chain__node:last-child { padding-block-end: 0; }
.chain__node::before {
  content: '';
  position: absolute;
  inset-block: 22px 0;
  inset-inline-start: 10px;
  inline-size: 2px;
  background: var(--hairline);
}
.chain__node:last-child::before { display: none; }
.chain__node[data-state="done"]::before { background: var(--state-ok); }
.chain__dot {
  inline-size: 22px; block-size: 22px;
  border-radius: 50%;
  border: 2px solid var(--hairline);
  background: var(--surface);
  display: grid;
  place-items: center;
  z-index: var(--z-raised);
}
.chain__node[data-state="done"] .chain__dot { border-color: var(--state-ok); background: var(--state-ok); }
.chain__node[data-state="active"] .chain__dot { border-color: var(--attention); box-shadow: 0 0 0 4px var(--amber-glow); }
.chain__dot svg { inline-size: 12px; block-size: 12px; color: var(--surface); }
.chain__body { display: grid; gap: 2px; }
.chain__label { font-family: var(--font-display); font-size: var(--t-md); font-weight: 600; color: var(--fg-strong); line-height: 1.2; }
.chain__meta { font-size: var(--t-sm); color: var(--fg-muted); }
.chain__node[data-state="todo"] .chain__label { color: var(--fg-muted); }

/* --- Ranking table. Every row opens to show why the number is the number:
   the tournaments that counted, the ones that did not, and the rule version
   the release was computed under. */
.ranktable { inline-size: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.ranktable th, .ranktable td { padding: var(--s-3) var(--s-3); text-align: start; border-block-end: 1px solid var(--hairline); }
.ranktable thead th { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--track-wide); color: var(--fg-muted); font-weight: 600; }
:root:lang(ar) .ranktable thead th { text-transform: none; letter-spacing: 0; font-size: var(--t-sm); }
.ranktable td.tnum, .ranktable th.tnum { text-align: end; font-variant-numeric: tabular-nums; }
.ranktable tbody tr { transition: background-color var(--dur-1) var(--ease-out); }
.ranktable tbody tr:hover { background: var(--bg); }
.rank-pos { font-family: var(--font-display); font-size: var(--t-lg); font-weight: 700; color: var(--fg-strong); font-variant-numeric: tabular-nums; }
.rank-move { font-size: var(--t-xs); font-weight: 700; font-variant-numeric: tabular-nums; }
.rank-move[data-dir="up"] { color: var(--state-ok); }
.rank-move[data-dir="down"] { color: var(--state-stop); }
.rank-move[data-dir="flat"] { color: var(--fg-muted); }
.rank-name { color: var(--fg-strong); font-weight: 500; }
.rank-org { display: block; font-size: var(--t-xs); color: var(--fg-muted); }

.why { display: grid; gap: var(--s-3); padding: var(--s-4); background: var(--bg); border: 1px solid var(--hairline); border-radius: var(--r-2); }
.why__rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.why__row { display: flex; gap: var(--s-3); align-items: baseline; font-size: var(--t-sm); }
.why__row span:last-child { margin-inline-start: auto; font-variant-numeric: tabular-nums; color: var(--fg-strong); font-weight: 600; }
.why__row[data-counted="no"] { color: var(--fg-muted); text-decoration: line-through; text-decoration-color: var(--hairline); }
.why__total { display: flex; gap: var(--s-3); align-items: baseline; padding-block-start: var(--s-3); border-block-start: 1px solid var(--hairline); font-weight: 600; color: var(--fg-strong); }
.why__total span:last-child { margin-inline-start: auto; font-variant-numeric: tabular-nums; }

/* --- Draw bracket. Real SVG, drawn once when it scrolls into view. */
.bracket {
  inline-size: 100%; block-size: auto;
  /* The dir="ltr" attribute on the <svg> does nothing: dir is an HTML
     attribute and SVG resolves text placement from the CSS direction
     property, which was inheriting rtl from <html dir="rtl">. That flipped
     every text-anchor, so names ran leftwards out of their seats and the
     round labels fell off the edge. Pin the drawing to ltr here; the names
     inside each seat still shape in their own script. */
  direction: ltr;
}
.bracket text { unicode-bidi: isolate; }
.bracket .line { stroke: var(--hairline); stroke-width: 1.5; fill: none; }
.bracket .line--won { stroke: var(--accent); stroke-width: 2; }
.bracket .seat { fill: var(--bg); stroke: var(--hairline); stroke-width: 1; }
.bracket .seat--won { stroke: var(--accent); }
.bracket text { fill: var(--fg); font-family: var(--font-body); font-size: 11px; }
.bracket .seed { fill: var(--fg-muted); font-variant-numeric: tabular-nums; }
.bracket .score { fill: var(--fg-strong); font-variant-numeric: tabular-nums; font-weight: 600; }

/* --- Member record. The registry entry as a federation actually reads it. */
.record { display: grid; gap: var(--s-4); }
.record__id { display: flex; align-items: center; gap: var(--s-4); }
.record__photo {
  inline-size: 56px; block-size: 56px;
  border-radius: var(--r-2);
  background: var(--panel);
  display: grid; place-items: center;
  color: var(--fg-muted);
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 700;
  flex-shrink: 0;
}
.record__name { display: block; font-family: var(--font-display); font-size: var(--t-lg); font-weight: 600; color: var(--fg-strong); line-height: 1.15; }
.record__sub { display: block; font-size: var(--t-sm); color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.record__fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); gap: var(--s-4) var(--s-5); }
.record__field { display: grid; gap: 3px; }
.record__value { font-size: var(--t-sm); color: var(--fg-strong); font-weight: 500; font-variant-numeric: tabular-nums; }

/* Validity as a bar, not a date string: the question a secretary is actually
   asking is "is she covered on the day of the tournament", not "what is the
   value of valid_to". */
.validity { display: grid; gap: var(--s-2); }
.validity__bar { block-size: 6px; border-radius: var(--r-pill); background: var(--panel); overflow: hidden; }
.validity__fill { block-size: 100%; background: var(--state-ok); border-radius: inherit; }
.validity__scale { display: flex; justify-content: space-between; font-size: var(--t-xs); color: var(--fg-muted); font-variant-numeric: tabular-nums; }

/* --- Officiating slate. Proposed, with the reason attached to each name. */
.slate { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--hairline); }
.slate__row { background: var(--surface); padding: var(--s-3) var(--s-4); display: grid; gap: 3px; }
.slate__top { display: flex; align-items: baseline; gap: var(--s-3); flex-wrap: wrap; }
.slate__role { font-size: var(--t-xs); color: var(--fg-muted); min-inline-size: 7.5rem; }
.slate__name { font-weight: 600; color: var(--fg-strong); }
.slate__why { font-size: var(--t-xs); color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.slate__row .chip { margin-inline-start: auto; }

/* --- Data residency. Region chips with the regime each one answers to. */
.regions { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); gap: 1px; background: var(--bg); border: 1px solid var(--hairline); border-radius: var(--r-3); overflow: hidden; }
.region { background: var(--surface); padding: var(--s-4); display: grid; gap: var(--s-2); box-shadow: 0 0 0 1px var(--hairline); }
.region__place { font-family: var(--font-display); font-size: var(--t-md); font-weight: 600; color: var(--fg-strong); }
.region__law { font-size: var(--t-xs); color: var(--fg-muted); }

/* --- The bidirectional demonstration. The page mirrors a fragment of the
   product on demand, because a claim about RTL that you cannot see is just
   a bullet point. */
.bidi__stage { padding: var(--s-5); background: var(--bg); border-block-end: 1px solid var(--hairline); }
.bidi__frame {
  border: 1px solid var(--hairline);
  border-radius: var(--r-2);
  background: var(--surface);
  padding: var(--s-4);
  display: grid;
  gap: var(--s-3);
  transition: none;
}
.bidi__frame[dir="rtl"] { font-family: 'IBM Plex Sans Arabic', var(--font-body); }
.bidi__bar { display: flex; align-items: center; gap: var(--s-3); }
.bidi__bar .record__photo { inline-size: 38px; block-size: 38px; font-size: var(--t-base); }
.bidi__bar .chip { margin-inline-start: auto; }

/* --- The comparison ledger: what a federation is asked, and what answering
   it costs today. Not a feature table — the left column is questions real
   secretaries get, which is why it lands. */
/* Separators are borders on the rows, not a coloured parent showing through
   1px gaps. The gap trick is fine for a grid whose children never change
   opacity — but these rows fade in one by one, and a transparent child over a
   hairline-coloured parent paints the whole row grey until the fade finishes. */
.questions { display: grid; border-block-start: 1px solid var(--hairline); }
.question {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-5) 0;
  border-block-end: 1px solid var(--hairline);
}
.question__ask { font-family: var(--font-display); font-size: var(--t-lg); font-weight: 600; color: var(--fg-strong); line-height: 1.2; }
.question__answers { display: grid; gap: var(--s-3); }
.answer { display: grid; gap: var(--s-1); font-size: var(--t-sm); }
@media (min-width: 34rem) {
  .answer { grid-template-columns: minmax(0, auto) minmax(0, 1fr); gap: var(--s-2) var(--s-4); align-items: baseline; }
}
.answer__who { font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--track-wide); text-transform: uppercase; min-inline-size: 6.5rem; }
:root:lang(ar) .answer__who { text-transform: none; letter-spacing: 0; font-size: var(--t-sm); }
.answer--before .answer__who { color: var(--fg-muted); }
.answer--before { color: var(--fg-muted); }
.answer--after .answer__who { color: var(--accent); }
.answer--after { color: var(--fg-strong); }
@media (min-width: 54rem) {
  .question { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-6); align-items: start; padding-block: var(--s-6); }
}

/* --- Pillar board. Six entries, deliberately unequal: two carry a working
   artefact, four carry a line and a link. An even grid of identical cards
   would say all six matter the same amount, and they do not. */
.board { display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--hairline); border-radius: var(--r-3); overflow: hidden; }
.board__cell { background: var(--bg); padding: var(--s-5); display: grid; gap: var(--s-4); align-content: start; box-shadow: 0 0 0 1px var(--hairline); }
.board__cell--feature { gap: var(--s-5); }
.board__title { font-family: var(--font-display); font-size: var(--t-xl); font-weight: 700; color: var(--fg-strong); line-height: 1.1; }
.board__cell--feature .board__title { font-size: var(--t-2xl); }
.board__text { color: var(--fg-muted); font-size: var(--t-sm); line-height: 1.6; }
.board__cell--feature .board__text { font-size: var(--t-base); }
@media (min-width: 48rem) {
  .board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 68rem) {
  .board { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .board__cell { grid-column: span 2; padding: var(--s-6); }
  .board__cell--feature { grid-column: span 3; }
}

/* --- Migration ledger: GBA to FMS V2, stated plainly. */
.upgrade { display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--hairline); border-radius: var(--r-3); overflow: hidden; }
.upgrade__row { background: var(--bg); display: grid; gap: var(--s-2); padding: var(--s-4) var(--s-5); box-shadow: 0 0 0 1px var(--hairline); }
.upgrade__then { font-size: var(--t-sm); color: var(--fg-muted); }
.upgrade__now { font-size: var(--t-sm); color: var(--fg-strong); font-weight: 500; }
@media (min-width: 48rem) {
  .upgrade__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-5); align-items: baseline; }
}

/* --- Capability list on the detail pages. A definition list, because that is
   what it is: a name and what it does. */
.caps { display: grid; border-block-start: 1px solid var(--hairline); }
.cap { padding: var(--s-5) 0; display: grid; gap: var(--s-2); border-block-end: 1px solid var(--hairline); }
.cap__name { font-family: var(--font-display); font-size: var(--t-lg); font-weight: 600; color: var(--fg-strong); line-height: 1.2; }
.cap__text { color: var(--fg-muted); font-size: var(--t-sm); line-height: 1.65; max-inline-size: 68ch; }
.cap__note { font-size: var(--t-xs); color: var(--accent); }
@media (min-width: 54rem) {
  .cap { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--s-6); padding-block: var(--s-6); align-items: start; }
  .cap__body { display: grid; gap: var(--s-2); }
}

/* --- Related pages strip. */
.related { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); gap: 1px; background: var(--bg); border: 1px solid var(--hairline); border-radius: var(--r-3); overflow: hidden; }
.related__item { background: var(--bg); padding: var(--s-5); text-decoration: none; display: grid; gap: var(--s-2); align-content: start; transition: background-color var(--dur-1) var(--ease-out); box-shadow: 0 0 0 1px var(--hairline); }
.related__item:hover { background: var(--surface); }
.related__name { font-family: var(--font-display); font-size: var(--t-md); font-weight: 600; color: var(--fg-strong); }
.related__text { font-size: var(--t-sm); color: var(--fg-muted); line-height: 1.55; }

/* ---------- 8  Accordion and tabs --------------------------------------- */

.faq { display: grid; gap: 1px; background: var(--hairline); border-block: 1px solid var(--hairline); }
.faq__item { background: var(--bg); }
.faq__q {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-5) 0;
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 600;
  color: var(--fg-strong);
  cursor: pointer;
  list-style: none;
}
.faq__q::after {
  content: '';
  margin-inline-start: auto;
  inline-size: 14px; block-size: 14px;
  flex-shrink: 0;
  align-self: center;
  background: currentColor;
  color: var(--fg-muted);
  clip-path: polygon(46% 0, 54% 0, 54% 46%, 100% 46%, 100% 54%, 54% 54%, 54% 100%, 46% 100%, 46% 54%, 0 54%, 0 46%, 46% 46%);
  transition: transform var(--dur-2) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.faq__item[open] .faq__q::after { transform: rotate(135deg); color: var(--accent); }
.faq__a { padding-block-end: var(--s-5); color: var(--fg-muted); max-inline-size: 74ch; }

/* ---------- 9  Forms ----------------------------------------------------- */

.form { display: grid; gap: var(--s-5); }
.form__grid { display: grid; gap: var(--s-5); }
@media (min-width: 40rem) { .form__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.field { display: grid; gap: var(--s-2); }
.field--full { grid-column: 1 / -1; }
.field > label { font-size: var(--t-sm); font-weight: 600; color: var(--fg-strong); }
.field__hint { font-size: var(--t-xs); color: var(--fg-muted); }
.field input, .field select, .field textarea {
  inline-size: 100%;
  min-block-size: 48px;
  padding: var(--s-3) var(--s-4);
  font-family: inherit;
  font-size: var(--t-base);
  color: var(--fg-strong);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-2);
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.field textarea { min-block-size: 7.5rem; resize: vertical; line-height: 1.55; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--cyan-glow);
}
.field input::placeholder, .field textarea::placeholder { color: var(--fg-muted); opacity: 1; }
.field select { appearance: none; background-image: none; }

/* ---------- 10  Footer --------------------------------------------------- */

.footer { background: var(--ink-950); color: var(--ink-fg); padding-block: var(--band) var(--s-7); border-block-start: 1px solid var(--ink-800); }
.footer__top { display: grid; gap: var(--s-8); padding-block-end: var(--s-8); border-block-end: 1px solid var(--ink-800); }
@media (min-width: 54rem) { .footer__top { grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr)); gap: var(--s-7); } }
.footer__blurb { color: var(--ink-400); font-size: var(--t-sm); max-inline-size: 38ch; line-height: 1.65; }
.footer__col h3 { font-family: var(--font-body); font-size: var(--t-xs); font-weight: 700; letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--ink-400); margin-block-end: var(--s-4); }
:root:lang(ar) .footer__col h3 { text-transform: none; letter-spacing: 0; font-size: var(--t-sm); }
.footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.footer__col a { color: var(--ink-200); text-decoration: none; font-size: var(--t-sm); transition: color var(--dur-1) var(--ease-out); }
.footer__col a:hover { color: var(--cyan); }
.footer__bottom { display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center; padding-block-start: var(--s-6); font-size: var(--t-xs); color: var(--ink-400); }
.footer__bottom a { color: var(--ink-300); text-decoration: none; }
.footer__bottom a:hover { color: var(--cyan); }
.footer__legal { margin-inline-start: auto; display: flex; gap: var(--s-5); flex-wrap: wrap; }

/* ---------- 11  Motion --------------------------------------------------- */

/* Reveals enhance content that is already there. Without JS the `js` class is
   never set, nothing is hidden, and the page reads exactly the same — which
   also means a headless renderer or a background tab can never ship a blank
   section because a transition did not fire. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-4) var(--ease-out), transform var(--dur-4) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.js .reveal.is-in { opacity: 1; transform: none; }

.js .ledger__row.is-pending { opacity: 0; transform: translateY(-6px); }
.ledger__row { transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out); }

.bracket .line, .bracket .seat {
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
}
.bracket.is-drawn .line, .bracket.is-drawn .seat {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.1s var(--ease-out);
  transition-delay: calc(var(--d, 0) * 90ms);
}
.js .bracket:not(.is-drawn) text { opacity: 0; }
.bracket text { transition: opacity var(--dur-3) var(--ease-out) 700ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .js .ledger__row.is-pending { opacity: 1; transform: none; }
  .rail__track { animation: none; flex-wrap: wrap; inline-size: auto; justify-content: center; }
  .rail { mask-image: none; }
  .js .bracket:not(.is-drawn) text { opacity: 1; }
  .bracket .line, .bracket .seat { stroke-dashoffset: 0; }
}

/* ---------- Utilities ---------------------------------------------------- */

.u-muted { color: var(--fg-muted); }
.u-strong { color: var(--fg-strong); }
.u-accent { color: var(--accent); }
.u-center { text-align: center; }
.u-mt-6 { margin-block-start: var(--s-6); }
.u-mt-7 { margin-block-start: var(--s-7); }
.u-mt-8 { margin-block-start: var(--s-8); }
.u-hairline { border-block-start: 1px solid var(--hairline); }

/* ---------- Additions ---------------------------------------------------- */

.footer__contact { list-style: none; margin: var(--s-5) 0 0; padding: 0; display: grid; gap: var(--s-3); }
.footer__contact a { color: var(--ink-200); text-decoration: none; font-size: var(--t-sm); }
.footer__contact a:hover { color: var(--cyan); }

/* Closing promises next to the final call to action. Three lines, each one a
   commitment we can be held to, which is a different job from a feature list. */
.promises {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  overflow: hidden;
}
.promise { background: var(--bg); padding: var(--s-5); display: grid; gap: var(--s-2); box-shadow: 0 0 0 1px var(--hairline); }
.promise__title { font-family: var(--font-display); font-size: var(--t-md); font-weight: 600; color: var(--fg-strong); }
.promise__text { font-size: var(--t-sm); color: var(--fg-muted); line-height: 1.6; }

/* Form status message. Announced politely, coloured by outcome, never the
   only signal — the wording says what happened on its own. */
.form__status {
  padding: var(--s-3) var(--s-4);
  border: 1px solid currentColor;
  border-radius: var(--r-2);
  font-size: var(--t-sm);
  font-weight: 500;
}
.form__status[data-tone="ok"] { color: var(--state-ok); }
.form__status[data-tone="stop"] { color: var(--state-stop); }
.form__status[data-tone="busy"] { color: var(--fg-muted); }

/* The honeypot. Off-screen rather than display:none, because some bots skip
   anything that is not rendered. Hidden from assistive tech and from tabbing. */
.trap { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); }

/* Two columns of running text, used once — for the founding story, where the
   content really is prose and a card grid would be a lie about its shape. */
.columns { columns: 2; column-gap: clamp(var(--s-6), 5vw, var(--s-8)); }
.columns p { break-inside: avoid; }
.columns p + p { margin-block-start: var(--s-4); }
@media (max-width: 47.99rem) { .columns { columns: 1; } }

/* Sport coverage. Not buttons — they do nothing — so they are a plain list
   with a hairline, sized to be scanned rather than clicked. */
.sports { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s-2); }
.sports li {
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  color: var(--fg-muted);
}
.sports li[data-live="yes"] { color: var(--fg-strong); border-color: var(--border); }

/* Definition lists carry a UA indent that fights the grid. */
.caps dd { margin: 0; }
.cap__body { display: grid; gap: var(--s-2); }

/* An artefact nested inside a board cell is a framed table, not a second card.
   Dropping the shadow is what keeps it from reading as a card-in-a-card. */
.board__cell .artefact { box-shadow: none; }

/* The board: two features on the first row, four short entries on the second. */
@media (min-width: 48rem) {
  .board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .board__cell { grid-column: span 1; }
  .board__cell--feature { grid-column: span 2; }
}
@media (min-width: 68rem) {
  .board { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .board__cell { grid-column: span 1; padding: var(--s-6); }
  .board__cell--feature { grid-column: span 2; }
}

/* Demo page: the form and the reassurance sit side by side, form first on a
   phone because that is what the visitor came to do. */
.demo-grid { display: grid; gap: clamp(var(--s-7), 6vw, var(--s-9)); align-items: start; }
@media (min-width: 62rem) { .demo-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); } }



/* A tick belongs on a step that is done. The other two states are carried by
   the ring — an amber halo for the step waiting on someone, a plain outline
   for the step that has not been reached. */
.chain__node:not([data-state="done"]) .chain__dot svg { display: none; }


/* The upgrade ledger names its two columns once, at the top, where a table
   names its columns. Repeating the pair on all six rows was six times the
   label for the same information. On a phone the columns stack, so the
   header no longer describes anything and the per-row labels come back. */
.upgrade__head { display: none; }
.upgrade__row .field-label { display: block; margin-block-end: 2px; }
@media (min-width: 48rem) {
  .upgrade__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--s-5);
    background: var(--surface);
    padding: var(--s-3) var(--s-5);
  }
  .upgrade__row .field-label { display: none; }
}

/* Three closing promises side by side rather than a column with a gap
   beside it. */
.promises--row { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }

/* Which sports are running today, said once. */
.sports-legend { display: flex; flex-wrap: wrap; gap: var(--s-4); font-size: var(--t-xs); color: var(--fg-muted); }
.sports-legend span { display: inline-flex; align-items: center; gap: var(--s-2); }
.sports-legend span::before {
  content: '';
  inline-size: 14px; block-size: 8px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
}
.sports-legend span:first-child::before { border-color: var(--border); }

/* On a narrow phone the header cannot carry the brand, a language switch, a
   call to action and a menu button at once — something gets pushed off the
   edge, and it was the menu button. The call to action goes: it is the first
   item in the drawer, it repeats at the foot of every section, and losing the
   way into the menu is worse than losing one of five routes to the same page. */
@media (max-width: 33.99rem) {
  .masthead__inner { gap: var(--s-3); }
  .masthead__actions .btn { display: none; }
  .brand__mark { block-size: 28px; }
}

/* The hero splits only when both halves have room. At 1100px the ledger was
   wrapping every row onto two lines, which is exactly the thing it is there
   to prove does not happen. */
@media (min-width: 68rem) and (max-width: 74.99rem) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); }
  .hero h1 { max-inline-size: 20ch; }
}


/* A results table is the one thing on this site that is allowed to be wider
   than the phone holding it. Squeezing "L. Al-Harbi" onto three lines to
   avoid a scrollbar makes the table less readable, not more, so it scrolls
   sideways inside its own frame instead — reachable by keyboard, and the
   page itself never scrolls horizontally. */
.scroll-x {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}
.scroll-x > table { min-inline-size: 32rem; }
.scroll-x:focus-visible { outline-offset: -2px; }

/* Descriptive metadata in an artefact header is not a status. A chip promises
   a state, refuses to wrap, and got clipped on a phone; this is just the
   caption saying which release you are looking at. */
.artefact__meta {
  margin-inline-start: auto;
  font-size: var(--t-xs);
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
  text-align: end;
}



/* Why the cells draw their own hairline instead of the container painting one
   through 1px gaps: a grid whose items do not fill the last row leaves the
   container's colour exposed, and six regions in a five-column grid produced a
   grey slab where the sixth row's empty cells were. A ring on each cell lands
   in the same 1px gutter, adjacent rings overlap into one crisp line, and the
   leftover space stays the section's own background. It also means a cell can
   fade in without flashing the parent's colour underneath. */
.regions { grid-template-columns: 1fr; }
@media (min-width: 34rem) { .regions { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .regions { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.regions--wide { grid-template-columns: 1fr; }
@media (min-width: 34rem) { .regions--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .regions--wide { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ---------- Ten languages ------------------------------------------------

   German and French set 20–30% longer than English, Finnish and Hungarian
   longer still, and compounds like "Wettkampfgenehmigung" do not break at a
   space. None of the controls below may assume the English width.
   ------------------------------------------------------------------------- */

/* Buttons grow downward, never sideways off the edge, and their label is
   allowed to take two lines rather than overflow. */
.btn {
  block-size: auto;
  white-space: normal;
  text-align: center;
  text-wrap: balance;
  hyphens: auto;
  max-inline-size: 100%;
}

/* Long compounds are permitted to break rather than push a column open. */
.board__title, .cap__name, .promise__title, .question__ask, .related__name,
.nav-drawer__link, .counter__label, .chain__label, .region__place, .lede, h1, h2, h3, h4 {
  overflow-wrap: break-word;
}
h1, h2, h3 { hyphens: auto; }

/* Grid children default to min-content width, which is what makes a long
   German word widen its column and shove the layout sideways. */
.split > *, .board__cell, .cap, .question, .promise, .region, .related__item,
.counter, .upgrade__row, .hero__grid > * { min-inline-size: 0; }

/* The desktop navigation carries more words in some languages than others.
   Rather than pick a breakpoint that works for English and breaks for German,
   the bar is allowed to shrink its own type and spacing before the drawer
   takes over. */
@media (min-width: 68rem) and (max-width: 84rem) {
  .nav__list { gap: 0; }
  .nav__link { padding-inline: var(--s-2); font-size: var(--t-xs); }
  .lang-switch__label { display: none; }
}

/* The language picker. Ten entries, listed by endonym, because a reader
   looking for their own language scans for "Deutsch", never for "German". */
.lang__panel {
  inline-size: max-content;
  max-inline-size: min(92vw, 26rem);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px;
  inset-inline-start: auto;
  inset-inline-end: 0;
}
.lang__item {
  padding: var(--s-3);
  border-radius: var(--r-2);
  text-decoration: none;
  color: var(--ink-100);
  font-size: var(--t-sm);
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.lang__item:hover { background: var(--ink-800); color: var(--ink-050); }
.lang__item[aria-current="true"] { color: var(--cyan); font-weight: 600; }

.footer__langs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  padding-block: var(--s-6);
  border-block-start: 1px solid var(--ink-800);
}
.footer__langs a { color: var(--ink-400); text-decoration: none; font-size: var(--t-sm); }
.footer__langs a:hover { color: var(--cyan); }
.footer__langs a[aria-current="true"] { color: var(--ink-050); }

/* ---------- The stage ----------------------------------------------------

   The animated backdrop behind the hero and behind two of the ink bands.

   It is drawn rather than filmed. A background video for a hero is typically
   4–15 MB before it says anything, it stalls on the mobile data a federation
   secretary is actually on, and it cannot be recoloured for a white-label
   tenant. This costs nothing to download, adapts to the palette, and stops
   completely under prefers-reduced-motion.

   If you do want footage, drop a file in and set HERO_VIDEO in build.mjs: the
   <video> layer sits underneath everything here and simply takes over.

   Four layers, back to front:
     video    optional footage
     aurora   three slow cyan/amber light fields
     lattice  a canvas drawing draw-sheet columns that keep forming
     veil     a scrim that guarantees the headline's contrast
   ------------------------------------------------------------------------- */

.stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: var(--z-base);
  pointer-events: none;
  contain: strict;
}

.stage__video {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  opacity: 0.35;
  filter: saturate(0.6) contrast(1.05);
}

.stage__aurora { position: absolute; inset: -20%; }
.stage__aurora i {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(60px);
  will-change: transform;
  opacity: 1;
  mix-blend-mode: screen;
}
.stage__aurora i:nth-child(1) {
  inline-size: 58vw; block-size: 58vw;
  inset-block-start: -14%; inset-inline-start: 2%;
  background: radial-gradient(circle, rgb(16 166 214 / 0.85), rgb(9 111 158 / 0.35) 42%, transparent 70%);
  animation: drift-a 34s var(--ease-in-out) infinite alternate;
}
.stage__aurora i:nth-child(2) {
  inline-size: 46vw; block-size: 46vw;
  inset-block-end: -18%; inset-inline-end: 0%;
  background: radial-gradient(circle, rgb(249 170 51 / 0.5), rgb(249 170 51 / 0.16) 45%, transparent 70%);
  animation: drift-b 44s var(--ease-in-out) infinite alternate;
}
.stage__aurora i:nth-child(3) {
  inline-size: 62vw; block-size: 42vw;
  inset-block-start: 18%; inset-inline-start: 34%;
  background: radial-gradient(circle, rgb(56 200 240 / 0.5), rgb(16 166 214 / 0.2) 45%, transparent 72%);
  animation: drift-c 52s var(--ease-in-out) infinite alternate;
}
@keyframes drift-a { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(9%, 7%, 0) scale(1.18); } }
@keyframes drift-b { from { transform: translate3d(0,0,0) scale(1.1); } to { transform: translate3d(-11%, -8%, 0) scale(0.92); } }
@keyframes drift-c { from { transform: translate3d(0,0,0) scale(0.95); } to { transform: translate3d(-7%, 10%, 0) scale(1.16); } }

.stage__lattice { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; opacity: 0.9; }

/* The scrim is what lets the headline sit on a moving background and still
   measure past 4.5:1. It is heaviest at the reading edge and clears toward
   the far side, and it mirrors with the document direction. */
.stage__veil {
  position: absolute;
  inset: 0;
  background:
    /* A pool of ink under the headline, so the type keeps its contrast
       wherever the light field happens to drift. */
    radial-gradient(120% 90% at var(--veil-at, 22% 46%), rgb(4 12 18 / 0.94), rgb(4 12 18 / 0.55) 42%, transparent 72%),
    /* The seam into the next section, which has to be a clean edge. */
    linear-gradient(to bottom, rgb(4 12 18 / 0.45), transparent 26%, transparent 74%, rgb(4 12 18 / 0.92));
}
:root[dir="rtl"] .stage__veil { --veil-at: 78% 46%; }
@media (max-width: 67.99rem) {
  .stage__veil { --veil-at: 50% 38%; }
  :root[dir="rtl"] .stage__veil { --veil-at: 50% 38%; }
}

/* Content sits above the stage without needing a z-index race. */
.band > .shell { position: relative; z-index: var(--z-raised); }

/* The hero is a full viewport statement, not a banner. It stops short of a
   whole screen on desktop so the section beneath is visibly there — a hero
   that fills the fold exactly reads as a dead end. */
.hero {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
  min-block-size: min(88svh, 940px);
  padding-block: clamp(4rem, 9vw, 7rem) clamp(4rem, 9vw, 7rem);
  overflow: hidden;
}
.hero h1 { max-inline-size: 16ch; text-shadow: 0 2px 30px rgb(4 12 18 / 0.5); }

/* A quiet cue that there is more below, on the hero only. */
.hero__more {
  position: absolute;
  inset-block-end: var(--s-5);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: var(--z-raised);
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  font-size: var(--t-xs);
  color: var(--ink-400);
  text-decoration: none;
}
.hero__more::after {
  content: '';
  inline-size: 1px;
  block-size: 26px;
  background: linear-gradient(to bottom, var(--ink-500), transparent);
  animation: reach 2.6s var(--ease-in-out) infinite;
}
@keyframes reach { 0%, 100% { transform: scaleY(0.55); opacity: 0.4; } 50% { transform: scaleY(1); opacity: 1; } }
@media (max-width: 47.99rem) { .hero__more { display: none; } }

/* The ledger lifts off the moving backdrop rather than sitting flat on it. */
.hero .artefact {
  background: rgb(10 21 28 / 0.82);
  backdrop-filter: blur(18px) saturate(1.3);
  border-color: rgb(87 101 109 / 0.5);
  box-shadow: 0 40px 80px -40px rgb(0 0 0 / 0.95), 0 0 0 1px rgb(16 166 214 / 0.08);
}
.hero .artefact__head, .hero .artefact__foot { background: rgb(4 12 18 / 0.5); }

/* The lighter variant, for ink bands that want depth but not a performance. */
.band--staged { position: relative; isolation: isolate; overflow: hidden; }
.band--staged .stage__aurora i { opacity: 0.55; filter: blur(100px); }
.band--staged .stage__veil {
  background: linear-gradient(to bottom, rgb(4 12 18 / 0.9), rgb(4 12 18 / 0.6) 45%, rgb(4 12 18 / 0.9));
}

@media (prefers-reduced-motion: reduce) {
  .stage__aurora i { animation: none; }
  .stage__lattice { display: none; }
  .hero__more::after { animation: none; }
  .stage__video { display: none; }
}

/* Reach figures: four numbers that carry the platform's span. Set large in the
   display face because the number is the argument, with the qualifier beneath
   it so nobody has to take "30+" on trust. */
.figures {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}
.figure {
  background: var(--bg);
  box-shadow: 0 0 0 1px var(--hairline);
  padding: var(--s-6) var(--s-5);
  display: grid;
  gap: var(--s-2);
  align-content: start;
  min-inline-size: 0;
}
.figure__value {
  font-family: var(--font-display);
  font-size: var(--t-3xl);
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--track-display);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.figure__label {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 600;
  color: var(--fg-strong);
  line-height: 1.15;
}
.figure__note { font-size: var(--t-sm); color: var(--fg-muted); line-height: 1.6; }

/* The ten languages, listed in full where the claim is made — a number is a
   claim, a list of endonyms is evidence. */
.lang-grid { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.lang-grid a {
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  color: var(--fg-muted);
  text-decoration: none;
  transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.lang-grid a:hover { color: var(--fg-strong); border-color: var(--border); }
.lang-grid a[aria-current="true"] { color: var(--accent); border-color: var(--accent); }

/* Japanese and Chinese do not put spaces between words, so the break-word rule
   that rescues a long German compound will happily split a CJK phrase in half
   — "連盟が決めたこ / とすべてを" is not a line break, it is a mistake. These
   scripts get the browser's own line-breaking rules instead, and where the
   engine supports it, phrase-aware breaking for Japanese. */
:root:lang(ja) :where(h1, h2, h3, h4, .board__title, .cap__name, .promise__title, .question__ask, .lede, .figure__label),
:root:lang(zh-Hans) :where(h1, h2, h3, h4, .board__title, .cap__name, .promise__title, .question__ask, .lede, .figure__label) {
  overflow-wrap: normal;
  word-break: auto-phrase;
  line-break: strict;
  hyphens: none;
}
/* Devanagari joins letters with a shirorekha; breaking inside a word cuts the
   line that holds it together. */
:root:lang(hi) :where(h1, h2, h3, h4, .board__title, .cap__name, .promise__title, .question__ask) {
  overflow-wrap: normal;
  hyphens: none;
}

/* A single artefact with nothing beside it should not run the full content
   width — a framed record stretched to 1180px stops reading as an object. */
.artefact--centred { max-inline-size: 44rem; margin-inline: auto; }

/* ---------- The federation's own site --------------------------------------

   The website page used to show a palette of the sixteen content blocks the
   site can be built from, which is a feature list drawn as a diagram. What the
   page is selling is simpler and harder to fake: the public site and the office
   are reading the same numbers. So it shows the site, with the rankings on it
   marked live.
   ------------------------------------------------------------------------- */

.sitepreview {
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  overflow: hidden;
  background: var(--bg);
}
.sitepreview__chrome {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--s-3) var(--s-4);
  background: var(--surface);
  border-block-end: 1px solid var(--hairline);
}
.sitepreview__chrome > span { inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--hairline); }
.sitepreview__domain {
  inline-size: auto !important;
  block-size: auto !important;
  border-radius: var(--r-pill) !important;
  background: var(--bg) !important;
  border: 1px solid var(--hairline);
  padding: 3px var(--s-4);
  margin-inline-start: var(--s-3);
  font-size: var(--t-xs);
  color: var(--fg-muted);
  flex: 1;
}
.sitepreview__page { padding: var(--s-4); display: grid; gap: var(--s-3); }
.sitepreview__masthead { display: flex; align-items: center; gap: var(--s-3); }
.sitepreview__masthead i { block-size: 6px; inline-size: 42px; border-radius: 3px; background: var(--hairline); }
.sitepreview__logo { inline-size: 26px !important; block-size: 18px !important; border-radius: var(--r-2) !important; background: var(--accent) !important; margin-inline-end: auto; }
.sitepreview__banner {
  block-size: 74px;
  border-radius: var(--r-2);
  background:
    radial-gradient(120% 140% at 18% 30%, rgb(16 166 214 / 0.22), transparent 60%),
    radial-gradient(100% 120% at 85% 80%, rgb(249 170 51 / 0.16), transparent 60%),
    var(--panel);
}
.sitepreview__panel { border: 1px solid var(--hairline); border-radius: var(--r-2); overflow: hidden; }
.sitepreview__panelhead {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--surface);
  border-block-end: 1px solid var(--hairline);
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--fg-strong);
}
.sitepreview__live {
  margin-inline-start: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--accent);
}
.sitepreview__row {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-2) var(--s-4);
  border-block-end: 1px solid var(--hairline);
  font-size: var(--t-sm);
}
.sitepreview__row:last-child { border-block-end: none; }
.sitepreview__pos { font-family: var(--font-display); font-weight: 700; color: var(--fg-muted); min-inline-size: 1.2em; }
.sitepreview__who { color: var(--fg-strong); }
.sitepreview__pts { margin-inline-start: auto; color: var(--fg-muted); }

/* ---------- Case studies --------------------------------------------------

   Three components, one subject, three jobs.

   .studycard  the home page. Two of them, each a link to a study. It leads
               with the crest and the association because that is what gets
               recognised, then one number, then the sentence the secretary
               actually said. Nothing else: the card is an invitation, not the
               study.

   .studyrow   the index at /case-studies/. Wider, quieter, and carrying all of
               a study's numbers, because here the reader is choosing between
               studies rather than being told there are some.

   .studyhead  the study's own page. The association set as the subject of the
               page rather than as a logo in someone else's section.

   Both cards are links by way of a stretched pseudo-element on the heading's
   anchor rather than by wrapping the whole card in one: a link whose
   accessible name is four sentences of testimonial is unusable in a screen
   reader's link list, and two links both called "Read the case study" name
   neither of the pages they open. The name is the association; the arrow and
   the hover state are for the eye. */

.studies-head {
  display: grid;
  gap: var(--s-5);
  margin-block-end: var(--s-8);
}
.studies-head .section-head { margin-block-end: 0; }
@media (min-width: 62rem) {
  .studies-head {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: var(--s-8);
  }
}

.studycards {
  display: grid;
  gap: var(--s-5);
}
@media (min-width: 58rem) {
  .studycards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.studycard {
  position: relative;
  /* Flex rather than grid so the two cards, which carry quotes of different
     lengths, still line their "read the case study" up with each other: the
     cue takes an auto top margin and the slack collects above it. */
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  padding: var(--s-6);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  background: var(--surface);
  min-inline-size: 0;
  /* The top edge lights up on hover rather than the whole card lifting: these
     sit on the dark band, where a shadow has nothing to fall on. */
  transition: border-color var(--dur-2) var(--ease-out),
              background-color var(--dur-2) var(--ease-out),
              transform var(--dur-2) var(--ease-out);
}
.studycard::before {
  content: '';
  position: absolute;
  inset-block-start: -1px;
  inset-inline: -1px;
  block-size: 2px;
  border-start-start-radius: var(--r-3);
  border-start-end-radius: var(--r-3);
  background: var(--accent);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out);
}
.studycard:hover,
.studycard:focus-within {
  border-color: var(--border);
  background: var(--panel);
  transform: translateY(-2px);
}
.studycard:hover::before,
.studycard:focus-within::before { opacity: 1; }

.studycard__head { display: flex; align-items: center; gap: var(--s-4); }
/* The crests arrive at every aspect ratio their association drew them at, so
   the box is fixed and the image is fitted inside it rather than stretched. */
.studycard__crest {
  inline-size: 52px;
  block-size: 52px;
  object-fit: contain;
  flex-shrink: 0;
}
.studycard__id { min-inline-size: 0; }
.studycard__org {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 600;
  line-height: 1.15;
  color: var(--fg-strong);
  overflow-wrap: break-word;
}
.studycard__link { text-decoration: none; color: inherit; }
/* The whole card is the click target; the anchor is still only the name. */
.studycard__link::after { content: ''; position: absolute; inset: 0; border-radius: var(--r-3); }
.studycard:hover .studycard__org { color: var(--accent); }
.studycard__meta,
.studyrow__meta,
.studyhead__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-3);
  margin-block-start: var(--s-1);
  font-size: var(--t-xs);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
:root:lang(ar) .studycard__meta,
:root:lang(ar) .studyrow__meta,
:root:lang(ar) .studyhead__meta { text-transform: none; letter-spacing: 0; font-size: var(--t-sm); }
.studycard__meta > span + span::before,
.studyrow__meta > span + span::before,
.studyhead__meta > span + span::before { content: "·"; margin-inline-end: var(--s-3); }

/* One number, set at the size the number deserves. The label underneath is
   what stops "₹10M" being a claim nobody can place. */
.studycard__stat {
  display: grid;
  gap: var(--s-2);
  padding-block: var(--s-4);
  border-block: 1px solid var(--hairline);
}
.studycard__value {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--track-display);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.studycard__unit { font-size: var(--t-sm); color: var(--fg-muted); line-height: 1.5; }

.studycard__quote {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 500;
  line-height: 1.45;
  color: var(--fg-strong);
  text-wrap: pretty;
}
.studycard__quote::before { content: '“'; }
.studycard__quote::after { content: '”'; }

.studycard__by { display: grid; gap: 2px; font-size: var(--t-sm); }
.studycard__name { font-weight: 600; color: var(--fg-strong); }
.studycard__role { color: var(--fg-muted); }

.studycard__cue,
.studyrow__cue {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--accent);
}
:root:lang(ar) .studycard__cue,
:root:lang(ar) .studyrow__cue { text-transform: none; letter-spacing: 0; }
/* After the shorthand above, not before it: the slack in a card whose quote
   runs a line shorter collects here, so the two cues line up with each other. */
.studycard__cue { margin-block-start: auto; }
.studycard__cue svg,
.studyrow__cue svg,
.nextstudy__arrow { transition: transform var(--dur-2) var(--ease-out); }
:root[dir="rtl"] .studycard__cue svg,
:root[dir="rtl"] .studyrow__cue svg,
:root[dir="rtl"] .nextstudy__arrow { transform: scaleX(-1); }
.studycard:hover .studycard__cue svg,
.studyrow:hover .studyrow__cue svg { transform: translateX(4px); }
:root[dir="rtl"] .studycard:hover .studycard__cue svg,
:root[dir="rtl"] .studyrow:hover .studyrow__cue svg { transform: scaleX(-1) translateX(4px); }

/* ---------- The index of case studies ------------------------------------ */

.studyrows { display: grid; gap: var(--s-6); }

.studyrow {
  position: relative;
  display: grid;
  gap: var(--s-6);
  align-items: start;
  padding: var(--s-6);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  background: var(--bg);
  min-inline-size: 0;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.studyrow:hover,
.studyrow:focus-within {
  border-color: var(--border);
  box-shadow: 0 24px 48px -40px rgb(10 21 28 / 0.45);
}
@media (min-width: 64rem) {
  .studyrow { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-8); padding: var(--s-7); }
}

.studyrow__lede { display: grid; gap: var(--s-5); align-content: start; min-inline-size: 0; }
.studyrow__head { display: flex; align-items: center; gap: var(--s-4); }
.studyrow__crest { inline-size: 64px; block-size: 64px; object-fit: contain; flex-shrink: 0; }
.studyrow__org {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: 600;
  line-height: 1.1;
  color: var(--fg-strong);
  overflow-wrap: break-word;
}
.studyrow__link { text-decoration: none; color: inherit; }
.studyrow__link::after { content: ''; position: absolute; inset: 0; border-radius: var(--r-3); }
.studyrow:hover .studyrow__org { color: var(--accent); }
.studyrow__teaser { margin: 0; color: var(--fg-muted); line-height: 1.65; text-wrap: pretty; }

/* The numbers carry the whole right-hand column, so they are allowed to reflow
   from three across to one — a figure squeezed to fit is a figure nobody
   reads. The odd one out takes the full row rather than leaving a bordered
   hole where a fourth would go. */
.studyrow__metrics { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 40rem) {
  .studyrow__metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.studyrow__metrics .figure { padding: var(--s-5); }
.studyrow__metrics .figure__value { font-size: var(--t-2xl); }
.studyrow__metrics .figure__label { font-size: var(--t-md); }
.studyrow__metrics .figure:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* ---------- A study's own page ------------------------------------------- */

.studyhead { padding-block: clamp(2.5rem, 5.5vw, 4rem) clamp(3rem, 6vw, 5rem); }
.studyhead__id { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; }
.studyhead__crest { inline-size: 72px; block-size: 72px; object-fit: contain; flex-shrink: 0; }
.studyhead h1 { max-inline-size: 20ch; font-size: var(--t-3xl); }
.studyhead__metrics { margin-block-start: var(--s-7); }
/* A study with one number would otherwise stretch it across the full width of
   the page, which reads as a figure with three siblings missing. */
.studyhead__metrics:has(.figure:only-child) { max-inline-size: 40rem; }
.studyhead .hero__actions { margin-block-start: var(--s-7); }

/* Before and after, at the same weight. The association reading this
   recognises itself in the left-hand column, and shrinking it would be
   arguing with them. The accent rule marks which one is the after without
   making the before look like a mistake. */
.prospect { display: grid; gap: var(--s-6); }
@media (min-width: 60rem) {
  .prospect { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-7); }
}
.prospect__side {
  display: grid;
  gap: var(--s-4);
  align-content: start;
  padding: var(--s-6);
  border-radius: var(--r-3);
  background: var(--surface);
  border-inline-start: 3px solid var(--hairline);
  min-inline-size: 0;
}
.prospect__side--before { border-inline-start-color: var(--border); }
.prospect__side--after { border-inline-start-color: var(--accent); }
.prospect__label {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
:root:lang(ar) .prospect__label { text-transform: none; letter-spacing: 0; font-size: var(--t-sm); }
.prospect__side--after .prospect__label { color: var(--accent); }
.prospect__text { margin: 0; font-size: var(--t-md); line-height: 1.65; color: var(--fg); text-wrap: pretty; }
.prospect__side--after .prospect__text { color: var(--fg-strong); }

/* The quote is the loudest thing on the study page, on purpose: it is the one
   part a reader believes without checking, and burying it under a metric grid
   is how a testimonial ends up read as marketing. */
.pullquote { margin: 0; display: grid; gap: var(--s-6); }
.pullquote__text {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: 500;
  line-height: 1.35;
  color: var(--fg-strong);
  text-wrap: pretty;
}
.pullquote__text::before { content: '“'; }
.pullquote__text::after { content: '”'; }
.pullquote__by { display: flex; align-items: center; gap: var(--s-4); font-size: var(--t-sm); }
.pullquote__crest { inline-size: 44px; block-size: 44px; object-fit: contain; flex-shrink: 0; }
.pullquote__name { display: block; font-weight: 600; color: var(--fg-strong); }
.pullquote__role { display: block; color: var(--fg-muted); }

/* Where a reader goes at the end of a study: the other one. */
.nextstudy {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-block-start: var(--s-4);
  padding: var(--s-5);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  text-decoration: none;
  background: var(--bg);
  transition: border-color var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out);
}
.nextstudy:hover { border-color: var(--border); background: var(--surface); }
.nextstudy__crest { inline-size: 52px; block-size: 52px; object-fit: contain; flex-shrink: 0; }
.nextstudy__body { display: grid; gap: 2px; min-inline-size: 0; }
.nextstudy__org {
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--fg-strong);
  overflow-wrap: break-word;
}
.nextstudy__meta { font-size: var(--t-sm); color: var(--fg-muted); }
.nextstudy__arrow { margin-inline-start: auto; color: var(--accent); flex-shrink: 0; }
.nextstudy:hover .nextstudy__arrow { transform: translateX(4px); }
:root[dir="rtl"] .nextstudy:hover .nextstudy__arrow { transform: scaleX(-1) translateX(4px); }

/* ---------- Quoted officers ----------------------------------------------

   The quote cards on the index, which are testimonials rather than studies:
   no association crest, no numbers, just what was said and who said it. */

.quotecard {
  display: grid;
  gap: var(--s-4);
  margin: 0;
  padding: var(--s-6);
  border-radius: var(--r-3);
  background: var(--surface);
  border: 1px solid var(--hairline);
}
.quotecard__text {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 500;
  line-height: 1.45;
  color: var(--fg-strong);
  text-wrap: pretty;
}
.quotecard__text::before { content: '“'; }
.quotecard__text::after { content: '”'; }
.quotecard__by {
  display: grid;
  gap: 2px;
  padding-block-start: var(--s-4);
  border-block-start: 1px solid var(--hairline);
  font-size: var(--t-sm);
}
.quotecard__name { font-weight: 600; color: var(--fg-strong); }
.quotecard__role { color: var(--fg-muted); }

.voices { display: grid; gap: var(--s-5); list-style: none; margin: 0; padding: 0; }
@media (min-width: 54rem) {
  .voices { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 86rem) {
  .voices { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Long compounds are permitted to break rather than push a card open. */
.studycard, .studyrow, .prospect__side, .nextstudy, .quotecard { min-inline-size: 0; }
