/* darrell.sg — polish & consistency pass (2026-10-18)
   ─────────────────────────────────────────────────────────────────────────────
   One reviewable override file. Loaded AFTER site.css (and after pages.css on booking.html / 404.html),
   so every rule here wins over an equal-specificity rule there, including rules inside site.css /
   pages.css media queries. Section letters mirror the build spec (1, A–I).

   Cascade guards: a base override here would also beat the existing <=1100 / <=900 / <=760 / <=640 /
   <=420 / <=400 / reduced-motion rules in site.css and pages.css. Every responsive rule therefore lives
   in section Z at the end of this file (after all base overrides), and restates the phone/tablet values
   the original files intended. Spec items J (HTML glyph edits) are not part of this file.

   No new libraries, fonts, filters, blurs, keyframes, continuous animation or will-change. Colours are
   aliases of values already used in site.css. Hero rules (.hero*) and the desktop nav are untouched, except
   the approved opening sequence (section O). */


/* ════════════════════════════════════════════════════════════════════════════
   1. TOKENS
   ════════════════════════════════════════════════════════════════════════════ */
:root {
  /* spacing: 4px base */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 20px; --s-6: 24px;
  --s-8: 32px; --s-10: 40px; --s-12: 48px; --s-16: 64px; --s-20: 80px; --s-24: 96px;
  /* one fluid ramp: 0 at a 390px viewport, 1px at 1352px (where .wrap reaches 1240px); clamp() freezes it,
     so 1440 and 1920 get identical whole-number spacing (the content width is identical there) */
  --fluid: calc((100vw - 390px) / 962);
  --section-pt: clamp(64px, calc(64px + 32 * var(--fluid)), 96px);
  --section-pb: clamp(80px, calc(80px + 48 * var(--fluid)), 128px);
  --head-gap:   clamp(48px, calc(48px + 32 * var(--fluid)), 80px);
  --sub-gap:    clamp(64px, calc(64px + 32 * var(--fluid)), 96px);
  --band-pad:   clamp(128px, calc(128px + 64 * var(--fluid)), 192px);
  --split:      clamp(40px, calc(40px + 40 * var(--fluid)), 80px);
  --split-card: clamp(24px, calc(24px + 24 * var(--fluid)), 48px);
  --tl-gap:     clamp(20px, calc(20px + 12 * var(--fluid)), 32px);
  --grid-gap: 16px;
  /* card padding (390 -> 1352+) */
  --pad-nested:  clamp(16px, calc(16px + 4 * var(--fluid)), 20px);
  --pad-compact: clamp(20px, calc(20px + 4 * var(--fluid)), 24px);
  --pad-card:    clamp(24px, calc(24px + 8 * var(--fluid)), 32px);
  --pad-feature: clamp(24px, calc(24px + 24 * var(--fluid)), 48px);
  /* radii */
  --r-sm: 10px; --r-md: 14px; --r-lg: 20px; --r-xl: 28px; --r-pill: 999px;
  /* surfaces */
  --surface-1: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.012));
  --shadow-1: inset 0 1px 0 rgba(255, 255, 255, 0.045), 0 40px 80px -50px rgba(0, 0, 0, 0.9);
  --shadow-2: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 60px 120px -60px rgba(0, 0, 0, 0.95);
  --shadow-lift: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 34px 70px -34px rgba(0, 0, 0, 0.95), 0 0 50px -14px rgba(214, 178, 110, 0.28);
  --well: rgba(255, 255, 255, 0.025);
  /* gold alphas */
  --gold-line: rgba(214, 178, 110, 0.22);       /* passive outlines: featured cards, tags, awards, gold wells */
  --gold-line-2: rgba(214, 178, 110, 0.35);     /* badges, icon tiles, outline tags, interactive rest */
  --gold-line-hover: rgba(214, 178, 110, 0.55); /* controls on hover */
  --gold-fill: rgba(214, 178, 110, 0.06);
  --gold-fill-hover: rgba(214, 178, 110, 0.12);
  --card-hover: rgba(214, 178, 110, 0.26);      /* info cards */
  --featured-hover: rgba(214, 178, 110, 0.36);  /* featured info cards */
  --link-card-hover: rgba(214, 178, 110, 0.42); /* whole-card links */
  /* pills (labels) and controls */
  --pill-xs: 20px; --pill-sm: 28px; --pill-md: 36px; --control-sm: 32px; --control: 40px;
  /* type */
  --fs-mono-label: 0.72rem;  /* uppercase, .18em: free-standing labels/eyebrows */
  --fs-mono-tag: 0.6875rem;  /* uppercase, .12em: text in pills and meta rows; 11px floor */
  --fs-mono-data: 0.78rem;   /* .08em: dates and years */
  --fs-h3: clamp(2.25rem, 3.6vw, 3rem);
  --fs-card-lg: clamp(1.65rem, 2.35vw, 2.2rem);
  --fs-card: clamp(1.3rem, 1.6vw, 1.55rem);
  --fs-card-body: 0.9rem;
  --fs-small: 0.8125rem;
  /* hover motion */
  --dur-1: 0.3s;  /* color, border, background */
  --dur-2: 0.5s;  /* transform, box-shadow, icon nudges */
}
/* (phone radius token: see Z, <=640) */


/* ════════════════════════════════════════════════════════════════════════════
   A. BUGS AND REGRESSIONS
   ════════════════════════════════════════════════════════════════════════════ */
/* A1 LSE Khattar award: .src-link { color: inherit } turned it white; its siblings are gold */
button.edu__award { color: var(--gold-hi); }
/* A2 h4 inherits 700, which JetBrains Mono does not ship: no synthesised faux bold */
.dossier__group-title { font-weight: 400; }
/* A3 one height per button size: gold and ghost CTAs share the 1px ring */
.btn { border: 1px solid transparent; }
.btn--ghost { border-color: var(--line-strong); } /* guard: .btn above would reset the ghost outline */
.btn--gold { background-origin: border-box; }
/* A4 grade badges: A / B / C all the same height */
.dossier__grade { border: 1px solid transparent; background-origin: border-box; }


/* ════════════════════════════════════════════════════════════════════════════
   B. SECTION RHYTHM
   ════════════════════════════════════════════════════════════════════════════ */
/* B1 */ .section { padding-block: var(--section-pt) var(--section-pb); }
/* B2 equal air on both sides of the bordered talk band */
.talk + .section { padding-top: var(--section-pb); }
/* B3 */ .section-head { margin-bottom: var(--head-gap); }
/* B4 one eyebrow-to-title gap */
.section-head__index { margin-bottom: var(--s-6); }
.talk .section-head__index { margin-bottom: var(--s-6); }
/* B5 */ .talk { padding-block: var(--band-pad); }
/* B6 sub-sections: "In the press", "Honours" */
.press__head { margin: var(--sub-gap) 0 var(--s-6); }
.honours { margin-top: var(--sub-gap); }
.honours__head { margin-bottom: var(--s-6); }
/* B7 two-column splits */
.about__grid { gap: var(--split); }
.deal { gap: var(--split); }
.beyond__card--life { gap: var(--split-card); }
.pg-head { gap: var(--s-8) var(--split); }
.pg-lost { gap: var(--s-8) var(--split); }
/* B8 grid gaps */
.timeline__list { gap: var(--tl-gap); }
.stats { gap: var(--grid-gap); }
.mandates { gap: var(--grid-gap); margin-top: var(--s-6); }
.bento, .press__grid, .beyond__grid, .contact-grid { gap: var(--grid-gap); }
/* B9 32 above and below the footer hairline */
.footer__top { padding-bottom: var(--s-8); }
.footer__bottom { padding-top: var(--s-8); }


/* ════════════════════════════════════════════════════════════════════════════
   C. CARD SYSTEM
   ════════════════════════════════════════════════════════════════════════════ */
/* ── C1 Surfaces ── */
/* S1 card: one glass for every card (Press and Beyond gain the top-edge light). The backdrop blur is
   removed (no visible difference, one filter fewer); every card here is already position: relative. */
.stat, .tl-card, .edu, .contact-card, .press-card, .beyond__card {
  border: 1px solid var(--line);
  background: var(--surface-1);
  box-shadow: var(--shadow-1);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.pg-alt { background: var(--surface-1); box-shadow: var(--shadow-1); }
/* featured cards keep their own light (guard: S1 above would flatten .edu--featured) */
.edu--featured {
  background:
    radial-gradient(80% 60% at 100% 0%, rgba(214, 178, 110, 0.13), transparent 62%),
    radial-gradient(70% 60% at 0% 100%, rgba(70, 110, 190, 0.16), transparent 62%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.012));
  border-color: var(--gold-line); /* .18 -> .22, same hairline as the current role and the deal */
}
.tl-item.is-current .tl-card { border-color: var(--gold-line); }
/* S2 wells */
.mandate { background: var(--well); border-radius: var(--r-md); padding: var(--pad-nested); }
.tl-card__also { border-color: var(--gold-line); border-radius: var(--r-md); }
.dossier__score { border-radius: var(--r-md); padding: var(--pad-nested); margin: var(--s-8) 0 0; }
/* S3 frame: the featured deal gets the gold hairline (keeps its own blue radial background) */
.deal {
  border: 1px solid var(--gold-line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-2); padding: var(--pad-feature);
}

/* ── C2 Radii ── */
.stat, .tl-card, .edu, .contact-card, .press-card, .beyond__card, .pg-alt { border-radius: var(--r-lg); }
button.deal__photos:focus-visible { border-radius: var(--r-lg); }
.deal__photo, .term, .reader__photo, .pg-card__inner { border-radius: var(--r-md); }
.pg-lost__path code { border-radius: var(--r-sm); }
.footer__copy:focus-visible, .menu__copy:focus-visible { border-radius: 6px; }

/* ── C3 Padding ── */
.stat { padding: var(--pad-compact); }
.stat::before { left: var(--pad-compact); }
.press-card { padding: var(--pad-compact); }
.contact-card { padding: var(--pad-compact); }
.tl-card { padding: var(--tl-pad); }
.edu { padding: var(--pad-card); } /* featured included: year labels and logos share one line across the row */
.beyond__card { padding: var(--pad-card); }
.beyond__card--run { padding-bottom: clamp(5.5rem, 9vw, 7rem); } /* guard: keeps the route-line reserve */
.term__body { padding: var(--pad-nested); }
.term__bar { padding: 10px var(--pad-nested); }
.tl-card__also { padding: var(--s-3) var(--s-4); }
.dossier__panel {
  --pad-x: clamp(20px, calc(20px + 36 * var(--fluid)), 56px);
  --pad-top: clamp(24px, calc(24px + 24 * var(--fluid)), 48px);
}

/* ── C4 Hover language ── */
/* (1) whole-card links: lift 4px, gold rim, soft gold glow */
.contact-card:hover {
  transform: translate3d(0, -4px, 0);
  border-color: var(--link-card-hover);
  box-shadow: var(--shadow-lift);
}
.contact-card.is-copied { border-color: rgba(214, 178, 110, 0.45); } /* guard: copied state stays on top of hover */
.press-card:hover { border-color: var(--link-card-hover); transform: translate3d(0, -4px, 0); box-shadow: var(--shadow-lift); }
.press-card:hover .press-card__more svg { transform: translateX(3px); }
/* (2) info cards: the rim warms, no lift */
.tl-card:hover { border-color: var(--card-hover); }
.tl-item.is-current .tl-card:hover { border-color: var(--featured-hover); }
.edu:hover { border-color: var(--card-hover); }
.edu--featured:hover { border-color: var(--featured-hover); }
.beyond__card { transition: border-color var(--dur-1) var(--ease-out); }
.beyond__card:hover { border-color: var(--card-hover); }
/* (3) controls: gold rim, gold text, faint gold fill, no lift */
.btn--ghost:hover { border-color: var(--gold-line-hover); }
.to-top:hover { border-color: var(--gold-line-hover); }
.to-top:hover svg { transform: translateY(-3px); }
.nav__toggle:hover { border-color: var(--gold-line-hover); }
.edu__open:hover { background: var(--gold-fill-hover); border-color: var(--gold-line-hover); }
.edu__award--link:hover { border-color: var(--gold-line-hover); }
.dossier__close:hover { border-color: var(--gold-line-hover); }
.contact-card:hover .contact-card__icon { border-color: var(--gold-line-hover); }
a:hover > .ext { transform: translate(3px, -3px); }
.pg-alt__links :is(a, button) { border: 1px solid var(--line-strong); }
.pg-alt__links :is(a, button):hover {
  border-color: var(--gold-line-hover); background: var(--gold-fill);
  box-shadow: none; transform: none;
}
.pg-alt__links :is(a, button):hover .pg-alt__value { color: var(--gold-hi); }
/* the tool chip is a plain list item: no hover affordance */
.chip { transition: none; }
.chip:hover { border-color: var(--line-strong); color: var(--text-2); background: rgba(255, 255, 255, 0.02); }

/* ── C5 Transition timing (hover only): colour/border/background dur-1, transform/shadow dur-2 ── */
.tl-card {
  transition: border-color var(--dur-1) var(--ease-out), opacity 1s var(--ease-out), transform 1.2s var(--ease-out);
  transition-delay: 0s, var(--d, 0ms), var(--d, 0ms); /* keeps the shared .reveal entrance */
}
.edu { transition: transform 0.7s var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.contact-card { transition: transform var(--dur-2) var(--ease-out), border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
.contact-card__icon { transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
.contact-card__label { transition: color var(--dur-1) var(--ease-out); }
.contact-card__arrow { transition: transform var(--dur-2) var(--ease-out), color var(--dur-1) var(--ease-out); }
.press-card { transition: border-color var(--dur-1) var(--ease-out), transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
.press-card__more svg { transition: transform var(--dur-2) var(--ease-out); }
.edu__open { transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.edu__open svg { transition: transform var(--dur-2) var(--ease-out); }
.edu__award--link { transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.to-top { transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.to-top svg { transition: transform var(--dur-2) var(--ease-out); }
.nav__links a:not(.btn) { transition: color var(--dur-1) var(--ease-out); }
.nav__toggle { transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }
.footer__links a { transition: color var(--dur-1) var(--ease-out); }
.footer__copy, .menu__copy { transition: color var(--dur-1) var(--ease-out); }
.org-mark img { transition: opacity var(--dur-1) var(--ease-out); }
.ext { transition: transform var(--dur-2) var(--ease-out), opacity var(--dur-1) var(--ease-out); }
.ledger__what a, .ledger__what .src-link { transition: background-size 0.45s var(--ease-out), color var(--dur-1) var(--ease-out); }
.dossier__close { transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), transform var(--dur-2) var(--ease-out); }
.pg-back { transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }
.pg-back svg { transition: transform var(--dur-2) var(--ease-out); }
.pg-alt__links :is(a, button) { transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }
.pg-alt__value { transition: color var(--dur-1) var(--ease-out); }


/* ════════════════════════════════════════════════════════════════════════════
   D. ALIGNMENT
   ════════════════════════════════════════════════════════════════════════════ */
/* D1 career cards end on the wrap edge like every other block (line length stays capped by the points) */
.tl-card { max-width: none; }
/* D2 timeline: date, node, role first line and logo share one centre line at every width */
.timeline {
  --tl-pad: var(--pad-card);
  --tl-role: var(--fs-card-lg);
  --tl-mid: calc(1px + var(--tl-pad) + var(--tl-role) * 0.54); /* border + padding + half the 1.08 line */
}
.tl-card__role { font-size: var(--tl-role); }
.tl-item__date { font-size: var(--fs-mono-data); letter-spacing: 0.08em; line-height: 20px; }
@media (min-width: 761px) {
  .tl-item__when { padding-top: calc(var(--tl-mid) - 10px); }
  .tl-item__node { margin-top: calc(var(--tl-mid) - 5.5px); }
}
/* D3 org-mark logos centred on the first title line (career) / the year line (education) */
.edu__year { line-height: 20px; white-space: nowrap; } /* "2013 – 2016" stays one line beside the logo in 4-column bentos */
@media (min-width: 641px) {
  .tl-card .org-mark { top: calc(var(--tl-pad) + var(--tl-role) * 0.54); right: var(--tl-pad); transform: translateY(-50%); }
  .edu .org-mark { top: calc(var(--pad-card) + 10px); right: var(--pad-card); transform: translateY(-50%); }
}
/* D4 contact arrow centred on the 48px icon tile */
.contact-card__arrow { top: calc(var(--pad-compact) + 15px); right: var(--pad-compact); }
/* D5 education bento: small cells top-anchor the degree, bottom-anchor award + button; LSE stays bottom-anchored */
.edu__body { padding-top: var(--s-8); }
.edu:not(.edu--featured) .edu__body { margin-top: 0; flex: 1 0 auto; }
.edu:not(.edu--featured) .edu__award { margin-top: auto; }
.edu:not(.edu--featured) .edu__body > :has(+ .edu__award) { margin-bottom: var(--s-6); }
.edu__open { margin-top: var(--s-4); }
/* D6 Beyond row 1: icon, label, title and list share rows across the three cards (3-column layout only) */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 1101px) {
    .beyond__grid > li:not(.beyond__wide):not(:has(.beyond__card--run)) { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; }
    .beyond__grid > li:not(.beyond__wide):not(:has(.beyond__card--run)) > .beyond__card { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; align-content: start; }
    .beyond__grid > li:not(.beyond__wide):not(:has(.beyond__card--run)) .beyond__icon { justify-self: start; }
  }
}
/* the list's own rows stay packed at the top when its subgrid track is taller than the list */
.beyond__list { align-content: start; }
/* D7 honours ledger: text on the shared edge; hover slides the row content on the compositor (no padding
   animation) and the rows get the shared reveal back (their old transition shorthand cancelled it) */
.ledger__row {
  padding: var(--s-5) 0;
  transition: background var(--dur-1) var(--ease-out), opacity 1s var(--ease-out), transform 1.2s var(--ease-out);
  transition-delay: 0s, var(--d, 0ms), var(--d, 0ms);
}
.ledger__row:hover { padding-left: 0; }
.ledger__row > * { transition: transform var(--dur-2) var(--ease-out); }
.ledger__row:hover > * { transform: translate3d(8px, 0, 0); }
.ledger__row::before { transition: transform var(--dur-2) var(--ease-out); }


/* ════════════════════════════════════════════════════════════════════════════
   E. PILLS AND MONO LABELS
   ════════════════════════════════════════════════════════════════════════════ */
/* ── E1 Pill sizes: labels 20 / 28 / 36; controls 32 / 40 / 46.8 / 59.6 ── */
/* XS (20) */
.ledger__tag, .press-card__tag, .tl-card__now, .tl-card__also-label, .badge-now {
  display: inline-flex; align-items: center;
  height: var(--pill-xs); padding: 0 8px; line-height: 1;
  font-family: var(--font-mono); font-size: var(--fs-mono-tag); letter-spacing: 0.12em; text-transform: uppercase;
  border-radius: var(--r-pill);
}
.press-card__tag { margin-top: var(--s-4); }
.badge-now {
  padding: 0 8px 0 7px; gap: 6px;
  border: 1px solid var(--gold-line-2); background: var(--gold-fill);
}
/* SM (28): tags and awards */
.tags { gap: var(--s-2); margin-top: var(--s-6); }
.tags li, .edu__award {
  display: inline-flex; align-items: center;
  min-height: var(--pill-sm); padding: 4px 12px; line-height: 1.45;
  font-size: var(--fs-mono-tag); letter-spacing: 0.12em;
  border: 1px solid var(--gold-line); background: var(--gold-fill);
}
/* wrap-prone labels are boxes; single-line labels stay capsules (and never wrap inside the capsule) */
.edu__award { border-radius: var(--r-sm); }
.tags li { white-space: nowrap; }
/* MD (36) */
.deal__facts { gap: var(--s-2); margin-top: var(--s-6); }
.deal__facts li {
  display: inline-flex; align-items: center;
  min-height: var(--pill-md); padding: 4px 14px; line-height: 1.45;
  font-size: var(--fs-small); border-radius: var(--r-pill);
}
.life__chips { gap: var(--s-2); margin-top: var(--s-6); }
.life__chips li {
  display: inline-flex; align-items: center;
  min-height: var(--pill-md); padding: 4px 14px; line-height: 1.45;
  font-size: var(--fs-small); border-radius: var(--r-pill);
  border: 1px solid var(--gold-line); background: var(--gold-fill);
}
.dossier__facts { gap: var(--s-2); margin: var(--s-6) 0 0; }
.dossier__facts li {
  display: inline-flex; align-items: center;
  min-height: var(--pill-md); padding: 4px 12px; line-height: 1.45;
  font-size: var(--fs-small); border-radius: var(--r-sm);
}
.dossier__facts li.is-gold { border-color: var(--gold-line-2); background: var(--gold-fill); }
.chips { gap: var(--s-2); }
.chip {
  display: inline-flex; align-items: center;
  min-height: var(--pill-md); padding: 4px 14px; line-height: 1.45;
  border-radius: var(--r-pill);
}
/* LSE featured award: the MD size */
.edu--featured .edu__award,
.edu--featured button.edu__award {
  min-height: var(--pill-md); padding: 4px 16px;
  font-size: var(--fs-mono-tag); margin-top: var(--s-6);
}
/* controls */
.edu__open { min-height: var(--control-sm); padding: 0 14px 0 16px; border-color: var(--gold-line-2); }
.dossier__chips { gap: var(--s-2); }

/* ── E2 Mono type: three tokens, 11px floor ── */
/* label: free-standing, uppercase, .18em */
.label-mono, .stat__label, .contact-card__label, .portrait__caption, .edu__year, .deal__eyebrow,
.beyond__label, .dossier__group-title, .footer__role, .to-top, .pg-facts dt, .pg-loader__text {
  font-size: var(--fs-mono-label); letter-spacing: 0.18em;
}
/* tag: text in pills and meta rows, uppercase, .12em */
.press-card__meta, .press-card__more, .tl-card__context, .mandate__context, .dossier__mod-when,
.footer__bottom, .reader__quote cite, .pg-alt__label, .pg-lost__path {
  font-size: var(--fs-mono-tag); letter-spacing: 0.12em;
}
.term__bar { font-size: var(--fs-mono-tag); } /* 10.9 -> 11px floor; keeps its own tracking */
.dossier__group-title span { white-space: nowrap; } /* a grade count ("1 DIST · 4 A") never splits */
/* press meta: the date takes the data tracking and the row an 8px gap, so the 11px floor does not push
   "· Press release" onto a line of its own (the outlet/type stack itself is HTML item J3) */
.press-card__meta { gap: var(--s-2); }
.press-card__meta time { letter-spacing: 0.08em; }
/* data: dates and years, .08em (.tl-item__date: see D2; .ledger__year already matches) */
.beyond__list li { grid-template-columns: 3.75rem 1fr; align-items: baseline; }
.beyond__list :is(time, .beyond__key) { font-size: var(--fs-mono-data); letter-spacing: 0; padding-top: 0; }


/* ════════════════════════════════════════════════════════════════════════════
   F. IN-CARD RHYTHM LADDER
   4 between stacked meta lines · 8 title -> org/meta and label -> title · 16 header -> body ·
   24 body -> pills/wells/actions · 32-48 between blocks
   ════════════════════════════════════════════════════════════════════════════ */
/* career */
.tl-card__org { margin-top: var(--s-2); }
.tl-card__context { margin-top: var(--s-2); max-width: 70ch; text-wrap: balance; }
.tl-card__points { margin-top: var(--s-4); gap: var(--s-2); }
.tl-card__also { margin-top: var(--s-6); }
/* sabbatical mandates */
.mandate__org { margin-top: var(--s-2); }
.mandate__context { margin-top: var(--s-2); }
.mandate__desc { margin-top: var(--s-4); }
/* education (the featured school keeps its 1rem) */
.edu__school { margin-top: var(--s-2); }
.edu__note { margin-top: var(--s-1); }
/* press */
.press-card__title { margin-top: var(--s-4); }
.press-card__sub { margin-top: var(--s-3); }
.press-card__more { padding-top: var(--s-6); }
/* deal (title keeps its 1rem) */
.deal__text { margin-top: var(--s-6); }
.deal__actions { margin-top: var(--s-8); }
/* beyond (title keeps its 8) */
.beyond__label { margin-top: var(--s-6); }
.beyond__list { margin-top: var(--s-6); gap: var(--s-3); }
.beyond__card--run .beyond__big { margin-top: var(--s-6); }
.life__text { margin-top: var(--s-6); }
/* about */
.about__tools { margin-top: var(--s-12); }
.about__tools .label-mono { margin-bottom: var(--s-4); }
.stat__label { margin-top: var(--s-3); }
/* contact */
.contact-card__text { padding-top: var(--s-10); }
/* dossier / reader */
.dossier__title { margin: var(--s-4) 0 var(--s-2); }
.dossier__group { margin-top: var(--s-8); }
.dossier__group-title { margin-bottom: var(--s-3); }
.reader__quote { margin: var(--s-8) 0 0; }
.reader__gallery { margin-top: var(--s-8); }
/* icon tiles: one recipe, the brand-mark language (contact keeps its hover glow) */
.contact-card__icon, .beyond__icon {
  width: 48px; height: 48px; border-radius: var(--r-md);
  background: linear-gradient(145deg, #121b2e, #0a0f1b);
  border: 1px solid var(--gold-line-2); color: var(--gold);
}


/* ════════════════════════════════════════════════════════════════════════════
   G. TYPE SCALE, ACCENT, WRAPPING, MEASURE
   ════════════════════════════════════════════════════════════════════════════ */
/* ── G1 Serif ── */
.honours__title, .dossier__title { font-size: var(--fs-h3); }
.beyond__title { font-size: var(--fs-card-lg); }
.press-card__title, .mandate__role, .ledger__what { font-size: var(--fs-card); }
.edu__degree { font-size: var(--fs-card); line-height: 1.15; } /* the featured degree keeps its own size */
/* ledger titles that wrap at the larger size: the arrow follows the last word instead of being pushed
   to the far edge of an inline-flex box (unwrapped titles render as before) */
.ledger__what .src-link { display: inline; }
/* ── G2 Inter (weight 300 only at >= 16px) ── */
.tl-card__points li { font-size: 1rem; }
.mandate__desc { font-size: var(--fs-card-body); font-weight: 400; }
.press-card__sub, .beyond__list li, .tl-card__also p { font-size: var(--fs-card-body); }
.tl-card__org { font-size: 0.95rem; }
.edu__school { font-size: 0.95rem; font-weight: 500; }
.ledger__what small, .ledger__who { font-size: var(--fs-small); line-height: 1.5; }
.dossier__legend, .dossier__score-note { font-size: var(--fs-small); }
/* ── G3 One gold accent rule: italic gradient for emphasised words ── */
.honours__title em, .about__lede em, .pg-alt__title em {
  font-style: italic;
  background: linear-gradient(100deg, var(--gold-hi), var(--gold) 50%, var(--gold-deep));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  padding-right: 0.08em;
}
.about__lede em { margin-right: -0.08em; } /* the period after "Asia-Pacific" stays put */
/* emphasis by brightness, so it no longer competes in gold with the GPA pill and button below */
.edu__note--dual { color: var(--text); }
/* ── G4 Wrapping and measure ── */
.about__prose p, .tl-card__points li, .mandate__desc, .deal__text, .press-card__sub, .edu__note,
.ledger__what small, .ledger__who, .beyond__list li, .life__text, .reader__points li, .talk__text, .pg-lede {
  text-wrap: pretty;
}
.about__lede, .reader__quote p { text-wrap: balance; }
.ledger__what { text-wrap: balance; } /* like the card titles; its <small> line keeps "pretty" (more specific) */
.tl-card__points { max-width: 40rem; }
.tl-card__also { max-width: 40rem; } /* the "Also" well ends on the bullets' measure, not the wider card edge */
.dossier .reader__points { max-width: 38rem; }


/* ════════════════════════════════════════════════════════════════════════════
   H. SUBPAGES (booking.html, 404.html)
   ════════════════════════════════════════════════════════════════════════════ */
/* H1 same content edge as home (x = 100 at 1440) */
.pg-main, .pg-foot { width: min(1240px, 100% - 2 * var(--gutter)); }
/* H2 */ .pg-alt { padding: var(--s-4) var(--s-6); border-radius: var(--r-lg); }
/* H3 */ .pg-title { margin: var(--s-6) 0 var(--s-6); }
/* H4 footer reads like the home .footer__bottom */
.pg-foot { font-family: var(--font-mono); font-size: var(--fs-mono-tag); letter-spacing: 0.12em; text-transform: uppercase; }
.pg-foot__time { font-size: inherit; letter-spacing: inherit; }
.pg-foot .pg-back { font-size: inherit; letter-spacing: inherit; }


/* ════════════════════════════════════════════════════════════════════════════
   I. CONTROLS AND PHONE
   ════════════════════════════════════════════════════════════════════════════ */
/* I1 one control height of 40 (the desktop hero nav CTA is untouched; see Z <=900 for the phone CTA) */
.nav__toggle { width: var(--control); height: var(--control); }
.pg-nav .pg-back { min-height: var(--control); padding: 0 16px; }
.to-top { min-height: var(--control); padding: 0 16px; }
/* I3 赖政豪 large enough for CJK strokes */
.footer__cn { font-size: var(--fs-small); letter-spacing: 0.06em; }


/* ════════════════════════════════════════════════════════════════════════════
   Z. RESPONSIVE — every max-width rule lives here, after all base overrides above.
   "guard" = restates an existing site.css / pages.css media rule that a base override above would beat.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width: 1101px) and (max-width: 1180px) {
  /* D3 narrowest 4-column bento: the one-line year keeps clear of the logo (tag tracking here only) */
  .edu.has-mark .edu__year { letter-spacing: 0.12em; }
}

@media (max-width: 900px) {
  /* I1 phone CTA beside the toggle: one 40px control height */
  .nav .btn--sm { min-height: var(--control); padding-block: 0; }
  /* guards (pages.css <=900): one-column subpage headers keep their gaps */
  .pg-head { gap: 1.8rem; }
  .pg-lost { gap: 0.5rem; }
}

@media (max-width: 640px) {
  /* 1 phone radius token: replaces the per-component phone radii (.stat 16, .contact-card 18, icon 13) */
  :root { --r-lg: 18px; }
  /* B8 */
  .stats { gap: var(--s-3); margin-top: var(--s-10); }
  .contact-grid { gap: var(--s-3); }                        /* guard (was 0.75rem) */
  /* C2 bottom-sheet dossier */
  .dossier__panel { border-radius: var(--r-lg) var(--r-lg) 0 0; }
  /* E2 in the narrow sheet the field headers take the tag tracking, so "Accounting, economics & data
     1 DIST · 4 A" stays on one line at 390 as it did before the label token */
  .dossier__group-title { letter-spacing: 0.12em; }
  /* C3 contact row layout */
  .contact-card { padding: var(--s-4) var(--s-5); }
  .contact-card__text { padding-top: 0; }                   /* guard: the row layout has no top gap */
  /* F icon tiles: 44px on phones, same radius */
  .contact-card__icon, .beyond__icon { width: 44px; height: 44px; }
  /* I2 nested boxes removed on phone: mandates become hairline-topped blocks */
  .mandate { padding: var(--s-4) 0 0; background: none; border: 0; border-top: 1px solid var(--line); border-radius: 0; }
  /* H2 / H3 / I1 subpages */
  .pg-alt { padding: var(--s-6); }
  .pg-title { margin: var(--s-4) 0 var(--s-4); }
  .pg-nav .pg-back { padding: 0 14px; }
}

@media (max-width: 420px) {
  /* C3 / E2 guards: "Asia-Pacific" and "YEARS IN FINANCE" must fit the two-column stats at 360 */
  .stat { padding: var(--s-4); }
  .stat::before { left: var(--s-4); }
  .stat__label { font-size: 0.66rem; letter-spacing: 0.1em; }
  /* E1 the longest career tag ("2018–20 EM Asia (PE / Infra)") fits its capsule at 360 */
  .tags li { letter-spacing: 0.1em; }
}

@media (max-width: 400px) {
  /* guard (site.css <=400): the terminal keeps its tighter side padding; the bar text stays aligned */
  .term__body, .term__bar { padding-inline: 0.9rem; }
}

@media (prefers-reduced-motion: reduce) {
  /* guard (site.css reduced-motion block): C5 gave .press-card a transition again */
  .press-card { transition: none; }
}

/* ── Section R: review fixes (2026-10-19) ───────────────────────────── */
/* Career: bullets back to the live 46rem measure; the "Also" well spans the card like the mandates */
.tl-card__points { max-width: 46rem; }
.tl-card__also { max-width: none; }
/* Pills and award boxes that can wrap: no orphaned last word */
.dossier__facts li, .tags li, .edu__award, .ledger__tag { text-wrap: balance; }
/* Ledger slide only where hover is real (a tap would leave it stuck on phones) */
@media (hover: none), (pointer: coarse) { .ledger__row:hover > * { transform: none; } }
@media (max-width: 900px) {
  /* 44px touch targets for the phone nav pair */
  .nav__toggle { width: 44px; height: 44px; }
  .nav .btn--sm { min-height: 44px; }
}
@media (min-width: 761px) and (max-width: 900px) {
  .has-mark .tl-card__role { padding-right: 6rem; text-wrap: balance; }
  .edu__award { letter-spacing: 0.1em; }
}
@media (max-width: 640px) {
  .dossier__title { font-size: clamp(1.7rem, 7.4vw, 1.95rem); text-wrap: balance; }
  .tl-card__points li { font-size: 0.98rem; text-wrap: balance; }
}
@media (max-width: 420px) { .edu__award { letter-spacing: 0.1em; } }

/* keep the selective-certificate highlight gold (client emphasis) */
.edu__note--dual { color: var(--gold-hi); }

/* ── Language switch: EN / 中文 (2026-10-19) ── */
.lang-switch {
  display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 32px; padding: 0 0.7rem;
  border-radius: var(--r-pill, 999px); border: 1px solid var(--line-strong); color: var(--text-2); text-decoration: none;
  font: 500 0.8rem/1 var(--font-body); letter-spacing: 0.04em; transition: color 0.3s, border-color 0.3s, background 0.3s;
}
.lang-switch:hover { color: var(--gold-hi); border-color: var(--gold-line-hover, rgba(214,178,110,0.55)); background: var(--gold-fill, rgba(214,178,110,0.06)); }
.lang-switch:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.pg-nav-right { display: flex; align-items: center; gap: 0.6rem; }
@media (max-width: 900px) {
  .nav__links li.nav__lang { display: list-item; }
  .lang-switch { height: 44px; min-width: 44px; }
}

/* Cross-document view transition: switching EN <-> 中文 (same origin) cross-fades instead of flashing */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.32s; animation-timing-function: var(--ease-out); }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }

/* ── Section M: final mobile pass (2026-10-19) ───────────────────────── */
/* Nav: never wrap; below 430px the EN nav shows the D mark only (the name is right below in the hero) */
@media (max-width: 900px) {
  .nav__links { gap: 0.5rem; }
  .nav .nav__name, .nav .lang-switch, .nav .btn--sm, .pg-back { white-space: nowrap; }
  .nav > .nav__brand { min-height: 44px; }
  .edu__open { min-height: 44px; }
  .pg-nav .pg-back { min-height: 44px; }
  .menu__meta a, .menu__copy, .footer__links a, .footer__copy { display: inline-flex; align-items: center; gap: 0.5em; min-height: 44px; }
  .menu__meta, .footer__links { row-gap: 0; }
  /* the menu scrolls inside its own box, below the nav */
  .menu { overflow: hidden; }
  .menu__inner { height: 100%; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
}
@media (max-width: 429px) { html[lang="en"] .nav .nav__name { display: none; } }
@media (max-width: 374px) { .lang-zh .nav .nav__name { display: none; } }
/* Phone landscape: bring the portrait back on screen; compact menu */
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  .hero__portrait { right: 0; height: 88svh; }
  .hero__content { padding-bottom: 2.5rem; }
  .hero__lede { max-width: 30rem; }
  .menu__links { display: grid; grid-template-columns: 1fr 1fr; column-gap: 2rem; }
  .menu__links a { font-size: 2rem; padding: 0.7rem 0 0.6rem; }
  .menu__inner { gap: 1.5rem; }
}
@media (max-width: 640px) {
  /* Deal photos: captions under the photos, not over the people */
  .reader__gallery { grid-template-columns: 1fr 1fr; }
  .reader__photo:nth-child(1) { grid-column: 1 / -1; grid-row: auto; }
  .reader__photo:nth-child(2), .reader__photo:nth-child(3) { grid-column: auto; grid-row: auto; }
  .reader__photo { display: flex; flex-direction: column; }
  .reader__photo img { height: auto; aspect-ratio: 4 / 3; }
  .reader__photo figcaption { position: static; padding: 0.55rem 0.75rem 0.65rem; background: none; color: var(--text-2); }
  /* Dossier field headers: label, count and rule wrap cleanly */
  .dossier__group-title { flex-wrap: wrap; column-gap: 0.45rem; row-gap: 0.2rem; text-wrap: balance; }
  .dossier__group-title span { margin-left: 0; white-space: nowrap; }
  .dossier__group-title::after { min-width: 1.5rem; }
  .dossier__year, .dossier .reader__cta .btn { text-wrap: balance; }
  /* "Now La Caisse" / "Now part of Seviora Group" pills sit flush when they wrap */
  .tl-card__org .tl-card__now { display: flex; width: fit-content; margin: 0.45rem 0 0; }
}
.press-card__meta span, .tl-card__org, .mandate__org, .tl-card__context, .mandate__context { text-wrap: balance; }
@media (pointer: coarse) { .ledger__what .src-link { padding-block: 0.6rem; margin-block: -0.6rem; } }
@media (max-width: 900px) { .footer__top .nav__brand { min-height: 44px; } }
@media (max-width: 900px) { .pg-foot .pg-back { min-height: 44px; } }

/* ── Section P: iPhone Safari pass (2026-10-19) ──────────────────────────
   iOS 26+ Safari lays the page out BELOW the status bar and ABOVE its floating bottom bar
   (env(safe-area-inset-*) is 0 there) but still paints whatever sits just outside that box
   into both bands. Fixed layers therefore reach past it, with padding to keep content clear. */
/* P1 the off-screen skip link stays invisible until it is focused (it showed as a gold pill
   in the status-bar band) */
.skip-link, .pg-skip { opacity: 0; pointer-events: none; transition: transform 0.35s var(--ease-out), opacity 0.2s; }
.skip-link:focus, .skip-link:focus-visible, .pg-skip:focus-visible { opacity: 1; pointer-events: auto; }
/* P6 rotating the phone never inflates the text */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
/* P7 phone landscape (viewport-fit=cover): side gutters clear the Dynamic Island and the corners;
   env() is 0 in portrait and on desktop, so nothing changes there */
:root { --gutter: max(clamp(1rem, 4vw, 3.5rem), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); }
/* P2 a solid strip just above the viewport fills the status-bar band, so text scrolling up
   never shows through above the fixed nav (its own ::before would be clipped by its
   backdrop-filter in WebKit, hence a separate fixed layer) */
body::before {
  content: ""; position: fixed; left: 0; right: 0; top: -160px; height: 160px; z-index: 51;
  background: var(--ink-0); pointer-events: none;
}
@media (max-width: 900px) {
  /* P3 the phone menu runs on under Safari's bottom bar; the scroller's own padding keeps the
     CTA and contact row above it (the menu's padding used to clip them in a hard rectangle) */
  .menu { bottom: -160px; padding-bottom: 0; }
  .menu__inner { padding-bottom: calc(1.75rem + 160px + env(safe-area-inset-bottom)); }
  /* an opaque base (it was 95% plus a blur), and once the overlay has faded in the page behind it
     hides: with its bar expanded Safari clips fixed layers at the bar but keeps drawing the page
     under it, so the menu's foot sat on top of section text */
  .menu {
    background:
      radial-gradient(90% 55% at 85% 0%, rgba(70, 110, 190, 0.24), transparent 70%),
      radial-gradient(70% 45% at 0% 100%, rgba(214, 178, 110, 0.11), transparent 70%),
      var(--ink-0);
  }
  html.menu-open :is(.hero, main, .footer) { visibility: hidden; transition: visibility 0s linear 0.5s; }
}
@media (max-width: 900px) and (min-height: 501px) {
  /* P5 the hero keeps a portrait-tall space under the text: the cutout (50svh) no longer rides
     up over the clock/coordinates line, and the face sits fully on screen */
  .hero__content { padding-bottom: 50svh; }
  .hero__portrait { right: -16%; }
}
@media (max-width: 640px) {
  /* P4 the bottom sheet ends at Safari's bar (dialogs are clipped there): rows fade out into its
     edge instead of being sliced; the sheet's 4rem bottom padding scrolls the last row clear */
  .dossier__panel::after {
    content: ""; display: block; position: sticky; bottom: -4rem; z-index: 2;
    height: 2.75rem; margin: 0 calc(-1 * var(--pad-x)) -2.75rem; pointer-events: none;
    background: linear-gradient(to bottom, rgba(7, 10, 18, 0), #070a12 85%);
  }
}
/* P8 touch screens: a tap leaves no stuck hover (iOS keeps :hover until the next tap elsewhere), so
   cards don't stay lifted or rimmed, the Carro photos don't stay fanned, the ledger row doesn't stay lit */
@media (hover: none) {
  .contact-card:hover, .press-card:hover { transform: none; border-color: var(--line); box-shadow: var(--shadow-1); }
  .contact-card.is-copied:hover { border-color: rgba(214, 178, 110, 0.45); }
  .contact-card:hover .contact-card__icon { border-color: var(--gold-line-2); box-shadow: none; }
  .contact-card:hover .contact-card__arrow, .contact-card:hover .contact-card__arrow--copy { color: var(--muted); transform: none; }
  .press-card:hover .press-card__more svg, .edu__open:hover svg, .to-top:hover svg { transform: none; }
  .deal__photos:hover .deal__photo--a { transform: rotate(-3deg); }
  .deal__photos:hover .deal__photo--b { transform: rotate(4deg); }
  .deal__photos:hover .deal__photo--c { transform: rotate(-7deg); }
  .ledger__row:hover { background: none; }
  .ledger__row:hover::before { transform: scaleY(0); }
  .tl-card:hover, .edu:hover, .beyond__card:hover { border-color: var(--line); }
  .tl-item.is-current .tl-card:hover, .edu--featured:hover { border-color: var(--gold-line); }
  .btn--ghost:hover { color: var(--text); border-color: var(--line-strong); }
  .to-top:hover, .nav__toggle:hover { border-color: var(--line-strong); color: var(--text-2); }
  .nav__toggle:hover { color: var(--text); }
  .footer__links a:hover, .footer__copy:not(.is-copied):hover { color: var(--text-2); }
  /* a short press feedback instead */
  .contact-card:active, .press-card:active { border-color: var(--link-card-hover); }
  .contact-card, .press-card, .press-card__open, .deal__photos, .src-link, .edu__open, .edu__award, .btn,
  .lang-switch, .to-top, .menu__links a { -webkit-tap-highlight-color: transparent; }
}
/* P9 the film grain is a static tile: a viewport-sized layer looks identical to the old 4x one and is
   far cheaper to blend on phones */
body::after { inset: 0; }
@media (max-width: 900px) {
  /* P10 the menu's base is opaque now (P3), so its full-screen blur has nothing left to show */
  .menu { -webkit-backdrop-filter: none; backdrop-filter: none; }
}
/* P11 Safari before 26 has no text-wrap: pretty; short blurbs then balance instead of leaving one word */
@supports not (text-wrap: pretty) {
  @media (max-width: 640px) {
    .press-card__sub, .edu__note, .talk__text, .pg-lede, .ledger__what small, .ledger__who, .deal__text { text-wrap: balance; }
  }
}

/* ── Section Q: phone layout pass (2026-10-19, audit) ─────────────────── */
/* Q1 About portrait in phone landscape: a centred frame that fits under the nav, caption inside */
@media (max-height: 500px) and (orientation: landscape) and (max-width: 1100px) {
  .portrait { min-height: 0; max-height: none; aspect-ratio: auto; height: calc(100svh - var(--nav-h) - var(--s-8)); }
}
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  .portrait { width: min(100%, 26rem); margin-inline: auto; }
  /* side sheet: its padding clears the Dynamic Island too */
  .dossier__panel { --pad-x: max(clamp(20px, calc(20px + 36 * var(--fluid)), 56px), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); }
}
/* Q2 short landscape screens: section air scaled to the height, not the width */
@media (max-width: 940px) and (max-height: 500px) and (orientation: landscape) {
  :root { --section-pt: 56px; --section-pb: 64px; --band-pad: 88px; }
}
@media (max-width: 640px) {
  /* Q3 career bullets fill their measure (balance left short ragged lines and a leading em dash) */
  .tl-card__points li { text-wrap: pretty; }
  /* Q4 stat values read as headline numbers (they sat at the 23px floor) */
  .stat__value { font-size: clamp(1.75rem, 20cqi, 2.6rem); }
  /* Q6 footer links: 44px-wide targets; English sets them as a 2 x 2 grid (WeChat no longer alone) */
  .footer__links { column-gap: var(--s-2); margin-left: calc(-1 * var(--s-3)); }
  .footer__links a, .footer__copy { min-width: 44px; justify-content: center; padding-inline: var(--s-3); }
  html[lang="en"] .footer__links { display: grid; grid-template-columns: repeat(2, max-content); }
}
@media (max-width: 420px) {
  /* Q7 narrow phones: a slimmer rail indent and card padding give the career text ~20px more measure */
  .tl-item { padding-left: var(--s-6); }
  .timeline { --tl-pad: var(--s-5); }
  .stat__label { font-size: var(--fs-mono-tag); letter-spacing: 0.08em; }
}
/* Q8 the footer's back-to-top pill gets the 44px phone target like the other controls */
@media (max-width: 900px) { .to-top { min-height: 44px; } }
/* Q9 landscape / small tablet English footer: brand left, button right, role line below */
@media (min-width: 641px) and (max-width: 960px) {
  html[lang="en"] .footer__top { display: grid; grid-template-columns: 1fr auto; align-items: center; row-gap: var(--s-4); }
  html[lang="en"] .footer__top > .nav__brand { justify-self: start; }
  html[lang="en"] .footer__role { grid-row: 2; grid-column: 1 / -1; }
  html[lang="en"] .to-top { grid-row: 1; grid-column: 2; }
}
/* Q10 Carro photo stack: the Geely photo sits lower, so the faces in it (Darrell centre) clear the
   bottom edge of the MoU photo in front instead of hiding under it */
.deal__photo--b { top: 52%; }
/* Q11 the role line (hero eyebrow, footer) wraps as "Director, International Business" over
   "SY Holdings (6069.HK)" on phones: the separator dot drops out instead of ending or starting a line */
@media (max-width: 640px) {
  html[lang="en"] .role-sep { display: none; }
  html[lang="en"] :is(.hero__content > .eyebrow, .footer__role) .nowrap { display: block; }
  html[lang="en"] .footer__role .nowrap { margin-top: var(--s-1); }
}
/* Q12 a panel closed by tap/click hands focus back to its opener without the gold keyboard ring */
.is-quiet-focus:focus-visible { outline: none !important; }
.press-card:has(.is-quiet-focus) { outline: none !important; }

/* ── Section S: phone audit, second batch (2026-10-19) ─────────────────── */
/* S1 nav home link: a 44px-wide target when only the D mark shows */
@media (max-width: 900px) { .nav > .nav__brand { min-width: 44px; } }
/* S2 phone menu: rows scale with the visible height, so the CTA and email / WeChat fit without scrolling */
@media (max-width: 640px) and (orientation: portrait) {
  .menu__links a { font-size: max(1.9rem, min(10.5vw, 5.2svh, 3.6rem)); padding: min(1.05rem, 1.4svh) 0 min(0.95rem, 1.2svh); }
  .menu__inner { gap: clamp(1.25rem, 3svh, 2.5rem); }
  .menu__foot { gap: clamp(0.9rem, 2svh, 1.6rem); }
}
/* phone landscape: links in two columns on the left, CTA and contacts in a column on the right */
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  .menu__inner { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; column-gap: 1.5rem; }
  .menu__links { column-gap: 1.25rem; }
  .menu__links a { font-size: clamp(1.4rem, 3.6vw, 1.75rem); padding: 0.6rem 0 0.5rem; gap: 0.9rem; }
  .menu__foot { gap: 1rem; }
  .menu__meta { flex-direction: column; align-items: flex-start; }
}
/* S3 phone landscape hero: a shorter headline so the buttons and clock line are on the first screen */
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape),
       (max-height: 500px) and (orientation: landscape) and (hover: none) and (pointer: coarse) {
  .hero__content { padding-top: calc(var(--nav-h) + 0.75rem); padding-bottom: 2.5rem; }
  .hero__title { font-size: clamp(2.6rem, 14svh, 4rem); margin: 0.5rem 0 0.7rem; }
  .hero__actions { margin-top: 1.1rem; }
  .hero__meta { margin-top: 1rem; }
  .scroll-cue { display: none; }
}
@media (max-width: 720px) and (max-height: 500px) and (orientation: landscape) {
  .hero__portrait { right: -12%; }
  .hero__lede { max-width: 27rem; }
}
/* S4 phone landscape: the Carro photo fan fits under the nav */
@media (min-width: 641px) and (max-width: 1100px) and (max-height: 500px) and (orientation: landscape) {
  .deal__photos { max-width: min(640px, calc((100svh - var(--nav-h) - 2rem) * 1.08)); min-height: 0; }
}
@media (max-width: 640px) {
  /* S5 reader CTA: a two-line label gets real leading and the arrow follows the text */
  .dossier .reader__cta .btn { display: block; line-height: 1.4; padding-block: 0.8rem; }
  .dossier .reader__cta .btn svg { display: inline-block; vertical-align: -0.125em; margin-left: 0.25em; }
  /* S6 sheet header lines without one-word orphans */
  .dossier__school { text-wrap: pretty; }
  .dossier__score-note { text-wrap: balance; }
  /* S7 the source link is underlined text, not a full-width rule */
  .dossier__link .src-link {
    border-bottom: 0; padding-bottom: 0;
    text-decoration-line: underline; text-decoration-color: var(--gold-line-2);
    text-decoration-thickness: 1px; text-underline-offset: 0.3em;
  }
  .dossier__link .src-link:hover { text-decoration-color: var(--gold-hi); }
  html[lang="en"] .dossier__link .src-link { text-wrap: balance; }
  /* S8 every field header gets its hairline underneath (some had it inline, some on a line of its own) */
  .dossier__group-title { row-gap: var(--s-2); }
  .dossier__group-title::after { flex: 1 0 100%; min-width: 0; }
  /* S9 the close-button scrim fades cleanly (its masked blur ended in a hard cut in the rounded sheet) */
  .dossier__top::before {
    -webkit-backdrop-filter: none; backdrop-filter: none;
    -webkit-mask-image: none; mask-image: none;
    height: calc(var(--pin) + 44px + 2.4rem);
    background: linear-gradient(180deg, #0a0f1b 0%, #0a0f1b 55%, rgba(10, 15, 27, 0) 100%);
  }
}
/* ── booking + 404 on phones ── */
@media (max-width: 900px) {
  /* S10 the scrolled nav stays dark over the white scheduler (it blended to flat grey) */
  .pg .nav.is-scrolled { background: rgba(4, 6, 11, 0.9); }
}
/* S11 the fixed horizon arc cut through the facts and the message card on phones */
@media (max-width: 640px), (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  .pg--booking .pg-bg::after { display: none; }
}
@media (max-width: 380px) {
  /* S12 the scheduler fits its frame at 360; the three facts share one row */
  .pg-calendly { min-width: 0; }
  .pg-facts { grid-template-columns: repeat(3, auto); gap: 0 0.9rem; }
  .pg-facts > div { padding-left: 0.6rem; }
}
@media (max-width: 340px) { .pg-facts { grid-template-columns: repeat(2, auto); gap: 0.9rem 1.1rem; } }
/* S13 landscape / small tablet booking: the four message pills as an even 2 x 2 */
@media (min-width: 641px) and (max-width: 900px) {
  .pg-alt__links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  .pg-alt__links button { width: 100%; }
  .pg-alt__value { margin-left: auto; }
}
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  /* S14 landscape booking: the facts sit beside a smaller title, the scheduler starts on the first screen */
  .pg--booking .pg-main { padding-top: calc(var(--nav-h) + var(--s-4)); }
  .pg-head { grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: var(--s-6) var(--s-8); margin-bottom: var(--s-6); }
  .pg--booking .pg-title { font-size: 3.25rem; margin: var(--s-3) 0; }
  /* S15 landscape 404: text left, globe right, both buttons on the first screen */
  .pg-main.pg-lost {
    grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "text globe";
    justify-items: start; text-align: left; gap: 0 var(--s-8);
    padding-top: calc(var(--nav-h) + var(--s-2));
  }
  .pg-lost__globe { width: min(38vw, 72svh); }
  .pg-lost .pg-lede { margin-inline: 0; }
  .pg-lost .pg-title { margin: var(--s-3) 0; }
  .pg-lost__path { margin-top: var(--s-4); }
  .pg-lost__path, .pg-lost__actions { justify-content: flex-start; }
  .pg-lost__actions { margin-top: var(--s-5); }
}
/* S16 404 on short phones: a smaller globe so both buttons are on the first screen */
@media (max-width: 640px) and (max-height: 760px) {
  .pg-main.pg-lost { padding-top: calc(var(--nav-h) + var(--s-2)); }
  .pg-lost__globe { width: min(76vw, 380px, 30svh); }
  .pg-lost .pg-title { margin: var(--s-3) 0; }
  .pg-lost__path { margin-top: var(--s-4); }
  .pg-lost__actions { margin-top: var(--s-6); }
}

/* ── Pavilion Capital: Temasek family row (2026-10-19, per Darrell: wholly owned by Temasek) ──
   The gold "Also" well of the SY card, holding the official Temasek wordmark (white) and the
   ownership line; it replaces the old mono context line. */
.tl-card__family { margin-top: var(--s-4); gap: var(--s-3); max-width: none; }
.tl-card__family-mark { flex: none; display: block; width: auto; height: 14px; opacity: 0.92; }
.tl-card__family p { padding-left: var(--s-3); border-left: 1px solid var(--gold-line-2); line-height: 1.45; }
@media (max-width: 420px) {
  /* narrow cards: the wordmark sits on its own line above the text */
  .tl-card__family { flex-wrap: wrap; row-gap: var(--s-2); }
  .tl-card__family p { flex-basis: 100%; padding-left: 0; border-left: 0; }
}

/* ── Section U: elevation pass (2026-10-19) ─────────────────────────────── */
/* U1 the hero role line splits into two clean lines (no stranded "·") whenever its column is
   too narrow for one line: phones, and desktop windows of about 900-1180px */
.hero__content { container-type: inline-size; }
@container (max-width: 540px) {
  html[lang="en"] .hero__content > .eyebrow .role-sep { display: none; }
  html[lang="en"] .hero__content > .eyebrow .nowrap { display: block; }
}

/* ── Section V: signal discipline (2026-10-19) ──────────────────────────
   Gold keeps four jobs: the italic accent word, the primary gold buttons, live state (Now, live dot,
   timeline fill, progress bar) and true distinctions (award pills, ledger tags, grade badges, the
   selective-certificate line). Everything else rests neutral and turns gold only on hover or keyboard
   focus. Mono stays for data (dates, coordinates, counts, section indexes); sentences drop it. */
/* V1 career: bullets are quiet dashes on the first line's x-height (EN 1.6 / ZH 1.85 leading), tags neutral */
.tl-card__points li::before {
  top: 0.83em; top: calc(0.5lh + 0.03em);
  width: 10px; height: 1px; border-radius: 0; background: var(--muted); box-shadow: none;
}
.tags li { color: var(--text-2); border-color: var(--line-strong); background: transparent; }
/* V2 context lines are sentences (authored in sentence case): Inter, no caps, no tracking */
.tl-card__context, .mandate__context { font-family: var(--font-body); text-transform: none; letter-spacing: 0; color: var(--muted); }
.tl-card__context { font-size: 0.875rem; line-height: 1.55; }
.mandate__context { font-size: var(--fs-small); line-height: 1.5; }
/* zh.css gives these its mono-label tracking and a 12px phone size (its selector lists hold ".tags li",
   so they weigh 0,2,1); as sentences they match English */
.lang-zh .tl-card .tl-card__context { letter-spacing: 0; font-size: 0.875rem; }
.lang-zh .mandate .mandate__context { letter-spacing: 0; font-size: var(--fs-small); }
/* V3 years and keys are data: still mono, now muted (the gold went to the honours beside them) */
.edu__year, .ledger__year, .beyond__list :is(time, .beyond__key) { color: var(--muted); }
/* V4 controls rest neutral and warm to gold on hover or keyboard focus (not after a tap-close, Q12) */
.edu__open {
  color: var(--text-2); border-color: var(--line-strong); background: transparent;
  transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.edu__open:hover, .edu__open:focus-visible:not(.is-quiet-focus) { color: var(--gold-hi); border-color: var(--gold-line-hover); background: var(--gold-fill-hover); }
.press-card__tag { color: var(--text-2); border-color: var(--line-strong); }
.press-card__more { color: var(--text-2); transition: color var(--dur-1) var(--ease-out); }
.press-card:hover .press-card__more,
.press-card:has(.press-card__open:focus-visible:not(.is-quiet-focus)) .press-card__more { color: var(--gold); }
/* V5 marquee: the roman / italic alternation in two neutral tones; only the star glyphs stay gold */
.marquee__group li:nth-child(even) { color: var(--muted); }
/* V6 hobby chips: the neutral chip of the About tools */
.life__chips li { border-color: var(--line-strong); background: rgba(255, 255, 255, 0.02); }
/* V7 touch screens: a tap leaves no stuck gold (see P8); a press shows it briefly instead */
@media (hover: none) {
  .edu__open:hover { color: var(--text-2); border-color: var(--line-strong); background: transparent; }
  .press-card:hover .press-card__more { color: var(--text-2); }
  .edu__open:active { color: var(--gold-hi); border-color: var(--gold-line-hover); background: var(--gold-fill-hover); }
  .press-card:active .press-card__more { color: var(--gold); }
}

/* ── Section W: career proof + timecode years (2026-10-19) ─────────────────
   The current role carries its own proof (three rows that open the existing deal / press panels), and
   the rail shows each year as a large serif numeral that brightens when the gold line reaches its node.
   Range rows draw the numeral from data-tl-year (not data-year: that hook is the footer's live ©
   year, which initYear() overwrites); year-only rows ("2024", "2017") set their own text as the numeral,
   so nothing is read twice; the second 2017 keeps its small date line. */
/* W1 Highlights: the "Also" well with a label column; the Also well under it shares that column, so
   both texts start on one edge (English: the HIGHLIGHTS pill is 10 mono caps = 5.95rem; Chinese: the
   two labels are both two characters wide) */
.tl-card__highlights {
  --hl-pad: 4px; --hl-lh: 1.55;
  display: grid; grid-template-columns: var(--hl-label) minmax(0, 1fr); align-items: start; column-gap: var(--s-4);
}
.tl-card__highlights, .tl-card__highlights + .tl-card__also { --hl-label: max-content; }
html[lang="en"] :is(.tl-card__highlights, .tl-card__highlights + .tl-card__also) { --hl-label: minmax(5.95rem, max-content); }
.tl-card__highlights .tl-card__also-label { justify-self: start; margin-top: calc(var(--hl-pad) + (var(--hl-lh) * var(--fs-card-body) - var(--pill-xs)) / 2); }
.tl-card__hl { list-style: none; display: grid; }
.tl-card__hl .src-link {
  display: block; width: fit-content; max-width: 100%; padding-block: var(--hl-pad); /* the focus ring hugs the text */
  font-size: var(--fs-card-body); line-height: var(--hl-lh); color: var(--text); text-wrap: pretty;
  text-decoration: underline 1px transparent; text-underline-offset: 0.3em;
  transition: color var(--dur-1) var(--ease-out), text-decoration-color var(--dur-1) var(--ease-out);
}
.tl-card__hl-meta { color: var(--muted); }
.tl-card__hl .src-link:hover, .tl-card__hl .src-link:focus-visible:not(.is-quiet-focus) { color: var(--gold-hi); text-decoration-color: var(--gold-line-2); }
.tl-card__hl .src-link:focus-visible { outline-offset: 2px; }
.tl-card__hl .ext { margin-left: 0.4em; }
.tl-card__highlights + .tl-card__also { margin-top: var(--s-3); }
@media (min-width: 641px) {
  .tl-card__highlights + .tl-card__also { display: grid; grid-template-columns: var(--hl-label) minmax(0, 1fr); align-items: center; column-gap: var(--s-4); }
  .tl-card__highlights + .tl-card__also .tl-card__also-label { justify-self: start; }
}
@media (max-width: 640px) {
  /* phones: the label sits above the rows, which need the full measure */
  .tl-card__highlights { grid-template-columns: minmax(0, 1fr); row-gap: var(--s-2); }
  .tl-card__highlights .tl-card__also-label { margin-top: 0; }
}
/* Chinese rows break at the spaces around "·", not inside 演讲嘉宾 / 谅解备忘录 */
.lang-zh .tl-card__hl .src-link { word-break: keep-all; overflow-wrap: anywhere; }
/* touch: a taller row is the target; a tap leaves no stuck gold (P8), a press shows it */
@media (pointer: coarse) { .tl-card__highlights { --hl-pad: 10px; } }
@media (hover: none) {
  .tl-card__hl .src-link:hover { color: var(--text); text-decoration-color: transparent; }
  .tl-card__hl .src-link:hover > .ext { transform: none; opacity: 0.75; }
  .tl-card__hl .src-link:active { color: var(--gold-hi); }
}
/* W2 timecode years: Instrument Serif numerals, right-aligned in the rail; --text-2 until the gold line
   reaches the node (initTimeline's .is-active), then --text; the current year in the headings' gold.
   The digits' centre sits 0.47em below the top of a line-height 1 box (ascent .99, descent .31, figures
   .745), so a numeral shares the node / role-title centre line of D2 */
.timeline { --tl-year: clamp(2.75rem, 4vw, 3.75rem); }
.tl-item__date[data-tl-year]::before, .tl-item__date--year {
  font-family: var(--font-display); font-weight: 400; font-size: var(--tl-year); line-height: 1;
  letter-spacing: -0.01em; text-transform: none; color: var(--text-2);
  transition: color 0.6s var(--ease-out);
}
.tl-item__date[data-tl-year]::before {
  content: attr(data-tl-year); content: attr(data-tl-year) / "";
  display: block; margin-bottom: var(--s-2);
}
.tl-item.is-active .tl-item__date[data-tl-year]::before, .tl-item.is-active .tl-item__date--year { color: var(--text); }
.tl-item.is-current .tl-item__date[data-tl-year]::before {
  background: linear-gradient(100deg, var(--gold-hi), var(--gold) 50%, var(--gold-deep));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* the small date lines step back a tone (under a numeral, and the second 2017 that has none) */
.tl-item__date { color: var(--text-2); }
.tl-item__date--year + .tl-item__tenure { margin-top: var(--s-2); }
@media (min-width: 761px) {
  .tl-item__date[data-tl-year]::before, .tl-item__date--year { margin-top: calc(10px - 0.47em); }
  /* the year rides beside long cards (CDPQ, Sabbatical) until its own entry ends */
  .tl-item__when { position: sticky; top: calc(var(--nav-h) + var(--s-6)); }
}
@media (max-width: 760px) {
  /* one line above each card: the numeral, then the date / tenure line under it; more air above a
     year than below it, so it reads as the head of its own entry */
  .timeline { --tl-year: 2rem; }
  .timeline__list { gap: var(--s-8); }
  .tl-item__date[data-tl-year] { display: contents; }
  .tl-item__date[data-tl-year]::before, .tl-item__date--year { flex-basis: 100%; margin: 0; }
  .tl-item__date--year + .tl-item__tenure { margin-top: 0; }
  .tl-item:has(.tl-item__date[data-tl-year], .tl-item__date--year) .tl-item__node { top: calc(var(--tl-year) * 0.47 - 5.5px); }
}

/* ── Section X: intertitle, his Asian Banker quote (2026-10-19) ─────────────
   A change of pace between Career and Deals & press: one line of his own words from a publisher, set
   like a film intertitle (a <figure>, not a section: no card, no number). The words rise one by one
   through the headings' data-split mask; the attribution is a quiet button that opens the article's
   existing reader panel. Gold stays with the accent words (V): hairline, light and caption are neutral. */
.voice {
  position: relative; isolation: isolate; overflow: hidden;
  padding: clamp(96px, 12vw, 176px) var(--gutter);
  text-align: center;
}
/* X1 light: a faint moonlight-blue pool with a warm core behind the gold words (site.css alphas) */
.voice::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(42% 56% at 50% 52%, rgba(70, 110, 190, 0.13), transparent 70%),
    radial-gradient(24% 30% at 50% 54%, rgba(214, 178, 110, 0.06), transparent 70%);
}
/* X2 a 64px hairline drops from top centre; it draws down as the words rise (static: reduced motion, no JS) */
.voice::after {
  content: ""; position: absolute; left: 50%; top: 0; width: 1px; height: 64px;
  background: linear-gradient(var(--line-strong), transparent);
  transform-origin: top;
}
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .voice::after { transform: scaleY(0); transition: transform 1.4s var(--ease-out); }
  .voice:has(.is-in)::after { transform: none; }
  html:not(.js-ready) .voice::after { animation: reveal-failsafe 0.01s 3s forwards; }
}
/* X3 the quote: Instrument Serif italic, three balanced lines; "trust at scale" in the headings' gold */
.voice__text {
  max-width: 18ch; margin-inline: auto;
  font-family: var(--font-display); font-style: italic; font-weight: 400;
  font-size: clamp(2.6rem, 5.4vw, 5.6rem); line-height: 1.08; letter-spacing: -0.01em;
  color: var(--text); text-wrap: balance;
}
.voice__text em {
  font-style: italic;
  background: linear-gradient(100deg, var(--gold-hi), var(--gold) 50%, var(--gold-deep));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  padding-right: 0.08em; margin-right: -0.08em; /* the italic's overhang stays gold; the comma keeps its place */
}
/* wider word masks: the italic I's top serif reaches past the headings' 0.08em */
.voice__text .split-word { padding-inline: 0.16em; margin-inline: -0.16em; }
/* X4 the attribution: a mono byline that rises in after the words; "Read summary" warms to gold on
   hover or keyboard focus (V4), never after a tap-close (Q12) */
.voice__cite { margin-top: clamp(28px, 3vw, 40px); }
.voice__cite.reveal { transition-delay: 0.7s; }
.voice__src {
  display: inline-block; max-width: 100%; padding: var(--s-2) var(--s-3); margin-right: -0.18em;
  font-family: var(--font-mono); font-size: var(--fs-mono-label); line-height: 1.9;
  letter-spacing: 0.18em; text-transform: uppercase; text-wrap: balance;
  color: var(--muted); background: none; border: 0; border-radius: var(--r-sm); cursor: pointer;
}
.voice__who { color: var(--text-2); }
.voice__more { white-space: nowrap; transition: color var(--dur-1) var(--ease-out); }
.voice__more svg { display: inline-block; width: 0.95em; height: 0.95em; margin-left: 0.5em; vertical-align: -0.1em; transition: transform var(--dur-2) var(--ease-out); }
.voice__src:hover .voice__more, .voice__src:focus-visible:not(.is-quiet-focus) .voice__more { color: var(--gold-hi); }
.voice__src:hover .voice__more svg { transform: translateX(3px); }
@media (hover: none) {
  .voice__src:hover .voice__more { color: var(--muted); }
  .voice__src:hover .voice__more svg { transform: none; }
  .voice__src:active .voice__more { color: var(--gold-hi); }
}
@media (pointer: coarse) { .voice__src { padding-block: var(--s-3); } }
/* X5 Chinese: upright serif (the slant could only be faked), CJK leading, phrases break at the U+200B
   hints in zh-Hans.json; the byline drops caps and wide tracking like the other zh labels */
.lang-zh .voice__text, .lang-zh .voice__text em { font-style: normal; }
.lang-zh .voice__text { max-width: 11em; font-size: clamp(2.3rem, 4.6vw, 4.8rem); line-height: 1.3; letter-spacing: 0.02em; word-break: keep-all; }
/* the full-width ， that ends 大规模建立信任 takes its half-width form ("halt"), so that line centres on its ink */
.lang-zh .voice__text .split-punct { font-feature-settings: "halt"; }
/* the byline breaks only at its spaces after "·", never inside 《亚洲银行家》 or the date; half-width 《》
   keep the gaps around each "·" even */
.lang-zh .voice__src { text-transform: none; letter-spacing: 0.06em; margin-right: -0.06em; word-break: keep-all; font-feature-settings: "halt"; }
@media (max-width: 640px) {
  .voice__text { font-size: 2.4rem; } /* 18ch still gives the same three lines down to 360px */
  /* the first line (“金融领域的AI 应当助力, 10.33em) still fits on a 360px phone */
  .lang-zh .voice__text { font-size: min(2rem, calc((100vw - 2 * var(--gutter)) / 10.6)); }
}

/* ── Section Y: About, the mandate first + the figures band (2026-10-19) ────────
   The lede now states the current mandate and the strongest result (copy only, same facts: blocks
   s053-s055). The four figures leave the copy column and close About as one full-width band, read like
   a statement rather than four buttons: no glass, one hairline rule, serif values that rise once through
   a mask instead of counting up (the count-up showed "0+" and "$0.7B+" on the way), the currency spelled
   out. The LSE card's empty upper half becomes its focal figure: the same Khattar button, set as £33,000
   in the headings' gold, still opens the src-khattar panel (SPEC "Verifiable links"). */
/* Y1 the band: four columns on a --line-strong rule with --line dividers, each with the 40px gold tick;
   subgrid rows, so the values share one baseline (numbers large, words smaller) and the labels one line */
.stats {
  --fig-lg: clamp(3.5rem, 6.2vw, 6.5rem); /* numbers: 8+, USD 1B+ */
  /* words: Asia-Pacific, EN · 中文; capped by the column, so "Asia-Pacific" (4.03em) always clears the next divider */
  --fig-md: min(clamp(2.6rem, 4.2vw, 4rem), calc((25cqi - var(--col-pad) - var(--s-4)) / 4.15));
  --col-pad: clamp(20px, 2.2vw, 32px);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0;
  margin-top: var(--sub-gap); border-top: 1px solid var(--line-strong);
  container-type: inline-size; /* phones size the words in cqi of the band (a .stat container would block subgrid) */
}
.stat {
  display: grid; grid-row: span 2; grid-template-rows: subgrid;
  padding: var(--s-8) var(--s-4) var(--s-1) var(--col-pad);
  border: 0; border-left: 1px solid var(--line); border-radius: 0;
  background: none; box-shadow: none; overflow: visible; container-type: normal;
}
.stat:first-child { padding-left: 0; border-left: 0; }
.stat::before { left: var(--col-pad); width: 40px; transform-origin: left; }
.stat:first-child::before { left: 0; }
/* Y2 values: Instrument Serif on one baseline; the <p> is the rise mask (overflow: clip keeps its baseline,
   hidden would not); 0.12em of padding lets the CJK tops of 中文 / 亚太地区 inside it */
.stat__value {
  --fs: var(--fig-lg);
  align-self: baseline;
  font-size: var(--fs); line-height: 1; letter-spacing: -0.02em;
  overflow: clip; padding-block: 0.12em; margin-block: -0.12em;
}
.stat--word .stat__value { --fs: var(--fig-md); letter-spacing: -0.01em; }
.stat__rise { display: inline-block; }
/* the currency as a small mono unit, its cap top level with the figures' tops (figures .735em under a
   line-height-1 box top of .105em; mono caps .13em) */
.stat__unit {
  display: inline-block; vertical-align: top;
  margin: calc(0.105 * var(--fs) - 0.13em) 0.7em 0 0;
  font: 500 var(--fs-mono-label)/1 var(--font-mono); letter-spacing: 0.12em; color: var(--text-2);
}
.stat__label { margin-top: var(--s-4); }
/* Y3 entrance: the value rises through its mask while the tick draws and the label fades in, staggered
   by column (data-stagger's --d); the column itself stays put. Static under reduced motion or without JS. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .stats .stat.reveal { opacity: 1; transform: none; }
  .stat__rise { transform: translate3d(0, 118%, 0); transition: transform 1.25s var(--ease-out) calc(var(--d, 0ms) + 60ms); }
  .stat::before { transform: scaleX(0); transition: transform 1.1s var(--ease-out) var(--d, 0ms); }
  .stat__label { opacity: 0; transition: opacity 0.9s var(--ease-out) calc(var(--d, 0ms) + 0.4s); }
  .stat.is-in .stat__rise, .stat.is-in::before { transform: none; }
  .stat.is-in .stat__label { opacity: 1; }
  html:not(.js-ready) :is(.stat__rise, .stat__label), html:not(.js-ready) .stat::before { animation: reveal-failsafe 0.01s 3s forwards; }
}
/* Y4 two by two from the one-column About down: a hairline cross, ticks on both rows */
@media (max-width: 900px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); --fig-md: clamp(2.6rem, 4.2vw, 4rem); }
  .stat { padding-block: var(--s-6) var(--s-6); }
  .stat:nth-child(odd) { padding-left: 0; border-left: 0; }
  .stat:nth-child(even) { padding-left: var(--col-pad); border-left: 1px solid var(--line); }
  .stat:nth-child(n + 3) { border-top: 1px solid var(--line); }
  .stat:nth-child(odd)::before { left: 0; }
}
@media (max-width: 640px) {
  /* ~3rem numbers; the words scale with the column so "Asia-Pacific" (4.03em) fits at 360 */
  .stats { --fig-lg: 3rem; --fig-md: clamp(1.75rem, calc(11.5cqi - 4px), 2.6rem); --col-pad: var(--s-4); margin-top: var(--s-12); }
}
/* Y5 LSE: the Khattar button is the card's focal figure, centred in the space the bottom-anchored degree
   leaves (both auto margins share it; the year's 32px keeps a floor when there is none) */
.edu--featured .edu__year { margin-bottom: var(--s-8); }
.edu__prize {
  position: relative; z-index: 2; margin-top: auto; align-self: flex-start; max-width: 100%;
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-3);
  padding: 0; background: none; border: 0; border-radius: var(--r-sm); text-align: left;
}
.edu__prize-figure {
  font-family: var(--font-display); font-weight: 400; font-size: clamp(4rem, 7vw, 7rem);
  line-height: 1; padding-bottom: 0.06em; letter-spacing: -0.02em; white-space: nowrap;
  background: linear-gradient(100deg, var(--gold-hi), var(--gold) 50%, var(--gold-deep));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.edu__prize-cap {
  font-family: var(--font-mono); font-size: var(--fs-mono-label); line-height: 1.5;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-2); text-wrap: balance;
  transition: color var(--dur-1) var(--ease-out);
}
.edu__prize .ext { margin-left: 0.6em; }
.edu--featured .edu__open { margin-top: var(--s-6); }
/* the caption warms to gold on hover or keyboard focus (V4), never after a tap-close (Q12) */
.edu__prize:hover .edu__prize-cap, .edu__prize:focus-visible:not(.is-quiet-focus) .edu__prize-cap { color: var(--gold-hi); }
.edu__prize:hover .ext { transform: translateX(3px); opacity: 1; }
.edu__prize:focus-visible { outline-offset: 8px; }
@media (hover: none) {
  .edu__prize:hover .edu__prize-cap { color: var(--text-2); }
  .edu__prize:hover .ext { transform: none; opacity: 0.75; }
  .edu__prize:active .edu__prize-cap { color: var(--gold-hi); }
}
/* the full-width LSE card on tablets: the degree bottom-left and the figure bottom-right, so the wide card has
   no empty half; the caption centres on the "View courses" label beside it */
@media (min-width: 761px) and (max-width: 1100px) {
  .edu--featured { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto 1fr; column-gap: var(--s-8); }
  .edu--featured .edu__year { grid-column: 1 / -1; margin-bottom: 0; }
  .edu--featured .edu__body { grid-area: 2 / 1; align-self: end; margin-top: 0; }
  .edu__prize {
    grid-area: 2 / 2; align-self: end; margin: 0 0 calc((var(--control-sm) - 1.5 * var(--fs-mono-label)) / 2);
    align-items: flex-end; text-align: right;
  }
}
@media (min-width: 761px) and (max-width: 900px) {
  .edu__prize { margin-bottom: calc((44px - 1.5 * var(--fs-mono-label)) / 2); } /* the course button is 44px here (M) */
}
/* Y6 Chinese: the lede breaks only between phrases (U+200B hints in zh-Hans.json s053), never inside
   东南亚市场拓展 or before a lone 我; labels without caps or wide tracking, like the other zh labels */
.lang-zh .about__lede { word-break: keep-all; overflow-wrap: anywhere; line-height: 1.3; } /* four CJK lines need more air than 1.17 (phones: zh.css 1.4) */
.lang-zh .edu__prize-cap { text-transform: none; letter-spacing: 0.06em; word-break: keep-all; }
@media (max-width: 640px) { .lang-zh .edu__prize-cap { font-size: 0.75rem; } }

/* ── Section O: the hero opening (2026-10-19) ────────────────────────────────
   The one approved change to the hero (#9): the name lands first, then Singapore launches the routes
   (globe.js `intro`, played on the first home view of a tab session; main.js initIntro). The chrome waits
   for the scene: the nav and the scroll cue fade in at 1.6s instead of sitting over an empty frame. Every
   later view (html.intro-seen: a reload, the other language, back from booking, a deep link) comes in
   quickly with the nav already in place (index.html modulepreloads main.js's imports, so it can decide before
   the first frame; when it decides late, html.intro-late brings in only the nav). Existing keyframes only; composition, colours and the settled
   motion are unchanged. Reduced motion: site.css ends every entrance at once; the globe draws its settled frame. */
/* O1 the name first: 0.35s (it was 0.62s, after the role line); the role, lede, buttons and clock keep theirs */
.hero__content > .hero__title { animation-delay: 0.35s; }
/* O2 nav and scroll cue, home only (the subpages' nav has no .hero after it) */
.nav:has(~ .hero) > :is(.nav__brand, .nav__links, .nav__toggle), .hero .scroll-cue {
  opacity: 0; animation: fade-in 0.9s 1.6s var(--ease-out) forwards;
}
/* ...a later view whose script ran once the entrance was under way (html.intro-late; main.js initIntro sets
   --intro-late to how long the nav has already waited): its wait ends now and it fades in quickly, while the
   hero keeps the timing it is already playing (moving that forward would jump) */
.intro-late .nav:has(~ .hero) > * { animation-delay: var(--intro-late, 0s); animation-duration: 0.4s; }
/* ...but at once, and for good, when the reader reaches for them first (html.intro-chrome: a key, a tap on
   the nav, a scroll; main.js). Focus alone also works without JS. Only the timing changes, so a running fade
   is never restarted. */
.intro-chrome .nav:has(~ .hero) > *, .intro-chrome .hero .scroll-cue,
.nav:has(~ .hero):focus-within > *, .menu-open .nav:has(~ .hero) > *, .hero .scroll-cue:focus-visible {
  animation-delay: 0s; animation-duration: 0.2s;
}
/* O3 the intro fades the land in on the canvas itself (the 2.2s CSS fade would dim the hub's ignition) */
html.intro .hero__globe { animation: none; opacity: 1; }
/* O4 later views: the same order, quicker, and no wait for the nav */
.intro-seen .hero__globe { animation-duration: 1.2s; animation-delay: 0s; }
.intro-seen .hero__portrait { animation-duration: 1s; animation-delay: 0.08s; }
.intro-seen .hero__content > * { animation-duration: 0.8s; }
.intro-seen .hero__content > .hero__title { animation-delay: 0.1s; }
.intro-seen .hero__content > .eyebrow { animation-delay: 0.18s; }
.intro-seen .hero__content > .hero__lede { animation-delay: 0.26s; }
.intro-seen .hero__content > .hero__actions { animation-delay: 0.32s; }
.intro-seen .hero__content > .hero__meta { animation-delay: 0.38s; }
.intro-seen .hero .scroll-cue { animation-duration: 0.6s; animation-delay: 0.45s; }
.intro-seen .nav:has(~ .hero) > * { animation: none; opacity: 1; }

/* ── Section T: booking tidy-up (2026-10-19) ─────────────────────────────────
   #3, the code part. The scheduler opens on the calendar: hide_event_type_details=1 drops Calendly's white
   details column, and its facts (length, format) join the page's own facts row in the site's type, with the
   visitor's own clock beside Singapore's (subpage.js initYourTime). The frame is capped as close to Calendly's
   own width as its fixed-height layout allows (T2), so it reads as a framed insert in the 1240px page. */
/* T1 two rows of three: the meeting (length, format, languages) over the clocks (Singapore's, where he is
   based, the visitor's). Fixed cells, so a hidden "Your time" (UTC+8 visitors, no JS) leaves an empty cell
   instead of moving the others */
.pg-facts {
  grid-auto-flow: row;
  grid-template-columns: repeat(3, auto);
  grid-template-areas: "length format langs" "local base yours";
  gap: var(--s-6) 2.4rem;
}
.pg-facts__length { grid-area: length; }
.pg-facts__format { grid-area: format; }
.pg-facts__langs { grid-area: langs; }
.pg-facts__local { grid-area: local; }
.pg-facts__base { grid-area: base; }
.pg-facts__yours { grid-area: yours; }
.pg-facts > [hidden] { display: none; }
/* the third column is held at the width "Your time" usually needs ("Singapore is 12 h ahead"), so the
   right-aligned facts do not widen leftwards when it appears */
.pg-facts__langs { min-width: 10.25rem; }
/* a value's second line ("link on confirmation", "Singapore is 7 h ahead"): quieter, on its own line. Those
   values flow as text (a wrapping flex row would size its column to both lines side by side) */
.pg-facts dd:has(.pg-facts__note) { display: block; }
.pg-facts__note { display: block; margin-top: 2px; font-size: 0.8rem; line-height: 1.45; color: var(--muted); }
.pg-facts__note:empty { display: none; }
/* the clocks row keeps a note line's height whether or not "Your time" (and its note) shows, so the
   scheduler never moves when subpage.js reveals it */
.pg-facts__local::after { content: ""; display: block; height: calc(2px + 0.8rem * 1.45); }
/* T2 the scheduler's frame, capped but never under Calendly's wide layout. Calendly switches layout at a 1000px
   frame: from there its page keeps a fixed 660px and the times scroll inside it; in a narrower frame, picking a
   date grows the page ~630px into one long column of times beside a white void (it did at an 840px cap). 1040
   leaves a 1018px frame, so even a classic 17px scrollbar inside it stays clear of the switch. The wide layout
   opens on a 402px calendar that widens to 680 when a date is picked (sideways only) */
.pg--booking .pg-card { max-width: 1040px; margin-inline: auto; container: pg-card / inline-size; }
/* first-paint guesses = the page height Calendly then reports, per its three layouts: 602 in a frame under 650px,
   700 up to 999px, 660 from 1000px. The queries read the card's content box, which is the frame's own width, so
   they switch exactly where Calendly does (phones included; on the half pixel, as its frame width rounds) and nothing
   moves when it reports */
.pg--booking .pg-calendly { height: 700px; }
@container pg-card (max-width: 649.49px) { .pg--booking .pg-calendly { height: 602px; } }
@container pg-card (min-width: 999.5px) { .pg--booking .pg-calendly { height: 660px; } }
@media (min-width: 901px) and (max-width: 1100px) {
  /* T3 here the six facts no longer fit beside the title (it broke into "Book a / meeting"): the header
     stacks, as it already does at 900px and below */
  .pg-head { grid-template-columns: minmax(0, 1fr); align-items: start; gap: 1.8rem; }
  .pg-facts { justify-content: start; }
}
@media (min-width: 641px) and (max-width: 1100px) {
  /* T3 the stacked header is taller by the facts' second row: the horizon arc drops with the card, so it
     still rises behind the scheduler instead of cutting through the facts */
  .pg--booking .pg-bg::after { top: max(46vh, 540px); }
}
@media (max-width: 640px) {
  /* T4 phones: two columns, the meeting / the place / the clocks. The clocks go last: for UTC+8 visitors "Your
     time" stays hidden, and its empty cell then ends the grid like a wrap instead of leaving a hole mid-grid */
  .pg-facts {
    grid-template-columns: repeat(2, auto);
    grid-template-areas: "length format" "base langs" "local yours";
    gap: var(--s-4) 1.1rem;
  }
}
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  /* T5 phone landscape: the facts stay beside the title (S14) in a tighter grid, so the title keeps one line
     and the scheduler still starts on the first screen */
  .pg-facts { gap: var(--s-3) 1.1rem; }
  .pg-facts > div { padding-left: 0.75rem; }
  .pg-facts dd { font-size: 0.9rem; }
  .pg-facts__note { font-size: 0.75rem; }
  .pg-facts__local::after { height: calc(2px + 0.75rem * 1.45); }
  .pg-facts__langs { min-width: 9rem; }
}
@media (max-width: 799px) and (max-height: 500px) and (orientation: landscape) {
  /* T5 smaller landscape phones (667-799px): two columns, as in portrait, so the title still has room */
  .pg-facts { grid-template-columns: repeat(2, auto); grid-template-areas: "length format" "base langs" "local yours"; }
}

/* ── Section A2: legible "1" in the figures band (2026-10-19) ──
   Instrument Serif's 1 is drawn like an l, so "1B+" read as "lB+". Only that digit borrows the
   flagged 1 of the system Times (Windows, macOS, iOS), scaled to the serif's figure height. */
.stat__one { font-family: "Times New Roman", Times, serif; font-size: 1.07em; line-height: 0; }

/* ── Section A3: LSE card, the Khattar Scholar title (2026-10-19, per Darrell) ──
   The focal line reads "LSE Khattar Scholar" instead of a large £ figure: set a step below the degree title
   (so the degree stays the card's heading), "Khattar Scholar" in the gold italic accent of the headings; the
   £33,000 moves into the caption as a plain fact. */
.edu__prize-figure {
  font-size: clamp(2rem, 3vw, 2.75rem); line-height: 1.05; letter-spacing: 0; padding-bottom: 0;
  white-space: normal; text-wrap: balance; color: var(--text); background: none;
  -webkit-background-clip: border-box; background-clip: border-box;
}
.edu__prize-figure em {
  font-style: italic; padding-right: 0.06em;
  background: linear-gradient(100deg, var(--gold-hi), var(--gold) 50%, var(--gold-deep));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.edu__prize { gap: var(--s-2); }
.lang-zh .edu__prize-figure { font-size: clamp(1.75rem, 2.6vw, 2.4rem); } /* CJK glyphs fill the em box: one step down, like the zh headings */

/* ── Section A4: the current role reads "Now", not its start year (2026-10-19, per Darrell) ──
   A large "2025" beside the current role read as if the page were out of date. The current entry's
   numeral is the word Now (现任 on /zh/) in the headings' gold italic, with "Since 2025" and the live
   tenure under it; the NOW pill would repeat it, so it stays for screen readers only. The other
   entries keep their start years. */
.tl-item.is-current .tl-item__date[data-tl-year]::before { font-style: italic; padding-right: 0.08em; }
.lang-zh .tl-item.is-current .tl-item__date[data-tl-year]::before { content: "现任"; content: "现任" / ""; font-style: normal; padding-right: 0; }
.tl-item.is-current .tl-item__tenure .badge-now {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.lang-zh .tl-item.is-current .tl-item__date[data-tl-year]::before { font-size: calc(var(--tl-year) * 0.8); } /* CJK fills the em box: one step down to match "Now" */
