/* ============================================================================
   Karky Academy — Components
   Requires tokens.css. Everything here reads tokens; nothing hard-codes colour.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

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

:lang(ta), .ta { font-family: var(--font-tamil); }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  font-weight: 700;
  color: var(--text);
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); line-height: var(--lh-snug); }
h4 { font-size: var(--fs-h4); line-height: var(--lh-snug); }

p { text-wrap: pretty; }
a { color: var(--brand); text-decoration: none; }

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

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

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: var(--z-modal);
  background: var(--navy-900); color: var(--paper); padding: var(--sp-3) var(--sp-5);
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; }

/* ---------- Layout ------------------------------------------------------- */
.wrap        { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-tight  { max-width: var(--wrap-tight); margin-inline: auto; padding-inline: var(--gutter); }

.section {
  position: relative;
  padding-block: var(--section-y);
  background: var(--bg);
  color: var(--text);
}
.section--alt  { background: var(--bg-alt); }
.section--flush{ padding-block: 0; }

.stack > * + *   { margin-top: var(--sp-4); }
.stack-lg > * + *{ margin-top: var(--sp-6); }

.grid { display: grid; gap: var(--sp-5); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

/* ---------- Type helpers ------------------------------------------------- */
.kicker {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--fs-kicker);
  font-weight: 700;
  letter-spacing: var(--ls-kicker);
  text-transform: uppercase;
  color: var(--kicker);
  margin-bottom: var(--sp-3);
}
.lead     { font-size: var(--fs-lead); color: var(--text-soft); max-width: 62ch; }
.muted    { color: var(--text-muted); }
.small    { font-size: var(--fs-sm); }
.xs       { font-size: var(--fs-xs); }
.serif    { font-family: var(--font-serif); font-weight: 700; }
.hero-title { font-size: var(--fs-hero); font-weight: 800; }
.mark     { color: var(--accent); }

.quote {
  font-family: var(--font-serif);
  font-size: clamp(1.25rem, 2.6vw, 1.75rem);
  line-height: 1.4;
  font-weight: 600;
  border-left: 3px solid var(--accent);
  padding-left: var(--sp-5);
  border-radius: 0;
}
.quote-ta { font-family: var(--font-tamil); font-weight: 600; line-height: 1.55; }

/* ---------- Buttons ------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 0.9rem 1.75rem;
  font-family: var(--font-body);
  font-size: var(--fs-sm); font-weight: 700; line-height: 1;
  border: 2px solid transparent; border-radius: var(--radius-pill);
  cursor: pointer; text-decoration: none;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease),
              color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
  will-change: transform;
}
.btn:hover  { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn-primary { background: var(--cta); color: var(--on-cta); box-shadow: var(--shadow-cta); }
.btn-primary:hover { background: var(--cta-hover); color: var(--on-cta); }

.btn-brand { background: var(--brand); color: var(--on-brand); box-shadow: var(--shadow-brand); }
.btn-brand:hover { background: var(--cta); color: var(--on-cta); box-shadow: var(--shadow-cta); }

.btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn-ghost:hover { border-color: var(--text); background: var(--brand-soft); }

.btn-sm { padding: 0.6rem 1.25rem; font-size: var(--fs-xs); }

/* A button that is deliberately not yet a button. Used where a destination is
   announced but not built — Thambaa Indie enrolment, pending payment gateway
   and login management. Reads as unavailable rather than broken. */
.btn-soon {
  background: var(--accent-soft); color: var(--amber-600);
  border-color: transparent; box-shadow: none; cursor: default;
}
.btn-soon:hover, .btn-soon:active { transform: none; background: var(--accent-soft); }

.link-arrow {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-weight: 700; font-size: var(--fs-sm); color: var(--brand);
}
.link-arrow::after { content: "→"; transition: transform var(--dur) var(--ease); }
.link-arrow:hover::after { transform: translateX(5px); }

/* ---------- Cards -------------------------------------------------------- */
.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.card--lift:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
  border-color: transparent;
}
.card--flat { background: var(--bg-alt); border-color: transparent; }
.card__icon { height: 34px; width: auto; margin-bottom: var(--sp-4); }
.card__title { margin-bottom: var(--sp-2); }
.card__title .ta { display: block; font-size: 0.72em; font-weight: 600; color: var(--text-muted); }
.card__body { color: var(--text-soft); font-size: var(--fs-sm); }

/* Product card — the four-product architecture */
.pcard { display: flex; flex-direction: column; gap: var(--sp-3); }
.pcard__meta {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted);
}

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); font-weight: 700; line-height: 1;
  padding: 6px 12px; border-radius: var(--radius-pill);
  background: var(--brand-soft); color: var(--brand);
}
.badge--soon  { background: var(--accent-soft); color: var(--amber-600); }
.badge--live  { background: var(--teal-100);    color: var(--teal-600); }

/* ---------- Stats -------------------------------------------------------- */
/* A fixed 4-up row, unlike .grid-4 which is auto-fit with a 200px minimum and
   will silently drop to 3 columns in a narrow container. Halves to 2x2 on phones. */
.stats {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  max-width: 840px;
  margin-inline: auto;
}
@media (max-width: 720px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5) var(--sp-3); }
}

.stat { text-align: center; }
.stat__n {
  display: block;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.75rem, 3.6vw, 2.75rem);
  line-height: 1; letter-spacing: var(--ls-tight);
  color: var(--brand);
}
.stat__l {
  display: block; margin-top: var(--sp-2);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted);
}
.r-bright-dark .stat__n { color: var(--accent); }

/* ---------- Header + mega-menu ------------------------------------------ */
.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.site-header.is-scrolled { border-bottom-color: var(--border); }

.site-header__in {
  max-width: var(--wrap); margin-inline: auto;
  padding: var(--sp-3) var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-5);
}

.brand { display: flex; align-items: center; gap: var(--sp-3); }
/* The lockup is 5:1, so 46px tall reads as ~230px wide — enough for the wordmark
   to be legible without the header growing into the content. */
.brand img { height: 46px; width: auto; transition: transform var(--dur) var(--ease); }
.brand:hover img { transform: rotate(-3deg) scale(1.03); }
@media (max-width: 900px) { .brand img { height: 38px; } }
@media (max-width: 420px) { .brand img { height: 32px; } }

.nav { display: flex; align-items: center; gap: var(--sp-5); }
.nav__link {
  position: relative;
  font-size: var(--fs-sm); font-weight: 600; color: var(--text);
  padding-block: var(--sp-2); background: none; border: 0; cursor: pointer;
  font-family: var(--font-body);
  display: inline-flex; align-items: center; gap: 5px;
}
.nav__link::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 0; height: 2px; background: var(--accent);
  transition: width var(--dur) var(--ease);
}
.nav__link:hover::after, .nav__link[aria-expanded="true"]::after { width: 100%; }
.nav__caret { font-size: 10px; transition: transform var(--dur) var(--ease); }
.nav__link[aria-expanded="true"] .nav__caret { transform: rotate(180deg); }

.mega {
  position: absolute; left: 0; right: 0; top: 100%;
  z-index: var(--z-menu);
  background: var(--surface);
  border-block: 1px solid var(--border);
  box-shadow: var(--shadow);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility var(--dur);
}
.mega.is-open { opacity: 1; visibility: visible; transform: none; }
.mega__in {
  max-width: var(--wrap); margin-inline: auto;
  padding: var(--sp-6) var(--gutter);
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
}
.mega__item {
  display: block; padding: var(--sp-4);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.mega__item:hover { border-color: var(--brand); background: var(--brand-soft); transform: translateY(-3px); }
.mega__item h4 { margin-bottom: 4px; }
.mega__item p  { font-size: var(--fs-xs); color: var(--text-muted); }

.nav-toggle { display: none; background: none; border: 0; cursor: pointer; color: var(--text); font-size: 22px; }

@media (max-width: 900px) {
  /* The nav opens in flow rather than floating over the page, so an opened
     mega panel — which lives outside .nav, as a sibling of .site-header__in —
     stacks underneath the links instead of behind them. */
  .site-header__in { flex-wrap: wrap; }
  .nav { display: none; }
  .nav.is-open {
    display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-2);
    order: 3; width: 100%;
    margin-top: var(--sp-3); padding-top: var(--sp-4);
    border-top: 1px solid var(--border);
  }
  .nav-toggle { display: block; }

  /* display:none is load-bearing. The base .mega rule hides a closed panel with
     opacity:0 + visibility:hidden and relies on position:absolute to keep it out
     of the flow. Making it static here without also removing it from the flow put
     all three closed panels back into the header — 693px of invisible blank space
     on a laptop, far more on a phone, between the header and the page content.
     That was the whole of "the mobile version is not working". */
  .mega {
    position: static; box-shadow: none; border: 0;
    display: none; transform: none;
  }
  .mega.is-open { display: block; }
  .mega__in { padding: var(--sp-3) 0; }

  /* With the menu in flow the header can now outgrow a short screen. */
  .site-header { max-height: 100dvh; overflow-y: auto; }
}

/* ---------- Footer ------------------------------------------------------- */
.site-footer {
  background: var(--footer-bg); color: var(--footer-text);
  padding-block: var(--sp-8) var(--sp-6);
  font-size: var(--fs-sm);
}
.site-footer h4 { color: var(--footer-head); font-size: var(--fs-xs); letter-spacing: var(--ls-kicker);
                  text-transform: uppercase; margin-bottom: var(--sp-3); font-family: var(--font-body); }
.site-footer a { color: var(--footer-text); }
.site-footer a:hover { color: var(--amber-500); }
.site-footer__grid {
  display: grid; gap: var(--sp-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  padding-bottom: var(--sp-6);
  border-bottom: 1px solid var(--footer-line);
}
.site-footer__list { list-style: none; display: grid; gap: var(--sp-2); }
.site-footer__legal {
  padding-top: var(--sp-5);
  display: flex; flex-wrap: wrap; gap: var(--sp-4); justify-content: space-between;
  font-size: var(--fs-xs); color: var(--footer-faint);
}

/* ---------- Reveal on scroll -------------------------------------------- */
.reveal {
  opacity: 0; transform: translateY(28px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
.reveal.is-in { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: .08s; }
.reveal[data-delay="2"] { transition-delay: .16s; }
.reveal[data-delay="3"] { transition-delay: .24s; }
.reveal[data-delay="4"] { transition-delay: .32s; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Scroll progress --------------------------------------------- */
.progress {
  position: fixed; inset-block-start: 0; inset-inline-start: 0;
  height: 3px; width: 0; z-index: var(--z-modal);
  background: linear-gradient(90deg, var(--navy-900), var(--amber-500));
  transition: width .1s linear;
}

/* ============================================================================
   FLOATING LAYER
   Real product screenshots drifting in parallax depth behind the copy.
   Populated by float.js from assets/float/manifest.json.
   ========================================================================= */
.floatbed {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.floatbed > .wrap,
.floatbed > .wrap-tight { position: relative; z-index: var(--z-body); }

.floatlayer {
  position: absolute; inset: 0;
  z-index: var(--z-float);
  pointer-events: none;
}

.floater {
  position: absolute;
  width: var(--tile, 108px);
  border-radius: 14px;
  overflow: hidden;
  pointer-events: auto;
  border: 1px solid rgba(255,255,255,.18);
  box-shadow: 0 14px 40px rgba(0,0,0,.28);
  opacity: 0;
  /* --py is the parallax offset, written by float.js on scroll.
     Keeping the transform here means hover still composes on top of it. */
  transform: translate3d(0, var(--py, 0px), 0) rotate(var(--rot, 0deg)) scale(.9);
  /* Short transform transition: this is for the hover lift only. Parallax is
     eased frame by frame in float.js, because an unregistered custom property
     like --py cannot be transitioned by CSS. A long duration here would fight
     that easing and make hover feel sluggish. */
  transition: opacity .9s var(--ease-out), transform .25s var(--ease);
  will-change: transform;
  background: var(--navy-800);
}
.floater.is-in {
  opacity: var(--op, .78);
  transform: translate3d(0, var(--py, 0px), 0) rotate(var(--rot, 0deg)) scale(1);
}
.floater img { width: 100%; aspect-ratio: var(--ar, 1); object-fit: cover; }

/* Ambient drift.
   Lives on an inner wrapper so it composes with the parallax transform on
   .floater instead of overwriting it.

   Purely vertical, and slow: 18 to 34 seconds each way over 16 to 32px. Half
   the tiles rise, half fall. An earlier version also nudged sideways and
   rotated, which close up read as a wobble rather than a float; straight up and
   down is what looks suspended. Each tile has its own duration and a negative
   delay, so the layer never pulses in unison. */
.floater__in {
  display: block;
  animation: ka-drift var(--drift-dur, 24s) ease-in-out var(--drift-delay, 0s) infinite alternate;
  will-change: transform;
}
@keyframes ka-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, var(--drift-y, 20px), 0); }
}

/* Settle while hovered, so a tile someone is reading holds still. */
.floater:hover .floater__in,
.floater:focus-within .floater__in { animation-play-state: paused; }

.floater:hover,
.floater:focus-within {
  opacity: 1;
  transform: translate3d(0, calc(var(--py, 0px) - 8px), 0) rotate(0deg) scale(1.1);
  box-shadow: 0 22px 60px rgba(0,0,0,.4);
  z-index: 3;
}

.floater__cap {
  position: absolute; inset-inline: 0; inset-block-end: 0;
  padding: 16px 8px 6px;
  background: linear-gradient(to top, rgba(0,10,45,.94), rgba(0,10,45,0));
  opacity: 0; transition: opacity var(--dur) var(--ease);
}
.floater:hover .floater__cap, .floater:focus-within .floater__cap { opacity: 1; }
.floater__cap b { display: block; font-family: var(--font-tamil); font-size: 11px; color: var(--amber-500); line-height: 1.3; }
.floater__cap span { display: block; font-size: 9px; color: var(--navy-100); line-height: 1.3; }

.floatbed--light .floater { border-color: var(--border); box-shadow: var(--shadow); background: var(--paper); }
.floatbed--light .floater.is-in { opacity: var(--op, .92); }

/* Bare tiles.
   Book pages and computing cards are already designed objects: a Payil page has
   a transparent margin around a printed page, and a computing card has its own
   background and rounded corners. Wrapping either in the .floater card chrome
   puts a visible dark frame behind it. So those tiles drop the fill, hairline,
   radius and box-shadow, and get a soft drop-shadow that follows the artwork's
   own silhouette instead of a rectangle. */
.floater--bare,
.floatbed--light .floater--bare {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
  filter: drop-shadow(0 14px 26px rgba(0,0,0,.34));
}
.floatbed--light .floater--bare { filter: drop-shadow(0 12px 22px rgba(19,26,46,.22)); }
.floater--bare:hover,
.floater--bare:focus-within { box-shadow: none; filter: drop-shadow(0 22px 40px rgba(0,0,0,.45)); }
.floatbed--light .floater--bare:hover,
.floatbed--light .floater--bare:focus-within { filter: drop-shadow(0 20px 34px rgba(19,26,46,.3)); }

/* The caption still needs a readable backing, but only across its own width. */
.floater--bare .floater__cap { border-radius: 0 0 8px 8px; }

/* No floating layer on phones.
   The tiles are placed in the gutters beside the text column. On a phone there
   is no gutter — the text column IS the viewport — so there is no placement
   that does not sit on the copy. float.js already declines to build the layer
   below this width; this rule is the belt to that braces, and also covers the
   case where a bed was built wide and the window was then narrowed before the
   rebuild lands.

   Keep MOBILE_MAX in float.js in step with this number. */
@media (max-width: 900px) {
  .floatlayer { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .floater { transition: opacity .2s linear; }
  .floater.is-in { transform: rotate(var(--rot,0deg)); }
  .floater__in { animation: none; }
}

/* Turn the drift off for a whole bed with data-float-drift="0". */
.floatbed[data-float-drift="0"] .floater__in { animation: none; }

/* ---------- Hero --------------------------------------------------------- */
.hero {
  position: relative;
  padding-block: clamp(4rem, 11vw, 8rem);
  text-align: center;
}
.hero .lead { margin-inline: auto; }
.hero__actions {
  display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center;
  margin-top: var(--sp-6);
}

/* ============================================================================
   PRESS — "As featured in"
   Mastheads in greyscale, colour on hover, always linking out to the original.
   Never rehost article text. Mark paywalled pieces honestly.
   ========================================================================= */
.press {
  display: flex; flex-wrap: wrap;
  gap: var(--sp-5) var(--sp-7);
  align-items: center; justify-content: center;
}
.press__item {
  display: inline-flex; align-items: center;
  filter: grayscale(1); opacity: .55;
  transition: filter var(--dur) var(--ease), opacity var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.press__item:hover, .press__item:focus-visible {
  filter: none; opacity: 1; transform: translateY(-2px);
}
.press__item img { height: 30px; width: auto; }
.press__item span { font-family: var(--font-serif); font-size: 1.15rem; font-weight: 700; color: var(--text); }

/* Full press list, for the About page */
.presslist { list-style: none; display: grid; gap: 0; }
.presslist li { border-bottom: 1px solid var(--border); }
.presslist a {
  display: grid; gap: var(--sp-1) var(--sp-4);
  grid-template-columns: 1fr auto;
  padding: var(--sp-4) 0;
  color: var(--text);
  transition: background var(--dur) var(--ease), padding-inline var(--dur) var(--ease);
}
.presslist a:hover { background: var(--bg-alt); padding-inline: var(--sp-3); }
.presslist__head { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-h4); }
.presslist__meta { font-size: var(--fs-xs); color: var(--text-muted); grid-column: 1; }
.presslist__pub  { font-size: var(--fs-xs); font-weight: 700; color: var(--kicker);
                   letter-spacing: var(--ls-kicker); text-transform: uppercase;
                   grid-column: 2; grid-row: 1 / span 2; align-self: center; text-align: right; }

/* ============================================================================
   VOICES — school testimonials
   Cut-out portrait of the person, their words beside it. The portraits are
   full-length transparent cut-outs, so they stand on the card rather than
   sitting in a crop; a circular avatar would either behead them or shrink them
   to nothing.
   ========================================================================= */
.vquotes {
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}

.vquote {
  position: relative;
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--sp-5);
  align-items: end;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-5) var(--sp-5) 0;
  overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.vquote:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); border-color: transparent; }

.vquote__pic {
  align-self: end;
  margin-bottom: -1px;           /* stand the figure on the card edge */
  filter: drop-shadow(0 10px 18px rgba(19,26,46,.18));
}
.vquote__pic img { width: 100%; height: auto; display: block; }

.vquote__body { padding-bottom: var(--sp-5); }
.vquote__mark {
  font-family: var(--font-serif); font-size: 3rem; line-height: .6;
  color: var(--accent); display: block; margin-bottom: var(--sp-2);
}
.vquote__text {
  font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600;
  line-height: 1.5; color: var(--text);
}
.vquote__who  { margin-top: var(--sp-4); font-size: var(--fs-sm); font-weight: 700; color: var(--text); }
.vquote__role { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.4; }

@media (max-width: 520px) {
  .vquote { grid-template-columns: 1fr; padding-inline: var(--sp-4); }
  .vquote__pic { max-width: 130px; }
}

/* On a dark register the cut-outs need a lighter card to sit against. */
.r-bright-dark .vquote { background: var(--surface); }

/* ============================================================================
   VOICES — video testimonials
   Poster frame + play affordance. The <video> or embed is swapped in on click,
   so nothing heavy loads until someone actually asks for it.
   ========================================================================= */
.voices { display: grid; gap: var(--sp-5);
          grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }

.voice {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--navy-900);
  border: 1px solid var(--border);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.voice:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); }

.voice__media { position: relative; aspect-ratio: 16 / 10; background: var(--navy-800); }
.voice__media img,
.voice__media video,
.voice__media iframe { width: 100%; height: 100%; object-fit: cover; border: 0; display: block; }

.voice__play {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: linear-gradient(to top, rgba(0,10,45,.55), rgba(0,10,45,.12));
  border: 0; cursor: pointer; padding: 0;
}
.voice__play::before {
  content: "";
  width: 58px; height: 58px; border-radius: 50%;
  background: var(--paper);
  box-shadow: var(--shadow-lg);
  transition: transform var(--dur) var(--ease);
}
.voice__play::after {
  content: "";
  position: absolute;
  border-style: solid;
  border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent var(--navy-900);
  margin-left: 4px;
  transition: transform var(--dur) var(--ease);
}
.voice:hover .voice__play::before,
.voice:hover .voice__play::after { transform: scale(1.1); }

.voice__cap { padding: var(--sp-4); background: var(--surface); }
.voice__quote {
  font-family: var(--font-serif); font-weight: 600;
  font-size: 1.0625rem; line-height: 1.45; color: var(--text);
  margin-bottom: var(--sp-3);
}
.voice__who  { font-size: var(--fs-sm); font-weight: 700; color: var(--text); }
.voice__role { font-size: var(--fs-xs); color: var(--text-muted); }
.voice__len  { position: absolute; right: 10px; bottom: 10px;
               font-size: 11px; font-weight: 700; color: var(--paper);
               background: rgba(0,10,45,.7); padding: 3px 8px; border-radius: var(--radius-pill); }

/* ============================================================================
   COMING SOON
   Used by Payil Computing Books, Thambaa Computing Labs and Payil Courses.
   ========================================================================= */
.soon {
  display: grid; gap: var(--sp-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  align-items: center;
}
.soon__panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
}
/* Flex, not grid. With grid, any inline child (a <strong>, an <em>) becomes its
   own grid item and the rest of the line wraps into the 22px marker column. */
.soon__list { list-style: none; display: grid; gap: var(--sp-3); margin-top: var(--sp-5); }
.soon__list li { display: flex; gap: var(--sp-3);
                 font-size: var(--fs-sm); color: var(--text-soft); line-height: var(--lh-body); }
.soon__list li::before { content: "→"; flex: 0 0 auto; width: 14px;
                         color: var(--accent); font-weight: 700; }

/* Label + description pairs. A <dl> laid out as a two-column grid so every
   description starts on the same left edge, however long the label runs. A <ul>
   cannot do this — each <li> is its own formatting context, so the columns
   never line up between rows. No em dashes; the column gap does that work. */
.soon__defs { display: grid; grid-template-columns: auto 1fr;
              column-gap: var(--sp-4); row-gap: var(--sp-3);
              margin-top: var(--sp-5);
              font-size: var(--fs-sm); line-height: var(--lh-body); }
.soon__defs dt { position: relative; padding-left: 22px;
                 font-weight: 700; color: var(--text); }
.soon__defs dt::before { content: "→"; position: absolute; left: 0;
                         color: var(--accent); font-weight: 700; }
.soon__defs dd { margin: 0; color: var(--text-soft); }
@media (max-width: 560px) {
  .soon__defs { grid-template-columns: 1fr; row-gap: 0; }
  .soon__defs dd { padding-left: 22px; margin-bottom: var(--sp-3); }
  .soon__defs dd:last-child { margin-bottom: 0; }
}

.form-row { display: grid; gap: var(--sp-3); }
.form-row label { font-size: var(--fs-xs); font-weight: 700; color: var(--text-soft); }
.form-row input, .form-row select, .form-row textarea {
  width: 100%; padding: 0.85rem 1rem;
  font-family: var(--font-body); font-size: var(--fs-sm); color: var(--text);
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.form-row input:focus, .form-row select:focus, .form-row textarea:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.form-note { font-size: var(--fs-xs); color: var(--text-muted); }

/* ============================================================================
   LEVEL EXPLORER
   Pills across the top, detail panel below. Populated by explorer() in float.js
   from assets/data/levels.json.
   ========================================================================= */
/* Faint watercolour path behind the level explorer. The brief for this image was
   "err on the side of too faint" — so it is held at .16 opacity in a ::before,
   which keeps it well clear of the text above it and costs nothing in contrast.
   Raise the opacity only if you have checked the level names against it. */
.levels-bed { position: relative; margin-top: var(--sp-8); isolation: isolate; }
.levels-bed::before {
  content: ""; position: absolute; z-index: -1;
  inset: calc(var(--sp-6) * -1) calc(var(--sp-5) * -1);
  background: url("../illus/payil-tamil/level-journey.webp") center / cover no-repeat;
  opacity: .16;
  border-radius: var(--radius-lg);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 82%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 82%, transparent);
}
.levels-bed > h3 { margin-top: 0; }

.levels__rail {
  display: flex; gap: var(--sp-2);
  overflow-x: auto; padding-bottom: var(--sp-3);
  scrollbar-width: thin;
}
.levels__pill {
  flex: 0 0 auto;
  padding: 0.6rem 1.1rem;
  font-family: var(--font-body);
  font-size: var(--fs-xs); font-weight: 700; line-height: 1.2;
  color: var(--text-soft);
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.levels__pill:hover { border-color: var(--brand); transform: translateY(-2px); }
.levels__pill[aria-selected="true"] {
  background: var(--brand); color: var(--on-brand); border-color: var(--brand);
}
.levels__pill[data-status="production"] { border-style: dashed; }
.levels__pill[data-status="planned"]    { border-style: dashed; opacity: .6; }

.levels__panel {
  margin-top: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  min-height: 260px;
}
.levels__head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--sp-3); margin-bottom: var(--sp-5);
}
.levels__name  { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 800;
                 letter-spacing: var(--ls-tight); color: var(--text); }
.levels__sub   { font-family: var(--font-tamil); font-size: var(--fs-lead);
                 font-weight: 600; color: var(--kicker); }
/* The English gloss of the Tamil theme. Deliberately quiet — it is a translation
   of the line beside it, not a third title. */
.levels__theme { font-family: var(--font-body); font-size: var(--fs-sm);
                 font-weight: 600; color: var(--text-muted); }
.levels__desc  { max-width: 74ch; margin: calc(var(--sp-5) * -1) 0 var(--sp-5);
                 font-size: var(--fs-sm); color: var(--text-soft);
                 line-height: var(--lh-body); }
.levels__grid  { display: grid; gap: var(--sp-6);
                 grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.levels__col h4 { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
                  letter-spacing: var(--ls-kicker); text-transform: uppercase;
                  color: var(--text-muted); margin-bottom: var(--sp-3); }
/* Flex for the same reason as .soon__list — see the note there. */
.levels__list { list-style: none; display: grid; gap: var(--sp-3); }
.levels__list li { display: flex; gap: var(--sp-3);
                   font-size: var(--fs-sm); color: var(--text-soft); line-height: var(--lh-body); }
.levels__list li::before { content: "•"; flex: 0 0 auto; width: 12px;
                           color: var(--accent); font-weight: 700; }
.levels__list--check li::before { content: "✓"; color: var(--teal-500); font-size: .85em; }
.levels__list--play  li::before { content: "▸"; color: var(--brand); }

.levels__streams { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-4); }
.levels__empty { color: var(--text-muted); font-size: var(--fs-sm); }

/* ============================================================================
   STROKE COMPARISON
   The Payil Method argument, side by side. Honest: it compares stroke COUNT and
   the order characters are introduced. It does not animate stroke paths — that
   needs real path data from the design team.
   ========================================================================= */
.strokes { display: grid; gap: var(--sp-5);
           grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }

.strokebox {
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--sp-6); background: var(--surface);
}
.strokebox--hard { border-color: var(--coral-500); }
.strokebox--easy { border-color: var(--teal-500); }

.strokebox__chars { display: flex; gap: var(--sp-5); justify-content: center; margin-block: var(--sp-5); }
.glyph { text-align: center; }
.glyph__ch {
  display: block;
  font-family: var(--font-tamil);
  font-size: clamp(3.5rem, 9vw, 5.5rem);
  line-height: 1; font-weight: 500; color: var(--text);
}
.glyph__n { display: block; margin-top: var(--sp-3); font-size: var(--fs-xs);
            font-weight: 700; color: var(--text-muted); }

.meter { height: 8px; border-radius: var(--radius-pill); background: var(--border); overflow: hidden; }
.meter i { display: block; height: 100%; border-radius: var(--radius-pill); }
.meter--hard i { background: var(--coral-500); }
.meter--easy i { background: var(--teal-500); }

/* ============================================================================
   FRANCHISE CALCULATOR
   Driven by calculator.js. The maths is ported verbatim from the original.
   ========================================================================= */
.calc {
  margin-top: var(--sp-7);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.calc__head {
  padding: var(--sp-5) var(--sp-6);
  border-bottom: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: center; justify-content: space-between;
}
.calc__rate { font-size: var(--fs-xs); color: var(--text-muted); }

.toggle {
  display: inline-flex; padding: 4px; gap: 2px;
  background: var(--bg-alt); border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}
.toggle button {
  border: 0; background: transparent; cursor: pointer;
  padding: 0.65rem 1.4rem; border-radius: var(--radius-pill);
  font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
  color: var(--text-muted);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.toggle button.is-active { background: var(--brand); color: var(--on-brand); }

.calc__body { display: grid; grid-template-columns: 1fr 1.3fr; }
.calc__inputs  { padding: var(--sp-6); border-right: 1px solid var(--border); }
.calc__results { padding: var(--sp-6); }
@media (max-width: 900px) {
  .calc__body { grid-template-columns: 1fr; }
  .calc__inputs { border-right: 0; border-bottom: 1px solid var(--border); }
}

.calc__label { font-size: var(--fs-xs); font-weight: 700; letter-spacing: var(--ls-kicker);
               text-transform: uppercase; color: var(--text-muted); }
.calc__big { font-family: var(--font-display); font-size: clamp(2.25rem, 5vw, 3rem);
             font-weight: 800; color: var(--brand); letter-spacing: var(--ls-tight);
             margin: var(--sp-2) 0 var(--sp-4); line-height: 1; }

.calc input[type="range"] {
  width: 100%; height: 8px; border-radius: var(--radius-pill);
  appearance: none; -webkit-appearance: none; outline: none; cursor: pointer;
  background: var(--border);
}
.calc input[type="range"]::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--surface); border: 3px solid var(--cta);
  box-shadow: var(--shadow-sm); cursor: grab;
  transition: transform var(--dur-fast) var(--ease);
}
.calc input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.14); }
.calc input[type="range"]::-moz-range-thumb {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--surface); border: 3px solid var(--cta);
  box-shadow: var(--shadow-sm); cursor: grab;
}
.calc__range-labels { display: flex; justify-content: space-between;
                      font-size: var(--fs-xs); color: var(--text-muted); margin-top: var(--sp-2); }

.calc__assume {
  margin-top: var(--sp-5); padding: var(--sp-4);
  background: var(--bg-alt); border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: var(--fs-xs); color: var(--text-muted); line-height: 2;
}
.calc__assume b { color: var(--text); }

.calc__cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-3); }
@media (max-width: 560px) { .calc__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.calc__card {
  background: var(--bg-alt); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: var(--sp-4);
  transition: transform var(--dur) var(--ease);
}
.calc__card:hover { transform: translateY(-3px); }
.calc__card small { display: block; font-size: 11px; font-weight: 700;
                    letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.calc__card b { display: block; margin-top: 4px;
                font-family: var(--font-display); font-size: clamp(1.1rem, 2vw, 1.5rem);
                font-weight: 800; color: var(--brand); letter-spacing: var(--ls-tight); }
.calc__card--hl { background: var(--accent-soft); border-color: transparent; }
.calc__card--hl b { color: var(--cta); }

.calc__chart { margin-top: var(--sp-6); }
.calc__chart h4 { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
                  letter-spacing: var(--ls-kicker); text-transform: uppercase;
                  color: var(--text-muted); margin-bottom: var(--sp-4); }
.bars { display: flex; gap: var(--sp-3); align-items: flex-end; height: 190px; }
.bar-col { flex: 1; height: 100%; display: flex; flex-direction: column;
           justify-content: flex-end; align-items: center; gap: var(--sp-2); }
.bar {
  width: 100%; max-width: 66px; min-height: 6px;
  border-radius: 10px 10px 4px 4px; background: var(--brand);
  transition: height .6s var(--ease), filter var(--dur-fast) var(--ease);
  cursor: pointer;
}
.bar:hover { filter: brightness(1.18); }
.bar.is-recouped { background: var(--cta); }
.bar-val { font-size: 11.5px; font-weight: 700; color: var(--brand); }
.bar-yr  { font-size: var(--fs-xs); color: var(--text-muted); }

.calc__legend { display: flex; flex-wrap: wrap; gap: var(--sp-5);
                margin-top: var(--sp-4); font-size: var(--fs-xs); color: var(--text-muted); }
.calc__legend i { display: inline-block; width: 11px; height: 11px;
                  border-radius: 3px; margin-right: 6px; vertical-align: -1px; }

.calc__note { padding: var(--sp-4) var(--sp-6); border-top: 1px solid var(--border);
              background: var(--bg-alt); font-size: var(--fs-xs); color: var(--text-muted); }

/* ============================================================================
   NUMBERED STEPS
   ========================================================================= */
.steps { display: grid; gap: var(--sp-3); counter-reset: step;
         grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); }
.step {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--sp-5) var(--sp-4);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.step:hover { transform: translateY(-6px); box-shadow: var(--shadow); border-color: var(--cta); }
.step::before { counter-increment: step; content: counter(step, decimal-leading-zero);
                font-size: var(--fs-xs); font-weight: 800; letter-spacing: .1em; color: var(--cta); }
.step h3 { font-size: var(--fs-h4); margin: var(--sp-2) 0 var(--sp-1); }
.step p  { font-size: var(--fs-xs); color: var(--text-muted); }

/* ============================================================================
   PRICE / TERMS TABLE
   ========================================================================= */
.terms { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.terms th, .terms td { padding: var(--sp-3) 0; text-align: left;
                       border-bottom: 1px solid var(--border); vertical-align: top; }
.terms th { font-weight: 500; color: var(--text-muted); width: 55%; }
.terms td { font-weight: 700; color: var(--text); text-align: right; }
.terms tr:last-child th, .terms tr:last-child td { border-bottom: 0; }

/* ============================================================================
   PARTNER REGISTER — the QR-only page
   ========================================================================= */
.partner {
  display: grid; gap: var(--sp-2);
  padding: var(--sp-5) 0; border-bottom: 1px solid var(--border);
}
.partner__top { display: flex; flex-wrap: wrap; gap: var(--sp-3);
                align-items: baseline; justify-content: space-between; }
.partner__name { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 700; }
.partner__where { font-size: var(--fs-sm); color: var(--text-muted); }
.partner__contact { font-size: var(--fs-sm); }

/* ============================================================================
   ANNUAL WINNERS
   Warm register. Ported off Tailwind CDN onto house tokens.
   ========================================================================= */
.flourish { color: var(--accent); letter-spacing: .6em; font-size: var(--fs-sm); }
.gold-rule { height: 2px; border: 0; margin-inline: auto;
             background: linear-gradient(90deg, transparent, var(--accent), transparent); }

.wtabs { display: flex; justify-content: center; gap: var(--sp-6);
         border-block: 1px solid var(--border); background: var(--bg-alt); }
.wtabs button {
  border: 0; background: none; cursor: pointer;
  padding: var(--sp-5) var(--sp-2);
  font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: var(--ls-kicker); text-transform: uppercase;
  color: var(--text-muted); border-bottom: 2px solid transparent;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.wtabs button.is-active { color: var(--brand); border-bottom-color: var(--accent); }

.wfilters { display: grid; gap: var(--sp-5); }
.wfilter { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-6); }
.wfilter > .calc__label { flex: 0 0 130px; }
.wfilter select { max-width: 340px; }

.wpodium {
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  align-items: stretch;
}
.wcard {
  position: relative; text-align: center;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--sp-6) var(--sp-5);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.wcard:hover { transform: translateY(-5px); box-shadow: var(--shadow); }
.wcard--1 { border: 2px solid var(--accent); box-shadow: var(--shadow); }
@media (min-width: 760px) { .wcard--1 { transform: scale(1.04) translateY(-8px); }
                            .wcard--1:hover { transform: scale(1.05) translateY(-12px); } }

.wcard__rank { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
               letter-spacing: var(--ls-kicker); text-transform: uppercase; color: var(--accent); }
.wcard__crest {
  width: 74px; height: 74px; margin: var(--sp-4) auto;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand);
  font-family: var(--font-serif); font-size: 1.5rem; font-weight: 700;
}
.wcard__name  { font-family: var(--font-serif); font-size: var(--fs-h3); font-weight: 700;
                line-height: 1.2; }
.wcard__ta    { display: block; font-size: .72em; font-weight: 500; color: var(--text-muted);
                margin-top: 4px; }
.wcard__sub   { font-size: var(--fs-sm); color: var(--text-muted); margin-top: var(--sp-2); }
.wcard__score { font-family: var(--font-display); font-size: 1.6rem; font-weight: 800;
                color: var(--brand); margin-top: var(--sp-4); letter-spacing: var(--ls-tight); }

.wempty { text-align: center; padding-block: var(--sp-8); color: var(--text-muted); }
.wempty p { font-family: var(--font-serif); font-size: var(--fs-h3); color: var(--text-soft); }

/* ============================================================================
   TEAM
   43 people is a lot of scrolling. The grid is filterable and searchable, and
   a portrait opens a detail panel rather than making every card carry a bio.
   ========================================================================= */
.team__bar {
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: center; justify-content: space-between;
  margin-bottom: var(--sp-6);
}
.team__chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.team__chip {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: var(--radius-pill); cursor: pointer;
  padding: 0.5rem 1rem;
  font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
  color: var(--text-soft);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.team__chip:hover { border-color: var(--brand); transform: translateY(-2px); }
.team__chip.is-active { background: var(--brand); color: var(--on-brand); border-color: var(--brand); }
.team__chip span { opacity: .65; margin-left: 5px; font-weight: 500; }

.team__search { max-width: 260px; }
.team__count { font-size: var(--fs-xs); color: var(--text-muted); }
.team__blurb { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-5);
               min-height: 1.5em; }

.team__grid {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 132px), 1fr));
}
.tmember {
  border: 0; background: none; padding: 0; cursor: pointer;
  text-align: center; font-family: inherit;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.tmember[hidden] { display: none; }
.tmember:hover, .tmember:focus-visible { transform: translateY(-6px); }

/* display:block is load-bearing. This is a <span> inside a <button>, so it
   defaults to display:inline — and on an inline box aspect-ratio and
   overflow:hidden are both ignored. The portrait then renders at its natural
   height, overflows the button, and pushes the name out from under the picture.
   Safari happened to mask it; Chrome, Edge and Firefox did not. Do not remove. */
.tmember__pic {
  display: block;
  position: relative; aspect-ratio: 1; overflow: hidden;
  border-radius: 50%; background: var(--brand-soft);
  border: 3px solid transparent;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tmember:hover .tmember__pic,
.tmember:focus-visible .tmember__pic { border-color: var(--accent); box-shadow: var(--shadow); }
.tmember.is-open .tmember__pic { border-color: var(--brand); box-shadow: var(--shadow); }
.tmember__pic img { width: 100%; height: 100%; object-fit: cover; }

.tmember__name { display: block; margin-top: var(--sp-3);
                 font-size: var(--fs-sm); font-weight: 700; color: var(--text); line-height: 1.25; }
.tmember__role { display: block; margin-top: 2px;
                 font-size: 11.5px; color: var(--text-muted); line-height: 1.35; }

.team__detail {
  margin-top: var(--sp-6);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--sp-6);
  display: grid; gap: var(--sp-5);
  grid-template-columns: 128px 1fr;
  align-items: start;
}
@media (max-width: 560px) { .team__detail { grid-template-columns: 1fr; text-align: center; } }
.team__detail[hidden] { display: none; }
.team__detail img { width: 128px; height: 128px; border-radius: 50%; object-fit: cover;
                    margin-inline: auto; border: 3px solid var(--accent); }
.team__detail h3 { font-size: var(--fs-h3); }
.team__detail .role { font-size: var(--fs-sm); font-weight: 700; color: var(--kicker);
                      margin-top: 2px; }
.team__detail .bio  { margin-top: var(--sp-4); color: var(--text-soft); }
.team__close { margin-top: var(--sp-4); }

.team__empty { padding: var(--sp-8) 0; text-align: center; color: var(--text-muted); }

/* Leadership, larger treatment */
.leader { display: grid; gap: var(--sp-5); grid-template-columns: 160px 1fr; align-items: center; }
@media (max-width: 620px) { .leader { grid-template-columns: 1fr; text-align: center; } }
.leader img { width: 160px; height: 160px; border-radius: 50%; object-fit: cover;
              margin-inline: auto; border: 4px solid var(--accent); }

/* ============================================================================
   PHOTOS
   Real classroom photography. Columns rather than a rigid grid, so portrait and
   landscape frames sit together without either being cropped.
   ========================================================================= */
.photos {
  columns: 3 260px;
  column-gap: var(--sp-4);
}
@media (max-width: 640px) { .photos { columns: 2 150px; column-gap: var(--sp-3); } }

.photo {
  break-inside: avoid;
  margin: 0 0 var(--sp-4);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.photo:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.photo img { width: 100%; height: auto; display: block; }
.photo figcaption {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.45;
}

/* Strip variant: a single row that scrolls, for use inside another section.

   The photographs range from 0.56 to 2.22 in aspect ratio — a fourfold spread,
   because they came from different phones held different ways. In the masonry
   above that variety is the point. In a single row it is a mess: flex stretches
   every card to the tallest, and a wide photo then floats in a tall empty box.

   So the strip crops. Every card is one ratio, filled edge to edge, which is
   the only thing that makes a row of mixed-source photos look deliberate. */
.photos--strip {
  columns: auto;
  display: flex;
  align-items: flex-start;        /* never stretch a card to its neighbour */
  gap: var(--sp-4);
  overflow-x: auto;
  padding-bottom: var(--sp-3);
  scroll-snap-type: x proximity;
}
.photos--strip .photo {
  flex: 0 0 clamp(220px, 26vw, 300px);
  margin: 0;
  scroll-snap-align: start;
}
.photos--strip .photo img {
  aspect-ratio: 4 / 3;
  height: auto;
  object-fit: cover;
  /* Bias the crop upward. In a classroom photo the faces and the screen are
     almost always above the midline; a centred crop tends to fill the frame
     with desk. */
  object-position: center 38%;
}
/* Captions vary from three words to nine, which would leave the cards ragged
   along the bottom. Two lines each, clipped. */
.photos--strip .photo figcaption {
  min-height: 3.4em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ============================================================================
   PARTNER LOGOS
   Sixteen marks from sixteen designers: different weights, colours and amounts
   of white space. Greyscale at rest is what makes them read as one row rather
   than a collision; colour returns on hover, which also rewards looking.
   ========================================================================= */
.partners {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(110px, 14vw, 150px), 1fr));
  gap: var(--sp-3);
  align-items: stretch;
}

.partner-logo {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-3);
  border: 1px solid transparent; border-radius: var(--radius);
  text-decoration: none;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

/* Hover is scoped to .partner-logo, NOT a.partner-logo.
   Three partners have no website, so they render as <span> rather than <a>.
   Scoping the hover to the anchor left those three dead while their neighbours
   lit up, which reads as broken rather than as "this one has no link". Every
   logo now responds; only the linked ones actually navigate. */
.partner-logo:hover, .partner-logo:focus-visible {
  background: var(--surface); border-color: var(--border); transform: translateY(-3px);
}
span.partner-logo { cursor: default; }

.partner-logo img {
  width: 100%; max-width: 84px; height: auto; aspect-ratio: 1; object-fit: contain;
  filter: grayscale(1); opacity: .62;
  transition: filter var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.partner-logo:hover img, .partner-logo:focus-visible img { filter: none; opacity: 1; }

/* The name is the point on a school logo — half of them are a crest that means
   nothing to someone outside that town. Small, quiet, always there. */
.partner__name {
  font-size: 11.5px; line-height: 1.35; text-align: center;
  color: var(--text-muted);
  transition: color var(--dur) var(--ease);
}
.partner-logo:hover .partner__name,
.partner-logo:focus-visible .partner__name { color: var(--text); }

@media (max-width: 520px) {
  .partners { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--sp-2); }
  .partner-logo { padding: var(--sp-3) var(--sp-2); }
  .partner-logo img { max-width: 60px; }
}

/* ---------- Utilities ---------------------------------------------------- */
.center     { text-align: center; }
.center-x   { margin-inline: auto; }
.flow-sm > * + * { margin-top: var(--sp-2); }
.hr { height: 1px; background: var(--border); border: 0; }
.logo-strip {
  display: flex; flex-wrap: wrap; gap: var(--sp-6);
  align-items: center; justify-content: center;
}
.logo-strip img { height: 40px; width: auto; opacity: .62; transition: opacity var(--dur) var(--ease); }
.logo-strip img:hover { opacity: 1; }

/* ============================================================================
   SLIDER
   Sample report pages on For Schools. Enhancement only — without .is-slider
   the markup is a readable vertical list of figures.
   ============================================================================ */
.stats-lite > * {
  padding-top: var(--sp-4);
  border-top: 2px solid var(--brand);
}
.stats-lite .card__title { margin-bottom: var(--sp-2); }

.slider {
  /* Its own duration token: --dur is too quick to read a page turn, --dur-slow
     (.8s) is long enough to feel unresponsive on a click. */
  --dur-slide: .45s;
}
.slider__track { display: grid; gap: var(--sp-6); }

.is-slider .slider__viewport {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  transition: height var(--dur-slide) var(--ease);
}
.is-slider .slider__track {
  display: flex;
  /* NOT the default `stretch`. With stretch every slide grows to the height of
     the tallest, so measuring the active slide would always return the cover's
     height and the viewport would never shrink for the wider pages. Same trap
     as the school photo strip. */
  align-items: flex-start;
  gap: 0;
  transition: transform var(--dur-slide) var(--ease);
  will-change: transform;
}
.is-slider .slider__slide {
  flex: 0 0 100%;
  min-width: 0;
  /* Inactive slides stay in the flow so the track keeps its width, but they
     must not be tabbable or announced. */
  opacity: .25;
  transition: opacity var(--dur) var(--ease);
}
.is-slider .slider__slide.is-active { opacity: 1; }
.is-slider .slider__slide[aria-hidden="true"] { pointer-events: none; }

.slider__slide figure { margin: 0; }
.slider__slide img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border-soft);
  box-shadow: var(--shadow-lg);
  background: #fff;
}
.slider__slide figcaption {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  text-align: center;
}

.slider__arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 2;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  font-size: 26px; line-height: 1;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.slider__arrow:hover { background: var(--bg-alt); }
.slider__arrow:active { transform: translateY(-50%) scale(.94); }
.slider__arrow--prev { left: var(--sp-3); }
.slider__arrow--next { right: var(--sp-3); }

.slider__dots {
  display: flex; justify-content: center; gap: var(--sp-2);
  margin-top: var(--sp-5);
}
.slider__dot {
  width: 9px; height: 9px; padding: 0;
  border: 0; border-radius: var(--radius-pill);
  background: var(--border);
  cursor: pointer;
  transition: background var(--dur) var(--ease), width var(--dur) var(--ease);
}
.slider__dot.is-active { background: var(--brand); width: 26px; }

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

@media (max-width: 640px) {
  .slider__arrow { width: 38px; height: 38px; font-size: 22px; }
  .slider__arrow--prev { left: 4px; }
  .slider__arrow--next { right: 4px; }
}

@media (prefers-reduced-motion: reduce) {
  .is-slider .slider__track,
  .is-slider .slider__viewport { transition: none; }
}

/* ---------- Proof card (product screenshot on a dark register) ------------ */
/* The progress card ships with its own warm cream background, so on the navy
   register it needs to read as a lit panel rather than a floating rectangle
   with a hard edge. Padding in the same cream, then a soft lift. */
.proof-card { margin: 0; }
.proof-card img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius);
  box-shadow: 0 24px 64px rgba(0,0,0,.28);
}
.proof-card figcaption {
  margin-top: var(--sp-4);
  max-width: 64ch; margin-inline: auto;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* ---------- Form consent + honeypot -------------------------------------- */
.form-check {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  margin-top: var(--sp-2);
}
.form-check input[type="checkbox"] {
  flex: 0 0 auto; width: 18px; height: 18px; margin-top: 3px;
  accent-color: var(--brand); cursor: pointer;
}
.form-check label {
  font-size: var(--fs-sm); line-height: 1.5; color: var(--text-muted); cursor: pointer;
}

/* Honeypot. Must be invisible to people but still fillable by a bot, so it is
   NOT display:none — some bots skip hidden fields, which would defeat it. */
.hp {
  position: absolute !important; left: -9999px !important;
  width: 1px; height: 1px; overflow: hidden;
}

/* ---------- Checkbox group ------------------------------------------------ */
/* Used for "what are you interested in", which maps to a HubSpot multiple-
   checkboxes property. Two columns on desktop, one on a phone. */
.check-grid {
  display: grid; gap: var(--sp-2) var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  margin-top: var(--sp-2);
}
.check-grid label {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  font-size: var(--fs-sm); line-height: 1.45; color: var(--text);
  cursor: pointer; padding: 3px 0;
}
.check-grid input[type="checkbox"] {
  flex: 0 0 auto; width: 17px; height: 17px; margin-top: 2px;
  accent-color: var(--brand); cursor: pointer;
}

/* ---------- Prose (long-form legal / policy pages) ----------------------- */
.prose h2 {
  margin-top: var(--sp-8); margin-bottom: var(--sp-3);
  padding-top: var(--sp-5); border-top: 1px solid var(--border-soft);
  font-size: var(--fs-h3);
}
.prose h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.prose p { margin-bottom: var(--sp-4); max-width: 68ch; }
.prose ul { margin-bottom: var(--sp-4); }
/* An unresolved placeholder must look wrong. If one of these reaches a public
   page it should be the first thing anyone notices. */
.todo {
  background: #ffe8a3; color: #6b4a00; font-weight: 700;
  padding: 1px 6px; border-radius: 4px;
}

/* ---------- Download size hint ------------------------------------------- */
/* A school on a slow connection deserves to know that a guide is 46 MB before
   they tap it, not after. Shown beside every download link. */
.dl-size {
  display: inline-block;
  margin-left: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
@media (max-width: 520px) {
  .dl-size { display: block; margin-left: 0; margin-top: 4px; }
}

/* ============================================================================
   VIDEO GALLERY
   The .webp card is the artwork — no chrome of ours on top of it. We add a
   play affordance, a lift on hover, and a focus ring, and otherwise stay out
   of the designer's way.
   ============================================================================ */
.vgal {
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
}
.vgal__card {
  position: relative; display: block; padding: 0; border: 0; background: none;
  cursor: pointer; border-radius: var(--radius);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.vgal__card img { display: block; width: 100%; height: auto; border-radius: var(--radius); }
.vgal__card:hover { transform: translateY(-4px); }
.vgal__card:hover, .vgal__card:focus-visible { box-shadow: var(--shadow-lg); }
.vgal__card:focus-visible { outline: 3px solid var(--brand); outline-offset: 3px; }
/* The cards already carry a play glyph in the artwork; ours only appears on
   hover, as a hit-target hint rather than a second button. */
.vgal__play {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 34px; color: #fff; opacity: 0;
  border-radius: var(--radius); background: rgba(19,26,46,.28);
  transition: opacity var(--dur) var(--ease);
}
.vgal__card:hover .vgal__play, .vgal__card:focus-visible .vgal__play { opacity: 1; }

/* ---------- Lightbox ----------------------------------------------------- */
.lightbox {
  position: fixed; inset: 0; z-index: 1000;
  display: grid; place-items: center; padding: var(--sp-5);
  background: rgba(10,14,24,.88);
}
.lightbox__in { max-width: min(96vw, 900px); width: 100%; }
.lightbox video {
  display: block; width: 100%; max-height: 74vh;
  border-radius: var(--radius); background: #000;
}
.lightbox__cap { margin-top: var(--sp-4); color: #fff; text-align: center; }
.lightbox__cap strong { display: block; font-family: var(--font-display); font-size: var(--fs-h3); }
.lightbox__cap span   { display: block; color: rgba(255,255,255,.72); font-size: var(--fs-sm); margin-top: 2px; }
.lightbox__cap p      { color: rgba(255,255,255,.72); font-size: var(--fs-sm); margin: var(--sp-3) auto 0; max-width: 56ch; }
.lightbox__close {
  position: absolute; top: var(--sp-4); right: var(--sp-5);
  width: 44px; height: 44px; display: grid; place-items: center;
  font-size: 30px; line-height: 1; color: #fff;
  background: rgba(255,255,255,.12); border: 0; border-radius: var(--radius-pill);
  cursor: pointer;
}
.lightbox__close:hover { background: rgba(255,255,255,.22); }

/* ============================================================================
   BOOKSHELF — the Payil wrappers, and the sample flipbook behind each
   The cover is the thing a teacher recognises, so the cover is the button.
   ============================================================================ */
/* Four across, so seven books fall 4 + 3 rather than 5 + 2 with two orphans. */
.shelf {
  display: grid; gap: var(--sp-5) var(--sp-5);
  grid-template-columns: repeat(4, 1fr);
}
/* align-content:start matters. Grid rows default to stretch, so a book with a
   two-line caption in a row where another has three ends up with its cover
   pushed down and the whole row out of line. */
.shelf__book {
  display: grid; align-content: start; gap: var(--sp-3);
  padding: 0; text-align: left;
  font: inherit; color: inherit; background: none; border: 0; cursor: pointer;
}
/* The wrappers are not all scanned to the same ratio — payil-4 is a little
   squarer than the rest. The ratio is pinned on the frame and the artwork
   fills it, so every spine is the same height and the captions below line up. */
.shelf__cover {
  position: relative; display: block; aspect-ratio: 640 / 878;
  border-radius: var(--radius-sm); overflow: hidden; box-shadow: var(--shadow);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.shelf__cover img { display: block; width: 100%; height: 100%; object-fit: cover; }
.shelf__book:hover .shelf__cover { transform: translateY(-5px); box-shadow: var(--shadow-lg); }
.shelf__book:focus-visible .shelf__cover { outline: 3px solid var(--brand); outline-offset: 3px; }

/* The prompt sits over the foot of the cover, out of the artwork's way. */
.shelf__open {
  position: absolute; inset: auto 0 0 0; padding: var(--sp-5) var(--sp-3) var(--sp-3);
  font-size: var(--fs-sm); font-weight: 700; color: #fff; text-align: center;
  background: linear-gradient(to top, rgba(10,14,24,.86), rgba(10,14,24,0));
  opacity: 0; transition: opacity var(--dur) var(--ease);
}
.shelf__book:hover .shelf__open,
.shelf__book:focus-visible .shelf__open { opacity: 1; }
/* Touch has no hover, and a cover that says nothing looks like a picture. */
@media (hover: none) { .shelf__open { opacity: 1; } }

.shelf__meta  { display: grid; gap: 1px; }
.shelf__grade { font-size: var(--fs-sm); font-weight: 700; color: var(--brand); }
.shelf__name  { font-family: var(--font-display); color: var(--text); }
.shelf__sub   { font-size: var(--fs-sm); color: var(--muted); }
.shelf__note  { font-size: var(--fs-sm); color: var(--muted); margin-top: 2px; }

/* ---------- The sample, open ---------------------------------------------- */
.lightbox__in--book { max-width: min(96vw, 1180px); }
.bookview {
  display: grid; grid-template-rows: auto 1fr;
  border-radius: var(--radius); overflow: hidden; background: #182c3d;
}
.bookview__bar {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); background: rgba(255,255,255,.08); color: #fff;
}
.bookview__bar strong { font-family: var(--font-display); }
.bookview__bar span   { color: rgba(255,255,255,.78); font-size: var(--fs-sm); }
.bookview__tag {
  padding: 2px 10px; border-radius: var(--radius-pill);
  background: rgba(255,255,255,.12); font-size: var(--fs-xs, .75rem) !important;
}
/* .bookview__out was the "Open in a new tab" link in the bar. Removed from the
   markup on 14 Aug 2026 — see the bookshelf comment in float.js for why. The rule
   is gone rather than left behind, because it carried `margin-left:auto`, and a
   dead rule with layout in it is the kind of thing that gets copied onto the next
   element that lands in this bar. */
.bookview__frame { display: block; width: 100%; height: min(78vh, 760px); border: 0; background: #182c3d; }

@media (max-width: 860px) { .shelf { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) {
  .shelf { grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); }
  .bookview__frame { height: 70vh; }
}

/* ============================================================================
   PRESENTATION PLAYER
   One stage, a chapter rail beneath. The rail is the customisation made
   visible — chapter 1 differs per audience, the rest are shared.
   ============================================================================ */
.pres__stage { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-lg); background: #000; }
.pres__video { display: block; width: 100%; aspect-ratio: 16/9; background: #000; }

/* ---------- Presets ------------------------------------------------------ */
.pres__presets {
  display: grid; gap: var(--sp-3); margin-bottom: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}
.pres__preset {
  display: grid; gap: 2px; text-align: left; cursor: pointer; font: inherit;
  padding: var(--sp-4); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.pres__preset:hover { border-color: var(--brand); }
.pres__preset.is-active { border-color: var(--brand); border-width: 2px; background: var(--bg-alt); }
.pres__preset strong { font-family: var(--font-display); font-size: var(--fs-h4, 1rem); color: var(--text); }
.pres__mins { font-size: var(--fs-sm); font-weight: 700; color: var(--brand); }
.pres__why  { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.4; }

/* ---------- The bar between stage and list ------------------------------- */
.pres__bar {
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: center; justify-content: space-between;
  margin: var(--sp-4) 0 var(--sp-5);
}
.pres__now { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.pres__play:disabled { opacity: .45; cursor: not-allowed; }

/* ---------- The chapter list --------------------------------------------- */
.pres__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.pres__row {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
/* Unticked chapters fade but stay legible — a principal should still be able
   to read what they chose to skip. */
.pres__row.is-off { opacity: .45; }
.pres__row.is-playing { border-color: var(--brand); border-width: 2px; background: var(--bg-alt); }
.pres__pick { display: flex; align-items: center; gap: var(--sp-3); flex: 1 1 auto; cursor: pointer; min-width: 0; }
.pres__pick input { width: 18px; height: 18px; flex: 0 0 auto; accent-color: var(--brand); cursor: pointer; }
.pres__num {
  flex: 0 0 auto; width: 24px; height: 24px; display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: #fff;
  background: var(--muted); border-radius: var(--radius-pill);
}
.pres__row.is-playing .pres__num { background: var(--brand); }
.pres__title { flex: 1 1 auto; font-size: var(--fs-sm); min-width: 0; }
.pres__len { flex: 0 0 auto; font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap; }
.pres__jump {
  flex: 0 0 auto; cursor: pointer; font: inherit; font-size: var(--fs-sm);
  padding: 4px var(--sp-3); color: var(--navy-600, var(--text));
  background: none; border: 1px solid var(--border); border-radius: var(--radius-pill);
}
.pres__jump:hover { border-color: var(--brand); color: var(--brand); }

@media (max-width: 520px) {
  .pres__bar { flex-direction: column; align-items: stretch; }
  .pres__play { width: 100%; }
}
