/* ============================================================
   TSM GAUTENG — shared stylesheet
   ------------------------------------------------------------
   ALL colours are variables in :root below. To rebrand, change
   those values and nothing else. Do not hunt for colours further
   down the file.

   The one idea behind the look: truth is light. Dark navy night,
   and the brand blue is what switches on.
   ============================================================ */

@font-face {
  font-family: "Poppins"; font-weight: 800; font-style: normal; font-display: swap;
  src: url("../assets/fonts/poppins-extrabold.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins"; font-weight: 700; font-style: normal; font-display: swap;
  src: url("../assets/fonts/poppins-bold.woff2") format("woff2");
}

:root {
  /* --- brand, taken from the TSM logo --- */
  --brand:        #4EC2FF;  /* the logo blue. ACCENTS and LIGHT ON DARK only — see warning below */
  --brand-deep:   #0B6FB8;  /* interactive: buttons, links. White text = 5.3:1, passes AA */
  --brand-darker: #084E82;  /* deep surfaces. White text = 8.7:1 */
  --brand-soft:   #E7F6FF;  /* pale tint for section backgrounds */
  --accent:       #FFB612;  /* SA flag gold — echoes the flag ribbon in the logo. FILLS ONLY */
  --accent-text:  #8A5A00;  /* accent as TEXT on light backgrounds. #FFB612 on white is
                               only 1.75:1 and fails; this is 5.9:1 and passes AA */
  --accent-soft:  #FFF6E0;
  --on-dark:      #c9ddf0;  /* muted text on navy. 12:1 on --night, passes AA */

  /* WARNING: never put white text on --brand (#4EC2FF). It is a light blue and
     the contrast is only 2.0:1, which fails accessibility badly. Use
     --brand-deep or --brand-darker behind white text. On the navy surfaces
     --brand itself is the text colour (9.4:1 on --night). */

  /* --- night: the dark surfaces (header, heroes, footer) --- */
  --night:      #071224;
  --night-2:    #0E1C3A;   /* the campaign navy */
  --night-line: rgba(255,255,255,.12);

  --ink:        #0b1a2b;
  --body:       #3d4d57;
  --muted:      #5c6c76;
  --line:       #dde7ed;
  --bg:         #ffffff;
  --bg-alt:     #f3f8fc;
  --card:       #ffffff;

  --radius: 16px;
  --wrap: 1160px;
  --shadow: 0 1px 2px rgba(7,18,36,.05), 0 10px 30px rgba(7,18,36,.07);
  --shadow-lift: 0 2px 4px rgba(7,18,36,.06), 0 22px 48px rgba(7,18,36,.14);
  --display: "Poppins", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --serif: var(--display);   /* older pages ask for --serif; headings are Poppins now */
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* motion: one set of curves for the whole site */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --brand-soft:  #0d2231;
    --accent-soft: #2a2211;
    /* On dark, the darkened gold is only 3.18:1. The true brand gold is 10.7:1
       and reads correctly as gold, so flip back to it here. */
    --accent-text: #FFB612;
    --ink:         #eaf2f7;
    --body:        #bccbd4;
    --muted:       #8b9ca6;
    --line:        #22323d;
    --bg:          #0a1218;
    --bg-alt:      #0f1a21;
    --card:        #121e26;
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.3);
    --shadow-lift: 0 2px 4px rgba(0,0,0,.4), 0 22px 48px rgba(0,0,0,.45);
  }
}

/* Moving between pages: the header stays put and the page cross-fades.
   Browsers without this simply load the page as usual. */
@view-transition { navigation: auto; }

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  scroll-padding-top: 90px;
}

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  color: var(--body);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--ink);
  line-height: 1.12;
  margin: 0 0 .5em;
  font-weight: 800;
  letter-spacing: -.02em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.15rem, 6vw, 3.9rem); letter-spacing: -.035em; line-height: 1.04; }
h2 { font-size: clamp(1.65rem, 4vw, 2.6rem); letter-spacing: -.03em; }
h3 { font-size: 1.22rem; font-weight: 700; letter-spacing: -.01em; line-height: 1.25; }

p { margin: 0 0 1.1em; }
a { color: var(--brand-deep); text-decoration-thickness: 1px; text-underline-offset: 3px; }
@media (prefers-color-scheme: dark) { a { color: #7ACBFF; } }

img { max-width: 100%; height: auto; display: block; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 22px; }
.narrow { max-width: 760px; }

/* ---------- skip link (accessibility) ---------- */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #24190a; padding: 12px 18px; border-radius: 0 0 8px 0; font-weight: 700;
}
.skip:focus { left: 0; }

/* ---------- header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: var(--night);
  border-bottom: 1px solid var(--night-line);
  view-transition-name: site-head;
}
.head-in { display: flex; align-items: center; gap: 14px; height: 76px; }

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; margin-right: auto; }
.brand img { height: 52px; width: auto; }
.brand-fallback {
  height: 44px; width: 44px; border-radius: 10px; flex: 0 0 auto;
  background: var(--brand-deep); color: #fff;
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 800; font-size: 1.05rem; letter-spacing: .5px;
}
.brand-txt { display: flex; flex-direction: column; line-height: 1.12; }
.brand-txt b { font-family: var(--display); font-weight: 800; color: #fff; font-size: 1.12rem; letter-spacing: -.01em; }
.brand-txt span { font-size: .72rem; font-weight: 700; color: var(--brand); letter-spacing: .16em; text-transform: uppercase; }

.nav { display: flex; align-items: center; gap: 2px; }
.nav a {
  color: #dbe7f3; text-decoration: none; font-size: .94rem; font-weight: 600;
  padding: 9px 14px; border-radius: 999px;
  transition: background-color 160ms ease, color 160ms ease;
}
.nav a[aria-current="page"]:not(.btn) { color: #fff; background: rgba(78,194,255,.16); }

.nav-toggle {
  display: none; background: none; border: 1px solid var(--night-line);
  border-radius: 10px; padding: 9px 11px; cursor: pointer; color: #fff; font-size: 1.05rem;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}

@media (max-width: 860px) {
  .head-in { height: 68px; }
  .brand img { height: 46px; }
  .brand-txt b { font-size: 1rem; }
  .nav-toggle { display: block; }
  .nav {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--night); border-bottom: 1px solid var(--night-line);
    padding: 10px 16px 18px; box-shadow: 0 24px 40px rgba(0,0,0,.35);
    transform-origin: top;
    transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
  }
  .nav.open { display: flex; }
  @starting-style { .nav.open { opacity: 0; transform: translateY(-8px); } }
  .nav a { padding: 13px 14px; border-radius: 12px; font-size: 1.02rem; }
  .nav .btn { margin-top: 8px; text-align: center; }
}

/* ---------- buttons ---------- */
.btn {
  display: inline-block; padding: 13px 24px; border-radius: 999px;
  background: var(--brand-deep); color: #fff !important; text-decoration: none;
  font-family: var(--display); font-weight: 700; font-size: .95rem; letter-spacing: .005em;
  border: 1px solid var(--brand-deep);
  cursor: pointer;
  transition: transform 140ms var(--ease-out), background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
.btn:active { transform: scale(.97); }
.btn.gold, .nav .btn { background: var(--accent); border-color: var(--accent); color: #24190a !important; }
.btn.ghost {
  background: transparent; color: var(--brand-deep) !important; border-color: var(--line);
}
@media (prefers-color-scheme: dark) { .btn.ghost { color: #7ACBFF !important; } }
.btn .arr { display: inline-block; margin-left: 8px; transition: transform 200ms var(--ease-out); }

.btnrow { display: flex; flex-wrap: wrap; gap: 12px; margin: 26px 0 0; }

/* Every hover style lives in here. A phone fakes :hover on tap and leaves
   it stuck, so touch screens never get these. Press feedback is :active. */
@media (hover: hover) and (pointer: fine) {
  .nav a:hover { background: rgba(255,255,255,.09); color: #fff; }
  .btn:hover { background: var(--brand-darker); border-color: var(--brand-darker); }
  .btn:hover .arr { transform: translateX(3px); }
  .btn.gold:hover, .nav .btn:hover { background: #ffc53d; border-color: #ffc53d; box-shadow: 0 8px 26px rgba(255,182,18,.32); }
  .btn.ghost:hover { background: var(--bg-alt); border-color: var(--brand-deep); }
  .on-night .btn.ghost:hover, .hero .btn.ghost:hover { background: rgba(255,255,255,.1); border-color: #fff; }
  .hero .btn:not(.ghost):not(.gold):hover { background: #e3f3ff; border-color: #e3f3ff; }
  .person:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); }
  .person:hover img { transform: scale(1.04); }
  .person .contact a:hover { background: var(--brand-deep); color: #fff; }
  .card.lift:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); }
  .site-foot a:hover { color: #fff; text-decoration: underline; }
  .socials a:hover { background: var(--accent); color: #24190a; }
  .chip:hover { border-color: var(--brand-deep); }
  .faq summary:hover { color: var(--brand-deep); }
  .q-opts button:hover:not(:disabled) { border-color: var(--brand); background: rgba(78,194,255,.1); }
  .video:hover .play { transform: scale(1.06); }
}

/* ---------- hero (every page) ----------
   Navy night with a faint dot grid and one blue glow. Text colours are
   measured against --night: white 17.6:1, lede 13:1, --brand 9.4:1. */
.hero {
  position: relative; isolation: isolate; overflow: hidden;
  padding: clamp(52px, 8vw, 96px) 0 clamp(56px, 8vw, 100px);
  background: var(--night);
  color: var(--on-dark);
}
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(760px 420px at 88% -8%, rgba(27,160,222,.34), transparent 62%),
    radial-gradient(620px 380px at -6% 108%, rgba(11,111,184,.30), transparent 60%),
    radial-gradient(circle at 1px 1px, rgba(255,255,255,.085) 1px, transparent 1.6px) 0 0 / 22px 22px;
}
.hero h1 { color: #fff; }
.hero .eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--display); font-size: .74rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--brand);
  border: 1px solid rgba(78,194,255,.38); background: rgba(78,194,255,.08);
  padding: 7px 14px; border-radius: 999px; margin-bottom: 22px;
}
.hero .eyebrow::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--brand); box-shadow: 0 0 0 4px rgba(78,194,255,.22);
}
.hero p.lede { font-size: clamp(1.06rem, 1.6vw, 1.2rem); max-width: 60ch; color: #d3e2f0; }
.hero a:not(.btn) { color: var(--brand); }
.hero .btn:not(.ghost):not(.gold) { background: #fff; color: var(--night) !important; border-color: #fff; }
.hero .btn.ghost, .on-night .btn.ghost { color: #fff !important; border-color: rgba(255,255,255,.45); background: transparent; }
.hero :focus-visible, .on-night :focus-visible { outline-color: var(--accent); }

/* Entrance: the resting state is fully visible, so the page reads with no
   script and no animation support. The keyframes only describe where it
   comes FROM. */
@keyframes rise { from { opacity: 0; transform: translateY(18px); } }
.hero .eyebrow, .hero h1, .hero p.lede, .hero .btnrow, .hero .count, .hero .gmap-col {
  animation: rise 700ms var(--ease-out) backwards;
}
.hero h1 { animation-delay: 60ms; }
.hero p.lede { animation-delay: 140ms; }
.hero .btnrow { animation-delay: 220ms; }
.hero .count { animation-delay: 300ms; }
.hero .gmap-col { animation-delay: 180ms; }

/* the underline that draws itself under the last words of the headline */
.mark { position: relative; white-space: nowrap; color: var(--brand); }
.mark svg {
  position: absolute; left: -2%; right: -2%; bottom: -.16em; width: 104%; height: .34em;
  overflow: visible; pointer-events: none;
}
.mark path {
  fill: none; stroke: var(--accent); stroke-width: 5; stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: 0;
  animation: draw 900ms var(--ease-in-out) 760ms backwards;
}
@keyframes draw { from { stroke-dashoffset: 1; } }

/* ---------- home hero: words on the left, the map of Gauteng on the right ---------- */
.hero-home { padding-bottom: clamp(40px, 6vw, 72px); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr); gap: clamp(24px, 4vw, 56px); align-items: center; }
@media (max-width: 940px) { .hero-grid { grid-template-columns: 1fr; } }

.gmap-col { min-width: 0; }
.gmap {
  position: relative; width: 100%; max-width: 540px; margin: 0 auto;
  aspect-ratio: 98 / 101;
  /* the still picture: what you see before the script runs, or without it */
  background: url("../assets/map-still.webp") center / contain no-repeat;
}
.gmap canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: pan-y; cursor: crosshair; }
.gmap.live { background-image: none; }
.gmap-label {
  position: absolute; transform: translate(-50%, -50%); pointer-events: none;
  font-family: var(--display); font-weight: 700; font-size: .72rem; letter-spacing: .02em;
  color: #fff; text-align: center; line-height: 1.2; white-space: nowrap;
  padding: 5px 10px; border-radius: 999px;
  background: rgba(7,18,36,.78); border: 1px solid rgba(78,194,255,.5);
  opacity: 0; transition: opacity 400ms ease;
}
.gmap-label b { color: var(--accent); font-weight: 800; }
.gmap.ready .gmap-label { opacity: 1; }
.gmap-note {
  max-width: 540px; margin: 10px auto 0; min-height: 3.2em;
  font-size: .86rem; line-height: 1.5; color: var(--on-dark); text-align: center;
}
.gmap-note b { color: #fff; }
.gmap-note .lg { display: inline-block; white-space: nowrap; }
.gmap-note .key { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin: 0 6px 0 0; vertical-align: baseline; }
.gmap-note .key.on { background: var(--brand); box-shadow: 0 0 8px var(--brand); }
.gmap-note .key.off { background: rgba(255,255,255,.32); }
.gmap-note .lg + .lg { margin-left: 14px; }
.gmap-note .tap { display: block; }
.gmap-credit { display: block; font-size: .74rem; color: #8fa6bd; margin-top: 4px; }
.gmap-credit a { color: inherit !important; }

/* ---------- countdown ---------- */
.count { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; margin-top: 34px; }
.count-label {
  font-family: var(--display); font-weight: 700; font-size: .74rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--on-dark); max-width: 11em; line-height: 1.35; margin: 0;
}
@media (max-width: 560px) { .count-label { max-width: none; flex-basis: 100%; } }
.count-label b { display: block; color: var(--accent); font-size: .95rem; letter-spacing: .06em; }
.count-cells { display: flex; gap: 8px; }
.count-cells[hidden] { display: none; }   /* shown by the script once it has real numbers */
.count-cell {
  min-width: 64px; padding: 10px 8px 8px; text-align: center; border-radius: 14px;
  background: rgba(255,255,255,.06); border: 1px solid var(--night-line);
}
.count-cell b {
  display: block; font-family: var(--display); font-weight: 800; font-size: 1.7rem; line-height: 1;
  color: #fff; font-variant-numeric: tabular-nums;
}
.count-cell span { font-size: .72rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--on-dark); }
@media (max-width: 400px) { .count-cell { min-width: 56px; } .count-cell b { font-size: 1.45rem; } }

/* legacy single-pill countdown, still used as the no-script fallback text */
.countdown {
  display: inline-flex; align-items: baseline; gap: 10px;
  background: rgba(255,255,255,.06); border: 1px solid var(--night-line); color: #fff;
  padding: 12px 20px; border-radius: 999px;
}
.countdown b { font-family: var(--display); font-size: 1.3rem; color: var(--accent); }

/* ---------- the four words, running ---------- */
.ticker {
  background: var(--accent); color: #1d1503; overflow: hidden;
  border-block: 1px solid rgba(0,0,0,.08);
}
.ticker-run { display: flex; width: max-content; animation: ticker 38s linear infinite; }
.ticker-set { display: flex; flex: none; }
.ticker-set span {
  font-family: var(--display); font-weight: 800; font-size: clamp(1rem, 2.4vw, 1.35rem);
  letter-spacing: .08em; text-transform: uppercase; padding: 13px 0; white-space: nowrap;
}
.ticker-set span::after { content: "★"; margin: 0 1.2em; font-size: .7em; vertical-align: .15em; opacity: .7; }
@keyframes ticker { to { transform: translateX(-50%); } }

/* ---------- sections ---------- */
section { padding: clamp(56px, 8vw, 104px) 0; }
section.alt { background: var(--bg-alt); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
section.on-night { background: var(--night); color: var(--on-dark); position: relative; isolation: isolate; overflow: hidden; }
section.on-night::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(700px 380px at 100% 0%, rgba(27,160,222,.26), transparent 62%),
    radial-gradient(circle at 1px 1px, rgba(255,255,255,.07) 1px, transparent 1.6px) 0 0 / 22px 22px;
}
.on-night h2, .on-night h3 { color: #fff; }
.on-night a:not(.btn) { color: var(--brand); }
/* The party badge as a watermark on the light sections: one per section, very
   half off the right edge, where the page is empty on a wide screen. At 25%
   the grey intro text and the small blue kicker would drop under 4.5:1 where
   they cross the badge (measured 3.4 to 4.6), so inside a marked section those
   two use the darker body and deep-blue colours (measured 5.5:1 or better). */
section.wm, .hero + section { position: relative; overflow: hidden; isolation: isolate; }
section.wm::after, .hero + section::after {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  width: clamp(300px, 46vw, 660px); aspect-ratio: 1;
  right: clamp(-200px, -9vw, -70px); top: 50%; transform: translateY(-50%) rotate(-8deg);
  background: url("../assets/logo-mark.webp") center / contain no-repeat;
  opacity: .25;
}
section.wm.wm-l::after { right: auto; left: clamp(-200px, -9vw, -70px); transform: translateY(-50%) rotate(8deg); }
section.wm.wm-top::after { top: 0; transform: translateY(-18%) rotate(-8deg); }
section.wm.wm-low::after { top: auto; bottom: 0; transform: translateY(22%) rotate(8deg); }
@media (prefers-color-scheme: dark) { section.wm::after, .hero + section::after { opacity: .18; } }
@media print { section.wm::after, .hero + section::after { display: none; } }
section.wm .sec-head p, .hero + section .sec-head p { color: var(--body); }
section.wm .kicker, .hero + section .kicker { color: var(--brand-darker); }
@media (prefers-color-scheme: dark) { section.wm .kicker, .hero + section .kicker { color: #7ACBFF; } }

.sec-head { max-width: 68ch; margin-bottom: 44px; }
.sec-head p { font-size: 1.08rem; color: var(--muted); margin: 0; }
.on-night .sec-head p { color: var(--on-dark); }
.kicker {
  display: block; font-family: var(--display); font-weight: 700; font-size: .74rem;
  letter-spacing: .16em; text-transform: uppercase; color: var(--brand-deep); margin-bottom: 12px;
}
.on-night .kicker { color: var(--brand); }
@media (prefers-color-scheme: dark) { .kicker { color: #7ACBFF; } }

/* Reveal on scroll. The hiding is switched on by the script itself
   (html.io), never by plain CSS, so with no script everything just shows. */
html.io .reveal { opacity: 0; transform: translateY(22px); }
html.io .reveal.in {
  opacity: 1; transform: none;
  transition: opacity 640ms var(--ease-out), transform 640ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 60ms);
}

/* ---------- grid + cards ---------- */
.grid { display: grid; gap: 20px; }
.g2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.g3 { grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); }

.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow);
}
.card.lift { transition: transform 220ms var(--ease-out), box-shadow 220ms var(--ease-out); }
.card h3 { margin-bottom: .4em; }
.card p:last-child { margin-bottom: 0; }
.card .num {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  background: var(--night); color: var(--brand);
  font-family: var(--display); font-weight: 800; font-size: 1.1rem; margin-bottom: 16px;
}

/* ---------- "whose job is it?" ---------- */
.try { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: clamp(28px, 5vw, 64px); align-items: center; }
@media (max-width: 880px) { .try { grid-template-columns: 1fr; } }
.try-copy p { font-size: 1.08rem; }
.quiz {
  position: relative; background: var(--night); color: var(--on-dark);
  border-radius: 24px; padding: clamp(24px, 4vw, 40px); box-shadow: var(--shadow-lift);
  isolation: isolate; overflow: hidden;
}
.quiz::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(520px 300px at 100% 0%, rgba(27,160,222,.32), transparent 65%);
}
.quiz-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.quiz-step { font-family: var(--display); font-weight: 700; font-size: .74rem; letter-spacing: .14em; text-transform: uppercase; color: var(--brand); }
.quiz-dots { display: flex; gap: 6px; }
.quiz-dots i { width: 26px; height: 5px; border-radius: 3px; background: rgba(255,255,255,.16); transition: background-color 300ms ease; }
.quiz-dots i.done { background: var(--accent); }
.q-text { font-family: var(--display); font-weight: 700; font-size: clamp(1.15rem, 2.4vw, 1.45rem); line-height: 1.3; color: #fff; margin: 0 0 20px; }
.q + .q { margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--night-line); }
.q-opts { display: none; gap: 10px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 460px) { .q-opts { grid-template-columns: 1fr; } }
.q-opts button {
  font: inherit; font-family: var(--display); font-weight: 700; font-size: .95rem; color: #fff;
  min-height: 52px; padding: 12px 10px; border-radius: 14px; cursor: pointer;
  background: rgba(255,255,255,.06); border: 1.5px solid rgba(255,255,255,.22);
  transition: transform 140ms var(--ease-out), background-color 160ms ease, border-color 160ms ease, opacity 200ms ease;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
.q-opts button:active:not(:disabled) { transform: scale(.97); }
.q-opts button:disabled { cursor: default; opacity: .45; }
.q-opts button.right { opacity: 1; background: #12804a; border-color: #35c27d; }
.q-opts button.wrong { opacity: 1; background: #8f2330; border-color: #e0667a; }
.q-answer { margin: 0; }
.q-answer summary { cursor: pointer; color: var(--brand); font-weight: 600; padding: 6px 0; }
.q-explain { margin: 16px 0 0; color: #e6eef7; font-size: 1rem; }
.q-explain b { color: var(--accent); }
.quiz-end { margin-top: 22px; }
.quiz-end p { color: #fff; font-family: var(--display); font-weight: 700; font-size: 1.12rem; margin: 0 0 4px; }
.quiz-end .btnrow { margin-top: 16px; }
/* with the script running: one question at a time, real buttons, no <details> */
html.js .q-opts { display: grid; }
html.js .q-answer { display: none; }
html.js .quiz .q { display: none; margin: 0; padding: 0; border: 0; }
html.js .quiz .q.now { display: block; animation: rise 360ms var(--ease-out) backwards; }

/* ---------- feature (course promo) ---------- */
.feature {
  display: grid; grid-template-columns: 1.15fr .85fr; gap: 44px; align-items: center;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 24px; padding: clamp(28px, 4vw, 52px); box-shadow: var(--shadow);
}
@media (max-width: 880px) { .feature { grid-template-columns: 1fr; gap: 30px; } }
.feature ul { margin: 0 0 4px; padding: 0; list-style: none; }
.feature li { margin-bottom: 11px; padding-left: 32px; position: relative; }
.feature li::before {
  content: ""; position: absolute; left: 0; top: .28em; width: 20px; height: 20px; border-radius: 50%;
  background: var(--brand-soft) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5.5 10.4l3 3 6-6.6' fill='none' stroke='%230B6FB8' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 20px no-repeat;
}

.stat-row { display: flex; flex-wrap: wrap; gap: 26px; margin-top: 26px; }
.stat b {
  display: block; font-family: var(--display); font-weight: 800; font-size: 2.6rem; letter-spacing: -.03em;
  color: var(--brand-deep); line-height: 1; font-variant-numeric: tabular-nums;
}
@media (prefers-color-scheme: dark) { .stat b { color: #7ACBFF; } }
.stat span { font-size: .86rem; color: var(--muted); }
.stat-card {
  background: var(--night); color: var(--on-dark); border-radius: 20px; padding: clamp(24px, 3vw, 34px);
}
.stat-card .stat-row { margin-top: 0; }
.stat-card .stat b { color: var(--brand); }
.stat-card .stat span { color: var(--on-dark); }
.stat-card p { margin: 22px 0 0; font-size: .94rem; color: var(--on-dark); }

/* ---------- callout ---------- */
.callout {
  border-left: 4px solid var(--accent); background: var(--accent-soft);
  padding: 20px 24px; border-radius: 0 var(--radius) var(--radius) 0; margin: 28px 0;
}
.callout b { color: var(--ink); display: block; margin-bottom: 5px; }
.callout p:last-child { margin-bottom: 0; }
.callout p b { display: inline; margin: 0; }
.on-night .callout { background: rgba(255,182,18,.1); color: #e9eef5; }
.on-night .callout b { color: #fff; }

/* ---------- forms ---------- */
label { display: block; font-weight: 600; color: var(--ink); margin-bottom: 6px; font-size: .93rem; }
/* 16px minimum: iPhones zoom the whole page into any smaller input and do not zoom back. */
input, textarea, select {
  width: 100%; padding: 13px 15px; font: inherit; font-size: max(16px, 1em); color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 12px;
  margin-bottom: 18px;
}
input:focus, textarea:focus { outline: 2px solid var(--brand-deep); outline-offset: 1px; border-color: transparent; }
textarea { min-height: 150px; resize: vertical; }

/* ---------- footer ---------- */
.site-foot {
  background: var(--night); color: var(--on-dark);
  padding: 64px 0 calc(30px + env(safe-area-inset-bottom, 0px)); margin-top: 0;
  border-top: 4px solid var(--accent);
}
.site-foot .foot-h { color: #fff; font-family: var(--display); font-weight: 700; font-size: .76rem; letter-spacing: .14em; text-transform: uppercase; margin-bottom: 14px; }
.site-foot a { color: var(--on-dark); text-decoration: none; }
.foot-word {
  font-family: var(--display); font-weight: 800; text-transform: uppercase; color: #fff;
  font-size: clamp(1.5rem, 5.2vw, 3.6rem); line-height: 1.02; letter-spacing: -.03em; margin: 0 0 44px;
}
.foot-word span { color: var(--brand); }
.foot-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.3fr; gap: 36px; }
@media (max-width: 820px) { .foot-grid { grid-template-columns: 1fr 1fr; gap: 30px; } }
@media (max-width: 500px) { .foot-grid { grid-template-columns: 1fr; } }
.foot-grid ul { list-style: none; margin: 0; padding: 0; }
.foot-grid li { margin-bottom: 9px; }
.foot-bottom {
  border-top: 1px solid var(--night-line); margin-top: 40px; padding-top: 22px;
  font-size: .85rem; color: var(--on-dark);
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between;
}
.socials { display: flex; gap: 10px; margin-top: 14px; }
.socials a {
  width: 38px; height: 38px; border-radius: 9px; display: grid; place-items: center;
  background: rgba(255,255,255,.09); color: #fff;
}
.socials svg { width: 18px; height: 18px; fill: currentColor; }

/* ---------- misc ---------- */
.pill {
  display: inline-block; font-family: var(--display); font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; padding: 6px 12px; border-radius: 999px;
  background: var(--accent-soft); color: #7a5a12; border: 1px solid rgba(200,149,43,.35);
}
@media (prefers-color-scheme: dark) { .pill { color: var(--accent); } }

.placeholder {
  border: 2px dashed var(--accent); background: var(--accent-soft);
  padding: 16px 20px; border-radius: var(--radius); margin: 18px 0;
  font-size: .93rem; color: #7a5a12;
}
@media (prefers-color-scheme: dark) { .placeholder { color: var(--accent); } }

table { width: 100%; border-collapse: collapse; margin: 22px 0; font-size: .96rem; }
th, td { text-align: left; padding: 13px 14px; border-bottom: 1px solid var(--line); }
th { font-family: var(--sans); font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.table-scroll { overflow-x: auto; }

/* Long-read pages (manifesto, privacy): numbered principles get room and a rule. */
.narrow > h2 { margin-top: 1.6em; }
.narrow > h2:first-child { margin-top: 0; }

/* ---------- visible focus for keyboard users (WCAG 2.4.11 Focus Appearance) ---------- */
:focus-visible {
  outline: 3px solid var(--brand-deep);
  outline-offset: 2px;
  border-radius: 4px;
}
.site-head :focus-visible, .site-foot :focus-visible, .btn:focus-visible, .quiz :focus-visible { outline-color: var(--accent); }
@media (prefers-color-scheme: dark) { :focus-visible { outline-color: #7ACBFF; } }

/* ---------- screen-reader-only text ---------- */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- target size (WCAG 2.5.8): min 24x24 for pointer targets ---------- */
.nav a, .socials a, .btn { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
.foot-grid a { display: inline-block; padding: 2px 0; min-height: 24px; }

/* .nav-toggle gets the touch target WITHOUT a display value. It is display:none
   on desktop and display:block under 860px, and setting display here would win
   on specificity-tie-plus-source-order and show the hamburger on desktop. */
.nav-toggle { min-height: 44px; min-width: 44px; }


/* ============================================================
   PEOPLE — portraits with the name set as real HTML text.
   The source posters have the old (compromised) domain baked
   into the artwork, so we crop to the person and typeset the
   name ourselves. Also keeps names selectable and translatable.
   ============================================================ */
.people { display: grid; gap: 22px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.people.fill { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.person {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
  display: flex; flex-direction: column;
  transition: transform 220ms var(--ease-out), box-shadow 220ms var(--ease-out);
}
.person picture { display: block; overflow: hidden; background: var(--brand-soft); }
.person img {
  width: 100%; aspect-ratio: 1; object-fit: cover; object-position: top; background: var(--brand-soft);
  transition: transform 500ms var(--ease-out);
}
.person .who { padding: 18px 20px 20px; border-top: 3px solid var(--brand); }
.person h3 { font-size: 1.1rem; margin-bottom: 4px; }
.person .role { color: var(--brand-deep); font-weight: 700; font-size: .92rem; margin: 0 0 3px; }
@media (prefers-color-scheme: dark) { .person .role { color: #7ACBFF; } }
.person .area { color: var(--muted); font-size: .88rem; margin: 0; }
.person[hidden] { display: none; }

/* On a phone a card is a row: face on the left, words on the right. Eleven
   full-width portraits in a column made the page three screens longer than
   it needed to be. */
@media (max-width: 560px) {
  .people, .people.fill, #roster-grid { grid-template-columns: 1fr; gap: 14px; }
  .person { flex-direction: row; align-items: stretch; }
  .person picture, .person .initials { flex: 0 0 112px; width: 112px; }
  .person img { height: 100%; min-height: 112px; aspect-ratio: auto; }
  .person .who { flex: 1; min-width: 0; padding: 14px 16px 16px; border-top: 0; border-left: 3px solid var(--brand); }
  .person .initials { aspect-ratio: auto; font-size: 2rem; }
}

/* Fallback avatar for candidates with no photograph yet. Same square as the
   photos so the grid stays even. Swap for a <picture> the moment a photo
   arrives — do NOT leave a mix of styles, it reads as second-class. */
.person .initials {
  width: 100%; aspect-ratio: 1;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--brand-deep), var(--night-2));
  color: #fff; font-family: var(--display); font-weight: 800;
  font-size: clamp(2.6rem, 7vw, 3.4rem); letter-spacing: .04em;
}
.person .initials span { opacity: .95; }

/* Optional direct-contact line on a candidate card. Only add it for candidates
   who have agreed their number can be published — it is a public web page and
   the number will be scraped within days. */
.person .contact {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 8px;
}
.person .contact a {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .88rem; font-weight: 600; text-decoration: none;
  padding: 8px 12px; border-radius: 999px; min-height: 44px;
  background: var(--brand-soft); color: var(--brand-deep);
  transition: background-color 160ms ease, color 160ms ease;
  touch-action: manipulation;
}
@media (prefers-color-scheme: dark) { .person .contact a { color: #7ACBFF; } }

/* filter chips above the Gauteng candidates; the map in the hero drives them too */
.chips { display: none; flex-wrap: wrap; gap: 8px; margin: 0 0 26px; }
html.js .chips { display: flex; }
.chip {
  font: inherit; font-family: var(--display); font-weight: 700; font-size: .88rem; color: var(--ink);
  min-height: 44px; padding: 8px 16px; border-radius: 999px; cursor: pointer;
  background: var(--card); border: 1.5px solid var(--line);
  transition: transform 140ms var(--ease-out), background-color 160ms ease, border-color 160ms ease, color 160ms ease;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
.chip:active { transform: scale(.97); }
.chip span { color: var(--muted); font-weight: 700; margin-left: 4px; }
.chip[aria-pressed="true"] { background: var(--night); border-color: var(--night); color: #fff; }
.chip[aria-pressed="true"] span { color: var(--brand); }

/* leader — bigger, side by side */
.leader { display: grid; grid-template-columns: 320px 1fr; gap: clamp(28px, 5vw, 60px); align-items: center; }
@media (max-width: 760px) { .leader { grid-template-columns: 1fr; gap: 28px; } }
.leader picture { position: relative; display: block; max-width: 320px; }
.leader picture::before {
  content: ""; position: absolute; inset: 14px -14px -14px 14px; border-radius: 22px;
  border: 3px solid var(--accent); z-index: 0;
}
.leader img {
  position: relative; z-index: 1;
  width: 100%; max-width: 320px; aspect-ratio: 1; object-fit: cover; object-position: top;
  border-radius: 22px; box-shadow: var(--shadow-lift);
  background: var(--brand-soft);
}

.leader .role { color: var(--brand-deep); font-weight: 700; margin-bottom: 14px; }
@media (prefers-color-scheme: dark) { .leader .role { color: #7ACBFF; } }

/* ---------- why-truth page: quote, numbered commitments, questions ---------- */
blockquote.pull {
  margin: 44px 0 0; padding: 26px 30px; border-left: 5px solid var(--accent); border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--night); color: #fff; box-shadow: var(--shadow-lift);
}
blockquote.pull p { font-family: var(--display); font-weight: 700; font-size: clamp(1.15rem, 2.6vw, 1.6rem); line-height: 1.3; margin: 0 0 12px; letter-spacing: -.01em; }
blockquote.pull footer { font-size: .9rem; color: var(--on-dark); }
.commands .card h3 { font-size: 1.12rem; }
.commands .principle, .card .principle { margin: 12px 0 0; padding-top: 12px; border-top: 1px solid var(--line); font-weight: 700; color: var(--brand-deep); }
@media (prefers-color-scheme: dark) { .commands .principle, .card .principle { color: #7ACBFF; } }
ol.checks { counter-reset: q; }
ol.checks.five li { padding-left: 62px; font-family: var(--display); font-size: 1.08rem; }
ol.checks.five li::before {
  counter-increment: q; content: counter(q); background: none; border: 0; left: 16px; top: 10px; width: 34px; height: 34px;
  border-radius: 50%; background: var(--accent); color: #1d1503; font-weight: 800; display: grid; place-items: center;
}
.faq details { border: 1px solid var(--line); border-radius: 14px; background: var(--card); margin: 12px 0; box-shadow: var(--shadow); }
.faq summary {
  cursor: pointer; list-style: none; padding: 18px 52px 18px 20px; position: relative; min-height: 44px;
  font-family: var(--display); font-weight: 700; font-size: 1.05rem; color: var(--ink); line-height: 1.35;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; position: absolute; right: 18px; top: 50%; transform: translateY(-50%);
  font-family: var(--display); font-weight: 800; font-size: 1.5rem; color: var(--brand-deep);
}
.faq details[open] summary::after { content: "–"; }
.faq details p { margin: 0; padding: 0 20px 20px; }
.faq .sources { font-size: .9rem; color: var(--muted); margin-top: 28px; }
.vote-cards .card h3 { font-size: 1.15rem; }

/* ---------- before 4 November ---------- */
.date-grid { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(28px, 5vw, 64px); align-items: start; }
@media (max-width: 860px) { .date-grid { grid-template-columns: 1fr; } }
.bigdate { font-family: var(--display); font-weight: 800; text-transform: uppercase; color: #fff; line-height: .9; letter-spacing: -.04em; margin: 0; }
@media (min-width: 861px) { .bigdate { position: sticky; top: 120px; } }
.bigdate .d { display: block; font-size: clamp(6rem, 17vw, 11rem); color: var(--brand); }
.bigdate .m { display: block; font-size: clamp(2rem, 6vw, 3.6rem); }
.bigdate .y { display: block; font-size: clamp(1rem, 2.4vw, 1.3rem); letter-spacing: .3em; color: var(--accent); margin-top: 14px; }
.checks { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 12px; }
.checks li {
  position: relative; padding: 14px 18px 14px 54px; border-radius: 14px;
  background: rgba(255,255,255,.05); border: 1px solid var(--night-line); color: #e6eef7;
}
.checks li::before {
  content: ""; position: absolute; left: 16px; top: 14px; width: 26px; height: 26px; border-radius: 7px;
  border: 2px solid var(--brand);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 26'%3E%3Cpath d='M7 7l12 12M19 7L7 19' fill='none' stroke='%23FFB612' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") center / 22px no-repeat;
}
.checks b { color: #fff; }

/* ============================================================
   VIDEO — click-to-load facade.
   Nothing from YouTube loads until the visitor actually clicks:
   no third-party script, no cookies, no data cost, and the strict
   CSP stays intact until it is needed. See DEPLOY.md.
   ============================================================ */
.videos { display: grid; gap: 22px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.video {
  position: relative; aspect-ratio: 16/9; border-radius: var(--radius); overflow: hidden;
  background: var(--night-2); border: 1px solid var(--line); cursor: pointer;
  display: grid; place-items: center; padding: 0;
}
.video img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .55; }
.video .play {
  position: relative; z-index: 1; width: 68px; height: 68px; border-radius: 50%;
  background: var(--accent); display: grid; place-items: center;
  box-shadow: 0 4px 18px rgba(0,0,0,.35); transition: transform 200ms var(--ease-out);
}
.video .play::after {
  content: ""; width: 0; height: 0; margin-left: 5px;
  border-left: 21px solid #24190a; border-top: 13px solid transparent; border-bottom: 13px solid transparent;
}
.video .vlabel {
  position: absolute; z-index: 1; left: 0; right: 0; bottom: 0; padding: 16px 18px;
  background: linear-gradient(transparent, rgba(7,18,36,.95));
  color: #fff; font-weight: 600; font-size: .97rem; text-align: left;
}
.video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ============================================================
   MEMBER REGISTER
   ------------------------------------------------------------
   The wall of faces reuses .people / .person from above — a
   member card and a candidate card are the same object, so they
   should not be two different components. Only the pieces that
   did not already exist are defined here.
   ============================================================ */

/* ---------- demo banner ----------
   Not dismissable on purpose. While the register is running on
   sample data, every screenshot of it has to say so. */
.demo-banner {
  background: var(--accent-soft); color: #7a5a12;
  border-bottom: 2px solid var(--accent);
  padding: 12px 22px; font-size: .9rem; line-height: 1.6; text-align: center;
}
@media (prefers-color-scheme: dark) { .demo-banner { color: var(--accent-text); } }

/* ---------- ward coverage grid ----------
   One cell per ward. An empty cell is the point: it reads as a
   job opening rather than an absence. */
.cov-block { margin: 0 0 30px; }
.cov-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px; margin-bottom: 12px; }
.cov-head h3 { margin: 0; font-size: 1.08rem; }
.cov-count { font-size: .88rem; color: var(--muted); font-weight: 600; }
.cov-grid { display: flex; flex-wrap: wrap; gap: 5px; }
.cov-cell {
  width: 15px; height: 15px; border-radius: 3px;
  background: var(--line); border: 1px solid transparent;
}
.cov-cell.on { background: var(--brand-deep); border-color: var(--brand-deep); }
@media (prefers-color-scheme: dark) { .cov-cell.on { background: var(--brand); border-color: var(--brand); } }
.cov-note { font-size: .82rem; color: var(--muted); margin: 10px 0 0; }

/* ---------- filters ---------- */
#roster-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 0 0 26px; }
#roster-filters select { width: auto; min-width: 240px; margin-bottom: 0; }
.filter-label { margin-bottom: 0; }
#roster-count { font-size: .9rem; color: var(--muted); margin: 0 0 20px; }

/* ---------- form feedback ---------- */
.form-msg {
  padding: 13px 16px; border-radius: 10px; margin: 16px 0;
  background: var(--brand-soft); color: var(--brand-deep); font-size: .93rem;
}
.form-msg.error { background: #fdecec; color: #9b1c1c; }
@media (prefers-color-scheme: dark) {
  .form-msg { color: #7ACBFF; }
  .form-msg.error { background: #2e1414; color: #ff9b9b; }
}

/* ---------- consent block ----------
   Given real visual weight rather than fine print, because these
   are three separate decisions and people should read them. */
.consent { border: 1px solid var(--line); border-radius: var(--radius); padding: 20px 22px; margin: 28px 0; }
.consent h3 { font-size: 1.02rem; margin: 0 0 14px; }
.consent-item { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 16px; }
.consent-item:last-child { margin-bottom: 0; }
.consent-item input[type="checkbox"] {
  width: 22px; height: 22px; margin: 2px 0 0; flex: 0 0 auto; accent-color: var(--brand-deep);
}
.consent-item label { margin: 0; font-weight: 500; line-height: 1.6; }
.consent-item .req { color: var(--brand-deep); font-weight: 700; }
@media (prefers-color-scheme: dark) { .consent-item .req { color: #7ACBFF; } }
.consent-item .why { display: block; font-weight: 400; font-size: .87rem; color: var(--muted); margin-top: 3px; }

/* ---------- photo picker ---------- */
.photo-row { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
#photo-preview img {
  width: 120px; height: 120px; border-radius: 12px; object-fit: cover;
  border: 1px solid var(--line);
}
.photo-note { font-size: .86rem; color: var(--muted); margin: 8px 0 0; max-width: 46ch; }

/* ---------- member card preview ---------- */
.card-preview img {
  width: 100%; max-width: 340px; border-radius: var(--radius);
  border: 1px solid var(--line); box-shadow: var(--shadow);
}

/* ---------- moderation queue ---------- */
.queue-item {
  background: var(--card); border: 1px solid var(--line); border-left: 4px solid var(--line);
  border-radius: var(--radius); padding: 20px 22px; margin-bottom: 18px; box-shadow: var(--shadow);
}
.queue-item.candidate { border-left-color: var(--accent); }
.queue-head { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 8px; }
.queue-head h3 { margin: 0; font-size: 1.1rem; }
.queue-quote {
  margin: 14px 0; padding: 12px 16px; border-left: 3px solid var(--line);
  color: var(--body); font-size: .93rem; font-style: italic;
}
.queue-consent { font-size: .84rem; color: var(--muted); margin: 10px 0 0; }
.queue-note { font-size: .84rem; color: var(--muted); margin: 14px 0 0; }
.queue-warn {
  background: #fdecec; color: #9b1c1c; border-radius: 10px;
  padding: 12px 15px; margin: 14px 0 0; font-size: .9rem; line-height: 1.6;
}
@media (prefers-color-scheme: dark) { .queue-warn { background: #2e1414; color: #ff9b9b; } }

/* The roster grids fill from the left instead of stretching. .people uses
   auto-fit, which is right for the leadership section where the card count
   is fixed, but wrong here: with one confirmed candidate, auto-fit stretches
   that single card the full width of the page and the avatar becomes an
   enormous blue slab. auto-fill keeps the empty tracks, so one card looks
   like one card. This page starts life with one or two entries, so this is
   the normal case, not the edge case. */
#roster-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }

/* ---------- reduced motion ----------
   Fewer and gentler, not zero: colour and opacity changes stay, movement goes.
   The map draws its finished picture at once (see js/map.js). */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important;
  }
  .ticker-run { animation: none !important; }
  html.io .reveal, html.io .reveal.in { opacity: 1; transform: none; transition: none; }
  .btn, .chip, .person, .person img, .card.lift, .q-opts button, .nav { transition-property: background-color, border-color, color, opacity, box-shadow; }
  .btn:active, .chip:active, .q-opts button:active { transform: none; }
  @view-transition { navigation: none; }
}

/* on paper nothing scrolls, so nothing may wait for a scroll */
@media print { html.io .reveal { opacity: 1 !important; transform: none !important; } }
