/* ============================================================
   HP AI Academy — home.css (HOMEPAGE ONLY)
   Hero, pyramid, streams, programme cards, impact, faculty.
   Loaded by index.html after css/styles.css.
   ============================================================ */
/* ============================================================
   HERO — 45/55 split
   Copy on a clean white left 45%; the photograph occupies the
   right 55% behind an angled seam that echoes the brand
   parallelogram. Nothing overlays the picture, so there is no
   scrim washing the children out, and cropping to the right half
   means the 800px-wide source covers about half the area it used
   to — roughly doubling its effective sharpness.
   ============================================================ */
.hero {
  position: relative; overflow: hidden;
  background: var(--white); color: var(--black);
  min-height: clamp(520px, 76vh, 780px);
  display: flex; align-items: center;
}

/* --- The photograph, right 55% only --- */
.hero__photo {
  position: absolute; top: 0; bottom: 0; right: 0; left: 45%;
  z-index: 0;
  /* Angled seam: top edge starts further right than the bottom, so the
     diagonal leans like the HP parallelogram. */
  clip-path: polygon(14% 0, 100% 0, 100% 100%, 0 100%);
}
.hero__photo img {
  width: 100%; height: 100%; object-fit: cover;
  /* Hold the boys' faces in the visible half. */
  object-position: 42% 34%;
}

/* --- Copy, on the clean white left --- */
/* .hero__inner also carries .container (max-width + auto margins); the
   hero needs it pinned left inside the page gutter, not centred. */
.hero__inner {
  position: relative; z-index: 1;
  width: 100%; max-width: var(--maxw); margin: 0 auto;
}
/* Stay clear of the angled seam. The photo starts at 45vw but .container
   is centred inside --maxw, so on wide screens the copy column begins
   further right than the gutter — subtract that offset rather than
   assuming the two share an origin. */
.hero__copy {
  max-width: min(560px, calc(45vw - (100vw - min(100vw, var(--maxw))) / 2 - 56px));
}
/* The wordmark comes down a step and the tagline goes up a step, so the
   two lines end close to level without the tagline growing large enough
   to wrap. It must stay on ONE line — matching the widths exactly pushed
   "Shape AI." onto a second row. */
/* Both stay on ONE line each. The copy column is only ~45vw now, so the
   sizes are tuned to that width rather than the full viewport. */
.hero__wordmark {
  font-size: clamp(34px, 4.4vw, 62px); font-weight: 700; line-height: 1.04;
  letter-spacing: -.01em; color: var(--ink); margin: 0 0 .12em;
  white-space: nowrap;
}
.hero__tagline {
  font-size: clamp(19px, 2.42vw, 34px); font-weight: 700; line-height: 1.12;
  letter-spacing: -.012em; color: var(--coral); margin: 0 0 26px;
  white-space: nowrap;
}
.hero__kicker { font-size: 15px; font-weight: 500; color: var(--gray); margin: 0 0 10px; }
.hero__lede {
  font-size: clamp(16px, 1.5vw, 18px); color: #3A3A42;
  max-width: 54ch; margin-bottom: 28px;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: 14px; margin: 0; }
/* On phones the two CTAs stack; give them equal (full) width so their
   left AND right edges line up instead of sizing to their text. */
@media (max-width: 720px) {
  .hero__cta { flex-direction: column; align-items: stretch; }
  .hero__cta .btn { width: 100%; text-align: center; }
}

/* Above ~1700px the copy column stops growing (it is capped by --maxw)
   but 45vw keeps marching right, so the nowrap tagline — which cannot
   shrink — reaches past the seam. Pin the seam in pixels there. */
@media (min-width: 1700px) {
  .hero__photo { left: 920px; }
}

@media (max-width: 1024px) {
  /* Give the copy a little more room as the viewport narrows. */
  .hero__photo { left: 50%; clip-path: polygon(11% 0, 100% 0, 100% 100%, 0 100%); }
  .hero__copy { max-width: 45vw; }
}

@media (max-width: 760px) {
  /* Side by side stops working here — stack instead: photo as a band on
     top, copy beneath on white. No scrim needed either way. */
  /* Breathing room under the sticky nav — the photo previously sat
     flush against it (0px gap). */
  .hero {
    min-height: 0; display: block; padding: 28px 0 60px;
  }
  .hero__photo {
    position: relative; left: auto; right: auto; top: auto; bottom: auto;
    display: block; width: 100%; height: clamp(220px, 46vw, 320px);
    margin-bottom: 40px; clip-path: none;
  }
  .hero__photo img { object-position: 50% 28%; }
  .hero__copy { max-width: none; }
  .hero__lede { max-width: none; }
}

/* ---------- Stats strip ---------- */
/* Dividers come from a 1px gap showing the container's line colour
   through, not from per-cell borders. That way the grid can reflow to
   any column count — 4, 3, 2 or 1 — and every cell still reads
   identically with no doubled or missing edges. */
.facts {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--line);
  background: var(--line); gap: 1px;
}
.stat { text-align: center; padding: 34px 8px; background: var(--white); }
.stat strong { display: block; font-size: 46px; font-weight: 700; line-height: 1; color: var(--accent); }
.stat span { font-size: 12px; text-transform: uppercase; letter-spacing: 2px; color: var(--gray); }

/* ---------- Section banner (brochure photo across a section top) ---------- */
.sec-banner {
  position: relative; overflow: hidden;
  height: clamp(180px, 26vw, 320px); margin-bottom: clamp(38px, 5vw, 64px);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 8% 100%);
}
.sec-banner img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- Programme media figures ---------- */
/* Equal-width columns whose ROWS do not stretch: each figure is its own
   fixed 3:2 window, so mixed-ratio source photos all crop to the same
   shape instead of the tallest one dictating the row height. */
.prog-media {
  display: grid;
  /* auto-fill/auto-fit leaves phantom 0px tracks here, so size the
     columns from the item count instead. */
  grid-template-columns: repeat(var(--cols, 2), 1fr);
  align-items: start;
  gap: 22px; margin-top: 40px;
}
.prog-media:has(> :nth-child(3)) { --cols: 3; }
.prog-media__fig {
  margin: 0; position: relative; overflow: hidden;
  /* The window, not the image. Wider ratio in 3-up so the shorter
     column still reads as a proper photograph rather than a strip. */
  aspect-ratio: 3 / 2;
}
.prog-media:has(> :nth-child(3)) .prog-media__fig { aspect-ratio: 4 / 3; }
.prog-media__fig img {
  width: 100%; height: 100%;    /* fill the window; height:100% beats the
                                   global `img { height:auto }` */
  object-fit: cover; display: block;
  transition: transform .9s var(--ease);
}
.prog-media__fig:hover img { transform: scale(1.05); }
.prog-media__fig figcaption {
  position: absolute; left: 0; bottom: 0; right: 0;
  background: var(--black); color: var(--white);
  font-size: 11.5px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase;
  padding: 9px 16px;
  /* Long labels must not push past the figure at narrow widths */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- Pyramid ---------- */
/* The pyramid is the whole section — it needs far less breathing room
   below it than a text section does, and the padding was landing
   asymmetrically (172px under vs 127px over at 1440px). */
/* The pyramid carries its own visual margin, so this section stays
   tighter than the 124px rhythm — but closer to it than before, and
   symmetric top/bottom rather than 72/43. */
/* The pyramid sits tighter than a standard section — it already carries
   its own internal air. Scaled with .section so the rhythm holds. */
#programmes { padding-top: clamp(48px, 4.5vw, 64px); padding-bottom: clamp(48px, 4.5vw, 64px); }
/* The pyramid is the main visual of the page — let it fill the column. */
.pyramid-wrap { position: relative; max-width: 1240px; margin: 0 auto; }
.pyramid-svg { width: 100%; height: auto; display: block; }
/* Reference SVG values, not the shared tokens. */
.py-apex { fill: #3d3d3d; }
.py-band { fill: #c7c7c7; }
/* Black bars under each row, and the thin rule splitting paired
   segments — both present in the brochure. */
.py-sep  { fill: #000; }
/* White 2px divider between paired programmes (a <line> in the
   reference, so it needs stroke rather than fill). */
/* non-scaling-stroke keeps the 2px divider at 2 device px however far the
   SVG scales down. Without it the stroke scales with the viewBox and lands
   at ~0.4px on a 390px phone — antialiased into a grey smudge. */
.py-rule { stroke: #fff; stroke-width: 2; fill: none; vector-effect: non-scaling-stroke; }

.py-seg { cursor: pointer; transition: filter .2s var(--ease), opacity .2s; }
.py-seg:hover .py-fill, .py-seg:focus-visible .py-fill, .py-seg.is-active .py-fill { filter: brightness(1.14); }
.py-seg:hover, .py-seg:focus-visible { outline: none; }
.py-seg .py-fill { transition: filter .2s var(--ease); }

/* Colours taken verbatim from the reference SVG. main.js also sets a
   fill attribute from the data module; these rules take precedence. */
.py-fill--shape { fill: #1747d9 !important; }
.py-fill--lead  { fill: #ff5054 !important; }
.py-fill--learn { fill: #5b899b !important; }

/* Seam fix: the coloured blocks, black shadows, grey platforms and base
   are separate abutting polygons; when the SVG is scaled down the browser
   leaves a 1px anti-aliasing hairline along shared edges (most visible at
   HP Cambridge). Giving each shape a hairline stroke equal to its own fill
   paints over that seam. Geometry is unchanged. */
.py-apex, .py-band, .py-sep, .py-base, .py-fill { stroke-width: 1.2px; shape-rendering: geometricPrecision; }
.py-apex { stroke: #3d3d3d; }
.py-band { stroke: #c7c7c7; }
.py-sep  { stroke: #000; }
.py-base { stroke: #1747d9; }
.py-fill--shape { stroke: #1747d9; }
.py-fill--lead  { stroke: #ff5054; }
.py-fill--learn { stroke: #5b899b; }

.py-label   { font-family: var(--font); font-weight: 700; fill: #fff; }
.py-sub     { font-family: var(--font); font-weight: 400; font-style: italic; fill: #fff; }
.py-tier    { font-family: var(--font); font-weight: 700; fill: #000; letter-spacing: 0; }
.py-side    { font-family: var(--font); font-weight: 700; fill: #000; }
/* Bubble accent follows the tier colour */
.py-bubble--shape .py-bubble__tier { color: var(--shape); }
.py-bubble--lead  .py-bubble__tier { color: var(--coral-ink); }
.py-bubble--learn .py-bubble__tier { color: var(--learn); }

/* Bubble / popover */
.py-bubble {
  position: absolute; z-index: 20; width: min(360px, 88vw);
  background: var(--white); border: 1px solid var(--line);
  box-shadow: 0 24px 60px -12px rgba(10,15,40,.25);
  padding: 22px 24px; opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}
.py-bubble.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
.py-bubble::before { content: ""; position: absolute; top: -7px; left: var(--arrow-x, 32px); width: 12px; height: 12px; background: var(--white); border-left: 1px solid var(--line); border-top: 1px solid var(--line); transform: rotate(45deg); }
.py-bubble .eyebrow { margin-bottom: 6px; font-size: 11px; }
.py-bubble h4 { margin: 0 0 6px; font-size: 19px; font-weight: 700; }
.py-bubble p { font-size: 14.5px; margin: 0 0 10px; }
.py-bubble .py-bubble__meta { display: inline-block; font-size: 12px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--gray-2); margin-bottom: 4px; }
.py-bubble a.py-bubble__link { font-weight: 700; font-size: 14px; color: var(--accent); }
.py-bubble a.py-bubble__link::after { content: " →"; }
.py-bubble .py-bubble__soon { font-size: 13px; color: var(--gray-2); font-style: italic; }
.py-bubble__close { position: absolute; top: 8px; right: 10px; border: 0; background: none; font-size: 20px; line-height: 1; cursor: pointer; color: var(--gray-2); padding: 4px; }
.py-bubble__close:hover { color: var(--black); }

.pyramid-hint { text-align: center; font-size: 19.2px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--gray); margin-top: 18px; }

/* ---------- Streams (Learn AI) ---------- */
.streams { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.stream { background: var(--white); border: 1px solid var(--line); border-top: 4px solid var(--accent); padding: 0 0 24px; display: flex; flex-direction: column; transition: transform .25s var(--ease), box-shadow .25s var(--ease); }
.stream:hover { transform: translateY(-6px); box-shadow: 0 24px 48px -18px rgba(10,15,40,.18); }
.stream__media { display: block; overflow: hidden; height: 150px; background: var(--bg-soft); }
.stream__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .9s var(--ease); }
.stream:hover .stream__media img { transform: scale(1.05); }
.stream__head { background: var(--accent); color: var(--white); padding: 16px 22px; }
.stream__head h3 { color: var(--white); margin: 0; font-size: 19px; letter-spacing: .3px; text-transform: uppercase; }
.stream__meta { padding: 14px 22px 0; font-size: 12.5px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--gray-2); }
.stream__tagline { padding: 10px 22px 0; margin: 0; font-size: 14.5px; font-style: italic; color: var(--gray); }
.stream ul { list-style: none; margin: 10px 0 0; padding: 0 22px; flex: 1; }
.stream li { padding: 11px 0; border-bottom: 1px solid var(--line); font-size: 15px; font-weight: 500; color: #222; }
.stream li:last-child { border-bottom: 0; }
.stream__foot { padding: 16px 22px 0; }
.stream__foot .py-bubble__soon { font-size: 13px; }

/* ---------- Programme tiers overview ---------- */
.tiers {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px;
  /* eyebrow / heading / body — shared by every card via subgrid */
  grid-template-rows: auto auto 1fr;
}
/* Each card shares one row track per element, so the eyebrow, the
   heading and the body copy line up across all three even though the
   eyebrows differ in length (one line for Shape, two for the others). */
.tier {
  border: 1px solid var(--line); background: var(--white); padding: 28px;
  position: relative; overflow: hidden;
  display: grid; grid-template-rows: subgrid; grid-row: span 3;
}
@supports not (grid-template-rows: subgrid) {
  /* Fallback: reserve two lines for the eyebrow so the headings still
     start at the same y. */
  .tier { display: block; }
  .tier .tier__kind { min-height: 2.6em; }
}
.tier::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px; }
.tier--learn::before { background: var(--learn); }
.tier--lead::before  { background: var(--lead); }
.tier--shape::before { background: var(--shape); }
.tier h3 { font-size: 26px; margin: 0 0 .3em; }
.tier .tier__kind { font-size: 12px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--gray-2); display: block; margin: 0 0 14px; }
.tier p { font-size: 15px; margin: 0; }

/* ---------- Faculty ---------- */
.faculty-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 22px 18px; }
.fac { text-align: center; }
.fac__avatar { width: 92px; height: 92px; margin: 0 auto 12px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 26px; color: var(--white); background: linear-gradient(135deg, var(--accent), #0096D6); border: 3px solid var(--white); box-shadow: 0 0 0 1px var(--line), 0 10px 24px -10px rgba(10,15,40,.35); overflow: hidden; }
.fac__avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.fac:nth-child(3n+2) .fac__avatar { background: linear-gradient(135deg, #F4694E, #C2472F); }
.fac:nth-child(3n)   .fac__avatar { background: linear-gradient(135deg, #45718C, #27455A); }
.fac strong { display: block; font-size: 14.5px; line-height: 1.25; }
.fac span { display: block; font-size: 12.5px; color: var(--gray); font-style: italic; margin-top: 3px; }

/* ---------- CTA band ---------- */
.cta-band { text-align: center; }
.cta-band h2 { max-width: 20ch; margin: 0 auto .4em; }
/* Two balanced lines, no full stop. The break is explicit rather than
   left to wrapping, so it reads the same at every width. */
.cta-band__title { max-width: none; }
.cta-band__line2 { display: block; }
.cta-band p { max-width: 58ch; margin: 0 auto 1.6em; }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }
.cta-band .eyebrow { color: var(--coral-ink); }

/* ---------- Webflow-style section rhythm (REDESIGN §7) ----------
   Desktop rhythm tightened per the client review: the old max of 124px
   put 248px of dead space between adjacent sections. 88px caps the
   combined gap at 176px, which still reads as a clear section break.
   The mobile floor stays at 64px — small screens were never the problem
   and cutting further would crowd the headings. */
.section { padding: clamp(64px, 6.5vw, 88px) 0; }
#programmes, #shape, #lead, #learn, #impact, #faculty { scroll-margin-top: 76px; }
#home, #academy, #cta { scroll-margin-top: 76px; }

/* The academy lede must set in two lines, not three. The global .lede
   caps at 62ch (~707px) while its container offers 820px; using the full
   width fits the sentence in two at the existing 19px, so nothing shrinks.
   Scoped to #academy — the generic .lede measure is right elsewhere. */
#academy .sec-open .lede { max-width: 100%; }

/* ---------- Programme cards (rich) ---------- */
.prog-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; margin-top: 44px; }
.prog { background: var(--white); border: 1px solid var(--line); padding: 30px 30px 26px; position: relative; overflow: hidden; transition: transform .25s var(--ease), box-shadow .25s var(--ease); }
.prog:hover { transform: translateY(-5px); box-shadow: 0 26px 52px -20px rgba(10,15,40,.2); }
.prog::before { content: ""; position: absolute; top: 0; left: 0; bottom: 0; width: 4px; background: var(--accent); }
.prog--lead::before { background: var(--lead); }
.prog--shape::before { background: var(--shape); }
.prog--learn::before { background: var(--learn); }
.prog h3 { font-size: 24px; margin-bottom: 2px; }
.prog .prog__tag { display: block; font-size: 13px; font-weight: 700; color: var(--accent); margin-bottom: 12px; }
.prog--lead .prog__tag { color: #D24A2F; }
.prog--learn .prog__tag { color: #35617C; }
.prog p { font-size: 15px; }
.prog__dur { position: absolute; top: 26px; right: 26px; font-size: 11.5px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--gray-2); border: 1px solid var(--line); padding: 5px 10px; }

/* ---------- Fact chips ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.chip { border: 1px solid var(--line); background: var(--bg-soft); padding: 6px 12px; font-size: 12px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase; color: #333; }
.chip b { color: var(--accent); }

/* ---------- Impact band (dark, big numbers) ---------- */
.impact { display: grid; grid-template-columns: repeat(4, 1fr); gap: 28px; margin-top: 12px; }
.impact__item { border-top: 2px solid rgba(255,255,255,.18); padding-top: 22px; }
.impact__item strong { display: block; font-size: clamp(44px, 5vw, 68px); font-weight: 700; line-height: 1; color: var(--white); letter-spacing: -.02em; }
.impact__item strong em { font-style: normal; color: #7EA4FF; }
.impact__item span { display: block; margin-top: 10px; font-size: 13px; letter-spacing: 1.5px; text-transform: uppercase; color: #9aa0ad; }

/* ---------- Quote / photo band ---------- */
.photo-band { position: relative; color: var(--white); padding: 140px 0; background-size: cover; background-position: center 30%; }
/* Background set here, not inline (CODE-REVIEW L1).
   Portrait source in a full-width band: anchor right so the teacher
   stays in frame while the quote sits over the classroom on the left. */
.photo-band--nova {
  background-image: url("../assets/images/site/nova-teacher.jpg");
  background-position: right 8%;
}
.photo-band::before { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(8,10,20,.88) 0%, rgba(8,10,20,.55) 55%, rgba(8,10,20,.25) 100%); }
.photo-band .container { position: relative; }
.photo-band blockquote { margin: 0; max-width: 720px; font-size: clamp(24px, 3.4vw, 40px); font-weight: 700; line-height: 1.2; color: var(--white); text-wrap: balance; }
.photo-band cite { display: block; margin-top: 22px; font-style: normal; font-size: 14px; letter-spacing: 2px; text-transform: uppercase; color: #B8C2D8; }

/* ---------- Endorsement / logos strip ---------- */
.endorse { display: flex; flex-wrap: wrap; gap: 10px 28px; align-items: baseline; margin-top: 18px; }
.endorse span { font-size: 14px; font-weight: 500; color: var(--gray); }
.endorse span::before { content: "◆"; color: var(--accent); font-size: 9px; margin-right: 8px; vertical-align: 2px; }

/* ---------- Scroll reveal ---------- */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: .12s; }
.reveal[data-delay="2"] { transition-delay: .24s; }
.reveal[data-delay="3"] { transition-delay: .36s; }

/* ---------- Responsive (home) ---------- */
@media (max-width: 980px) {
  .streams, .tiers { grid-template-columns: 1fr 1fr; }
  .prog-grid { grid-template-columns: 1fr; }
  .impact { grid-template-columns: 1fr 1fr; }
  .faculty-grid { grid-template-columns: repeat(4, 1fr); }
  .facts { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  /* Keep the top padding set at 760px — it is the gap under the sticky
     nav. Only the bottom tightens here. */
  .hero { padding: 28px 0 56px; }
  .streams, .tiers { grid-template-columns: 1fr; }
  .faculty-grid { grid-template-columns: repeat(3, 1fr); }
  .photo-band { padding: 96px 0; }
  .sec-banner { height: 160px; clip-path: none; }
  /* Hint runs larger on desktop (19.2px) but smaller on phones, where the
     uppercase tracking would otherwise crowd the narrow column. */
  .pyramid-hint { font-size: 12.8px; }
}

/* Programme media: 3-up -> 2-up -> stacked. Three columns at phone
   width would leave ~100px thumbnails with truncated captions, so
   stack rather than shrink. */
@media (max-width: 900px) {
  .prog-media:has(> :nth-child(3)) { --cols: 2; }
  .prog-media:has(> :nth-child(3)) .prog-media__fig { aspect-ratio: 3 / 2; }
}
@media (max-width: 620px) {
  .prog-media,
  .prog-media:has(> :nth-child(3)) { --cols: 1; }
  .prog-media__fig,
  .prog-media:has(> :nth-child(3)) .prog-media__fig { aspect-ratio: 16 / 9; }
}
@media (max-width: 480px) {
  .faculty-grid { grid-template-columns: repeat(2, 1fr); }
  .facts { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   2026-07-29 REVIEW — brochure-faithful sections
   Big coral "Shape AI." / "Lead AI." / "Learn AI." headers with a
   rule; one consistent photo card for every programme; pyramid base.
   ============================================================ */

/* ---------- 3-up ecosystem stats ---------- */
.facts--3 { grid-template-columns: repeat(3, 1fr); }

/* ---------- Section header (brochure style) ---------- */
.sec-head { margin-bottom: clamp(34px, 5vw, 56px); }
.sec-title {
  /* Baseline, not centre: in the brochure the rule sits on the text's
     baseline rather than running through the middle of the letters. */
  display: flex; align-items: baseline; gap: 16px;
  font-size: clamp(40px, 6vw, 72px); font-weight: 700; line-height: 1;
  letter-spacing: -.02em; margin: 0 0 8px;
}
/* The rule that trails the title. In the brochure it is BLACK against
   the red heading and sits ON the baseline — level with the full stop
   after "Lead AI." The -0.16em lift used before floated it well above
   that. align-self:baseline puts the box bottom on the baseline, so the
   rule only needs pulling up by its own 4px height. */
.sec-title::after {
  content: ""; flex: 1; height: 4px; background: var(--black);
  align-self: baseline; position: relative; top: -4px;
}
/* All three section headings are Orange Bloom (#FF5050) in the
   brochure — they are not tinted per tier. */
.sec-title--shape,
.sec-title--lead,
.sec-title--learn { color: var(--lead); }
.sec-sub { font-size: clamp(18px, 2.4vw, 26px); font-weight: 700; color: var(--ink); margin: 0; }

/* ---------- One programme card, every tier ---------- */
.pcards { display: grid; gap: 26px; }
.pcards--2 { grid-template-columns: 1fr 1fr; }
.pcards--3 { grid-template-columns: repeat(3, 1fr); }

.pcard {
  background: var(--white); border: 1px solid var(--line); border-top: 4px solid var(--accent);
  display: flex; flex-direction: column; overflow: hidden;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.pcard:hover { transform: translateY(-5px); box-shadow: 0 26px 52px -20px rgba(10,15,40,.2); }
.pcard--shape { border-top-color: var(--shape); }
.pcard--lead  { border-top-color: var(--lead); }
.pcard--learn { border-top-color: var(--learn); }

.pcard__media { display: block; overflow: hidden; aspect-ratio: 16 / 10; background: var(--bg-soft); }
.pcard__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .9s var(--ease); }
.pcard:hover .pcard__media img { transform: scale(1.04); }

.pcard__body { padding: 24px 26px 28px; display: flex; flex-direction: column; flex: 1; }
.pcard__title { font-size: 22px; line-height: 1.12; margin: 0 0 4px; color: var(--accent); }
/* Two authored break variants; display:none keeps the unused one out of
   the accessibility tree so the heading is announced once. */
.pcard__title-narrow { display: none; }
.pcard__title a { color: var(--accent); }
.pcard__title a:hover { text-decoration: underline; }
.pcard__tag { font-size: 14px; font-weight: 700; color: var(--ink); margin: 0 0 12px; }
/* Paragraphs are separated as in the brochure; the last one carries no
   trailing space so the card bottom stays tight. */
.pcard__desc { font-size: 14.5px; color: var(--gray); margin: 0 0 .85em; }
.pcard__desc:last-child { margin-bottom: 0; }

/* ---------- Card CTA ----------
   margin-top:auto pushes the button to the card foot, so buttons line up
   across a row even though the brochure copy runs to different lengths.
   Cards are grid items stretched to the tallest in the row, so the card
   grows to fit the CTA — no fixed height needed. */
.pcard__cta { margin: auto 0 0; padding-top: 22px; }
.pcard__btn { display: inline-flex; align-items: center; gap: 8px; }
.pcard__btn-arrow { transition: transform .2s var(--ease); }
/* Arrow nudges on hover of the whole card, reinforcing that the card
   itself is the target — not just the button. */
.pcard:hover .pcard__btn-arrow { transform: translateX(3px); }

/* The whole card reads as clickable: cursor, a lifted border, and the
   button filling in. :focus-within keeps keyboard parity with :hover. */
.pcard { cursor: pointer; }
.pcard:hover, .pcard:focus-within { border-color: var(--gray-2); }
.pcard:hover .pcard__title a, .pcard:focus-within .pcard__title a { text-decoration: underline; }
.pcard:hover .pcard__btn { background: var(--white); color: var(--black); }

/* sr-only: off-screen but reachable by assistive tech. */
.u-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- Pyramid base band ---------- */
.py-base { fill: #1747d9; }
.py-base-label { font-family: var(--font); font-weight: 700; fill: #fff; letter-spacing: .3px; }

@media (max-width: 900px) {
  .pcards--3 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) {
  .pcards--2, .pcards--3 { grid-template-columns: 1fr; }
  .facts--3 { grid-template-columns: 1fr; }
  .sec-title { gap: 14px; }
}

/* ---------- Card heading: narrow-column variant ----------
   Keyed to the CARD's own width, not the viewport: the same card is wide
   at 1440 (3-up), cramped at 800 (2-up) and wide again below 620 (1-up),
   so a viewport query would need two disjoint ranges and would still
   break if the grid changed.

   The UCL desktop line 1 needs ~453px of text plus 52px padding, so the
   wide break only holds above a ~505px card. Below that, switch to the
   earlier break; below a 380px card the type also drops to 18px, which
   is what clears both lines on a 360px phone. Engines without container
   queries fall back to the wide variant — correct copy, old wrap. */
.pcard { container-type: inline-size; container-name: pcard; }

@container pcard (max-width: 505px) {
  .pcard__title-wide { display: none; }
  .pcard__title-narrow { display: inline; }
}
@container pcard (max-width: 380px) {
  .pcard__title { font-size: 18px; }
}
