/* ==========================================================================
   WY4Privacy — wy4privacy.org
   Hand-written CSS. No build step, no framework, no remote assets.
   Contrast pairs verified against WCAG 2.1 AA before authoring.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* Light palette (default). Every value defined here, unconditionally. */
  --bg:            #faf8f5;
  --bg-alt:        #f2eee7;
  --surface:       #ffffff;
  --ink:           #1a1c20;   /* 16.09:1 on --bg */
  --ink-muted:     #575d67;   /*  6.26:1 on --bg */
  --accent:        #8a4b0f;   /*  6.40:1 on --bg */
  --accent-hover:  #6d3b0b;
  --on-accent:     #ffffff;   /*  6.79:1 on --accent */
  --header-bg:     #1f2937;
  --header-ink:    #f4f1ec;   /* 13.03:1 on --header-bg */
  --header-muted:  #c3cad6;   /*  8.91:1 on --header-bg */
  --line:          #d9d3c9;
  --line-strong:   #b9b1a3;
  --flag-bg:       #fdf3e3;
  --flag-ink:      #6d3b0b;
  --focus-ring:    #8a4b0f;   /*  6.40:1 on --bg */
  --on-dark-link:  #e0ad63;   /*  7.22:1 on --header-bg */
  --on-dark-hover: #f0c689;   /*  9.19:1 on --header-bg */
  --field-border:  #8a8375;   /*  3.55:1 on --bg, 3.76:1 on --surface */
  --shadow:        0 1px 2px rgba(26, 28, 32, .06), 0 8px 24px rgba(26, 28, 32, .06);
  --shadow-lift:   0 2px 4px rgba(26, 28, 32, .08), 0 14px 40px rgba(26, 28, 32, .10);

  /* Fluid scale */
  --step--1: clamp(.82rem, .79rem + .12vw, .90rem);
  --step-0:  clamp(1rem, .96rem + .18vw, 1.125rem);
  --step-1:  clamp(1.15rem, 1.08rem + .34vw, 1.4rem);
  --step-2:  clamp(1.4rem, 1.26rem + .68vw, 1.95rem);
  --step-3:  clamp(1.8rem, 1.53rem + 1.32vw, 2.85rem);
  --step-4:  clamp(2.3rem, 1.79rem + 2.5vw, 4.4rem);

  --wrap:      1240px;
  --wrap-wide: 1600px;
  --gap:       clamp(1rem, .7rem + 1.4vw, 1.75rem);
  --pad-y:     clamp(2.75rem, 2rem + 3.4vw, 5.5rem);
  --radius:    12px;
  --radius-sm: 8px;

  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:           #14161a;
    --bg-alt:       #1a1d23;
    --surface:      #1c1f25;
    --ink:          #e8ebef;   /* 15.15:1 on --bg */
    --ink-muted:    #a9b2be;   /*  8.45:1 on --bg */
    --accent:       #e0ad63;   /*  8.91:1 on --bg */
    --accent-hover: #f0c689;
    --on-accent:    #14161a;   /*  8.91:1 on --accent */
    --header-bg:    #0f1116;
    --header-ink:   #f0f3f7;
    --header-muted: #aeb7c3;
    --line:         #2b3038;
    --line-strong:  #3d444f;
    --flag-bg:      #2a2115;
    --flag-ink:     #e8c48d;
    --focus-ring:   #e0ad63;
    --on-dark-link: #e0ad63;
    --on-dark-hover:#f0c689;
    --field-border: #6c7480;   /*  3.84:1 on --bg, 3.50:1 on --surface */
    --shadow:       0 1px 2px rgba(0, 0, 0, .5), 0 8px 24px rgba(0, 0, 0, .35);
    --shadow-lift:  0 2px 4px rgba(0, 0, 0, .55), 0 14px 40px rgba(0, 0, 0, .45);
  }
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/* The filter JS hides rows with the `hidden` property. The UA rule for [hidden]
   is author-beatable, and .paper-list li sets display:grid, so without this the
   newspaper filter silently does nothing while the counter claims it worked. */
[hidden] { display: none !important; }

/* Available to screen readers, invisible on screen. Used to warn that a link
   retargets the window, which is otherwise a silent surprise (WCAG 3.2.5). */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.65;
  overflow-wrap: break-word;
}

h1, h2, h3, h4 {
  line-height: 1.18;
  margin: 0 0 .5em;
  text-wrap: balance;
  letter-spacing: -.015em;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); }
h4 { font-size: var(--step-0); }

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a {
  color: var(--accent);
  text-decoration-thickness: max(1px, .06em);
  text-underline-offset: .18em;
}
a:hover { color: var(--accent-hover); }

img, svg { max-width: 100%; height: auto; }

/* External links used to carry a "\2197" arrow here, as the sighted counterpart
   to the .visually-hidden "(opens in a new tab)" cue. The arrow is gone by
   request; the hidden cue stays, because it is what screen reader users rely
   on and removing it too would take away the only remaining warning. Anything
   that needs to mark a destination should do it in the link text. */

address { font-style: normal; }

:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Enhancement-only controls. Hidden when JS is absent; when JS is present they
   keep whatever display their own rule gives them (flex, grid, inline-block). */
html:not(.js) .js-only { display: none !important; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--accent);
  color: var(--on-accent);
  padding: .8rem 1.2rem;
  border-radius: 0 0 var(--radius-sm) 0;
  font-weight: 650;
}
.skip-link:focus {
  left: 0;
  color: var(--on-accent);
}

.wrap {
  width: min(100% - 2 * var(--gap), var(--wrap));
  margin-inline: auto;
}

@media (min-width: 1800px) {
  .wrap { width: min(100% - 4rem, var(--wrap-wide)); }
}

/* --------------------------------------------------------------------------
   3. Header and nav
   -------------------------------------------------------------------------- */

.site-header :focus-visible,
.section-contact :focus-visible { outline-color: var(--header-ink); }

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--header-bg);
  color: var(--header-ink);
}

.header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding-block: .7rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  color: var(--header-ink);
  text-decoration: none;
  min-height: 44px;
}
.brand:hover { color: var(--header-ink); }
.brand-mark { display: inline-flex; color: var(--header-ink); flex: none; }
.brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.brand-text strong { font-size: 1.2rem; letter-spacing: -.02em; }
.brand-text small {
  font-size: .74rem;
  color: var(--header-muted);
  letter-spacing: .01em;
}

.nav-wrap { position: relative; }
.nav-wrap summary::-webkit-details-marker { display: none; }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-height: 44px;
  min-width: 44px;
  padding: .35rem .9rem;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: var(--radius-sm);
  color: var(--header-ink);
  font-weight: 600;
  font-size: .95rem;
  cursor: pointer;
  list-style: none;
}
.nav-toggle:hover { background: rgba(255, 255, 255, .1); }

/* In normal flow, not an overlay. When the disclosure is open, .nav-wrap grows
   past the space beside the brand and flex-wrap drops it onto its own row, so
   the menu pushes the page down instead of covering the hero. That keeps the
   no-JS case usable, where the menu is always expanded. */
.site-nav {
  margin-top: .5rem;
  min-width: 15rem;
  max-height: 65vh;
  overflow-y: auto;
  background: var(--header-bg);
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  padding: .5rem;
}
.site-nav ul { list-style: none; margin: 0; padding: 0; }
.site-nav a {
  display: block;
  padding: .6rem .8rem;
  min-height: 44px;
  border-radius: var(--radius-sm);
  color: var(--header-ink);
  text-decoration: none;
  font-weight: 500;
}
.site-nav a:hover { background: rgba(255, 255, 255, .12); color: var(--header-ink); }
.site-nav .nav-cta {
  margin-top: .35rem;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 650;
  text-align: center;
}
.site-nav .nav-cta:hover { background: var(--accent-hover); color: var(--on-accent); }

/* Desktop: no disclosure, nav always open, laid out inline.

   The brand and the nav share one row here; letting the nav drop below the
   brand is the narrow-screen shape and reads as broken on a wide window. At
   full size the row wants 1168px (brand 308 + gap 12 + nav 848) and .wrap only
   offers ~910px at 60rem, so two things give across this range. The nav's type
   and horizontal padding ramp fluidly from compact at 60rem to full size at
   80rem, and the tagline -- the widest part of the brand -- is held back until
   80rem (rule below), where the full-size row fits with room to spare. The
   clamp() values are lines through those two anchor widths, so nothing steps.
   .header-inner keeps flex-wrap: wrap as a safety valve for font stacks wider
   than the ones this was measured against. */
@media (min-width: 60rem) {
  .nav-toggle { display: none; }
  .site-nav {
    border: 0;
    box-shadow: none;
    background: none;
    padding: 0;
    min-width: 0;
    margin-top: 0;
    max-height: none;
    overflow: visible;
  }
  .site-nav ul { display: flex; flex-wrap: wrap; align-items: center; gap: .15rem; }
  .site-nav a {
    display: inline-flex;
    align-items: center;
    padding-block: .5rem;
    padding-inline: clamp(.35rem, 1.75vw - .7rem, .7rem);
    font-size: clamp(.85rem, .61rem + .4vw, .93rem);
    white-space: nowrap;
  }
  .site-nav .nav-cta {
    margin-top: 0;
    margin-left: .4rem;
    padding-inline: clamp(.7rem, 1.5vw - .2rem, 1rem);
  }
}

/* The tagline costs 155px, which is the difference between a one-row header
   and a wrapped one below 80rem. It stays in the markup and stays visible on
   narrow screens, where the nav collapses to a disclosure and the room is
   there. */
@media (min-width: 60rem) and (max-width: 79.999rem) {
  .brand-text small { display: none; }
}

/* --------------------------------------------------------------------------
   4. Hero
   -------------------------------------------------------------------------- */

.hero {
  background:
    radial-gradient(120% 100% at 15% 0%, color-mix(in srgb, var(--accent) 10%, transparent) 0%, transparent 60%),
    var(--bg-alt);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(3rem, 2rem + 5vw, 7rem);
}

.hero-inner { max-width: 62ch; }

@media (min-width: 90rem) { .hero-inner { max-width: 70ch; } }

.eyebrow {
  font-size: var(--step--1);
  font-weight: 650;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: .9rem;
}

.hero h1 { margin-bottom: .35em; }

.lede {
  font-size: var(--step-1);
  color: var(--ink-muted);
  max-width: 58ch;
}

.disclaimer {
  display: inline-block;
  background: var(--flag-bg);
  color: var(--flag-ink);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 999px;
  padding: .4rem 1.1rem;
  font-size: var(--step--1);
  margin: 1.4rem 0;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem;
  margin: .6rem 0 1.6rem;
}

/* Three buttons cannot share one row: .hero-inner measures 62ch, and the first
   two already fill it to within 6px, so the third wraps no matter how short its
   label is. Letting them grow makes both rows end flush at the same edge
   instead of stranding the last button, and on a phone — where each button
   already owns a row — it lines all three up to one width. */
.hero-actions .btn { flex: 1 1 auto; }

.hero-note {
  font-size: var(--step--1);
  color: var(--ink-muted);
  max-width: 52ch;
}

/* The song player under the hero buttons. One row on a desktop; on a phone
   the flex basis on <audio> is small enough to sit beside the label, so only
   the Lyrics link wraps. The height is set because Chrome draws <audio> at
   54px, taller than a 48px button, and min-width: 0 lets the control shrink
   instead of forcing a horizontal scroll. */
.listen-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem .8rem;
}
.listen-strip-label {
  font-size: var(--step--1);
  font-weight: 650;
  color: var(--ink-muted);
  white-space: nowrap;
}
.listen-strip audio {
  flex: 1 1 9rem;
  min-width: 0;
  max-width: 100%;
  height: 40px;
}
.listen-strip-link {
  font-size: var(--step--1);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1rem;
  min-height: 48px;
  padding: .8rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 650;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, transform .15s ease;
}
.btn:active { transform: translateY(1px); }
.btn small { font-weight: 450; font-size: .78rem; opacity: .85; }

.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); color: var(--on-accent); }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}
.btn-ghost:hover { background: var(--surface); color: var(--ink); border-color: var(--accent); }

.btn-small {
  flex-direction: row;
  min-height: 44px;
  padding: .55rem 1.1rem;
  font-size: var(--step--1);
  background: var(--accent);
  color: var(--on-accent);
}
.btn-small:hover { background: var(--accent-hover); color: var(--on-accent); }
.btn-small.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn-small.btn-ghost:hover { background: var(--surface); color: var(--ink); border-color: var(--accent); }

/* A send button with nobody selected, or an office that publishes no address
   at all. Never hidden — the reason why is spelled out in the .flag beneath
   it, and a control that vanishes reads as a bug. */
.btn[disabled] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
}
.btn-primary[disabled]:hover { background: var(--accent); }
.btn-ghost[disabled]:hover { background: transparent; border-color: var(--line-strong); }
.btn-small[disabled]:hover { background: var(--accent); }

.copy {
  margin-left: .5rem;
  min-height: 32px;
  min-width: 44px;
  padding: .2rem .6rem;
  border: 1px solid var(--field-border);
  border-radius: 6px;
  background: transparent;
  color: var(--ink-muted);
  font: inherit;
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .02em;
  cursor: pointer;
  flex: none;
}
.copy:hover { border-color: var(--accent); color: var(--accent); }
.copy[data-copied] { border-color: var(--accent); color: var(--accent); }

/* Touch devices get a full-size target. */
@media (pointer: coarse) {
  .copy { min-height: 44px; padding-inline: .8rem; }
  /* The primary affordance ("Call them. Write to them.") must be at least as
     tappable as the secondary Copy button sitting against it. */
  .contact-line a,
  .directory-foot a,
  .paper-list a,
  .resource-list h3 a,
  .link-list a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* --------------------------------------------------------------------------
   6. Section shell
   -------------------------------------------------------------------------- */

.section { padding-block: var(--pad-y); }
.section-alt { background: var(--bg-alt); }

.section > .wrap > h2 { max-width: 24ch; }

.section-intro {
  color: var(--ink-muted);
  max-width: 68ch;
  margin-bottom: 1.8rem;
  font-size: var(--step-0);
}

.subhead { margin-top: 3.5rem; font-size: var(--step-2); }

.source-note {
  margin-top: 2rem;
  font-size: var(--step--1);
  color: var(--ink-muted);
}

/* --------------------------------------------------------------------------
   7. Cards and lists
   -------------------------------------------------------------------------- */

.card-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
}
.card-list.cols-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.card-list.cols-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  padding: 1.15rem 1.35rem;
  box-shadow: var(--shadow);
  font-size: var(--step-0);
}

.numbered-list {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: .9rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 27rem), 1fr));
}
.numbered-list li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  gap: .85rem;
  align-items: start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  box-shadow: var(--shadow);
}
.numbered-list li::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
  font-size: .95rem;
  font-variant-numeric: tabular-nums;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.15rem, .9rem + .8vw, 1.75rem);
  box-shadow: var(--shadow);
}
.panel h3 {
  padding-bottom: .55rem;
  margin-bottom: .9rem;
  border-bottom: 2px solid var(--accent);
}
.panel h4 {
  margin: 1.1rem 0 .3rem;
  font-size: var(--step--1);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-muted);
}
.panel h4:first-of-type { margin-top: 0; }

.grid-3 {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  align-items: start;
}

/* The Signal invite QR codes — one per channel, each inside its own card.
   The white quiet zone is baked into the SVG rather than painted here: in
   dark mode the card behind it is nearly black, and a code with no light
   margin does not scan. width/height are also on the element itself so the
   space is reserved before the file arrives. */
.qr {
  display: block;
  width: 200px;
  max-width: 100%;
  height: auto;
  margin-top: 1.1rem;
  border-radius: var(--radius-sm);
}

/* The FAQ. Native <details>, so it needs no script; this only dresses it in
   the card vocabulary above. The whole <summary> is the hit target, which on
   a phone is the difference between tapping the question and missing a
   12px triangle.

   The open/closed cue is a border-drawn chevron with empty content, not a
   "+" glyph: generated text on a <summary> is folded into its accessible
   name in Chromium, so every question would be read out ending in "plus". */
.faq-list {
  display: grid;
  gap: .75rem;
  max-width: 62rem;
}
.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.faq-item > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 44px;
  padding: 1rem 1.35rem;
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius);
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary h3 {
  margin: 0;
  font-size: var(--step-0);
  line-height: 1.35;
}
.faq-item > summary::after {
  content: "";
  flex: none;
  width: .6rem;
  height: .6rem;
  margin-right: .2rem;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: translateY(-25%) rotate(45deg);
}
.faq-item[open] > summary::after { transform: translateY(25%) rotate(-135deg); }
.faq-item > summary:hover h3 { color: var(--accent); }
.faq-answer {
  padding: 0 1.35rem 1.15rem;
  max-width: 68ch;
  font-size: var(--step-0);
}
.faq-answer > :first-child { margin-top: 0; }
.faq-answer > :last-child { margin-bottom: 0; }
.faq-steps { padding-left: 1.4rem; }
.faq-steps li + li { margin-top: .5rem; }
.faq-reviewed {
  font-size: var(--step--1);
  color: var(--ink-muted);
}

/* --------------------------------------------------------------------------
   8. Speech + records widgets
   -------------------------------------------------------------------------- */

.widget {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.2rem, .95rem + .9vw, 2rem);
  box-shadow: var(--shadow);
  max-width: 62rem;
}
.widget h3 { margin-bottom: .35rem; }

.widget-fields {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  margin-bottom: 1.5rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px dashed var(--line-strong);
}
.field { display: flex; flex-direction: column; gap: .35rem; margin: 0; }
.field label {
  font-size: var(--step--1);
  font-weight: 650;
  color: var(--ink-muted);
}

input[type="text"], input[type="search"], select {
  min-height: 48px;
  padding: .6rem .85rem;
  border: 1px solid var(--field-border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  width: 100%;
}
input[type="text"]:focus, input[type="search"]:focus, select:focus { border-color: var(--accent); }

/* Left as a native <select>. The dropdown list itself is painted by the OS,
   which is why :root declares `color-scheme: light dark` — without it the
   open list renders white-on-white for a visitor in dark mode. */
select { max-width: 100%; }

.speech {
  margin: 0;
  padding-left: 1.4rem;
  font-size: var(--step-1);
  line-height: 1.75;
}
.speech li { margin-bottom: .35rem; }

.blank {
  display: inline-block;
  min-width: 7ch;
  padding: 0 .3rem;
  border-bottom: 2px solid var(--accent);
  font-weight: 650;
  color: var(--accent);
  text-align: center;
}

.widget-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin: 1.5rem 0 0;
}

.request-body {
  margin: 0 0 .5rem;
  padding: 1.15rem 1.3rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.7;
  white-space: pre-wrap;
  overflow-x: auto;
}

/* The letter is a real <textarea> so that what the visitor reads and what the
   buttons send cannot differ. A textarea inherits neither font nor color, and
   main.js sizes it to its content, so the height here is only the floor it
   starts from. */
textarea.request-body {
  display: block;
  width: 100%;
  min-height: 12rem;
  color: var(--ink);
  resize: vertical;
  overflow-y: hidden;
}
textarea.request-body:focus { border-color: var(--accent); }
textarea.request-body:disabled {
  color: var(--ink-muted);
  cursor: not-allowed;
}

/* The composed subject line, above the letter body it belongs to. */
.letter-subject {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .35rem;
  margin: 0 0 .6rem;
  font-size: var(--step--1);
}
.letter-subject-label {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
/* Override the global width:100% for text inputs — inside this flex row it
   would push the copy button onto a line of its own. */
.letter-subject input[type="text"] {
  flex: 1 1 20rem;
  width: auto;
  min-width: 0;
  font-weight: 650;
}
.letter-subject .copy { margin-left: .15rem; }

/* Only on screen once the visitor has changed something. */
.letter-edited {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem .75rem;
  margin: 0 0 .5rem;
  font-size: .8rem;
  line-height: 1.5;
  color: var(--flag-ink);
}
.letter-edited span { flex: 1 1 16rem; }

.callout {
  margin-top: var(--gap);
  background: var(--flag-bg);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: var(--radius);
  padding: clamp(1.15rem, .9rem + .8vw, 1.75rem);
  max-width: 62rem;
}
.callout h3 { font-size: var(--step-0); margin-top: 1.1rem; }
.ombuds { line-height: 1.9; }

/* --------------------------------------------------------------------------
   9. Sign idea
   -------------------------------------------------------------------------- */

.sign-grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  max-width: 56rem;
}
.sign { margin: 0; }
.sign-face {
  display: grid;
  place-items: center;
  text-align: center;
  aspect-ratio: 4 / 3;
  padding: 1.5rem;
  background: var(--surface);
  border: 3px solid var(--ink);
  border-radius: var(--radius);
  font-size: var(--step-2);
  font-weight: 750;
  letter-spacing: -.02em;
  box-shadow: var(--shadow);
}
.sign figcaption {
  margin-top: .7rem;
  font-size: var(--step--1);
  color: var(--ink-muted);
  text-align: center;
}

/* --------------------------------------------------------------------------
   10. Directory
   -------------------------------------------------------------------------- */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .7rem;
  margin-bottom: 1.5rem;
}
.filter-bar label {
  font-size: var(--step--1);
  font-weight: 650;
  color: var(--ink-muted);
}
.filter-bar input { max-width: 22rem; }
.filter-count {
  font-size: var(--step--1);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

.directory .person {
  padding: .8rem 0;
  border-bottom: 1px solid var(--line);
}
.directory .person:last-of-type { border-bottom: 0; }
.person h4 {
  margin: 0 0 .25rem;
  font-size: var(--step-0);
  text-transform: none;
  letter-spacing: -.01em;
  color: var(--ink);
}

.role-tag {
  margin: 0 0 .3rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
}

.is-clerk { border-top: 1px solid var(--line); margin-top: .5rem; padding-top: 1rem; }

.contact-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .15rem .1rem;
  margin: 0 0 .3rem;
  font-size: var(--step--1);
}
.contact-line a { word-break: break-word; }
.contact-line .loc {
  min-width: 6.5rem;
  color: var(--ink-muted);
  font-size: .8rem;
}
/* Divides the parts of the composed contact line. .contact-line sets a .1rem
   gap, which is tight enough that an address and a phone number would
   otherwise read as one string. */
.contact-sep {
  margin-inline: .4rem;
  color: var(--line-strong);
}

.directory-foot {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 2px solid var(--line-strong);
  font-size: var(--step--1);
  color: var(--ink-muted);
}
.directory-foot address { margin-bottom: .4rem; }

.person-lg .role {
  margin-bottom: .8rem;
  font-size: var(--step--1);
  font-weight: 650;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.person-lg h3 { border-bottom-width: 2px; }

.flag {
  margin: .4rem 0 0;
  padding: .5rem .75rem;
  background: var(--flag-bg);
  color: var(--flag-ink);
  border-radius: var(--radius-sm);
  font-size: .8rem;
  line-height: 1.5;
}
.flag a { color: inherit; }

.flag-inline {
  display: block;
  margin-top: .2rem;
  font-size: .75rem;
  color: var(--flag-ink);
}

/* --------------------------------------------------------------------------
   11. Organizations, resources, papers, books
   -------------------------------------------------------------------------- */

.org-abbr {
  margin: 0 0 .3rem;
  font-size: var(--step-2);
  font-weight: 800;
  letter-spacing: -.03em;
  color: var(--accent);
  line-height: 1;
}
.org h3 { font-size: var(--step-0); border-bottom: 0; padding-bottom: 0; }

.link-list { list-style: none; margin: 1rem 0 0; padding: 0; }
.link-list li { margin-bottom: .6rem; font-size: var(--step--1); }
.link-list span {
  display: block;
  font-weight: 650;
  color: var(--ink-muted);
  font-size: .78rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.link-list a { word-break: break-word; }

.resource-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
}
.resource-list.cols-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); }
.resource-list li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.15rem 1.35rem;
  box-shadow: var(--shadow);
}
.resource-list h3 { font-size: var(--step-0); margin-bottom: .3rem; }
.resource-list .url {
  margin: 0;
  font-size: .78rem;
  color: var(--ink-muted);
  font-family: var(--font-mono);
  word-break: break-all;
}
.resource-list .note {
  margin: .7rem 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
  border-left: 3px solid var(--accent);
  padding-left: .75rem;
}

/* The two Substack pieces the action plan opens with. Marked, not moved:
   source order is still reading order. */
.resource-list li.is-featured { border-left: 4px solid var(--accent); }

/* Share controls under a news story. "Copy link" is a <button> and needs
   main.js; "Email this" is a plain mailto: anchor and does not — so the two
   are normalized to one shape here rather than styled as different things. */
.share-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  margin: .9rem 0 0;
}
.share-row .copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 0;
  text-decoration: none;
}
.share-row a.copy:hover { color: var(--accent); border-color: var(--accent); }

.paper-list {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: paper;
  display: grid;
  gap: .6rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
}
.paper-list li {
  counter-increment: paper;
  display: grid;
  grid-template-columns: 2.4rem 1fr;
  gap: .1rem .6rem;
  align-items: baseline;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: .7rem .9rem;
}
.paper-list li::before {
  content: counter(paper);
  grid-row: 1 / span 3;
  align-self: center;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: .85rem;
  color: var(--ink-muted);
  text-align: right;
  padding-right: .3rem;
  border-right: 1px solid var(--line);
}
.paper-list a { font-weight: 600; }
.paper-list .url {
  font-size: .74rem;
  color: var(--ink-muted);
  font-family: var(--font-mono);
  word-break: break-all;
}

.book-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .8rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
}
.book-list li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: .9rem 1.1rem;
}
.book-list cite {
  display: block;
  font-style: normal;
  font-weight: 650;
  line-height: 1.35;
  margin-bottom: .2rem;
}
.book-list .by { font-size: var(--step--1); color: var(--ink-muted); }

/* --------------------------------------------------------------------------
   12. Contact, footer, toast
   -------------------------------------------------------------------------- */

.section-contact {
  background: var(--header-bg);
  color: var(--header-ink);
}
.section-contact h2 { color: var(--header-ink); }
.section-contact .lede { color: var(--header-muted); }
.section-contact .hero-note { color: var(--header-muted); }
.section-contact a { color: var(--on-dark-link); }
.section-contact a:hover { color: var(--on-dark-hover); }
.section-contact .copy { color: var(--header-muted); border-color: rgba(255, 255, 255, .3); }
.section-contact .copy:hover { color: var(--header-ink); border-color: var(--header-ink); }

.contact-big {
  font-size: var(--step-2);
  font-weight: 700;
  margin: 1.2rem 0 1.6rem;
}
.contact-big a { word-break: break-word; }

.site-footer {
  background: var(--bg-alt);
  border-top: 1px solid var(--line);
  padding-block: clamp(2rem, 1.5rem + 2vw, 3.5rem);
  font-size: var(--step--1);
  color: var(--ink-muted);
}
.footer-inner {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.footer-brand strong { font-size: 1.1rem; color: var(--ink); letter-spacing: -.02em; }
.footer-head {
  font-weight: 700;
  color: var(--ink);
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  margin-bottom: .6rem;
}
.footer-col .url { font-family: var(--font-mono); font-size: .74rem; }
.make-copies {
  margin-top: .8rem;
  font-weight: 650;
  color: var(--ink);
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  z-index: 300;
  background: var(--header-bg);
  color: var(--header-ink);
  padding: .7rem 1.3rem;
  border-radius: 999px;
  box-shadow: var(--shadow-lift);
  font-size: var(--step--1);
  font-weight: 600;
}

.print-only { display: none; }
.print-addresses { display: none; }
.note-lines { display: none; }

/* --------------------------------------------------------------------------
   13. Press kit
   Six hooks press-kit.html needs and the landing page has no use for.
   Everything else on that page is built from the classes above.
   -------------------------------------------------------------------------- */

/* Three boilerplate blocks in a row. .widget carries no vertical rhythm of its
   own because the landing page only ever shows one. */
.widget-stacked { margin-top: var(--gap); }

/* A domain, a hex value or an address quoted mid-sentence. .url is scoped to
   the lists that own it, so an inline mention needs its own hook -- and unlike
   .url this one does not break-all, which shatters a short token sitting
   inside a paragraph. */
.url-inline {
  font-family: var(--font-mono);
  font-size: .9em;
  word-break: break-word;
}

/* The third line of a .paper-list entry: who published it, and why it is on
   the list. .paper-list .url is mono and break-all, which is right for an
   address and wrong for a sentence. */
.paper-list .meta {
  font-size: .78rem;
  line-height: 1.45;
  color: var(--ink-muted);
}

/* A published position, sitting inside a .card. Two things to undo: the UA
   stylesheet indents a blockquote by 40px, which inside an already-padded card
   strands the text; and an accent bar of its own would sit 1.35rem inboard of
   the card's accent edge and read as one doubled border. The card already
   says "quote" -- so this only has to say "pull quote", which it does with
   size. */
.pull {
  margin: 0;
  font-size: var(--step-1);
  line-height: 1.5;
}

/* Asset previews. Each mark ships with its own dark plate baked into the file,
   so the card behind it only has to hold a border rather than fight it. The
   width is also on the element itself, so the space is reserved before the
   file arrives. */
.asset-thumb {
  display: block;
  width: 120px;
  max-width: 100%;
  height: auto;
  margin: .2rem 0 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.asset-thumb.is-wide { width: 240px; }

/* .numbered-list gets its first use on the press kit. Its h3 defaults to
   --step-1, which beside a 2.25rem counter reads as a section heading rather
   than a list item. */
.numbered-list h3 { font-size: var(--step-0); margin-bottom: .25rem; }

/* .callout h3 carries a top margin for a heading that follows a paragraph,
   which is the landing page's only use of it. On the press kit a callout can
   open with its heading, where that margin is just dead space. */
.callout h3:first-child { margin-top: 0; }

/* --------------------------------------------------------------------------
   14. Print — the handout view
   The source document's own instruction is "Make copies of this document."
   -------------------------------------------------------------------------- */

@media print {
  :root {
    --bg: #fff;
    --bg-alt: #fff;
    --surface: #fff;
    --ink: #000;
    --ink-muted: #333;
    --accent: #000;
    --line: #999;
    --line-strong: #666;
    --flag-bg: #fff;
    --flag-ink: #000;
    --on-accent: #000;
    --focus-ring: #000;
    --on-dark-link: #000;
    --on-dark-hover: #000;
    --field-border: #666;
    --header-bg: #fff;
    --header-ink: #000;
    --header-muted: #333;
    --shadow: none;
    --shadow-lift: none;
  }

  @page { margin: 14mm; }

  html { scroll-behavior: auto; }

  body {
    background: #fff;
    color: #000;
    font-size: 10.5pt;
    line-height: 1.45;
  }

  /* Drop the furniture. */
  .site-header,
  .skip-link,
  .hero-actions,
  .nav-wrap,
  .copy,
  .btn,
  .filter-bar,
  .share-row,
  .widget-fields,
  .widget-actions,
  .toast,
  .js-only {
    display: none !important;
  }

  .print-only { display: block; }

  .section, .hero { padding-block: 0; margin-bottom: 8mm; }
  .wrap { width: 100%; }

  h1 { font-size: 22pt; }
  h2 {
    font-size: 14pt;
    border-bottom: 1.5pt solid #000;
    padding-bottom: 2mm;
    margin-top: 6mm;
  }
  h3 { font-size: 11.5pt; }
  h4 { font-size: 10pt; }

  a { color: #000; text-decoration: underline; }

  /* Print the destination of external links; internal anchors stay bare.
     No ::after reset is needed above any more: the screen arrow that this
     used to cancel has been removed, so nothing generates content here
     except the rules below. */
  .resource-list a[href^="http"]::after,
  .link-list a[href^="http"]::after,
  .numbered-list a[href^="http"]::after,
  .directory-foot a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    font-family: var(--font-mono);
    word-break: break-all;
  }
  .paper-list a[href^="http"]::after { content: ""; }

  /* Each news story already prints its own .url line, so the generic
     resource-list rule above would print every address a second time. */
  .news-list a[href^="http"]::after { content: ""; }
  .news-list li.is-featured { border-left-width: 1pt; }

  /* Never split a contact or a card across a page. */
  .card,
  .panel,
  .person,
  .directory,
  .resource-list li,
  .paper-list li,
  .book-list li,
  .numbered-list li,
  .widget,
  .callout,
  .sign {
    break-inside: avoid;
    page-break-inside: avoid;
    box-shadow: none;
  }

  h2, h3 { break-after: avoid; page-break-after: avoid; }

  .card-list.cols-2,
  .card-list.cols-3,
  .numbered-list,
  .book-list { grid-template-columns: 1fr 1fr; }

  .grid-3 { grid-template-columns: 1fr 1fr 1fr; }
  .paper-list { grid-template-columns: 1fr 1fr; }
  .resource-list, .resource-list.cols-3 { grid-template-columns: 1fr 1fr; }

  .card, .panel, .resource-list li, .paper-list li, .book-list li, .numbered-list li {
    border: .5pt solid #999;
    padding: 2mm 3mm;
  }

  /* Do not rely on a painted circle: browsers default background graphics off. */
  .numbered-list li::before {
    background: none;
    color: #000;
    border: 1pt solid #000;
    width: 7mm;
    height: 7mm;
  }

  .speech { font-size: 12pt; }
  .sign-face { border: 2pt solid #000; aspect-ratio: 3 / 2; font-size: 16pt; }

  .disclaimer {
    border: 1pt solid #000;
    border-radius: 0;
    font-weight: 700;
  }

  .section-contact { color: #000; }
  .section-contact h2, .section-contact .lede, .section-contact .hero-note { color: #000; }

  /* The "My notes" writing area — print only. */
  /* The send buttons are hidden in print, so surface their addresses instead. */
  .print-addresses { display: block !important; }

  .note-lines { display: block; margin-top: 4mm; }
  .note-lines span {
    display: block;
    border-bottom: .5pt solid #666;
    height: 9mm;
  }

  .site-footer { border-top: 1.5pt solid #000; margin-top: 6mm; }
  .make-copies { font-size: 12pt; font-weight: 700; }

  /* Each Signal card prints its invite address, because the Join button is
     dropped on paper. A signal.group link is one unbroken token of about 100
     characters, and left alone it sets the min-content width of its grid
     column: the Announcements card grew to fill the row and pushed the
     community chat card off the page, so a printed handout could not be
     used to join the chat. An address that is meant to be typed can break
     anywhere. */
  .card .print-only.url {
    font-family: var(--font-mono);
    font-size: 8pt;
    word-break: break-all;
    overflow-wrap: anywhere;
  }

  /* FAQ on paper: every question with its answer, no chevrons, and the
     addresses of the outside links spelled out. Answers are short, so each
     item is kept whole on one page. */
  .faq-item {
    border: .5pt solid #999;
    box-shadow: none;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .faq-item > summary { padding: 2mm 3mm 1mm; min-height: 0; }
  .faq-item > summary::after { display: none; }
  .faq-answer { padding: 0 3mm 2mm; max-width: none; }

  /* The FAQ ships with every <details> open (see the comment above #faq in
     index.html), which is what makes the printout work in old browsers. This
     rule covers the reader who folded an answer away before printing: the UA
     hides a closed <details> body through ::details-content with
     content-visibility: hidden, and an author rule outranks a UA rule, so
     current browsers (Chrome/Edge 131+, Firefox 143+, Safari 18.4+) unfold
     it on paper without touching the [open] state on screen. Kept as its own
     rule: an engine that does not know the pseudo-element drops only this
     rule, and only an answer that reader closed by hand prints without its
     text. */
  .faq-item::details-content {
    content-visibility: visible;
    display: block;
  }
  .faq-answer a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    font-family: var(--font-mono);
    word-break: break-all;
  }

  /* Press kit. An asset preview is decoration in a printed handout, and the
     download line under each one already carries the filename as text. */
  .asset-thumb { display: none; }
  .pull { border-left: 1.5pt solid #000; padding-left: 2.5mm; font-size: 11pt; }
  .widget-stacked { margin-top: 4mm; }
}

/* --------------------------------------------------------------------------
   15. News story page
   Five hooks news.html needs. Everything else on that page — the hero, the
   callout, the pull quote, the share row, the Sources list — is built from
   the classes above, and the Sources list is literally the landing page's
   news list with the copy buttons taken out.
   -------------------------------------------------------------------------- */

/* Dateline and byline. .role-tag and .url are the two classes the News list
   uses for a source name and a date, so a story page is set in the same type
   as the link that led to it -- but .url is scoped to .resource-list and
   .paper-list, which own every other use of it, so it needs re-stating here
   rather than being unscoped in place. */
.article-dateline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .3rem .9rem;
  margin-bottom: .2rem;
}
.article-dateline .url {
  margin: 0;
  font-size: .78rem;
  color: var(--ink-muted);
  font-family: var(--font-mono);
  word-break: break-word;
}

/* The story itself. Nothing else on the site runs more than a paragraph at a
   time, so this is the only place a reading measure is needed: 68ch matches
   .section-intro, which is the longest running text the landing page has. */
.article-body {
  max-width: 68ch;
  margin-top: 1.6rem;
  font-size: var(--step-0);
}
.article-body > p { margin-bottom: 1.1em; }

/* A subhead inside the story is not a section heading. h2 defaults to
   --step-3, which beside body copy reads as a second page title. */
.article-body h2 {
  font-size: var(--step-1);
  margin-top: 2.2rem;
  margin-bottom: .5rem;
}
.article-body h3 { font-size: var(--step-0); margin-top: 1.6rem; margin-bottom: .4rem; }

/* .pull and .callout were both authored for a grid that supplies their
   spacing. Standing alone in a column of prose they need their own. */
.article-body .card { margin: var(--gap) 0; }
.article-body .card .note {
  margin: .7rem 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
}
.article-body .callout { margin-bottom: var(--gap); }

/* A photograph or a document scan. The UA stylesheet indents a figure by
   40px, which strands it out of the text column. */
.article-figure {
  margin: var(--gap) 0;
}
.article-figure img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.article-figure figcaption {
  margin-top: .55rem;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-muted);
}

/* An interview recording. The caption sits above the control rather than
   below it so a screen reader reaches "who is speaking" before it reaches a
   play button, and <audio> is given a full-width box because its intrinsic
   width is UA-dependent and overflows a narrow phone in some of them. */
.article-audio {
  margin: var(--gap) 0;
}
.article-audio figcaption {
  margin-bottom: .55rem;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-muted);
}
.article-audio audio {
  display: block;
  width: 100%;
  max-width: 100%;
}
.article-audio .note {
  margin: .6rem 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
}

.article-back {
  font-weight: 600;
  margin-bottom: 1.2rem;
}

@media print {
  /* The measure is a screen concern; on paper the page box is the measure. */
  .article-body { max-width: none; }
  .article-body h2 { font-size: 12pt; }
  .article-dateline { display: block; }
  .article-dateline .url { font-size: 8.5pt; }

  /* A player cannot be printed. The download line under it carries the file
     name as text, so the recording is still findable on paper. */
  .article-audio audio { display: none; }

  .article-figure,
  .article-audio { break-inside: avoid; page-break-inside: avoid; }

  /* The story is the point of the printout; the back link is not. */
  .article-back { display: none; }
}
