/* ============================================================
   get2gether — homepage rebuild
   Palette: ink #17181C · brand red #D7263D (logo "2") ·
   blue #00539C · yellow #FBC02D · warm cream ground
   Type: Bricolage Grotesque (display) + Source Sans 3 (body)
   ============================================================ */

/* ---------- Fonts (self-hosted, latin subset, variable) ---------- */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../fonts/bricolage-grotesque-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-display: swap;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/source-sans-3-latin.woff2") format("woff2");
  font-weight: 200 900;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  --ink: #17181C;
  --ink-soft: #4B4E58;
  --red: #D7263D;
  --red-deep: #A31226;
  --blue: #00539C;
  --blue-deep: #003A6E;
  --yellow: #FBC02D;
  --cream: #FAF6F0;
  --cream-deep: #F2EAE0;
  --white: #FFFFFF;
  --line: #E7DFD3;

  --font-display: "Bricolage Grotesque", "Arial Black", sans-serif;
  --font-body: "Source Sans 3", "Segoe UI", Arial, sans-serif;

  --fs-hero: clamp(2.45rem, 5.2vw + 1rem, 4.4rem);
  --fs-h2: clamp(1.8rem, 2.4vw + .9rem, 2.9rem);
  --fs-h3: clamp(1.25rem, .6vw + 1rem, 1.45rem);
  --fs-body: 1.125rem;
  --fs-small: .9375rem;

  --pill: 999px;
  --radius: 18px;
  --wrap: 1180px;
  --pad: clamp(1.1rem, 4vw, 2.5rem);

  --shadow-card: 0 10px 30px rgba(23, 24, 28, .10);
  --shadow-lift: 0 18px 44px rgba(23, 24, 28, .16);
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html.js { scroll-behavior: smooth; }
body {
  margin: 0;
  overflow-x: clip;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; display: block; }
h1, h2, h3 { font-family: var(--font-display); line-height: 1.08; margin: 0 0 .6em; letter-spacing: -.01em; }
h2 { font-size: var(--fs-h2); font-weight: 800; }
h3 { font-size: var(--fs-h3); font-weight: 700; }
p { margin: 0 0 1em; }
a { color: var(--blue); }
a:hover { color: var(--red); }
ul { padding: 0; margin: 0; list-style: none; }
blockquote { margin: 0; }
address { font-style: normal; }
em.soft { font-style: normal; color: var(--red); }

:focus-visible { outline: 3px solid var(--red); outline-offset: 3px; border-radius: 4px; }
.mission :focus-visible, .donate :focus-visible, .site-footer :focus-visible { outline-color: var(--yellow); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
.skip-link {
  position: absolute; left: 1rem; top: -4rem; z-index: 200;
  background: var(--ink); color: var(--white); padding: .7rem 1.2rem;
  border-radius: 0 0 12px 12px; text-decoration: none; transition: top .2s;
}
.skip-link:focus { top: 0; color: var(--white); }
/* <main> takes focus so the skip link really lands there (Base.astro), but it
   is a container, not a control: the global :focus-visible rule would otherwise
   draw a 3px red box around the entire page contents. Same call GOV.UK makes
   on its own skip target. The feedback is the page jumping and the next Tab
   starting inside the content. */
main:focus, main:focus-visible { outline: none; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .55rem;
  font-family: var(--font-body); font-weight: 600; font-size: 1.06rem;
  padding: .78rem 1.5rem; border-radius: var(--pill);
  text-decoration: none; border: 2px solid transparent;
  transition: transform .18s ease, box-shadow .18s ease, background-color .18s ease, color .18s ease;
  min-height: 44px;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn-lg { padding: .95rem 1.9rem; font-size: 1.13rem; }
.btn-red { background: var(--red); color: var(--white); box-shadow: 0 8px 22px rgba(215, 38, 61, .32); }
.btn-red:hover { background: var(--red-deep); color: var(--white); }
.btn-ink { background: var(--ink); color: var(--white); box-shadow: 0 8px 22px rgba(23, 24, 28, .25); }
.btn-ink:hover { background: #000; color: var(--white); }
.btn-white { background: var(--white); color: var(--red); box-shadow: 0 8px 22px rgba(0, 0, 0, .18); }
.btn-white:hover { color: var(--red-deep); }
.btn-ghost { background: rgba(255, 255, 255, .12); color: var(--white); border-color: rgba(255, 255, 255, .75); backdrop-filter: blur(3px); }
.btn-ghost:hover { background: rgba(255, 255, 255, .24); color: var(--white); }

.text-link {
  display: inline-flex; align-items: center; gap: .45rem;
  font-weight: 600; color: var(--blue); text-decoration: none;
  border-bottom: 2px solid currentColor; padding-bottom: .1rem;
}
.text-link:hover { color: var(--red); }
.text-link svg { transition: transform .18s; }
.text-link:hover svg { transform: translateX(4px); }
.text-link-light { color: var(--yellow); }
.text-link-light:hover { color: var(--white); }

/* ---------- Eyebrows ---------- */
.eyebrow {
  display: inline-flex; align-items: center; gap: .55rem;
  font-size: .85rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft); margin-bottom: 1rem;
}
.eyebrow-dot { width: .55em; height: .55em; border-radius: 50%; background: var(--red); flex: none; }
.eyebrow-light { color: rgba(255, 255, 255, .85); }
.eyebrow-light .eyebrow-dot { background: var(--yellow); }
.eyebrow-ink { color: rgba(23, 24, 28, .72); }
.eyebrow-ink .eyebrow-dot { background: var(--ink); }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(250, 246, 240, .92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: box-shadow .25s, border-color .25s;
}
.site-header.scrolled { border-color: var(--line); box-shadow: 0 6px 24px rgba(23, 24, 28, .08); }
/* flex-wrap is a WCAG 1.4.4 fix, not a layout preference. A reader who turns
   text up to 200% WITHOUT zooming the page — Firefox's "Zoom text only", a
   user stylesheet, the OS font scale — keeps a 1280px viewport, so no width
   media query fires and the header keeps its desktop row. The Join and Donate
   buttons are `flex: none`, so the row simply ran 43px off the side of the
   screen and took the whole page's horizontal scroll with it. Wrapping lets
   the buttons drop to a second line instead. Nothing wraps at normal size —
   verified box-for-box at 1280 and 375 (scripts/wcag-zoom-lab.mjs). */
.header-inner {
  max-width: var(--wrap); margin: 0 auto; padding: .55rem var(--pad);
  display: flex; align-items: center; gap: 1.2rem; flex-wrap: wrap;
}
.brand { flex: none; display: inline-flex; }
.brand img { width: 116px; height: auto; transition: width .25s; }
.site-header.scrolled .brand img { width: 96px; }
.site-nav { margin-left: auto; }
.site-nav ul { display: flex; gap: clamp(.9rem, 2vw, 1.9rem); flex-wrap: wrap; }
.site-nav a {
  font-weight: 600; color: var(--ink); text-decoration: none; font-size: 1.02rem;
  padding: .45rem .15rem; border-bottom: 3px solid transparent; transition: border-color .18s, color .18s;
}
.site-nav a:hover { color: var(--red); border-bottom-color: var(--yellow); }
.header-donate { flex: none; padding: .6rem 1.25rem; }
.nav-toggle {
  display: none; background: none; border: 0; cursor: pointer; padding: .6rem;
  margin-right: -.4rem;
}
.nav-toggle-box { display: block; width: 26px; height: 18px; position: relative; }
.nav-toggle-bar, .nav-toggle-box::before, .nav-toggle-box::after {
  content: ""; position: absolute; left: 0; width: 100%; height: 3px; border-radius: 3px;
  background: var(--ink); transition: transform .25s, opacity .2s, top .25s;
}
.nav-toggle-bar { top: 7.5px; }
.nav-toggle-box::before { top: 0; }
.nav-toggle-box::after { top: 15px; }
.nav-open .nav-toggle-box::before { top: 7.5px; transform: rotate(45deg); }
.nav-open .nav-toggle-box::after { top: 7.5px; transform: rotate(-45deg); }
.nav-open .nav-toggle-bar { opacity: 0; }

/* ---------- Hero ---------- */
.hero { position: relative; min-height: min(92vh, 780px); display: flex; align-items: flex-end; overflow: hidden; }
.hero-media, .hero-media picture { position: absolute; inset: 0; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 38%; }
.js .hero-media img { animation: kenburns 16s ease-out forwards; }
@keyframes kenburns { from { transform: scale(1.07); } to { transform: scale(1); } }
.hero-scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(13, 14, 18, .88) 0%, rgba(13, 14, 18, .48) 38%, rgba(13, 14, 18, .18) 62%, rgba(13, 14, 18, .30) 100%);
}
.hero-content {
  position: relative; z-index: 2; width: 100%;
  max-width: var(--wrap); margin: 0 auto;
  padding: 7.5rem var(--pad) 4.2rem;
  color: var(--white);
}
.hero-eyebrow { color: rgba(255, 255, 255, .92); }
.hero-eyebrow .eyebrow-dot { background: var(--yellow); }
.hero-title {
  font-size: var(--fs-hero); font-weight: 800; color: var(--white);
  max-width: 13ch; margin-bottom: .45em; text-wrap: balance;
}
.hero-sub { max-width: 46ch; font-size: clamp(1.08rem, .5vw + 1rem, 1.3rem); color: rgba(255, 255, 255, .93); }
.hero-ctas { display: flex; flex-wrap: wrap; gap: .9rem; margin: 1.6rem 0 1.4rem; }
.hero-caption { font-size: .85rem; color: rgba(255, 255, 255, .62); margin: 0; }

/* headline word-stagger */
.js .hero-title .w { display: inline-block; opacity: 0; transform: translateY(.45em); animation: wordUp .7s cubic-bezier(.2, .7, .2, 1) forwards; }
.js .hero-title .w:nth-child(1) { animation-delay: .05s; }
.js .hero-title .w:nth-child(2) { animation-delay: .13s; }
.js .hero-title .w:nth-child(3) { animation-delay: .21s; }
.js .hero-title .w:nth-child(4) { animation-delay: .29s; }
.js .hero-title .w:nth-child(5) { animation-delay: .37s; }
.js .hero-title .w:nth-child(6) { animation-delay: .48s; }
.js .hero-title .w:nth-child(7) { animation-delay: .48s; }
@keyframes wordUp { to { opacity: 1; transform: none; } }

/* the marker swipe — signature moment */
.marker { position: relative; }
@media (min-width: 721px) { .marker { white-space: nowrap; } }
.marker > span { position: relative; z-index: 1; }
.marker-swipe {
  position: absolute; left: -.12em; right: -.12em; bottom: .02em;
  width: calc(100% + .24em); height: .62em; z-index: 0;
}
.js .marker-swipe { clip-path: inset(0 100% 0 0); animation: swipe .55s ease-out 1.05s forwards; }
@keyframes swipe { to { clip-path: inset(0 0 0 0); } }

/* ---------- Stats / ticket strip ---------- */
.stats { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad); position: relative; }
.ticket-strip {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem;
  margin-top: -3.2rem; position: relative; z-index: 5;
}
.ticket {
  background: var(--white); border-radius: 14px; box-shadow: var(--shadow-card);
  display: flex; align-items: stretch; overflow: hidden; position: relative;
}
.ticket-stub {
  flex: none; width: 66px; display: flex; align-items: center; justify-content: center;
  background: var(--cream); color: var(--red);
  border-right: 2px dashed var(--line);
  position: relative; padding: 1rem .35rem;
}
/* punched holes on the perforation */
.ticket-stub::before, .ticket-stub::after {
  content: ""; position: absolute; right: -8px; width: 14px; height: 14px; border-radius: 50%;
  background: var(--cream); box-shadow: inset 0 0 0 20px var(--cream);
  z-index: 2;
}
.ticket-stub::before { top: -7px; background: var(--cream); }
.ticket-stub::after { bottom: -7px; background: var(--cream); }
.ticket-tag {
  display: block; font-size: .6rem; font-weight: 700; letter-spacing: .17em; text-transform: uppercase;
  color: var(--ink-soft); opacity: .75; margin-bottom: .3rem;
}
.ticket-body { padding: 1.05rem 1.15rem 1.1rem; display: flex; flex-direction: column; justify-content: center; }
.ticket-num {
  font-family: var(--font-display); font-weight: 800; font-size: clamp(1.9rem, 1.4vw + 1.4rem, 2.6rem);
  line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums;
}
.ticket-label { font-size: .95rem; color: var(--ink-soft); margin-top: .35rem; line-height: 1.35; }
.stats-source { text-align: right; font-size: .84rem; color: var(--ink-soft); margin: .8rem 0 0; }
.stats-source a { color: inherit; }

/* ---------- Sections shared ---------- */
section { scroll-margin-top: 90px; }
.section-head { max-width: 720px; margin: 0 auto 2.6rem; text-align: center; padding: 0 var(--pad); }
.section-head h2 { text-wrap: balance; }
.section-intro { color: var(--ink-soft); font-size: 1.1rem; }

/* ---------- What we do / photo-print cards ---------- */
.what { padding: 5.2rem 0 4.6rem; }
.print-grid {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.2rem, 2.5vw, 2.2rem);
}
.print-card { position: relative; }
.print-link { display: block; text-decoration: none; color: inherit; }
.print-frame {
  background: var(--white); padding: 12px 12px 14px; border-radius: 6px;
  box-shadow: var(--shadow-card);
  transform: rotate(-1.4deg);
  transition: transform .3s ease, box-shadow .3s ease;
  position: relative;
}
.print-card:nth-child(2) .print-frame { transform: rotate(1.2deg); }
.print-card:nth-child(3) .print-frame { transform: rotate(-.8deg); }
/* tape strip */
.print-frame::before {
  content: ""; position: absolute; top: -12px; left: 50%; transform: translateX(-50%) rotate(-3deg);
  width: 96px; height: 26px; background: rgba(251, 192, 45, .68); border-radius: 3px;
  box-shadow: 0 1px 3px rgba(23, 24, 28, .12);
}
.print-frame img { border-radius: 3px; aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }
.print-link:hover .print-frame, .print-link:focus-visible .print-frame { transform: rotate(0) translateY(-8px); box-shadow: var(--shadow-lift); }
.print-card h3 { margin: 1.35rem 0 .4rem; }
.print-card p { color: var(--ink-soft); font-size: 1.02rem; margin-bottom: .7rem; }
.card-more {
  display: inline-flex; align-items: center; gap: .45rem; font-weight: 600; color: var(--red);
  border-bottom: 2px solid transparent;
}
.print-link:hover .card-more { border-bottom-color: var(--yellow); }
.print-link:hover .card-more svg { transform: translateX(4px); }
.card-more svg { transition: transform .18s; }

/* ---------- Mission band ---------- */
.mission { background: var(--blue-deep); color: var(--white); padding: 5rem 0; margin-top: 1.5rem; }
/* Photos left, words right — the same easy-read rule as .split, which this
   band predates and does not use. */
.mission-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad);
  display: grid; grid-template-columns: .85fr 1.15fr; gap: clamp(2rem, 4vw, 4rem); align-items: center;
}
.mission h2 { color: var(--white); max-width: 18ch; }
.mission p { color: rgba(255, 255, 255, .88); max-width: 52ch; }
.mission-strong { font-weight: 600; color: var(--white); }
.mission-prints { display: grid; gap: 1.4rem; justify-items: center; order: -1; }
.print { background: var(--white); padding: 10px 10px 12px; border-radius: 6px; box-shadow: 0 14px 40px rgba(0, 0, 0, .35); margin: 0; }
.print img { border-radius: 3px; }
.print figcaption { font-size: .82rem; color: var(--ink-soft); padding: .55rem .15rem 0; font-weight: 600; }
.print.small { max-width: 300px; }
.tilt-l { transform: rotate(-2.2deg); }
.tilt-r { transform: rotate(1.8deg); }
.mission-prints .tilt-r { margin-top: -0.4rem; }

/* ---------- Member voices ---------- */
.voices { padding: 5.2rem 0 4.8rem; background: var(--cream); }
.voices-stage {
  max-width: 880px; margin: 0 auto; padding: 0 var(--pad); position: relative; text-align: center;
}
.voices-mark {
  font-family: var(--font-display); font-weight: 800; font-size: 7rem; line-height: .6;
  color: var(--red); display: block; margin-bottom: 1.2rem;
}
.voices-track { position: relative; min-height: 15em; display: grid; }
.voice {
  grid-area: 1 / 1; opacity: 0; transition: opacity .5s ease; pointer-events: none;
}
.voice.is-active { opacity: 1; pointer-events: auto; }
.voice p {
  font-family: var(--font-display); font-weight: 600; font-size: clamp(1.35rem, 1.4vw + 1rem, 1.9rem);
  line-height: 1.35; color: var(--ink); text-wrap: balance; margin-bottom: 1rem;
}
.voice cite { font-style: normal; font-weight: 600; color: var(--ink-soft); font-size: 1rem; }
.voices-controls { display: flex; align-items: center; justify-content: center; gap: 1.1rem; margin-top: 1.8rem; }
.voices-btn {
  width: 46px; height: 46px; border-radius: 50%; border: 2px solid var(--line);
  background: var(--white); color: var(--ink); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .18s, color .18s, transform .18s;
}
.voices-btn:hover { border-color: var(--red); color: var(--red); transform: translateY(-2px); }
/* Pause / play for the rotator (WCAG 2.2.2). One button, two icons: whichever
   one is not the current state is hidden, and main.js keeps the label in step
   so the accessible name always says what pressing it will DO. */
.voices-pause .ic-play { display: none; }
.voices-pause.is-paused .ic-pause { display: none; }
.voices-pause.is-paused .ic-play { display: block; }
.voices-dots { display: flex; gap: .55rem; }
.dot {
  width: 12px; height: 12px; border-radius: 50%; border: 0; padding: 0;
  background: var(--line); cursor: pointer; transition: background .18s, transform .18s;
}
.dot.is-active { background: var(--red); transform: scale(1.25); }

/* WCAG 2.2 2.5.8 Target Size (Minimum): these were 12x12, and 15x15 once the
   active one scaled up — well under the 24x24 floor, and too close together to
   claim the spacing exception. This is the quote picker on a site for adults
   with learning disabilities, so pointer accuracy is the last thing to assume.
   The DOT stays 12px: the button becomes a 24x24 target with the dot drawn as
   a centred pseudo-element, so the hit area grows and nothing looks different.
   Scoped to .voices-dots because `.dot` is also a character in the Backstage
   wordmark. */
.voices-dots .dot {
  width: 24px; height: 24px; background: none; border-radius: 50%;
  display: inline-grid; place-items: center; transform: none;
}
.voices-dots .dot::before {
  content: ""; width: 12px; height: 12px; border-radius: 50%;
  background: var(--line); transition: background .18s, transform .18s;
}
.voices-dots .dot.is-active { transform: none; }
.voices-dots .dot.is-active::before { background: var(--red); transform: scale(1.25); }

/* ---------- Objectives ---------- */
.objectives { padding: 1rem 0 5rem; }
.obj-grid {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.2rem;
}
.obj-card {
  background: var(--white); border-radius: var(--radius); padding: 1.6rem 1.4rem 1.4rem;
  box-shadow: var(--shadow-card); border-top: 4px solid var(--yellow);
  transition: transform .25s ease, box-shadow .25s ease;
}
.obj-card:hover { transform: translateY(-6px); box-shadow: var(--shadow-lift); }
.obj-card:nth-child(2) { border-top-color: var(--red); }
.obj-card:nth-child(3) { border-top-color: var(--blue); }
.obj-card:nth-child(4) { border-top-color: var(--ink); }
.obj-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 14px; background: var(--cream); color: var(--red);
  margin-bottom: 1rem;
}
.obj-card h3 { font-size: 1.18rem; margin-bottom: .45rem; }
.obj-card p { font-size: .98rem; color: var(--ink-soft); font-style: italic; margin: 0; }
.obj-card--plain p { font-style: normal; }

/* ---------- News ---------- */
.news { background: var(--cream-deep); padding: 4.8rem 0; }
.news-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad);
  display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(2rem, 4vw, 4rem); align-items: center;
}
.news-print { max-width: 460px; justify-self: center; }
.news-list h2 { max-width: 16ch; }
.news-list ul { margin: 1.4rem 0 1.6rem; border-top: 1px solid var(--line); }
.news-list li a {
  display: block; padding: 1rem .2rem; border-bottom: 1px solid var(--line);
  text-decoration: none; color: var(--ink); font-weight: 600; font-size: 1.12rem;
  transition: padding-left .18s, color .18s;
}
.news-list li a:hover { color: var(--red); padding-left: .7rem; }
.news-sub { display: block; font-weight: 400; font-size: .92rem; color: var(--ink-soft); margin-top: .15rem; }

/* ---------- Join ---------- */
.join { background: var(--yellow); padding: 5rem 0; }
.join-inner { max-width: 820px; margin: 0 auto; padding: 0 var(--pad); text-align: center; color: var(--ink); }
.join h2 { max-width: 22ch; margin-left: auto; margin-right: auto; }
.join-free {
  display: inline-block; background: var(--ink); color: var(--yellow);
  padding: 0 .35em; border-radius: .18em; transform: rotate(-1.5deg);
}
.join p { max-width: 56ch; margin-left: auto; margin-right: auto; }
.join .btn { margin-top: .6rem; }
.join-note { font-size: calc(.95rem * var(--t-scale, 1)); margin-top: 1.4rem; color: rgba(23, 24, 28, .8); }
/* Mojca, 21 Aug 2026: "I'd like the Member Code of Conduct to be slightly
   bigger." That phrase IS the link, so the link is what grows.

   In `em`, so it is 15% larger than whatever the line around it currently is —
   which means it rides on her Small/Medium/Large choice instead of arguing with
   it, and on the visitor's "Bigger text" as well. A fixed size here would have
   made "Small" leave the link bigger than the sentence containing it. */
.join-note a { color: var(--ink); font-weight: 600; font-size: 1.15em; }

/* ---------- The three text sizes Mojca can choose ----------
   Mojca, 21 Aug 2026, on the yellow band: "I'd like the Member Code of Conduct
   to be slightly bigger, but I do not see how we could change the size of the
   font."

   A MULTIPLIER, NOT A SIZE. `--t-scale` nudges whatever the stylesheet already
   sets for that line; it never states a size of its own. So the site's own
   scale still decides the base, a line she has never touched is untouched
   (`t-md` is ×1, and the var defaults to 1 anyway), and the rule cannot leak
   into anything that has not opted in with a calc().

   In `rem`, so "Bigger text" in the accessibility panel — html { font-size:
   115% } — still multiplies on top. Her choice and the visitor's compose;
   neither overrides the other.

   To size a second line: give it `font-size: calc(<its size> * var(--t-scale, 1))`
   and hand it `sizeClass(...)`. Nothing else. */
.t-sm { --t-scale: .875; }
.t-md { --t-scale: 1; }
.t-lg { --t-scale: 1.25; }

/* ---------- Donate ---------- */
.donate { background: linear-gradient(120deg, var(--red-deep), var(--red) 65%); color: var(--white); padding: 4.6rem 0; }
.donate-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad);
  display: grid; grid-template-columns: 1.2fr .8fr; gap: 2.5rem; align-items: center;
}
.donate h2 { color: var(--white); }
.donate p { color: rgba(255, 255, 255, .92); max-width: 46ch; }
.donate-cta { justify-self: center; text-align: center; }
.donate-note { font-size: .88rem; margin-top: 1rem; color: rgba(255, 255, 255, .85); max-width: 34ch; }
.donate-note a { color: var(--white); }

/* ---------- Funders ---------- */
.funders { padding: 4.4rem 0 4.8rem; text-align: center; }
.funders-line {
  font-size: 1.15rem; font-family: var(--font-body); font-weight: 600; color: var(--ink-soft);
  margin-bottom: 2rem; letter-spacing: 0;
}
.funders-logos {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: clamp(1.6rem, 4vw, 3.5rem); padding: 0 var(--pad);
}
.funders-logos img {
  max-height: 64px; width: auto; filter: grayscale(1) opacity(.65); transition: filter .25s;
}
.funders-logos li:hover img { filter: none; }
.funder-name { font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; color: var(--ink-soft); }
.funders-more { max-width: 640px; margin: 2rem auto 0; font-size: .95rem; color: var(--ink-soft); padding: 0 var(--pad); }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: rgba(255, 255, 255, .85); padding: 3.8rem 0 0; }
.footer-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad) 2.6rem;
  display: grid; grid-template-columns: 1.3fr 1fr 1fr 1fr 1fr; gap: 2.4rem;
}
/* Explore is eleven links. Stacked in one column it set the height of the
   whole footer, so it takes two of the five columns and splits the list
   across them — same links, about half as tall. Source order is unchanged,
   so it still reads top-to-bottom for a screen reader. */
.footer-col--wide { grid-column: span 2; }
/* Only the left of Explore's two link columns sits under the heading, so the
   right one read as an unlabelled fifth section. A panel behind both ties
   them together. The negative side margins let it bleed into the gutter
   while the text stays on the same grid rhythm as Visit us and Contact —
   1.1rem is under half the 2.4rem gap, so it cannot touch its neighbour. */
.footer-col--wide {
  background: rgba(255, 255, 255, .05); border-radius: 14px;
  margin: -1.3rem -1.1rem 0; padding: 1.3rem 1.1rem;
}
.footer-col--wide ul { columns: 2; column-gap: 1.4rem; }
.footer-col--wide li { break-inside: avoid; }
.footer-logo { display: inline-block; background: var(--white); border-radius: 12px; padding: .55rem .8rem; margin-bottom: 1rem; }
.footer-brand p { max-width: 30ch; }
.footer-col h3 { font-size: 1.02rem; color: var(--white); margin-bottom: .8rem; }
/* The other half of the same 1.4.4 fix. At 200% text-only zoom, "Policies +
   documents" and "Accessibility" set the min-content width of their grid
   track, and an `fr` track will not shrink below that — so the two longest
   links in Explore pushed the footer 38px past the viewport. Letting the words
   break lets the track fit. Only these two rules changed; the grid itself is
   untouched, so the 1.3fr brand column and the mobile single-column rule both
   still behave exactly as before. */
.footer-col a, .footer-base p { overflow-wrap: anywhere; }
.footer-col a { color: rgba(255, 255, 255, .85); text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, .25); }
.footer-col a:hover { color: var(--yellow); border-bottom-color: var(--yellow); }
.footer-col li { margin-bottom: .5rem; }
.footer-social { margin-top: .8rem; }
.footer-base { border-top: 1px solid rgba(255, 255, 255, .14); padding: 1.3rem var(--pad); text-align: center; }
.footer-base p { margin: 0; font-size: .9rem; color: rgba(255, 255, 255, .6); }
.footer-base a { color: rgba(255, 255, 255, .75); }
.footer-base a:hover { color: var(--yellow); }

/* ---------- Sticky donate ---------- */
.sticky-donate {
  position: fixed; right: 22px; bottom: 22px; z-index: 90;
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--red); color: var(--white); text-decoration: none;
  font-weight: 700; font-size: 1.02rem; padding: .85rem 1.5rem; border-radius: var(--pill);
  box-shadow: 0 14px 34px rgba(215, 38, 61, .45);
  opacity: 0; transform: translateY(18px) scale(.94); pointer-events: none;
  transition: opacity .3s, transform .3s, background-color .18s;
}
.sticky-donate:hover { background: var(--red-deep); color: var(--white); }
.sticky-donate.is-visible { opacity: 1; transform: none; pointer-events: auto; }
.sticky-donate.is-visible .ic { animation: heartbeat 2.4s ease-in-out infinite; }
@keyframes heartbeat { 0%, 28%, 100% { transform: scale(1); } 10% { transform: scale(1.18); } 19% { transform: scale(1.05); } }

/* ---------- Inner pages ---------- */
/* photo banner (id="hero" so the sticky donate appears once it scrolls out) */
.page-hero {
  position: relative; min-height: clamp(300px, 46vh, 430px);
  display: flex; align-items: flex-end; overflow: hidden;
}
.page-hero .hero-media img { object-position: 50% 42%; }
.page-hero .hero-scrim {
  background: linear-gradient(to top, rgba(13, 14, 18, .84) 0%, rgba(13, 14, 18, .38) 55%, rgba(13, 14, 18, .22) 100%);
}
.page-hero-content {
  position: relative; z-index: 2; width: 100%; max-width: var(--wrap);
  margin: 0 auto; padding: 6.5rem var(--pad) 2.6rem; color: var(--white);
}
.page-hero-content h1 {
  font-size: clamp(2.2rem, 3.4vw + 1rem, 3.6rem); font-weight: 800;
  color: var(--white); margin-bottom: .25em; text-wrap: balance;
}
.page-hero-content .lede { max-width: 52ch; font-size: clamp(1.05rem, .4vw + 1rem, 1.25rem); color: rgba(255, 255, 255, .92); margin: 0; }

/* plain banner (no photo) */
.page-hero--plain { background: var(--blue-deep); min-height: 0; }
.page-hero--plain .page-hero-content { padding-top: 6rem; }

/* anchor pills under a banner */
.anchor-pills {
  display: flex; flex-wrap: wrap; gap: .6rem;
  max-width: var(--wrap); margin: 0 auto; padding: 1.4rem var(--pad) 0;
}
.anchor-pills a {
  display: inline-flex; align-items: center; min-height: 44px; padding: .45rem 1.15rem;
  border-radius: var(--pill); background: var(--white); border: 2px solid var(--line);
  color: var(--ink); font-weight: 600; font-size: .98rem; text-decoration: none;
  transition: border-color .18s, color .18s, transform .18s;
}
.anchor-pills a:hover { border-color: var(--red); color: var(--red); transform: translateY(-2px); }

/* generic page section + prose */
.page-section { max-width: var(--wrap); margin: 0 auto; padding: 3.8rem var(--pad); }
.page-section--tight { padding-top: 2.6rem; }
.prose { max-width: 68ch; }
.prose h2 { margin-top: 1.6em; }
.prose h3 { margin-top: 1.4em; }
.prose ul { list-style: disc; padding-left: 1.3em; margin: 0 0 1em; }
.prose li { margin-bottom: .45em; }
.prose a { font-weight: 600; }

/* split section: photo print beside text.

   Photo on the left, text on the right — everywhere, not section by section.
   Mojca's rule, 19 Aug: "general easy-read principle for adults with learning
   disabilities is photo on the left, text to the right". It was a modifier
   (.split--rev) until then, which meant every new split started out wrong and
   had to be corrected. It is the default now, so it cannot be forgotten.

   Source order inside a .split no longer decides anything: the media is pulled
   first either way. Write the section whichever way reads better. */
.split {
  max-width: var(--wrap); margin: 0 auto; padding: 3.4rem var(--pad);
  display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(2rem, 4vw, 4rem); align-items: center;
}
.split .split-media { order: -1; }
/* ...unless the slot holds a box of words rather than a picture. The rule
   above is about PHOTOGRAPHS — a photo on the left and the words about it on
   the right. /contact/'s "Find us at the Thistle" has the red Safeguarding
   callout in that slot, so the rule was pulling a second block of text in
   front of the address it belongs beside. Michal's call, 21 Aug: the Thistle
   goes on the left.

   Keyed to what is actually in the slot rather than a modifier on the
   section, for the reason the modifiers were deleted in the first place —
   a modifier is a thing to remember, and the next one gets forgotten.

   The column swap is inside a min-width and the stacking breakpoint's own
   max-width is 1020px, on purpose: `:has()` outspecifies the plain `.split`
   that collapses this to one column below 1020px, so writing it unqualified
   held the section in two 135px columns on a phone. Order needs no such
   guard — stacked, it is already 0. */
@media (min-width: 1021px) {
  .split:has(.split-media > .callout) { grid-template-columns: 1.1fr .9fr; }
}
.split:has(.split-media > .callout) .split-media { order: 0; }
.split h2 { max-width: 20ch; }
.split .split-body p { max-width: 56ch; }
.split-media { justify-self: center; max-width: 480px; }
.split--band { background: var(--white); }

/* callout box */
.callout {
  background: var(--white); border-left: 6px solid var(--yellow);
  border-radius: 0 var(--radius) var(--radius) 0; box-shadow: var(--shadow-card);
  padding: 1.4rem 1.6rem; margin: 1.8rem 0; max-width: 640px;
}
.callout--blue { border-left-color: var(--blue); }
.callout--red { border-left-color: var(--red); }
.callout p:last-child { margin-bottom: 0; }
.callout .callout-title { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; display: block; margin-bottom: .35rem; }

/* ---------- the printed flyer, words beside the sheets ----------
   /whats-on/, the Big Nights Out programme. The words come FIRST in the
   markup, and stay first on a phone, because they are the half that everybody
   can read; the two sheets sit beside them on a wide screen as what they are —
   two pieces of paper on a table. */
/* Sheets left, words right — the same easy-read rule as `.split` and
   `.course-block`. A third copy of the two-column shape, and the third one to
   have to be corrected by hand. */
.flyer-grid {
  display: grid; grid-template-columns: .95fr 1.05fr;
  gap: clamp(1.6rem, 4vw, 3.4rem); align-items: start;
}
.flyer-grid .flyer-sheets { order: -1; }
.flyer-words { max-width: 56ch; }
.flyer-words h3 { margin: 1.6rem 0 .5rem; font-size: 1.15rem; }
.flyer-words h3:first-child { margin-top: 0; }
.flyer-dates ul { list-style: none; padding: 0; margin: 0 0 .4rem; }
.flyer-dates li {
  padding: .38rem 0 .38rem .95rem; border-left: 3px solid var(--yellow);
  margin-bottom: .3rem; line-height: 1.4;
}
/* The two sheets, side by side and slightly askew — the same treatment every
   photograph on this site gets, so the flyer reads as something printed rather
   than as two files that were uploaded. */
.flyer-sheets { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; align-items: start; }
.flyer-sheets .print { max-width: 100%; }
.flyer-sheets .print img { width: 100%; }
@media (max-width: 860px) {
  .flyer-grid { grid-template-columns: 1fr; }
  /* One column: stacks as written, words first, as it always did. */
  .flyer-grid .flyer-sheets { order: 0; }
  /* Under the words, and no longer tilted: at this width the two sheets are
     narrow enough that a rotation costs real reading size. */
  .flyer-sheets { max-width: 520px; }
  .flyer-sheets .tilt-l, .flyer-sheets .tilt-r { transform: none; }
}

/* big pull-quote on inner pages */
.pull-quote {
  max-width: 760px; margin: 2.6rem auto; padding: 0 var(--pad); text-align: center;
}
.pull-quote p {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.25rem, 1.2vw + 1rem, 1.7rem); line-height: 1.4; color: var(--ink);
}
.pull-quote cite { font-style: normal; font-weight: 600; color: var(--ink-soft); font-size: .98rem; }
.pull-quote .q-mark { font-family: var(--font-display); font-weight: 800; font-size: 3.4rem; line-height: .5; color: var(--red); display: block; margin-bottom: .8rem; }

/* small fact chips row (e.g. when/where) */
.fact-chips { display: flex; flex-wrap: wrap; gap: .6rem; margin: 1rem 0 1.4rem; padding: 0; }
.fact-chips li {
  background: var(--yellow); color: var(--ink); font-weight: 600; font-size: .95rem;
  padding: .35rem .95rem; border-radius: var(--pill);
}
.fact-chips--light li { background: var(--cream-deep); }

/* people cards (team page) */
.people-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.4rem;
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad);
}
.person-card {
  background: var(--white); border-radius: var(--radius); box-shadow: var(--shadow-card);
  overflow: hidden; display: flex; flex-direction: column;
  transition: transform .25s ease, box-shadow .25s ease;
}
.person-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lift); }
.person-card > img { width: 100%; aspect-ratio: 1; object-fit: cover; }
.person-body { padding: 1.25rem 1.35rem 1.45rem; }
.person-body h3 { margin: 0 0 .3rem; font-size: 1.22rem; }
.person-pronouns {
  display: inline-block; font-size: .8rem; font-weight: 700; letter-spacing: .04em;
  background: var(--cream-deep); border-radius: var(--pill); padding: .12rem .75rem;
  margin: 0 0 .75rem; color: var(--ink-soft);
}
.person-role { font-weight: 600; color: var(--blue); font-size: .98rem; margin: 0 0 .55rem; }
.person-body p { font-size: .95rem; color: var(--ink-soft); margin-bottom: .6rem; }
.person-body p strong { color: var(--ink); }
/* The staff email links measured 22px tall — 2px under 2.5.8. axe exempts them
   as inline links inside a paragraph and it is probably right, but 2px is not
   worth the argument. The padding is on the INLINE element deliberately:
   vertical padding on an inline box grows the hit area without changing the
   line box, so the target clears 24px and not one thing moves on the page. */
.person-mail,
.ask-card p > a[href^="mailto:"] { padding-block: 2px; }
.person-mail { font-weight: 600; font-size: .95rem; word-break: break-all; }
.team-section { padding: 3.2rem 0; }
.team-section--band { background: var(--white); }
.team-section .section-head { text-align: left; margin: 0 auto 1.8rem; max-width: var(--wrap); padding: 0 var(--pad); }
.team-section .section-intro { max-width: 68ch; }

/* active nav item */
.site-nav a[aria-current="page"] { border-bottom-color: var(--red); color: var(--red); }

/* ---------- Reveal-on-scroll ---------- */
.js .reveal { opacity: 0; transform: translateY(26px); transition: opacity .7s ease, transform .7s cubic-bezier(.2, .7, .2, 1); }
.js .reveal.in { opacity: 1; transform: none; }
.js .ticket.reveal { transition-delay: calc(var(--d, 0) * 90ms); }
.js .print-card.reveal:nth-child(2), .js .obj-card.reveal:nth-child(2) { transition-delay: .1s; }
.js .print-card.reveal:nth-child(3), .js .obj-card.reveal:nth-child(3) { transition-delay: .2s; }
.js .obj-card.reveal:nth-child(4) { transition-delay: .3s; }
/* keep the tilted prints tilted while revealing */
.js .print.tilt-l.reveal { transform: rotate(-2.2deg) translateY(26px); }
.js .print.tilt-r.reveal { transform: rotate(1.8deg) translateY(26px); }
.js .print.tilt-l.reveal.in { transform: rotate(-2.2deg); }
.js .print.tilt-r.reveal.in { transform: rotate(1.8deg); }

/* ---------- Responsive ---------- */
@media (max-width: 1020px) {
  .ticket-strip { grid-template-columns: repeat(2, 1fr); }
  .obj-grid { grid-template-columns: repeat(2, 1fr); }
  .print-grid { grid-template-columns: 1fr; max-width: 560px; }
  .mission-inner, .news-inner, .donate-inner { grid-template-columns: 1fr; }
  .people-grid { grid-template-columns: repeat(2, 1fr); }
  /* One column, so there is no left or right to honour. Sections fall back to
     the order they are written in, which is what they did before the swap. */
  .split { grid-template-columns: 1fr; }
  .split .split-media { order: 0; }
  .mission-prints { grid-auto-flow: column; align-items: start; order: 0; }
  .footer-inner { grid-template-columns: 1fr 1fr; }
  /* Brand across the top and Explore across the bottom, so the two short
     columns pair up in the middle instead of leaving a hole beside Contact. */
  .footer-brand { grid-column: span 2; }
  .donate-cta { justify-self: start; text-align: left; }
}
@media (max-width: 720px) {
  :root { --fs-body: 1.0625rem; }
  .site-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--cream); border-bottom: 1px solid var(--line);
    box-shadow: 0 18px 30px rgba(23, 24, 28, .12);
    display: none; padding: .6rem var(--pad) 1.2rem;
  }
  .nav-open .site-nav { display: block; }
  .site-nav ul { flex-direction: column; gap: 0; }
  .site-nav a { display: block; padding: .85rem .2rem; font-size: 1.15rem; border-bottom: 1px solid var(--line); }
  .nav-toggle { display: inline-flex; align-items: center; }
  .header-donate { margin-left: auto; }
  .brand img { width: 96px; }
  .site-header.scrolled .brand img { width: 86px; }

  .hero { min-height: 88vh; }
  .hero-content { padding-top: 6rem; padding-bottom: 3.4rem; }
  .hero-ctas .btn { width: 100%; justify-content: center; }
  /* on small screens the marker phrase may wrap: swap the SVG swipe
     for a highlight that clones across line boxes */
  .marker-swipe { display: none; }
  .marker > span {
    background: linear-gradient(to top, rgba(251, 192, 45, .9) 24%, transparent 24%);
    -webkit-box-decoration-break: clone; box-decoration-break: clone;
    padding: 0 .06em; margin: 0 -.06em;
  }

  .ticket-strip { grid-template-columns: 1fr; margin-top: -2.4rem; }
  .people-grid { grid-template-columns: 1fr; }
  .stats-source { text-align: left; }
  .what { padding-top: 3.6rem; }
  .obj-grid { grid-template-columns: 1fr; }
  .mission { padding: 3.6rem 0; }
  .mission-prints { grid-auto-flow: row; }
  .voices-track { min-height: 19em; }
  .news-print { max-width: 360px; }
  .footer-inner { grid-template-columns: 1fr; gap: 1.8rem; }
  /* One column is too narrow to split — "Policies + documents" would wrap.
     The spans have to go too, or grid adds a second, empty implicit column. */
  .footer-brand, .footer-col--wide { grid-column: auto; }
  .footer-col--wide ul { columns: 1; }
  /* --pad bottoms out at 1.1rem here, so the panel would sit hard against the
     screen edge. Bleed less. */
  .footer-col--wide { margin-inline: -.6rem; padding-inline: .6rem; }
  .sticky-donate { right: 14px; bottom: 14px; padding: .78rem 1.3rem; }
}

/* ---------- Reduced motion: neutralise everything ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .hero-media img { animation: none !important; transform: none; }
  .js .hero-title .w { opacity: 1; transform: none; animation: none !important; }
  .js .marker-swipe { clip-path: none; animation: none !important; }
  .js .reveal { opacity: 1; transform: none; }
  .js .print.tilt-l.reveal, .js .print.tilt-l.reveal.in { transform: rotate(-2.2deg); }
  .js .print.tilt-r.reveal, .js .print.tilt-r.reveal.in { transform: rotate(1.8deg); }
  .sticky-donate { opacity: 1; transform: none; pointer-events: auto; }
  .sticky-donate .ic { animation: none !important; }
}
