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

:root{
  --display:"Playfair Display",Georgia,"Times New Roman",serif;
  --sans:"Poppins",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,monospace;
  /* Accent face. Caps-only in practice — used for the hero level line and
     nothing else, so it never has to carry body copy. */
  --accent:"Italiana","Playfair Display",Georgia,serif;

  /* The light theme's gold was mixed for a dark ground and never re-mixed
     for this one. #F3DDA4 is a highlight on oxblood and very nearly the paper
     colour on ivory, which is why every stat figure, citation and eyebrow set
     in it was washing out. Both are pulled down here; the dark theme keeps
     the original values further down. */
  --gold:#B0821F;
  --gold-lo:#8A6414;
  --gold-hi:#8C6516;
  /* Gold that is always painted on the oxblood medallions — student
     initials, avatar plates — and so must stay light in BOTH themes. It is
     the one gold that does not flip: the ground under it never does. */
  --gold-on-dark:#EBC470;
  --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:#F5F2E9;
  --bg-2:#EBE6D9;
  --ink:#1B1A17;
  --text-1:#1B1A17;
  --text-2:rgba(27,26,23,.74);
  --text-3:rgba(27,26,23,.62);
  --line:rgba(27,26,23,.13);
  --line-2:rgba(27,26,23,.24);
  --gold-text:#7E5A11;

  --panel:rgba(255,255,255,.4);
  --ck-bg:rgba(252,249,243,.97);
  --panel-fx:blur(40px) saturate(1.72);
  --panel-solid:rgba(255,255,255,.965);
  --edge:rgba(27,26,23,.10);
  --hi:rgba(255,255,255,.85);
  --sheen:rgba(255,255,255,.62);
  --shadow:0 22px 50px -26px rgba(42,38,32,.34);
  --shadow-lg:0 40px 90px -40px rgba(42,38,32,.45);
  --scroll-track:rgba(27,26,23,.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,#FFFFFF 0%,#F7F5F0 54%,#E9E6DE 100%);
  --bar-edge:rgba(48,44,38,.13);
  --bar-edge-2:rgba(48,44,38,.26);
  --bar-gloss:rgba(48,44,38,.4);
  --bar-gloss-2:rgba(48,44,38,.22);
  --bar-sweep:rgba(48,44,38,.09);
  --bar-shadow:0 2px 0 rgba(48,44,38,.08) inset,0 14px 34px -18px rgba(42,38,32,.42);
  --bar-shadow-lg:0 2px 0 rgba(48,44,38,.12) inset,0 20px 46px -18px rgba(42,38,32,.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,255,255,.1);
  --clear-fx:blur(38px) saturate(2);
  --clear-solid:rgba(255,255,255,.94);
  --clear-edge:rgba(255,255,255,.72);
  --clear-edge-2:rgba(48,44,38,.11);
  --clear-rim:rgba(255,255,255,.92);
  --clear-rim-lo:rgba(255,255,255,.46);
  --clear-shadow:0 18px 44px -22px rgba(42,38,32,.42);
  --clear-shadow-hi:0 26px 60px -22px rgba(42,38,32,.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,255,255,.20);
  --wiz-input-on:rgba(255,255,255,.42);
  --wiz-input-edge:rgba(48,44,38,.12);

  /* Floating theme + sound controls. */
  --ctl-fill:linear-gradient(180deg,#FFFFFF,#F1EFE9);
  --ctl-fill-off:linear-gradient(180deg,#F6F4EF,#E6E3DB);
  --ctl-edge:rgba(48,44,38,.14);
  --ctl-ink:#22201C;
  --ctl-knob:#FFFFFF;
  --ctl-knob-shadow:0 3px 9px rgba(42,38,32,.28);
  --ctl-live:#5A1015;
  --ctl-shadow:0 12px 28px -14px rgba(42,38,32,.5),inset 0 1px 0 #fff;
  --ctl-shadow-hi:0 18px 36px -14px rgba(42,38,32,.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(62,56,48,.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,255,255,.36) 100%);
  --sf-fx:blur(16px) saturate(1.5);
  --sf-solid:#FCFBF8;
  --sf-edge:rgba(27,26,23,.09);
  --sf-lip:rgba(255,255,255,.95);
  --sf-floor:rgba(62,56,48,.1);
  --sf-cast:rgba(62,56,48,.15);
  --sf-bloom:rgba(255,255,255,.8);
  --sf-ink:#242220;
  /* 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(42,38,32,.42);
  --scrim:rgba(244,242,237,.5);
  --scrim-solid:rgba(244,242,237,.93);
  --btn-chip:linear-gradient(180deg,#FFFFFF,#ECE9E1);
  --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(48,44,38,.15);
  --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,.15),rgba(255,255,255,.04));
  --by-fx:blur(16px) saturate(1.22);
  --by-inner:rgba(255,255,255,.5);
  --by-floor:rgba(62,56,48,.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,255,255,.62),rgba(248,244,235,.46));
  --mob-fx:blur(36px) saturate(1.3);
  --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(27,26,23,.10);
  --pl-arc:rgba(201,152,47,.85);
  --pl-cast:rgba(42,38,32,.30);
  --pl-spoke:rgba(27,26,23,.24);
  /* Deeper and less transparent on cream — a pale mote on a pale page is
     nothing at all, so the light-theme dust is closer to old gold. */
  --dust-c:rgba(150,109,26,.72);
  --dust-glow:rgba(201,152,47,.5);
  --pl-dark:brightness(.2) saturate(.18) contrast(.92);
  --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(62,56,48,.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(44,40,34,.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:.36;
  --hero-bg-filter:sepia(.16) saturate(.86) brightness(1.07) contrast(.92);
}

/* ------------------------------------------------------------------- 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;
  /* Dark theme: the originals, unchanged — these were always right here. */
  --gold:#C9982F;
  --gold-lo:#A8781C;
  --gold-hi:#F3DDA4;
  --gold-on-dark:#EBC470;

  --panel:rgba(38,12,13,.34);
  --ck-bg:rgba(28,10,11,.97);
  --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);
  --pl-spoke:rgba(227,181,93,.34);
  --dust-c:rgba(243,221,164,.85);
  --dust-glow:rgba(227,181,93,.6);
  --pl-dark:brightness(.26) saturate(.14) contrast(.9);
  --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:14.85px;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,.21), transparent 62%),
    radial-gradient(720px 560px at 4% 22%, rgba(86,80,66,.085), transparent 66%),
    radial-gradient(1000px 700px at 50% 106%, rgba(201,152,47,.115), 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. */
/* Enrol and WhatsApp were each given their own right/bottom arithmetic, which
   meant one of them only had to change for the two to collide — which is what
   happened on a phone. They hang off shared variables now, so the gap between
   them is stated once and cannot drift. */
:root{
  --dock-r:calc(18px + env(safe-area-inset-right));
  --dock-b:calc(20px + env(safe-area-inset-bottom));
  --dock-h:46px;                     /* the Enrol pill's height */
  --dock-gap:12px;
}
@media (max-width:720px){
  :root{
    --dock-r:calc(14px + env(safe-area-inset-right));
    --dock-b:calc(16px + env(safe-area-inset-bottom));
    --dock-h:42px;
    --dock-gap:10px;
  }
}
.btn.fenrol{position:fixed;left:auto;top:auto;right:var(--dock-r);bottom:var(--dock-b);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{--pad:13px 18px;font-size:.8rem}
}


/* -------------------------------------------------------------- typography */
h1,h2,h3,h4{
  font-family:var(--display);font-weight:500;line-height:1.1;
  letter-spacing:-.012em;margin:0 0 .5em;color:var(--text-1);
}
h1{font-size:clamp(1.992rem,4.15vw,3.6105rem)}
h2{font-size:clamp(1.66rem,3.237vw,2.739rem)}
h3{font-size:clamp(.996rem,1.494vw,1.2865rem);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(.918rem,1.08vw,1.008rem);color:var(--text-2);max-width:62ch}
.center .lede{margin-inline:auto}
.note{font-size:.738rem;color:var(--text-3);line-height:1.6}

/* ----------------------------------------------------------------- layout */
.wrap{width:min(100% - 44px,var(--wrap));margin-inline:auto}
.sec{padding-block:clamp(40px,4.6vw,76px);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}
.head.center h2{text-wrap:balance}
/* The distinction teachers lead straight into the full list: no second
   section's worth of air between them. */
#honours{padding-bottom:clamp(16px,2vw,28px)}
#faculty{padding-top:clamp(28px,3vw,44px)}
.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:.828rem;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:.855rem;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:.747rem}
/* 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:.765rem;
  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.2616rem;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:.81rem;
  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:.558rem;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:.9rem;
  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 old loader lit a crest that was already there. This one draws the mark
   from nothing: the whole logo is inline line art, banded, and each band inks
   in as real load progress arrives — so the animation can never be caught
   half-finished by a fast cache, because the cache is what is driving it. The
   finished gold crest fades up through the lines at the end, which is also
   the moment the page opens. */
#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 */
.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:.801rem;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:.711rem;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:.774rem;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:.702rem;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:.666rem;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:.594rem;letter-spacing:.16em}
  .nxb__go{padding:9px 13px;font-size:.648rem}
}
@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:13.95px}
  .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:.774rem}
  .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:.522rem;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.17rem;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}
  /* Thinned rather than dropped. Three hundred and forty motes is not what a
     tier that has already given up its blurs should be asked to composite, but
     off entirely made small screens the one place where enlarging the field
     changed nothing at all. Every sixth mote survives — about fifty-seven dots,
     a little more than the old field carried here, and the crest keeps
     something moving behind it. The 6n stride also samples both populations
     evenly, so the phone keeps the wide skirt rather than just the core. */
  .medal__dust i:nth-child(6n+2),
  .medal__dust i:nth-child(6n+3),
  .medal__dust i:nth-child(6n+4),
  .medal__dust i:nth-child(6n+5),
  .medal__dust i:nth-child(6n+6){display:none}
  .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}
  /* The blanket rule above would run each mote's cycle out in a millisecond
     and leave it parked at opacity:0 anyway — this just says so out loud
     rather than relying on that. */
  .medal__dust{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(.936rem,1.17vw,1.062rem);margin-bottom:26px;max-width:52ch}
/* 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:.702rem;color:var(--text-3);line-height:1.5}
.hero__by b{display:block;font-weight:500;font-size:.783rem;color:var(--text-1)}

/* ---- the card in its new job: leading the column ------------------------
   Sitting above the headline it is doing a different job than it did under
   the buttons, where it was a signature. Here it is the first claim on the
   page, so it gets a touch more presence — a larger mark, a gold-lettered
   top line, and room underneath it rather than the h1 crowding straight in. */
.hero__by--lead{
  margin-bottom:22px;
  padding:13px 24px 13px 15px;
  gap:14px;
}
.hero__by--lead img{width:42px;height:42px}
.hero__by--lead div{font-size:.6615rem;letter-spacing:.005em}
.hero__by--lead b{
  font-family:var(--mono);font-weight:500;
  font-size:.635rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold-text);margin-bottom:2px;
}

/* ---- the level line -----------------------------------------------------
   Italiana, wide-tracked. It is the one place on the page that face appears,
   which is the point: it reads as a plate rather than as another paragraph,
   and it keeps the qualification names from competing with the lede above
   them or the buttons below. */
.hero__levels{
  font-family:var(--accent);
  font-size:clamp(1rem,1.28vw,1.2rem);
  letter-spacing:.13em;
  color:var(--text-1);
  margin:0 0 28px;
  display:flex;align-items:center;flex-wrap:wrap;gap:0 12px;
}
/* The first pass filled a rounded box behind each level and it read as three
   gold buttons — a painted block is the one thing this page's gold never does.
   The mark is a rule instead: a gold hairline seated on the baseline, fading
   as it runs, with a barely-there wash above it so the word sits on something
   rather than floating. No box, no radius, no padding on the sides, so the
   line breaks at the same points it always did. */
.hero__levels b{
  font-weight:600;font-style:normal;
  padding:0 1px 6px;
  background:
    linear-gradient(180deg,transparent 0 62%,
      color-mix(in srgb,var(--gold) 11%,transparent) 62%),
    linear-gradient(90deg,
      color-mix(in srgb,var(--gold) 88%,transparent),
      color-mix(in srgb,var(--gold) 34%,transparent));
  background-repeat:no-repeat;
  background-size:100% 100%,100% 1.5px;
  background-position:left top,left bottom;
}
/* On the dark ground the rule is what carries, so it runs brighter and picks
   up a short throw; the wash above it stays almost nothing. */
[data-theme="dark"] .hero__levels b{
  color:#FBF5EC;
  background:
    linear-gradient(180deg,transparent 0 62%,
      color-mix(in srgb,var(--gold) 13%,transparent) 62%),
    linear-gradient(90deg,
      color-mix(in srgb,var(--gold) 100%,transparent),
      color-mix(in srgb,var(--gold) 40%,transparent));
  background-repeat:no-repeat;
  background-size:100% 100%,100% 1.5px;
  background-position:left top,left bottom;
}
.hero__levels i{font-style:normal;color:var(--gold);font-size:.7em;opacity:.85}

/* ---- the facts strip ----------------------------------------------------
   Replaces the credit card that used to close the column. Four counts on one
   two claims under the buttons, stacked two lines each: the claim itself in
   the display face at full ink, the qualifier under it in mono. It was set a
   third of the way to invisible before — --text-3 at 500 weight on a .6rem
   mono — which is the right treatment for a footnote and the wrong one for
   the only proof-point in the hero. Both lines carry now. */
.hero__facts{
  display:flex;flex-wrap:wrap;align-items:stretch;
  gap:16px 0;
  margin:0;padding:22px 0 0;
  border-top:1px solid var(--line-2);
  width:min(100%,560px);
}
.hero__facts li{
  display:flex;flex-direction:column;gap:7px;
  flex:1 1 0;min-width:0;
}
/* The plate used to hold two short pairs and could refuse to wrap. "Multiple
   campuses / across Pakistan" is longer than either of them, so the value
   line keeps nowrap and the qualifier under it is allowed to break. */
.hero__facts b{white-space:nowrap}
.hero__facts span{white-space:normal}
/* Hairline between the pair rather than a bullet — it holds them as one
   group without adding a third mark to the column. */
.hero__facts li+li{
  padding-left:clamp(26px,3vw,42px);
  margin-left:clamp(26px,3vw,42px);
  border-left:1px solid var(--line);
}
.hero__facts b{
  font-family:var(--display);font-weight:600;
  font-size:clamp(1.18rem,1.5vw,1.4rem);line-height:1;letter-spacing:-.008em;
  color:var(--text-1);
}
.hero__facts span{
  font-family:var(--mono);font-weight:500;
  font-size:.665rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold-text);
}

/* ---- hero density -------------------------------------------------------
   The hero is drawn at poster scale, which is right on a 27" monitor and too
   tall on the 1440x900 laptop most people actually open this on — the column
   ran past the fold and the scroll cue got pushed off the bottom.

   The whole trim runs off ONE NUMBER. --hero-k multiplies every size and
   every gap in the column, so the hero can be retuned by changing a single
   character instead of hunting eleven values that have to stay in proportion
   with each other. The unit values below are the tight end; --hero-k opens
   them back up.

     --hero-k: 1     hard trim, everything ~12% under the original
     --hero-k: 1.2   current — a shade under the original poster scale, which
                     is where the column stops running past the fold

   Two things this deliberately does NOT do. It does not touch phones: the
   whole block is behind min-width:900px, so below that the original clamps
   are what render, untouched, and the lower bound of every clamp stays where
   the original design put it. And it does not multiply --hdr — the header is
   a fixed bar and scaling the padding that clears it would push the headline
   down rather than pull the column up. */
@media (min-width:900px){
  .hero{
    --hero-k:1.2;
    padding-top:calc(var(--hdr) + clamp(24px,3.6vw,46px) * var(--hero-k));
    padding-bottom:calc(clamp(78px,8vw,112px) * var(--hero-k));
  }
  /* calc() around clamp() rather than three separate multiplications: scaling
     the resolved value is identical to scaling all three terms, and it keeps
     the original clamp readable underneath the scale. */
  .hero h1{
    font-size:calc(clamp(1.88rem,3.62vw,3.12rem) * var(--hero-k));
    margin-bottom:calc(21px * var(--hero-k));
  }
  .hero .lede{
    font-size:calc(clamp(.9rem,1.08vw,1.005rem) * var(--hero-k));
    margin-bottom:calc(21px * var(--hero-k));
  }
  .hero__levels{
    font-size:calc(clamp(.95rem,1.18vw,1.1rem) * var(--hero-k));
    margin-bottom:calc(22px * var(--hero-k));
  }
  .hero__by--lead{
    margin-bottom:calc(17px * var(--hero-k));
    padding:calc(11px * var(--hero-k)) calc(21px * var(--hero-k))
            calc(11px * var(--hero-k)) calc(13px * var(--hero-k));
    gap:calc(12px * var(--hero-k));
  }
  .hero__by--lead img{width:calc(38px * var(--hero-k));height:calc(38px * var(--hero-k))}
  .hero__cta{gap:calc(14px * var(--hero-k));margin-bottom:calc(27px * var(--hero-k))}
  /* --pad is substituted verbatim into padding, so each side carries its own
     calc. min-height has to scale with it or the face stops tracking the type. */
  .hero__cta .btn--liquid{
    --pad:calc(13px * var(--hero-k)) calc(26px * var(--hero-k));
    min-height:calc(50px * var(--hero-k));
    font-size:calc(.795rem * var(--hero-k));
  }
  .hero__facts{padding-top:calc(18px * var(--hero-k));gap:calc(13px * var(--hero-k)) 0}
  .hero__facts b{font-size:calc(clamp(1.1rem,1.34vw,1.25rem) * var(--hero-k))}
}

/* Short screens — laptops at 1366x768 and 1440x900, and any window dragged
   down to half height. Same dial, tighter units, because the block above is
   not enough at 768px of viewport and applying THESE units everywhere would
   waste a large monitor. Keyed on height and a desktop width together, so a
   tall phone in portrait never sees it. */
@media (min-width:900px) and (max-height:860px){
  .hero{
    padding-top:calc(var(--hdr) + 22px * var(--hero-k));
    padding-bottom:calc(clamp(64px,7vh,88px) * var(--hero-k));
  }
  .hero h1{
    font-size:calc(clamp(1.8rem,3.15vw,2.72rem) * var(--hero-k));
    margin-bottom:calc(17px * var(--hero-k));
  }
  .hero .lede{font-size:calc(.945rem * var(--hero-k));margin-bottom:calc(17px * var(--hero-k));max-width:48ch}
  .hero__levels{font-size:calc(.96rem * var(--hero-k));margin-bottom:calc(18px * var(--hero-k))}
  .hero__by--lead{
    margin-bottom:calc(14px * var(--hero-k));
    padding:calc(9px * var(--hero-k)) calc(18px * var(--hero-k))
            calc(9px * var(--hero-k)) calc(11px * var(--hero-k));
  }
  .hero__by--lead img{width:calc(34px * var(--hero-k));height:calc(34px * var(--hero-k))}
  .hero__cta{margin-bottom:calc(22px * var(--hero-k))}
  .hero__cta .btn--liquid{
    --pad:calc(12px * var(--hero-k)) calc(23px * var(--hero-k));
    min-height:calc(46px * var(--hero-k));
    font-size:calc(.775rem * var(--hero-k));
  }
  .hero__facts{padding-top:calc(15px * var(--hero-k))}
  /* At this height the cue is the first thing to collide with the facts
     strip, so it tucks closer to the edge. Not scaled — it is a fixed piece
     of furniture at the bottom of the viewport, not part of the column. */
  .cue{bottom:16px}
  .cue__s{width:24px;height:38px}
}

@media (max-width:480px){
  .hero__facts{gap:12px 0;padding-top:18px}
  .hero__facts li+li{padding-left:18px;margin-left:18px}
  .hero__facts span{font-size:.6rem;letter-spacing:.13em}
  .hero__by--lead{padding:12px 18px 12px 13px;gap:12px}
  .hero__by--lead img{width:36px;height:36px}
  .hero__by--lead div{font-size:.63rem}
  .hero__levels{margin-bottom:24px}
}

/* 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--lead{transition-delay:.1s}
.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;
}
/* ---- hero density: the crest ----
   Part of the hero trim further up, but it has to sit here: .medal is
   declared after the hero block, so an override grouped with the rest of
   that trim lost the tie on source order and the field never changed.

   The crest is sized off viewport height and the text column is not, so on a
   short screen the crest was the thing squeezing the headline rather than the
   other way round. */
.medal{--field:min(calc(60vh * var(--hero-k,1)),calc(516px * var(--hero-k,1)),74vh)}
@media (min-width:900px) and (max-height:860px){
  .medal{--field:min(calc(56vh * var(--hero-k,1)),calc(440px * var(--hero-k,1)),66vh)}
}
.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. */
/* The one sharp copy. Everything behind it is blurred, so a touch of contrast
   here is what separates the lettering from its own depth stack rather than
   letting the two average together. */
.medal__face img.crest{filter:contrast(1.07) saturate(1.05)}
/* One artwork, two grounds. LEARN · PREPARE · SUCCEED is painted dark with a
   thin gold rim: correct on the ivory theme, and all but invisible on the dark
   one, where the letters sit at the same value as the page behind them.
   Recolouring the file itself fixes the dark theme and breaks the light one,
   so the dark theme loads a second copy instead — identical to the original
   except that the tagline band alone is lifted to gold. The logo the client
   signed off is untouched and is still what light mode serves. */
.medal__face img.crest--dk{display:none}
[data-theme="dark"] .medal__face img.crest--lt{display:none}
[data-theme="dark"] .medal__face img.crest--dk{display:block}
.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.1px) brightness(.76) saturate(.8)}
[data-theme="light"] .medal__stage img.sl2{filter:blur(2px)   brightness(.7)  saturate(.7)}
[data-theme="light"] .medal__stage img.sl3{filter:blur(3.2px) brightness(.64) saturate(.6)}
.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)}}

/* ---- dust ----
   A slow sprinkle off the back of the crest. Three hundred and forty particles,
   each one a 1.2–3.8px dot with its own drift, size, opacity, duration and a NEGATIVE
   delay — the negative delay is what matters: it starts every particle
   part-way through its own cycle, so the field is already in motion on the
   first frame instead of firing as one synchronised burst and then settling.

   The field started at a hundred and eight motes born in a tight cluster,
   drifting about a quarter of the crest's height — a thin ring hugging the
   artwork. It is three times that now, and in two populations: two thirds born
   inside the silhouette and drifting to half the crest's height, one third born
   well outside it and carrying to nearly three quarters. The second group is
   what gives the field a skirt instead of an edge.

   Everything animated here is transform and opacity, so the whole field is
   three hundred and forty composited layers and not one layout pass — each is a 3px
   dot, so the layer memory stays trivial even at this count. No script: the offsets
   are inline, expressed against --field, so they scale with the crest. */
.medal__dust{
  /* Deliberately NOT inset:0. The .medal cell is wider than the artwork, so
     against the cell the emitter percentages would put half the particles in
     the open space either side of the crest — born visible, which is exactly
     what the layer is trying not to do. This box is .medal__stage's box, so
     left:48% means 48% of the crest. */
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  height:calc(var(--field) * .9);aspect-ratio:695/760;max-width:94%;
  pointer-events:none;
  /* Behind the artwork but in front of the glow, so the motes read as lit by
     the same pool of light the crest is sitting in. */
  z-index:0;
}
.medal__dust i{
  position:absolute;width:var(--s);height:var(--s);border-radius:50%;
  background:var(--dust-c);
  box-shadow:0 0 calc(var(--s) * 2.4) var(--dust-glow);
  opacity:0;
  animation:mdDust var(--dur) linear var(--dl) infinite;
  will-change:transform,opacity;
}
/* Fades up out of nothing, drifts, fades back to nothing — never a hard edge
   at either end, or the loop becomes visible the moment it is watched. */
@keyframes mdDust{
  0%  {opacity:0;transform:translate3d(0,0,0) scale(.35)}
  14% {opacity:var(--o);transform:translate3d(calc(var(--x) * .16),calc(var(--y) * .16),0) scale(1)}
  68% {opacity:var(--o)}
  100%{opacity:0;transform:translate3d(var(--x),var(--y),0) scale(.6)}
}
/* 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:.8217rem;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{
  background:
    linear-gradient(160deg,color-mix(in srgb,var(--gold) 12%,transparent),transparent 55%),
    color-mix(in srgb,var(--panel-solid) 94%,transparent);
  border-color:color-mix(in srgb,var(--gold) 62%,transparent);
  box-shadow:var(--clear-shadow-hi,var(--clear-shadow)),0 0 0 1px color-mix(in srgb,var(--gold) 22%,transparent),
             0 28px 60px -30px color-mix(in srgb,var(--gold) 55%,transparent);
}
.aclear.is-front .card__n,.aclear.is-front h3{color:var(--gold-text)}
.aclear.is-front h3{color:var(--text-1)}
.aclear.is-front .btn__trace rect{stroke-dashoffset:0;opacity:.7}
.aclear.is-front:hover{border-color:color-mix(in srgb,var(--gold) 80%,transparent)}
.aclear--stat b.aclear__word{font-size:clamp(2rem,3vw,2.55rem)}

/* ---- 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:.801rem;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(2.656rem,4.15vw,3.486rem);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:.738rem;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:.7605rem;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:.495rem;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.241rem,5.81vw,2.988rem);
  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:.837rem;line-height:1.62;color:var(--text-2);margin:0;max-width:58ch}

.incl__wrap{min-width:0;width:100%}
.incl{display:flex;gap:10px;height:clamp(300px,30vw,340px);padding:2px}
.incl__c{
  position:relative;isolation:isolate;overflow:hidden;
  flex:1 1 0;min-width:0;border-radius:18px;cursor:pointer;text-align:left;
  padding:0;font:inherit;color:inherit;
  background:var(--clear-fill);border:1px solid var(--clear-edge-2);
  box-shadow:var(--clear-shadow);
  transition:flex-grow .8s cubic-bezier(.22,.9,.28,1),border-color .4s var(--ease),
             box-shadow .4s var(--ease),background .4s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .incl__c{-webkit-backdrop-filter:var(--clear-fx);backdrop-filter:var(--clear-fx)}
}
.incl__c:hover{border-color:color-mix(in srgb,var(--gold) 45%,transparent)}
.incl__c:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.incl__c.on{
  flex-grow:10;cursor:default;
  background:linear-gradient(160deg,color-mix(in srgb,var(--gold) 10%,transparent),transparent 60%),var(--clear-fill);
  border-color:color-mix(in srgb,var(--gold) 50%,transparent);
  box-shadow:var(--clear-shadow-hi,var(--clear-shadow));
}
.incl__spine{
  position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:space-between;padding:18px 0;transition:opacity .35s var(--ease);
}
.incl__spine b{font-family:var(--display);font-weight:600;font-size:1.05rem;color:var(--gold-text)}
.incl__spine span{
  writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap;
  font-size:.76rem;color:var(--text-2);overflow:hidden;text-overflow:ellipsis;max-height:74%;
}
.incl__c:hover .incl__spine span{color:var(--text-1)}
.incl__c.on .incl__spine{opacity:0;pointer-events:none}
.incl__body{
  position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;
  padding:clamp(22px,2.6vw,32px);min-width:260px;
  opacity:0;transform:translateY(10px);pointer-events:none;
  transition:opacity .45s var(--ease) .18s,transform .55s var(--out) .18s;
}
.incl__c.on .incl__body{opacity:1;transform:none}
.incl__top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.incl__n{font-family:var(--display);font-weight:600;font-size:2.2rem;line-height:1;
  color:color-mix(in srgb,var(--gold) 38%,transparent)}
.incl__t{display:block;font-family:var(--display);font-size:clamp(1.2rem,1.7vw,1.45rem);
  line-height:1.2;margin:16px 0 10px;color:var(--text-1)}
.incl__p{display:block;font-size:.86rem;line-height:1.62;color:var(--text-2);max-width:52ch}
@media (max-width:860px){
  .incl__wrap{margin-inline:-16px;width:calc(100% + 32px)}
  .incl{
    height:auto;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;
    padding:6px max(16px,calc((100% - min(310px,74vw)) / 2)) 22px;
    scrollbar-width:none;overscroll-behavior-x:contain;
  }
  .incl::-webkit-scrollbar{display:none}
  .incl__c{flex:0 0 min(310px,74vw);min-height:250px;scroll-snap-align:center;transition:border-color .4s var(--ease),box-shadow .4s var(--ease),opacity .4s var(--ease)}
  .incl__c:not(.on){opacity:.62}
  .incl__c.on{flex-grow:0}
  .incl__spine{display:none}
  .incl__body{position:relative;inset:auto;min-width:0;opacity:1;transform:none;pointer-events:auto;height:100%}
}
@media (prefers-reduced-motion:reduce){.incl__c,.incl__body,.incl__spine{transition:none}}
.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;
      --cw:318px;--lap:.1}
/* Four cards have to fit inside --wrap at every desktop width, not just the
   widest one. Card width and overlap step down together as the column
   narrows, so the deck stays a deck instead of running off the right edge:
   layout width is 4*cw - 3*cw*lap plus the rail's own left pad. */
@media (min-width:1151px) and (max-width:1279px){.trio{--cw:296px;--lap:.12}}
@media (min-width:1001px) and (max-width:1150px){.trio{--cw:268px;--lap:.12}}
@media (min-width:901px)  and (max-width:1000px){.trio{--cw:238px;--lap:.16}}
/* 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(40px,6.5vw,100px);
}

.trio__c{
  position:relative;width:min(var(--cw),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) * -32%)) rotateY(22deg) 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:translateZ(calc(var(--i) * -44px)) rotateY(22deg);
  transition-delay:calc(var(--i) * 115ms);
}
/* 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:22px 21px 22px;
  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:700;font-size:1.36rem;line-height:1.14;
  margin:15px 0 10px;letter-spacing:-.014em;color:var(--text-1);
}
.trio__d{font-size:.783rem;line-height:1.58;color:var(--text-2);margin:0 0 16px;max-width:32ch}
/* 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:.6rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-2);font-weight:600;
  border:1px solid var(--line-2);border-radius:99px;padding:6px 11px;
  white-space:nowrap;
}
/* The subject line is the thing a student actually scans this rail for, and
   it was set at footnote weight next to the teacher count. It now reads as
   the card's label: deeper wash, a gold rim at near full strength, an inner
   highlight along the top and a soft throw underneath so the pill sits off
   the pane rather than flat on it. */
.trio__chip--acc{
  color:var(--gold-text);font-weight:700;
  font-size:.67rem;letter-spacing:.115em;padding:7px 13px;
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--gold) 30%,transparent),
    color-mix(in srgb,var(--gold) 16%,transparent));
  border-color:color-mix(in srgb,var(--gold) 88%,transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--gold) 36%,transparent),
    0 4px 12px -6px color-mix(in srgb,var(--gold) 60%,transparent);
  transition:box-shadow .42s var(--ease),transform .42s var(--out);
}
.trio__c:hover .trio__chip--acc,.trio__c.on .trio__chip--acc{
  transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--gold) 44%,transparent),
    0 7px 16px -6px color-mix(in srgb,var(--gold) 74%,transparent);
}
/* A transparent gold wash works on the dark pane and all but vanishes on the
   ivory one — 30% of #C9982F over cream is cream. The light cut mixes toward
   an opaque warm gold instead and takes the text down to a deeper brown, so
   the pill reads as a filled label rather than a tint. */
[data-theme="light"] .trio__chip--acc{
  color:#5C3E08;
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--gold) 48%,#FFF9EC),
    color-mix(in srgb,var(--gold) 31%,#FFF9EC));
  border-color:var(--gold);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.62),
    0 4px 12px -6px color-mix(in srgb,var(--gold) 72%,transparent);
}
[data-theme="light"] .trio__c:hover .trio__chip--acc,
[data-theme="light"] .trio__c.on .trio__chip--acc{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.75),
    0 7px 16px -6px color-mix(in srgb,var(--gold) 85%,transparent);
}
/* The count chip beside it holds its own edge on the ivory pane. */
[data-theme="light"] .trio__chip[data-count-chip]{border-color:var(--line)}
/* The count chip holds second place but is no longer a whisper. */
.trio__chip[data-count-chip]{color:var(--text-2)}
@media (prefers-reduced-motion:reduce){
  .trio__chip--acc{transition:none}
  .trio__c:hover .trio__chip--acc,.trio__c.on .trio__chip--acc{transform:none}
}
.trio__n{
  font-family:var(--display);font-weight:600;font-size:2.407rem;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:.72rem;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:.765rem;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}
  /* The overlap, in layout rather than in transform. */
  .trio__c + .trio__c{margin-left:calc(var(--cw) * -1 * var(--lap))}

  .trio.in .trio__c:hover{
    transform:translateZ(calc(var(--i) * -44px + 40px)) rotateY(16deg);
    border-color:rgba(201,152,47,.45);
  }
  /* The chosen card is also drawn toward the middle, so the outer two do
     not magnify past the edge of the column when they come forward. */
  .trio.in .trio__c.on{
    transform:translateX(calc((1.5 - var(--i)) * 24%)) 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.32rem;margin:14px 0 9px}
  .trio__d{font-size:.7695rem;line-height:1.56;margin-bottom:14px}
  .trio__n{font-size:2.385rem}
  .trio__code{font-size:.522rem;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 deck narrows rather than
   clips. Card width and overlap both come from --cw/--lap above, so this band
   only has to deal with what is inside the card. */
@media (min-width:901px) and (max-width:1180px){
  .trio__in{padding:20px 18px 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 (min-width:901px) and (max-width:1000px){
  .trio__in{padding:18px 16px 18px;min-height:424px}
  .trio__t{font-size:1.2rem;margin:12px 0 8px}
  .trio__d{font-size:.735rem;margin-bottom:13px}
  .trio__code{font-size:.55rem;padding:5px 9px}
}

@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(1.909rem,3.32vw,2.739rem);line-height:1;color:var(--gold-text);
        margin-bottom:9px;font-variant-numeric:tabular-nums}
.stat span{font-size:.711rem;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:.819rem;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:2.905rem;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:.9545rem;margin-bottom:10px;padding-right:52px}
.step p{font-size:.783rem;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;
  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}

/* ---- the header ----
   Subject first, at display size and in the subject's own accent. A student
   scanning this grid is scanning for "Physics", not for a name, so the name
   has been demoted to the footer and the subject given the line that used to
   hold it. */
.fac__top{
  position:relative;z-index:2;display:flex;flex-direction:column;
  padding:13px 17px 14px;
}
.fac__marks{
  display:flex;align-items:flex-start;justify-content:space-between;
  gap:12px;min-height:13px;
}
/* Hatch block, top-left. */
.fac__hatch{
  width:56px;height:11px;flex:0 0 auto;margin-top:1px;
  background:repeating-linear-gradient(115deg,
    var(--hud-mark) 0 2px,transparent 2px 6px);
}
.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));
}
[data-theme="dark"] .fac__subj{color:color-mix(in srgb,var(--acc) 92%,#FFF6EE)}

/* Syllabus code, sitting under the headline as a caption rather than as the
   old top-right callout — the corner it used to occupy is now the star's. */
.fac__code{
  display:flex;align-items:center;gap:8px;margin-top:6px;
  font-family:var(--mono);font-size:.545rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--hud-mark-hi);
}
.fac__code i{
  width:16px;height:1.5px;flex:0 0 auto;background:var(--acc);opacity:.7;
  transition:width .42s var(--out);
}
.fac:hover .fac__code i,.fac.is-hot .fac__code i{width:26px}

/* ---- the portrait ----
   Placeholder art ships in the subject accent; a real photograph replaces it
   the moment <id>.webp exists. `is-ph` is set by the fallback so the
   drawn slot can be treated differently from a photograph — it is line art on
   a transparent ground and does not want the cover-crop or the saturation
   pass a real portrait gets. */
.fac__shot{
  position:relative;z-index:2;display:block;overflow:hidden;
  margin:0 15px;aspect-ratio:16/10;
  clip-path:polygon(12px 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%,0 12px);
  background:
    radial-gradient(120% 96% at 50% 0%,
      color-mix(in srgb,var(--acc) 9%,transparent),transparent 72%),
    var(--hud-shot);
}
.fac__shot img{
  width:100%;height:100%;display:block;object-fit:cover;object-position:center 22%;
  filter:saturate(.94) contrast(1.03);
  transition:transform .6s var(--out),filter .4s var(--ease);
}
.fac__shot img.is-ph{object-fit:contain;filter:none}
/* The plinth under an unfilled slot. Same brocade the photographs were shot
   against, so the drawn placeholder reads as a portrait not taken yet rather
   than as a different kind of card. */
.fac__shot.is-ph{
  background-image:
    radial-gradient(120% 96% at 50% 0%,
      color-mix(in srgb,var(--acc) 9%,transparent),transparent 72%),
    url("_plinth.webp");
  background-size:auto,cover;background-position:center,center;
}
.fac__dc{
  display:inline-flex;align-items:baseline;gap:5px;margin:6px 0 2px;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--text-3);
}
.fac__dc b{font-family:var(--display);font-size:1.02rem;letter-spacing:0;color:var(--gold-text);font-weight:600}
.fac__dc.is-ph b{color:var(--text-3)}
.fac:hover .fac__shot img,.fac.is-hot .fac__shot img{transform:scale(1.045)}
.fac:hover .fac__shot img.is-ph,.fac.is-hot .fac__shot img.is-ph{transform:none}
/* Hairline and a top-edge bloom, so the band reads as inset into the frame
   rather than pasted onto it. */
.fac__shot::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--acc) 22%,transparent);
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--hud-bloom) 26%,transparent),transparent 7%);
}
@media (prefers-reduced-motion:reduce){
  .fac__shot img{transition:none}
  .fac:hover .fac__shot img,.fac.is-hot .fac__shot img{transform:none}
}

/* ---- 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{
  /* No longer floated over the panel. It used to fill the dead half of the
     card beside the initials medallion; that space is a photograph now, and a
     glyph laid over a face is the one place this mark cannot go. It sits in
     the shoulder row instead, at badge size, where it is a subject cue rather
     than a watermark. */
  flex:0 0 auto;width:26px;height:26px;margin-top:-4px;
  color:var(--acc);opacity:.42;
  transition:opacity .42s var(--ease),transform .5s var(--out);
  transform:rotate(-6deg);
}
.fac:hover .fac__glyph,.fac.is-hot .fac__glyph{
  opacity:.85;transform:rotate(-6deg) scale(1.08);
}
@media (prefers-reduced-motion:reduce){
  .fac__glyph{transition:none}
  .fac:hover .fac__glyph,.fac.is-hot .fac__glyph{transform:rotate(-6deg)}
}

/* ---- footer ----
   Who teaches it. Second in the reading order on purpose, and set smaller than
   the subject above it. */
.fac__b{position:relative;z-index:2;padding:13px 17px 17px;
        display:flex;flex-direction:column;gap:5px;flex:1}
.fac__name{
  font-family:var(--display);font-size:.98rem;font-weight:500;
  line-height:1.16;margin:0;color:var(--text-1);
}
.fac__tag{font-size:.72rem;line-height:1.45;color:var(--text-2);margin:0;flex:1}
/* 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:flex-start;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:10px;
  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}
/* Same reason as the headline: the lighter accents are hairline colours, and
   the plate and the open-details line are type. Mixed toward the ink under the
   light theme only. */
.fac__more,.fac__plate{color:color-mix(in srgb,var(--acc) 62%,#3E1D0A)}
[data-theme="dark"] .fac__more,[data-theme="dark"] .fac__plate{color:var(--acc)}
.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:.575rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--acc);white-space:nowrap;
  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);
  --hud-shot:#F6F0E4;
}
[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);
  --hud-shot:#100C0D;
}

/* ---- the phone card ----
   At half a phone's width there is roughly 165px of usable line, so everything
   that was sized for a 300px card has to come down with it. The alternative is
   a full-width card, and twenty-one of those is a section nobody scrolls to
   the end of. */
@media (max-width:640px){
  .fac__top{padding:10px 11px 11px}
  .fac__b{padding:10px 11px 13px;gap:3px}
  .fac__shot{margin:0 10px}
  /* The hatch and the glyph are decoration, and decoration is the first thing
     to go when the row it sits in is 140px wide — dropping them is what leaves
     the distinction chip enough room to stay on one line. */
  .fac__hatch,.fac__glyph{display:none}
  .fac__marks{min-height:0}
  .fac__star{font-size:.44rem;letter-spacing:.1em;padding:3px 7px}
  .fac__subj{
    font-size:.99rem;margin-top:7px;
    /* Still two lines reserved, so cards sharing a row keep a common horizon
       whatever the length of the subject. */
    min-height:2.08em;
  }
  .fac__code{font-size:.475rem;letter-spacing:.1em;gap:5px;margin-top:4px}
  .fac__code i{width:10px}
  .fac__name{font-size:.83rem}
  .fac__tag{
    font-size:.635rem;line-height:1.38;
    /* Two lines of tag, then it clips. Left free, one long tag adds a line to
       every card in its row. */
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;
  }
  .fac__more{font-size:.475rem;letter-spacing:.13em;gap:5px;margin-top:8px}
  .fac__plate{font-size:.46rem;letter-spacing:.1em;padding:5px 10px 5px 20px}
}
@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:.756rem;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:.81rem;
  letter-spacing:.1em;
}
.rev__q{
  font-family:var(--display);font-size:clamp(.8466rem,1.245vw,1.0624rem);
  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:.747rem;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:.81rem;color:var(--rev-ink);
            overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rev__dist{
  display:inline-block;margin-left:6px;padding:2px 8px;border-radius:99px;vertical-align:1px;
  font-family:var(--mono);font-size:.54rem;letter-spacing:.12em;text-transform:uppercase;
  color:#2A0608;background:linear-gradient(101deg,#B8862B,#F0D089 52%,#B8862B);
}
.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);
}

/* ---- the phone carriage ----
   Hidden by default. It only exists below 860px, where the accordion is not
   an accordion any more and the row needs something to say where you are in
   it. */
.revs__ctl{display:none}
.revs__n{
  display:flex;align-items:center;gap:9px;margin:0;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--gold);
}
.revs__n::before{
  content:"";width:6px;height:6px;flex:0 0 auto;
  background:var(--gold);transform:rotate(45deg);
}
.revs__arrows{display:flex;gap:9px}
.revs__a{
  width:38px;height:38px;flex:0 0 auto;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  background:transparent;border:1px solid var(--line-2);color:var(--text-2);
  transition:border-color .3s var(--ease),color .3s var(--ease),transform .3s var(--spring);
}
.revs__a svg{width:17px;height:17px}
.revs__a:hover{border-color:color-mix(in srgb,var(--gold) 55%,transparent);color:var(--gold)}
.revs__a:active{transform:scale(.93)}

/* 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 snapped row of whole cards instead, one to a screen
   and driven by the carriage above rather than by a timer — an auto-advance
   that yanks the rail sideways under a thumb is worse than no motion at all,
   and on a phone there is no hover to pause it with. */
@media (max-width:860px){
  .revs__ctl{
    display:flex;align-items:center;justify-content:space-between;
    gap:12px;margin:0 0 14px;
  }
  .revs{
    height:auto;overflow-x:auto;gap:14px;
    scroll-snap-type:x mandatory;overscroll-behavior-x:contain;
    padding:2px 0 14px;margin-inline:0;scrollbar-width:none;
  }
  .revs::-webkit-scrollbar{display:none}
  .rev{
    /* One card to a screen rather than the old 310px with a slice of the next
       one showing. The peek was there to advertise that the row scrolled; the
       arrows and the counter say that now, and they say it without cropping
       the quote you are trying to read. */
    flex:0 0 100%;width:auto;min-height:280px;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__q{-webkit-line-clamp:7}
  .rev::before{opacity:1}
  /* The pip fill is a countdown to the next auto-advance. Nothing counts down
     here, so it reads as a flat marker. */
  .revs__bar{justify-content:flex-start}
  .revs__bar i.on::after{animation:none;transform:scaleX(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:.7636rem;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%}
/* The photograph over the drawn poster. Same 16:10 as the plate, so it seats
   without a crop; if the file is missing the img removes itself and the drawn
   artwork underneath is what shows. */
.fpop__shot{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:saturate(.94) contrast(1.03);
}
.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:.9rem;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.245rem;margin:0;line-height:1.16;color:#FBF5EC}
.fpop__mins{
  flex:0 0 auto;font-family:var(--display);font-size:1.0956rem;font-weight:600;
  color:var(--acc);letter-spacing:-.01em;
}
.fpop__tag{font-size:.81rem;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:.63rem;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:.756rem;
}
.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:.828rem;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:.765rem;
  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:.738rem}
  .fpop__right{border-left:0;border-top:1px solid var(--fp-line);overflow:visible;padding:20px 18px 22px}
  .fpop__head h3{font-size:1.0624rem}
}
@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:.891rem}
.sub span span{font-size:.675rem;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:.918rem;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:.873rem;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:.72rem;
  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:.855rem}
  .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:.882rem;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:.918rem;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:.846rem;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:.792rem;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:.765rem;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:.913rem;line-height:1.24;margin:0;color:#F7EFE2}
.camp--flag .camp__top h3{font-size:1.1122rem}
.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:.765rem;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:.702rem;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:.711rem;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:.9628rem}
}
@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.079rem,1.826vw,1.4276rem);margin:10px 0 0;color:#FBF5EC;line-height:1.18}
.cpop__head p{margin:9px 0 0;font-size:.783rem;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}
}

/* ========================= SWK BAND ========================= */
/* This band used to be a navy plate, dark in both themes, with the page's
   glass tokens pinned to their dark values so the components inside it kept
   working. It sits on the page colour now. Two things follow from that: the
   band joins the page instead of interrupting it, and every glass surface in
   it can go back to reading the theme rather than a pinned copy — which is
   why the pinned block, the vignette and the two edge fades that used to
   dissolve a dark plate into a cream page are all gone. Only the gold is
   still SWK's, and it darkens under the light theme so it can be read on
   cream. */
.cine{
  --swk-gold:#C08D18;
  --swk-gold-hi:#A8761A;
  position:relative;overflow:hidden;
  padding-block:clamp(72px,8vw,124px);
  margin-block:0;
}
[data-theme="dark"] .cine{--swk-gold:#F3BD1D;--swk-gold-hi:#FFDA74}
/* One soft bloom behind the pane, centred on it. */
.cine::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(circle 660px at 50% 46%,
    color-mix(in srgb,var(--swk-gold) 11%,transparent),transparent 74%);
}


/* ---- 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,color-mix(in srgb,var(--swk-gold) 13%,transparent) 0 1px,transparent 1px 13px),
    radial-gradient(circle at 1px 1px,color-mix(in srgb,var(--swk-gold) 18%,transparent) 1px,transparent 0);
  background-size:auto,28px 28px;
  /* The scoop was at 32% because the shield used to sit on the left. The
     composition is centred now and so is the hole. */
  -webkit-mask-image:
    radial-gradient(56% 60% at 50% 46%,transparent 24%,#000 80%),
    linear-gradient(180deg,transparent,#000 16%,#000 84%,transparent);
  mask-image:
    radial-gradient(56% 60% at 50% 46%,transparent 24%,#000 80%),
    linear-gradient(180deg,transparent,#000 16%,#000 84%,transparent);
  -webkit-mask-composite:source-in;mask-composite:intersect;
  opacity:.75;
}
/* ── glass composition ─────────────────────────────────────────────────────
   One frosted pane, centred, with everything inside it stacked on the same
   axis. Four tiers of the same glass: the pane is the heaviest, the figures
   sit a tier clearer inside it, the campus chips are the lightest, and the
   crest is a lens. Four tiers is what stops a stack of translucent boxes
   from flattening into one grey slab.

   Every tier is written twice — once for cream and once for the dark theme.
   Glass is the one component that cannot be theme-agnostic: on cream it is a
   white film with a warm shadow, on near-black it is a white film at a
   twentieth of the strength with no shadow to speak of, and the same numbers
   give a milky smear in one and an invisible box in the other. */
.cine--glass{padding-block:clamp(72px,8vw,124px)}
.cine__hold{position:relative;z-index:3}

/* Orbs. Slow, large, heavily blurred — a glass pane needs colour behind it or
   the blur has nothing to bend and the whole effect reads as grey. */
.gorbs{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:hidden}
.gorbs i{
  position:absolute;display:block;border-radius:50%;
  /* Dimmer on cream than on navy: a bright orb under a white film washes the
     film out, and the copy on top of it loses its contrast. */
  filter:blur(96px);opacity:.3;
  animation:gdrift 26s var(--ease) infinite alternate;
}
[data-theme="dark"] .gorbs i{opacity:.4}
.gorbs i:nth-child(1){
  width:min(46vw,540px);aspect-ratio:1;left:-12%;top:-20%;
  background:radial-gradient(circle,rgba(226,168,42,.6),transparent 68%);
}
.gorbs i:nth-child(2){
  width:min(40vw,470px);aspect-ratio:1;right:-6%;top:14%;
  background:radial-gradient(circle,rgba(150,62,54,.44),transparent 68%);
  animation-duration:32s;animation-delay:-8s;
}
.gorbs i:nth-child(3){
  width:min(34vw,400px);aspect-ratio:1;left:36%;bottom:-22%;
  background:radial-gradient(circle,rgba(70,104,150,.4),transparent 70%);
  animation-duration:38s;animation-delay:-16s;
}
@keyframes gdrift{
  from{transform:translate3d(0,0,0) scale(1)}
  to{transform:translate3d(4%,-5%,0) scale(1.14)}
}

/* ---- the pane ---- */
.gpane{
  position:relative;isolation:isolate;overflow:hidden;
  /* Wider and shallower than it was. At 880 the headline broke across two
     lines and the lede across three, which turned a centred card into a tall
     column with a lot of air at both ends. */
  max-width:calc(var(--wrap) - 120px);margin-inline:auto;
  display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:clamp(34px,3.4vw,50px) clamp(26px,4.4vw,76px) clamp(34px,3.4vw,50px);
  border-radius:clamp(20px,2vw,30px);
  background:linear-gradient(148deg,
    rgba(255,255,255,.66) 0%,
    rgba(255,255,255,.4) 46%,
    rgba(255,255,255,.3) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    0 34px 74px -34px rgba(66,42,20,.36),
    0 0 70px -22px color-mix(in srgb,var(--swk-gold) 22%,transparent);
}
[data-theme="dark"] .gpane{
  background:linear-gradient(148deg,
    rgba(255,255,255,.115) 0%,
    rgba(255,255,255,.045) 44%,
    rgba(255,255,255,.02) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.3),
    0 40px 80px -34px rgba(0,0,0,.78),
    0 0 60px -18px rgba(243,189,29,.13);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .gpane{-webkit-backdrop-filter:blur(34px) saturate(1.5);backdrop-filter:blur(34px) saturate(1.5)}
}
/* Without backdrop-filter the pane is a near-transparent box over three bright
   orbs, which is unreadable rather than merely plainer. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .gpane{background:var(--panel-solid)}
}
/* The rim, lit from the top left and dying out at the opposite corner. A
   uniform 1px border round a glass pane is the tell that it is a rectangle
   with a stroke rather than an edge catching light. On cream the far side of
   that edge has to go warm-dark instead of white, or there is no edge there
   at all. */
.gpane__rim{
  position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:2;
  padding:1px;
  background:linear-gradient(142deg,
    rgba(255,255,255,1) 0%,
    rgba(255,255,255,.6) 24%,
    rgba(120,86,40,.13) 58%,
    rgba(120,86,40,.2) 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;
}
[data-theme="dark"] .gpane__rim{
  background:linear-gradient(142deg,
    rgba(255,255,255,.62) 0%,
    rgba(255,246,226,.24) 26%,
    rgba(255,255,255,.06) 56%,
    rgba(255,255,255,.14) 100%);
}
/* A single slow specular pass — the one thing that makes a frosted rectangle
   read as a physical surface rather than a blurred background. */
.gpane__sheen{
  position:absolute;top:-60%;left:-40%;width:52%;height:220%;z-index:1;
  pointer-events:none;transform:rotate(18deg);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.34),transparent);
  animation:gsheen 9s var(--ease) infinite;
}
[data-theme="dark"] .gpane__sheen{
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.09),transparent);
}
@keyframes gsheen{
  0%,62%{transform:translateX(0) rotate(18deg)}
  92%,100%{transform:translateX(340%) rotate(18deg)}
}

/* The founder's art column crops a portrait to fill. A shield cropped to fill
   is a shield with its corners cut off, so this one is contained and given
   room to breathe instead. */
/* The crest sits on its own lit plate: a warm pool of light behind it, a
   real two-layer shadow under it (tight contact shadow plus a long soft one)
   and the caption set in the plate as text, not over a dark scrim. */
.fdlg--swk .fdlg__art{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(14px,2vh,22px);
}
.fdlg--swk .fdlg__art::before{
  content:"";position:absolute;inset:var(--fd-pad);z-index:0;pointer-events:none;
  border-radius:var(--fd-r);
  border:1px solid color-mix(in srgb,var(--swk-gold,#C08D18) 28%,var(--edge));
  background:
    radial-gradient(60% 46% at 50% 40%,
      color-mix(in srgb,var(--swk-gold,#C08D18) 30%,transparent),transparent 72%),
    linear-gradient(180deg,
      color-mix(in srgb,var(--panel-solid) 94%,#fff),
      color-mix(in srgb,var(--panel-solid) 86%,var(--swk-gold,#C08D18)));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 16px 36px -22px rgba(10,4,4,.45);
}
.fdlg--swk .fdlg__art::after{display:none}
.fdlg--swk .fdlg__art img{
  position:relative;z-index:1;
  width:min(68%,240px);height:auto;aspect-ratio:1;object-fit:contain;
  padding:0;background:none;border-radius:0;box-shadow:none;
  filter:drop-shadow(0 3px 3px rgba(20,14,2,.22)) drop-shadow(0 22px 26px rgba(20,14,2,.26));
}
.fdlg--swk .fdlg__cap{
  position:relative;z-index:1;left:auto;right:auto;bottom:auto;
  padding:0 16px;text-align:center;justify-items:center;
}
.fdlg--swk .fdlg__cap b{color:var(--text-1);font-size:1.12rem}
.fdlg--swk .fdlg__cap span{color:var(--gold-text)}
@media (max-width:760px){
  .fdlg--swk .fdlg__art{aspect-ratio:auto;padding:var(--fd-pad);padding-bottom:var(--fd-pad);min-height:0}
  .fdlg--swk .fdlg__art img{width:min(34%,150px);margin-top:18px}
  .fdlg--swk .fdlg__cap{padding-bottom:18px}
}

/* ---- the filament ----
   Same silver hairline the buttons use, borrowed wholesale: one dash the
   length of the perimeter, parked off the path until hover, then laid all the
   way round. The rect only needs its corner radius told to it, because the
   trace rect is sized from the element it sits in and 19.4px is the button's
   radius, not this pane's. */
.gpane > .btn__trace rect{rx:clamp(20px,2vw,30px);ry:clamp(20px,2vw,30px)}
.gstats li > .btn__trace rect{rx:14px;ry:14px}
.gpane:hover > .btn__trace rect,
.gpane:focus-within > .btn__trace rect,
.gstats li:hover > .btn__trace rect{stroke-dashoffset:0;opacity:1}

/* The whole pane is pressable, so it takes the pointer that says so. Anything
   interactive inside it keeps its own cursor. */
.gpane{cursor:pointer}
.gpane a,.gpane button{cursor:pointer}

/* ---- read the full story ---- */
.gmore{
  margin-top:14px;padding:8px 4px;border:0;background:none;cursor:pointer;
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:.56rem;letter-spacing:.17em;
  text-transform:uppercase;color:var(--swk-gold-hi);
  transition:gap .34s var(--out),color .3s var(--ease);
}
.gmore i{font-style:normal;transition:transform .34s var(--out)}
.gpane:hover .gmore i,.gmore:hover i,.gmore:focus-visible i{transform:translateX(3px)}
.gmore:hover,.gmore:focus-visible{gap:13px}

/* ---- inline route into the SWK band ----
   The band was reachable from exactly two places: the hero badge and the
   footer mark. Every other mention of the institute was flat text, so a reader
   who wondered what SWK is had to go looking. These are prose links, so they
   are marked the way prose links are — a gold rule under the words that fills
   in on hover — rather than styled as another button. */
.ilink{
  color:inherit;text-decoration:none;
  background-image:linear-gradient(var(--gold-text,#9A6B12),var(--gold-text,#9A6B12));
  background-size:100% 1px;background-position:0 100%;background-repeat:no-repeat;
  padding-bottom:1px;
  transition:color .3s var(--ease),background-size .34s var(--out);
}
.ilink:hover,.ilink:focus-visible{
  color:var(--gold-text,#9A6B12);
  background-size:100% 2px;
}

/* Everything inside sits on the pane's own axis.

   The three overlays have to be exempted by name. This rule gives every direct
   child position:relative so its z-index applies, and it was quietly winning
   against the rim, the sheen and the filament — all three were being laid out
   as flow items, which is where the empty band above the eyebrow came from and
   why none of them were painting over the pane. */
.gpane > *{position:relative;z-index:3;max-width:100%}
.gpane > .gpane__rim,
.gpane > .gpane__sheen,
.gpane > .btn__trace{position:absolute}
.gpane .eyebrow{color:var(--swk-gold)}
.gpane .eyebrow::before{background:var(--swk-gold)}
.gpane .rule{background:linear-gradient(90deg,transparent,var(--swk-gold),transparent);margin-bottom:6px}
.gpane h2{letter-spacing:-.014em;margin-top:2px;text-wrap:balance}
.gpane h2 em{color:var(--swk-gold-hi)}
.gpane .lede{color:var(--text-2);max-width:62ch;margin-inline:auto}

/* ---- the crest, as a lens ---- */
.gmed{
  position:relative;width:min(128px,34vw);aspect-ratio:1;margin:clamp(16px,1.8vw,22px) 0 12px;
  border-radius:50%;display:grid;place-items:center;
  background:radial-gradient(circle at 34% 28%,
    rgba(255,255,255,.85),rgba(255,255,255,.45) 54%,rgba(255,255,255,.28) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,1),
    inset 0 -14px 30px -18px color-mix(in srgb,var(--swk-gold) 50%,transparent),
    0 18px 36px -18px rgba(66,42,20,.4);
}
[data-theme="dark"] .gmed{
  background:radial-gradient(circle at 34% 28%,
    rgba(255,255,255,.2),rgba(255,255,255,.05) 52%,rgba(255,255,255,.015) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.45),
    inset 0 -14px 30px -18px rgba(243,189,29,.5),
    0 20px 40px -20px rgba(0,0,0,.7);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .gmed{-webkit-backdrop-filter:blur(8px) saturate(1.5) brightness(1.04);
        backdrop-filter:blur(8px) saturate(1.5) brightness(1.04)}
}
.gmed img{width:66%;height:auto;position:relative;z-index:2;
          filter:drop-shadow(0 6px 14px rgba(50,32,12,.3))}
.gmed__ring{
  position:absolute;inset:-11px;border-radius:50%;
  border:1px dashed color-mix(in srgb,var(--swk-gold) 42%,transparent);
  animation:gspin 44s linear infinite;
}
@keyframes gspin{to{transform:rotate(360deg)}}
.gmed__k{margin:0;font-family:var(--display);font-weight:500;font-size:1.02rem;color:var(--text-1)}
.gmed__s{
  margin:2px 0 clamp(12px,1.4vw,18px);
  font-family:var(--mono);font-size:.52rem;letter-spacing:.17em;
  text-transform:uppercase;color:var(--text-3);
}

/* ---- the figures: a clearer tier set into the pane ---- */
.gstats{
  list-style:none;margin:clamp(20px,2.2vw,28px) 0 0;padding:0;width:100%;
  display:flex;flex-wrap:wrap;justify-content:center;gap:10px;
}
.gstats li{
  flex:1 1 150px;max-width:230px;min-width:0;
  padding:15px 16px 14px;border-radius:14px;
  display:grid;gap:5px;justify-items:center;
  background:linear-gradient(160deg,rgba(255,255,255,.72),rgba(255,255,255,.34));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,1),
    inset 0 0 0 1px rgba(120,86,40,.11),
    0 12px 24px -18px rgba(66,42,20,.5);
  transition:background .45s var(--ease),box-shadow .45s var(--ease),transform .45s var(--spring);
}
[data-theme="dark"] .gstats li{
  background:linear-gradient(160deg,rgba(255,255,255,.1),rgba(255,255,255,.025));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.28),
    inset 0 0 0 1px rgba(255,255,255,.075),
    0 12px 26px -18px rgba(0,0,0,.8);
}
.gstats li:hover{transform:translateY(-3px)}
.gstats b{
  font-family:var(--display);font-weight:500;line-height:1;
  font-size:clamp(1.5rem,2.3vw,2rem);color:var(--swk-gold-hi);
}
[data-theme="dark"] .gstats b{text-shadow:0 0 24px rgba(243,189,29,.32)}
/* A word where the other two plates carry a numeral. Set down a step so it
   holds the same optical weight as 2006 and 18 instead of overrunning the
   plate. */
.gstats b.gstats__w{
  font-size:clamp(1.02rem,1.45vw,1.28rem);letter-spacing:-.004em;
  line-height:1.1;text-align:center;text-wrap:balance;
}
.gstats span{
  font-family:var(--mono);font-size:.52rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--text-3);
}

/* ---- campus chips: the lightest tier ---- */
.gchips{
  list-style:none;margin:clamp(14px,1.6vw,20px) 0 0;padding:0;
  display:flex;flex-wrap:wrap;justify-content:center;gap:6px;
}
.gchips li{
  padding:5px 11px;border-radius:999px;
  font-family:var(--mono);font-size:.5rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text-2);
  background:rgba(255,255,255,.5);
  box-shadow:inset 0 0 0 1px rgba(120,86,40,.12),inset 0 1px 0 rgba(255,255,255,.9);
}
[data-theme="dark"] .gchips li{
  color:rgba(237,243,250,.66);background:rgba(255,255,255,.055);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.1),inset 0 1px 0 rgba(255,255,255,.16);
}
.gchips li.is-on{
  color:#FFF6E2;
  background:linear-gradient(160deg,var(--swk-gold),var(--swk-gold-hi));
  box-shadow:0 6px 16px -8px color-mix(in srgb,var(--swk-gold) 80%,transparent);
}
[data-theme="dark"] .gchips li.is-on{color:#0F1A2A}
.cine__cta{margin-top:clamp(20px,2.2vw,28px)}

@media (max-width:560px){
  .gstats li{flex:1 1 100%;max-width:none;padding:13px 14px 12px}
  .gpane{padding:24px 18px 26px}
  .gorbs i{filter:blur(64px)}
}
/* The blur is the expensive part of this band; the orbs and the sheen are what
   make it expensive to animate as well. */
@media (prefers-reduced-motion:reduce){
  .gorbs i,.gpane__sheen,.gmed__ring{animation:none}
  .gstats li{transition:none}
  .gstats li:hover{transform:none}
}

/* ------------------------------------------------------------------ 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:.828rem;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:14.4px; /* 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:.792rem;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:.684rem;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:.765rem;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:.774rem;
  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:.747rem;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:.756rem;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:.684rem;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:.477rem;letter-spacing:.09em}
  .wiz__steps b{width:27px;height:27px;font-size:.63rem}
  .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:.738rem;
            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.26rem;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.035rem}
.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.2035rem,1.992vw,1.66rem);margin:0}
.player__chips{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px}
.player__chips span{font-size:.612rem;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:.81rem}
.chap__b small{font-size:.666rem;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:.792rem;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:.702rem;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}

.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.1205rem;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:.783rem;
           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}
  /* Two to a row on phones rather than one. Twenty-one full-width cards is
     roughly nine thousand pixels of scrolling to get past the faculty, and the
     card only needs about half a phone's width to stay legible once the type
     inside it is sized for that width — see the compaction block further
     down. */
  /* --cmax matches --cw so the odd card at the end of the roster stays a
     half-width card and centres, instead of stretching across the screen and
     reading as a different kind of thing. */
  .facgrid{--cw:calc(50% - 6px);--cmax:calc(50% - 6px);gap:12px}
  /* 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:.747rem;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");  /* <- your file */
  --secbg-size:auto;                  /* leave as auto unless you must scale */
}
/* One tile per theme. The light cut is an ivory damask, the dark cut the same
   motif in oxblood — the cloth the faculty portraits were shot against, which
   is what ties the plinth shots to the page they sit on. Both are 750px
   square-ish and tile at their own size; see the note above about --secbg-size. */
[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 520px}
  #courses  {content-visibility:auto;contain-intrinsic-size:auto 800px}
  #campuses {content-visibility:auto;contain-intrinsic-size:auto 520px}
  #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:.828rem;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:.792rem;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:.774rem;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:.72rem;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:.738rem;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:14.4px}   /* 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:.846rem}
  .sel__opt::before{left:6px;height:19px;margin-top:-9.5px}
  .sel__opt em{font-size:.72rem}
  .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:.846rem}
  .find__sort.sel .sel__btn{padding:12px 34px 12px 16px;font-size:.774rem}
  .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.245rem,2.49vw,1.6185rem);
  line-height:1.14;color:#FCF6EC;margin:0 0 12px;
}
.nx__box > p{font-size:.846rem;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:.774rem;
}
.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:.81rem;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:.774rem;
  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:.972rem}
  .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:.8964rem;line-height:1.2;
  color:var(--text-1);margin:0 0 5px;font-weight:600;
}
.ad__p{font-size:.711rem;line-height:1.55;color:var(--text-2);margin:0 0 11px}
.ad__go{
  display:inline-flex;align-items:center;gap:7px;
  font-size:.711rem;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:.9rem}
}
/* 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}
/* The road runs along the BOTTOM of the pill, not through its middle. Centred,
   the dashed line struck straight through the message riding above it and read
   as a strikethrough. Held low, the button splits cleanly into two registers:
   carriageway underneath, message on top of it — which is also the way round
   the brief asked for. */
.dlv__deck{
  position:absolute;left:0;right:0;bottom:6px;height:0;
  background:linear-gradient(180deg,var(--dlv-1),var(--dlv-2) 52%,var(--dlv-1));
  transition:height .52s var(--out);
}
/* The deck opens from nothing 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:20px}
/* The dashes only start running once the deck has opened. */
.dlv__line{
  position:absolute;left:-30%;right:-30%;bottom:15px;height:2px;
  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. */
/* Sized so the wheels sit on the carriageway rather than hovering over it or
   sinking through it: at 58px the body is 21px tall and the axles land just
   inside the deck's upper edge. */
.dlv__bus{
  position:absolute;bottom:9px;left:0;width:58px;
  transform:translateX(-80px);
  filter:drop-shadow(0 3px 5px rgba(30,10,4,.55));
}
.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:translateX(-80px)}
  100%{transform:translateX(calc(100vw))}
}
/* 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. */
/* The message rides in the register above the road. The bottom padding is the
   deck's own height plus its offset, so the line centres in what is left
   rather than in the whole pill. */
.dlv__say{
  position:absolute;inset:0;z-index:2;display:grid;place-items:center;
  padding-bottom:26px;
  font-size:.738rem;font-weight:500;letter-spacing:.01em;
  /* Themed, not fixed. The message sits on the page's own background above
     the road, so a single gold would be right on the dark page and invisible
     on the cream one — which is exactly what it was. */
  color:var(--dlv-ink);text-shadow:var(--dlv-ink-sh);
  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);
  --dlv-ink:#6B4A0E;
  --dlv-ink-sh:0 1px 0 rgba(255,255,255,.6);
}
[data-theme="dark"]{
  --dlv-1:#160B0C;--dlv-2:#231314;--dlv-paint:rgba(255,236,190,.6);
  --dlv-ink:var(--gold-hi);
  --dlv-ink-sh:0 1px 8px rgba(20,6,2,.9);
}
@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 HONOURS BAND ═══════════════════════
   The record, given its own weight on the page. Three objects: the founder's
   plate, the four-cell ledger, and the pinned faculty row underneath.

   The plate is the only element on the site that carries a moving gild — a
   single sweep, slow, on a long loop. It is the visual hook for the one award
   counted apart from the rest, and it is deliberately not reused anywhere
   else: a highlight that appears twice stops being a highlight. */
.hon{position:relative}
/* It is a section now rather than a block inside Results, so it carries the
   section's own top rule and does not sit flush against the band above it. */
.hon .hon__world{margin-top:clamp(30px,3.4vw,46px)}

/* ---- the world ribbon ----------------------------------------------------
   One object, used in the three places the award is claimed: the founder's
   portrait, his card in the faculty list and the head of his detail panel.
   Shared so the mark is identical everywhere and cannot drift into three
   slightly different badges. */
.wrib{
  position:absolute;z-index:6;left:50%;bottom:14px;transform:translateX(-50%);
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  padding:7px 14px;border-radius:999px;
  background:linear-gradient(101deg,#B8862B,#F0D089 50%,#B8862B);
  color:#2A0608;font-family:var(--mono);font-weight:600;
  font-size:.58rem;letter-spacing:.15em;text-transform:uppercase;
  box-shadow:0 8px 22px -8px rgba(42,6,8,.7),inset 0 1px 0 rgba(255,255,255,.5);
}
.wrib svg{width:12px;height:12px;flex:0 0 auto}
@media (max-width:720px){.wrib{font-size:.52rem;padding:6px 11px;bottom:-11px}}

.fmsg__note--rec{margin-top:12px}
.fmsg__note--rec .ilink{white-space:nowrap}

/* The same mark, seated in the detail panel's header rather than floating. */
.fpop__wrib{
  position:static;transform:none;margin-bottom:11px;
}

/* ---- the founder's plate ----
   Three beats: crest, copy, seal. It was two, and the right third of the card
   was empty — which made it read as a paragraph that had been given a border
   rather than as a plate. The seal closes the composition and puts the single
   figure that matters where the eye finishes. */
.hon__world{
  position:relative;overflow:hidden;cursor:pointer;
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  gap:clamp(22px,3vw,42px);align-items:center;
  padding:clamp(26px,3.2vw,40px) clamp(24px,3.4vw,46px);
  margin-top:clamp(26px,3vw,40px);
  transition:transform .5s cubic-bezier(.16,1,.3,1),box-shadow .5s;
}
.hon__world:hover{transform:translateY(-3px)}
/* The sweep. Parked off-canvas for most of the cycle, then crossing once —
   the same cadence the header pill uses, so the two read as one language. */
.hon__gild{
  position:absolute;inset:0;pointer-events:none;z-index:1;
  background:linear-gradient(104deg,transparent 38%,rgba(201,152,47,.16) 47%,
             rgba(255,241,214,.24) 50%,rgba(201,152,47,.16) 53%,transparent 62%);
  background-size:280% 100%;background-position:190% 0;
  animation:honGild 9s cubic-bezier(.4,0,.2,1) infinite;
}
@keyframes honGild{0%,62%{background-position:190% 0}100%{background-position:-90% 0}}

.hon__worldArt{position:relative;flex:0 0 auto;display:grid;place-items:center}
.hon__worldArt img.hon__photo{
  width:clamp(118px,12vw,176px);aspect-ratio:4/5;height:auto;object-fit:cover;object-position:center 20%;
  border-radius:18px;border:1px solid color-mix(in srgb,var(--gold) 55%,transparent);
  box-shadow:0 0 0 5px color-mix(in srgb,var(--gold) 12%,transparent),0 18px 34px -16px rgba(42,6,8,.55);
  filter:none;
}
/* Now a lead-in rather than a footnote, so the air moves: a section's worth
   above it, a heading's worth below it before the cards start. */
.hon__after{margin-top:clamp(44px,5vw,72px);margin-bottom:clamp(24px,2.8vw,38px)}
/* A step up from the base h3, which is sized for a card title. It is a
   subsection under the section's own h2 and should not rival it. */
.hon__afterT{font-size:clamp(1.28rem,2.1vw,1.78rem);line-height:1.14;margin:0}
/* The line that hands the reader on to the roster. Sits under the three
   cards and carries only the air it needs to separate them from the faculty
   section's own heading. */
.hon__into{margin-top:clamp(26px,3.2vw,42px);margin-bottom:0}
/* Heading, cards and hand-off as one centred column. The nav's About link
   lands on this, so it has to read as a block with a top and a bottom rather
   than as whatever happens to be under the anchor. */
.hon__set{
  display:flex;flex-direction:column;align-items:center;
  scroll-margin-top:96px;
}
.hon__set > *{width:100%}
/* The founder's card leads the three: centred and larger on a laptop, alone
   on top across the full width on a phone. */
.facgrid--dist{align-items:center}
.facgrid--dist > .fac:nth-child(2){order:1}
.facgrid--dist > .fac--world{order:2;flex-basis:420px;max-width:440px}
.facgrid--dist > .fac:nth-child(3){order:3}
@media (max-width:640px){
  .facgrid--dist > .fac--world{order:0;flex-basis:100%;max-width:100%}
}
.hon__worldArt img{
  position:relative;z-index:2;
  width:clamp(96px,10vw,150px);height:auto;display:block;
  filter:drop-shadow(0 14px 30px rgba(42,6,8,.32));
}
/* A pool of light under the crest, breathing on a long cycle. */
.hon__ray{
  position:absolute;width:150%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(201,152,47,.30),transparent 66%);
  filter:blur(16px);animation:honRay 7.5s ease-in-out infinite;
}
@keyframes honRay{0%,100%{transform:scale(1);opacity:.72}50%{transform:scale(1.14);opacity:1}}

.hon__worldTxt{position:relative;z-index:2;min-width:0}
.hon__eyebrow{display:inline-flex;align-items:center;gap:8px;color:var(--gold);margin-bottom:9px}
.hon__eyebrow svg{width:15px;height:15px;flex:0 0 auto}
.hon__world h3{margin:0 0 10px;font-size:clamp(1.32rem,2.3vw,1.86rem)}
.hon__worldP{
  margin:0 0 16px;max-width:58ch;
  font-size:clamp(.88rem,1.15vw,.97rem);color:var(--text-2);line-height:1.72;
}
.hon__more{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:.63rem;letter-spacing:.17em;
  text-transform:uppercase;color:var(--gold);
}
.hon__more svg{width:14px;height:14px;transition:transform .4s cubic-bezier(.16,1,.3,1)}
.hon__world:hover .hon__more svg{transform:translateX(5px)}

/* ---- the seal ---- */
.hon__seal{
  position:relative;z-index:2;
  display:flex;flex-direction:column;align-items:center;text-align:center;
  padding-left:clamp(20px,2.4vw,34px);flex:0 0 auto;
}
/* A hairline, not a border: it fades at both ends so the column is separated
   without a rule being drawn across the plate. */
.hon__sealRule{
  position:absolute;left:0;top:6%;bottom:6%;width:1px;
  background:linear-gradient(180deg,transparent,var(--line) 18%,var(--line) 82%,transparent);
}
.hon__seal b{
  font-family:var(--display);font-weight:600;line-height:.9;
  font-size:clamp(2.6rem,5vw,3.9rem);
  background:linear-gradient(160deg,#B8862B,#F0D089 46%,#B8862B);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.hon__sealK{
  margin-top:10px;max-width:17ch;
  font-family:var(--mono);font-size:.56rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text-2);line-height:1.75;
  text-wrap:balance;
}
.hon__sealS{
  margin-top:6px;font-family:var(--mono);font-size:.55rem;
  letter-spacing:.14em;text-transform:uppercase;color:var(--text-3);
}

/* ---- the ledger ---- */
.hon__ledger{
  display:grid;grid-template-columns:repeat(4,1fr);
  gap:clamp(12px,1.4vw,20px);margin-top:clamp(16px,2vw,26px);
}
.hon__cell{
  display:flex;flex-direction:column;align-items:flex-start;
  position:relative;isolation:isolate;
  padding:clamp(18px,2.1vw,26px) clamp(16px,1.9vw,24px);
  border-radius:var(--r-sm);background:var(--panel);border:1px solid var(--line);
}
/* The specular rim — the same ring the glass panes and the wizard carry. A
   flat border alone reads as a sticker; the ledger sits directly under the
   world card, which has one, so without it the four cells looked like a
   different material to the thing they belong to. Bright where light enters
   at the top-left, running down to a floor rather than to nothing, so the
   edge stays continuous the whole way round and only its brightness varies. */
.hon__cell::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. */
.hon__cell::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  border-radius:inherit;background:var(--clear-tint);
}
.hon__cell > *{position:relative;z-index:1}
.hon__cell--act{justify-content:center}
/* The four cells carry different things — a numeral, a word, a row of chips,
   a button — so their labels landed at four different heights. The value slot
   is given one height and its contents sit on its floor, which puts every
   DISTINCTIONS / WORLD / WHERE THEY SIT label on the same line across the
   row. */
.hon__cell > :first-child{
  min-height:clamp(2.4rem,4.4vw,3.2rem);
  display:flex;align-items:flex-end;
}
.hon__cell--act > :first-child{min-height:0;display:block}
.hon__n{
  font-family:var(--display);font-weight:600;line-height:.95;
  font-size:clamp(2.1rem,4.2vw,3.1rem);color:var(--gold);
}
.hon__n--word{font-size:clamp(1.5rem,2.6vw,2rem);letter-spacing:-.01em}
.hon__k{
  margin-top:11px;font-family:var(--mono);font-size:.6rem;
  letter-spacing:.19em;text-transform:uppercase;color:var(--text-2);
}
.hon__s{margin-top:5px;font-size:.78rem;color:var(--text-3);line-height:1.5}
.hon__lv{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:3px;align-content:flex-end}
.hon__lv i{
  font-style:normal;padding:5px 10px;border-radius:7px;
  border:1px solid var(--line);background:var(--panel-2);
  font-family:var(--mono);font-size:.6rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--text-2);
}

@media (max-width:1080px){
  /* The seal is the first thing to go: below this the copy column is too
     narrow to carry a third column beside it without the lines breaking
     badly. It becomes a strip under the copy instead. */
  .hon__world{grid-template-columns:auto minmax(0,1fr)}
  .hon__seal{
    grid-column:2;flex-direction:row;align-items:baseline;gap:11px;
    padding-left:0;padding-top:16px;margin-top:4px;text-align:left;
  }
  .hon__sealRule{
    left:0;right:0;top:0;bottom:auto;width:auto;height:1px;
    background:linear-gradient(90deg,var(--line),transparent 72%);
  }
  .hon__seal b{font-size:1.7rem}
  .hon__sealK{margin-top:0;max-width:none}
  .hon__sealS{margin-top:0}
  .hon__sealS::before{content:"\00b7";margin-right:9px;opacity:.6}
}
@media (max-width:1000px){
  .hon__ledger{grid-template-columns:repeat(2,1fr)}
  .hon__cell--wide{grid-column:1 / -1}
}
@media (max-width:720px){
  .hon__world{grid-template-columns:1fr;text-align:center;justify-items:center}
  .hon__worldP{margin-inline:auto}
  .hon__seal{grid-column:1;justify-content:center;text-align:center}
  .hon__ledger{grid-template-columns:1fr}
  .hon__cell{align-items:center;text-align:center}
  .hon__cell > :first-child{justify-content:center}
  .hon__lv{justify-content:center}
  .hon__cell--act{align-items:stretch}
}
@media (prefers-reduced-motion:reduce){.hon__gild,.hon__ray{animation:none}}

/* ══════════════════ FACULTY — the honours cards ════════════════
   A distinction card is the ordinary card with three things added: a warmer
   pane, a gilt hairline down the leading edge, and a lifted rest state. It is
   not a different component — keeping it the same object means the grid still
   aligns and the finder still filters it without a special case. */
.fac--dist .fac__pane{
  background:linear-gradient(150deg,rgba(201,152,47,.075),transparent 46%),var(--panel);
  border-color:color-mix(in srgb,var(--gold) 34%,var(--line));
}
.fac--dist .fac__pane::after{
  content:"";position:absolute;left:0;top:12%;bottom:12%;width:2px;
  border-radius:2px;pointer-events:none;
  background:linear-gradient(180deg,transparent,var(--gold) 22%,var(--gold) 78%,transparent);
  opacity:.7;
}
.fac--dist{transform:translateY(-2px)}
.fac--dist:hover{transform:translateY(-7px)}
/* The gilt corner. A single triangle in the top-right, behind the marks. */
.fac__gilt{
  position:absolute;top:0;right:0;width:64px;height:64px;
  pointer-events:none;z-index:0;border-top-right-radius:inherit;
  background:linear-gradient(225deg,rgba(201,152,47,.30),transparent 62%);
}
.fac__star--world{
  background:linear-gradient(101deg,var(--gold),#F0D089 52%,var(--gold));
  color:#2A0608;border-color:transparent;
  display:inline-flex;align-items:center;gap:5px;
  box-shadow:0 3px 14px -4px rgba(201,152,47,.7);
}
.fac__star--world svg{width:11px;height:11px;flex:0 0 auto}
.facgrid--dist{margin-top:clamp(22px,2.6vw,34px)}
.facmore{display:flex;justify-content:center;margin-top:clamp(22px,2.6vw,34px)}
.mix .head{max-width:760px;margin-bottom:0}
.mix .lede{max-width:64ch;margin-inline:auto}
.mix__row{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:26px}
@media (max-width:640px){.mix__row .btn{width:100%}}
.facmore[hidden]{display:none}
/* The cookie bar parks bottom-left; while it is up the band keeps clear of it
   rather than letting a ledger cell sit under a floating panel. */
body:has(.ck) .hon__ledger{padding-bottom:clamp(0px,1vw,10px)}
@media (max-width:720px){
  .fac__gilt{width:46px;height:46px}
  .fac__star--world svg{width:9px;height:9px}
}

/* ══════════════════ THE RECORD — the dialog ═══════════════════ */
/* ═══════════════════ THE RECORD DIALOG — the shell ════════════════════════
   Identical to the founder and SWK dialogs, on purpose. It used to roll its
   own white-alpha gradient over a near-black veil of its own, which meant
   that in light mode the panel was filtering a dark ground and came out as a
   grey rectangle — a different material from every other panel on the site,
   sitting two sections away from them. Same veil token, same --panel fill,
   same 22px radius, same gold pool from the top-left, same close affordance.
   Anything that changes about .fdlg__box should change here too. */
.hdlg{
  position:fixed;inset:0;z-index:120;display:none;
  align-items:center;justify-content:center;padding:clamp(14px,3.5vw,40px);
}
.hdlg.on{display:flex}
.hdlg__veil{
  position:absolute;inset:0;background:var(--fd-veil);
  -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
  opacity:0;transition:opacity .3s var(--ease);
}
.hdlg.in .hdlg__veil{opacity:1}
.hdlg__box{
  position:relative;isolation:isolate;
  width:min(760px,100%);max-height:min(90vh,860px);
  display:flex;flex-direction:column;overflow:hidden;
  border-radius:22px;color:var(--text-1);
  background:var(--panel);
  border:1px solid var(--edge);
  box-shadow:var(--shadow-lg);
  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)){
  .hdlg__box{-webkit-backdrop-filter:var(--panel-fx);backdrop-filter:var(--panel-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .hdlg__box{background:var(--panel-solid)}
}
/* The lite tier exists to avoid exactly this blur. */
[data-perf="lite"] .hdlg__box{
  background:var(--panel-solid);
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
.hdlg.in .hdlg__box{opacity:1;transform:none}
/* The pool of gold bled in from the top-left, the same gesture .fdlg__box and
   .fpop__box both make. */
.hdlg__box::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(640px 400px at 6% 0%,rgba(201,152,47,.16),transparent 62%);
}
.hdlg__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(--line);background:var(--hi);
  color:var(--text-2);cursor:pointer;transition:.24s var(--ease);
}
.hdlg__x:hover{color:var(--text-1);border-color:var(--line-2);transform:translateY(-1px)}
.hdlg__x svg{width:14px;height:14px}
@media (prefers-reduced-motion:reduce){
  .hdlg__veil,.hdlg__box{transition:none}
  .hdlg__box{transform:none}
}
/* The content ran off the bottom edge on a hard line, which on a translucent
   panel reads as a rendering fault rather than as more copy below. Masked so
   it dissolves into the pane instead. */
.hdlg__scroll{
  position:relative;z-index:1;
  overflow-y:auto;padding:clamp(26px,3.4vw,44px);-webkit-overflow-scrolling:touch;
  -webkit-mask-image:linear-gradient(180deg,#000 calc(100% - 34px),transparent);
  mask-image:linear-gradient(180deg,#000 calc(100% - 34px),transparent);
}
.hdlg__scroll::-webkit-scrollbar{width:8px}
.hdlg__scroll::-webkit-scrollbar-thumb{
  background:color-mix(in srgb,var(--gold) 52%,transparent);border-radius:9px;
}

.hrec__lead{
  display:flex;align-items:center;gap:9px;color:var(--gold);
  font-family:var(--mono);font-size:.61rem;letter-spacing:.19em;
  text-transform:uppercase;margin:0 0 12px;
}
.hrec__lead svg{width:15px;height:15px}
.hrec h3{margin:0 0 8px;font-size:clamp(1.4rem,2.6vw,2rem)}
.hrec__sub{margin:0 0 22px;color:var(--text-2);font-size:.94rem;line-height:1.75}
.hrec__band{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:26px}
/* Same plate the honours ledger uses out on the page — --hi over --line —
   rather than a bespoke white wash. One token pair covers both themes, and
   the three tiers in here now match the four cells the visitor clicked to
   get to them. */
.hrec__b{
  padding:16px 15px;border-radius:var(--r-xs);
  background:var(--hi);border:1px solid var(--line);
}
.hrec__b b{display:block;font-family:var(--display);font-size:1.5rem;color:var(--gold);line-height:1}
.hrec__b span{
  display:block;margin-top:7px;font-family:var(--mono);font-size:.57rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--text-3);
}
/* Short labels only. A mono caps rule is a label language and it works at
   two or three words; the line naming the teacher ran to nine and became a
   paragraph in capitals, which is why it has its own class below. */
.hrec__h4{
  margin:0 0 12px;font-family:var(--mono);font-size:.61rem;
  letter-spacing:.19em;text-transform:uppercase;color:var(--text-2);
}
/* Set in the display face at title case: it is a heading about a person, and
   the dialog has no other line at this weight, so it carries the section
   without a rule or a size jump. */
.hrec__name{
  margin:0 0 12px;font-family:var(--display);font-weight:500;
  font-size:1.06rem;line-height:1.3;letter-spacing:-.008em;
  color:var(--text-1);text-wrap:balance;
}
/* The role sits tight under the name — negative top margin so the pair reads
   as one two-line unit rather than as a heading with a caption below it. */
.hrec__role{
  margin:-7px 0 15px;font-family:var(--mono);font-size:.61rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--gold-text);
}
.hrec__p{margin:0 0 15px;color:var(--text-2);font-size:.9rem;line-height:1.78}
/* The closing line. Set in the display face above a rule so it lands as a
   statement rather than as one more body paragraph, and it is the last thing
   read before the two buttons. */
.hrec__close{
  margin:26px 0 0;padding-top:21px;border-top:1px solid var(--line);
  font-family:var(--display);font-weight:500;font-size:1.02rem;line-height:1.55;
  letter-spacing:-.006em;color:var(--text-1);text-wrap:balance;
}
.hrec__lvls{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:26px}
.hrec__lvls i{
  font-style:normal;padding:8px 13px;border-radius:8px;
  border:1px solid var(--line);background:var(--hi);
  font-family:var(--mono);font-size:.63rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text-2);
}
.hrec__row{
  display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;
  padding:13px 15px;border-radius:var(--r-xs);
  border:1px solid var(--line);background:var(--hi);
  margin-bottom:8px;
}
.hrec__row b{font-size:.92rem}
.hrec__row em{font-style:normal;display:block;font-size:.78rem;color:var(--text-3);margin-top:2px}
.hrec__row i{
  font-style:normal;font-family:var(--mono);font-size:.58rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--gold);
}
.hrec__cta{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}
@media (max-width:640px){
  .hrec__band{grid-template-columns:1fr}
  .hdlg__box{width:100%;max-height:92vh}
}

/* ═══════════════════════════ THE COOKIE BAR ════════════════════════
   Sits at the bottom left rather than across the full width: the promo ribbon
   already owns the full-width bottom slot, and two stacked full-width bars is
   the exact clutter this pass is meant to remove. Answered once, it never
   returns — the answer is kept in localStorage, not the session. */
.ck{
  position:fixed;left:16px;bottom:16px;z-index:74;
  width:min(410px,calc(100vw - 32px));
  padding:18px 19px 16px;border-radius:var(--r-sm);
  /* Glass, on the same terms as the dialog — but this one floats over live
     copy with no veil beneath it to quiet the ground first, so the fill sits
     denser than the modal's. Graded, not flat, for the same reason. */
  background:linear-gradient(150deg,
    rgba(255,255,255,.86) 0%,
    rgba(255,255,255,.74) 100%);
  -webkit-backdrop-filter:blur(30px) saturate(175%);
  backdrop-filter:blur(30px) saturate(175%);
  border:1px solid var(--edge);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.85),var(--sh-lg);
  transform:translateY(calc(100% + 26px));opacity:0;
  transition:transform .6s cubic-bezier(.16,1,.3,1),opacity .4s;
}
.ck.in{transform:translateY(0);opacity:1}
[data-theme="dark"] .ck{
  background:linear-gradient(150deg,rgba(58,22,24,.82),rgba(26,8,9,.74));
  -webkit-backdrop-filter:blur(30px) brightness(.88) saturate(150%);
  backdrop-filter:blur(30px) brightness(.88) saturate(150%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),var(--sh-lg);
}
/* Same two fallbacks as the dialog, for the same two reasons. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .ck,[data-theme="dark"] .ck{background:var(--panel-solid)}
}
[data-perf="lite"] .ck,[data-perf="lite"][data-theme="dark"] .ck{
  background:var(--panel-solid);
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
.ck__t{
  display:flex;align-items:center;gap:8px;margin:0 0 8px;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.19em;
  text-transform:uppercase;color:var(--gold);
}
.ck__t svg{width:14px;height:14px}
.ck p{margin:0 0 14px;font-size:.83rem;line-height:1.65;color:var(--text-2)}
.ck p a{color:var(--gold);text-decoration:underline;text-underline-offset:3px}
.ck__row{display:flex;gap:9px;flex-wrap:wrap}
.ck__b{
  flex:1 1 0;min-width:112px;padding:10px 14px;border-radius:9px;cursor:pointer;
  font-family:var(--mono);font-size:.63rem;letter-spacing:.13em;text-transform:uppercase;
  border:1px solid var(--edge);background:rgba(255,255,255,.34);color:var(--text-1);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6);
  transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s;
}
.ck__b:hover{transform:translateY(-2px);border-color:var(--gold)}
[data-theme="dark"] .ck__b{
  background:rgba(255,255,255,.07);box-shadow:inset 0 1px 0 rgba(255,255,255,.09);
}
.ck__b--y,[data-theme="dark"] .ck__b--y{
  background:var(--gold);color:#2A0608;border-color:transparent;font-weight:600;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4);
}
@media (max-width:520px){
  /* On a 390px screen the bar was taking a third of the viewport. Tighter
     padding, smaller copy, and the buttons on one row. */
  .ck{left:10px;right:10px;bottom:10px;width:auto;padding:14px 15px 13px}
  .ck p{font-size:.78rem;line-height:1.55;margin-bottom:12px}
  .ck__b{padding:9px 10px;font-size:.58rem;min-width:0}
}
@media (max-width:640px){
  .medal{--field:min(34vh,250px)}
  /* The cookie note as a slim strip: no title, short copy, one row. */
  .ck{padding:11px 12px 10px}
  .ck__t{display:none}
  .ck p{font-size:.7rem;line-height:1.45;margin-bottom:8px}
  .ck__b{padding:8px 10px}
}

@media (prefers-reduced-motion:reduce){.ck{transition:opacity .2s}}

/* ══════════════════════ FOUNDER'S MESSAGE ══════════════════════
   A hero portrait and a short statement, floating on a photographed room,
   sitting directly under the hero.

   Four things are load-bearing and none of them are decoration:

   1. THE PLATE IS SUBMERGED, NOT STACKED. The backdrop runs full-bleed and
      is masked to nothing at the top and bottom, so the photograph surfaces
      out of the page colour and sinks back into it. The section has no
      visible boundary — only a region where the page happens to be a room.

   2. THE CARD IS A LENS, NOT A SLAB. This was the first pass's mistake and
      it is worth writing down. The card was taking --clear-*, which carries
      brightness(1.12) in its backdrop filter and a white radial tint on top.
      Over a dark page a brightness lift does not read as glass — it reads as
      a grey rectangle someone laid on the photograph, because the eye sees a
      hard-edged region that is a different LUMINANCE from its surroundings,
      and no amount of blur undoes that. So this pass keeps the blur and the
      saturation and removes every term that changes brightness: a ~3% fill,
      no tint layer, no heavy cast shadow. What is left is refraction only.
      The card is located by its rim and by what the blur does to the room
      behind it, which is what actual glass is located by.

   3. THE PORTRAIT IS A PLATE, NOT A THUMBNAIL. 4:5, running the full height
      of the card. The frame is a 6px rim rather than the 14px moulding the
      first pass used — at that weight the metal became the subject and the
      man inside it became an inset. Name and title sit BELOW the frame, in
      the card, not engraved into the metal: inside it they were clipped by
      the card's own overflow the moment the text column ran short.

   4. IT FLIPS WITH THE THEME. Every colour resolves through a token and the
      backdrop carries its own per-theme tone the way the hero photo does.
      Nothing here is a literal hex that would strand itself in one theme.
   ────────────────────────────────────────────────────────────────────── */

[data-theme="light"]{
  /* The room is a backdrop, not a subject: pulled back in brightness and
     saturation so dark ink still wins on top of it. */
  --fm-bg-op:.70;
  --fm-bg-filter:sepia(.18) saturate(.76) brightness(.86) contrast(.94);
  /* Scrim. Cream at the edges, thinner in the middle, so the plate has
     something quiet to sit on without wiping the image out. */
  --fm-veil:radial-gradient(124% 92% at 50% 44%,rgba(245,242,233,.14) 0%,rgba(245,242,233,.6) 66%,var(--bg) 100%);
  /* Blooms are ambient light in the ROOM, behind the glass — not a wash
     inside the card. Kept low; at the first pass's .16/.08 they pooled under
     the plate and gave it a coloured floor, which is exactly the boxed-in
     look the card is trying not to have. */
  --fm-bloom:rgba(201,152,47,.09);
  --fm-bloom-2:rgba(90,16,21,.05);

  /* The glass itself. Fill is nearly nothing; the blur does the work. */
  --fm-fill:rgba(255,255,255,.36);
  --fm-fx:blur(30px) saturate(1.5);
  --fm-solid:rgba(255,255,255,.9);
  --fm-edge:rgba(27,26,23,.10);
  --fm-rim:rgba(255,255,255,.85);
  --fm-rim-lo:rgba(255,255,255,.5);
  --fm-cast:0 34px 80px -60px rgba(42,38,32,.4);

  /* Portrait rim. Warm pewter on the light page — true silver on cream reads
     as unfinished aluminium. */
  --fm-metal:linear-gradient(150deg,#FFFDF7 0%,#E8E1CF 20%,#BCAF92 42%,#F7F1DF 56%,#AEA080 74%,#EBE4D2 88%,#FCF9F1 100%);
  --fm-metal-rim:rgba(70,60,40,.24);
  --fm-metal-in:rgba(60,50,32,.28);
  --fm-shot-bg:#2A2318;
  --fm-shot-sh:0 18px 40px -22px rgba(42,38,32,.55);
  --fm-quote:rgba(27,26,23,.88);
}
[data-theme="dark"]{
  --fm-bg-op:.72;
  --fm-bg-filter:sepia(.3) saturate(.64) brightness(.6) contrast(1.12);
  --fm-veil:radial-gradient(124% 92% at 50% 44%,rgba(12,3,4,.24) 0%,rgba(12,3,4,.62) 66%,var(--bg) 100%);
  --fm-bloom:rgba(201,152,47,.11);
  --fm-bloom-2:rgba(190,46,54,.07);

  /* Dark glass. 3% white — enough to catch the rim light, not enough to
     become a panel. No brightness term anywhere in the filter. */
  --fm-fill:rgba(20,6,7,.30);
  --fm-fx:blur(30px) saturate(1.35);
  --fm-solid:rgba(26,9,10,.9);
  --fm-edge:rgba(245,237,224,.09);
  --fm-rim:rgba(255,236,214,.26);
  --fm-rim-lo:rgba(255,236,214,.13);
  --fm-cast:0 40px 90px -70px rgba(0,0,0,.7);

  /* On the dark page the rim can be true silver — it is the brightest edge
     in the section and it is meant to be. */
  --fm-metal:linear-gradient(150deg,#F4F2EC 0%,#C2BDB3 18%,#75716A 42%,#E9E5DB 56%,#66625B 74%,#B8B3A9 88%,#EFEDE7 100%);
  --fm-metal-rim:rgba(255,244,226,.26);
  --fm-metal-in:rgba(0,0,0,.5);
  --fm-shot-bg:#150304;
  --fm-shot-sh:0 22px 50px -24px rgba(0,0,0,.85);
  --fm-quote:rgba(245,237,224,.9);
}

/* The section is full-bleed so the photograph can run edge to edge, then
   rebuilds the 1280px measure with padding — the same trick .sec--orn uses,
   and for the same reason: .wrap would stop the image ~320px short of each
   side on a wide screen, and a 100vw child gets clipped by paint containment. */
.fmsg{
  position:relative;isolation:isolate;
  width:100%;max-width:none;margin-inline:0;
  padding-block:clamp(62px,7.6vw,124px);
  padding-inline:max(22px,calc((100% - var(--wrap)) / 2));
  overflow:clip;
}

/* ---- the room ---------------------------------------------------------- */
/* The blur is BAKED INTO THE FILE, not applied here. A full-bleed bitmap
   under a CSS blur() gets re-rasterised on every scroll frame, and this one
   sits under a card that is already running a 30px backdrop-filter — two
   large blurred layers stacked is the single most expensive thing that could
   go in this section. Blurring in the file costs nothing at runtime, and
   blur destroys detail the asset still compresses to 35KB at 1600px.

   The radius is deliberately mild — enough that the hall reads as depth of
   field rather than as subject matter, not so much that it becomes an
   abstract wash. Source resolution had to come UP when the radius came down:
   at a soft radius the real detail survives, and if the file is too small for
   it the softness starts reading as a low-resolution image instead of as a
   lens, which is a very different-looking mistake.

   Two files in one declaration. The first is painted on top; if it is missing
   the browser skips that layer and the hero's own hall photo shows through,
   so the section never renders as a bare rectangle. */
.fmsg__bg{
  position:absolute;inset:0;z-index:-2;pointer-events:none;
  background-image:url("founder-room.webp"),url("hero-crowd.webp");
  background-size:cover;background-position:center 38%;
  opacity:var(--fm-bg-op);
  filter:var(--fm-bg-filter);
  -webkit-mask-image:linear-gradient(180deg,transparent 0%,#000 24%,#000 78%,transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0%,#000 24%,#000 78%,transparent 100%);
}
.fmsg__veil{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(44% 50% at 24% 38%,var(--fm-bloom),transparent 72%),
    radial-gradient(50% 58% at 80% 78%,var(--fm-bloom-2),transparent 74%),
    var(--fm-veil);
}

/* ---- the plate --------------------------------------------------------- */
/* Capped and centred. Left at the full 1280 the text column ran to 46ch and
   left ~300px of empty glass on the right, which made the card look like a
   container rather than a composition. */
.fmsg__card{
  position:relative;
  width:min(100%,1168px);margin-inline:auto;
  display:grid;
  grid-template-columns:clamp(222px,28vw,332px) minmax(0,1fr);
  gap:clamp(30px,3.8vw,60px);
  align-items:center;
  padding:clamp(26px,3vw,46px);
  border-radius:var(--fm-r,30px);
  background:var(--fm-fill);
  border:1px solid var(--fm-edge);
  box-shadow:var(--fm-cast);
  /* overflow is back. It was dropped in pass two because the caption was
     being clipped by it — but the caption was only overflowing because it
     lived inside the metal frame, and it does not any more. The sheen sweeps
     from -40% to +62% of the card, so it needs a box to sweep inside. */
  overflow:hidden;isolation:isolate;
  transition:opacity .8s var(--out),transform .8s var(--out),
              border-color .4s var(--ease),box-shadow .5s var(--ease);
}
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  .fmsg__card{-webkit-backdrop-filter:var(--fm-fx);backdrop-filter:var(--fm-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .fmsg__card{background:var(--fm-solid)}
}
/* The sheen. Same 115deg sweep and same 1.15s curve as .glass--sheen, on
   ::before rather than ::after because ::after is carrying the top rim here.
   Parked off-card at rest, so unlike the tint layer this replaced it adds
   nothing to the card's resting luminance — which is what turned the first
   pass grey. */
.fmsg__card::before{
  content:"";position:absolute;inset:-40%;pointer-events:none;z-index:2;
  background:linear-gradient(115deg,transparent 42%,var(--sheen) 50%,transparent 58%);
  transform:translateX(-62%);transition:transform 1.15s var(--out);
}
.fmsg__card:hover::before,
.fmsg__card.is-hot::before{transform:translateX(62%)}

/* Top rim: one pixel of bright, brightest in the middle, gone at the corners
   — the specular line along the top edge of a sheet of glass. This and the
   filament are the ONLY things drawing the card's outline at rest. */
.fmsg__card::after{
  content:"";position:absolute;inset:0 0 auto;height:1px;pointer-events:none;
  border-radius:inherit;
  background:linear-gradient(90deg,transparent,var(--fm-rim) 28%,var(--fm-rim) 72%,transparent);
}
/* Lower edge. A hairline, not the 74px band the first pass used — that band
   sat inside a clipped box and read as a lit floor stripe across the bottom
   of the card, which is the single loudest way to announce a rectangle. */
.fmsg__glow{
  position:absolute;left:16%;right:16%;bottom:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(201,152,47,.5) 30%,rgba(243,221,164,.6) 50%,rgba(201,152,47,.5) 70%,transparent);
}
/* Geometry, dash and offset come from the base .btn__trace rule — only the
   radius and stroke are the plate's own. Redeclaring width and height here
   would undo the 0.6px inset that keeps the hairline off the SVG's edge. */
/* The silver filament, on the page's own token rather than a warm white of
   its own — #8B939F on the ivory page, #E4EAF1 on the oxblood one, the same
   line that runs the buttons, the wheel panes, the steps and the footer
   crest. Geometry, dash and offset all come from the base .btn__trace rule;
   only the radius, the stroke and the run length are the plate's own.
   Redeclaring width and height would undo the 0.6px inset that keeps the
   hairline off the SVG's own edge.

   It draws on hover, not on reveal. A filament that is permanently lit is
   just a border — the whole point of the treatment is that the line arrives
   when you approach the thing. */
.fmsg__card .btn__trace{
  z-index:4;
  filter:drop-shadow(0 0 1.4px var(--lq2-trace-glow));
}
.fmsg__card .btn__trace rect{
  rx:30px;ry:30px;
  stroke:var(--lq2-trace);stroke-width:1.4;
  vector-effect:non-scaling-stroke;
  shape-rendering:geometricPrecision;
  /* Slower than a button's 1.1s. The perimeter here is roughly six times a
     button's, so at the button's duration the line whips round and reads as
     a flash rather than as something being drawn. */
  transition:stroke-dashoffset 1.5s cubic-bezier(.55,.06,.3,1),opacity .3s linear;
}
.fmsg__card:hover .btn__trace rect,
.fmsg__card.is-hot .btn__trace rect{stroke-dashoffset:0;opacity:.82}
/* The lift, matching .card and .step at their five pixels — and the rim warms
   to the same gold those cards take on approach. */
.fmsg__card:hover,
.fmsg__card.is-hot{
  transform:translateY(-4px);
  border-color:rgba(201,152,47,.34);
  box-shadow:var(--fm-cast),0 0 40px -18px rgba(201,152,47,.34);
}
/* The portrait leans in with it, the way the footer crest does. */
.fmsg__shot img{transition:transform .7s var(--out)}
.fmsg__card:hover .fmsg__shot img,
.fmsg__card.is-hot .fmsg__shot img{transform:scale(1.045)}

/* ---- the portrait ------------------------------------------------------ */
.fmsg__pf{margin:0;position:relative;z-index:1;display:grid;gap:14px}
/* A rim, not a moulding. The bevel is two inset shadows — dark from below,
   light lip from above — which is the whole reason 6px of metal still reads
   as a milled edge rather than a border. */
.fmsg__frame{
  position:relative;
  padding:6px;
  border-radius:16px;
  background:var(--fm-metal);
  border:1px solid var(--fm-metal-rim);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 -1px 0 rgba(0,0,0,.3),
    var(--fm-shot-sh);
}
.fmsg__shot{
  position:relative;
  border-radius:11px;overflow:hidden;
  background:var(--fm-shot-bg);
  /* Hero proportion. A portrait plate, held whatever ratio the source file
     turns out to be, so a mis-cropped upload cannot change the layout. */
  aspect-ratio:4/5;
  box-shadow:inset 0 0 0 1px var(--fm-metal-in);
}
.fmsg__shot img{
  width:100%;height:100%;object-fit:cover;object-position:center;display:block;
}
/* Name and title live in the card, under the frame. Inside the metal they
   were clipped by the card's overflow whenever the text column ran shorter
   than the portrait — which on a wide screen it always does. */
.fmsg__id{display:grid;gap:5px;padding-left:2px}
.fmsg__id b{
  font-family:var(--display);font-weight:500;
  font-size:clamp(1rem,1.24vw,1.15rem);line-height:1.15;
  color:var(--text-1);
}
.fmsg__id span{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.17em;
  text-transform:uppercase;color:var(--gold-text);
}

/* ---- the message ------------------------------------------------------- */
.fmsg__body{position:relative;z-index:1}
/* A touch under the global h2 scale. At the full 2.739rem the heading was
   taller than the eyebrow, the quote and the closing line put together, and
   the section stopped being a message and became a banner. */
.fmsg__body h2{
  font-size:clamp(1.58rem,2.86vw,2.5rem);
  margin-bottom:.5em;
}
/* The quote carries the display face at reading size. Playfair at ~1.2rem
   with generous leading is the one place on this page where a serif does
   body-copy work, and it does it because this paragraph is a person speaking
   rather than the site explaining itself. */
.fmsg__q{
  margin:0 0 20px;border:0;padding:0;
  font-family:var(--display);font-weight:400;
  font-size:clamp(1.04rem,1.46vw,1.34rem);
  line-height:1.62;color:var(--fm-quote);
  max-width:46ch;
  /* Hanging punctuation: the opening quote sits in the margin so the first
     line of text still starts on the same axis as the heading. */
  text-indent:-.4em;
}
/* The closing line. Sans, smaller, --text-2 — it is the site talking again
   after the founder has stopped, so it must not look like more of the quote. */
.fmsg__note{
  margin:0;max-width:52ch;
  font-size:clamp(.86rem,1.02vw,.95rem);line-height:1.66;color:var(--text-2);
  padding-top:18px;border-top:1px solid var(--line);
}

/* ---- responsive -------------------------------------------------------- */
/* Below the break the portrait goes above the message and both centre. The
   frame is capped rather than stretched — a 700px-wide metal rim around a
   head-and-shoulders shot looks like a mirror. */
@media (max-width:900px){
  .fmsg__card{
    grid-template-columns:1fr;
    justify-items:center;text-align:center;
    gap:clamp(22px,4vw,30px);
  }
  .fmsg__pf{width:min(100%,292px);justify-items:center}
  .fmsg__id{padding-left:0;justify-items:center}
  .fmsg__q{max-width:52ch;text-indent:0;margin-bottom:16px}
  .fmsg__body .eyebrow::before{display:none}
  .fmsg__note{max-width:56ch;margin-inline:auto}
}
@media (max-width:560px){
  .fmsg{padding-inline:22px}
  .fmsg__card{--fm-r:20px;padding:22px 18px 26px}
  .fmsg__card .btn__trace rect{rx:20px;ry:20px}
  .fmsg__glow{left:10%;right:10%}
}
/* Phones: the card is a preview. Portrait, name, heading and the opening of
   the quote; the full message lives in the popup behind "Read the full
   message". */
@media (max-width:640px){
  .fmsg__card{gap:16px;padding:20px 16px 22px}
  .fmsg__pf{width:min(62%,200px);gap:20px}
  .fmsg__body h2{font-size:clamp(1.3rem,6vw,1.55rem);margin-bottom:10px}
  .fmsg__q{
    font-size:1rem;line-height:1.55;margin-bottom:12px;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;overflow:hidden;
  }
  .fmsg__note{display:none}
  .fmsg__more{margin-top:4px}
}

/* ---- performance ------------------------------------------------------- */
/* A full-bleed bitmap under a blurred plate is the most expensive pair on
   the page after the cinematic band. On the lite tier the photograph and the
   blur both go; the section keeps its layout and its type and loses only the
   atmosphere. */
[data-perf="lite"] .fmsg__bg{display:none}
[data-perf="lite"] .fmsg__card{
  -webkit-backdrop-filter:none;backdrop-filter:none;
  background:var(--fm-solid);
}

/* ═══════════════════════ FOUNDER'S MESSAGE — the dialog ═══════════════════
   Same shell language as the faculty and campus panels: a blurred veil, a box
   that rises into place, Escape or a veil press to leave.

   One deliberate departure. .fpop is hard-coded dark in both themes, because
   the thing it frames is a lit video poster and a cream panel would put the
   brightest object on screen in the margins. Nothing in here is lit — it is a
   portrait, a quote and two links — so this panel takes the page's own
   surface tokens instead and flips with the toggle. On the ivory page it is
   ivory; on the oxblood page it is oxblood. Every colour below resolves
   through --panel / --text-* / --line / --edge, so there is no value here
   that could strand itself in one theme. */
[data-theme="light"]{ --fd-veil:rgba(34,29,22,.5) }
[data-theme="dark"] { --fd-veil:rgba(6,3,4,.72) }

.fdlg{
  position:fixed;inset:0;z-index:120;display:none;
  align-items:center;justify-content:center;padding:clamp(14px,3.5vw,40px);
}
.fdlg.on{display:flex}
.fdlg__veil{
  position:absolute;inset:0;background:var(--fd-veil);
  -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
  opacity:0;transition:opacity .3s var(--ease);
}
.fdlg.in .fdlg__veil{opacity:1}

.fdlg__box{
  position:relative;isolation:isolate;
  --fd-h:min(90vh,680px);
  width:min(880px,100%);max-height:var(--fd-h);
  display:grid;grid-template-columns:minmax(0,.42fr) minmax(0,.58fr);
  border-radius:22px;overflow:hidden;
  color:var(--text-1);
  background:var(--panel);
  border:1px solid var(--edge);
  box-shadow:var(--shadow-lg);
  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)){
  .fdlg__box{-webkit-backdrop-filter:var(--panel-fx);backdrop-filter:var(--panel-fx)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .fdlg__box{background:var(--panel-solid)}
}
.fdlg.in .fdlg__box{opacity:1;transform:none}
/* A pool of gold bled in from the top-left, the same gesture .fpop__box makes
   with the teacher's accent. */
.fdlg__box::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(640px 400px at 6% 0%,rgba(201,152,47,.16),transparent 62%);
}

.fdlg__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(--line);background:var(--hi);
  color:var(--text-2);cursor:pointer;transition:.24s var(--ease);
}
.fdlg__x:hover{color:var(--text-1);border-color:var(--line-2);transform:translateY(-1px)}
.fdlg__x svg{width:14px;height:14px}

/* ---- left: the portrait ----
   An inset plate rather than a full bleed. This started as a bug: <figure>
   carries a browser default margin of 1em 40px, which was never zeroed here,
   so the portrait sat in a lopsided well of its own accident. The inset looks
   better than the bleed did, so it stays — but as a stated padding, symmetric,
   with the corners rounded to match every other plate on the site.

   --fd-pad drives the inset, the scrim and the caption together. Three
   separate values would drift apart the first time the padding changed. */
.fdlg__art{
  --fd-pad:clamp(14px,1.6vw,20px);
  --fd-r:16px;
  position:relative;margin:0;min-height:0;padding:var(--fd-pad);
}
.fdlg__art img{
  width:100%;height:100%;object-fit:cover;object-position:center 18%;display:block;
  border-radius:var(--fd-r);
  background:var(--bg-2);
  box-shadow:0 14px 34px -18px rgba(10,4,4,.5);
}
/* The portrait's own dark lifted into the frame so the caption has something
   to sit on. Radius only on the bottom two corners — it is the foot of the
   image, not a box of its own. */
.fdlg__art::after{
  content:"";position:absolute;z-index:1;pointer-events:none;
  left:var(--fd-pad);right:var(--fd-pad);bottom:var(--fd-pad);height:34%;
  border-radius:0 0 var(--fd-r) var(--fd-r);
  background:linear-gradient(0deg,rgba(10,4,4,.62),transparent);
}
.fdlg__cap{
  position:absolute;z-index:2;
  left:var(--fd-pad);right:var(--fd-pad);bottom:var(--fd-pad);
  padding:14px 16px;display:grid;gap:3px;
}
.fdlg__cap b{
  font-family:var(--display);font-weight:500;font-size:1.06rem;
  color:#FBF5EC;line-height:1.15;
}
.fdlg__cap span{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.16em;
  text-transform:uppercase;color:rgba(243,221,164,.86);
}

/* ---- right: the message ---- */
.fdlg__body{
  position:relative;z-index:1;min-width:0;min-height:0;max-height:var(--fd-h);
  padding:clamp(22px,2.6vw,34px);
  overflow:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  display:grid;align-content:start;gap:0;
}
.fdlg__body h3{
  font-size:clamp(1.28rem,1.9vw,1.55rem);margin:0 0 13px;line-height:1.14;
}
.fdlg__q{
  margin:0 0 15px;border:0;padding:0;
  font-family:var(--display);font-weight:400;
  font-size:clamp(.98rem,1.2vw,1.07rem);line-height:1.56;
  color:var(--text-1);
}
.fdlg__p{
  margin:0 0 14px;font-size:.86rem;line-height:1.64;color:var(--text-2);
}
.fdlg__facts{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;
  padding:13px 0;margin:2px 0 18px;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
/* Two shared rows rather than three independent stacks. One value wraps to a
   second line and the others do not, and with each cell stacking on its own
   that dropped one label below the other two. The value row takes the height
   of the tallest, the labels sit on its floor, and the three read as one
   line again. */
.fdlg__facts div{display:grid;grid-template-rows:1fr auto;gap:3px;min-width:0}
.fdlg__facts b{font-family:var(--display);font-weight:500;font-size:1.02rem;color:var(--text-1)}
.fdlg__facts span{
  font-family:var(--mono);font-size:.56rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold-text);
}
.fdlg__act{display:flex;gap:10px;flex-wrap:wrap}

/* ---- the affordance on the card upstairs ---- */
/* An invisible click target is a bug, not a subtlety — the card has to say
   it opens. This is a real <button>, so keyboard and screen readers get a
   proper control; the card-wide press is a convenience layered on top of it,
   not the only way in. */
.fmsg__more{
  margin-top:18px;display:inline-flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--gold-text);
  cursor:pointer;transition:gap .3s var(--out),color .3s var(--ease);
}
.fmsg__more i{
  font-style:normal;display:inline-block;
  transition:transform .3s var(--out);
}
.fmsg__card:hover .fmsg__more i,
.fmsg__card.is-hot .fmsg__more i,
.fmsg__more:hover i{transform:translateX(4px)}
.fmsg__more:hover{color:var(--text-1)}
.fmsg__card{cursor:pointer}

/* ---- responsive ---- */
@media (max-width:760px){
  /* Phones: the popup is one plain scrolling column. As a grid its body row
     came out shorter than its content, which pushed the buttons under the
     bottom edge where scrolling could not quite reach them. */
  .fdlg__box{
    --fd-h:min(92vh,720px);
    display:block;
    overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  }
  .fdlg__body{max-height:none;overflow:visible;padding-bottom:calc(26px + env(safe-area-inset-bottom))}
  /* The portrait becomes a band. Its own 4:5 would eat the whole screen on a
     phone and leave the quote below the fold, which is the one thing the
     dialog exists to show. */
  .fdlg__art{aspect-ratio:16/9;min-height:0;padding-bottom:0}
  .fdlg__art img{object-position:center 16%}
  .fdlg__facts{grid-template-columns:1fr 1fr}
  .fdlg__facts div:last-child{grid-column:1/-1}
}
@media (prefers-reduced-motion:reduce){
  .fdlg__veil,.fdlg__box,.fdlg__x,.fmsg__more,.fmsg__more i{transition:none}
}

[data-perf="lite"] .fmsg__card::before{display:none}
@media (prefers-reduced-motion:reduce){
  .fmsg__card,.fmsg__card::before,.fmsg__shot img{transition:none}
  .fmsg__card:hover,.fmsg__card.is-hot{transform:none}
  .fmsg__card .btn__trace rect{transition:none}
}


/* ══════════════════════════════════════════════════════════════════════════
   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)}
/* The link sat 1.19:1 against the sentence around it with the underline
   only on hover, which is not a link anyone can find. */
.ach__note a{color:var(--gold-text);text-decoration:underline;
  text-underline-offset:2px;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%}
}
