/* ==========================================================================
   /almost — campaign poll stylesheet
   --------------------------------------------------------------------------
   A deliberate SUBSET of the main site's design system (website/assets/css/
   site.css, itself a translation of STYLING_GUIDE.md and the app's theme).
   Only the tokens this one page uses are carried over, so the file stays
   readable rather than inheriting a stylesheet built for fifteen documents.

   Rules carried over from the app, unchanged:
     - Only Inter, weights 400 / 500 / 600. NEVER 700+.
     - Brand primary #A3124F ("wine pink"), secondary #BA7287.
     - Warm off-white background #FAF7F9; white cards; 8pt-based spacing.
     - Pill buttons (radius 999), SemiBold labels.
     - No emojis anywhere.

   MOBILE-FIRST IS AN OWNER RULING (8), NOT A PREFERENCE. Every rule below is
   written for a phone first; the only media query widens things for larger
   screens. The seventeen-option picker is the load-bearing case — it has to be
   reachable with one thumb, which is why the options are a two-column grid of
   large targets rather than a list of text links.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Self-hosted fonts
   --------------------------------------------------------------------------
   Copied from website/assets/fonts/ — the same woff2 files the main site
   serves, converted from the exact TTFs the mobile app loads, so glyph
   rendering matches the app. Self-hosting keeps the font off a third-party
   CDN; this origin already has to allow Google script hosts for App Check, and
   there is no reason to widen that to fonts as well.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Inter-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/Inter-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/Inter-SemiBold.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */
:root {
  --color-primary: #A3124F;
  --color-primary-dark: #8A0F43;
  --color-secondary: #BA7287;

  --color-bg: #FAF7F9;
  --color-card: #FFFFFF;
  --color-bg-elevated: #F3EFF1;

  --color-text: #2C2C2E;
  --color-text-secondary: #6E6E73;
  --color-text-tertiary: rgba(28, 28, 30, 0.4);

  /* ⛔ SECONDARY TEXT IS NOT ACCESSIBLE ON THE ELEVATED SURFACE.
     #6E6E73 measures 4.77:1 on the page background but only **4.45:1** on
     #F3EFF1 — under the 4.5:1 that WCAG 2.2 SC 1.4.3 requires. The inactive
     toggle label sits on exactly that surface, and the browser gate caught it
     only once the contrast check covered every text element rather than the
     disclosure alone. This is the same family, two steps darker: 4.72:1. */
  --color-text-on-elevated: #6A6A6F;

  --color-border: rgba(0, 0, 0, 0.10);
  --color-divider: rgba(0, 0, 0, 0.08);

  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 20px;
  --space-xxl: 24px;
  --space-xxxl: 32px;

  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-full: 999px;

  --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.07);

  --content-narrow: 640px;
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* ⛔ `hidden` MUST ACTUALLY HIDE (found by the browser render check).
   The UA stylesheet's `[hidden] { display: none }` is a single attribute
   selector, so ANY class rule that sets `display` outranks it — `.cta` sets
   `display: inline-block`, which left `el.retry.hidden = true` visually inert:
   the retry button stayed on screen for a failure that cannot be retried.
   A global override is the fix, because the next element given `hidden` would
   hit the same trap; `!important` is deliberate and is the narrow exception. */
[hidden] { display: none !important; }

/* ⛔ HIDDEN FROM EYES, NOT FROM THE ACCESSIBILITY TREE (audit W29-1).
   The status announcer has to stay in the tree so it can RECEIVE an update —
   `display: none` or `visibility: hidden` would remove it and the announcement
   would never happen. The clip technique keeps it exposed and unreadable. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-weight: 400;
  line-height: 1.5;
  /* The poll is one screen of content; keep it off the very edge on notched
     phones without needing a wrapper element. */
  padding: max(var(--space-xxl), env(safe-area-inset-top))
           max(var(--space-xl), env(safe-area-inset-right))
           max(var(--space-xxl), env(safe-area-inset-bottom))
           max(var(--space-xl), env(safe-area-inset-left));
}

.wrap {
  width: 100%;
  max-width: var(--content-narrow);
  margin: 0 auto;
}

/* --------------------------------------------------------------------------
   4. Steps
   --------------------------------------------------------------------------
   One page, several states. Only one section is present at a time; the others
   are removed from the accessibility tree rather than merely hidden visually,
   so a screen reader never reaches the picker after the vote is cast.
   -------------------------------------------------------------------------- */
.step { display: none; }
.step--active { display: block; }

/* --------------------------------------------------------------------------
   5. The question
   -------------------------------------------------------------------------- */
.eyebrow {
  margin: 0 0 var(--space-lg);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-primary);
}

.question {
  margin: 0 0 var(--space-md);
  font-size: 1.75rem;
  font-weight: 600;      /* SemiBold — the heaviest weight the system allows */
  line-height: 1.25;
}

.lede {
  margin: 0 0 var(--space-xxl);
  color: var(--color-text-secondary);
}

/* --------------------------------------------------------------------------
   6. The picker
   --------------------------------------------------------------------------
   Two columns on a phone. Each target is a full-height pill with a 48px
   minimum — comfortably above the 44px touch minimum, since these are the only
   interactive elements on the screen and mis-taps cost a vote that cannot be
   corrected by the visitor.
   -------------------------------------------------------------------------- */
.options {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-md);
  margin-bottom: var(--space-xxl);
}

.option {
  min-height: 52px;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-card);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  box-shadow: var(--shadow-card);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* "Something else" is the ruled non-text escape. It spans both columns so it
   reads as the bucket it is rather than as the seventeenth activity. */
.option--escape { grid-column: 1 / -1; }

.option:hover {
  border-color: var(--color-secondary);
  color: var(--color-primary);
}

.option:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.option:active,
.option[aria-pressed="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #FFFFFF;
}

.option[disabled] { cursor: default; opacity: 0.55; }

/* --------------------------------------------------------------------------
   7. Fine print
   -------------------------------------------------------------------------- */
/* ⛔ SECONDARY, NOT TERTIARY (audit W18-4). This paragraph carries the reCAPTCHA
   disclosure and the rate-limit statement — required text, not decoration.
   `--color-text-tertiary` is rgba(28,28,30,0.4), which composites to #A19FA1 on
   this background: a measured **2.47:1**, well under the 4.5:1 that WCAG 2.2
   SC 1.4.3 requires for normal-sized text. `--color-text-secondary` (#6E6E73)
   measures 4.77:1 and is the narrowest fix that uses an existing token.
   The browser gate asserts the COMPUTED ratio, so this cannot silently regress. */
.fineprint {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--color-text-secondary);
}

/* --------------------------------------------------------------------------
   8. Sending
   -------------------------------------------------------------------------- */
.sending {
  margin: var(--space-xxxl) 0;
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--color-text-secondary);
}

.dots::after {
  content: "";
  animation: dots 1.2s steps(4, end) infinite;
}

@keyframes dots {
  0%   { content: ""; }
  25%  { content: "."; }
  50%  { content: ".."; }
  75%  { content: "..."; }
}

@media (prefers-reduced-motion: reduce) {
  .dots::after { animation: none; content: "..."; }
  .bar__fill { transition: none !important; }
}

/* --------------------------------------------------------------------------
   9. Acknowledgement
   -------------------------------------------------------------------------- */
.ack {
  margin: 0 0 var(--space-sm);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.3;
}

.ack-line {
  margin: 0 0 var(--space-xxxl);
  color: var(--color-text-secondary);
}

/* --------------------------------------------------------------------------
   10. The growing stack
   -------------------------------------------------------------------------- */
.stack {
  padding: var(--space-xl);
  border-radius: var(--radius-lg);
  background: var(--color-card);
  box-shadow: var(--shadow-card);
}

.stack__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.stack__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}

.toggle {
  display: inline-flex;
  padding: 3px;
  border-radius: var(--radius-full);
  background: var(--color-bg-elevated);
}

.toggle__btn {
  padding: var(--space-sm) var(--space-lg);
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-text-on-elevated);
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
}

.toggle__btn--on {
  background: var(--color-card);
  color: var(--color-text);
  box-shadow: var(--shadow-card);
}

.toggle__btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Bars ---------------------------------------------------------------------
   A count and a proportional bar. The bar is decorative — every figure is also
   present as text, so nothing depends on reading a length.
   -------------------------------------------------------------------------- */
.bars {
  margin: 0;
  padding: 0;
  list-style: none;
}

.bar { margin-bottom: var(--space-lg); }
.bar:last-child { margin-bottom: 0; }

.bar__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-xs);
  font-size: 0.875rem;
}

.bar__name { font-weight: 500; }

.bar__count {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}

.bar__track {
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--color-bg-elevated);
  overflow: hidden;
}

.bar__fill {
  height: 100%;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  transition: width 0.5s ease;
}

.bar--mine .bar__fill { background: var(--color-primary); }
.bar--other .bar__fill { background: var(--color-secondary); }

/* --------------------------------------------------------------------------
   10b. The manual refresh (design §8.5)

   The only visitor-driven read. Deliberately quiet: it sits under the total as
   a secondary control, because the common case is that the figures arrived on
   load and nobody needs it. `:disabled` is the in-flight state — the button
   stays in the tab order and keeps its label, so a screen-reader user is told
   it is unavailable rather than finding it gone.
   -------------------------------------------------------------------------- */
.refresh {
  display: block;
  margin: var(--space-lg) auto 0;
  padding: var(--space-sm) var(--space-lg);
  border: 0;
  border-radius: var(--radius-full);
  background: var(--color-bg-elevated);
  color: var(--color-text-on-elevated);
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
}

.refresh:disabled {
  opacity: 0.55;
  cursor: default;
}

.refresh-status {
  margin: var(--space-sm) 0 0;
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  text-align: center;
}

.refresh:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   11. The total
   -------------------------------------------------------------------------- */
.total {
  margin: var(--space-xxl) 0 0;
  font-size: 1.125rem;
  font-weight: 500;
  text-align: center;
}

.total strong {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}

/* --------------------------------------------------------------------------
   12. The transition to INTNT
   -------------------------------------------------------------------------- */
.outro {
  margin-top: var(--space-xxxl);
  padding-top: var(--space-xxxl);
  border-top: 1px solid var(--color-divider);
  text-align: center;
}

.outro__body {
  margin: 0 0 var(--space-xl);
  color: var(--color-text-secondary);
}

.outro__line {
  margin: 0 0 var(--space-xl);
  font-size: 1.1875rem;
  font-weight: 600;
  line-height: 1.35;
}

.cta {
  display: inline-block;
  min-height: 50px;
  padding: var(--space-md) var(--space-xxxl);
  border: 0;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: #FFFFFF;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 600;
  line-height: 26px;
  text-decoration: none;
  cursor: pointer;
}

.cta:hover { background: var(--color-primary-dark); }

.cta:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}

.cta--button { margin-top: var(--space-lg); }

/* --------------------------------------------------------------------------
   13. Wider screens
   --------------------------------------------------------------------------
   The page is designed for a phone. On a larger viewport it stays a single
   narrow column — the content does not become more useful when stretched — and
   only gains a little breathing room and a third picker column.
   -------------------------------------------------------------------------- */
@media (min-width: 600px) {
  body { padding: var(--space-xxxl) var(--space-xxl); }

  .question { font-size: 2.25rem; }

  .options { grid-template-columns: repeat(3, 1fr); }

  .ack { font-size: 1.75rem; }
}

/* --------------------------------------------------------------------------
   14. Dark mode
   --------------------------------------------------------------------------
   The app and the main site are light-only, so the poll follows them rather
   than inventing a second palette. Declared explicitly so a device in dark mode
   does not get a browser-invented rendering of an unspecified surface.
   -------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root { color-scheme: light; }
}
