/* ============================================================
 * MODULAR BANDS — the Monzo pattern, site-wide (5 Aug 2026)
 *
 * LOADED LAST ON EVERY PAGE, and it has to be. The section tints are declared in
 * gsap-trial.css, product-v3.css, onsite-v2.css and school-types.css, all of
 * which load after home-v2.css — so the same rules living there lost on both load
 * order and specificity (`.hv2 .band--blog` is 0,2,0 against a bare class). A
 * separate last-loaded sheet wins on order without a specificity arms race.
 *
 * WHAT MONZO ACTUALLY DOES, measured on monzo.com at 1440x900, 5 Aug 2026:
 *   - NO full-bleed coloured areas anywhere. I checked every element whose width
 *     equals the viewport and paints a background: the list came back empty.
 *   - Section backgrounds: 6 white, 7 transparent (so white), 4 on a tint, 3 dark.
 *     That tint is #F2F8F3 — about 1.5% off pure white, which is why Rebecca read
 *     the whole page as white.
 *   - Their real colour is in SIX cards, none full-bleed: the hero, three dark
 *     panels, one red card and the footer. 24px inset, 64px radius.
 *
 * SO THE RULE IS:
 *   1. Every section background is WHITE. No tints, no washes.
 *   2. Colour survives only in DARK cards — inset 24px, 64px radius.
 *
 * ⚠ THIS RETIRES TWO RULES IN CLAUDE.md, which still carries both:
 *   - "No flat seams: every section boundary has one element crossing it."
 *     Cards cannot be crossed, so the seam overlaps are flattened below.
 *   - "Colour-block sections: pages read as a rhythm of full-width colour
 *     washes... no two adjacent sections sharing a background." With every
 *     section white there is no rhythm to hold; the dark cards carry it instead.
 * ============================================================ */

:root {
  /* ⚠ 64px, MEASURED off monzo.com/current-account/personal (the page Rebecca
     linked) at 1440: their hero card is 1312 wide in a 1440 window, i.e. 64px
     each side, radius 64. Ours was 24 — the cards ran much closer to the screen
     edge than theirs. "we should be doing number one across site."
     One token, so every carded band on every page moves together. */
  /* ⚠ THE INSET CAN NEVER EXCEED THE PAGE'S OWN TEXT INSET, or the card's edge
     ends up further in than the words beside it and the two can never line up.
     Measured at 1200px: a flat 64px put module headings at 64 while everything
     else sat at 32 — unalignable, because you cannot give a container negative
     padding.
     So it is derived, not fixed: the page's effective text inset is
     (viewport − container cap) ÷ 2 + the container's own padding, i.e.
     (100vw − 1280px)/2 + 32px. Capped at Monzo's 64 and floored at 16 for phones.
       1440 → 112 → 64 (Monzo's number, which is the point of the exercise)
       1344 → 64  → 64
       1280 → 32  → 32
       1200 → −8  → 16
     Below the cap the card tucks in as the page does, and everything stays in
     line without a single hard-coded breakpoint. */
  --band-inset: clamp(16px, calc((100vw - 1280px) / 2 + 32px), 64px);
  /* the widest any card, hero or content column ever gets — her rule from 3 Aug,
     previously only obeyed by the heroes. See the wide-screen note below. */
  --page-cap: 1500px;
  --band-seam: 24px;                  /* card-to-card gap DOWN the page */
  --band-radius: 64px;                /* Monzo's */
}

/* THE PAGE ITSELF. gsap-trial.css sets `body.hv2 { background: #F7F6F3 }` — the
   home page's whole page background is the warm off-white, which made it the
   single biggest non-white surface on the site. Monzo's page background is pure
   white. This is the change that actually delivers "only white backgrounds";
   the section rules below were being read against a tinted page. */
body.hv2 { background: #fff; }

/* ---------- 1. every section tint becomes white ---------- */
/* Every selector carries body.hv2 (0,2,1) on purpose. gsap-trial.css declares
   `.hv2 .band--sky, .hv2 .band--price, .hv2 .band--blog { background: #F7F6F3 }`
   at 0,2,0 — a bare class here loses to that no matter how late this file loads,
   which is exactly what happened on the first attempt: every page went white
   except the home page. */
body.hv2 .band--sky, body.hv2 .band--quote, body.hv2 .band--light, body.hv2 .band--price,
body.hv2 .band--blog, body.hv2 .band--readmore, body.hv2 .band--mtx,
body.hv2 .ml-faqs, body.hv2 .os-says, body.hv2 .os-ml, body.hv2 .pcband,
/* .dm-steps and Founders Club's .band--light are modules now — see below */
body.hv2 .ph-support, body.hv2 .pol-hero, body.hv2 .st-lineup, body.hv2 .st-proof,
body.hv2 .ab2-benefits, body.hv2 .ab2-jobs--close,
body.hv2 .bp-trust, body.hv2 .auth-wrap, body.hv2 .trust2,
body.hv2 .pv3-acc, body.hv2 .pv3-appall, body.hv2 .pv3-benefits,
body.hv2 .pv3-chapters, body.hv2 .pv3-feat, body.hv2 .pv3-parents,
body.hv2 .pv3-voice, body.hv2 .pv3-steps, body.hv2 .os-mods, body.hv2 .os-trust,
body.hv2 .os-used, body.hv2 .os-mis {
  background: #fff;
  /* deliberately NOT cards. A card on a white section is an invisible box whose
     only effect is to inset the content — which is why Monzo's white sections
     are not cards either. */
  margin-inline: 0;
  border-radius: 0;
}

/* ---------- 2. dark bands are the cards ----------
 * Our equivalent of Monzo's six coloured cards, and now the only place colour
 * appears at section scale. */
/* .band--quote was here and has been removed (5 Aug): the home testimonial is a
   plain white section now, not a card. See the note on .band--quote in
   home-v2.css — four surfaces have been tried and dropped for that one quote. */
body.hv2 .band--blue, body.hv2 .band--navy,
body.hv2 .band--mlviolet, body.hv2 .pv3-switch, body.hv2 .pp-band {
  margin-inline: var(--band-inset);
  border-radius: var(--band-radius);
  overflow: hidden;
}

/* ---------- 2a. NEUTRAL MODULES ----------
 * Monzo's modules come in two flavours, not one: DARK cards and a neutral
 * near-white card. Their neutral is #F2F8F3 — 4.2% off pure white. Rebecca asked
 * for the equivalent in our own palette, so this uses the brand's cool near-white
 * --ge-bg-light #F3F7FA, which is 3.3% off white: on-brand with the navy/sky
 * family, and a shade subtler than theirs.
 * Add `band--module` to any section that should read as a distinct panel rather
 * than as part of the white page. Use it sparingly — the whole point of the white
 * page is that a module means something.
 * Must come AFTER rule 1, which sets these same sections to white at the same
 * specificity (0,2,1); this only wins by being later in the file. */
body.hv2 .band--module {
  background: var(--ge-bg-light, #F3F7FA);
  margin-inline: var(--band-inset);
  border-radius: var(--band-radius);
  overflow: hidden;
}

/* ---------- 2b. PHOTO BANDS are modules too ----------
 * Rebecca, 5 Aug: "the full width photos need to be put into modules too."
 * Two sections carry a full-bleed blurred photograph behind their content — the
 * home page's "How switching works" band and Classroom's testimonial. Both wear
 * .band--photo. Their sections went white with rule 1, but the PHOTO inside was
 * still running the full width of the viewport, so they were the last full-width
 * areas left on the site.
 * Must come AFTER rule 1: .band--photo co-occurs with .band--light and
 * .pv3-voice, which rule 1 sets to `margin-inline: 0; border-radius: 0` at the
 * same specificity (0,2,1) — so this only wins by being later in the file.
 * overflow: hidden is what clips the photo to the rounded corners; the photo's
 * own `inset: -30px` blur bleed is clipped with it, which is correct.
 * The home hero's photo needs nothing — it already sits inside .hero2__frame,
 * which has been an inset 64px-radius card all along. */
body.hv2 .band--photo {
  margin-inline: var(--band-inset);
  border-radius: var(--band-radius);
  overflow: hidden;
}

/* ---------- 3. flatten the seams ----------
 * The -56px margin on .seam-curve pulled each band up under the one above so
 * elements could cross the join. Cards must not overlap. */
.seam-curve { margin-bottom: 0; }
/* ⚠ --band-seam, NOT --band-inset. These were one token until the inset went to
   Monzo's 64px, and the vertical gap between cards silently went with it: the
   section rhythm jumped from 176px to 216 on every page at once.
   They are different measurements. --band-inset is how far a card sits from the
   SIDE of the window (Monzo: 64). --band-seam is the gap between one card and
   the next going DOWN the page, which stays at the 24px it was designed as — the
   rhythm is set by the sections' own padding, and 2×76 + 24 = 176, Monzo's
   measured median. */
main > section + section { margin-top: var(--band-seam); }

/* ---------- 4. straddling elements come back inside ----------
 * Each was built to hang out of a band edge. With cards there is no edge to
 * cross. ⚠ NOT .crests or .proof — those are ordinary blocks with a legitimate
 * top margin, and zeroing it made the crest strip collide with the element above
 * on Primary, Secondary and LAs & MATs. Only true straddlers belong here. */
.proofrow, .stepscard, .pricegrid, .roigrid,
.pv3-acc__media, .pp-final__card {
  margin-top: 0;
  margin-bottom: 0;
  transform: none;
}

/* ⚠ .pcband__card TAKEN OUT of the straddle reset above (5 Aug: "i dont like how
   close the card is to the module edge"). It was never a straddler — it is a
   white card sitting INSIDE a photo frame, and its margin is the inset that holds
   it off the frame's edges. Zeroing margin-top/bottom with the genuine straddlers
   pinned it flush to the top and bottom of the module while it kept its left
   inset, so it read as a card that had been cropped rather than placed.
   Inset restored, and widened while we are here: was clamp(20px,3vw,48px), now
   clamp(24px,4vw,64px) — 58px at 1440 against 43px. transform:none is kept,
   because that part of the reset was doing real work. */
.pcband__card { transform: none; margin: clamp(24px, 4vw, 64px); }
/* The footer contact-band straddle is left alone on purpose: the footer is not a
   carded band, so it still has a flat edge to cross. */

@media (max-width: 700px) {
  :root { --band-inset: 16px; --band-radius: 32px; --band-seam: 16px; }   /* 64px would leave ~260px of card on a phone */
}


/* ============================================================
 * ONE MARGIN FOR EVERY SECTION (5 Aug 2026)
 * "can we make sure all sections of the home page are using the same margins."
 * Measured on the home page: content was starting at THREE different x positions
 * — 88px in a plain white section, but 112px inside a module, because the module's
 * own 24px inset stacks on top of the container's 88px padding. The 24px shift was
 * visible as headings not lining up down the page.
 * Fix: inside a carded section the container gives back exactly what the card took.
 * 88 - 24 = 64, so content lands at 88px either way.
 * --page-gutter has to exist because the container's padding differs by page (the
 * home page runs Monzo's 88px, every other page 32px) and CSS cannot read a
 * sibling's padding.
 * ============================================================ */
/* ⚠ These MUST mirror .container's real padding at every breakpoint, because the
   product scroller's full-bleed maths subtracts this value from the viewport. They
   did not: body.home .container drops to 24px at max-width 900 (home-v2.css), but
   this only dropped at 767 — so between 768 and 900 they disagreed by 64px, which
   pulled the scroller 64px wider than the page and gave the whole page a horizontal
   scrollbar on an iPad. If you change .container's padding, change these too. */
body.hv2 { --page-gutter: 32px; }
body.home { --page-gutter: 88px; }
@media (max-width: 900px) {
  body.home { --page-gutter: 24px; }
}
@media (max-width: 767px) {
  /* :not(.home) matters. body.hv2 and body.home are the same specificity, and this
     block sits AFTER the 900px one, so an unscoped body.hv2 here won the cascade on
     the home page and set 20px while its container was actually on 24px. */
  body.hv2:not(.home) { --page-gutter: 20px; }
}
body.hv2 .band--module > .container,
body.hv2 .band--photo > .container,
body.hv2 .band--blue > .container,
body.hv2 .band--navy > .container,
body.hv2 .band--mlviolet > .container,
body.hv2 .pv3-switch > .container,
body.hv2 .pp-band > .container {
  /* ⚠ NO COMPENSATION *WHILE THE CONTAINER IS CAPPED* — and it depends on width,
     which is why this took two goes and a measurement to get right.
       · When the card is WIDER than the container's max-width, the container is
         capped and centred inside the card. The card is also centred in the page,
         so the inset cancels exactly and the container's left edge is identical
         inside or out. Any compensation here is padding removed for no reason —
         that was the old bug: headings inside modules sat at 86px against 110px
         everywhere else.
       · When the card is NARROWER than the cap, the container FILLS it, and the
         inset really does push the content in. Then it must be subtracted.
     The two cases are split by media query below, per container cap.
     ⚠ SUPERSEDED FOR NON-HOME hv2 PAGES by the ONE MARGIN block further down,
     which uncaps .container entirely — the two cases above stop existing once
     there is no cap to be inside or outside of. This rule and its 1407px
     companion still run the HOME page, which keeps its 1440 cap. */
  padding-inline: var(--page-gutter);
}

/* ============================================================
 * ONE MARGIN, PART 2: THE CONTENT COLUMN  (6 Aug 2026)
 * Rebecca: "everything on this site bar the home page hero should have this
 * margin", then — shown that card edges and body text had ended up on two
 * different lines — "what does monzo do?"
 *
 * MEASURED LIVE on monzo.com at 1440×900, not from memory:
 *   · their card edges sit at 64px, radius 64
 *   · their body text and section headings, when NOT inside a card, sit at 64px
 *     too — it is the single most common left edge on the page (9 of 49 text
 *     blocks) and every big H2 outside a card is on it exactly
 *   · text INSIDE a card is indented by that card's own padding (100, 360, 744)
 *   · their widest text block runs 1392px — no narrow reading cap
 * So Monzo puts page text on the same margin as its cards. An earlier note in
 * my own memory said their text sat at 112 and the cards at 64; that came off a
 * different page and is wrong for the home page. The live numbers win.
 *
 * Therefore: uncap .container on every hv2 page except the home page, and let
 * --band-inset position it. Non-carded sections move out from 112 to 64 at 1440.
 *
 * ⚠ CARDS ARE DELIBERATELY UNCHANGED. Inside a card the container gets its own
 * padding instead, sized so in-card content lands on 112 at 1440 — exactly where
 * it sits today. Without it, content would touch the card's rounded edge.
 *
 * ⚠ THE HOME PAGE IS EXCLUDED, same as everywhere else in this file: it caps at
 * 1440 with an 88px gutter of its own and Rebecca has asked twice for it to be
 * left alone.
 * ============================================================ */
body.hv2:not(.home) .container {
  max-width: none;
  padding-inline: var(--band-inset, 24px);
}

/* ---- and the same box above 1628px ----
 * Heroes have been capped at 1500px and centred since 3 Aug, her rule. Cards and
 * the content column had no cap, so past 1628px (where 100vw − 2×64 exceeds
 * 1500) they carried on to the window while the hero stopped — measured at 1920:
 * hero 1500 starting at 210, cards 1792 starting at 64. One margin has to mean
 * one margin at every width, not just on a laptop.
 *
 * Rather than add a max-width to seven card rules in two files, the CAP goes into
 * --band-inset itself: once the page is wider than 1500 + 2×64, the inset grows
 * to whatever centres a 1500px box. Everything that reads the token — every card,
 * the content column, the nav, and --hero-gutter — follows automatically and
 * lands on the identical edge.
 *   1440 → 64  (unchanged)     1628 → 64  (the crossover, no jump)
 *   1920 → 210 (box = 1500)    2560 → 530 (box = 1500)
 * ⚠ Scoped to :not(.home) like everything else today — the home page runs a 1440
 * container with an 88px gutter and Rebecca has asked twice for it to be left as
 * it is. */
@media (min-width: 1628px) {
  body.hv2:not(.home) { --band-inset: calc((100vw - var(--page-cap)) / 2); }
}
body.hv2:not(.home) .band--module > .container,
body.hv2:not(.home) .band--photo > .container,
body.hv2:not(.home) .band--blue > .container,
body.hv2:not(.home) .band--navy > .container,
body.hv2:not(.home) .band--mlviolet > .container,
body.hv2:not(.home) .pv3-switch > .container,
body.hv2:not(.home) .pp-band > .container {
  /* the card's own breathing room, replacing what the 1280 cap used to provide
     by accident. 48px at desktop keeps in-card content on 112 — unchanged. */
  padding-inline: clamp(20px, 3.4vw, 48px);
}

/* ============================================================
 * HOME PAGE: ONE SECTION RHYTHM  (5 Aug 2026)
 * Rebecca: "i love the home page now - the spacing between sections is the only
 * thing we need to tidy up."
 *
 * MEASURED before touching anything: the gap between one section's content and
 * the next's ran 153, 181, 198, 234, 266, 273, 283, 290, 299px — NINE different
 * values down one page. Three causes, all historical:
 *   - Four bands carry padding-BOTTOM only, no top: .band--proof, .band--sky
 *     (1px, see below), .band--blog, .band--mtx. That is left over from the
 *     retired straddle system, where the element above hung down into the gap
 *     and the top padding would have pushed it away.
 *   - The bottoms disagree: 140px on some bands, 130 on others, 120 on the blue.
 *   - .statement is 160px, the biggest on the page, and sits right under the hero.
 *
 * One token now sets both sides of every band, so the gap is 2×pad + the 24px
 * card margin and there is exactly one number to change. 96px at 1440 gives a
 * ~216px gap: tighter than the loose end it replaces, looser than the tight end,
 * and the page loses about 700px of dead height overall.
 *
 * ⚠ HOME ONLY for now, deliberately — every other page shares these band
 * classes, and this is her home-page judgement, not a site-wide sign-off.
 * Rolling it out is a one-line change: drop `body.home` from the selectors.
 *
 * ⚠ The pinned switching band is NOT a child of main — GSAP wraps it in a
 * .pin-spacer — so it needs its own selector or it keeps the old padding.
 *
 * Three deliberate exceptions:
 *   - the hero keeps its tiny top inset and zero bottom (the frame is the edge)
 *   - .final2 keeps its deep bottom padding; the contact band straddles up into
 *     it from the footer, which is the one straddle the modular system kept
 *   - .band--sky's padding-top: 1px was a margin-collapse guard; a real padding
 *     value satisfies that just as well, so the guard is now redundant here.
 * ============================================================ */
/* MEASURED off monzo.com at 1440x900, 5 Aug 2026, when Rebecca asked to copy
   their section spacing. Their ink-to-ink gaps between consecutive sections:
   104, 128, 128, 152, 168, 176, 192, 192, 197, 280, 325 — median 176. (They are
   not rigidly uniform; the 280 and 325 are around their pricing block.)
   Ours was 202. This token is set so 2×pad + the 24px card seam = 176 at 1440,
   landing us exactly on their median: 76px each side.
   Their own section padding is mostly 0 with a few 64s — the space lives in the
   content wrappers, not the sections. We do it on the section instead, which
   gets the same result with one number instead of thirteen. */
/* MEASURED off monzo.com at 1440x900, 5 Aug 2026, when Rebecca asked to copy
   their section spacing. Their ink-to-ink gaps between consecutive sections:
   104, 128, 128, 152, 168, 176, 192, 192, 197, 280, 325 — median 176. (They are
   not rigidly uniform; the 280 and 325 are around their pricing block.)
   This token is set so 2×pad + the 24px card seam = 176 at 1440, landing us on
   their median: 76px each side.
   Their own section padding is mostly 0 with a few 64s — the space lives in the
   content wrappers, not the sections. We do it on the section instead, which
   gets the same result with one number instead of thirteen.

   ⚠ EXTENDED TO THE PRODUCT PAGES 5 Aug ("can you apply all the styling and
   rules we did for the home page"). They were looser and less even than the home
   page had been: gaps of 282–283px with a 78px odd one out, a 101px band on
   Parent App and a 383px outlier — a 182px spread on three pages and 282px on
   Parent App. Same single token now drives One, OnSite, Classroom and Parent App,
   which takes roughly 850px of dead height off each of them. */
/* ⚠ THE FLOOR IS THE MOBILE VALUE — 10 Aug 2026. Rebecca: "whilst looking on
   mobile i dont think the section spacing looks good".
   This was clamp(56px, 5.3vw, 80px). 5.3vw only reaches 56px at a 1057px viewport,
   so the FLOOR was what every phone, tablet and small laptop actually got — the
   clamp scaled nothing below 1057 and every screen from 320 to 1057 had an
   identical 56/56. With the 16px card gap that is 128px between one section's
   content and the next, on a screen 844px tall.
   Measured monzo.com at 390x844 over CDP for comparison: their sections run mostly
   32/32 (several at 0, one at 48) with gaps of 0, 8, 24, 32, 56 and 64 — roughly
   64-88px between content, and deliberately varied so related blocks sit close and
   only real topic changes get air.
   Dropping the floor to 32 makes the clamp do its job: 32 on a phone, ~44 on iPad
   portrait, ~54 on iPad landscape, 80 on desktop. Desktop is unchanged. */
body.hv2 { --band-pad: clamp(32px, 5.3vw, 80px); }

/* ⚠ :not(:first-child) rather than naming the hero classes. Every page's first
   section IS its hero — .hero2, .pv3g, .dm-hero, .ab2-open, .fs-hero, the
   statement on About us — and naming them meant six exclusions that a new page
   would silently miss. This way a hero keeps its own padding by construction.
   The pinned selector is for the home page's switching band, which GSAP wraps in
   a .pin-spacer so `main > section` cannot reach it. */
/* ⚠ :first-OF-TYPE, not :first-child — 7 Aug 2026. Rebecca: "when i click on
   the home page the hero isnt in place like it on the other pages."
   13 pages open <main> with an invisible skip-link target,
   `<a id="top" tabindex="-1"></a>`. That anchor is the first CHILD, so the hero
   section after it was not :first-child and picked up the 76px band padding
   instead of the hero's own 18px — measured on the home page: a 76px white gap
   under the nav where every other page has 11–19px.
   :first-of-type counts only <section> siblings, so the anchor stops mattering.
   It also cannot be broken again by adding anything non-section above the hero. */
body.hv2 main > section:not(:first-of-type),
body.hv2 main > .pin-spacer > section {
  padding-top: var(--band-pad);
  padding-bottom: var(--band-pad);
}

/* ⚠ ONE HERO SEAM SITE-WIDE. Every page's first section is its hero and keeps its
   own padding — but their BOTTOM paddings all differed (0 on .hero2 and .pv3g,
   43 on About's statement, 92 on Careers' ab2-open), so the gap between a hero
   and the band under it measured 100, 143 and 192 depending which page you were
   on. Zeroed, so it is 100 everywhere: the 24px seam plus the next band's own
   padding.
   Deliberately tighter than the 176 between ordinary bands — a hero's bottom is
   a card edge, and the same gap after an edge reads larger than it does after a
   line of text. */
body.hv2 main > section:first-of-type { padding-bottom: 0; }   /* :first-of-type — see the note above */

/* ============================================================
 * .statement--hero — THE PALE CARD HERO  (About us · Book a Demo · Launch Deal)
 *
 * Started as the About us hero on 6 Aug ("i dont think the hero looks defined
 * enough what can we do to make it look more monzo"), and the same day she asked
 * for it on the other two: "lets use the same hero style for the book a demo and
 * the launch deal page". So it is a component, not a page style.
 *
 * ⚠ IT HAS TO LIVE IN THIS FILE. `body.hv2 main > section.statement--hero` is
 * (0,2,3) and the `:first-of-type { padding-bottom: 0 }` rule above is also
 * (0,2,3) — a tie modular wins on load order. Written from any earlier
 * stylesheet the bottom padding silently vanished and the closing paragraph sat
 * flat on the card's rounded edge (Rebecca, 6 Aug: "the text looks too close to
 * the bottom edge"). Keeping the whole component here means the two halves
 * cannot drift apart again.
 *
 * The base type — .statement, .statement__line (84px/600/30ch) and
 * .statement__sub — is in home-v2.css and loads on every page, so this file only
 * has to supply the card and the pieces the two CTA pages add.
 *
 * Geometry is the site's module geometry, not the --hero-frame-w one: the same
 * --band-inset and 64px radius as every other card down the page, so the hero
 * belongs to the family below it instead of introducing a fourth surface.
 * ============================================================ */
body.hv2 main > section.statement--hero {
  background: var(--ge-bg-light, #F3F7FA);
  margin-inline: var(--band-inset, 24px);
  /* the breath between the nav and the top of the card. Every other hero on the
     site gets this from `.hero2 { padding-top: clamp(10px,1.4vw,18px) }` (and
     .pv3g's identical copy), but on a carded hero padding is INSIDE the card, so
     it has to be a margin or the card still butts up under the nav — which is
     what it did (Rebecca, 6 Aug: "the about us hero doesnt have a gap up the top
     like the school types and product pages do"). Same clamp, so all three
     hero families sit on one line. */
  margin-top: clamp(10px, 1.4vw, 18px);
  border-radius: var(--band-radius, 64px);
  overflow: hidden;
  /* equal top and bottom, and deliberately tighter than the 56–96 they replace,
     so the headline starts ~30px higher up the fold (Rebecca, 6 Aug: "can we
     move content up so its above the fold more") */
  padding-top: clamp(40px, 3.6vw, 56px);
  padding-bottom: clamp(40px, 3.6vw, 56px);
}

/* ⚠ text-align is INHERITED as centre from an ancestor — no rule sets it on
   .statement__sub itself, which is why it read as indented and ragged on both
   sides while its box was correctly left-aligned with the headline. Stated
   explicitly rather than hunting the ancestor, so it cannot drift again. */
body.hv2 .statement--hero,
body.hv2 .statement--hero .statement__sub,
body.hv2 .statement--hero .statement__line { text-align: left; }

/* the eyebrow pill. White chip with navy type — the same component the
   school-type heroes use, so a visitor moving between pages sees one thing. */
body.hv2 .statement--hero .statement__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 clamp(18px, 2vw, 26px);
  padding: 8px 16px;
  border-radius: 999px;
  background: #fff;
  color: var(--ge-navy, #0F1438);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  box-shadow: 0 2px 10px rgba(15, 20, 56, 0.06);
}

/* ---- the parts only the two CTA pages use ----
   About us is copy-only; Book a Demo and the Launch Deal both close their hero
   with a button, and Book a Demo carries a time line above it and a quiet
   confirmation line below. */
body.hv2 .statement--hero .statement__when {
  margin: clamp(16px, 1.8vw, 22px) 0 0;
  font-size: clamp(18px, 1.6vw, 23px);
  font-weight: 700;
  color: var(--ge-blue, #1B367E);
}
body.hv2 .statement--hero .statement__cta {
  margin-top: clamp(24px, 2.6vw, 34px);
  /* .btn on its own paints no background — it needs a modifier or an explicit
     fill, which is how the footer CTA button once shipped invisible. Navy fill
     with a white arrow disc, the same recipe as the pre-footer CTA card. */
  background: var(--ge-navy, #0F1438);
  color: #fff;
  border: none;
}
body.hv2 .statement--hero .statement__cta .btn__arrow {
  background: #fff;
  color: var(--ge-navy, #0F1438);
}
/* ⚠ the About us hero's paragraph runs to TWO lines, not three — 7 Aug 2026,
   at her request. The fix is the MEASURE, not the words: .statement__sub caps at
   48ch, which at 19px is ~598px and broke this particular sentence over three
   lines. 74ch takes it to two without touching her copy or the shared 48ch cap
   that every other statement band relies on.
   ⚠ If the copy is ever rewritten, re-check the line count — a measure tuned to
   one sentence is not a rule, it is a fit. */
body.hv2 .statement--hero .statement__sub { max-width: 74ch; }

body.hv2 .statement--hero .statement__note {
  margin: 16px 0 0;
  font-size: 14.5px;
  color: #4A5876;
}

/* the closing CTA bands keep a deep bottom: the footer's contact card straddles
   UP into them by ~210px, and without the reserve it would sit on the copy */
body.hv2 main > section.final2,
body.hv2 main > section.pp-final,
/* ⚠ .fc-how, not .fc-claim-section. The Launch Deal's blue claim board carried
   this reserve until 6 Aug, when its message moved into the pre-footer card and
   the board was removed — leaving "What claiming a place involves" as the last
   section on that page, with nothing holding the footer's card off it. The
   .fc-claim-section selector is kept below it, inert, because the class is still
   defined in founders-club.css and could be used again. */
/* ⚠ 6 Aug 2026 — THIS IS NOW STRUCTURAL, NOT A LIST OF CLASSES, and that change
   is the point. The rule used to name each page's closing section by hand
   (.final2, .pp-final, .fc-how, .cta-close…). Rebecca found the consequence on the
   school-type pages: "bugs here on the school type pages" — the footer's contact
   card straddles UP out of the footer, and any closing section not on the list
   reserved no room for it, so the card landed ON TOP of the copy.
   Measured at 1440: SIX pages were broken this way — primary-schools,
   secondary-schools and local-authorities-and-trusts (.st-final), martyns-law
   (.ml-final), onsite-launch-campaign-v2 (.hi-final) and compare-school-mis
   (.band) — each overlapping by 210-226px with only 76px of padding.
   Keyed off the STRAIGHT FACTS instead: this page has a straddling footer card,
   and this is the last section in <main>. A new page cannot miss it now.
   ⚠ :has(.cb--footer) is load-bearing — pages with no contact band (Blog articles,
   the policy pages) must NOT get 380px of dead space at the bottom.
   ⚠ My own site-wide overlap sweep missed all six because it only compared
   sections inside <main>, and the offending card lives in the <footer>. Any future
   sweep has to cross that boundary. */
body.hv2:has(.cb--footer) main > section:last-child,
body.hv2 main > section.fc-how,
body.hv2 main > section.fc-claim-section,
body.hv2 main > section.cta-close {
  padding-bottom: clamp(280px, 22vw, 380px);
}

/* first-child top margins would stack on the padding and put the gap back out of
   step — the token has to be the only thing setting it */
body.hv2 main > section > .container > *:first-child,
body.hv2 main > .pin-spacer > section > .container > *:first-child { margin-top: 0; }

/* Several bandheads carry a big padding-top of their own — .band--white
   130-190px ("room for the hanging stat strip"), #products 58-96px, .band--mtx
   80-140px. That padding stood IN for the section top padding those bands never
   had, and for straddling elements that no longer straddle. With a real section
   padding above, the two stacked: 129 + 89 = 219px over "What's included in each
   product" against 89px elsewhere. Zeroed so the token is the single source. */
body.hv2 main > section .bandhead,
body.hv2 main > .pin-spacer > section .bandhead { padding-top: 0; }
/* #products.band--white .bandhead carries an ID, so it outranks the pair above
   (1,2,1 vs 0,2,3) and kept its 96px. Same selector plus the id to take it. */
body.hv2 main > section#products .bandhead { padding-top: 0; }



/* ============================================================
 * ONE MARGIN FOR EVERY HERO  (6 Aug 2026)
 * Rebecca: "everything on this site bar the home page hero should have this
 * margin", pointing at the Book a Demo hero card.
 *
 * There were two systems running side by side. --band-inset positioned every
 * carded BAND (16px on a phone, 32 at 1280, 64 from 1408 up), while heroes had
 * their own --hero-gutter of clamp(10px, 1.6vw, 22px) — so at 1440 a hero card's
 * edge sat at 22px and every band card below it at 64px, a 42px step down the
 * left of the page. Feeding one token into the other collapses them into a
 * single edge.
 *
 * ⚠ --hero-gutter, NOT margin-inline — the same trap school-types.css hit when
 * the audience heroes did this first. A frame's width is
 * `min(--hero-cap, 100% - 2 × --hero-gutter)`, so a margin stacked on top of a
 * width that still assumed the old gutter makes the frame wider than its own box
 * (16–21px of page overflow, immediately). Feeding the token into the gutter
 * keeps the width formula and the edge in agreement, and --hero-inset re-derives
 * from --hero-frame-w on its own.
 *
 * ⚠ THE HOME PAGE HERO IS EXPLICITLY EXCLUDED, by her instruction on both 5 Aug
 * ("leave the home page hero the same for now though") and again here. It sets
 * its own --hero-gutter: 24px in home-v2.css under body.home; :not(.home) here
 * means this never reaches it, whichever file loads last.
 *
 * ⚠ KNOWN, AND NOT FIXED HERE: above ~1628px the two part company again. Hero
 * frames are capped at --hero-cap (1500px) and centred — her rule from 3 Aug —
 * while band cards have no cap and keep running to 64px from each edge. Below
 * 1628 they are identical, which covers every laptop. Capping the bands to match
 * would change how all 31 pages look on a large external monitor, so it needs
 * her eyes first rather than shipping blind.
 *
 * ⚠⚠ --hero-frame-w AND --hero-inset HAVE TO BE RESTATED HERE, not just the
 * gutter. Both are declared on :root in home-v2.css, and an unregistered custom
 * property substitutes its var()s at the element where it is DECLARED — so
 * :root's --hero-frame-w already has the old 22px baked into it, and every
 * descendant inherits that finished value. Overriding only --hero-gutter on
 * body changed nothing at all: measured, the hero edge stayed on 22 while the
 * cards sat on 64. Re-declaring the two derived tokens on the same element
 * forces them to re-substitute against the new gutter.
 * ============================================================ */
body.hv2:not(.home) {
  --hero-gutter: var(--band-inset, 24px);
  --hero-frame-w: min(var(--hero-cap), calc(100% - 2 * var(--hero-gutter)));
  --hero-inset: max(0px, calc((var(--hero-frame-w) - var(--hero-content-cap)) / 2));
}

/* THE NAV COMES WITH THEM. On any page that has a hero FRAME, the nav already
   follows it — `body:has(.hero2__frame, …) .nv__inner { width: var(--hero-frame-w) }`
   in home-v2.css — so it moved to 64px on its own and the logo now sits exactly
   on the hero's left edge, measured.
   The four pages with a CARDED hero and no frame (About us, Book a Demo, the
   Launch Deal, Contact) do not match that :has() list, so the nav fell back to
   its own `padding: 14px clamp(10px,1.6vw,22px)` and sat 42px outside the card
   at 1440 — logo at 22, card at 64. Same token, same edge.
   ⚠ Padding, not width: .nv__inner on these pages is max-width: none and full
   bleed, so the gutter is what positions it.
   ⚠⚠ The :not(:has(…)) is REQUIRED and must mirror home-v2.css's list exactly.
   The frame pages zero the nav's padding and position it by width instead;
   without the exclusion this rule adds the gutter back on top and the logo lands
   at 128px against a 64px tile — measured on the blog article, which is in that
   list via .arthero. */
body.hv2:not(.home):not(:has(.hero2__frame, .pv3g__frame, .ph-hero__frame, .arthero, .dm-hero__frame)) .nv__inner {
  padding-inline: var(--hero-gutter);
}

/* ---- AND THE HOME PAGE COMES WITH THEM (11 Aug 2026) ----
 * Rebecca: "ive noticed the nav bar is moving on certain pages - keep it uniform
 * for all pages." Measured at 1440 across all 30 pages: 25 were identical (logo at
 * 64px), the home page sat at 22px. Clicking home → anywhere slid the whole nav
 * 42px inwards, which is what she was seeing.
 *
 * ⚠ THIS DELIBERATELY BREAKS THE HOME NAV AWAY FROM ITS OWN HERO CARD, and she
 * chose that trade knowingly when asked. The home hero keeps its 22px Monzo gutter
 * (--hero-gutter: 24px on body.home, and the whole home geometry in CLAUDE.md hangs
 * off it) — only the NAV moves in to 64px. So on the home page the logo no longer
 * lines up with the hero card's left edge. That is the cost of the nav not moving
 * between pages; do not "fix" it by dragging the hero card out to 64px, which would
 * undo the measured home geometry.
 *
 * ⚠ WIDTH, not padding. Home matches home-v2.css's
 *   `body:has(.hero2__frame, …) .nv__inner { width: var(--hero-frame-w) }`
 * so the nav is positioned by its own width plus auto margins, and adding padding
 * would leave it 1396px wide with the content pushed in — the logo would land at
 * 86px, further out of step, not less. The expression below is the same one
 * --hero-frame-w resolves to on every other framed page; it is written out rather
 * than reusing the token because body.home re-declares --hero-frame-w against its
 * own 22px gutter, which is exactly the value we are trying not to inherit. */
body.hv2.home .nv__inner {
  width: min(1500px, calc(100% - 2 * var(--band-inset, 24px)));
}

/* The remaining hard-coded copies of the old clamp(10px,1.6vw,22px) gutter.
   Each of these predates the --hero-gutter token and wrote the value out
   literally, so none of them followed when the token moved. All are hero-tile
   edges or something explicitly padded back to one, which is why they belong
   here rather than being left at 22px next to a 64px card.
   The nav's own copy in home-v2.css is deliberately NOT in this list — it is
   handled by the rule above, which keeps the home page on its own gutter. */
body.hv2:not(.home) .arthero .container,   /* blog article photo tile */
body.hv2:not(.home) .ph-hero,              /* Parent Help Centre header */
body.hv2:not(.home) .sth__strip {          /* school-type seam strip, padded back to the tile margin */
  padding-inline: var(--hero-gutter);
}
body.hv2:not(.home) .pp-hero__frame,       /* legacy product hero */
body.hv2:not(.home) .os-hero__frame,       /* legacy OnSite hero */
body.hv2:not(.home) .fs-hero__frame {      /* OnSite launch campaign hero */
  margin-inline: var(--hero-gutter);
}

/* ============================================================
 * ONE HERO RADIUS, EVERY PAGE  (12 Aug 2026)
 * Rebecca: "the news and insights hero has larger corner radius than the other
 * heros - i want it to be uniform across site."
 *
 * ⚠ THE BLOG HERO WAS NEVER THE ODD ONE OUT. Measured at 1440 across 19 pages:
 * ELEVEN were already on 64px (home, Book a Demo, Launch Deal, Primary, Secondary,
 * LAs & MATs, compare, contact, help centre, school login, blog index) and SIX were
 * on 34px (One, OnSite, Classroom, Parent App, Parents, Martyn's Law), plus the blog
 * ARTICLE heroes. She chose to bring the 34s up rather than take the blog down.
 * What she was actually seeing is HEIGHT, not radius: the blog hero is 324px tall
 * against 648-761px elsewhere, and the same 64px corner on a card half the height
 * reads far rounder. That is unchanged by this rule — see the note on
 * .bhhead__frame min-height in blog-home.css if it still looks wrong to her.
 *
 * ⚠ WHY THIS IS SAFE HERE AND WOULD NOT HAVE BEEN IN THE PAGE STYLESHEETS:
 * school-types.css records the trap — moving a hero to a 64px radius without also
 * moving its GUTTER to --band-inset overflowed the page by 16-21px, because a
 * frame's width is `min(cap, 100% - 2*gutter)` and the two have to agree. Those
 * gutters were already fixed (--hero-gutter: var(--band-inset) on
 * body.hv2:not(.home), and the margin-inline rule directly above), so only the
 * radius was left behind. Verified after: zero overflow at 390/768/1024/1440.
 *
 * ⚠ .hero2__frame is listed even though home, Primary, Secondary and LAs are
 * already 64 — it is what fixes Martyn's Law, which uses the same class but loads
 * martyns-v2.css instead of school-types.css. Re-asserting 64 on the others is a
 * no-op, and cheaper than a page-by-page selector list that will rot.
 * ⚠ On phones --band-radius is 32px, so these follow it down. That replaces the
 * hard-coded 22px on .trust2__frame in home-v2.css's mobile block — deliberate:
 * one token, one radius, at every width.
 * ============================================================ */
body.hv2 .hero2__frame,
body.hv2 .pv3g__frame,
body.hv2 .pp-hero__frame,
body.hv2 .os-hero__frame,
body.hv2 .fs-hero__frame,
body.hv2 .ph-hero__frame,
body.hv2 .arthero .trust2__frame {
  border-radius: var(--band-radius, 64px);
}

/* The fill case, per container cap. hv2 pages cap at 1280, so the card stops
   being wider than the cap below 1280 + 2×64 = 1408. The home page caps at 1440,
   so its threshold is 1568. Above each of these, the rule above applies and no
   compensation is wanted.
   ⚠ These numbers are derived from .container's max-width. If that ever changes,
   change these with it — or the module content steps out of line again. */
@media (max-width: 1407px) {
  body.hv2 .band--module > .container,
  body.hv2 .band--photo > .container,
  body.hv2 .band--blue > .container,
  body.hv2 .band--navy > .container,
  body.hv2 .band--mlviolet > .container,
  body.hv2 .pv3-switch > .container,
  body.hv2 .pp-band > .container {
    padding-inline: max(0px, calc(var(--page-gutter) - var(--band-inset)));
  }
}
/* ⛔ SUPERSEDED 6 Aug 2026 — see the block below. This gave home-page cards
   `max(0, 88 - 64)` = 24px of side padding, so that in-card content lined up
   with the page's non-card text at 88px. Alignment was right; the breathing room
   was not. Rebecca, of the navy stats card: "the module content seems a bit
   tight on this - what do you think". Measured: 24px at the sides against 76px
   top and bottom, on a card with a 64px corner radius — the text started inside
   the curve, and every other page in the site was already on 48px.
@media (max-width: 1567px) {
  body.home .band--module > .container,
  body.home .band--photo > .container,
  body.home .band--blue > .container,
  body.home .band--navy > .container,
  body.home .pv3-switch > .container {
    padding-inline: max(0px, calc(var(--page-gutter) - var(--band-inset)));
  }
}
*/

/* HOME CARDS ON THE SITE'S IN-CARD PADDING  (6 Aug 2026)
 * The identical clamp the other 28 pages use (line ~303), so a card reads the
 * same wherever you land. 48px at 1440.
 *
 * ⚠ This deliberately DE-aligns in-card content from the home page's own body
 * text: text lands at 64 + 48 = 112 inside a card and 88 outside one. That is
 * not a regression — it is what Monzo does and what the rest of this site
 * already did. From the measurement note higher up this file: "text INSIDE a
 * card is indented by that card's own padding (100, 360, 744)". A card is a
 * container; its contents step in from its edge. */
body.home .band--module > .container,
body.home .band--photo > .container,
body.home .band--blue > .container,
body.home .band--navy > .container,
body.home .band--mtx > .container,
body.home .pv3-switch > .container {
  padding-inline: clamp(20px, 3.4vw, 48px);
}


/* ============================================================
 * BOOK A DEMO + LAUNCH DEAL — ONE MODULE EACH  (5 Aug 2026)  ⛔ BOTH NOW GONE
 *
 * The idea: both pages were flat white end to end, so each got ONE tinted card,
 * on the section carrying the substance — a shape without a stack of boxes.
 *   · Book a Demo → "What happens in the 30 minutes" (.dm-steps)
 *   · Launch Deal → "Be one of the first thousand" (.fc-first)
 *
 * ⛔ 6 Aug 2026, BOTH REMOVED, a few hours apart:
 *   · .dm-steps — the whole section was cut from Book a Demo at her request, so
 *     there is nothing left for the selector to match.
 *   · .fc-first — Rebecca: "for the launch deal page - take the be one of the
 *     first thousdan out of a module". Taking something OUT OF a container on
 *     this project means lose the wrapper and keep the content, never delete it:
 *     the heading, the lede and all four perk cards are untouched and now sit on
 *     plain white like the rest of the page.
 *
 * Kept as a commented block rather than deleted, because it is the exact recipe
 * (tint, inset, radius) if either page ever wants its one module back.
 *
 * body.hv2 main > section.dm-steps,
 * body.hv2 main > section.fc-first {
 *   background: var(--ge-bg-light, #F3F7FA);
 *   margin-inline: var(--band-inset, 24px);
 *   border-radius: var(--band-radius, 64px);
 *   overflow: hidden;
 * }
 *
 * ⚠ If it is ever restored, the body.hv2 + main > section context is not
 * decoration: modular's own all-white list lists .band--light at (0,2,1) and
 * would otherwise win.
 * ============================================================ */


/* ---- the agency note sits WITH the roles  (6 Aug 2026) ----
 * "we dont need a big gap here as the recruiment part is to do with new roles."
 * The note is a qualifier on the vacancy list above it, not a new subject, and
 * the 176px rhythm is for moving between subjects. A full section break made
 * them read as two unrelated blocks.
 * ~80px instead: enough to separate the navy card from the list, not enough to
 * suggest the page has moved on. Trimmed on both sides so the seam stays even —
 * the gap is jobs' bottom + the 24px card seam + the note's top.
 * ⚠ Lives HERE, not in statement-page.css, because it has to beat this file's
 * own `main > section:not(:first-child)` rule, which it ties with on specificity. */
/* ⚠ :not(.cta-close) IS THE WHOLE FIX — added 7 Aug after this rule broke the
   About us page. Careers ends .ab2-jobs with an .ab2-note underneath, so the
   tight bottom is right there. About us uses the SAME .ab2-jobs class on its
   CLOSING section, which also carries .cta-close — the class whose entire job is
   to reserve ~280px so the footer's contact card can straddle up into it.
   Both selectors are (0,2,3), a tie, and this one sits later in the file, so the
   28px won and the contact card landed 182px ON TOP of "Fancy joining the
   GroupEd team?" — measured. Excluding closing sections lets .cta-close win
   again without touching it. */
/* ⚠ :has(+ .ab2-note) IS THE POINT: tighten ONLY when the note follows.
   The tight bottom exists for one reason — on Careers the recruitment note is a
   qualifier on the vacancy list above it, not a new subject, so the full 176px
   rhythm read as two unrelated blocks. Stating that as "when a note follows"
   instead of "whenever .ab2-jobs appears" fixes two bugs at once:
     · About us uses .ab2-jobs on its CLOSING section, which also carried
       .cta-close. Both selectors were (0,2,3) and this one sat later, so 28px
       beat the ~300px straddle reserve and the footer's contact card landed
       182px on top of "Fancy joining the GroupEd team?" (measured, 7 Aug).
     · With the card since removed from About us, 28px left the closing section
       almost touching the footer. It now takes the normal band padding.
   ⚠ Do not swap this back for a class list — the condition really is "is a note
   coming next", and any class-based version has to be re-fixed per page. */
body.hv2 main > section.ab2-jobs:has(+ .ab2-note) { padding-bottom: clamp(20px, 2vw, 28px); }
body.hv2 main > section.ab2-note { padding-top: clamp(20px, 2vw, 28px); }


/* ============================================================
 * ACCESSIBILITY — WCAG 2.2 AA fixes  (6 Aug 2026)
 * From the AccessLint audit (see ACCESSIBILITY-AUDIT.md). These live in
 * modular.css because it loads LAST on all 28 pages, so one rule reaches the
 * whole site and cannot be out-specified by a page stylesheet.
 * ============================================================ */

/* ---- SC 1.4.1 — links in running text need a non-colour cue ----
 * The engine found 11 inline links across 7 pages set apart from the sentence
 * around them by colour alone (--ge-blue #1B367E on white). Colour on its own
 * fails for anyone who cannot distinguish it from the body grey.
 *
 * ⚠ Scoped to links INSIDE running text, not every link on the site. Nav,
 * footer columns, buttons, cards and tiles are not "text blocks" — underlining
 * those would be both wrong and ugly. Two things do the scoping:
 *   · `main` — the header nav and footer sit outside it
 *   · `:not([class])` — every button, card and CTA on this site carries a class;
 *     a bare <a> inside a <p>, <li> or <span> is prose by construction
 * The two exceptions below are named because they DO carry a class but are
 * still inline in a sentence. */
/* ⚠ NOT scoped to body.hv2, unlike everything else in this file. Six pages —
   partners, become-a-partner, partner-application, create-account and the two
   OnSite campaign pages — are built on an older template and carry no `hv2`
   class, so every hv2-scoped rule here skips them. They DO load this stylesheet,
   so dropping the scope on this one rule is what reaches them; scoping by `main`
   alone still keeps the nav and footer out. Verified: create-account and
   partner-application were still failing 1.4.1 until this changed. */
main p > a:not([class]),
main li > a:not([class]),
main span > a:not([class]),
main .ab2-link,
main .parents__link,
main .jw__readmore,
/* the article byline — "By Cerys Furlong, CEO · 4 August 2026" links her name
   inside a sentence, so it is a text-block link despite carrying a class */
main .art-meta__author {
  text-decoration: underline;
  /* clear of descenders, and thin enough not to shout */
  text-underline-offset: 0.18em;
  text-decoration-thickness: 0.07em;
}
/* the arrow-carrying links keep the arrow un-underlined — a struck-through
   chevron reads as a mistake */
main .ab2-link svg,
main .parents__link svg,
main .jw__readmore svg { text-decoration: none; }

/* ============================================================
 * TRUST BAND ON THE HOME MARGIN  (6 Aug 2026)
 * Rebecca: "shouldnt this tile be wider to have the same margin as the module
 * below it", of the "Your data's in safe hands" photo band.
 *
 * She was right, and it was the only card on the page that was off. Measured at
 * 1440: every modular card paints at 64px from each edge (--band-inset); the
 * trust frame painted at 88px, because it is the one card that takes its width
 * from the home page's own .container (1440 max / 88px gutters) instead of the
 * band inset.
 *
 * ⚠ Home page ONLY. On Primary, Secondary and LAs & Trusts the same band is
 * already correct — they get `body.hv2:not(.home) .container { padding-inline:
 * var(--band-inset) }` higher up this file, and the home page is explicitly
 * excepted from that rule. Don't "fix" it there too.
 * ============================================================ */
body.hv2.home .trust2 > .container {
  max-width: none;
  padding-inline: var(--band-inset, 24px);
}

/* ============================================================
 * THE BIG STATEMENT ON THE IN-CARD LINE  (6 Aug 2026)
 * Rebecca: "can we give the big statement the same margin as the text in the
 * module below", of "Five logins. Multiple disconnected systems." against
 * "Built for every corner of school life." in the card beneath it.
 *
 * The statement is a full-bleed band with no card, so it was on the home page's
 * 88px gutter, while card text lands on 64 (card edge) + 48 (in-card padding)
 * = 112. Two big navy display lines, 24px apart. This puts them on one line.
 *
 * ⚠ Written as the sum, not as a literal 112, so it follows if either the card
 * inset or the in-card padding is ever retuned. The clamp is the same one the
 * cards use — keep them identical or the alignment silently drifts.
 *
 * ⚠ This is a deliberate departure from the Monzo measurement recorded higher up
 * this file ("their body text and section headings, when NOT inside a card, sit
 * at 64px too"). Her call, and it is the more consistent read on THIS page,
 * where the statement is sandwiched between two cards rather than standing
 * alone. Home page only — the statement bands on Careers, Martyn's Law, Sync and
 * Founders Club are untouched.
 * ============================================================ */
body.home .statement > .container {
  padding-inline: calc(var(--band-inset, 24px) + clamp(20px, 3.4vw, 48px));
}

/* ============================================================
 * THE FOUR LEGACY PAGES JOIN THE SITE  (6 Aug 2026)
 * Rebecca: "lets amend these pages to make them look like the rest of the site",
 * naming Partners, Become a Partner, Partner Application and Create Account.
 *
 * They were the last pages outside the system. Two things were wrong and both
 * are fixed in the HTML, not here:
 *   1. no `hv2` class on <body>, so every body.hv2 rule in this file skipped
 *      them — the margin system included. Their text sat at 112px against 64
 *      everywhere else.
 *   2. they never loaded home-v2.css, which is where `.hv2 h1/h2/h3
 *      { font-weight: 600 }` lives — so their headings rendered at --fw-light
 *      (300) while the whole site is on SemiBold 600. Adding the class alone did
 *      NOT fix this, which is worth remembering: the type system is in
 *      home-v2.css, not in the class.
 * home-v2.css is linked immediately after foundation.css, the same slot it takes
 * on the other 25 pages, so the cascade order matches theirs exactly.
 *
 * What is left for this file is the nav, which is a different component on these
 * pages: the OnSite sub-site uses `.nav__inner` (1280 cap / 32px padding → logo
 * at 112) where the main site uses `.nv__inner`. Content moved to 64 and the
 * logo did not follow.
 *
 * ⚠ `.nav__inner` appears on SIX pages — these four plus both OnSite launch
 * campaign pages. Scoped to body.hv2 on purpose: the two campaign pages have NOT
 * been converted, so their content is still on the old margin and moving their
 * nav alone would misalign them in the opposite direction.
 * ============================================================ */
body.hv2 .nav__inner {
  max-width: none;
  padding-inline: var(--band-inset, 24px);
}

/* ============================================================
 * HERO HIGHLIGHT PILLS GO WHITE  (6 Aug 2026)
 * Rebecca: "can we change all hero highlight to be white other than on the home
 * page". The pill was pale sky #D9F4FF everywhere; in a hero it now sits white.
 *
 * ⚠ THIS IS A NARROW EXCEPTION TO THE SITE-WIDE PILL RULE, not a replacement for
 * it. CLAUDE.md still holds for every OTHER pill on the site: "every .mark pill is
 * pale sky #D9F4FF with blue #1B367E text, on every page, whatever colour that page
 * leads with". Only pills inside a HERO headline change, and only off the home page.
 * ⚠ body.home is excluded by name — her instruction, and its hero pill is part of a
 * composition that has been signed off.
 * ⚠ Text stays blue #1B367E: 9.8:1 on white, and it keeps the pills recognisable as
 * the same device. Do not "simplify" it to navy.
 * Listed hero by hero rather than by a structural selector because the heroes are
 * six different components with nothing reliable in common — .hero2 (audience,
 * Martyn's Law, home), .pv3g (products), .statement--hero (About/Demo/Launch Deal),
 * .ab2-open (Careers), .arthero (blog articles), .hi-hero/.fs-hero (campaigns).
 * ============================================================ */
body.hv2:not(.home) .hero2 h1 .mark,
body.hv2:not(.home) .hero2__copy h1 .mark,
body.hv2:not(.home) .pv3g h1 .mark,
body.hv2:not(.home) .ab2-open h1 .mark,
body.hv2:not(.home) .arthero h1 .mark,
/* ⚠ .statement--hero IS DELIBERATELY NOT IN THIS LIST — it was, for about ten
   minutes, and Rebecca caught it: "remove highlight here on the about us page".
   Those heroes (About us, Book a Demo, Launch Deal) are the PALE CARD, and their
   .mark has never had a pill at all — home-v2.css gives it blue text and nothing
   else, on purpose. Putting a white background on it drew a white box on a
   #F3F7FA card, which is the one background white cannot sit on invisibly.
   If a hero pill is ever wanted there, it needs a colour that is not white. */
body:not(.hv2) .hi-hero h1 .mark,
body:not(.hv2) .fs-hero h1 .mark,
body.hv2 .hi-hero h1 .mark,
body.hv2 .fs-hero h1 .mark {
  background: #fff;
  color: var(--ge-blue, #1B367E);
}

/* ============================================================
 * A CARD NEVER ENDS FLUSH AGAINST THE FOOTER  (6 Aug 2026)
 * Rebecca: "can we move the fancy joining th emission tile up - its touching the
 * footer", of the pale careers module at the foot of About us.
 *
 * Measured across every page: the gap between the last section and the footer is
 * 0 EVERYWHERE, and on every other page that is correct — their last section is a
 * flat white band, so white meeting navy is a clean seam with nothing to separate.
 * About us is the only page whose last section is a rounded, inset CARD, and a
 * card with 64px corners sitting flush on the footer reads as a collision.
 *
 * So the gap is conditional on being a card, not on being last: the same
 * --band-seam every other card-to-card join on the site uses.
 * ⚠ Keyed off the card classes, not off About us, so any future page that happens
 * to end on a module gets it for free.
 * ⚠ margin-bottom, NOT padding — padding would grow the card's own pale area and
 * push its contents around; the gap has to be outside it. */
body.hv2 main > section:last-child.band--module,
body.hv2 main > section:last-child.band--photo,
body.hv2 main > section:last-child.band--blue,
body.hv2 main > section:last-child.band--navy,
body.hv2 main > section:last-child.band--mlviolet,
body.hv2 main > section:last-child.pp-band {
  margin-bottom: var(--band-seam, 24px);
}

/* ============================================================
 * A SECOND HEADING INSIDE ONE MODULE NEEDS A GAP  (6 Aug 2026)
 * Rebecca: "you need to spread this out on the pricing cards."
 *
 * The spacing standard above zeroes padding-top on EVERY .bandhead, because the
 * section's own top padding is meant to be the single source of the gap. That is
 * right while a section has one heading. It stopped being right the moment
 * pricing and "What's included" were merged into one .band--mtx module — the
 * second heading is mid-card, gets no section padding, and had 16px of air above
 * it (0px on LAs & Trusts, where the blue tile sits in between). The price cards
 * ran straight into the next heading.
 *
 * So: a bandhead that is NOT the first thing in its container is a mid-module
 * heading and takes the gap itself. Deliberately generic rather than a
 * .pricegrid + .bandhead special case — any module that grows a second section
 * gets the right rhythm without another rule.
 *
 * ⚠ MARGIN, NOT PADDING. Padding would be re-zeroed by the rule above (0,2,3);
 * more importantly the gap belongs between two blocks, so it should collapse and
 * measure like a margin.
 * ⚠ Sized under the 80-140px band rhythm on purpose. These are two parts of ONE
 * card, not two bands — matching the full band gap would make the module read as
 * two sections that forgot to separate.
 * ============================================================ */
body.hv2 main > section > .container > .bandhead:not(:first-child),
body.hv2 main > .pin-spacer > section > .container > .bandhead:not(:first-child) {
  margin-top: clamp(64px, 7vw, 104px);
}

/* ============================================================
 * ONE DISTANCE ABOVE EVERY HERO  (6 Aug 2026)
 * Rebecca: "can we make sure that all hero banners have the same distance above
 * them". Measured all 30 pages at 1440: 23 already sat at exactly 18px under the
 * nav. These six did not, and they were all off for the same reason.
 *
 * THE CAUSE: on these six legacy pages .nav is `position: fixed` (foundation.css),
 * so it floats OVER the page instead of taking up space. Their hero then needs a
 * big padding-top just to clear it — 124px on Partners, 144px on the account
 * pages, 112-124px on the campaign pages. That padding is nav-height PLUS the
 * gap, so the real gap was whatever was left over: 32, 52, 24 and 12px. And
 * because the nav's own height changes with the viewport (92 -> 64 on Partners,
 * 100 -> 84 on the campaigns) no fixed padding could ever hold one gap at every
 * width.
 *
 * THE FIX: sticky, not fixed — which is what the other 24 pages already use. The
 * nav takes up its own space again, so the hero needs no clearance at all and the
 * plain 18px works at every width by itself. This removes the guesswork rather
 * than re-tuning it.
 *
 * ⚠ The nav still sticks to the top when you scroll. The only thing that changes
 * is that it no longer overlaps the page.
 * ⚠ These navs are also frosted (translucent + blur), which the brand rules say a
 * nav never is. Left alone — that is a look, not a spacing bug, and not what was
 * asked for here.
 * ============================================================ */
body.hv2 .nav { position: sticky; }

/* with the nav back in the flow, the clearance padding is the gap itself */
body.hv2 .pn-hero,
body.hv2 .auth-wrap,
body.hv2 .hi-hero,
body.hv2 .fs-hero { padding-top: var(--hero-top, 18px); }

/* ---- wider supporting paragraph on one statement band (10 Aug 2026) --------
 * Rebecca, on the Parent app band: "Can we make the paragraph line length longer".
 * ⚠ SCOPED, NOT GLOBAL. .statement__sub is 48ch site-wide and the same band is on
 * Home, Book a Demo, Founders Club and Compare — all signed off at that measure.
 * A modifier keeps this change to the one band that was actually complained about.
 * ⚠ text-wrap: balance is switched off here too. Balance evens the line lengths,
 * which on a short paragraph pulls it NARROWER than its max-width — it was most of
 * why this one looked cramped. Widening without turning balance off does very little. */
body.hv2 .statement--wide .statement__sub {
  max-width: 68ch;
  text-wrap: pretty;
}

/* ============================================================
 * HERO WATERMARKS — ONE POSITION, ONE OPACITY  (10 Aug 2026)
 * Rebecca: "on all the heros that have the watermark icon - can we reduce its
 * opacity further so its fainter. can we also make them all in the same position.
 * choose the position that they are for school types".
 *
 * There were SIX different treatments across the site — .hero2__mark (two
 * variants), .pv3g__wm on the product heroes, .bhhead__wm on the blog,
 * .fc-hero__mark on the Launch Deal and .ph-help__wm on the help centre — with
 * opacities of 0.08, 0.11 and 0.20 and five different offsets. They now all take
 * the SCHOOL-TYPES geometry, which is the one she picked.
 *
 * ⚠ Lives here, not in the six source files, deliberately: modular.css loads last,
 * so this wins without having to keep six sets of numbers in agreement. The
 * original values are left in place, commented as superseded — do not "tidy" them
 * away, they record why each page had its own before.
 * ⚠ .ph-help__wm is a CLIPPING WRAPPER (inset:0; overflow:hidden) with the mark on
 * the inner <img>, not on the span — so it is targeted separately below. Setting
 * top/right on the span would move the clip box, not the mark.
 * ============================================================ */
body.hv2 .hero2__mark,
body.hv2 .hero2--cutout .hero2__mark,
body.hv2 .st .hero2--cutout .hero2__mark,
body.hv2 .pv3g__wm,
body.hv2 .bhhead__wm,
body.hv2 .fc-hero__mark,
body.hv2 .dm-hero__mark {
  top: clamp(-40px, 2vw, 30px);
  bottom: auto;
  right: clamp(-240px, -15vw, -120px);
  width: clamp(420px, 60vw, 960px);
  opacity: 0.07;
}

/* the help centre's mark is drawn by the inner img inside a clipped wrapper */
body.hv2 .ph-help__wm { opacity: 0.07; }
body.hv2 .ph-help__wm img {
  top: clamp(-40px, 2vw, 30px);
  bottom: auto;
  right: clamp(-240px, -15vw, -120px);
  width: clamp(420px, 60vw, 960px);
}

/* ⚠ ONE EXCEPTION, AND IT IS A PERCEPTUAL ONE, NOT A STYLISTIC ONE.
   Every other hero mark is WHITE on a dark card. The Launch Deal hero is a PALE
   card and its mark is sky (#2FB7F1), so the same 7% lands at roughly double the
   perceived contrast — it reads as a large blue shape rather than a ghost. Taken
   to 0.05 so it matches the others by eye, which is what "make them all fainter"
   actually meant. Position and size stay identical to every other hero. */
/* ⚠ Book a Demo joins it — 13 Aug 2026. Rebecca: "the watermark doesnt look like the
   claim deal hero." It didn't: my first attempt copied the numbers out of
   founders-club.css (0.20, width 300-560px, bleeding off the TOP), not knowing THIS
   rule silently overrides all of them. Measured live, the Launch Deal mark is 907px
   wide at 0.05, sitting 30px BELOW the hero's top edge — nothing like what
   founders-club.css says. The page stylesheet is dead code for these five properties.
   ⚠ So .dm-hero__mark is added to the shared rule above and to this exception, rather
   than getting a block of its own. Both heroes are the same blue with the same sky
   mark, so they need the same 0.05. THIS is the "no per-page overrides" rule working
   as intended — and the trap is that a per-page override still LOOKS authoritative
   when you read it. */
body.hv2 .fc-hero__mark,
body.hv2 .dm-hero__mark { opacity: 0.05; }

/* the per-page opacity overrides that made the audience heroes darker are gone too */
body.hv2 .st .hero2--aud.hero2--cutout .hero2__mark,
body.hv2 .st--las .hero2--tile .hero2__mark { opacity: 0.07; }

@media (max-width: 900px) {
  body.hv2 .hero2__mark,
  body.hv2 .hero2--cutout .hero2__mark,
  body.hv2 .st .hero2--cutout .hero2__mark,
  body.hv2 .pv3g__wm,
  body.hv2 .bhhead__wm,
  body.hv2 .fc-hero__mark,
  body.hv2 .dm-hero__mark,
  body.hv2 .ph-help__wm img {
    right: clamp(-200px, -16vw, -100px);
    width: clamp(400px, 66vw, 700px);
  }
}

/* ============================================================
 * PRESS STATES  (10 Aug 2026)
 * 160 selectors on this site had a :hover. Four had an :active. So nothing
 * responded to being pressed — and on a phone, where there is no hover at all,
 * most buttons gave no feedback whatsoever between tap and page change.
 *
 * ⚠ THIS CLOSES A HOLE I OPENED. Earlier the same day I set
 * `-webkit-tap-highlight-color: transparent` in foundation.css to kill Android's
 * grey flash. That is correct ONLY if the control has its own press state. These
 * did not, so for a few hours tapping a button on Android did visibly nothing.
 * If you ever remove these rules, put the tap highlight back.
 *
 * ⚠ USES THE STANDALONE `scale` PROPERTY, NOT `transform: scale()`. This matters:
 * .btn, .blogcard, .partner-card, .mm__apptile and a dozen others already animate
 * `transform` on hover (translateX(4px), translateY(-4px), scale(1.03)…). A
 * `transform: scale(0.97)` on :active REPLACES the whole transform, so a hovered
 * card would snap back to its resting position at the moment you pressed it —
 * a jump, not a press. `scale` is its own property and composes on top, so the
 * card stays lifted and simply presses in. Do not "simplify" this to transform.
 *
 * ⚠ 0.97 on controls, 0.995 on big cards. A card is 400px wide; 0.97 on that is a
 * 12px shift and reads as a glitch. The perceived press should be roughly equal in
 * pixels, not in percent.
 * ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  /* buttons, CTAs and small controls */
  body.hv2 .btn:active,
  body.hv2 .nv__cta:active,
  body.hv2 .hero2__cta:active,
  body.hv2 .pst__cta:active,
  body.hv2 .pcard__cta:active,
  body.hv2 .price__cta:active,
  body.hv2 .sth__cta:active,
  body.hv2 .fs-hero__cta:active,
  body.hv2 .ab2-role__cta:active,
  body.hv2 .os-btn:active,
  body.hv2 .pp-btn:active,
  body.hv2 .auth-submit:active,
  body.hv2 .auth-social__btn:active,
  body.hv2 .cb--cta:active,
  body.hv2 .final-cta__small:active,
  body.hv2 .tcar__btn:active,
  body.hv2 .pstnav__btn:active,
  body.hv2 .modes__nav-btn:active,
  body.hv2 .art__share-btn:active,
  body.hv2 .ph-search__clear:active,
  body.hv2 .directory__search-clear:active,
  body.hv2 .psmenu__tab:active,
  body.hv2 .pv3-tab:active,
  body.hv2 .os-tab:active,
  body.hv2 .mtx-tab:active,
  body.hv2 .pp-hero__tab:active,
  body.hv2 .os-toggle__seg:active,
  body.hv2 .pp-net__chip:active,
  body.hv2 .tcar__dot:active,
  body.hv2 .cornerdots__dot:active { scale: 0.97; }

  /* large surfaces — same perceived movement, much smaller number */
  body.hv2 .blogcard:active,
  body.hv2 .bhfeat:active,
  body.hv2 .st-card:active,
  body.hv2 .ph-guide-card:active,
  body.hv2 .partner-card:active,
  body.hv2 .mm__tile:active,
  body.hv2 .mm__apptile:active,
  body.hv2 .hero-panel__card:active { scale: 0.995; }

  /* ⚠ NO TRANSITION ON THE PRESS — deliberate, and it was nearly a bug.
     The obvious move is `transition-property: scale` so the release eases back.
     But transition-property is one property: declaring it here (in modular.css,
     which loads last) would REPLACE each element's existing transition list —
     .btn's background/border-color/color fades would simply stop working. There is
     no way to append to a transition in CSS.
     An instant press and instant release is a legitimate pattern and is what the
     press is for: immediate acknowledgement that the finger landed. If a softer
     release is ever wanted, it has to be added to each element's OWN transition
     declaration, not bolted on here. */
}

/* ============================================================
 * THE TWO CONVERSION HEROES GO BLUE  (11 Aug 2026)
 * Rebecca: "can we give the founders club hero a blue colour", then "can we do
 * the same colour treatment for the book a demo page too".
 *
 * Brand blue #1B367E with white type, on the Launch Deal (.fc-hero) and Book a
 * Demo (.dm-hero). These are the two pages whose only job is to get a booking,
 * and a solid colour block gives them weight the pale card never had.
 *
 * ⚠ IT LIVES IN THIS FILE, like the rest of .statement--hero, for two reasons:
 *   1. Both pages need it, so a page stylesheet would mean duplicating it and
 *      letting the two drift apart.
 *   2. modular.css LOADS LAST. Written in founders-club.css (where it started),
 *      `body.hv2 .fc-hero .statement__cta` tied with modular's own
 *      `body.hv2 .statement--hero .statement__cta` at (0,3,0) and LOST, so the
 *      button stayed navy-on-blue. Here it simply comes later in the same file.
 *
 * ⚠ About us and compare-school-mis share .statement--hero and KEEP the pale
 *   #F3F7FA card. Never widen these selectors to bare .statement--hero.
 * ============================================================ */
body.hv2 main > section.statement--hero.fc-hero,
body.hv2 main > section.statement--hero.dm-hero { background: var(--ge-blue, #1B367E); }

body.hv2 .statement--hero.fc-hero .statement__line,
body.hv2 .statement--hero.dm-hero .statement__line { color: #fff; }

/* 0.82 white on #1B367E is ~7.5:1 — comfortably past AA at this size */
body.hv2 .statement--hero.fc-hero .statement__sub,
body.hv2 .statement--hero.dm-hero .statement__sub { color: rgba(255, 255, 255, 0.82); }
body.hv2 .statement--hero.fc-hero .statement__note,
body.hv2 .statement--hero.dm-hero .statement__note { color: rgba(255, 255, 255, 0.72); }

/* ⚠ Book a Demo's "30 minutes · free · no slides" line was --ge-blue #1B367E —
   the exact colour the card now is, so it vanished completely. */
body.hv2 .statement--hero.dm-hero .statement__when { color: var(--ge-blue-3, #D9F4FF); }

/* ⚠ THE HIGHLIGHT PILL NEEDS ITS GEOMETRY, NOT JUST ITS COLOURS.
   On the pale-card heroes `.mark` has only ever been blue TEXT — no padding, no
   radius (see the note further up: these heroes deliberately never had a pill).
   Setting background+colour alone therefore painted a hard-edged block behind
   the words with no padding at all, which is what Rebecca saw as the broken
   pill. These four lines are the site's standard pill, copied from
   `.hero2__copy h1 .mark` in home-v2.css — keep them in step with it. */
body.hv2 .statement--hero.fc-hero .statement__line .mark,
body.hv2 .statement--hero.dm-hero .statement__line .mark {
  display: inline-block;
  line-height: 1;
  background: var(--ge-blue-3, #D9F4FF);
  color: var(--ge-blue, #1B367E);
  border-radius: 0.24em;
  padding: 0.1em 0.18em 0.16em;
  margin-block: 0.14em 0.08em;
}

/* ⚠ the CTA was navy-filled, which on a blue card is nearly invisible. White
   pill, navy text, navy arrow disc — the treatment the site already uses for a
   button on photography or any dark surface. */
body.hv2 .statement--hero.fc-hero .statement__cta,
body.hv2 .statement--hero.dm-hero .statement__cta { background: #fff; color: var(--ge-navy, #0F1438); }
body.hv2 .statement--hero.fc-hero .statement__cta:hover,
body.hv2 .statement--hero.dm-hero .statement__cta:hover { background: var(--ge-blue-3, #D9F4FF); color: var(--ge-navy, #0F1438); }
body.hv2 .statement--hero.fc-hero .statement__cta .btn__arrow,
body.hv2 .statement--hero.dm-hero .statement__cta .btn__arrow { background: var(--ge-navy, #0F1438); color: #fff; }

/* ---- Book a Demo's hero needs the same two STRUCTURAL rules the Launch Deal has ----
   (.fc-hero gets these from founders-club.css, which book-a-demo.html does not load.)
   Geometry and opacity are NOT here on purpose — they come from the shared hero-mark
   rule further up this file, which is what makes the two heroes match. */
body.hv2 .dm-hero { position: relative; }
/* the copy sits over the mark — without this the mark paints on top of the headline */
body.hv2 .dm-hero > .container { position: relative; z-index: 1; }
/* ⚠ THE SHARED HERO-MARK RULE ONLY SETS top/right/width/opacity. It assumes the mark
   is ALREADY absolutely positioned with a sized <img> inside — every other hero gets
   that from its own page stylesheet. Book a Demo has no such stylesheet, so without
   these five lines the <span> stays INLINE, `width` is ignored on an inline box, and
   the mark rendered 1312x193 (full container width at the img's intrinsic height)
   instead of 864x954. Measured; this is what fixed it. */
body.hv2 .dm-hero__mark {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  line-height: 0;
}
body.hv2 .dm-hero__mark img { width: 100%; height: auto; display: block; }
