/* ==========================================================================
   Islamabad Career College - Design System
   Typography: Outfit throughout, matching the brand lockup. Headings lean on
   weight and tight tracking for contrast rather than a second typeface.
   Proportions measured from 12 reference school sites: 1360px container,
   ~92vh hero, 1.55 body leading, near-black text, 8px control radius.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root{
  /* Brand, sampled from the ICC crest. Green is the dominant colour of the
     emblem (cap, globe, laurels) so it leads here; the cobalt blue of the
     ribbon is the secondary accent. Interactive greens are darkened until
     they clear 4.5:1 against white, which #78C018 itself does not. */
  /* Dark greens sit on the same hue as the crest green (86) so the bright
     #78C018 button reads as the same colour family as the dark grounds,
     rather than a yellow-green sitting on a blue-green. */
  --forest-900:#0e1604;
  --forest-800:#192608;
  --forest-700:#24350e;
  --forest-600:#344c15;
  --green-800:#385f0a;
  --green-700:#47790d;
  --green-600:#5d9a11;
  --green-500:#78c018;
  --green-400:#96d63c;
  --blue-900:#01315f;
  --blue-700:#004a96;
  --blue-600:#0060c0;
  --blue-500:#3078d8;
  --blue-400:#5f9ce8;

  /* Neutrals: near-black text, the way every reference site sets it */
  --ink:#11161c;
  --ink-soft:#2a313a;
  --muted:#5c6673;
  --line:#e4e7ec;
  --line-soft:#f0f2f5;
  --bg:#ffffff;
  --bg-soft:#f6f7f9;
  --bg-tint:#eff6e4;

  /* Effects */
  /* Softer, larger corners. Every top-ranked site surveyed sits far above
     the 14px this used to use: Overlake 68, ACS 58, Carroll 56, Westminster
     42, Dulwich 27. Controls stay tight; surfaces and imagery open up. */
  --radius-sm:8px;
  --radius:14px;
  --radius-lg:22px;
  --radius-xl:32px;
  --radius-2xl:44px;

  /* Motion */
  --ease:cubic-bezier(.22,1,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);

  /* Type */
  --font-sans:"Outfit",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-display:"Outfit",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;

  /* Layout */
  --header-h:84px;
  --gutter:clamp(20px,4.5vw,56px);
}

/* --------------------------------------------------------------------------
   2. Reset & base
   -------------------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:calc(var(--header-h) + 20px);-webkit-text-size-adjust:100%}
body{
  margin:0;
  font-family:var(--font-sans);
  font-size:clamp(16px,.35vw + 15px,17.5px);
  line-height:1.55;
  color:var(--ink-soft);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
body.nav-open{overflow:hidden}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
h1,h2,h3,h4{color:var(--ink);font-family:var(--font-display);font-weight:600;letter-spacing:-.028em;line-height:1.06;text-wrap:balance}
h3,h4{font-weight:500;letter-spacing:-.018em;line-height:1.24}
p{text-wrap:pretty}
::selection{background:var(--green-700);color:#fff}
:focus-visible{outline:3px solid var(--green-600);outline-offset:3px;border-radius:6px}

.container{width:min(1360px,100% - var(--gutter)*2);margin-inline:auto}
.container-narrow{width:min(1060px,100% - var(--gutter)*2);margin-inline:auto}

/* Inline SVG icons inherit colour and sit on the text baseline. */
.ico{width:1.25em;height:1.25em;display:inline-block;vertical-align:-.28em;flex:0 0 auto;stroke-width:1.7}
.ico-sm{width:1em;height:1em;vertical-align:-.15em}
.ico-lg{width:26px;height:26px;vertical-align:middle}

/* --------------------------------------------------------------------------
   3. Scroll progress + skip link
   -------------------------------------------------------------------------- */
.scroll-progress{
  position:fixed;inset:0 auto auto 0;height:3px;width:100%;z-index:200;
  transform:scaleX(0);transform-origin:0 50%;
  background:var(--green-500);
  pointer-events:none;
}
.skip-link{position:absolute;left:-9999px}
.skip-link:focus{left:16px;top:16px;z-index:300;background:#fff;color:var(--ink);padding:14px 20px;border-radius:10px;border:2px solid var(--green-700);font-weight:600}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* --------------------------------------------------------------------------
   4. Topbar
   -------------------------------------------------------------------------- */
/* The one place the crest's cobalt ribbon carries the page, edge to edge. */
.topbar{background:var(--blue-600);color:#e8f1fb;font-size:12.5px;position:relative;z-index:60;overflow:hidden}
.topbar-inner{min-height:32px;display:flex;align-items:center}
.topbar-track{display:flex;align-items:center;justify-content:space-between;gap:20px;width:100%}
/* the duplicate only exists to make the mobile loop seamless */
.topbar-track > [data-dup]{display:none}
.topbar a{color:#fff;font-weight:600;display:inline-block;padding:7px 2px}
.topbar a:hover{color:#c9e3ff}
.topbar-pulse{
  display:inline-block;position:relative;width:7px;height:7px;border-radius:50%;
  background:var(--green-400);margin-right:8px;
}
.topbar-pulse::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:1px solid var(--green-400);animation:pulse 2.4s ease-out infinite;
}
@keyframes pulse{0%{transform:scale(1);opacity:.9}70%,100%{transform:scale(3.2);opacity:0}}

/* --------------------------------------------------------------------------
   5. Header & navigation
   -------------------------------------------------------------------------- */
/* The blur lives on a pseudo-element: a backdrop-filter on .header itself would
   make it the containing block for the position:fixed mobile drawer inside it. */
.header{
  position:sticky;top:0;z-index:100;isolation:isolate;
  border-bottom:1px solid transparent;
  transition:border-color .35s var(--ease);
}
.header::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:rgba(255,255,255,.82);
  -webkit-backdrop-filter:blur(18px) saturate(180%);
  backdrop-filter:blur(18px) saturate(180%);
  transform:translateZ(0);
  transition:background .35s var(--ease);
}
.header.is-stuck::before{background:rgba(255,255,255,.97)}
.header.is-stuck{border-bottom-color:var(--line)}
.nav-wrap{min-height:var(--header-h);display:flex;align-items:center;justify-content:space-between;gap:24px}

.brand{display:flex;align-items:center;gap:12px;min-width:0}
/* The crest is square (1:1) — the mark keeps that ratio at every size. */
.brand-mark{
  flex:0 0 48px;width:48px;aspect-ratio:1;border-radius:14px;
  display:block;object-fit:contain;background:#fff;padding:3px;
  border:1px solid var(--line);
  transition:transform .5s var(--ease);
}
.brand:hover .brand-mark{transform:rotate(-4deg) scale(1.06);border-color:var(--green-600)}
/* Lockup: the sans reads far better than the display serif at this size.
   Green is the darkened #47790d (5.24:1) because 18px bold still counts as
   small text; the crest green itself would only manage 2.25:1. */
.brand strong{
  display:block;font-family:var(--font-sans);font-size:18.5px;line-height:1.15;
  color:var(--green-700);letter-spacing:-.025em;font-weight:700;
}
.brand small{
  display:block;font-family:var(--font-sans);color:var(--blue-700);
  font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;margin-top:4px;font-weight:600;
}

/* No pill, no background, no radius: every reference nav surveyed (Overlake,
   Dulwich, Riverdale, Hotchkiss) sets all three to zero and lets generous
   gaps do the spacing. Hover and current page are told apart by three things
   at once, not one: colour, weight and the weight of the rule. */
.nav{display:flex;align-items:center;gap:clamp(18px,2vw,32px);font-size:14.5px;font-weight:500}
.nav>a:not(.btn){
  position:relative;color:var(--ink-soft);padding:8px 0;
  transition:color .25s var(--ease);
}
/* hover: a hairline wipes in from the left */
.nav>a:not(.btn)::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;border-radius:2px;
  background:var(--green-600);
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .32s var(--ease),background .32s var(--ease),height .32s var(--ease);
}
.nav>a:not(.btn):hover{color:var(--ink)}
.nav>a:not(.btn):hover::after{transform:scaleX(1)}
/* current page: heavier rule in the brand green, and it never retracts */
/* Active text matches its underline (--green-500). Note: that green on the
   white bar is about 2.3:1, below the 4.5:1 AA text minimum; chosen for brand
   match. --green-700 is the nearest shade that passes if that matters later. */
.nav>a.is-active,.nav>a.is-active:hover{color:var(--green-500);font-weight:700}
.nav>a.is-active::after{transform:scaleX(1);height:3px;background:var(--green-500)}
.nav>a.is-active:hover::after{background:var(--green-500)}
.nav-cta{margin-left:clamp(6px,1vw,14px)}
/* Dropdown groups. The toggle looks exactly like a link (same colour, rule
   and active state), with a caret. The panel is square and flat to match the
   drawer: a hairline border, no radius, no shadow. It opens on hover where a
   mouse is present and on click everywhere; app.js handles click, Escape and
   clicking outside. */
.nav-group{position:relative}
.nav-group-toggle{
  position:relative;display:flex;align-items:center;gap:5px;
  padding:8px 0;border:0;background:none;cursor:pointer;
  font:inherit;color:var(--ink-soft);
  transition:color .25s var(--ease);
}
.nav-group-toggle::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;border-radius:2px;
  background:var(--green-600);transform:scaleX(0);transform-origin:0 50%;
  transition:transform .32s var(--ease);
}
.nav-caret{width:14px;height:14px;stroke-width:2.2;transition:transform .3s var(--ease)}
.nav-group-toggle:hover{color:var(--ink)}
.nav-group-toggle:hover::after{transform:scaleX(1)}
.nav-group.is-active>.nav-group-toggle{color:var(--green-500);font-weight:700}
.nav-group.is-active>.nav-group-toggle::after{transform:scaleX(1);height:3px;background:var(--green-500)}
.nav-group.is-open .nav-caret{transform:rotate(180deg)}
.nav-menu a{display:block;color:var(--ink-soft);transition:color .2s var(--ease),background .2s var(--ease)}
.nav-menu a:hover{color:var(--ink);background:var(--bg-tint)}
.nav-menu a.is-active{color:var(--green-600);font-weight:700}
@media(min-width:1181px){
  .nav-menu{
    position:absolute;top:100%;left:-18px;z-index:5;min-width:228px;
    margin-top:14px;padding:8px 0;
    background:#fff;border:1px solid var(--line);border-top:3px solid var(--green-500);
    opacity:0;visibility:hidden;transform:translateY(8px);
    transition:opacity .22s var(--ease),transform .22s var(--ease),visibility .22s;
  }
  /* invisible bridge over the gap, so moving the pointer down keeps it open */
  .nav-menu::before{content:"";position:absolute;left:0;right:0;top:-18px;height:18px}
  .nav-group.is-open>.nav-menu{opacity:1;visibility:visible;transform:none}
  .nav-menu a{padding:11px 20px;font-size:14.5px;white-space:nowrap;border-left:3px solid transparent}
  .nav-menu a.is-active{border-left-color:var(--green-500);background:var(--bg-tint)}
}
@media(min-width:1181px) and (hover:hover){
  .nav-group:hover>.nav-menu{opacity:1;visibility:visible;transform:none}
  .nav-group:hover .nav-caret{transform:rotate(180deg)}
}
/* Apply Now, styled after the hero ribbon: a slanted green shape with a small
   accent stroke, a light sweeping across it, and a short beat every few
   seconds to catch the eye. The shape is drawn by ::before (skewed, so the
   text itself stays upright and crisp); overflow is opened up so the slanted
   corners and the stroke are not clipped by the .btn box. Solid colour, no
   shadow. Only transform and background-position animate. */
.btn.nav-cta{
  background:transparent;overflow:visible;border-radius:0;white-space:nowrap;
  padding:16px 30px;color:var(--forest-900);font-weight:700;
  animation:cta-beat 3s ease-in-out infinite;
}
.btn.nav-cta::before{
  opacity:1;z-index:-1;
  /* the nav active-link green; dark text on it reads at 8.2:1 (white would
     be about 2.3:1, too faint) */
  background:var(--green-500) linear-gradient(100deg,transparent 35%,rgba(255,255,255,.6) 50%,transparent 65%) no-repeat;
  background-size:260% 100%;background-position:190% 0;
  transform:skewX(-14deg);
  animation:cta-shine 3s ease-in-out infinite;
  transition:background-color .3s var(--ease);
}
.btn.nav-cta::after{
  content:"";position:absolute;left:-12px;top:-7px;width:20px;height:2px;
  background:var(--blue-600);transform:rotate(-28deg);
}
.btn.nav-cta:hover{color:var(--forest-900);animation-play-state:paused}
.btn.nav-cta:hover::before{background-color:var(--green-400)}
.btn.nav-cta:focus-visible{outline:3px solid var(--blue-600);outline-offset:4px}
@keyframes cta-beat{
  0%,72%,100%{transform:scale(1)}
  80%{transform:scale(1.07)}
  88%{transform:scale(.97)}
  94%{transform:scale(1.02)}
}
@keyframes cta-shine{
  0%,40%{background-position:190% 0}
  75%,100%{background-position:-90% 0}
}
@media(prefers-reduced-motion:reduce){
  .btn.nav-cta,.btn.nav-cta::before{animation:none}
}

.nav-head{display:none}
.nav-brand{display:flex;align-items:center;gap:11px;min-width:0}
.nav-brand .brand-mark{flex:0 0 40px;width:40px;border-radius:10px}
.nav-brand strong{
  display:block;font-size:14.5px;line-height:1.15;font-weight:700;
  color:var(--green-700);letter-spacing:-.02em;
}
.nav-brand small{
  /* Sized to clear the logo, the gap and the close button on one line: the
     tagline wrapped to two at the page-bar tracking and inflated the row. */
  display:block;margin-top:3px;font-size:8px;font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:var(--blue-700);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.nav-close{
  flex:0 0 44px;width:44px;height:44px;padding:0;
  display:grid;place-items:center;
  border:1px solid var(--line);border-radius:8px;background:#fff;
  color:var(--forest-800);cursor:pointer;
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
}
.nav-close .ico{width:20px;height:20px}
.nav-close:hover{background:var(--forest-800);border-color:var(--forest-800);color:#fff}
.nav-close:focus-visible{outline:3px solid var(--green-600);outline-offset:2px}

.menu-toggle{
  display:none;flex:0 0 46px;width:46px;height:46px;border:1px solid var(--line);border-radius:14px;
  background:#fff;cursor:pointer;position:relative;padding:0;color:var(--forest-800);
}
.menu-toggle span{position:absolute;left:13px;width:20px;height:2px;border-radius:2px;background:currentColor;transition:transform .35s var(--ease),opacity .2s linear}
.menu-toggle span:nth-child(1){top:16px}
.menu-toggle span:nth-child(2){top:22px}
.menu-toggle span:nth-child(3){top:28px}
.menu-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.menu-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.menu-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  border:0;border-radius:8px;padding:17px 32px;
  font-family:var(--font-sans);font-size:12.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;line-height:1;
  cursor:pointer;position:relative;overflow:hidden;isolation:isolate;
  transition:transform .3s var(--ease),background .3s var(--ease),color .3s var(--ease);
}
.btn::before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(120deg,var(--green-400),var(--green-500));opacity:0;transition:opacity .35s var(--ease)}
.btn:hover{transform:translateY(-3px)}
.btn:active{transform:translateY(-1px)}
.btn-primary{background:var(--green-500);color:var(--forest-900)}
.btn-primary:hover::before{opacity:1}
.btn-primary:hover{color:var(--forest-900)}
.btn-light{background:#fff;color:var(--forest-800)}
.btn-light:hover{color:var(--green-800)}
.btn-outline{border:1.5px solid var(--line);color:var(--forest-800);background:#fff}
.btn-outline:hover{border-color:var(--green-600);color:var(--green-800)}
.btn-ghost{border:1.5px solid rgba(255,255,255,.32);color:#fff;background:rgba(255,255,255,.06);backdrop-filter:blur(6px)}
.btn-ghost:hover{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.6)}
.btn .arrow,.btn .ico{transition:transform .35s var(--ease)}
.btn .ico{width:17px;height:17px}
.btn:hover .arrow,.btn:hover .ico-arrow{transform:translateX(4px)}

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */
.hero{
  position:relative;color:#fff;overflow:hidden;isolation:isolate;
  /* start, not center: centring added the leftover height above the copy
     too, which left a large empty band between the header and the badge.
     Spare height now collects at the bottom, where the dots sit. */
  min-height:min(92vh,900px);display:grid;align-content:start;
  padding:clamp(30px,3.2vw,48px) 0 clamp(88px,9vw,124px);
  background:var(--blue-900);
}
/* Backdrop: photographs cross-fade with a slow push in. Only opacity and
   transform animate so the whole thing stays on the compositor. */
.hero-bg{position:absolute;inset:0;z-index:-2;overflow:hidden}
.hero-frame{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;
  opacity:0;transform:scale(1.08);
  transition:opacity 1.4s var(--ease-out);
  will-change:opacity;
}
.hero-frame.is-active{opacity:1;animation:ken-burns 11s ease-out forwards}
@keyframes ken-burns{from{transform:scale(1.08)}to{transform:scale(1)}}

/* Copy deck: every slide occupies the same grid cell, so the hero is as tall
   as its tallest slide and never resizes when the slide changes. */
/* No width here: .hero-deck shares its element with .container, and a
   width:100% would override the container width and push the copy flush
   against the window edge. */
.hero-deck{display:grid}
.hero-slide{
  grid-area:1/1;max-width:min(62ch,780px);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .6s var(--ease-out),visibility .6s;
}
.hero-slide.is-active{opacity:1;visibility:visible;pointer-events:auto}
/* Each line rises in turn. Written so that VISIBLE is the resting state and
   only an inactive slide hides its lines: if the animation never runs, for any
   reason, the current slide still reads. The reverse (animating up from
   opacity:0) leaves the copy invisible whenever the animation is skipped. */
.hero-slide > *{
  opacity:1;transform:none;
  transition:opacity .6s var(--ease-out),transform .6s var(--ease-out);
}
.hero-slide:not(.is-active) > *{opacity:0;transform:translateY(22px)}
.hero-slide.is-active > :nth-child(1){transition-delay:.06s}
.hero-slide.is-active > :nth-child(2){transition-delay:.17s}
.hero-slide.is-active > :nth-child(3){transition-delay:.28s}
.hero-slide.is-active > :nth-child(5){transition-delay:.5s}

/* Quoted tagline. Real curly quotes, drawn in the primary green so they read
   as quotation marks at a glance rather than as punctuation in the text. */
/* .hero prefix beats the generic `.hero p` width. A width of about 36em plus
   balanced wrapping splits the tagline into two even lines on desktop. The
   opening mark hangs in the left gutter, level with the first line; the
   closing mark sits on the last line. */
.hero .hero-quote{
  position:relative;margin:0 0 24px;padding-left:40px;max-width:calc(36em + 40px);
  font-size:clamp(17px,1.45vw,22px);line-height:1.5;font-style:italic;font-weight:400;
  color:rgba(255,255,255,.92);text-wrap:balance;
}
.hero-quote::before,.hero-quote::after{
  color:var(--green-400);font-style:normal;font-weight:700;font-family:Georgia,"Times New Roman",serif;
}
.hero-quote::before{
  content:"\201C";position:absolute;left:0;top:0;font-size:2.4em;line-height:.9;
}
.hero-quote::after{
  content:"\201D";margin-left:6px;font-size:1.5em;line-height:0;vertical-align:-.36em;
}

/* Classes line above the buttons: plain text straight on the hero, no
   panels. Label in the primary green, the range in white; both clear AA over
   the dark photo overlay. */
.hero-classes{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 12px;margin:0;
  font-size:clamp(16px,1.3vw,19px);font-weight:600;line-height:1.3;
}
.hero-classes-label{
  color:var(--green-400);font-size:.78em;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
}
.hero-classes-label::after{content:":"}
.hero-classes-range{color:#fff;letter-spacing:.01em}
.hero-classes-to{margin:0 .35em;color:var(--green-400);font-weight:700}


.hero-slide.is-active > :nth-child(4){transition-delay:.39s}

/* Dots */
/* Single forward control, pinned to the right edge and centred between the
   top and bottom of the hero. The slider loops, so one direction reaches
   every slide and a second arrow would be redundant. */
.hero-next{
  position:absolute;z-index:3;
  right:clamp(14px,3vw,40px);top:50%;transform:translateY(-50%);
  width:56px;height:56px;padding:0;border-radius:50%;
  display:grid;place-items:center;
  border:1.5px solid rgba(255,255,255,.45);
  background:rgba(255,255,255,.14);color:#fff;cursor:pointer;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease);
}
.hero-next .ico{width:24px;height:24px}
.hero-next:hover{background:#fff;border-color:#fff;color:var(--forest-800)}
/* keep the centring transform when the press state scales it */
.hero-next:active{transform:translateY(-50%) scale(.94)}
.hero-next:focus-visible{outline:3px solid var(--green-400);outline-offset:3px}
@media(max-width:560px){
  /* On a phone the copy runs the full width of the hero, so the button would
     sit on top of the paragraph. Shrink it and reserve its column instead of
     moving it: the control belongs on the right, vertically centred. */
  .hero-next{width:46px;height:46px}
  .hero-next .ico{width:20px;height:20px}
  .hero-slide p{padding-right:66px}
}

.hero-dots{
  position:absolute;left:50%;bottom:26px;transform:translateX(-50%);
  display:flex;gap:10px;z-index:2;
}
.hero-dot{
  width:34px;height:34px;padding:0;border:0;background:none;cursor:pointer;
  display:grid;place-items:center;
}
.hero-dot::after{
  content:"";width:30px;height:4px;border-radius:2px;
  background:rgba(255,255,255,.38);
  transition:background .35s var(--ease),width .35s var(--ease);
}
.hero-dot:hover::after{background:rgba(255,255,255,.66)}
.hero-dot.is-active::after{background:var(--green-500);width:44px}
/* still used by any single-image hero */
.hero-media{
  position:absolute;inset:0;z-index:-2;
  width:100%;height:100%;object-fit:cover;object-position:center 28%;
}
/* Overlay: one blue tone across the whole photograph, solid behind the copy
   and turning more transparent towards the right so the photo shows through. */
.hero::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(90deg,rgba(1,49,95,.94) 0%,rgba(1,49,95,.9) 45%,rgba(1,49,95,.62) 72%,rgba(1,49,95,.38) 100%);
}
.hero::after{content:none}
.hero-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:clamp(32px,4vw,60px)}
/* Below 1280px the copy spans most of the hero, so the overlay stays close to
   solid across the full width to keep the text readable. */
@media(max-width:1279px){
  .hero::before{background:rgba(1,49,95,.86)}
  .hero-media{object-position:center 22%}
}
.hero-copy{max-width:min(62ch,780px)}
.eyebrow{
  display:inline-flex;align-items:center;gap:9px;padding:10px 18px;border-radius:4px;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.20);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  font-size:11px;font-weight:600;letter-spacing:.24em;text-transform:uppercase;color:#e7f6da;
}
/* Admission ribbon. Two stacked, slanted bars in brand colours with folded
   tails and a small tab on top, after the classic "admission open" banner.
   Solid colours and no shadows, like the rest of the site.
     tab        blue-600 / white     6.1:1
     ADMISSION  white / blue-700     9.9:1
     OPEN       green-500 / forest   8.2:1
   The bars are clipped to their slanted shape, so the folds and accent lines
   hang off the unclipped .adm-row wrappers instead. */
.adm-badge{
  position:relative;display:inline-block;padding:13px 0 12px;
  text-decoration:none;line-height:1;
  font-family:var(--font-sans);text-transform:uppercase;
}
.adm-tab{
  position:absolute;top:0;left:30px;z-index:3;
  padding:6px 14px 6px 12px;background:var(--blue-600);color:#fff;
  font-size:clamp(11px,1.1vw,15px);font-weight:700;letter-spacing:.16em;white-space:nowrap;
  clip-path:polygon(7px 0,100% 0,calc(100% - 7px) 100%,0 100%);
}
.adm-row{position:relative;display:block;width:max-content}
.adm-bar{
  position:relative;display:block;overflow:hidden;
  font-weight:800;white-space:nowrap;
}
.adm-row-1{z-index:2}
.adm-row-1 .adm-bar{
  padding:12px 34px 11px 20px;background:#fff;color:var(--blue-700);
  font-size:clamp(28px,3.8vw,56px);letter-spacing:.03em;
  clip-path:polygon(0 0,100% 0,calc(100% - 16px) 100%,0 100%);
}
/* folded tail under the left end of the white bar */
.adm-row-1::before{
  content:"";position:absolute;left:0;top:100%;width:18px;height:12px;
  background:var(--blue-700);clip-path:polygon(0 0,100% 0,100% 100%);
}
/* short accent stroke off the top-left corner */
.adm-row-1::after{
  content:"";position:absolute;left:-14px;top:-9px;width:26px;height:2px;
  background:var(--green-400);transform:rotate(-24deg);transform-origin:right center;
}
.adm-row-2{z-index:1;margin:-5px 0 0 36px}
.adm-row-2 .adm-bar{
  padding:11px 34px 13px 30px;background:var(--green-500);color:var(--forest-900);
  font-size:clamp(38px,5.6vw,84px);letter-spacing:.05em;
  clip-path:polygon(16px 0,100% 0,100% 100%,0 100%);
}
/* folded tail under the right end of the green bar */
.adm-row-2::before{
  content:"";position:absolute;right:0;top:100%;width:20px;height:13px;
  background:var(--green-800);clip-path:polygon(0 0,100% 0,0 100%);
}
.adm-row-2::after{
  content:"";position:absolute;right:-18px;bottom:-4px;width:30px;height:2px;
  background:rgba(255,255,255,.7);transform:rotate(-24deg);transform-origin:left center;
}
/* A light sweeps across OPEN every few seconds: movement is what the eye
   catches first, and it stays inside the bar because the bar is clipped. */
.adm-row-2 .adm-bar::after{
  content:"";position:absolute;top:0;bottom:0;left:-60%;width:40%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);
  transform:skewX(-20deg);
  animation:adm-shine 4.2s var(--ease) 1.2s infinite;
}
@keyframes adm-shine{
  0%{left:-60%}
  38%,100%{left:130%}
}
.adm-badge:hover .adm-row-1 .adm-bar{color:var(--green-800)}
.adm-badge:hover .adm-row-2 .adm-bar{background:var(--green-400)}
.adm-badge .adm-bar{transition:background .3s var(--ease),color .3s var(--ease)}
.adm-badge:focus-visible{outline:3px solid #fff;outline-offset:6px}

/* Continuous motion so the badge keeps drawing the eye: the two bars sway
   against each other like a ribbon in a breeze, the tab bobs, and OPEN
   breathes. Only transforms animate (no layout shift, compositor only), and
   only on the visible slide, so a hidden slide costs nothing and each slide
   starts its loop fresh when it comes in. */
@keyframes adm-sway-l{0%,100%{transform:translateX(0)}50%{transform:translateX(-6px)}}
@keyframes adm-sway-r{0%,100%{transform:translateX(0)}50%{transform:translateX(7px)}}
@keyframes adm-bob{0%,100%{transform:translateY(0) rotate(0deg)}50%{transform:translateY(-5px) rotate(-3deg)}}
@keyframes adm-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.045)}}
.hero-slide.is-active .adm-row-1{animation:adm-sway-l 3.2s ease-in-out infinite}
.hero-slide.is-active .adm-row-2{animation:adm-sway-r 3.2s ease-in-out infinite}
.hero-slide.is-active .adm-tab{transform-origin:left bottom;animation:adm-bob 2.4s ease-in-out infinite}
/* grows from its right end so the folded tail underneath stays attached */
.hero-slide.is-active .adm-row-2 .adm-bar{transform-origin:right center;animation:adm-breathe 2s ease-in-out infinite}
/* Right-hand placement. On desktop the badge leaves the text column and
   sits in the open upper-right of the hero, high enough to stay clear of the
   vertically centred next-slide arrow. Taken out of flow, so the heading
   moves up into the space it used to occupy. Below 961px there is no room
   beside the heading, so it stays in flow above it, aligned right. */
@media(min-width:961px){
  .hero-deck{position:relative}
  .hero .adm-badge{position:absolute;top:clamp(0px,1vw,16px);right:0}
}
@media(max-width:960px){
  .hero .adm-badge{display:block;width:max-content;margin-left:auto}
  .hero .adm-badge + h1,.hero .adm-badge + .hero-title{margin-top:18px}
}
@media(prefers-reduced-motion:reduce){
  .adm-row-2 .adm-bar::after{animation:none;display:none}
  .hero-slide.is-active .adm-row-1,.hero-slide.is-active .adm-row-2,
  .hero-slide.is-active .adm-tab,.hero-slide.is-active .adm-row-2 .adm-bar{animation:none}
}

.hero h1,.hero .hero-title{
  font-size:clamp(44px,6.4vw,92px);line-height:1.02;letter-spacing:-.034em;
  margin:26px 0 22px;color:#fff;font-weight:600;
  /* the explicit <br> sets the break, so do not let balancing re-wrap it */
  text-wrap:normal;
}
/* Small phones: the 44px floor pushed "at your doorstep" onto a third line.
   Scale with the viewport instead so each hero line stays on one line. */
@media(max-width:480px){.hero h1,.hero .hero-title{font-size:clamp(28px,8.6vw,44px)}}
.hero h1 span,.hero .hero-title span{
  font-weight:600;
  color:var(--green-400);
}
.hero p{font-size:clamp(16.5px,1.1vw,19.5px);line-height:1.5;max-width:52ch;color:#ccdcc2}
.actions{display:flex;gap:14px;flex-wrap:wrap;margin-top:32px}


.hero-scroll{
  position:absolute;left:50%;bottom:22px;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:8px;
  font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.55);
}
.hero-scroll i{display:block;width:1px;height:38px;background:linear-gradient(rgba(255,255,255,.6),transparent);animation:drop 2s ease-in-out infinite}
@keyframes drop{0%{transform:scaleY(0);transform-origin:50% 0}50%{transform:scaleY(1);transform-origin:50% 0}51%{transform:scaleY(1);transform-origin:50% 100%}100%{transform:scaleY(0);transform-origin:50% 100%}}

/* --------------------------------------------------------------------------
   8. Page hero (inner pages)
   -------------------------------------------------------------------------- */
/* Inner page headers carry the brand green, the same colour as the Apply Now
   button, rather than a dark olive. White would only reach 2.25:1 on it, so
   the type is the dark forest: 8.24:1 for the heading, 5.4:1 for the
   breadcrumb at its lightest. */
.page-hero{
  position:relative;overflow:hidden;color:rgba(14,22,4,.82);
  padding:clamp(56px,7vw,92px) 0 clamp(60px,7.5vw,96px);
  background:linear-gradient(140deg,var(--green-500) 0%,var(--green-600) 100%);
}
.page-hero::after{
  content:"";position:absolute;right:-120px;top:-120px;width:420px;height:420px;border-radius:50%;
  border:1px solid rgba(14,22,4,.16);
  pointer-events:none;
}
.page-hero .container{position:relative;z-index:1}
.page-hero h1{font-size:clamp(38px,6vw,80px);line-height:1.04;letter-spacing:-.03em;margin:0 0 18px;color:var(--forest-900);font-weight:600}
.page-hero p{color:rgba(14,22,4,.82);max-width:62ch;font-size:clamp(15.5px,1vw,17.5px)}
/* ---- Campuses hero: live map of Islamabad behind the heading ----
   The map fills the hero; the heading sits on a solid brand-green panel so
   the text keeps its contrast whatever map detail is underneath. Without JS,
   or before Leaflet loads, the hero is simply green. */
.map-hero{
  padding:0;background:var(--green-500);
  min-height:clamp(300px,26vw,380px);display:flex;align-items:center;
}
.map-hero::after{display:none}
.map-hero-map{position:absolute;inset:0;z-index:0;background:#e8ebe4}
/* muted, grey map so the green pins and panel carry the colour; the filter
   sits on the tile layer only, never on the pins */
.map-hero .leaflet-tile-pane{filter:grayscale(1) contrast(.92) brightness(1.04)}
.map-hero .container{z-index:2;padding-block:clamp(22px,2.4vw,34px);pointer-events:none}
.map-hero-panel{
  pointer-events:auto;max-width:540px;
  background:var(--green-500);padding:clamp(22px,2.4vw,34px) clamp(24px,2.6vw,38px);
}
.map-hero-panel h1{font-size:clamp(30px,3.1vw,44px);margin-bottom:12px}
.map-hero-panel .breadcrumb{margin-bottom:12px}
.map-hero-panel p{margin:0}
.map-hero-note{margin-top:14px !important;font-size:13.5px !important;color:rgba(14,22,4,.78) !important}

/* pins and popups: brand green pin, flat popup (no shadow) */
.map-pin{background:none;border:0}
.map-pin svg{display:block;transition:transform .2s var(--ease);transform-origin:50% 100%}
.map-pin:hover svg{transform:scale(1.12)}
.map-popup .leaflet-popup-content-wrapper{
  border-radius:8px;box-shadow:none;border:1px solid var(--line);
}
.map-popup .leaflet-popup-tip{box-shadow:none;border:1px solid var(--line)}
.map-popup .leaflet-popup-content{margin:12px 14px;font-family:var(--font-sans);line-height:1.4}
.map-popup strong{display:block;color:var(--ink);font-size:14.5px}
.map-popup span{display:block;margin:2px 0 8px;color:var(--blue-700);font-size:10.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase}
.map-popup a{color:var(--green-800);font-size:13px;font-weight:700}
.map-hero .leaflet-control-attribution{font-size:10px}

/* Stacked on narrower screens: heading first, then the map as its own strip,
   so no pin is ever hidden under the text. */
@media(max-width:900px){
  .map-hero{display:block;min-height:0}
  .map-hero .container{padding-block:0;width:100%}
  .map-hero-panel{max-width:none;padding:clamp(30px,6vw,48px) var(--gutter)}
  .map-hero-map{position:relative;inset:auto;height:clamp(220px,48vw,300px)}
}

.breadcrumb{font-size:11px;color:rgba(14,22,4,.78);margin-bottom:20px;letter-spacing:.22em;text-transform:uppercase;font-weight:600}

/* --------------------------------------------------------------------------
   9. Sections
   -------------------------------------------------------------------------- */
.section{padding:clamp(64px,8vw,110px) 0;position:relative}
.section.soft{background:var(--bg-soft)}

/* ---- Section variants -------------------------------------------------
   Rhythm comes from alternating grounds rather than one flat page: white,
   soft grey, a cobalt band, a forest band and a photographic band. Text on
   every coloured ground is checked to at least 4.5:1. ------------------- */

/* Cobalt band, the crest ribbon at full width */
.section.brand{
  /* stops no lighter than #0060c0: the band body text needs 4.5:1 and the
     lighter #0a6fd6 tail only reached 4.01 */
  background:linear-gradient(135deg,var(--blue-700) 0%,var(--blue-600) 100%);
  color:#dbe9fb;
}
.section.brand h2,.section.brand h3,.section.brand h4{color:#fff}
.section.brand .section-head p{color:#dbe9fb}
.section.brand .kicker{color:#fff}
.section.brand .kicker::before{background:linear-gradient(90deg,rgba(255,255,255,.65),rgba(255,255,255,0))}
.section.brand .kicker::after{background:#fff}
.section.brand .section-head.center .kicker::before{background:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,.65),rgba(255,255,255,0))}
/* solid white cards keep normal text contrast on the band */
.section.brand .card{background:#fff;border-color:rgba(255,255,255,.28);color:var(--ink-soft)}
.section.brand .card h3{color:var(--ink)}
.section.brand .card p{color:var(--muted)}
.section.brand .card:hover{border-color:#fff;transform:translateY(-8px)}
.section.brand .program{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.24)}
.section.brand .program h3{color:#fff}
.section.brand .program p{color:#dbe9fb}
.section.brand .program:hover{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.45)}
/* The brand green only reaches 2.72:1 against this cobalt, under the 3:1 a
   control needs to read as a distinct shape. White clears it at 6.11:1. */
.section.brand .btn-primary{background:#fff;color:var(--blue-700)}
.section.brand .btn-primary:hover::before{opacity:0}
.section.brand .btn-primary:hover{background:#eaf2fd;color:var(--blue-700)}
.section.brand .btn-outline{background:transparent;border-color:rgba(255,255,255,.5);color:#fff}
/* Inside a white card those band rules would put white on white. Controls
   nested in a card always use the default light-ground styling. */
.section.brand .card .btn-outline,
.section.forest .card .btn-outline,
.section.picture .card .btn-outline{
  background:#fff;border-color:var(--line);color:var(--forest-800);
}
.section.brand .card .btn-outline:hover,
.section.forest .card .btn-outline:hover,
.section.picture .card .btn-outline:hover{
  background:var(--forest-900);border-color:var(--forest-900);color:var(--green-500);
}
.section.brand .card .btn-primary{background:var(--green-500);color:var(--forest-900)}
.section.brand .btn-outline:hover{background:#fff;color:var(--blue-700);border-color:#fff}

/* Forest band */
.section.forest{
  background:linear-gradient(135deg,var(--green-500) 0%,var(--green-600) 100%);
  color:rgba(14,22,4,.82);
}
.section.forest h2,.section.forest h3,.section.forest h4{color:var(--forest-900)}
.section.forest .section-head p{color:rgba(14,22,4,.82)}
.section.forest .kicker{color:var(--forest-900)}
.section.forest .kicker::before{background:linear-gradient(90deg,rgba(14,22,4,.55),rgba(14,22,4,0))}
.section.forest .kicker::after{background:var(--forest-900)}
.section.forest .section-head.center .kicker::before{background:linear-gradient(90deg,rgba(14,22,4,0),rgba(14,22,4,.55),rgba(14,22,4,0))}
/* solid white cards, the same approach the cobalt band uses */
.section.forest .card{background:#fff;border-color:rgba(14,22,4,.14);color:var(--ink-soft)}
.section.forest .card h3{color:var(--ink)}
.section.forest .card p{color:var(--muted)}
.section.forest .card:hover{background:#fff;border-color:var(--forest-900)}
.section.forest .icon{background:var(--bg-tint);color:var(--green-700)}
/* a green button would vanish into a green band */
.section.forest .btn-primary{background:var(--forest-900);color:#fff}
.section.forest .btn-primary:hover::before{opacity:0}
.section.forest .btn-primary:hover{background:var(--forest-800);color:#fff}

/* Photographic band */
.section.picture{position:relative;isolation:isolate;color:#fff;overflow:hidden}
.section-bg{position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover}
.section.picture::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    linear-gradient(180deg,rgba(14,22,4,.90) 0%,rgba(14,22,4,.80) 50%,rgba(14,22,4,.92) 100%),
    radial-gradient(760px 420px at 82% 12%,rgba(120,192,24,.20),transparent 66%);
}
.section.picture h2,.section.picture h3{color:#fff}
.section.picture .section-head p{color:#ccdcc2}
.section.picture .kicker{color:var(--green-400)}
.section.picture .kicker::before{background:linear-gradient(90deg,rgba(150,214,60,.75),rgba(150,214,60,0))}
.section.picture .kicker::after{background:var(--green-500)}
.section.picture .section-head.center .kicker::before{background:linear-gradient(90deg,rgba(150,214,60,0),rgba(150,214,60,.75),rgba(150,214,60,0))}
.section.picture .card{
  background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.20);color:#e4ecdd;
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.section.picture .card h3{color:#fff}
.section.picture .card p{color:#dae5d0}
.section.picture .card:hover{background:rgba(255,255,255,.14);border-color:var(--green-500)}
.section.picture .icon{background:rgba(255,255,255,.12);color:var(--green-400)}

/* Elements that hard-code dark text need lifting inside the dark bands,
   otherwise they render near-invisible on the coloured grounds. */
.section.picture .check b{color:#fff}
.section.forest .check b{color:var(--forest-900)}
.section.forest .check>div{color:rgba(14,22,4,.82)}
.section.forest .check>span{background:var(--forest-900);color:var(--green-500)}
.section.picture .check>div{color:#dae5d0}
.section.brand .check b{color:#fff}
.section.brand .check>div{color:#dbe9fb}
.section.brand .check>span{background:#fff;color:var(--blue-700)}

.section.picture .btn-outline{background:transparent;border-color:rgba(255,255,255,.45);color:#fff}
.section.picture .btn-outline:hover{background:#fff;color:var(--forest-900);border-color:#fff}
.section.forest .btn-outline{background:transparent;border-color:rgba(14,22,4,.42);color:var(--forest-900)}
.section.forest .btn-outline:hover{background:var(--forest-900);color:var(--green-500);border-color:var(--forest-900)}
.section.picture hr,.section.brand hr{border:0;border-top:1px solid rgba(255,255,255,.18);margin:22px 0}
.section.forest hr{border:0;border-top:1px solid rgba(14,22,4,.20);margin:22px 0}
/* photo cards sit on a dark ground, so drop the light frame */
.section.forest .photo-card,.section.picture .photo-card{background:transparent}
/* white stat cards keep working on the forest band, but the divider grid
   line should not glow against it */
.section.forest .stats-grid{background:rgba(14,22,4,.22);border-color:rgba(14,22,4,.22)}
/* The width cap belongs on the paragraph, not the whole block. Capping the
   block at 52ch squeezed 50px+ headings to a few words per line, so short
   headings wrapped onto two or three lines. Headings now use the full
   column; body copy keeps a comfortable reading measure. */
.section-head{margin-bottom:clamp(36px,4.4vw,60px)}
.section-head p{max-width:62ch}
.section-head.center p{margin-inline:auto}
.section-head.center{text-align:center;margin-inline:auto}
/* The label carries a rule underneath instead of a dash in front: a hairline
   that fades out across the full width, with a bolder skewed segment sitting
   on top of its start. The skew matches the programme chips. */
.kicker{
  display:inline-block;position:relative;padding-bottom:13px;
  color:var(--green-800);font-weight:600;text-transform:uppercase;letter-spacing:.24em;font-size:11px;
}
.kicker::before{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(90deg,rgba(120,192,24,.75),rgba(120,192,24,0));
}
.kicker::after{
  content:"";position:absolute;left:0;bottom:0;width:32px;height:3px;border-radius:1px;
  background:linear-gradient(90deg,var(--green-600),var(--green-500));
  transform:skewX(-20deg);
}
/* centred heads mirror the rule out from the middle */
.section-head.center .kicker::before{
  background:linear-gradient(90deg,rgba(120,192,24,0),rgba(120,192,24,.75),rgba(120,192,24,0));
}
.section-head.center .kicker::after{left:50%;transform:translateX(-50%) skewX(-20deg)}
.section h2{font-size:clamp(32px,4.4vw,60px);line-height:1.06;letter-spacing:-.03em;margin:18px 0 18px;font-weight:600}
.section-head p{color:var(--muted);font-size:clamp(16px,1.05vw,18.5px);line-height:1.55;margin:0}
/* A button dropped inside a section head sat flush against the paragraph,
   because .section-head p carries no bottom margin. */
.section-head > .btn{margin-top:clamp(22px,2.2vw,30px)}

/* --------------------------------------------------------------------------
   10. Stats
   -------------------------------------------------------------------------- */
.stats{padding:0;margin-top:-64px;position:relative;z-index:5}
.stats-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);
  border-radius:var(--radius-lg);overflow:hidden;
}
.stat{background:#fff;padding:clamp(32px,3.4vw,52px) 22px;text-align:center;position:relative;transition:background .3s var(--ease)}
.stat::after{content:"";position:absolute;inset:auto 0 0 0;height:4px;background:var(--green-500);transform:scaleX(0);transition:transform .45s var(--ease)}
.stat:hover{background:var(--bg-tint)}
.stat:hover::after{transform:scaleX(1)}
/* Solid primary green, the same as the header Apply Now button; no gradient.
   Note: this green on white is about 2.3:1, under the 3:1 large-text guide;
   chosen for brand match. --green-600 is the nearest shade that clears it. */
.stat strong{
  display:block;font-family:var(--font-display);font-size:clamp(38px,4.2vw,64px);font-weight:700;
  letter-spacing:-.045em;line-height:.95;font-variant-numeric:tabular-nums;
  color:var(--green-500);
}
/* Direct child only. The counter sits in its own span inside the <strong>,
   and a plain .stat span rule was catching it and rendering the figure at
   label size. */
.stat > span{display:block;color:var(--blue-700);font-size:12.5px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;margin-top:18px;line-height:1.45}

/* --------------------------------------------------------------------------
   11. Cards
   -------------------------------------------------------------------------- */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,1.8vw,24px)}
.card{
  background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:clamp(24px,2.4vw,32px);
  position:relative;overflow:hidden;isolation:isolate;
  transition:transform .45s var(--ease),border-color .45s var(--ease);
}
.card::before{
  content:"";position:absolute;inset:0;z-index:-1;opacity:0;
  background:radial-gradient(420px 220px at var(--mx,50%) var(--my,0%),rgba(120,192,24,.12),transparent 70%);
  transition:opacity .45s var(--ease);
}
.card:hover{transform:translateY(-8px);border-color:var(--green-600)}
.card:hover::before{opacity:1}
.card h3{margin:0 0 10px;font-size:clamp(19px,1.5vw,23px)}
.card p{margin:0;color:var(--muted);font-size:15.5px;line-height:1.55}
/* .card p has no bottom margin, so a button placed straight after the copy sat
   flush against it. Mirrors the .section-head > .btn rule. The adjacent-sibling
   form means it only applies to a button that actually follows something, and
   direct-child only, so the campus cards (buttons nested in .campus-actions,
   which sets its own padding-top) are untouched. */
.card > * + .btn{margin-top:clamp(20px,1.8vw,26px)}
.icon{
  width:56px;height:56px;border-radius:18px;display:grid;place-items:center;
  background:linear-gradient(140deg,var(--bg-tint),#e9f7d6);
  color:var(--green-700);margin-bottom:20px;
  transition:transform .5s var(--ease),background .4s var(--ease),color .4s var(--ease);
}
.icon .ico{width:26px;height:26px;vertical-align:middle;stroke-width:1.6}
.card:hover .icon{transform:translateY(-3px) rotate(-6deg) scale(1.06);background:linear-gradient(140deg,#e2f2cc,#d6f0bb)}

/* --------------------------------------------------------------------------
   12. Split / photo
   -------------------------------------------------------------------------- */
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,4.5vw,68px);align-items:center}
.photo-card{
  border-radius:var(--radius-xl);overflow:hidden;
  background:var(--bg-tint);position:relative;
}
.photo-card::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 55%,rgba(4,16,31,.28));
}
.photo-card img{width:100%;aspect-ratio:4/3.4;object-fit:cover;transition:transform 1.1s var(--ease)}
.photo-card:hover img{transform:scale(1.06)}

/* ---- Homepage About ICC: main split, then mirrored mission / vision ---- */
.about-main .section-head{margin-bottom:28px}
.about-main .section-head p + p{margin-top:14px}
/* height:auto is required: the height="720" attribute is a presentational
   height, and aspect-ratio only applies while height is auto. Without it the
   photo rendered 720px tall in a 589px column. */
.about-main .photo-card img{height:auto;aspect-ratio:16/11}
/* square corners throughout this section, image included */
.about-icc .photo-card{border-radius:0}

.mv{display:grid;gap:clamp(20px,2.4vw,32px);margin-top:clamp(52px,6.4vw,96px)}
/* Each row: the photograph fills its half edge to edge, the statement gets
   the other half. */
.mv-row{
  display:grid;grid-template-columns:1fr 1fr;align-items:stretch;
  border-radius:0;overflow:hidden;min-height:clamp(340px,32vw,460px);
}
/* white panels, same as the section, per request */
.mv-row.is-mission,.mv-row.is-vision{background:#fff}
/* mirrored: statement first, photograph second */
.mv-row.is-vision .mv-photo{order:2}

.mv-photo{margin:0;position:relative;overflow:hidden;min-height:260px}
.mv-photo img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform 1.1s var(--ease);
}
.mv-row.is-mission .mv-photo img{object-position:center 6%}
/* portrait source: keep the face in frame */
.mv-row.is-vision .mv-photo img{object-position:center 0%}
.mv-row:hover .mv-photo img{transform:scale(1.05)}
/* One sweeping curved corner per photo, on opposite corners so the two rows
   mirror each other: Mission bottom-right, Vision top-left. The figure clips
   the image (overflow:hidden), so the zoom on hover stays inside the curve. */
.mv-row.is-mission .mv-photo{border-bottom-right-radius:55%}
.mv-row.is-vision .mv-photo{border-top-left-radius:55%}
/* About page: a third row after Vision mirrors back to the Mission layout
   (photo left, curve bottom-right), keeping the zig-zag going. */
.mv-row.is-approach .mv-photo img{object-position:center 45%}

/* About page story: three quick facts under the copy */
.facts{
  list-style:none;margin:0;padding:24px 0 0;border-top:1px solid var(--line);
  display:grid;grid-template-columns:repeat(3,1fr);gap:18px;
}
.facts li{display:flex;flex-direction:column;gap:6px}
.facts strong{font-size:clamp(26px,2.4vw,34px);font-weight:700;line-height:1;letter-spacing:-.03em;color:var(--green-500)}
.facts span{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--blue-700);line-height:1.4}

/* About page leadership: real portraits, three across */
.people.is-three{grid-template-columns:repeat(3,1fr)}
.person-photo{
  flex:0 0 72px;width:72px;height:72px;border-radius:50%;object-fit:cover;object-position:center 25%;
  border:2px solid var(--green-500);background:var(--bg-soft);
}
@media(max-width:1024px){.people.is-three{grid-template-columns:1fr}}
@media(max-width:480px){.facts{grid-template-columns:1fr 1fr}.facts li:last-child{grid-column:1/-1}}

.mv-body{
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(28px,4vw,64px);
}
.mv-body .kicker{align-self:flex-start;margin-bottom:14px}
.is-vision .mv-body .kicker{color:var(--blue-700)}
.mv-body h3{margin:0 0 16px;font-size:clamp(32px,3.3vw,50px);letter-spacing:-.025em;line-height:1.1}
.is-mission .mv-body h3{color:var(--green-800)}
.is-vision .mv-body h3{color:var(--blue-700)}
.mv-lead{
  margin:0 0 14px;color:var(--ink);font-size:clamp(17px,1.35vw,20px);line-height:1.5;font-weight:500;
}
.mv-body p:not(.mv-lead){margin:0;color:var(--ink-soft);font-size:15.5px;line-height:1.65}

/* Side by side holds down to tablet width; stacking earlier made the portrait
   photo over 650px tall. Stacked, both photos share one landscape ratio. */
@media(max-width:700px){
  .mv-row{grid-template-columns:1fr;min-height:0}
  /* stacked, the photograph always leads, including the mirrored row */
  .mv-row.is-vision .mv-photo{order:0}
  .mv-photo{min-height:0;aspect-ratio:16/10}
}
.check-list{display:grid;gap:18px;margin:28px 0}
.check{display:flex;gap:16px;align-items:flex-start}
.check>span{
  flex:0 0 32px;height:32px;border-radius:11px;display:grid;place-items:center;
  background:var(--blue-600);color:#fff;
  font-size:14px;font-weight:800;
}
.check>span .ico{width:17px;height:17px;vertical-align:middle;stroke-width:2.4}
.check b{color:var(--ink);font-family:var(--font-display);font-size:18px;font-weight:500;letter-spacing:-.018em}
.check>div{font-size:15px;color:var(--muted)}

/* --------------------------------------------------------------------------
   13. Programs
   -------------------------------------------------------------------------- */
.programs{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(14px,1.5vw,20px)}
.program{
  padding:clamp(22px,2.2vw,28px);border-radius:var(--radius-lg);background:#fff;
  border:1px solid var(--line);position:relative;overflow:hidden;
  transition:transform .45s var(--ease),border-color .45s var(--ease);
}
.program::after{
  content:"";position:absolute;width:110px;height:110px;border-radius:50%;
  right:-38px;bottom:-38px;background:radial-gradient(circle,rgba(120,192,24,.16),transparent 70%);
  transition:transform .6s var(--ease);
}
.program::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:linear-gradient(var(--green-700),var(--green-500));
  transform:scaleY(0);transform-origin:50% 0;transition:transform .45s var(--ease);
}
.program:hover{transform:translateY(-6px);border-color:var(--green-600)}
.program:hover::after{transform:scale(1.5)}
.program:hover::before{transform:scaleY(1)}
.program h3{font-size:19px;margin:0 0 9px;position:relative}
.program p{font-size:14px;color:var(--muted);margin:0;position:relative}

/* --------------------------------------------------------------------------
   14. Campus & events
   -------------------------------------------------------------------------- */
.event-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,1.8vw,24px)}
/* ---- Homepage campuses ---- */
/* heading on the left, "view all" on the right, bottoms aligned */
.head-row{
  display:flex;align-items:flex-end;justify-content:space-between;gap:20px 40px;flex-wrap:wrap;
  margin-bottom:clamp(30px,3.6vw,48px);
}
.head-row .section-head{margin-bottom:0}
/* One campus grid for every page. Seven campuses do not fill a 3-column grid
   evenly, so it wraps in centred flex rows instead: 3 + 3 + 1 on desktop,
   2 + 2 + 2 + 1 on tablets, one column on phones. Any campus count stays
   balanced, and the homepage and Campuses page lay out identically. */
.campus-grid{
  --gap:clamp(16px,1.8vw,24px);
  display:flex;flex-wrap:wrap;justify-content:center;gap:var(--gap);
}
.campus-grid > .campus{flex:0 1 calc((100% - var(--gap) * 2) / 3)}
@media(max-width:960px){.campus-grid > .campus{flex-basis:calc((100% - var(--gap)) / 2)}}
@media(max-width:680px){.campus-grid > .campus{flex-basis:100%}}
/* Column layout so the actions can be pushed to the bottom of every card:
   addresses wrap to different lengths, and without this the phone buttons
   sat at three different heights across a row. */
.campus{overflow:hidden;padding:0;display:flex;flex-direction:column}
.campus>img,.campus>picture>img{width:100%;height:216px;object-fit:cover;flex:0 0 auto;transition:transform 1s var(--ease)}
.campus:hover>img,.campus:hover>picture>img{transform:scale(1.07)}
.campus-body{
  padding:clamp(22px,2.2vw,28px);
  display:flex;flex-direction:column;flex:1;
}
/* explicit rhythm: the tag and the button were both sitting flush */
/* Section label on campus cards: plain blue text, no chip, aligned flush
   with the campus name below it. blue-600 on white: 6.1:1. */
.campus-body .tag{align-self:flex-start;margin-bottom:10px;padding:0;background:none;color:var(--blue-600)}
.campus-body h3{margin:0 0 10px;font-size:clamp(18px,1.4vw,21px)}
.campus-body p{margin:0;font-size:14.5px;line-height:1.5;color:var(--muted)}
.campus-actions{
  display:flex;flex-wrap:wrap;gap:10px;
  margin-top:auto;padding-top:22px;
}
/* grow to fill the row: two buttons split it evenly when they fit, and each
   goes full width once the card is too narrow, so no ragged right edge */
.campus-actions .btn{flex:1 1 auto;justify-content:center;padding:15px 16px;font-size:11.5px;letter-spacing:.08em}
.campus-actions .ico{width:15px;height:15px}
/* View location: solid brand green. Dark text, because white on this green
   is only about 2.3:1; forest on green reads at 8.2:1. */
.campus-map{background:var(--green-500);border-color:var(--green-500);color:var(--forest-900)}
.campus-map:hover{background:var(--green-400);border-color:var(--green-400);color:var(--forest-900)}
.tag{
  display:inline-block;padding:6px 12px;border-radius:4px;
  background:#e8f1fb;color:var(--blue-700);font-size:10.5px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;
}
.event{position:relative}
.event img{aspect-ratio:16/10;object-fit:cover;border-radius:var(--radius-lg);margin-bottom:18px;transition:transform 1s var(--ease)}
.event:hover img{transform:scale(1.03) translateY(-4px)}
.event h3{margin:0;font-size:21px;transition:color .3s var(--ease)}
.event:hover h3{color:var(--green-800)}


/* --------------------------------------------------------------------------
   16. FAQ
   -------------------------------------------------------------------------- */
.faq{max-width:820px;margin-inline:auto}
.faq-item{
  border:1px solid var(--line);border-radius:var(--radius);background:#fff;
  margin-bottom:14px;overflow:hidden;
  transition:border-color .35s var(--ease),background .35s var(--ease);
}
.faq-item:last-child{margin-bottom:0}
.faq-item:hover{border-color:#cfe2b4}
.faq-item.open{border-color:var(--green-600);background:#fcfdfa}
.faq-q{
  width:100%;padding:22px 26px;background:none;border:0;text-align:left;
  font-family:var(--font-display);font-size:17.5px;font-weight:500;color:var(--ink);letter-spacing:-.018em;
  line-height:1.35;
  display:flex;justify-content:space-between;align-items:flex-start;gap:24px;cursor:pointer;
}
.faq-q>span{
  flex:0 0 30px;height:30px;margin-top:1px;border-radius:50%;position:relative;
  background:var(--bg-tint);color:var(--green-800);
  transition:transform .4s var(--ease),background .3s var(--ease),color .3s var(--ease);
}
.faq-q>span::before,.faq-q>span::after{
  content:"";position:absolute;left:50%;top:50%;width:11px;height:2px;border-radius:2px;
  background:currentColor;transform:translate(-50%,-50%);
}
.faq-q>span::after{transform:translate(-50%,-50%) rotate(90deg)}
.faq-item.open .faq-q>span{transform:rotate(135deg);background:var(--green-500);color:var(--forest-900)}
/* Collapse trick: the row animates 0fr -> 1fr, so the direct grid child has
   to be a bare clipper. Any padding on it is not reducible and would leave the
   panel that many pixels tall when closed, which is why the text sits in its
   own element inside. */
.faq-a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .42s var(--ease);color:var(--muted)}
.faq-a-inner{overflow:hidden;min-height:0}
.faq-item.open .faq-a{grid-template-rows:1fr}
.faq-a-inner>p{
  margin:0;padding:0 26px 24px;font-size:16px;line-height:1.6;color:var(--muted);
  opacity:0;transform:translateY(-4px);
  transition:opacity .3s var(--ease) .05s,transform .3s var(--ease) .05s;
}
.faq-item.open .faq-a-inner>p{opacity:1;transform:none}

/* --------------------------------------------------------------------------
   17. CTA
   -------------------------------------------------------------------------- */
/* The footer brings its own top padding, so a trailing section with no
   background of its own does not need a full section bottom as well: that
   reads as a hole between the panel and the footer. Coloured bands keep their
   full padding, because there the space is part of the band, not a gap. */
/* The panel needs clearance of its own above it. With padding-top:0 the box
   sat 6-8px under the tinted section edge and read as stuck to it: the space
   above belonged to that section, not to this one. */
.cta{padding:clamp(44px,4.6vw,72px) 0 clamp(36px,3.6vw,58px)}
main > .section:last-child:not(.soft):not(.brand):not(.forest):not(.picture){
  padding-bottom:clamp(40px,4vw,64px);
}
.cta-box{
  border-radius:var(--radius-xl);padding:clamp(34px,4.4vw,60px);
  color:rgba(14,22,4,.82);position:relative;overflow:hidden;isolation:isolate;
  display:flex;align-items:center;justify-content:space-between;gap:30px;flex-wrap:wrap;
  background:linear-gradient(125deg,var(--green-500) 0%,var(--green-600) 100%);
}
.cta-box::after{
  content:"";position:absolute;right:-90px;bottom:-140px;width:360px;height:360px;border-radius:50%;z-index:-1;
  background:radial-gradient(circle,rgba(255,255,255,.22),transparent 66%);
}
.cta-box h2{font-size:clamp(30px,3.6vw,52px);line-height:1.06;letter-spacing:-.03em;margin:0 0 12px;color:var(--forest-900);font-weight:600}
.cta-box p{margin:0;color:rgba(14,22,4,.82)}
.cta-box>*{position:relative}

/* --------------------------------------------------------------------------
   18. Forms
   -------------------------------------------------------------------------- */
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.field{display:grid;gap:8px}
.field.full{grid-column:1/-1}
.field label{font-weight:600;font-size:11px;color:var(--ink);letter-spacing:.14em;text-transform:uppercase}
.field input,.field textarea,.field select{
  width:100%;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:14px 16px;font:inherit;font-size:15px;color:var(--ink);
  outline:none;background:#fff;
  transition:border-color .3s var(--ease),transform .3s var(--ease);
}
.field textarea{resize:vertical;min-height:120px}
.field input::placeholder,.field textarea::placeholder{color:#9db0c6}
.field input:focus,.field textarea:focus,.field select:focus{
  border-color:var(--green-600);transform:translateY(-1px);
}
.notice{
  padding:16px 20px;border-radius:var(--radius);background:#e9f8f2;color:#0f6045;
  margin-bottom:22px;font-size:15px;font-weight:600;border:1px solid #bfe8d8;
  animation:notice-in .5s var(--ease) both;
}
@keyframes notice-in{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}

/* --------------------------------------------------------------------------
   19. Gallery
   -------------------------------------------------------------------------- */
/* Masonry by CSS columns: each photo keeps its natural aspect ratio and the
   column packs them by height, so portraits and landscapes mix without gaps.
   The zoom happens on the image inside a clipped figure, otherwise a scaled
   image would spill over its neighbours. */
/* Category filters. A horizontal strip that scrolls on a phone rather than
   wrapping to three ragged rows. */
.gal-filters{
  display:flex;gap:10px;flex-wrap:wrap;
  margin-bottom:clamp(22px,2.6vw,34px);
}
.chip{
  display:inline-flex;align-items:center;gap:8px;
  padding:14px 18px;border-radius:999px;
  border:1.5px solid var(--line);background:#fff;
  color:var(--forest-800);font-family:var(--font-sans);
  font-size:11.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  cursor:pointer;transition:background .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease);
}
.chip:hover{border-color:var(--green-600);color:var(--green-800)}
.chip.is-on{background:var(--green-500);border-color:var(--green-500);color:var(--forest-900)}
.chip-n{
  font-size:10.5px;font-weight:700;letter-spacing:.06em;
  color:var(--muted);
}
.chip.is-on .chip-n{color:var(--forest-800)}
.chip:focus-visible{outline:3px solid var(--green-600);outline-offset:2px}
.gal-empty{
  margin:40px 0;text-align:center;color:var(--muted);font-size:15.5px;
}
@media(max-width:680px){
  /* one scrolling row beats three stacked rows of chips on a phone */
  .gal-filters{
    flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter);
    scroll-snap-type:x proximity;
  }
  .gal-filters::-webkit-scrollbar{display:none}
  .chip{flex:0 0 auto;scroll-snap-align:start}
}

.gallery{columns:3 300px;column-gap:16px}
/* [hidden] is only display:none in the UA sheet, and .shot sets display
   explicitly, which wins on specificity. Without this the category filter
   marks figures hidden and nothing disappears. */
.shot[hidden]{display:none}
.shot{
  position:relative;display:block;margin:0 0 18px;
  break-inside:avoid;-webkit-column-break-inside:avoid;page-break-inside:avoid;
  border-radius:var(--radius-lg);overflow:hidden;background:var(--bg-soft);
  isolation:isolate;
}
.shot-open{
  display:block;width:100%;padding:0;border:0;background:none;
  cursor:zoom-in;position:relative;font:inherit;color:inherit;
}
.shot img{
  display:block;width:100%;height:auto;
  transition:transform .8s var(--ease),filter .6s var(--ease);
}
.shot:hover img{transform:scale(1.06);filter:saturate(1.08)}
/* keyboard users get the same affordance the mouse gets on hover */
.shot-open:focus-visible{outline:3px solid var(--green-600);outline-offset:3px}
.shot-zoom{
  position:absolute;top:14px;right:14px;
  display:grid;place-items:center;width:38px;height:38px;border-radius:50%;
  background:rgba(14,22,4,.62);color:#fff;
  opacity:0;transform:scale(.85);
  transition:opacity .35s var(--ease),transform .35s var(--ease);
}
.shot-zoom .ico{width:17px;height:17px}
.shot:hover .shot-zoom,.shot-open:focus-visible .shot-zoom{opacity:1;transform:none}
.shot figcaption{
  position:absolute;inset:auto 0 0 0;padding:44px 18px 16px;
  font-size:13.5px;font-weight:500;line-height:1.4;color:#fff;
  background:linear-gradient(180deg,transparent,rgba(14,22,4,.88));
  opacity:0;transform:translateY(10px);
  transition:opacity .4s var(--ease),transform .4s var(--ease);
}
.shot:hover figcaption,.shot:focus-within figcaption{opacity:1;transform:none}
@media(max-width:900px){.gallery{columns:2 240px}}
@media(max-width:560px){.gallery{columns:1}}

/* --------------------------------------------------------------------------
   19b. Gallery lightbox
   --------------------------------------------------------------------------
   Fixed to the viewport and above everything, including the sticky header
   (z-index 100) and the mobile drawer scrim (95). The panel is a grid of
   three rows so the caption and the counter bar never overlap the photo:
   the image row is the only one that flexes, and it is capped with
   max-height so a tall portrait cannot push the caption off screen. */
.lb{
  position:fixed;inset:0;z-index:200;
  /* The row must STRETCH, not centre. With place-items:center the grid row is
     sized by its content, so the height:100% on .lb-inner resolves against an
     indefinite height and is dropped, and a tall portrait then renders at its
     intrinsic size and runs off the screen. Stretching gives the row a
     definite height, which is what lets the 1fr stage cap the photo. */
  display:grid;align-items:stretch;justify-items:center;
  /* minmax(0,1fr), not the implicit auto row: an auto row grows to fit a tall
     portrait, and align-items:stretch then stretches the panel to that
     overgrown row instead of to the viewport. */
  grid-template-rows:minmax(0,1fr);
  padding:clamp(12px,2.4vw,32px);
  opacity:0;visibility:hidden;
  transition:opacity .28s var(--ease),visibility .28s var(--ease);
}
.lb.is-open{opacity:1;visibility:visible}
.lb[hidden]{display:none}
/* the page behind must not scroll under the dialog */
html.lb-lock,html.lb-lock body{overflow:hidden}

.lb-backdrop{position:absolute;inset:0;background:rgba(9,14,4,.90);cursor:zoom-out}

.lb-inner{
  position:relative;z-index:1;
  display:grid;grid-template-rows:auto 1fr auto;gap:12px;
  width:min(1180px,100%);height:100%;min-height:0;
  transform:scale(.97);
  transition:transform .28s var(--ease);
}
.lb.is-open .lb-inner{transform:none}

.lb-bar{display:flex;align-items:center;justify-content:space-between;gap:16px}
.lb-count{
  margin:0;color:rgba(255,255,255,.86);
  font-size:12.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
}
.lb-current{color:var(--green-400)}

.lb-btn{
  display:grid;place-items:center;
  width:46px;height:46px;flex:0 0 46px;
  border:1.5px solid rgba(255,255,255,.28);border-radius:50%;
  background:rgba(255,255,255,.08);color:#fff;
  cursor:pointer;transition:background .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease);
}
.lb-btn .ico{width:20px;height:20px}
.lb-btn:hover{background:#fff;border-color:#fff;color:var(--forest-800)}
.lb-btn:focus-visible{outline:3px solid var(--green-400);outline-offset:3px}

.lb-stage{
  display:flex;align-items:center;justify-content:center;gap:clamp(8px,1.6vw,20px);
  min-height:0;                 /* lets the 1fr row actually shrink */
}
.lb-figure{
  margin:0;flex:1;min-width:0;min-height:0;height:100%;
  display:flex;align-items:center;justify-content:center;
}
.lb-img{
  max-width:100%;max-height:100%;
  width:auto;height:auto;object-fit:contain;
  border-radius:var(--radius);background:rgba(255,255,255,.04);
}
/* only the picture cross-fades on prev/next, so the frame stays put */
.lb-figure.is-swapping .lb-img{opacity:0}
.lb-img{transition:opacity .18s var(--ease)}

.lb-caption{
  margin:0;text-align:center;color:rgba(255,255,255,.82);
  font-size:14.5px;line-height:1.5;
  padding-inline:clamp(0px,4vw,60px);
  min-height:1.5em;            /* reserved, so a one to two line caption never shifts the image */
}

@media(max-width:720px){
  /* The arrows would crowd a phone-width photo, so they drop below it. They
     stay in flow rather than being absolutely positioned: an out-of-flow
     button reserves no space, which left them sitting on top of the caption
     and pushed the photo past the bottom of the viewport. */
  .lb-inner{gap:10px}
  .lb-stage{
    display:grid;
    grid-template-columns:auto 1fr auto;
    grid-template-rows:minmax(0,1fr) auto;
    gap:10px;align-items:center;
  }
  /* height:100%, never auto: the photo caps itself with max-height:100%,
     and a percentage max-height resolves to none against an auto-height
     parent, which let a tall portrait run up over the counter bar. */
  .lb-figure{grid-area:1/1/2/4;height:100%;min-height:0}
  .lb-prev{grid-area:2/1/3/2}
  .lb-next{grid-area:2/3/3/4}
  .lb-caption{padding-inline:8px;font-size:13.5px}
}

@media(prefers-reduced-motion:reduce){
  .lb,.lb-inner,.lb-img{transition:none}
}




/* --------------------------------------------------------------------------
   20. Footer
   -------------------------------------------------------------------------- */
/* Solid deep brand green (--forest-900), no gradient. Light text on it, with
   the primary green kept for accents only. Measured on #0e1604:
     white            18.9:1   headings in --green-400  11.4:1
     links (white .82) 13.6:1  muted text (white .66)    8.9:1
   It also separates cleanly from both the blue and the green call-to-action
   bands that sit directly above the footer on different pages. */
.footer{
  background:var(--forest-900);color:rgba(255,255,255,.72);
  padding:clamp(54px,6vw,80px) 0 24px;position:relative;
  border-top:4px solid var(--green-500);
}
.footer-grid{display:grid;grid-template-columns:1.8fr 1fr 1fr 1.3fr;gap:clamp(28px,3.4vw,48px);position:relative}
.footer-brand{margin-bottom:20px}
.footer-brand .brand-mark{border-color:rgba(255,255,255,.2)}
.footer-brand strong{color:#fff}
.footer-brand small{color:var(--green-400)}
.footer h3{
  color:var(--green-400);font-size:11px;font-family:var(--font-sans);font-weight:700;
  letter-spacing:.22em;text-transform:uppercase;margin:0 0 18px;
}
.footer a{
  display:block;margin:6px 0;padding:5px 0;color:rgba(255,255,255,.82);
  font-size:15px;font-weight:500;
  transition:color .25s var(--ease),transform .25s var(--ease);
}
.footer a:hover{color:var(--green-400);transform:translateX(4px)}
.footer p{max-width:44ch;font-size:15px;line-height:1.65}
.footer .footer-hours{font-size:13px;color:rgba(255,255,255,.66)}
/* Inline credit link: undo the block layout and spacing footer links use in
   the columns above, so it stays on the same line as its label. */
.footer .footer-credit a{display:inline;margin:0;padding:0;font-size:inherit;font-weight:700;color:var(--green-400)}
.footer .footer-credit a:hover{color:#fff;transform:none;text-decoration:underline}
/* Keep clear of the fixed back-to-top button, which sits over this corner
   once you reach the bottom of the page. */
.footer-bottom{
  border-top:1px solid rgba(255,255,255,.12);margin-top:clamp(34px,4vw,52px);padding:24px 76px 0 0;
  display:flex;justify-content:space-between;gap:16px;font-size:12.5px;flex-wrap:wrap;position:relative;
  color:rgba(255,255,255,.66);
}
.social{display:flex;gap:10px;margin-top:18px;flex-wrap:wrap}
.social a{
  width:38px;height:38px;border-radius:12px;display:grid;place-items:center;margin:0;padding:0;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
  font-size:13px;font-weight:700;color:#fff;
  transition:background .3s var(--ease),border-color .3s var(--ease),transform .3s var(--ease),color .3s var(--ease);
}
.social a:hover{background:var(--green-500);border-color:var(--green-500);color:var(--forest-900);transform:translateY(-3px)}
.social a .ico,.social span .ico{width:18px;height:18px}
/* A channel with no URL on file yet: same footprint so the row does not
   reflow when the link is added, but visibly inactive and not clickable. */
.social .is-pending{
  width:38px;height:38px;border-radius:12px;display:grid;place-items:center;
  background:transparent;border:1px dashed rgba(255,255,255,.22);
  color:rgba(255,255,255,.38);cursor:default;
}

.to-top{
  position:fixed;right:24px;bottom:24px;width:48px;height:48px;border-radius:50%;z-index:90;
  display:grid;place-items:center;border:0;cursor:pointer;font-size:18px;
  background:var(--green-500);color:var(--forest-900);
  opacity:0;visibility:hidden;transform:translateY(14px) scale(.9);
  transition:opacity .4s var(--ease),transform .4s var(--ease),visibility .4s;
}
.to-top.show{opacity:1;visibility:visible;transform:none}
.to-top:hover{transform:translateY(-3px) scale(1.05)}
.to-top .ico{width:20px;height:20px}

/* --------------------------------------------------------------------------
   21. Scroll reveal
   -------------------------------------------------------------------------- */
[data-reveal]{opacity:0;transform:translateY(26px);transition:opacity .8s var(--ease-out),transform .8s var(--ease-out)}
[data-reveal="left"]{transform:translateX(-34px)}
[data-reveal="right"]{transform:translateX(34px)}
[data-reveal="zoom"]{transform:scale(.94)}
[data-reveal].is-visible{opacity:1;transform:none}
/* Used for a single frame after an SPA swap so above-the-fold content appears
   at once instead of replaying its entrance animation. */
[data-reveal].no-anim{transition:none !important}
/* Below the split breakpoint the side gutters are narrower than the horizontal
   offset, so a sideways start position would widen the page. Come up instead. */
@media(max-width:960px){
  [data-reveal="left"],[data-reveal="right"]{transform:translateY(26px)}
}

/* --------------------------------------------------------------------------
   22. Responsive
   -------------------------------------------------------------------------- */
@media(max-width:1080px){
  .programs{grid-template-columns:repeat(3,1fr)}
  .footer-grid{grid-template-columns:1.6fr 1fr 1fr}
  .footer-grid>div:last-child{grid-column:1/-1}
}
/* The header collapses to the drawer at 1180px, not 960px: with eight links
   and the Apply Now button, anything narrower squeezed the college name
   into four lines and grew the header from 85px to 113px. Layout rules
   below still switch at 960px. app.js closes the drawer above 1180px. */
@media(max-width:1180px){
  .nav{
    position:fixed;inset:0 0 0 auto;width:min(340px,86vw);
    flex-direction:column;align-items:stretch;justify-content:flex-start;gap:4px;
    padding:calc(var(--safe-t) + 14px) 18px 32px;
    background:#fff;border-left:1px solid var(--line);
    transform:translateX(100%);transition:transform .45s var(--ease);
    overflow-y:auto;z-index:110;font-size:16px;
  }
  /* Crest and close control on one row, so the sheet opens with the same
     identity the page bar carries. */
  .nav-head{
    display:flex;align-items:center;justify-content:space-between;gap:12px;
    padding-bottom:14px;margin-bottom:8px;border-bottom:1px solid var(--line);
  }
  /* The burger stays the opener only; the sheet closes with its own button,
     so hide the burger while the sheet is up rather than showing two X's.
     visibility (not opacity) also takes it out of the tab order. */
  body.nav-open .menu-toggle{visibility:hidden}
  .nav.open{transform:none}
  .nav>a:not(.btn){padding:15px 16px;border-radius:0;border-bottom:1px solid var(--line-soft)}
  .nav>a:not(.btn):last-of-type{border-bottom:0}
  /* in the drawer the rule becomes a left marker instead of an underline */
  .nav>a:not(.btn)::after{left:0;right:auto;top:50%;bottom:auto;width:3px;height:20px;
    transform:translateY(-50%) scaleY(0);transform-origin:50% 50%;border-radius:0 3px 3px 0}
  .nav>a:not(.btn):hover::after{transform:translateY(-50%) scaleY(1)}
  .nav>a.is-active{background:var(--bg-tint)}
  .nav>a.is-active::after{transform:translateY(-50%) scaleY(1);height:26px;width:3px;background:var(--green-500)}
  .nav-cta{margin:14px 0 0}
  .menu-toggle{display:block;z-index:120}
  /* groups become accordions: the toggle is a full-width row, the links
     indent beneath it and only the open group shows them */
  .nav-group{border-bottom:1px solid var(--line-soft)}
  .nav-group-toggle{width:100%;justify-content:space-between;padding:15px 16px;font-size:16px}
  .nav-group-toggle::after{left:0;right:auto;top:50%;bottom:auto;width:3px;height:20px;
    transform:translateY(-50%) scaleY(0);border-radius:0 3px 3px 0}
  .nav-group-toggle:hover::after{transform:translateY(-50%) scaleY(1)}
  .nav-group.is-active>.nav-group-toggle::after{transform:translateY(-50%) scaleY(1);height:26px;width:3px}
  .nav-caret{width:18px;height:18px}
  .nav-menu{display:none;padding:0 0 10px}
  .nav-group.is-open>.nav-menu{display:block}
  .nav-menu a{padding:12px 16px 12px 30px;font-size:15px}
  .nav-menu a.is-active{background:var(--bg-tint)}
  /* Must sit BELOW the header. .header is its own stacking context (sticky
     + z-index:100 + isolation), so the drawer nested inside it can never
     paint above a sibling with a higher z-index, whatever the drawer own
     z-index says. 95 keeps the scrim over the page and the back-to-top
     button (90) while leaving the header and its drawer on top. */
  .nav-scrim{
    position:fixed;inset:0;background:rgba(14,22,4,.48);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:95;
    opacity:0;visibility:hidden;transition:opacity .4s var(--ease),visibility .4s;
  }
  .nav-scrim.show{opacity:1;visibility:visible}
}
@media(max-width:960px){
  .hero-grid,.split{grid-template-columns:1fr}
  .split>.photo-card{order:-1}
  .stats-grid{grid-template-columns:repeat(2,1fr)}
  .cards,.event-grid{grid-template-columns:repeat(2,1fr)}
  .cta-box{flex-direction:column;align-items:flex-start}
}
@media(max-width:680px){
  :root{--header-h:66px}
  /* One line instead of two: the bar becomes a marquee, so both messages
     still get read without doubling the header height. */
  .topbar-inner{min-height:30px;font-size:12px}
  .topbar-track{
    width:max-content;justify-content:flex-start;gap:34px;
    animation:topbar-scroll 26s linear infinite;
  }
  .topbar-track > span{white-space:nowrap}
  .topbar-track > [data-dup]{display:inline-flex;align-items:center}
  .topbar:hover .topbar-track{animation-play-state:paused}
  @keyframes topbar-scroll{from{transform:translateX(0)}to{transform:translateX(calc(-50% - 17px))}}
  .hero{padding:26px 0 90px}
  .hero-scroll{display:none}
  .brand strong{font-size:14.5px}
  .brand small{font-size:9.5px;letter-spacing:.06em}
  .stats{margin-top:-34px}
  .stats-grid,.cards,.event-grid,.programs,.form-grid{grid-template-columns:1fr}
  .field.full{grid-column:auto}
  /* 44px tap targets: these links were a 23px strip on a phone, below even
     the 24px minimum, and the columns stack here so there is room. */
  .footer a{margin:2px 0;padding:11px 0}
  .footer-grid{grid-template-columns:1fr}
  .footer-grid>div:last-child{grid-column:auto}
  .footer-bottom{flex-direction:column}
  .to-top{right:16px;bottom:16px}
}
@media(max-width:430px){
  /* The tagline wraps to two lines and doubles the header height here. */
  .brand small{display:none}
  .brand strong{font-size:15px}
}


/* --------------------------------------------------------------------------
   23a. Courses
   -------------------------------------------------------------------------- */
.course-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(18px,2vw,26px)}
.course{padding:0;overflow:hidden;display:flex;flex-direction:column}
.course>img,.course>picture>img{width:100%;height:220px;object-fit:cover;flex:0 0 auto;transition:transform 1s var(--ease)}
.course:hover>img,.course:hover>picture>img{transform:scale(1.06)}
.course-body{padding:clamp(24px,2.4vw,32px);display:flex;flex-direction:column;flex:1}
.course-body h2{margin:0 0 12px;font-size:clamp(19px,1.5vw,23px)}
.course-body p{margin:0;color:var(--muted);font-size:15px;line-height:1.6}
/* The action sits on the card floor however long the description runs.
   margin-top:auto does the pushing; do NOT zero the padding here, that
   collapses the button under a 44px touch target. */
.course-body .btn{align-self:flex-start}
.course-body>*+.btn{margin-top:auto}
.course-list{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,1.6vw,20px);
}
.course-list li{
  display:flex;align-items:center;gap:14px;
  padding:clamp(18px,1.8vw,22px) clamp(20px,2vw,26px);
  font-size:15.5px;font-weight:500;color:var(--ink);
}
.course-list .ico{width:22px;height:22px;flex:0 0 22px;color:var(--green-700)}
@media(max-width:860px){
  .course-grid,.course-list{grid-template-columns:1fr}
}

/* --------------------------------------------------------------------------
   23d. Mobile app page
   -------------------------------------------------------------------------- */
/* Official Google Play badge. The artwork carries its own transparent
   padding, so it is sized by height and the link gets no extra box. */
.app-get{display:flex;align-items:center;flex-wrap:wrap;gap:14px 22px;margin-top:26px}
.play-badge{display:inline-block;line-height:0;border-radius:10px;transition:transform .3s var(--ease)}
.play-badge img{height:64px;width:auto;display:block}
.play-badge.is-large img{height:78px}
.play-badge:hover{transform:translateY(-3px)}
.play-badge:focus-visible{outline:3px solid var(--forest-900);outline-offset:2px}
.app-meta{
  display:inline-flex;align-items:center;gap:8px;
  color:rgba(14,22,4,.82);font-size:13px;font-weight:600;letter-spacing:.04em;
}
.app-meta .ico{width:18px;height:18px}

/* Illustrative device. Drawn in CSS rather than a screenshot so nothing on it
   can be mistaken for real student data. */
.phone-wrap{display:grid;place-items:center;padding:clamp(10px,2vw,28px) 0}
.phone{
  position:relative;width:min(290px,100%);aspect-ratio:9/18.5;
  border-radius:44px;padding:12px;background:var(--forest-900);
}
.phone-notch{
  position:absolute;top:20px;left:50%;transform:translateX(-50%);
  width:84px;height:22px;border-radius:12px;background:var(--forest-900);z-index:2;
}
.phone-screen{
  height:100%;border-radius:34px;overflow:hidden;background:var(--bg-soft);
  padding:58px 16px 18px;display:flex;flex-direction:column;gap:14px;
}
.phone-head{
  display:flex;align-items:center;gap:10px;padding:12px;border-radius:16px;
  background:var(--green-500);color:var(--forest-900);
}
.phone-head img{width:40px;height:40px;border-radius:10px;background:#fff;padding:2px}
.phone-head strong{display:block;font-size:16px;line-height:1.1}
.phone-head small{display:block;font-size:11px;font-weight:600}
.phone-tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.phone-tiles span{
  display:flex;flex-direction:column;gap:8px;padding:14px 12px;border-radius:14px;
  background:#fff;border:1px solid var(--line);
  font-size:12.5px;font-weight:600;color:var(--ink);
}
.phone-tiles .ico{width:22px;height:22px;color:var(--green-700)}
.phone-notice{
  margin-top:auto;display:flex;align-items:center;gap:10px;padding:12px;border-radius:14px;
  background:var(--blue-600);color:#fff;font-size:12px;font-weight:500;line-height:1.35;
}
.phone-notice .ico{width:20px;height:20px;flex:0 0 20px}

.steps.steps-3{grid-template-columns:repeat(3,1fr)}
.app-help{margin:clamp(26px,3vw,36px) 0 0;color:var(--muted);font-size:15px}
.app-help a{color:var(--blue-700);font-weight:600}

/* Five reasons do not fill a grid evenly: auto-fit left one card stranded on
   its own row. Wrapping flex rows, centred, gives 3 + 2 on desktop and
   2 + 2 + 1 on a tablet, each row balanced. */
.app-why{
  --gap:clamp(14px,1.6vw,20px);
  list-style:none;margin:0 auto;padding:0;max-width:1080px;
  display:flex;flex-wrap:wrap;justify-content:center;gap:var(--gap);
}
.app-why li{flex:0 1 calc((100% - var(--gap) * 2) / 3)}
@media(max-width:960px){.app-why li{flex-basis:calc((100% - var(--gap)) / 2)}}
@media(max-width:560px){.app-why li{flex-basis:100%}}
.app-why li{
  display:flex;gap:14px;align-items:flex-start;padding:22px;border-radius:var(--radius-lg);
  background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.24);color:#e8f1fb;
  font-size:14.5px;line-height:1.5;
}
.app-why li>span{
  flex:0 0 30px;height:30px;border-radius:9px;display:grid;place-items:center;
  background:#fff;color:var(--blue-700);
}
.app-why li>span .ico{width:16px;height:16px;stroke-width:2.4}
.app-why b{display:block;margin-bottom:4px;color:#fff;font-size:16px;font-weight:600}
.app-final{margin-top:clamp(30px,3.4vw,44px);text-align:center}

@media(max-width:960px){
  .app-intro .phone-wrap{order:-1}
}
@media(max-width:760px){
  .steps.steps-3{grid-template-columns:1fr}
  .play-badge img{height:58px}
  .play-badge.is-large img{height:66px}
}

/* --------------------------------------------------------------------------
   23e. Our Projects
   -------------------------------------------------------------------------- */
.proj-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,2vw,28px)}
.proj{margin:0}
.proj-img{border-radius:var(--radius-lg);overflow:hidden;background:var(--bg-soft);aspect-ratio:4/3}
.proj-img img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 1s var(--ease)}
.proj:hover .proj-img img{transform:scale(1.05)}
.proj figcaption{margin-top:14px;color:var(--ink);font-size:15.5px;font-weight:500;line-height:1.5}

.strengths{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(18px,2vw,26px)}
.strength .tag{margin-bottom:14px}
.strength h3{margin:0 0 14px;font-size:clamp(21px,1.8vw,26px)}
.strength p + p{margin-top:12px}

@media(max-width:960px){.proj-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:760px){.strengths{grid-template-columns:1fr}}
@media(max-width:600px){.proj-grid{grid-template-columns:1fr}}
/* nine features split evenly as 3x3; the shared 2-column tablet rule left one stranded */
@media(min-width:681px) and (max-width:960px){.cards.virtual{grid-template-columns:repeat(3,1fr)}}
@media(hover:none){.proj:hover .proj-img img{transform:none}}


/* --------------------------------------------------------------------------
   23b. Leadership
   --------------------------------------------------------------------------
   Portrait beside the statement, alternating sides down the page so three
   long quotes do not read as one wall of text. The photo column is fixed so
   the faces line up regardless of how long each statement runs. */
.leaders{display:grid;gap:clamp(28px,4vw,56px)}
.leader{
  display:grid;grid-template-columns:300px 1fr;
  gap:clamp(24px,3vw,44px);align-items:center;
}
/* Mirrored rows swap the column widths as well as the order. Swapping order
   alone left the text in the narrow 300px column and stretched the photo
   across the wide one. */
.leader.is-flipped{grid-template-columns:1fr 300px}
.leader.is-flipped .leader-photo{order:2}
.leader-photo{margin:0;border-radius:var(--radius-lg);overflow:hidden;background:var(--bg-soft)}
.leader-photo img{display:block;width:100%;height:340px;object-fit:cover;object-position:center 8%}
.leader-body .tag{margin-bottom:14px}
.leader-body h2{margin:0 0 4px;font-size:clamp(22px,2vw,29px)}
.leader-role{
  margin:0 0 18px;color:var(--green-700);
  font-size:12px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
}
.leader blockquote{
  margin:0;padding-left:22px;border-left:3px solid var(--green-500);
}
.leader blockquote p{margin:0 0 14px;color:var(--ink-soft);font-size:15.5px;line-height:1.62}
.leader blockquote p:last-child{margin-bottom:0}

@media(max-width:860px){
  .leader,.leader.is-flipped{grid-template-columns:1fr}
  /* the alternating order only works while there are two columns */
  .leader.is-flipped .leader-photo{order:0}
  .leader-photo img{height:280px}
}

/* --------------------------------------------------------------------------
   23c. Testimonials
   -------------------------------------------------------------------------- */
.quotes{
  display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(18px,2.2vw,30px);
  max-width:1120px;margin-inline:auto;
}
/* margin:0 matters: <figure> carries a UA margin of 1em 40px, which pushed
   both cards 40px in from the grid and opened a 106px gap between them. */
.quote{
  margin:0;position:relative;display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:clamp(28px,3vw,40px);
  transition:border-color .35s var(--ease);
}
.quote:hover{border-color:var(--green-600)}
/* A real opening quotation mark, set large in the brand green. */
.quote-mark{
  display:block;height:.5em;margin:-.05em 0 18px;
  font-family:Georgia,"Times New Roman",serif;font-size:88px;line-height:1;
  color:var(--green-500);
}
.quote.is-alt .quote-mark{color:var(--blue-600)}
.quote blockquote{margin:0 0 28px}
.quote blockquote p{margin:0;color:var(--ink-soft);font-size:clamp(16px,1.2vw,17.5px);line-height:1.7}
/* author row sits on the card floor, under a hairline, so both cards line up
   however long each quote is */
.quote figcaption{
  margin-top:auto;padding-top:22px;border-top:1px solid var(--line);
  display:flex;align-items:center;gap:14px;
}
.quote-avatar{
  flex:0 0 48px;width:48px;height:48px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--green-500);color:var(--forest-900);
  font-size:15px;font-weight:700;letter-spacing:.04em;
}
.quote.is-alt .quote-avatar{background:var(--blue-600);color:#fff}
.quote-who{display:flex;flex-direction:column;gap:4px;min-width:0}
.quote .quote-name{font-weight:700;color:var(--ink);font-size:16px;line-height:1.2}
.quote .quote-role{
  color:var(--blue-700);font-size:11px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;line-height:1.3;
}
@media(max-width:860px){.quotes{grid-template-columns:1fr;max-width:680px}}
@media(hover:none){.quote:hover{border-color:var(--line)}}

/* --------------------------------------------------------------------------
   24. Mobile app shell
   --------------------------------------------------------------------------
   On a phone the site should read as an installed app rather than a page: the
   chrome is an app bar that gets out of the way, the menu is a sheet, touches
   give physical feedback, and nothing hides under the notch or the home
   indicator. Deliberately no bottom tab bar; the app bar and sheet carry
   navigation.

   Everything here is additive and gated behind a width or an input-capability
   query, so the desktop layout is untouched. */

/* Safe areas, named once so every edge that has to clear the notch, the
   rounded corners or the home indicator refers to the same value and falls
   back to 0 on hardware with no insets. */
:root{
  --safe-t:env(safe-area-inset-top,0px);
  --safe-r:env(safe-area-inset-right,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-l:env(safe-area-inset-left,0px);
}

/* ---- touch input, any width ---------------------------------------------
   hover:none means a touchscreen. Tapping fires :hover there and it STICKS
   until the next tap elsewhere, so a tapped card stayed lifted and a tapped
   photo stayed zoomed. Worse, the gallery caption and the zoom badge are
   hover-revealed, which left them invisible on a phone. */
@media (hover:none){
  .card:hover{transform:none;border-color:var(--line)}
  .card:hover::before{opacity:0}
  .card:hover .icon{transform:none;background:linear-gradient(140deg,var(--bg-tint),#e9f7d6)}
  .shot:hover img{transform:none;filter:none}
  .campus:hover>img,.campus:hover>picture>img{transform:none}
  .shot figcaption{opacity:1;transform:none}
  .shot-zoom{opacity:1;transform:none}
  .topbar:hover .topbar-track{animation-play-state:running}
}

/* Physical feedback in place of hover: a press shrinks slightly and springs
   back. pointer:coarse rather than hover:none so a touch laptop gets it too. */
@media (pointer:coarse){
  .btn,.menu-toggle,.lb-btn,.shot-open,.to-top,.nav>a{
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    -webkit-user-select:none;user-select:none;
  }
  .btn:active{transform:scale(.97)}
  .lb-btn:active,.to-top:active{transform:scale(.92)}
  .shot-open:active img{transform:scale(1.03)}
  .card:active{transform:scale(.995)}
  .nav>a:not(.btn):active{background:var(--bg-tint)}
}

/* ---- the phone layout ---------------------------------------------------- */
@media (max-width:680px){
  /* Chrome must not sit under the status bar in standalone mode. The inset is
     padding, not margin, so the bar's own blue still paints up behind the
     clock instead of leaving a white strip. */
  .topbar{padding-top:var(--safe-t)}
  .container{padding-left:var(--safe-l);padding-right:var(--safe-r)}

  /* App bar. The header already sticks; on a phone it also gets out of the way
     as you scroll down and returns as soon as you scroll up, which is what
     makes a screen feel like an app rather than a document.

     It moves with `top`, NOT transform. A transform (or even
     will-change:transform) on .header would make it the containing block for
     the position:fixed drawer nested inside it and trap the drawer in the bar,
     which is exactly what backdrop-filter did here before. Animating the
     sticky offset has no such side effect. */
  .header{transition:top .3s var(--ease),border-color .35s var(--ease)}
  .header.is-tucked{top:calc((var(--header-h) + 2px) * -1)}
  .header.is-stuck::before{background:rgba(255,255,255,.98)}
  .header.is-stuck{box-shadow:0 1px 0 var(--line)}

  /* A drawer that starts below the app bar reads as a menu. One that runs the
     full height of the screen with a rounded leading edge reads as a sheet,
     which is the app idiom. Top padding clears the burger, which stays above
     the sheet and turns into the close control. */
  .nav{
    width:min(380px,92vw);
    padding:calc(var(--safe-t) + 14px) calc(var(--safe-r) + 18px)
            calc(var(--safe-b) + 28px) 18px;
    border-left:0;
    gap:2px;
    overscroll-behavior:contain;          /* no scroll chaining to the page */
    -webkit-overflow-scrolling:touch;
  }
  .nav>a:not(.btn){
    padding:16px 14px;border-bottom:0;
    font-size:16.5px;font-weight:500;
  }
  .nav-group{border-bottom:0}
  .nav-group-toggle{padding:16px 14px;font-size:16.5px}
  .nav-menu a{padding:13px 14px 13px 28px;font-size:15.5px}
  .nav-cta{margin-top:16px;padding:16px 18px;font-size:12px;letter-spacing:.1em}
  .nav-scrim{-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}

  /* Content rhythm: an app uses tighter gutters, rounder surfaces and
     full-width controls rather than inline ones. */
  .container{--gutter:18px}
  .card{border-radius:20px}
  .section{padding:46px 0}
  .section-head{margin-bottom:26px}
  .card>*+.btn,
  .section-head>.btn,
  .cta-box .btn{width:100%;justify-content:center}

  /* Fixed and bottom-edge furniture has to clear the home indicator. */
  .to-top{bottom:calc(var(--safe-b) + 16px);right:calc(var(--safe-r) + 16px)}
  .footer{padding-bottom:calc(var(--safe-b) + 24px)}
  .lb{
    padding:calc(var(--safe-t) + 12px) calc(var(--safe-r) + 12px)
            calc(var(--safe-b) + 12px) calc(var(--safe-l) + 12px);
    overscroll-behavior:contain;
  }

  /* Touch targets that were sized for a mouse. The visual size is set by
     the dot's ::after and the icon inside the social link, so only the hit
     area grows. */
  .hero-dot{width:44px;height:44px}
  .campus-actions .btn{padding:15px 16px}

  /* iOS Safari zooms the entire page in when a focused form control is under
     16px, and leaves it zoomed afterwards. 16px is a hard threshold, not a
     preference, and nothing kills the app illusion faster. -webkit-appearance
     also drops the inset shadow iOS paints on unstyled fields. */
  .field input,.field select,.field textarea{font-size:16px}
  /* appearance:none drops the inset shadow iOS paints on unstyled fields, but
     it is NOT applied to select: that would also strip the native dropdown
     arrow, and nothing here replaces it. */
  .field input,.field textarea{-webkit-appearance:none;appearance:none}
  .social{gap:12px}
  .social a,.social .is-pending{width:44px;height:44px;border-radius:14px}

  /* Rubber-banding past the end of the page exposes the browser's own
     background and breaks the illusion; contain keeps the bounce inside. */
  html{overscroll-behavior-y:contain}
  body{-webkit-tap-highlight-color:transparent}
}

/* ---- installed (standalone) --------------------------------------------
   Launched from the home screen there is no browser UI, so the promo bar sits
   directly under the status bar. Trim it so the app bar stays the focus. */
@media (display-mode:standalone) and (max-width:680px){
  .topbar-inner{min-height:26px;font-size:11.5px}
}

/* --------------------------------------------------------------------------
   23. Accessibility: reduced motion & print
   -------------------------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .hero-frame{transform:none}
  .hero-frame.is-active{animation:none;transform:none}
  .hero-slide > *{transition:none}
  .hero-slide.is-active > *{opacity:1;transform:none}
  .hero-slide{transform:none}
  .hero-slide.is-active{animation:none;transform:none}
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;
  }
  [data-reveal]{opacity:1;transform:none}
}
@media print{
  .header,.topbar,.to-top,.scroll-progress,.hero-scroll,.marquee,.nav-scrim{display:none}
  body{color:#000}
  .hero,.page-hero,.cta-box,.footer{background:none !important;color:#000}
}

/* --------------------------------------------------------------------------
   24. Journey, admission steps, leadership, credentials
   Section patterns taken from the award-winning school sites surveyed
   (Chapin's division cards, Punahou's leadership block, Overlake's value
   pillars), rebuilt on this palette rather than copied.
   -------------------------------------------------------------------------- */

/* ---- Academic journey: a stepped timeline rather than a flat grid ---- */
.journey{
  --journey-gap:clamp(18px,2.2vw,32px);
  list-style:none;margin:0;padding:0;position:relative;
  display:grid;grid-template-columns:repeat(4,1fr);gap:var(--journey-gap);
}
.stage{position:relative;padding-top:70px}
/* The connector is drawn per stage, from just past its own marker across the
   gap to the next one. Drawing it once on the wrapper cannot line up, because
   the markers sit at the left edge of each column rather than its centre. */
.stage::before{
  content:"";position:absolute;top:23px;left:60px;right:calc(-1 * var(--journey-gap));
  height:2px;background:linear-gradient(90deg,var(--green-500),var(--blue-600));
  opacity:.4;
}
.stage:last-child::before{display:none}
.stage-step{
  position:absolute;top:0;left:0;width:48px;height:48px;border-radius:50%;
  display:grid;place-items:center;z-index:1;
  background:#fff;border:2px solid var(--green-500);
  font-size:13px;font-weight:700;letter-spacing:.04em;color:var(--forest-900);
  transition:background .4s var(--ease),color .4s var(--ease),transform .4s var(--ease);
}
.stage:hover .stage-step{background:var(--green-500);transform:translateY(-3px)}
.stage h3{margin:0 0 8px;font-size:clamp(18px,1.5vw,21px)}
.stage p{margin:0 0 14px;color:var(--muted);font-size:15px;line-height:1.55}
.stage-tag{
  display:inline-block;padding:5px 11px;border-radius:4px;
  background:var(--bg-tint);color:var(--green-800);
  font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
}

/* ---- Admission steps: oversized numerals on a tinted ground ---- */
.steps{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(20px,2.4vw,36px)}
.step{position:relative;padding-top:8px;border-top:2px solid var(--line)}
.step::after{
  content:"";position:absolute;top:-2px;left:0;width:0;height:2px;
  background:var(--green-500);transition:width .6s var(--ease);
}
.step:hover::after,.step.is-visible::after{width:100%}
/* Was --line (#e4e7ec), which measured 1.24:1 and read as blank space.
   #638d42 clears the 3:1 large-text threshold on white and on the tinted
   ground (3.88 and 3.62), while still sitting back from the heading. */
.step-no{
  display:block;font-size:clamp(40px,4.4vw,62px);font-weight:700;line-height:1;
  letter-spacing:-.05em;color:#638d42;margin:14px 0 12px;
  transition:color .4s var(--ease);
}
.step:hover .step-no{color:var(--green-500)}
.step h3{margin:0 0 8px;font-size:17.5px}
.step p{margin:0;color:var(--muted);font-size:15px;line-height:1.55}

/* ---- Leadership ---- */
.center-link{margin:clamp(26px,3vw,38px) 0 0;text-align:center}
.people{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(18px,2vw,26px)}
.person{
  display:flex;align-items:flex-start;gap:20px;
  padding:clamp(22px,2.4vw,30px);
  border:1px solid var(--line);border-radius:var(--radius-lg);background:#fff;
  transition:border-color .4s var(--ease),transform .4s var(--ease);
}
.person:hover{border-color:var(--green-600);transform:translateY(-4px)}
.person-mark{
  flex:0 0 60px;height:60px;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(140deg,var(--forest-900),var(--green-700));
  color:#fff;font-size:17px;font-weight:700;letter-spacing:.02em;
}
.person h3{margin:0 0 8px;font-size:19px}
.person-role{
  display:block;color:var(--green-800);font-size:10.5px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;margin-bottom:10px;
}
.person p{margin:0;color:var(--muted);font-size:14.5px;line-height:1.55}

/* ---- Credentials strip ---- */
.creds{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;
}
.cred{
  background:#fff;padding:clamp(22px,2.4vw,30px);
  display:flex;align-items:flex-start;gap:14px;
  transition:background .3s var(--ease);
}
.cred:hover{background:var(--bg-tint)}
.cred .ico{width:24px;height:24px;flex:0 0 24px;color:var(--green-700)}
.cred b{display:block;font-size:15.5px;color:var(--ink);margin-bottom:3px;font-weight:600}
.cred span{display:block;font-size:13.5px;color:var(--muted);line-height:1.45}

@media(max-width:1080px){
  .journey,.steps,.creds{grid-template-columns:repeat(2,1fr)}
  .stage::before{display:none}
}
@media(max-width:680px){
  .journey,.steps,.creds,.people{grid-template-columns:1fr}
  .stage{padding-top:62px}
}

/* --------------------------------------------------------------------------
   25. Values band, quicklinks, ambient grounds
   Patterns drawn from the 17 school sites surveyed: named-virtue bands
   (Overlake, Harrow, SAS), image quicklink grids (Hotchkiss, Dulwich,
   St Paul's) and ambient gradient grounds (Westminster, WIS, Overlake).
   -------------------------------------------------------------------------- */

/* ---- Ambient ground: replaces the flat grey with a soft tinted wash ---- */
.section.soft{
  background:
    radial-gradient(900px 520px at 12% 0%,rgba(120,192,24,.10),transparent 62%),
    radial-gradient(760px 480px at 92% 100%,rgba(0,96,192,.08),transparent 60%),
    var(--bg-soft);
}

/* ---- Named values ---- */
.values{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2vw,26px)}
.value{
  position:relative;padding:clamp(28px,3vw,40px);
  border-radius:var(--radius-xl);overflow:hidden;isolation:isolate;
  background:#fff;border:1px solid var(--line);
  transition:transform .5s var(--ease),border-color .5s var(--ease);
}
.value::before{
  content:attr(data-index);
  position:absolute;right:18px;top:6px;z-index:-1;
  font-size:108px;font-weight:700;line-height:1;letter-spacing:-.06em;
  color:var(--bg-tint);
}
.value:hover{transform:translateY(-6px);border-color:var(--green-600)}
.value .ico{width:30px;height:30px;color:var(--green-700);margin-bottom:18px}
.value h3{margin:0 0 10px;font-size:clamp(20px,1.7vw,25px)}
.value p{margin:0;color:var(--muted);font-size:15.5px;line-height:1.55}

/* ---- Quicklinks: image cards that lead somewhere ---- */
.quicklinks{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(14px,1.6vw,20px)}
.quick{
  position:relative;display:block;overflow:hidden;isolation:isolate;
  border-radius:var(--radius-xl);min-height:clamp(230px,22vw,310px);
  color:#fff;
}
.quick img{
  position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover;
  transition:transform 1.1s var(--ease);
}
.quick::after{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(14,22,4,.18) 0%,rgba(14,22,4,.62) 58%,rgba(14,22,4,.88) 100%);
  transition:background .5s var(--ease);
}
.quick:hover img{transform:scale(1.07)}
.quick:hover::after{background:linear-gradient(180deg,rgba(14,22,4,.28) 0%,rgba(14,22,4,.70) 58%,rgba(14,22,4,.92) 100%)}
.quick-body{position:absolute;inset:auto 0 0 0;padding:clamp(20px,2vw,26px)}
.quick h3{margin:0 0 6px;color:#fff;font-size:clamp(18px,1.5vw,22px)}
.quick p{margin:0;color:#dce8d2;font-size:14px;line-height:1.45}
.quick-go{
  display:inline-flex;align-items:center;gap:8px;margin-top:14px;
  font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--green-400);
}
.quick-go .ico{width:15px;height:15px;transition:transform .35s var(--ease)}
.quick:hover .quick-go .ico{transform:translateX(4px)}

@media(max-width:1080px){
  .quicklinks{grid-template-columns:repeat(2,1fr)}
  .values{grid-template-columns:repeat(3,1fr)}
}
@media(max-width:760px){
  .values{grid-template-columns:1fr}
}
@media(max-width:560px){
  .quicklinks{grid-template-columns:1fr}
}

/* Form helpers for the shared inquiry forms */
.notice.is-error{background:#fff2f0;color:#a43b2b}
.field-opt{font-weight:500;letter-spacing:.04em;text-transform:none;color:var(--muted)}

/* ---- Alumni, Partners, Scholarships ---- */
.cards.cards-4{grid-template-columns:repeat(4,1fr)}
.split.form-split{align-items:start}
.form-split .check-list{margin-bottom:0}
.check>div a{color:var(--blue-700);font-weight:600}
.check>div a:hover{color:var(--green-700)}
.text-link{display:inline-flex;align-items:center;gap:8px;color:var(--blue-700);font-weight:600}
.text-link .ico{width:17px;height:17px;transition:transform .3s var(--ease)}
.text-link:hover{color:var(--green-700)}
.text-link:hover .ico{transform:translateX(4px)}
.inquiry .notice{margin-bottom:18px}

/* partnership tracks: equal-height cards with the button pinned to the foot */
.tracks{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,1.8vw,24px)}
.track{display:flex;flex-direction:column;align-items:flex-start}
.track .tag{margin-bottom:12px}
.track-points{list-style:none;margin:20px 0 26px;padding:0;display:grid;gap:10px}
.track-points li{display:flex;gap:10px;align-items:flex-start;font-size:15px;line-height:1.5;color:var(--ink-soft)}
.track-points .ico{flex:0 0 18px;width:18px;height:18px;margin-top:2px;color:var(--green-600);stroke-width:2.4}
.card.track > .btn{margin-top:auto}
@media(max-width:1080px){
  .cards.cards-4{grid-template-columns:repeat(2,1fr)}
  .tracks{grid-template-columns:1fr;max-width:640px;margin-inline:auto}
}
@media(max-width:680px){
  .cards.cards-4{grid-template-columns:1fr}
}

/* Partners "Why ICC": the photo takes the height of the text column instead
   of its own 4:3 height, so text and image line up top and bottom. */
.why-split{align-items:stretch}
.why-split .photo-card{min-height:300px}
.why-split .photo-card img{position:absolute;inset:0;height:100%;aspect-ratio:auto}
@media(max-width:960px){
  .why-split .photo-card{min-height:0;aspect-ratio:16/10}
}

/* Next-gen images: <picture> wrappers added by includes/images.php take no
   box of their own, so every layout still sees the <img> as before. */
picture{display:contents}
/* With the wrapper gone, <source> elements would become empty flex/grid
   items and each would add a gap. Browsers never render them anyway. */
picture>source{display:none}

/* ---- Our Projects cards (homepage and projects page) ---- */
.project-item{display:flex;flex-direction:column;align-items:flex-start;color:inherit}
.project-range{
  display:block;margin-bottom:8px;font-size:11px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--blue-700);
}
.project-item p{margin-bottom:20px}
.project-go{
  display:inline-flex;align-items:center;gap:8px;margin-top:auto;
  font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--green-700);
}
.project-go .ico{width:16px;height:16px;margin:0;color:inherit;transition:transform .35s var(--ease)}
.project-item:hover .project-go .ico{transform:translateX(4px)}
.project-item:focus-visible{outline:3px solid var(--green-600);outline-offset:3px}
.center-cta{display:flex;justify-content:center;margin-top:clamp(28px,3vw,44px)}
@media(max-width:1080px) and (min-width:761px){
  .projects-list{grid-template-columns:repeat(2,1fr)}
}

/* ---- Hero on phones: an app welcome screen ------------------------------
   The photo shows at the top and the copy sits at the bottom of a screen-tall
   hero, within thumb reach. The overlay stays light over the photo and deepens
   behind the text. Two equal buttons share one row, slides change with a
   swipe (app.js), so the floating arrow is dropped; the dots remain as the
   tappable indicator. */
@media(max-width:680px){
  .hero{
    min-height:calc(100svh - var(--header-h) - 32px);
    align-content:end;
    padding:20px 0 calc(var(--safe-b) + 64px);
  }
  .hero::before{
    background:linear-gradient(180deg,
      rgba(1,49,95,.18) 0%,rgba(1,49,95,.38) 26%,
      rgba(1,49,95,.86) 50%,rgba(1,49,95,.96) 70%,rgba(1,49,95,.98) 100%);
  }
  .hero-slide{max-width:none}

  /* badge: smaller, left-aligned above the heading */
  .hero .adm-badge{zoom:.74;margin:0 0 4px;margin-left:0}
  .hero .adm-badge + h1,.hero .adm-badge + .hero-title{margin-top:14px}

  .hero h1,.hero .hero-title{font-size:clamp(34px,10.4vw,44px);line-height:1.04;margin:14px 0 14px}
  .hero p{font-size:15.5px;line-height:1.5;max-width:none;padding-right:0}
  .hero .hero-quote{font-size:16px;padding-left:32px;margin-bottom:16px}
  .hero-classes{margin:0}

  .hero .actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:22px}
  .hero .actions .btn{
    justify-content:center;min-height:52px;padding:14px 8px;
    font-size:11.5px;letter-spacing:.06em;white-space:nowrap;
  }
  .hero .actions .btn .ico{display:none}

  .hero-next{display:none}
  .hero-dots{bottom:calc(var(--safe-b) + 12px);gap:4px}
}
@media(max-width:340px){
  .hero .actions{grid-template-columns:1fr}
}

/* Drawer rows run edge to edge: the sheet has no side padding, so the row
   dividers and the active highlight reach both edges like an app list. The
   header row and the Apply Now button carry their own side padding instead. */
@media(max-width:1180px){
  .nav{padding-left:0;padding-right:0}
  .nav-head{padding-left:18px;padding-right:18px}
  .nav>a:not(.btn),.nav-group-toggle{padding-left:18px;padding-right:18px}
  .nav-menu a{padding-left:34px;padding-right:18px}
  .nav-cta{margin-left:18px!important;margin-right:18px!important}
}
@media(max-width:680px){
  .nav{padding-right:var(--safe-r)}
  .nav-head{padding-left:16px;padding-right:16px}
  .nav>a:not(.btn),.nav-group-toggle{padding-left:18px;padding-right:18px}
}

/* Phones: the Admission Open badge sits centred at the top of the hero, over
   the photo, instead of in the copy block. Centred with auto margins, not a
   transform, because the slide animation already sets the badge's transform.
   The hero's top padding reserves its height, so on short screens the copy
   can never slide underneath it. */
@media(max-width:680px){
  .hero{padding-top:136px}
  .hero .adm-badge{
    position:absolute;top:22px;left:0;right:0;z-index:2;
    width:max-content;margin:0 auto;
  }
  .hero .adm-badge + h1,.hero .adm-badge + .hero-title{margin-top:0}
}

/* ---- About sections on phones (homepage About, About page, leadership
   people): app-style layout. Photos run the full screen width with square
   corners, and text lines up with the page's single side margin instead of
   sitting inside a second layer of padding. `width:100vw` with a negative
   margin lets a photo break out of the container without changing markup. */
@media(max-width:680px){
  .about-icc .photo-card,
  .about-icc .mv-photo{
    width:100vw;margin-left:calc(50% - 50vw);margin-right:0;
    border-radius:0 !important;
  }
  .about-icc .split.about-main{gap:24px}
  .about-icc .about-main .photo-card img{aspect-ratio:16/11}

  .about-icc .mv{gap:36px;margin-top:44px}
  .about-icc .mv-row{overflow:visible;border-radius:0}
  .about-icc .mv-photo{aspect-ratio:16/11}
  .about-icc .mv-body{padding:22px 0 0}
  .about-icc .mv-body h3{font-size:30px;margin-bottom:12px}

  /* leadership: full-width list rows divided by hairlines, square portraits */
  .people{gap:0}
  .person{
    width:100vw;margin-left:calc(50% - 50vw);
    padding:22px 18px;border:0;border-top:1px solid var(--line);border-radius:0;
  }
  .person:last-child{border-bottom:1px solid var(--line)}
  .person:hover{transform:none}
  .person-photo{border-radius:0}
}

/* file inputs in the shared forms */
.field input[type=file]{padding:12px;background:#fff;cursor:pointer}
.field-hint{font-size:12.5px;color:var(--muted)}

/* campus card: second number and the campus's own social pages */
.campus-extra{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:14px}
.campus-alt{display:inline-flex;align-items:center;min-height:44px;white-space:nowrap;margin-right:auto;font-size:13.5px;font-weight:600;color:var(--blue-700)}
.campus-alt:hover{color:var(--green-700)}
.campus-social{
  display:grid;place-items:center;width:44px;height:44px;
  border:1px solid var(--line);color:var(--blue-700);
  transition:color .25s var(--ease),border-color .25s var(--ease),background .25s var(--ease);
}
.campus-social .ico{width:18px;height:18px}
.campus-social:hover{background:var(--blue-700);border-color:var(--blue-700);color:#fff}
