
/* ==========================================================================
   CAMBRIDGE ONLINE — core
   Light is the default theme. Palette is lifted from the crest: oxblood,
   antique gold, ivory.
   ========================================================================== */

:root{
  --display:"Cormorant Garamond",Georgia,"Times New Roman",serif;
  --sans:"Outfit",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,monospace;

  --gold:#C9982F;
  --gold-lo:#A8781C;
  --gold-hi:#F3DDA4;
  --maroon:#5A1015;
  --maroon-dp:#2A0608;

  --wrap:1280px;
  --r:22px;
  --r-sm:15px;
  --r-xs:10px;
  --hdr:78px;

  --ease:cubic-bezier(.22,.61,.36,1);
  --out:cubic-bezier(.16,1,.3,1);
  --spring:cubic-bezier(.34,1.56,.64,1);
}

/* ------------------------------------------------------------ light (default) */
[data-theme="light"]{
  --bg:#F6F1E6;
  --bg-2:#EDE3D0;
  --ink:#24100F;
  --text-1:#24100F;
  --text-2:rgba(36,16,15,.74);
  --text-3:rgba(36,16,15,.62);
  --line:rgba(36,16,15,.13);
  --line-2:rgba(36,16,15,.24);
  --gold-text:#8A6212;

  --panel:rgba(255,253,248,.46);
  --panel-fx:blur(38px) saturate(1.55);
  --panel-solid:rgba(253,250,243,.965);
  --edge:rgba(36,16,15,.10);
  --hi:rgba(255,255,255,.85);
  --sheen:rgba(255,255,255,.62);
  --shadow:0 22px 50px -26px rgba(74,26,10,.34);
  --shadow-lg:0 40px 90px -40px rgba(74,26,10,.45);
  --scroll-track:rgba(36,16,15,.06);
  --cine:#1A0708;
  --veil:linear-gradient(0deg,rgba(42,12,6,.52),transparent 54%);
  --veil-bar:linear-gradient(0deg,rgba(30,10,6,.78),transparent);
  --veil-ink:rgba(255,248,236,.92);

  /* Header pill — warm ivory, lit along the edges in the crest's oxblood. */
  --bar-fill:linear-gradient(180deg,#FFFDF8 0%,#F8F2E5 54%,#EDE2CE 100%);
  --bar-edge:rgba(90,16,21,.14);
  --bar-edge-2:rgba(90,16,21,.34);
  --bar-gloss:rgba(90,16,21,.62);
  --bar-gloss-2:rgba(90,16,21,.3);
  --bar-sweep:rgba(90,16,21,.1);
  --bar-shadow:0 2px 0 rgba(90,16,21,.09) inset,0 14px 34px -18px rgba(74,26,10,.42);
  --bar-shadow-lg:0 2px 0 rgba(90,16,21,.13) inset,0 20px 46px -18px rgba(74,26,10,.55);

  /* Clear glass — the rail cards. Far more transparent than --panel, which is
     a frosted slab; this one is a lens. Blur does the legibility work, not
     opacity, so whatever passes behind it stays readable as colour. */
  --clear-fill:rgba(255,253,248,.12);
  --clear-fx:blur(36px) saturate(1.85);
  --clear-solid:rgba(253,250,243,.94);
  --clear-edge:rgba(255,255,255,.72);
  --clear-edge-2:rgba(90,16,21,.12);
  --clear-rim:rgba(255,255,255,.92);
  --clear-rim-lo:rgba(255,255,255,.46);
  --clear-shadow:0 18px 44px -22px rgba(74,26,10,.42);
  --clear-shadow-hi:0 26px 60px -22px rgba(74,26,10,.5);
  --clear-tint:radial-gradient(120% 100% at 12% 0%,rgba(255,255,255,.5),transparent 62%);
  --clear-spec:rgba(255,255,255,.5);
  --wiz-input:rgba(255,253,247,.20);
  --wiz-input-on:rgba(255,255,255,.42);
  --wiz-input-edge:rgba(90,16,21,.13);

  /* Floating theme + sound controls. */
  --ctl-fill:linear-gradient(180deg,#FFFFFF,#F3EBDA);
  --ctl-fill-off:linear-gradient(180deg,#F7F3EA,#E9E2D4);
  --ctl-edge:rgba(90,16,21,.15);
  --ctl-ink:#2E1A18;
  --ctl-knob:#FFFFFF;
  --ctl-knob-shadow:0 3px 9px rgba(74,26,10,.28);
  --ctl-live:#5A1015;
  --ctl-shadow:0 12px 28px -14px rgba(74,26,10,.5),inset 0 1px 0 #fff;
  --ctl-shadow-hi:0 18px 36px -14px rgba(74,26,10,.6),inset 0 1px 0 #fff;

  /* Soft pill. Two shadows, not one: a warm cast down and right, and a light
     bloom up and left. A single drop shadow makes a sticker; a matched pair
     makes the surface look like it is being lit from a real direction, which
     is the whole of this effect. */
  /* Step numerals — cut into the card face. */
  --step-n:rgba(90,50,20,.14);
  --step-n-lip:rgba(255,255,255,.9);
  --step-n-hi:rgba(201,152,47,.38);
  --sf-face:linear-gradient(180deg,rgba(255,255,255,.62) 0%,rgba(255,253,247,.36) 100%);
  --sf-fx:blur(15px) saturate(1.35);
  --sf-solid:#FBF7EE;
  --sf-edge:rgba(36,16,15,.09);
  --sf-lip:rgba(255,255,255,.95);
  --sf-floor:rgba(120,88,44,.1);
  --sf-cast:rgba(92,62,26,.15);
  --sf-bloom:rgba(255,255,255,.8);
  --sf-ink:#2B2420;
  /* Selected: crest red, not gold. Gold is already carrying the eyebrows, the
     rules, the numerals and half the buttons on this page — one more gold
     object stops reading as "selected" and starts reading as decoration. Red
     is the other half of the palette and appears nowhere else at this size. */
  --sf-on-face:linear-gradient(180deg,#7E1C23 0%,#5A1015 52%,#3C090D 100%);
  --sf-on-edge:rgba(60,9,13,.6);
  --sf-on-cast:rgba(90,16,21,.42);
  --sf-on-lip:rgba(243,221,164,.3);
  --sf-on-ink:#F8F0E3;

  /* Buttons. */
  --btn-rim:#7A4A12;
  --btn-soft:rgba(255,255,255,.72);
  --btn-soft-2:rgba(255,255,255,.94);
  --btn-soft-hi:rgba(255,255,255,.9);
  --btn-soft-sh:rgba(74,26,10,.42);
  --scrim:rgba(246,241,230,.5);
  --scrim-solid:rgba(246,241,230,.93);
  --btn-chip:linear-gradient(180deg,#FFFFFF,#EFE6D4);
  --btn-ink:linear-gradient(180deg,#43191D,#1D0709);
  --btn-ink-fg:#F7EFE1;
  --btn-ink-rim:#120405;
  --btn-ink-ring:rgba(201,152,47,.34);
  --btn-ink-glow:rgba(201,152,47,.42);
  --btn-chip-ink:linear-gradient(180deg,#F3DDA4,#C9982F);
  /* Retired with the machined-metal hero pair, kept so that treatment is one
     class swap away. Nothing references these now. */
  --chrome-face:linear-gradient(180deg,#FDF3D9 0%,#E5C87F 30%,#B98B1E 51%,#E8D097 72%,#FEF7E4 100%);
  --chrome-rim:rgba(255,255,255,.7);
  --chrome-face-2:linear-gradient(180deg,#8A3238 0%,#551A1F 32%,#2E080B 52%,#632126 74%,#93393F 100%);
  --chrome-rim-2:rgba(201,152,47,.5);
  --chrome-bezel:rgba(255,252,244,.72);
  --chrome-glow:rgba(201,152,47,.42);
  --field-face:linear-gradient(180deg,#F0E4C6 0%,#FBF3DE 48%,#EFE2C2 100%);
  --field-edge:rgba(138,98,18,.34);
  --field-recess:rgba(90,16,21,.16);
  --field-lip:rgba(255,255,255,.95);
  --field-bezel:rgba(255,255,255,.85);
  --field-fg:#6E4C0C;
  --field-fg-hi:#4A3006;

  /* Liquid glass — the hero pair. Two states of the same material: a dense
     smoked pane and a clear one. Both are lit, not filled. */
  /* Barely a fill at all — a breath of warm white so the pane sits a shade
     above the page, and nothing more. The shape is carried by the bevel and
     the shadow, not by a tint. The primary keeps a whisper of gold in it so
     it still leads the pair; that whisper is the only thing separating the
     two now that neither has a face. */
  --lq-fill:linear-gradient(180deg,rgba(236,237,241,.46),rgba(216,218,225,.20));
  --lq-fg:#24100F;
  --lq-fg-sh:0 1px 0 rgba(255,255,255,.78);
  /* Bottom, middle, top of the ring. The gap between them used to be the
     whole point; now it only has to be enough to read as a lit edge. */
  --lq-rim:rgba(255,255,255,.62);
  --lq-rim-hi:rgba(255,255,255,1);
  /* Was a warm ivory — the one drop of gold left in the ring. Silver now, so
     the whole edge reads as one metal instead of two. */
  --lq-rim-warm:rgba(224,231,241,.86);
  --lq-bevel:rgba(255,255,255,.95);
  --lq-bevel-2:rgba(255,255,255,.6);
  --lq-inner:rgba(255,255,255,.85);
  --lq-floor:rgba(38,48,64,.10);
  --lq-fx:blur(26px) saturate(.42) brightness(1.03);
  --lq-sky:rgba(255,255,255,.14);
  --lq-bounce:rgba(255,255,255,.06);

  /* The SWK card. Thinner than the buttons and it does not drain colour —
     the buttons are meant to read grey, but a grey plate this size just looks
     like a panel laid over the hero. Here the photo goes through more or less
     as it is, and only the edge says there is glass in the way. */
  --by-fill:linear-gradient(180deg,rgba(255,255,255,.13),rgba(255,255,255,.035));
  --by-fx:blur(15px) saturate(1.05);
  --by-inner:rgba(255,255,255,.5);
  --by-floor:rgba(90,50,20,.05);
  /* The drawer sits over live page copy, so it keeps more body than the card
     while using the same bevel and the same filament. */
  --mob-fill:linear-gradient(180deg,rgba(255,253,248,.62),rgba(248,244,235,.46));
  --mob-fx:blur(34px) saturate(1.15);
  --mob-item:rgba(255,255,255,.42);

  /* Preloader. */
  --pl-bloom:rgba(201,152,47,.16);
  --pl-bloom-2:rgba(90,16,21,.07);
  --pl-ring:rgba(36,16,15,.10);
  --pl-arc:rgba(201,152,47,.85);
  --pl-cast:rgba(74,26,10,.30);
  --lq-spec:rgba(255,255,255,.55);
  --lq-lens:rgba(255,255,255,.9);
  /* The cast and the halo were brown and putty — a gold button's shadow. A
     silver one throws a cool grey. */
  --lq-cast:rgba(34,44,60,.28);
  --lq-halo:rgba(148,162,182,.26);
  /* The header CTA sits on the opaque ivory bar, not the hero photo, so a
     white pane on a white bar would be nothing. It used to solve that with a
     gold tint; it solves it with a cool steel one now, which separates from
     ivory just as well and keeps every button on the page the same metal. */
  --lq-fill-sm:linear-gradient(180deg,rgba(236,241,248,.80),rgba(203,213,229,.44));
  /* Steel, not white. Both panes are near-white now, so a white filament has
     nothing to sit against — this was silver-on-smoked-oxblood before. */
  --lq-trace:#8B939F;
  --lq-trace-glow:rgba(255,255,255,.9);

  /* ---- argent: the solid-face replacement ------------------------------
     Five buttons on this site used to be painted gold — a hard 135deg ramp
     from --gold-hi to --gold-lo with near-black ink on it. Against a page
     that is already gold-rimmed, gold-ruled and gold-lettered, a gold FACE
     was the one place the colour stopped being an accent and became the
     object, and it flattened every panel it sat on.

     They are all the same material now: the pane from the liquid buttons,
     with the rim pushed from white toward a real silver so the edge reads as
     drawn metal rather than as a highlight. Nothing is filled. The shape is
     the lining. */
  --sv-fill:linear-gradient(180deg,rgba(247,250,254,.56),rgba(210,218,231,.26));
  --sv-fg:#1B2331;
  --sv-fg-sh:0 1px 0 rgba(255,255,255,.82);
  /* Top, middle and bottom of the ring. The middle stop is the silver: a
     white-to-white ring is a highlight, a white-to-grey one is metal. */
  --sv-rim-hi:rgba(255,255,255,1);
  --sv-rim-mid:rgba(226,232,241,.94);
  --sv-rim:rgba(142,156,176,.62);
  --sv-bevel:rgba(255,255,255,.96);
  --sv-bevel-2:rgba(255,255,255,.58);
  --sv-inner:rgba(255,255,255,.82);
  --sv-floor:rgba(38,48,64,.10);
  --sv-cast:rgba(34,44,60,.28);
  --sv-halo:rgba(148,162,182,.26);
  --sv-sky:rgba(255,255,255,.16);
  --sv-fx:blur(22px) saturate(.48) brightness(1.04);
  /* Where the face has to sit on a photograph — the two round play buttons
     over a poster frame — the pane needs body or the glyph is unreadable. */
  --sv-fill-solid:linear-gradient(180deg,rgba(250,252,255,.86),rgba(214,222,235,.7));
  --sv-fg-solid:#171E2A;

  --lq2-fill:linear-gradient(180deg,rgba(232,234,239,.30),rgba(212,215,222,.10));
  --lq2-fg:#24100F;
  --lq2-fg-sh:0 1px 0 rgba(255,255,255,.7);
  --lq2-rim:rgba(255,255,255,.58);
  --lq2-rim-hi:rgba(255,255,255,1);
  --lq2-rim-warm:rgba(255,255,255,.82);
  --lq2-bevel:rgba(255,255,255,.9);
  --lq2-bevel-2:rgba(255,255,255,.55);
  --lq2-inner:rgba(255,255,255,.75);
  --lq2-floor:rgba(90,50,20,.08);
  --lq2-fx:blur(26px) saturate(.42) brightness(1.03);
  --lq2-sky:rgba(255,255,255,.12);
  --lq2-bounce:rgba(255,255,255,.05);
  --lq2-spec:rgba(255,255,255,.45);
  --lq2-lens:rgba(255,255,255,.8);
  --lq2-cast:rgba(74,32,14,.24);
  --lq2-halo:rgba(140,132,120,.16);
  /* Steel rather than white — a white filament vanishes on the clear pane. */
  --lq2-trace:#8B939F;
  --lq2-trace-glow:rgba(255,255,255,.9);

  --hero-bg-op:.34;
  --hero-bg-filter:sepia(.3) saturate(.75) brightness(1.08) contrast(.9);
}

/* ------------------------------------------------------------------- dark */
[data-theme="dark"]{
  --bg:#0C0304;
  --bg-2:#170708;
  --ink:#F5EDE0;
  --text-1:#F5EDE0;
  --text-2:rgba(245,237,224,.73);
  --text-3:rgba(245,237,224,.52);
  --line:rgba(245,237,224,.12);
  --line-2:rgba(245,237,224,.22);
  --gold-text:#E3B55D;

  --panel:rgba(38,12,13,.34);
  --panel-fx:blur(40px) brightness(.72) saturate(1.3);
  --panel-solid:#1A0708;
  --edge:rgba(245,237,224,.13);
  --hi:rgba(255,255,255,.07);
  --sheen:rgba(255,255,255,.07);
  --shadow:0 26px 60px -28px rgba(0,0,0,.85);
  --shadow-lg:0 44px 100px -44px rgba(0,0,0,.95);
  --scroll-track:rgba(245,237,224,.05);
  --cine:#080202;
  --veil:linear-gradient(0deg,rgba(8,2,2,.62),transparent 58%);
  --veil-bar:linear-gradient(0deg,rgba(8,2,2,.85),transparent);
  --veil-ink:rgba(247,239,225,.85);

  /* Header pill — deep oxblood glass, rimmed in a lifted crest red. */
  --bar-fill:linear-gradient(180deg,#3A1418 0%,#1E080A 56%,#130405 100%);
  --bar-edge:rgba(168,36,44,.24);
  --bar-edge-2:rgba(190,46,54,.44);
  --bar-gloss:rgba(214,72,78,.85);
  --bar-gloss-2:rgba(160,30,38,.6);
  --bar-sweep:rgba(206,64,70,.17);
  --bar-shadow:0 1px 0 rgba(224,96,102,.16) inset,0 16px 40px -18px rgba(0,0,0,.9);
  --bar-shadow-lg:0 1px 0 rgba(224,96,102,.22) inset,0 24px 54px -18px rgba(0,0,0,.95);

  /* Clear glass, dark. The lens picks up the oxblood behind it rather than
     laying a grey film over it, and the rim warms toward the crest red. */
  --clear-fill:rgba(84,26,30,.10);
  --clear-fx:blur(38px) saturate(1.62) brightness(1.12);
  --clear-solid:rgba(32,11,13,.96);
  --clear-edge:rgba(226,148,152,.24);
  --clear-edge-2:rgba(226,148,152,.14);
  --clear-rim:rgba(255,214,216,.42);
  --clear-rim-lo:rgba(255,214,216,.22);
  --clear-shadow:0 20px 50px -22px rgba(0,0,0,.86);
  --clear-shadow-hi:0 28px 66px -22px rgba(0,0,0,.94);
  --clear-tint:radial-gradient(120% 100% at 12% 0%,rgba(255,255,255,.09),transparent 62%);
  --clear-spec:rgba(255,226,196,.10);
  --wiz-input:rgba(255,240,225,.038);
  --wiz-input-on:rgba(255,240,225,.085);
  --wiz-input-edge:rgba(226,148,152,.18);

  /* Floating theme + sound controls — same oxblood glass as the header. */
  --ctl-fill:linear-gradient(180deg,#3A1418,#170607);
  --ctl-fill-off:linear-gradient(180deg,#241214,#120708);
  --ctl-edge:rgba(214,72,78,.26);
  --ctl-ink:#F5EDE0;
  --ctl-knob:#FFFFFF;
  --ctl-knob-shadow:0 3px 10px rgba(0,0,0,.6);
  --ctl-live:#D6484E;
  --ctl-shadow:0 14px 32px -14px rgba(0,0,0,.85),inset 0 1px 0 rgba(224,96,102,.18);
  --ctl-shadow-hi:0 20px 42px -14px rgba(0,0,0,.9),inset 0 1px 0 rgba(224,96,102,.26);

  /* Soft pill, dark. The bloom cannot be white here — on a near-black page a
     white top-left glow reads as a smear rather than light. It becomes a
     faint warm lift instead, and the cast does most of the work. */
  /* Dark: the engraved edge catches light from above, so the lip goes light
     and the fill goes darker than the card rather than lighter. */
  --step-n:rgba(0,0,0,.42);
  --step-n-lip:rgba(255,214,216,.13);
  --step-n-hi:rgba(201,152,47,.42);
  --sf-face:linear-gradient(180deg,rgba(255,242,228,.10) 0%,rgba(255,242,228,.035) 100%);
  --sf-fx:blur(16px) saturate(1.15) brightness(.96);
  --sf-solid:#1E0A0B;
  --sf-edge:rgba(245,237,224,.12);
  --sf-lip:rgba(255,255,255,.17);
  --sf-floor:rgba(0,0,0,.5);
  --sf-cast:rgba(0,0,0,.72);
  --sf-bloom:rgba(255,240,225,.045);
  --sf-ink:#F2E9DC;
  /* The red has to come up a long way in dark mode — a #5A1015 pill on a page
     that is already near-black oxblood would disappear into it. */
  --sf-on-face:linear-gradient(180deg,#A52A32 0%,#7A1B21 52%,#530F14 100%);
  --sf-on-edge:rgba(226,110,116,.34);
  --sf-on-cast:rgba(0,0,0,.7);
  --sf-on-lip:rgba(243,221,164,.28);
  --sf-on-ink:#FCF4E7;

  /* Buttons. */
  --btn-rim:#4A2A08;
  --btn-soft:rgba(58,20,24,.72);
  --btn-soft-2:rgba(74,26,30,.92);
  --btn-soft-hi:rgba(224,96,102,.18);
  --btn-soft-sh:rgba(0,0,0,.8);
  --scrim:rgba(12,3,4,.58);
  --scrim-solid:rgba(12,3,4,.94);
  --btn-chip:linear-gradient(180deg,#4A2028,#1E0A0C);
  --btn-ink:linear-gradient(180deg,#4E1D22,#20090B);
  --btn-ink-fg:#F7EFE1;
  --btn-ink-rim:#0A0203;
  --btn-ink-ring:rgba(214,72,78,.4);
  --btn-ink-glow:rgba(214,72,78,.45);
  --btn-chip-ink:linear-gradient(180deg,#F3DDA4,#C9982F);
  /* Retired — see the note in the light block. */
  --chrome-face:linear-gradient(180deg,#FFF8E6 0%,#EFD59D 30%,#C9982F 51%,#F0DDAC 72%,#FFFBEF 100%);
  --chrome-rim:rgba(255,246,224,.62);
  --chrome-face-2:linear-gradient(180deg,#8A6A34 0%,#573F17 32%,#33240C 52%,#654A1D 74%,#96743A 100%);
  --chrome-rim-2:rgba(227,181,93,.55);
  --chrome-bezel:rgba(201,152,47,.2);
  --chrome-glow:rgba(201,152,47,.55);
  --field-face:linear-gradient(180deg,#2C1013 0%,#3E181C 48%,#250C0F 100%);
  --field-edge:rgba(227,181,93,.34);
  --field-recess:rgba(0,0,0,.6);
  --field-lip:rgba(227,181,93,.26);
  --field-bezel:rgba(243,221,164,.13);
  --field-fg:#E3B55D;
  --field-fg-hi:#F3DDA4;

  /* On near-black the smoked pane lifts to warm oxblood so it doesn't sink
     into the page, and the clear pane becomes a lit sliver of white. */
  /* Same clear material inverted: the pane holds a little light instead of a
     little dark, and the bevel does the rest. */
  --lq-fill:linear-gradient(180deg,rgba(222,228,238,.085),rgba(198,206,220,.02));
  --lq-fg:#FDF7EB;
  --lq-fg-sh:0 1px 2px rgba(0,0,0,.55);
  --lq-rim:rgba(255,255,255,.44);
  /* Every one of these was a warm ivory (255,246,228) — candlelight on the
     bevel. Cooled to a lit silver so the edge matches the filament. */
  --lq-rim-hi:rgba(255,255,255,.95);
  --lq-rim-warm:rgba(212,224,241,.72);
  --lq-bevel:rgba(230,239,251,.6);
  --lq-bevel-2:rgba(230,239,251,.28);
  /* The inner glow and the specular are what turned into a film on near-black,
     so both come down hard here, and the floor deepens to pull the pane back
     toward the page. */
  --lq-inner:rgba(226,232,242,.16);
  --lq-floor:rgba(0,0,0,.42);
  --lq-spec:rgba(226,232,242,.14);
  /* Brightness under 1: the pane darkens what it sees instead of lifting it. */
  --lq-fx:blur(28px) saturate(.5) brightness(.78);
  --lq-sky:rgba(255,255,255,.055);
  --lq-bounce:rgba(255,255,255,.02);

  --by-fill:linear-gradient(180deg,rgba(245,237,224,.055),rgba(245,237,224,.015));
  --by-fx:blur(15px) saturate(1.05) brightness(.92);
  --by-inner:rgba(255,255,255,.09);
  --by-floor:rgba(0,0,0,.3);
  --mob-fill:linear-gradient(180deg,rgba(38,16,18,.66),rgba(18,7,8,.52));
  --mob-fx:blur(34px) saturate(1.1) brightness(.9);
  --mob-item:rgba(245,237,224,.07);

  /* Preloader. */
  --pl-bloom:rgba(201,152,47,.13);
  --pl-bloom-2:rgba(140,22,28,.14);
  --pl-ring:rgba(245,237,224,.10);
  --pl-arc:rgba(227,181,93,.9);
  --pl-cast:rgba(0,0,0,.7);
  --lq-lens:rgba(224,235,250,.5);
  --lq-cast:rgba(0,0,0,.66);
  --lq-halo:rgba(178,190,208,.34);
  /* On the dark bar the pane is already well clear of its ground. */
  --lq-fill-sm:linear-gradient(180deg,rgba(224,235,250,.20),rgba(198,212,234,.06));
  --lq-trace:#EDF1F6;
  --lq-trace-glow:rgba(206,224,255,.55);

  /* ---- argent, inverted ------------------------------------------------
     On near-black the pane holds a little light instead of a little dark,
     and the ring runs the other way: bright at the top where the page glows,
     falling to a cool graphite at the bottom. */
  --sv-fill:linear-gradient(180deg,rgba(224,233,247,.13),rgba(190,203,223,.04));
  --sv-fg:#F0F5FD;
  --sv-fg-sh:0 1px 2px rgba(0,0,0,.6);
  --sv-rim-hi:rgba(255,255,255,.94);
  --sv-rim-mid:rgba(206,220,240,.68);
  --sv-rim:rgba(150,166,190,.44);
  --sv-bevel:rgba(230,239,251,.56);
  --sv-bevel-2:rgba(230,239,251,.26);
  --sv-inner:rgba(214,228,246,.17);
  --sv-floor:rgba(0,0,0,.42);
  --sv-cast:rgba(0,0,0,.66);
  --sv-halo:rgba(168,184,206,.32);
  --sv-sky:rgba(255,255,255,.06);
  --sv-fx:blur(24px) saturate(.55) brightness(.84);
  --sv-fill-solid:linear-gradient(180deg,rgba(236,243,253,.9),rgba(196,209,230,.74));
  --sv-fg-solid:#141A25;

  --lq2-fill:linear-gradient(180deg,rgba(220,226,236,.05),rgba(206,214,228,.012));
  --lq2-fg:#F5EDE0;
  --lq2-fg-sh:0 1px 2px rgba(0,0,0,.5);
  --lq2-rim:rgba(245,237,224,.30);
  --lq2-rim-hi:rgba(255,255,255,.66);
  --lq2-rim-warm:rgba(255,255,255,.46);
  --lq2-bevel:rgba(255,255,255,.42);
  --lq2-bevel-2:rgba(255,255,255,.18);
  --lq2-inner:rgba(255,255,255,.12);
  --lq2-floor:rgba(0,0,0,.38);
  --lq2-spec:rgba(255,255,255,.11);
  --lq2-fx:blur(28px) saturate(.5) brightness(.78);
  --lq2-sky:rgba(255,255,255,.04);
  --lq2-bounce:rgba(255,255,255,.015);
  --lq2-lens:rgba(255,255,255,.36);
  --lq2-cast:rgba(0,0,0,.6);
  --lq2-halo:rgba(178,182,192,.10);
  --lq2-trace:#E4EAF1;
  --lq2-trace-glow:rgba(206,224,255,.5);

  --hero-bg-op:.3;
  --hero-bg-filter:sepia(.42) saturate(.6) brightness(.52) contrast(1.06);
}

/* ------------------------------------------------------------------- base */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-padding-top:104px;overflow-x:clip}
/* Smooth scrolling is driven in JS on pointer devices; keep the native
   behaviour as the fallback everywhere else. */
html:not(.lenis){scroll-behavior:smooth}
html.lenis{scroll-behavior:auto}

body{
  margin:0;font-family:var(--sans);font-weight:300;
  font-size:16.5px;line-height:1.65;
  color:var(--text-1);background:var(--bg);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  transition:background .6s var(--ease);
}
[data-theme="light"] body::before{
  background:
    radial-gradient(920px 640px at 82% -6%, rgba(201,152,47,.20), transparent 62%),
    radial-gradient(720px 560px at 4% 22%, rgba(90,16,21,.09), transparent 66%),
    radial-gradient(1000px 700px at 50% 106%, rgba(201,152,47,.10), transparent 70%);
}
[data-theme="dark"] body::before{
  background:
    radial-gradient(920px 640px at 82% -6%, rgba(201,152,47,.15), transparent 62%),
    radial-gradient(720px 560px at 4% 22%, rgba(140,22,28,.20), transparent 66%),
    radial-gradient(1000px 700px at 50% 106%, rgba(201,152,47,.07), transparent 70%);
}
.base{position:relative;z-index:1}

img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
ul{margin:0;padding:0;list-style:none}
::selection{background:rgba(201,152,47,.3);color:var(--text-1)}
:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:6px}

/* -------------------------------------------------------- the scrollbar */
/* Gold rail on an ivory groove — matches the crest rather than the OS. */
/* Chrome and Edge read the gold rail below; setting scrollbar-color for
   them too would switch them to the plain system bar with arrows. Firefox
   only understands the standard pair, so it alone gets it. */
@supports (-moz-appearance:none){*{scrollbar-width:thin;scrollbar-color:var(--gold) var(--scroll-track)}}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:var(--scroll-track);border-radius:99px}
::-webkit-scrollbar-thumb{
  border-radius:99px;border:3px solid transparent;background-clip:content-box;
  background-image:linear-gradient(180deg,var(--gold-hi),var(--gold) 45%,var(--gold-lo));
}
::-webkit-scrollbar-thumb:hover{
  background-image:linear-gradient(180deg,var(--gold-hi),var(--gold-hi) 40%,var(--gold));
}
::-webkit-scrollbar-corner{background:transparent}

/* Phones and tablets have no hover, so the silver outline draws itself
   instead: each button and card traces its edge once as it scrolls into
   view, and keeps it. */
@media (hover:none){
  .is-traced > .btn__trace rect{stroke-dashoffset:0;opacity:1}
  .has-edge.is-traced{border-color:transparent !important}
}
@media (hover:hover){
  .has-edge:hover{border-color:transparent !important}
}

/* Enrol now, always to hand: pinned to the right side of the screen on
   every page, opposite the theme and sound dock. It steps aside while the
   form itself is on screen. */
.btn.fenrol{position:fixed;left:auto;top:auto;right:calc(18px + env(safe-area-inset-right));bottom:calc(20px + env(safe-area-inset-bottom));z-index:60;
  box-shadow:0 14px 34px -12px rgba(42,6,8,.5);transition:opacity .35s var(--ease),transform .35s var(--out)}
.fenrol .btn__lq{display:inline-flex;align-items:center;gap:8px}
.fenrol .btn__lq svg{width:18px;height:18px}
.btn.fenrol.is-away{opacity:0;transform:translateY(16px);pointer-events:none}
@media (max-width:720px){
  .btn.fenrol{right:calc(14px + env(safe-area-inset-right));bottom:calc(16px + env(safe-area-inset-bottom));--pad:13px 18px;font-size:.8rem}
}


/* -------------------------------------------------------------- typography */
h1,h2,h3,h4{
  font-family:var(--display);font-weight:500;line-height:1.06;
  letter-spacing:-.014em;margin:0 0 .5em;color:var(--text-1);
}
h1{font-size:clamp(2.4rem,5vw,4.35rem)}
h2{font-size:clamp(2rem,3.9vw,3.3rem)}
h3{font-size:clamp(1.2rem,1.8vw,1.55rem);line-height:1.2}
h4{
  font-size:.74rem;font-family:var(--mono);font-weight:400;
  letter-spacing:.18em;text-transform:uppercase;color:var(--gold-text);
}
h1 em,h2 em{font-style:italic;font-weight:400;color:var(--gold-text)}
p{margin:0 0 1.05em}p:last-child{margin-bottom:0}

.eyebrow{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:.69rem;letter-spacing:.24em;
  text-transform:uppercase;color:var(--gold-text);margin:0 0 15px;
}
.eyebrow::before{
  content:"";width:22px;height:1px;background:var(--gold);flex:0 0 auto;
}
.center .eyebrow::before{display:none}
.rule{width:58px;height:1px;margin:0 0 24px;
      background:linear-gradient(90deg,var(--gold),transparent)}
.center .rule{margin-inline:auto;background:linear-gradient(90deg,transparent,var(--gold),transparent)}
.lede{font-size:clamp(1.02rem,1.2vw,1.12rem);color:var(--text-2);max-width:62ch}
.center .lede{margin-inline:auto}
.note{font-size:.82rem;color:var(--text-3);line-height:1.6}

/* ----------------------------------------------------------------- layout */
.wrap{width:min(100% - 44px,var(--wrap));margin-inline:auto}
.sec{padding-block:clamp(64px,8vw,132px);position:relative}
/* Note for later: content-visibility:auto on .sec cuts load work noticeably,
   but it collapses every unmeasured section to its intrinsic placeholder, so
   the offsets the nav computes are wrong until a section has been scrolled
   past once. Tested it — "Campuses" landed 11,000px short. Not worth a broken
   menu for the milliseconds it saved. */
.head{margin-bottom:clamp(32px,3.8vw,54px);max-width:72ch}
.head.center{margin-inline:auto;text-align:center}
.split{display:grid;grid-template-columns:1.04fr .96fr;gap:clamp(32px,4.4vw,70px);align-items:center}

/* ----------------------------------------------------------------- panel */
.glass{
  position:relative;border-radius:var(--r);
  background:var(--panel);border:1px solid var(--edge);
  box-shadow:var(--shadow);overflow:hidden;isolation:isolate;
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .glass{-webkit-backdrop-filter:var(--panel-fx);backdrop-filter:var(--panel-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass{background:var(--panel-solid)}
}
.glass::before{
  content:"";position:absolute;inset:0 0 auto;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--hi) 22%,var(--hi) 78%,transparent);
}
.glass--sm{border-radius:var(--r-sm)}
.glass--gilt{border-color:rgba(201,152,47,.4)}
.glass--gilt::before{
  background:linear-gradient(90deg,transparent,rgba(201,152,47,.8) 30%,rgba(201,152,47,.8) 70%,transparent);
}
.glass--sheen::after{
  content:"";position:absolute;inset:-40%;pointer-events:none;
  background:linear-gradient(115deg,transparent 42%,var(--sheen) 50%,transparent 58%);
  transform:translateX(-62%);transition:transform 1.15s var(--out);
}
.glass--sheen:hover::after{transform:translateX(62%)}
/* ---------------------------------------------------- touch: no hover ----
   A coarse pointer never fires :hover, so every treatment below was dead on
   phones. Each one is mirrored onto .is-hot, which JS applies as an element
   crosses the middle of the viewport — the sheen sweeps, the cards lift and
   the filament runs as you scroll, instead of waiting for a cursor that will
   never arrive. Kept as separate rules rather than a shared selector list:
   Safari drops an entire list if it cannot parse one selector in it. */
.glass--sheen.is-hot::after{transform:translateX(62%)}
.card.is-hot{transform:translateY(-5px);border-color:rgba(201,152,47,.4)}
.step.is-hot{transform:translateY(-5px);border-color:rgba(201,152,47,.36)}
.sub.is-hot{transform:translateY(-3px);border-color:rgba(201,152,47,.4)}
/* The card's own is-hot states live with the card, further down — the rail
   and play button they used to target no longer exist. */
/* The silver filament. Same run as the hover state, same 1.1s curve. */
.btn--liquid.is-hot .btn__trace rect{stroke-dashoffset:0;opacity:1}
.btn--liquid.is-hot{
  transform:translateY(-3px);
  box-shadow:
    inset 0 2px 1px -1px var(--lqx-bevel),
    inset 0 -2px 1px -1px var(--lqx-bevel-2),
    inset 2px 0 2px -2px var(--lqx-bevel-2),
    inset -2px 0 2px -2px var(--lqx-bevel-2),
    inset 0 0 14px -4px var(--lqx-inner),
    inset 0 -14px 20px -18px var(--lqx-floor),
    0 1px 1px rgba(0,0,0,.07),
    0 14px 32px -16px var(--lqx-cast),
    0 38px 72px -34px var(--lqx-cast),
    0 0 66px -16px var(--lqx-halo);
}
.btn--sm.btn--liquid.is-hot{transform:translateY(-2px)}
.hero__by.is-hot .btn__trace rect{stroke-dashoffset:0;opacity:1}

@media (prefers-reduced-transparency:reduce){
  .glass{background:var(--panel-solid);-webkit-backdrop-filter:none;backdrop-filter:none}
}

/* --------------------------------------------------------------- buttons */
/* Three treatments, no outline style: a 3D primary with a lit rim and a
   glow bed, a soft shadow secondary, and a brushed-chrome variant for dark
   plates. Every one keeps the same pill geometry so they line up in a row. */
.btn{
  --pad:14px 28px;
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:var(--pad);border-radius:99px;font-size:.92rem;line-height:1;
  border:1px solid transparent;cursor:pointer;white-space:nowrap;
  transition:transform .24s var(--out),box-shadow .32s var(--ease),
             background .26s var(--ease),color .26s var(--ease),
             border-color .26s var(--ease),filter .26s var(--ease);
}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0) scale(.985)}

/* ---- primary: 3D. Dark rim, embossed face, glow bed underneath ---- */
.btn--gold{
  background:var(--sv-fill);
  -webkit-backdrop-filter:var(--sv-fx);backdrop-filter:var(--sv-fx);
  color:var(--sv-fg);font-weight:600;
  border:0;
  text-shadow:var(--sv-fg-sh);
  box-shadow:var(--sv-lift);
}
.btn--gold:hover{box-shadow:var(--sv-lift-hi)}

/* ---- secondary: shadow. No hard edge, just a deep diffuse bed ---- */
/* ══════════════════════════════════════ ARGENT ═══════════════════════════
   One material, five buttons. Every one of them used to carry a painted gold
   face; they now carry the same pane of glass the hero buttons do, ringed in
   silver.

   Two shadow stacks, held as tokens because .btn--gold, .nx__go, .fpop__buy,
   .camp__go--p and the two round play buttons all want them and none of them
   share a selector.

   The lining itself is a masked ring, not a border: a border cannot hold a
   gradient, and a flat one-colour edge on a translucent pane reads as a
   sticker. Padding-box is knocked out of the gradient with mask-composite,
   leaving a 1.4px band that runs bright at the top and falls to graphite at
   the bottom — which is how a turned metal edge actually catches a room. */
:root,[data-theme="light"],[data-theme="dark"]{
  --sv-lift:
    inset 0 2px 1px -1px var(--sv-bevel),
    inset 0 -2px 1px -1px var(--sv-bevel-2),
    inset 2px 0 2px -2px var(--sv-bevel-2),
    inset -2px 0 2px -2px var(--sv-bevel-2),
    inset 0 0 14px -4px var(--sv-inner),
    inset 0 -14px 20px -18px var(--sv-floor),
    0 1px 1px rgba(0,0,0,.07),
    0 10px 26px -14px var(--sv-cast),
    0 0 40px -18px var(--sv-halo);
  --sv-lift-hi:
    inset 0 2px 1px -1px var(--sv-bevel),
    inset 0 -2px 1px -1px var(--sv-bevel-2),
    inset 2px 0 2px -2px var(--sv-bevel-2),
    inset -2px 0 2px -2px var(--sv-bevel-2),
    inset 0 0 14px -4px var(--sv-inner),
    inset 0 -14px 20px -18px var(--sv-floor),
    0 1px 1px rgba(0,0,0,.07),
    0 16px 36px -16px var(--sv-cast),
    0 0 60px -16px var(--sv-halo);
}
/* The lining is attached by rule rather than by a class in the markup: four
   of these six buttons are built by script, and a utility class would have to
   be threaded through the generated HTML for no gain. */
.btn--gold,.nx__go,.fpop__buy,.camp__go--p,.fpop__go,.player__big{
  position:relative;isolation:isolate;
}
.btn--gold::before,.nx__go::before,.fpop__buy::before,
.camp__go--p::before,.fpop__go::before,.player__big::before{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;padding:1.4px;
  background:linear-gradient(180deg,
    var(--sv-rim-hi) 0%,
    var(--sv-rim-mid) 44%,
    var(--sv-rim) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
/* The label has to clear the ring's stacking context. */
.fpop__buy > *,.camp__go--p > *,.nx__go > *{position:relative;z-index:2}

.btn--line{
  background:var(--btn-soft);
  color:var(--text-1);font-weight:500;
  border-color:transparent;
  box-shadow:inset 0 1px 0 var(--btn-soft-hi),0 12px 26px -12px var(--btn-soft-sh);
}
.btn--line:hover{
  color:var(--gold-text);background:var(--btn-soft-2);
  box-shadow:inset 0 1px 0 var(--btn-soft-hi),0 20px 40px -14px var(--btn-soft-sh);
}

/* ---- liquid: the hero pair only. A pane of glass, not a painted face ----
   Nothing here is filled in the way the other buttons are. The face is a
   translucent sheet that blurs and over-saturates whatever sits behind it —
   the classroom photo, the gold bloom — and the shape is read entirely from
   its edge: a rim that varies in brightness around the perimeter the way a
   real bevel catches a room, warm where the page is warm, and a specular
   pool that tracks the cursor across the surface. Two states of the one
   material: a smoked pane for the primary, a clear pane for the secondary.
   Every colour comes from the theme, so it inverts with the page. */
.btn--liquid{
  /* Material slots. The clear variant swaps these and nothing else. */
  --lqx-fill:var(--lq-fill);
  --lqx-fg:var(--lq-fg);
  --lqx-rim:var(--lq-rim);
  --lqx-rim-hi:var(--lq-rim-hi);
  --lqx-rim-warm:var(--lq-rim-warm);
  --lqx-spec:var(--lq-spec);
  --lqx-lens:var(--lq-lens);
  --lqx-cast:var(--lq-cast);
  --lqx-halo:var(--lq-halo);
  --lqx-fg-sh:var(--lq-fg-sh);
  --lqx-bevel:var(--lq-bevel);
  --lqx-bevel-2:var(--lq-bevel-2);
  --lqx-inner:var(--lq-inner);
  --lqx-floor:var(--lq-floor);
  --lqx-fx:var(--lq-fx);
  --lqx-sky:var(--lq-sky);
  --lqx-bounce:var(--lq-bounce);
  --lqx-trace:var(--lq-trace);
  --lqx-trace-glow:var(--lq-trace-glow);
  /* Cursor position for the specular pool; set from JS, safe without it. */
  --lqx-mx:50%;
  --lqx-my:-14%;

  --pad:17px 32px;
  min-height:58px;
  border-radius:20px;
  border:0;
  overflow:hidden;
  isolation:isolate;
  font-size:.95rem;font-weight:500;letter-spacing:.012em;
  color:var(--lqx-fg);
  text-shadow:var(--lqx-fg-sh);
  background:var(--lqx-fill);
  /* With almost no fill left, the blur is doing nearly all the work — and so
     is the saturation, in the other direction. Pulling it below 1 drains the
     colour out of whatever sits behind the pane, which is what makes the glass
     read grey rather than picking up the gold and oxblood of the hero. The
     brightness term goes the opposite way per theme, though, which is why this
     is a token: on cream the pane has to be lifted off the page, on near-black
     it has to be pushed into it, or the grey stops being a tint and becomes a
     milky film sitting on top of a dark hero. */
  -webkit-backdrop-filter:var(--lqx-fx);
  backdrop-filter:var(--lqx-fx);
  box-shadow:
    /* The bevel. Four insets standing in for a thick rolled edge: a bright
       top lip, a softer return along the bottom, and a pair of shorter
       catches down the sides. This is what gives the pane its shape now that
       there is no face to give it one. */
    inset 0 2px 1px -1px var(--lqx-bevel),
    inset 0 -2px 1px -1px var(--lqx-bevel-2),
    inset 2px 0 2px -2px var(--lqx-bevel-2),
    inset -2px 0 2px -2px var(--lqx-bevel-2),
    /* Light gathering all the way round the inside of that edge. */
    inset 0 0 14px -4px var(--lqx-inner),
    /* And pooling on the floor of the pane, which is what stops it reading
       as a flat cutout. */
    inset 0 -14px 20px -18px var(--lqx-floor),
    /* Contact shadow, the float, then the warm halo it throws. */
    0 1px 1px rgba(0,0,0,.07),
    0 8px 22px -14px var(--lqx-cast),
    0 24px 50px -30px var(--lqx-cast),
    0 0 44px -18px var(--lqx-halo);
  transition:transform .3s var(--out),box-shadow .42s var(--ease),
             background .42s var(--ease),color .26s var(--ease);
}

/* The rim. A hairline ring masked out of a gradient running top to bottom.

   It used to be a conic gradient sweeping eight stops around the perimeter,
   on the theory that a real bevel catches a room unevenly. Two things went
   wrong with that. The stops spanned .16 to .95 alpha, so across a hairline
   the ring did not read as *lit* unevenly — it read as broken, with whole
   stretches of edge missing. And a conic gradient wraps: the colour at 360deg
   butted straight into the colour at 0deg with nothing blending them, leaving
   a hard cut at the start angle, plainly visible on the upper-left curve.

   A linear gradient has no wrap point, so it cannot produce that seam, and
   top-to-bottom is the direction a lit edge actually falls off. The range is
   narrow enough now that no part of the ring ever drops out of sight. */
.btn--liquid::before{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;padding:1.4px;
  background:linear-gradient(180deg,
    var(--lqx-rim-hi) 0%,
    var(--lqx-rim-warm) 46%,
    var(--lqx-rim) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  transition:filter .42s var(--ease),opacity .42s var(--ease);
}

/* The specular. A pool of light that slides along the top edge with the
   pointer, plus the fixed sky gradient and a faint bounce off the bottom.
   It is parked above the top edge on purpose — dragged down into the middle
   of the face it stops reading as a highlight and starts reading as fog. */
.btn--liquid::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  border-radius:inherit;
  background:
    radial-gradient(160px 96px at var(--lqx-mx) var(--lqx-my),var(--lqx-spec),transparent 70%),
    linear-gradient(180deg,var(--lqx-sky) 0%,rgba(255,255,255,0) 48%),
    linear-gradient(0deg,var(--lqx-bounce) 0%,rgba(255,255,255,0) 24%);
  opacity:.86;
  transition:background .12s linear;
}

/* Label rides above both pseudo layers. */
.btn__lq{position:relative;z-index:2;display:inline-flex;align-items:center;gap:11px}
.btn__lq svg{width:19px;height:19px;flex:0 0 auto;opacity:.95}

/* Hover. Nothing about the face changes — not the blur, not the saturation,
   and not the internal lighting. Earlier passes brightened the rim, opened
   the specular to full and widened the inset glow; stacked on a dark pane
   that read as a haze settling over the button rather than as a response.
   So the inset stack here is byte-identical to the resting one. Only the
   outer float deepens, the button lifts, and the trace runs. */
.btn--liquid:hover{
  transform:translateY(-3px);
  box-shadow:
    inset 0 2px 1px -1px var(--lqx-bevel),
    inset 0 -2px 1px -1px var(--lqx-bevel-2),
    inset 2px 0 2px -2px var(--lqx-bevel-2),
    inset -2px 0 2px -2px var(--lqx-bevel-2),
    inset 0 0 14px -4px var(--lqx-inner),
    inset 0 -14px 20px -18px var(--lqx-floor),
    0 1px 1px rgba(0,0,0,.07),
    0 14px 32px -16px var(--lqx-cast),
    0 38px 72px -34px var(--lqx-cast),
    0 0 66px -16px var(--lqx-halo);
}
.btn--liquid:active{transform:translateY(-1px) scale(.988)}
.btn--liquid:focus-visible{outline:2px solid var(--sv-rim-hi);outline-offset:4px}

/* ---- the trace ---------------------------------------------------------
   A single silver filament that starts at one point on the top edge and runs
   the whole perimeter, then holds there for as long as the cursor stays. It
   is an SVG rect rather than a border, because only a stroke can be drawn
   progressively: pathLength normalises the perimeter to 100 units whatever
   the button's width, so one dashoffset transition works on both of them and
   at every breakpoint. Leaving retracts it back the way it came. */
.btn__trace{
  position:absolute;inset:0;z-index:4;
  width:100%;height:100%;pointer-events:none;overflow:visible;
}
.btn__trace rect{
  x:.6px;y:.6px;
  width:calc(100% - 1.2px);height:calc(100% - 1.2px);
  rx:19.4px;ry:19.4px;
  fill:none;
  stroke:var(--lqx-trace,var(--lq2-trace));
  stroke-width:1.2;
  /* One dash the length of the whole perimeter, one gap the same. Offset 100
     parks the dash entirely off the path; 0 lays it all the way round. */
  stroke-dasharray:100;
  stroke-dashoffset:100;
  /* Near-constant speed with a soft landing — an ease-out curve makes the
     filament sprint the top edge and crawl the last corner. */
  transition:stroke-dashoffset 1.1s cubic-bezier(.55,.06,.3,1),opacity .26s linear;
  opacity:0;
}
.btn--liquid:hover .btn__trace rect,
.btn--liquid:focus-visible .btn__trace rect{
  stroke-dashoffset:0;
  opacity:1;
}
/* A breath of glow so the filament reads on the clear pane in light mode,
   where a bare silver hairline sits too close to the face behind it. */
.btn__trace{filter:drop-shadow(0 0 2.5px var(--lqx-trace-glow,var(--lq2-trace-glow)))}
.btn--sm.btn--liquid .btn__trace rect{rx:13.4px;ry:13.4px}

/* Browsers without CSS SVG geometry properties get the line as a plain ring
   rather than nothing at all. */
@supports not (x:1px){
  .btn__trace rect{stroke-dasharray:none;stroke-dashoffset:0}
}
/* No drawing for reduced motion — the line simply appears and holds. */
@media (prefers-reduced-motion:reduce){
  .btn__trace rect{transition-duration:.001ms}
}

/* The secondary of the pair: the same sheet, undyed. Reads as the clear
   pane the smoked one was cut from. */
.btn--liquid-clear{
  --lqx-fill:var(--lq2-fill);
  --lqx-fg:var(--lq2-fg);
  --lqx-rim:var(--lq2-rim);
  --lqx-rim-hi:var(--lq2-rim-hi);
  --lqx-rim-warm:var(--lq2-rim-warm);
  --lqx-spec:var(--lq2-spec);
  --lqx-lens:var(--lq2-lens);
  --lqx-cast:var(--lq2-cast);
  --lqx-halo:var(--lq2-halo);
  --lqx-fg-sh:var(--lq2-fg-sh);
  --lqx-bevel:var(--lq2-bevel);
  --lqx-bevel-2:var(--lq2-bevel-2);
  --lqx-inner:var(--lq2-inner);
  --lqx-floor:var(--lq2-floor);
  --lqx-fx:var(--lq2-fx);
  --lqx-sky:var(--lq2-sky);
  --lqx-bounce:var(--lq2-bounce);
  --lqx-trace:var(--lq2-trace);
  --lqx-trace-glow:var(--lq2-trace-glow);
}

/* No backdrop-filter, or transparency turned down: fall back to an opaque
   face so the pair never becomes unreadable text on a photograph. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .btn--liquid{background:var(--panel-solid);border:1px solid var(--line-2)}
}
@media (prefers-reduced-transparency:reduce){
  .btn--liquid,.mob,.hero__by{
    -webkit-backdrop-filter:none;backdrop-filter:none;
    background:var(--panel-solid);border:1px solid var(--line-2);
  }
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .mob,.hero__by{background:var(--panel-solid);border:1px solid var(--line-2)}
}

/* ---- field: the navbar CTA. Recessed face, lit lip, raised bezel ring ----
   Tinted rather than neutral white — a plain grey field would sink into the
   bar it sits in. */
.btn--field{
  background:var(--field-face);
  color:var(--field-fg);font-weight:600;
  border:1px solid var(--field-edge);
  box-shadow:
    inset 0 2px 5px var(--field-recess),
    inset 0 -2px 0 var(--field-lip),
    0 0 0 5px var(--field-bezel),
    0 8px 18px -10px rgba(74,26,10,.45);
}
.btn--field:hover{
  color:var(--field-fg-hi);
  box-shadow:
    inset 0 2px 6px var(--field-recess),
    inset 0 -2px 0 var(--field-lip),
    0 0 0 6px var(--field-bezel),
    0 12px 24px -10px rgba(74,26,10,.55);
}

/* ---- ink: the dark rimmed pill. Deep face, lit edge, glow ring ---- */
.btn--ink{
  background:
    linear-gradient(180deg,rgba(255,255,255,.16),rgba(255,255,255,0) 46%),
    var(--btn-ink);
  color:var(--btn-ink-fg);font-weight:600;
  border:2px solid var(--btn-ink-rim);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.22),
    inset 0 -2px 6px rgba(0,0,0,.45),
    0 0 0 1px var(--btn-ink-ring),
    0 10px 26px -8px rgba(42,6,8,.7),
    0 0 30px -6px var(--btn-ink-glow);
}
.btn--ink:hover{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.3),
    inset 0 -2px 6px rgba(0,0,0,.38),
    0 0 0 1px var(--btn-ink-ring),
    0 16px 34px -8px rgba(42,6,8,.78),
    0 0 44px -4px var(--btn-ink-glow);
}

/* ---- chip: a circular icon puck seated in the pill's left end ---- */
.btn--chip{padding-left:8px;gap:12px}
.btn__chip{
  width:32px;height:32px;border-radius:50%;flex:0 0 auto;
  display:grid;place-items:center;
  background:var(--btn-chip);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 2px 6px rgba(42,6,8,.32);
}
.btn__chip svg{width:16px;height:16px}
.btn--sm{--pad:10px 18px;font-size:.83rem}
/* Small: the header CTA. Sized to sit inside the 60px bar with air on both
   sides, and with the blur dialled back — the pane is only 40px tall, so the
   heavy hero blur would smear the bar's own gradient into mush. */
.btn--sm.btn--liquid{
  --lqx-fill:var(--lq-fill-sm);
  --pad:11px 22px;
  min-height:40px;
  font-size:.85rem;
  border-radius:14px;
  -webkit-backdrop-filter:blur(14px) saturate(1.7);
  backdrop-filter:blur(14px) saturate(1.7);
}
.btn--sm.btn--liquid:hover{transform:translateY(-2px)}
.btn--sm.btn--chip{padding-left:6px;gap:9px}
.btn--sm .btn__chip{width:26px;height:26px}
.btn--sm .btn__chip svg{width:14px;height:14px}
/* On the ink pill the puck goes gold so it still reads as the accent. */
.btn--ink .btn__chip{background:var(--btn-chip-ink);color:#2A1403;
                     box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 2px 6px rgba(0,0,0,.5)}
/* On gold it stays ivory in both themes — the themed puck went dark-on-gold. */
.btn--gold .btn__chip{background:linear-gradient(180deg,#FFFFFF,#DFE6F1);color:var(--sv-fg-solid);
                      box-shadow:inset 0 1px 0 #fff,0 2px 6px rgba(90,16,21,.34)}
/* `.btn` sets display:inline-flex, which outranks the user-agent rule the
   `hidden` attribute relies on. Without this the wizard's Back button is
   visible on step one, where there is nowhere to go back to. */
.btn[hidden]{display:none}
.btn--wide{width:100%}
/* `.btn--sm.btn--liquid` reassigns --lqx-fill to the smoked small pane, and
   at two classes it outranks the single-class `.btn--liquid-clear`. Without
   this the clear variant silently renders smoked at small size. */
.btn--sm.btn--liquid.btn--liquid-clear{--lqx-fill:var(--lq2-fill)}

/* ---------------------------------------------------------------- header */
/* A single solid pill floating clear of the page, with a lit top edge, a
   dimmer return shine along the bottom and a slow specular sweep. */
.hdr{
  position:fixed;top:0;left:0;right:0;z-index:60;
  display:flex;align-items:center;height:var(--hdr);
  transition:transform .4s var(--out);
}
.hdr.hide{transform:translateY(-118%)}
.hdr__in{
  position:relative;isolation:isolate;
  width:min(100% - 44px,var(--wrap));margin-inline:auto;
  height:60px;display:flex;align-items:center;gap:20px;
  padding-inline:16px 17px;border-radius:99px;
  border:1px solid var(--bar-edge);
  background-image:
    linear-gradient(102deg,transparent 40%,var(--bar-sweep) 48%,transparent 57%),
    var(--bar-fill);
  background-size:280% 100%,100% 100%;
  background-position:190% 0,0 0;
  box-shadow:var(--bar-shadow);
  animation:hdrSheen 9s var(--ease) infinite;
  transition:box-shadow .35s var(--ease),border-color .35s var(--ease);
}
/* The sweep parks off-canvas for most of the cycle, then crosses once. */
@keyframes hdrSheen{
  0%,68%{background-position:190% 0,0 0}
  100%  {background-position:-90% 0,0 0}
}
/* Lit top edge — brightest in the middle, gone at the caps. */
.hdr__in::before{
  content:"";position:absolute;z-index:-1;top:0;left:9%;right:9%;height:1px;
  background:linear-gradient(90deg,transparent,var(--bar-gloss),transparent);
  border-radius:2px;pointer-events:none;
}
/* Return shine, shorter and offset left, the way light actually falls. */
.hdr__in::after{
  content:"";position:absolute;z-index:-1;bottom:0;left:14%;right:38%;height:1px;
  background:linear-gradient(90deg,transparent,var(--bar-gloss-2),transparent);
  border-radius:2px;pointer-events:none;
}
.hdr.stuck .hdr__in{box-shadow:var(--bar-shadow-lg);border-color:var(--bar-edge-2)}

/* The lockup. Both halves sized up, and centred on the bar's axis rather than
   on their own text box: a serif with ascenders and descenders sits low inside
   its line box, so `align-items:center` alone leaves the wordmark reading a
   couple of pixels below the crest and below the nav links. Setting the line
   box to the crest's height and centring the glyphs inside it with
   flex+justify puts the cap-height on the same axis as everything else. */
.logo{display:flex;align-items:center;gap:14px;flex:0 0 auto}
.logo img{width:46px;height:46px;object-fit:contain}
.logo b{
  font-family:var(--display);font-size:1.52rem;font-weight:700;
  line-height:1;letter-spacing:-.005em;
  display:flex;align-items:center;height:46px;
  /* The lift that used to be here was measured off the text box, which counts
     the descender space under "Cambridge" as if it were ink. Against the cap
     block — the mass the eye actually centres on — it put the wordmark 2.4px
     high. Replaced with a measured 3px top pad, which lands the cap block's
     midpoint on the bar's own midpoint and on the crest's centre. */
  padding-top:3px;
}
.logo b i{font-style:italic;font-weight:500;color:var(--gold-text);margin-left:.3em}

/* Nav sits on the bar's centre axis rather than crowding the right cap: auto
   margins on both sides push it off the logo and off the end cluster equally,
   so it stays centred as either side changes width. */
.nav{display:flex;gap:2px;margin-inline:auto}
.nav a{
  position:relative;padding:9px 15px;border-radius:99px;font-size:.9rem;
  color:var(--text-2);transition:color .22s var(--ease),background .22s var(--ease);
}
.nav a:hover{color:var(--text-1);background:rgba(201,152,47,.1)}
/* Current section is marked in gold alone — no rule beneath it. On a centred
   row the underline reads as a stray tick; colour and weight carry it. */
.nav a.on{color:var(--gold-text);font-weight:600}

/* ---------------------------------------------------- header end cluster */
.hdr__end{display:flex;align-items:center;gap:13px;flex:0 0 auto}
.hdr__cta{display:flex;align-items:center;gap:10px;flex:0 0 auto}

/* Icon buttons: outline only, no fill, so they sit on the glass instead of
   stacking another slab on top of it. Squircles rather than circles — the
   soft-square reads as a control, the pill next to them as the action. */
.hdr__ic{display:flex;align-items:center;gap:8px}
.hdr__ic a{
  width:35px;height:35px;border-radius:11px;
  display:grid;place-items:center;
  border:1px solid var(--ctl-edge);color:var(--text-2);
  background:transparent;
  transition:color .22s var(--ease),border-color .22s var(--ease),
             background .22s var(--ease),transform .3s var(--spring);
}
.hdr__ic a svg{width:16px;height:16px;display:block}
.hdr__ic a:hover{
  color:var(--gold-text);border-color:var(--bar-edge-2);
  background:rgba(201,152,47,.1);transform:translateY(-2px);
}
/* Hairline between the icon set and the enrol pill. */
.hdr__sep{width:1px;height:22px;background:var(--line);flex:0 0 auto}

/* ------------------------------------------------- theme + sound controls */
/* Both controls are cut from one material — same height, same fill, same
   edge — so the pair reads as a single instrument, not two stray buttons. */
.tgl,.snd{
  height:50px;flex:0 0 auto;
  border:1px solid var(--ctl-edge);
  background:var(--ctl-fill);
  box-shadow:var(--ctl-shadow);
  color:var(--ctl-ink);
  transition:background .4s var(--ease),border-color .4s var(--ease),
             box-shadow .3s var(--ease),transform .3s var(--spring);
}
.tgl:hover,.snd:hover{transform:translateY(-2px);box-shadow:var(--ctl-shadow-hi)}

/* ---- theme pill: a real switch. The knob travels, the label follows ---- */
/* Geometry is deliberate: the widest label line measures ~38px, so the text
   block is 42px. An oversized block is what leaves a dead gap beside the
   knob. 16px of breathing room each end, 17px between label and knob. */
.tgl{
  position:relative;width:118px;border-radius:99px;
}
.tgl__t{
  position:absolute;top:50%;left:16px;width:42px;
  font-size:.62rem;font-weight:600;letter-spacing:.09em;line-height:1.15;
  text-transform:uppercase;text-align:left;white-space:nowrap;
  transform:translateY(-50%);
  /* Eased, not sprung — a spring overshoot would shove the label past
     the pill's cap mid-slide. */
  transition:transform .5s var(--out);
}
[data-theme="dark"] .tgl__t{text-align:right;transform:translateY(-50%) translateX(44px)}
.tgl__t span{display:block}
[data-theme="light"] .t-d,[data-theme="dark"] .t-l{display:none}
.tgl__k{
  position:absolute;top:5px;overflow:hidden;
  width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;background:var(--ctl-knob);
  box-shadow:var(--ctl-knob-shadow);
  transition:left .5s var(--out),background .4s var(--ease);
}
/* Light throws the knob to the sunny side; dark parks it back at the start. */
[data-theme="light"] .tgl__k{left:calc(100% - 43px)}
[data-theme="dark"]  .tgl__k{left:5px}
.tgl__k svg{width:19px;height:19px;position:absolute;
            transition:opacity .3s,transform .45s var(--spring)}
.ic-sun,.ic-moon{color:#2A1012}
[data-theme="light"] .ic-moon{opacity:0;transform:rotate(-70deg) scale(.5)}
[data-theme="dark"]  .ic-sun {opacity:0;transform:rotate(70deg) scale(.5)}
/* Turn the icon on hover, not the knob — rotating a circle changes nothing
   you can see and only inflates its paint box. */
[data-theme="light"] .tgl:hover .ic-sun {transform:rotate(35deg)}
[data-theme="dark"]  .tgl:hover .ic-moon{transform:rotate(-16deg)}

/* ---- sound: a squircle in the same material, sized to match the pill ---- */
.snd{
  width:50px;border-radius:17px;position:relative;
  display:grid;place-items:center;
}
.snd svg{width:20px;height:20px}
/* Muted reads as switched off: struck speaker, drained fill, no accent. */
.snd[aria-pressed="false"]{color:var(--text-3);background:var(--ctl-fill-off)}
.snd__x{opacity:0;transition:opacity .25s}
.snd[aria-pressed="false"] .snd__x{opacity:1}
/* Live: a small oxblood dot in the corner instead of a pulsing halo. */
.snd[aria-pressed="true"]::after{
  content:"";position:absolute;top:9px;right:9px;width:5px;height:5px;
  border-radius:50%;background:var(--ctl-live);
  animation:sndLive 2.4s var(--ease) infinite;
}
@keyframes sndLive{0%,100%{opacity:1}50%{opacity:.32}}

/* ------------------------------------------------ floating control dock */
/* Theme + sound sit at the bottom-left corner of every screen, out of the
   header's way and inside thumb reach on a phone. */
.dock{
  position:fixed;z-index:68;
  left:clamp(14px,2vw,26px);
  bottom:calc(clamp(14px,2vw,26px) + env(safe-area-inset-bottom));
  display:flex;align-items:center;gap:10px;
  opacity:0;transform:translateY(16px);
  transition:opacity .7s var(--out) .5s,transform .7s var(--out) .5s;
}
body.ready .dock{opacity:1;transform:none}

.burger{
  display:none;width:44px;height:44px;border-radius:12px;
  border:1px solid var(--line-2);flex-direction:column;
  justify-content:center;align-items:center;gap:5px;margin-left:auto;
}
.burger i{display:block;width:18px;height:1.6px;background:var(--text-1);border-radius:2px;
          transition:transform .32s var(--out),opacity .2s}
.burger.on i:nth-child(1){transform:translateY(6.6px) rotate(45deg)}
.burger.on i:nth-child(2){opacity:0}
.burger.on i:nth-child(3){transform:translateY(-6.6px) rotate(-45deg)}

/* ----------------------------------------------------------- mobile menu */
/* The drawer. Same material as the hero: a clear pane read from its bevel
   rather than from a fill. It carries more body than the SWK card does,
   though — this one has page copy running underneath it, and a card that
   disappears is charming where a nav that disappears is unusable. */
/* ------------------------------------------------------------------ scrim */
/* Full-screen blur behind the open drawer. The panel is translucent by
   design, so without this the page copy underneath read straight through the
   menu items. Blur plus a wash of the page colour pushes everything back a
   plane and leaves the drawer as the only thing in focus.

   This is the one backdrop-filter kept alive on phones: the ≤720px block
   further down strips the rest because they repaint on every scrolled frame,
   but the scrim only exists while the menu is open — and while it is open the
   page underneath is locked and static, so it composites once. */
.scrim{
  position:fixed;inset:0;z-index:58;
  background:var(--scrim);
  -webkit-backdrop-filter:blur(16px) saturate(.86);
  backdrop-filter:blur(16px) saturate(.86);
  opacity:0;pointer-events:none;
  transition:opacity .34s var(--out);
}
.scrim.on{opacity:1;pointer-events:auto}
/* No backdrop-filter support: lean harder on the wash so the text still goes. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .scrim{background:var(--scrim-solid)}
}
/* The floating theme and sound controls sit above the scrim's layer, so they
   would stay sharp over a blurred page. Take them out while the menu is up. */
body.nav-open .dock{opacity:0;transform:translateY(10px);pointer-events:none}
/* ---- yielding -----------------------------------------------------------
   The dock is fixed to the bottom-left, and on a single-column layout every
   full-width button in the page passes directly underneath it on the way up.
   The wizard's Continue was the worst of them — the one control the whole
   admissions section is built around, sitting behind a theme switch.

   Fading it to a ghost would be worse than leaving it: a half-visible control
   that still swallows taps. So it leaves entirely — down and out, pointer
   events off — for as long as something tappable is in its corner, and comes
   back the moment that thing scrolls clear. Nothing here is load-bearing;
   theme and sound can wait a few hundred pixels. */
/* `body.ready .dock` sets opacity:1 at (0,2,1) — two classes plus a type
   selector. A bare `.dock.is-yield` is (0,2,0) and loses to it, so the class
   toggled correctly and nothing moved. It has to be qualified the same way. */
body.ready .dock.is-yield,
.dock.is-yield{
  opacity:0;transform:translateY(22px) scale(.94);pointer-events:none;
}
/* Switched on by script once the entrance has finished, so getting out of the
   way is quick without costing the arrival its delay. */
.dock.is-live{transition:opacity .28s var(--ease),transform .32s var(--out)}
@media (prefers-reduced-motion:reduce){
  body.ready .dock.is-yield,
  .dock.is-yield{transform:none}
}
/* The header auto-hides on downward scroll. If it happened to be tucked away
   when the drawer opened, the close button went with it — so pin it for as
   long as the menu is up. It sits above the scrim, and should: it holds the
   only way out. */
body.nav-open .hdr{transform:none}
/* Freeze the page behind the drawer. */
body.nav-open{overflow:hidden}

.mob{
  position:fixed;top:calc(var(--hdr) + 8px);left:22px;right:22px;z-index:59;
  padding:15px;display:none;flex-direction:column;gap:2px;
  border-radius:var(--r);
  background:var(--mob-fill);
  -webkit-backdrop-filter:var(--mob-fx);
  backdrop-filter:var(--mob-fx);
  box-shadow:
    inset 0 2px 1px -1px var(--lq2-bevel),
    inset 0 -2px 1px -1px var(--lq2-bevel-2),
    inset 2px 0 2px -2px var(--lq2-bevel-2),
    inset -2px 0 2px -2px var(--lq2-bevel-2),
    inset 0 0 18px -6px var(--by-inner),
    inset 0 -18px 24px -22px var(--by-floor),
    0 1px 1px rgba(0,0,0,.06),
    0 18px 40px -18px var(--lq2-cast),
    0 44px 84px -40px var(--lq2-cast);
  opacity:0;transform:translateY(-14px) scale(.985);pointer-events:none;
  transition:opacity .32s var(--out),transform .32s var(--out);
}
.mob.on{opacity:1;transform:none;pointer-events:auto}

/* Each row is its own small pane. The gold wash that used to sit under a
   hovered row is gone — the filament is the whole gesture now, same as the
   buttons, so the drawer speaks the one language.

   Every selector here is a child combinator on purpose. The Enrol now CTA is
   also an <a> inside .mob, so a plain `.mob a` outranked the button's own
   rules and was overwriting four of them at once: the padding, the fill (to
   none, which is why it read as a bare outline), the justification, and via
   `.mob a span` the label itself, which was coming out in 10px mono at half
   opacity. The CTA lives in .mob__row, so `>` leaves it alone. */
.mob>a{
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;justify-content:space-between;align-items:center;
  padding:13px 15px;border-radius:12px;font-size:1rem;
  background:transparent;
  transition:background .26s var(--ease);
}
.mob>a:hover,.mob>a:active{background:var(--mob-item)}
.mob>a .btn__trace rect{rx:11.4px;ry:11.4px;stroke:var(--lq2-trace);stroke-width:1}
.mob>a:hover .btn__trace rect,
.mob>a:active .btn__trace rect,
.mob>a:focus-visible .btn__trace rect{stroke-dashoffset:0;opacity:1}
.mob>a span{font-family:var(--mono);font-size:.67rem;color:var(--text-3)}
.mob__sep{height:1px;background:var(--line);margin:11px 4px}
.mob__row{display:flex;gap:10px;padding:0 4px 4px;align-items:center}
/* Same outline treatment as the bar, sized up to a comfortable tap target. */
.mob__ic{display:flex;gap:10px;padding:12px 4px 4px}
.mob__ic a{
  width:44px;height:44px;border-radius:13px;display:grid;place-items:center;
  border:1px solid var(--ctl-edge);color:var(--text-2);
  transition:color .22s var(--ease),border-color .22s var(--ease),background .22s var(--ease);
}
.mob__ic a svg{width:19px;height:19px;display:block}
.mob__ic a:active,.mob__ic a:hover{
  color:var(--gold-text);border-color:var(--bar-edge-2);background:rgba(201,152,47,.1);
}

/* ------------------------------------------------------------- preloader */
/* The first thing anyone sees, so it carries the crest at a size worth
   looking at and reveals in stages rather than pulsing. A ring of light turns
   behind the crest while the bar fills; the whole group settles upward as it
   arrives instead of appearing all at once. */
#pre{
  position:fixed;inset:0;z-index:200;display:grid;place-items:center;
  background:var(--bg);
  transition:opacity .6s var(--ease),visibility .6s;
  animation:preFail .5s 5s forwards;
}
/* The same warm bloom the page carries, so the loader is not a flat plate. */
#pre::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(680px 480px at 50% 38%, var(--pl-bloom), transparent 68%),
    radial-gradient(520px 420px at 50% 96%, var(--pl-bloom-2), transparent 70%);
}
#pre.gone{opacity:0;visibility:hidden;pointer-events:none}
#pre.gone .pl{transform:scale(1.06);opacity:0}
.pl{transition:transform .62s var(--out),opacity .42s var(--ease)}
@keyframes preFail{to{opacity:0;visibility:hidden}}

.pl{position:relative;display:grid;justify-items:center;gap:30px}

/* Crest and its ring share a cell so the ring stays concentric at any size. */
.pl__seal{position:relative;display:grid;place-items:center;width:236px;height:236px}
.pl img{
  position:relative;z-index:2;
  width:188px;height:188px;object-fit:contain;
  filter:drop-shadow(0 14px 30px var(--pl-cast));
  /* Two animations on one property. The rise plays once and holds its end
     state; the breath starts a beat later and, being second in the list,
     takes over from there. Both are pure transform, so neither costs a
     layout — the crest is composited and nothing else on the screen is
     touched while it moves. */
  animation:plRise .8s var(--out) both,
            plBreathe 3.6s ease-in-out .9s infinite;
  will-change:transform;
}
/* A thin gold arc that turns once every two seconds — the only moving part. */
.pl__seal::before{
  content:"";position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(from 0deg,transparent 0 42%,var(--pl-arc) 78%,transparent 96%);
  -webkit-mask:radial-gradient(closest-side,transparent calc(100% - 2.5px),#000 calc(100% - 2.5px));
          mask:radial-gradient(closest-side,transparent calc(100% - 2.5px),#000 calc(100% - 2.5px));
  filter:drop-shadow(0 0 5px var(--pl-arc));
  animation:plSpin 2.2s cubic-bezier(.5,0,.5,1) infinite;
  will-change:transform;
}
/* A second arc, fainter and turning the other way at a different rate. Two
   rings at odds with each other never repeat visibly, which is what stops a
   spinner reading as a loop the moment it is watched for more than a second. */
.pl__seal .pl__arc2{
  position:absolute;inset:11px;border-radius:50%;pointer-events:none;
  background:conic-gradient(from 180deg,transparent 0 62%,var(--pl-arc) 88%,transparent 99%);
  -webkit-mask:radial-gradient(closest-side,transparent calc(100% - 1.5px),#000 calc(100% - 1.5px));
          mask:radial-gradient(closest-side,transparent calc(100% - 1.5px),#000 calc(100% - 1.5px));
  opacity:.42;
  animation:plSpinBack 3.4s linear infinite;
  will-change:transform;
}
@keyframes plSpinBack{to{transform:rotate(-1turn)}}
/* A static hairline underneath it, so the ring reads as a full circle. */
.pl__seal::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:1px solid var(--pl-ring);
}
@keyframes plSpin{to{transform:rotate(1turn)}}
@keyframes plRise{from{opacity:0;transform:translateY(14px) scale(.94)}}
/* A slow swell, small enough that it reads as the crest being lit rather than
   as an animation. Under three per cent — any more and it pulses. */
@keyframes plBreathe{
  0%,100%{transform:translateY(0) scale(1)}
  50%{transform:translateY(-2px) scale(1.026)}
}

.pl__t{
  width:248px;height:2px;background:var(--line-2);border-radius:2px;overflow:hidden;
  animation:plRise .9s .12s var(--out) both;
}
/* scaleX, not width. The bar is repainted every frame now, and animating
   width would put a layout pass in that loop; a transform is composited. No
   transition either — the easing lives in the script, and a transition on top
   of a per-frame update just adds lag. */
.pl__b{height:100%;width:100%;transform:scaleX(0);transform-origin:left center;
       background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));
       box-shadow:0 0 10px var(--pl-arc);will-change:transform}
.pl__x{font-family:var(--mono);font-size:.66rem;letter-spacing:.34em;
       text-transform:uppercase;color:var(--text-3);
       animation:plRise .9s .22s var(--out) both}

@media (max-width:560px){
  .pl{gap:24px}
  .pl__seal{width:184px;height:184px}
  .pl img{width:146px;height:146px}
  .pl__t{width:204px}
}
/* No spin, no rise — the crest and bar simply sit there. */
@media (prefers-reduced-motion:reduce){
  .pl img{animation:none}
  .pl__seal .pl__arc2{display:none}
  .pl{transition:none}
  #pre.gone .pl{transform:none}
  .pl__seal::before{display:none}
}

#prog{position:fixed;top:0;left:0;z-index:80;height:2.5px;width:0;
      background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));
      box-shadow:0 0 12px rgba(201,152,47,.7)}

/* ---------------------------------------------------------------- footer */
.foot{padding-block:clamp(50px,5.5vw,80px) 32px;border-top:1px solid var(--line)}
.foot__g{display:grid;grid-template-columns:1.7fr repeat(3,minmax(0,1fr));gap:clamp(28px,3.6vw,54px)}
.foot__lock{margin-bottom:16px}
.foot__blurb{max-width:34ch}
.foot__g h4{margin-bottom:17px}
.foot__g li{margin-bottom:10px}
.foot__g li a{font-size:.89rem;color:var(--text-2);transition:color .2s var(--ease)}
.foot__g li a:hover{color:var(--gold-text)}
/* ---- the SWK badge -----------------------------------------------------
   The same plate as the hero credit card, at footer scale. It used to be a
   dead box; it is now the way through to the SWK band, so it answers the
   cursor the way every other pressable thing on the page does — a small lift
   and the silver filament running the perimeter. The radius on the rect is
   the card's own minus the stroke, or the line rides half outside the
   corner. */
.foot__swk{position:relative;isolation:isolate;overflow:hidden;
           display:flex;align-items:center;gap:13px;margin-top:22px;padding:13px 15px;
           border:1px solid var(--line);border-radius:var(--r-sm);
           font-size:.79rem;color:var(--text-3);line-height:1.5;max-width:340px;
           transition:transform .34s var(--out),border-color .3s var(--ease),
                      box-shadow .44s var(--ease)}
/* The fill arrives as a layer that fades rather than as a background swap —
   a gradient cannot be transitioned, so swapping it would snap. */
.foot__swk::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:var(--by-fill);opacity:0;transition:opacity .3s var(--ease);
}
.foot__swk:hover,.foot__swk.is-hot{
  transform:translateY(-4px);
  border-color:var(--line-2);
  box-shadow:0 10px 26px -16px var(--lq2-cast),0 28px 58px -34px var(--lq2-cast);
}
.foot__swk:hover::before,.foot__swk.is-hot::before{opacity:1}
.foot__swk .btn__trace rect{rx:14.4px;ry:14.4px;stroke:var(--lq2-trace)}
.foot__swk:hover .btn__trace rect,
.foot__swk:focus-visible .btn__trace rect,
.foot__swk.is-hot .btn__trace rect{stroke-dashoffset:0;opacity:1}
.foot__swk>img,.foot__swk>span{position:relative;z-index:2}
.foot__swk img{width:38px;height:38px;object-fit:contain;flex:0 0 auto;
               transition:transform .4s var(--out)}
.foot__swk:hover img,.foot__swk.is-hot img{transform:scale(1.05)}
.foot__swk b{display:block;font-weight:500;font-size:.86rem;color:var(--text-1)}
/* Tagline set the way the cinematic card sets it — same badge, same voice. */
.foot__swk i{display:block;font-style:normal;font-family:var(--mono);font-size:.6rem;
             letter-spacing:.13em;text-transform:uppercase;color:var(--gold-text);margin-top:3px}
@media (prefers-reduced-motion:reduce){
  .foot__swk{transition:none}
  .foot__swk:hover,.foot__swk.is-hot{transform:none}
}
.foot__bar{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
           margin-top:clamp(32px,3.8vw,54px);padding-top:24px;border-top:1px solid var(--line);
           font-size:.78rem;color:var(--text-3)}
.foot__bar span:last-child{font-family:var(--mono);letter-spacing:.12em;color:var(--gold-text)}

/* ═════════════════════════════════════ NEXLYR ═════════════════════════════
   The studio credit. A mark, a name, one button — nothing more, because this
   is the client's site and not ours.

   It keeps its own black and its own cyan in both themes rather than taking
   the page's gold. A credit dressed in the host's palette reads as part of
   Cambridge Online, which is the one thing it must not do; sitting in its own
   colour is what makes it legible as somebody else's signature. */
.nxb{
  --nxb-a:#00D4FF;
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin-top:clamp(26px,3vw,36px);padding:9px 12px;border-radius:12px;
  background:linear-gradient(140deg,#04070c,#0A1420 60%,#04070c);
  border:1px solid rgba(0,212,255,.26);
  box-shadow:0 10px 30px rgba(4,7,12,.22);
}
.nxb__id{
  display:inline-flex;align-items:center;gap:8px;padding:6px 4px;
  min-height:40px;opacity:.92;transition:opacity .3s var(--ease);
}
.nxb__id:hover{opacity:1}
.nxb__mk{
  width:19px;height:19px;min-width:19px;flex:0 0 19px;
  display:grid;place-items:center;
  color:var(--nxb-a);transition:transform .8s var(--ease);
}
.nxb__mk svg{width:19px;height:19px;display:block}
.nxb__id:hover .nxb__mk{transform:rotate(180deg) scale(1.1)}
.nxb__nm{
  font-family:var(--mono);font-weight:700;font-size:.7rem;letter-spacing:.2em;
  background:linear-gradient(96deg,#00D4FF,#8FEBFF 55%,#00D4FF);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
}
.nxb__go{
  display:inline-flex;align-items:center;gap:7px;margin-left:auto;
  padding:9px 15px;min-height:40px;border-radius:9px;
  font-size:.74rem;font-weight:600;color:#04070c;
  background:linear-gradient(120deg,var(--nxb-a),#66E4FF);
  transition:transform .28s var(--out),box-shadow .28s var(--ease);
}
.nxb__go:hover{transform:translateY(-2px);box-shadow:0 10px 24px rgba(0,212,255,.34)}
.nxb__go svg{width:14px;height:14px;min-width:14px;flex:0 0 14px;display:block}
@media (max-width:520px){
  .nxb{padding:8px 10px;gap:8px}
  .nxb__nm{font-size:.66rem;letter-spacing:.16em}
  .nxb__go{padding:9px 13px;font-size:.72rem}
}
@media (prefers-reduced-motion:reduce){
  .nxb__id:hover .nxb__mk{transform:none}
  .nxb__go:hover{transform:none}
}

/* ----------------------------------------------------------- breakpoints */
@media (max-width:1120px){
  .nav{display:none}
  .burger{display:flex}
  .mob{display:flex}
  /* The moment the nav collapses, the bar is logo + burger and nothing else.
     Icons and the enrol pill both live in the drawer from here down — three
     35px squares plus a 44px burger plus the lockup overruns the pill well
     before phone widths and shoves the burger past the right cap. */
  .hdr__end{display:none}
}
@media (max-width:900px){
  .split{grid-template-columns:1fr}
  /* The brand block takes the full width and the three link groups share the
     row beneath it. Two columns here left each one about 340px wide for a
     four-word list, which read as three labels adrift in a lot of nothing. */
  .foot__g{grid-template-columns:repeat(3,minmax(0,1fr))}
  .foot__brand{grid-column:1/-1}
}
@media (max-width:720px){
  :root{--hdr:66px}
  body{font-size:15.5px}
  .wrap{width:calc(100% - 32px)}
  .hdr__in{width:calc(100% - 32px);gap:12px}
  /* The lockup yields before the burger does: without a shrink floor of zero
     a flex item refuses to go under its content width and pushes its
     neighbour out of the bar instead of narrowing itself. */
  .logo{min-width:0;flex:0 1 auto}
  .logo b{min-width:0;overflow:hidden;white-space:nowrap}
  .foot__bar{flex-direction:column;gap:8px}
  /* ---- footer, compacted --------------------------------------------
     Every measurement here was set for a four-column footer with room to
     breathe. Stacked on a phone the same spacing reads as dead air between
     short lists, so the whole block tightens: less padding top and bottom,
     smaller gaps between groups, and the lists closer set. */
  .foot{padding-block:38px 20px}
  .foot__g{gap:26px 22px}
  .foot__g h4{margin-bottom:10px}
  .foot__g li{margin-bottom:7px}
  .foot__g li a{font-size:.86rem}
  .foot__lock{margin-bottom:11px}
  .foot__blurb{max-width:none}
  .foot__swk{margin-top:15px;padding:11px 13px;gap:11px;max-width:none}
  .foot__swk img{width:33px;height:33px}
  .foot__bar{margin-top:22px;padding-top:16px}
}
@media (max-width:720px){
  /* The dock is fixed to the bottom-left and the closing bar is the last thing
     on the page, so without this the copyright line sits permanently behind a
     theme switch. The dock only yields for buttons; this is plain text, so the
     footer makes room for it instead. */
  .foot{padding-bottom:calc(74px + env(safe-area-inset-bottom))}
  .dock{bottom:calc(16px + env(safe-area-inset-bottom));left:14px;gap:8px}
  .tgl,.snd{height:46px}
  .snd{width:46px;border-radius:15px}
  .tgl{width:110px}
  .tgl__t{left:14px;width:40px;font-size:.58rem;letter-spacing:.07em}
  [data-theme="dark"] .tgl__t{transform:translateY(-50%) translateX(42px)}
  .tgl__k{top:5px;width:35px;height:35px}
  [data-theme="light"] .tgl__k{left:calc(100% - 40px)}
}
/* Three columns hold down to about 600px; below that a +92 number and
   "Gulistan-e-Johar" start wrapping mid-label, so the groups go two-up and
   Contact takes the full width with its own list running two-up beneath. */
@media (max-width:600px){
  .foot__g{grid-template-columns:1fr 1fr}
  .foot__col--contact{grid-column:1/-1}
  .foot__col--contact ul{display:grid;grid-template-columns:1fr 1fr;column-gap:22px}
}
/* Phone footer, about a third shorter: tighter type and spacing, Study and
   Campuses side by side, the SWK card and blurb set beside each other. */
@media (max-width:600px){
  .foot{padding-top:16px;padding-bottom:calc(64px + env(safe-area-inset-bottom))}
  .foot__g{gap:12px 18px}
  .foot__lock{margin-bottom:6px}
  .foot__lock img{width:34px;height:34px}
  .foot__blurb{font-size:.72rem;line-height:1.5;margin:0}
  .foot__swk{margin-top:10px;padding:8px 11px;gap:9px}
  .foot__swk img{width:28px;height:28px}
  .foot__g h4{margin-bottom:6px;font-size:.6rem}
  .foot__g li{margin-bottom:2px;line-height:1.3}
  .foot__g li a{font-size:.72rem}
  .foot__col--contact ul{column-gap:14px}
  .nxb{margin-top:12px;padding:5px 8px}
  .nxb__go{padding:7px 12px}
  .foot__bar{margin-top:12px;padding-top:10px;gap:4px;font-size:.64rem}
}
@media (max-width:430px){
  /* The footer used to collapse to one column here, which stacked twelve
     links end to end and made it 994px tall on an 850px phone — a full screen
     of scrolling past a sitemap to reach the copyright line. The two-column
     arrangement set at 600px carries all the way down instead. */
  .logo{gap:11px}
  .logo b{font-size:1.3rem;height:38px}
  .logo img{width:38px;height:38px}
}
@media (max-width:360px){
  /* The full wordmark still fits beside the menu button on the narrowest phones. */
  .logo b{font-size:1.02rem}
  .logo img{width:34px;height:34px}
  .logo{gap:9px}
  .hdr__in{padding-inline:13px 14px;gap:10px}
}

/* ------------------------------------------------------- phone rendering --
   Everything below is a paint-cost cut, not a look change. The hero idles at
   ~21fps on a throttled phone because the crest spins fourteen layers, each
   carrying a CSS blur, over a page stacked with backdrop-filters — and blur
   on a transformed layer is recomputed every single frame. On a 390px screen
   the deep slices are a couple of pixels of edge nobody can resolve, so they
   come out; the glow gradient is already soft enough to lose its blur; and
   the glass panes fall back to the solid fill they already ship for the
   reduced-transparency case. */
@media (max-width:1000px){
  /* Seven layers per face down to four. The silhouette is unchanged. */
  .medal__face img.sl3{display:none}
  .medal__face img.sl2:nth-of-type(3){display:none}
  .medal__glow{filter:none;opacity:.75}
  .medal__sh{filter:blur(5px)}
}
@media (max-width:720px){
  /* Backdrop blur is the single most expensive thing a phone GPU can be
     asked to do per scrolled frame, and there are seventeen of them. */
  .glass,.hdr__in,.mob,.snd,.btn--liquid{
    -webkit-backdrop-filter:none!important;backdrop-filter:none!important;
  }
  .glass{background:var(--panel-solid)}
}

/* -------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  .glass--sheen::after{display:none}
}

/* ==========================================================================
   CAMBRIDGE ONLINE — components
   Hero medallion · scroll cue · cinematic band · faculty cards · lecture page
   ========================================================================== */

/* ------------------------------------------------------------------ hero */
.hero{
  position:relative;min-height:100svh;display:grid;
  grid-template-columns:1.06fr .94fr;gap:clamp(30px,4vw,64px);
  align-items:center;padding-top:calc(var(--hdr) + clamp(28px,5vw,64px));
  padding-bottom:clamp(96px,10vw,132px);
}
.hero h1{margin-bottom:26px}

/* ------------------------------------------------- hero classroom backdrop */
/* Full-bleed behind the hero column, faded hard at the top and sides so the
   headline never has to fight it. Sits at z-index 0; hero content is lifted
   to 1 rather than the backdrop being pushed negative, which would drop it
   behind the page's own background layer. */
.hero__bg{
  position:absolute;inset:auto 50% 0 50%;
  width:100vw;height:min(92%,820px);
  transform:translateX(-50%);
  z-index:0;pointer-events:none;
  background-image:url("hero-crowd.webp");
  background-size:cover;background-position:center 58%;
  opacity:var(--hero-bg-op);
  /* Tone it into the palette per theme — the asset itself stays neutral. */
  filter:var(--hero-bg-filter);
  /* Dissolve on every edge so it never ends on a hard line. */
  -webkit-mask-image:
    linear-gradient(180deg,transparent 0%,#000 40%,#000 74%,transparent 100%),
    linear-gradient(90deg,transparent 0%,#000 18%,#000 82%,transparent 100%);
  mask-image:
    linear-gradient(180deg,transparent 0%,#000 40%,#000 74%,transparent 100%),
    linear-gradient(90deg,transparent 0%,#000 18%,#000 82%,transparent 100%);
  -webkit-mask-composite:source-in;mask-composite:intersect;
}
/* Lifts the hero's own content above the background layers. The cue is
   excluded: it is absolutely positioned to the hero's bottom centre, and
   `.hero .cue` at two classes was outranking `.cue`'s own `position:absolute`
   — which dropped it into the grid as a third column item, so it sat left of
   centre and floated in the flow instead of pinning to the bottom. */
.hero>div:not(.hero__bg),.hero .medal{position:relative;z-index:1}
.hero .lede{font-size:clamp(1.04rem,1.3vw,1.18rem);margin-bottom:34px}
/* Closer than the old pair sat. The panes throw their own halo, so the gap
   between them reads wider than it measures. */
.hero__cta{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:34px}
/* Below the wrap point they stack rather than sitting as two short stubs. */
@media (max-width:480px){
  .hero__cta{gap:12px}
  .hero__cta .btn--liquid{width:100%;--pad:16px 24px}
}
/* Transparent, so the classroom backdrop reads straight through it. Only a
   hairline holds the group together — no fill, no blur, no top highlight. */
/* The SWK card. It used to be a bare hairline sitting flat on the hero photo.
   Now it is a raised plate: the same clear material as the buttons, seated on
   a float shadow so it reads as lying above the page rather than drawn on it,
   and it climbs a little further on hover. The silver trace runs it too, so
   the whole hero column answers the cursor in one language. */
.hero__by{
  position:relative;
  display:inline-flex;align-items:center;gap:15px;
  padding:14px 24px 14px 16px;
  border-radius:18px;
  border:0;
  overflow:hidden;
  isolation:isolate;
  background:var(--by-fill);
  -webkit-backdrop-filter:var(--by-fx);
  backdrop-filter:var(--by-fx);
  box-shadow:
    inset 0 2px 1px -1px var(--lq2-bevel),
    inset 0 -2px 1px -1px var(--lq2-bevel-2),
    inset 2px 0 2px -2px var(--lq2-bevel-2),
    inset -2px 0 2px -2px var(--lq2-bevel-2),
    inset 0 0 14px -4px var(--by-inner),
    inset 0 -14px 20px -18px var(--by-floor),
    0 1px 1px rgba(0,0,0,.06),
    0 10px 26px -16px var(--lq2-cast),
    0 28px 58px -34px var(--lq2-cast);
  transform:translateY(0);
  transition:transform .34s var(--out),box-shadow .44s var(--ease);
}
.hero__by:hover{
  transform:translateY(-5px);
  box-shadow:
    inset 0 2px 1px -1px var(--lq2-bevel),
    inset 0 -2px 1px -1px var(--lq2-bevel-2),
    inset 2px 0 2px -2px var(--lq2-bevel-2),
    inset -2px 0 2px -2px var(--lq2-bevel-2),
    inset 0 0 14px -4px var(--by-inner),
    inset 0 -14px 20px -18px var(--by-floor),
    0 1px 1px rgba(0,0,0,.06),
    0 20px 42px -20px var(--lq2-cast),
    0 46px 84px -40px var(--lq2-cast);
}
.hero__by.is-hot{
  transform:translateY(-5px);
  box-shadow:
    inset 0 2px 1px -1px var(--lq2-bevel),
    inset 0 -2px 1px -1px var(--lq2-bevel-2),
    inset 2px 0 2px -2px var(--lq2-bevel-2),
    inset -2px 0 2px -2px var(--lq2-bevel-2),
    inset 0 0 14px -4px var(--by-inner),
    inset 0 -14px 20px -18px var(--by-floor),
    0 1px 1px rgba(0,0,0,.06),
    0 20px 42px -20px var(--lq2-cast),
    0 46px 84px -40px var(--lq2-cast);
}
/* Same filament as the buttons, on the card's own radius. */
.hero__by .btn__trace rect{rx:17.4px;ry:17.4px;stroke:var(--lq2-trace)}
.hero__by:hover .btn__trace rect{stroke-dashoffset:0;opacity:1}
.hero__by>img,.hero__by>div{position:relative;z-index:2}
.hero__by img{width:46px;height:46px;object-fit:contain;flex:0 0 auto}
.hero__by div{font-size:.78rem;color:var(--text-3);line-height:1.5}
.hero__by b{display:block;font-weight:500;font-size:.87rem;color:var(--text-1)}

/* Split headline — each line rises independently once the hero is ready. */
.rise{display:block;overflow:hidden}
.rise>span{
  display:block;transform:translateY(110%);
  transition:transform 1.05s var(--out);
}
.ready .rise>span{transform:none}
.ready .rise:nth-child(2)>span{transition-delay:.1s}
.fadeup{opacity:0;transform:translateY(24px);transition:opacity .9s var(--out) .35s,transform .9s var(--out) .35s}
.ready .fadeup{opacity:1;transform:none}
.fadeup--2{transition-delay:.48s}
.fadeup--3{transition-delay:.6s}

/* -------------------------------------------------- the rotating crest */
/* Two faces, never both at once. Each face carries one crisp plate plus a
   short blurred depth stack that only ever peeks at the silhouette edge.
   backface-visibility hands the render over at exactly 90° and 270°, so the
   face turning away leaves and the face turning toward you is already sharp
   — no two logos sitting on top of each other. */
.medal{
  --field:min(66vh,580px);
  position:relative;display:grid;place-items:center;
  min-height:var(--field);perspective:1500px;
}
.medal__stage{
  /* Sized off the field height so the full artwork always fits inside
     the rings — width follows from the artwork's own ratio. */
  position:relative;height:calc(var(--field) * .9);width:auto;max-width:94%;
  /* Full artwork ratio — crest AND wordmark, nothing clipped. */
  aspect-ratio:695/760;
  transform-style:preserve-3d;
  animation:medalSpin 28s linear infinite;
  /* No filter/opacity on this element ever — either would flatten the 3D. */
  will-change:transform;
  /* Grab to spin it. pan-y, not none: a vertical swipe still scrolls the
     page, so the crest never traps a thumb on mobile. */
  cursor:grab;touch-action:pan-y;-webkit-user-select:none;user-select:none;
}
.medal__stage.is-held{cursor:grabbing}
.medal__stage img{-webkit-user-drag:none;user-drag:none}
@keyframes medalSpin{
  from{transform:rotateX(8deg) rotateY(0deg)}
  to  {transform:rotateX(8deg) rotateY(360deg)}
}
/* The reverse side. Pre-flipped, so its plate reads the right way round. */
.medal__face{position:absolute;inset:0;transform-style:preserve-3d}
.medal__face--b{transform:rotateY(180deg)}
.medal__stage img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;object-position:center;
  /* The half-turn switch. Each copy disappears the instant it faces away. */
  -webkit-backface-visibility:hidden;backface-visibility:hidden;
}
/* Depth stack: blurred and darkened so it reads as a milled edge, never as
   a second copy of the artwork. Blur deepens with distance. */
.medal__stage img.sl{filter:blur(1.6px) brightness(.4) saturate(.6)}
.medal__stage img.sl2{filter:blur(3px) brightness(.32) saturate(.5)}
.medal__stage img.sl3{filter:blur(5px) brightness(.24) saturate(.45)}
[data-theme="light"] .medal__stage img.sl {filter:blur(1.6px) brightness(.66) saturate(.75)}
[data-theme="light"] .medal__stage img.sl2{filter:blur(3px) brightness(.58) saturate(.65)}
[data-theme="light"] .medal__stage img.sl3{filter:blur(5px) brightness(.5) saturate(.55)}
.medal__glow{
  position:absolute;width:76%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(201,152,47,.42),transparent 66%);
  filter:blur(34px);animation:glowPulse 6s var(--ease) infinite;
}
@keyframes glowPulse{0%,100%{opacity:.6;transform:scale(.94)}50%{opacity:1;transform:scale(1.04)}}
.medal__ring{
  position:absolute;border-radius:50%;pointer-events:none;
  border:1px solid rgba(201,152,47,.22);
}
.medal__ring--1{width:calc(var(--field) * .84);max-width:92%;aspect-ratio:1;border-top-color:rgba(201,152,47,.7);animation:spin 26s linear infinite}
.medal__ring--2{width:calc(var(--field) * .98);max-width:106%;aspect-ratio:1;border-bottom-color:rgba(201,152,47,.5);animation:spin 38s linear reverse infinite}
@keyframes spin{to{transform:rotate(360deg)}}
/* Ground shadow so it reads as floating rather than pasted on. */
.medal__sh{
  position:absolute;bottom:6%;width:44%;height:16px;border-radius:50%;
  background:radial-gradient(ellipse,rgba(42,6,8,.34),transparent 70%);
  filter:blur(9px);animation:shPulse 28s linear infinite;
}
@keyframes shPulse{0%,100%{transform:scaleX(1);opacity:.7}50%{transform:scaleX(.55);opacity:.4}}

/* ------------------------------------------------------------ scroll cue */
/* A shield with a descending chevron — the crest's own silhouette.
   Absolutely positioned so it is centred on the hero's full width, not on
   whichever grid column it would otherwise land in. */
.cue{
  position:absolute;left:0;right:0;bottom:clamp(22px,3.5vw,42px);
  margin-inline:auto;width:max-content;
  display:grid;justify-items:center;gap:11px;
  color:var(--text-3);z-index:3;
}
.cue__s{position:relative;width:28px;height:44px}
.cue__s svg{width:100%;height:100%;color:var(--gold);opacity:.65}
.cue__s i{
  position:absolute;left:50%;top:12px;width:7px;height:7px;
  border-right:1.6px solid var(--gold);border-bottom:1.6px solid var(--gold);
  transform:translateX(-50%) rotate(45deg);
  animation:cueDrop 1.9s var(--ease) infinite;
}
@keyframes cueDrop{
  0%{opacity:0;transform:translate(-50%,0) rotate(45deg)}
  35%{opacity:1}
  75%{opacity:0;transform:translate(-50%,13px) rotate(45deg)}
  100%{opacity:0}
}
.cue span{font-family:var(--mono);font-size:.6rem;letter-spacing:.32em;text-transform:uppercase}

/* --------------------------------------------------------------- marquee */
/* One flat oxblood band, gold type, thin gold rules top, bottom and between
   subjects. No gradient and no chips — a single colour carrying its
   opposite. Same in both themes; the point of the band is to interrupt. */
.mq{
  /* Full-bleed again, but three quarters of the old height: padding and
     type both scaled by .75 so the proportions hold (68.8px → 51.6px). */
  overflow:hidden;padding-block:12px;
  background:#5A1015;
  border-block:1px solid rgba(243,221,164,.42);
}
.mq__t{display:flex;align-items:center;width:max-content;animation:mqRun 42s linear infinite}
.mq:hover .mq__t{animation-play-state:paused}
@keyframes mqRun{to{transform:translateX(-50%)}}
.mq__t span{
  display:inline-flex;align-items:center;flex:0 0 auto;gap:28px;padding-inline:28px;
  font-family:var(--display);font-size:.99rem;font-style:italic;
  color:#F3DDA4;white-space:nowrap;
}
/* A hairline divider rather than a glyph — it stays crisp at any size. */
.mq__t span::after{
  content:"";width:1px;height:14px;flex:0 0 auto;
  background:rgba(243,221,164,.38);
}

/* ----------------------------------------------------------------- stats */
/* ═══════════════════════════════════ ABOUT: the clear-card wheel ══════════
   Six panes set on a shallow arc rather than a flat line. The one at front is
   square to the reader; its neighbours angle away and recede, so the row
   reads as a curved shelf continuing past both edges of the screen.

   The wheel steps rather than glides: it turns for half a second, holds long
   enough for the card to be read, then turns again. All positioning is done
   in JS because each card's transform depends on its distance from whichever
   one is currently at front, and that changes every step.

   The heading sits outside the wheel: it is the one thing that must not move
   while the eye is tracking panes past it. */
/* The two columns were bottom-aligned, which left the heading stranded low
   against a tall column of copy and a large hole above it. Aligned to the top
   instead, with the eyebrow's cap line meeting the first line of body copy —
   the eyebrow is smaller than the body text, so a straight top edge reads
   slightly high; the nudge puts the two on the same optical line. */
.abt__head{
  display:grid;grid-template-columns:1.02fr .98fr;
  gap:clamp(28px,4.4vw,72px);align-items:start;
  margin-bottom:clamp(34px,4vw,56px);
}
.abt__head > :first-child{padding-top:4px}
.abt__head h2{margin-bottom:0}
.abt__cta{display:flex;gap:14px;flex-wrap:wrap;margin-top:28px}

/* ------------------------------------------------------------- the stage */
/* Full-bleed: panes that stop at the content gutter look parked, panes that
   run off both edges read as an arc that continues past the frame. */
.awheel{
  --acw:360px;            /* pane width  */
  --ach:300px;            /* pane height */
  position:relative;width:100vw;margin-inline:calc(50% - 50vw);
  height:calc(var(--ach) + 46px);
  perspective:1500px;perspective-origin:50% 44%;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 13%,#000 87%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 13%,#000 87%,transparent);
}
.awheel__t{position:absolute;inset:0;transform-style:preserve-3d}

/* Pause affordance. Lives over the stage, not on it, so it does not travel. */
.awheel__hint{
  position:absolute;right:clamp(16px,4vw,44px);bottom:0;z-index:20;
  display:inline-flex;align-items:center;gap:7px;
  padding:6px 12px;border-radius:99px;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--text-3);background:var(--clear-fill);border:1px solid var(--clear-edge-2);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  transition:color .25s var(--ease),border-color .25s var(--ease);
  pointer-events:none;user-select:none;
}
.awheel__hint i{
  width:6px;height:6px;border-radius:50%;background:var(--gold);
  animation:awheelDot 2.2s var(--ease) infinite;
}
@keyframes awheelDot{0%,100%{opacity:1}50%{opacity:.25}}
.awheel.paused .awheel__hint{color:var(--gold-text);border-color:rgba(201,152,47,.36)}
.awheel.paused .awheel__hint i{animation:none;border-radius:1px;background:var(--gold-text)}

/* ------------------------------------------------------- the clear panes */
/* Uniform footprint, unlike the old flat row. On an arc, panes of differing
   widths make the curve read as a mistake rather than a curve. */
.aclear{
  position:absolute;top:0;left:50%;
  width:var(--acw);height:var(--ach);
  margin-left:calc(var(--acw) / -2);
  border-radius:26px;overflow:hidden;
  background:var(--clear-fill);
  border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow);
  transform-style:preserve-3d;backface-visibility:hidden;
  /* Same detent curve as the dial — quick out, settled in. */
  transition:transform .55s cubic-bezier(.6,0,.2,1),
             opacity .55s var(--ease),
             filter .55s var(--ease),
             box-shadow .45s var(--ease),
             border-color .35s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .aclear{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .aclear{background:var(--clear-solid)}
}
/* The specular rim. A single flat border reads as a sticker; real glass is
   bright where light enters at the top-left and nearly gone by the bottom
   right, so the rim is drawn as a gradient ring rather than a border colour. */
.aclear::before{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;padding:1px;
  background:linear-gradient(155deg,var(--clear-rim),var(--clear-rim-lo) 58%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
/* Light pooling in the top-left corner, the way it does on a curved edge. */
.aclear::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:var(--clear-tint);
}
/* Only the pane at front takes a hover — the angled ones are not the target. */
.aclear.is-front:hover{border-color:rgba(201,152,47,.34)}

/* ---- the filament ---- */
/* Same silver trace the buttons use, on the pane's own radius. Its rx has to
   be the border-radius minus the rect's 0.6px inset, or the line cuts the
   corner instead of hugging it. */
.aclear .btn__trace{
  z-index:3;
  filter:drop-shadow(0 0 1px var(--lq2-trace-glow));
}
.aclear .btn__trace rect{
  rx:25.4px;ry:25.4px;
  stroke:var(--lq2-trace);stroke-width:1.5;
  /* The panes sit under a perspective transform, so their whole layer is
     resampled — without this the hairline is scaled with it and frays. */
  vector-effect:non-scaling-stroke;
  shape-rendering:geometricPrecision;
}
/* Front pane on hover, or any pane lit by scroll position on touch. */
.aclear.is-front:hover .btn__trace rect,
.aclear.is-hot .btn__trace rect{stroke-dashoffset:0;opacity:.82}

.aclear__in{
  position:relative;z-index:1;height:100%;padding:28px 30px;
  display:flex;flex-direction:column;min-width:0;
}
.aclear__in > *{min-width:0}

/* -- a front door -- */
.aclear--wide .aclear__in{justify-content:flex-start}
.aclear--wide .card__n{
  display:inline-block;font-family:var(--mono);font-size:.63rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gold-text);margin-bottom:13px;
}
.aclear--wide h3{margin:0 0 11px}
.aclear--wide p{font-size:.89rem;line-height:1.6;color:var(--text-2);margin:0;overflow-wrap:anywhere}
.aclear--gilt{border-color:rgba(201,152,47,.3)}

/* -- a figure -- */
.aclear--stat .aclear__in{align-items:center;justify-content:center;text-align:center}
.aclear--stat b{
  display:block;font-family:var(--display);font-weight:500;line-height:1;
  font-size:clamp(3.2rem,5vw,4.2rem);margin-bottom:12px;
  background-image:linear-gradient(180deg,var(--gold-hi),var(--gold) 45%,var(--gold-lo));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.aclear--stat span{font-size:.82rem;color:var(--text-3);line-height:1.4}

@media (max-width:900px){
  .awheel{--acw:300px;--ach:272px;perspective:1100px}
  .aclear{border-radius:22px}
  .aclear .btn__trace rect{rx:21.4px;ry:21.4px}
  .aclear__in{padding:22px 22px}
  .aclear--wide p{font-size:.845rem;line-height:1.56}
}
@media (max-width:720px){
  .abt__head{grid-template-columns:1fr;gap:26px;align-items:start}
  /* Stacked, there is nothing to align to, so the optical nudge just adds a
     stray gap above the eyebrow. */
  .abt__head > :first-child{padding-top:0}
  .abt__cta{gap:12px;margin-top:24px}
  .awheel{--acw:266px;--ach:262px}
  .aclear__in{padding:20px 19px}
  .awheel__hint{right:14px;font-size:.55rem;padding:5px 10px}
}

/* No arc, no turning — the panes become an ordinary swipeable row. */
@media (prefers-reduced-motion:reduce){
  .awheel{
    height:auto;perspective:none;overflow-x:auto;
    display:flex;gap:14px;padding:4px 16px 18px;
    scroll-snap-type:x mandatory;overscroll-behavior-x:contain;
    -webkit-mask-image:none;mask-image:none;scrollbar-width:none;
  }
  .awheel::-webkit-scrollbar{display:none}
  .awheel__t{position:static;display:flex;gap:14px;transform-style:flat}
  .aclear{
    position:relative;left:auto;top:auto;margin-left:0;flex:0 0 auto;
    transform:none !important;opacity:1 !important;filter:none !important;
    scroll-snap-align:center;transition:none;
  }
  .awheel__hint{display:none}
}

/* ═══════════════════════════════════════ THE DIAL — what's included ═══════
   Eight stops, so the ring turns exactly 45 degrees per step. It turns in
   half a second, then holds long enough for the card to be read before
   turning again. Pressing the ring holds it where it stands.

   Only the ring rotates. The figure and the words sit still inside it —
   text carried through 360 degrees is text nobody reads. */
.dial{
  display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);
  gap:clamp(26px,4.4vw,60px);align-items:center;
}
.dial__l{display:flex;flex-direction:column;align-items:center;gap:16px}

.dial__ring{
  position:relative;width:min(292px,74vw);aspect-ratio:1;flex:0 0 auto;
  background:transparent;border:0;padding:0;cursor:pointer;border-radius:50%;
  display:grid;place-items:center;
}
.dial__ring:focus-visible{outline:2px solid var(--gold);outline-offset:6px}
.dial__svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.dial__trk{fill:none;stroke:var(--line);stroke-width:1.5}
.dial__arc{
  fill:none;stroke:var(--gold);stroke-width:2.5;stroke-linecap:round;
  transform:rotate(-90deg);transform-origin:110px 110px;
  transition:stroke-dashoffset .5s cubic-bezier(.6,0,.2,1);
}
/* Quick out, settled in — a detent, not a drift. */
.dial__spin{
  transform:rotate(var(--rot,0deg));transform-origin:110px 110px;
  transition:transform .5s cubic-bezier(.6,0,.2,1);
}
.dial__m{fill:var(--line-2);transition:fill .4s var(--ease),r .4s var(--spring)}
.dial__m.on{fill:var(--gold)}
.dial__sp{stroke:var(--line);stroke-width:1}

/* The fixed marker each stop turns up to meet. The ring of background colour
   around it is what makes it read as sitting on top of the track. */
.dial__pin{
  position:absolute;top:-4px;left:50%;translate:-50% 0;width:11px;height:11px;
  rotate:45deg;background:var(--gold);border-radius:2px;
  box-shadow:0 0 0 5px var(--bg);transition:background .3s var(--ease);
}
.dial.is-held .dial__pin{background:var(--gold-hi)}

.dial__mid{
  display:grid;place-items:center;text-align:center;padding:0 19%;
  transition:opacity .28s var(--ease),transform .38s var(--ease);
}
.dial.is-turning .dial__mid{opacity:0;transform:translateY(9px)}
.dial__n{
  font-family:var(--display);font-weight:500;line-height:1;letter-spacing:-.02em;
  font-size:clamp(2.7rem,7vw,3.6rem);
  background-image:linear-gradient(180deg,var(--gold-hi),var(--gold) 45%,var(--gold-lo));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.dial__k{
  font-family:var(--mono);font-size:.63rem;letter-spacing:.19em;line-height:1.5;
  text-transform:uppercase;color:var(--text-3);margin-top:11px;
}

.dial__hint{
  display:flex;align-items:center;gap:8px;margin:0;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--text-3);
}
.dial__hint::before{
  content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);
  transition:background .3s var(--ease),border-radius .3s var(--ease);
}
.dial.is-held .dial__hint::before{background:var(--text-3);border-radius:1px}

/* The panel is cut from the same clear glass as the About rail, so the two
   interactive blocks on the page are visibly the same material. */
.dial__panel{
  position:relative;isolation:isolate;border-radius:26px;overflow:hidden;
  padding:clamp(24px,3vw,34px);min-height:236px;
  display:flex;flex-direction:column;justify-content:center;
  background:var(--clear-fill);border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow);
  transition:opacity .28s var(--ease),transform .38s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .dial__panel{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .dial__panel{background:var(--clear-solid)}
}
.dial__panel::before{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;padding:1px;
  background:linear-gradient(155deg,var(--clear-rim),var(--clear-rim-lo) 58%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
.dial__panel::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:var(--clear-tint);
}
.dial.is-turning .dial__panel{opacity:0;transform:translateX(10px)}
/* A column flex would stretch the chip to full width. */
.dial__chip{
  align-self:flex-start;font-family:var(--mono);font-size:.63rem;
  letter-spacing:.17em;text-transform:uppercase;color:var(--gold-text);
  padding:5px 12px;border:1px solid rgba(201,152,47,.4);border-radius:99px;
}
.dial__panel h3{margin:15px 0 10px}
.dial__panel p{font-size:.93rem;line-height:1.62;color:var(--text-2);margin:0;max-width:58ch}

.dial__dots{display:flex;gap:7px;margin-top:20px;flex-wrap:wrap}
.dial__dots button{
  width:7px;height:7px;border-radius:50%;background:var(--line-2);
  border:0;padding:0;cursor:pointer;transition:.3s var(--ease);
}
.dial__dots button:hover{background:var(--gold-lo)}
.dial__dots button.on{background:var(--gold);width:22px;border-radius:99px}
.dial__dots button:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

@media (max-width:860px){
  .dial{grid-template-columns:1fr;gap:28px;justify-items:center}
  .dial__panel{min-height:0;text-align:center;align-items:center;width:100%}
  .dial__chip{align-self:center}
  .dial__dots{justify-content:center}
}
@media (prefers-reduced-motion:reduce){
  .dial__spin,.dial__arc,.dial__mid,.dial__panel{transition:none}
  .dial.is-turning .dial__mid,.dial.is-turning .dial__panel{opacity:1;transform:none}
}

/* ═══════════════════════════════════════════ THE STREAMS — raked deck ═════
   Three cards arrive gathered, then spread into a raked perspective — each
   angled and set back from the one before it. Pressing one pulls it forward,
   square to the reader, and the teachers who take that stream unfold inside.

   On a phone the rake is dropped and the cards swipe one at a time: a
   receding stack leaves the back card a few pixels wide and unreadable, and
   a showpiece that cannot be read is not a showpiece. */
.trio{position:relative;perspective:1500px;perspective-origin:50% 46%;padding:8px 0 4px}
/* The rake pushes the group visually left, so the rail is nudged back to sit
   centred under its heading. */
.trio__rail{
  position:relative;display:flex;justify-content:center;align-items:center;
  min-height:534px;transform-style:preserve-3d;
  padding-left:clamp(60px,13vw,190px);
}

.trio__c{
  position:relative;width:min(376px,76vw);flex:0 0 auto;
  border-radius:22px;overflow:hidden;cursor:pointer;text-align:left;
  /* Glassier than the rail cards: less fill, more blur. The card is meant to
     read as a pane you are looking through, so the page tint behind it stays
     visible and legibility comes from the blur, not from opacity. */
  background:
    linear-gradient(158deg,color-mix(in srgb,var(--clear-rim) 16%,transparent),transparent 46%),
    color-mix(in srgb,var(--clear-fill) 74%,transparent);
  border:1px solid var(--clear-edge);
  box-shadow:var(--clear-shadow),inset 0 1px 0 var(--clear-rim-lo);
  transform-style:preserve-3d;
  /* Gathered to begin with — the spread is what the reveal animates. */
  transform:translateX(calc(var(--i) * -46%)) rotateY(-24deg) scale(.9);
  opacity:0;
  transition:transform .9s cubic-bezier(.22,.9,.28,1),
             opacity .6s var(--ease),
             box-shadow .5s var(--ease),
             border-color .4s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .trio__c{
    -webkit-backdrop-filter:blur(34px) saturate(1.7);
    backdrop-filter:blur(34px) saturate(1.7);
  }
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .trio__c{background:var(--clear-solid)}
}
/* The spread, once the section is looked at. */
.trio.in .trio__c{
  opacity:1;
  transform:translateX(calc(var(--i) * -14%))
            translateZ(calc(var(--i) * -74px))
            rotateY(-24deg);
  transition-delay:calc(var(--i) * 130ms);
}
/* Once the spread has landed, drop the stagger — a press should answer on
   the frame it was made, not wait its turn in the queue. */
.trio.set .trio__c{transition-delay:0s !important}

/* The sheen running across each face, and the specular rim. */
.trio__glass{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(112deg,var(--sheen),transparent 42%,
             color-mix(in srgb,var(--sheen) 40%,transparent) 78%,transparent);
  opacity:.7;transition:opacity .5s var(--ease);
}
.trio__c::before{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;padding:1px;
  background:linear-gradient(155deg,var(--clear-rim),var(--clear-rim-lo) 58%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}

/* The stream emblem. It sits at z-index 0 — beneath the sheen layer and
   beneath the text — so it reads as etched into the pane rather than stuck on
   top of it, and it bleeds off the corner so the card looks like a crop of
   something larger. It also fills the gap the taller card opens up between
   the description and the chip row. */
.trio__mark{
  position:absolute;right:-16px;bottom:-16px;z-index:0;pointer-events:none;
  width:152px;height:152px;color:var(--gold);opacity:.17;
  transition:opacity .5s var(--ease),transform .7s var(--out);
}
.trio__mark svg{width:100%;height:100%;display:block}
.trio__c:hover .trio__mark{opacity:.28;transform:translate(-5px,-5px) rotate(-4deg)}
/* Out of the way once the teacher list is showing — it would otherwise sit
   directly behind the names. */
.trio__c.on .trio__mark{opacity:.07;transform:translate(6px,6px) scale(.94)}

/* ---- the filament on the stream cards ----
   The shared trace carries a 2.5px drop-shadow so it reads against a bright
   pane in light mode. On the dark card that halo is wider than the hairline
   it surrounds, and the soft edge is what makes the line look ragged. Tight
   glow, marginally heavier stroke, and geometric rendering instead.

   non-scaling-stroke matters here specifically: the open card sits at
   translateZ(90px) under a 1500px perspective, so its whole layer is
   magnified about 6%. Without this the 1.2px stroke is resampled up with it
   and frays. */
.trio .btn__trace{filter:drop-shadow(0 0 1px var(--lqx-trace-glow,var(--lq2-trace-glow)))}
.trio .btn__trace rect{
  stroke-width:1.5;
  vector-effect:non-scaling-stroke;
  shape-rendering:geometricPrecision;
}
/* Softer than the default silver — a full-strength hairline reads as a hard
   outline against the smoked pane rather than a lit edge. */
.trio .btn--liquid:hover .btn__trace rect,
.trio .btn--liquid.is-hot .btn__trace rect,
.trio .btn--liquid:focus-visible .btn__trace rect{opacity:.85}

.trio__in{
  position:relative;z-index:2;padding:24px 24px 24px;
  display:flex;flex-direction:column;min-height:483px;min-width:0;
}
/* A flex child refuses to go under its content width unless told to, which is
   how a long word or an unbreakable label pushes past the card edge. */
.trio__in > *{min-width:0}
.trio__t,.trio__d{overflow-wrap:anywhere}
/* The numeral used to be absolutely positioned at the top-right, which meant
   a long level chip ran straight underneath it. Chip and numeral now share a
   flex row: the chip can shrink, the numeral holds its size, and the two can
   never occupy the same pixels no matter how the copy changes. */
.trio__top{
  display:flex;align-items:flex-start;justify-content:space-between;
  gap:12px;margin-bottom:2px;
}
.trio__code{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--gold-text);border:1px solid rgba(201,152,47,.38);border-radius:99px;
  padding:6px 11px;flex:0 1 auto;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.trio__t{
  font-family:var(--display);font-weight:600;font-size:1.32rem;line-height:1.18;
  margin:15px 0 10px;letter-spacing:-.012em;
}
.trio__d{font-size:.87rem;line-height:1.58;color:var(--text-2);margin:0 0 16px;max-width:34ch}
/* A floor under the chip row so the description can never crowd it, and the
   unfolded list can never push it flush against the button above. */
.trio__chips{display:flex;gap:7px;flex-wrap:wrap;margin-top:auto;padding-top:14px}
.trio__chip{
  font-family:var(--mono);font-size:.58rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--text-3);border:1px solid var(--line-2);border-radius:99px;padding:5px 10px;
  white-space:nowrap;
}
.trio__chip--acc{color:var(--gold-text);border-color:rgba(201,152,47,.42)}
.trio__n{
  font-family:var(--display);font-weight:600;font-size:2.9rem;line-height:.86;
  color:color-mix(in srgb,var(--gold) 32%,transparent);
  flex:0 0 auto;pointer-events:none;
}

/* What unfolds when a card is chosen. */
.trio__more{
  max-height:0;overflow:hidden;opacity:0;
  transition:max-height .6s var(--ease),opacity .4s var(--ease);
}
.trio__list{display:grid;gap:0;margin:4px 0 14px;font-size:.8rem;min-width:0}
/* Originally one flex row of subject / name / levels. Three columns do not
   fit a 300px card: the level label is nowrap and cannot shrink, so as soon
   as "O Level & IGCSE · A Level" ran long the row overran the card and got
   clipped by its overflow. Each entry is now two stacked lines — name above,
   subject and levels below — which has no minimum width to overrun. */
.trio__list a{
  display:grid;gap:3px;padding:9px 0;min-width:0;color:var(--text-1);
  border-bottom:1px solid var(--line);transition:.2s var(--ease);
}
.trio__list a:last-child{border-bottom:0}
.trio__list a:hover{color:var(--gold-text)}
.trio__list em{
  font-style:normal;font-size:.85rem;line-height:1.3;
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.trio__meta{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 9px;min-width:0;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;
  line-height:1.35;
}
.trio__meta b{color:var(--gold-text);font-weight:500}
.trio__meta span{color:var(--text-3)}
/* The fold clips at the padding box, so a few pixels of bottom padding keep
   the button's trace glow from being sheared off by overflow:hidden. */
.trio__more{min-width:0;padding-bottom:4px}
.trio__more .btn{margin-bottom:2px}

/* ---- the chosen card ---- */
@media (min-width:901px){
  /* The rail is a flat plane at z=0 while cards 2 and 3 sit behind it at
     -74px and -148px. In a preserve-3d context that puts the parent's own box
     in FRONT of those cards, so it swallows every press meant for them and
     only the first card ever opens. Making the rail transparent to the
     pointer hands the press back to the card underneath. Desktop only: on a
     phone the rail is the scroll container and must keep receiving touches. */
  .trio,.trio__rail{pointer-events:none}
  .trio__c{pointer-events:auto}

  .trio.in .trio__c:hover{
    transform:translateX(calc(var(--i) * -14%))
              translateZ(calc(var(--i) * -74px + 40px))
              rotateY(-18deg);
    border-color:rgba(201,152,47,.45);
  }
  .trio.in .trio__c.on{
    transform:translateX(calc(var(--i) * -14%)) translateZ(90px) rotateY(0deg);
    border-color:rgba(201,152,47,.5);z-index:5;
    box-shadow:var(--clear-shadow-hi);
  }
  .trio.in .trio__c.on .trio__glass{opacity:.28}
  /* Headroom for seven teachers plus the button, even when a name wraps — a
     cap that fits exactly is a cap that clips. */
  .trio.in .trio__c.on .trio__more{max-height:460px;opacity:1}
  /* The min-height floor stays in place while open. Releasing it made the
     card collapse to its content, so a card with a short list got *smaller*
     on press — the open one should only ever grow. */
  /* Two columns once the card is open. Seven teachers stacked in one column
     is what made the card twice as tall as it was wide; in two it comes back
     to four rows and the card stays roughly square. */
  .trio.in .trio__c.on .trio__list{grid-template-columns:1fr 1fr;gap:0 18px}
  /* The others fall back so the chosen one is the only thing reading. */
  .trio.in.picked .trio__c:not(.on){opacity:.42;filter:saturate(.7)}
}

/* ---- phones: one card at a time, swiped ---- */
@media (max-width:900px){
  .trio{perspective:none;padding:4px 0}
  .trio__rail{
    display:flex;gap:12px;min-height:0;overflow-x:auto;
    scroll-snap-type:x mandatory;
    /* A horizontal swipe at the edge of the viewport otherwise triggers the
       browser's back gesture instead of moving the rail. */
    overscroll-behavior-x:contain;
    /* touch-action is left at auto on purpose: pan-x alone would let the rail
       swallow a vertical swipe and trap the thumb, so the page could not be
       scrolled while a finger was on a card. */
    cursor:grab;
    /* justify-content:center on an overflowing scroller splits the overflow
       across BOTH ends, parking the first card at a negative offsetLeft where
       scrollLeft can never reach it — the rail then refuses to swipe back to
       card one. Start-aligned, with the side padding doing the centring. */
    justify-content:flex-start;
    padding:14px max(12px,calc((100% - min(352px,90vw)) / 2 + 14px)) 20px;
    margin-inline:-16px;
    -webkit-overflow-scrolling:touch;scrollbar-width:none;
  }
  /* Snapping has to be off mid-drag, or every frame of a manual scrollLeft
     write gets yanked back to the nearest snap point. */
  .trio__rail.is-drag{scroll-snap-type:none;cursor:grabbing;scroll-behavior:auto}
  .trio__rail.is-drag .trio__c{cursor:grabbing}
  .trio__rail::-webkit-scrollbar{display:none}
  .trio__c{
    width:min(352px,90vw);scroll-snap-align:center;
    transform:translateY(16px);opacity:0;
    transition:transform .55s cubic-bezier(.22,.9,.28,1),opacity .5s var(--ease),
               box-shadow .45s var(--ease),border-color .35s var(--ease),filter .45s var(--ease);
  }
  .trio.in .trio__c{transform:none;opacity:1;transition-delay:calc(var(--i) * 90ms)}
  .trio__in{
    /* Roughly the desktop card's 376:483 proportion, so a phone card reads as
       the same object rather than a squashed version of it. Capped so it
       cannot outgrow a short viewport. */
    min-height:min(430px,116vw);padding:22px 20px 20px;
  }
  .trio__t{font-size:1.22rem;margin:14px 0 9px}
  .trio__d{font-size:.855rem;line-height:1.56;margin-bottom:14px}
  .trio__n{font-size:2.65rem}
  .trio__code{font-size:.58rem;letter-spacing:.11em;padding:6px 10px}
  .trio__mark{width:134px;height:134px;right:-14px;bottom:-14px}
  /* No perspective here, so the lift is scale and shadow rather than depth;
     the rail keeps snapping normally while a card is open. */
  .trio.in .trio__c.on{
    transform:translateY(-6px) scale(1.025);
    border-color:rgba(201,152,47,.5);z-index:5;box-shadow:var(--clear-shadow-hi);
  }
  .trio__c.on .trio__more{max-height:620px;opacity:1}
  .trio__c.on .trio__glass{opacity:.3}
  .trio.in.picked .trio__c:not(.on){opacity:.5;filter:saturate(.7);transform:scale(.965)}
  .trio__dots{display:flex;justify-content:center;gap:2px;margin-top:4px}
  /* The visible dot stays 6px; the tap target around it does not. */
  .trio__dots button{
    width:32px;height:32px;display:grid;place-items:center;
    border:0;padding:0;cursor:pointer;background:none;
  }
  .trio__dots button::after{
    content:"";display:block;width:6px;height:6px;border-radius:50%;
    background:var(--line-2);transition:.3s var(--ease);
  }
  .trio__dots button.on::after{background:var(--gold);width:18px;border-radius:99px}
  .trio__dots button:focus-visible{outline:2px solid var(--gold);outline-offset:-4px;border-radius:50%}
}
@media (min-width:901px){.trio__dots{display:none}}
/* Between the phone rail and a full desktop the three raked cards at 376px
   run wider than the container, so they narrow rather than clip. */
@media (min-width:901px) and (max-width:1180px){
  .trio__c{width:min(322px,32vw)}
  .trio__rail{padding-left:clamp(40px,9vw,120px)}
  .trio__in{padding:20px 20px 20px;min-height:459px}
  .trio.in .trio__c.on .trio__list{grid-template-columns:1fr;gap:0}
  .trio.in .trio__c.on .trio__more{max-height:560px}
}

@media (prefers-reduced-motion:reduce){
  .trio__c,.trio.in .trio__c{transition:none;opacity:1;transform:none}
  .trio.in .trio__c.on,.trio.in.picked .trio__c:not(.on){transform:none;transition:none}
}

.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:15px}
.stat{padding:30px 24px;text-align:center;position:relative;overflow:hidden}
.stat b{display:block;font-family:var(--display);font-weight:500;
        font-size:clamp(2.3rem,4vw,3.3rem);line-height:1;color:var(--gold-text);
        margin-bottom:9px;font-variant-numeric:tabular-nums}
.stat span{font-size:.79rem;color:var(--text-3)}

/* ----------------------------------------------------------------- cards */
.cards{--cw:258px;--cmax:420px;gap:17px}
.card{padding:clamp(24px,2.5vw,32px);transition:transform .38s var(--out),border-color .3s}
.card:hover{transform:translateY(-5px);border-color:rgba(201,152,47,.4)}
.card__n{display:inline-block;font-family:var(--mono);font-size:.63rem;letter-spacing:.2em;
         text-transform:uppercase;color:var(--gold-text);margin-bottom:15px}
.card h3{margin-bottom:11px}
.card p{font-size:.91rem;color:var(--text-2);margin:0}

/* ----------------------------------------------------------------- steps */
.steps{--cw:220px;--cmax:330px;gap:15px;counter-reset:s}
.step{
  position:relative;isolation:isolate;overflow:hidden;
  padding:26px 26px 26px;counter-increment:s;
  transition:transform .38s var(--out),border-color .3s;
}
.step:hover{transform:translateY(-5px);border-color:rgba(201,152,47,.36)}
/* The silver filament, same component as the buttons. The rect's rx is the
   card's own radius minus its 0.6px inset, or the line cuts the corner
   instead of following it. */
.step .btn__trace{z-index:2;filter:drop-shadow(0 0 1px var(--lq2-trace-glow))}
.step .btn__trace rect{
  rx:calc(var(--r-sm) - .6px);ry:calc(var(--r-sm) - .6px);
  stroke:var(--lq2-trace);stroke-width:1.5;
  vector-effect:non-scaling-stroke;shape-rendering:geometricPrecision;
}
.step:hover .btn__trace rect,.step.is-hot .btn__trace rect{stroke-dashoffset:0;opacity:.82}
/* The numeral is set into the card's top-right rather than printed above the
   heading. Two things make it read as cut in rather than laid on: the fill is
   barely there, and a one-pixel light edge sits directly beneath it, which is
   the shadow an engraved edge casts on the surface below it.

   ::after, not ::before. An element has one ::before, and .glass already owns
   it for the top hairline: its `inset:0 0 auto` includes left:0, which merged
   with a right:16px here to stretch the box and pin the numeral to the LEFT
   edge — and overriding its content:"" put the hairline out entirely.

   decimal-leading-zero rather than "0" + counter, which would print 011 at
   step eleven. */
.step::after{
  content:counter(s,decimal-leading-zero);
  position:absolute;top:2px;right:18px;left:auto;bottom:auto;z-index:0;
  pointer-events:none;
  font-family:var(--display);font-weight:600;font-size:3.5rem;line-height:1;
  color:var(--step-n);text-shadow:0 1px 0 var(--step-n-lip);
  transition:color .4s var(--ease);
}
.step:hover::after,.step.is-hot::after{color:var(--step-n-hi)}
/* Above the numeral, and clear of it. The filament is excluded: it is
   absolutely positioned to the card's edge, and this rule at equal
   specificity but later in the sheet would reset it to relative and drop it
   into the flow above the heading. */
.step > *:not(.btn__trace){position:relative;z-index:1}
.step h3{font-size:1.15rem;margin-bottom:10px;padding-right:52px}
.step p{font-size:.87rem;color:var(--text-2);margin:0}

/* ============================ FACULTY CARDS ============================ */
/* Rebuilt: subject-tinted crown, medallion portrait, and the demo lesson
   promoted to a footer rail so the card sells the lesson, not just the name. */
/* ─────────────────────────────────────── centred card rows ────────────────
   Every card row on the page uses this. Grid was the wrong tool for it: a
   grid centred with justify-content centres the whole track set, so a last
   row holding two of four items still sits hard left under the row above it —
   the tracks are fixed for the entire grid, not per row.

   Flex wrap solves each row independently, so an orphan row of two or three
   centres itself. The basis is the old minmax floor and the ceiling stops a
   single leftover card from stretching to the full width of the container. */
.row{display:flex;flex-wrap:wrap;justify-content:center}
.row > *{flex:1 1 var(--cw,300px);max-width:var(--cmax,400px);min-width:0}

.facgrid{--cw:300px;--cmax:376px;gap:20px}

/* ═══════════════════════════════════════════ FACULTY — the HUD frame ══════
   Chamfered corners, a grid mesh across the face, light blooming along the
   top and bottom edges, a hatch marker at one shoulder and a coded callout at
   the other. The subject sits on a separate angled plate below the frame.

   The border is drawn as two stacked clipped layers, not as a border: a
   clip-path cuts a real border off at the chamfer and leaves the diagonals
   bare. The outer box carries the edge colour, an inset pseudo-element carries
   the fill, and the 1.3px of outer box still showing between them IS the
   edge — which follows every angle exactly. */
.fac{
  --acc:var(--gold);
  /* One shape, reused by both layers and by the glow. Top-left and bottom-left
     are small chamfers; the bottom-right is the long diagonal. */
  --hud:polygon(
    20px 0, 100% 0,
    100% calc(100% - 34px), calc(100% - 34px) 100%,
    18px 100%, 0 calc(100% - 18px), 0 20px);
  position:relative;display:flex;flex-direction:column;text-align:left;
  width:100%;cursor:pointer;background:none;border:0;padding:0;
  transform-style:preserve-3d;
}
.fac__pane{
  position:relative;isolation:isolate;flex:1;
  display:flex;flex-direction:column;min-height:274px;
  clip-path:var(--hud);
  background:linear-gradient(160deg,
    var(--hud-edge-hi), var(--hud-edge) 38%, var(--hud-edge-lo));
  transition:transform .42s var(--out),filter .42s var(--ease);
}
/* The face. Inset by the width of the edge; the same polygon resolves against
   the smaller box, so the chamfers stay parallel. */
.fac__pane::before{
  content:"";position:absolute;inset:1.3px;z-index:0;clip-path:var(--hud);
  background:
    /* mesh */
    linear-gradient(var(--hud-grid) 1px,transparent 1px),
    linear-gradient(90deg,var(--hud-grid) 1px,transparent 1px),
    /* accent pooling in from the top-left */
    radial-gradient(150% 110% at 6% 0%,
      color-mix(in srgb,var(--acc) 22%,transparent),transparent 58%),
    var(--hud-fill);
  background-size:26px 26px,26px 26px,auto,auto;
}
/* Light blooming along the top and bottom edges — the strongest single cue in
   the reference, and the reason the frame reads as lit rather than drawn. */
.fac__pane::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:
    radial-gradient(58% 14px at 62% 0%,var(--hud-bloom),transparent 70%),
    radial-gradient(46% 12px at 32% 100%,var(--hud-bloom),transparent 70%);
  opacity:.85;transition:opacity .4s var(--ease);
}
.fac:hover .fac__pane,.fac.is-hot .fac__pane{
  transform:translateY(-5px);
  filter:drop-shadow(0 18px 30px rgba(0,0,0,.3))
         drop-shadow(0 0 14px color-mix(in srgb,var(--acc) 26%,transparent));
}
.fac:hover .fac__pane::after,.fac.is-hot .fac__pane::after{opacity:1}
.fac:focus-visible .fac__pane{outline:2px solid var(--gold);outline-offset:5px}

/* ---- shoulder marks ---- */
.fac__marks{
  position:relative;z-index:2;display:flex;align-items:flex-start;
  justify-content:space-between;gap:12px;padding:13px 15px 0 17px;
}
/* Hatch block, top-left. */
.fac__hatch{
  width:56px;height:11px;flex:0 0 auto;
  background:repeating-linear-gradient(115deg,
    var(--hud-mark) 0 2px,transparent 2px 6px);
}
/* Coded callout, top-right: label over two rules and a node. */
.fac__code{
  display:grid;justify-items:end;gap:3px;flex:0 0 auto;
  font-family:var(--mono);font-size:.53rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--hud-mark-hi);
}
/* Label and node share a row. Absolutely positioning the node over the corner
   put it on top of the label the moment a syllabus code ran long. */
.fac__code em{display:flex;align-items:center;gap:7px;font-style:normal}
.fac__code i{display:block;height:1.5px;background:var(--hud-mark);width:52px}
.fac__code i:last-of-type{width:30px}
.fac__node{
  width:7px;height:7px;border-radius:50%;flex:0 0 auto;
  border:1.4px solid var(--acc);background:var(--hud-fill);
  box-shadow:0 0 7px color-mix(in srgb,var(--acc) 70%,transparent);
}

/* ---- the subject glyph ----
   Sits in the empty right half of the panel, level with the medallion. z-index
   1 puts it above the mesh face (0) and below the body text (2), so the name
   and tag never have to compete with it — which is what separates an etched
   mark from an icon lying on top of the card.

   The band it occupies is narrow on purpose. A first pass put it at 31% down
   and up to 116px across, and the taller glyphs — the flask, the microscope —
   ran straight through the teacher's name into the level chips. It is anchored
   to the medallion row instead, and sized off the pane so it holds proportion
   when the cards narrow in the rail.

   Deliberately faint: it is there to give the eye something to land on in a
   corner that was bare mesh, not to be read. */
.fac__glyph{
  position:absolute;z-index:1;pointer-events:none;
  right:8%;top:13%;
  width:clamp(56px,29%,84px);height:auto;
  color:var(--acc);opacity:.14;
  transition:opacity .42s var(--ease),transform .5s var(--out);
  transform:rotate(-6deg);
}
.fac:hover .fac__glyph,.fac.is-hot .fac__glyph{
  opacity:.24;transform:rotate(-6deg) scale(1.05) translateY(-3px);
}
@media (prefers-reduced-motion:reduce){
  .fac__glyph{transition:none}
  .fac:hover .fac__glyph,.fac.is-hot .fac__glyph{transform:rotate(-6deg)}
}

/* ---- body ---- */
.fac__b{position:relative;z-index:2;padding:14px 20px 20px;
        display:flex;flex-direction:column;gap:7px;flex:1}
.fac__med{
  width:62px;height:62px;border-radius:50%;display:grid;place-items:center;
  margin-bottom:9px;
  background:var(--hud-fill);
  border:1.6px solid color-mix(in srgb,var(--acc) 70%,transparent);
  box-shadow:0 0 18px -4px color-mix(in srgb,var(--acc) 60%,transparent);
  font-family:var(--display);font-size:1.32rem;font-weight:600;color:var(--acc);
  transition:transform .45s var(--spring),box-shadow .4s var(--ease);
}
.fac:hover .fac__med,.fac.is-hot .fac__med{
  transform:scale(1.06);
  box-shadow:0 0 26px -2px color-mix(in srgb,var(--acc) 80%,transparent);
}
.fac__name{font-family:var(--display);font-size:1.34rem;font-weight:500;line-height:1.14;margin:0}
.fac__tag{font-size:.85rem;color:var(--text-2);margin:0;flex:1}
.fac__lv{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}
.fac__lv span{
  font-size:.64rem;padding:3px 9px;
  /* Clipped corners rather than pills — a rounded chip inside a chamfered
     frame is the one shape that breaks the language. */
  clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),calc(100% - 5px) 100%,0 100%,0 5px);
  color:var(--text-3);background:var(--hud-chip);
}
/* In the marks row, not floated over the body — pinned to the bottom-left it
   landed straight on top of the "Open details" line. */
.fac__star{
  align-self:center;flex:0 0 auto;
  font-family:var(--mono);font-size:.5rem;letter-spacing:.14em;text-transform:uppercase;
  padding:4px 9px;color:#2A1403;white-space:nowrap;
  clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),calc(100% - 5px) 100%,0 100%,0 5px);
  background:linear-gradient(135deg,var(--gold-hi),var(--gold-lo));
}
/* With three items the hatch is the one that yields. */
.fac__marks .fac__hatch{min-width:0}
.fac__more{
  display:flex;align-items:center;gap:8px;margin-top:12px;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--acc);opacity:.8;transition:opacity .3s var(--ease),gap .3s var(--out);
}
.fac:hover .fac__more,.fac.is-hot .fac__more{opacity:1;gap:12px}
.fac__more svg{width:12px;height:12px}

/* ---- the detached plate ---- */
/* Bottom-right, tucked under the frame's long diagonal — the reference puts
   its sub-panel exactly where the cut opens the space for it. */
.fac__plate{
  align-self:flex-end;margin:7px 0 0;
  display:inline-flex;align-items:center;gap:9px;
  padding:9px 17px 9px 14px;
  clip-path:polygon(13px 0,100% 0,100% calc(100% - 11px),calc(100% - 11px) 100%,0 100%,0 13px);
  font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--acc);
  background:linear-gradient(160deg,var(--hud-edge-hi),var(--hud-edge) 40%,var(--hud-edge-lo));
  position:relative;
  transition:transform .42s var(--out),filter .4s var(--ease);
}
.fac__plate::before{
  content:"";position:absolute;inset:1.3px;z-index:0;
  clip-path:polygon(13px 0,100% 0,100% calc(100% - 11px),calc(100% - 11px) 100%,0 100%,0 13px);
  background:var(--hud-fill);
}
.fac__plate i,.fac__plate span{position:relative;z-index:1}
.fac__plate i{width:6px;height:6px;border-radius:50%;background:var(--acc);flex:0 0 auto;
              box-shadow:0 0 8px color-mix(in srgb,var(--acc) 80%,transparent)}
/* Lags the frame slightly so the two read as separate objects. */
.fac:hover .fac__plate,.fac.is-hot .fac__plate{
  transform:translateY(-3px);transition-delay:.05s;
  filter:drop-shadow(0 0 10px color-mix(in srgb,var(--acc) 30%,transparent));
}

:root,[data-theme="light"]{
  --hud-fill:#FBF7EE;
  --hud-grid:rgba(90,50,20,.055);
  --hud-edge:rgba(90,16,21,.16);
  --hud-edge-hi:rgba(90,16,21,.34);
  --hud-edge-lo:rgba(90,16,21,.08);
  --hud-bloom:rgba(255,255,255,.95);
  --hud-mark:rgba(90,50,20,.28);
  --hud-mark-hi:rgba(90,50,20,.5);
  --hud-chip:rgba(90,50,20,.07);
}
[data-theme="dark"]{
  --hud-fill:#17090A;
  --hud-grid:rgba(226,148,152,.07);
  --hud-edge:rgba(226,148,152,.24);
  --hud-edge-hi:rgba(255,220,222,.62);
  --hud-edge-lo:rgba(226,148,152,.1);
  --hud-bloom:rgba(255,238,230,.55);
  --hud-mark:rgba(226,148,152,.38);
  --hud-mark-hi:rgba(255,214,216,.6);
  --hud-chip:rgba(226,148,152,.09);
}

@media (max-width:560px){
  .fac__pane{min-height:250px}
  .fac__b{padding:12px 17px 18px}
}
@media (prefers-reduced-motion:reduce){
  .fac__pane,.fac__plate,.fac__med{transition:none}
  .fac:hover .fac__pane,.fac:hover .fac__plate,.fac.is-hot .fac__pane{transform:none}
}

/* ═══════════════════════════════════════════ REVIEWS — the accordion ══════
   Panels sit collapsed to a spine with their name set vertically. One is open
   at a time and the open one steps along on its own.

   The width is animated with flex-grow rather than with `width`, so the whole
   row solves as one layout and the panels either side absorb the difference
   exactly. Animating width instead leaves the row's total off by a fraction
   each frame and the far edge jitters. */
.revs{
  display:flex;gap:10px;
  height:clamp(360px,44vw,470px);
  padding:2px;
}
.rev{
  position:relative;isolation:isolate;overflow:hidden;
  flex:1 1 0;min-width:0;border-radius:16px;cursor:pointer;
  border:1px solid var(--rev-edge);
  background:linear-gradient(165deg,var(--rev-1),var(--rev-2) 55%,var(--rev-3));
  color:var(--rev-ink);
  transition:flex-grow .9s cubic-bezier(.22,.9,.28,1),
             border-color .5s var(--ease),
             box-shadow .5s var(--ease);
}
.rev.on{
  /* Eight of these on a row: the open one takes roughly half and the seven
     spines share the rest. */
  flex-grow:9;
  border-color:color-mix(in srgb,var(--gold) 42%,transparent);
  box-shadow:0 26px 60px -28px rgba(0,0,0,.8);
}
/* Accent pooling into the open panel. */
.rev::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(120% 90% at 20% 100%,var(--rev-glow),transparent 62%);
  opacity:0;transition:opacity .8s var(--ease);
}
.rev.on::before{opacity:1}

/* ---- the spine ---- */
/* Kept in the flow of every panel, open or not, and faded out on the open one
   — removing it would change the panel's contents mid-transition and the text
   would jump as the width solved. */
.rev__spine{
  position:absolute;inset:0;z-index:2;
  display:flex;flex-direction:column;align-items:center;justify-content:space-between;
  padding:18px 0;
  transition:opacity .4s var(--ease);
}
.rev.on .rev__spine{opacity:0;pointer-events:none}
.rev__vert{
  writing-mode:vertical-rl;transform:rotate(180deg);
  font-size:.84rem;letter-spacing:.02em;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-height:78%;
  color:var(--rev-ink);
}
.rev__mark{
  width:26px;height:26px;flex:0 0 auto;display:grid;place-items:center;
  border-radius:8px;border:1px solid var(--rev-edge);
  font-family:var(--mono);font-size:.56rem;color:var(--rev-dim);
}

/* ---- the open body ---- */
.rev__body{
  position:absolute;inset:0;z-index:3;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:clamp(20px,2.4vw,30px);
  opacity:0;transform:translateY(12px);pointer-events:none;
  transition:opacity .5s var(--ease) .2s,transform .6s var(--out) .2s;
}
.rev.on .rev__body{opacity:1;transform:none;pointer-events:auto}
.rev__stars{
  display:flex;gap:3px;margin-bottom:14px;color:var(--gold);font-size:.9rem;
  letter-spacing:.1em;
}
.rev__q{
  font-family:var(--display);font-size:clamp(1.02rem,1.5vw,1.28rem);
  line-height:1.45;margin:0 0 18px;max-width:46ch;color:var(--rev-ink);
  /* Long quotes clamp instead of pushing the attribution off the panel. */
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:6;overflow:hidden;
}
.rev__who{display:flex;align-items:center;gap:12px;min-width:0}
.rev__ini{
  width:38px;height:38px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;
  font-family:var(--display);font-size:.9rem;font-weight:600;color:var(--gold-hi);
  background:rgba(201,152,47,.16);border:1px solid rgba(201,152,47,.34);
}
.rev__who div{min-width:0;display:grid;gap:2px}
.rev__who b{font-weight:400;font-size:.9rem;color:var(--rev-ink);
            overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rev__who small{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--rev-dim);
}

/* ---- the progress bar under the row ---- */
.revs__bar{
  display:flex;gap:6px;margin-top:16px;justify-content:center;
}
.revs__bar i{
  width:26px;height:3px;border-radius:2px;background:var(--line-2);
  overflow:hidden;position:relative;
}
.revs__bar i.on::after{
  content:"";position:absolute;inset:0;background:var(--gold);
  transform-origin:left;animation:revFill var(--rev-dwell,5.2s) linear forwards;
}
.revs.paused ~ .revs__bar i.on::after{animation-play-state:paused}
@keyframes revFill{from{transform:scaleX(0)}to{transform:scaleX(1)}}

:root,[data-theme="light"]{
  --rev-1:#2E2723;--rev-2:#241E1B;--rev-3:#191413;
  --rev-edge:rgba(243,234,220,.12);
  --rev-ink:#F2E9DB;--rev-dim:rgba(242,233,219,.5);
  --rev-glow:rgba(201,152,47,.2);
}
[data-theme="dark"]{
  --rev-1:#2A1214;--rev-2:#1D0C0E;--rev-3:#120608;
  --rev-edge:rgba(226,148,152,.16);
  --rev-ink:#F5EADF;--rev-dim:rgba(245,234,223,.5);
  --rev-glow:rgba(201,152,47,.22);
}

/* Below this an accordion cannot work: eight spines plus one open panel needs
   more width than a phone has, and the open panel ends up narrower than its
   own text. It becomes a swipeable row of whole cards instead. */
@media (max-width:860px){
  .revs{
    height:auto;overflow-x:auto;gap:12px;
    scroll-snap-type:x mandatory;overscroll-behavior-x:contain;
    padding:2px 16px 14px;margin-inline:-16px;scrollbar-width:none;
  }
  .revs::-webkit-scrollbar{display:none}
  .rev{
    flex:0 0 auto;width:min(310px,84vw);min-height:290px;scroll-snap-align:center;
    transition:border-color .4s var(--ease),box-shadow .4s var(--ease);
  }
  .rev.on{flex-grow:0}
  .rev__spine{display:none}
  .rev__body{
    position:relative;inset:auto;opacity:1;transform:none;pointer-events:auto;
    height:100%;transition:none;
  }
  .rev::before{opacity:1}
}
@media (prefers-reduced-motion:reduce){
  .rev,.rev__body,.rev__spine{transition:none}
  .revs__bar i.on::after{animation:none;transform:scaleX(1)}
}

/* ═══════════════════════════════════════ FACULTY — the detail panel ═══════
   A landscape two-column panel: the demo lesson on the left with a rail of
   the teacher's colleagues beside it, and everything else in a column on the
   right that ends in one full-width action.

   Dark in both themes. The poster is the subject of this panel and it is a
   lit object, so the surface around it has to recede — a cream panel in light
   mode would put the brightest thing on screen in the margins. */
.fpop{
  position:fixed;inset:0;z-index:120;display:none;
  align-items:center;justify-content:center;padding:clamp(14px,3.5vw,40px);
}
.fpop.on{display:flex}
.fpop__veil{
  position:absolute;inset:0;background:rgba(6,3,4,.68);
  -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
  opacity:0;transition:opacity .3s var(--ease);
}
.fpop.in .fpop__veil{opacity:1}

.fpop__box{
  --acc:var(--gold);
  --fp-ink:#F3EADC;
  --fp-dim:rgba(243,234,220,.56);
  --fp-faint:rgba(243,234,220,.34);
  --fp-line:rgba(243,234,220,.1);
  position:relative;isolation:isolate;
  width:min(940px,100%);max-height:min(88vh,660px);
  display:grid;grid-template-columns:1.06fr .94fr;
  border-radius:22px;overflow:hidden;color:var(--fp-ink);
  background:linear-gradient(150deg,#2E2724 0%,#241E1C 48%,#1A1513 100%);
  border:1px solid rgba(243,234,220,.1);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.9);
  opacity:0;transform:translateY(20px) scale(.975);
  transition:opacity .34s var(--ease),transform .44s var(--out);
}
.fpop.in .fpop__box{opacity:1;transform:none}
/* A pool of the teacher's own accent, bled in from the top-left. */
.fpop__box::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(680px 420px at 8% 0%,
    color-mix(in srgb,var(--acc) 20%,transparent),transparent 62%);
}

.fpop__x{
  position:absolute;top:14px;right:14px;z-index:8;
  width:34px;height:34px;border-radius:11px;display:grid;place-items:center;
  border:1px solid var(--fp-line);background:rgba(243,234,220,.06);
  color:var(--fp-dim);cursor:pointer;transition:.24s var(--ease);
}
.fpop__x:hover{color:var(--fp-ink);border-color:rgba(243,234,220,.3);background:rgba(243,234,220,.12)}
.fpop__x svg{width:14px;height:14px}

/* ---- left: the lesson ---- */
.fpop__left{
  position:relative;z-index:1;min-width:0;
  display:grid;grid-template-columns:64px 1fr;gap:14px;
  padding:22px 10px 22px 18px;align-content:center;
}
/* The colleague rail. Same subject, so switching between them is the one
   comparison a visitor on this panel is actually likely to make. */
.fpop__rail{display:flex;flex-direction:column;gap:9px;align-self:center}
.fpop__rail button{
  width:52px;height:52px;border-radius:14px;flex:0 0 auto;cursor:pointer;
  display:grid;place-items:center;
  font-family:var(--display);font-size:.92rem;font-weight:600;
  color:var(--fp-dim);background:rgba(243,234,220,.05);
  border:1px solid var(--fp-line);
  transition:.26s var(--ease);
}
.fpop__rail button:hover{color:var(--fp-ink);border-color:rgba(243,234,220,.3);transform:translateY(-2px)}
.fpop__rail button.on{
  color:var(--acc);border-color:color-mix(in srgb,var(--acc) 60%,transparent);
  background:color-mix(in srgb,var(--acc) 16%,transparent);
}
.fpop__rail span{
  width:52px;height:52px;border-radius:14px;display:grid;place-items:center;
  font-family:var(--mono);font-size:.62rem;color:var(--fp-faint);
  border:1px dashed var(--fp-line);
}

.fpop__stage{min-width:0;display:grid;gap:10px}
.fpop__poster{
  position:relative;border-radius:16px;overflow:hidden;display:block;width:100%;
  aspect-ratio:16/10;border:1px solid var(--fp-line);
  background:#181312;cursor:pointer;
}
.fpop__poster svg{position:absolute;inset:0;width:100%;height:100%}
.fpop__poster::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(60% 60% at 50% 50%,transparent,rgba(10,6,6,.5));
}
.fpop__go{
  position:absolute;left:50%;top:50%;translate:-50% -50%;z-index:2;
  width:58px;height:58px;border-radius:50%;display:grid;place-items:center;
  /* The one place the pane carries body: a fully translucent disc over a
     poster frame leaves the triangle sitting on whatever the artwork happens
     to be doing underneath it. */
  background:var(--sv-fill-solid);color:var(--sv-fg-solid);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  font-size:1rem;padding-left:3px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7),0 14px 30px -10px rgba(0,0,0,.7);
  transition:transform .35s var(--spring);
}
.fpop__poster:hover .fpop__go{transform:scale(1.1)}
.fpop__cap{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--fp-faint);text-align:center;margin:0;
}

/* ---- right: the detail column ---- */
.fpop__right{
  position:relative;z-index:1;min-width:0;overflow:auto;
  padding:26px 26px 26px 22px;
  display:flex;flex-direction:column;gap:0;
  border-left:1px solid var(--fp-line);
}
.fpop__sub{
  display:inline-flex;align-items:center;gap:8px;align-self:flex-start;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.17em;text-transform:uppercase;
  color:var(--acc);padding:5px 11px;border-radius:99px;
  border:1px solid color-mix(in srgb,var(--acc) 40%,transparent);
  background:color-mix(in srgb,var(--acc) 12%,transparent);
  margin-bottom:14px;
}
/* Name and headline figure on one line, the way the reference sets its title
   against the price. */
.fpop__head{display:flex;align-items:baseline;justify-content:space-between;gap:14px}
.fpop__head h3{font-size:1.5rem;margin:0;line-height:1.16;color:#FBF5EC}
.fpop__mins{
  flex:0 0 auto;font-family:var(--display);font-size:1.32rem;font-weight:600;
  color:var(--acc);letter-spacing:-.01em;
}
.fpop__tag{font-size:.9rem;line-height:1.55;color:var(--fp-dim);margin:9px 0 18px}

.fpop__lv{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:18px}
.fpop__lv span{
  font-size:.7rem;padding:6px 13px;border-radius:99px;
  color:var(--fp-dim);border:1px solid var(--fp-line);background:rgba(243,234,220,.04);
}
/* The summary block — the reference's balance / VAT / total stack. */
.fpop__sum{display:grid;gap:0;margin-bottom:20px}
.fpop__sum div{
  display:flex;justify-content:space-between;gap:14px;align-items:baseline;
  padding:10px 0;border-bottom:1px solid var(--fp-line);font-size:.84rem;
}
.fpop__sum div:last-child{border-bottom:0}
.fpop__sum dt{color:var(--fp-faint);font-family:var(--mono);font-size:.6rem;
              letter-spacing:.13em;text-transform:uppercase}
.fpop__sum dd{margin:0;color:var(--fp-ink);text-align:right;min-width:0;overflow-wrap:anywhere}
.fpop__sum div.tot dd{color:var(--acc);font-weight:500}

.fpop__hint{
  margin:16px 0 0;font-family:var(--mono);font-size:.57rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--fp-faint);line-height:1.7;
}
.fpop__act{
  margin-top:auto;display:flex;flex-direction:column;gap:9px;
}
/* The popup shell is dark in BOTH themes, so this one button cannot take the
   page's argent tokens — on the light theme those are dark ink on a pale
   pane, and the panel behind it is oxblood. It is pinned to the dark set. */
.fpop__buy{
  --sv-fill:linear-gradient(180deg,rgba(224,233,247,.15),rgba(190,203,223,.05));
  --sv-fg:#F0F5FD;
  --sv-fg-sh:0 1px 2px rgba(0,0,0,.6);
  --sv-rim-hi:rgba(255,255,255,.94);
  --sv-rim-mid:rgba(206,220,240,.7);
  --sv-rim:rgba(150,166,190,.46);
  --sv-bevel:rgba(230,239,251,.56);
  --sv-bevel-2:rgba(230,239,251,.26);
  --sv-inner:rgba(214,228,246,.18);
  --sv-floor:rgba(0,0,0,.42);
  --sv-cast:rgba(0,0,0,.66);
  --sv-halo:rgba(168,184,206,.32);
  --sv-fx:blur(20px) saturate(.55) brightness(.9);
  display:flex;align-items:center;justify-content:center;gap:9px;
  width:100%;padding:14px 20px;border-radius:12px;
  font-size:.92rem;color:var(--sv-fg);text-shadow:var(--sv-fg-sh);
  background:var(--sv-fill);
  -webkit-backdrop-filter:var(--sv-fx);backdrop-filter:var(--sv-fx);
  box-shadow:var(--sv-lift);
  transition:transform .26s var(--out),box-shadow .26s var(--ease),filter .26s var(--ease);
}
.fpop__buy:hover{transform:translateY(-2px);box-shadow:var(--sv-lift-hi)}
.fpop__alt{
  display:block;text-align:center;padding:11px;border-radius:12px;font-size:.85rem;
  color:var(--fp-dim);border:1px solid var(--fp-line);
  transition:.24s var(--ease);
}
.fpop__alt:hover{color:var(--fp-ink);border-color:rgba(243,234,220,.28)}

@media (max-width:820px){
  .fpop__box{
    grid-template-columns:1fr;max-height:90vh;
    /* Stacked, the panel scrolls as one rather than two independent columns —
       nested scrollers on a phone are a trap. */
    overflow:auto;
  }
  .fpop__left{padding:18px 16px 4px;grid-template-columns:56px 1fr;gap:12px}
  .fpop__rail button,.fpop__rail span{width:46px;height:46px;border-radius:12px;font-size:.82rem}
  .fpop__right{border-left:0;border-top:1px solid var(--fp-line);overflow:visible;padding:20px 18px 22px}
  .fpop__head h3{font-size:1.28rem}
}
@media (max-width:520px){
  .fpop{padding:0}
  .fpop__box{border-radius:0;width:100%;max-height:100vh;height:100%}
  .fpop__left{grid-template-columns:1fr}
  /* Below this the vertical rail costs more width than it earns; it goes
     horizontal under the poster instead. */
  .fpop__rail{flex-direction:row;order:2;overflow-x:auto;padding-bottom:2px}
  .fpop__stage{order:1}
}
@media (prefers-reduced-motion:reduce){
  .fpop__box,.fpop__veil{transition:none}
  .fpop__box{opacity:1;transform:none}
}

/* -------------------------------------------------------------- subjects */
.subs{--cw:232px;--cmax:340px;gap:13px}
.sub{display:flex;align-items:center;gap:15px;padding:19px 21px;
     transition:transform .32s var(--out),border-color .3s}
.sub:hover{transform:translateY(-3px);border-color:rgba(201,152,47,.4)}
.sub__dot{width:10px;height:10px;border-radius:50%;flex:0 0 auto}
.sub>span{display:grid;gap:2px;min-width:0}
.sub b{font-weight:400;font-size:.99rem}
.sub span span{font-size:.75rem;color:var(--text-3)}

/* ════════════════════════════════════════════ FINDER — the subject search ═
   This replaced a full section. The old "What you can study" block printed
   fifteen subject tiles in two route grids, and every tile did one thing:
   send you to a teacher. That is a search result wearing a card, so it is a
   search now — one lens-glass bar above the roster that filters it live, with
   the subject list moved into the bar's own dropdown where it costs no page
   height until asked for.

   The bar is CLEAR glass, not the frosted --panel used by the cards below it.
   That is deliberate: the control has to read as a layer floating above the
   roster rather than as the first card in it. */
.find{position:relative;z-index:6;margin-bottom:34px;display:grid;gap:18px}

/* ---- the bar ---- */
.find__bar{
  position:relative;display:flex;align-items:center;gap:14px;
  padding:0 8px 0 22px;min-height:66px;border-radius:999px;
  background:var(--clear-fill);border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow);
  transition:border-color .3s var(--ease),box-shadow .35s var(--ease),background .3s;
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .find__bar{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .find__bar{background:var(--clear-solid)}
}
/* Rim light along the top lip — the same one-pixel gradient every glass
   surface on this page carries, so the bar belongs to the set. */
.find__bar::before{
  content:"";position:absolute;inset:1px 1px auto;height:1px;border-radius:999px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--clear-rim) 26%,var(--clear-rim) 74%,transparent);
}
.find__bar:focus-within{
  border-color:rgba(201,152,47,.55);
  box-shadow:var(--clear-shadow-hi),0 0 0 3px rgba(201,152,47,.13);
}

.find__ico{width:19px;height:19px;flex:0 0 auto;color:var(--text-3);
  transition:color .3s}
.find__bar:focus-within .find__ico{color:var(--gold-text)}

.find__in{
  flex:1 1 auto;min-width:0;height:64px;border:0;background:transparent;
  color:var(--text-1);font-family:var(--sans);font-size:1.02rem;letter-spacing:.005em;
  outline:none;
}
.find__in::placeholder{color:var(--text-3)}
/* The UA search affordances fight the custom clear button for the same
   corner, so both are removed. */
.find__in::-webkit-search-cancel-button,
.find__in::-webkit-search-decoration{-webkit-appearance:none;appearance:none}

/* Live result count. Mono, because it is a readout, not a label. */
.find__n{
  flex:0 0 auto;font-family:var(--mono);font-size:.63rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--text-3);white-space:nowrap;
  padding-right:4px;
}
@media (max-width:640px){ .find__n{display:none} }

.find__x{
  flex:0 0 auto;display:grid;place-items:center;width:44px;height:44px;
  margin-right:5px;border-radius:50%;border:1px solid transparent;
  background:transparent;color:var(--text-2);cursor:pointer;
  opacity:0;visibility:hidden;transform:scale(.82);
  transition:opacity .22s,transform .28s var(--spring),visibility .22s,
             background .25s,color .25s,border-color .25s;
}
.find.has-q .find__x{opacity:1;visibility:visible;transform:none}
.find__x:hover{background:var(--wiz-input-on);border-color:var(--wiz-input-edge);color:var(--text-1)}
.find__x svg{width:16px;height:16px}

/* ---- suggestion sheet ----
   Absolutely positioned so opening it does not push the roster down the page;
   the list below is already reflowing on the same keystroke and two things
   moving at once reads as a glitch. */
.find__sugg{
  position:absolute;top:calc(100% + 10px);left:0;right:0;z-index:20;
  max-height:min(52vh,392px);overflow:auto;overscroll-behavior:contain;
  padding:8px;border-radius:var(--r);
  background:var(--clear-solid);border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow-hi);
  opacity:0;visibility:hidden;transform:translateY(-8px) scale(.985);
  transform-origin:50% 0;
  transition:opacity .24s var(--ease),transform .34s var(--out),visibility .24s;
  scrollbar-width:thin;scrollbar-color:var(--line-2) transparent;
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .find__sugg{background:var(--clear-fill);
    -webkit-backdrop-filter:blur(40px) saturate(1.4) brightness(.92);
    backdrop-filter:blur(40px) saturate(1.4) brightness(.92)}
}
.find__sugg::-webkit-scrollbar{width:8px}
.find__sugg::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:99px}
.find.is-open .find__sugg{opacity:1;visibility:visible;transform:none}

.find__grp{
  padding:12px 14px 7px;font-family:var(--mono);font-size:.6rem;
  letter-spacing:.2em;text-transform:uppercase;color:var(--text-3);
}
.find__opt{
  display:flex;align-items:center;gap:13px;width:100%;
  padding:12px 14px;border:0;border-radius:var(--r-xs);
  background:transparent;color:var(--text-1);text-align:left;cursor:pointer;
  font-family:var(--sans);transition:background .18s;
}
.find__opt:hover,.find__opt.on{background:var(--wiz-input-on)}
.find__opt.on{box-shadow:inset 2px 0 0 var(--gold)}
.find__opt i{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
.find__opt em{font-style:normal;font-size:.97rem;flex:1 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The matched run is lit rather than bolded — weight change reflows the row
   under the cursor as you type. */
.find__opt mark{background:transparent;color:var(--gold-text);font-weight:500}
.find__opt b{font-family:var(--mono);font-size:.62rem;letter-spacing:.12em;
  color:var(--text-3);font-weight:400;flex:0 0 auto}

/* ---- control deck: groups on the left, route + sort on the right ---- */
.find__deck{display:flex;flex-wrap:wrap;align-items:center;gap:14px 20px}
.find__deck .tabs{margin-bottom:0;padding:2px 2px 4px;flex:1 1 auto}
.find__rt{display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  margin-left:auto}

/* Segmented route switch. One track, three cells, gold cell for the live one. */
.find__seg{
  display:flex;padding:4px;border-radius:999px;
  background:var(--wiz-input);border:1px solid var(--wiz-input-edge);
}
.find__seg button{
  padding:9px 16px;border:0;border-radius:999px;background:transparent;
  color:var(--text-3);cursor:pointer;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.13em;
  text-transform:uppercase;white-space:nowrap;
  transition:color .25s,background .3s var(--ease),box-shadow .3s;
}
.find__seg button:hover{color:var(--text-1)}
.find__seg button.on{
  color:var(--sf-on-ink,#fff);background:var(--sf-on-face,var(--maroon));
  box-shadow:inset 0 1.5px 0 var(--sf-on-lip,rgba(255,255,255,.2)),
             0 6px 16px -8px rgba(0,0,0,.6);
}

.find__sortw{position:relative;display:flex;align-items:center}
.find__sort{
  appearance:none;-webkit-appearance:none;
  padding:11px 34px 11px 15px;border-radius:999px;
  background:var(--wiz-input);border:1px solid var(--wiz-input-edge);
  color:var(--text-2);cursor:pointer;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.11em;
  text-transform:uppercase;
  transition:border-color .25s,color .25s,background .25s;
}
.find__sort:hover{color:var(--text-1);background:var(--wiz-input-on)}
.find__sort:focus-visible{outline:none;border-color:var(--gold);color:var(--text-1)}
.find__sort option{background:var(--panel-solid);color:var(--text-1)}
.find__sortw svg{position:absolute;right:13px;width:11px;height:11px;
  pointer-events:none;color:var(--text-3)}

/* ---- active-filter chips ---- */
.find__chips{display:flex;flex-wrap:wrap;gap:9px}
.find__chips:empty{display:none}
.find__chip{
  display:inline-flex;align-items:center;gap:9px;padding:8px 10px 8px 14px;
  border-radius:999px;border:1px solid rgba(201,152,47,.34);
  background:rgba(201,152,47,.09);color:var(--text-1);cursor:pointer;
  font-family:var(--sans);font-size:.8rem;
  transition:border-color .25s,background .25s,transform .3s var(--out);
}
.find__chip:hover{border-color:rgba(201,152,47,.6);background:rgba(201,152,47,.15);
  transform:translateY(-1px)}
.find__chip svg{width:12px;height:12px;opacity:.66}
.find__chip.find__chip--all{border-style:dashed;background:transparent}

@media (max-width:760px){
  .find__bar{min-height:58px;padding-left:18px;gap:11px}
  .find__in{height:56px;font-size:.95rem}
  .find__rt{margin-left:0;width:100%}
  .find__seg{flex:1 1 auto;justify-content:center}
  .find__seg button{flex:1 1 0;padding:9px 10px;text-align:center}
  .find__sortw,.find__sort{width:100%}
}
@media (prefers-reduced-motion:reduce){
  .find__bar,.find__sugg,.find__x,.find__chip,.find__seg button{transition:none}
  .find__sugg{transform:none}
  .find__chip:hover{transform:none}
}

/* ═══════════════════════════════════════════════ FAQ — the stack ═════════
   A single narrow column, because an answer is prose and prose wants a
   measure. Two columns of accordions would put the reader's eye in two
   places while one panel is opening.

   The open panel is the only lit object in the stack: gold filament down its
   left edge, a warmer face, a raised cast. Everything else stays quiet. */
.faq{max-width:820px;margin-inline:auto}

/* ---- deck: search + categories ---- */
.faq__deck{display:grid;gap:16px;margin-bottom:clamp(26px,3vw,38px)}
.faq__find{
  position:relative;display:flex;align-items:center;gap:13px;
  padding:0 8px 0 20px;min-height:58px;border-radius:999px;
  background:var(--clear-fill);border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow);
  transition:border-color .3s var(--ease),box-shadow .35s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .faq__find{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .faq__find{background:var(--clear-solid)}
}
.faq__find::before{
  content:"";position:absolute;inset:1px 1px auto;height:1px;border-radius:999px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--clear-rim) 26%,var(--clear-rim) 74%,transparent);
}
.faq__find:focus-within{border-color:rgba(201,152,47,.55);
  box-shadow:var(--clear-shadow-hi),0 0 0 3px rgba(201,152,47,.13)}
.faq__find svg{width:17px;height:17px;flex:0 0 auto;color:var(--text-3)}
.faq__find input{
  flex:1 1 auto;min-width:0;height:56px;border:0;background:transparent;
  color:var(--text-1);font-family:var(--sans);font-size:.98rem;outline:none;
}
.faq__find input::placeholder{color:var(--text-3)}
.faq__find input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}

.faq__cats{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.faq__cat{
  padding:9px 16px;border-radius:999px;cursor:pointer;
  background:var(--wiz-input);border:1px solid var(--wiz-input-edge);
  color:var(--text-3);font-family:var(--mono);font-size:.62rem;
  letter-spacing:.13em;text-transform:uppercase;white-space:nowrap;
  transition:color .25s,background .3s var(--ease),border-color .25s,box-shadow .3s;
}
.faq__cat:hover{color:var(--text-1);background:var(--wiz-input-on)}
.faq__cat.on{
  color:var(--sf-on-ink,#fff);background:var(--sf-on-face,var(--maroon));
  border-color:var(--sf-on-edge,transparent);
  box-shadow:inset 0 1.5px 0 var(--sf-on-lip,rgba(255,255,255,.2)),
             0 8px 20px -10px rgba(0,0,0,.7);
}
.faq__all{
  margin-left:auto;padding:9px 4px;border:0;background:transparent;cursor:pointer;
  color:var(--text-3);font-family:var(--mono);font-size:.62rem;
  letter-spacing:.13em;text-transform:uppercase;
  border-bottom:1px solid transparent;transition:color .25s,border-color .25s;
}
.faq__all:hover{color:var(--gold-text);border-bottom-color:rgba(201,152,47,.5)}

/* ---- the stack ---- */
.faq__list{display:grid;gap:13px}

.faq__i{
  position:relative;border-radius:var(--r-sm);overflow:hidden;isolation:isolate;
  background:var(--panel);border:1px solid var(--edge);
  box-shadow:var(--shadow);
  transition:border-color .34s var(--ease),box-shadow .38s var(--ease),
             background .34s,transform .34s var(--out);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .faq__i{-webkit-backdrop-filter:var(--panel-fx);backdrop-filter:var(--panel-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .faq__i{background:var(--panel-solid)}
}
.faq__i::before{
  content:"";position:absolute;inset:0 0 auto;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--hi) 22%,var(--hi) 78%,transparent);
}
/* Gold filament down the open panel's left edge. Scales from the middle so
   it grows out of the row rather than dropping onto it. */
.faq__i::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;pointer-events:none;
  background:linear-gradient(180deg,transparent,var(--gold) 18%,var(--gold-hi) 50%,var(--gold) 82%,transparent);
  transform:scaleY(0);transform-origin:50% 50%;opacity:0;
  transition:transform .52s var(--out),opacity .32s;
}
.faq__i.on::after{transform:scaleY(1);opacity:1}
.faq__i:hover{border-color:rgba(201,152,47,.28)}
.faq__i.on{
  border-color:rgba(201,152,47,.42);
  box-shadow:var(--shadow-lg),0 0 0 1px rgba(201,152,47,.06);
}
.faq__i.is-hot{border-color:rgba(201,152,47,.28)}
.faq__i[hidden]{display:none}

.faq__q{
  display:flex;align-items:center;gap:16px;width:100%;
  padding:clamp(17px,2vw,21px) clamp(17px,2vw,23px);
  border:0;background:transparent;color:var(--text-1);cursor:pointer;
  text-align:left;font-family:var(--sans);
}
.faq__n{
  flex:0 0 auto;font-family:var(--mono);font-size:.63rem;letter-spacing:.12em;
  color:var(--text-3);padding-top:3px;transition:color .3s;
}
.faq__i.on .faq__n{color:var(--gold-text)}
.faq__t{
  flex:1 1 auto;min-width:0;font-size:1.02rem;line-height:1.45;font-weight:400;
  letter-spacing:.004em;transition:color .3s;
}
.faq__i.on .faq__t{color:var(--text-1)}
.faq__t mark{background:rgba(201,152,47,.2);color:var(--gold-text);
  border-radius:3px;padding:0 2px}

.faq__cv{
  flex:0 0 auto;display:grid;place-items:center;width:32px;height:32px;
  border-radius:50%;border:1px solid var(--line);color:var(--text-2);
  transition:transform .44s var(--out),border-color .3s,color .3s,background .3s;
}
.faq__cv svg{width:13px;height:13px}
.faq__q:hover .faq__cv{border-color:var(--line-2);color:var(--text-1)}
.faq__i.on .faq__cv{
  transform:rotate(180deg);color:var(--gold-text);
  border-color:rgba(201,152,47,.45);background:rgba(201,152,47,.1);
}

/* Height animation on grid-template-rows rather than max-height. A max-height
   guess either clips a long answer or coasts through empty space on a short
   one; 0fr → 1fr is the real content height either way. */
.faq__a{
  display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .46s var(--out),opacity .3s var(--ease);
  opacity:0;
}
.faq__i.on .faq__a{grid-template-rows:1fr;opacity:1}
.faq__a > div{overflow:hidden;min-height:0}
.faq__ai{
  padding:0 clamp(17px,2vw,23px) clamp(19px,2.2vw,23px) calc(clamp(17px,2vw,23px) + 34px);
}
.faq__ai p{color:var(--text-2);font-size:.94rem;line-height:1.72;max-width:62ch}
.faq__ai p + p{margin-top:11px}
.faq__ai a{color:var(--gold-text);border-bottom:1px solid rgba(201,152,47,.36);
  transition:border-color .25s}
.faq__ai a:hover{border-bottom-color:var(--gold)}

.faq__foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  margin-top:15px;padding-top:14px;border-top:1px solid var(--line)}
.faq__tag{
  padding:5px 11px;border-radius:99px;border:1px solid var(--line);
  font-family:var(--mono);font-size:.58rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-3);
}
.faq__cp{
  margin-left:auto;display:inline-flex;align-items:center;gap:7px;
  padding:5px 4px;border:0;background:transparent;cursor:pointer;
  color:var(--text-3);font-family:var(--mono);font-size:.58rem;
  letter-spacing:.14em;text-transform:uppercase;transition:color .25s;
}
.faq__cp:hover{color:var(--gold-text)}
.faq__cp svg{width:12px;height:12px}

.faq__none{
  padding:34px 22px;text-align:center;color:var(--text-3);
  border:1px dashed var(--line-2);border-radius:var(--r-sm);
}

/* ---- closing card ---- */
.faq__ask{
  display:flex;flex-wrap:wrap;align-items:center;gap:18px;
  margin-top:clamp(24px,3vw,34px);padding:clamp(22px,2.6vw,28px);
  border-radius:var(--r);
  background:var(--clear-fill);border:1px solid rgba(201,152,47,.26);
  box-shadow:var(--clear-shadow);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .faq__ask{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
.faq__ask div{flex:1 1 280px;min-width:0}
.faq__ask h4{margin-bottom:5px}
.faq__ask p{color:var(--text-3);font-size:.88rem;line-height:1.6}

@media (max-width:640px){
  .faq__q{gap:12px;padding-left:16px;padding-right:16px}
  .faq__n{display:none}
  .faq__ai{padding-left:16px;padding-right:16px}
  .faq__all{margin-left:0}
}
@media (prefers-reduced-motion:reduce){
  .faq__i,.faq__a,.faq__cv,.faq__i::after,.faq__cat,.faq__find{transition:none}
  .faq__i::after{transform:scaleY(1)}
}

/* ------------------------------------------------------------------ tabs */
/* ══════════════════════════════════════ ADMISSIONS — the road ═════════════
   The section sits on a road seen from above. It is drawn, not photographed:
   a strip of asphalt, a dashed centre line, and a coach that runs
   the lane. Everything is tinted toward the page rather than laid over it —
   a true asphalt grey would drop a slab into the middle of a cream page.

   Two coaches, deliberately. One runs the far lane behind the panels as
   ambient traffic. The other only appears once the enquiry has actually been
   sent, and it runs in FRONT of the form — the reward for finishing, not
   decoration. A coach rather than the freight lorry that used to be here: the
   thing this section moves is students, not cargo. */
#contact{position:relative;isolation:isolate}
/* Lifts the section's real content above the road. The road and the haul coach
   are excluded by name: an id selector outranks their own class rules, so
   without the :not() this would reset both to position:relative and z-index:1
   — dropping the backdrop into the flow and pinning the coach behind the form
   it is supposed to drive over. */
#contact > *:not(.road):not(.bus){position:relative;z-index:1}

.road{
  position:absolute;top:0;bottom:0;left:50%;translate:-50% 0;
  width:100vw;z-index:0;overflow:hidden;pointer-events:none;
  /* Fades into the page at both ends so the strip has no hard edge. */
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 12%,#000 84%,transparent);
  mask-image:linear-gradient(180deg,transparent,#000 12%,#000 84%,transparent);
}
/* The carriageway. Warm dark rather than neutral grey — it has to read as the
   same world as the rest of the page. */
.road__deck{
  position:absolute;left:0;right:0;top:var(--lane-top,63%);height:var(--lane-h,132px);
  background:
    linear-gradient(180deg,var(--road-edge),transparent 8%,transparent 92%,var(--road-edge)),
    linear-gradient(180deg,var(--road-1),var(--road-2) 50%,var(--road-1));
  opacity:var(--road-a,.5);
}
/* Verge lines, solid, one at each shoulder. */
.road__deck::before,.road__deck::after{
  content:"";position:absolute;left:0;right:0;height:1.5px;background:var(--road-paint-dim);
}
.road__deck::before{top:14px}
.road__deck::after{bottom:14px}

/* The dashed centre line. It scrolls, which is what sells the road as moving
   rather than as a static stripe with a truck sliding along it. */
.road__line{
  position:absolute;left:-20%;right:-20%;top:calc(var(--lane-top,63%) + var(--lane-h,132px) / 2);
  height:3px;margin-top:-1.5px;
  background:repeating-linear-gradient(90deg,
    var(--road-paint) 0 46px,transparent 46px 104px);
  opacity:var(--road-a,.5);
  animation:roadRun 2.6s linear infinite;
}
@keyframes roadRun{to{transform:translateX(-104px)}}

/* Aura. Two slow pools of colour drifting behind the panels — glass has to
   have something to refract or it is just a grey rectangle with a border.
   Large, heavily blurred and low contrast, so they read as light in the room
   rather than as shapes on the page. */
.road__aura{position:absolute;inset:-15%;pointer-events:none;opacity:var(--aura-a,.5)}
.road__aura i{
  position:absolute;display:block;border-radius:50%;filter:blur(70px);
  animation:auraDrift 26s var(--ease) infinite alternate;
}
.road__aura i:nth-child(1){
  width:46%;height:58%;left:2%;top:4%;
  background:radial-gradient(closest-side,var(--aura-1),transparent 72%);
}
.road__aura i:nth-child(2){
  width:52%;height:62%;right:0%;top:18%;
  background:radial-gradient(closest-side,var(--aura-2),transparent 72%);
  animation-duration:34s;animation-direction:alternate-reverse;
}
@keyframes auraDrift{
  from{transform:translate3d(0,0,0) scale(1)}
  to{transform:translate3d(6%,-5%,0) scale(1.14)}
}
@media (prefers-reduced-motion:reduce){.road__aura i{animation:none}}

/* Grain, so the deck is not a flat fill. */
.road__grit{
  position:absolute;left:0;right:0;top:var(--lane-top,63%);height:var(--lane-h,132px);
  opacity:.5;mix-blend-mode:overlay;
  background-image:radial-gradient(circle at 1px 1px,var(--road-grit) 1px,transparent 0);
  background-size:7px 7px;
}

/* ---- the coaches ---- */
.bus{position:absolute;pointer-events:none;will-change:transform}
.bus svg{display:block;width:100%;height:auto}

/* Ambient: far lane, behind everything, running continuously. */
.bus--far{
  top:calc(var(--lane-top,63%) + 6px);
  width:250px;opacity:var(--bus-far-a,.42);
  animation:busFar 19s linear infinite;
}
@keyframes busFar{
  from{transform:translateX(-280px)}
  to{transform:translateX(calc(100vw + 40px))}
}

/* The haul: sits above the form, parked off-screen until it is earned. */
.bus--haul{
  top:var(--haul-top,32%);
  width:clamp(230px,26vw,330px);
  z-index:6;opacity:0;
  transform:translateX(-40vw);
  filter:drop-shadow(0 22px 30px rgba(40,18,8,.4));
}
/* One pass, left to right. The fade sits inside the keyframes rather than on
   a transition so the coach cannot be caught half-visible mid-run. */
#contact.is-hauling .bus--haul{animation:busHaul 3.4s cubic-bezier(.4,0,.35,1) forwards}
@keyframes busHaul{
  0%{transform:translateX(-40vw);opacity:0}
  9%{opacity:1}
  88%{opacity:1}
  100%{transform:translateX(115vw);opacity:0}
}

/* Colours. Two sets, because a road is a dark object and the page is not
   always light. */
:root,[data-theme="light"]{
  --road-1:#3A2A22;
  --road-2:#4A382D;
  --road-edge:rgba(246,241,230,.9);
  --road-paint:rgba(255,244,214,.62);
  --road-paint-dim:rgba(255,244,214,.22);
  --road-grit:rgba(255,240,220,.14);
  --road-a:.22;
  --aura-1:rgba(201,152,47,.4);
  --aura-2:rgba(150,60,52,.26);
  --aura-a:.55;
  --bus-body:#FBF7EE;
  --bus-edge:#C9BFA9;
  --bus-band:#C9982F;
  --bus-glass:#3A2A22;
  --bus-sheen:#FFFFFF;
  --bus-blind:rgba(58,42,34,.5);
  --bus-tyre:#241512;
  --bus-hub:#8E8272;
  --bus-shade:#4A2A18;
}
[data-theme="dark"]{
  --road-1:#140A0B;
  --road-2:#1E1011;
  --road-edge:rgba(12,3,4,.9);
  --road-paint:rgba(255,236,190,.5);
  --road-paint-dim:rgba(255,236,190,.16);
  --road-grit:rgba(255,235,205,.1);
  --road-a:.5;
  --aura-1:rgba(201,152,47,.3);
  --aura-2:rgba(168,36,44,.3);
  --aura-a:.8;
  --bus-body:#EFE6D6;
  --bus-edge:#8E8272;
  --bus-band:#C9982F;
  --bus-glass:#160809;
  --bus-sheen:#FFF3D2;
  --bus-blind:rgba(10,4,5,.55);
  --bus-tyre:#0A0405;
  --bus-hub:#5A4E42;
  --bus-shade:#000000;
}

@media (max-width:900px){
  .road{--lane-top:70%;--lane-h:104px}
  .bus--far{width:190px}
  .bus--haul{width:clamp(190px,54vw,250px)}
}
/* A vehicle driving across the screen is exactly the kind of motion this
   setting exists for, so the road stays and the traffic stops. */
@media (prefers-reduced-motion:reduce){
  .road__line{animation:none}
  .bus--far{display:none}
  #contact.is-hauling .bus--haul{animation:none;opacity:0}
}

/* ═══════════════════════════════════════════ SOFT — a pill you could press ═
   Reusable: put .btn--soft on anything, or lean on the shared .soft selector
   list. The shape comes almost entirely from light rather than from an edge —
   a bright inner lip along the top, a faint floor shadow inside the bottom,
   then a matched pair of outer shadows: a warm cast down-and-right and a
   light bloom up-and-left. */
.soft,.btn--soft,.tab{
  position:relative;isolation:isolate;
  border:1px solid var(--sf-edge);border-radius:99px;cursor:pointer;
  color:var(--sf-ink);background:var(--sf-face);
  -webkit-backdrop-filter:var(--sf-fx);backdrop-filter:var(--sf-fx);
  box-shadow:
    inset 0 1.5px 0 var(--sf-lip),          /* the lit top lip        */
    inset 0 -3px 4px -3px var(--sf-floor),  /* the face's own floor   */
    -7px -7px 16px var(--sf-bloom),         /* bloom, up and left     */
    7px 10px 22px -6px var(--sf-cast),      /* cast, down and right   */
    0 1px 2px rgba(0,0,0,.05);
  transition:transform .28s var(--out),box-shadow .32s var(--ease),
             color .24s var(--ease),background .3s var(--ease);
}
.soft:hover,.btn--soft:hover,.tab:hover{
  transform:translateY(-2px);
  box-shadow:
    inset 0 1.5px 0 var(--sf-lip),
    inset 0 -3px 4px -3px var(--sf-floor),
    -9px -9px 20px var(--sf-bloom),
    9px 15px 30px -8px var(--sf-cast),
    0 1px 2px rgba(0,0,0,.05);
}
/* Pressed, the pill sinks INTO the surface rather than moving down it: both
   outer shadows collapse and the lighting flips inward. Dropping the button
   two pixels would keep it sitting proud, which is the wrong story for a
   surface this soft. */
.soft:active,.btn--soft:active,.tab:active{
  transform:translateY(0);
  box-shadow:
    inset 2px 3px 6px -1px var(--sf-cast),
    inset -2px -2px 5px -1px var(--sf-bloom),
    0 1px 1px rgba(0,0,0,.04);
}
.soft:focus-visible,.btn--soft:focus-visible,.tab:focus-visible{
  outline:2px solid var(--gold);outline-offset:4px;
}
/* Without a blur the translucent face has nothing behind it doing the work,
   so it falls back to an opaque one rather than sitting there as a wash. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .soft,.btn--soft,.tab{background:var(--sf-solid)}
}
@media (prefers-reduced-transparency:reduce){
  .soft,.btn--soft,.tab{
    -webkit-backdrop-filter:none;backdrop-filter:none;background:var(--sf-solid);
  }
}

/* ---- tabs: the soft pill at filter size ---- */
/* The gap has to clear the bloom as well as the cast, or the light spilling
   left off one tab lands on the tab beside it. */
.tabs{display:flex;gap:15px;flex-wrap:wrap;margin-bottom:34px;padding:4px 2px 8px}
.tab{padding:12px 22px;font-size:.85rem;line-height:1}
/* The lit tab is the same object in gold. */
/* The selected tab is solid where the others are glass — the material change
   marks it as much as the colour does. Its top lip is gold rather than white,
   which is the one thread tying it back to the rest of the page. */
.tab.on{
  color:var(--sf-on-ink);border-color:var(--sf-on-edge);background:var(--sf-on-face);
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:
    inset 0 1.5px 0 var(--sf-on-lip),
    inset 0 -4px 6px -4px rgba(0,0,0,.5),
    -7px -7px 16px var(--sf-bloom),
    7px 12px 26px -6px var(--sf-on-cast),
    0 1px 2px rgba(0,0,0,.08);
}
.tab.on:hover{
  color:var(--sf-on-ink);
  box-shadow:
    inset 0 1.5px 0 var(--sf-on-lip),
    inset 0 -4px 6px -4px rgba(0,0,0,.5),
    -9px -9px 20px var(--sf-bloom),
    9px 17px 34px -8px var(--sf-on-cast),
    0 1px 2px rgba(0,0,0,.08);
}
.tab.on:active{
  box-shadow:
    inset 2px 3px 7px -1px rgba(0,0,0,.55),
    inset -2px -2px 5px -1px rgba(243,221,164,.16),
    0 1px 1px rgba(0,0,0,.06);
}


@media (prefers-reduced-motion:reduce){
  .soft,.btn--soft,.tab{transition:none}
  .soft:hover,.btn--soft:hover,.tab:hover{transform:none}
}

/* -------------------------------------------------------------- campuses */
/* ═════════════════════════════════════ CAMPUSES — the bento plates ════════
   Dark plates in both themes, the same call the cinematic band makes: the
   look depends on light coming out of the card rather than off it, and a
   cream card in light mode has nothing for a glow to read against.

   The campuses laid out as a bento rather than a single row — the flagship
   takes a double-width cell on the top row, the other four sit beneath it. */
.camps{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(12px,1.2vw,18px);
}
.camp{
  position:relative;isolation:isolate;overflow:hidden;
  border-radius:20px;padding:0;
  display:flex;flex-direction:column;
  color:#F1E7DA;
  background:
    radial-gradient(120% 90% at 18% 0%,rgba(120,38,44,.34),transparent 58%),
    linear-gradient(168deg,#241012 0%,#150809 46%,#0D0405 100%);
  border:1px solid rgba(226,148,152,.16);
  box-shadow:0 22px 54px -26px rgba(0,0,0,.9);
  transition:transform .42s var(--out),border-color .35s var(--ease),
             box-shadow .42s var(--ease);
}
.camp:hover,.camp.is-hot{
  transform:translateY(-6px);
  border-color:rgba(226,148,152,.3);
  box-shadow:0 34px 74px -28px rgba(0,0,0,.95);
}
/* The flagship. A gradient rim rather than a brighter border — the reference
   card is picked out by an edge that changes hue around the perimeter, which
   a single border-color cannot do. */
.camp--flag{grid-column:span 2}
.camp--flag::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;padding:1.2px;
  background:linear-gradient(135deg,
    var(--gold-hi) 0%,var(--gold) 26%,#B4474E 54%,var(--gold-lo) 78%,var(--gold-hi) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  opacity:.72;transition:opacity .4s var(--ease);
}
.camp--flag:hover::after,.camp--flag.is-hot::after{opacity:1}

/* ---- the motif ---- */
/* Range rings radiating from a pin. Drawn rather than photographed so it
   costs nothing to load and inherits the gold straight from the theme. */
.camp__viz{
  position:relative;height:132px;flex:0 0 auto;overflow:hidden;
  display:grid;place-items:end center;
}
.camp--flag .camp__viz{height:158px}
.camp__viz svg{
  width:min(100%,300px);height:auto;display:block;
  color:var(--gold);opacity:.5;
  transition:opacity .45s var(--ease),transform .6s var(--out);
}
.camp:hover .camp__viz svg,.camp.is-hot .camp__viz svg{opacity:.78;transform:translateY(-3px)}
/* The bloom the rings sit in. */
.camp__viz::before{
  content:"";position:absolute;left:50%;bottom:-46px;translate:-50% 0;
  width:230px;height:170px;border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(201,152,47,.28),transparent 72%);
  filter:blur(6px);
  transition:opacity .45s var(--ease);opacity:.85;
}
.camp:hover .camp__viz::before,.camp.is-hot .camp__viz::before{opacity:1}
/* A hairline where the motif ends and the copy begins. */
.camp__viz::after{
  content:"";position:absolute;left:22px;right:22px;bottom:0;height:1px;
  background:linear-gradient(90deg,transparent,rgba(226,148,152,.22),transparent);
}

/* ---- the copy ---- */
.camp__b{
  position:relative;z-index:2;
  padding:22px 24px 24px;display:flex;flex-direction:column;gap:12px;flex:1 1 auto;
}
.camp--flag .camp__b{padding:24px 28px 26px}
.camp__top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.camp__top h3{font-size:1.1rem;line-height:1.24;margin:0;color:#F7EFE2}
.camp--flag .camp__top h3{font-size:1.34rem}
.camp__flag{
  flex:0 0 auto;font-family:var(--mono);font-size:.54rem;letter-spacing:.16em;
  text-transform:uppercase;padding:5px 10px;border-radius:99px;color:var(--gold-hi);
  border:1px solid rgba(226,148,152,.34);background:rgba(201,152,47,.12);
}
.camp__addr{
  font-size:.85rem;line-height:1.55;margin:0;
  color:rgba(241,231,218,.6);overflow-wrap:anywhere;
}
.camp__meta{
  display:grid;gap:7px;margin-top:auto;padding-top:4px;
  font-size:.78rem;color:rgba(241,231,218,.45);
}
.camp__meta>span{display:flex;gap:9px;align-items:baseline;min-width:0}
.camp__meta b{font-weight:400;color:rgba(241,231,218,.72)}
.rate i{font-style:normal;color:var(--gold)}

/* ---- the pills ---- */
/* Local buttons rather than the site's --btn tokens: those resolve to a white
   face under the light theme, which on a permanently dark plate would read as
   a hole punched in the card. */
.camp__row{display:flex;gap:9px;flex-wrap:wrap;padding-top:6px}
.camp__go{
  display:inline-flex;align-items:center;gap:8px;
  padding:9px 16px;border-radius:99px;font-size:.79rem;line-height:1;
  border:1px solid rgba(226,148,152,.24);
  background:rgba(255,240,220,.06);color:#F1E7DA;
  transition:background .26s var(--ease),border-color .26s var(--ease),
             color .26s var(--ease),transform .26s var(--out);
}
.camp__go:hover{
  background:rgba(255,240,220,.12);border-color:rgba(226,148,152,.44);
  transform:translateY(-2px);
}
/* The campus cards are dark in both themes too. */
.camp__go--p{
  --sv-fill:linear-gradient(180deg,rgba(224,233,247,.15),rgba(190,203,223,.05));
  --sv-fg:#F0F5FD;
  --sv-fg-sh:0 1px 2px rgba(0,0,0,.6);
  --sv-rim-hi:rgba(255,255,255,.92);
  --sv-rim-mid:rgba(206,220,240,.66);
  --sv-rim:rgba(150,166,190,.44);
  --sv-bevel:rgba(230,239,251,.5);
  --sv-bevel-2:rgba(230,239,251,.24);
  --sv-inner:rgba(214,228,246,.16);
  --sv-floor:rgba(0,0,0,.4);
  --sv-cast:rgba(0,0,0,.6);
  --sv-halo:rgba(168,184,206,.3);
  --sv-fx:blur(18px) saturate(.55) brightness(.92);
  border-color:transparent;color:var(--sv-fg);text-shadow:var(--sv-fg-sh);
  background:var(--sv-fill);
  -webkit-backdrop-filter:var(--sv-fx);backdrop-filter:var(--sv-fx);
  box-shadow:var(--sv-lift);
}
.camp__go--p:hover{
  color:var(--sv-fg);background:var(--sv-fill);
  border-color:transparent;box-shadow:var(--sv-lift-hi);
}
.camp__go svg{width:14px;height:14px;flex:0 0 auto}

@media (max-width:1000px){
  .camps{grid-template-columns:repeat(2,1fr)}
  .camp--flag{grid-column:span 2}
}
@media (max-width:640px){
  .camps{grid-template-columns:1fr}
  .camp--flag{grid-column:span 1}
  .camp__viz,.camp--flag .camp__viz{height:118px}
  .camp__b,.camp--flag .camp__b{padding:20px 20px 22px}
  .camp--flag .camp__top h3{font-size:1.16rem}
}
@media (prefers-reduced-motion:reduce){
  .camp,.camp__viz svg{transition:none}
  .camp:hover,.camp.is-hot{transform:none}
}

/* ═════════════════════════════════ CAMPUSES — the dialog ══════════════════
   The shell is the faculty panel's, deliberately: two dialogs on one site
   that open differently would read as two sites. What changes is the shape —
   this one is wide rather than landscape-split, because the bento inside it
   wants three columns to keep the flagship's double cell meaningful. */
.cpop{
  position:fixed;inset:0;z-index:120;display:none;
  align-items:center;justify-content:center;padding:clamp(14px,3.5vw,40px);
}
.cpop.on{display:flex}
/* The veil is deliberately thinner than the faculty panel's. That one sits
   behind an opaque box, so it does all the dimming on its own; this one sits
   behind glass, and a veil heavy enough to hide the page leaves the glass
   with nothing to be transparent to. It takes the edge off the contrast and
   the box's own brightness() does the rest. */
.cpop__veil{
  position:absolute;inset:0;background:rgba(8,4,5,.42);
  -webkit-backdrop-filter:blur(3px) saturate(1.1);backdrop-filter:blur(3px) saturate(1.1);
  opacity:0;transition:opacity .3s var(--ease);
}
.cpop.in .cpop__veil{opacity:1}
.cpop__box{
  --cp-ink:#F3EADC;
  --cp-line:rgba(243,234,220,.14);
  position:relative;isolation:isolate;
  width:min(1120px,100%);max-height:min(90vh,880px);
  display:grid;grid-template-rows:auto minmax(0,1fr);
  border-radius:22px;overflow:hidden;color:var(--cp-ink);
  /* Glass, on the same recipe as --panel in the dark theme: a thin warm tint
     over a heavy blur, with brightness() pulled down inside the filter rather
     than opacity pushed up in the fill. That distinction is the whole trick —
     a darker fill would hide the page and stop it being glass, while dimming
     the backdrop keeps the shapes moving behind it and still leaves enough
     contrast under light type. */
  background:rgba(40,14,16,.46);
  border:1px solid rgba(255,240,232,.16);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 -1px 0 rgba(0,0,0,.28),
    inset 0 0 60px -20px rgba(255,220,200,.08),
    0 40px 90px -30px rgba(0,0,0,.86);
  opacity:0;transform:translateY(20px) scale(.975);
  transition:opacity .34s var(--ease),transform .44s var(--out);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .cpop__box{
    -webkit-backdrop-filter:blur(40px) brightness(.56) saturate(1.4);
    backdrop-filter:blur(40px) brightness(.56) saturate(1.4);
  }
}
/* Without the filter there is no glass to be had, so it falls back to the
   solid panel rather than to a washed-out box you cannot read. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .cpop__box{background:linear-gradient(150deg,#2A1416 0%,#1D0E10 46%,#120708 100%)}
}
.cpop.in .cpop__box{opacity:1;transform:none}
/* The same pool of gold the plates sit in, bled from the top-left so the
   header has something behind it. */
.cpop__box::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(760px 420px at 6% 0%,rgba(201,152,47,.2),transparent 62%);
}
/* The specular. A wide, very low-contrast band raked across the sheet — it is
   what tells the eye the surface is a pane rather than a tinted hole, and it
   has to stay this faint or it turns into a stripe. */
.cpop__box::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(128deg,rgba(255,255,255,.09) 0%,rgba(255,255,255,.02) 26%,
                    transparent 44%,transparent 100%),
    linear-gradient(200deg,transparent 62%,rgba(255,228,214,.05) 100%);
}
.cpop__x{
  position:absolute;top:14px;right:14px;z-index:8;
  width:34px;height:34px;border-radius:11px;display:grid;place-items:center;
  border:1px solid var(--cp-line);background:rgba(243,234,220,.06);
  color:rgba(243,234,220,.56);cursor:pointer;transition:.24s var(--ease);
}
.cpop__x:hover{color:var(--cp-ink);border-color:rgba(243,234,220,.3);background:rgba(243,234,220,.12)}
.cpop__x svg{width:14px;height:14px}

.cpop__head{
  position:relative;z-index:2;
  padding:clamp(22px,2.4vw,30px) clamp(20px,2.6vw,34px) clamp(16px,1.6vw,20px);
  padding-right:60px;border-bottom:1px solid var(--cp-line);
}
.cpop__head .eyebrow{color:var(--gold)}
.cpop__head .eyebrow::before{background:var(--gold)}
.cpop__head h2{font-size:clamp(1.3rem,2.2vw,1.72rem);margin:10px 0 0;color:#FBF5EC;line-height:1.18}
.cpop__head p{margin:9px 0 0;font-size:.87rem;line-height:1.55;
              color:rgba(243,234,220,.56);max-width:62ch}

/* The one scroller in the dialog. Padding at the foot so the last row of
   plates does not sit flush against the cut edge as it scrolls out. */
.cpop__scroll{
  position:relative;z-index:2;overflow:auto;overscroll-behavior:contain;
  padding:clamp(18px,2.2vw,26px) clamp(20px,2.6vw,34px) clamp(24px,2.8vw,34px);
  -webkit-overflow-scrolling:touch;
}
.cpop__scroll::-webkit-scrollbar{width:9px}
.cpop__scroll::-webkit-scrollbar-thumb{
  background:rgba(243,234,220,.16);border-radius:99px;
  border:3px solid transparent;background-clip:content-box;
}
.cpop__scroll::-webkit-scrollbar-thumb:hover{background:rgba(243,234,220,.3);
  border:3px solid transparent;background-clip:content-box}

/* ---- the plates, in glass ----
   The bento covers most of the sheet. Leaving the cards opaque would have
   made the box glass only in its gutters and the header strip, which is the
   usual way this effect gets built and then quietly does nothing. They take
   the same treatment at a shallower depth — lighter tint, shorter blur — so
   the sheet reads as one pane with five panes set into it. The hover and
   target states are restated because these rules land after .camp:hover in
   the sheet and would otherwise sit on top of it. */
.cpop .camp{
  background:
    radial-gradient(120% 90% at 18% 0%,rgba(158,56,64,.26),transparent 58%),
    linear-gradient(168deg,rgba(62,28,31,.44) 0%,rgba(32,14,16,.36) 46%,rgba(16,7,8,.44) 100%);
  border-color:rgba(255,238,232,.16);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.1),
    0 22px 54px -26px rgba(0,0,0,.82);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .cpop .camp{
    -webkit-backdrop-filter:blur(18px) brightness(.86) saturate(1.25);
    backdrop-filter:blur(18px) brightness(.86) saturate(1.25);
  }
}
.cpop .camp:hover,.cpop .camp.is-hot{
  border-color:rgba(255,238,232,.32);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.17),
    0 34px 74px -28px rgba(0,0,0,.9);
}
/* The hairline where the copy begins was drawn for an opaque plate and is
   too dim to survive on glass. */
.cpop .camp__viz::after{
  background:linear-gradient(90deg,transparent,rgba(255,235,228,.3),transparent);
}
/* Same problem one level down. The address and the metadata were set against
   a near-black card; a translucent one sits several stops lighter, and at
   .45 the timings had thinned to the edge of legible. Nudged up rather than
   restyled — the hierarchy between name, address and detail is unchanged. */
.cpop .camp__addr{color:rgba(244,235,224,.7)}
.cpop .camp__meta{color:rgba(244,235,224,.58)}
.cpop .camp__meta b{color:rgba(244,235,224,.86)}


   [data-reveal] any more — that layer keys off the viewport, and inside a
   display:none dialog it has nothing to observe until the moment the panel
   opens, which is exactly one frame too late.

   The entrance rides the independent `translate` property rather than
   `transform`. The plates already spend `transform` on their hover lift, and
   a descendant rule setting transform:none here outweighs .camp:hover — the
   cards would arrive correctly and then sit dead under the cursor. These two
   compose instead of competing. */
.cpop .camp{opacity:0;translate:0 16px}
.cpop.in .camp{
  opacity:1;translate:0 0;
  transition:opacity .5s var(--out),translate .5s var(--out);
  transition-delay:calc(var(--i,0) * 62ms + 120ms);
}
/* A campus reached from a chip or a footer link is marked so the eye lands
   on it rather than on the top-left plate. */
.cpop .camp.is-target{
  border-color:rgba(255,214,200,.5);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.2),
    0 0 0 1px rgba(201,152,47,.42),
    0 34px 74px -28px rgba(0,0,0,.9);
}
@media (max-width:640px){
  .cpop{padding:0}
  .cpop__box{border-radius:0;width:100%;max-height:100dvh;height:100dvh}
  /* Five nested blurs inside a sixth is a scroll-killer on a phone. The
     plates drop their own filter here and take a thicker tint instead; the
     box keeps its glass, which is the part you actually see at this width. */
  .cpop .camp{
    -webkit-backdrop-filter:none;backdrop-filter:none;
    background:
      radial-gradient(120% 90% at 18% 0%,rgba(150,50,58,.3),transparent 58%),
      linear-gradient(168deg,rgba(52,23,26,.72) 0%,rgba(27,12,13,.68) 46%,rgba(14,6,7,.72) 100%);
  }
}
@media (prefers-reduced-motion:reduce){
  .cpop__box,.cpop__veil{transition:none}
  .cpop__box{opacity:1;transform:none}
  .cpop .camp{opacity:1;translate:none}
  .cpop.in .camp{transition:none}
}

/* ====================== CINEMATIC SWK BAND ====================== */
/* This band belongs to SWK, not to Cambridge Online, so it carries SWK's own
   colours rather than the page's oxblood: navy #051F3A and gold #F3BD1D,
   both sampled straight off the shield. Dark in both themes on purpose —
   the whole band is lit from inside, and a cream plate gives the bloom
   nothing to read against.

   Every colour here is literal rather than tokenised. The theme tokens flip
   with the page, and half of them resolve to dark browns under the light
   theme, which on a permanently navy plate would be invisible. */
.cine{
  --swk-navy:#061F3A;
  --swk-gold:#F3BD1D;
  --swk-gold-hi:#FFDA74;
  --swk-ink:#EDF3FA;

  /* The hero's glass components are reused verbatim in this band, but their
     tokens flip with the page theme — under the light theme --lq2-fg is a
     dark brown and --by-fill is a white wash, both of which are wrong on a
     plate that is near-black in BOTH themes. Pinning the dark-theme values
     here means the pane, the bevel and the silver filament all behave the
     same way whichever theme the visitor is in. */
  --lq2-fill:linear-gradient(180deg,rgba(220,226,236,.055),rgba(206,214,228,.014));
  --lq2-fg:#F3F7FC;
  --lq2-fg-sh:0 1px 2px rgba(0,0,0,.55);
  --lq2-rim:rgba(237,243,250,.32);
  --lq2-rim-hi:rgba(255,255,255,.66);
  --lq2-rim-warm:rgba(255,246,226,.48);
  --lq2-bevel:rgba(255,255,255,.4);
  --lq2-bevel-2:rgba(255,255,255,.16);
  --lq2-inner:rgba(255,255,255,.11);
  --lq2-floor:rgba(0,0,0,.42);
  --lq2-spec:rgba(255,255,255,.1);
  --lq2-fx:blur(26px) saturate(.6) brightness(.86);
  --lq2-sky:rgba(255,255,255,.04);
  --lq2-bounce:rgba(255,255,255,.015);
  --lq2-lens:rgba(255,255,255,.34);
  --lq2-cast:rgba(0,0,0,.62);
  --lq2-halo:rgba(243,189,29,.1);
  --lq2-trace:#E9EEF5;
  --lq2-trace-glow:rgba(216,232,255,.5);
  --by-fill:linear-gradient(180deg,rgba(237,243,250,.06),rgba(237,243,250,.016));
  --by-fx:blur(16px) saturate(1.05) brightness(.94);
  --by-inner:rgba(255,255,255,.1);
  --by-floor:rgba(0,0,0,.34);
  /* The reduced-transparency fallback swaps these panes to --panel-solid,
     which is cream under the light theme — a white block carrying light text
     on a black plate. Pinned dark so the fallback stays readable. */
  --panel-solid:#101821;
  --line-2:rgba(237,243,250,.2);
  position:relative;overflow:hidden;isolation:isolate;
  color:var(--swk-ink);
  /* Near-black with only a whisper of the brand navy in it. A full navy field
     turned the band into a blue section with a gold logo on it; at this depth
     the plate reads as black and the gold is the only colour in the frame,
     which is what makes the shield carry. */
  background:linear-gradient(168deg,#0E141C 0%,#080C12 48%,#04060A 100%);
  padding-block:clamp(104px,12vw,178px);
  /* No margin. The band used to be separated from its neighbours by a strip
     of page colour, which is what put a hard horizontal line at each end.
     The edges now dissolve into --bg instead, so the join is a gradient
     rather than a border. */
  margin-block:0;
}
.cine::before{
  content:"";position:absolute;inset:0;z-index:0;
  background:
    /* Circular and centred on the shield. It was a 760x460 ellipse offset to
       32% — an oval light source behind a symmetrical object is what made the
       halo look lopsided. Three stops instead of two so the falloff has no
       detectable edge. */
    radial-gradient(circle 560px at 26% 50%,
      rgba(243,189,29,.16) 0%, rgba(243,189,29,.07) 42%, transparent 78%),
    radial-gradient(900px 620px at 88% 94%, rgba(20,42,68,.4), transparent 72%);
}
/* Vignette, plus the two edge fades that submerge the band into the page.
   All three live in one stack because the fades must paint OVER the vignette
   — the vignette darkens every edge, so a fade underneath it would be
   fighting the very corners it is trying to dissolve. Earlier layers in a
   background list sit on top, so the fades are listed first.

   --bg is the page colour and flips with the theme, so this join works in
   both directions: the band emerges from cream in light mode and from near
   black in dark mode, where it becomes almost invisible. */
.cine::after{
  content:"";position:absolute;inset:0;z-index:4;pointer-events:none;
  background:
    linear-gradient(180deg,var(--bg) 0%,rgba(0,0,0,0) 17%),
    linear-gradient(0deg,var(--bg) 0%,rgba(0,0,0,0) 15%),
    radial-gradient(ellipse at 40% 46%, transparent 44%, rgba(1,3,6,.7) 100%);
}

/* ---- the pattern ---- */
/* A fine diagonal hatch crossed with a dot grid, both in gold at a few
   percent. The double mask is what submerges it: it fades out toward the
   edges of the band AND is scooped away behind the shield, so the pattern
   sits under the content rather than competing with it. */
.cine__pat{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background-image:
    repeating-linear-gradient(128deg,rgba(243,189,29,.05) 0 1px,transparent 1px 13px),
    radial-gradient(circle at 1px 1px,rgba(243,189,29,.075) 1px,transparent 0);
  background-size:auto,28px 28px;
  -webkit-mask-image:
    radial-gradient(58% 62% at 32% 46%,transparent 22%,#000 78%),
    linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent);
  mask-image:
    radial-gradient(58% 62% at 32% 46%,transparent 22%,#000 78%),
    linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent);
  -webkit-mask-composite:source-in;mask-composite:intersect;
  opacity:.75;
}
.cine__in{position:relative;z-index:3;display:grid;
          grid-template-columns:.92fr 1.08fr;gap:clamp(34px,5vw,74px);align-items:center}
.cine__in h2{color:#F8FBFF;letter-spacing:-.014em}
.cine__in h2 em{color:var(--swk-gold-hi)}
.cine__in .lede{color:rgba(237,243,250,.72);max-width:56ch}
.cine__in .lede + .lede{margin-top:15px}
.cine__in .eyebrow{color:var(--swk-gold)}
.cine__in .eyebrow::before{background:var(--swk-gold)}
.cine__in .rule{background:linear-gradient(90deg,var(--swk-gold),transparent)}

.cine__stage{position:relative;display:grid;place-items:center;min-height:min(58vh,520px);perspective:1200px}
.cine__mark{
  /* Scales with the viewport instead of being pinned to a small ceiling —
     the shield was capped at 340px inside a column nearly twice that wide,
     which is what made it look shrunken rather than placed. */
  position:relative;width:clamp(230px,32vw,470px);max-width:94%;z-index:2;
  /* Two soft passes at different radii rather than one tight 34px rim, which
     hugged the shield's outline and read as an outline rather than a glow. */
  filter:drop-shadow(0 26px 52px rgba(0,0,0,.7))
         drop-shadow(0 0 58px rgba(243,189,29,.14))
         drop-shadow(0 0 110px rgba(243,189,29,.09));
  transform:translateZ(0) scale(var(--cs,1));
  transition:transform .2s linear;
}
/* Spotlight that tracks the pointer and drifts on its own otherwise. */
.cine__spot{
  position:absolute;width:150%;aspect-ratio:1;z-index:1;pointer-events:none;
  /* Ends at 100%, not 62%. Cutting a radial gradient short leaves a faint
     ring where the last stop lands, and against the shield's own gold that
     ring read as a smudge rather than as light. */
  background:radial-gradient(circle,
    rgba(255,226,150,.26) 0%,
    rgba(250,208,120,.14) 28%,
    rgba(243,189,29,.06) 55%,
    rgba(243,189,29,.02) 76%,
    transparent 100%);
  filter:blur(26px);
  transform:translate(var(--sx,0),var(--sy,0));
  transition:transform .7s var(--out);
}
/* Anamorphic streak sweeping across the mark. */
.cine__flare{
  position:absolute;left:-30%;width:160%;height:3px;z-index:3;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,240,205,.85),transparent);
  filter:blur(2px);opacity:0;
  animation:flare 7s var(--ease) infinite;
}
@keyframes flare{
  0%,72%{opacity:0;transform:translateY(-40px) scaleX(.4)}
  80%{opacity:.9;transform:translateY(0) scaleX(1)}
  92%,100%{opacity:0;transform:translateY(40px) scaleX(.4)}
}
/* Slow drifting dust motes in the beam. */
.cine__dust{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:hidden}
.cine__dust i{
  position:absolute;width:3px;height:3px;border-radius:50%;
  background:rgba(255,232,170,.55);
  animation:mote linear infinite;
}
@keyframes mote{
  from{transform:translateY(110%) translateX(0);opacity:0}
  15%{opacity:.8}
  85%{opacity:.5}
  to{transform:translateY(-20%) translateX(24px);opacity:0}
}

/* ---- the identity card ---- */
/* The hero's own credit pane, reused. Only the type colours are restated,
   because --text-1 and --text-3 go dark under the light theme and this plate
   never does. */
.cine__by{margin-top:30px}
.cine__by div{color:rgba(237,243,250,.62)}
.cine__by b{color:#FFFFFF}
.cine__by span{
  display:block;font-family:var(--mono);font-size:.65rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--swk-gold-hi);margin-top:3px;
}
.cine__by img{width:46px;height:46px}

/* ---- the pill ---- */
.cine__cta{margin-top:22px}

@media (max-width:900px){
  .cine__in{grid-template-columns:1fr;gap:34px}
  /* Stacked, the shield has the full column width to itself, so the desktop
     vw scale would run it edge to edge. */
  .cine__stage{min-height:min(42vh,360px)}
  .cine__mark{width:clamp(210px,54vw,330px)}
  .cine__by{margin-top:24px}
}
@media (max-width:560px){
  .cine__by{padding:12px 18px 12px 13px;gap:12px}
  .cine__by img{width:40px;height:40px}
  .cine__by b{font-size:.85rem}
  .cine__by span{font-size:.58rem;letter-spacing:.12em}
}

/* ------------------------------------------------------------------ band */
.band{padding:clamp(36px,4.6vw,66px);text-align:center;display:grid;justify-items:center}
.band h2{margin-bottom:13px}
.band .lede{margin-bottom:28px}
/* 16px rather than the old 13. The liquid panes throw a halo of their own, so
   at the tighter gap the two glows overlapped and the pair read as one wide
   smear instead of two buttons — same spacing the hero pair uses. */
.band__row{display:flex;gap:16px;flex-wrap:wrap;justify-content:center}

/* ------------------------------------------------------------------ form */
.form{display:grid;gap:17px}
.two{display:grid;grid-template-columns:1fr 1fr;gap:15px}
.field{display:grid;gap:7px}
.field label{font-family:var(--mono);font-size:.63rem;letter-spacing:.16em;
             text-transform:uppercase;color:var(--text-3)}
.field input,.field select,.field textarea{
  width:100%;padding:14px 16px;border-radius:var(--r-xs);font-size:.92rem;font-weight:300;
  background:rgba(201,152,47,.06);border:1px solid var(--line);
  transition:border-color .22s,background .22s,box-shadow .22s;
}
.field textarea{min-height:118px;resize:vertical;font-family:var(--sans)}
.field input::placeholder,.field textarea::placeholder{color:var(--text-3)}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--gold);background:rgba(201,152,47,.1);
  box-shadow:0 0 0 3px rgba(201,152,47,.16);
}
.field select{appearance:none;cursor:pointer;padding-right:40px;
  background-image:linear-gradient(45deg,transparent 50%,var(--gold-text) 50%),
                   linear-gradient(135deg,var(--gold-text) 50%,transparent 50%);
  background-position:calc(100% - 20px) 22px,calc(100% - 15px) 22px;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.field select option{background:var(--panel-solid);color:var(--text-1)}

/* ---- the telephone control ---------------------------------------------
   Two controls that have to read as one. The dial-code picker is a real
   `<select>` for the keyboard and screen-reader behaviour it brings for free,
   but it is laid out underneath a span that prints just the code — a select
   wide enough to show "United Arab Emirates" would swallow the field, and one
   narrow enough to fit would truncate every long country name to nonsense.
   So the select is transparent and stretched over the code, and the span is
   what you actually see. Clicking anywhere on the block opens the native
   list, which on a phone is a full-screen picker with search. */
.tel{
  display:flex;align-items:stretch;gap:0;
  border-radius:var(--r-xs);overflow:hidden;
  border:1px solid var(--line);
  background:rgba(201,152,47,.06);
  transition:border-color .22s,background .22s,box-shadow .22s;
}
.tel__cc{
  position:relative;flex:0 0 auto;display:grid;place-items:center;
  padding:0 13px 0 15px;cursor:pointer;
  border-right:1px solid var(--line);
}
/* The caret, drawn on the divider side so the block reads as a control. */
.tel__cc::after{
  content:"";position:absolute;right:10px;top:50%;
  width:5px;height:5px;margin-top:-4px;
  border-right:1.4px solid var(--gold-text);
  border-bottom:1.4px solid var(--gold-text);
  transform:rotate(45deg);pointer-events:none;
}
.tel__cc{padding-right:28px}
.tel__cc select{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;cursor:pointer;border:0;padding:0;
  font-size:16px; /* iOS zooms any control under 16px on focus. */
}
.tel__code{
  font-family:var(--mono);font-size:.86rem;letter-spacing:.03em;
  color:var(--text-1);white-space:nowrap;pointer-events:none;
}
.tel input{
  flex:1 1 auto;min-width:0;
  border:0!important;border-radius:0!important;background:transparent!important;
  box-shadow:none!important;
}
.tel input:focus{outline:none}
/* The ring goes on the wrapper, so focusing the number lights the whole
   control rather than half of it. */
.tel:focus-within{
  border-color:var(--gold);background:rgba(201,152,47,.1);
  box-shadow:0 0 0 3px rgba(201,152,47,.16);
}
.field.bad .tel{border-color:#C0392B;background:rgba(192,57,43,.06)}
.field.bad .tel:focus-within{box-shadow:0 0 0 3px rgba(192,57,43,.16)}
.field.ok .tel{border-color:rgba(201,152,47,.42)}
.wiz .tel{
  background:var(--wiz-input);border-color:var(--wiz-input-edge);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.wiz .tel:focus-within{background:var(--wiz-input-on);border-color:var(--gold)}
.tel__cc{border-right-color:var(--wiz-input-edge)}

/* ══════════════════════════════════════ THE ENQUIRY WIZARD ════════════════
   The enquiry used to be one long column of nine fields. Split into three
   steps it asks for three things at a time, and the tracker at the top makes
   the cost of finishing visible up front — which is the whole reason a
   stepped form converts better than a tall one.

   All three panes stay in the DOM. Only their visibility changes, so a value
   typed on step one is still there when you walk back to it. */
/* Clear glass, not the frosted panel. The road runs behind this section, so
   the card is worth seeing through — a solid panel would cover the one thing
   giving the section its ground. Legibility comes from the blur rather than
   from opacity, which is what separates glass from a tinted rectangle.

   The same material is now shared with `.cpane`, the three cards in the right
   column. They used to be `.glass` — the frosted panel — which meant the two
   halves of one section were made of two different substances sitting side by
   side, and the frosted column read as the solid thing the form was floating
   in front of. One material, one column of glass. */
.wiz,.cpane{
  position:relative;isolation:isolate;
  padding:clamp(24px,3.2vw,38px);
  border-radius:var(--r);
  background:var(--clear-fill);
  border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow-hi);
}
/* The cards are smaller objects and carry less inside them, so they take the
   tighter radius and their own padding rather than the form's. */
.cpane{padding:28px 26px;border-radius:var(--r-sm)}
/* The one card that keeps a warm edge — it holds the demo-lesson CTA, and the
   gold rim is what marks it as the offer rather than another note. */
.cpane--gilt{border-color:rgba(201,152,47,.34)}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .wiz,.cpane{
    -webkit-backdrop-filter:var(--clear-fx);
    backdrop-filter:var(--clear-fx);
  }
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .wiz,.cpane{background:var(--clear-solid)}
}
@media (prefers-reduced-transparency:reduce){
  .wiz,.cpane{
    -webkit-backdrop-filter:none;backdrop-filter:none;background:var(--clear-solid);
  }
}
/* The specular rim: brighter where light enters, dimmer away from it. It used
   to end in `transparent 70%`, which meant the far half of every pane had no
   rim at all and the falloff to nothing was visible as a break in the edge —
   the same fault the buttons had. It runs down to a floor now instead, so the
   edge is continuous the whole way round and only its brightness varies. */
.wiz::before,.cpane::before{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;padding:1px;
  background:linear-gradient(155deg,var(--clear-rim),var(--clear-rim-lo) 58%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
/* The tint layer, now carrying a specular pool that follows the pointer —
   the same light the liquid buttons have, at pane scale. Thinning the fill
   made the glass more transparent but also flatter, because opacity was the
   only thing giving it a surface; a moving highlight puts the surface back
   without putting the opacity back. It rests parked above the top edge, so a
   pane nobody has touched still reads as lit from above rather than as a
   rectangle waiting for a mouse. Coarse pointers never move it and lose
   nothing. */
.wiz::after,.cpane::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  border-radius:inherit;
  background:
    radial-gradient(420px 240px at var(--px,50%) var(--py,-10%),var(--clear-spec),transparent 68%),
    var(--clear-tint);
  transition:background .2s linear;
}
.wiz > *,.cpane > *{position:relative;z-index:1}

/* ---- the filament, on the panes ----------------------------------------
   Same component as the buttons: an SVG rect whose perimeter is normalised to
   100 units by pathLength, so one dashoffset transition draws the line right
   round a 640px form and a 300px card alike. The rect's rx has to be the
   pane's border-radius minus its own 0.6px inset, or the line cuts the corner
   instead of hugging it.

   These two rules have to re-declare position and z-index because `.wiz > *`
   above sets every direct child to position:relative;z-index:1 — at equal
   specificity and later in the sheet, that would otherwise beat `.btn__trace`
   and drop the filament into the content layer. */
.wiz > .btn__trace,.cpane > .btn__trace{
  position:absolute;z-index:3;
  filter:drop-shadow(0 0 1px var(--lq2-trace-glow));
}
.wiz > .btn__trace rect{rx:calc(var(--r) - .6px);ry:calc(var(--r) - .6px)}
.cpane > .btn__trace rect{rx:calc(var(--r-sm) - .6px);ry:calc(var(--r-sm) - .6px)}
.wiz > .btn__trace rect,.cpane > .btn__trace rect{
  stroke:var(--lq2-trace);stroke-width:1.5;
  vector-effect:non-scaling-stroke;shape-rendering:geometricPrecision;
}
/* On the form the line runs on focus-within as well as hover — a visitor
   filling it from the keyboard never hovers it, and the card they are working
   inside is exactly the one that should be lit. */
.wiz:hover > .btn__trace rect,
.wiz:focus-within > .btn__trace rect,
.wiz.is-hot > .btn__trace rect,
.cpane:hover > .btn__trace rect,
.cpane.is-hot > .btn__trace rect{stroke-dashoffset:0;opacity:.82}
/* The gilt card keeps a gold *border*, which is what marks it as the offer,
   but its filament stays silver like every other one on the page. A gold line
   at full strength on a gold rim doubled up and read as the card catching
   fire rather than as the same trace running. */
.cpane:hover{border-color:var(--clear-rim-lo)}
.cpane--gilt:hover{border-color:rgba(201,152,47,.5)}
/* A `.card` built on the clear pane keeps the card's own roomier padding —
   `.cpane` is declared later in the sheet and would otherwise win at equal
   specificity and crush a text card into the tighter card-column measure. */
.card.cpane{padding:clamp(24px,2.5vw,32px)}

/* The controls have to be glass too. Opaque inputs inside a transparent card
   read as holes punched in it. */
.wiz .field input,.wiz .field select,.wiz .field textarea{
  background:var(--wiz-input);
  border-color:var(--wiz-input-edge);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.wiz .field input:focus,.wiz .field select:focus,.wiz .field textarea:focus{
  background:var(--wiz-input-on);border-color:var(--gold);
}
.wiz .wiz__steps b{background:var(--wiz-input);backdrop-filter:blur(6px)}
.wiz__review{background:var(--wiz-input);border-color:var(--wiz-input-edge)}
.wiz__lead{margin-bottom:26px}
.wiz__lead h3{margin:0 0 6px}
.wiz__lead p{font-size:.88rem;color:var(--text-3);margin:0;max-width:46ch}

/* ---- the tracker ---- */
.wiz__steps{
  display:flex;align-items:flex-start;gap:0;
  margin:0 0 28px;padding:0;list-style:none;counter-reset:none;
}
.wiz__steps li{
  position:relative;flex:1 1 0;min-width:0;
  display:flex;flex-direction:column;align-items:center;gap:9px;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--text-3);text-align:center;
  transition:color .3s var(--ease);
}
/* The connector is drawn from each step to the one before it, so the first
   step has none and the line can never overshoot either end of the row. */
.wiz__steps li + li::before{
  content:"";position:absolute;top:15px;right:50%;left:-50%;height:1.5px;
  background:var(--line-2);z-index:0;
  transition:background .4s var(--ease);
}
.wiz__steps b{
  position:relative;z-index:1;
  width:31px;height:31px;border-radius:50%;display:grid;place-items:center;
  font-size:.76rem;font-weight:500;
  background:var(--panel-solid);color:var(--text-3);
  border:1.5px solid var(--line-2);
  transition:background .3s var(--ease),color .3s var(--ease),
             border-color .3s var(--ease),transform .35s var(--spring);
}
.wiz__steps span{padding:0 4px;overflow-wrap:anywhere}
/* Done. */
.wiz__steps li.done{color:var(--gold-text)}
.wiz__steps li.done b{
  background:var(--gold);border-color:var(--gold);color:#2A1403;
  font-size:0;                       /* the numeral gives way to the tick */
}
.wiz__steps li.done b::after{
  content:"";width:11px;height:6px;margin-top:-3px;
  border-left:2px solid #2A1403;border-bottom:2px solid #2A1403;
  transform:rotate(-45deg);
}
.wiz__steps li.done + li::before{background:var(--gold)}
/* Current. */
.wiz__steps li.on{color:var(--text-1)}
.wiz__steps li.on b{
  background:var(--gold);border-color:var(--gold);color:#2A1403;
  transform:scale(1.1);
  box-shadow:0 0 0 5px rgba(201,152,47,.16);
}

/* ---- the panes ---- */
.wiz__pane{display:none;animation:wizIn .45s var(--out)}
.wiz__pane.on{display:grid;gap:17px}
@keyframes wizIn{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.wiz__pane{animation:none}}

/* ---- consent ---- */
.wiz__agree{
  display:flex;align-items:flex-start;gap:11px;cursor:pointer;
  font-size:.85rem;line-height:1.5;color:var(--text-2);
}
.wiz__agree input{
  appearance:none;flex:0 0 auto;width:19px;height:19px;margin-top:1px;
  border-radius:6px;border:1.5px solid var(--line-2);
  background:rgba(201,152,47,.06);cursor:pointer;
  display:grid;place-items:center;
  transition:background .22s var(--ease),border-color .22s var(--ease);
}
.wiz__agree input:checked{background:var(--gold);border-color:var(--gold)}
.wiz__agree input:checked::after{
  content:"";width:9px;height:5px;margin-top:-2px;
  border-left:2px solid #2A1403;border-bottom:2px solid #2A1403;
  transform:rotate(-45deg);
}
.wiz__agree input:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.wiz__agree a{color:var(--gold-text);text-decoration:underline;text-underline-offset:2px}

/* ---- the review ---- */
/* Step three shows back what was typed rather than a bare confirm button —
   the last thing before sending should be the thing being sent. */
.wiz__review{
  display:grid;gap:0;border:1px solid var(--line);border-radius:var(--r-xs);
  background:rgba(201,152,47,.045);overflow:hidden;
}
.wiz__review div{
  display:flex;gap:14px;padding:11px 16px;font-size:.86rem;
  border-bottom:1px solid var(--line);
}
.wiz__review div:last-child{border-bottom:0}
.wiz__review dt{
  flex:0 0 116px;font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text-3);padding-top:3px;
}
.wiz__review dd{margin:0;min-width:0;color:var(--text-1);overflow-wrap:anywhere}

/* ---- footer ---- */
.wiz__foot{display:flex;align-items:center;gap:14px;margin-top:24px}
/* Back was a bare outlined pill — the one control in the section still drawn
   as a border on nothing. It is the same liquid pane as everything else now,
   just narrower and carrying the quieter clear fill, so the pair in the foot
   reads as two weights of one material rather than two unrelated buttons. */
.wiz__back{flex:0 0 auto}
.wiz__foot .btn{flex:1 1 auto}
.wiz__foot .btn.wiz__back{flex:0 0 auto}
/* The foot message now reports the shape of the failure — "three fields need
   attention" — rather than restating one field's complaint, since each field
   prints its own underneath itself. A dot carries the state alongside the
   colour, so it is not the only thing distinguishing pass from fail. */
.wiz__err{
  font-size:.83rem;color:#C0392B;margin:14px 0 0;min-height:1.2em;
  display:flex;align-items:flex-start;gap:9px;
}
.wiz__err::before{content:"";flex:0 0 auto;width:0;height:0}
.wiz__err[data-state="bad"]::before{
  width:7px;height:7px;margin-top:.42em;border-radius:50%;
  background:currentColor;
}
.wiz__err[data-state="ok"]::before{
  width:7px;height:7px;margin-top:.42em;border-radius:50%;
  border:1.5px solid currentColor;box-sizing:border-box;
}
.wiz__sign{
  margin:18px 0 0;text-align:center;font-size:.84rem;color:var(--text-3);
}
.wiz__sign a{color:var(--gold-text)}

/* A field the visitor has been sent back to. The message is printed under the
   control it belongs to, not only at the foot of the form — with three fields
   on a step, a single line at the bottom saying "that email does not look
   complete" makes the visitor hunt for which one it means. */
.field.bad input,.field.bad select,.field.bad textarea{
  border-color:#C0392B;background:rgba(192,57,43,.06);
}
.field.bad input:focus,.field.bad select:focus,.field.bad textarea:focus{
  border-color:#C0392B;box-shadow:0 0 0 3px rgba(192,57,43,.16);
}
/* A field that has been filled and passed. Deliberately quiet — a green tick
   on every satisfied box turns a three-field step into a scoreboard. Just the
   edge, warmed toward the page's own gold. */
.field.ok input,.field.ok select,.field.ok textarea{
  border-color:rgba(201,152,47,.42);
}
.field__err{
  font-size:.76rem;line-height:1.4;color:#C0392B;
  margin:0;min-height:0;max-height:0;overflow:hidden;opacity:0;
  transition:max-height .26s var(--ease),opacity .2s linear,margin .26s var(--ease);
}
.field.bad .field__err{max-height:3.4em;opacity:1;margin-top:-1px}
@media (prefers-reduced-motion:reduce){.field__err{transition:none}}
/* A live count under the subjects box, so the minimum is visible before it is
   enforced rather than only after it fails. */
.field__hint{
  font-size:.72rem;color:var(--text-3);margin:0;
  font-family:var(--mono);letter-spacing:.06em;
}
.field__hint.over{color:#C0392B}

@media (max-width:560px){
  .wiz__steps span{font-size:.53rem;letter-spacing:.09em}
  .wiz__steps b{width:27px;height:27px;font-size:.7rem}
  .wiz__steps li + li::before{top:13px}
  .wiz__review div{flex-direction:column;gap:4px}
  .wiz__review dt{flex:none;padding-top:0}
  .wiz__foot{flex-wrap:wrap}
  /* Full width and below Continue, not a stub beside it. Specificity has to
     match `.wiz__foot .btn.wiz__back` above or the desktop flex wins here. */
  .wiz__foot .btn.wiz__back{flex:1 1 100%;order:2}
}

/* ---------------------------------------------------------------- reveal */
[data-reveal]{opacity:0;transform:translateY(28px);
              transition:opacity .8s var(--out),transform .8s var(--out)}
[data-reveal].in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){[data-reveal]{opacity:1;transform:none}}

/* ======================== LECTURE PAGE ======================== */
.lec{padding-top:calc(var(--hdr) + clamp(26px,4vw,52px))}
.lec__crumb{display:flex;align-items:center;gap:9px;font-size:.82rem;
            color:var(--text-3);margin-bottom:24px}
.lec__crumb a:hover{color:var(--gold-text)}
.lec__top{display:grid;grid-template-columns:1.55fr .95fr;gap:clamp(24px,3vw,40px);align-items:start}

.player{--acc:var(--gold);border-radius:var(--r);overflow:hidden;
        border:1px solid var(--edge);box-shadow:var(--shadow-lg);background:var(--panel-solid)}
.player__st{position:relative;aspect-ratio:16/9;background:var(--bg-2);cursor:pointer;overflow:hidden}
.player__st svg.poster{position:absolute;inset:0;width:100%;height:100%}
.player__veil{position:absolute;inset:0;display:grid;place-items:center;
              background:var(--veil);transition:opacity .35s var(--ease)}
.player.playing .player__veil{opacity:0}
.player.playing:hover .player__veil{opacity:1}
.player__big{
  width:84px;height:84px;border-radius:50%;display:grid;place-items:center;
  background:var(--sv-fill-solid);color:var(--sv-fg-solid);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  font-size:1.4rem;padding-left:5px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.72),
             0 18px 46px -14px rgba(20,30,46,.8);
  transition:transform .35s var(--spring);
}
.player__st:hover .player__big{transform:scale(1.1)}
.player.playing .player__big{padding-left:0;font-size:1.15rem}
.player__bar{position:absolute;left:0;right:0;bottom:0;padding:14px 18px;z-index:3;
             background:var(--veil-bar);display:grid;gap:9px}
.player__t{height:4px;border-radius:99px;background:rgba(255,255,255,.2);cursor:pointer;position:relative}
.player__f{height:100%;width:0;border-radius:99px;
           background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi))}
.player__f::after{content:"";position:absolute;top:50%;right:-1px;width:11px;height:11px;
                  border-radius:50%;background:var(--gold-hi);transform:translate(50%,-50%);
                  box-shadow:0 0 10px rgba(243,221,164,.9)}
.player__row{display:flex;align-items:center;gap:14px;
             font-family:var(--mono);font-size:.72rem;color:var(--veil-ink)}
.player__row button{color:inherit;display:grid;place-items:center;width:26px;height:26px;
                    border-radius:6px;transition:background .2s}
.player__row button:hover{background:rgba(255,255,255,.14)}
.player__row .sp{margin-left:auto}
.player__meta{padding:20px 22px;display:grid;gap:9px;border-top:1px solid var(--edge)}
.player__meta h1{font-size:clamp(1.45rem,2.4vw,2rem);margin:0}
.player__chips{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px}
.player__chips span{font-size:.68rem;padding:5px 11px;border-radius:99px;
                    border:1px solid var(--line);color:var(--text-3)}
.player__chips span.code{font-family:var(--mono);color:var(--acc);
                         border-color:color-mix(in srgb,var(--acc) 45%,transparent)}

.chaps{display:grid;gap:2px;max-height:474px;overflow:auto;padding-right:4px}
.chap{display:flex;gap:14px;align-items:flex-start;padding:14px 15px;border-radius:var(--r-xs);
      cursor:pointer;text-align:left;width:100%;
      transition:background .22s var(--ease)}
.chap:hover{background:rgba(201,152,47,.1)}
.chap.on{background:rgba(201,152,47,.16)}
.chap__n{font-family:var(--mono);font-size:.7rem;color:var(--gold-text);flex:0 0 auto;padding-top:2px}
.chap__b{display:grid;gap:3px;min-width:0}
.chap__b b{font-weight:400;font-size:.9rem}
.chap__b small{font-size:.74rem;color:var(--text-3)}
.chap__t{margin-left:auto;font-family:var(--mono);font-size:.7rem;color:var(--text-3);flex:0 0 auto}

.lec__side{display:grid;gap:16px;position:sticky;top:calc(var(--hdr) + 20px)}
.lec__tut{display:flex;align-items:center;gap:15px;padding:20px 22px}
.lec__tut .med{width:60px;height:60px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
               font-family:var(--display);font-size:1.35rem;font-weight:600;
               border:2px solid var(--acc,var(--gold));color:var(--acc,var(--gold));
               background:var(--panel-solid)}
.lec__dl{display:grid;gap:10px}
.lec__dl a{display:flex;align-items:center;gap:12px;padding:13px 15px;border-radius:var(--r-xs);
           border:1px solid var(--line);font-size:.87rem;
           transition:border-color .22s,background .22s,transform .22s var(--out)}
.lec__dl a:hover{border-color:var(--gold);background:rgba(201,152,47,.09);transform:translateX(3px)}
.lec__dl i{font-style:normal;color:var(--gold-text)}

@media (max-width:1000px){
  .hero{grid-template-columns:1fr;min-height:auto;text-align:left}
  .medal{order:-1;--field:min(48vh,360px)}
  .cine__in{grid-template-columns:1fr}
  .stats{grid-template-columns:1fr 1fr}
  .steps{--cw:240px}
  .lec__top{grid-template-columns:1fr}
  .lec__side{position:static}
  .cue{display:none}
}
@media (max-width:640px){
  .two,.stats{grid-template-columns:1fr}
  /* One per row at this width. The basis goes to 100% rather than the track
     count changing — there are no tracks any more. */
  .steps,.subs,.cards{--cw:100%;--cmax:none}
  .facgrid{--cw:100%;--cmax:none}
  /* Stacked, and with the hero pair's tightened padding — the liquid pane's
     32px inline padding leaves too little room for the icon plus label once
     the button is full-width at 360px. */
  .band__row .btn{width:100%}
  .band__row{gap:12px}
  .band__row .btn--liquid{--pad:16px 24px}
  .mq__t span{font-size:.83rem;gap:16px;padding-inline:16px}
  .mq__t span::after{height:12px}
}
/* ══════════════════════════════ SECTION CLOTH ════════════════════════════
   A repeating image behind the sections that carry the most cards.

   ── THE ONE LINE YOU CHANGE ──────────────────────────────────────────────
   Put the file next to index.html and set --secbg below. That is the only
   edit; nothing else in this block needs touching.

   ── WHY IT IS NOT SCALED ─────────────────────────────────────────────────
   --secbg-size is `auto`, meaning the image tiles at its own pixel size, and
   that is deliberate. The usual cause of a visible seam in a CSS tile is not
   a badly made image — it is background-size landing on a fractional pixel.
   Ask for 420px on a 512px tile and every repeat starts a third of a pixel
   off, the browser resamples each copy slightly differently, and a grid of
   hairlines appears that is not in the source at all. At `auto` there is no
   resampling and a seamless file stays seamless.

   If it tiles too large, resize the FILE rather than setting --secbg-size —
   or if you must set it, use a whole number that divides the image's real
   width exactly (512 -> 256, not 300).

   ── NOT BLURRED ──────────────────────────────────────────────────────────
   No mask over the artwork, no filter, no blur. The only thing shaping it is
   opacity and a soft fade at the top and bottom edges so two stacked
   sections run into each other instead of meeting on a hard line — a fade of
   the whole layer, which never touches the sharpness of the image itself. */
:root{
  --secbg:url("brocade2-light.png");
  --secbg-size:auto;               /* leave as auto unless you must scale */
}
/* The brocade, same as every other page. This one was still on a placeholder
   filename that was never supplied, so the section rendered bare and the
   layer never switched with the theme. */
[data-theme="light"]{ --secbg:url("brocade2-light.png"); --secbg-op:.30 }
[data-theme="dark"] { --secbg:url("brocade2-dark.png");  --secbg-op:.55 }

/* These sections are .sec.wrap, and .wrap caps them at 1280px — so without
   this the cloth stops ~320px short of each viewport edge on a wide screen.
   A 100vw breakout does not work either: four of them carry
   content-visibility:auto, which implies PAINT CONTAINMENT and clips a child
   back to the section's own border box however wide it is told to be. So the
   section goes full-bleed and re-creates the 1280px measure with padding.
   Same column, same gutters, but the box the image paints into runs edge to
   edge. */
.sec--orn{
  isolation:isolate;
  width:100%;
  max-width:none;
  margin-inline:0;
  padding-inline:max(22px,calc((100% - var(--wrap)) / 2));
}
/* z-index:-1 inside an isolated context: pinned to the back of THIS section,
   unable to escape onto the body. Restacking the children instead would have
   flattened the finder's z-index:6 and dropped its suggestion sheet behind
   the faculty grid. */
.sec--orn::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--secbg);
  background-repeat:repeat;
  background-size:var(--secbg-size);
  background-position:center top;
  opacity:var(--secbg-op);
}
@supports ((mask-image:url("")) or (-webkit-mask-image:url(""))){
  .sec--orn::before{
    -webkit-mask-image:linear-gradient(180deg,transparent,#000 14%,#000 86%,transparent);
    mask-image:linear-gradient(180deg,transparent,#000 14%,#000 86%,transparent);
  }
  /* Sections butting straight onto the one above carry the cloth up to their
     own top edge, so the pair reads as one bolt rather than as two fades
     meeting in a bright band. */
  .sec--orn.sec--orn-top::before{
    -webkit-mask-image:linear-gradient(180deg,#000 84%,transparent);
    mask-image:linear-gradient(180deg,#000 84%,transparent);
  }
}
/* Decoding and compositing a full-bleed repeating bitmap is the most
   expensive background on the page. On the lite tier it goes first. */
[data-perf="lite"] .sec--orn::before{display:none}

/* ══════════════════════════════ PERFORMANCE ══════════════════════════════
   Last block in the sheet on purpose: everything here overrides, and it must
   win without !important. Three separate jobs, kept apart because they fail
   in different ways.
   ────────────────────────────────────────────────────────────────────────── */

/* ---- 1. containment ------------------------------------------------------
   Every card in a repeated row is its own layout and paint scope. Without
   this, hovering one faculty card lets the browser consider the whole grid
   for reflow; with it, the work stops at the card's own box. `style` is
   deliberately NOT contained — counters and custom properties cascade in. */
.fac,.faq__i,.sub,.card,.step,.rev,.camp{contain:layout paint}
/* The finder repaints twenty-one cards on a debounce; scoping the container
   keeps that off the rest of the page. */
#grid,#faqList,.revs{contain:layout}

/* ---- 2. offscreen sections ----------------------------------------------
   The note further up this sheet is right: bare content-visibility:auto
   collapses an unmeasured section to nothing and the nav then scrolls to a
   position that does not exist. "Campuses" landing 11,000px short was that
   bug.

   The fix is the part that was missing — contain-intrinsic-size with the
   `auto` keyword. `auto` tells the browser to REMEMBER each section's real
   height once it has been rendered once, and the px value is only the guess
   used before that. So the offsets are right after first paint, and the
   estimates below are close enough that they are right before it too.
   initSpy's observer also forces layout on the sections it watches, and the
   nav scroll now self-corrects — belt and braces on the one bug this
   optimisation is known to cause.

   The hero is excluded. It is the LCP element; skipping it would be a
   deliberate own goal. */
@supports (content-visibility:auto) and (contain-intrinsic-size:auto 100px){
  #streams  {content-visibility:auto;contain-intrinsic-size:auto 900px}
  #about    {content-visibility:auto;contain-intrinsic-size:auto 1000px}
  #courses  {content-visibility:auto;contain-intrinsic-size:auto 800px}
  #campuses {content-visibility:auto;contain-intrinsic-size:auto 1400px}
  #results  {content-visibility:auto;contain-intrinsic-size:auto 1100px}
  #reviews  {content-visibility:auto;contain-intrinsic-size:auto 700px}
  #faq      {content-visibility:auto;contain-intrinsic-size:auto 1200px}
  /* #faculty and #contact stay live. The faculty grid is the finder's target
     and the form holds focus state — a skipped subtree drops neither, but
     both are measured constantly and the saving is not worth the risk. */
}
/* Print and find-in-page both need the whole document laid out. */
@media print{ .sec{content-visibility:visible} }

/* ---- 3. the lite tier ----------------------------------------------------
   Not "turn the design off". The glass stays glass — same fills, same rims,
   same gold. What goes is the live gaussian: backdrop-filter is replaced by
   an opaque approximation of what it was producing, so the material reads the
   same in a screenshot and costs nothing per frame.

   Retuning the tokens rather than writing new rules means every one of the
   sixty-five surfaces downgrades at once and none can be missed. */
[data-perf="lite"]{
  --panel-fx:none;
  --clear-fx:none;
  --lq2-fx:none;
}
[data-perf="lite"] .glass,
[data-perf="lite"] .faq__i{background:var(--panel-solid)}
[data-perf="lite"] .find__bar,
[data-perf="lite"] .find__sugg,
[data-perf="lite"] .faq__find,
[data-perf="lite"] .faq__ask{background:var(--clear-solid)}
/* Blur on a pseudo-element behind content is cheaper than backdrop-filter
   but still per-frame. At this tier the ambient blooms become flat radials. */
[data-perf="lite"] .cine__dust,
[data-perf="lite"] .road__aura{display:none}
[data-perf="lite"] .glass--sheen::after{display:none}
/* The pointer-tilt on faculty cards is a transform per pointermove across
   twenty-one elements. It is a desktop flourish; a lite device is a phone
   and has no pointer to follow anyway. */
[data-perf="lite"] .fac{transform:none !important}

/* ---- 4. paint hints ------------------------------------------------------
   will-change is a promise, not a hint — each one holds a compositor layer
   for the life of the element. Applied only to the two things that actually
   animate transform continuously, and removed the moment they settle. */
.mq__t,.revs{will-change:transform}
@media (prefers-reduced-motion:reduce){
  .mq__t,.revs{will-change:auto}
}
/* Long text blocks: let the engine break them incrementally instead of
   laying out the whole measure before showing any of it. */
.lede,.faq__ai p,.fpop__bio{content-visibility:auto;contain-intrinsic-size:auto 120px}

/* ══════════════════════════════════════ THE DROPDOWN ══════════════════════
   A native <select> paints its list with the operating system, not with the
   page — a white slab, Helvetica, and a blue highlight row, dropped on top of
   an oxblood-and-gold site. There is no CSS that reaches inside it, so the
   only fix is to stop showing it.

   The real <select> stays in the document and stays the source of truth: it
   keeps the form value, the label association, the required state and the
   change event. It is made visually hidden rather than display:none, so it is
   still focusable by script and still submits. On top of it sits a button and
   a listbox built from the same glass the rest of the page is made of, wired
   to the select in both directions — pick in the list, the select updates and
   fires change; set the select from script, the button repaints.

   Below 640px the native picker is genuinely better — iOS and Android render
   it as a full-screen wheel with its own search — so the enhancement stands
   down and the select is handed back its own appearance. */
.sel{position:relative;display:block;width:100%}
.sel__native{
  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;
}

/* The face. Deliberately the same metrics as .field input so a row holding
   one of each lines up on the baseline. */
.sel__btn{
  position:relative;display:flex;align-items:center;gap:10px;width:100%;
  padding:13px 42px 13px 15px;
  font-family:var(--sans);font-size:.92rem;line-height:1.35;text-align:left;
  color:var(--text-1);
  background:rgba(201,152,47,.06);
  border:1px solid var(--line);border-radius:var(--r-xs);
  cursor:pointer;
  transition:border-color .22s var(--ease),background .22s var(--ease),
             box-shadow .22s var(--ease),color .22s var(--ease);
}
.sel__btn:hover{border-color:var(--line-2);background:rgba(201,152,47,.1)}
.sel__btn:focus-visible{
  outline:none;border-color:var(--gold);background:rgba(201,152,47,.1);
  box-shadow:0 0 0 3px rgba(201,152,47,.16);
}
.sel.is-open .sel__btn{
  border-color:var(--gold);background:rgba(201,152,47,.12);
  box-shadow:0 0 0 3px rgba(201,152,47,.16);
}
/* An unset select shows its placeholder in the same grey a text field shows
   one, so the two read as equally unfilled rather than one looking answered. */
.sel__btn[data-empty="1"]{color:var(--text-3)}
.sel__lab{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* The caret. One glyph that rotates, rather than a pair that cross-fade —
   fewer moving parts and it survives a colour change. */
.sel__car{
  position:absolute;right:15px;top:50%;width:9px;height:9px;
  margin-top:-6px;pointer-events:none;
  border-right:1.5px solid var(--gold-text);
  border-bottom:1.5px solid var(--gold-text);
  transform:rotate(45deg);
  transition:transform .3s var(--out),border-color .22s;
}
.sel.is-open .sel__car{transform:rotate(-135deg);margin-top:-2px}

/* The list. Positioned by script into a fixed layer so it can escape a card
   with overflow:hidden — every panel on this page clips, and a dropdown that
   is clipped by its own card is worse than the native one it replaced. */
.sel__pop{
  position:fixed;z-index:400;
  min-width:180px;max-height:290px;
  padding:6px;border-radius:var(--r-sm);
  background:var(--sel-fill);
  border:1px solid var(--sel-edge);
  box-shadow:var(--sel-shadow);
  overflow:hidden auto;overscroll-behavior:contain;
  opacity:0;transform:translateY(-7px) scale(.985);transform-origin:top center;
  pointer-events:none;visibility:hidden;
  transition:opacity .2s var(--ease),transform .26s var(--out),visibility 0s .26s;
  scrollbar-width:thin;scrollbar-color:var(--gold-lo) transparent;
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .sel__pop{-webkit-backdrop-filter:var(--sel-fx);backdrop-filter:var(--sel-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .sel__pop{background:var(--sel-solid)}
}
.sel__pop::-webkit-scrollbar{width:8px}
.sel__pop::-webkit-scrollbar-thumb{background:var(--gold-lo);border-radius:99px}
.sel__pop.is-up{transform-origin:bottom center}
/* The list lives on <body> rather than inside .sel — see the note in the
   script — so its open state cannot be expressed as a descendant of .sel and
   is carried on the list itself. */
.sel__pop.is-open{
  opacity:1;transform:none;pointer-events:auto;visibility:visible;
  transition:opacity .2s var(--ease),transform .3s var(--spring),visibility 0s;
}

.sel__opt{
  position:relative;display:flex;align-items:center;gap:10px;width:100%;
  padding:10px 13px;border:0;border-radius:var(--r-xs);
  background:none;cursor:pointer;
  font-family:var(--sans);font-size:.88rem;line-height:1.35;text-align:left;
  color:var(--sel-ink);
  transition:background .16s var(--ease),color .16s var(--ease),
             padding-left .2s var(--out);
}
/* Hover and keyboard focus are the same visual state — a list where the
   pointer and the arrow keys highlight differently reads as two lists. */
.sel__opt:hover,.sel__opt.is-cur{
  background:var(--sel-hot);color:var(--sel-ink-hi);padding-left:17px;
}
.sel__opt[aria-selected="true"]{color:var(--gold);font-weight:500}
/* The gold bar on the chosen row. Scaled from zero rather than faded in, so
   it draws itself downward instead of blinking on. */
.sel__opt::before{
  content:"";position:absolute;left:5px;top:50%;
  width:2.5px;height:15px;margin-top:-7.5px;border-radius:99px;
  background:var(--gold);
  transform:scaleY(0);transform-origin:center;
  transition:transform .26s var(--spring);
}
.sel__opt[aria-selected="true"]::before{transform:scaleY(1)}
.sel__opt:disabled{opacity:.42;cursor:not-allowed}

/* A rule between a placeholder row and the real choices, where one exists. */
.sel__opt.is-ph{color:var(--text-3)}
.sel__sep{height:1px;margin:5px 9px;background:var(--sel-edge)}

/* Search. Pinned to the top of the list so it stays reachable while the rows
   scroll under it — a filter that scrolls away is a filter you cannot clear. */
.sel__find{
  position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:9px;
  margin:-6px -6px 5px;padding:11px 14px;
  background:var(--sel-fill);border-bottom:1px solid var(--sel-edge);
}
[data-perf="lite"] .sel__find{background:var(--sel-solid)}
.sel__find svg{width:14px;height:14px;flex:0 0 auto;color:var(--gold);opacity:.85}
.sel__find input{
  flex:1;min-width:0;border:0;background:none;padding:0;
  font-family:var(--sans);font-size:.86rem;color:var(--sel-ink-hi);
}
.sel__find input:focus{outline:none}
.sel__find input::placeholder{color:var(--sel-ink);opacity:.6}
.sel__opt[hidden]{display:none}
.sel__none{
  margin:0;padding:16px 14px;text-align:center;
  font-size:.8rem;color:var(--sel-ink);opacity:.75;
}

/* Type-ahead, for the short lists that get no search field. */
.sel__typed{
  position:sticky;top:0;z-index:2;margin:-6px -6px 5px;
  padding:8px 13px;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--gold);
  background:var(--sel-fill);border-bottom:1px solid var(--sel-edge);
}

/* Inside the wizard the field material is the clear glass, not the warm
   tint the standalone fields use. */
.wiz .sel__btn{
  background:var(--wiz-input);border-color:var(--wiz-input-edge);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.wiz .sel__btn:hover,.wiz .sel.is-open .sel__btn{background:var(--wiz-input-on)}
.field.bad .sel__btn{border-color:#C0392B;background:rgba(192,57,43,.06)}
.field.ok .sel__btn{border-color:rgba(201,152,47,.42)}

/* The dial-code picker is a special case: the face has to stay narrow and
   print only "+92", but the list has to be wide enough for country names. */
.tel .sel{position:static}
.tel .sel__btn{
  border:0;background:none!important;box-shadow:none!important;
  padding:0 26px 0 0;width:auto;
  font-family:var(--mono);font-size:.86rem;letter-spacing:.03em;
}
.tel .sel__car{right:8px}
/* The standalone code span belongs to the native fallback. Where the themed
   control is running, the button prints the code and the span would double
   it, so it is folded away. */
.tel__cc.has-sel .tel__code{display:none}
.tel__cc.has-sel::after{display:none}
.tel__cc.has-sel{padding:0 6px 0 13px}
/* Mounted on the body, so the dial list is tagged rather than descended. */
.sel__pop--dial{min-width:280px}
/* The side column reads against the LIST's material, not the page's. It was
   using --text-3, which is near-black ink on the light theme — invisible on a
   panel that is dark in both themes, so every dial code vanished except on
   the one row being hovered. */
.sel__opt em{
  font-style:normal;color:var(--sel-ink);opacity:.62;
  font-family:var(--mono);font-size:.76rem;margin-left:auto;padding-left:12px;
}
.sel__opt:hover em,.sel__opt.is-cur em{color:var(--sel-ink-hi);opacity:1}
.sel__opt[aria-selected="true"] em{color:var(--gold);opacity:1}

/* The sort control on the faculty finder sits on the clear bar and is sized
   down to match the segmented buttons beside it. */
.find__sort.sel .sel__btn{padding:9px 34px 9px 13px;font-size:.82rem;border-radius:99px}
.find__sort.sel .sel__car{right:13px;width:7px;height:7px}

/* Materials. The list is the darkest glass on the page in either theme,
   because it has to sit over arbitrary content and stay readable. */
[data-theme="light"]{
  --sel-fill:rgba(38,14,13,.9);
  --sel-solid:#2C1210;
  --sel-fx:blur(22px) saturate(1.5);
  --sel-edge:rgba(243,221,164,.17);
  --sel-ink:rgba(248,238,222,.84);
  --sel-ink-hi:#FFF6E6;
  --sel-hot:rgba(201,152,47,.26);
  --sel-shadow:0 26px 60px -22px rgba(40,12,6,.6),0 0 0 1px rgba(255,255,255,.05);
}
[data-theme="dark"]{
  --sel-fill:rgba(30,10,12,.92);
  --sel-solid:#1B080A;
  --sel-fx:blur(24px) saturate(1.35);
  --sel-edge:rgba(226,148,152,.18);
  --sel-ink:rgba(246,232,216,.82);
  --sel-ink-hi:#FFF3E4;
  --sel-hot:rgba(201,152,47,.28);
  --sel-shadow:0 30px 70px -24px rgba(0,0,0,.92),0 0 0 1px rgba(255,255,255,.04);
}
/* The lite tier drops every blur on the page; the list keeps a solid fill
   instead so it does not turn into a transparent smear. */
[data-perf="lite"] .sel__pop{
  -webkit-backdrop-filter:none;backdrop-filter:none;background:var(--sel-solid);
}
@media (prefers-reduced-motion:reduce){
  .sel__pop{transition:opacity .12s linear,visibility 0s}
  .sel__pop.is-open{transform:none}
  .sel__car{transition:none}
  .sel__opt{transition:background .1s linear}
  .sel__opt::before{transition:none}
}

/* ---- phones: the same list, a different shape ----------------------------
   This enhancement used to stand down below 640px on the theory that a
   native picker beats a custom one on a phone. On this page it does not:
   iOS and Android paint their own slab — system grey, system typeface, a
   column of radio dots — directly over an oxblood-and-gold document, and it
   was the loudest break in the whole design.

   So the list runs everywhere now and changes shape instead. On a phone an
   anchored popover is the wrong object anyway: it is pinned to a control the
   thumb is already covering, it is as wide as that control, and it fights
   the keyboard. It becomes a sheet — full width, off the bottom edge, over a
   veil, with rows sized for a thumb rather than a cursor. */
@media (max-width:640px){
  .sel__veil{
    position:fixed;inset:0;z-index:399;
    background:rgba(18,5,6,.6);touch-action:none;
    -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
    opacity:0;pointer-events:none;
    transition:opacity .32s var(--ease);
  }
  .sel__veil.is-open{opacity:1;pointer-events:auto}
  [data-perf="lite"] .sel__veil{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(18,5,6,.78)}

  /* The script still writes top/left/min-width for the popover case; in sheet
     mode it clears them, and these carry !important so a stale inline value
     from a rotation cannot leave the sheet hanging mid-screen. */
  .sel__pop{
    top:auto!important;bottom:0!important;left:0!important;right:0;
    width:100%!important;min-width:0!important;max-width:none;
    max-height:min(74vh,540px)!important;
    max-height:min(74svh,540px)!important;   /* dropped by engines without svh */
    padding:0 8px calc(12px + env(safe-area-inset-bottom,0px));
    border-radius:22px 22px 0 0;border-width:1px 0 0;
    box-shadow:0 -26px 64px -20px rgba(0,0,0,.8);
    /* The sheet slides. It does not fade — a translucent panel fading in over
       a veil that is also fading in reads as a rendering fault. */
    opacity:1;transform:translateY(101%);
    transition:transform .42s var(--out),visibility 0s .42s;
  }
  .sel__pop.is-open{
    transform:translateY(0);
    transition:transform .46s var(--spring),visibility 0s;
  }
  .sel__pop.is-up{transform-origin:bottom center}

  /* The grab bar and the field's own name. A sheet with no title is a list of
     answers with the question missing — on a form with four of these in a
     column, that matters. */
  .sel__head{
    position:sticky;top:0;z-index:4;
    height:54px;box-sizing:border-box;
    margin:0 -8px;padding:9px 20px 0;
    background:var(--sel-solid);border-bottom:1px solid var(--sel-edge);
  }
  .sel__grip{
    display:block;width:38px;height:4px;margin:0 auto 11px;
    border-radius:99px;background:rgba(243,221,164,.26);
  }
  .sel__ttl{
    display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    font-family:var(--mono);font-size:.6rem;letter-spacing:.16em;
    text-transform:uppercase;color:var(--gold);
  }
  /* Search sits under the header rather than at the top of the scroller. */
  .sel__pop--sheet .sel__find{
    top:54px;margin:0 -8px 6px;padding:13px 20px;background:var(--sel-solid);
  }
  .sel__pop--sheet .sel__find input{font-size:16px}   /* under 16px iOS zooms the page */
  .sel__pop--sheet .sel__typed{top:54px;margin:0 -8px 6px;padding:9px 20px}

  /* Rows sized for a thumb: 48px of target, not 38px. */
  .sel__opt{padding:14px 16px;border-radius:13px;font-size:.94rem}
  .sel__opt::before{left:6px;height:19px;margin-top:-9.5px}
  .sel__opt em{font-size:.8rem}
  .sel__none{padding:22px 16px}

  /* Faces get the same floor. The finder's sort control was styled down to
     sit beside the segmented buttons and came out at 36px on a phone. */
  .sel__btn{padding:14px 42px 14px 16px;font-size:.94rem}
  .find__sort.sel .sel__btn{padding:12px 34px 12px 16px;font-size:.86rem}
  .sel__btn,.sel__opt{-webkit-tap-highlight-color:transparent}
}

/* Touch has no hover, but it does leave :hover stuck on the last thing
   tapped — so the highlight is handed to :active and to the keyboard's own
   is-cur state, and the pointer rule is fenced off. */
@media (max-width:640px) and (hover:none){
  .sel__opt:hover{background:none;color:var(--sel-ink);padding-left:16px}
  .sel__opt:hover::before{transform:scaleY(0)}
  .sel__opt[aria-selected="true"]:hover{color:var(--gold)}
  .sel__opt[aria-selected="true"]:hover::before{transform:scaleY(1)}
  .sel__opt.is-cur,.sel__opt:active{background:var(--sel-hot);color:var(--sel-ink-hi)}
  .sel__opt:hover em{color:var(--sel-ink);opacity:.62}
}

@media (max-width:640px) and (prefers-reduced-motion:reduce){
  .sel__pop{transition:opacity .14s linear,visibility 0s .14s;opacity:0;transform:none}
  .sel__pop.is-open{opacity:1;transform:none;transition:opacity .14s linear,visibility 0s}
  .sel__veil{transition:opacity .14s linear}
}


/* ═══════════════════════════════════ THE NOTICE ═══════════════════════════
   The session announcement. Same shell language as the faculty and campus
   dialogs — a blurred veil, a dark box that rises — so it reads as part of
   the site rather than as a browser alert bolted on top.

   It carries real information: the live Cambridge series, the entry deadline
   for it, and the three admissions numbers. A banner that says "important
   notice" and then nothing is worse than no banner. */
.nx{
  position:fixed;inset:0;z-index:320;display:none;
  align-items:center;justify-content:center;padding:22px;
}
.nx.on{display:flex}
.nx__veil{
  position:absolute;inset:0;background:rgba(18,5,6,.62);
  -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
  opacity:0;transition:opacity .34s var(--ease);
}
.nx.in .nx__veil{opacity:1}
.nx__box{
  position:relative;width:min(560px,100%);max-height:88vh;overflow:auto;
  border-radius:var(--r);padding:clamp(26px,3.4vw,38px);
  background:var(--nx-fill);border:1px solid var(--nx-edge);
  box-shadow:0 40px 100px -34px rgba(0,0,0,.76);
  opacity:0;transform:translateY(20px) scale(.975);
  transition:opacity .38s var(--ease),transform .48s var(--out);
  isolation:isolate;
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .nx__box{-webkit-backdrop-filter:blur(26px) saturate(1.4);backdrop-filter:blur(26px) saturate(1.4)}
}
.nx.in .nx__box{opacity:1;transform:none}
/* The lit top edge the rest of the panels carry. */
.nx__box::before{
  content:"";position:absolute;inset:0 0 auto;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(243,221,164,.6) 26%,rgba(243,221,164,.6) 74%,transparent);
}
.nx__x{
  position:absolute;top:14px;right:14px;width:34px;height:34px;
  display:grid;place-items:center;border-radius:50%;
  background:rgba(243,234,220,.07);border:1px solid rgba(243,234,220,.16);
  color:rgba(243,234,220,.62);cursor:pointer;
  transition:color .2s,border-color .2s,background .2s,transform .24s var(--out);
}
.nx__x:hover{color:#FFF6E6;border-color:rgba(243,234,220,.34);background:rgba(243,234,220,.14);transform:rotate(90deg)}
.nx__x svg{width:14px;height:14px}

/* The pulsing dot. Slow — a fast blink reads as an error, and this is a
   deadline, not a fault. */
.nx__tag{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--gold);margin-bottom:16px;
}
.nx__tag i{
  width:7px;height:7px;border-radius:50%;background:var(--gold);
  box-shadow:0 0 0 0 rgba(201,152,47,.6);
  animation:nxPulse 2.6s var(--ease) infinite;
}
@keyframes nxPulse{
  0%{box-shadow:0 0 0 0 rgba(201,152,47,.55)}
  70%{box-shadow:0 0 0 11px rgba(201,152,47,0)}
  100%{box-shadow:0 0 0 0 rgba(201,152,47,0)}
}
.nx__box h3{
  font-family:var(--display);font-size:clamp(1.5rem,3vw,1.95rem);
  line-height:1.14;color:#FCF6EC;margin:0 0 12px;
}
.nx__box > p{font-size:.94rem;line-height:1.66;color:var(--nx-dim);margin:0 0 22px}

/* The countdown. Four cells, mono, so the digits do not jitter as they tick. */
.nx__cd{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;margin-bottom:22px}
.nx__cd div{
  padding:13px 6px;border-radius:var(--r-xs);text-align:center;
  background:rgba(201,152,47,.11);border:1px solid rgba(201,152,47,.24);
}
.nx__cd b{
  display:block;font-family:var(--mono);font-size:1.34rem;line-height:1;
  color:var(--gold-hi);font-weight:400;font-variant-numeric:tabular-nums;
}
.nx__cd span{
  display:block;margin-top:7px;font-family:var(--mono);
  font-size:.53rem;letter-spacing:.16em;text-transform:uppercase;color:var(--nx-faint);
}

.nx__rows{display:grid;gap:0;margin-bottom:24px}
.nx__rows div{
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:11px 0;border-bottom:1px solid var(--nx-edge);font-size:.86rem;
}
.nx__rows div:last-child{border-bottom:0}
.nx__rows dt{
  font-family:var(--mono);font-size:.58rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--nx-faint);margin:0;
}
.nx__rows dd{margin:0;color:#F6EEE0;text-align:right}
.nx__rows a{color:var(--gold-hi)}
.nx__rows a:hover{text-decoration:underline}

.nx__act{display:flex;gap:11px;flex-wrap:wrap}
/* The notice box is dark in both themes. */
.nx__go{
  --sv-fill:linear-gradient(180deg,rgba(224,233,247,.16),rgba(190,203,223,.055));
  --sv-fg:#F2F6FD;
  --sv-fg-sh:0 1px 2px rgba(0,0,0,.6);
  --sv-rim-hi:rgba(255,255,255,.95);
  --sv-rim-mid:rgba(210,223,242,.72);
  --sv-rim:rgba(152,168,192,.48);
  --sv-bevel:rgba(232,241,253,.58);
  --sv-bevel-2:rgba(232,241,253,.28);
  --sv-inner:rgba(216,230,248,.2);
  --sv-floor:rgba(0,0,0,.42);
  --sv-cast:rgba(0,0,0,.66);
  --sv-halo:rgba(172,188,210,.34);
  --sv-fx:blur(20px) saturate(.55) brightness(.92);
  flex:1 1 190px;display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:14px 22px;border-radius:99px;font-size:.9rem;font-weight:600;
  color:var(--sv-fg);text-shadow:var(--sv-fg-sh);
  background:var(--sv-fill);
  -webkit-backdrop-filter:var(--sv-fx);backdrop-filter:var(--sv-fx);
  border:0;cursor:pointer;
  box-shadow:var(--sv-lift);
  transition:transform .24s var(--out),box-shadow .3s var(--ease);
}
.nx__go:hover{transform:translateY(-2px);box-shadow:var(--sv-lift-hi)}
.nx__alt{
  flex:0 1 auto;display:inline-flex;align-items:center;justify-content:center;
  padding:14px 20px;border-radius:99px;font-size:.86rem;
  color:var(--nx-dim);background:rgba(243,234,220,.06);
  border:1px solid rgba(243,234,220,.16);cursor:pointer;
  transition:color .2s,border-color .2s,background .2s;
}
.nx__alt:hover{color:#FFF6E6;border-color:rgba(243,234,220,.32);background:rgba(243,234,220,.12)}

[data-theme="light"]{
  --nx-fill:rgba(36,13,12,.93);
  --nx-edge:rgba(243,221,164,.18);
  --nx-dim:rgba(246,238,224,.72);
  --nx-faint:rgba(246,238,224,.45);
}
[data-theme="dark"]{
  --nx-fill:rgba(26,8,10,.94);
  --nx-edge:rgba(226,148,152,.18);
  --nx-dim:rgba(246,232,216,.7);
  --nx-faint:rgba(246,232,216,.42);
}
@media (max-width:520px){
  .nx__cd{grid-template-columns:repeat(4,1fr);gap:6px}
  .nx__cd div{padding:10px 3px}
  .nx__cd b{font-size:1.08rem}
  .nx__act{flex-direction:column}
  /* flex-basis is measured along the MAIN axis. The moment this row flips to
     a column, `flex:1 1 190px` stopped meaning "at least 190px wide" and
     started meaning "190px TALL" — and with border-radius:99px on a box that
     tall, the gold CTA rendered as a lozenge the height of a paragraph. On a
     column the buttons want their content height and the full width. */
  .nx__go,.nx__alt{flex:0 0 auto;width:100%}
}
@media (prefers-reduced-motion:reduce){
  .nx__box{transition:opacity .16s linear}
  .nx.in .nx__box{transform:none}
  .nx__tag i{animation:none}
}


/* ═══════════════════════════════════ CORNER ADS ═══════════════════════════
   A rotating promo card that parks in a screen corner. One at a time, never
   two — a page with a card in every corner is a page nobody reads.

   The rules it runs on:
     · a card lives for ten minutes, then retires itself and the next one
       enters from a different corner
     · dismissing a card sends it away for three minutes, after which the
       rotation resumes
     · the corner advances each time, so the same spot is never used twice in
       a row and the card never becomes furniture
     · it stands down entirely on the enquiry section, where a floating card
       over a form is an obstacle rather than an offer

   The card is the same clear glass as the rail panels, so it belongs to the
   page instead of looking bought. */
.ad{
  position:fixed;z-index:58;width:min(320px,calc(100vw - 32px));
  border-radius:var(--r-sm);overflow:hidden;isolation:isolate;
  background:var(--ad-fill);border:1px solid var(--ad-edge);
  box-shadow:var(--ad-shadow);
  opacity:0;pointer-events:none;
  transition:opacity .5s var(--ease),transform .72s var(--out);
  will-change:transform,opacity;
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .ad{-webkit-backdrop-filter:var(--ad-fx);backdrop-filter:var(--ad-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .ad{background:var(--ad-solid)}
}
[data-perf="lite"] .ad{-webkit-backdrop-filter:none;backdrop-filter:none;background:var(--ad-solid)}

/* Corners. Each one parks the card off its own edge, so the entrance is a
   slide in from the nearest side rather than a fade in place. */
.ad--bl{left:22px;bottom:22px;transform:translateX(calc(-100% - 30px))}
.ad--br{right:22px;bottom:22px;transform:translateX(calc(100% + 30px))}
.ad--tr{right:22px;top:calc(var(--hdr) + 16px);transform:translateX(calc(100% + 30px))}
.ad--tl{left:22px;top:calc(var(--hdr) + 16px);transform:translateX(calc(-100% - 30px))}
.ad.in{opacity:1;transform:none;pointer-events:auto}
/* Leaving goes down and back rather than reversing the entrance — a card that
   retraces its own path reads as a mistake being undone. */
.ad.out{opacity:0;transform:translateY(26px) scale(.94);pointer-events:none}

.ad__lip{
  position:absolute;inset:0 0 auto;height:1px;pointer-events:none;z-index:3;
  background:linear-gradient(90deg,transparent,var(--ad-lip) 24%,var(--ad-lip) 76%,transparent);
}
/* The accent wash. Coloured by the card's own subject, so the Physics promo
   and the Accounts promo are not the same rectangle twice. */
.ad__wash{
  position:absolute;inset:0;z-index:-1;pointer-events:none;opacity:.5;
  background:radial-gradient(130% 100% at 8% 0%,var(--ad-acc,var(--gold)),transparent 62%);
  filter:blur(20px);
}
.ad__x{
  position:absolute;top:9px;right:9px;z-index:4;
  width:26px;height:26px;display:grid;place-items:center;border-radius:50%;
  background:var(--ad-xbg);border:1px solid var(--ad-edge);
  color:var(--text-3);cursor:pointer;
  transition:color .2s,transform .26s var(--out),background .2s,border-color .2s;
}
.ad__x:hover{color:var(--text-1);transform:rotate(90deg);background:var(--ad-xbg-2);border-color:var(--line-2)}
.ad__x svg{width:11px;height:11px}

.ad__in{display:flex;gap:14px;align-items:flex-start;padding:16px 40px 16px 16px}
/* The glyph. Real subject notation, drawn from the same motif set the lesson
   posters use, rather than a stock icon. */
.ad__ic{
  flex:0 0 auto;width:46px;height:46px;border-radius:12px;display:grid;place-items:center;
  background:color-mix(in srgb,var(--ad-acc,var(--gold)) 17%,transparent);
  border:1px solid color-mix(in srgb,var(--ad-acc,var(--gold)) 34%,transparent);
  color:var(--ad-acc,var(--gold));
}
.ad__ic svg{width:24px;height:24px}
.ad__tx{min-width:0;flex:1}
.ad__k{
  display:block;font-family:var(--mono);font-size:.53rem;letter-spacing:.19em;
  text-transform:uppercase;color:var(--ad-acc,var(--gold-text));margin-bottom:6px;
}
.ad__h{
  font-family:var(--display);font-size:1.08rem;line-height:1.2;
  color:var(--text-1);margin:0 0 5px;font-weight:600;
}
.ad__p{font-size:.79rem;line-height:1.55;color:var(--text-2);margin:0 0 11px}
.ad__go{
  display:inline-flex;align-items:center;gap:7px;
  font-size:.79rem;font-weight:500;color:var(--gold-text);
  transition:gap .26s var(--out),color .2s;
}
.ad__go:hover{gap:11px;color:var(--gold)}
.ad__go svg{width:13px;height:13px}

/* The life bar. Ten minutes drawn as a hairline that empties left to right —
   the card says how long it is staying instead of just leaving. */
.ad__life{
  position:absolute;left:0;right:0;bottom:0;height:2px;
  background:color-mix(in srgb,var(--ad-acc,var(--gold)) 16%,transparent);
  overflow:hidden;
}
.ad__life i{
  display:block;height:100%;width:100%;
  background:linear-gradient(90deg,var(--ad-acc,var(--gold)),var(--gold-hi));
  transform-origin:left center;
  animation:adLife var(--ad-life,600s) linear forwards;
}
@keyframes adLife{from{transform:scaleX(1)}to{transform:scaleX(0)}}
/* Hovering pauses the clock. Reading a card should not cost you the card. */
.ad:hover .ad__life i{animation-play-state:paused}

[data-theme="light"]{
  --ad-fill:rgba(255,253,248,.72);
  --ad-solid:#FDFAF3;
  --ad-fx:blur(26px) saturate(1.6);
  --ad-edge:rgba(36,16,15,.11);
  --ad-lip:rgba(255,255,255,.9);
  --ad-shadow:0 22px 52px -22px rgba(74,26,10,.44);
  --ad-xbg:rgba(36,16,15,.05);
  --ad-xbg-2:rgba(36,16,15,.11);
}
[data-theme="dark"]{
  --ad-fill:rgba(44,14,16,.68);
  --ad-solid:#231012;
  --ad-fx:blur(28px) saturate(1.4);
  --ad-edge:rgba(226,148,152,.16);
  --ad-lip:rgba(255,214,216,.32);
  --ad-shadow:0 26px 62px -22px rgba(0,0,0,.86);
  --ad-xbg:rgba(243,234,220,.06);
  --ad-xbg-2:rgba(243,234,220,.13);
}

/* On a phone the card takes the full width at the bottom and the corner
   rotation collapses to one slot — there is only one place a floating card
   can sit on a 360px screen without covering the content. It also lifts clear
   of the sticky tap bar where one is present. */
@media (max-width:700px){
  .ad{
    left:12px;right:12px;width:auto;
    top:auto!important;bottom:calc(12px + var(--ad-lift,0px));
  }
  .ad--bl,.ad--tl{transform:translateY(calc(100% + 26px))}
  .ad--br,.ad--tr{transform:translateY(calc(100% + 26px))}
  .ad__in{padding:14px 36px 14px 14px;gap:12px}
  .ad__ic{width:40px;height:40px}
  .ad__h{font-size:1rem}
}
/* The floating dock owns the bottom-left corner. Where both are on screen the
   card takes the other side rather than stacking on top of it. */
@media (min-width:701px){
  .ad--bl{left:calc(22px + var(--dock-w,138px))}
}
@media (prefers-reduced-motion:reduce){
  .ad{transition:opacity .2s linear}
  .ad--bl,.ad--br,.ad--tr,.ad--tl{transform:none}
  .ad.out{transform:none}
  .ad__life i{animation:none;transform:scaleX(0)}
}


/* ══════════════════════════════ THE DELIVERY BUTTON ═══════════════════════
   The last press of the enquiry does not just change its own label. The
   button hollows out — the filled face drains away and leaves the rim — the
   inside becomes a lit strip of carriageway, and the bus that has been
   running the far lane all along drives through it carrying the message.

   It is one element throughout. Nothing is swapped in, so there is no reflow
   at the moment of submit and the button never changes size; only what is
   painted inside it changes. */
.wiz__foot{position:relative}

/* Hollow. The liquid face and its specular are faded out and the rim is
   pushed to full gold, so the shape survives while the fill leaves. */
#wizNext.is-hollow{
  background:transparent!important;
  -webkit-backdrop-filter:none!important;backdrop-filter:none!important;
  box-shadow:inset 0 0 0 1.6px var(--gold),0 0 34px -12px rgba(201,152,47,.6)!important;
  cursor:default;pointer-events:none;
  transition:background .5s var(--ease),box-shadow .5s var(--ease),
             color .4s var(--ease);
}
#wizNext.is-hollow::after{opacity:0;transition:opacity .45s var(--ease)}
#wizNext.is-hollow::before{opacity:0;transition:opacity .45s var(--ease)}
/* The label goes first and comes back as the delivery line, so the two never
   overlap mid-fade. */
#wizNext.is-hollow .btn__lq{
  opacity:0;transform:translateY(-6px);
  transition:opacity .3s var(--ease),transform .3s var(--ease);
}

/* The carriageway inside the button. Clipped to the pill, so the road takes
   the button's own shape rather than sitting in a rectangle behind it. */
.dlv{
  position:absolute;inset:0;z-index:1;border-radius:inherit;overflow:hidden;
  pointer-events:none;opacity:0;
  transition:opacity .42s var(--ease);
}
#wizNext.is-hollow .dlv{opacity:1}
.dlv__deck{
  position:absolute;left:0;right:0;top:50%;height:0;
  margin-top:-1px;
  background:linear-gradient(180deg,var(--dlv-1),var(--dlv-2) 52%,var(--dlv-1));
  transition:height .52s var(--out),margin-top .52s var(--out);
}
/* The deck opens from a hairline to full height, which is what makes it read
   as a road being laid rather than a bar appearing. */
#wizNext.is-hollow .dlv__deck{height:22px;margin-top:-11px}
/* The dashes only start running once the deck has opened. */
.dlv__line{
  position:absolute;left:-30%;right:-30%;top:50%;height:2px;margin-top:-1px;
  background:repeating-linear-gradient(90deg,var(--dlv-paint) 0 14px,transparent 14px 32px);
  opacity:0;transition:opacity .3s .34s var(--ease);
}
#wizNext.is-hollow .dlv__line{opacity:1;animation:dlvRun 1.1s linear infinite}
@keyframes dlvRun{to{transform:translateX(-32px)}}

/* The bus. Enters from the left, crosses, exits right — one pass, matched to
   the length of the message it is carrying. */
.dlv__bus{
  position:absolute;top:50%;left:0;width:74px;
  transform:translate(-90px,-50%);
  filter:drop-shadow(0 4px 6px rgba(30,10,4,.5));
}
.dlv__bus svg{display:block;width:100%;height:auto}
#wizNext.is-hollow .dlv__bus{animation:dlvDrive 3.6s cubic-bezier(.36,0,.3,1) .5s forwards}
@keyframes dlvDrive{
  0%{transform:translate(-90px,-50%)}
  100%{transform:translate(calc(100% + 90px),-50%)}
}
/* A shallow bounce on the body only, so the wheels stay on the road while the
   shell rides the surface. */
.dlv__bus .dlv__body{animation:dlvJog .42s ease-in-out infinite}
@keyframes dlvJog{
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-.7px)}
}

/* The line the bus is carrying. Sits above the road, inside the same pill. */
.dlv__say{
  position:absolute;inset:0;z-index:2;display:grid;place-items:center;
  font-size:.84rem;font-weight:500;letter-spacing:.01em;
  color:var(--gold-hi);text-shadow:0 1px 8px rgba(20,6,2,.8);
  opacity:0;transform:translateY(7px);pointer-events:none;
  transition:opacity .4s var(--ease),transform .5s var(--out);
}
#wizNext.is-hollow .dlv__say{opacity:1;transform:none;transition-delay:.42s}
/* The three dots that follow the line while it is in flight. */
.dlv__say i{display:inline-block;width:0;overflow:hidden;vertical-align:bottom;
  animation:dlvDots 1.4s steps(4) infinite}
@keyframes dlvDots{to{width:1.1em}}

/* Delivered. The road closes, the line settles to a tick and the rim goes
   from gold to a held, brighter gold for a beat. */
#wizNext.is-done .dlv__deck{height:0;margin-top:-1px}
#wizNext.is-done .dlv__line{opacity:0}
#wizNext.is-done .dlv__say i{animation:none;width:0}
/* The coach has left by the time the receipt lands — its own animation ends
   off the right edge and holds there. Hidden outright as well, so a paused or
   interrupted run cannot leave it parked on top of the finished state. */
#wizNext.is-done .dlv__bus{opacity:0;transition:opacity .3s var(--ease)}
/* Once the road has closed there is nothing below the line to make room for,
   so the padding that held the message clear of the carriageway comes off and
   the receipt sits in the middle of the button. */
#wizNext.is-done .dlv__say{padding-bottom:0;transition:padding-bottom .5s var(--out),opacity .4s var(--ease)}
#wizNext.is-done{
  box-shadow:inset 0 0 0 1.6px var(--gold-hi),0 0 48px -10px rgba(201,152,47,.75)!important;
}

:root,[data-theme="light"]{
  --dlv-1:#3A2A22;--dlv-2:#4C392E;--dlv-paint:rgba(255,244,214,.7);
}
[data-theme="dark"]{
  --dlv-1:#160B0C;--dlv-2:#231314;--dlv-paint:rgba(255,236,190,.6);
}
@media (prefers-reduced-motion:reduce){
  .dlv__bus,#wizNext.is-hollow .dlv__bus{animation:none;display:none}
  .dlv__line,#wizNext.is-hollow .dlv__line{animation:none}
  .dlv__say i{animation:none}
  .dlv__deck,#wizNext.is-hollow .dlv__deck{transition:none}
}

/* ══════════════════════════════════════════ THE LESSON PAGE ═══════════════
   Everything above this point is the shared sheet, byte-identical to the one
   the index loads. Only what is unique to a lesson lives below: the player,
   the chapter rail and the two-column split they sit in. */
.lec{padding-top:calc(var(--hdr) + clamp(26px,4vw,52px))}
.lec__crumb{
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  font-size:.82rem;color:var(--text-3);margin-bottom:24px;
}
.lec__crumb a{transition:color .2s var(--ease)}
.lec__crumb a:hover{color:var(--gold-text)}
.lec__crumb span[aria-current]{color:var(--text-2)}
.lec__top{
  display:grid;grid-template-columns:1.55fr .95fr;
  gap:clamp(24px,3vw,40px);align-items:start;
}

/* ---- the player ----
   Built on the same clear glass as the rail cards rather than the opaque
   panel it used to sit on, so the aura behind the page reads through its
   edges the way it does everywhere else. */
.player{
  --acc:var(--gold);
  position:relative;border-radius:var(--r);overflow:hidden;isolation:isolate;
  background:var(--clear-fill);border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow-hi);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .player{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .player{background:var(--clear-solid)}
}
[data-perf="lite"] .player{-webkit-backdrop-filter:none;backdrop-filter:none;background:var(--clear-solid)}
.player::before{
  content:"";position:absolute;inset:0 0 auto;height:1px;z-index:4;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--clear-rim) 22%,var(--clear-rim) 78%,transparent);
}
.player__st{position:relative;aspect-ratio:16/9;background:var(--bg-2);cursor:pointer;overflow:hidden}
.player__st svg.poster{position:absolute;inset:0;width:100%;height:100%}
.player__veil{
  position:absolute;inset:0;display:grid;place-items:center;
  background:var(--veil);transition:opacity .35s var(--ease);
}
.player.playing .player__veil{opacity:0}
.player.playing:hover .player__veil{opacity:1}
/* The lecture page redefines the play badge to add a hover shadow, and being
   later in the sheet it was quietly overriding the argent conversion above —
   the one gold face left on the site. Converted here too. */
.player__big{
  width:84px;height:84px;border-radius:50%;display:grid;place-items:center;
  background:var(--sv-fill-solid);color:var(--sv-fg-solid);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  font-size:1.4rem;padding-left:5px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.72),
             0 18px 46px -14px rgba(20,30,46,.82);
  transition:transform .35s var(--spring),box-shadow .35s var(--ease);
}
.player__st:hover .player__big{
  transform:scale(1.1);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.8),
             0 22px 56px -12px rgba(20,30,46,.9);
}
.player.playing .player__big{padding-left:0;font-size:1.15rem}
.player__bar{
  position:absolute;left:0;right:0;bottom:0;padding:14px 18px;z-index:3;
  background:var(--veil-bar);display:grid;gap:9px;
}
.player__t{height:4px;border-radius:99px;background:rgba(255,255,255,.2);cursor:pointer;position:relative}
.player__f{
  height:100%;width:0;border-radius:99px;position:relative;
  background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));
}
.player__f::after{
  content:"";position:absolute;top:50%;right:-1px;width:11px;height:11px;
  border-radius:50%;background:var(--gold-hi);transform:translate(50%,-50%);
  box-shadow:0 0 10px rgba(243,221,164,.9);
}
.player__row{
  display:flex;align-items:center;gap:14px;
  font-family:var(--mono);font-size:.72rem;color:var(--veil-ink);
}
.player__row button{
  color:inherit;display:grid;place-items:center;width:26px;height:26px;
  border-radius:6px;transition:background .2s var(--ease),transform .2s var(--out);
}
.player__row button:hover{background:rgba(255,255,255,.14);transform:translateY(-1px)}
.player__row .sp{margin-left:auto}
.player__meta{padding:20px 22px;display:grid;gap:9px;border-top:1px solid var(--edge)}
.player__meta h1{font-size:clamp(1.45rem,2.4vw,2rem);margin:0}
.player__chips{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px}
.player__chips span{
  font-size:.68rem;padding:5px 11px;border-radius:99px;
  border:1px solid var(--line);color:var(--text-3);
}
.player__chips span.code{
  font-family:var(--mono);color:var(--acc);
  border-color:color-mix(in srgb,var(--acc) 45%,transparent);
}

/* ---- the chapter rail ---- */
.chaps{display:grid;gap:2px;max-height:474px;overflow:auto;padding-right:4px;
       scrollbar-width:thin;scrollbar-color:var(--gold-lo) transparent}
.chaps::-webkit-scrollbar{width:7px}
.chaps::-webkit-scrollbar-thumb{background:var(--gold-lo);border-radius:99px}
.chap{
  position:relative;display:flex;gap:14px;align-items:flex-start;
  padding:14px 15px;border-radius:var(--r-xs);
  cursor:pointer;text-align:left;width:100%;
  transition:background .22s var(--ease),padding-left .24s var(--out);
}
.chap:hover{background:rgba(201,152,47,.1);padding-left:19px}
.chap.on{background:rgba(201,152,47,.16)}
/* The same gold spine the dropdown uses for its chosen row, so "this is the
   one you are on" is one visual idea across the whole site. */
.chap::before{
  content:"";position:absolute;left:5px;top:50%;width:2.5px;height:17px;
  margin-top:-8.5px;border-radius:99px;background:var(--gold);
  transform:scaleY(0);transition:transform .26s var(--spring);
}
.chap.on::before{transform:scaleY(1)}
.chap__n{font-family:var(--mono);font-size:.7rem;color:var(--gold-text);flex:0 0 auto;padding-top:2px}
.chap__b{display:grid;gap:3px;min-width:0}
.chap__b b{font-weight:400;font-size:.9rem}
.chap__b small{font-size:.74rem;color:var(--text-3)}
.chap__t{margin-left:auto;font-family:var(--mono);font-size:.7rem;color:var(--text-3);flex:0 0 auto}

/* ══════════════════════════════════ THE COURSE ════════════════════════════
   The lecture list. One row per lecture in the teacher's course, with the
   free one open and the rest closed.

   A locked row is deliberately not greyed out into unreadability. The point
   of showing eight locked lectures is that a visitor can see exactly what
   they would be paying for — a list of blurred titles sells nothing. So the
   title stays fully legible and only the *affordance* changes: no spine, a
   padlock where the number was, and a hover that reveals the one thing the
   row actually does, which is start a conversation with admissions. */
.crs{display:grid;gap:3px}
.crs__row{
  position:relative;display:flex;gap:13px;align-items:center;
  padding:13px 14px;border-radius:var(--r-xs);
  text-align:left;width:100%;cursor:pointer;
  transition:background .22s var(--ease),padding-left .24s var(--out);
}
.crs__row:hover{background:rgba(226,232,242,.07);padding-left:18px}
[data-theme="light"] .crs__row:hover{background:rgba(40,52,70,.05)}

/* The free lecture. It is the one the visitor is already watching, so it
   carries the same spine the chapter list uses for "you are here". */
.crs__row--free{background:rgba(201,152,47,.13)}
.crs__row--free::before{
  content:"";position:absolute;left:5px;top:50%;width:2.5px;height:17px;
  margin-top:-8.5px;border-radius:99px;background:var(--gold);
}
.crs__row--free:hover{background:rgba(201,152,47,.18)}

/* The marker column: a number for the free lecture, a padlock for the rest. */
.crs__k{
  flex:0 0 auto;width:22px;height:22px;display:grid;place-items:center;
  font-family:var(--mono);font-size:.68rem;color:var(--gold-text);
}
.crs__k svg{width:13px;height:13px;color:var(--text-3);transition:color .22s var(--ease)}
.crs__row:hover .crs__k svg{color:var(--sv-rim-hi)}

.crs__b{display:grid;gap:3px;min-width:0;flex:1 1 auto}
.crs__b b{font-weight:400;font-size:.88rem;line-height:1.35;color:var(--text-1)}
.crs__b small{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text-3);
}
.crs__row--free .crs__b small{color:var(--gold-text)}
.crs__t{
  margin-left:auto;flex:0 0 auto;
  font-family:var(--mono);font-size:.68rem;color:var(--text-3);
}
/* The prompt that replaces the runtime on hover. Both are in the row at all
   times and cross-fade, so the row does not change width as the pointer
   crosses it and the list does not jitter. */
.crs__t i{font-style:normal}
.crs__t u{
  display:none;text-decoration:none;color:var(--sv-rim-hi);
  letter-spacing:.06em;
}
.crs__row:hover .crs__t i{display:none}
.crs__row:hover .crs__t u{display:inline}

/* The line under the list that says what the locked rows are. */
.crs__foot{
  margin:14px 9px 0;padding-top:13px;border-top:1px solid var(--line);
  font-size:.78rem;line-height:1.6;color:var(--text-3);
}
.crs__foot b{color:var(--text-2);font-weight:500}

/* The free/paid badge on the player. */
.player__free{
  display:inline-flex;align-items:center;gap:7px;
  padding:5px 11px 5px 9px;border-radius:99px;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--gold-hi);
  background:rgba(201,152,47,.14);border:1px solid rgba(201,152,47,.3);
}
.player__free svg{width:12px;height:12px}

/* ---- the side column ---- */
.lec__side{display:grid;gap:16px;position:sticky;top:calc(var(--hdr) + 20px)}
.lec__tut{display:flex;align-items:center;gap:15px;padding:20px 22px}
.lec__tut .med{
  width:60px;height:60px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
  font-family:var(--display);font-size:1.35rem;font-weight:600;
  border:2px solid var(--acc,var(--gold));color:var(--acc,var(--gold));
  background:color-mix(in srgb,var(--acc,var(--gold)) 12%,transparent);
}
.lec__dl{display:grid;gap:10px}
.lec__dl a{
  display:flex;align-items:center;gap:12px;padding:13px 15px;border-radius:var(--r-xs);
  border:1px solid var(--line);font-size:.87rem;
  transition:border-color .22s var(--ease),background .22s var(--ease),transform .22s var(--out);
}
.lec__dl a:hover{border-color:var(--gold);background:rgba(201,152,47,.09);transform:translateX(3px)}
.lec__dl i{font-style:normal;color:var(--gold-text)}

/* ---- the sticky tap bar ----
   Phone only. Two things the visitor is most likely to want next, held at the
   bottom of the screen so neither costs a scroll back to the header. */
.tapbar{
  position:fixed;left:0;right:0;bottom:0;z-index:70;display:none;gap:10px;
  padding:11px 16px calc(11px + env(safe-area-inset-bottom));
  /* Its own fill, not the shared --panel. The panels were made considerably
     more transparent so the aura reads through them, which is right for a
     card sitting in the page and wrong for a bar pinned over scrolling
     content — at panel opacity the paragraph underneath showed straight
     through the labels. This one stays dense enough to read against
     anything that passes behind it. */
  background:var(--tap-fill);border-top:1px solid var(--line);
  box-shadow:0 -12px 30px -18px rgba(40,14,6,.5);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .tapbar{-webkit-backdrop-filter:blur(22px) saturate(1.4);backdrop-filter:blur(22px) saturate(1.4)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .tapbar{background:var(--panel-solid)}
}
[data-perf="lite"] .tapbar{-webkit-backdrop-filter:none;backdrop-filter:none;background:var(--panel-solid)}
/* ---- player: real video, the site's own controls under the picture ---- */
.player__yt{position:absolute;inset:0;z-index:1;display:none;background:#000}
.player__yt iframe,.player__yt > div{width:100%;height:100%;display:block;border:0}
.player.is-live .player__yt{display:block}
.player.is-live #poster,.player.is-live .player__veil{display:none}
.player.is-live .player__st{cursor:default}
.player.is-loading .player__yt::after{
  content:"";position:absolute;left:50%;top:50%;width:34px;height:34px;margin:-17px 0 0 -17px;
  border-radius:50%;border:3px solid rgba(255,255,255,.25);border-top-color:var(--gold-hi);
  animation:plSpin .8s linear infinite;pointer-events:none;
}
@keyframes plSpin{to{transform:rotate(360deg)}}
.player__big svg{width:30px;height:30px;margin-left:3px}
.player.playing .player__big svg{margin-left:0}
.player__soon{
  position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:4;
  width:min(92%,420px);padding:12px 16px;border-radius:14px;text-align:center;
  background:rgba(18,12,10,.82);color:#F4EBDD;display:grid;gap:3px;
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
}
.player__soon[hidden]{display:none}
.player__soon b{font-family:var(--display);font-weight:600;font-size:1rem}
.player__soon span{font-size:.76rem;line-height:1.45;opacity:.85}
.player__soon.nudge{animation:plNudge .45s var(--out)}
@keyframes plNudge{0%,100%{transform:translateX(-50%)}30%{transform:translateX(calc(-50% - 7px))}60%{transform:translateX(calc(-50% + 6px))}}
.player__bar{position:relative;left:auto;right:auto;bottom:auto;z-index:3;
  padding:12px 16px 12px;background:linear-gradient(180deg,#1C1411,#120D0B);gap:10px}
.player__t{height:5px}
.player__t:hover{height:7px;margin-block:-1px}
.player__row{gap:6px}
.player__row button{width:36px;height:36px;border-radius:9px}
.player__row button svg{width:19px;height:19px}
.player__row .player__txt{width:auto;padding:0 10px;font-family:var(--mono);font-size:.72rem}
.player__time{margin-left:6px;white-space:nowrap}
#btnMute .x{display:none}
#btnMute.is-muted .x{display:inline}
#btnMute.is-muted .w{display:none}
.player.no-video .player__bar{opacity:.8}
.player.no-video .player__veil{display:none}
.player.no-video .player__soon{top:50%;bottom:auto;transform:translate(-50%,-50%)}
.player.no-video .player__soon.nudge{animation:none}
[data-theme="light"] .player__free{color:var(--gold-text);background:rgba(201,152,47,.12);border-color:rgba(154,111,18,.35)}
.player:fullscreen{display:flex;flex-direction:column;background:#000;border-radius:0}
.player:fullscreen .player__st{flex:1;aspect-ratio:auto}
.player:fullscreen .player__meta{display:none}
.player:-webkit-full-screen{display:flex;flex-direction:column;background:#000}
.player:-webkit-full-screen .player__st{flex:1;aspect-ratio:auto}
.player:-webkit-full-screen .player__meta{display:none}
.crs__row--free{width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer}
.crs__more{display:block;font-size:.82rem;line-height:1.55;color:var(--text-2);margin:4px 0 12px}
.crs__more b{color:var(--text-1);font-weight:600}
.crs__join{margin-top:2px}
.crs__row--free.is-on{cursor:default}
/* phones: the lecture, then the course list, then the rest */
@media (max-width:1000px){
  .lec__top{display:flex;flex-direction:column;align-items:stretch;gap:16px}
  .lec__top > div:first-child,.lec__side{display:contents}
  .lec__top > div:first-child > *,.lec__side > *{width:100%;min-width:0;max-width:none}
  .lec__o1{order:1}.lec__o2{order:2;margin:0 !important}.lec__o3{order:3}.lec__o4{order:4}
  .lec__o5{order:5;margin-top:0 !important}.lec__o6{order:6}.lec__o7{order:7}
}
@media (max-width:560px){
  .player{margin-inline:0}
  .player__bar{padding:10px 10px}
  .player__row{gap:2px}
  .player__row button{width:34px;height:34px}
  .player__meta{padding:16px 16px}
  .player__meta h1{font-size:1.35rem}
  .player__free{font-size:.56rem}
}
[data-theme="light"]{--tap-fill:rgba(250,246,238,.94)}
[data-theme="dark"]{--tap-fill:rgba(26,10,11,.94)}
.tapbar .btn{flex:1}

@media (max-width:1000px){
  .lec__top{grid-template-columns:1fr}
  .lec__side{position:static}
}


/* ══════════════════════════════════════════════════════════════════════════
   THE FOOTER, COMPACTED
   Every measurement above was set for a footer that closed a single very long
   page, where a deep block of air read as a proper ending. Across four shorter
   pages the same block is just distance between the last sentence and the
   next tap, and on a phone — where the four columns stack — it was running to
   most of a screen on its own.

   Nothing is removed here. The columns, the lockup, the SWK card and the bar
   all stay; the space between them comes down to roughly two fifths of what
   it was, and on a phone the three link columns pack two-up instead of
   stacking, which is where most of the height was going.
   ══════════════════════════════════════════════════════════════════════════ */
.foot{padding-block:clamp(20px,2.2vw,32px) 13px}
.foot__g{gap:clamp(13px,1.5vw,22px)}
.foot__lock{margin-bottom:7px}
.foot__g h4{margin-bottom:7px}
.foot__g li{margin-bottom:4px}
.foot__swk{margin-top:9px;padding:8px 11px;gap:10px}
.foot__bar{margin-top:clamp(13px,1.5vw,22px);padding-top:11px}

@media (max-width:760px){
  .foot{padding-block:15px 9px}
  /* Four stacked columns were the whole problem. The brand block keeps the
     full width it needs for the lockup and the SWK card; the three link lists
     underneath it sit two across, which folds three column-heights into two. */
  .foot__g{grid-template-columns:repeat(2,minmax(0,1fr));gap:11px 16px}
  .foot__brand{grid-column:1/-1}
  .foot__col--contact{grid-column:1/-1}
  .foot__col--contact ul{display:flex;flex-wrap:wrap;gap:2px 18px}
  .foot__g h4{margin-bottom:5px}
  .foot__g li{margin-bottom:2px}
  .foot__g li a{font-size:.736rem}
  .foot__lock{margin-bottom:5px}
  .foot__blurb{max-width:none}
  .foot__swk{margin-top:7px;padding:7px 9px;gap:9px;max-width:none}
  .foot__swk img{width:27px;height:27px}
  .foot__bar{margin-top:11px;padding-top:8px;gap:4px}
}

/* ══════════════════════════════════════════════════════════════════════════
   THE DISTINCTION STRIP
   Every card carries its teacher's citations; only the three-up band has the
   width to print them. In the roster grid they stay hidden, because four
   lines of small caps under sixteen cards is noise, not evidence.
   ══════════════════════════════════════════════════════════════════════════ */
.fac__dist{display:none}
.facgrid--dist .fac__dist{
  display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 2px}
.facgrid--dist .fac__dist i{
  font-style:normal;font-family:var(--mono);font-size:.598rem;letter-spacing:.07em;
  line-height:1.5;padding:4px 9px;border-radius:999px;
  color:var(--gold-text);background:color-mix(in srgb,var(--acc,#C9982F) 11%,transparent);
  border:1px solid color-mix(in srgb,var(--acc,#C9982F) 30%,transparent)}
@media (max-width:640px){
  .facgrid--dist .fac__dist{gap:5px;margin:8px 0 2px}
  .facgrid--dist .fac__dist i{font-size:.566rem;padding:3px 8px}
}



/* ══════════════════════════════════════════════════════════════════════════
   VIDEO INSIDE THE REVIEW CARD
   The clip sits where the quote sits, in the same card, on the same rail —
   so a video review and a written one are the same object with the same
   frame, rather than two sections saying the same thing twice.

   Until it is pressed the pane is a still and a play button. On press it
   becomes the player in place, at the same size, so nothing below it moves.
   ══════════════════════════════════════════════════════════════════════════ */
.rev__vid{
  /* 16:9, matching the footage. The box was 16:10, which meant object-fit had
     to shave a sliver off each side of every clip to fill it — a crop nobody
     asked for, on footage that has already been cropped once. */
  position:relative;display:block;width:100%;aspect-ratio:16/9;margin:0 0 15px;
  border-radius:var(--r-xs);overflow:hidden;cursor:pointer;
  background:var(--maroon-dp);border:1px solid var(--line);
  transition:border-color .3s var(--ease)}
.rev__vid:hover,.rev__vid:focus-visible{border-color:var(--gold);outline:none}
.rev__vid img,.rev__vid iframe,.rev__vid video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border:0;display:block}
.rev__vid::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(10,3,4,.6),rgba(10,3,4,0) 62%)}
.rev__vid.is-live{cursor:default;border-color:color-mix(in srgb,var(--gold) 48%,transparent)}
.rev__vid.is-live::after{display:none}
.rev__play{
  position:absolute;left:50%;top:50%;translate:-50% -50%;z-index:2;
  width:54px;height:54px;border-radius:50%;display:grid;place-items:center;
  color:var(--maroon-dp);background:var(--gold);
  box-shadow:0 10px 28px -10px rgba(0,0,0,.72);
  transition:scale .4s var(--spring)}
.rev__vid:hover .rev__play,.rev__vid:focus-visible .rev__play{scale:1.09}
.rev__vid.is-live .rev__play{display:none}
.rev__play svg{width:20px;height:20px;margin-left:3px;fill:currentColor}
@media (max-width:860px){
  .rev__vid{margin-bottom:13px}
  .rev__play{width:46px;height:46px}
  .rev__play svg{width:17px;height:17px}
}




/* ══════════════════════════════════════════════════════════════════════════
   THE MATHEMATICS DISTINCTION BOARD
   Three plinths, each carrying its citation written out — "Top in the World
   Distinction", not a badge reading "World". A capsule was never going to
   hold that phrase, and shrinking the phrase to fit the capsule was the wrong
   way round: the citation is the whole point of the section.

   The plinths are level and the portraits are one size. Two of these results
   are identical, so raising one above the other would be inventing a ranking
   the school would then have to defend. What does differ is real: a Top in
   the World portrait carries a second gold ring, and its plinth face is lit
   a shade warmer.

   Every tile is a button; pressing one opens the student's panel, which
   borrows .fdlg wholesale so it is the same sheet the founder's message uses.
   ══════════════════════════════════════════════════════════════════════════ */
.pod{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));align-items:stretch;
  gap:clamp(10px,1.6vw,22px);max-width:820px;margin:0 auto clamp(26px,3.4vw,44px)}
.pod__c{
  position:relative;display:flex;flex-direction:column;align-items:center;
  padding:0;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:center}
.pod__crown{margin:0 auto 8px;width:19px;height:19px;color:var(--gold-hi);display:block}
.pod__c:not(.has-w) .pod__crown{visibility:hidden}
.pod__av{
  position:relative;width:clamp(76px,9.6vw,98px);height:clamp(76px,9.6vw,98px);
  margin:0 auto 13px;border-radius:50%;overflow:hidden;display:grid;place-items:center;
  background:linear-gradient(155deg,var(--maroon),var(--maroon-dp));
  box-shadow:0 0 0 1px color-mix(in srgb,var(--gold) 46%,transparent);
  transition:transform .55s var(--spring),box-shadow .45s var(--out)}
.pod__av--w{
  box-shadow:0 0 0 2px var(--gold),0 0 0 8px color-mix(in srgb,var(--gold) 12%,transparent),
             0 16px 36px -18px rgba(0,0,0,.78)}
.pod__c:hover .pod__av,.pod__c:focus-visible .pod__av{transform:translateY(-5px)}
.pod__av img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
/* Painted on the medallion, not on the page: --gold-text goes dark under the
   light theme and put dark lettering on a dark oxblood disc. */
.pod__ini{font-family:var(--display);font-size:1.62rem;font-weight:600;color:var(--gold-on-dark)}
.pod__nm{display:block;font-family:var(--display);font-size:1.02rem;font-weight:600;
  line-height:1.25;margin-bottom:3px}
.pod__sb{display:block;font-size:.675rem;color:var(--text-3);line-height:1.45;margin-bottom:12px}
.pod__p{
  position:relative;margin-top:auto;width:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  min-height:clamp(74px,8.4vw,92px);padding:15px 12px 17px;
  border-radius:14px 14px 0 0;
  background:linear-gradient(180deg,color-mix(in srgb,var(--gold) 13%,transparent),
                                    color-mix(in srgb,var(--gold) 2%,transparent));
  border:1px solid color-mix(in srgb,var(--gold) 26%,transparent);border-bottom:0;
  transition:border-color .35s var(--ease),background .35s var(--ease)}
.pod__p--w{
  background:linear-gradient(180deg,color-mix(in srgb,var(--gold) 20%,transparent),
                                    color-mix(in srgb,var(--gold) 3%,transparent));
  border-color:color-mix(in srgb,var(--gold) 42%,transparent)}
.pod__c:hover .pod__p{border-color:var(--gold)}
.pod__cite{
  font-family:var(--display);font-size:clamp(.84rem,1.5vw,1.02rem);font-weight:600;
  line-height:1.25;color:var(--gold-hi);text-wrap:balance;max-width:15ch}
.pod__p:not(.pod__p--w) .pod__cite{color:var(--gold)}
.pod__code{
  font-family:var(--mono);font-size:.578rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-3)}

.lb{display:flex;flex-direction:column;gap:9px;max-width:820px;margin:0 auto}
.lb__r{
  display:flex;align-items:center;gap:13px;width:100%;
  padding:11px 18px 11px 12px;border-radius:13px;text-align:left;
  background:var(--panel);border:1px solid var(--line);font:inherit;color:inherit;cursor:pointer;
  transition:border-color .3s var(--ease),transform .45s var(--out),background .3s var(--ease)}
.lb__r:hover,.lb__r:focus-visible{
  border-color:color-mix(in srgb,var(--gold) 50%,transparent);
  background:color-mix(in srgb,var(--gold) 6%,transparent);transform:translateX(3px)}
.lb__no{flex:0 0 auto;width:22px;text-align:center;font-family:var(--mono);font-size:.735rem;color:var(--text-3)}
.lb__av{
  position:relative;flex:0 0 auto;width:42px;height:42px;border-radius:50%;overflow:hidden;
  display:grid;place-items:center;
  background:linear-gradient(155deg,var(--maroon),var(--maroon-dp));
  border:1px solid color-mix(in srgb,var(--gold) 28%,transparent)}
.lb__av img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.lb__av .pod__ini{font-size:.885rem}
.lb__x{flex:1 1 auto;min-width:0}
.lb__nm{display:block;font-weight:500;font-size:.85rem;line-height:1.3}
.lb__sb{display:block;font-size:.675rem;color:var(--text-3)}
.lb__cite{
  flex:0 0 auto;text-align:right;max-width:13ch;
  font-family:var(--display);font-size:.9rem;font-weight:600;line-height:1.25;
  color:var(--gold);text-wrap:balance}
.lb__cite--w{color:var(--gold-hi)}

.ach__note{
  max-width:820px;margin:clamp(20px,2.4vw,30px) auto 0;padding-top:15px;
  border-top:1px solid var(--line);
  text-align:center;font-size:.745rem;line-height:1.6;color:var(--text-3)}
.ach__note a{color:var(--gold-text);text-decoration:none;border-bottom:1px solid transparent;
  transition:border-color .3s var(--ease)}
.ach__note a:hover{border-bottom-color:var(--gold)}

@media (max-width:720px){
  /* Three plinths across a phone leaves four characters a line. One column,
     and the plinth becomes a footing under each portrait instead. */
  .pod{grid-template-columns:1fr;gap:12px;max-width:420px}
  .pod__c{flex-direction:row;align-items:center;gap:13px;text-align:left;
    background:var(--panel);border:1px solid var(--line);border-radius:13px;padding:12px 14px}
  .pod__crown{display:none}
  .pod__av{width:54px;height:54px;margin:0;flex:0 0 auto}
  .pod__ini{font-size:1.15rem}
  .pod__nm{font-size:.9rem;margin-bottom:1px}
  .pod__sb{font-size:.63rem;margin-bottom:0}
  .pod__p{margin:0;width:auto;flex:0 0 auto;min-height:0;padding:0;gap:2px;
    background:none;border:0;align-items:flex-end;text-align:right;margin-left:auto}
  .pod__cite{font-size:.8rem;max-width:11ch}
  .pod__code{font-size:.53rem}
  .lb__r{gap:10px;padding:10px 14px 10px 9px}
  .lb__av{width:36px;height:36px}
  .lb__av .pod__ini{font-size:.8rem}
  .lb__cite{font-size:.8rem;max-width:11ch}
}

#adlg .fdlg__facts b{font-family:var(--display);font-size:1.02rem;line-height:1.25}


/* ══════════════════════════════════════════════════════════════════════════
   THE SWK CREDIT PANEL
   A seal, a sentence and three facts. The device is the hairline between the
   two columns: it makes the mark read as a seal pressed into a document
   rather than an icon sitting next to a paragraph.

   The lockup is one object — mark, "a project of", the name, the line under
   it. When the panel stacks, it turns on its side and stays one object,
   instead of the eyebrow drifting up beside the mark while the name falls
   below it.

   Depth is a single wash from the top left and the mark itself ghosted large
   at the right edge. No glow, no shadow, no second gradient: those are what
   make a panel like this read as an advertisement dropped into the page.
   ══════════════════════════════════════════════════════════════════════════ */
.swkp{
  position:relative;isolation:isolate;overflow:hidden;
  display:grid;grid-template-columns:minmax(0,252px) minmax(0,1fr);
  gap:clamp(20px,3vw,46px);align-items:center;
  padding:clamp(24px,3vw,40px) clamp(22px,3.2vw,42px);
  border:1px solid color-mix(in srgb,var(--gold) 24%,transparent);
  border-radius:var(--r-sm);
  background:var(--panel);
  -webkit-backdrop-filter:var(--panel-fx);backdrop-filter:var(--panel-fx);
  transition:border-color .45s var(--ease),transform .6s var(--out)}
.swkp:hover{border-color:color-mix(in srgb,var(--gold) 48%,transparent);transform:translateY(-2px)}
/* The wash. */
.swkp::before{
  content:"";position:absolute;inset:0;z-index:-2;pointer-events:none;
  background:radial-gradient(118% 150% at 6% -10%,
    color-mix(in srgb,var(--gold) 14%,transparent), transparent 60%)}
/* The mark, ghosted large at the right edge — the panel's only ornament, and
   it is the client's own artwork rather than an invented flourish. */
.swkp::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  right:-44px;top:50%;translate:0 -50%;width:300px;height:300px;
  background:url("swk.png") center/contain no-repeat;
  opacity:.045;filter:grayscale(1) brightness(2.4)}
/* A gold seam along the top edge, brightest where the wash begins. */
.swkp__seam{
  position:absolute;left:0;right:0;top:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--gold) 68%,transparent), transparent 52%)}

.swkp__side{
  display:flex;flex-direction:column;align-items:flex-start;gap:15px;
  padding-right:clamp(18px,2.6vw,36px);
  border-right:1px solid color-mix(in srgb,var(--gold) 22%,transparent)}
.swkp__medal{
  flex:0 0 auto;width:70px;height:70px;border-radius:18px;
  display:grid;place-items:center;
  background:color-mix(in srgb,var(--gold) 9%,transparent);
  border:1px solid color-mix(in srgb,var(--gold) 30%,transparent);
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--gold-hi) 24%,transparent);
  transition:border-color .45s var(--ease)}
.swkp:hover .swkp__medal{border-color:color-mix(in srgb,var(--gold) 58%,transparent)}
.swkp__medal img{width:46px;height:46px;object-fit:contain;display:block}
.swkp__id{display:flex;flex-direction:column;gap:3px;min-width:0}
.swkp__k{
  font-family:var(--mono);font-size:.578rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--gold-text)}
.swkp__nm{
  font-family:var(--display);font-size:clamp(1.26rem,2.1vw,1.66rem);font-weight:600;
  line-height:1.14;color:var(--text-1)}
.swkp__tag{font-size:.755rem;color:var(--text-3);line-height:1.5;margin-top:1px}

.swkp__lede{
  font-size:.885rem;line-height:1.74;color:var(--text-2);
  margin:0 0 clamp(17px,2.1vw,23px);max-width:60ch;text-wrap:pretty}
.swkp__stats{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  padding:clamp(14px,1.7vw,19px) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  margin-bottom:clamp(16px,2vw,22px)}
/* Ticks between the facts rather than gaps: three numbers with air around
   them read as three unrelated numbers. */
.swkp__stats div{padding:0 clamp(12px,1.6vw,20px)}
.swkp__stats div:first-child{padding-left:0}
.swkp__stats div:last-child{padding-right:0}
.swkp__stats div + div{border-left:1px solid color-mix(in srgb,var(--gold) 17%,transparent)}
.swkp__stats b{
  display:block;font-family:var(--display);font-size:clamp(1.04rem,1.7vw,1.3rem);
  font-weight:600;color:var(--gold-hi);line-height:1.2;margin-bottom:4px}
.swkp__stats span{display:block;font-size:.69rem;color:var(--text-3);line-height:1.45}
.swkp__act{display:flex}

@media (max-width:820px){
  .swkp{grid-template-columns:1fr;gap:clamp(17px,3vw,23px);padding:22px 20px}
  .swkp::after{right:-70px;width:230px;height:230px;opacity:.035}
  /* On its side, and still one object: mark left, the whole lockup right,
     both centred against each other. */
  .swkp__side{
    flex-direction:row;align-items:center;gap:15px;
    padding:0 0 clamp(16px,2.6vw,21px);
    border-right:0;border-bottom:1px solid color-mix(in srgb,var(--gold) 22%,transparent)}
  .swkp__medal{width:58px;height:58px;border-radius:15px}
  .swkp__medal img{width:38px;height:38px}
}
@media (max-width:540px){
  .swkp{padding:19px 17px;border-radius:var(--r-xs)}
  .swkp__medal{width:50px;height:50px;border-radius:13px}
  .swkp__medal img{width:33px;height:33px}
  .swkp__lede{font-size:.83rem;line-height:1.7}
  /* Three columns at 320px gives each fact four characters. Stacked as
     label-and-value rows instead, with the tick turned horizontal. */
  .swkp__stats{grid-template-columns:1fr;padding:13px 0}
  .swkp__stats div{display:flex;align-items:baseline;gap:11px;padding:8px 0}
  .swkp__stats div + div{border-left:0;border-top:1px solid color-mix(in srgb,var(--gold) 14%,transparent)}
  .swkp__stats b{margin:0;flex:0 0 auto;min-width:7em;font-size:1rem}
  .swkp__act .btn{width:100%}
}

/* ---- the distinction plinths get a floor -------------------------------
   The plinth is drawn with no bottom edge, which is right: it is meant to be
   standing on something. Nothing was there, so three blocks simply stopped
   mid-air. This is the line they stand on — brightest under the centre and
   falling away at both ends, so it reads as a lit surface rather than a
   border added to close a shape. */
.pod{position:relative;padding-bottom:1px}
.pod::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,
    color-mix(in srgb,var(--gold) 62%,transparent) 22%,
    color-mix(in srgb,var(--gold) 62%,transparent) 78%, transparent)}
@media (max-width:720px){
  /* Stacked, the plinths are rows rather than blocks — there is no floor to draw. */
  .pod::after{display:none}
}


/* ══════════════════════════════════════════════════════════════════════════
   THE SWK CARD'S TRACE
   The same line the liquid buttons draw, at the scale of the panel. It runs
   from the top left, so the light wash, the seam and the trace all start from
   the same corner and the card reads as lit from one place.

   Drawn as an SVG rect rather than a border so it can be dashed and run: a
   border can only fade, and a fade does not tell you the whole card is the
   control. Browsers without CSS SVG geometry properties get a plain ring.
   ══════════════════════════════════════════════════════════════════════════ */
.swkp__trace{
  position:absolute;inset:0;z-index:3;
  width:100%;height:100%;pointer-events:none;overflow:visible;
  filter:drop-shadow(0 0 3px var(--lq2-trace-glow))}
.swkp__trace rect{
  x:.6px;y:.6px;width:calc(100% - 1.2px);height:calc(100% - 1.2px);
  rx:14.4px;ry:14.4px;fill:none;
  stroke:var(--lq2-trace);stroke-width:1.2px;
  stroke-dasharray:100;stroke-dashoffset:100;opacity:0;
  transition:stroke-dashoffset 1.15s var(--out),opacity .4s var(--ease)}
.swkp:hover .swkp__trace rect,
.swkp:focus-within .swkp__trace rect{stroke-dashoffset:0;opacity:1}
@supports not (x:1px){
  .swkp__trace rect{stroke-dasharray:none;stroke-dashoffset:0}
}
@media (max-width:540px){ .swkp__trace rect{rx:9.4px;ry:9.4px} }

/* ══════════════════════════════════════════════════════════════════════════
   WHATSAPP, BESIDE ENROL
   Sized and seated to the Enrol button it sits next to, in WhatsApp's own
   green rather than the site's gold — this is the one control on the page
   that should read as a different thing from everything around it, because
   pressing it leaves the site.
   ══════════════════════════════════════════════════════════════════════════ */
.fwa{
  position:fixed;z-index:60;right:var(--dock-r);
  bottom:calc(var(--dock-b) + var(--dock-h) + var(--dock-gap));
  width:52px;height:52px;border-radius:50%;display:grid;place-items:center;
  color:#fff;background:linear-gradient(160deg,#2BC44C,#12933B);
  border:1px solid rgba(255,255,255,.22);cursor:pointer;
  box-shadow:0 10px 30px -12px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,255,255,.3);
  transition:transform .5s var(--spring),box-shadow .4s var(--ease)}
.fwa svg{width:27px;height:27px}
.fwa:hover,.fwa:focus-visible{transform:scale(1.07);
  box-shadow:0 14px 36px -12px rgba(0,0,0,.65),inset 0 1px 0 rgba(255,255,255,.34)}
.fwa[aria-expanded="true"]{transform:scale(.95)}

.wapop{
  position:fixed;z-index:61;right:var(--dock-r);
  bottom:calc(var(--dock-b) + var(--dock-h) + var(--dock-gap) + 52px + 10px);
  width:min(264px,calc(100vw - 32px));
  padding:11px;border-radius:var(--r-xs);
  background:var(--panel-solid);border:1px solid var(--line-2);
  box-shadow:0 22px 54px -22px rgba(0,0,0,.72);
  opacity:0;visibility:hidden;transform:translateY(8px) scale(.97);transform-origin:100% 100%;
  transition:opacity .3s var(--ease),transform .45s var(--out),visibility .3s}
.wapop.on{opacity:1;visibility:visible;transform:none}
.wapop__k{
  margin:0 0 8px;padding:0 5px;
  font-family:var(--mono);font-size:.55rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--text-3)}
.wapop a{
  display:flex;flex-direction:column;gap:1px;padding:9px 11px;border-radius:9px;
  text-decoration:none;color:inherit;
  transition:background .25s var(--ease)}
.wapop a:hover,.wapop a:focus-visible{background:color-mix(in srgb,var(--gold) 10%,transparent)}
.wapop a b{font-family:var(--mono);font-size:.8rem;font-weight:500;color:var(--text-1)}
.wapop a span{font-size:.66rem;color:var(--text-3)}
@media (max-width:560px){
  .fwa{width:46px;height:46px}
  .fwa svg{width:24px;height:24px}
  .wapop{bottom:calc(var(--dock-b) + var(--dock-h) + var(--dock-gap) + 46px + 10px)}
}
/* Enrol slides away as you reach the form; WhatsApp follows it down rather
   than being left hovering on its own over nothing. */
.btn.fenrol.is-away ~ .fwa,
.btn.fenrol.is-away ~ .wapop{transform:translateY(16px);opacity:0;pointer-events:none}

/* ══════════════════════════════════════════════════════════════════════════
   THE PREMIUM PASS
   Three changes, all of them restraint rather than addition.

   1 · Headings set with text-wrap:balance. A two-line heading that breaks
       one-word-then-seven is the single most common thing that makes an
       expensive-looking page look automated.
   2 · Display type takes proportional old-style figures where the face has
       them, so "2004" and "11" sit on the line with the lowercase instead of
       standing above it like a spreadsheet.
   3 · A grain layer at 2% over the whole page. Flat vector colour is what
       reads as cheap on a large screen; a little tooth is what print has and
       screens usually do not. It is one tiled SVG, no image request, and it
       sits under every interactive layer so nothing is intercepted.
   ══════════════════════════════════════════════════════════════════════════ */
h1,h2,h3,.head h2,.pod__nm,.swkp__nm,.fdlg__body h3{text-wrap:balance}
p,.lede,.swkp__lede,.rev__q{text-wrap:pretty}
h1,h2,h3,.swkp__stats b,.pod__cite,.lb__cite,.hrec__b b{
  font-variant-numeric:oldstyle-nums proportional-nums;
  font-feature-settings:"onum" 1,"pnum" 1}
/* Tabular figures where columns have to line up — the opposite need. */
.lb__no,.wapop a b,.foot__col--contact a{
  font-variant-numeric:tabular-nums lining-nums;
  font-feature-settings:"tnum" 1,"lnum" 1}

body::after{
  content:"";position:fixed;inset:0;z-index:40;pointer-events:none;
  opacity:.02;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px}
@media (prefers-reduced-transparency:reduce){ body::after{display:none} }

/* ══════════════════════════════════════════════════════════════════════════
   THE CREST MOTTO, SET AS TYPE
   The words are about eighteen pixels tall inside crest-960.webp and already
   soft there, so at the size the crest renders they are at 1:1 with the file
   and no srcset can sharpen them. The logo was generated rather than drawn,
   so there is no vector to go back to.

   What the artwork puts under the words is a plain dark pill with a gold
   hairline — something CSS draws exactly. So the pill is redrawn on top and
   the words are set live. Sharp at any size and any pixel ratio, and the
   image underneath is untouched, which matters because the preloader traces
   the same crest as line art.

   Everything is sized from --field, the same variable the medallion is built
   from, so the plate stays locked to the artwork at every breakpoint.
   ══════════════════════════════════════════════════════════════════════════ */
.motto{
  position:absolute;z-index:5;
  /* x 104..854 of 960 and y 1013..1032 of 1050, opened out slightly. */
  left:10.4%;right:10.4%;top:96.05%;height:2.72%;
  display:flex;align-items:center;justify-content:center;
  gap:calc(var(--field) * .0092);
  border-radius:999px;background:#140406;
  box-shadow:inset 0 0 0 1px rgba(201,152,47,.52);
  /* A hair in front of the crest layer, which sits at Z 0. */
  transform:translateZ(1px);
  -webkit-backface-visibility:hidden;backface-visibility:hidden;
  pointer-events:none;overflow:hidden}
.motto i{
  font-style:normal;font-family:var(--display);font-weight:600;
  font-size:calc(var(--field) * .0138);line-height:1;
  letter-spacing:.19em;text-indent:.19em;text-transform:uppercase;
  /* Brighter than the artwork's own gold and struck with a dark underside,
     so the words read as engraved into the plate rather than laid on it. */
  color:#F2D283;text-shadow:0 1px 0 rgba(0,0,0,.55);white-space:nowrap}
.motto s{
  flex:0 0 auto;text-decoration:none;
  width:calc(var(--field) * .0072);height:calc(var(--field) * .0072);
  rotate:45deg;background:#C9982F;border-radius:1px}
@media (max-width:640px){
  /* The plate is a fraction of the artwork, so it shrinks with it; the
     letter-spacing is what stops holding at small sizes, not the box. */
  .motto i{letter-spacing:.14em;text-indent:.14em}
  .motto{gap:calc(var(--field) * .007)}
}

/* ══════════════════════════════════════════════════════════════════════════
   THE TEACHER PICKER
   Borrows .fdlg for the veil, the box and the close control, so it arrives
   already matching the founder's message and the student panel. What it adds
   is a scrolling list with its own search, because eighteen names is more
   than a dialog should ask anyone to read through.
   ══════════════════════════════════════════════════════════════════════════ */
.fdlg__box--pick{max-width:min(520px,calc(100vw - 32px))}
.pick__lede{font-size:.83rem;line-height:1.65;color:var(--text-3);margin:0 0 15px}
.pick__find{display:block;margin-bottom:11px}
.pick__find input{
  width:100%;font:inherit;font-size:.86rem;color:var(--text-1);
  padding:11px 14px;border-radius:10px;
  background:color-mix(in srgb,var(--text-1) 5%,transparent);
  border:1px solid var(--line);outline:none;
  transition:border-color .3s var(--ease)}
.pick__find input::placeholder{color:var(--text-3)}
.pick__find input:focus{border-color:var(--gold)}
.pick__list{
  display:flex;flex-direction:column;gap:5px;
  max-height:min(46vh,340px);overflow-y:auto;overscroll-behavior:contain;
  padding-right:4px}
.pick__r{
  display:flex;align-items:center;gap:12px;padding:9px 11px;border-radius:11px;
  text-decoration:none;color:inherit;border:1px solid transparent;
  transition:background .25s var(--ease),border-color .25s var(--ease)}
.pick__r:hover,.pick__r:focus-visible{
  background:color-mix(in srgb,var(--gold) 9%,transparent);
  border-color:color-mix(in srgb,var(--gold) 34%,transparent);outline:none}
.pick__av{
  position:relative;flex:0 0 auto;width:40px;height:40px;border-radius:50%;
  overflow:hidden;display:grid;place-items:center;
  background:linear-gradient(155deg,var(--maroon),var(--maroon-dp));
  border:1px solid color-mix(in srgb,var(--gold) 26%,transparent)}
.pick__av img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.pick__av .pod__ini{font-size:.85rem}
.pick__x{flex:1 1 auto;min-width:0}
.pick__nm{display:block;font-weight:500;font-size:.85rem;line-height:1.3}
.pick__sb{display:block;font-size:.68rem;color:var(--text-3)}
.pick__go{
  flex:0 0 auto;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;
  color:var(--gold);background:color-mix(in srgb,var(--gold) 12%,transparent);
  transition:background .25s var(--ease),color .25s var(--ease)}
.pick__r:hover .pick__go{background:var(--gold);color:var(--maroon-dp)}
.pick__go svg{width:13px;height:13px;margin-left:1px}
.pick__none{font-size:.82rem;color:var(--text-3);padding:16px 4px;margin:0}
@media (max-width:560px){
  .pick__list{max-height:52vh}
  .pick__av{width:36px;height:36px}
}

/* ══════════════════════════════════════════════════════════════════════════
   THE ABOUT PAGE'S INTRODUCTION
   Same sheet as every other dialog on the site, held a little narrower than
   the founder's message because it is four sentences rather than a career.
   The crest sits above the eyebrow so the panel opens on the mark rather than
   on a wall of words.
   ══════════════════════════════════════════════════════════════════════════ */
.fdlg__box--intro{max-width:min(560px,calc(100vw - 32px));text-align:center}
.fdlg__box--intro .fdlg__body{padding-block:clamp(26px,3.4vw,40px)}
.fdlg__box--intro .eyebrow{justify-content:center}
.intro__mark{
  display:grid;place-items:center;width:64px;height:64px;margin:0 auto 17px;
  border-radius:50%;
  background:color-mix(in srgb,var(--gold) 10%,transparent);
  border:1px solid color-mix(in srgb,var(--gold) 30%,transparent)}
.intro__mark img{width:38px;height:42px;object-fit:contain;display:block}
.fdlg__box--intro h3{
  font-family:var(--display);font-size:clamp(1.42rem,3vw,1.94rem);font-weight:600;
  line-height:1.16;margin:0 0 15px;text-wrap:balance}
.fdlg__box--intro h3 em{font-style:italic;font-weight:400;color:var(--gold-hi)}
.intro__p{
  font-size:.875rem;line-height:1.78;color:var(--text-2);
  max-width:46ch;margin:0 auto 13px;text-wrap:pretty}
.intro__p:last-of-type{margin-bottom:clamp(19px,2.4vw,26px)}
.fdlg__box--intro .fdlg__act{justify-content:center}
@media (max-width:560px){
  .fdlg__box--intro{text-align:left}
  .fdlg__box--intro .eyebrow{justify-content:flex-start}
  .intro__mark{margin:0 0 14px;width:54px;height:54px}
  .intro__p{max-width:none}
  .fdlg__box--intro .fdlg__act{justify-content:stretch}
  .fdlg__box--intro .fdlg__act .btn{width:100%}
}

#pre{
  position:fixed;inset:0;z-index:200;display:grid;place-items:center;
  background:var(--bg);
  transition:opacity .6s var(--ease),visibility .6s;
  animation:preFail .5s 6s forwards;
}
/* The same warm bloom the page carries, so the loader is not a flat plate. */
#pre::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(680px 480px at 50% 40%, var(--pl-bloom), transparent 68%),
    radial-gradient(520px 420px at 50% 96%, var(--pl-bloom-2), transparent 70%);
}
#pre.gone{opacity:0;visibility:hidden;pointer-events:none}
#pre.gone .pl{transform:scale(1.04);opacity:0}
@keyframes preFail{to{opacity:0;visibility:hidden}}

.pl{position:relative;display:grid;justify-items:center;gap:clamp(20px,3vw,30px);
    transition:transform .62s var(--out),opacity .42s var(--ease)}

.pl__art{position:relative;width:min(310px,62vw);aspect-ratio:600/656;
         animation:plRise .8s var(--out) both}

/* The line art. stroke-dashoffset is set on the eight <g> bands, not on the
   270-odd paths inside them — dash properties inherit, so one style write per
   band per frame covers the whole drawing instead of hundreds. */
.pl__ink{position:absolute;inset:0;width:100%;height:100%;overflow:visible;
         transition:opacity .5s var(--ease)}
.pl__ink g{fill:none;stroke:var(--gold-text);stroke-width:1.5;
           stroke-linecap:round;stroke-linejoin:round;
           stroke-dasharray:1;stroke-dashoffset:1}
/* Engraved interior lines sit lighter than the structural outline, so the mark
   reads as a shape with detail inside it rather than a uniform mesh of wire.
   The class is on the paths, not the bands — the bands are draw order, which
   runs top to bottom across the whole mark and cuts through both kinds. */
.pl__ink path.d{stroke-width:1.05;opacity:.55}

/* The finished mark, held at nothing until the drawing closes. */
.pl__real{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
          opacity:0;transform:scale(.985);
          transition:opacity .5s var(--ease),transform .6s var(--out)}
.pl__art.lit .pl__real{opacity:1;transform:scale(1)}
.pl__art.lit .pl__ink{opacity:0}

.pl__t{
  width:min(248px,54vw);height:2px;background:var(--line-2);border-radius:2px;overflow:hidden;
  animation:plRise .9s .12s var(--out) both;
}
/* scaleX, not width — the bar is repainted every frame, and animating width
   would put a layout pass in that loop. */
.pl__b{height:100%;width:100%;transform:scaleX(0);transform-origin:left center;
       background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));
       box-shadow:0 0 10px var(--pl-arc);will-change:transform}

@keyframes plRise{from{opacity:0;transform:translateY(14px) scale(.96)}}

@media (max-width:560px){
  .pl__art{width:66vw}
}
/* Nothing draws — the finished mark is simply there. */
@media (prefers-reduced-motion:reduce){
  .pl__art,.pl__t{animation:none}
  .pl__ink{display:none}
  .pl__real{opacity:1;transform:none;transition:none}
  .pl,.pl__real{transition:none}
  #pre.gone .pl{transform:none}
}

#prog{position:fixed;top:0;left:0;z-index:80;height:2.5px;width:0;
      background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));
      box-shadow:0 0 12px rgba(201,152,47,.7)}

/* ---------------------------------------------------------------- footer */


/* The subject label. Present on the faculty grid, absent here because this
   page's card never showed one; it does now. Copied verbatim from
   site.css so the two cards cannot drift apart. */
.fac__subj{
  font-family:var(--display);font-weight:500;line-height:1.06;
  font-size:clamp(1.28rem,1.05rem + .8vw,1.56rem);
  letter-spacing:-.012em;
  /* The raw accent is tuned for hairlines and dots, not for 1.5rem of type.
     Biology's green and Sociology's pink sit at roughly 2:1 against the cream
     face — fine for a 6px node, unreadable as a headline — so under the light
     theme the accent is mixed toward the page ink far enough to clear AA while
     still identifying the subject by colour. On the dark face the accent is
     already the bright value and only needs lifting. */
  color:color-mix(in srgb,var(--acc) 58%,#3E1D0A);
  margin-top:11px;text-wrap:balance;
  /* Two lines are reserved whether the subject needs them or not. Without it
     "Physics" and "Sociology & Psychology" push their photographs to different
     heights and the row of cards stops sharing a horizon. */
  min-height:2.06em;
  filter:drop-shadow(0 0 16px color-mix(in srgb,var(--acc) 22%,transparent));
}