/* ==========================================================================
   Prosper data center petition — design system
   One stylesheet, no framework, no build step. Loads in one round trip.
   ========================================================================== */

:root {
  /* Light throughout. The audience skews older and reads on a phone in
     daylight, so the page is one calm cream ground with a slightly deeper
     band for rhythm. No dark sections, no reverse-out type. */
  --paper:       #faf7f1;
  --band:        #efe9dd;
  --card:        #ffffff;
  --rule:        rgba(26, 31, 40, 0.14);
  --rule-strong: rgba(26, 31, 40, 0.26);

  --text:        #1a1f28;
  --text-muted:  #4b5563;

  /* Signal. Burnt orange, the only saturated colour on the page, reserved for
     actions. Dark enough for white text (5.5:1) and to read as text on the
     cream (5.0:1). One value now, not three: with no dark ground left there
     is nothing for a light variant to sit on. */
  --signal:       #b8410f;
  --signal-press: #9c3709;
  --signal-dim:   rgba(184, 65, 15, 0.12);

  --sage:  #35604f;
  --alert: #a3271b;

  --display: "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --measure: 62ch;
  --wide: 1120px;
  --shell: min(92vw, var(--wide));

  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 20px;

  --shadow-lift: 0 1px 2px rgba(26,31,40,.05), 0 8px 24px -10px rgba(26,31,40,.14);
  --shadow-pop: 0 24px 70px -20px rgba(26,31,40,.30), 0 2px 8px rgba(26,31,40,.10);

  --step: clamp(3.25rem, 7vw, 6rem);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--sans);
  /* Deliberately larger than a default body size. Older eyes, small screens. */
  font-size: clamp(1.09rem, 1.02rem + .3vw, 1.24rem);
  line-height: 1.68;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  font-synthesis-weight: none;
  overflow-wrap: break-word;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.03;
  letter-spacing: -0.022em;
  margin: 0;
  font-variation-settings: "SOFT" 0, "WONK" 0;
}
h1 { font-size: clamp(2.9rem, 1.6rem + 5.6vw, 6.2rem); letter-spacing: -0.035em; }
h2 { font-size: clamp(2rem, 1.35rem + 2.7vw, 3.5rem); letter-spacing: -0.028em; }
h3 { font-size: clamp(1.25rem, 1.08rem + .75vw, 1.7rem); }
p { margin: 0 0 1.15em; }
a { color: inherit; }

.shell { width: var(--shell); margin-inline: auto; }
.measure { max-width: var(--measure); }
.center { margin-inline: auto; }

section { padding-block: var(--step); scroll-margin-top: 5rem; }
.tight { padding-block: clamp(2.5rem, 5vw, 4rem); }

/* --- Reusable atoms ----------------------------------------------------- */

.eyebrow {
  font-family: var(--sans);
  font-size: .72rem;
  font-weight: 650;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 1.1rem;
  display: block;
}

.lede {
  font-size: clamp(1.16rem, 1.05rem + .55vw, 1.42rem);
  line-height: 1.5;
  color: var(--text-muted);
}

.btn {
  --btn-bg: var(--signal);
  --btn-fg: #fff;
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  font-family: var(--sans);
  font-weight: 640; font-size: 1.02rem; letter-spacing: -.006em;
  padding: 1.02rem 1.9rem;
  border: 0; border-radius: 999px;
  background: var(--btn-bg); color: var(--btn-fg);
  text-decoration: none; cursor: pointer;
  transition: transform .16s cubic-bezier(.2,.8,.3,1), box-shadow .16s, background-color .16s;
  box-shadow: 0 1px 2px rgba(26,31,40,.10);
  text-align: center;
}
.btn:hover { background: var(--signal-press); box-shadow: 0 2px 6px rgba(26,31,40,.16); }
.btn:active { transform: translateY(0); }
.btn--ghost {
  --btn-bg: transparent; --btn-fg: var(--text);
  box-shadow: inset 0 0 0 1.5px var(--rule);
}
.btn--ghost:hover { background: rgba(17,21,29,.045); box-shadow: inset 0 0 0 1.5px rgba(17,21,29,.28); }
.btn--block { display: flex; width: 100%; }
.btn[disabled] { opacity: .55; pointer-events: none; }

:where(a, button, input, textarea, summary, [tabindex]):focus-visible {
  outline: 2.5px solid var(--signal);
  outline-offset: 3px;
  border-radius: 4px;
}

.card {
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 3.2vw, 2.2rem);
  box-shadow: var(--shadow-lift);
}

/* Small caps label used above data points. */
.label {
  font-size: .72rem; font-weight: 680; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-muted);
  margin: 0 0 .35rem;
}

.stat-num {
  font-family: var(--display);
  font-size: clamp(2.4rem, 1.6rem + 3.2vw, 4rem);
  line-height: .95; letter-spacing: -.035em;
  font-weight: 600;
  display: block;
}

/* ==========================================================================
   Header
   ========================================================================== */

.masthead {
  position: sticky; top: 0; z-index: 60;
  background: rgba(250, 247, 241, .92);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--rule);
  color: var(--text);
}
.masthead__in {
  display: flex; align-items: center; gap: 1.2rem;
  min-height: 62px;
}
.wordmark {
  font-family: var(--display); font-weight: 600; font-size: clamp(.94rem, .86rem + .34vw, 1.06rem);
  letter-spacing: -.02em; text-decoration: none; color: var(--text);
  display: flex; align-items: baseline; margin-right: auto;
  padding-block: .5rem;
}
.wordmark__rest { display: none; }
@media (min-width: 620px) { .wordmark__rest { display: inline; } }
.masthead .btn__long { display: none; }
@media (min-width: 620px) { .masthead .btn__long { display: inline; } }
.masthead nav { display: none; gap: 1.6rem; }
.masthead nav a {
  font-size: .875rem; font-weight: 520; text-decoration: none;
  color: var(--text-muted); transition: color .15s;
}
.masthead nav a:hover { color: var(--text); }
.masthead .btn { padding: .62rem 1.2rem; font-size: .9rem; }
@media (min-width: 900px) { .masthead nav { display: flex; } }

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative; isolation: isolate;
  background: var(--paper);
  color: var(--text);
  padding-block: clamp(2.5rem, 6vw, 5rem) clamp(3rem, 7vw, 5.5rem);
  overflow: hidden;
}
/* Faint horizon rule, the prairie line. */
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--rule); z-index: -1;
}
.hero__lead {
  font-family: var(--display); font-style: italic;
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.8rem);
  color: var(--signal); margin: 0 0 .1rem; letter-spacing: -.01em;
}
.hero__tag {
  font-family: var(--sans); font-weight: 700;
  font-size: clamp(.82rem, .76rem + .3vw, .96rem);
  letter-spacing: .04em; color: var(--signal);
  margin: 1rem 0 0;
}
.hero__grid { display: grid; gap: clamp(2.4rem, 5vw, 4rem); align-items: start; }
@media (min-width: 1000px) {
  .hero__grid { grid-template-columns: 1.06fr .94fr; gap: clamp(3rem, 5vw, 5rem); }
}
h1 .thin { display: block; color: var(--text-muted); font-weight: 300; }
h1 em {
  font-style: normal; color: var(--signal);
  font-variation-settings: "SOFT" 40, "WONK" 1;
}
.hero__sub { max-width: 40ch; margin-top: 1.6rem; }

.hero__meta {
  display: flex; flex-wrap: wrap; gap: .55rem; margin-top: 1.9rem;
}
.chip {
  display: inline-flex; align-items: center; gap: .45rem;
  font-size: .8rem; font-weight: 560; letter-spacing: -.005em;
  padding: .42rem .85rem; border-radius: 999px;
  background: rgba(247,243,236,.08);
  border: 1px solid var(--rule);
  color: var(--text-muted);
}
.chip strong { color: var(--text); font-weight: 640; }

/* The same pill row as the hero's, anywhere a set of hard numbers is easier
   to scan than to read. A list, because that is what it is. */
.pills {
  display: flex; flex-wrap: wrap; gap: .55rem;
  margin: 1.4rem 0 0; padding: 0; list-style: none;
}

/* A quieter block inside a card, for a note that is the neighbours' own
   rather than the applicant's or the Town's. A tint, not a left bar. */
.note {
  background: var(--band); border-radius: var(--r-sm);
  padding: 1rem 1.15rem; color: var(--text-muted); font-size: .92rem;
  line-height: 1.6;
}

/* --- Counter ------------------------------------------------------------ */

.counter { margin-top: 2.4rem; }
.counter__row { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; }
.counter__num {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(2.6rem, 1.8rem + 3vw, 3.9rem);
  line-height: 1; letter-spacing: -.04em;
  font-variant-numeric: tabular-nums; color: var(--text);
}
.counter__of { font-size: .95rem; color: var(--text-muted); }
.meter {
  margin-top: .85rem; height: 7px; border-radius: 999px;
  background: rgba(247,243,236,.14); overflow: hidden;
}
.meter__fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--signal), var(--signal));
  border-radius: 999px;
  transition: width 1.1s cubic-bezier(.2,.8,.3,1);
}

/* ==========================================================================
   Form
   ========================================================================== */

.signform {
  background: var(--card);
  color: var(--text);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 3.4vw, 2.1rem);
  box-shadow: var(--shadow-pop);
  position: relative;
}
.signform__head { margin-bottom: 1.3rem; }
.signform__head h2 { font-size: clamp(1.5rem, 1.2rem + 1.1vw, 1.95rem); }
.signform__head p { margin: .5rem 0 0; font-size: .95rem; color: var(--text-muted); }

.field { margin-bottom: .85rem; }
.field label {
  display: block; font-size: .78rem; font-weight: 620;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: .35rem;
}
.field input[type="text"],
.field input[type="email"],
.field textarea {
  width: 100%; font: inherit; font-size: 1rem;
  padding: .82rem .95rem;
  border: 1.5px solid var(--rule-strong);
  border-radius: var(--r-sm);
  background: #fff; color: var(--text);
  transition: border-color .15s, box-shadow .15s;
}
.field input::placeholder, .field textarea::placeholder { color: #6b7280; }
.field input:focus-visible, .field textarea:focus-visible {
  /* Keep the ring. The tinted border plus soft glow alone was barely
     perceptible, which is the whole point of a focus indicator. */
  outline: 2.5px solid var(--signal); outline-offset: 1px;
  border-color: var(--signal);
  box-shadow: 0 0 0 4px var(--signal-dim);
}
.field input:focus, .field textarea:focus {
  border-color: var(--signal);
  box-shadow: 0 0 0 4px var(--signal-dim);
}
.field textarea { resize: vertical; min-height: 84px; }
.field--row { display: grid; gap: .85rem; grid-template-columns: 1fr; }
@media (min-width: 480px) { .field--row { grid-template-columns: 1.35fr 1fr; } }

.check {
  display: flex; gap: .7rem; align-items: flex-start;
  font-size: .89rem; line-height: 1.45; color: var(--text-muted);
  padding: .5rem 0; cursor: pointer;
}
.check input { margin: .18rem 0 0; width: 17px; height: 17px; flex: none; accent-color: var(--signal); cursor: pointer; }
.check strong { color: var(--text); font-weight: 620; }
/* Room between the last box and the button. Without it the third way to help
   sits hard against Add my name and reads as part of it. */
.check + .btn--block { margin-top: 1.15rem; }

/* Honeypot. Off-screen rather than display:none — some bots skip hidden. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.formnote { font-size: .78rem; color: var(--text-muted); margin: .9rem 0 0; line-height: 1.5; }

/* ---- Write to the Town ------------------------------------------------- */

.mailer__meta { margin: 0 0 1.1rem; display: grid; gap: .5rem; }
.mailer__meta > div { display: grid; grid-template-columns: 5.2rem 1fr; gap: .8rem; align-items: baseline; }
.mailer__meta dt {
  font-size: .78rem; font-weight: 620; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-muted);
}
.mailer__meta dd { margin: 0; font-size: .95rem; color: var(--text); }

/* The letter itself. Set in the reading face rather than a monospace: this is
   a letter a neighbour is about to send, not a code sample. white-space
   pre-line keeps the paragraph breaks that make it look like one. */
.mailer__body {
  white-space: pre-line;
  background: var(--band); border-radius: var(--r-sm);
  padding: 1.1rem 1.25rem;
  font-size: .93rem; line-height: 1.65; color: var(--text);
}
.mailer__btns {
  display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 1.2rem;
}
@media (max-width: 520px) {
  .mailer__btns { display: grid; }
  .mailer__meta > div { grid-template-columns: 1fr; gap: .1rem; }
}

/* The small repeat of this call, dropped into sections above. */
.mailcta { margin: 2rem 0 0; text-align: center; }
.formmsg {
  margin: 0 0 1rem; padding: .8rem 1rem; border-radius: var(--r-sm);
  font-size: .9rem; display: none;
}
.formmsg--err { display: block; background: rgba(192,57,43,.09); color: #8f2a20; border: 1px solid rgba(192,57,43,.25); }

.signform__done { display: none; text-align: left; }
.signform.is-done .signform__body { display: none; }
.signform.is-done .signform__done { display: block; }
.signform__done h3 { margin-bottom: .6rem; }
.tick {
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--sage); color: #fff;
  display: grid; place-items: center; margin-bottom: 1rem;
}

/* ==========================================================================
   Content blocks
   ========================================================================== */

.band { background: var(--band); }


/* Width is set in rem, not ch. `ch` here would resolve against this
   container's font-size (body size), not the much larger display size of the
   h2 inside it -- which clamped every section headline to about 300px. */
.sect-head { max-width: 46rem; margin-bottom: clamp(2rem, 4vw, 3.2rem); }
.sect-head .lede { margin-top: 1.1rem; max-width: 54ch; }

.grid { display: grid; gap: clamp(1rem, 2.2vw, 1.6rem); }
.grid--2 { grid-template-columns: 1fr; }
.grid--3 { grid-template-columns: 1fr; }
@media (min-width: 720px) { .grid--2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 860px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }

/* Numbered "ask" list */
.asks { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--rule); border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--rule); }
.band .asks { background: var(--rule); border-color: var(--rule); }
/* DIRECT children only. `.asks li` also matched the li of any list nested
   inside an ask, which turned each of those into its own two column grid with
   a 3.2rem first column -- the bullets under ask four rendered one word per
   line down a thin strip. */
.asks > li { background: var(--card); padding: clamp(1.4rem, 3vw, 2rem); display: grid; gap: .85rem; }
.band .asks > li { background: var(--band); }
@media (min-width: 760px) { .asks > li { grid-template-columns: 3.2rem 1fr; gap: 1.4rem; align-items: start; } }
.asks .n {
  font-family: var(--display); font-size: 1.7rem; font-weight: 600;
  color: var(--signal); line-height: 1; letter-spacing: -.03em;
}
.asks h3 { margin-bottom: .5rem; }
.asks p { margin: 0; color: var(--text-muted); }
/* The four points under ask four. Plain bullets, indented enough to hang
   clear of the text above them. */
.asks__points {
  margin: 0; padding-left: 1.2rem; color: var(--text-muted);
  display: grid; gap: .3rem;
}
.band .asks p { color: var(--text-muted); }

/* Decibel scale */
.db { display: grid; gap: 1.1rem; margin: 3rem 0 0; }

/* Wide screens: value column, then the bar, with the caption lifted on top of
   the bar. The caption is positioned against the ROW rather than nested in the
   fill -- a fill at 27% width cannot hold its own caption, and clipping the
   text to the fill truncated every label to a fragment below about 1024px. */
.db__row {
  position: relative;
  display: grid;
  grid-template-columns: 4.6rem 1fr;
  grid-template-rows: auto auto;
  column-gap: 1rem; row-gap: .4rem; align-items: center;
}
.db__val { grid-column: 1; grid-row: 1;
  font-family: var(--display); font-weight: 600; font-size: 1.2rem;
  text-align: right; font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.db__bar { grid-column: 2; grid-row: 1; height: 34px; border-radius: 6px; position: relative; background: rgba(247,243,236,.09); }
.db__fill { position: absolute; inset: 0 auto 0 0; border-radius: 6px; }
.db__label {
  position: absolute; left: calc(4.6rem + 1rem + .85rem); right: .5rem; top: 0;
  height: 34px;
  /* line-height, not flex: a flex container drops the whitespace between its
     children and renders "day <em>and</em> night" as "dayandnight". */
  line-height: 34px;
  /* The bar follows this in source order and makes its own stacking context,
     so without a z-index it paints over the caption. */
  z-index: 2;
  font-size: .84rem; font-weight: 620; white-space: nowrap;
  color: var(--text); pointer-events: none;
}
.db__ref {
  grid-column: 2; grid-row: 2;
  font-size: .88rem; color: var(--text-muted); line-height: 1.4;
}
.db__fill--who { background: rgba(111,154,134,.34); }
.db__fill--night { background: rgba(111,154,134,.22); }
.db__fill--cap { background: linear-gradient(90deg, rgba(212,84,30,.95), rgba(239,106,48,.85)); }
.db__fill--gen { background: rgba(192,57,43,.7); }

/* Narrow screens: no caption fits inside a bar, so the row simply stacks in
   its natural reading order -- value, caption, then the bar as a quantity. */
@media (max-width: 760px) {
  .db__row { grid-template-rows: none; }
  .db__val, .db__bar, .db__ref { grid-column: auto; grid-row: auto; }
  .db__ref { font-size: .84rem; }
  .db { gap: 1.35rem; }
  .db__row { grid-template-columns: 1fr; gap: .3rem; }
  .db__val { text-align: left; font-size: 1.15rem; }
  .db__label {
    position: static; display: block; height: auto; line-height: 1.4;
    white-space: normal; font-size: .92rem; line-height: 1.4;
    color: var(--text-muted);
  }
  .db__bar { height: 12px; }
}

.hear {
  margin-top: 3.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 3vw, 2.2rem);
  background: var(--card);
}
.hear__head h3 { margin: .5rem 0 .7rem; }
.hear__head p { color: var(--text-muted); margin: 0; max-width: 56ch; }
.hear__btns { display: grid; gap: .9rem; margin: 1.8rem 0 0; }
@media (min-width: 620px) { .hear__btns { grid-template-columns: 1fr 1fr; max-width: 620px; } }
.hear__btn { justify-content: flex-start; gap: 1rem; padding: 1rem 1.5rem; text-align: left; }
/* display:block on both, or the label and the caption run together as
   "40 dBAWhat protects sleep". */
.hear__btn strong { display: block; font-size: 1.05rem; line-height: 1.25; }
.hear__btn small { display: block; font-size: .88rem; font-weight: 500; color: var(--text-muted); }
.hear__btn:not(.btn--ghost) small { color: rgba(255,255,255,.88); }
/* Play and stop drawn in css, so the button needs no icon font or sprite.
 *
 * THE GLYPH COLOUR IS A VARIABLE because it has to be the button's own
 * BACKGROUND, not a fixed white. The disc is currentColor, so on the ghost
 * button it comes out dark and a white triangle reads; on the solid button
 * currentColor is white, and a white triangle on a white disc is invisible.
 * That is exactly what happened: 65 dBA showed a blank circle while 40 dBA
 * showed a play arrow. */
.hear__icon {
  --icon-fg: var(--card);
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: currentColor; position: relative;
}
.hear__btn:not(.btn--ghost) .hear__icon { --icon-fg: var(--signal); }
.hear__icon::before {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 0; height: 0; margin: -6px 0 0 -3px;
  border-left: 10px solid var(--icon-fg);
  border-top: 6px solid transparent; border-bottom: 6px solid transparent;
}
.hear__btn[aria-pressed="true"] .hear__icon::before {
  border: 0; width: 10px; height: 10px; margin: -5px 0 0 -5px;
  background: var(--icon-fg);
}
.hear__note {
  margin: 1.6rem 0 0; font-size: .88rem; line-height: 1.65;
  color: var(--text-muted); max-width: 64ch;
}
.hear__note strong { color: var(--text); }

.db__note { font-size: .88rem; color: var(--text-muted); margin-top: 1.2rem; }

/* ---- Target ordinances table ------------------------------------------- */

.ord { margin-top: 3rem; }

/* The table scrolls inside its own box rather than widening the page.
   min-width: 0 is what makes that work -- a grid or flex item defaults to
   min-width:auto, so without it the table's floor propagates up and becomes
   a page level horizontal scrollbar instead of a local one. */
.ord__scroll { overflow-x: auto; min-width: 0; -webkit-overflow-scrolling: touch; }
.ord__scroll:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; border-radius: var(--r-sm); }
.ord__table {
  width: 100%; min-width: 34rem;
  border-collapse: collapse; text-align: left;
  font-size: .93rem; line-height: 1.5;
}
.ord__table th, .ord__table td {
  padding: .85rem 1rem; vertical-align: top;
  border-bottom: 1px solid var(--rule);
}
.ord__table thead th {
  font-family: var(--sans); font-size: .78rem; font-weight: 620;
  letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted);
  border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap;
}
.ord__table tbody th { font-weight: 620; color: var(--text); }
/* The parenthetical under a place name, on its own line rather than running
   into it. */
.ord__table tbody th span {
  display: block; margin-top: .2rem;
  font-weight: 400; font-size: .84rem; color: var(--text-muted);
}
.ord__table td { color: var(--text-muted); }
.ord__table td strong {
  color: var(--signal); font-family: var(--display);
  font-size: 1.15rem; font-weight: 600; white-space: nowrap;
}
.ord__table tbody tr:last-child th,
.ord__table tbody tr:last-child td { border-bottom: 0; }
/* The substation caveat. A tint across the whole block, never a bar down one
   edge. This section runs on the dark band, so the tint is a lift not a wash. */
.db__note--warn {
  background: rgba(26,31,40,.05);
  border-radius: var(--r-sm);
  padding: .85rem 1.1rem;
  margin-top: 1.6rem;
}

/* Play control inside a chart row's caption. Inline, so it rides along at the
   end of the sentence and needs nothing from .db__row's hand placed grid.
   Hidden until the script confirms Web Audio: a play button that cannot play
   is worse than no button. */
.db__play { display: none; }
.has-audio .db__play {
  display: inline-flex; align-items: center; gap: .4rem;
  margin-left: .6rem; vertical-align: baseline;
  padding: .22rem .6rem .22rem .5rem; border-radius: 999px;
  font: inherit; font-size: .8rem; font-weight: 620; line-height: 1.5;
  color: var(--text); background: #fff;
  border: 1px solid var(--rule-strong);
  cursor: pointer; transition: background .14s ease;
}
.has-audio .db__play:hover { background: var(--signal-dim); }
.db__playicon {
  width: 0; height: 0; flex: none;
  border-left: 7px solid currentColor;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
}
/* Playing: the triangle becomes a pause bar pair. */
.db__play[aria-pressed="true"] { background: var(--signal); border-color: var(--signal); color: #fff; }
.db__play[aria-pressed="true"] .db__playicon {
  width: 8px; height: 10px; border: 0;
  background: linear-gradient(90deg, currentColor 0 3px, transparent 3px 5px, currentColor 5px 8px);
}
@media (prefers-reduced-motion: reduce) { .has-audio .db__play { transition: none; } }

/* The orientation diagram keeps a 420px floor so its labels stay legible;
   below that it scrolls inside its own box rather than the page.
   `min-width: 0` is what makes that work: a grid item defaults to
   min-width:auto, so without it the 420px floor propagates up and widens the
   whole track -- which is a page-level horizontal scrollbar, not a local one. */
/* The wrapper owns the shape. The still sits at the bottom of the stack and
   the interactive map lies on top of it, so a Maps auth failure only has to
   hide one layer to reveal a real picture underneath. */
.promap__wrap {
  position: relative; width: 100%; aspect-ratio: 4 / 3; min-height: 300px;
  border-radius: 14px; overflow: hidden; border: 1px solid var(--rule);
  background: #e9e4d9;
}
@media (min-width: 1000px) { .promap__wrap { aspect-ratio: 1 / 1; min-height: 0; } }
.promap__still {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.promap { position: absolute; inset: 0; }

/* Street level inset, bottom right, the way Google's own map corners it. */
.promap__sv {
  position: absolute; right: 12px; top: 12px;
  width: clamp(104px, 30%, 168px); aspect-ratio: 4 / 3;
  border-radius: 10px; overflow: hidden;
  border: 2px solid rgba(255,255,255,.92);
  box-shadow: 0 6px 18px rgba(0,0,0,.42);
  text-decoration: none; display: block; background: #cfcabd;
  transition: transform .16s ease;
}
.promap__sv:hover, .promap__sv:focus-visible { transform: scale(1.045); }
.promap__sv img { width: 100%; height: 100%; object-fit: cover; display: block; }
.promap__svcap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: .3rem .45rem;
  font-family: var(--sans); font-size: .66rem; font-weight: 650;
  letter-spacing: .04em; text-transform: uppercase; color: #fff;
  background: linear-gradient(transparent, rgba(0,0,0,.72));
}
@media (max-width: 480px) { .promap__sv { right: 8px; top: 8px; } }



/* Google imagery refused this origin. Show the reason rather than two broken
   image icons; the map link above the card still works. */
.promap--noimg .promap__still,
.promap--noimg .promap__sv,
.promap--noimg .promap { display: none; }
.promap--noimg::after {
  content: "Satellite and street level imagery are not showing because this site's address is not yet on the Google Maps API key's allowed referrer list.";
  display: flex; align-items: center; justify-content: center;
  height: 100%; padding: 1.4rem; text-align: center;
  font-size: .84rem; line-height: 1.5; color: var(--text-muted);
}
.promap__cap { margin: .6rem 0 0; font-size: .8rem; color: var(--text-muted); line-height: 1.5; }
.promap__key { list-style: none; margin: .7rem 0 0; padding: 0; display: grid; gap: .38rem; }
.promap__key li { display: flex; align-items: flex-start; gap: .5rem; font-size: .82rem; color: var(--text-muted); line-height: 1.4; }
.promap__sw { width: 14px; height: 14px; border-radius: 3px; flex: none; margin-top: .12rem; }
/* Legend swatches carry the SAME colours the server draws with. A satellite
   photograph is dark green, brown and grey, so every one of these is a colour
   the ground cannot produce, and no two features share one. Change a colour
   in functions/api/mapimg.js and change it here in the same commit, or the
   legend starts describing a map that no longer exists. */
.promap__sw--site  { background: rgba(255,106,43,.35); border: 2px solid #ff6a2b; }
.promap__sw--exist { background: rgba(0,230,118,.3); border: 2px solid #00a353; }
/* One colour for all three rings. Three read as scribble rather than as a set
   of range rings, which is exactly how it read. */
.promap__sw--ring  { background: none; border: 2px solid #e8102f; border-radius: 50%; }
.promap__sw--school{ background: #2979ff; border: 2px solid #2979ff; border-radius: 50%; }

.promap__hint {
  margin: 0 0 .55rem; font-size: .82rem; color: var(--text-muted);
}

/* The tooltip. Dark, because it sits on a satellite photograph and has to
   read over grass, dirt and roofs alike; pointer-events off, so it can never
   sit between the cursor and the thing being pointed at. */
.promap__tip {
  position: absolute; z-index: 3; pointer-events: none;
  transform: translateX(-50%);
  max-width: min(260px, 78%);
  padding: .45rem .7rem; border-radius: 8px;
  background: rgba(17, 21, 29, .93); color: #fff;
  font-family: var(--sans); font-size: .8rem; line-height: 1.35;
  box-shadow: 0 4px 14px rgba(0,0,0,.3);
  opacity: 0; transition: opacity .12s ease;
}
.promap__tip.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .promap__tip { transition: none; } }
.promap__still { cursor: crosshair; }
.promap__keybody { min-width: 0; }
.promap__schools {
  list-style: none; margin: .4rem 0 0; padding: 0;
  display: grid; gap: .3rem;
}
.promap__schools li {
  display: grid; grid-template-columns: 18px 1fr auto; align-items: center;
  gap: .5rem; font-size: .82rem; line-height: 1.35; color: var(--text-muted);
}
.promap__pin {
  width: 18px; height: 18px; border-radius: 50%;
  background: #2f6b52; color: #fff;
  font-family: var(--sans); font-size: .66rem; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}
.promap__dist { white-space: nowrap; font-variant-numeric: tabular-nums; opacity: .85; }
@media (max-width: 420px) {
  .promap__schools li { grid-template-columns: 18px 1fr; }
  .promap__dist { grid-column: 2; }
}
.grid > *, .hero__grid > * { min-width: 0; }

/* Q&A / unanswered questions */
.qlist { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); border-radius: var(--r-lg); overflow: hidden; }
.qlist > div { background: #fff; padding: clamp(1.3rem, 2.8vw, 1.8rem); }
.qlist h3 { font-size: 1.12rem; margin-bottom: .55rem; font-family: var(--sans); font-weight: 650; letter-spacing: -.012em; }
.qlist p { margin: 0; font-size: .95rem; color: var(--text-muted); }
.qlist p + p, .qlist ul + p { margin-top: .7rem; }
.qlist .label { margin-bottom: .3rem; }
/* The questions themselves, set apart from the argument around them. */
.qlist__ask {
  margin: .7rem 0 0; padding-left: 1.15rem;
  display: grid; gap: .35rem;
  font-size: .95rem; color: var(--text-muted); line-height: 1.55;
}

/* Precedent cards */
.prec { display: grid; gap: .9rem; }
.prec__item {
  display: grid; gap: .3rem;
  padding: 1.1rem 0; border-top: 1px solid var(--rule);
}
.prec__item:first-child { border-top: 0; }
.prec__where { font-family: var(--display); font-size: 1.22rem; font-weight: 600; letter-spacing: -.02em; }
.prec__what { font-size: .93rem; color: var(--text-muted); }
.prec__tag {
  font-size: .68rem; font-weight: 680; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sage);
}

/* Meeting card */
.meeting {
  display: grid; gap: 1.6rem;
  border: 1.5px solid var(--signal);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 3.4vw, 2.4rem);
  background: #fff;
  box-shadow: var(--shadow-lift);
}
@media (min-width: 820px) { .meeting { grid-template-columns: 1fr 1.25fr; gap: 2.6rem; } }
.meeting__when { border-right: 0; }
@media (min-width: 820px) { .meeting__when { border-right: 1px solid var(--rule); padding-right: 2.4rem; } }
.meeting__date { font-family: var(--display); font-size: clamp(1.7rem,1.3rem+1.6vw,2.3rem); font-weight: 600; letter-spacing: -.03em; line-height: 1.05; }
.meeting dl { margin: 1.2rem 0 0; display: grid; gap: .8rem; }
.meeting dt { font-size: .7rem; font-weight: 680; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); }
.meeting dd { margin: .15rem 0 0; font-size: .97rem; }
.steps { list-style: none; margin: 0; padding: 0; counter-reset: s; display: grid; gap: 1rem; }
.steps li { counter-increment: s; display: grid; grid-template-columns: 1.9rem 1fr; gap: .9rem; font-size: .97rem; }
.steps li::before {
  content: counter(s);
  width: 1.9rem; height: 1.9rem; border-radius: 50%;
  background: var(--signal-dim); color: var(--signal);
  display: grid; place-items: center;
  font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.steps strong { font-weight: 640; }

/* Script box */
.script {
  background: var(--band); color: var(--text);
  border-radius: var(--r-md); padding: clamp(1.2rem, 2.6vw, 1.7rem);
  font-size: .97rem; line-height: 1.65;
}
.script p:last-child { margin-bottom: 0; }
.script .blank { color: var(--signal); font-weight: 600; }

/* FAQ */
.faq { border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  list-style: none; cursor: pointer; padding: 1.35rem 2.5rem 1.35rem 0;
  font-family: var(--display); font-size: clamp(1.08rem,1rem+.4vw,1.3rem); font-weight: 600;
  letter-spacing: -.018em; position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: .3rem; top: 50%;
  width: 11px; height: 11px; margin-top: -6px;
  border-right: 2px solid var(--signal); border-bottom: 2px solid var(--signal);
  transform: rotate(45deg); transition: transform .22s;
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq .faq__a { padding: 0 0 1.5rem; max-width: var(--measure); color: var(--text-muted); }
.faq .faq__a p:last-child { margin-bottom: 0; }

/* Sources */
.sources { font-size: .88rem; color: var(--text-muted); }
.sources ul { margin: .6rem 0 0; padding-left: 1.1rem; display: grid; gap: .35rem; }
.sources a { color: var(--text-muted); }

/* Footer */
.foot { background: var(--band); color: var(--text-muted); padding-block: clamp(2.8rem,5vw,4rem) 2rem; font-size: .9rem; }
.foot a { color: var(--text); }
.foot__grid { display: grid; gap: 2rem; }
@media (min-width: 780px) { .foot__grid { grid-template-columns: 1.6fr 1fr 1fr; } }
.foot h3 { font-family: var(--sans); font-size: .74rem; letter-spacing: .13em; text-transform: uppercase; color: var(--text); margin-bottom: .9rem; font-weight: 680; }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.foot__legal { margin-top: 2.6rem; padding-top: 1.6rem; border-top: 1px solid var(--rule); font-size: .78rem; line-height: 1.6; }

/* Sticky mobile CTA */
.stickycta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  padding: .7rem max(3vw, .7rem) calc(.7rem + env(safe-area-inset-bottom));
  background: rgba(17,21,29,.93);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--rule);
  /* visibility, not just transform: translated off-screen it stayed in the
     tab order, so keyboard focus landed on an invisible button. */
  transform: translateY(120%); visibility: hidden;
  transition: transform .3s cubic-bezier(.2,.8,.3,1), visibility .3s;
  display: flex; align-items: center; gap: .9rem;
}
.stickycta.is-in { transform: translateY(0); visibility: visible; }
.stickycta__n { font-size: .82rem; color: var(--text-muted); line-height: 1.3; }
.stickycta__n strong { color: var(--text); display: block; font-size: 1rem; font-variant-numeric: tabular-nums; }
.stickycta .btn { margin-left: auto; padding: .78rem 1.4rem; font-size: .93rem; }
@media (min-width: 900px) { .stickycta { display: none; } }
/* Reserve the bar's height so it never parks on top of the last section --
   footer links were fully covered and could not be scrolled clear. */
@media (max-width: 899px) {
  /* On .foot rather than body so the reserved strip keeps the footer's dark
     ground instead of showing bone below it. */
  .foot { padding-bottom: 6rem; }
  html { scroll-padding-bottom: 5.25rem; }
}

/* Modal */
.modal {
  position: fixed; inset: 0; z-index: 100;
  /* `place-items: center` clips the TOP of a panel taller than the viewport,
     because an overflowing centered grid item cannot be scrolled back to.
     `margin: auto` on the panel centers it when it fits and lets it scroll
     normally when it does not. */
  display: grid; padding: max(4vh, 1rem) max(4vw, 1rem);
  background: rgba(11,14,20,.72);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden; transition: opacity .26s, visibility .26s;
  overflow-y: auto;
}
.modal.is-open { opacity: 1; visibility: visible; }
/* `display: grid` above overrides the user-agent [hidden] rule, so say it
   explicitly rather than relying on visibility to do the hiding. */
.modal[hidden] { display: none; }
.modal__panel {
  background: var(--card); border-radius: var(--r-lg);
  width: min(540px, 100%); position: relative; margin: auto;
  box-shadow: var(--shadow-pop);
  transform: translateY(18px) scale(.985); transition: transform .3s cubic-bezier(.2,.8,.3,1);
  max-height: none;
}
.modal.is-open .modal__panel { transform: none; }
.modal__close {
  position: absolute; top: .75rem; right: .75rem; z-index: 2;
  width: 36px; height: 36px; border-radius: 50%;
  border: 0; background: rgba(17,21,29,.07); color: var(--text-muted);
  cursor: pointer; display: grid; place-items: center; font-size: 1.1rem; line-height: 1;
  transition: background-color .15s, color .15s;
}
.modal__close:hover { background: rgba(17,21,29,.14); color: var(--text); }
.modal__banner {
  background: var(--band); color: var(--text);
  padding: 1.15rem clamp(1.5rem,3.4vw,2.1rem);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  font-size: .9rem;
}
.modal__banner strong { color: var(--signal); }
.modal .signform { box-shadow: none; border-radius: 0 0 var(--r-lg) var(--r-lg); }
.modal__panel:not(:has(.modal__banner)) .signform { border-radius: var(--r-lg); }

.skip {
  position: absolute; left: 50%; transform: translate(-50%, -140%);
  z-index: 200; background: var(--card); color: var(--text);
  padding: .8rem 1.4rem; border-radius: 0 0 var(--r-sm) var(--r-sm);
  font-weight: 640; text-decoration: none;
  transition: transform .18s;
}
.skip:focus { transform: translate(-50%, 0); }

/* Utility */
.vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.nowrap { white-space: nowrap; }


/* ---- Blocks added with the staff-report rewrite ------------------------ */

/* The finding that the zoning rules set no noise limit and no water cap is
   the strongest thing on the page, so it is bordered in the signal colour
   rather than left as another card in the stack. */
.card--flag { background: var(--band); }

.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }
.ticks li {
  position: relative; padding-left: 1.9rem; font-size: .96rem; line-height: 1.5;
  color: var(--text-muted);
}
.ticks li::before {
  content: ""; position: absolute; left: 0; top: .45em;
  width: 11px; height: 6px;
  border-left: 2.5px solid var(--sage); border-bottom: 2.5px solid var(--sage);
  transform: rotate(-45deg);
}
.ticks li strong { color: var(--text); }
/* The "and here is what they do not cover" list, marked with a cross. */
.ticks--no li::before {
  width: 12px; height: 12px; top: .3em;
  border: 0; transform: none;
  background:
    linear-gradient(to bottom right, transparent 44%, var(--alert) 44%, var(--alert) 56%, transparent 56%),
    linear-gradient(to bottom left,  transparent 44%, var(--alert) 44%, var(--alert) 56%, transparent 56%);
}

/* The hearing date carries the signal colour; the other chips stay quiet. */
.chip--hot {
  background: var(--signal-dim);
  border-color: rgba(184, 65, 15, .35);
  color: var(--text);
}
.chip--hot strong { color: var(--signal); }

/* The split illustration. Labelled as an illustration in its own caption:
   it is a fair depiction of a contrast, not a photograph of the site, and a
   campaign whose whole asset is being right cannot blur that line. */
/* Before and after: the template the two photographs drop into, left and
   right. Equal panels on a wide screen, stacked on a phone in reading order,
   because a phone cannot show them side by side without making both too small
   to read. No labels over them -- the pictures say it. */
.ba {
  margin: 2.6rem 0 0;
  display: grid; gap: 1rem;
  grid-template-columns: 1fr;
  text-align: left;
}
@media (min-width: 760px) { .ba { grid-template-columns: 1fr 1fr; gap: 1.2rem; } }

.ba__panel { margin: 0; }
.ba__panel img {
  display: block; width: 100%; height: auto; aspect-ratio: 29 / 28;
  object-fit: cover;
  border-radius: var(--r-lg); border: 1px solid var(--rule);
  background: var(--band);
}
.ba__panel figcaption {
  margin-top: .7rem; font-size: .88rem; color: var(--text-muted); line-height: 1.5;
}
/* A section's closing line. Weight and the body colour, not the signal:
   these sit a few lines above an orange button, and two accents that close
   together stop reading as emphasis at all. Sized at the lede's exact clamp,
   not a near miss -- a second size within a tenth of a rem of an existing one
   is noise, not hierarchy. */
.verdict {
  margin: 1.8rem 0 0; text-align: center;
  font-size: clamp(1.16rem, 1.05rem + .55vw, 1.42rem);
  font-weight: 660; color: var(--text); letter-spacing: -.01em;
}
.prec__note {
  margin: 2.2rem auto 0; max-width: 62ch; text-align: center;
  font-size: .92rem; line-height: 1.6; color: var(--text-muted);
}


/* ---- Evidence blocks --------------------------------------------------- */
/* Every claim carries its own source link rather than deferring to a
   bibliography at the foot of the page. Someone deciding whether to believe
   this should not have to go looking. */
.ev {
  margin-top: 2.6rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 3vw, 2.1rem);
  background: var(--card);
}
.ev--flag { background: var(--band); }
.ev__h { margin: .35rem 0 .6rem; }
.ev__lede { color: var(--text-muted); margin: 0 0 1.6rem; max-width: 54ch; }
.ev__grid { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); border-radius: var(--r-md); overflow: hidden; }
@media (min-width: 720px) { .ev__grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .ev__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 720px) { .ev__grid--2 { grid-template-columns: 1fr 1fr; } }
.ev__item { background: var(--card); padding: 1.3rem; display: flex; flex-direction: column; gap: .55rem; }
.ev__item--hot { background: var(--signal-dim); }
.ev__n {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.7rem, 1.4rem + 1.1vw, 2.2rem);
  line-height: 1; letter-spacing: -.03em; color: var(--signal);
  font-variant-numeric: tabular-nums;
}
.ev__item p { margin: 0; font-size: .96rem; color: var(--text-muted); flex: 1; }
.ev__item p strong, .ev__item p em { color: var(--text); }
.ev__item a {
  font-size: .88rem; color: var(--text-muted); text-underline-offset: 3px;
  margin-top: auto;
}
.ev__item a:hover { color: var(--signal); }
.ev__note {
  margin: 1.4rem 0 0; font-size: .88rem; line-height: 1.6;
  color: var(--text-muted); max-width: 68ch;
}

/* ---- Street view of the substation ------------------------------------- */
.sv { margin-top: 1.6rem; }
.sv__frame {
  position: relative; display: block; border-radius: var(--r-md);
  overflow: hidden; border: 1px solid var(--rule); background: var(--band);
}
.sv__frame img { display: block; width: 100%; height: auto; }
.sv__tag {
  position: absolute; left: 0; bottom: 0; right: 0;
  padding: 1.6rem .9rem .7rem;
  background: linear-gradient(to top, rgba(26,31,40,.82), transparent);
  color: #fff; font-size: .82rem; font-weight: 560;
  display: flex; align-items: center; gap: .4rem;
}
.sv figcaption { margin-top: .7rem; font-size: .88rem; color: var(--text-muted); }

/* ---- Sticky next-meeting cue ------------------------------------------- */
/* One element, two shapes. A card pinned to the right edge on a wide screen,
   a slim strip stacked above the sign bar on a narrow one. Held back until
   the visitor has scrolled a little, so the first thing on screen is the
   page. */
.meetingcue {
  position: fixed; z-index: 54;
  display: grid; align-items: center;
  text-decoration: none; color: var(--text);
  background: var(--card);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-lift);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .28s, visibility .28s, transform .28s cubic-bezier(.2,.8,.3,1);
}
.meetingcue.is-in { opacity: 1; visibility: visible; pointer-events: auto; }
.meetingcue__label {
  font-size: .66rem; font-weight: 680; letter-spacing: .13em;
  text-transform: uppercase; color: var(--signal);
}
.meetingcue__day { font-family: var(--display); font-weight: 600; letter-spacing: -.02em; }
.meetingcue__time { color: var(--text-muted); }
.meetingcue__go {
  display: inline-flex; align-items: center; gap: .25rem;
  font-size: .78rem; font-weight: 640; color: var(--signal);
}

/* Wide: a card on the right edge, clear of the page's own content. */
@media (min-width: 900px) {
  .meetingcue {
    right: 1.25rem; bottom: 1.25rem; width: 190px;
    padding: .9rem 1rem; border-radius: var(--r-md);
    gap: .12rem; transform: translateY(10px);
  }
  .meetingcue.is-in { transform: none; }
  .meetingcue__day { font-size: 1.25rem; }
  .meetingcue__time { font-size: .92rem; }
  .meetingcue__go { margin-top: .45rem; }
}

/* Narrow: a strip directly above the sign bar. Grid rather than flex so the
   date and the call to action sit on one line without wrapping. */
@media (max-width: 899px) {
  .meetingcue {
    left: 0; right: 0; bottom: 0; border-radius: 0;
    border-bottom: 0;
    padding: .55rem max(3vw, .8rem);
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "label day go" "label time go";
    column-gap: .6rem; row-gap: 0;
    transform: translateY(100%);
    /* Sits on top of the sign bar, which is 64px plus the safe area. */
    margin-bottom: calc(4rem + env(safe-area-inset-bottom));
    transition: transform .28s cubic-bezier(.2,.8,.3,1), opacity .28s,
                visibility .28s, margin-bottom .28s;
  }
  .meetingcue.is-in { transform: none; }
  .meetingcue.is-solo { margin-bottom: env(safe-area-inset-bottom); }
  .meetingcue__label {
    grid-area: label; align-self: center;
    writing-mode: vertical-rl; transform: rotate(180deg);
    font-size: .58rem; letter-spacing: .1em;
  }
  .meetingcue__day { grid-area: day; font-size: 1rem; align-self: end; }
  .meetingcue__time { grid-area: time; font-size: .8rem; align-self: start; }
  .meetingcue__go { grid-area: go; align-self: center; }
  /* Two fixed bars now, so the footer has to clear both: the sign bar is
     about 64px and the cue sits 64px above it and is about 102px tall, so
     roughly 166px is occluded. Reserve more than that, measured rather than
     guessed -- 10rem was 6px short and the last line of the footer sat under
     the cue. */
  .foot { padding-bottom: 13rem; }
  html { scroll-padding-bottom: 12rem; }
}

/* The petition's formal preamble. Set apart from the surrounding explanation
   because it is the sentence people are actually signing. */
.petition-preamble {
  font-family: var(--display);
  font-size: clamp(1.15rem, 1.02rem + .6vw, 1.45rem);
  line-height: 1.45; letter-spacing: -.015em;
  max-width: 44ch; margin: 0 0 1.6rem;
  padding: 1.4rem 1.6rem; background: var(--band); border-radius: var(--r-md);
}

/* The hero runs voice, then fact, then the call to act. The fact paragraph is
   set smaller so the opening reads as the residents talking and the second as
   the plain thing being proposed. The call comes back up to the opening's size
   and carries its weight in colour, so no new type size enters the page. */
.hero__sub--fact {
  font-size: clamp(1rem, .95rem + .3vw, 1.12rem);
  color: var(--text-muted);
  margin-top: 1.1rem;
}
/* Weight, not colour. The headline already ends on an orange word and the
   hashtag below is orange, so an orange call between them stacks three
   accents down one column and they stop reading as emphasis. */
.hero__sub--rally {
  margin-top: 1.3rem;
  font-weight: 640;
  color: var(--text);
}

/* --- Legal pages -------------------------------------------------------- */
/* /privacy/ and /terms/. One narrow column of running text, no cards, no
   panels. The main page earns its structure because it is making an argument;
   these two are read start to finish by someone checking one thing, so the
   only job is a comfortable measure and honest spacing between headings.
   Type sizes are the page's existing ones -- the h1 comes down to h2's scale
   because a six-rem headline over a privacy policy is a joke. */
.doc { padding-block: clamp(2.6rem, 5vw, 4.5rem) clamp(3rem, 6vw, 5rem); }
.doc .shell { max-width: 66ch; }
/* Each heading and its text is a <section> so scripts/readability.mjs, which
   scores per `main section`, can grade these pages the same way it grades the
   main one. They are sections for measurement, not for rhythm, so the global
   section padding comes back off. */
.doc section { padding-block: 0; }
.doc h1 {
  font-size: clamp(2rem, 1.35rem + 2.7vw, 3.5rem);
  letter-spacing: -0.028em;
  margin-bottom: 1.4rem;
}
.doc h2 {
  font-size: clamp(1.25rem, 1.08rem + .75vw, 1.7rem);
  letter-spacing: -0.02em;
  margin-top: 2.9rem;
  margin-bottom: .9rem;
}
.doc .lede { margin-bottom: 2.2rem; }
.doc__date {
  font-family: var(--sans);
  font-size: .82rem;
  color: var(--text-muted);
  margin-bottom: 2rem;
}
.doc ul { margin: 0 0 1.15em; padding-left: 1.15rem; }
.doc li { margin-bottom: .7rem; }
.doc a { color: var(--signal); text-underline-offset: .18em; }
.doc a:hover { color: var(--signal-press); }
