/* ==========================================================================
   ANH NGỮ MỞ — demo for Hoàng Anh Studio
   --------------------------------------------------------------------------
   CONCEPT
   A level ladder. The page is one climb from "mất gốc" to IELTS: the hero
   names the climb, Cách học explains how a rung is earned, Lộ trình shows the
   ladder itself filling as you scroll, and the placement form tells you which
   rung to step onto.

   PALETTE — every ratio below was computed, not estimated (WCAG 2.2)
     --cobalt      #0F2A9E  primary fill / CTA / links
     --cobalt-deep #081A66  hero + placement ground
     --cobalt-lift #1B3BC4  primary hover
     --ink         #0B1533  body text                    17.96 : 1 on #FFF
     --ink-soft    #414C74  secondary text                8.36 : 1 on #FFF
     --ink-mute    #5A6489  meta text                     5.80 : 1 on #FFF
     --paper       #F5F7FD  quiet section ground
     --paper-2     #EDF1FC  divider inside the stacked ladder
     rung highlight: rgba(15,42,158,.10) over --paper = #DEE3F4
                    ink-soft on it 6.53 : 1, ink 14.03 : 1
     --sun         #FFC83D  accent fill, eyebrow on dark
     --sun-ink     #3A2A00  text on sun                   8.99 : 1 on #FFC83D
     --line        #DCE2F3  hairline, non-text only
     --border-ctl  #7A88B4  input/choice border           3.50 : 1 on #FFF
   On the dark grounds:
     #FFFFFF on --cobalt-deep  15.56 : 1
     #C9D3F7 on --cobalt-deep  10.48 : 1   muted body on dark
     #A9B6E8 on --cobalt-deep   7.81 : 1   aside on dark
     --sun on --cobalt-deep    10.06 : 1
     #8E9CD4 on footer #06124A  6.58 : 1   credit line
     #C9D3F7 on footer #06124A 11.85 : 1
   Text pairs on light grounds: ink-soft on paper 7.81, ink-mute on paper 5.42,
   ink-mute on paper-2 5.14, cobalt on white 11.38, white on cobalt 11.38,
   placeholder #5E6A92 on paper 4.96, error #B3261E on white 6.54.
   Sun is never text on white (1.5 : 1) — it is a fill only. The focus ring is
   #C2410C on light (5.18 : 1) and #FFFFFF on dark (15.56 : 1), both over 3 : 1;
   the white hero panel restores #C2410C locally.
   Separation that is not text: --line is 1.21 : 1 on --paper, so cards carry a
   resting box-shadow instead of relying on the border, and the header shadow
   is rgba(11,21,51,.18), which composites to #D3D5DA (1.47 : 1) on white.

   TYPE (Google Fonts)
     Display  Sora 500/600/700
     Text     Be Vietnam Pro 400/500/600
     display  clamp(1.75rem,6.5vw,4rem) / 1.14 / -0.038em / 700
     h1       = display
     h2       clamp(1.6rem,3.2vw,2.4rem) / 1.1 / -0.025em / 700
     h3       1.1875rem / 1.28 / -0.015em / 600
     body     1.0625rem (17px) / 1.65 / 0 / 400
     small    0.9375rem (15px) / 1.55 / 0 / 400
     meta     0.8125rem (13px) / 1.4 / 0.09em / 600 uppercase
     Smallest text on the page is 0.75rem (12px): chip labels, tick labels,
     level tags and footer credit. Nothing goes below 12px.

   LAYOUT
   1200px wrap. Lộ trình is the structural idea: a 0.7 / 1.3 split with a
   sticky ladder column on the left and the filter bar + two-up card grid on
   the right. Below 1080px the ladder unsticks and becomes an index card read
   top to bottom; the cards go one-up below 620px.

   SIGNATURE MOTION
   The ladder in #lo-trinh. Its fill is a scaleY on the cobalt track, driven by
   the view timeline of the section itself, so it grows with the scroll position
   of its container. Each rung's highlight, dot fill and level tag light in the
   same frame the fill's leading edge reaches it. Falls back to a complete
   ladder when view timelines are unsupported. Nothing else on the page moves
   on scroll; the rest is IntersectionObserver reveals and hover states. The
   hero mask is the one other entrance and stays quiet.
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */
:root {
  --cobalt: #0F2A9E;
  --cobalt-deep: #081A66;
  --cobalt-lift: #1B3BC4;
  --ink: #0B1533;
  --ink-soft: #414C74;
  --ink-mute: #5A6489;
  --paper: #F5F7FD;
  --paper-2: #EDF1FC;
  --sun: #FFC83D;
  --sun-ink: #3A2A00;
  --white: #FFFFFF;
  --line: #DCE2F3;
  --line-dark: rgba(255, 255, 255, 0.16);

  --font-display: "Sora", "Segoe UI", system-ui, sans-serif;
  --font-text: "Be Vietnam Pro", "Segoe UI", system-ui, sans-serif;

  --ease-enter: cubic-bezier(.16, 1, .3, 1);
  --ease-expo: cubic-bezier(.19, 1, .22, 1);
  --ease-move: cubic-bezier(.65, 0, .35, 1);
  --ease-exit: cubic-bezier(.7, 0, .84, 0);
  --ease-pop: cubic-bezier(.34, 1.4, .64, 1);

  --dur-micro: 140ms;
  --dur-small: 220ms;
  --dur-med: 320ms;
  --dur-large: 480ms;
  --dur-reveal: 680ms;
  --dur-hero: 900ms;

  --wrap: 1200px;
  --gutter: clamp(20px, 5vw, 48px);
  --radius: 4px;
  --radius-lg: 10px;
  --focus: #C2410C;
  --border-ctl: #7A88B4;
}

/* ---------- 2. Reset / base --------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.1;
  text-wrap: balance;
}
/* The section scale is declared once here rather than left to the UA default,
   so every h2 on the page is the same size. The two compact headings
   (.panel__title, .qa__btn) opt out by class. */
h2 { font-size: clamp(1.6rem, 3.2vw, 2.4rem); }
h3 { font-size: 1.1875rem; line-height: 1.28; letter-spacing: -0.015em; }

p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }
img, svg { display: block; max-width: 100%; }
a { color: inherit; }
button, input { font: inherit; color: inherit; }
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}
.hero, .check, .site-footer { --focus: #FFFFFF; }
.form, .result { --focus: #C2410C; }

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

.skip {
  position: absolute;
  left: 12px;
  top: 12px;
  z-index: 200;
  transform: translateY(-160%);
  background: var(--sun);
  color: var(--sun-ink);
  font-weight: 600;
  font-size: 0.9375rem;
  padding: 12px 18px;
  border-radius: var(--radius);
  text-decoration: none;
  transition: transform var(--dur-small) var(--ease-enter);
}
.skip:focus-visible { transform: translateY(0); }

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

/* ---------- 3. Type helpers --------------------------------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 18px;
  font-family: var(--font-text);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--cobalt);
}
.eyebrow--light { color: var(--sun); }
.eyebrow__dot {
  width: 6px; height: 6px;
  background: currentColor;
  border-radius: 50%;
}
.lede {
  max-width: 46ch;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(36px, 5vw, 60px);
}
.section-head h2 { margin-bottom: 16px; }
.section-head--split {
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(20px, 4vw, 64px);
  align-items: end;
}
.section-head--split h2 { max-width: 18ch; }

/* ---------- 4. Buttons --------------------------------------------------- */
.btn {
  --btn-bg: var(--cobalt);
  --btn-fg: var(--white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 13px 24px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-text);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur-small) var(--ease-enter),
              background-color var(--dur-small) var(--ease-move),
              color var(--dur-small) var(--ease-move),
              border-color var(--dur-small) var(--ease-move);
}
.btn:active { transform: scale(0.97); transition-duration: 90ms; }

.btn--primary { --btn-bg: var(--cobalt); --btn-fg: #fff; }
.btn--sun { --btn-bg: var(--sun); --btn-fg: var(--sun-ink); }
.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: #fff;
  border-color: rgba(255, 255, 255, 0.45);
}
.btn--quiet {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border-color: var(--border-ctl);
}
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover { background: var(--cobalt-lift); transform: translateY(-1px); }
  .btn--sun:hover { background: #FFD469; transform: translateY(-1px); }
  .btn--ghost:hover { border-color: #fff; background: rgba(255, 255, 255, 0.08); transform: translateY(-1px); }
  .btn--quiet:hover { border-color: var(--cobalt); color: var(--cobalt); }
  .nav-toggle:hover { border-color: var(--cobalt); }
}

/* ---------- 5. Header ---------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.94);
  border-bottom: 1px solid var(--line);
  backdrop-filter: saturate(1.4) blur(10px);
}
.site-header::after {
  content: "";
  position: absolute;
  inset: 100% 0 auto 0;
  height: 18px;
  background: linear-gradient(to bottom, rgba(11, 21, 51, 0.18), rgba(11, 21, 51, 0));
  pointer-events: none;
}
/* The header reacts to scroll by fading in a soft shadow under the bar. The
   keyframes supply opacity only. The base gradient above is the fallback: in an
   engine without scroll timelines the shadow simply stays at full strength, so
   the header still reads as separated from the page instead of losing the
   effect altogether (contract §5). */
@supports (animation-timeline: scroll()) {
  .site-header::after {
    animation: header-shadow linear both;
    animation-timeline: scroll(root);
    animation-range: 0 220px;
  }
}
@keyframes header-shadow { from { opacity: 0; } to { opacity: 1; } }

.site-header__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 76px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  color: var(--ink);
  padding: 6px 0;
  min-height: 44px;
}
.brand__mark { flex: none; border-radius: 7px; }
.brand__name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.brand__name b { font-weight: 700; color: var(--cobalt); }

.site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
}
.site-nav__list {
  display: flex;
  align-items: center;
  gap: 4px;
}
.site-nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 10px;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  border-radius: var(--radius);
  transition: color var(--dur-small) var(--ease-move);
}
.site-nav__link::after {
  content: "";
  position: absolute;
  left: 10px; right: 10px; bottom: 8px;
  height: 2px;
  background: var(--cobalt);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-small) var(--ease-enter);
}
.site-nav__link[aria-current="page"] { color: var(--ink); font-weight: 600; }
.site-nav__link[aria-current="page"]::after { transform: scaleX(1); }
@media (hover: hover) and (pointer: fine) {
  .site-nav__link:hover { color: var(--cobalt); }
  .site-nav__link:hover::after { transform: scaleX(1); }
}
.site-header__actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sound-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 6px 12px;
  border: 1px solid var(--border-ctl);
  border-radius: 999px;
  background: rgba(15, 42, 158, 0.05);
  color: var(--cobalt);
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: all var(--dur-small) var(--ease-enter);
}
.sound-toggle:hover {
  background: var(--cobalt);
  color: #fff;
  border-color: var(--cobalt);
  transform: translateY(-1px);
}
.sound-toggle.is-active {
  background: var(--cobalt);
  color: #fff;
  border-color: var(--cobalt);
  box-shadow: 0 0 12px rgba(15, 42, 158, 0.35);
}
.sound-toggle__icon--on { display: none; }
.sound-toggle.is-active .sound-toggle__icon--off { display: none; }
.sound-toggle.is-active .sound-toggle__icon--on { display: block; }

.site-nav__cta { min-height: 44px; padding: 10px 18px; font-size: 0.875rem; }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 48px; height: 48px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border-ctl);
  border-radius: var(--radius);
  cursor: pointer;
  transition: transform var(--dur-micro) var(--ease-enter),
              border-color var(--dur-small) var(--ease-move);
}
.nav-toggle:active { transform: scale(0.94); transition-duration: 90ms; }
.nav-toggle__bars {
  display: grid;
  gap: 5px;
  width: 20px;
}
.nav-toggle__bars span {
  display: block;
  height: 2px;
  background: var(--ink);
  transition: transform var(--dur-med) var(--ease-enter);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:first-child { transform: translateY(3.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

/* ---------- 6. Hero ------------------------------------------------------ */
.hero {
  position: relative;
  overflow: hidden;
  background: var(--cobalt-deep);
  color: #fff;
  isolation: isolate;
}
.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  opacity: 0.6;
}
.hero__status-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  background: rgba(255, 200, 61, 0.12);
  border: 1px solid rgba(255, 200, 61, 0.35);
  border-radius: 999px;
  margin-bottom: 18px;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--sun);
  backdrop-filter: blur(8px);
}
.pulse-beacon {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--sun);
  box-shadow: 0 0 0 0 rgba(255, 200, 61, 0.7);
  animation: beacon-pulse 2s infinite cubic-bezier(0.66, 0, 0, 1);
}
@keyframes beacon-pulse {
  to {
    box-shadow: 0 0 0 10px rgba(255, 200, 61, 0);
  }
}
.voice-analyzer {
  margin-top: 32px;
  padding: 14px 18px;
  background: rgba(15, 42, 158, 0.28);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius);
  backdrop-filter: blur(12px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  max-width: 480px;
}
.voice-analyzer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 0.75rem;
}
.voice-analyzer__tag {
  display: flex;
  align-items: center;
  gap: 6px;
  color: #A9B6E8;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.voice-analyzer__wave-dot {
  width: 6px;
  height: 6px;
  background: #00F0FF;
  border-radius: 50%;
  box-shadow: 0 0 8px #00F0FF;
}
.voice-analyzer__stat {
  color: var(--sun);
  font-weight: 500;
  font-family: var(--font-display);
}
.voice-analyzer__bars {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 28px;
}
.voice-analyzer__bars span {
  flex: 1;
  height: var(--h, 40%);
  background: linear-gradient(to top, rgba(0, 240, 255, 0.4), #FFC83D);
  border-radius: 2px;
  transition: height 120ms ease;
  animation: bar-dance 1.4s ease-in-out infinite alternate;
  animation-delay: calc(var(--i, 0) * 80ms);
}
@keyframes bar-dance {
  0% { transform: scaleY(0.4); }
  50% { transform: scaleY(1); }
  100% { transform: scaleY(0.6); }
}
.hero__grid-lines {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
  background-size: 12.5% 100%;
  mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}
.hero::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -18%;
  right: -10%;
  width: 46vw;
  min-width: 420px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 40%, rgba(51, 92, 255, 0.42), transparent 66%);
  pointer-events: none;
}
.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.85fr);
  gap: clamp(36px, 5vw, 72px);
  align-items: center;
  padding-block: clamp(52px, 7vw, 96px) clamp(64px, 8vw, 112px);
}
.hero__title {
  font-size: clamp(1.75rem, 6.5vw, 4rem);
  line-height: 1.14;
  letter-spacing: -0.038em;
  margin-bottom: 26px;
}
.hero__title em {
  font-style: normal;
  color: var(--sun);
  white-space: nowrap;
}
/* The mask: the clip sits on the line, the inner span travels up into it. The
   text itself is never transparent, so the headline is painted from the first
   frame and stays the LCP node. Vietnamese stacks marks above and below the
   letter, so the clip box is opened with padding and the same amount pulled
   back with a negative margin; the start offset (160%) is larger than the
   padded box, so no sliver of a letter is ever visible at rest. */
.line {
  display: block;
  overflow: hidden;
  padding-block: 0.14em 0.2em;
  margin-block: -0.14em -0.2em;
}
.line__in { display: block; }

html.js-motion .line__in {
  animation: line-up var(--dur-hero) var(--ease-expo) both;
}
html.js-motion .line:nth-child(1) .line__in { animation-delay: 0ms; }
html.js-motion .line:nth-child(2) .line__in { animation-delay: 55ms; }
html.js-motion .line:nth-child(3) .line__in { animation-delay: 110ms; }
@keyframes line-up {
  from { transform: translate3d(0, 160%, 0); }
  to { transform: translate3d(0, 0, 0); }
}

.hero__lede {
  max-width: 52ch;
  font-size: clamp(1rem, 1.25vw, 1.125rem);
  line-height: 1.62;
  color: #C9D3F7;
}
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
}
.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-top: 36px;
  padding-top: 22px;
  border-top: 1px solid var(--line-dark);
}
.hero__facts li {
  position: relative;
  padding-left: 14px;
  font-size: 0.875rem;
  color: #C9D3F7;
}
.hero__facts li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.62em;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--sun);
}

.hero__panel { align-self: center; }
.hero__copy { min-width: 0; }
.programmes { min-width: 0; }
.panel {
  position: relative;
  background: #fff;
  color: var(--ink);
  border-radius: var(--radius-lg);
  padding: 26px 26px 22px;
  box-shadow: 0 28px 60px -28px rgba(3, 10, 40, 0.7);
  transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1), box-shadow 0.25s ease;
  transform-style: preserve-3d;
  will-change: transform;
  /* The panel sits inside the dark hero, whose focus ring is white. On the
     white card the ring has to go back to the light-ground colour. */
  --focus: #C2410C;
}
.panel:hover {
  box-shadow: 0 32px 70px -24px rgba(0, 240, 255, 0.2), 0 28px 60px -28px rgba(3, 10, 40, 0.8);
}
.panel::before {
  content: "";
  position: absolute;
  left: 0; top: 22px; bottom: 22px;
  width: 4px;
  background: var(--sun);
  border-radius: 0 4px 4px 0;
}
.panel__head { margin-bottom: 18px; }
.panel__title {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.panel__sub {
  margin-top: 4px;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--ink-mute);
}
.panel__list { border-top: 1px solid var(--line); }
.panel__list li {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  align-items: start;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.panel__n {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}
.panel__l {
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
}
.panel__l small {
  display: block;
  margin-top: 2px;
  font-size: 0.8125rem;
  font-weight: 400;
  line-height: 1.45;
  color: var(--ink-mute);
}
.panel__c {
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--cobalt);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.panel__foot {
  margin-top: 4px;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink-mute);
}
.panel__foot a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  font-weight: 600;
  color: var(--cobalt);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.panel__foot a span { transition: transform var(--dur-small) var(--ease-enter); }
@media (hover: hover) and (pointer: fine) {
  .panel__foot a:hover span { transform: translateX(4px); }
}

/* Tech Marquee */
.tech-marquee {
  background: #06144A;
  color: #fff;
  overflow: hidden;
  white-space: nowrap;
  padding: 12px 0;
  border-block: 1px solid rgba(255, 255, 255, 0.12);
}
.tech-marquee__track {
  display: inline-flex;
  gap: 24px;
  animation: marquee-roll 28s linear infinite;
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #C9D3F7;
}
.tech-marquee__track span:first-child { color: var(--sun); }
@keyframes marquee-roll {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}

/* ---------- 7. Method ---------------------------------------------------- */
.method {
  padding-block: clamp(64px, 9vw, 112px);
  background: var(--white);
}
.method__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.mstep {
  background: var(--white);
  padding: clamp(24px, 3vw, 40px) clamp(20px, 2.6vw, 34px) clamp(28px, 3.4vw, 44px) 0;
}
.mstep + .mstep { padding-left: clamp(20px, 2.6vw, 34px); }
.mstep__n {
  display: block;
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--cobalt);
  margin-bottom: clamp(28px, 4vw, 52px);
}
.mstep h3 { margin-bottom: 10px; }
.mstep p { font-size: 0.9375rem; line-height: 1.62; color: var(--ink-soft); }

/* ---------- 8. Journey: the ladder + programmes -------------------------- */
.journey {
  position: relative;
  padding-block: clamp(64px, 9vw, 112px);
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  view-timeline-name: --journey;
  view-timeline-axis: block;
}
.journey__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.7fr) minmax(0, 1.3fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}

.ladder-col {
  position: sticky;
  top: 96px;
  align-self: start;
  padding-block: 8px;
}
.ladder {
  position: relative;
  padding-left: 40px;
  isolation: isolate;
}
.ladder__track {
  position: absolute;
  left: 5px;
  top: 8%;
  bottom: 8%;
  width: 3px;
  background: #D5DCF0;
  border-radius: 3px;
}
.ladder__fill {
  position: absolute;
  inset: 0;
  background: var(--cobalt);
  border-radius: 3px;
  /* Static glow so the leading edge reads as a moving light, not a 3px line.
     The shadow is not animated — only `scale` is. */
  box-shadow: 0 0 0 3px rgba(15, 42, 158, 0.10);
  transform-origin: 50% 0;
}

.ladder__rungs { position: relative; height: 472px; }
.rung {
  position: absolute;
  top: var(--at);
  left: 0;
  right: 0;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 12px;
  translate: 0 -50%;
  padding: 6px 0 6px 4px;
  border-radius: 4px;
}
.rung::before {
  content: "";
  position: absolute;
  inset: 0;
  left: -6px;
  background: rgba(15, 42, 158, 0.10);
  border-radius: 4px;
  z-index: -1;
}
.rung__dot {
  position: absolute;
  left: -40px;
  top: 50%;
  width: 13px;
  height: 13px;
  margin-top: -6.5px;
  border-radius: 50%;
  /* A hollow cobalt ring at rest; `lit-on` fills the centre as the fill's
     leading edge arrives. The state is carried by that fill alone — never by
     animating border-color, which is a paint property on a scroll-driven
     timeline and would cost a repaint every frame. */
  border: 2px solid var(--cobalt);
  background: var(--paper);
}
.rung__dot::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--cobalt);
}
.rung__name {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-soft);
}
.rung__code {
  position: relative;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rung__code::before {
  content: "";
  position: absolute;
  inset: -3px -6px;
  background: var(--sun);
  border-radius: 3px;
  z-index: -1;
}
.ladder__caption {
  margin-top: 20px;
  padding-left: 40px;
  font-size: 0.8125rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* The signature motion. The fill is bound to the view timeline of #lo-trinh, so
   it grows with the scroll position of its own container; each rung lights at
   the exact point the fill's leading edge reaches it.

   Geometry: the track spans 8% -> 92% of the ladder, and the rungs are placed
   by --at on that same band, so the fill's leading edge meets a rung at --at
   when the fill has travelled (--at - 8) / 84 of its length. The fill itself
   runs cover 26% -> 74% (it starts as the sticky column pins and finishes
   before the section leaves), so a rung lights at
   cover 26 + 48 * (--at - 8) / 84. The six numbers below are that formula,
   each widened by 1.6% so the light-up reads as a step rather than a fade.
   Where view timelines are unsupported, or the ladder is no longer sticky, the
   ladder is simply drawn complete. */
/* Rung positions on the ladder band (track spans 8% -> 92%). Declared here so
   they apply with or without view timelines, and sit next to the matching
   animation-range values inside the @supports block below. */
.rung:nth-child(1) { --at: 8%; }
.rung:nth-child(2) { --at: 24.8%; }
.rung:nth-child(3) { --at: 41.6%; }
.rung:nth-child(4) { --at: 58.4%; }
.rung:nth-child(5) { --at: 75.2%; }
.rung:nth-child(6) { --at: 92%; }

@supports (animation-timeline: view()) {
  .ladder__fill {
    animation: ladder-fill linear both;
    animation-timeline: --journey;
    animation-range: cover 26% cover 74%;
  }
  @keyframes ladder-fill { from { scale: 1 0; } to { scale: 1 1; } }

  .rung::before,
  .rung__dot::after {
    animation: lit-on linear both;
    animation-timeline: --journey;
  }
  @keyframes lit-on { from { opacity: 0; } to { opacity: 1; } }

  /* The level tag wipes in from its left edge — the one flourish that reads as
     "this rung is now earned" without moving any text. */
  .rung__code::before {
    transform-origin: 0 50%;
    animation: tag-wipe linear both;
    animation-timeline: --journey;
  }
  @keyframes tag-wipe {
    from { opacity: 0; transform: scaleX(0.3); }
    to { opacity: 1; transform: scaleX(1); }
  }

  /* Rung positions on the ladder band live above this block; the track runs
     8% -> 92% and the animation-range values below are derived from them. */

  /* --at: 8%  -> 26 + 48 * 0 / 84 */
  .rung:nth-child(1)::before,
  .rung:nth-child(1) .rung__dot::after,
  .rung:nth-child(1) .rung__code::before { animation-range: cover 26% cover 27.6%; }
  /* --at: 24.8% -> 26 + 48 * 16.8 / 84 = 35.6 */
  .rung:nth-child(2)::before,
  .rung:nth-child(2) .rung__dot::after,
  .rung:nth-child(2) .rung__code::before { animation-range: cover 35.6% cover 37.2%; }
  /* --at: 41.6% -> 26 + 48 * 33.6 / 84 = 45.2 */
  .rung:nth-child(3)::before,
  .rung:nth-child(3) .rung__dot::after,
  .rung:nth-child(3) .rung__code::before { animation-range: cover 45.2% cover 46.8%; }
  /* --at: 58.4% -> 26 + 48 * 50.4 / 84 = 54.8 */
  .rung:nth-child(4)::before,
  .rung:nth-child(4) .rung__dot::after,
  .rung:nth-child(4) .rung__code::before { animation-range: cover 54.8% cover 56.4%; }
  /* --at: 75.2% -> 26 + 48 * 67.2 / 84 = 64.4 */
  .rung:nth-child(5)::before,
  .rung:nth-child(5) .rung__dot::after,
  .rung:nth-child(5) .rung__code::before { animation-range: cover 64.4% cover 66%; }
  /* --at: 92% -> 26 + 48 * 84 / 84 = 74, the fill's own end, so this one
     completes with the fill rather than after it. */
  .rung:nth-child(6)::before,
  .rung:nth-child(6) .rung__dot::after,
  .rung:nth-child(6) .rung__code::before { animation-range: cover 72.4% cover 74%; }
}

/* --- filters --- */
.filters {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.chips {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 2px;
  margin: -2px;
}
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex: none;
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid var(--border-ctl);
  border-radius: 999px;
  background: #fff;
  color: var(--ink-soft);
  font-family: var(--font-text);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur-small) var(--ease-move),
              color var(--dur-small) var(--ease-move),
              border-color var(--dur-small) var(--ease-move),
              transform var(--dur-micro) var(--ease-enter);
}
.chip:active { transform: scale(0.97); transition-duration: 90ms; }
.chip[aria-pressed="true"] {
  background: var(--cobalt);
  border-color: var(--cobalt);
  color: #fff;
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .chip:hover:not([aria-pressed="true"]) { border-color: var(--cobalt); color: var(--cobalt); }
}
.filter-count {
  flex: none;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- cards --- */
.cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 24px 22px 22px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  /* A resting shadow, not a hover one: the card sits on --paper, where a
     1px --line border is only 1.21:1. The shadow carries the separation at
     rest; the hover layer below adds depth on top of it. */
  box-shadow: 0 1px 2px rgba(11, 21, 51, 0.06), 0 8px 20px -18px rgba(11, 21, 51, 0.35);
  transition: transform var(--dur-med) var(--ease-enter),
              border-color var(--dur-med) var(--ease-move);
}
/* Decorative shadow layer. It carries no content — the card itself is always
   painted, with or without JS. */
.card::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  box-shadow: 0 20px 44px -24px rgba(11, 21, 51, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-med) var(--ease-move);
}
.card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}
.card__level {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--cobalt);
  font-variant-numeric: tabular-nums;
}
.card__cat {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  padding: 3px 8px;
  border: 1px solid var(--border-ctl);
  border-radius: 999px;
}
.card h3 {
  margin-bottom: 8px;
}
.card__desc {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-soft);
  margin-bottom: 18px;
}
.card__facts {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px dashed var(--line);
}
.card__facts > div {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: 8px;
  padding: 3px 0;
}
.card__facts dt {
  font-size: 0.8125rem;
  color: var(--ink-mute);
}
.card__facts dd {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--ink);
}
.card__label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 10px;
}
.card__out { margin-bottom: 18px; }
.card__out li {
  position: relative;
  padding-left: 16px;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-bottom: 7px;
}
.card__out li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 7px;
  height: 1.5px;
  background: var(--cobalt);
}
.card__link {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  margin-bottom: -10px;
  padding: 8px 0;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--cobalt);
  text-decoration: none;
  align-self: flex-start;
}
.card__link span {
  transition: transform var(--dur-small) var(--ease-enter);
}
@media (hover: hover) and (pointer: fine) {
  .card:hover { transform: translateY(-3px); border-color: #C3CDF0; }
  .card:hover::after { opacity: 1; }
  .card:hover .card__link span { transform: translateX(4px); }
}
/* Focus affordance is not hover-only: a touch-primary device with a hardware
   keyboard still needs the card to read as focused. */
.card:focus-within { border-color: #C3CDF0; }
.card:focus-within::after { opacity: 1; }
.card__link:focus-visible span { transform: translateX(4px); }

/* Filtering animates the survivors in; hidden cards are removed from the flow
   immediately by main.js, so the layout never holds a hole open. The reveal
   animates `translate`, not `transform`, so the hover lift (which owns
   `transform`) still applies while `.is-in` is present — contract §4.5. */
.card.is-in {
  animation: card-in var(--dur-large) var(--ease-enter) both;
}
@keyframes card-in {
  from { opacity: 0; translate: 0 10px; }
  to { opacity: 1; translate: 0 0; }
}

.empty {
  padding: 44px 24px;
  text-align: center;
  background: #fff;
  border: 1px dashed var(--border-ctl);
  border-radius: var(--radius-lg);
}
.empty__title {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  margin-bottom: 6px;
}
.empty__text {
  max-width: 40ch;
  margin: 0 auto 20px;
  font-size: 0.9375rem;
  color: var(--ink-soft);
}

/* ---------- 9. Formats --------------------------------------------------- */
.formats {
  padding-block: clamp(64px, 9vw, 112px);
  background: var(--white);
  content-visibility: auto;
  contain-intrinsic-size: auto 800px;
}
.formats__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}
.format {
  display: flex;
  flex-direction: column;
  padding: 28px 26px 30px;
  background: var(--paper);
  border-radius: var(--radius-lg);
  border-top: 3px solid var(--cobalt);
}
.format__kicker {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 10px;
}
.format h3 { margin-bottom: 10px; }
.format > p:not(.format__kicker) {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink-soft);
  margin-bottom: 20px;
}
.format__list { margin-top: auto; border-top: 1px solid var(--line); padding-top: 14px; }
.format__list li {
  position: relative;
  padding-left: 18px;
  font-size: 0.875rem;
  line-height: 1.5;
  margin-bottom: 8px;
  color: var(--ink);
}
.format__list li:last-child { margin-bottom: 0; }
.format__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 8px;
  height: 2px;
  background: var(--cobalt);
}
.formats__note {
  max-width: 68ch;
  margin-top: 28px;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ink-mute);
}

/* ---------- 10. FAQ ------------------------------------------------------ */
.faq {
  padding-block: clamp(64px, 9vw, 112px);
  background: var(--paper);
  border-top: 1px solid var(--line);
  content-visibility: auto;
  contain-intrinsic-size: auto 800px;
}
.faq__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
}
.faq__grid .section-head { margin-bottom: 0; position: sticky; top: 104px; }
.faq__list { border-top: 1px solid var(--line); }
.qa { border-bottom: 1px solid var(--line); }
.qa__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  min-height: 64px;
  padding: 18px 4px;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.35;
  color: var(--ink);
  list-style: none;
  transition: color var(--dur-small) var(--ease-move),
              transform var(--dur-micro) var(--ease-enter);
}
.qa__btn:active { transform: translateY(1px); transition-duration: 90ms; }
.qa__btn::-webkit-details-marker { display: none; }
.qa__icon {
  position: relative;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--border-ctl);
  transition: border-color var(--dur-small) var(--ease-move),
              background-color var(--dur-small) var(--ease-move);
}
.qa__icon::before,
.qa__icon::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  background: var(--cobalt);
  transition: transform var(--dur-med) var(--ease-enter);
}
.qa__icon::before { width: 9px; height: 1.5px; translate: -50% -50%; }
.qa__icon::after { width: 1.5px; height: 9px; translate: -50% -50%; }
.qa[open] .qa__icon { background: var(--cobalt); border-color: var(--cobalt); }
.qa[open] .qa__icon::before,
.qa[open] .qa__icon::after { background: #fff; }
.qa[open] .qa__icon::after { transform: rotate(90deg); }
.qa__panel {
  padding: 0 40px 24px 4px;
  animation: qa-open var(--dur-med) var(--ease-enter) both;
}
.qa__panel p {
  max-width: 58ch;
  font-size: 0.9375rem;
  line-height: 1.68;
  color: var(--ink-soft);
}
.qa__q { display: block; }
@keyframes qa-open {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (hover: hover) and (pointer: fine) {
  .qa__btn:hover { color: var(--cobalt); }
  .qa__btn:hover .qa__icon { border-color: var(--cobalt); }
}

/* ---------- 11. Placement check ------------------------------------------ */
.check {
  position: relative;
  overflow: hidden;
  padding-block: clamp(64px, 9vw, 112px);
  background: var(--cobalt-deep);
  color: #fff;
  content-visibility: auto;
  contain-intrinsic-size: auto 800px;
}
.check::before {
  content: "";
  position: absolute;
  left: -8%;
  bottom: -30%;
  width: 42vw;
  min-width: 380px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, rgba(51, 92, 255, 0.34), transparent 68%);
  pointer-events: none;
}
.check__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(32px, 5vw, 80px);
  align-items: start;
}
.check__intro h2 {
  margin-bottom: 18px;
  max-width: 16ch;
}
.check__lede {
  max-width: 42ch;
  font-size: 1rem;
  line-height: 1.65;
  color: #C9D3F7;
}
.check__aside {
  max-width: 40ch;
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--line-dark);
  font-size: 0.875rem;
  line-height: 1.6;
  color: #A9B6E8;
}

.form {
  background: #fff;
  color: var(--ink);
  border-radius: var(--radius-lg);
  padding: clamp(22px, 3vw, 34px);
  box-shadow: 0 30px 70px -34px rgba(3, 10, 40, 0.75);
}
.form__progress { margin-bottom: 24px; }
.form__progress-label {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--ink-mute);
  margin-bottom: 10px;
  font-variant-numeric: tabular-nums;
}
html:not(.js) .form__live { display: none; }
html:not(.js) .form__ticks { display: none; }
.form__ticks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.tick__bar {
  display: block;
  height: 3px;
  border-radius: 2px;
  background: var(--line);
  transition: background-color var(--dur-med) var(--ease-move);
}
.tick__name {
  display: block;
  margin-top: 7px;
  font-size: 0.75rem;
  color: var(--ink-mute);
  transition: color var(--dur-med) var(--ease-move);
}
.tick.is-done .tick__bar { background: var(--cobalt); }
.tick.is-done .tick__name { color: var(--cobalt); font-weight: 600; }

.form__step {
  border: 0;
  padding: 0;
  margin: 0 0 26px;
  min-width: 0;
}
/* Without JS all three questions are visible and the form submits normally.
   JS upgrades it to a stepped flow. */
html.js .form__step:not(.is-active) { display: none; }
html.js .form__step.is-active {
  animation: step-in var(--dur-med) var(--ease-enter) both;
}
@keyframes step-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
html:not(.js) .form__progress,
html:not(.js) [data-next],
html:not(.js) [data-prev] { display: none !important; }
html.js [data-submit] { display: none !important; }
html.js .form.is-last [data-submit] { display: inline-flex !important; }
html.js [data-next] { display: inline-flex !important; }
html.js .form.is-last [data-next] { display: none !important; }
html.js [data-prev] { display: inline-flex !important; }
html.js .form.is-first [data-prev] { display: none !important; }
.form__legend {
  padding: 0;
  margin-bottom: 16px;
  font-family: var(--font-display);
  font-size: 1.1875rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.3;
}
.field__label {
  display: block;
  margin-bottom: 7px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
}
.field { display: block; }
.field__input {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid var(--border-ctl);
  border-radius: var(--radius);
  font-size: 1rem;
  color: var(--ink);
  transition: border-color var(--dur-small) var(--ease-move),
              background-color var(--dur-small) var(--ease-move);
}
.field__input::placeholder { color: #5E6A92; opacity: 1; }
.field__input:focus-visible { outline-offset: 2px; }
.field__input[aria-invalid="true"] { border-color: #B3261E; background: #FFF7F6; }
.field__error {
  margin-top: 7px;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.45;
  color: #B3261E;
}

.choice-set {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.choice-set__label {
  grid-column: 1 / -1;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
  margin-bottom: 2px;
}
.choice-set .field__error { grid-column: 1 / -1; margin-top: 0; }
.choice {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 12px 14px;
  border: 1px solid var(--border-ctl);
  border-radius: var(--radius);
  background: #fff;
  font-size: 0.9375rem;
  line-height: 1.4;
  cursor: pointer;
  transition: border-color var(--dur-small) var(--ease-move),
              background-color var(--dur-small) var(--ease-move);
}
.choice input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}
.choice__box {
  position: relative;
  flex: none;
  width: 18px;
  height: 18px;
  border: 1.5px solid #6E7CA8;
  border-radius: 50%;
  background: #fff;
  transition: border-color var(--dur-small) var(--ease-move);
}
.choice__box::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--cobalt);
  scale: 0;
  transition: scale var(--dur-small) var(--ease-pop);
}
.choice__text { min-width: 0; }

/* The dot works with plain sibling selectors, so the selected state is legible
   even where :has() is unavailable; :has() only adds the tinted container. */
.choice input:checked ~ .choice__box { border-color: var(--cobalt); }
.choice input:checked ~ .choice__box::after { scale: 1; }
.choice:has(input:checked) { border-color: var(--cobalt); background: #F2F5FF; }
.choice:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .choice:hover { border-color: var(--cobalt); }
}
.choice-set.is-invalid .choice { border-color: #B3261E; }
.choice-set.is-invalid .choice__box { border-color: #B3261E; }

.form__alert {
  margin-bottom: 18px;
  padding: 12px 14px;
  background: #FFF1EF;
  border-left: 3px solid #B3261E;
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.875rem;
  font-weight: 500;
  color: #8C1D17;
}
.form__nav { display: flex; gap: 10px; flex-wrap: wrap; }
.form__nav .btn { flex: 1 1 auto; }
.form__note {
  margin-top: 14px;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

/* result card */
.result {
  grid-column: 2;
  background: #fff;
  color: var(--ink);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 3vw, 36px);
  box-shadow: 0 30px 70px -34px rgba(3, 10, 40, 0.75);
  border-top: 4px solid var(--sun);
  animation: result-in var(--dur-large) var(--ease-enter) both;
}
@keyframes result-in {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
.result__eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 10px;
}
.result__title {
  font-size: clamp(1.4rem, 2.4vw, 1.75rem);
  line-height: 1.2;
  margin-bottom: 12px;
}
.result__why {
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ink-soft);
  margin-bottom: 22px;
}
.result__facts {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: 20px;
}
.result__facts > div {
  display: grid;
  grid-template-columns: 100px minmax(0, 1fr);
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px dashed var(--line);
}
.result__facts > div:last-child { border-bottom: 0; }
.result__facts dt { font-size: 0.8125rem; color: var(--ink-mute); }
.result__facts dd { font-size: 0.875rem; font-weight: 500; }
.result__next {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink-soft);
  margin-bottom: 22px;
}
.result__actions { display: flex; flex-wrap: wrap; gap: 10px; }
.result__actions .btn--ghost { --btn-fg: var(--ink); border-color: var(--border-ctl); }
@media (hover: hover) and (pointer: fine) {
  .result__actions .btn--ghost:hover { border-color: var(--cobalt); color: var(--cobalt); background: transparent; }
}
.result__note {
  margin-top: 16px;
  font-size: 0.8125rem;
  color: var(--ink-mute);
}

/* ---------- 12. Footer --------------------------------------------------- */
.site-footer {
  background: #06124A;
  color: #fff;
  padding-block: clamp(44px, 6vw, 68px) clamp(28px, 4vw, 40px);
}
.site-footer__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 32px clamp(24px, 5vw, 72px);
  align-items: start;
}
.brand--footer { color: #fff; margin-bottom: 12px; }
.brand--footer .brand__name b { color: var(--sun); }
.site-footer__brand { min-width: 0; }
.site-footer__line {
  max-width: 30ch;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: #A9B6E8;
}
.site-footer__nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 28px;
}
.site-footer__nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9375rem;
  color: #C9D3F7;
  text-decoration: none;
  transition: color var(--dur-small) var(--ease-move);
}
@media (hover: hover) and (pointer: fine) {
  .site-footer__nav a:hover { color: var(--sun); }
}
.site-footer__credit {
  grid-column: 1 / -1;
  margin-top: 12px;
  padding-top: 24px;
  border-top: 1px solid var(--line-dark);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: #8E9CD4;
  max-width: 78ch;
}
.site-footer__credit a {
  color: #C9D3F7;
  text-underline-offset: 3px;
}
@media (hover: hover) and (pointer: fine) {
  .site-footer__credit a:hover { color: var(--sun); }
}

/* ---------- 13. Reveal system ------------------------------------------- */
html.js-motion [data-reveal] {
  opacity: 0;
  translate: 0 18px;
  transition: opacity var(--dur-reveal) var(--ease-enter),
              translate var(--dur-reveal) var(--ease-enter);
}
html.js-motion [data-reveal].is-revealed {
  opacity: 1;
  translate: 0 0;
}
/* Stagger is set per batch by main.js (55 ms apart, capped at six). No CSS
   transition-delay rules here: an inline style would win anyway. */

/* ---------- 14. Responsive ---------------------------------------------- */
/* Below 1080px the ladder stops being a scroll instrument and becomes a
   static index card above the programmes: same six rungs, read top to bottom. */
@media (max-width: 1080px) {
  .hero__inner { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .hero__panel { max-width: 460px; }
  .panel__list li { padding: 10px 0; }
  .journey__grid { grid-template-columns: minmax(0, 1fr); }
  .ladder-col {
    position: static;
    margin-bottom: 24px;
    padding: 20px 22px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
  }
  .ladder { padding-left: 34px; }
  .ladder__rungs { height: auto; }
  .rung {
    position: relative;
    top: auto;
    translate: none;
    padding: 9px 0;
    border-bottom: 1px solid var(--paper-2);
  }
  .rung:last-child { border-bottom: 0; }
  .rung::before { display: none; }
  .rung__dot { left: -34px; }
  .ladder__track { top: 20px; bottom: 20px; }
  .ladder__caption { display: none; }
  .ladder__fill,
  .rung::before,
  .rung__dot::after,
  .rung__code::before { animation: none !important; }
  .ladder__fill { scale: 1 1 !important; }
  .rung__dot::after,
  .rung__code::before { opacity: 1 !important; }
  .faq__grid { grid-template-columns: minmax(0, 1fr); }
  .faq__grid .section-head { position: static; }
  .check__grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .check__intro h2 { max-width: 22ch; }
  .result { grid-column: auto; }
}

@media (max-width: 860px) {
  .site-header__inner { min-height: 68px; }
  html.js-nav .nav-toggle { display: inline-flex; }
  html.js-nav .site-nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 12px var(--gutter) 20px;
    background: #fff;
    border-bottom: 1px solid var(--line);
    box-shadow: 0 24px 40px -28px rgba(11, 21, 51, 0.5);
    opacity: 0;
    translate: 0 -8px;
    visibility: hidden;
    /* Closing is the exit, so it runs on --ease-exit at 0.65x the entrance. */
    transition: opacity var(--dur-small) var(--ease-exit),
                translate var(--dur-small) var(--ease-exit),
                visibility 0s linear var(--dur-small);
  }
  html.js-nav .site-nav.is-open {
    opacity: 1;
    translate: 0 0;
    visibility: visible;
    transition: opacity var(--dur-small) var(--ease-enter),
                translate var(--dur-small) var(--ease-enter),
                visibility 0s;
  }
  /* Without the script the nav is a plain wrapping list under the brand. */
  html:not(.js-nav) .site-header__inner {
    flex-wrap: wrap;
    padding-block: 12px;
    gap: 8px;
  }
  html:not(.js-nav) .site-nav {
    width: 100%;
    flex-wrap: wrap;
    gap: 0 20px;
  }
  html:not(.js-nav) .site-nav__list { flex-wrap: wrap; gap: 0 4px; }
  html:not(.js-nav) .site-nav__link { min-height: 44px; padding: 0 8px; font-size: 0.9375rem; }
  html:not(.js-nav) .site-nav__cta { margin-left: auto; margin-top: 0; }

  html.js-nav .site-nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  html.js-nav .site-nav__link { min-height: 48px; padding: 0 4px; font-size: 1rem; }
  html.js-nav .site-nav__link::after { left: 4px; right: auto; width: 22px; bottom: 10px; }
  html.js-nav .site-nav__cta { margin-top: 12px; min-height: 48px; }

  .method__grid { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .mstep { padding: 24px 0 26px; border-bottom: 1px solid var(--line); }
  .mstep + .mstep { padding-left: 0; }
  .mstep:last-child { border-bottom: 0; }
  .mstep__n { margin-bottom: 14px; }
  .formats__grid { grid-template-columns: minmax(0, 1fr); }
  .section-head--split { grid-template-columns: minmax(0, 1fr); align-items: start; gap: 16px; }
  .section-head--split h2 { max-width: 24ch; }
  .site-footer__inner { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .site-footer__nav ul { gap: 0 22px; }
}

@media (max-width: 620px) {
  .cards { grid-template-columns: minmax(0, 1fr); }
  .ladder-col { padding: 16px 16px 16px 12px; }
  .ladder { padding-left: 30px; }
  .rung__dot { left: -30px; }
  .rung__name { font-size: 0.9375rem; }
  .filters {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .chips { padding-bottom: 4px; }
  .filter-count { padding-left: 2px; }
  .choice-set { grid-template-columns: minmax(0, 1fr); }
  .card__facts > div { grid-template-columns: 84px minmax(0, 1fr); }
  .hero__actions .btn { flex: 1 1 100%; }
  .hero__facts { gap: 8px 18px; }
  .hero__facts li { font-size: 0.8125rem; }
  .qa__panel { padding-right: 8px; }
  .qa__btn { font-size: 1rem; gap: 14px; }
  .form { padding: 20px 18px 24px; }
  .result__facts > div { grid-template-columns: 88px minmax(0, 1fr); }
  .result__actions .btn { flex: 1 1 100%; }
  .check__aside { font-size: 0.8125rem; }
}

@media (max-width: 400px) {
  :root { --gutter: 18px; }
  .panel { padding: 22px 18px 18px; }
  .panel__list li { grid-template-columns: 26px 1fr auto; gap: 6px; }
  .card { padding: 20px 18px 18px; }
  .form__ticks { gap: 6px; }
  .site-footer__nav ul { gap: 0 16px; }
}

/* ---------- 15. Reduced motion ------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html.js-motion [data-reveal] {
    opacity: 1 !important;
    translate: none !important;
    scale: none !important;
  }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto; }

  /* Scroll-linked pieces are not time-based, so they need explicit kills.
     The header keeps its static shadow instead of losing it: the effect must
     still separate the bar from the page, it just must not animate. */
  .line__in { transform: none !important; animation: none !important; }
  .site-header::after { animation: none !important; opacity: 1 !important; }
  .ladder__fill,
  .rung::before,
  .rung__dot::after,
  .rung__code::before {
    animation: none !important;
    transform: none !important;
    scale: none !important;
    opacity: 1 !important;
  }
  .ladder__fill { scale: 1 1 !important; }

  .card.is-in,
  .result,
  .qa__panel { animation: none !important; }
  .site-nav { transition-duration: 1ms !important; }
}

@media (prefers-contrast: more) {
  :root { --line: #9AA6CC; --ink-soft: #2A3559; --ink-mute: #3A4468; }
  .site-header { background: #fff; backdrop-filter: none; }
  .card, .format, .form, .result { border-color: #6E7CA8; }
  .card { box-shadow: none; }
  .chip { border-color: #6E7CA8; }
  .field__input, .choice { border-color: #6E7CA8; }
}

@media (prefers-reduced-transparency: reduce) {
  .site-header { background: #fff; backdrop-filter: none; }
}

/* Classroom editorial: real learning imagery, with the level guide intact. */
.hero__photo { margin: 0 0 22px; }
.hero__photo img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-lg); }
.hero__photo figcaption { margin-top: 9px; color: #C9D3F7; font-size: 12px; line-height: 1.5; }
.hero__panel { min-width: 0; }
.method__photo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: clamp(24px, 5vw, 64px); margin: 0 0 48px; padding-bottom: 32px; border-bottom: 1px solid var(--line); }
.method__photo img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-lg); }
.method__photo h3 { margin-bottom: 14px; }
.method__photo p { font-size: 16px; line-height: 1.65; color: var(--ink); }
.method__photo small { display: block; margin-top: 16px; font-size: 12px; line-height: 1.5; color: var(--ink); }
/* Interactive Result Radar Visualization */
.result__badge-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.result__ai-tag {
  font-size: 0.75rem;
  font-family: var(--font-display);
  font-weight: 700;
  color: #00F0FF;
  background: rgba(0, 240, 255, 0.1);
  border: 1px solid rgba(0, 240, 255, 0.3);
  padding: 3px 8px;
  border-radius: 999px;
  letter-spacing: 0.04em;
}
.radar-box {
  margin: 20px 0;
  padding: 16px;
  background: rgba(15, 42, 158, 0.05);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.radar-box__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}
.radar-box__title {
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--cobalt);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.radar-box__target {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-mute);
}
.radar-box__metrics {
  display: grid;
  gap: 10px;
}
.metric-item__info {
  display: flex;
  justify-content: space-between;
  font-size: 0.8125rem;
  margin-bottom: 4px;
  color: var(--ink);
}
.metric-item__info strong {
  color: var(--cobalt);
  font-family: var(--font-display);
}
.metric-item__bar {
  height: 6px;
  background: #E2E8F0;
  border-radius: 999px;
  overflow: hidden;
}
.metric-item__fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--cobalt), #FFC83D);
  border-radius: 999px;
  transition: width 1s cubic-bezier(0.16, 1, 0.3, 1);
}
.result.is-active .metric-item__fill {
  width: var(--val, 50%);
}

/* Spotlight Hover Effect on Cards */
.card {
  --mouse-x: 50%;
  --mouse-y: 50%;
}
.card::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background: radial-gradient(400px circle at var(--mouse-x) var(--mouse-y), rgba(15, 42, 158, 0.15), transparent 40%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  z-index: 1;
}
.card:hover::before {
  opacity: 1;
}

/* Interactive Rung Hover Details */
.rung {
  cursor: pointer;
  transition: all var(--dur-small) var(--ease-enter);
}
.rung:hover {
  background: rgba(15, 42, 158, 0.08);
  transform: translateX(4px);
}
.rung.is-selected {
  background: rgba(15, 42, 158, 0.14);
}
.rung.is-selected .rung__dot {
  background: var(--cobalt);
  box-shadow: 0 0 10px rgba(15, 42, 158, 0.8);
}

@media (min-width: 1000px) { .hero__inner { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: clamp(32px, 4vw, 64px); } }
@media (max-width: 600px) { .method__photo { grid-template-columns: minmax(0, 1fr); } }
