/* Gaydio Academy — one stylesheet, no build step.
 *
 * Effra @font-face block, then the approved mockup's CSS verbatim, then the
 * additions the extracted markup needs (see the banner near the bottom).
 */

@font-face{font-family:'Effra';font-weight:300;font-style:normal;font-display:swap;src:url('../fonts/effra/effra-300.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:300;font-style:italic;font-display:swap;src:url('../fonts/effra/effra-300-italic.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:400;font-style:normal;font-display:swap;src:url('../fonts/effra/effra-400.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:400;font-style:italic;font-display:swap;src:url('../fonts/effra/effra-400-italic.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:500;font-style:normal;font-display:swap;src:url('../fonts/effra/effra-500.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:500;font-style:italic;font-display:swap;src:url('../fonts/effra/effra-500-italic.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:700;font-style:normal;font-display:swap;src:url('../fonts/effra/effra-700.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:700;font-style:italic;font-display:swap;src:url('../fonts/effra/effra-700-italic.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:900;font-style:normal;font-display:swap;src:url('../fonts/effra/effra-900.woff2') format('woff2')}
@font-face{font-family:'Effra';font-weight:900;font-style:italic;font-display:swap;src:url('../fonts/effra/effra-900-italic.woff2') format('woff2')}

:root{--p:#09475D;--s:#008577;--a:#00C9A7;--light:#F4F9FB;--white:#fff;--dark:#061318;--text:#1a3340;--muted:#4f7286;--s-text:#007064;--bdr:#dce8ed;--gap:clamp(72px,8vw,140px);--r:22px;
  /* Motion tokens — one shared vocabulary rather than a duration/easing typed
     fresh per component. Three tiers, deliberately not blurred together: a
     click/hover reacts instantly, a scroll reveal is quick and confident,
     ambient background motion (the funders ticker) is slow and continuous. */
  --motion-instant:.1s;--motion-fast:.3s;--motion-base:.5s;--motion-slow:28s;
  --ease-snap:cubic-bezier(.17,.67,0,.99);--ease-soft:cubic-bezier(.4,0,.2,1);
  --motion-stagger-step:.5s}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
/* nav is fixed at 68px — without this, jumping to any in-page anchor (Apply
   Now -> #apply, the scroll-cue chevron, an FAQ link) lands the target's
   top edge right under it, hidden. */
[id]{scroll-margin-top:84px}
body{font-family:'Effra',sans-serif;color:var(--text);background:var(--white);overflow-x:hidden}
h1,h2,h3,h4,h5{font-family:'Effra',sans-serif;line-height:1.1;font-weight:900}
a{text-decoration:none;color:inherit}
.page{display:none}.page.active{display:block}

/* NAV */
nav{position:fixed;top:0;left:0;right:0;z-index:1000;display:flex;align-items:center;justify-content:space-between;padding:0 clamp(14px,3.5vw,56px);height:68px;background:rgba(9,71,93,0);transition:background .4s,box-shadow .4s}
nav.scrolled,nav.solid{background:rgba(9,71,93,0.97);backdrop-filter:blur(18px);box-shadow:0 2px 28px rgba(0,0,0,.2)}
.nav-logo{cursor:pointer;display:flex;align-items:center}
.nav-logo img{height:36px;width:auto}
.nav-links{display:flex;align-items:center;gap:4px;list-style:none}
.nav-links>li{position:relative}
.nav-links>li>a{color:rgba(255,255,255,.9);font-size:13.5px;font-weight:500;padding:8px 12px;border-radius:8px;cursor:pointer;transition:color .2s,background .2s;display:flex;align-items:center;gap:4px;background:none;border:none;font-family:'Effra',sans-serif}
.nav-links>li>a:hover,.nav-links>li>a.active-link{color:white;background:rgba(255,255,255,.08)}
.dropdown{display:none;position:absolute;top:calc(100% + 4px);left:0;background:rgba(9,71,93,0.98);border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:8px;flex-direction:column;gap:2px;min-width:210px;box-shadow:0 12px 40px rgba(0,0,0,.3);z-index:200}
.dropdown.open{display:flex}
.dropdown a{color:rgba(255,255,255,.88);font-size:13px;padding:9px 14px;border-radius:8px;cursor:pointer;transition:all .2s;white-space:nowrap}
.dropdown a:hover{color:white;background:rgba(255,255,255,.1)}
.nav-cta{background:var(--s)!important;color:white!important;padding:9px 20px!important;border-radius:50px!important;font-weight:600!important;font-size:13px!important;transition:transform .2s,box-shadow .2s!important}
.nav-cta:hover{transform:translateY(-1px)!important;box-shadow:0 6px 20px rgba(0,133,119,.4)!important}
.chevron{font-size:10px;opacity:.6}
.hamburger{display:none;flex-direction:column;gap:5px;cursor:pointer;padding:4px}
.hamburger span{width:22px;height:2px;background:white;border-radius:2px;transition:all .3s}
.mobile-nav{display:none;position:fixed;top:68px;left:0;right:0;z-index:999;background:rgba(9,71,93,.98);backdrop-filter:blur(18px);padding:16px clamp(14px,3.5vw,56px) 28px;flex-direction:column;gap:2px;max-height:80vh;overflow-y:auto}
.mobile-nav.open{display:flex}
.mobile-nav a{color:rgba(255,255,255,.9);font-size:15px;font-weight:500;padding:11px 12px;border-radius:8px;cursor:pointer;transition:all .2s}
.mobile-nav a:hover{color:white;background:rgba(255,255,255,.08)}
.mob-section{font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--a);padding:12px 12px 4px;margin-top:4px}

/* BUTTONS */
.btn{background:var(--s);color:white;padding:14px 32px;border-radius:50px;font-family:'Effra',sans-serif;font-weight:700;font-size:14px;display:inline-flex;align-items:center;gap:8px;cursor:pointer;transition:transform .2s,box-shadow .2s;border:none}
.btn:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(0,133,119,.4)}
.btn-out{background:transparent;border:2px solid var(--p);color:var(--p);padding:12px 28px;border-radius:50px;font-family:'Effra',sans-serif;font-weight:700;font-size:14px;display:inline-flex;align-items:center;gap:8px;cursor:pointer;transition:all .2s}
.btn-out:hover{background:var(--p);color:white}
.btn-ghost{background:rgba(255,255,255,.1);border:1.5px solid rgba(255,255,255,.3);color:white;padding:14px 32px;border-radius:50px;font-family:'Effra',sans-serif;font-weight:600;font-size:14px;display:inline-flex;align-items:center;gap:8px;cursor:pointer;backdrop-filter:blur(8px);transition:all .2s;border-bottom-color:rgba(255,255,255,.3)}
.btn-ghost:hover{background:rgba(255,255,255,.18)}

/* SECTION COMMONS */
.lbl{display:inline-flex;align-items:center;font-size:11px;font-weight:700;letter-spacing:-0.03em;text-transform:uppercase;color:var(--s-text);margin-bottom:16px}
/* Same kicker, navy instead of --s-text. */
.lbl-p{color:var(--p)}
.ttl{font-size:clamp(32px,4.2vw,56px);color:var(--p);letter-spacing:-0.03em;line-height:1.05;max-width:660px;margin-bottom:14px}
.ttl em{font-style:normal;color:var(--s)}
/* A much bigger variant for one heading (About The Academy) — scoped
   rather than changed on .ttl itself, which every other section's
   heading on the site still uses at the normal size. */
.ttl-big{font-size:clamp(40px,6vw,84px);line-height:.98;max-width:none}
.body-txt{font-size:16px;line-height:1.78;color:var(--muted);max-width:560px}
/* A bar that grows in under one heading's emphasised word once its .rv
   wrapper is revealed — opt-in via .em-grow on that same wrapper, not every
   .ttl em site-wide. currentColor picks up whatever colour that word
   already is (teal on light, mint on the inverted navy bands), so this is
   one rule for both. */
.em-grow :is(.ttl,.ttl-inv,.ttl-big,h2) em{position:relative;display:inline-block}
.em-grow :is(.ttl,.ttl-inv,.ttl-big,h2) em::after{content:'';position:absolute;left:0;right:0;bottom:.08em;height:.07em;border-radius:4px;background:currentColor;opacity:.4;transform:scaleX(0);transform-origin:left;transition:transform .9s .25s var(--ease-soft,ease)}
.em-grow.vis :is(.ttl,.ttl-inv,.ttl-big,h2) em::after{transform:scaleX(1)}
/* A course's own Overview can use bold, accent-colour and link markup, the
   same as every other body-text field already accepts (sections.js's
   rich()) — but scoped to just this one spot rather than every .body-txt
   on the site, since most of those already use that markup to mean italic
   and changing that everywhere at once was not what was asked for. */
.course-overview strong{color:var(--text)}
.course-overview em{font-style:normal;color:var(--s-text);font-weight:600}
.inner{max-width:1240px;margin:0 auto;padding:0 clamp(14px,4vw,60px)}
/* Breaks an element out of .inner's 1240px cap to run the full width of the
   viewport — used only for a row/carousel that actually benefits from a
   wide screen's extra space (Find your course, Our Podcasts, the
   testimonials photo), never for body text, which stays readable at
   .inner's width regardless. Same clamp(14px,4vw,60px) gutter .inner
   itself uses, so nothing changes on a phone — .inner was already close
   to full width there — only a wide screen actually gains anything. */
.full-bleed{width:100vw;margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw)}

/* REVEAL — quick, confident, directional entrances (the workhorse duration
   is --motion-base, 0.5s; nothing here should linger). Plain .rv fades up;
   add .rv-left/.rv-right for an alternating image/text section (the image
   slides in from whichever side it sits on), or .rv-scale for a card/tile
   grid. Delay steps are 0.5s beats — a cascade should read as a deliberate
   "one, two, three", not a fast ripple. */
.rv{opacity:0;transform:translateY(60px);transition:opacity var(--motion-base) var(--ease-snap),transform var(--motion-base) var(--ease-snap)}
.rv.vis{opacity:1;transform:none}
.rv-left:not(.vis){transform:translateX(-70px)}
.rv-right:not(.vis){transform:translateX(70px)}
.rv-scale:not(.vis){transform:scale(.94);transition-timing-function:var(--ease-soft)}
/* A bigger, punchier entrance for the two "arrivals" this was built for —
   a heading swooping in ahead of a carousel, then its cards following one
   after another (with .d1/.d2/.d3 above) — rather than the site's usual
   gentle fade-up. Same opacity/vis contract as plain .rv, just a larger
   scale/travel and a steeper ease-out so it reads as arriving with more
   energy, not just ".rv-scale but bigger" quietly. No bounce/overshoot —
   the snap comes from the curve, not a spring. */
.rv-swoosh:not(.vis){transform:translateY(46px) scale(.88);transition-timing-function:cubic-bezier(.16,1,.3,1)}
.rv-swoosh-lg:not(.vis){transform:translateY(28px) scale(.7);transition-timing-function:cubic-bezier(.16,1,.3,1)}
.rv.d1{transition-delay:var(--motion-stagger-step)}
.rv.d2{transition-delay:calc(var(--motion-stagger-step) * 2)}
.rv.d3{transition-delay:calc(var(--motion-stagger-step) * 3)}

/* PAGE HERO */
/* A slow breathing glow instead of a flat static one — the same radial
   gradient, just gently changing size/strength, so every inner page's
   opening banner (there is one on every page but the home page) has a
   little life to it before anything even scrolls. */
@keyframes phGlow{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.7;transform:scale(1.12)}}
@keyframes spin{to{transform:rotate(360deg)}}
.ph{background:var(--p);padding:clamp(100px,11vw,140px) clamp(14px,4vw,60px) clamp(56px,6vw,80px);position:relative;overflow:hidden}
.ph::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 70% 0,rgba(0,201,167,.15),transparent 55%);animation:phGlow 7s ease-in-out infinite}
.ph .lbl{color:var(--a);animation:fU var(--motion-base) var(--ease-snap) both}
.ph h1{font-size:clamp(36px,5.5vw,72px);color:white;letter-spacing:-2px;margin-bottom:14px;animation:fU var(--motion-base) var(--ease-snap) both}
.ph h1 em{font-style:normal;color:var(--a)}
.ph p{color:rgba(255,255,255,.78);font-size:16px;max-width:540px;line-height:1.65;animation:fIn var(--motion-base) var(--motion-stagger-step) var(--ease-snap) both}

/* A hero with a real photo (a course's own page, or a project's once it has
   one) splits into content + photo. Only applied when a photo exists —
   .ph-content alone, with no .ph-grid on its parent, is just the hero's
   normal block flow, so every other pageHeader on the site is untouched. */
.ph-grid{display:grid;grid-template-columns:1fr auto;align-items:center;gap:clamp(24px,4vw,56px)}
.ph-photo{position:relative;width:clamp(180px,18vw,260px);height:clamp(180px,18vw,260px);flex-shrink:0;justify-self:end;animation:photoFloat 6s ease-in-out infinite}
.ph-photo img{width:100%;height:100%;border-radius:50%;object-fit:cover;position:relative;z-index:1;box-shadow:0 20px 50px rgba(0,0,0,.35)}
.ph-ring{position:absolute;inset:-16%;width:132%;height:132%;color:var(--a);opacity:.65;animation:spin 24s linear infinite}
@media(max-width:760px){
  .ph-grid{grid-template-columns:1fr;gap:24px}
  .ph-photo{justify-self:start;width:140px;height:140px}
}

/* FULL-BLEED PHOTO HERO — shared by course pages and project pages: the
   page's own photo (or a studio fallback, for courses) fills the band and
   the title sits centred over it — just the title, nothing else (Lee had
   the kicker label and a date/price subtitle here and asked for both
   taken off; where/when/what it costs is Practical Info's job, not the
   hero's). Opt-in only — a course page always gets it (courseDetailHtml),
   a generic pageHeader section gets it only with `variant:'full-bleed'`
   set, so every pageHeader without a photo (most of the site) is
   untouched. Courses and projects both add an action band underneath
   (.ch-band, below) — a course's is status-dependent (Apply Now /
   Register Interest / this course has run), a project's is a plain
   link to Courses, since a project itself has nothing to apply to. */
.fb-hero{position:relative;height:clamp(420px,58vw,640px);min-height:420px;overflow:hidden;display:flex;align-items:center;justify-content:center;text-align:center}
/* Sized 12% oversize so the slow scroll-linked drift (site.js, initParallax)
   never reveals an edge — JS sets the actual translateY each frame; this is
   just the headroom it drifts inside of. Static image, so no ambient cost
   when the visitor never scrolls.
   render.js sets transform-origin inline, to the same value as
   object-position: without it the zoom centres on the box's own middle
   rather than the chosen focus point (same class of bug as the radio-tips
   carousel's circle photo, CHANGELOG v4.214 — a focus point pushed toward
   an edge gets zoomed straight back out by a transform centred elsewhere).
   initParallax's own translateY only ever rewrites the transform property
   itself, never transform-origin, so this stays put through every frame of
   scroll. */
.fb-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transform:scale(1.12)}
.fb-hero-ov{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(6,26,34,.2) 0%,rgba(6,26,34,.55) 60%,rgba(6,26,34,.9) 100%)}
.fb-hero-inner{position:relative;z-index:2;width:100%}
.fb-hero h1{font-size:clamp(38px,6.4vw,88px);color:white;letter-spacing:-2px;line-height:1.02;max-width:900px;margin:0 auto;animation:fU var(--motion-base) var(--ease-snap) both}

/* Podcast cover art is always a SQUARE design (title, logos and all laid
   out for a 1:1 canvas) — the plain .fb-hero-img cover-crop built for a
   landscape course/project photo was slicing most of it away, then the
   12% parallax headroom scaled that already-thin sliver up further,
   reading as both cropped AND blurry. Here the full image goes on as a
   blurred backdrop (same element, same parallax JS — just softened and
   darkened further so it reads as texture, not content), with the whole
   un-cropped square shown crisp in front of the title. */
.fb-hero-podcast .fb-hero-img{filter:blur(34px) saturate(1.15) brightness(.65);transform:scale(1.28)}
.fb-hero-art{display:block;width:clamp(120px,18vw,200px);aspect-ratio:1/1;object-fit:cover;border-radius:20px;margin:0 auto 24px;box-shadow:0 24px 60px rgba(6,26,34,.5);animation:fU var(--motion-base) var(--ease-snap) both}
/* Static until clicked — a scroll cue, not a pulsing "look at me" icon. */
.fb-scroll{position:absolute;left:50%;bottom:22px;transform:translateX(-50%);z-index:2;width:34px;height:34px;border-radius:50%;border:1.5px solid rgba(255,255,255,.4);background:transparent;padding:0;cursor:pointer;display:flex;align-items:center;justify-content:center;color:white;transition:background var(--motion-fast)}
.fb-scroll:hover,.fb-scroll:focus-visible{background:rgba(255,255,255,.15)}
@media(max-width:640px){.fb-scroll{display:none}}

/* The "back" pill (to Courses, or to Projects) sits over the top-left of
   the photo, outside the centred title block it used to open. */
.ch-back{position:absolute;top:88px;left:clamp(14px,4vw,60px);z-index:2;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.3);color:white;padding:8px 16px;border-radius:50px;font-size:13px;font-family:'Effra',sans-serif;cursor:pointer;display:inline-flex;align-items:center;gap:6px;backdrop-filter:blur(8px);transition:background .2s}
.ch-back:hover{background:rgba(255,255,255,.2)}
@media(max-width:640px){.ch-back{top:80px}}
.ch-band{background:var(--p);padding:clamp(24px,4vw,34px) clamp(14px,4vw,60px)}
.ch-band-inner{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:20px 32px}
.ch-band-actions{display:flex;gap:12px;flex-wrap:wrap}
.ch-band-funders{display:flex;flex-wrap:wrap;align-items:center;gap:28px}
.ch-band-funders-lbl{color:rgba(255,255,255,.6);font-size:14px}

/* The course and project pages' shared two-column body: the description
   on the left, a sticky info-and-contact sidebar on the right (Practical
   & Criteria Info on a course, a plain Project Info box on a project).
   Was inline grid-template-columns:2fr 1fr with no breakpoint at all, so
   a phone got two half-width columns squeezed side by side instead of
   one stacked column — this is that missing breakpoint. On mobile, the
   sidebar (what a visitor most wants first: dates and price, or a
   project's year) moves above the longer description via `order`, while
   the DOM keeps the description first for anyone reading with a screen
   reader. */
.cd-grid{display:grid;grid-template-columns:2fr 1fr;gap:52px;align-items:start}
/* A grid item's default min-width is auto, which floors it at its content's
   own min-content size — normally invisible, but .cd-main can hold a
   gallery carousel (.crs-track: a flex row of fixed-width cards, deliberately
   NOT wrapping, so it can scroll sideways) whose un-scrolled min-content
   width is the sum of every card. Without this, that width becomes the
   GRID TRACK's own floor, so the 2fr column grows to fit the whole
   carousel instead of its own share — pushing everything else in .cd-main,
   including testimonials, far to the right on any project with a gallery. */
.cd-main{min-width:0}
.cd-side{position:sticky;top:88px;display:flex;flex-direction:column;gap:16px}
@media(max-width:860px){
  .cd-grid{grid-template-columns:1fr;gap:32px}
  .cd-side{position:static;order:-1}
}
/* A project's own "what happened"/testimonials/gallery/audio, nested
   inside .cd-main rather than breaking full-width below the grid (see
   projectDetailHtml's own comment on why). Each still carries the padding
   and .inner width it needs for its normal full-width use elsewhere, so
   both are stripped here — the column itself already supplies the page's
   outer gutter, and an .inner wider than the column does nothing once the
   column is already narrower than 1240px. The !important only overrides
   the inline padding these sections set on themselves; nothing else on
   the page sets inline padding on a bare <section>. */
.cd-main > section{padding:36px 0 0 !important}
.cd-main > section > .inner{padding:0;max-width:none}

/* CTA SECTION */
.cta-sec{background:var(--p);text-align:center;padding:clamp(70px,9vw,120px) clamp(14px,4vw,60px);position:relative;overflow:hidden}
.cta-sec h2{font-size:clamp(34px,5vw,68px);color:white;letter-spacing:-2px;margin-bottom:16px;position:relative;z-index:1}
.cta-sec h2 em{font-style:normal;color:var(--a)}
.cta-sec .rv>p{color:rgba(255,255,255,.72);font-size:16px;max-width:460px;margin:0 auto 32px;line-height:1.65;position:relative;z-index:1}
.cta-note{color:rgba(255,255,255,.72);font-size:12px;margin-top:16px;position:relative;z-index:1}
.cta-btns{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;position:relative;z-index:1}

/* FOOTER */
footer{background:#09475D;padding:52px clamp(14px,4vw,60px) 26px;color:rgba(255,255,255,.72)}
.foot-grid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:48px;margin-bottom:40px}
.foot-brand p{font-size:13px;line-height:1.75;margin-top:12px;max-width:270px}
.foot-tagline{margin-top:16px;font-family:'Effra',sans-serif;font-size:11px;color:var(--a);letter-spacing:1.2px;font-weight:600}
.foot-social{display:flex;gap:10px;margin-top:18px}
.foot-social a{width:34px;height:34px;border-radius:50%;background:rgba(255,255,255,.1);color:rgba(255,255,255,.85);display:flex;align-items:center;justify-content:center;transition:background .2s,color .2s}
.foot-social a:hover{background:var(--s);color:white}
.foot-brand img{height:32px;width:auto;margin-bottom:0}
.foot-col h5{font-size:11px;color:rgba(255,255,255,.75);letter-spacing:.5px;margin-bottom:14px;text-transform:uppercase}
.foot-col ul{list-style:none}
.foot-col ul li{margin-bottom:8px}
.foot-col ul a{color:rgba(255,255,255,.72);font-size:13px;cursor:pointer;transition:color .2s}
.foot-col ul a:hover{color:rgba(255,255,255,.95)}
.foot-btm{border-top:1px solid rgba(255,255,255,.15);padding-top:20px;display:flex;justify-content:space-between;align-items:center;font-size:11px;flex-wrap:wrap;gap:8px}
.foot-links{display:flex;gap:16px}
.foot-links a{color:rgba(255,255,255,.72);font-size:11px;cursor:pointer;transition:color .2s}
.foot-links a:hover{color:rgba(255,255,255,.95)}

/* COURSE CARDS — also Projects and Bespoke Partnerships, which share this
   same class via the generic cards() renderer (render.js's projectCard()
   and bespokePartnershipItems()). One change here reaches all three.
   Lee: cards needed to be "bigger so we can see more of the text", with
   "bigger logos for funders" (done separately, see .cc-funder-logo) and
   a brand-colour border "going round the cards" — picked the mint accent
   over the dark navy option, since it already runs through the FREE tag,
   ticks and chips elsewhere on the card grid, deepening to the teal on
   hover same as before. Shape (rounded corners, taller photo, full
   border) matches .media-card, the podcast cards Lee pointed to as
   already being what these should look like. */
.cc{background:white;border-radius:16px;overflow:hidden;border:1.5px solid var(--a);transition:transform .3s,border-color .3s,box-shadow .3s;display:flex;flex-direction:column;cursor:pointer}
.cc:hover{border-color:var(--s);transform:translateY(-6px);box-shadow:0 12px 32px rgba(9,71,93,.12)}
/* The hover zoom centres on transform-origin, set inline (render.js /
   sections.js) to the same value as object-position, same reasoning as
   .fb-hero-img above — a small zoom, so a wrong centre is subtle here
   rather than the whole subject disappearing, but the fix is the same. */
.cc:hover .cc-img img{transform:scale(1.04)}
.cc-img img{transition:transform .5s var(--ease-soft,ease)}
.cc-img{height:200px;display:flex;align-items:center;justify-content:center;font-size:44px;position:relative;overflow:hidden}
.ci1{background:#09475D}.ci2{background:#008577}.ci3{background:#08374a}.ci4{background:#005f50}.ci5{background:#003d4d}.ci6{background:#007a6a}
.free-tag{position:absolute;top:12px;left:12px;background:var(--a);color:var(--p);padding:4px 12px;border-radius:50px;font-size:10px;font-weight:800;letter-spacing:.5px;line-height:1;box-shadow:0 3px 10px rgba(0,0,0,.18)}
.lvl-tag{position:absolute;top:12px;right:12px;background:rgba(255,255,255,.15);border:1px solid rgba(255,255,255,.3);backdrop-filter:blur(8px);color:white;padding:4px 12px;border-radius:50px;font-size:10px;font-weight:700;line-height:1}
.cc-body{padding:24px;flex:1;display:flex;flex-direction:column}
.cc-meta{display:flex;gap:12px;margin-bottom:10px;flex-wrap:wrap}
.cc-meta span{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--muted);font-weight:500}
.cc h3{font-size:19px;font-weight:500;color:var(--p);margin-bottom:8px;letter-spacing:-.3px}
.cc p{font-size:14px;color:var(--muted);line-height:1.65;flex:1;margin-bottom:18px}
/* The "View Course Details" / "Find out more" / "Listen & watch" button at
   the foot of every course, project and podcast card. Ian: a pill, centred,
   in the mint — the same mint and navy as the FREE tag on the photo above
   it, so the card carries one accent rather than two. Its row takes
   margin-top:auto, which sits it on the bottom edge so a row of cards keeps
   its buttons in line however long each title runs; the padding is the
   least gap it keeps above. On hover it deepens to the teal, same as the
   card's border. */
.cc-cta-row{margin-top:auto;padding-top:16px;display:flex;justify-content:center}
.cc-cta{display:inline-flex;align-items:center;gap:6px;padding:9px 20px;border-radius:50px;background:var(--a);color:var(--p);font-weight:700;font-family:'Effra',sans-serif;font-size:13px;line-height:1;transition:gap .2s,background .2s,color .2s}
.cc:hover .cc-cta,.media-card .cc-cta:hover{background:var(--s);color:white}
/* The funder credit on a course card — their real mark where there is one
   (same pattern as the funders ticker and the course hero band), the name
   in type where there isn't. Lee asked for this bigger once already (28px);
   bumped again to 36px — still well short of crowding the title and CTA
   below it, with more width to grow into for a wide mark. */
.cc-funder{display:flex;align-items:center;gap:8px;margin-bottom:12px;min-height:36px}
.cc-funder-lbl{font-size:10px;color:var(--muted);flex-shrink:0}
.cc-funder-logo{height:36px;width:auto;max-width:190px;object-fit:contain;display:block}
.cc-funder-name{font-size:11px;color:var(--muted);font-weight:600}
.cc:hover .cc-cta{gap:12px}

/* CHIPS (FILTER) */
.chip-bar{display:flex;flex-wrap:wrap;gap:8px}
.chip{padding:6px 15px;border-radius:50px;border:1.5px solid var(--bdr);background:white;font-family:'Effra',sans-serif;font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:all .2s}
.chip.on{background:var(--a);border-color:var(--a);color:var(--p);font-weight:700}
.chip:hover{background:var(--p);border-color:var(--p);color:white}

/* FORM ELEMENTS */
.fg{margin-bottom:16px}
.fg label{display:block;font-size:11px;font-weight:700;color:var(--p);text-transform:uppercase;letter-spacing:.8px;margin-bottom:6px}
.fc{width:100%;padding:12px 14px;border:1.5px solid var(--bdr);border-radius:10px;font-family:'Effra',sans-serif;font-size:14px;color:var(--text);background:white;transition:border-color .2s;outline:none}
.fc:focus{border-color:var(--s)}
textarea.fc{height:90px;resize:vertical}
select.fc{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b8fa0' d='M6 8L1 3h10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center}

/* TESTIMONIAL SLIDER */
.t-slider{position:relative;overflow:hidden;margin-top:32px}
.t-track{display:flex;transition:transform .6s cubic-bezier(.4,0,.2,1)}
/* display:flex + align-items:center here, not on .t-card itself: .t-track's
   own flex row stretches every .t-slide to match the tallest one (so the
   carousel doesn't resize on every transition), and a shorter quote's card
   used to just sit at the top of that taller box with empty space below it
   — Lee: "the smaller one go to the top but I want them centralised". */
.t-slide{min-width:100%;padding:0 4px;display:flex;align-items:center}
.t-dots{display:flex;justify-content:center;gap:8px;margin-top:24px}
.t-dot{width:8px;height:8px;border-radius:50%;background:var(--bdr);cursor:pointer;transition:all .3s}
.t-dot.on{background:var(--a);width:24px;border-radius:4px}
/* A carousel that opted out of auto-advancing (noAuto on quoteCards — the
   radio-tips carousel) gets its own pair of arrows, same .slide-arrow the
   podcast shelf uses. An opaque white circle with its own shadow reads
   against either backdrop this carousel sits on: the plain white card, or
   the gradient full-bleed panel around it. Kept visible on mobile, unlike
   .slide-arrow's usual sitewide rule (below 640px) — this carousel has no
   native-scroll fallback for a visitor without a mouse, so hiding its own
   named navigation there would leave swipe and the dots as the only way
   through it. */
.t-arrows .slide-arrow{background:white;color:var(--p);box-shadow:0 2px 10px rgba(0,0,0,.15);border:1px solid var(--bdr)}
.t-arrows .slide-arrow:hover{background:var(--a);border-color:var(--a)}
@media(max-width:640px){.t-arrows .slide-arrow{display:flex}}
.t-card{background:transparent;border-radius:0;padding:0;border:none;max-width:740px;margin:0 auto;position:relative;text-align:left}
/* Used to carry a giant quote-mark glyph (content:'"') above the text, in
   the brand's own Effra font — which renders a plain straight double-quote
   as two short vertical bars, not a curly typographic one, so it read as
   a pause icon rather than a quote mark. Lee: "why is there a green pause/
   quote marks on the top? Can we get rid of those please?" Removed rather
   than fixed, since that was the ask. */
.t-card p{font-size:clamp(17px,1.9vw,22px);line-height:1.5;color:var(--p);font-style:normal;font-weight:500;letter-spacing:-.3px;margin-bottom:28px}
/* The homepage carousel's own quote, boxed — the shared .t-card above stays
   plain for the full Testimonials page's grid of cards, which already has
   its own rhythm; only the one beside the big photo gets a visible box. */
.t-with-photo .t-card{background:white;border-radius:var(--r);padding:clamp(28px,3.4vw,48px);border:1.5px solid var(--bdr);box-shadow:0 20px 50px rgba(9,71,93,.08);max-width:640px;margin:0}
/* A Course/Project/Podcast's own testimonials — same flat tinted box they
   used stacked one under another before this became a carousel, just one
   at a time now instead of taking up the full height of the page. */
.t-boxed .t-card{background:var(--light);border-radius:16px;padding:32px;max-width:680px;margin:0}
.t-boxed .t-card p{font-size:16px;line-height:1.78;font-style:italic;font-weight:400;letter-spacing:normal;color:var(--text);margin-bottom:18px}
/* Several lead-in tips from one person aren't a single quotation, so the
   giant quote-mark glyph above doesn't fit — it was reading as clutter
   rather than a quote. Shown as a tick list instead (same pattern as the
   course "what you'll learn" checklists), which is also just more
   scannable than a block of lead-in paragraphs for a "here's my advice"
   card. */
.t-card-tips::before{display:none}
.t-card-tips .tp-item{align-items:flex-start}
.t-card-tips .tp-item + .tp-item{margin-top:0}
.t-author{display:flex;align-items:center;gap:14px}
.av{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-family:'Effra',sans-serif;font-weight:800;font-size:16px;color:white;flex-shrink:0;background:var(--p)}
.av img{width:44px;height:44px;border-radius:50%;object-fit:cover}
.av2{background:var(--s)}
.av3{background:#062f3f}
.av4{background:#005f50}
/* The photo beside the testimonials carousel — only present when at least
   one testimonial in it has one (sections.js only puts a testimonial here
   at all if it has a photo). Lee: "I want the picture to fill the whole of
   this red box" — the photo now fills the entire row edge to edge (full-
   bleed, both ways) as a background, with the quote floating over it in
   its own opaque white card so it still reads clearly whatever the photo
   behind it looks like. */
.t-with-photo{position:relative;overflow:hidden;margin-top:32px;min-height:clamp(420px,42vw,560px);padding:32px 0;display:flex;align-items:center;justify-content:center;gap:clamp(20px,3vw,48px)}
.t-photos{position:absolute;inset:0}
/* No photos on file for any item — same moving aurora gradient as the
   Figures band (.stats-bar), so the panel still has life to it instead of
   sitting empty. Swaps for the real photo panel the moment one is added. */
.t-photos-aurora{background:linear-gradient(115deg,var(--p),var(--s),var(--a),var(--s),var(--p));background-size:300% 300%;animation:aurora 14s ease infinite}
.t-photo-slide{position:absolute;inset:0;opacity:0;transition:opacity .6s ease}
.t-photo-slide.on{opacity:1}
.t-photo-slide img{position:relative;z-index:1;width:100%;height:100%;object-fit:cover}
/* A real photo beside the card instead of filling the whole panel — Lee:
   "can I have a circle next to them where I can put a headshot too?",
   drawn on a screenshot as a circle roughly the card's own height, beside
   it rather than behind it. Falls back to a single initial, same idea as
   .av elsewhere, while no photo is on file for that item; swaps to the
   real photo the moment one is added, same crossfade as the background. */
.t-circle-photo{position:relative;z-index:2;flex-shrink:0;width:clamp(180px,20vw,300px);height:clamp(180px,20vw,300px);border-radius:50%;overflow:hidden;box-shadow:0 20px 50px rgba(9,71,93,.18)}
.t-circle-photo .t-photo-slide{display:flex;align-items:center;justify-content:center;background:var(--p)}
.t-circle-photo .t-photo-slide span{font-family:'Effra',sans-serif;font-weight:800;font-size:clamp(48px,6vw,84px);color:white}
@media(max-width:900px){.t-circle-photo{display:none}}
/* The radio-tips carousel's headshots are cut-out PNGs/WEBPs — the subject
   against a transparent background, not a full rectangular photo — so
   object-fit:cover's usual "always fills the box, no gaps" guarantee
   doesn't hold: the transparent margin around the subject shows the
   slide's own dark background through, off-centre and with visible empty
   space around whoever's pictured. Lee: "need white background behind the
   headshots... can we make Vicky centred?" White reads as a normal matte
   instead of a colour clash, and a modest zoom crops the transparent
   margin away on every side, bringing an off-centre subject closer to the
   middle. Scoped to .t-circle-photo-cutout rather than the base
   .t-circle-photo — the shared learner-testimonial carousel uses ordinary
   photographs with no transparency, where this zoom would just be an
   unwanted extra crop.
   transform-origin defaults to the box's own centre (50% 50%), which fought
   a chosen focus point rather than respecting it: object-position moves the
   subject to wherever imageFocus says, then a centre-anchored zoom crops
   evenly off every edge regardless, which for a focus point pushed up near
   the top (to bring a face into frame) cropped that same face straight back
   out. Each image now sets its own transform-origin inline to the same
   value as its object-position (sections.js), so the zoom is centred on the
   chosen focus point instead of the box's geometric middle. */
.t-circle-photo-cutout .t-photo-slide{background:#fff}
.t-circle-photo-cutout .t-photo-slide img{transform:scale(1.3)}
/* The card floats centred over the photo (or gradient) rather than pinned
   to one side — Lee: "I like the styling of all the testimonials but they
   need to be centred in the middle". min-width:0 matters here same as it
   does for .cd-main elsewhere: .t-with-photo is a flex container, and
   .t-track inside .t-slider lays every testimonial out in one non-wrapping
   row (so it can slide between them) — without it, that row's full,
   every-slide-at-once width becomes .t-slider's own content-based floor,
   overriding max-width. No padding on the slider at all, by design:
   overflow:hidden on .t-with-photo clips at .t-slider's own padding box,
   not .t-track's narrower content box, so padding on EITHER side left a
   gap inside that clip boundary the neighbouring slide could show
   through as the track moved — this is what was actually behind "I can
   still see the next card's side coming across". Centring comes from
   .t-with-photo's own justify-content instead, which needs no padding to
   do it. */
.t-with-photo .t-slider{position:relative;z-index:2;margin-top:0;width:100%;max-width:640px;min-width:0}
/* Below this width the card can no longer float legibly over a photo at a
   useful size — it goes back to a modest stacked block. This used to stack
   .t-photos itself above the quote as "a photo, same as any other photo on
   the page" (position:relative, aspect-ratio:4/3), from when .t-photos
   could hold a real one. Both callers now always force the aurora gradient
   class on it (Lee: "always use the gradient, never real photos") — so on
   mobile this was stacking an empty decorative gradient box with nothing
   in it above the quote, for no reason. Lee: "shouldn't it look like
   seeing it on a pc?" .t-photos is purely a desktop full-bleed backdrop
   behind the circle+card; on mobile, where the circle is already hidden
   (900px, above) and the card goes full-width anyway, it has no job left
   to do, so it's hidden rather than given a hollow block of its own. */
@media(max-width:760px){.t-with-photo{display:block;min-height:0;padding:0 clamp(14px,4vw,60px)}.t-photos{display:none}.t-with-photo .t-slider{max-width:none;padding-top:clamp(14px,4vw,60px)}.t-with-photo .t-card{max-width:none}}
.author-name{font-family:'Effra',sans-serif;font-weight:700;font-size:13px;color:var(--p)}
.author-role{font-size:11px;color:var(--muted);margin-top:2px}

/* PODCAST CAROUSEL (HOME) — one podcast at a time: big art one side, its
   description and platform links the other, same shape as the podcast's
   own page. Slides via translateX on .pod-one-track, driven by site.js's
   ONE-AT-A-TIME CAROUSELS (same mechanism the testimonials use below). */
.pod-one{position:relative;overflow:hidden}
.pod-one-track{display:flex;transition:transform .6s cubic-bezier(.4,0,.2,1)}
.pod-one-slide{min-width:100%;display:grid;grid-template-columns:340px 1fr;gap:48px;align-items:center;padding:0 4px}
/* A border and a drop shadow, not just the corner radius — a cover that
   happens to share the band's own dark teal (several do) would otherwise
   have no visible edge against it at all. Works for any artwork colour,
   since the border reads regardless of what's inside it. */
.pod-one-art{width:100%;aspect-ratio:1;border-radius:var(--r);overflow:hidden;position:relative;border:1.5px solid rgba(255,255,255,.3)}
.pod-one-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.pod-one-info h3{font-size:clamp(24px,2.6vw,32px);color:white;margin-bottom:14px;letter-spacing:-.5px}
.pod-one-info p{font-size:16px;color:rgba(255,255,255,.78);line-height:1.7;max-width:520px;margin-bottom:22px}
.pod-one-info p .txt-link{color:var(--a)}
.pod-one-info .chip-bar{margin-bottom:26px}
@media(max-width:760px){.pod-one-slide{grid-template-columns:1fr;gap:24px}.pod-one-art{max-width:280px;margin:0 auto}}
/* The glow pulses on its own box-shadow layer, never transform — so it never
   fights anything else animating on the tile. */
@keyframes playPulse{0%,100%{box-shadow:0 3px 10px rgba(0,0,0,.25),0 0 0 0 rgba(0,201,167,.45)}50%{box-shadow:0 3px 10px rgba(0,0,0,.25),0 0 0 7px rgba(0,201,167,0)}}
.play-c{position:absolute;bottom:14px;right:14px;width:38px;height:38px;background:var(--a);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;color:var(--p);box-shadow:0 3px 10px rgba(0,0,0,.25);animation:playPulse 2.6s ease-in-out infinite}

/* SLIDE ARROWS — shared by the podcast carousel and the course row. Overlaid
   on the track itself (not outside it) so they never depend on the page's
   side padding, and never get clipped on a narrow screen. Faded out by
   site.js when a native-scroll track (the course row) is scrolled all the
   way to that end; the podcast carousel loops, so its arrows stay enabled. */
.slide-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:18px;line-height:1;cursor:pointer;border:none;transition:background .2s,opacity .2s}
.slide-prev{left:6px}
.slide-next{right:6px}
.slide-arrow[disabled]{opacity:0;pointer-events:none}
.pod-one .slide-arrow{background:rgba(9,20,26,.6);color:white;border:1px solid rgba(255,255,255,.25);backdrop-filter:blur(2px)}
.pod-one .slide-arrow:hover{background:var(--a);color:var(--p);border-color:var(--a)}
.cs-slider .slide-arrow{background:white;color:var(--p);box-shadow:0 2px 10px rgba(0,0,0,.15);border:1px solid var(--bdr)}
.cs-slider .slide-arrow:hover{background:var(--a);border-color:var(--a)}
@media(max-width:640px){.slide-arrow{display:none}}

/* PARTNER TICKER */
.ticker-wrap{overflow:hidden;padding:40px 0;background:white;border-top:1px solid var(--bdr);border-bottom:1px solid var(--bdr)}
/* A steady, unbroken drift — ambient background motion, not something the
   visitor interacts with, so it never pauses or eases in a direction. */
.ticker-track{display:flex;gap:0;animation:tickerAnim var(--motion-slow) linear infinite;width:max-content}
.ticker-item{display:flex;align-items:center;padding:0 36px;white-space:nowrap;font-family:'Effra',sans-serif;font-weight:700;font-size:14px;color:var(--p);opacity:.55;transition:opacity .2s;border-right:1px solid var(--bdr);text-decoration:none}
a.ticker-item{cursor:pointer}
.ticker-item:hover{opacity:1}
.ticker-item span{margin-right:10px;font-size:18px}
.ticker-logo-item{padding:0 40px}
.ticker-logo{height:52px;width:auto;max-width:190px;object-fit:contain;filter:grayscale(1);opacity:.7;transition:filter .2s,opacity .2s}
.ticker-item:hover .ticker-logo{filter:grayscale(0);opacity:1}
@keyframes tickerAnim{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}

/* STATS COUNTER */
/* A slow-moving colour wash instead of a flat navy band — the same three
   brand colours, never a hard edge to fade (unlike the CTA glow this site
   already had and removed): the whole band is filled edge to edge at every
   frame, so there's nothing for the section boundary to catch mid-fade. */
@keyframes aurora{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}
.stats-bar{position:relative;overflow:hidden;background:linear-gradient(115deg,var(--p),var(--s),var(--a),var(--s),var(--p));background-size:300% 300%;animation:aurora 14s ease infinite;padding:clamp(36px,5vw,54px) clamp(14px,4vw,60px)}
.stats-grid{position:relative;z-index:1;display:grid;grid-template-columns:repeat(var(--n,4),1fr);max-width:1240px;margin:0 auto;gap:2px}
.s-item{text-align:center;padding:26px 16px}
.s-item+.s-item{border-left:1px solid rgba(255,255,255,.12)}
.s-num{font-family:'Effra',sans-serif;font-weight:800;font-size:clamp(34px,4vw,58px);color:white;letter-spacing:-2px;line-height:1;margin-bottom:5px;font-variant-numeric:tabular-nums}
.s-lbl{font-size:12px;color:rgba(255,255,255,.75)}
/* "Rise and cover": the Figures band stays pinned while the section after
   it scrolls up over the top of it. site.js's initStatsCover() builds this
   wrapper at render time around the band and whichever section follows —
   sticky's own stick-for-how-long is set by its containing block, and the
   two need one in common to get any runway at all. The safety-net
   background on the covering child matters for any page where the section
   after Stats doesn't set its own (a plain prose block, say) — without it
   the band would still show through underneath as it's meant to disappear. */
.stats-cover-wrap{position:relative}
.stats-cover-wrap .stats-bar{position:sticky;top:0;z-index:0}
.stats-cover-wrap>*:last-child{position:relative;z-index:1;background:var(--white)}

/* HERO */
.hero{position:relative;height:100vh;min-height:580px;overflow:hidden;display:flex;align-items:center;justify-content:center}
.hero-bg{position:absolute;inset:0;background:#09475D}
/* Same 12% headroom as .fb-hero-img, for the same reason. */
.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transform:scale(1.12)}

.hero-ov{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(9,71,93,.3) 0%,rgba(9,71,93,.55) 50%,rgba(9,71,93,.88) 100%)}
.hero-content{position:relative;z-index:2;text-align:center;padding:0 20px;max-width:1460px}
/* The headline group (kicker + h1) slides up and fades in together; the
   subtext/CTA group fades in only, one stagger beat later — a confident
   entrance rather than everything arriving in a pile at once. */
.hero-content .lbl{color:var(--a);justify-content:center;animation:fU var(--motion-base) var(--ease-snap) both}
.hero h1{font-size:clamp(44px,8.5vw,106px);color:white;letter-spacing:-2px;line-height:.93;margin-bottom:26px;animation:fU var(--motion-base) var(--ease-snap) both}
/* Above phone width, the headline is one line rather than wrapping
   wherever the words happen to break — a size tied to the viewport
   (not the fixed clamp above) so it keeps fitting as the window
   narrows, down to the point mobile takes over with the original,
   wrap-allowed size. */
@media(min-width:600px){.hero h1{white-space:nowrap;font-size:clamp(32px,6vw,100px)}}
.hero h1 em{font-style:normal;background:linear-gradient(90deg,var(--a),#6eecd8);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.hero-sub{font-size:clamp(14px,1.7vw,18px);color:rgba(255,255,255,.82);max-width:520px;margin:0 auto 36px;line-height:1.65;font-weight:300;animation:fIn var(--motion-base) var(--motion-stagger-step) var(--ease-snap) both}
.hero-acts{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;animation:fIn var(--motion-base) var(--motion-stagger-step) var(--ease-snap) both}
@keyframes fU{from{opacity:0;transform:translateY(60px)}to{opacity:1;transform:none}}
@keyframes fIn{from{opacity:0}to{opacity:1}}


/* STORY */
.story-wrap{background:var(--light);border-radius:var(--r);margin:0 clamp(8px,2vw,36px);padding:clamp(48px,7vw,86px) clamp(32px,5vw,80px)}
.story-grid{display:grid;grid-template-columns:1fr 1fr;gap:72px;align-items:center}
.story-vis{border-radius:18px;overflow:hidden;aspect-ratio:4/3;background:var(--p);display:flex;align-items:center;justify-content:center;position:relative;animation:photoFloat 6s ease-in-out infinite}
.story-vis::before{content:'';position:absolute;width:200px;height:200px;border:56px solid rgba(0,201,167,.1);border-radius:50%;top:-56px;right:-56px}
.story-vis::after{content:'';position:absolute;width:100px;height:100px;background:rgba(0,201,167,.08);border-radius:50%;bottom:16px;left:16px}
.story-vis-inner{text-align:center;color:white;position:relative;z-index:1}
.big-icon{font-size:68px;margin-bottom:12px;display:block}
.story-vis-inner p{font-family:'Effra',sans-serif;font-weight:700;font-size:16px;opacity:.6}
.take-parts{display:flex;flex-direction:column;gap:10px;margin-top:22px}
.tp-item{display:flex;align-items:flex-start;gap:11px;font-size:15px;color:var(--text);line-height:1.6}
.tp-item::before{content:'✓';width:20px;height:20px;background:var(--s);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;color:white;font-weight:700;flex-shrink:0;margin-top:2px;transition:transform .3s var(--ease-soft)}
/* A playful nudge on hover — the point itself lifts a touch and its
   checkmark gives a little spin, rather than nothing happening at all
   until the next one. Cheap, reversible, and only for people who can
   point a mouse at it (a tap has nowhere to "hover" back from). */
.tp-item{transition:transform .3s var(--ease-soft)}
@media(hover:hover){.tp-item:hover{transform:translateX(3px)}.tp-item:hover::before{transform:rotate(14deg) scale(1.15)}}

/* BENTO — words on one side, one plain photo on the other, in its own
   full-bleed light band. Same story-grid two-column shape split() uses
   below. Upright rather than landscape (6/7, not the site's usual 4/3) —
   matched against a reference where the photo reads as a modest upright
   rectangle beside the text, not a wide frame stretching to match the
   text column's own height. */
@keyframes photoFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-14px)}}
.bento-photo-big{position:relative;border-radius:18px;overflow:hidden;aspect-ratio:6/7;animation:photoFloat 6s ease-in-out infinite;box-shadow:0 30px 50px rgba(9,71,93,.18)}
.bento-photo-big img{width:100%;height:100%;object-fit:cover;object-position:center 80%}
/* The checkmark points, in their own row under the photo/words pair,
   rather than inside the text column — two columns on desktop, one on
   the narrow layout the whole story-grid collapses to at the same
   breakpoint (960px, see .story-grid's own media query). */
.chk-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px 48px;margin-top:56px;padding-top:36px;border-top:1px solid var(--bdr)}
/* Lee: the ticks under the homepage's "About the Academy" section (the
   only place .chk-grid is used) needed to read bigger — scoped here
   rather than on .tp-item itself, which the Work With Us card and a
   course's "what you'll walk away with" list also use at their own,
   smaller size. */
.chk-grid .tp-item{gap:14px;font-size:17px;line-height:1.65}
.chk-grid .tp-item::before{width:26px;height:26px;font-size:13px}
@media(max-width:960px){.chk-grid{grid-template-columns:1fr;margin-top:36px}}
/* Each point arrives on its own beat (sections.js gives every .chk-grid
   .tp-item the usual .rv + .d1-.d4 stagger, see the stats band's own
   comment for that pattern) rather than the whole grid fading up as one
   flat block — and its checkmark gets a livelier entrance than a plain
   fade: a spin-and-overshoot "stamp", not the sitewide .rv's deliberately
   bounce-free ease. Scoped to .chk-grid's own ticks, not every .tp-item
   site-wide (the Work With Us card and course "what you'll walk away
   with" list keep the plain mark — this is the one place "funky" was
   asked for). tpPop runs off the item's own .vis, so it's naturally tied
   to the same reveal rather than a second timer to keep in sync. */
.chk-grid .tp-item:not(.vis)::before{opacity:0;transform:scale(0) rotate(-45deg)}
.chk-grid .tp-item.vis::before{animation:tpPop .55s var(--motion-stagger-step) cubic-bezier(.34,1.56,.64,1) both}
@keyframes tpPop{0%{opacity:0;transform:scale(0) rotate(-45deg)}55%{opacity:1;transform:scale(1.3) rotate(10deg)}100%{opacity:1;transform:scale(1) rotate(0)}}

/* The intro line reads as alternating weight/colour rather than a flat
   paragraph — a light italic clause into a bold, on-brand one, same
   **bold**/*italic* markup every body paragraph already accepts, just
   rendered differently in this one spot (see .course-overview above for
   the same scoped-override approach). */
.bento-blurb{font-size:19px;line-height:1.7;color:var(--muted);max-width:760px}
.bento-blurb em{font-style:italic;font-weight:400;color:var(--muted)}
.bento-blurb strong{font-style:normal;font-weight:800;color:var(--p)}

/* PROJECT CARD COLOURS — the tint behind a project's photo on its .cc-img
   card (same pbX classes the admin's Card colour field picks from). The
   dark icon-panel card these used to colour (.prj-card etc) is gone; every
   project card is a real photo now, same as Current Courses. */
.pb1{background:#09475D}.pb2{background:#008577}.pb3{background:#062f3f}.pb4{background:#005f50}.pb5{background:#003d4d}.pb6{background:#006a58}

/* PDF CARDS */
.pdf-card{background:white;border-radius:14px;border:1.5px solid var(--bdr);padding:24px;display:flex;align-items:center;gap:16px;cursor:pointer;transition:all .2s}
.pdf-card:hover{border-color:var(--s);box-shadow:0 8px 24px rgba(0,133,119,.12);transform:translateY(-2px)}
.pdf-icon{width:48px;height:48px;border-radius:12px;background:var(--p);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0}
.pdf-info h4{font-size:15px;color:var(--p);margin-bottom:4px}
.pdf-info p{font-size:12px;color:var(--muted)}
.pdf-dl{margin-left:auto;color:var(--s-text);font-size:18px}
/* A document card led by a picture of its own cover/first page, instead of
   the generic icon row above — same card shape and hover lift, laid out as
   a column so the image can run full-width at the top. */
.pdf-card-img-wrap{background:white;border-radius:14px;border:1.5px solid var(--bdr);overflow:hidden;cursor:pointer;transition:all .2s;display:block;text-decoration:none}
.pdf-card-img-wrap:hover{border-color:var(--s);box-shadow:0 8px 24px rgba(0,133,119,.12);transform:translateY(-2px)}
.pdf-card-img{width:100%;aspect-ratio:16/9;object-fit:cover;display:block}
.pdf-card-img-info{padding:18px 24px;display:flex;align-items:center;gap:16px}
.pdf-card-img-info h4{font-size:15px;color:var(--p);margin-bottom:4px}
.pdf-card-img-info p{font-size:12px;color:var(--muted)}

/* WORK RADIO CARDS */
.radio-co{background:white;border-radius:14px;border:1.5px solid var(--bdr);padding:20px;display:flex;align-items:center;gap:14px;cursor:pointer;transition:all .2s;text-decoration:none}
.radio-co:hover{border-color:var(--s);box-shadow:0 6px 20px rgba(0,133,119,.1);transform:translateY(-2px)}
.radio-co-logo{width:60px;height:40px;border-radius:8px;background:var(--light);display:flex;align-items:center;justify-content:center;font-family:'Effra',sans-serif;font-weight:800;font-size:11px;color:var(--p);flex-shrink:0;text-align:center;padding:4px}
.radio-co-info h4{font-size:14px;color:var(--p);margin-bottom:3px}
.radio-co-info p{font-size:12px;color:var(--muted);line-height:1.5}
.radio-co-arr{margin-left:auto;color:var(--s-text);font-size:14px}

/* FAQ */
.faq-item{border-bottom:1px solid var(--bdr)}
.faq-q{display:flex;justify-content:space-between;align-items:center;padding:18px 0;cursor:pointer;font-family:'Effra',sans-serif;font-weight:700;font-size:16px;color:var(--p);gap:16px}
.faq-q .ico{font-size:12px;color:var(--s-text);transition:transform .3s;flex-shrink:0}
.faq-item.open .faq-q .ico{transform:rotate(180deg)}
.faq-a{display:none;padding:0 0 18px;font-size:15px;color:var(--muted);line-height:1.75}
.faq-item.open .faq-a{display:block}

/* VOLUNTEER REASONS — also Previous Courses' "flagship" role breakdown,
   the only other live user of the features() section type (featureRow(),
   .vol-r). Lee: the "bread and butter" cards there needed to be "more
   exciting and appealing" — bumped the border to the same mint accent
   .cc picked up, and the text a size up, rather than inventing a new
   component for one section. */
.vol-r{display:flex;align-items:flex-start;gap:14px;padding:22px;background:white;border-radius:14px;border:1.5px solid var(--a)}
.vol-ico{width:48px;height:48px;border-radius:12px;background:var(--s);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
.vol-r h4{font-size:16px;color:var(--p);margin-bottom:4px}
.vol-r p{font-size:13px;color:var(--muted);line-height:1.6}

/* TEAM */
.team-card{background:var(--light);border-radius:16px;padding:24px;display:flex;align-items:center;gap:18px}
.team-av{width:96px;height:96px;border-radius:50%;background:var(--p);display:flex;align-items:center;justify-content:center;font-family:'Effra',sans-serif;font-weight:800;font-size:30px;color:white;flex-shrink:0}
.team-av img{width:96px;height:96px;border-radius:50%;object-fit:cover}
.team-info h4{font-size:16px;color:var(--p);margin-bottom:2px}
.team-info .role{font-size:13px;color:var(--s-text);font-weight:600;margin-bottom:2px}
.team-info .pronouns{font-size:11px;color:var(--muted)}

/* WORK-WITH-US */
.wwu-card{background:white;border-radius:18px;border:1.5px solid var(--bdr);padding:28px;transition:box-shadow .3s,border-color .3s}
.wwu-card:hover{border-color:rgba(0,133,119,.3);box-shadow:0 12px 32px rgba(9,71,93,.09)}
.wwu-icon{width:52px;height:52px;border-radius:14px;background:var(--p);display:flex;align-items:center;justify-content:center;font-size:22px;margin-bottom:16px}
.wwu-card h3{font-size:18px;color:var(--p);margin-bottom:8px;letter-spacing:-.3px}
.wwu-card p{font-size:14px;color:var(--muted);line-height:1.65}
.wwu-card .take-parts{margin-top:14px;gap:8px}
.wwu-card .tp-item{font-size:14px;color:var(--muted)}
/* numbered steps (sections.js `steps`): the same row as a feature, with the number where the icon goes */
.steps{list-style:none;padding:0;margin:28px 0 0;display:flex;flex-direction:column;gap:14px}
.step{display:flex;align-items:flex-start;gap:16px;padding:20px;background:white;border-radius:14px;border:1.5px solid var(--bdr)}
.step-n{width:42px;height:42px;border-radius:50%;background:var(--s);color:white;font-family:'Effra',sans-serif;font-weight:800;font-size:17px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.step h4{font-size:16px;color:var(--p);margin-bottom:4px}
.step p{font-size:14px;color:var(--muted);line-height:1.65}

/* ALUMNI PAGE */
.alum-card{background:white;border-radius:18px;padding:28px;border:1.5px solid var(--bdr);position:relative;transition:box-shadow .3s;display:flex;flex-direction:column}
.alum-card::before{content:'"';position:absolute;top:16px;right:18px;font-family:'Effra',sans-serif;font-size:58px;color:var(--a);opacity:.1;line-height:1}
.alum-card p{font-size:14px;line-height:1.78;color:var(--text);font-style:italic;margin-bottom:20px;flex:1}
.alum-card:hover{box-shadow:0 12px 32px rgba(9,71,93,.09)}
.circle-av{width:56px;height:56px;border-radius:50%;background:var(--p);display:flex;align-items:center;justify-content:center;font-family:'Effra',sans-serif;font-weight:800;font-size:18px;color:white;border:3px solid var(--s)}
.read-more-btn{color:var(--s-text);font-weight:700;font-size:13px;font-family:'Effra',sans-serif;cursor:pointer;background:none;border:none;display:inline-flex;align-items:center;gap:6px;transition:gap .2s;margin-top:12px;padding:0}
.read-more-btn:hover{gap:12px}

/* NEWSLETTER */
.nl-box{background:var(--p);border-radius:18px;padding:32px;color:white}
.nl-box h3{font-size:20px;margin-bottom:10px;letter-spacing:-.4px}
.nl-box p{color:rgba(255,255,255,.75);font-size:14px;margin-bottom:20px;line-height:1.6}
.nl-row{display:flex;gap:10px;flex-wrap:wrap}
.nl-row input{flex:1;padding:12px 14px;border-radius:10px;border:none;font-family:'Effra',sans-serif;font-size:14px;min-width:160px}

/* STUDIO IMAGES PLACEHOLDER */
.studio-img{border-radius:16px;overflow:hidden;background:var(--p);aspect-ratio:16/10;display:flex;align-items:center;justify-content:center;font-size:60px;position:relative}
.studio-img::before{content:'';position:absolute;inset:0;background:rgba(9,71,93,.2)}
.studio-caption{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(to top,rgba(9,71,93,.8),transparent);padding:16px;color:white;font-family:'Effra',sans-serif;font-weight:700;font-size:14px}

/* KEEP UPDATED B2B */
.tab-btns{display:flex;gap:0;background:var(--light);border-radius:12px;padding:4px;margin-bottom:28px;width:fit-content}
.tab-btn{padding:10px 22px;border-radius:10px;border:none;background:transparent;font-family:'Effra',sans-serif;font-weight:700;font-size:13px;color:var(--muted);cursor:pointer;transition:all .2s}
.tab-btn.on{background:white;color:var(--p);box-shadow:0 2px 8px rgba(0,0,0,.08)}

/* RESPONSIVE */
@media(max-width:960px){.nav-links{display:none}.hamburger{display:flex}.story-grid,.vol-grid,.connect-grid{grid-template-columns:1fr;gap:36px}.stats-grid{grid-template-columns:repeat(2,1fr)}.s-item:nth-child(odd){border-left:none}.foot-grid{grid-template-columns:1fr 1fr;gap:28px}}
@media(max-width:640px){.stats-grid{grid-template-columns:1fr 1fr}.foot-grid{grid-template-columns:1fr;gap:22px}.ph h1{letter-spacing:-1.5px}}
/* ══════════════════════════════════════════════════════════════════════════
   ADDITIONS TO THE MOCKUP

   Everything above this line is the approved mockup's CSS, unchanged. What
   follows covers the markup that changed on the way out of the single file:
   real links where there were click handlers, real forms where there were
   alert() calls, and a visible focus ring now that the whole site can be
   driven from the keyboard.
   ══════════════════════════════════════════════════════════════════════════ */

/* The logo and the course cards became links; the hamburger became a button.
   None of them should look any different for it. */
a.nav-logo{text-decoration:none}
a.cc{color:inherit;text-decoration:none}
button.hamburger{background:none;border:none;font:inherit;color:inherit}
.has-dropdown>a{cursor:pointer}

/* Keyboard focus. The mockup had none: every control was a div or an <a> with
   no href, so nothing could be tabbed to in the first place. */
:focus-visible{outline:3px solid var(--a);outline-offset:2px;border-radius:4px}
nav :focus-visible,footer :focus-visible,.hero :focus-visible,.ph :focus-visible,
.cta-sec :focus-visible{outline-color:var(--a)}

/* Skip link — first stop for a keyboard or screen-reader visitor. */
.skip{position:absolute;left:-9999px;top:0;z-index:2000;background:var(--p);color:white;
  padding:12px 20px;border-radius:0 0 10px 0;font-weight:700;font-size:14px}
.skip:focus{left:0}

/* Visually hidden, still read out. */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Honeypot: a field no person sees and no person fills in. */
.hp{position:absolute!important;left:-9999px!important;width:1px!important;height:1px!important;
  opacity:0!important;pointer-events:none}

/* Cards that carry their own information and go nowhere. The mockup gave these
   a pointer and an alert() saying "coming soon"; they now simply sit there. */
.static-card{cursor:default}
.static-card:hover{border-color:var(--bdr);box-shadow:none;transform:none}
.pdf-soon{font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--muted);background:var(--light);border-radius:50px;padding:5px 12px}

/* Contact page social links (was a repeated inline style plus two JS hover
   handlers). */
.social-row{display:flex;align-items:center;gap:10px;padding:12px 16px;background:white;
  border-radius:10px;border:1.5px solid var(--bdr);color:var(--p);font-weight:600;
  font-size:14px;transition:border-color .2s}
.social-row:hover{border-color:var(--s)}
.social-ico{flex-shrink:0}

/* Form feedback. Empty until the server has actually answered. */
.form-msg{margin-top:12px;font-size:13.5px;line-height:1.6}
.form-msg:empty{margin-top:0}
.form-msg.ok{color:var(--s-text);font-weight:600}
.form-msg.bad{color:#b3261e;font-weight:600}
.nl-row .form-msg{flex-basis:100%;color:white}
.nl-row .form-msg.ok{color:var(--a)}
.nl-row .form-msg.bad{color:#ffd0cc}
.enq button[type=submit][disabled]{opacity:.6;cursor:progress;transform:none;box-shadow:none}
.fc:invalid:not(:placeholder-shown){border-color:#b3261e}

/* Beacon-embedded forms. The application and volunteering forms are Beacon's,
   shown in place — see assets/js/beacon-forms.js. */
a.btn,a.btn-out,a.btn-ghost{text-decoration:none}
.beacon-frame{position:relative;background:var(--white);border:1.5px solid var(--bdr);
  border-radius:16px;overflow:hidden}
.beacon-frame iframe{display:block;width:100%;height:1180px;border:0}
.beacon-alt{margin-top:12px;font-size:13px;color:var(--muted);line-height:1.6}
.beacon-alt a{color:var(--s-text);font-weight:600}
.beacon-empty{background:var(--white);border:1.5px dashed var(--bdr);border-radius:16px;padding:28px}
.beacon-empty h4{font-family:'Effra',sans-serif;font-weight:900;font-size:17px;color:var(--p);
  margin-bottom:10px;letter-spacing:-.3px}
.beacon-empty p{font-size:14px;color:var(--muted);line-height:1.7}
.beacon-empty a{color:var(--s-text);font-weight:600}
@media(max-width:760px){.beacon-frame iframe{height:1400px}}

/* Layout classes for the section library. The mockup carried these as inline
   styles on one-off elements; they are classes now so assets/js/sections.js can
   name them instead of repeating a style string. Values are the mockup's. */
.cc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:24px}
/* The home page's course shelf: the same cards as the Courses page grid,
   in a native horizontally-scrolling row — the arrows (site.js, SLIDERS)
   nudge it by one card, and a trackpad or a finger scrolls it directly.
   One real set of cards; a native scroll container needs no fixed count
   for the number of current courses to drift out of step with. */
.cs-slider{position:relative;margin-top:28px}
/* overflow-x:auto forces the browser to compute overflow-y as auto too
   (a scroll container can't be "auto" one way and "visible" the other) —
   so this box clips, not just scrolls, anything a card renders outside
   its own layout box. .cc's hover state lifts the card 6px and now also
   adds a soft shadow (the mint-border redesign), both of which need real
   headroom above and below or they get a hard flat edge cut into them —
   Lee: "the course cards are being cut off at the top". 4px wasn't
   enough even for the lift alone. */
.cs-track{display:flex;gap:24px;overflow-x:auto;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;padding:24px 2px}
.cs-track::-webkit-scrollbar{display:none}
.cs-track .cc{min-width:300px;max-width:300px;flex-shrink:0;scroll-snap-align:start}

/* A past course's own photo gallery — same native-scroll-plus-arrows
   mechanism as the podcast shelf and home course row above (site.js
   slideBy()), just narrower cards sized for a photo rather than a card. */
.crs-slider{position:relative;margin-top:16px}
.crs-track{display:flex;gap:16px;overflow-x:auto;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;padding:4px 2px}
.crs-track::-webkit-scrollbar{display:none}
.crs-item{min-width:280px;max-width:280px;flex-shrink:0;scroll-snap-align:start;border-radius:14px;overflow:hidden;background:var(--light)}
.crs-item img{width:100%;height:190px;object-fit:cover;display:block}
.crs-cap{padding:10px 12px;font-size:13px;color:var(--muted)}
.crs-slider .slide-arrow{background:white;color:var(--p);box-shadow:0 2px 10px rgba(0,0,0,.15);border:1px solid var(--bdr)}
.crs-slider .slide-arrow:hover{background:var(--light)}

/* A past course's own audio clips — up to 5, each its own card. */
.course-audio-card{background:var(--light);border-radius:16px;padding:20px}
.course-audio-card + .course-audio-card{margin-top:14px}
.course-audio-card h4{font-size:15px;color:var(--p);margin-bottom:4px;letter-spacing:-.2px}
.course-audio-card p{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:12px}
.course-audio-card audio{width:100%;display:block}

.radio-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px}
.course-filters{background:white;border-bottom:1.5px solid var(--bdr);
  padding:0 clamp(14px,4vw,60px);position:sticky;top:68px;z-index:500}
.filter-lbl{font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:1px}
.txt-link{color:var(--s-text);font-weight:600}

.no-results{grid-column:1/-1;text-align:center;padding:48px 20px;color:var(--muted);font-size:15px}

/* Respect a request for less movement. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .rv{opacity:1!important;transform:none!important}
}

/* ── SUPPORT AND PROJECT PAGES ──────────────────────────────────────────────
   Three section types added 2026-09-07 with the /life/ pages and the project
   pages: an urgent notice, a directory of organisations, and a plain list of
   pages. All three use the tokens above rather than new colours.             */

/* The emergency notice. Deliberately the loudest thing on the page: somebody
   reading it may be in trouble and should not have to hunt for the number. */
.notice-sec{padding:clamp(28px,4vw,44px) clamp(14px,4vw,60px) 0}
.notice{background:#fff5f4;border:1.5px solid #f3c9c4;border-left:5px solid #c0392b;
  border-radius:14px;padding:clamp(18px,2.6vw,26px)}
.notice-hd{font-size:14px;letter-spacing:.09em;text-transform:uppercase;color:#a5301f;margin-bottom:10px}
.notice p{color:var(--text);font-size:16px;line-height:1.65}
.notice p+p{margin-top:9px}
.notice a{color:#a5301f;text-decoration:underline;text-underline-offset:2px}

/* A directory of organisations. A list, not cards: these are read top to
   bottom by somebody looking for one specific thing. */
.dir-sec{padding:clamp(26px,3.5vw,44px) clamp(14px,4vw,60px) var(--gap)}
.dir-list{list-style:none;display:flex;flex-direction:column;gap:14px}
/* Capped to roughly the width of its own text (.dir-text's own 70ch cap,
   plus padding and room for a link pill or two) — full-bleed on its
   wide .dir-list container left a lot of entries as a card that was
   mostly blank background to the right of two short lines of text,
   especially next to the narrower copy in the two-column layout above
   it on a project page. */
.dir-item{background:var(--light);border:1.5px solid var(--bdr);border-radius:16px;
  padding:clamp(18px,2.4vw,24px);transition:border-color .25s,box-shadow .25s;max-width:760px}
.dir-item:hover{border-color:rgba(0,133,119,.35);box-shadow:0 10px 30px rgba(9,71,93,.07)}
.dir-name{font-size:clamp(18px,2.1vw,21px);color:var(--p);margin-bottom:7px}
.dir-text{color:var(--text);font-size:15.5px;line-height:1.7;max-width:70ch}
.dir-links{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.dir-links a{display:inline-flex;align-items:baseline;gap:7px;background:white;
  border:1.5px solid var(--bdr);border-radius:50px;padding:7px 15px;font-size:13.5px;
  transition:border-color .2s,background .2s;max-width:100%}
.dir-links a:hover{border-color:var(--s);background:#f2fbf9}
.dir-link-lbl{font-weight:700;color:var(--s-text);white-space:nowrap}
.dir-link-val{color:var(--muted);overflow-wrap:anywhere}

/* A list of pages: the support index, and every project we have run. */
.pl-sec{padding:clamp(26px,3.5vw,44px) clamp(14px,4vw,60px) var(--gap)}
.pl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:16px}
.pl-item{display:flex;flex-direction:column;background:white;border:1.5px solid var(--bdr);
  border-radius:16px;padding:clamp(18px,2.2vw,24px);transition:transform .3s,box-shadow .3s,border-color .3s}
.pl-item:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(9,71,93,.1);border-color:rgba(0,133,119,.3)}
.pl-meta{font-size:11px;font-weight:700;letter-spacing:.08em;color:var(--s-text);margin-bottom:8px}
.pl-title{font-size:clamp(17px,1.9vw,20px);color:var(--p);line-height:1.22;margin-bottom:8px}
.pl-text{color:var(--muted);font-size:14.5px;line-height:1.6;flex:1}
.pl-cta{margin-top:14px;font-size:13px;font-weight:700;color:var(--s-text)}

@media(max-width:640px){
  .dir-links a{width:100%}
  .pl-grid{grid-template-columns:1fr}
}

/* ═══ SECTIONS THAT USED TO BE HAND-WRITTEN MARKUP ═══════════════════════════
   Fourteen blocks on this site were raw HTML held in the content, which meant
   the styling was typed out again in every one of them and nobody could edit
   the words without editing markup. They are proper section types now; these
   are the styles those types need, moved out of the content and into the one
   place a look belongs. */

/* Two columns — About, Contact, Keep Updated, Work With Us, Volunteer.
   The ratio arrives as --cols so this can override it: written straight into
   the element's style attribute, as it was before, `1fr 1fr` held all the way
   down to a phone and no media query could reach it. */
.col-grid{display:grid;grid-template-columns:var(--cols,1fr 1fr);gap:var(--col-gap,48px);align-items:start}
@media(max-width:860px){.col-grid{grid-template-columns:1fr;gap:36px}}

.panel-box{background:var(--light);border-radius:18px;padding:32px}
.panel-box-sm{border-radius:16px;padding:24px}
.panel-hd{font-size:20px;color:var(--p);margin-bottom:22px;letter-spacing:-.4px}
.panel-hd-sm{font-size:18px;margin-bottom:16px;letter-spacing:-.3px}
.panel-note{font-size:13px;color:var(--muted);margin-top:16px;line-height:1.6}
.panel-features{display:flex;flex-direction:column;gap:14px;margin-top:28px}
.panel-images{display:flex;flex-direction:column;gap:14px}
/* A picture inside the boxed split. The type has always taken an `image`,
   but every page using one wrote the positioning inline, so the rule was
   never needed until the home page stopped being raw markup: without it the
   photo renders at its natural size and pushes the whole page sideways. */
.story-vis img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

.panel-images .studio-img{overflow:hidden}
.panel-images .studio-img img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}
.social-list{display:flex;flex-direction:column;gap:10px}
.nl-btn{padding:12px 20px;font-size:14px}

/* A button that fills its column — a form's submit, a link in a grid of them. */
.btn-wide{width:100%;justify-content:center}
.btn-grid{display:grid;gap:14px;margin-top:24px}

/* The centred callout: Projects' "check back soon", the FAQ's "still got a
   question?". */
.cl-panel{background:var(--light);border-radius:16px;padding:32px;text-align:center;margin-top:24px}
.cl-icon{font-size:36px;margin-bottom:12px}
.cl-head{font-size:20px;color:var(--p);margin-bottom:8px;letter-spacing:-.3px}
.cl-text{font-size:14px;color:var(--muted);line-height:1.65}
.cl-acts{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:20px}

/* Podcast cards: artwork, then the words under it. */
.media-card{background:white;border:1.5px solid var(--bdr);border-radius:16px;overflow:hidden;display:flex;flex-direction:column;transition:box-shadow .3s,border-color .3s}
.media-card:hover{border-color:rgba(0,133,119,.3);box-shadow:0 12px 32px rgba(9,71,93,.09)}
/* Square, not a fixed 200px band: every podcast cover is a 1:1 design (see
   .fb-hero-podcast above), and a wide crop of a square sliced its bottom
   third off — Lee: "the card artwork cuts off". object-fit:cover still
   covers a non-square image sensibly if one is ever used here. */
.media-art{aspect-ratio:1/1;overflow:hidden;position:relative}
.media-art img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}
.media-body{padding:24px;flex:1;display:flex;flex-direction:column}
.media-body h3{font-size:18px;color:var(--p);margin-bottom:8px;letter-spacing:-.3px}
.media-body p{font-size:14px;color:var(--muted);line-height:1.65;margin-bottom:18px}
/* The listening platforms are labels by default, not buttons — a series that
   is not out yet has nowhere to send anyone, and a button that does nothing
   when pressed is worse than a label that never asked to be. A tag with a
   real link (.chip-link) is a real button again, restoring the hover a plain
   label deliberately loses. */
.media-body .chip{cursor:default}
.media-body .chip:hover{background:white;border-color:var(--bdr);color:var(--muted)}
.media-body .chip-link{cursor:pointer;text-decoration:none;display:inline-flex;align-items:center}
.media-body .chip-link:hover{background:var(--p);border-color:var(--p);color:white}
.chip img{height:16px;width:auto;display:block}

/* Alumni cards: who said it, then what they said. */
.story-who{display:flex;align-items:center;gap:12px;margin-bottom:18px}

/* The team. */
.team-bio{font-size:13px;color:var(--muted);margin-top:8px;line-height:1.6}

/* A quote card that names its source, and one that links onward. */
.q-source{font-family:'Effra',sans-serif;font-weight:700;font-size:14px;color:var(--s-text);margin-bottom:12px}
.q-more{display:inline-flex;align-items:center;gap:6px;color:var(--s-text);font-weight:700;font-size:13px;font-family:'Effra',sans-serif;margin-top:14px;transition:gap .2s}
.q-more:hover{gap:12px}

/* A section heading that sits in the middle rather than at the left. */
.sec-centre{text-align:center}
.sec-centre .lbl{justify-content:center}
.sec-centre .ttl{margin:0 auto;text-align:center}
.sec-centre .btn,.sec-centre .btn-out,.sec-centre .btn-ghost{display:inline-flex}

/* The podcast shelf on the home page. */
.pod-sec{background:var(--p);padding:var(--gap) 0}
.pod-head{display:flex;align-items:flex-end;justify-content:space-between;flex-wrap:wrap;gap:16px}
.lbl-a{color:var(--a)}
.ttl-inv{color:white}
.ttl-inv em{color:var(--a)}
.pod-card .pod-art{position:relative;overflow:hidden}
.pod-card .pod-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.pod-card .play-c{position:absolute;bottom:8px;right:8px;z-index:1}

/* The funders. */
.ticker-sec{padding:40px 0}

/* ═══ THE ICON SET ═══════════════════════════════════════════════════════════
   The emoji are gone; see assets/js/icons.js for why and for the set itself.
   Everything an icon needs to sit correctly is here, because the containers
   below were all built to hold a GLYPH — they set a `font-size` and centred a
   character in a box. An SVG ignores font-size, so each one now says how big
   its icon is instead.

   `currentColor` does the rest: an icon is whatever colour the thing around it
   is, so a white icon on the teal tile and a teal icon on a white card are the
   same markup with no variant classes. */
.icn{display:block;width:24px;height:24px;flex-shrink:0;
  stroke:currentColor;fill:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}

/* The boxed icons: a coloured tile with the icon centred in it. */
.wwu-icon .icn{width:26px;height:26px;color:#fff}
.vol-ico .icn{width:24px;height:24px;color:#fff}
.pdf-icon .icn{width:23px;height:23px;color:#fff}
.cl-icon{display:flex;justify-content:center;margin-bottom:14px}
.cl-icon .icn{width:34px;height:34px;color:var(--s-text)}

/* The download chevron on a document row, and the arrow on a station card. */
.pdf-dl .icn,.radio-co-arr .icn{width:19px;height:19px}
.pdf-dl{display:flex;align-items:center}

/* Beside a line of type — a location, a date, a price. Sized to the text it
   sits with and nudged onto its baseline, because an icon that is the same
   height as its line box always looks a shade too big next to it. */
.cc-meta-item{display:inline-flex;align-items:center;gap:5px}
.cc-meta-item .icn{width:13px;height:13px;color:var(--s-text);stroke-width:1.75}

.pi-row{display:flex;align-items:center;gap:9px;font-size:14px;color:var(--text)}
.pi-ico{display:flex;color:var(--s-text)}
.pi-ico .icn{width:16px;height:16px;stroke-width:1.75}

/* The play badge on a podcast tile. */
.play-c .icn{width:9px;height:9px;stroke-width:2;margin-left:1px;
  fill:currentColor;stroke:currentColor}

/* An icon standing in for a social platform we have no brand mark for. */
.social-row .icn{width:17px;height:17px;color:var(--s-text)}

/* The map card's pin, which sits beside a wrapping address. */
.pi-map .icn,.map-addr .icn{width:15px;height:15px;flex-shrink:0}

/* The funder row is wordmarks now, not emoji-plus-name, so the old gap
   between the two has nothing left to separate. */
.ticker-item span{margin-right:0}
