/* ============================================================
   MAX FOR MAYOR — DESIGN SYSTEM

   A neutral, minimal palette. The photography and the figures are
   the loud things on this site; the interface is not.

     Charcoal     #17202A   navigation, footer, full-width bands
     Warm white   #FAF9F6   main background
     Soft grey    #EEF1F3   alternating sections
     Teal         #087E8B   identity: links, icons, secondary actions
     Warm gold    #E4A11B   primary buttons and small accents

   THREE RULES THAT KEEP IT LOOKING LIKE THIS

   1. No more than three prominent colours on one screen. Charcoal and
      warm white are two of them, so an accent is the third — teal OR
      gold in a given block, not both competing.
   2. Gold is the most important button and nothing else. It is the
      single most expensive colour on the page; spend it once per view.
   3. Teal is the identity colour, not a background. It went from being
      a huge field to being an accent deliberately: large teal panels
      read as municipal signage, which is the opposite of the intent.

   TOKENS ARE NAMED BY ROLE, NOT BY COLOUR

   --band is the charcoal field, --accent is the teal, --gold is the
   action colour. An earlier version named these --teal and --teal-deep
   and then the palette changed, which left the stylesheet full of
   tokens whose names lied about their contents. Role names survive a
   repaint; colour names do not.
   ============================================================ */

/* ---------- Typefaces ----------

   Self-hosted, not loaded from Google.

   The site's privacy policy says nothing on it contacts a third party,
   and fonts were the last thing that did — Google saw an IP address and
   a page for every visitor, on every page. Do not "simplify" these into
   a <link> to fonts.googleapis.com; that quietly makes the privacy
   policy false.

   Manrope for text, DM Serif Display for the largest headlines only.
   Manrope is variable, so ONE file per subset covers 400 through 800.
   The  pair loads for English pages;  is fetched only if a page
   actually uses those characters.

   DM SERIF DISPLAY HAS EXACTLY ONE WEIGHT (400). Asking for 600 or 700
   on a heading does not make it bolder — the browser fakes it by
   smearing the glyphs, which on a high-contrast display face looks
   like a rendering fault. The heading rules below set 400 on purpose.

   Both licensed under the SIL Open Font License, which permits
   self-hosting. Farsi and Chinese on voting.html fall back to system
   fonts: neither family has Arabic or CJK coverage. */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('manrope-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('manrope-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Persian. Neither Manrope nor DM Serif Display has a single Arabic
   glyph, so without this the Farsi page falls back to whatever the
   device happens to have — usually a Naskh face at the wrong size next
   to the Latin. Vazirmatn is drawn for Persian specifically and is
   variable, so one file covers 400-700.

   The unicode-range means this is fetched ONLY by a page that actually
   contains Persian characters. The English pages never request it.

   SIL Open Font License, like the other two. */
@font-face {
  font-family: 'Vazirmatn';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('vazirmatn-arabic.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'DM Serif Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('dm-serif-display-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Serif Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('dm-serif-display-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: light;

  /* SURFACES and TEXT change between themes. The charcoal bands and the
     text on them do NOT — a band is dark in both themes, so --on-band
     and friends are defined once, here, and never overridden below. */
  --page:        #FAF9F6;   /* warm white — the main background */
  --surface:     #FFFFFF;   /* cards: white, so they lift off both grounds */
  --surface-2:   #EEF1F3;   /* soft grey — alternating sections */
  --surface-3:   #E2E8EC;   /* one step deeper, for blocks nested in those */
  --text:        #17202A;   /* charcoal */
  --text-muted:  #4C5A66;

  /* The teal identity colour, in two strengths.

     --accent is the colour as specified (#087E8B). It is 4.57:1 on the
     warm white page — a pass, but only just — and 4.24:1 on the soft
     grey sections, which is a FAIL. So it is used for icons, rules and
     fills, never for body-size text.

     --brand-fg is the same hue darkened until it passes on every light
     surface (5.0:1 on soft grey, 5.4:1 on warm white). That is the one
     that colours links and small text. `node contrast.js` checks both. */
  --accent:      #087E8B;
  --accent-hover: #066570;
  --brand-fg:    #0A717C;
  --link:        #0A717C;
  --on-accent:   #FFFFFF;   /* label on a teal fill — see the dark block */
  --icon-bg:     #DDEEF0;
  --icon-fg:     #0A717C;

  /* The charcoal bands: header, hero, footer, full-width feature
     sections. Identical in both themes. */
  --band:        #17202A;
  --band-2:      #22303C;   /* hover and gradient partner */
  --band-deep:   #101820;   /* footer and the thin bars */
  --on-band:       #FAF9F6;
  --on-band-muted: #B8C2C8;
  --accent-on-band: #27B3B8; /* the light teal reads on charcoal; #087E8B does not */

  /* Gold. Action only. */
  --gold:        #E4A11B;
  --gold-hover:  #F0B23F;
  --gold-edge:   #B87F12;   /* the 3px lip under a gold button */
  --gold-soft:   #FBEFD6;
  /* Gold text on a light surface. #E4A11B is 2.1:1 on the page —
     unreadable — so the 12px eyebrow labels use this instead: 5.1:1 on
     warm white, 4.7:1 on soft grey. Measured by `node contrast.js`,
     not guessed. */
  --gold-dark:   #8A6410;

  --line:        rgba(23, 32, 42, .12);
  --line-strong: rgba(23, 32, 42, .24);
  --alert:       #A3341A;

  /* Notice and form-status colours. These were raw hex for both themes,
     which meant the dark theme kept a pale pink notice and painted the
     near-white body text on it: 1.08:1, invisible. The disclaimers that
     sit in .notice--strong are exactly the ones that must stay readable
     ("this is a campaign website, not a District publication"), so they
     are tokens now and contrast.js checks them in both themes. */
  --notice-alert:     #FBEAE5;
  --status-ok-bg:     #E7F3EC;  --status-ok-line:   #A8CFBA;  --status-ok-fg:   #17563A;
  --status-err-bg:    #FBEAE5;  --status-err-line:  #E4B4A3;  --status-err-fg:  #7A2E12;
  --status-info-bg:   #FBEFD6;  --status-info-line: #DCC68A;  --status-info-fg: #6B4E0C;

  --font-display: 'DM Serif Display', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --font-body:    'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  --shell:  1180px;
  --prose:  68ch;
  --radius: 18px;
  --radius-sm: 12px;

  /* Shadows are neutral charcoal, not tinted. A coloured shadow on a
     neutral palette reads as a glow. */
  --shadow-sm: 0 1px 2px rgba(23,32,42,.05), 0 2px 8px rgba(23,32,42,.04);
  --shadow-md: 0 4px 14px rgba(23,32,42,.07), 0 12px 34px rgba(23,32,42,.06);
  --shadow-lg: 0 10px 30px rgba(23,32,42,.10), 0 30px 70px rgba(23,32,42,.08);

  --ease: cubic-bezier(.22,.61,.36,1);
  --step: clamp(3.25rem, 7vw, 6rem);   /* vertical section rhythm */
}

/* Dark theme.

   Three states, not two: an explicit choice stamps data-theme on <html>,
   and the default "system" setting stamps nothing — so the media query
   has to cover the un-stamped document while still losing to an explicit
   light choice. Hence the :not([data-theme="light"]) guard, and the
   repeat for the toggle's own data-theme="dark".

   Deep charcoal rather than black: black makes the warm white text
   glare, and the whole palette is warm.

   Only surfaces, text and the teal move. The bands stay charcoal in
   both themes, which is why none of the --on-band tokens are repeated
   here — they already work.

   Note --on-accent flips. #27B3B8 is bright enough that white text on
   it is 2.6:1, a clear fail; charcoal on it is 7.0:1. A teal button
   therefore has a white label in light and a charcoal label in dark. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  color-scheme: dark;

  --page:        #101820;
  --surface:     #1F2D37;
  --surface-2:   #17232D;
  --surface-3:   #243642;
  --text:        #F7F6F2;
  --text-muted:  #B8C2C8;

  --accent:      #27B3B8;
  --accent-hover: #45C7CC;
  --brand-fg:    #27B3B8;
  --link:        #27B3B8;
  --on-accent:   #101820;
  --icon-bg:     #14303A;
  --icon-fg:     #27B3B8;

  --gold:        #F2B544;
  --gold-hover:  #F7C866;
  --gold-edge:   #C08E26;
  --gold-soft:   #2A2413;
  --gold-dark:   #F2B544;

  --line:        #33434D;
  --line-strong: #4A5D69;
  --alert:       #F0A48C;

  --notice-alert:     #2E1A15;
  --status-ok-bg:     #12291E;  --status-ok-line:   #2C5C42;  --status-ok-fg:   #8FD9B0;
  --status-err-bg:    #2E1A15;  --status-err-line:  #6B3A2A;  --status-err-fg:  #F0A48C;
  --status-info-bg:   #2A2413;  --status-info-line: #5C4E20;  --status-info-fg: #F2B544;
  --focus-ring:  var(--gold);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --page:        #101820;
  --surface:     #1F2D37;
  --surface-2:   #17232D;
  --surface-3:   #243642;
  --text:        #F7F6F2;
  --text-muted:  #B8C2C8;

  --accent:      #27B3B8;
  --accent-hover: #45C7CC;
  --brand-fg:    #27B3B8;
  --link:        #27B3B8;
  --on-accent:   #101820;
  --icon-bg:     #14303A;
  --icon-fg:     #27B3B8;

  --gold:        #F2B544;
  --gold-hover:  #F7C866;
  --gold-edge:   #C08E26;
  --gold-soft:   #2A2413;
  --gold-dark:   #F2B544;

  --line:        #33434D;
  --line-strong: #4A5D69;
  --alert:       #F0A48C;

  --notice-alert:     #2E1A15;
  --status-ok-bg:     #12291E;  --status-ok-line:   #2C5C42;  --status-ok-fg:   #8FD9B0;
  --status-err-bg:    #2E1A15;  --status-err-line:  #6B3A2A;  --status-err-fg:  #F0A48C;
  --status-info-bg:   #2A2413;  --status-info-line: #5C4E20;  --status-info-fg: #F2B544;
  --focus-ring:  var(--gold);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* `clip` rather than `hidden`: it prevents sideways scroll without
     turning the root into a scroll container, which is what breaks
     position:sticky on the header in some browsers. */
  overflow-x: clip;
}
body {
  margin: 0;
  background: var(--page);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  /* `clip`, for the same reason as on <html> above, and this one was the
     remaining culprit: `overflow-x: hidden` here makes BODY a scroll
     container, and a position:sticky header then sticks inside a box that
     never scrolls — so it slid away with the page on every single page.
     The comment on <html> already described the bug; body was missed. */
  overflow-x: clip;
}
img, svg, video { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4 { margin: 0 0 .5em; text-wrap: balance; }
/* The serif is a display face, used on the two largest levels only. Below
   that it stops reading as a headline and starts reading as a magazine
   pull-quote, and h3 is a workhorse: it labels cards and form sections.
   Weight 400 is not a preference — DM Serif Display ships no other one,
   and asking for 700 makes the browser smear the glyphs instead. */
h1, h2 { font-family: var(--font-display); font-weight: 400; line-height: 1.06; letter-spacing: -.017em; }
h3, h4 { font-family: var(--font-body); font-weight: 700; line-height: 1.25; letter-spacing: -.011em; }
h1 { font-size: clamp(2.5rem, 5.8vw, 4.25rem); }
h2 { font-size: clamp(1.9rem, 3.7vw, 2.8rem); }
h3 { font-size: clamp(1.2rem, 2vw, 1.45rem); }
h4 { font-size: 1.05rem; letter-spacing: 0; }
p  { margin: 0 0 1.1em; text-wrap: pretty; }
a  { color: var(--link); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { color: var(--brand-fg); }
ul, ol { margin: 0 0 1.1em; padding-left: 1.25em; }
li { margin-bottom: .45em; }
strong { font-weight: 700; }
hr { border: 0; border-top: 1px solid var(--line); margin: var(--step) 0; }
small { font-size: .8125rem; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* ---------- Scroll reveal ----------

   Sections fade up as they arrive. Three constraints, all of which the
   obvious implementation gets wrong:

   - THE DEFAULT STATE IS VISIBLE. `.reveal` is added by JavaScript, so
     with JS off, blocked or broken, nothing is hidden. Content parked at
     opacity:0 waiting for an observer is a blank page to a crawler and
     to anyone whose script did not load.
   - Whatever is already on screen at load never animates. The first
     thing a visitor sees should be at rest, not mid-transition.
   - Reduced motion skips it entirely — app.js never creates the
     observer. The rule below is a second line of defence: without it,
     the global reduced-motion rule above would strip the transition and
     strand any .reveal element at opacity 0 forever. */
.reveal { opacity: 0; transform: translateY(16px); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.is-in { opacity: 1; transform: none; }
}
/* Printing does not scroll, so nothing would ever be revealed. */
@media print {
  .reveal, .reveal.is-in { opacity: 1 !important; transform: none !important; }
}

/* ---------- Accessibility ---------- */
/* Hidden ABOVE the viewport, not off to the side.

   This used to be `left: -9999px`, which is the usual trick and is
   harmless in a left-to-right page. On the right-to-left Farsi page it
   is not: in RTL, content at a negative left offset extends the
   scrollable area instead of falling off the end of it, and the
   document reported 10,356px of width on a 372px screen. Moving it
   vertically works identically in both directions, and the link stays
   in the tab order and in the accessibility tree either way. */
.skip-link {
  position: absolute; inset-inline-start: 0; top: 0; z-index: 999;
  transform: translateY(-200%);
  background: var(--gold); color: var(--band-deep); font-weight: 700;
  padding: .85rem 1.4rem; border-end-end-radius: var(--radius-sm);
}
.skip-link:focus { transform: none; }

/* Anchor targets clear the sticky header. Without this, jumping to
   #voting lands with the heading hidden behind the header — which the
   Farsi page notices immediately because its whole menu is in-page
   links, but it applies to #feedback and the legal.html anchors too. */
section[id], article[id], div[id], h2[id], h3[id] { scroll-margin-top: 5.5rem; }
/* Focus indicator.

   A gold ring is only 1.85:1 against white and 1.65:1 against stone —
   invisible on the majority of the site, which would leave keyboard
   users with no idea where they are. The ring colour therefore follows
   the surface: dark teal on the light pages, gold on the teal sections,
   dark teal again on the gold GOTV field. Custom properties inherit, so
   a section sets it once and everything inside picks it up.

   `node contrast.js` checks all three pairings. */
:root { --focus-ring: var(--brand-fg); }
.site-header, .section--band, .hero, .on-band, .cred-bar, .site-footer { --focus-ring: var(--gold); }
/* A plain link inside a charcoal band. Without this it inherits --link,
   which is the teal chosen to be readable on WHITE — 2.5:1 on charcoal.
   The footer already set its own link colour, which is why this was only
   visible on the wastewater flow diagram's source links. */
.section--band a:not(.btn), .hero a:not(.btn), .on-band a:not(.btn), .cred-bar a:not(.btn) {
  color: var(--accent-on-band);
}
.gotv-hero { --focus-ring: var(--band-deep); }

:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 3px;
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Layout ---------- */
.shell { width: min(100% - 2.5rem, var(--shell)); margin-inline: auto; }
@media (max-width: 560px) { .shell { width: calc(100% - 2rem); } }
.section { padding-block: var(--step); }
.section--soft { background: var(--surface-2); }
.section--band  { background: var(--band); color: var(--on-band); }
.section--band h2, .section--band h3 { color: var(--on-band); }
.section--tight { padding-block: clamp(2.25rem, 4vw, 3.25rem); }
.prose { max-width: var(--prose); }
.grid { display: grid; gap: clamp(1rem, 2.2vw, 1.6rem); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 275px), 1fr)); }

/* Two-column splits where the columns are NOT interchangeable — main
   column plus a sidebar. `auto-fit` cannot express that, so these are
   explicit, and they must collapse: written inline as a fixed two-column
   grid they stayed two columns at 375px, giving a 137px column with the
   heading wrapped over six lines. */
.split { display: grid; align-items: start; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1.1fr .9fr; }
.split--aside { grid-template-columns: 1fr 340px; }
@media (max-width: 860px) {
  .split, .split--aside { grid-template-columns: 1fr; }
}
.center { text-align: center; }
.center .prose { margin-inline: auto; }

/* Section eyebrow: the small gold-ruled label above a heading. */
.eyebrow {
  display: flex; align-items: center; gap: .7rem;
  font-size: .75rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--gold-dark); margin-bottom: .9rem;
}
.eyebrow::after { content: ''; flex: 0 0 2.25rem; height: 2px; background: var(--gold); border-radius: 2px; }
.section--band .eyebrow { color: var(--gold); }
.center .eyebrow { justify-content: center; }
.lede { font-size: clamp(1.075rem, 1.9vw, 1.25rem); color: var(--text-muted); line-height: 1.6; }
.section--band .lede { color: var(--on-band-muted); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  font-family: var(--font-body); font-size: 1rem; font-weight: 600; line-height: 1;
  padding: .95rem 1.5rem; border-radius: 999px; border: 2px solid transparent;
  text-decoration: none; cursor: pointer; transition: transform .18s var(--ease), background .18s, box-shadow .18s, border-color .18s;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn svg { width: 1.05em; height: 1.05em; flex: none; }

.btn--gold    { background: var(--gold); color: var(--band-deep); box-shadow: 0 3px 0 var(--gold-edge); }
.btn--gold:hover { background: var(--gold-hover); color: var(--band-deep); }
.btn--accent    { background: var(--accent); color: var(--on-accent); }
.btn--accent:hover { background: var(--accent-hover); color: var(--on-accent); }
.btn--outline { border-color: var(--line-strong); color: var(--brand-fg); background: transparent; }
.btn--outline:hover { border-color: var(--brand-fg); background: rgba(8,126,139,.07); color: var(--brand-fg); }
/* The header is a charcoal band, so its outline buttons take the same
   treatment as the ones on any other band. Without .site-header in this
   list they kept --brand-fg, which is the teal for LIGHT surfaces: 2.87:1
   on charcoal, a clear AA failure, and the border was a charcoal alpha on
   charcoal so it was invisible too. contrast.js checks token pairs, not
   which token ends up on which surface, so this was found by reading the
   rendered colours off the page. */
.site-header .btn--outline, .on-band .btn--outline, .section--band .btn--outline{ border-color: rgba(255,255,255,.45); color: var(--on-band); }
.site-header .btn--outline:hover, .on-band .btn--outline:hover, .section--band .btn--outline:hover { background: rgba(255,255,255,.12); border-color: var(--on-band); color: var(--on-band); }
.btn--sm { padding: .6rem 1.05rem; font-size: .875rem; }
.btn--block { width: 100%; }
.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }
.center .btn-row { justify-content: center; }

/* ---------- Header ---------- */
.alert-bar {
  background: var(--band-deep); color: var(--on-band-muted);
  font-size: .8125rem; text-align: center; padding: .55rem 1rem;
}
.alert-bar strong { color: var(--on-band); }
.alert-bar a { color: var(--gold); font-weight: 600; }

.site-header {
  position: sticky; top: 0; z-index: 60;
  /* Solid, and deliberately NOT backdrop-filter.
     A backdrop-filter makes the element a containing block for any
     position:fixed descendant, and the mobile nav drawer is one. With the
     filter here the drawer was clamped to the header's own ~120px height
     instead of filling the screen, so the phone menu opened as a small
     clipped box. Translucency is not worth a broken menu. */
  background: var(--band);
  /* On a charcoal bar the shared --line token (a charcoal alpha) is
     invisible, so the hairline is a white alpha instead. */
  border-bottom: 1px solid rgba(255,255,255,.10);
}
.site-header.is-scrolled { box-shadow: var(--shadow-sm); }
.header-inner { display: flex; align-items: center; gap: 1rem; min-height: 72px; }

.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; color: var(--on-band); flex: none; }
.brand-mark {
  width: 42px; height: 42px; border-radius: 11px; flex: none;
  /* Teal, not gold: gold is reserved for the one primary button, and a
     permanent gold chip in the header would compete with it on every
     page. This is where the identity colour lives. */
  background: var(--accent-on-band); color: var(--band);
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 400; font-size: 1.3rem; letter-spacing: -.02em;
}
.brand-text { line-height: 1.1; }
.brand-name { font-family: var(--font-display); font-weight: 400; font-size: 1.16rem; color: var(--on-band); display: block; }
.brand-sub  { font-size: .69rem; letter-spacing: .1em; text-transform: uppercase; color: var(--on-band-muted); }

.nav { margin-left: auto; display: flex; align-items: center; gap: .15rem; }
.nav a {
  font-size: .905rem; font-weight: 500; color: var(--on-band-muted); text-decoration: none;
  padding: .5rem .62rem; border-radius: 7px; white-space: nowrap;
}
.nav a:hover { background: rgba(255,255,255,.09); color: var(--on-band); }
.nav a[aria-current="page"] { color: var(--on-band); font-weight: 700; box-shadow: inset 0 -2px 0 var(--gold); }
.header-cta { display: flex; align-items: center; gap: .5rem; flex: none; }

/* Day / night control. Shows the theme it will switch TO, which is the
   convention people already expect from their phone. */
.theme-toggle {
  width: 40px; height: 40px; flex: none; cursor: pointer;
  border: 1px solid rgba(255,255,255,.24); border-radius: 10px;
  background: transparent; color: var(--on-band);
  display: grid; place-items: center;
  transition: background .16s, border-color .16s, color .16s;
}
.theme-toggle:hover { background: rgba(255,255,255,.10); border-color: var(--on-band); }
.theme-toggle svg { width: 19px; height: 19px; grid-area: 1 / 1; }
.theme-toggle .theme-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .theme-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .theme-sun  { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .theme-moon { display: none; }
}

.nav-toggle {
  display: none; margin-left: auto; width: 44px; height: 44px;
  /* flex:none, or it gets squeezed. It was shrinking to 13px on a phone
     once the theme toggle joined the header — a hamburger nobody could
     reliably hit, and the only way into the menu. */
  flex: none;
  border: 1px solid rgba(255,255,255,.24); border-radius: 10px; background: transparent;
  cursor: pointer; color: var(--on-band); align-items: center; justify-content: center;
}
.nav-toggle svg { width: 22px; height: 22px; }

@media (max-width: 1080px) {
  .nav {
    position: fixed; inset: 0 0 0 auto; width: min(86vw, 340px);
    background: var(--band); border-left: 1px solid rgba(255,255,255,.10);
    flex-direction: column; align-items: stretch; gap: .1rem;
    padding: 5.5rem 1.25rem 2rem; overflow-y: auto;
    transform: translateX(100%);
    /* `visibility` keeps the closed drawer out of the tab order and out of
       the accessibility tree. Without it a keyboard or screen-reader user
       tabs through nine invisible links parked off-screen. It also stops
       the off-canvas panel widening the document. Visibility flips to
       hidden only at the end of the transition, so the slide-out still
       animates. */
    visibility: hidden;
    transition: transform .28s var(--ease), visibility .28s var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .nav[data-open="true"] { transform: translateX(0); visibility: visible; }
  /* Right-to-left: the header-cta and the hamburger sit on the left, so a
     drawer flying in from the right would cross the whole screen and
     cover the button that opened it. */
  [dir="rtl"] .nav {
    inset: 0 auto 0 0;
    border-left: 0; border-right: 1px solid rgba(255,255,255,.10);
    transform: translateX(-100%);
  }
  [dir="rtl"] .nav[data-open="true"] { transform: translateX(0); }
  .nav a { padding: .85rem .75rem; font-size: 1.02rem; border-bottom: 1px solid var(--line); border-radius: 0; }
  .nav-social { display: flex; margin-top: 1.25rem; }
  .nav-social a { border-bottom: 0; padding: 0; }
  .nav-toggle { display: inline-flex; }
  /* Outline buttons fold into the drawer on a phone; the theme toggle
     stays. The language link is the exception and must never be hidden:
     on the English pages it is the only signpost a Farsi speaker can
     recognise, and on the Farsi page — which has no drawer at all — it
     is the only way back to English. It was invisible on a phone until
     this exception existed. */
  .header-cta .btn--outline:not(.lang-link) { display: none; }
  .nav-scrim {
    position: fixed; inset: 0; background: rgba(16,24,32,.55); z-index: 55;
    opacity: 0; pointer-events: none; transition: opacity .28s;
  }
  .nav-scrim[data-open="true"] { opacity: 1; pointer-events: auto; }
}
@media (max-width: 560px) {
  .brand-sub { display: none; }
  .header-cta .btn { padding: .7rem 1rem; font-size: .9rem; }
  /* Brand, menu, theme and Donate all have to fit across a phone. */
  .header-inner { gap: .5rem; }
  .brand { min-width: 0; }
  .brand-name { font-size: 1.05rem; white-space: nowrap; }
  .theme-toggle { width: 36px; height: 36px; }
  .theme-toggle svg { width: 17px; height: 17px; }
}

/* ---------- Hero ---------- */
.hero {
  position: relative; background: var(--band); color: var(--on-band); overflow: hidden;
  padding-block: clamp(3rem, 6vw, 5rem) 0;
}
/* North Shore ridge line — place, without stock photography. */
.hero::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 42%;
  background: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1400 300' preserveAspectRatio='none'%3E%3Cg fill='none' stroke='%23ffffff' stroke-opacity='.07' stroke-width='2'%3E%3Cpath d='M0 260 L180 150 L300 205 L470 70 L600 170 L760 40 L900 160 L1060 90 L1220 190 L1400 120'/%3E%3Cpath d='M0 300 L200 200 L340 250 L520 120 L660 215 L820 95 L960 205 L1120 140 L1280 235 L1400 175'/%3E%3Cpath d='M0 220 L160 110 L280 165 L450 30 L580 130 L740 5 L880 120 L1040 50 L1200 150 L1400 80'/%3E%3C/g%3E%3C/svg%3E") bottom center / 100% 100% no-repeat;
  pointer-events: none;
}
.hero-grid {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1.15fr .85fr; gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: end;
}
.hero-copy { padding-bottom: clamp(2.5rem, 5vw, 4rem); }
.hero h1 { color: var(--on-band); margin-bottom: .35em; }
.hero h1 .accent { color: var(--gold); display: block; }
.hero-sub { font-size: clamp(1.05rem, 1.9vw, 1.24rem); color: var(--on-band-muted); max-width: 34rem; margin-bottom: 1.9rem; }
.hero-name {
  display: inline-flex; align-items: center; gap: .6rem;
  font-size: .78rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 1.1rem;
}
.hero-name::before { content: ''; width: 2rem; height: 2px; background: var(--gold); }

.hero-portrait { position: relative; align-self: end; }
.hero-portrait picture { display: block; }
.hero-portrait img {
  width: 100%; height: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  box-shadow: 0 -6px 40px rgba(0,0,0,.28);
}
/* The portrait was shot against a bright sky, so it arrives as a pale
   rectangle. On the deep teal hero that needs an edge, or it reads as a
   hole punched in the section rather than a photograph sitting on it. */
.hero-portrait picture::after { content: none; }
.hero-portrait {
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden;
  outline: 1px solid rgba(228,161,27,.35);
  outline-offset: -1px;
}

/* Meet Max: the same portrait as a self-contained card. */
.portrait-card {
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line); box-shadow: var(--shadow-md);
}
.portrait-card img { width: 100%; height: auto; display: block; }
/* Graceful stand-in until the real portrait lands — looks deliberate, not broken. */
.portrait-placeholder {
  aspect-ratio: 4/5; border-radius: var(--radius) var(--radius) 0 0;
  background: linear-gradient(165deg, var(--band-2), var(--band-deep));
  border: 1px dashed rgba(228,161,27,.45); border-bottom: 0;
  display: grid; place-content: center; gap: .5rem; text-align: center; padding: 2rem;
  color: rgba(228,161,27,.85);
}
.portrait-placeholder .mono { font-family: var(--font-display); font-size: clamp(3rem, 7vw, 5rem); line-height: 1; color: var(--gold); }
.portrait-placeholder .hint { font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; color: var(--on-band-muted); }
@media (max-width: 860px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-portrait { max-width: 320px; margin-inline: auto; width: 100%; }
  .hero-copy { padding-bottom: 1.5rem; }
}

/* ---------- Countdown ---------- */
.countdown { display: flex; gap: .6rem; flex-wrap: wrap; margin-bottom: 1.75rem; }
.countdown-unit {
  background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.16);
  border-radius: var(--radius-sm); padding: .65rem .85rem; min-width: 68px; text-align: center;
}
.countdown-num {
  font-family: var(--font-display); font-size: 1.85rem; font-weight: 700; line-height: 1;
  color: var(--gold); font-variant-numeric: tabular-nums; display: block;
}
.countdown-label { font-size: .66rem; letter-spacing: .11em; text-transform: uppercase; color: #A9C7CB; }
.countdown-caption { font-size: .85rem; color: #A9C7CB; margin-bottom: .6rem; }
.countdown-caption strong { color: var(--on-band); }
.section--soft .countdown-unit { background: var(--surface); border-color: var(--line); }
.section--soft .countdown-num { color: var(--brand-fg); }
.section--soft .countdown-label, .section--soft .countdown-caption { color: var(--text-muted); }

/* ---------- Credibility bar ---------- */
.cred-bar { background: var(--band-deep); color: var(--on-band-muted); padding-block: 1.5rem; }
.cred-list {
  display: flex; flex-wrap: wrap; gap: .5rem clamp(1rem, 3vw, 2.5rem);
  align-items: center; justify-content: center; list-style: none; margin: 0; padding: 0;
  font-size: .92rem;
}
.cred-list li { display: flex; align-items: center; gap: .5rem; margin: 0; }
.cred-list li + li::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--gold); opacity: .55; margin-right: clamp(.5rem, 1.5vw, 1.25rem); }
.cred-stat { font-family: var(--font-display); font-weight: 700; font-size: 1.35rem; color: var(--gold); }

/* ---------- Cards ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: clamp(1.25rem, 2.4vw, 1.75rem);
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s;
}
.card--link:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--line-strong); }
.card h3 { margin-bottom: .4rem; }
.card h3 a { color: var(--brand-fg); text-decoration: none; }
.card h3 a:hover { text-decoration: underline; text-decoration-color: var(--gold); }
.card p:last-child { margin-bottom: 0; }
.section--soft .card { background: var(--surface); }
.card-icon {
  width: 46px; height: 46px; border-radius: 12px; margin-bottom: .9rem;
  background: var(--icon-bg); color: var(--icon-fg); display: grid; place-items: center;
}
.card-icon svg { width: 24px; height: 24px; }

/* ---------- Resident concerns ---------- */
/* Ranked cards. The rank is set large and quiet: it orders the list without
   competing with the concern itself, which is what people came to read. */
.concern { display: flex; flex-direction: column; }
.concern-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .9rem; }
.concern-head .card-icon { margin-bottom: 0; }
.concern-rank {
  font-family: var(--font-display); font-size: 2.1rem; font-weight: 700; line-height: 1;
  color: var(--surface-3); font-variant-numeric: tabular-nums;
}
.concern h3 { font-size: 1.12rem; margin-bottom: .6rem; }

.concern-voice {
  margin: 0 0 1rem; font-size: .95rem; line-height: 1.55; color: var(--text-muted);
  border-left: 2px solid var(--gold); padding-left: .85rem; font-style: italic;
}
/* Literal curly quotes, not CSS C escapes: one of the tools that wrote
   this file read the escape as octal and put a control character here. */
.concern-voice::before { content: '“'; }
.concern-voice::after  { content: '”'; }
/* A summary of concerns is not a quotation and must not be dressed as one. */
.concern-voice--plain { font-style: normal; border-left-color: var(--line-strong); }
.concern-voice--plain::before, .concern-voice--plain::after { content: none; }

.concern-who {
  margin: auto 0 0; padding-top: .85rem; border-top: 1px solid var(--line);
  font-size: .8rem; color: var(--text-muted); line-height: 1.45;
}
.concern-who span {
  display: block; font-size: .68rem; letter-spacing: .11em; text-transform: uppercase;
  color: var(--gold-dark); font-weight: 700; margin-bottom: .2rem;
}

/* ---------- Priority list ---------- */
.priority-points { list-style: none; padding: 0; margin: 1rem 0 0; }
.priority-points li { position: relative; padding-left: 1.7rem; margin-bottom: .55rem; color: var(--text-muted); }
.priority-points li::before {
  content: ''; position: absolute; left: 0; top: .58em; width: .6rem; height: .32rem;
  border-left: 2px solid var(--gold); border-bottom: 2px solid var(--gold);
  transform: rotate(-45deg);
}

/* Expandable policy block */
.accordion { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; margin-bottom: .75rem; }
.accordion > summary {
  list-style: none; cursor: pointer; padding: 1.15rem 1.4rem;
  display: flex; align-items: center; gap: 1rem; font-weight: 600; color: var(--brand-fg);
  font-family: var(--font-display); font-size: clamp(1.08rem, 1.8vw, 1.3rem);
}
.accordion > summary::-webkit-details-marker { display: none; }
.accordion > summary::after {
  content: ''; margin-left: auto; flex: none; width: .65rem; height: .65rem;
  border-right: 2px solid var(--brand-fg); border-bottom: 2px solid var(--brand-fg);
  transform: rotate(45deg); transition: transform .22s var(--ease);
}
.accordion[open] > summary::after { transform: rotate(-135deg); }
.accordion > summary:hover { background: var(--surface-2); }
.accordion-body { padding: 0 1.4rem 1.4rem; }

/* ---------- Wastewater dashboard ---------- */
.ww-figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 1rem; margin: 1.75rem 0; }
.ww-fig {
  border: 1px solid rgba(255,255,255,.18); border-radius: var(--radius);
  padding: 1.35rem; background: rgba(255,255,255,.05);
}
.ww-fig .label { font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--on-band-muted); margin-bottom: .4rem; }
.ww-fig .value { font-family: var(--font-display); font-size: clamp(2rem, 4.4vw, 2.9rem); font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.ww-fig--then .value { color: var(--on-band-muted); }
.ww-fig--now  .value { color: var(--gold); }
.ww-fig--gap  .value { color: var(--gold); }
.ww-fig .note { font-size: .8rem; color: var(--on-band-muted); margin-top: .5rem; }

/* The household figure. Sized larger than the programme totals on purpose:
   it is the number a resident can act on, and the billions are context for
   it rather than the other way round. */
.ww-household {
  border: 1px solid rgba(228,161,27,.4); border-radius: var(--radius);
  background: rgba(228,161,27,.07); padding: clamp(1.25rem, 3vw, 1.85rem);
  margin: 1.75rem 0;
}
.ww-household .label { font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--on-band-muted); margin: 0 0 .35rem; }
.ww-household .value {
  margin: 0 0 .75rem;
  display: flex; align-items: baseline; gap: .55rem; flex-wrap: wrap;
}
/* The number carries the weight; "Approximately" and "per year" qualify it
   without competing with it. */
.ww-household .value .amount {
  font-family: var(--font-display); font-size: clamp(2.6rem, 6vw, 4rem); font-weight: 700;
  line-height: 1; color: var(--gold); font-variant-numeric: tabular-nums;
}
.ww-household .value .approx,
.ww-household .value .per {
  font-family: var(--font-body); font-size: .95rem; font-weight: 600;
  letter-spacing: .04em; color: var(--on-band-muted);
}
.ww-household .value .approx { flex-basis: 100%; margin-bottom: -.15rem; }
.ww-household .note { font-size: .85rem; color: #A9C7CB; margin: 0 0 .5rem; max-width: 62ch; }
.ww-household .note:last-child { margin-bottom: 0; }

/* The full-span comparison, made as a multiple because the arithmetic is
   unarguable even though the dollar figure is not the one Metro Vancouver
   publishes. */
.ww-multiple {
  font-size: 1.05rem; font-weight: 600; color: var(--gold);
  margin: -.35rem 0 0; max-width: 62ch;
}

/* Who pays what, by sewerage area. A table because it is tabular data and
   a screen reader should be able to read the row header with the figure. */
.ww-compare { width: 100%; border-collapse: collapse; margin: 1.25rem 0 .75rem; }
.ww-compare caption {
  text-align: left; font-size: .8rem; color: var(--on-band-muted);
  margin-bottom: .6rem; max-width: 58ch;
}
.ww-compare th, .ww-compare td {
  padding: .5rem .2rem; border-bottom: 1px solid rgba(255,255,255,.12);
  font-size: .92rem; font-weight: 400; text-align: left; color: var(--on-band-muted);
}
.ww-compare td { text-align: right; font-variant-numeric: tabular-nums; }
.ww-compare thead th {
  font-size: .7rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--on-band-muted); font-weight: 700; vertical-align: bottom;
}
.ww-compare thead th + th { text-align: right; }
.ww-compare tbody tr:last-child th, .ww-compare tbody tr:last-child td { border-bottom: 0; }
.ww-compare tr.is-lead th, .ww-compare tr.is-lead td { color: var(--gold); font-weight: 700; }
/* Two numeric columns on a phone will not fit; let the table scroll in its
   own box rather than pushing the page sideways. */
.ww-compare { display: block; overflow-x: auto; }
.ww-compare--phase { margin-top: 1.75rem; }

/* The comparison, said in a sentence for anyone who does not read tables. */
.ww-headline-compare {
  font-size: 1.05rem; line-height: 1.55; font-weight: 600; color: var(--gold);
  border-left: 3px solid var(--gold); padding-left: 1rem;
  margin: 1.5rem 0; max-width: 58ch;
}

.ww-financing { margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid rgba(255,255,255,.14); }
.ww-financing h2 { font-size: 1.25rem; color: var(--on-band); margin-bottom: .75rem; }
.ww-financing p { font-size: .88rem; color: #A9C7CB; margin-bottom: .8rem; max-width: 64ch; }
.ww-financing p:last-child { margin-bottom: 0; }

.ww-chart { margin: 2rem 0 .75rem; }
.ww-bar-row { display: grid; grid-template-columns: 5.5rem 1fr; gap: 1rem; align-items: center; margin-bottom: .85rem; }
.ww-bar-year { font-size: .82rem; font-weight: 600; color: var(--on-band-muted); font-variant-numeric: tabular-nums; }
.ww-bar-track { position: relative; height: 40px; background: rgba(255,255,255,.07); border-radius: 6px; overflow: hidden; }
.ww-bar-fill {
  height: 100%; border-radius: 6px; width: 0;
  background: linear-gradient(90deg, var(--accent), var(--gold));
  transition: width 1.1s var(--ease);
  display: flex; align-items: center; justify-content: flex-end; padding-right: .7rem;
}
.ww-bar-track--none {
  background: repeating-linear-gradient(45deg, rgba(255,255,255,.07) 0 8px, transparent 8px 16px);
  display: flex; align-items: center; padding-left: .8rem;
}
.ww-bar-none { font-size: .8rem; font-style: italic; color: #8FAFB3; }
.ww-bar-value { font-size: .82rem; font-weight: 700; color: var(--band-deep); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Figure for a bar too short to contain it: sits in the empty track, and
   fades in with the bar rather than hovering over an empty row first. */
.ww-bar-value--out {
  position: absolute; top: 50%; transform: translateY(-50%);
  color: var(--on-band-muted); opacity: 0; transition: opacity .5s var(--ease) .35s;
}
.ww-bar-track.is-shown .ww-bar-value--out { opacity: 1; }
.ww-bar-note { font-size: .82rem; color: var(--on-band-muted); padding-left: .2rem; }

/* Flow chart — the stage-by-stage story */
.flow { display: grid; gap: .75rem; margin-top: 1.5rem; }
.flow-stage {
  display: grid; grid-template-columns: auto 1fr; gap: 1rem; align-items: start;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--radius); padding: 1.1rem 1.25rem; position: relative;
}
.flow-stage + .flow-stage::before {
  content: ''; position: absolute; left: 2.1rem; top: -.78rem; width: 2px; height: .78rem;
  background: rgba(228,161,27,.5);
}
.flow-dot {
  width: 2.1rem; height: 2.1rem; border-radius: 50%; flex: none;
  background: var(--gold); color: var(--band-deep);
  display: grid; place-items: center; font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.flow-title { font-weight: 600; color: var(--on-band); margin-bottom: .2rem; }
.flow-note { font-size: .875rem; color: #A9C7CB; margin: 0; }
.flow-budget { font-size: .82rem; font-weight: 700; color: var(--gold); font-variant-numeric: tabular-nums; margin-top: .35rem; }

/* Five-point plan */
.plan-step {
  display: grid; grid-template-columns: auto 1fr; gap: 1.25rem;
  padding: 1.5rem 0; border-bottom: 1px solid var(--line);
}
.plan-step:last-child { border-bottom: 0; }
.plan-num {
  width: 3rem; height: 3rem; border-radius: 50%; flex: none;
  /* Teal, not gold: gold is reserved for the one primary button, and a
     permanent gold chip in the header would compete with it on every
     page. This is where the identity colour lives. */
  background: var(--accent-on-band); color: var(--band);
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: 1.4rem; font-weight: 700;
}
.plan-step h3 { margin-bottom: .3rem; color: var(--brand-fg); }
.plan-summary { font-weight: 500; color: var(--text); margin-bottom: .6rem; }
.plan-detail { color: var(--text-muted); margin-bottom: .75rem; }
@media (max-width: 560px) {
  .plan-step { grid-template-columns: 1fr; gap: .75rem; }
  .plan-num { width: 2.5rem; height: 2.5rem; font-size: 1.15rem; }
}

/* Per-point share widget */
.share-row { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; font-size: .8rem; color: var(--text-muted); }
.share-btn {
  width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--surface); color: var(--brand-fg); display: grid; place-items: center; cursor: pointer;
  transition: background .16s, border-color .16s, transform .16s;
}
.share-btn:hover { background: var(--surface-2); border-color: var(--line-strong); transform: translateY(-1px); }
.share-btn svg { width: 15px; height: 15px; }

/* ---------- Dates & calendar ---------- */
.date-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); gap: .85rem; }
.date-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.1rem; text-align: center; position: relative;
}
.date-card--major { border-color: var(--gold); border-width: 2px; box-shadow: var(--shadow-sm); }
.date-card .dow { font-size: .72rem; letter-spacing: .11em; text-transform: uppercase; color: var(--text-muted); }
.date-card .day { font-family: var(--font-display); font-size: 2.3rem; font-weight: 700; line-height: 1; color: var(--brand-fg); font-variant-numeric: tabular-nums; }
.date-card--major .day { color: var(--gold-dark); }
.date-card .mon { font-size: .84rem; font-weight: 600; color: var(--text); }
.date-card .kind { font-size: .76rem; color: var(--text-muted); margin-top: .45rem; }
.date-card .where { display: block; font-size: .74rem; color: var(--text-muted); margin-top: .3rem; line-height: 1.35; opacity: .85; }
.badge {
  display: inline-block; font-size: .66rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: .2rem .5rem; border-radius: 999px; background: var(--surface-3); color: var(--text-muted);
}
.badge--unconfirmed { background: #FDF0D8; color: #8A5A00; }
.badge--major { background: var(--gold); color: var(--band-deep); }

.event-item {
  display: grid; grid-template-columns: 5.5rem 1fr; gap: 1.25rem;
  padding: 1.35rem 0; border-bottom: 1px solid var(--line);
}
.event-date {
  text-align: center; background: var(--surface-2); border-radius: var(--radius-sm); padding: .6rem .35rem; align-self: start;
}
.event-date .d { font-family: var(--font-display); font-size: 1.6rem; font-weight: 700; color: var(--brand-fg); line-height: 1; }
.event-date .m { font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }
.event-meta { display: flex; flex-wrap: wrap; gap: .4rem 1.1rem; font-size: .87rem; color: var(--text-muted); margin-bottom: .6rem; }
.event-meta span { display: inline-flex; align-items: center; gap: .35rem; }
.event-meta svg { width: 15px; height: 15px; opacity: .7; }
@media (max-width: 560px) { .event-item { grid-template-columns: 1fr; } .event-date { width: 5rem; } }

/* Empty states — an honest "nothing published yet", not a blank page. */
.empty-state {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  padding: clamp(1.75rem, 4vw, 2.75rem); text-align: center; background: var(--surface-2);
}
.empty-state h3 { color: var(--brand-fg); }
.empty-state p { color: var(--text-muted); max-width: 46ch; margin-inline: auto; }

/* ---------- Forms ---------- */
.form-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 2.25rem); box-shadow: var(--shadow-sm);
}
.field { margin-bottom: 1.15rem; }
.field > label, .fieldset-legend {
  display: block; font-size: .875rem; font-weight: 600; color: var(--text); margin-bottom: .4rem;
}
.field .hint { font-size: .8rem; color: var(--text-muted); font-weight: 400; margin-top: .3rem; display: block; }
.req { color: var(--alert); font-weight: 700; }
input[type=text], input[type=email], input[type=tel], input[type=number], select, textarea {
  width: 100%; font-family: inherit; font-size: 1rem; color: var(--text);
  padding: .78rem .9rem; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); transition: border-color .16s, box-shadow .16s;
}
textarea { min-height: 8rem; resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--link); box-shadow: 0 0 0 3px rgba(29,105,112,.16);
}
input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"] { border-color: var(--alert); }
.field-error { display: none; font-size: .82rem; color: var(--alert); margin-top: .35rem; font-weight: 500; }
.field-error[data-shown="true"] { display: block; }
fieldset { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 1.1rem 1.2rem; margin: 0 0 1.15rem; }
legend { padding: 0 .4rem; font-size: .875rem; font-weight: 600; color: var(--text); }
.check-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); gap: .55rem .9rem; }
.check {
  display: flex; align-items: flex-start; gap: .55rem; font-size: .92rem; cursor: pointer;
  color: var(--text-muted); line-height: 1.45;
}
.check input { width: 1.1rem; height: 1.1rem; margin: .17rem 0 0; accent-color: var(--link); flex: none; cursor: pointer; }
.check:hover { color: var(--text); }
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 0 1rem; }
.honeypot { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }

.form-status { border-radius: var(--radius-sm); padding: .9rem 1.1rem; margin-bottom: 1.15rem; font-size: .92rem; display: none; }
.form-status[data-state="ok"]    { display: block; background: var(--status-ok-bg);   border: 1px solid var(--status-ok-line);   color: var(--status-ok-fg); }
.form-status[data-state="error"] { display: block; background: var(--status-err-bg);  border: 1px solid var(--status-err-line);  color: var(--status-err-fg); }
.form-status[data-state="info"]  { display: block; background: var(--status-info-bg); border: 1px solid var(--status-info-line); color: var(--status-info-fg); }

/* ---------- Notices ---------- */
.notice {
  border-left: 4px solid var(--gold); background: var(--surface-2);
  padding: 1.1rem 1.3rem; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; margin-bottom: 1.5rem;
}
.notice p:last-child { margin-bottom: 0; }
.notice--strong { border-left-color: var(--alert); background: var(--notice-alert); }
/* Notice headings take whatever level the document outline needs; the
   look comes from the class, so the level is free to be correct. */
.notice h2, .notice h3, .notice h4 {
  font-family: var(--font-body); font-size: 1.05rem; font-weight: 700;
  letter-spacing: 0; margin-bottom: .35rem; color: var(--brand-fg);
}

/* ---------- Click-to-load map ---------- */
.map-embed { margin: 1.5rem 0 0; }
.map-embed iframe { display: block; width: 100%; border-radius: var(--radius); background: var(--surface-3); }
.map-facade {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--surface-2); padding: clamp(1.75rem, 4vw, 2.75rem); text-align: center;
}
.map-facade-title { font-family: var(--font-display); font-size: 1.2rem; font-weight: 600; color: var(--brand-fg); margin-bottom: .5rem; }
.map-facade-note { font-size: .9rem; color: var(--text-muted); max-width: 52ch; margin: 0 auto 1.25rem; }
.map-facade-alt { font-size: .85rem; margin: 1rem 0 0; }

/* ---------- Gallery ---------- */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr)); gap: .9rem; }
.gallery figure { margin: 0; }
.gallery img, .gallery .ph {
  width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: var(--radius-sm); background: var(--surface-3);
}
.gallery .ph {
  display: grid; place-items: center; border: 1px dashed var(--line-strong);
  color: var(--text-muted); font-size: .8rem; text-align: center; padding: 1rem;
}
.gallery figcaption { font-size: .82rem; color: var(--text-muted); margin-top: .45rem; }

/* ---------- Footer ---------- */
.site-footer { background: var(--band-deep); color: var(--on-band-muted); padding-block: clamp(2.5rem, 5vw, 4rem) 1.75rem; font-size: .92rem; }
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.3fr; gap: clamp(1.5rem, 3vw, 2.5rem); margin-bottom: 2.5rem; }
@media (max-width: 880px) { .footer-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); } }
.site-footer .footer-title { color: var(--on-band); font-size: .78rem; font-family: var(--font-body); font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; margin-bottom: .9rem; }
.site-footer a { color: var(--on-band-muted); text-decoration: none; }
.site-footer a:hover { color: var(--gold); text-decoration: underline; }
.footer-links { list-style: none; padding: 0; margin: 0; }
.footer-links li { margin-bottom: .5rem; }
.social-row { display: flex; gap: .5rem; margin-top: .9rem; }
.social-row a {
  width: 38px; height: 38px; border-radius: 10px; border: 1px solid rgba(255,255,255,.2);
  display: grid; place-items: center; color: var(--on-band-muted);
}
.social-row a:hover { background: var(--gold); color: var(--band-deep); border-color: var(--gold); }
/* In the mobile menu the row sits on white, not on the dark footer. */
.nav-social a { border-color: var(--line-strong); color: var(--brand-fg); }
.nav-social a:hover { background: var(--gold); color: var(--band); border-color: var(--gold); }

/* The social row belongs to the drawer only. Above the drawer breakpoint the
   header bar is already carrying nine links plus Volunteer and Donate, and
   every pixel there should push toward those two. Scoped to a min-width query
   rather than a bare rule so it cannot fight the drawer's own display:flex,
   which sits earlier in this file. */
@media (min-width: 1081px) {
  .nav-social { display: none; }
}
.social-row svg { width: 17px; height: 17px; }
.footer-legal {
  border-top: 1px solid rgba(255,255,255,.14); padding-top: 1.5rem;
  font-size: .8rem; color: #8FAFB3; display: grid; gap: .75rem;
}
.authorization {
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--radius-sm); padding: .85rem 1.1rem; color: var(--on-band-muted); font-size: .82rem;
}
.footer-bottom { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; align-items: center; }
.footer-bottom nav { display: flex; flex-wrap: wrap; gap: .5rem 1.1rem; }

/* ---------- GOTV mode ---------- */
/* In the final 72 hours the homepage flips to one job: where and how to vote. */
.gotv { display: none; }
body[data-gotv="on"] .gotv { display: block; }
body[data-gotv="on"] .gotv-hide { display: none !important; }
.gotv-hero { background: var(--gold); color: var(--band-deep); padding-block: clamp(2.5rem, 5vw, 4rem); }
.gotv-hero h1 { color: var(--band-deep); }
/* The eyebrow inverts on the gold field: gold-on-gold is invisible,
   and #6B4E0C only reaches 4.17:1 against it. Teal-deep is 8:1. */
.gotv-hero .eyebrow { color: var(--band-deep); }
.gotv-hero .eyebrow::after { background: var(--band-deep); opacity: .5; }
.gotv-hero .lede { color: #3F3111; }
.gotv-steps { counter-reset: gotv; display: grid; gap: 1rem; margin-top: 1.75rem; }
.gotv-step {
  background: rgba(255,255,255,.55); border: 1px solid rgba(11,36,40,.15);
  border-radius: var(--radius); padding: 1.2rem 1.4rem 1.2rem 3.6rem; position: relative;
}
.gotv-step::before {
  counter-increment: gotv; content: counter(gotv);
  position: absolute; left: 1.1rem; top: 1.15rem;
  width: 1.9rem; height: 1.9rem; border-radius: 50%; background: var(--band); color: var(--gold);
  display: grid; place-items: center; font-weight: 700; font-size: .9rem;
}
.gotv-step h2 { font-size: 1.2rem; color: var(--band-deep); margin-bottom: .25rem; }
.gotv-step p:last-child { margin-bottom: 0; color: #3F3111; }

/* ---------- Language switcher ---------- */
.lang-switch { display: inline-flex; gap: .2rem; flex-wrap: wrap; }
.lang-switch button {
  font: inherit; font-size: .8rem; font-weight: 600; padding: .3rem .6rem;
  border: 1px solid rgba(255,255,255,.25); background: transparent; color: inherit;
  border-radius: 999px; cursor: pointer;
}
.lang-switch button[aria-pressed="true"] { background: var(--gold); color: var(--band-deep); border-color: var(--gold); }
[dir="rtl"] { font-family: 'Vazirmatn', var(--font-body); }
[dir="rtl"] .eyebrow::after { display: none; }

/* ---------- Misc ---------- */
.tag-list { display: flex; flex-wrap: wrap; gap: .4rem; list-style: none; padding: 0; margin: 0; }
.tag-list li { margin: 0; }
.tag {
  display: inline-block; font-size: .8rem; padding: .3rem .7rem; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text-muted);
}
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: 1rem; }
.reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; } }

/* ---------- Print ---------- */
@media print {
  .site-header, .site-footer, .nav-toggle, .btn, .share-row, .alert-bar, .countdown { display: none !important; }
  body { font-size: 11pt; color: #000; }
  .section--band, .cred-bar { background: #fff !important; color: #000 !important; }
  .section--band h2, .section--band h3, .ww-fig .value { color: #000 !important; }
  a::after { content: ' (' attr(href) ')'; font-size: 9pt; color: #444; }
  a[href^="#"]::after, a[href^="./"]::after { content: ''; }
}


/* ---------- Farsi page (right-to-left) ----------

   Scoped to [dir="rtl"] rather than to a page class, so any block that
   is switched to Farsi — the voting essentials on voting.html already
   set dir on themselves — picks the same treatment up.

   Only three things actually need to change. Everything else in the
   design system is direction-agnostic because it was built with flex,
   grid and logical properties, which mirror on their own. */

[dir="rtl"] {
  /* Vazirmatn first for the Persian, then the Latin stack: a Farsi page
     still contains "Max Zahedi", "District Hall" and an email address,
     and those should render in Manrope, not in Vazirmatn's Latin. */
  --font-body: 'Vazirmatn', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Tahoma, Arial, sans-serif;
  /* No Persian serif is loaded, so headings share the text face. DM
     Serif Display would silently fall back to a system serif for the
     Persian and render DM Serif for any Latin inside the same heading —
     two typefaces in one line. */
  --font-display: 'Vazirmatn', 'Manrope', -apple-system, 'Segoe UI', Tahoma, Arial, sans-serif;
}
[dir="rtl"] h1, [dir="rtl"] h2 { font-weight: 700; letter-spacing: 0; line-height: 1.3; }
[dir="rtl"] h3, [dir="rtl"] h4 { letter-spacing: 0; }
/* Persian needs more room between lines than Latin: the descenders and
   the dots below the baseline collide at 1.65. */
[dir="rtl"] body, [dir="rtl"] p, [dir="rtl"] li { line-height: 1.95; }

/* The eyebrow rule is drawn with ::after and is the one decorative
   element that does not mirror by itself. */
[dir="rtl"] .eyebrow { letter-spacing: .04em; }

/* A Latin run inside Persian text — an email, a date, "$3.86 billion".
   Marked dir="ltr" in the markup; this keeps it on the Latin face so it
   does not inherit Vazirmatn's digits. */
[dir="rtl"] [dir="ltr"] { font-family: 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; }

.fa-english-note { display: flex; align-items: center; gap: .9rem; flex-wrap: wrap; margin-top: 1.5rem; }
.fa-english-note span { color: var(--on-band-muted); font-size: .95rem; }

/* Label/value pairs: voting day, the wastewater figures, contact. */
.fa-facts {
  display: grid; gap: 1rem; margin: 1.5rem 0 0;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}
.fa-fact {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
  padding: 1.1rem 1.25rem;
}
.fa-fact dt { font-size: .84rem; color: var(--text-muted); margin-bottom: .3rem; }
.fa-fact dd {
  margin: 0; font-size: 1.22rem; font-weight: 700; color: var(--brand-fg);
  font-variant-numeric: tabular-nums;
}

.fa-advance { list-style: none; padding: 0; margin: .75rem 0 0; display: grid; gap: .6rem; }
.fa-advance li {
  display: flex; flex-wrap: wrap; gap: .35rem 1rem; align-items: baseline;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: .8rem 1rem; margin: 0;
}
.fa-date  { font-weight: 700; }
.fa-where { color: var(--text-muted); font-size: .93rem; }

/* Persian numerals in a Persian list. Browsers that do not know this
   counter style fall back to decimal, which is what it did before, so
   there is nothing to lose. */
[dir="rtl"] ol { list-style-type: persian; }
.fa-ranked { padding-inline-start: 1.4em; }
.fa-ranked li { margin-bottom: .5em; }
