/* ============================================================
 * PRODUCT PAGE v3 — features & benefits led (trial on One, July 2026)
 * ------------------------------------------------------------
 * Loads AFTER home-v2.css and product-page.css. Reads the same
 * per-product palette vars (--pp-1..4, --pp-ink, --pp-dark,
 * --pp-glow) set by the body class (pp pp--one etc), so the whole
 * sheet recolours per product exactly like the v2 template.
 *
 * Sections: photo hero add-ons (headline chips, floating rebuilt
 * UI fragments, trust stickers) · straddling stat tiles · the
 * annotated-screenshot spine · benefit chapters · the before/with
 * toggle card · accordion explorer · switching steps rail.
 * ============================================================ */

/* ============================================================
 * HERO — hero2 photo frame + v3 add-ons
 * ============================================================ */
.hero2--pv3 .hero2__copy {
  max-width: 46rem;
  padding-bottom: clamp(120px, 15vh, 168px);   /* room for the stat tiles straddling the bottom edge */
}
/* hero chrome that school-types.css normally supplies — defined here so
   this sheet stands alone on product pages */
.hero2--pv3 .st-eyebrow {
  display: inline-block;
  margin-bottom: 16px;
  padding: 9px 20px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  color: #fff;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.hero2--pv3 .st-hero__actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.hero2--pv3 .st-hero__ghost.btn {
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.75);
  color: #fff;
}
.hero2--pv3 .st-hero__ghost.btn:hover { background: rgba(255, 255, 255, 0.16); color: #fff; }
.pv3-hero-logo {
  height: clamp(38px, 3.6vw, 52px);
  width: auto;
  display: block;
  margin-bottom: 20px;
}

/* micro-UI chips embedded in the headline — decorative, aria-hidden */
.pv3-h1chip {
  display: inline-flex;
  align-items: center;
  vertical-align: -0.12em;
  margin: 0 0.14em;
}
.pv3-nbr { white-space: nowrap; }   /* keeps the highlighted phrase and its full stop together */
.pv3-h1chip--avatars span {
  display: inline-grid;
  place-items: center;
  font-size: 0.26em;               /* set FIRST — the em sizes below are relative to this */
  width: 3.1em;                    /* ≈ 0.8 of the headline's em */
  height: 3.1em;
  border-radius: 50%;
  border: 0.22em solid #fff;
  background: var(--pp-2);
  color: var(--pp-ink);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.pv3-h1chip--avatars span + span { margin-left: -1.05em; }
.pv3-h1chip--avatars span:nth-child(2) { background: #D9F4FF; color: #1B367E; }
.pv3-h1chip--avatars span:nth-child(3) { background: #F6F4FF; color: #614DBA; }
.pv3-h1chip--tick {
  width: 0.8em;
  height: 0.8em;
  border-radius: 50%;
  background: var(--pp-4);
  color: #fff;
  display: inline-grid;
  place-items: center;
  box-shadow: 0 6px 18px var(--pp-glow);
}
.pv3-h1chip--tick svg { width: 55%; height: 55%; }

/* rebuilt UI fragments floating on the photo (not screenshots — tiny HTML cards) */
.pv3-frag {
  position: absolute;
  z-index: 2;
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 24px 60px rgba(15, 20, 56, 0.35);
  padding: 14px 16px;
  width: clamp(230px, 21vw, 290px);
  opacity: 0;
  animation: pv3-frag-in 600ms var(--hv2-ease) 900ms forwards;
}
.pv3-frag--reg { right: clamp(18px, 5vw, 84px); top: 16%; }
.pv3-frag__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.pv3-frag__title { font-size: 13px; font-weight: 600; color: var(--ge-navy, #0F1438); }
.pv3-frag__count {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--pp-1);
  color: var(--pp-ink);
  white-space: nowrap;
}
.pv3-frag__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 0;
  border-top: 1px solid #EEF2F7;
}
.pv3-frag__ava {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--pp-2);
  color: var(--pp-ink);
  font-size: 10px;
  font-weight: 700;
}
.pv3-frag__name { flex: 1; font-size: 13px; color: var(--ge-navy, #0F1438); }
.pv3-frag__state {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #F3FAEE;
  color: #4C9A2A;
}
.pv3-frag__state svg { width: 12px; height: 12px; }
.pv3-frag__state--late { background: #FFF7E0; color: #B58900; }
.pv3-frag__bar {
  margin-top: 10px;
  height: 6px;
  border-radius: 999px;
  background: var(--pp-1);
  overflow: hidden;
}
.pv3-frag__bar i {
  display: block;
  height: 100%;
  width: 86%;
  border-radius: 999px;
  background: var(--pp-4);
}

/* small floating praise chip — borrows the hero2 chip feel */
.pv3-praise {
  position: absolute;
  z-index: 2;
  right: clamp(120px, 16vw, 300px);
  bottom: 24%;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #fff;
  color: var(--ge-navy, #0F1438);
  font-size: 13.5px;
  font-weight: 600;
  padding: 10px 16px;
  border-radius: 999px;
  box-shadow: 0 16px 40px rgba(15, 20, 56, 0.3);
  opacity: 0;
  animation: pv3-frag-in 600ms var(--hv2-ease) 1600ms forwards;
}
.pv3-praise svg { width: 16px; height: 16px; color: var(--pp-ink); }

/* trust stickers pinned to the photo (frosted — allowed on photography) */
.pv3-stickers {
  position: absolute;
  z-index: 2;
  right: clamp(20px, 3.4vw, 56px);   /* photo corner, clear of the copy column */
  bottom: clamp(100px, 13vh, 150px);
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.pv3-sticker {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: rgba(255, 255, 255, 0.88);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: var(--ge-navy, #0F1438);
  font-size: 13px;
  font-weight: 600;
  padding: 9px 15px;
  border-radius: 999px;
}
.pv3-sticker svg { width: 15px; height: 15px; color: var(--pp-ink); }

@keyframes pv3-frag-in { to { opacity: 1; } }

/* ============================================================
 * GRADIENT HERO (trial B) — rich identity-colour panel, dimmed-
 * connective headline, cut-out person with device, chips riding
 * on a stage that scales with the person.
 * ============================================================ */
.pv3g { padding-top: clamp(10px, 1.4vw, 18px); }
.pv3g__frame {
  position: relative;
  overflow: hidden;
  /* same capped, centred card as every other hero — see the --hero-* tokens in
     home-v2.css (Rebecca, 29 Jul: "all heros follow the same margins as the
     home page"). Was margin-inline: clamp(10px,1.6vw,22px) with no ceiling. */
  width: var(--hero-frame-w);
  margin-inline: auto;
  border-radius: clamp(20px, 2.5vw, 34px);
  min-height: var(--hero-h);   /* shared hero height token — see home-v2.css :root */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 2.5vw, 40px);
  background: #116490;   /* One — solid deep sky ink (swapped from teal, 3 Aug) */
}
/* per-product hero colour — each product's own hue, flat */
.pp--classroom .pv3g__frame { background: #2248C0; }   /* Classroom royal blue */
.pp--sync .pv3g__frame      { background: var(--pp-ink); }   /* Sync sky is too light for white text, so use the AA-safe ink shade (same rule as One's teal) — was hardcoded to a slightly-off #12689B, corrected to match --pp-ink #116490 (Rebecca, 24 Jul) */
.pp--onsite .pv3g__frame    { background: #614DBA; }   /* OnSite violet */
.pp--parent .pv3g__frame    { background: var(--pp-ink); }   /* Parent & Carer pink — same "too light for white text" rule as Sync/One */
.pv3g__copy {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  /* kept clear of the big framed screenshot on the right (Rebecca 23 Jul) */
  max-width: 32rem;
  /* vertical padding right-sized for the shared 66svh hero height — the old
     84px was tuned for a taller 78svh hero (Rebecca 23 Jul) */
  padding: clamp(24px, 2.2vw, 34px) clamp(20px, 3.4vw, 56px);
}
/* oversized ghost icon — a crisp background feature bleeding off the top-right. */
.pv3g__wm {
  position: absolute;
  z-index: 0;
  top: clamp(-200px, -14vw, -90px);
  right: clamp(-220px, -14vw, -110px);
  width: clamp(500px, 70vw, 1120px);
  height: auto;
    /* ⚠ 0.11 — THE ONE VALUE FOR HERO MARKS ON A DARK BACKGROUND (7 Aug 2026).
     "make sure that all watermark icons in heros are the same opacity across the
     site." There were five values: 0.035, 0.065, 0.10, 0.11 and 0.20.
     They are now TWO, not one, and that is deliberate — see the pale-background
     note. On navy/teal/product colour the mark is a pale glyph on a dark field
     and 0.11 is the site's long-standing value. */
  opacity: 0.11;
  pointer-events: none;
}
/* one calm device floating on the teal — no person, no pop-ups */
.pv3g__device {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  width: min(56%, 860px);
  height: auto;
  margin-right: clamp(-40px, -2vw, -8px);   /* let it run closer to (and off) the tile edge */
  filter: drop-shadow(-14px 26px 46px rgba(0, 20, 18, 0.34));
  opacity: 0;
  animation: pv3-frag-in 700ms var(--hv2-ease) 250ms forwards;
}
/* OnSite is a phone-first app — a tall portrait handset, not a wide laptop.
   Size by height so it fills the hero and bleeds gently off the bottom edge. */
.pp--onsite .pv3g__device {
  width: auto;
  height: clamp(360px, 58svh, 540px);
  align-self: flex-end;
  margin-right: clamp(40px, 7vw, 120px);
  margin-bottom: clamp(-28px, -2vw, -12px);
  filter: drop-shadow(-16px 28px 50px rgba(10, 6, 30, 0.4));
}

/* ============================================================
   In-hero product screenshot in a chunky white frame that slides in —
   the treatment Rebecca signed off earlier (.os-hero__screen). A raw UI
   screenshot (not a device mockup) in a white bezel, soft shadow, entering
   with a gentle rise + un-rotate. (Rebecca, 23 Jul)
   ============================================================ */
.pv3g__shot {
  position: absolute;
  z-index: 1;
  right: clamp(-44px, -2.6vw, -18px);          /* anchored bottom-right, cropped by the tile edge */
  bottom: clamp(-78px, -5.5vw, -44px);
  width: min(62%, 900px);                       /* big — rises up out of the tile like the inspiration */
  background: #fff;
  border-radius: clamp(16px, 1.8vw, 26px);
  padding: clamp(10px, 1vw, 16px);             /* the chunky white bezel */
  box-shadow: 0 40px 90px rgba(0, 16, 20, 0.38);
  opacity: 0;
  transform: translateY(56px) rotate(-2deg);
  animation: pv3g-shot-in 720ms var(--hv2-ease) 200ms forwards;
}
.pv3g__shot img { width: 100%; height: auto; display: block; border-radius: clamp(8px, 0.9vw, 13px); }
@keyframes pv3g-shot-in { to { opacity: 1; transform: translateY(0) rotate(0deg); } }
@media (prefers-reduced-motion: reduce) { .pv3g__shot { animation: none; opacity: 1; transform: none; } }
/* white logo sits on a SOLID ink chip (brand rule: never straight on gradients) */
.pv3g__logochip {
  display: inline-grid;
  place-items: center;
  background: var(--pp-ink);
  /* chip grown with the logo (Rebecca, 29 Jul: "make the product logos bigger
     on the product page heros") — radius and padding scaled in proportion so
     the chip keeps the same visual weight around the wordmark. */
  border-radius: 20px;
  padding: 16px 22px;
  margin-bottom: 24px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.18);
}
/* was clamp(30px, 2.6vw, 40px) — up ~40% */
/* ⚠ width:auto is LOAD-BEARING — 10 Aug 2026. Every <img> on the site gained
   width/height attributes that day (to stop layout shift). For an <img> the width
   attribute is a sizing hint, so any image the CSS sizes by HEIGHT ONLY suddenly
   took its width from the attribute instead of its own proportions: this chip
   stretched from ~219px to 536px and the logo sat marooned in the middle of it.
   Rebecca: "I dont like the large pill around the onsite logo - it needs to be to
   fit the logo and to keep it left aligned". Do not remove width:auto. */
.pv3g__logochip img { height: clamp(42px, 3.6vw, 56px); width: auto; display: block; }
/* Parent & Carer's lockup is far wider than the other products' wordmarks
   (~7.6:1), so height-matching them would make it overwhelm the hero — size
   it by width instead. (Rebecca, 24 Jul) */
/* the real Parent & Carer logo (Rebecca's SVGs, 27 Jul) is 6.5:1 — close
   enough to the other product wordmarks to size by HEIGHT like they do, so
   every product hero logo now sits at the same scale */
.pp--parent .pv3g__logochip img { height: clamp(39px, 3.5vw, 52px); width: auto; }
.pv3g h1 {
  color: #fff;
  font-size: clamp(36px, 4.4vw, 62px);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0 0 18px;
}
/* ⚠ ALL HERO TYPE IS WHITE (Rebecca, 5 Aug: "i want hero text to be white in the
   product page heros", pointing at OnSite's headline where "solution for" was a
   pale lilac against the violet).
   It was rgba(255,255,255,0.55) — a deliberate device to make the connecting
   words recede so the benefit punched. At 55% on the product colours that lands
   between 2.1:1 (Parent & Carer's teal) and 3.4:1, i.e. under AA even for
   display type, and on OnSite it read as a different colour rather than a softer
   one. Kept as a class rather than stripped from the markup so the phrasing is
   still marked up if a subtler treatment is ever wanted — a slightly lighter
   WEIGHT would do the same job without touching contrast.
   Affects all five product heroes: One, OnSite, Classroom, Parent App, Parents. */
.pv3g h1 .dim { color: #fff; }
/* let the "keep-together" phrase wrap inside the narrower hero column so long
   headlines (e.g. Sync) don't spill onto the screenshot (Rebecca 23 Jul) */
.pv3g h1 .pv3-nbr { white-space: normal; }
.pv3g .pv3-h1chip--tick { background: #fff; color: var(--pp-ink); }
.pv3g__lede {
  color: rgba(255, 255, 255, 0.88);
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.6;
  max-width: 44ch;
  margin: 0 0 26px;
}
.pv3g__proof { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; }
/* staggered entrance for the hero copy — a little personality on load */
.pv3g__copy > * { animation: pv3-rise 620ms var(--hv2-ease) both; }
.pv3g__copy > *:nth-child(1) { animation-delay: 60ms; }
.pv3g__copy > *:nth-child(2) { animation-delay: 150ms; }
.pv3g__copy > *:nth-child(3) { animation-delay: 240ms; }
.pv3g__copy > *:nth-child(4) { animation-delay: 330ms; }
.pv3g__copy > *:nth-child(5) { animation-delay: 420ms; }
@keyframes pv3-rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .pv3g__copy > * { animation: none; } }

/* stage: person + floating chips move and scale as one unit */
.pv3g__stage {
  position: absolute;
  z-index: 1;
  right: clamp(0px, 3vw, 60px);
  bottom: 0;
  height: min(88%, 660px);
  aspect-ratio: 846 / 802;
}
.pv3g__person {
  height: 100%;
  width: 100%;
  object-fit: contain;
  display: block;
  filter: drop-shadow(-18px 24px 48px rgba(0, 20, 18, 0.35));
}
.pv3g__stage .pv3-frag {
  right: -4%;
  top: 2%;
  width: clamp(230px, 18vw, 270px);
}
.pv3g__stage .pv3-praise {
  right: auto;
  left: 22%;          /* hovers by the tablet in her hand */
  bottom: 9%;
}

/* eyebrow + ghost CTA + actions shared with the photo-hero variant */
.pv3g .st-eyebrow {
  display: inline-block;
  margin-bottom: 16px;
  padding: 9px 20px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  color: #fff;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.pv3g .st-hero__actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.pv3g .st-hero__ghost.btn {
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.75);
  color: #fff;
  /* symmetric padding — .btn--large reserves extra left padding for an arrow
     chip, but this ghost button has no arrow, so the label sat off-centre */
  padding-inline: 28px;
}
.pv3g .st-hero__ghost.btn:hover { background: rgba(255, 255, 255, 0.16); color: #fff; }

@media (max-width: 1020px) {
  .pv3g__stage, .pv3g__device, .pv3g__shot, .pv3g__photowrap { display: none; }
  .pv3g__copy { max-width: 100%; }
}
/* .pv3g__photowrap needs a WIDER cutoff than the other hero variants above —
   .pv3g__copy's fixed 32rem width + the card cluster's own minimum size
   collide and overlap between ~1021-1090px (this range includes iPad
   landscape, 1024px — a real, common device, not an edge case). Found by
   measuring getBoundingClientRect() across the range, not by eye.
   Cutoff moved 1100 -> 1300 (24 Jul) after widening .pv3g__copy--wide to
   40rem re-created the same overlap further out (measured clear at 1300,
   still overlapping at 1250) — kept in lockstep with the min-width query
   below that applies the wider column, so the two never disagree. */
@media (max-width: 1300px) {
  .pv3g__photowrap { display: none; }
  .pv3g__copy { max-width: 100%; }
  /* 4 Aug: with the photo cluster hidden, the hero was STILL forced to the full
     shared --hero-h (740px), so on an iPad — and on any laptop under 1300px —
     it rendered as a tall colour tile with copy in the top half and nothing
     underneath. Measured 740px tall against ~420px of content.
     So below this cutoff the hero becomes content-driven: the min-height comes
     off, and the copy's vertical padding grows to carry the tile instead. The
     old 24-34px padding was tuned for a hero whose height came from the photo
     and was centred by align-items — without that it read as cramped.
     NB this deliberately breaks the "all heroes are the same height" rule from
     29 Jul, but only below 1300px and only on the four product pages: at these
     widths there is no photo to be as tall as. Above 1300px nothing changes. */
  .pv3g__frame { min-height: 0; }
  .pv3g__copy { padding-block: clamp(40px, 6vw, 68px); }
}

/* ============================================================
 * HERO PHOTO + FLOATING DATA CARDS (trial, 24 Jul 2026) — a real
 * candid photo on the right, small UI-fragment cards overlapping
 * its corners (stat list / action pill / ring chart), rather than
 * a bare screenshot in a white bezel (.pv3g__shot, kept for other
 * products until this trial is approved). Uses the --pp-* tokens
 * so it drops into any product's palette unchanged.
 * ============================================================ */
/* the shared .pv3g__copy (32rem) was sized to clear the old, much wider
   .pv3g__shot (min(62%,900px)) — with the smaller photo+cards cluster
   there's ~240px of dead space unused, forcing the headline into an
   overly narrow column that wraps to 3 cramped, short lines. Widen it,
   scoped to this trial only, so Classroom/Sync/OnSite (still on
   .pv3g__shot) are untouched.
   IMPORTANT: this must only apply once the photo cluster is actually
   visible (matches the max-width:1300px hide query above) — giving it an
   unconditional rule fought the mobile-fallback's `max-width:100%` on
   equal specificity + later source order, silently breaking the
   copy-only fallback below 1300px (copy stayed stuck at 640px instead of
   going full-width). Scoping into this min-width query sidesteps the
   specificity fight entirely instead of relying on source order. */
@media (min-width: 1301px) {
  .pv3g__copy--wide { max-width: 40rem; }
}
/* SIZING REBUILT (24 Jul 2026): previously sized by width/vw while the frame's
   own height is tied to viewport HEIGHT (svh) — the two don't correlate, so
   at wide-but-short viewports (e.g. 2000x900) the card cluster came out
   TALLER than the frame itself and got clipped (measured -11px overlap).
   Now height-driven, mirroring the frame's own max(px, svh) formula scaled
   down, so it always stays a fixed, generous proportion of the ACTUAL frame
   height regardless of aspect ratio. align-self:center (not a manual
   bottom-offset) gives equal top/bottom teal margin by construction, not by
   hand-tuned clamp() guesswork. */
/* BALANCE ON WIDE SCREENS (24 Jul, Rebecca): on a full-bleed tile the
   space-between flex flings copy + photo to the extreme edges, leaving a
   huge void in the middle (measured 832px at 2000px wide). Cap the CONTENT
   to a centred ~1340px zone via symmetric padding — the teal tile stays
   full-bleed/immersive, only the content stops stretching, matching how the
   rest of the site constrains content on large screens. Scoped to the photo
   trial (--photo) so the .pv3g__shot product heroes are untouched. Only
   engages once the frame exceeds the cap (padding floors at 0 below that),
   so the already-approved ≤1360px layout is unchanged. */
.pv3g__frame--photo {
  /* 100% here is the section's (viewport) width, so the cap engages at ~1360px
     viewport — chosen to exactly equal the approved reference width, so at or
     below 1360 the padding floors at 0 and that layout is pixel-unchanged.
     Floor changed from a flat 0px to .pv3g__copy's own former padding value
     (Rebecca, 28 Jul: "the margin used for the text on left isnt the same as
     the content on the right"). Measured root cause: below ~1460px the frame's
     own cap contributed 0-20px while .pv3g__copy ADDED its own clamp(20px,
     3.4vw,56px) horizontal padding on top of it, and .pv3g__photowrap's margin
     was zeroed only above 1400px — so the text's left inset (frame padding +
     copy's own padding, ~44-89px) never matched the photo's right inset (frame
     padding alone above 1400, or a fixed ~72px JS gap below it). Now BOTH
     sides get their gutter from this one value and nothing else, so they are
     equal by construction at every width instead of by coincidence at some. */
  padding-inline: max(clamp(20px, 3.4vw, 56px), var(--hero-inset));
}
/* the frame now provides the full gutter (see above) — .pv3g__copy and
   .pv3g__photowrap no longer add their own competing horizontal margin/padding
   on top of it, at any width (this used to be conditional on a 1400px media
   query, which is exactly why the mismatch only showed up below that width). */
.pv3g__frame--photo .pv3g__copy { padding-inline: 0; }
/* The floating stat/pill/chart cards are positioned to BLEED past the photo by
   clamp(16px,2vw,30px) (see .pv3g__card--tr/--br's negative `right`). The frame
   padding alone therefore gutters the PHOTO, not the cluster's true outer edge:
   measured at 1512px the text sat 54px in while the rightmost card sat 24px in
   (Rebecca, 29 Jul, on her laptop: "the product pages dont seem to have the
   same margins for the hero content. we brought it in before").
   Pushing the wrap in by exactly the bleed distance lands the cluster's outer
   edge on the same inset as the text at every width. Same value as the cards'
   offset, so the two cannot drift apart. */
.pv3g__frame--photo .pv3g__photowrap { margin-right: clamp(16px, 2vw, 30px); }
.pv3g__photowrap {
  position: relative;
  z-index: 1;
  height: max(340px, 50svh);
  width: auto;
  flex: 0 0 auto;
  align-self: center;
  margin-left: auto;
  /* --pv3g-gap is measured live in product-v3.js from the frame's and
     photo's ACTUAL rendered heights — a formula alone can't be exact
     because the frame can grow taller than its min-height when the copy
     text needs more room (measured: 524.8px actual vs 480px predicted at
     one width/height combo), which shifts the true gap independently of
     any px/svh formula. The calc() fallback only fires with JS disabled. */
  margin-right: var(--pv3g-gap, calc((var(--hero-h) - max(340px, 50svh)) / 2));
  opacity: 0;
  transform: translateY(40px);
  animation: pv3g-shot-in 720ms var(--hv2-ease) 200ms forwards;
}
.pv3g__photo {
  /* pinned to a fixed aspect ratio + object-fit:cover so every product's
     hero photo renders at the SAME box size regardless of its own source
     image's natural shape (previously width:auto let each photo's ratio
     drive its own width — Classroom's wider new photo rendered 603px vs
     the other three's ~474-495px). (Rebecca, 24 Jul) */
  display: block;
  height: 100%;
  aspect-ratio: 1.1 / 1;
  width: auto;
  object-fit: cover;
  object-position: center;
  border-radius: clamp(18px, 2vw, 28px);
  box-shadow: 0 40px 90px rgba(0, 16, 20, 0.38);
}
.pv3g__card {
  position: absolute;
  z-index: 2;
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 18px 40px rgba(15, 20, 56, 0.22);
}
/* POSITION MODIFIERS — split out from the card TYPE classes so each product
   can mix a different set of cards into the same corner slots (Rebecca: "I
   don't want the tiles to be the same layout on each product").
   Deliberately NEGATIVE now (Rebecca, 28 Jul: "i want the pills to overlap
   the image too") — every corner bleeds up/out past the photo's own edge
   onto the frame's colour behind it, consistently on all four cards, rather
   than the earlier back-and-forth (bled unevenly → pulled fully inset →
   now bled again, evenly this time). The bleed amount is capped well inside
   .pv3g__photowrap's own equal margin (computed in product-v3.js as
   --pv3g-gap, typically 30-70px) so a card never reaches the frame's own
   edge and gets clipped by its overflow:hidden. --bl keeps its raised
   `bottom` so it still clears a --br card sitting below it. */
.pv3g__card--tl { top: clamp(-30px, -2vw, -16px); left:  clamp(-30px, -2vw, -16px); }
.pv3g__card--tr { top: clamp(-30px, -2vw, -16px); right: clamp(-30px, -2vw, -16px); }
.pv3g__card--bl { bottom: clamp(70px, 7vw, 96px);   left:  clamp(-30px, -2vw, -16px); }
.pv3g__card--br { bottom: clamp(-26px, -1.8vw, -14px); right: clamp(-30px, -2vw, -16px); }

/* ============================================================
 * PER-PRODUCT CARD CLUSTERS (Rebecca, 28 Jul: first "the tiles are on her
 * face" re: One's stat card grazing the teacher's hair, then "I want each of
 * the pills on each product page to be different... a few are the same
 * sizes and position"). Every product was pulling its 3 cards from the same
 * three fixed corner slots at the same size — fixing One's overlap the same
 * way Classroom/Sync's had already been fixed would have just made a FOURTH
 * identical corner. Instead each product now has its own sizes and
 * positions, chosen first to clear that photo's actual face/focal point,
 * second so no two products read as the same template.
 * ============================================================ */

/* ---- ONE — teacher's face is upper-right-of-centre. Stat list narrowed and
   bleeding up-left (away from her, not toward), which if anything gives it
   MORE clearance than a plain inset would; ring chart is enlarged into the
   hero's one big, bold element. ---- */
.pp--one .pv3g__card--tl.pv3g__cardstat { width: auto; max-width: 200px; }
.pp--one .pv3g__card--bl { bottom: clamp(84px, 8.6vw, 112px); }
.pp--one .pv3g__card--br.pv3g__cardchart { width: min(58%, 264px); padding: 20px; }
.pp--one .pv3g__card--br .pv3g__ring { width: 136px; height: 136px; }

/* ---- CLASSROOM — teacher's face is in the photo's own top-left corner.
   Note card keeps its big drop below his head (24 Jul fix) — bleeding it
   up/left doesn't reduce that vertical clearance, since his head is what the
   drop was clearing, not the card's horizontal reach. Pill sits lower than
   anyone else's, and the big-number card is the widest of the four. ---- */
.pp--classroom .pv3g__card--tl { top: clamp(150px, 19vw, 230px); }
.pp--classroom .pv3g__card--bl { bottom: clamp(-20px, -1.4vw, -6px); }
.pp--classroom .pv3g__card--br.pv3g__cardbig { width: min(64%, 280px); padding: 16px 22px; }

/* ---- SYNC — her face is upper-centre-left. Stat list narrowed (as One's
   is) — bleeding it up-left is safe for the same reason as One's, since the
   narrow max-width is what keeps its RIGHT edge clear of her, and bleed only
   moves the left/top edges further away from her, not closer. "Last sync"
   pill floats much higher than the other products' bottom-left card, and
   the sync-progress bar is the widest bar of the four. ---- */
.pp--sync .pv3g__card--tl.pv3g__cardstat { max-width: min(38%, 200px); }
/* Dropped from clamp(100px,10vw,132px) — the stat card above gained a 4th MIS
   row (ScholarPack, 29 Jul) and grew ~53px taller, which squeezed the gap
   between the two cards to just 9px on a short window (the photo is sized from
   svh, so the shorter the viewport the tighter it got). That is the same
   too-close-together crowding Rebecca flagged on Classroom. Moving the pill
   down restores a clear gap at every size; it can't collide with the --br bar
   below because that sits on the right (bar left edge 257px vs this pill's
   right edge 128px). */
.pp--sync .pv3g__card--bl { bottom: clamp(40px, 4.5vw, 64px); }
.pp--sync .pv3g__card--br.pv3g__cardbar { width: min(66%, 288px); }

/* ---- ONSITE — no face in frame (pupils walking away), so the freest to
   differ structurally: the live count sits top-RIGHT instead of top-left
   (see .pv3g__card--tr above and the markup change in onsite.html), the
   only product whose primary card isn't in the top-left corner at all. ---- */
.pp--onsite .pv3g__card--br.pv3g__cardbar { width: min(54%, 236px); }

/* ---- TYPE: stat list (One = pupil stats · Sync = connected systems) ----
   Sized up across the board (Rebecca, 28 Jul: "make the tiles/pills nice
   and big") — rows are taller, the number jumps a full size, and the
   whole card can run wider since it's now allowed to bleed rather than
   stay strictly inset. */
.pv3g__cardstat {
  width: min(54%, 280px);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pv3g__statrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  border-radius: 13px;
  background: #F3F6FA;
  font-size: 14px;
  color: var(--ge-navy, #0F1438);
}
.pv3g__statrow strong { font-size: 19px; font-weight: 700; }
/* one accent per row — teal, green, amber — instead of all teal */
.pv3g__statrow--teal  { background: var(--pp-1); }
.pv3g__statrow--teal  strong { color: var(--pp-ink); }
.pv3g__statrow--green { background: var(--ge-green-1, #F3FAEE); }
.pv3g__statrow--green strong { color: var(--ge-green-4, #76A74F); }
.pv3g__statrow--amber { background: var(--ge-yellow-1, #FDF8E9); }
.pv3g__statrow--amber strong { color: var(--ge-yellow-4, #D6AB14); }
/* ---- TYPE: pill (action chip — every product, different label/icon) ---- */
.pv3g__cardpill {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 22px 11px 11px;
  border-radius: 999px;
}
.pv3g__pillico {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 999px;
  background: #E7F4FD;                    /* default sky/blue */
  color: var(--ge-blue, #1B367E);
}
.pv3g__pillico--gold  { background: var(--ge-yellow-1, #FDF8E9); color: var(--ge-yellow-4, #D6AB14); }
.pv3g__pillico--green { background: var(--ge-green-1, #F3FAEE);  color: var(--ge-green-4, #76A74F); }
.pv3g__pillico svg { width: 21px; height: 21px; }
.pv3g__cardpill strong, .pv3g__cardnote strong { display: block; font-size: 16px; color: var(--ge-navy, #0F1438); }
.pv3g__cardpill small, .pv3g__cardnote small { display: block; font-size: 13.5px; color: #7C88A6; }

/* ---- TYPE: note/toast (Classroom praise) — like the pill but rectangular ---- */
.pv3g__cardnote {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 20px 13px 13px;
  border-radius: 18px;
}

/* ---- TYPE: big number (OnSite live count · Classroom points) ---- */
.pv3g__cardbig { padding: 14px 20px; }
.pv3g__biglabel { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--ge-navy, #0F1438); }
.pv3g__bignum { margin-top: 4px; font-size: 38px; font-weight: 800; line-height: 1.05; color: var(--pp-ink); }
/* ⚠ #3D6B22, not --ge-green-4 (#76A74F). On the hero card that token measured
   2.83:1 — under AA even for large text. Same substitution the numbered step
   chips needed on the home page: --ge-green-4 is a decorative green, not a
   text-on-light green. 5.6:1 now. */
.pv3g__bignum--green { color: #3D6B22; }
.pv3g__livedot {
  flex: none; width: 9px; height: 9px; border-radius: 999px;
  background: var(--ge-green-4, #76A74F);
  box-shadow: 0 0 0 0 rgba(118, 167, 79, 0.5);
  animation: pv3g-pulse 1.8s ease-out infinite;
}
@keyframes pv3g-pulse { to { box-shadow: 0 0 0 8px rgba(118, 167, 79, 0); } }
@media (prefers-reduced-motion: reduce) { .pv3g__livedot { animation: none; } }

/* ---- TYPE: progress bar (Sync records synced · OnSite accounted-for) ---- */
.pv3g__cardbar { width: min(62%, 280px); padding: 18px 20px; }
.pv3g__barhead { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 13px; }
.pv3g__barlabel { font-size: 13.5px; color: var(--ge-navy, #0F1438); }
.pv3g__barval { font-size: 22px; font-weight: 800; color: var(--pp-ink); }
.pv3g__bartrack { height: 10px; border-radius: 999px; background: #EAEEF5; overflow: hidden; }
/* LOOPS (Rebecca, 28 Jul: "id like all our product pages to have their
   animations loop"). Was a one-shot width transition triggered by
   product-v3.js adding .is-filled; now a pure-CSS keyframe that fills, holds,
   and resets on a 6s cycle, so no JS is involved and it repeats forever.
   Flat product colour — was a 3-stop gradient (Rebecca, 28 Jul: remove all
   gradients site-wide). */
.pv3g__barfill {
  height: 100%;
  border-radius: 999px;
  width: var(--bar, 80%);
  background: var(--pp-4, #2FB7F1);
  transform-origin: left center;
  animation: pv3g-bar-loop 6s var(--hv2-ease) infinite;
}
@keyframes pv3g-bar-loop {
  0%       { transform: scaleX(0.02); }
  38%, 80% { transform: scaleX(1); }
  100%     { transform: scaleX(0.02); }
}
@media (prefers-reduced-motion: reduce) {
  .pv3g__barfill { animation: none; transform: none; width: var(--bar, 80%); }
}

/* ---- TYPE: ring chart (One = attendance) ---- */
.pv3g__cardchart {
  width: min(54%, 240px);
  padding: 18px;
}
.pv3g__chart-head { font-size: 13.5px; font-weight: 700; color: var(--ge-navy, #0F1438); margin-bottom: 14px; }
.pv3g__ring {
  position: relative;
  width: 116px; height: 116px;
  margin: 0 auto;
  border-radius: 999px;
  display: grid; place-items: center;
  /* An animatable custom property lets a conic gradient be keyframed, which a
     plain gradient cannot be — this is what replaces the old requestAnimationFrame
     sweep in product-v3.js and makes the ring LOOP (Rebecca, 28 Jul). Hard
     edge at the sweep angle, not a blend — flat product colour for the
     filled arc, flat pale track behind it (was two blended accent colours;
     Rebecca, 28 Jul: remove all gradients site-wide). */
  background: conic-gradient(
    var(--pp-4, #2FB7F1) var(--ring-sweep),
    var(--ge-blue-3, #D9F4FF) var(--ring-sweep)
  );
  animation: pv3g-ring-loop 6.5s var(--hv2-ease) infinite;
}
@property --ring-sweep {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
@keyframes pv3g-ring-loop {
  0%       { --ring-sweep: 0deg; }
  42%, 82% { --ring-sweep: 350deg; }   /* 97.2% of the circle */
  100%     { --ring-sweep: 0deg; }
}
@media (prefers-reduced-motion: reduce) {
  .pv3g__ring { animation: none; --ring-sweep: 350deg; }
}
.pv3g__ring::before {
  content: "";
  position: absolute;
  inset: 13px;
  border-radius: 999px;
  background: #fff;
}
.pv3g__ring span {
  position: relative;
  font-size: 18px;
  font-weight: 700;
  color: var(--ge-navy, #0F1438);
}
@media (max-width: 560px) {
  .pv3g__cardstat { width: min(70%, 260px); }
}
/* on very wide screens the 520px cap (tuned/verified at ~1360px) leaves a
   big dead gap between the copy and the photo — grow it, but only above
   the width where 520px stops being the binding constraint, so the
   already-verified reference sizing is untouched. */
/* the old width-based wide-screen override (width:min(40%,640px)) is gone —
   the height-driven sizing above already scales the photo correctly at any
   width, since it now tracks the frame's actual height, not viewport width */

/* ============================================================
 * STAT TILES — uneven strip straddling the hero's bottom edge
 * ============================================================ */
.pv3-stats {
  position: relative;
  z-index: 3;
  margin-top: clamp(-96px, -8vw, -60px);
  padding-bottom: clamp(40px, 4.5vw, 64px);
}
.pv3-stats__grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1.1fr 1.2fr;
  gap: clamp(12px, 1.4vw, 20px);
}
.pv3-stat {
  position: relative;
  overflow: hidden;
  border-radius: 24px;
  padding: clamp(20px, 2vw, 28px);
  min-height: clamp(128px, 12vw, 168px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  box-shadow: 0 18px 44px rgba(15, 20, 56, 0.16);
}
.pv3-stat--ink { background: var(--pp-ink); color: #fff; }
.pv3-stat--tint { background: var(--pp-2); color: var(--pp-ink); }
.pv3-stat--white { background: #fff; color: var(--ge-navy, #0F1438); border: 1px solid #E6ECF4; }
.pv3-stat--navy { background: var(--ge-navy, #0F1438); color: #fff; }
.pv3-stat__num {
  font-size: clamp(32px, 3.4vw, 48px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.01em;
}
.pv3-stat__num sub, .pv3-stat__num span { font-size: 0.5em; font-weight: 700; }
.pv3-stat__cap { margin-top: 8px; font-size: 14.5px; line-height: 1.45; opacity: 0.86; }
.pv3-stat__wm {
  position: absolute;
  top: -8px;
  right: -6px;
  width: 74px;
  height: 74px;
  opacity: 0.09;  /* 5 Aug: watermark opacities cut ~40% ("can we make the watermarks in the product and school type pages fainter"). Was 0.16. */;
}
.pv3-stat__wm svg { width: 100%; height: 100%; }

/* ============================================================
 * BENEFITS grid (replaces the spine) — staggered reveal + hover
 * ============================================================ */
/* top only shortened (Rebecca, 28 Jul: "the gap below the hero beofre the
   next section starts is too big") — this was the standard site-wide band
   spacing, clamp(80px,9vw,140px), same top and bottom. That rhythm is fine
   between two plain bands, but straight after the hero's own bottom margin
   it read as a lot of empty space before the first heading. Bottom is
   untouched, so the gap to whatever comes after .pv3-benefits is unchanged. */
/* 3 Aug: section WASHES now use the home page's warm off-white, not the
   product tint (--pp-1) they used to. Her call: "i want the product pages to be
   using their product colour [but] i want it to reflect the colour we used for
   the home page sections". The product colour is still all over the page — hero
   frame, accent band, chips, icons, buttons, stat tiles — it just no longer
   tints whole sections, so a product page now reads with the home page's
   off-white / white rhythm. --pp-1 and --pp-2 are untouched as COMPONENT tints. */
.pv3-benefits { background: var(--ge-bg-warm, #F7F6F3); padding: clamp(48px, 5.4vw, 84px) 0 clamp(80px, 9vw, 140px); }
/* WHITE AFTER A HERO (site rule, Rebecca 4 Aug: "id like to make a rule that
   after a hero there is only white sections"). The band directly below a hero
   is white on every page, so the hero always lands on clean white. The sibling
   selector is deliberate: on OnSite this same section sits FOURTH, between two
   white bands, where it has to stay off-white — so it can't be a blanket rule.
   Everything below shifts one step to keep the off-white / white alternation:
   see .pv3-chapters and the .pp--parent / .pp--one overrides further down. */
.pv3g + .pv3-benefits { background: #fff; }
.pv3-benefits .bandhead { padding-top: 0; }
.pv3-ben__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(16px, 1.8vw, 24px);
  margin-top: clamp(30px, 3.4vw, 50px);
}
.pv3-ben {
  background: #fff;
  /* No stroke (3 Aug: "i can see strokes on the tiles on the parent pages -
     remove any strokes that are on tiles"). It was 1px solid var(--pp-2) — the
     product tint — which read as a visible outline now the sections behind
     these tiles are off-white rather than a matching tint. The border was the
     only thing separating a WHITE tile from a near-white band, though, so the
     site's standard soft card shadow takes over the job (it was previously on
     hover only). Design rules: navy-tinted, very soft. */
  box-shadow: 0 8px 24px rgba(15, 20, 56, 0.08);
  border-radius: 20px;
  padding: clamp(22px, 2.2vw, 30px);
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 520ms var(--hv2-ease), transform 520ms var(--hv2-ease),
    box-shadow 240ms var(--hv2-ease);
}
.pv3-ben.is-in { opacity: 1; transform: none; }
.pv3-ben.is-in:hover { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(15, 20, 56, 0.1); }
.pv3-ben__ico {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: var(--pp-2);
  color: var(--pp-ink);
  margin-bottom: 16px;
}
.pv3-ben__ico svg { width: 26px; height: 26px; }
.pv3-ben h3 { margin: 0 0 8px; font-size: clamp(17px, 1.35vw, 19px); }
.pv3-ben p { margin: 0; font-size: 14.5px; line-height: 1.55; color: #4A5876; }
@media (max-width: 1020px) { .pv3-ben__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .pv3-ben__grid { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) {
  .pv3-ben { opacity: 1; transform: none; transition: none; }
  .pv3-ben.is-in:hover { transform: none; }
}

/* chapter fragment card pops in just after its chapter reveals */
.pv3-chap.rv .pv3-chap__frag {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 520ms var(--hv2-ease), transform 520ms var(--hv2-ease);
}
.pv3-chap.rv.in .pv3-chap__frag { opacity: 1; transform: none; transition-delay: 200ms; }
@media (prefers-reduced-motion: reduce) {
  .pv3-chap.rv .pv3-chap__frag { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
 * SPINE — the annotated screenshot centrepiece (retired; CSS kept)
 * ============================================================ */
.pv3-spine {
  background: var(--pp-1);
  padding: clamp(80px, 9vw, 140px) 0;
}
.pv3-spine .bandhead { padding-top: 0; }
.pv3-spine__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.05fr) minmax(0, 1fr);
  gap: clamp(18px, 2.2vw, 34px);
  align-items: center;
  margin-top: clamp(30px, 3.4vw, 50px);
}
.pv3-spine__side { display: flex; flex-direction: column; gap: clamp(14px, 1.6vw, 22px); }

/* device: white bezel, tabs above, crossfade inside */
.pv3-spine__device { position: relative; }
.pv3-tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-bottom: 12px;
}
.pv3-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border: none;
  border-radius: 999px;
  background: #fff;
  color: var(--pp-ink);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(15, 20, 56, 0.1);
  transition: background 200ms var(--hv2-ease), color 200ms var(--hv2-ease),
    box-shadow 200ms var(--hv2-ease);
}
.pv3-tab svg { width: 14px; height: 14px; }
.pv3-tab:hover { box-shadow: 0 10px 22px rgba(15, 20, 56, 0.16); }
.pv3-tab.is-on { background: var(--pp-ink); color: #fff; box-shadow: 0 8px 22px var(--pp-glow); }
.pv3-tab:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(47, 183, 241, 0.45); }

.pv3-screen {
  background: #fff;
  border-radius: clamp(16px, 1.6vw, 24px);
  padding: clamp(9px, 0.9vw, 13px);
  box-shadow: 0 30px 70px rgba(15, 20, 56, 0.22);
  position: relative;
}
.pv3-frames {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: clamp(14px, 1.3vw, 18px);   /* inner radius scaled with the thicker frame */
  overflow: hidden;
}
.pv3-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  opacity: 0;
  transition: opacity 700ms var(--hv2-ease);
}
.pv3-slide.is-on { opacity: 1; }

/* circular "Only GroupEd" sticker badges pinned to the bezel corners */
.pv3-badge {
  position: absolute;
  z-index: 2;
  width: clamp(78px, 7vw, 96px);
  height: clamp(78px, 7vw, 96px);
  border-radius: 50%;
  background: var(--pp-ink);
  color: #fff;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 10px;
  font-size: clamp(10px, 0.8vw, 11.5px);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  transform: rotate(7deg);
  box-shadow: 0 14px 30px var(--pp-glow);
}
.pv3-badge--tl { top: -26px; left: -26px; transform: rotate(-8deg); }
.pv3-badge--br { bottom: -26px; right: -26px; }
.pv3-badge small { display: block; font-size: 0.82em; font-weight: 600; opacity: 0.85; text-transform: none; letter-spacing: 0.01em; }

/* benefit callouts either side — the active one lights up */
.pv3-call {
  position: relative;
  border-radius: 18px;
  padding: 16px 18px;
  cursor: pointer;
  transition: background 250ms var(--hv2-ease), box-shadow 250ms var(--hv2-ease);
}
.pv3-call h3 { margin: 0 0 5px; font-size: clamp(16px, 1.25vw, 18px); }
.pv3-call p { margin: 0; font-size: 14.5px; line-height: 1.5; color: #4A5876; }
.pv3-call.is-on { background: #fff; box-shadow: 0 14px 34px rgba(15, 20, 56, 0.12); }
.pv3-call:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(47, 183, 241, 0.45); }

/* ============================================================
 * BENEFIT CHAPTERS — photo + one rebuilt fragment on top
 * ============================================================ */
/* PARENTS BAND — the shared .parents* layout from home-v2.css. Only the
   section wrapper is set here: it needs a background that is neither the
   --pp-1 tint above nor the white .pv3-chapters below. --pp-2 is the next
   step up the same tint family. (The earlier number-only .pv3-stat band was
   replaced 3 Aug with the full section.) */
/* Both parent pages run benefits -> parents -> chapters, and every wash on
   the page is one off-white, so these three have to be dealt in alternation
   or two identical backgrounds end up touching, which the design rules bar.
   Re-dealt 4 Aug when the white-after-a-hero rule made benefits white: the
   whole run moved one step, so parents is now off-white (its default) and
   chapters is white. Sequence on Parent App: WHITE, off-white, white, NAVY,
   off-white, white, product-ink, white. */
.pv3-parents { background: var(--ge-bg-warm, #F7F6F3); padding: clamp(64px, 7vw, 104px) 0; }
.pp--parent .pv3-chapters { background: #fff; }
.pp--parent .pv3-feat { background: var(--ge-bg-warm, #F7F6F3); }

/* off-white by default since 4 Aug: on One and Classroom this section follows
   the now-WHITE benefits band, so it takes the off-white turn. The parent pages
   have an extra band between the two and flip it back to white above. */
.pv3-chapters { padding: clamp(80px, 9vw, 140px) 0 clamp(80px, 9vw, 140px); background: var(--ge-bg-warm, #F7F6F3); }
/* One's long-form "See the whole child" band sits third, straight after the
   off-white chapters, so on this page alone the light band goes white. Its
   copy/photo overrides in home-v2.css are tuned for "light", not specifically
   off-white, so they hold. */
.pp--one .band--warm { background: #fff; }
.pv3-chap {
  display: grid;
  grid-template-columns: 1.12fr 1fr;
  gap: clamp(30px, 4.5vw, 72px);
  align-items: center;
  margin-bottom: clamp(56px, 7vw, 96px);
}
.pv3-chap:last-child { margin-bottom: 0; }
.pv3-chap--flip .pv3-chap__media { order: 2; }
.pv3-chap__media { position: relative; }
.pv3-chap__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 24px;
  display: block;
}
.pv3-chap__frag {
  position: absolute;
  right: clamp(-14px, -1vw, -8px);
  bottom: clamp(-26px, -2vw, -16px);
  width: min(72%, 320px);
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 26px 60px rgba(15, 20, 56, 0.22);
  padding: 14px 16px;
}
.pv3-chap--flip .pv3-chap__frag { right: auto; left: clamp(-14px, -1vw, -8px); }
.pv3-chap__copy h3 { margin: 14px 0 12px; font-size: clamp(24px, 2.2vw, 32px); line-height: 1.22; }
.pv3-chap__copy > p { margin: 0 0 16px; font-size: clamp(15.5px, 1.2vw, 17px); line-height: 1.6; color: #4A5876; max-width: 46ch; }

/* alert-style fragment rows (chapter 2) */
.pv3-frag__dot {
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #E8BA19;
}
.pv3-frag__dot--red { background: #E2574C; }
.pv3-frag__tag {
  flex: none;
  font-size: 10.5px;
  font-weight: 600;
  color: #4A5876;
  background: #F3F7FA;
  border-radius: 999px;
  padding: 3px 8px;
}

/* ============================================================
 * TOGGLE CARD — life before / with, flips on as you scroll
 * ============================================================ */
.pv3-switch {
  background: var(--ge-navy, #0F1438);
  padding: clamp(80px, 9vw, 140px) 0;
}
.pv3-switch__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(30px, 4.5vw, 76px);
  align-items: center;
}
.pv3-switch__copy h2 { color: #fff; margin: 14px 0 14px; font-size: clamp(26px, 2.6vw, 38px); line-height: 1.2; }
.pv3-switch__copy > p { color: rgba(255, 255, 255, 0.78); font-size: clamp(15.5px, 1.2vw, 17px); line-height: 1.6; margin: 0 0 22px; max-width: 44ch; }
.pv3-switch__eyebrow {
  display: inline-block;
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* The video that replaced the toggle rows (3 Aug). The white bezel it had
   first was removed at her request — the clip now sits as a plain rounded
   rectangle on the navy, with the message cards providing the framing instead.
   position: relative because those cards are absolutely placed over it. */
.pv3-switch__video {
  position: relative;
  border-radius: clamp(18px, 2vw, 28px);
  overflow: visible;             /* the cards deliberately break the edges */
}
.pv3-switch__video video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: clamp(18px, 2vw, 28px);
}

/* Message cards floating over the clip. White on navy, so they read as app
   surfaces rather than page furniture. Positions are percentages of the video
   box, and each card is capped in ch so a long line can't grow it into its
   neighbour. GSAP animates them in (section 8 of gsap-parent.js); the CSS holds
   them VISIBLE by default so they still appear if GSAP fails to load or the
   visitor prefers reduced motion. */
.pv3-msg {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: max-content;
  max-width: 25ch;
  padding: 12px 14px;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 18px 40px rgba(0, 16, 20, 0.28);
}
/* Outward offsets are in PIXELS, not percentages. At -7% the right-hand card
   grew with the video and pushed 17px past the page edge, giving the whole page
   a horizontal scrollbar (measured 3 Aug). A px offset stays inside the
   container's own side padding at every width. The left card has the copy column
   beside it, so it has room to spare; only the right one is tight. */
.pv3-msg--1 { top: 8%;  left: -28px; }
.pv3-msg--2 { top: 44%; right: -14px; }
.pv3-msg--3 { bottom: 6%; left: 4%; }
.pv3-msg__ava {
  flex: none;
  width: 34px; height: 34px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: var(--pp-ink);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
/* the avatar's white initials measured 4.17:1 on #4C8B2B; #3F7523 takes it to
   5.2 and is indistinguishable at 34px */
.pv3-msg__ava--green { background: #3F7523; }
.pv3-msg__ava--navy  { background: var(--ge-navy, #0F1438); }
.pv3-msg__txt {
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--ge-text-secondary, #4A5876);
}
.pv3-msg__txt strong {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ge-navy, #0F1438);
}
/* On phones the cards would cover the clip entirely and their -6%/-7% offsets
   would push past the viewport edge, so they stack under it as a plain list. */
@media (max-width: 720px) {
  .pv3-switch__video { display: flex; flex-direction: column; gap: 10px; }
  .pv3-msg { position: static; max-width: none; width: auto; box-shadow: 0 10px 24px rgba(0, 16, 20, 0.2); }
}
.pv3-switch__card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 24px;
  padding: 8px 24px;
}
.pv3-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 17px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}
.pv3-row:first-child { border-top: none; }
.pv3-row__label {
  flex: 1;
  font-size: clamp(14.5px, 1.15vw, 16.5px);
  /* ⚠ 0.66, up from 0.42 (5 Aug sweep). This is the "before" side of the
     before/after list, deliberately quieter than the "after" rows — but 42%
     white on the switch card measured 3.92:1, under AA for body text. 66%
     clears 4.5 while staying visibly the fainter of the two states; the
     strikethrough on .pv3-row--struck is what carries the "this is the old way"
     meaning, not the fade, so nothing is lost by making the words readable. */
  color: rgba(255, 255, 255, 0.66);
  transition: color 350ms var(--hv2-ease), text-decoration-color 350ms var(--hv2-ease);
  text-decoration: line-through;
  text-decoration-color: transparent;
  text-decoration-thickness: 1.5px;
}
.pv3-row--on .pv3-row__label { color: #fff; }
.pv3-row--struck .pv3-row__label { text-decoration-color: rgba(255, 255, 255, 0.45); }
.pv3-toggle {
  flex: none;
  width: 46px;
  height: 26px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  position: relative;
  transition: background 350ms var(--hv2-ease);
}
.pv3-toggle::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.55);
  transition: transform 350ms var(--hv2-ease), background 350ms var(--hv2-ease);
}
.pv3-row--on .pv3-toggle { background: var(--pp-4); }
.pv3-row--on .pv3-toggle::after { transform: translateX(20px); background: #fff; }

/* ============================================================
 * WHAT'S IN THE APP — the calm replacement for the 15-row accordion
 * on the Parent & Carer page (3 Aug: "this layout is too overpowering.
 * we need to find a simpler way").
 * A term-and-line list — five group headings, each with its features on
 * ONE line — beside a single in-hand mockup. Every one of the fifteen
 * features is still named; none of them is behind a click, and the
 * fifteen raw phone screenshots are gone. The accordion component
 * below is untouched: One and Classroom still use it.
 * ============================================================ */
.pv3-appall { background: var(--ge-bg-warm, #F7F6F3); padding: clamp(80px, 9vw, 140px) 0; }
.pv3-appall .bandhead { padding-top: 0; }
.pv3-appall__grid {
  display: grid;
  /* The list leads, the photo supports it — hence the uneven split. Widened
     from 1.05/0.95 on 4 Aug: the photo keeps its aspect ratio, so a narrower
     column makes it shorter, which is what gives the now-sticky photo something
     to travel down. At the old split the list was only ~135px taller than the
     photo, so it pinned for barely a tenth of a screen and the effect was
     invisible. */
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: clamp(30px, 4.5vw, 72px);
  /* start, not center: a centred grid item is only as tall as its content, so
     the photo would have no column to travel down and sticky would do nothing */
  align-items: start;
}
.pv3-appall__media {
  order: 2;                      /* photo right, list left */
  border-radius: clamp(18px, 2vw, 28px);
  overflow: hidden;
  box-shadow: 0 30px 70px rgba(0, 16, 20, 0.16);
  /* the photo FOLLOWS the features as you scroll past them (Rebecca, 4 Aug:
     "can we get the 'everything in the app' image to follow as you scroll
     through the features"). Both parent pages get it from this one rule.
     The offset clears the sticky nav (81px) plus a bit of air, so the photo
     never tucks under it. Sticky needs no JavaScript and degrades to normal
     flow in anything that doesn't support it. */
  position: sticky;
  top: 105px;
}
@media (prefers-reduced-motion: reduce) {
  /* a sticky element still moves relative to the page as you scroll, so honour
     the preference and let the photo sit still in the column */
  .pv3-appall__media { position: static; }
}
.pv3-appall__media img { width: 100%; height: auto; display: block; }
.pv3-appall__list { margin: 0; }
.pv3-appall__list dt {
  margin: 0;
  font-size: clamp(17px, 1.5vw, 20px);
  font-weight: 600;
  line-height: 1.3;
  color: var(--ge-navy, #0F1438);
}
.pv3-appall__list dd {
  margin: 8px 0 0;
  /* a little more air per feature (was 18-26px): it suits the wider column and
     lengthens the list, which the sticky photo needs to travel */
  padding-bottom: clamp(20px, 2.4vw, 34px);
  border-bottom: 1px solid #E6ECF4;
  font-size: clamp(15.5px, 1.2vw, 17px);
  line-height: 1.6;
  color: var(--ge-text-secondary, #4A5876);
}
.pv3-appall__list dd + dt { margin-top: clamp(18px, 2vw, 26px); }
.pv3-appall__list dd:last-of-type { border-bottom: 0; padding-bottom: 0; }
@media (max-width: 860px) {
  .pv3-appall__grid { grid-template-columns: 1fr; }
  /* photo first once stacked — and NOT sticky: in one column it would ride down
     over the features it is meant to sit beside */
  .pv3-appall__media { order: 0; position: static; }
}

/* ============================================================
 * ACCORDION EXPLORER — everything in One
 * ============================================================ */
.pv3-acc { background: var(--ge-bg-warm, #F7F6F3); padding: clamp(80px, 9vw, 140px) 0; }
.pv3-acc .bandhead { padding-top: 0; }
.pv3-acc__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(30px, 4vw, 64px);
  align-items: center;
  margin-top: clamp(26px, 3vw, 44px);
}
/* single-column variant for pages with no real UI screenshots to swap in
   (the Parent & Carer app has no product shots yet) — same accordion,
   just without the media column (Rebecca, 24 Jul) */
.pv3-acc__grid--solo { grid-template-columns: 1fr; max-width: 760px; margin-inline: auto; }
.pv3-acc__item { border-bottom: 1px solid #E1E8F0; }
.pv3-acc__btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 19px 4px;
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: clamp(17px, 1.4vw, 20px);
  font-weight: 600;
  color: var(--ge-navy, #0F1438);
  text-align: left;
}
.pv3-acc__bar {
  flex: none;
  width: 5px;
  height: 1.5em;
  border-radius: 3px;
  background: transparent;
  transition: background 250ms var(--hv2-ease);
}
.pv3-acc__item.is-open .pv3-acc__bar { background: var(--pp-ink); }
.pv3-acc__plus { flex: none; margin-left: auto; width: 18px; height: 18px; color: var(--pp-ink); transition: transform 250ms var(--hv2-ease); }
.pv3-acc__item.is-open .pv3-acc__plus { transform: rotate(45deg); }
.pv3-acc__btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(47, 183, 241, 0.45); border-radius: 8px; }
.pv3-acc__body {
  max-height: 0;
  overflow: hidden;
  transition: max-height 320ms var(--hv2-ease);
}
.pv3-acc__item.is-open .pv3-acc__body { max-height: 180px; }
.pv3-acc__body p { margin: 0; padding: 0 4px 20px 23px; font-size: 15px; line-height: 1.55; color: #4A5876; }
.pv3-acc__note { margin: 18px 4px 0; font-size: 14px; color: #4A5876; }
.pv3-acc__note a { color: #1B367E; }
.pv3-acc__media {
  background: #fff;
  border-radius: clamp(16px, 1.6vw, 24px);
  padding: clamp(9px, 0.9vw, 13px);
  box-shadow: 0 26px 60px rgba(15, 20, 56, 0.14);
}
.pv3-acc__frames { position: relative; aspect-ratio: 16 / 9; border-radius: clamp(9px, 0.9vw, 14px); overflow: hidden; }
.pv3-acc__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  opacity: 0;
  transition: opacity 500ms var(--hv2-ease);
}
.pv3-acc__shot.is-on { opacity: 1; }
/* portrait phone-screen variant — for real mobile-app screenshots (already
   include their own status bar / home indicator) rather than the 16:9
   desktop screens the base rule is sized for (Rebecca, 24 Jul: Parent &
   Carer app screenshots). object-position:top so the status bar stays put
   and any crop happens at the bottom. */
.pv3-acc__frames--phone {
  aspect-ratio: 9 / 19.5;
  max-width: 300px;
  margin: 0 auto;
  border-radius: 30px;
}
/* long-list variant — when the feature list runs to a dozen-plus rows it is
   far taller than the phone beside it, so the phone sticks and travels down
   with you as you read instead of stranding a tall empty column (Rebecca,
   27 Jul: "we need to make sure we're adding all these to the page"). */
.pv3-acc__grid--long { align-items: start; }
/* small group labels break a long feature list into themes you can scan
   (hearing from school → how they're doing → instead of ringing up → paying
   → your account) rather than one undifferentiated run of 15 rows */
.pv3-acc__group {
  margin: clamp(26px, 2.6vw, 38px) 0 2px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pp-ink);
}
.pv3-acc__group:first-child { margin-top: 0; }

/* PHONE MOCKUP — the site's white-bezel device treatment (same white body and
   soft navy shadow as OnSite's .os-way__shot--phone), with a chunkier bezel and
   real side buttons so it reads as a handset rather than a rounded picture
   frame (Rebecca, 27 Jul: "make the framing thicker and add some buttons on the
   side"). A NAVY device body was tried before this and rejected — the body
   stays white, matching every other frame on the site. */
.pv3-acc__media--device {
  position: relative;
  background: #fff;
  padding: 15px;
  border-radius: 44px;
  box-shadow: 0 26px 56px rgba(15, 20, 56, 0.28);
}
.pv3-acc__media--device .pv3-acc__frames--phone { border-radius: 30px; }
/* side buttons — light grey so they read against a white body on the
   off-white band. Left sliver is drawn as two segments (silent switch above a
   volume rocker) with one gradient, so no extra markup is needed. */
.pv3-acc__media--device::before,
.pv3-acc__media--device::after {
  content: "";
  position: absolute;
  width: 4px;
  background: #DDE5EE;
}
.pv3-acc__media--device::before {
  left: -4px;
  top: 116px;
  height: 116px;
  border-radius: 3px 0 0 3px;
  background: linear-gradient(
    #DDE5EE 0 30px,
    transparent 30px 46px,
    #DDE5EE 46px 116px
  );
}
.pv3-acc__media--device::after {
  right: -4px;
  top: 152px;
  height: 92px;
  border-radius: 0 3px 3px 0;
}
@media (max-width: 1020px) {
  /* sits on its own above the list, so centre the bezel with it */
  .pv3-acc__media--device { width: 330px; max-width: 100%; margin-inline: auto; }
}
@media (min-width: 1021px) {
  /* the white card hugs the phone rather than being a wide empty panel with a
     narrow phone floating in the middle of it */
  .pv3-acc__grid--long { grid-template-columns: minmax(0, 1fr) auto; }
  .pv3-acc__grid--long > .pv3-acc__media {
    position: sticky;
    top: clamp(100px, 13vh, 150px);
    align-self: start;
  }
  .pv3-acc__grid--long .pv3-acc__frames--phone { width: 300px; max-width: 100%; }
}

/* ============================================================
 * STEPS RAIL — switching in four steps
 * ============================================================ */
.pv3-steps { background: #fff; padding: clamp(80px, 9vw, 140px) 0; }
.pv3-steps .bandhead { padding-top: 0; }
.pv3-steps__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(14px, 1.6vw, 22px);
  margin-top: clamp(28px, 3.2vw, 48px);
}
/* 3-step variant — for pages with a shorter onboarding flow than the
   4-step school-switching rail (Rebecca, 24 Jul: Parent & Carer app) */
.pv3-steps__grid--three { grid-template-columns: repeat(3, 1fr); }
.pv3-step {
  background: var(--ge-bg-light, #F3F7FA);
  border-radius: 20px;
  padding: clamp(20px, 2vw, 28px);
}
.pv3-step__num {
  display: inline-grid;
  place-items: center;
  min-width: 38px;
  height: 38px;
  padding: 0 6px;
  border-radius: 12px;
  background: var(--pp-2);
  color: var(--pp-ink);
  font-size: 15px;
  font-weight: 800;
  margin-bottom: 14px;
}
.pv3-step h3 { margin: 0 0 7px; font-size: clamp(16.5px, 1.3vw, 18.5px); }
.pv3-step p { margin: 0; font-size: 14.5px; line-height: 1.5; color: #4A5876; }
.pv3-step--hi { background: var(--pp-ink); }
.pv3-step--hi h3 { color: #fff; }
.pv3-step--hi p { color: rgba(255, 255, 255, 0.82); }
.pv3-step--hi .pv3-step__num { background: #fff; color: var(--pp-ink); }
/* NAVY HIGHLIGHT STEP (Rebecca, 5 Aug: "make the 02 tile navy" on One, and the
   same on the school-facing Parent app page). Pairs with --hi and simply
   re-points the ink token, so the background, heading, body and number-chip
   rules above all follow it — no duplicated declarations to drift. Classroom and
   the parent-facing Parents page keep their product-colour step. */
.pv3-step--hi.pv3-step--navy { --pp-ink: #0F1438; }

/* staggered entrance (JS adds .is-in per tile, left to right) + hover lift */
.pv3-step {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 520ms var(--hv2-ease), transform 520ms var(--hv2-ease),
    box-shadow 240ms var(--hv2-ease);
}
.pv3-step.is-in { opacity: 1; transform: none; }
.pv3-step__num { transform: scale(0.8); transition: transform 440ms var(--hv2-ease) 140ms; }
.pv3-step.is-in .pv3-step__num { transform: scale(1); }
.pv3-step.is-in:hover { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(15, 20, 56, 0.12); }
/* coloured hover glow removed 3 Aug (Rebecca, site-wide) — this step now
   just takes the neutral lift shadow from .pv3-step.is-in:hover above */
@media (prefers-reduced-motion: reduce) {
  .pv3-step { opacity: 1; transform: none; transition: none; }
  .pv3-step__num { transform: none; transition: none; }
  .pv3-step.is-in:hover { transform: none; }
}

/* ============================================================
 * VOICE — a single testimonial: navy card w/ big quote mark, on a
 * light identity-tint band so it never sits navy-next-to-accent.
 * ============================================================ */
.pv3-voice { position: relative; overflow: hidden; background: var(--ge-bg-warm, #F7F6F3); padding: clamp(80px, 9vw, 140px) 0; }
.pv3-voice__card {
  position: relative;
  z-index: 1;
  overflow: hidden;
  max-width: 900px;
  margin: 0 auto;
  background: var(--ge-navy, #0F1438);
  border-radius: clamp(20px, 2.4vw, 30px);
  padding: clamp(46px, 5.4vw, 78px) clamp(28px, 4vw, 64px) clamp(34px, 4vw, 56px);
  text-align: center;
}
/* Massive brand-mark watermark behind the testimonial card, spanning the
   whole section rather than sitting inside the card (Rebecca, 28 Jul: "behind
   this testimonial tile lets have a massive icon logo that covers the whole
   section"). Sits as a section-level child (a sibling of .container, not
   nested in the card) precisely so the card's own overflow:hidden doesn't
   clip it — it needs to bleed past the card's edges into the band around it.
   Replaces the old oversized quote-mark glyph, which no element ever used. */
.pv3-voice__mark {
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: clamp(560px, 64vw, 980px);
  aspect-ratio: 175.14 / 193.47;
  /* a solid tile in the product's own identity colour, cut to the symbol's
     shape via mask — this (not a pre-coloured SVG file) is what lets the same
     markup work on every product page and always come out on-brand, since
     --pp-4 already swaps per page */
  background: var(--pp-4, var(--ge-blue));
  opacity: 0.06;  /* 5 Aug: watermark opacities cut ~40% ("can we make the watermarks in the product and school type pages fainter"). Was 0.1. */;
  -webkit-mask: url('../assets/images/brand/grouped-symbol-color.svg') center / contain no-repeat;
  mask: url('../assets/images/brand/grouped-symbol-color.svg') center / contain no-repeat;
  pointer-events: none;
}
.pv3-voice__quote { margin: 0; position: relative; z-index: 1; }
.pv3-voice__quote p {
  margin: 0 auto;
  max-width: 22ch;
  font-size: clamp(23px, 3vw, 38px);
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #fff;
}
.pv3-voice__by {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 3px;
  margin-top: clamp(24px, 3vw, 36px);
}
.pv3-voice__name { font-weight: 700; font-size: clamp(16px, 1.3vw, 18px); color: #fff; }
.pv3-voice__role { font-size: 14.5px; color: rgba(255, 255, 255, 0.7); }

/* ============================================================
 * PRICING (trial B) — two columns (price + CTA · what's included),
 * widened to match the contact form card below it.
 * ============================================================ */
.pp-final .pp-card--split {
  max-width: none;
  margin-top: clamp(28px, 3vw, 44px);
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(20px, 2.4vw, 34px);
  align-items: stretch;                 /* both columns share the tall list's height */
  text-align: left;
  padding: clamp(18px, 1.8vw, 26px);
}
/* LEFT — solid ink price panel; price top, reassurance middle, CTA pinned bottom */
.pp-card--split .pp-card__lead {
  display: flex;
  flex-direction: column;
  gap: clamp(22px, 2.6vw, 32px);
  background: var(--pp-ink);
  color: #fff;
  border-radius: 18px;
  padding: clamp(28px, 3vw, 40px);
}
.pp-card--split .pp-card__price { text-align: left; }
.pp-card--split .pp-card__price .pp-price__eyebrow-sm { color: rgba(255, 255, 255, 0.72); }
.pp-card--split .pp-card__price .pp-price__amount { color: #fff; }
.pp-card--split .pp-card__price .pp-price__amount span { color: rgba(255, 255, 255, 0.72); }
.pp-card--split .pp-card__price .pp-price__per { color: rgba(255, 255, 255, 0.9); }
.pp-card--split .pp-card__price .pp-price__then { color: rgba(255, 255, 255, 0.62); }
.pp-card__assure { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 13px; }
.pp-card__assure li { display: flex; align-items: flex-start; gap: 10px; font-size: 14.5px; line-height: 1.4; color: rgba(255, 255, 255, 0.92); }
.pp-card__assure svg { flex: none; width: 18px; height: 18px; margin-top: 1px; color: var(--pp-3); }
.pp-card--split .pp-card__cta {
  width: 100%;
  margin-top: auto;                     /* pins the button to the panel's bottom edge */
  background: #fff;
  color: var(--pp-ink);
}
.pp-card--split .pp-card__cta:hover { background: #EAF1F8; color: var(--pp-ink); }
.pp-card--split .pp-card__cta .btn__arrow { background: var(--pp-ink); color: #fff; }
/* app-store buttons in the pricing panel — replaces the CTA button on pages
   where there's nothing to buy (Parent & Carer app: free, download instead) */
.pp-card__stores { display: flex; flex-wrap: wrap; gap: 10px; margin-top: auto; }
.pp-card__stores .fxb__store { flex: 1 1 180px; }
/* RIGHT — included checklist on the card's tint, top-aligned with the price */
.pp-card--split .pp-card__inc {
  margin-top: 0;
  border-top: none;
  padding: clamp(26px, 3vw, 40px) clamp(6px, 1vw, 16px) clamp(10px, 1.4vw, 18px);
  display: flex;
  flex-direction: column;
}
/* closing reassurance block — pinned to the bottom so the right column's foot
   lines up with the left panel's CTA, and the short feature list no longer
   leaves dead space beneath it. */
.pp-card__reassure {
  margin-top: auto;
  padding-top: clamp(22px, 2.6vw, 32px);
  border-top: 1px solid var(--pp-2);
  display: flex;
  gap: 14px;
  align-items: flex-start;
  text-align: left;
}
.pp-card__reassure-ico {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 12px;
  background: var(--pp-ink);
  color: #fff;
}
.pp-card__reassure-ico svg { width: 24px; height: 24px; }
.pp-card__reassure-title { margin: 0 0 5px; font-weight: 700; font-size: 16.5px; color: var(--pp-ink); }
.pp-card__reassure-text { margin: 0 0 8px; font-size: 14px; line-height: 1.55; color: #4A5876; }
.pp-card__reassure-stat { margin: 0; font-size: 14px; line-height: 1.5; color: #4A5876; }
.pp-card__reassure-stat strong { color: var(--pp-ink); font-size: 20px; font-weight: 800; margin-right: 2px; }
@media (max-width: 860px) { .pp-card__reassure { margin-top: clamp(22px, 4vw, 30px); } }
/* OnSite reuses two launch-price tiles inside the narrow ink panel. Their big
   amounts can't shrink, so side-by-side they overflow the panel edge — stack
   them at every width (the panel is always narrow relative to two big prices). */
.pp-card--split .pp-card__price .os-price__row { grid-template-columns: 1fr; gap: 12px; margin-top: 4px; }
@media (max-width: 860px) {
  .pp-final .pp-card--split { grid-template-columns: 1fr; align-items: start; }
  .pp-card--split .pp-card__inc { padding: clamp(24px, 3vw, 32px) 4px 4px; }
}

/* ============================================================
 * RESPONSIVE
 * ============================================================ */
@media (max-width: 1020px) {
  .pv3-frag, .pv3-praise { display: none; }         /* photo chips hide with the hero2 chips */
  .pv3-stickers { bottom: clamp(80px, 10vh, 110px); }
  .pv3-stats__grid { grid-template-columns: 1fr 1fr; }
  .pv3-spine__grid { grid-template-columns: 1fr; }
  .pv3-spine__device { order: -1; }
  .pv3-spine__side { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .pv3-chap, .pv3-switch__grid, .pv3-acc__grid { grid-template-columns: 1fr; }
  .pv3-chap--flip .pv3-chap__media { order: 0; }
  .pv3-chap__frag { right: 8px; bottom: -22px; }
  .pv3-chap--flip .pv3-chap__frag { left: 8px; }
  .pv3-acc__grid > .pv3-acc__media { order: -1; }
  .pv3-steps__grid { grid-template-columns: 1fr 1fr; }
  .pv3-badge--tl { top: -18px; left: -8px; }
  .pv3-badge--br { bottom: -18px; right: -8px; }
}
@media (max-width: 640px) {
  .pv3-stats { margin-top: clamp(-70px, -12vw, -48px); }
  .pv3-stats__grid { gap: 10px; }
  .pv3-stat { min-height: 112px; border-radius: 18px; }
  .pv3-spine__side { grid-template-columns: 1fr; }
  .pv3-steps__grid { grid-template-columns: 1fr; }
  .pv3-stickers { display: none; }
  .pv3-switch__card { padding: 4px 16px; }
}

/* ============================================================
 * REDUCED MOTION
 * ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .pv3-frag, .pv3-praise { animation: none; opacity: 1; }
  .pv3-slide, .pv3-acc__shot { transition: none; }
  .pv3-toggle, .pv3-toggle::after, .pv3-row__label { transition: none; }
  .pv3-acc__body { transition: none; }
}

/* ============================================================
 * HERO CARDS — LOOPING MOTION ON EVERY PRODUCT PAGE
 * Rebecca, 28 Jul: "id like all our product pages to have their
 * animations loop. dont be afraid to use colour."
 * One (ring) and OnSite/Sync (bars) already loop via their own
 * keyframes above. Classroom and the Parent App had NO motion at
 * all — their cards are a note, a pill and a big number — so the
 * shared card furniture gets its own loops here, which means every
 * product hero now has something alive in it.
 * All loops are slow and shallow, the cards themselves never move,
 * and prefers-reduced-motion stops the lot.
 * ============================================================ */

/* 1. the icon chip on a note/pill card breathes, and its colour cycles
      through the product hue and green so there are two colours in play */
.pv3g__pillico {
  animation: pv3g-ico-loop 4.4s var(--hv2-ease) infinite;
}
@keyframes pv3g-ico-loop {
  0%, 100% { background: var(--pp-2, #E8E4F9); color: var(--pp-ink, #1B367E); transform: scale(1); }
  45%      { background: #E6F3D9;              color: #4F7D2C;               transform: scale(1.07); }
}

/* 2. a big number gets an animated underline sweep in the flat product
      colour — a sparkline-ish accent rather than a static figure. Was a
      product-colour-to-green blend (Rebecca, 28 Jul: remove all gradients
      site-wide). */
/* overflow:hidden only — NOT position:relative. .pv3g__card already sets
   position:absolute (needed for the --tl/--tr/--bl/--br corner placement);
   this rule's own position:relative silently overwrote that, so the card
   rendered in normal document flow instead of pinned to its corner. That
   went unnoticed while every cardbig used --tl, because "first in flow,
   nudged by a small relative offset" happens to land close to true top-left
   anyway — moving OnSite's card to --tr exposed it outright (Rebecca, 28
   Jul), since a relative right/top offset from an in-flow position is
   nothing like an absolute top-right corner. */
.pv3g__cardbig { overflow: hidden; }
.pv3g__cardbig::after {
  content: "";
  position: absolute;
  left: 16px; right: 16px; bottom: 7px;
  height: 3px;
  border-radius: 999px;
  background: var(--pp-4, #2FB7F1);
  transform-origin: left center;
  animation: pv3g-underline-loop 5.2s var(--hv2-ease) infinite;
}
@keyframes pv3g-underline-loop {
  0%       { transform: scaleX(0); opacity: 0.35; }
  40%, 78% { transform: scaleX(1); opacity: 1; }
  100%     { transform: scaleX(0); opacity: 0.35; }
}

/* 3. the pill card's tick chip pulses on its own beat, in green */
.pv3g__cardpill .pv3g__pillico { animation-delay: 1.1s; }

@media (prefers-reduced-motion: reduce) {
  .pv3g__pillico { animation: none; }
  .pv3g__cardbig::after { animation: none; transform: none; opacity: 1; }
}

/* ============================================================
 * ACCORDION MOCKUP — COLOURED BACKDROP
 * Rebecca, 28 Jul: "i want to add a coloured background behind the
 * uni mockup. My goal is to add colour to this site. use any brand
 * colour but navy or white."
 *
 * The panel takes each product's own bright identity colour via
 * --pp-4, so it is a different colour on every product page (One
 * teal · OnSite violet · Classroom royal blue · Sync sky · Parent
 * pink) and never navy or white.
 *
 * The screenshot KEEPS its chunky white frame — that is a standing
 * site rule — so the white band now sits between the coloured panel
 * and the UI, rather than being the outermost layer. It is done with
 * a BORDER on .pv3-acc__frames rather than padding because the
 * screenshots are absolutely positioned with inset:0, which resolves
 * against the padding box: padding would not inset them, a border does.
 * ============================================================ */
.pv3-acc__media {
  background: var(--pp-4, #2FB7F1);
  padding: clamp(16px, 1.7vw, 28px);
}
.pv3-acc__frames {
  /* 4 Aug: was clamp(9px,0.95vw,14px) = 13.5px, half the site's frame. The
     white photo frame is ONE thickness sitewide — see --photo-frame. */
  border: var(--photo-frame) solid #fff;
  background: #fff;
}

/* ============================================================
 * BIGGER "EVERYTHING IN" TILE, WITH TWO WATERMARKS (4 Aug 2026)
 * "make the screenshot tiles bigger so we can add the icon to it in an
 * abistract way like in the example ive shared. can you trial it on the one
 * product page."
 * Trialled on One, then rolled out ("you can roll this out to the other
 * product pages"). Selectors hang off the .pv3-acc__media--mark MODIFIER, not a
 * page class, so a page opts in with markup alone: add the modifier, the mark
 * span and the caption span. The grid widening uses :has() on the same
 * modifier, so a page without it keeps the old column split.
 * How it works: the media column takes more of the row, and the panel's
 * padding is deliberately LOPSIDED — normal at the top and right, deep at the
 * bottom and left. That leaves a field of product colour on the diagonal,
 * which is what her reference has, and the hexagon mark fills it at 20% white,
 * bleeding off both edges so it reads as a brand shape rather than a logo
 * sitting in a corner. The panel clips it, so nothing escapes the tile.
 * ============================================================ */
.pv3-acc__grid:has(.pv3-acc__media--mark) {
  /* 1fr / 1.15fr -> the tile takes noticeably more of the row. The accordion
     still holds its four rows comfortably at this width. */
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.24fr);
}
.pv3-acc__media--mark {
  position: relative;
  isolation: isolate;                     /* keeps the watermarks behind the frame */
  overflow: hidden;
  /* ⚠ THE WATERMARKS ARE RETIRED — 5 Aug 2026, and BOTH complaints she raised
     have the same cause, so they are fixed together:
       "ive decided i dont like the watermark logo"
       "the screenshot isnt central to tile"
     --pv3-foot reserved a 58–96px band at the BOTTOM of the tile to hold the
     caption, against 18–30px at the top. The side padding was already even (an
     earlier pass fixed a left-heavy version she caught), so what remained was a
     vertical offset: the screenshot sat high with a deep empty band beneath it.
     That band existed only for the caption. With the caption gone the padding is
     even on all four sides and the screenshot is genuinely centred.
     The device is now rejected on every page that ever carried it — OnSite first
     (mark, then caption), now One and Classroom — so it is switched off here in
     the shared rule rather than page by page. The markup and the positioning
     rules survive untouched, so it is two lines to bring back.
     --pv3-foot is kept and set to the same value as the rest of the padding: it
     is referenced elsewhere, and this keeps that arithmetic honest. */
  --pv3-foot: clamp(18px, 1.9vw, 30px);
  padding: clamp(18px, 1.9vw, 30px);
}
/* TWO watermarks share the foot band (her third pass: "i wanted to keep the icon
   watermark still i wanted the text as an additonal"). The hexagon takes the
   bottom-LEFT corner and bleeds off both edges so it stays a cropped shape
   rather than a logo; the caption takes the bottom-RIGHT. Because both sit in
   the band below the screenshot, the side padding stays even and the screenshot
   stays centred. */
/* FULL-HEIGHT mark ("make the iccon logo bigger - i want it to cover the height
   of the tile"). It runs the whole height of the tile and bleeds off the left
   edge, so what you see is the right-hand arc of the shape wrapping the
   screenshot — top band, left edge and foot band — rather than a logo in a
   corner. Sized off the tile with top/bottom 0, not a fixed px height, so it
   still fits when the tile grows to hold a taller screenshot. */
/* The mark is now clipped to a COLUMN down the left of the tile ("i dont want it
   to cover text"). Before this it swept right across the foot band and passed
   behind the caption. The column is a hard stop that doesn't depend on how long
   the caption happens to be — captions run from 25 to 28 characters and grow
   with the viewport, so a right-edge offset tuned to one of them would have been
   wrong for the others. Its right edge is masked to a fade rather than a cut, so
   there is no visible vertical seam where the clipping happens. */
.pv3-acc__media--mark .pv3-acc__mark {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 34%;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, #000 60%, rgba(0, 0, 0, 0) 100%);
          mask-image: linear-gradient(90deg, #000 60%, rgba(0, 0, 0, 0) 100%);
}
.pv3-acc__media--mark .pv3-acc__mark img {
  position: absolute;
  /* Sizing history, so nobody re-litigates it: full tile height -> 172% ("even
     bigger") -> 145% ("a bit smaller") -> 118% ("even smaller"). Height is a
     percentage of the COLUMN, which is the full height of the tile, so this is
     still measured against the tile and scales with it. Over 100% on purpose:
     the overshoot top and bottom is what keeps the visible part an arc rather
     than a whole logo, so don't take it below ~105%. */
  top: 50%;
  left: -34%;
  height: 118%;
  width: auto;
  display: block;
  /* the tilt stays small: a steep angle just reads as a wonky edge in the narrow
     bands where you actually see the shape */
  transform: translateY(-50%) rotate(-5deg);
  /* 14%, down from 20% — across an area this size, 20% started to read as a
     second colour rather than a watermark */
  opacity: 0.08;  /* 5 Aug: watermark opacities cut ~40% ("can we make the watermarks in the product and school type pages fainter"). Was 0.14. */;
}
/* the caption names the screenshot currently on show; product-v3.js keeps it in
   step with the open accordion row */
/* The caption is a strip exactly as tall as the foot band, with its text centred
   in it ("move the text water mark up so its central to the screenshot and edge
   of tile") — so it sits midway between the screenshot's bottom edge and the
   bottom of the tile, not tucked against the corner. Reading the band from the
   same --pv3-foot token means the two can't fall out of step. */
.pv3-acc__media--mark .pv3-acc__wmtext {
  position: absolute;
  right: clamp(14px, 1.5vw, 24px);
  bottom: 0;
  height: var(--pv3-foot);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  z-index: 0;
  /* the longest caption ("Timetabling, seating & cover") is 28 characters, so it
     is smaller than the single fixed title it replaced */
  max-width: 62%;
  font-size: clamp(17px, 2.1vw, 30px);
  font-weight: 600;                       /* the site heading weight */
  line-height: 1.06;
  letter-spacing: -0.02em;
  text-align: right;
  color: rgba(255, 255, 255, 0.14);
  pointer-events: none;
  user-select: none;
  transition: opacity 180ms var(--hv2-ease);
}
.pv3-acc__media--mark .pv3-acc__wmtext.is-swapping { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .pv3-acc__media--mark .pv3-acc__wmtext { transition: none; }
}
.pv3-acc__media--mark .pv3-acc__frames { position: relative; z-index: 1; }
@media (max-width: 860px) {
  /* stacked, the tile needs its width for the screenshot; the watermark comes
     down with it and is allowed to wrap rather than run off the corner */
  .pv3-acc__grid:has(.pv3-acc__media--mark) { grid-template-columns: 1fr; }
  .pv3-acc__media--mark {
    --pv3-foot: clamp(44px, 9vw, 62px);
    padding: clamp(16px, 3vw, 24px) clamp(16px, 3vw, 24px) var(--pv3-foot);
  }
  .pv3-acc__media--mark .pv3-acc__wmtext { font-size: clamp(15px, 3.6vw, 22px); right: 14px; max-width: 58%; }
  /* stacked, the tile is much wider than it is tall, so the same height would
     leave the shape's arc off to the left of everything — pulled in. Came down
     with the desktop value when she asked for it a bit smaller. */
  .pv3-acc__media--mark .pv3-acc__mark { height: 128%; left: -8%; }
}

/* The phone variant keeps its white body — a phone is white furniture, not a
   frame — so instead of filling it, the colour becomes a solid ring hugging the
   handset, which reads as the same coloured backdrop. */
.pv3-acc__media--device {
  background: #fff;
  box-shadow:
    0 0 0 clamp(16px, 1.7vw, 28px) var(--pp-4, #2FB7F1),
    0 26px 56px rgba(15, 20, 56, 0.28);
}
.pv3-acc__media--device .pv3-acc__frames { border: 0; }

/* ============================================================
 * PARENT-FACING PAGE EXTRAS (parents.html only, 3 Aug 2026)
 * The parent twin dropped the hub band, the £0 price card and the
 * contact form; these three components are what replaced them.
 * ============================================================ */

/* Features list, deliberately styled like the HOME page's cornerlist
   (gsap-trial.css) — same two-column sky-disc ticks, same 1:1 photo —
   because she asked for that look by name. Duplicated rather than shared:
   this page doesn't load the home sheet, and the home version is entangled
   with .proofstat sizing this page doesn't have. */
/* Standard band padding both ends — the extra bottom padding added for the
   help banner's straddle went with the straddle itself. */
.pv3-feat { background: #fff; padding: clamp(80px, 9vw, 140px) 0; }
.pv3-feat__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(32px, 4.5vw, 76px);
  align-items: center;
}
.pv3-feat__copy h2 {
  margin: 0;
  max-width: 20ch;
  font-size: clamp(32px, 4vw, 54px);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.pv3-feat__sub {
  margin: 16px 0 0;
  max-width: 46ch;
  font-size: clamp(15.5px, 1.2vw, 17px);
  line-height: 1.6;
  color: var(--ge-text-secondary, #4A5876);
}
.pv3-feat__ticks {
  list-style: none;
  margin: clamp(22px, 2.6vw, 34px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(10px, 1.1vw, 14px) clamp(18px, 2vw, 28px);
}
.pv3-feat__ticks li {
  position: relative;
  padding-left: 28px;
  color: var(--ge-navy, #0F1438);
  font-size: clamp(15px, 1.2vw, 16.5px);
  line-height: 1.45;
}
/* the ONE accent: brand sky disc, navy glyph — sky never carries the glyph
   itself (fails AA), same rule as the home list */
/* BULLET RULE (3 Aug 2026): "can we change all site bullet points to be navy
   with white ticks. if they are on a navy section make them white with a navy
   tick." Every list bullet below follows it. Excluded on purpose: the comparison
   matrix's Included/Not-included marks (a data cell, not a bullet) and the ticks
   drawn inside the fake app screenshots (they're product UI, not page furniture).
   */
.pv3-feat__ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.28em;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: var(--ge-navy, #0F1438) center / 10px 10px no-repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
}
.pv3-feat__photo {
  margin: 0;
  aspect-ratio: 1 / 1;
  border-radius: 24px;
  overflow: hidden;
  background: var(--ge-bg-light, #F3F7FA);
}
.pv3-feat__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 900px) {
  .pv3-feat__grid { grid-template-columns: 1fr; }
  .pv3-feat__copy h2, .pv3-feat__sub { max-width: none; }
  .pv3-feat__photo { aspect-ratio: 16 / 10; }
}
@media (max-width: 560px) {
  .pv3-feat__ticks { grid-template-columns: 1fr; }
}

/* Store badges under the steps rail */
.pv3-steps__stores {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: clamp(28px, 3vw, 40px);
}
/* A second, QUIET route to the help centre, at the point people actually get
   stuck — the footer banner is the loud one, and two shouty CTAs for the same
   destination on one page would read as nagging. So this is a plain sentence
   with a link in it, not a button. */
.pv3-steps__help {
  margin: clamp(18px, 2vw, 26px) 0 0;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ge-text-secondary, #4A5876);
}
.pv3-steps__help a {
  color: var(--pp-ink);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.pv3-steps__help a:hover { color: var(--ge-navy, #0F1438); }

/* Help-centre banner — sits where the contact form's card sat, first thing
   inside the footer container, so it keeps the same straddle rhythm without
   the form. Light on navy footer = it must be a white card. */
/* NO straddle. First build pulled this card up over the section above with a
   negative margin, copying the contact band — two bugs at once: the section
   above is pure WHITE, so the top half of a white card simply vanished, and
   that section carries a .seam z-index of 2, so it painted OVER the card and
   clipped it mid-sentence (Rebecca: "bug here"). The contact band gets away
   with the straddle because the sections it hangs from are tinted, not white.
   So this sits wholly inside the navy footer, where a white card reads cleanly
   and nothing can overlap it. z-index guards against any future .seam above. */
.pv3-helpband {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: clamp(18px, 2.5vw, 32px);
  margin-bottom: clamp(48px, 6vw, 80px);
  padding: clamp(28px, 3.4vw, 48px);
  border-radius: 24px;
  background: #fff;
  box-shadow: 0 24px 60px rgba(15, 20, 56, 0.22);
}
.pv3-helpband__copy h2 {
  margin: 0;
  font-size: clamp(24px, 2.4vw, 34px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--ge-navy, #0F1438);
}
.pv3-helpband__copy p {
  margin: 10px 0 0;
  max-width: 46ch;
  font-size: clamp(15px, 1.2vw, 16.5px);
  line-height: 1.55;
  color: var(--ge-text-secondary, #4A5876);
}
@media (max-width: 720px) {
  .pv3-helpband { flex-direction: column; align-items: stretch; text-align: left; }
  .pv3-helpband .btn { justify-content: center; }
}


/* the two "everything in…" watermarks, off (5 Aug) — see the note on
   .pv3-acc__media--mark. display:none rather than opacity so they cost no paint.
   The OnSite-scoped versions of these in onsite-v2.css are now redundant but
   harmless: they set the same thing. */
.pv3-acc__media--mark .pv3-acc__mark,
.pv3-acc__media--mark .pv3-acc__wmtext { display: none; }
