/* =============================================================================
 * citizen-app.css -- the citizen application's stylesheet, and its ONLY copy.
 *
 * WHERE THIS CAME FROM. Every rule below was inline in index.html until
 * 2026-08-13, in one <style> block of 107,393 bytes that every visitor
 * re-downloaded on every request and on every deploy, because a <style> block
 * cannot be cached. It sat in the <head>, so the parser had to read all of it
 * before it reached <body> and the static hero -- the page's own LCP candidate,
 * which the 2026-08-12 batch had just gone to some trouble to put in the markup.
 *
 * THIS FILE IS THE SOURCE. index.html still carries a small inline <style>, but
 * that block is GENERATED from this file by scripts/build-critical-css.js and
 * must never be hand-edited; it is a comment-stripped SUBSET, emitted in this
 * file's own order, and this file is linked immediately after it. Edit rules
 * here and re-run the generator.
 *
 * WHY A SUBSET RATHER THAN A SPLIT, and this is the part worth reading. The
 * first attempt MOVED rules instead of copying them: the critical ones stayed
 * inline, the rest went to a second file. That reorders the cascade, because a
 * moved rule that used to sit AFTER a kept rule now sits before it. It is not a
 * theoretical risk -- the parity run measured 4,800 computed-style differences,
 * and the cause was ordinary stylesheet history: `.path-card` is declared three
 * times here at three different depths, `.path-desc` and `.path-time` likewise,
 * and the split inverted which declaration won. Mobile padding lost to a
 * desktop base rule, a 15.5px description rendered at 13px.
 *
 * Emitting a SUBSET and then loading this whole file after it cannot do that.
 * Whatever the generated block says, every rule here is declared again,
 * afterwards, in its original order -- so the final cascade is byte-for-byte the
 * cascade this file describes, and the inline block can only ever affect what
 * paints in the window BEFORE this file arrives. That window is the entire
 * point of it, and an imprecise subset costs a slightly worse early paint
 * rather than a wrong page. scripts/citizen-css-parity-check.js is what proves
 * it: zero computed-style differences across every citizen surface, two
 * viewports, both languages.
 *
 * THE COST, MEASURED RATHER THAN ESTIMATED. gzip -9 on the committed files,
 * rounded to the nearest 100 bytes -- deliberately, because a content-hash
 * stamp rewrite moves the exact figure by a byte or two and a number that
 * precise would be false by the next commit:
 *
 *   index.html        181,200 -> 91,000 raw     (49,300 -> 28,900 gzip)
 *   citizen-app.css   new, 111,900 raw          (29,500 gzip), frozen for a year
 *
 * The critical rules therefore exist twice, and a FIRST-time visitor downloads
 * roughly 9,200 gzipped bytes more than before. Every visit after the first,
 * and every in-page navigation, pays roughly 20,400 gzipped bytes LESS, because
 * an inline block is re-sent on every single request and this file is not.
 *
 * That trade is paid for several times over in the same change: supabase-js
 * left the landing page's script chain, which removes 51,200 gzipped bytes from
 * the first visit as well as the repeat one. Net, a first visit is about 42 KB
 * gzipped lighter, not heavier.
 *
 * EDITING. Ordinary source file, edit directly, then run:
 *     node scripts/build-critical-css.js        (rewrites index.html's block)
 *     node scripts/stamp-assets.js              (re-stamps the ?v= references)
 * `build-critical-css.js --check` fails CI if the generated block has drifted.
 * ============================================================================= */


*{box-sizing:border-box;margin:0;padding:0}
:root{
  /* A498 typography: body copy reads in near-black, not tinted indigo. */
  --ink:#1a1d2e;
  --bg:#f4f6f9;--s1:#ffffff;--s2:#eef0f5;--s3:#e6e8ee;
  --b1:#e2e5ed;--b2:#d0d4df;--b3:#b8bccb;
  --tx:#0c0f1a;--mu:#3d4461;--di:#5f6785; /* A501: was #7b82a0 (3.8:1); text token must clear 4.5:1 */
  --ac:#1b4fff;--ac2:#1347c2;--pu:#6c47ff;
  --gr:#075e3f;--am:#8a5a00;--re:#d63f3f; /* A501: green 4.2->6.3, amber 3.8->5.5 as text */
  --ripple-rings-travel:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'><circle cx='200' cy='200' r='150' fill='none' stroke='rgba(255,255,255,0.9)' stroke-width='5'/></svg>");
  --ripple-rings-travel-ink:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'><circle cx='200' cy='200' r='150' fill='none' stroke='rgba(27,79,255,0.75)' stroke-width='5'/></svg>");
  --ripple-rings:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'><g fill='none' stroke='rgba(255,255,255,0.10)' stroke-width='1.5'><circle cx='200' cy='200' r='60'/><circle cx='200' cy='200' r='110'/><circle cx='200' cy='200' r='165'/><circle cx='200' cy='200' r='225' stroke-dasharray='2 8'/></g></svg>");
  --civic:#0f2057;--civic-h:#1a2f73;--pulse:#ea580c;
  --sf:'Instrument Serif',Georgia,serif;--ss:'DM Sans',system-ui,sans-serif;
  --r0:6px;--r1:8px;--r2:14px;--r3:20px;--r4:28px;--rp:999px;
  --t1:all .15s ease;--t2:all .25s ease;
}
body{background:var(--bg);color:var(--tx);font-family:var(--ss);min-height:100vh;font-size:16px;line-height:1.65;-webkit-font-smoothing:antialiased;overflow-x:hidden}
body.acta-has-classroom-bar{padding-bottom:62px}

/* ── THE MASTHEAD (brand identity pass, 2026-08-17) ──────────────────────────
   One navy band, everywhere the Acta brand speaks: this file styles the SPA
   shell; marketing-shell.css and the inline-CSS legal pages carry the same
   treatment. The contract lives in docs/design/component-spec.md ("The
   masthead") -- read it before re-deciding any of this. The decisions:
   - The bar is var(--civic), the same surface as the hero, so on the home
     screen the header and the hero read as ONE navy field with no seam. The
     background-image is the hero's own top wash (rgba(27,79,255,.14) fading
     over 55% of its height) extrapolated up through the bar's 60px, so the
     join carries no step at all. On light interior screens the navy band IS
     the deliberate seam.
   - Everything in the bar is WHITE ink at ONE stroke weight (1.5px): the
     ring mark, the hamburger lines, the toggle border. The mark draws with
     currentColor, so it takes the ink of whatever surface it sits on.
   - Layout is flex: the lockup left, margin-right:auto on it pushes the
     utility cluster (desktop links, language toggle, menu) to the right.
     The language toggle is a utility, not a peer of the wordmark; its old
     centred grid column is retired deliberately. */
nav{position:sticky;top:0;z-index:200;background-color:var(--civic);background-image:linear-gradient(rgba(27,79,255,.16),rgba(27,79,255,.135));display:flex;align-items:center;column-gap:14px;height:60px;padding:0 28px;--focus-ring:#fff}
@media(max-width:480px){nav{padding:0 16px}}
.logo{display:inline-flex;align-items:center;gap:9px;color:#fff;text-decoration:none;margin-right:auto;min-width:0;max-width:100%;opacity:.86;transition:opacity .15s ease}
.logo-mark{width:30px;height:30px;flex-shrink:0;color:#fff;opacity:.92;transition:opacity .15s ease}
/* The wordmark is a LOCKED ASSET (recut 2026-08-17, header pass 5; canvas
 * margin fixed 2026-08-18): "Acta Civic" outlined from DM SANS into one SVG
 * path (viewBox 479.5x76.7 -- see below), cap height still 70 units,
 * rendered at 15.3px tall so the cap height itself still measures 14px --
 * cap height judged on real 390/1366 renders in both languages against the
 * 30px mark and the 14px/600 nav links, and unchanged by the margin fix.
 * CANVAS MARGIN (2026-08-18): the viewBox shipped flush against the glyph
 * ink on every side (0 margin -- verified by parsing every subpath, the
 * path's own y-bounds were EXACTLY 0/73.7, matching the old viewBox with
 * zero tolerance). Zero-margin is fragile: it leaves no room for a
 * rendering engine's own anti-aliasing/rounding at the boundary to clip
 * nothing while a different engine's rounding clips a sliver of a round
 * letter's baseline overshoot (the "c"/"a"/"C" terminals -- "Acta Civic" has
 * no actual descender letter). The canvas now grows 3 viewBox units
 * downward ONLY (viewBox min-x/min-y unchanged at 0/0, so the baseline does
 * not move); width/height are recomputed to hold the exact px-per-unit
 * scale the 14.7px/14px cap height was approved at, so only `height` moves
 * (14.7 -> 15.3px) and the optical size in the bar is unchanged. Generated
 * by scripts/build-wordmark.js from scripts/_lib/wordmark-asset.js -- see
 * that module for the full geometry writeup and scripts/build-wordmark.js
 * --check to verify no page has drifted from it.
 * Locked (unchanged since pass 3): live text wraps, reflows on the
 * font-load race, and every fix was another per-breakpoint font-size; an
 * outline cannot wrap and renders identically everywhere.
 * SANS, and the serif question is CLOSED: pass 4 argued that a sans
 * wordmark borrows the navigation's voice and set the name in Instrument
 * Serif. Miguel's call reversed it -- he prefers the sans, and the
 * decision is his. Do not re-litigate it; the argument has now been made
 * and lost once, and re-making it costs a round trip.
 * TWO WEIGHTS, ONE INK, ONE SIZE, and this is the part that actually
 * solves the problem pass 3 had. In a single weight, "Acta" and "Civic"
 * carried identically, so the eye had nothing to land on and the lockup
 * read as one flat label rather than a name with a descriptor beside it.
 * Acta is 700 and Civic is 400: the name dominates by WEIGHT alone, which
 * is the standard typographic way to set a name against a descriptor, and
 * it costs nothing else -- both words stay the same size, the same white,
 * on the same baseline.
 * WHY NOT TONE, measured rather than asserted: the alternative was both
 * words at 700 with "Civic" at ~62% ink. On the real bar at 390 that lands
 * "Civic" at almost exactly the ink of the INACTIVE language toggle (72%
 * white), so half the brand name reads as a disabled control. Rejected on
 * the render, not on principle.
 * WHY NOT A SIZE STEP: it works, but subordinating "Civic" by size is the
 * same family as the 34/14 "crumb" lockup already rejected in pass 2, and
 * re-opens a settled question.
 * Weight and size bake into the OUTLINE, so two weights are still ONE path
 * in ONE colour -- the "one locked asset, one ink" rule survives intact,
 * and component-spec-guard still pins a single currentColor path.
 * The display name is still exactly "Acta Civic": the .logo aria-label
 * carries it for screen readers.
 * Generation: fonts.gstatic DM Sans v17 wght 700 ("Acta") + wght 400
 * ("Civic"), opentype.js getPath with kerning on a shared baseline, the
 * two subpaths concatenated into one `d`, normalized to a zero-origin
 * viewBox (see component-spec.md).
 * THE WHOLE LOCKUP RESPONDS AS ONE OBJECT (2026-08-17). It is a single link
 * to the home page, so hovering the name must do what hovering the mark
 * does -- previously only the mark brightened, which told the reader the
 * ring was the button and the name was decoration. Now `.logo` itself sits
 * at 86% and goes to 100% on hover and on keyboard focus, carrying mark and
 * wordmark together.
 * The mark keeps its own further step down (.92 OF the container, ~79%
 * effective, so unchanged from the 80% it had) purely so icon and label
 * still separate in tone. That nesting is why both rules exist rather than
 * one: the outer rule is the interaction, the inner one is the hierarchy.
 * Still one object per rule -- the per-ring opacity ramp the spec bans is a
 * different (and banned) thing.
 * REJECTED: a background wash behind the lockup on hover. It reads as a
 * button chip and would be the only filled object on a bar this recut
 * deliberately stripped of fills (see the toggle note below). */
.logo-word{display:block;height:15.3px;width:95.6px;flex-shrink:0}
/* A614, MEASURED 2026-08-21, WITH THE FIFTH DESTINATION (Acta Pro).
 *
 * THE BAR HAD NO ROOM AND WAS ALREADY SPENDING IT. .logo is min-width:0 inside
 * the nav's flex row while .logo-mark and .logo-word are both flex-shrink:0, so
 * when the row runs out of space the logo BOX shrinks and the artwork inside it
 * does not. Measured on the FOUR-item row, before Acta Pro existed, index.html
 * in Spanish at 861px: the box was 12px wide and the wordmark was drawn 108px
 * THROUGH "Acerca de". English at the same width had 40px of clearance, so
 * every English review of that bar was correct and said nothing -- the
 * brJurLabel shape, a defect invisible in the language people review in.
 *
 * WHERE THE FIVE-ITEM ROW ACTUALLY FITS, measured rather than estimated:
 *   EN index    fits from  861px   (row 619px)
 *   ES marketing fits from 885px   (row 719px)
 *   ES index    fits from  969px   (row 767px -- the longest labels we ship)
 * and with the FULL wordmark beside it, ES index needs 1074px. Below 969px the
 * row cannot be made to fit by yielding the logo, because the logo box is
 * already at zero: at 861px in Spanish the bar overflows by 78px with nothing
 * left to give, and the language toggle goes off the right edge where
 * body{overflow-x:hidden} silently clips it.
 *
 * SO THE ROW STARTS AT 1024px, not 861px (see the media query further down),
 * and between 1024 and 1079 the wordmark stands down so the mark carries the
 * lockup alone. Below 1024 the hamburger holds every destination including Acta
 * Pro and the full wordmark has room, so it keeps it. The cost is honest and
 * worth naming: an English window between 861 and 1023px used to show the links
 * inline and now shows the hamburger. The alternative was a bar that fits in
 * one language, and the same 861-1023 band is where Spanish has been drawing
 * its own wordmark through its first link all along.
 *
 * overflow:hidden is the belt to that braces: a longer label can squeeze the
 * box again, and a clipped wordmark is a bad look where an overlapping one is
 * a broken page. */
.logo{overflow:hidden}
@media(min-width:1024px) and (max-width:1079px){
body:not(.acta-flow) .logo-word{display:none}
}
.logo:hover,.logo:focus-visible{opacity:1}
.logo:hover .logo-mark,.logo:focus-visible .logo-mark{opacity:1}
/* No bespoke focus outline here: the sitewide [role="button"]:focus-visible
 * ring (2px, --focus-ring, which nav sets to #fff) already covers the logo
 * and wins the cascade -- one ring convention, not two. */
.logo .logo-dot{color:inherit}
/* One ripple outward on load: 800ms, ONCE, then gone. A looping animation in
 * a sticky header reads as a loading state and follows the reader onto every
 * screen, so this never repeats. The ripple circle's own opacity attribute
 * is 0, so before the animation runs, after it ends, and always under
 * prefers-reduced-motion, it simply is not there.
 * The ripple circle shares its base geometry (r=13) with the OUTER ring, not
 * the dot, so its start scale is what actually decides where it appears to
 * originate. Start scale .17 (r≈2.21) was measured to match the dot's own
 * radius (2026-08-17) -- geometrically correct, and reported fixed on that
 * measurement TWICE. Both times it still looked wrong, because the check
 * proved the wrong thing: a CSS transform:scale() on an SVG shape scales
 * its stroke-width too, so at scale .17 the ring's 1.5px stroke rendered at
 * ~0.26px -- sub-pixel, invisible against the dot for the animation's first
 * ~60ms. Scrubbing the animation's own currentTime frame by frame (not
 * measuring radii) showed the ring only becomes visually perceptible once
 * it has grown enough for the scaled stroke to clear roughly 1px, which
 * happens around the INNER ring's own radius -- so the eye watched it start
 * from the second circle exactly as reported, while every geometric proof
 * showed the start radius was already correct. Fixed with
 * vector-effect="non-scaling-stroke" on the ripple circle (index.html and
 * every page's inline copy): the stroke now renders at a constant 1.5px
 * regardless of the shape's own scale, so it is visible from the very first
 * frame, sized correctly, at the dot. End scale (1.08, ~r=14) is unchanged
 * -- still finishes just past the outer ring. */
@keyframes lm-ripple{from{transform:scale(.17);opacity:.85}to{transform:scale(1.08);opacity:0}}
.lm-ripple{transform-box:fill-box;transform-origin:center;animation:lm-ripple .8s ease-out 1}
@media(prefers-reduced-motion:reduce){.lm-ripple{animation:none}}
/* Desktop navigation: four real destinations, visible where there is room to
 * show them. A hamburger where there is space is choosing to hide, which
 * sits badly on a product whose claim is that it shows you everything -- so
 * the hamburger is mobile-only, EXCEPT on the citizen flow screens
 * (body.acta-flow, take-action screens 2-5), where the numbered stepper is
 * the wayfinding and a second visible navigation system would compete with
 * it; there the links yield and the hamburger returns. */
#menu-btn{background:none;border:none;cursor:pointer;padding:8px;display:flex;flex-direction:column;gap:5px;justify-content:center}
.menu-line{display:block;width:22px;height:1.5px;background:#fff;border-radius:2px;transition:all .2s}
.nav-links{display:none}
.nav-links a{color:rgba(255,255,255,.92);font-family:var(--ss);font-size:14px;font-weight:600;text-decoration:none;letter-spacing:.01em;white-space:nowrap}
.nav-links a:hover{color:#fff;text-decoration:underline;text-underline-offset:4px}
/* Grassroots Advocacy carries the three audience pages (For Organizations,
 * For Nonprofits, For Educators) as a drop-down -- the same parent-with-
 * children structure the mobile menu already draws indented. The group
 * stretches to the bar's full 60px so the panel opens flush at the bar's
 * bottom edge with no hover dead-gap; it shows on hover AND focus-within,
 * so keyboard users reach the children by tabbing through the parent. */
.nav-group{position:relative;display:flex;align-items:center;align-self:stretch}
.nav-group>a::after{content:"\25BE";font-size:9px;margin-left:5px;opacity:.7;vertical-align:1px}
.nav-sub{display:none;position:absolute;top:100%;left:50%;transform:translateX(-50%);background:#fff;border:1.5px solid #e8e5dc;border-top:none;border-radius:0 0 10px 10px;box-shadow:0 4px 16px rgba(0,0,0,.08);padding:6px 0;min-width:200px;z-index:1000}
.nav-group:hover .nav-sub,.nav-group:focus-within .nav-sub{display:block}
.nav-sub a{display:block;padding:10px 18px;color:var(--civic);font-weight:500}
.nav-sub a:hover{color:var(--civic);background:#f0ede4;text-decoration:none}
/* 1024px, not 861px, since A614 added the fifth destination. The measurement
 * that moved it is at the .logo rules above: the Spanish row is 767px wide and
 * at 861px the bar overflows by 78px with the logo box already at zero, so
 * there is nothing left to yield. Below this the hamburger carries every
 * destination, Acta Pro included. */
@media(min-width:1024px){
.nav-links{display:flex;align-items:center;gap:22px;align-self:stretch}
#menu-btn{display:none}
body.acta-flow .nav-links{display:none}
body.acta-flow #menu-btn{display:flex}
}
/* Issue chips (see buildIssueChips in app-core.js). Padding lives here, not
 * inline, so desktop can trim it: at >=960px (where the card reaches its
 * full ~797px) the chips read as deliberate rows -- EN five-and-five, ES
 * 4/3/3 (its labels are too long for two fives; see the app-core comment).
 * Below 960px the measured order-table pairing governs and breaks are inert. */
.seed-chip{padding:6px 13px}
.chip-row-break{display:none}
@media(min-width:960px){
.seed-chip{padding:6px 10px}
.chip-row-break{display:block;flex-basis:100%;height:0}
}
.np{font-size:11px;font-weight:600;padding:3px 10px;border-radius:var(--r3);border:1px solid var(--b2);color:var(--mu);cursor:pointer}
.np.lv{border-color:#10b98140;color:var(--gr);background:#10b98112}
.stepbar{display:flex;align-items:center;padding:18px 20px 0;max-width:720px;margin:0 auto}
.st{display:flex;align-items:center;gap:5px;font-size:11px;font-weight:600;color:var(--di);white-space:nowrap}
.st.ac{color:var(--tx)}.st.dn{color:var(--gr)}
.sn{width:20px;height:20px;border-radius:50%;border:1.5px solid currentColor;display:flex;align-items:center;justify-content:center;font-size:11px;flex-shrink:0}
.st.dn .sn{background:var(--gr);border-color:var(--gr);color:#fff}
.st.ac .sn{border-color:var(--ac);color:var(--ac)}
.sl{flex:1;height:1px;background:var(--b2);margin:0 4px;min-width:6px}
.slb{display:none}@media(min-width:480px){.slb{display:inline}}
#app{max-width:900px;margin:0 auto;padding:0 28px 80px;position:relative;z-index:1}
/* NOTE: .hero, .ey, .h1, .hsb were defined here in an earlier wave.
   Canonical definitions now live in the "REDESIGNED HOME SCREEN" block
   below (around line 940). Removing duplicates eliminates cascade confusion. */
.onboard{background:linear-gradient(135deg,#4f8ef710,#9b6df708);border:1px solid var(--b2);border-radius:var(--r2);padding:13px 16px;margin-bottom:13px;box-sizing:border-box;margin-left:-28px;margin-right:-28px;width:calc(100% + 56px);border-radius:0}
.onboard-steps{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.os{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--mu);line-height:1.3}
.os-num{width:18px;height:18px;border-radius:50%;background:var(--ac);color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.os-div{display:none}








.optin{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r2);padding:18px 22px;margin-bottom:16px;box-shadow:0 2px 8px rgba(15,32,87,.04)}
.optin h3{font-family:var(--sf);font-size:19px;margin-bottom:6px;color:var(--civic)}
.optin p{font-size:13px;color:var(--mu);line-height:1.55;margin-bottom:12px}
.optin-row{display:flex;gap:8px;flex-wrap:wrap}
.optin-row input{flex:1;min-width:180px;background:#fff;border:1.5px solid var(--b1);border-radius:var(--r1);padding:10px 13px;color:var(--tx);font-family:var(--ss);font-size:16px;outline:none;transition:border .2s}
.optin-row input:focus{border-color:var(--ac)}
.optin-row input::placeholder{color:var(--di)}
/* ── Take Action brief: the capture card carries no fill ──
   Miguel's decision, 2026-07-30. The Acta Pulse capture card keeps its
   position first in the scroll; only its weight changes, so that
   "See your representatives" is the screen's one filled control.
   Measured before, fixture mirror at 390x844 in both languages: THREE
   filled controls inside the first 844px viewport, the Acta Pulse pill at
   y=137, Alert me at y=344 and See your representatives at y=719. Both
   card buttons were filled, not one, so the decision applies to both.
   Capture behaviour is untouched: same handlers, same ids, same copy. ── */
.optin-btn{background:transparent;color:var(--ac);border:1.5px solid var(--b2);border-radius:var(--r1);padding:10px 18px;font-family:var(--ss);font-size:16px;font-weight:600;cursor:pointer;white-space:nowrap;transition:border-color .15s,color .15s}
.optin-btn:hover{border-color:var(--ac);color:var(--ac2)}
.optin-badge{background:transparent;color:var(--mu);border:1px solid var(--b2);border-radius:var(--r1);padding:5px 11px;font-family:var(--ss);font-size:11px;font-weight:700;cursor:pointer;white-space:nowrap;transition:border-color .15s,color .15s}
.optin-badge:hover{border-color:var(--ac);color:var(--ac)}

/* ── Take Action letters: the name-apply utility stops outranking the send ──
   docs/design/interior-officials-card-hierarchy.md already fixed the card:
   call is step 1, send is step 2, and .btn-mailto is the card's ONE filled
   control. This button sits ABOVE the cards and was also filled var(--ac), so
   the screen carried two. Measured on the fixture mirror at 390x844 in both
   languages: "Apply to all letters" at y=566 and the send primary at y=861,
   295px apart, inside one viewport.
   Filling in your name is a utility, not an action on the letter, so it takes
   secondary weight. It was an inline style, which no stylesheet rule can
   reach, so the class is required rather than preferred; the onclick and the
   label are unchanged. ── */
.oc-name-apply{background:transparent;color:var(--ac);border:1.5px solid var(--b2);border-radius:var(--r1);padding:9px 16px;font-family:var(--ss);font-size:13px;font-weight:600;cursor:pointer;white-space:nowrap;transition:border-color .15s,color .15s}
.oc-name-apply:hover{border-color:var(--ac);color:var(--ac2)}

/* -- the rest of the cross-path navigation, same rule, same weight -- */
.xpath-chip{display:inline-flex;align-items:center;gap:6px;background:transparent;color:var(--ac);border:1.5px solid var(--b2);border-radius:var(--r1);padding:6px 13px;font-size:13px;font-weight:700;text-decoration:none;font-family:var(--ss);transition:border-color .15s,color .15s}
.xpath-chip:hover{border-color:var(--ac);color:var(--ac2)}
.xpath-notify{background:transparent;color:var(--civic);border:1.5px solid var(--b2);border-radius:var(--r1);padding:11px 18px;font-family:var(--ss);font-size:13px;font-weight:600;cursor:pointer;white-space:nowrap;transition:border-color .15s,color .15s}
.xpath-notify:hover{border-color:var(--ac);color:var(--ac)}

/* Bottom-nav forward button, on THESE TWO SCREENS ONLY.
   .bp is shared by every screen's bottom nav, so demoting it globally would
   reach screens 1, 4 and 5, which this pass has not rendered. On screen 4
   "Launch Campaign" is plausibly that screen's OWN primary, which is exactly
   the case the rule protects, so a blanket demotion could remove a fill that
   belongs. Scoped with a modifier and flagged for Miguel rather than assumed.
   ── */
.bp.bp-nav{background:transparent;color:var(--civic);border:1.5px solid var(--b2)}
/* background:transparent is REPEATED here on purpose. .bp:hover (defined
   later, line ~450) sets background:var(--ac); .bp.bp-nav's own non-hover
   background:transparent above has the same specificity (0,2,0) as
   .bp:hover, and the LATER rule wins a tie, so on hover .bp:hover's
   background used to win while THIS rule's color:var(--ac) also applied --
   var(--ac) text on a var(--ac) background, invisible. Restating
   background:transparent here, at (0,3,0), beats the tie outright. */
.bp.bp-nav:hover{background:transparent;border-color:var(--ac);color:var(--ac)}
.optin-note{font-size:11px;color:var(--di);margin-top:8px}
.optin-success{background:#10b98112;border:1.5px solid #10b98135;border-radius:var(--r2);padding:14px 18px;font-size:13px;color:var(--gr);margin-bottom:16px}


.is-row:last-child{margin:0}




@media(max-width:480px){#app{padding:0 16px 80px}.onboard{margin-left:-16px;margin-right:-16px;width:calc(100% + 32px)}}




.officials-loading{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:20px;margin-bottom:10px;text-align:center}
.api-notice{background:var(--s2);border:1px solid #f5a62330;border-radius:var(--r1);padding:10px 13px;font-size:13px;color:var(--am);margin-bottom:13px;line-height:1.5}
.api-notice strong{color:var(--tx)}
.share-link-box{background:linear-gradient(135deg,#4f8ef718,#9b6df712);border:1px solid #4f8ef730;border-radius:var(--r1);padding:14px;margin-bottom:13px}
.slb-lbl{font-size:11px;font-weight:600;letter-spacing:0.14em;text-transform:uppercase;color:var(--mu);margin-bottom:9px;display:flex;align-items:center;gap:6px}
.live-dot{width:7px;height:7px;border-radius:50%;background:var(--gr);flex-shrink:0}
.link-row{display:flex;gap:8px;margin-bottom:8px}
.link-input{flex:1;background:var(--bg);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 11px;font-size:13px;color:var(--mu);font-family:monospace;outline:none;cursor:text;transition:border .2s}
.link-input:focus{border-color:#4f8ef760}
.copy-btn{background:#2563eb;color:#fff;border:2px solid #60a5fa;border-radius:var(--r1);padding:9px 14px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer;white-space:nowrap}
.copy-btn:hover{background:#1d4ed8}
.share-note{font-size:11px;color:var(--di);line-height:1.5}
.zipwarn{background:#f5a62318;border:1px solid #f5a62340;border-radius:var(--r1);padding:9px 12px;font-size:13px;color:var(--am);margin-top:7px;display:none}
.cd{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:18px;margin-bottom:11px}
.lb{font-size:11px;font-weight:600;letter-spacing:0.14em;text-transform:uppercase;color:var(--mu);margin-bottom:9px;display:block}
textarea{width:100%;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:12px;color:var(--tx);font-family:var(--ss);font-size:16px;resize:none;outline:none;transition:border .2s;line-height:1.65;min-height:84px}
textarea:focus{border-color:#4f8ef760}textarea::placeholder{color:var(--di)}
textarea.fl{background:#4f8ef715;border-color:#4f8ef750}
.chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
.chip{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r3);padding:4px 11px;font-size:13px;color:var(--mu);cursor:pointer;transition:all .2s;user-select:none}
.chip:hover{border-color:#4f8ef760;color:var(--ac);background:#4f8ef715}
.csec{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--di);margin:10px 0 5px;display:block;width:100%;padding:5px 9px;background:var(--b1);border-radius:var(--r0)}
input[type=text],input[type=email]{width:100%;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:11px 13px;color:var(--tx);font-family:var(--ss);font-size:16px;outline:none;transition:border .2s}
input[type=text]:focus,input[type=email]:focus{border-color:#4f8ef760}
input[type=text]::placeholder,input[type=email]::placeholder{color:var(--di)}
input[type=text].ziperr{border-color:#f5a62360}
.ba{display:flex;align-items:center;justify-content:center;gap:8px;background:#2563eb;color:#fff;border:3px solid #60a5fa;border-radius:var(--r1);padding:13px 22px;font-family:var(--ss);font-size:16px;font-weight:700;cursor:pointer;width:100%}
.ba:hover{background:#1d4ed8}
/* The secondary escape from the intake. It used to sit BESIDE the primary as a
   bordered peer at flex:1, which made the end of a single task read as a choice
   between two equal actions. It is now a quiet text control centred beneath the
   primary: still one tap away, no longer competing for the same glance. */
.ta-skip{background:none;border:none;padding:6px 4px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);cursor:pointer;text-decoration:underline;text-underline-offset:3px;transition:color .15s}
.ta-skip:hover{color:var(--ac)}
.ta-skip:focus-visible{outline:2px solid var(--focus-ring,#0f2057);outline-offset:2px;border-radius:var(--r0)}
.bp{display:inline-flex;align-items:center;gap:6px;background:var(--civic);color:#fff;border:none;border-radius:var(--r1);padding:12px 22px;font-family:var(--ss);font-size:16px;font-weight:600;cursor:pointer;white-space:nowrap;transition:background .15s}
.bp:hover{background:var(--ac)}
/* Same low-contrast-ghost problem as .back-top, same root cause caught late:
   the first pass fixed the TEXT (var(--mu), 8.83:1) but left the BORDER at
   var(--b2) (1.37:1 against the page background, below WCAG 1.4.11's 3:1
   floor for a UI component boundary) -- none of --b1/--b2/--b3 clear it,
   they are hairline-divider tokens, not button-boundary tokens. Border now
   matches the text color, var(--mu) (8.83:1), same fix as .back-top. */
.bg2{background:transparent;color:var(--mu);border:1.5px solid var(--mu);border-radius:var(--r1);padding:12px 18px;font-family:var(--ss);font-size:16px;font-weight:600;cursor:pointer;transition:all .15s}
.bg2:hover{border-color:var(--ac);color:var(--ac)}
.bsn{background:#059669;color:#fff;border:2px solid #34d399;border-radius:var(--r1);padding:9px 13px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer;white-space:nowrap}
.pg{padding:32px 0 18px}
.tg{display:inline-flex;align-items:center;gap:5px;border-radius:var(--r3);padding:3px 12px;font-size:11px;font-weight:600;letter-spacing:0.02em;margin-bottom:9px}
.tp{background:#9b6df718;color:#5936d9;border:1px solid #9b6df730} /* A501 */
.tbl{background:#4f8ef720;color:var(--ac);border:1px solid #4f8ef730}
.tg2{background:#10b98118;color:#067a58;border:1px solid #10b98130} /* A501: text green darkened to 5.3:1 */
.ta{background:#f5a62318;color:#8a5a00;border:1px solid #f5a62330} /* A501: text amber darkened to 5.9:1 */
.jb{display:inline-flex;align-items:center;gap:4px;border-radius:var(--r0);padding:2px 8px;font-size:11px;font-weight:700;margin-left:8px;vertical-align:middle}
.jl{background:#4f8ef720;color:var(--ac)}.jrg{background:#10b98118;color:var(--gr)}.js{background:#9b6df718;color:var(--pu)}.jf{background:#f5a62318;color:var(--am)}
.h2{font-family:var(--sf);font-size:34px;line-height:1.2;margin-bottom:10px;color:var(--civic)}
.mr{display:flex;gap:14px;flex-wrap:wrap;font-size:13px;color:var(--di);margin-top:12px}
.sc{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r3);padding:24px 28px;margin-bottom:16px;box-shadow:0 2px 8px rgba(15,32,87,.05)}
/* A498: section titles are HEADINGS, not micro-labels. 11px uppercase told
   the reader every section weighed the same, which is precisely what made the
   brief read as underwhelming. */
.stl{font-family:var(--sf);font-size:20px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--tx);margin-bottom:10px}
/* A498: Now / Barrier / Leverage is the most valuable thing Acta produces, so
   it looks like the centrepiece: a framed reading panel, not another card. */
.sc-status{border:1.5px solid #1b4fff30;border-left:4px solid var(--ac);background:linear-gradient(135deg,#4f8ef70a,var(--s1));padding:26px 28px}
.sc-status .stl{font-size:22px}
.sc-status .st-row{display:flex;gap:12px;align-items:flex-start;font-size:16.5px;color:var(--ink);line-height:1.66;max-width:70ch}
.sc-status .st-k{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1px;flex:0 0 78px;padding-top:4px}

.sc p{font-size:16.5px;color:var(--ink);line-height:1.66;max-width:68ch}
.sc ul{list-style:none;display:flex;flex-direction:column;gap:10px}
.sc li{font-size:16px;color:var(--ink);line-height:1.62;padding-left:18px;position:relative;max-width:68ch}
.sc li::before{content:'→';position:absolute;left:0;color:var(--ac);font-size:13px;top:4px;font-weight:600}
/* Policy Options: a real selectable affordance. Was inline border/background
   set only via the ternary at render time and again by pickStance() on click,
   so there was no CSS :hover at all and the option text was not bold -- a row
   of options read as plain body copy with a checkbox, not as tappable choices.
   Bold text plus a real hover state now live in one class; pickStance() only
   toggles .stance-opt-selected (see the JS), so the hover rule below is never
   permanently overridden by an inline style the way it would be if selection
   still wrote row.style.border/background directly. */
.stance-opt{padding:10px 12px;margin-bottom:7px;border:1px solid var(--b2);background:#fff;border-radius:var(--r1);font-size:13px;font-weight:600;color:var(--tx);cursor:pointer;display:flex;align-items:center;gap:9px;transition:border-color .15s,background .15s}
.stance-opt:hover{border-color:var(--ac);background:rgba(27,79,255,.04)}
.stance-opt.stance-opt-selected,.stance-opt.stance-opt-selected:hover{border-color:var(--civic);background:rgba(27,79,255,.06)}
.acts{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:6px}
@media(max-width:480px){.acts{grid-template-columns:1fr}}
@media(max-width:600px){.h2{font-size:28px;line-height:1.2}.sc{padding:20px 22px;margin-bottom:14px;border-radius:var(--r3)}.pg{padding:24px 0 14px}.stl{margin-bottom:12px}}
.act{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r2);padding:14px 16px;display:flex;gap:10px;align-items:flex-start;transition:all .15s}
.act:hover{border-color:var(--ac);background:rgba(27,79,255,.04)}
.ai2{width:24px;height:24px;border-radius:var(--r0);display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0}
.ab{background:#4f8ef720;color:var(--ac)}.ap{background:#9b6df718;color:var(--pu)}.ag{background:#10b98118;color:var(--gr)}.aa{background:#f5a62318;color:var(--am)}
.act p{font-size:16px;color:var(--tx);line-height:1.65;font-weight:600}
.hi{background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:12px;margin-bottom:7px}
.hh{display:flex;align-items:flex-start;gap:7px;margin-bottom:6px;flex-wrap:wrap}
.hy{background:#f8717118;color:var(--re);border:1px solid #f8717130;border-radius:var(--r0);padding:2px 7px;font-size:11px;font-weight:700;white-space:nowrap}
.hy.ps{background:#10b98118;color:var(--gr);border-color:#10b98130}
.hy.pa{background:#f5a62318;color:var(--am);border-color:#f5a62330}
.hn{font-size:13px;font-weight:600}
.hb{font-size:13px;color:#5b6472;line-height:1.6}
.hl{font-size:13px;color:var(--ac);margin-top:5px;padding-top:5px;border-top:1px solid var(--b1);line-height:1.5}
.hl::before{content:'📌 '}
.shrb{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r1);padding:11px 13px;margin:12px 0;display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.shrl{font-size:11px;font-weight:600;color:var(--mu);white-space:nowrap;flex-shrink:0}
.shrbs{display:flex;gap:5px;flex-wrap:wrap;flex:1}
.shrbt{display:flex;align-items:center;gap:4px;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:4px 9px;font-size:13px;font-weight:600;color:var(--tx);cursor:pointer;white-space:nowrap;font-family:var(--ss);transition:all .2s}
.shrbt:hover{border-color:var(--b3);transform:translateY(-1px)}
.si2b{width:15px;height:15px;border-radius:var(--r0);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;flex-shrink:0}
.oc{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:16px;margin-bottom:10px}
/* Batch 34: officials arrive in the order government actually stacks --
   federal, then state, then local, about a beat apart. The content is in the
   DOM immediately and is never gated behind the animation: fill-mode is
   BACKWARDS, so the from-state applies only during the delay and an element
   whose animation never runs (unsupported, disabled, or reduced-motion) is
   simply visible. Nothing here defers rendering, focus, or copy. */
.oc[data-off-lvl]{animation:oc-arrive .42s ease-out backwards}
.oc[data-off-lvl="federal"]{animation-delay:0ms}
.oc[data-off-lvl="state"]{animation-delay:150ms}
.oc[data-off-lvl="local"]{animation-delay:300ms}
@keyframes oc-arrive{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.oc[data-off-lvl]{animation:none}}
/* Progressive disclosure for non-actionable officials: quiet expander,
   default collapsed. Native <details> so no JS state to manage. */
.other-reps{margin-top:8px;border-top:1px dashed var(--b1);padding-top:2px;margin-bottom:10px}
.other-reps>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px;padding:11px 2px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu)}
.other-reps>summary::-webkit-details-marker{display:none}
.other-reps>summary::after{content:'\25B8';font-size:11px;color:var(--di);transition:transform .15s}
.other-reps[open]>summary::after{transform:rotate(90deg)}
.other-reps>summary:hover{color:var(--tx)}
.other-reps .oc{opacity:.93}
.ot{display:flex;gap:11px;align-items:flex-start;margin-bottom:11px}
.av{width:42px;height:42px;border-radius:var(--r1);display:flex;align-items:center;justify-content:center;font-family:var(--sf);font-size:16px;font-weight:700;flex-shrink:0}
.oi h3{font-size:16px;font-weight:600;margin-bottom:2px}
.oi .ott{font-size:13px;color:var(--mu)}
/* A497 art direction: the party chip is a FACT, not a banner. It stays --
   factual, legible -- but recedes to plain small text so the official's NAME
   is what the eye meets. The colored-pill treatment competed with the name. */
.py{font-size:11px;font-weight:600;padding:1px 0;border-radius:0;display:inline-block;margin-top:3px;background:transparent!important;border:none!important;color:var(--mu)!important;letter-spacing:.02em}
.pd{background:#1d4ed820;color:#60a5fa;border:1px solid #1d4ed840}
.pr{background:#7f1d1d20;color:var(--re);border:1px solid #7f1d1d40}
.pi{background:#44403c20;color:#a8a29e;border:1px solid #44403c40}
.cts{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px}
.cc{display:flex;align-items:center;gap:4px;background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:5px 9px;font-size:13px;color:var(--mu);cursor:pointer;text-decoration:none;transition:all .2s}
.cc:hover{border-color:#4f8ef740;color:var(--ac)}
/* Read-and-edit is a way to INSPECT, not a way to act, so it gives up the
   filled-box button affordance and becomes a plain disclosure row. Tertiary
   under step 2. ── */
.dt{width:100%;background:transparent;border:none;border-top:1px solid var(--b1);border-radius:0;padding:8px 2px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);cursor:pointer;text-align:left;display:flex;justify-content:space-between;align-items:center;transition:color .2s}
.dt:hover{color:var(--tx)}
/* The post-send confirmation question. Demoting copy and read-and-edit above
   PROMOTED this by contrast: on the first restyle render it became the second
   most button-like thing in the card, which is a competing action again. It
   drops to the same text weight as the other subordinate elements. Not removed:
   removing it changes which paths reach confirmContact and is part of the
   deferred post-data decision (see the hierarchy doc). ── */
/* ── SPLIT-ZIP DISTRICT PICKER ──
   Found by the real-data artifact pass: ZIP 59301 spans 3 state Senate and 4
   state House districts, so the app shows this screen instead of officials. It
   had NO stylesheet rule at all; every option was inline-styled, which is why
   the markup change below is required rather than preferred.

   The critique from the first render: seven full-width white boxes reading as
   identical peers, with no visible selection affordance and nothing to say that
   TWO separate choices are required, one per chamber. The selected state was
   already in the DOM as aria-checked, just never styled, so the fix is to
   render the state the app already tracks. ── */
.dp-option{display:flex;align-items:center;gap:10px;width:100%;text-align:left;font-family:var(--ss);font-size:16px;font-weight:600;color:var(--tx);padding:12px 16px;border:1.5px solid var(--b2);border-radius:var(--r1);background:var(--s1);cursor:pointer;margin-bottom:8px;transition:border-color .15s,background .15s}
/* The radio affordance the screen never had. A ring, filled when chosen. */
.dp-option::before{content:"";flex:0 0 auto;width:16px;height:16px;border-radius:50%;border:1.5px solid var(--b3);background:transparent;box-shadow:inset 0 0 0 3px var(--s1)}
.dp-option[aria-checked="true"]{border-color:var(--ac);background:#1b4fff08;font-weight:600}
.dp-option[aria-checked="true"]::before{border-color:var(--ac);background:var(--ac)}
.dp-option:hover{border-color:var(--b3)}
.dp-option[aria-checked="true"]:hover{border-color:var(--ac)}
/* The address route is an ALTERNATIVE to picking, not a peer of it, so its
   submit is outlined rather than a second filled blue button. At rest it is
   hidden inside the disclosure; opening that panel is what used to put two
   filled primaries on screen at once. ── */
.dp-addr-submit{margin-top:8px;background:transparent;color:var(--ac);border:1.5px solid var(--ac);border-radius:var(--r1);padding:8px 16px;font-family:var(--ss);font-size:13px;font-weight:600;cursor:pointer}
.dp-addr-submit:hover{background:#0f20570e}
.oc-confirm{margin-top:8px;padding-top:8px;border-top:1px solid var(--b1);font-size:13px;color:var(--di)}
.oc-confirm-btn{background:none;border:none;padding:0 0 0 4px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);cursor:pointer;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.oc-confirm-btn:hover{color:var(--tx)}
.dt:hover{background:#4f8ef718;border-color:#4f8ef740}
/* A495 (2026-08-15): the letter is the artifact this screen exists to produce,
   so it is OPEN. It used to be display:none behind a faint grey "Read and edit
   the letter first" toggle, which meant a visitor could open the send chooser
   and complete a send having never seen what Acta wrote. The .dw.op modifier
   that the removed toggle used is gone with it; docs/screen-contracts.json SC1
   moves from held to met and now blocks a regression instead of recording one. */
.dw{display:block;margin-top:6px}
/* A497: the session letter -- THE artifact of screen 3, styled as the page's
   centrepiece: a document, not a card among cards. Quiet frame, generous
   padding, near-black text at reading size. */
.s3-letter{background:var(--s1);border:1.5px solid var(--b2);border-radius:var(--r2);padding:18px 18px 14px;margin-bottom:16px;box-shadow:0 2px 10px rgba(0,0,0,.05)}
.s3-letter-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;flex-wrap:wrap}
.s3-letter-title{font-family:var(--sf);font-size:22px;color:var(--tx);line-height:1.2}
.s3-letter-sub{font-size:13px;color:var(--mu);margin:3px 0 12px}
.s3-letter .db{white-space:pre-wrap;font-size:15.5px;line-height:1.68;color:var(--ink,#1a1d2e);background:transparent;border:none;padding:0;max-width:66ch}
.lslot{display:inline-block;background:#4f8ef714;border:1px dashed #4f8ef750;border-radius:5px;padding:0 6px;font-size:.92em;color:var(--ac);white-space:nowrap}
.lslot-you{background:#f5a62312;border-color:#f5a62360;color:#8a5a00}
.s3-name-row{display:flex;flex-direction:column;gap:5px;margin-top:12px}
.s3-name-label{font-size:13px;font-weight:600;color:var(--tx)}
.s3-name-row input{box-sizing:border-box;border:1.5px solid var(--b2);border-radius:var(--r1);padding:10px 12px;font-family:var(--ss);font-size:16px;color:var(--tx);max-width:340px}
.s3-letter-tools{margin-top:10px}
.s3-letter-disclosure{font-size:11.5px;color:var(--di);line-height:1.5;margin-top:10px;padding-top:9px;border-top:1px solid var(--b1)}
/* The card delta: the two-sentence difference, set as a quotation from the
   letter rather than a second document. */
.oc-delta{margin-top:9px;padding:9px 12px;border-left:2.5px solid #4f8ef735;background:#4f8ef706;border-radius:0 var(--r1) var(--r1) 0}
.oc-delta-label{font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--mu);margin-bottom:4px}
.oc-delta-line{font-size:14px;line-height:1.6;color:var(--ink,#1a1d2e)}
.oc-delta-greeting{font-weight:600}
.oc-delta-full{display:inline-block;margin-top:5px;font-size:12px;color:var(--ac);cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.db{background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:12px;font-size:13px;color:var(--mu);line-height:1.55;white-space:pre-wrap}
.lwarn{background:#f5a62318;border:1px solid #f5a62340;border-radius:var(--r1);padding:9px 12px;font-size:13px;color:var(--am);margin-top:8px;line-height:1.5}
.lwarn strong{font-weight:700}
.cmb{width:100%;background:transparent;border:1px solid var(--b2);border-radius:var(--r1);padding:7px;font-family:var(--ss);font-size:13px;color:var(--ac);cursor:pointer;margin-top:6px;display:flex;align-items:center;justify-content:center;gap:5px;transition:all .2s}
.cmb:hover{background:#4f8ef715}
.ri{background:linear-gradient(135deg,#4f8ef712,#9b6df710);border:1px solid var(--b2);border-radius:var(--r2);padding:16px;margin-bottom:13px}
.ri h3{font-family:var(--sf);font-size:16px;margin-bottom:5px}
.ri p{font-size:13px;color:#5b6472;line-height:1.6}
.pw{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:12px;margin-bottom:13px}
.pt{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;font-size:13px}
.pb{background:var(--s2);border-radius:var(--rp);height:5px;overflow:hidden}
.pf{height:100%;background:linear-gradient(90deg,var(--ac),var(--pu));border-radius:var(--rp);transition:width .5s}
.ps{font-size:11px;color:var(--di);margin-top:3px}
.road{display:flex;flex-direction:column}
.rs{display:flex}
.rl{display:flex;flex-direction:column;align-items:center;width:38px;flex-shrink:0}
.rn{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;border:2px solid transparent}
.rc{width:2px;flex:1;min-height:11px;background:var(--b2);margin:0 auto}
.rs:last-child .rc{display:none}
.rco{flex:1;padding:0 0 18px 11px}
.rp{font-size:11px;font-weight:600;letter-spacing:0.14em;text-transform:uppercase;margin-bottom:3px}
.rt{font-size:16px;font-weight:600;margin-bottom:3px;font-family:var(--sf)}
.rd{font-size:13px;color:#5b6472;line-height:1.55;margin-bottom:7px}
.subs{display:flex;flex-direction:column;gap:5px}
.sub{display:flex;align-items:flex-start;gap:7px;background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:9px 11px;cursor:pointer;user-select:none;transition:all .2s}
.sub.dn{opacity:.5}
.sc2{width:15px;height:15px;border-radius:var(--r0);border:1.5px solid var(--b3);flex-shrink:0;margin-top:2px;display:flex;align-items:center;justify-content:center;font-size:11px;transition:all .2s}
.sub.dn .sc2{background:var(--gr);border-color:var(--gr);color:#fff}
.sbx strong{font-size:13px;font-weight:600;display:block;margin-bottom:1px}
.sub.dn .sbx strong{text-decoration:line-through;color:var(--mu)}
.sbx span{font-size:13px;color:#59677f;line-height:1.4}
.tip{font-size:11px;color:var(--ac);margin-top:3px;padding-top:3px;border-top:1px solid var(--b1);line-height:1.4}
.tip::before{content:'💡 '}
.dest{background:linear-gradient(135deg,#f8717112,#f5a62310);border:1px solid #f8717128;border-radius:var(--r2);padding:16px;margin-bottom:14px;text-align:center}
.dest h3{font-family:var(--sf);font-size:19px;margin-bottom:5px}
.dest p{font-size:13px;color:#5b6472;line-height:1.55;margin-bottom:10px}
.di{display:grid;grid-template-columns:1fr 1fr;gap:6px;text-align:left}
@media(max-width:480px){.di{grid-template-columns:1fr}}
.dii{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:9px}
.dii .ic{font-size:13px;margin-bottom:3px}
.dii strong{font-size:13px;font-weight:600;display:block;margin-bottom:1px}
.dii span{font-size:13px;color:#59677f;line-height:1.4}
.cc2{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r3);overflow:hidden;margin-bottom:16px;box-shadow:0 2px 8px rgba(15,32,87,.05)}
.cb{background:linear-gradient(135deg,rgba(27,79,255,.06),rgba(155,109,247,.04));border-bottom:1.5px solid var(--b1);padding:24px 28px;text-align:center}
.cb h2{font-family:var(--sf);font-size:28px;line-height:1.3;margin-bottom:6px;color:var(--civic)}
.cb p{font-size:16px;color:var(--mu);line-height:1.6}
.sts{display:grid;grid-template-columns:repeat(3,1fr);border-bottom:1.5px solid var(--b1)}
.stt{padding:12px;text-align:center}
.stt+.stt{border-left:1px solid var(--b1)}
.sn2{font-family:var(--sf);font-size:22px;line-height:1}
.sl2{font-size:11px;color:var(--mu);margin-top:2px;text-transform:uppercase;letter-spacing:0.08em}
.cb2{padding:22px 26px}
.sll{font-size:11px;font-weight:600;letter-spacing:0.14em;text-transform:uppercase;color:var(--di);margin-bottom:7px}
.sg{display:grid;grid-template-columns:1fr 1fr;gap:5px;margin-bottom:12px}
.sb3{display:flex;align-items:center;gap:6px;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:8px 10px;font-family:var(--ss);font-size:13px;font-weight:600;cursor:pointer;transition:all .2s;color:var(--tx)}
.sb3:hover{transform:translateY(-1px)}
.si3{width:22px;height:22px;border-radius:var(--r0);display:flex;align-items:center;justify-content:center;font-size:11px;flex-shrink:0;font-weight:700}
.sn3{font-size:13px;font-weight:600}
.snt{font-size:11px;color:var(--mu)}
.mw{margin-bottom:11px}
.mt{display:flex;justify-content:space-between;font-size:13px;margin-bottom:4px}
.mb{background:var(--s2);border-radius:var(--rp);height:4px;overflow:hidden}
.mf{height:100%;background:linear-gradient(90deg,var(--ac),var(--pu));border-radius:var(--rp);transition:width 1.2s}
.ms{display:flex;justify-content:space-between;font-size:11px;color:var(--di);margin-top:3px}
.pet{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:12px}
.pet h4{font-size:13px;font-weight:600;margin-bottom:9px}
.sgr{display:flex;gap:6px;flex-wrap:wrap}
.sgr input{flex:1;min-width:85px;background:var(--bg);border:1px solid var(--b2);border-radius:var(--r1);padding:8px 10px;color:var(--tx);font-family:var(--ss);font-size:13px;outline:none}
.sgr input:focus{border-color:#4f8ef760}
.sigs{margin-top:9px;display:flex;flex-direction:column;max-height:130px;overflow-y:auto}
.sig-li{display:flex;align-items:center;gap:8px;font-size:16px;color:var(--mu);padding:8px 0;border-bottom:1px solid var(--b1)}
.sig-li:last-child{border:none}
.sav{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;color:#fff;flex-shrink:0}
.st3{margin-left:auto;font-size:11px;color:var(--di)}
.bnav{display:flex;justify-content:space-between;align-items:center;padding:24px 0 30px;margin-top:8px}
/* May 20 2026, mobile fix: on narrow viewports the flex:1 middle text
   element ("Step 2 of 5, next: find your real officials") got squeezed
   into a 60-80px column between the back/forward buttons and wrapped to
   7 thin lines. Stack vertically on mobile so the indicator and buttons
   each get full width. Text sits between the buttons as a visual divider. */
@media (max-width:540px){
  .bnav{flex-direction:column;gap:10px;align-items:stretch;padding:18px 0 24px}
  .bnav > div{text-align:center !important;padding:4px 0;font-size:13px;line-height:1.4}
  .bnav > button{width:100%}
}
/* Was color:var(--di) on a borderless, unpadded background:none button --
   the lowest-contrast text token with no chrome to give it a hit target or a
   visible edge, so it read as barely-there ghost text rather than a button.
   That first pass moved the TEXT to var(--mu) (8.83:1 against the page
   background, well past WCAG's 4.5:1) but kept the BORDER at var(--b2)
   (#d0d4df), which measures only 1.37:1 against the same background --
   var(--b1)/--b2/--b3 are all hairline-divider tokens, none of them clear
   WCAG 1.4.11's 3:1 floor for a UI component's boundary, so the button
   still read as barely-there. Border now matches the text color,
   var(--mu), so it actually clears 3:1 (8.83:1, same measured value as the
   text) instead of just changing what disappears. */
.back-top{display:inline-flex;align-items:center;gap:6px;color:var(--mu);font-size:13px;font-weight:600;text-decoration:none;margin-bottom:18px;background:transparent;border:1.5px solid var(--mu);border-radius:var(--r1);padding:7px 12px;cursor:pointer;font-family:var(--ss);transition:border-color .15s,color .15s}
.back-top:hover{border-color:var(--ac);color:var(--ac)}
.leg-showcase{background:linear-gradient(135deg,rgba(27,79,255,.06) 0%,rgba(108,71,255,.08) 100%);border:1.5px solid rgba(108,71,255,.25);border-radius:var(--r3);padding:28px 30px;margin:20px 0 18px;cursor:pointer;transition:all .2s;position:relative;overflow:hidden}
.leg-showcase:hover{border-color:rgba(108,71,255,.5);box-shadow:0 8px 24px rgba(108,71,255,.12);transform:translateY(-1px)}
.leg-showcase::before{content:'';position:absolute;top:-30px;right:-30px;width:140px;height:140px;background:radial-gradient(circle,rgba(108,71,255,.15) 0%,transparent 70%);pointer-events:none}
.leg-showcase-badge{display:inline-block;font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--pu);background:rgba(108,71,255,.1);border:1px solid rgba(108,71,255,.25);border-radius:var(--r0);padding:4px 10px;margin-bottom:14px;position:relative;z-index:1}
.leg-showcase-title{font-family:var(--sf);font-size:28px;line-height:1.3;color:var(--civic);margin-bottom:12px;font-weight:400;position:relative;z-index:1}
.leg-showcase-desc{font-size:16px;color:var(--mu);line-height:1.65;margin-bottom:22px;position:relative;z-index:1}
.leg-showcase-cta{display:flex;align-items:center;gap:14px;flex-wrap:wrap;position:relative;z-index:1}
/* ── Cross-path navigation is outlined, with no ranking among the four ──
   Miguel's decision, 2026-07-30. The four cross-path CTAs in the Take
   Action footer and screen 3's pair are NAVIGATION, and fill is reserved
   for each screen's own stated primary. They demote together and equally:
   keeping any one filled would silently rank it above the others, which is
   the larger distortion. Measured before, fixture mirror 390x844 both
   languages: worst 844px window held THREE filled controls at y=4200 EN
   and y=4400 ES, none of them the screen's primary. ── */
/* Stronger than a plain outlined button on purpose: these are the ONLY two
   "Acta exclusive" actions on the page, and a 1.5px var(--b2) gray border read
   as just another secondary link. The badge above each button is already
   var(--pu) purple, so the button now carries that same color instead of
   inventing a new one -- still no fill (background stays transparent, so this
   does not add to the R7 filled-primary census), just a thicker, colored
   border and bolder text that visually ties to the badge. */
.leg-showcase-btn{background:transparent;color:var(--pu);border:2px solid var(--pu);border-radius:var(--r1);padding:13px 22px;font-family:var(--ss);font-size:16px;font-weight:700;cursor:pointer;transition:border-color .15s,color .15s;display:inline-flex;align-items:center;gap:8px}
.leg-showcase-btn:hover{border-color:var(--ac);color:var(--ac)}
.leg-showcase-note{font-size:13px;color:var(--di);line-height:1.5}
@media(max-width:600px){
  .leg-showcase{padding:22px 22px;border-radius:var(--r3)}
  .leg-showcase-title{font-size:22px}
  .leg-showcase-desc{font-size:13px}
  .leg-showcase-cta{flex-direction:column;align-items:flex-start;gap:10px}
  .leg-showcase-btn{width:100%;justify-content:center}
}
.uh{color:var(--re)}.um{color:var(--am)}.ul{color:var(--gr)}
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(80px);background:#059669;color:#fff;padding:9px 16px;border-radius:var(--r4);font-size:13px;font-weight:600;z-index:9999;transition:transform .3s;pointer-events:none;white-space:nowrap}
.toast.show{transform:translateX(-50%) translateY(0)}
/* ── PHONE SCRIPT = STEP 1 of the officials card ──
   The card now expresses the sequence the on-page copy already states ("Call
   first ... Then send the letter the same day"): call is step 1, send is step 2,
   two visually distinct ordered steps with ONE primary affordance each. See
   docs/design/interior-officials-card-hierarchy.md.

   What changed and why: this block used to carry border #10b98128 with a
   var(--gr) toggle, sitting directly above .btn-mailto's background #10b98118 /
   border #10b98140 / var(--gr). Two green full-width blocks stacked adjacent,
   indistinguishable at a glance, which is the focal-point violation the first
   render exposed. Green also MEANS something here: it is the success colour
   used by "Logged. Thank you for taking action." It now means only that.

   Step 1 is neutral and outlined, and keeps its full width and its position
   first, so it is differentiated by ROLE, not demoted. Its single affordance is
   the disclosure that reveals the script. The ordinal is a CSS numeral, so it
   needs no new string and no translation. ── */
.phone-script{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r1);margin-top:16px}
.ps-toggle{width:100%;background:transparent;border:none;padding:8px 12px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--tx);cursor:pointer;text-align:left;display:flex;gap:8px;justify-content:space-between;align-items:center}
.ps-toggle::before{content:"1";flex:0 0 auto;width:18px;height:18px;border-radius:50%;background:var(--s3);color:var(--mu);font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1}
.ps-toggle > span:first-of-type{flex:1 1 auto;min-width:0}
.ps-toggle:hover{background:var(--s2)}
.ps-body{display:none;padding:0 12px 12px}
.ps-body.open{display:block}
.ps-line{font-size:13px;color:var(--mu);line-height:1.55;padding:4px 0;border-bottom:1px solid var(--b1)}
.ps-line:last-child{border:none}
.ps-line em{color:var(--tx);font-style:normal;font-weight:600}
.ps-tip{font-size:11px;color:var(--am);margin-top:8px;line-height:1.45;padding:7px 9px;background:#f5a62310;border-radius:var(--r0)}
/* ── MAILTO BUTTON (item 2) ── */
.action-btns{display:flex;gap:6px;margin-top:6px;flex-wrap:wrap}
/* ── SEND BUTTON = STEP 2, the card's ONE filled control ──
   Was success-green (#10b98118 / #10b98140 / var(--gr)), which both collided
   with step 1 above and told the visitor the send was already done. Now the
   system action accent, var(--ac), the same blue "Apply to all letters" uses
   on this screen. Every primary variant renders through this class (chooser
   toggle, contact form, website, and the copy-only last resort), so the step-2
   treatment and its ordinal are correct on all four. ── */
.btn-mailto{position:relative;display:inline-flex;align-items:center;gap:5px;background:var(--civic);border:1px solid var(--civic);border-radius:var(--r1);padding:8px 34px;font-family:var(--ss);font-size:13px;font-weight:600;color:#fff;cursor:pointer;text-decoration:none;transition:all .2s;white-space:normal;text-align:center;line-height:1.4}
.btn-mailto:hover{background:var(--civic-h);border-color:var(--civic-h)}
/* Absolute so the ordinal sits at the leading edge even though the primary
   send is centred (the button carries inline justify-content:center). */
.btn-mailto::before{content:"2";position:absolute;left:10px;top:50%;transform:translateY(-50%);width:18px;height:18px;border-radius:50%;background:rgba(255,255,255,.22);color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1}
/* The disabled "Preparing" state is not an action yet: no ordinal, no accent. */
/* Found by the real-data artifact pass, not by the fixtures: with 13 officials
   the letters had not hydrated yet, so every primary was in the DISABLED
   "Preparing" state, and the white-space:normal added for long Spanish labels
   let "Preparando tu carta..." wrap to two lines at h=52px. The fixtures set
   msg immediately, so this state never rendered locally and could not be seen.
   The disabled state has no ordinal, so it needs neither the 34px gutter nor
   wrapping. ── */
.btn-mailto[disabled]{background:var(--s2);border-color:var(--b2);color:var(--mu);padding:8px 11px;white-space:nowrap}
.btn-mailto[disabled]::before{display:none}
/* Copy drops to text weight. It STAYS: it is the only path that works for a
   member with no email and no form, and 3 of the 4 real sends in 60 days came
   through copy paths. It just stops competing with step 2. ── */
.btn-copy-msg{display:inline-flex;align-items:center;gap:5px;background:transparent;border:none;border-radius:0;padding:8px 2px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);cursor:pointer;transition:color .2s;white-space:nowrap;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.btn-copy-msg:hover{color:var(--tx)}
/* ── LEGISLATION MODAL ── */
.leg-modal{background:#ffffff;border:1px solid var(--b3);border-radius:var(--r2);max-width:560px;width:100%;position:relative;max-height:90vh;overflow:hidden;display:flex;flex-direction:column}
.leg-modal-body{padding:22px;overflow-y:auto;flex:1}
.leg-modal-body::-webkit-scrollbar{width:4px}.leg-modal-body::-webkit-scrollbar-thumb{background:var(--b3);border-radius:var(--r0)}
.leg-q{margin-bottom:18px}
.leg-q-label{font-size:13px;font-weight:600;color:var(--tx);margin-bottom:6px;line-height:1.55;display:block}
.leg-q-hint{font-size:11px;color:var(--di);margin-bottom:7px;line-height:1.4}
.leg-q textarea{min-height:64px;font-size:13px}
.leg-opts{display:flex;flex-direction:column;gap:5px}
.leg-opt{display:flex;align-items:flex-start;gap:8px;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 11px;cursor:pointer;transition:all .2s;user-select:none}
.leg-opt:hover{border-color:#4f8ef740}
.leg-opt.sel{background:#4f8ef715;border-color:#4f8ef750}
.leg-opt-dot{width:14px;height:14px;border-radius:50%;border:1.5px solid var(--b3);flex-shrink:0;margin-top:2px;transition:all .2s}
.leg-opt.sel .leg-opt-dot{background:var(--ac);border-color:var(--ac)}
.leg-opt-text{font-size:13px;color:var(--mu);line-height:1.4}
.leg-multi .leg-opt-dot{border-radius:var(--r0)}
.leg-section-label{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--di);margin:20px 0 10px;padding-bottom:6px;border-bottom:1px solid var(--b1)}
.leg-output{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:18px;margin-top:13px}
.leg-output-section{margin-bottom:16px}
.leg-output-section:last-child{margin:0}
.leg-output-label{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--ac);margin-bottom:8px;display:flex;align-items:center;gap:6px}
.leg-output-label::after{content:'';flex:1;height:1px;background:var(--b2)}
.leg-output-text{font-size:13px;color:var(--mu);line-height:1.55;white-space:pre-wrap;font-family:'DM Sans',sans-serif}
.leg-disclaimer{background:#f5a62310;border:1px solid #f5a62328;border-radius:var(--r1);padding:9px 12px;font-size:11px;color:var(--am);line-height:1.45;margin-top:12px}
@media print{
  @page{margin:1in}
  body{background:#fff;color:#000;font-size:12pt}
  nav,.stepbar,#leg-modal-bg .leg-modal>div:first-child,.leg-gen-btn,.action-btns,button:not(.leg-print-content){display:none!important}
  /* A532: chrome that printed alongside everything -- the marketing footer,
     the toast, the slide-out menu, and the share-bar / footer-nav wrappers
     whose buttons vanish but whose labels printed as orphans. */
  #site-footer,#toast,#nav-menu,.shrb,.bnav,#camp-strip-el{display:none!important}
  .inf-section,.gi-brief-section,.oc{break-inside:avoid}
  .leg-output{background:#fff;border:1px solid #ccc;border-radius:0;padding:0}
  .leg-output-label{color:#1a1a2e;border-bottom:1px solid #ccc;padding-bottom:4px;margin-bottom:8px}
  .leg-output-text{color:#111;font-size:11pt;line-height:1.7}
  .leg-modal{max-height:none;overflow:visible;border:none}
  .leg-modal-body{overflow:visible;padding:0}
  .mbg{position:static;background:none;padding:0}
  .leg-disclaimer{background:#fff8e6;border:1px solid #e6a800;color:#7a5200}
  h2{font-size:16pt}
  /* A532: the letter print sheet. When actaPrintSessionLetter arms
     body.printing-letter, ONLY the sheet prints: a dated letter in a serif
     face, the shape of a document you hand across a counter -- not a webpage
     that happens to contain one. */
  body.printing-letter > :not(#letter-print-sheet){display:none!important}
  body.printing-letter #letter-print-sheet{display:block;font-family:Georgia,'Times New Roman',serif;font-size:12pt;line-height:1.65;color:#000;max-width:6.5in}
  body.printing-letter #letter-print-sheet .lps-date{margin-bottom:22pt}
  body.printing-letter #letter-print-sheet .lps-body{white-space:pre-wrap;orphans:3;widows:3}
}
/* A532: the print sheet never renders on screen. */
#letter-print-sheet{display:none}
.leg-gen-btn{background:var(--civic);color:#fff;border:2px solid var(--civic-h);border-radius:var(--r1);padding:12px 20px;font-family:var(--ss);font-size:16px;font-weight:700;cursor:pointer;width:100%;margin-top:6px}
.leg-gen-btn:hover{background:#1d4ed8}
.leg-gen-btn:disabled{background:#1e3a5f;border-color:#2d4a6f;color:#4a6080;cursor:not-allowed}
.leg-loading{text-align:center;padding:32px 0}
.leg-progress{font-size:11px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:var(--di);text-align:right;margin-bottom:16px}
/* ── TALK TRACK & MEDIA KIT MODALS (shared styles) ── */
.tool-modal{background:#ffffff;border:1px solid var(--b3);border-radius:var(--r2);max-width:560px;width:100%;position:relative;max-height:90vh;overflow:hidden;display:flex;flex-direction:column}
.tool-modal-body{padding:22px;overflow-y:auto;flex:1}
.tool-modal-body::-webkit-scrollbar{width:4px}.tool-modal-body::-webkit-scrollbar-thumb{background:var(--b3);border-radius:var(--r0)}
.tool-modal-fade{position:absolute;bottom:0;left:0;right:0;height:44px;background:linear-gradient(transparent,#ffffff);pointer-events:none;border-radius:0 0 16px 16px}
.tool-section{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:14px;margin-bottom:11px}
.tool-section-label{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--di);margin-bottom:9px;display:flex;align-items:center;gap:6px}
.tool-section-label::after{content:'';flex:1;height:1px;background:var(--b1)}
.tool-msg{font-size:13px;color:var(--mu);line-height:1.55;white-space:pre-wrap}
.tool-short{font-size:13px;color:var(--tx);font-weight:600;line-height:1.55;margin-bottom:4px}
.tool-long{font-size:13px;color:#5b6472;line-height:1.7}
.tool-objection{background:var(--s2);border-left:3px solid var(--re);border-radius:0 8px 8px 0;padding:10px 12px;margin-bottom:8px}
.tool-objection:last-child{margin:0}
.tool-obj-q{font-size:13px;color:var(--re);font-weight:600;margin-bottom:4px}
.tool-obj-a{font-size:13px;color:var(--mu);line-height:1.7}
.tool-copy-row{display:flex;gap:7px;margin-top:10px}
.tool-copy-btn{flex:1;background:#2563eb;color:#fff;border:2px solid #60a5fa;border-radius:var(--r1);padding:9px 13px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer}
.tool-copy-btn:hover{background:#1d4ed8}
.tool-sec-btn{background:transparent;color:var(--mu);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 13px;font-family:var(--ss);font-size:13px;cursor:pointer}
.tool-sec-btn:hover{border-color:var(--b3);color:var(--tx)}
/* ── WEEKLY ACTION BANNER ── */





.ab-btn:hover{background:#1d4ed8}

/* ── NETWORK ASK FLOW ── */
.ask-contact{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:13px;margin-bottom:9px;transition:border-color .2s}
.ask-contact.asked{border-color:#10b98140;background:#10b98108}
.ask-contact-header{display:flex;align-items:center;gap:9px;margin-bottom:9px}
.ask-avatar{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;flex-shrink:0}
.ask-name{font-size:16px;font-weight:600;color:var(--tx)}
.ask-rel{font-size:11px;color:var(--di);margin-top:1px}
.ask-badge{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;padding:2px 7px;border-radius:var(--r0);margin-left:auto}
.ask-badge.sent{background:#10b98120;color:var(--gr);border:1px solid #10b98130}
.ask-badge.pending{background:var(--s1);color:var(--di);border:1px solid var(--b1)}
.ask-msg{font-size:13px;color:var(--mu);line-height:1.55;background:var(--s1);border-radius:var(--r1);padding:10px 12px;margin-bottom:9px;white-space:pre-wrap}
.ask-actions{display:flex;gap:7px}
.ask-copy-btn{flex:1;background:#2563eb;color:#fff;border:2px solid #60a5fa;border-radius:var(--r1);padding:8px 12px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer}
.ask-mark-btn{background:transparent;color:var(--mu);border:1px solid var(--b2);border-radius:var(--r1);padding:8px 12px;font-family:var(--ss);font-size:13px;cursor:pointer}
.ask-input-row{display:flex;gap:7px;margin-bottom:7px}
.ask-input-row input{flex:1;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 11px;color:var(--tx);font-family:var(--ss);font-size:13px;outline:none}
.ask-input-row select{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 11px;color:var(--tx);font-family:var(--ss);font-size:13px;outline:none;cursor:pointer}
.ask-add-btn{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 13px;font-family:var(--ss);font-size:13px;color:var(--ac);cursor:pointer;font-weight:600;white-space:nowrap}
.ask-progress{background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:11px 13px;margin-bottom:13px;display:flex;align-items:center;gap:11px}
.ask-progress-bar{flex:1;height:6px;background:var(--b1);border-radius:var(--r0);overflow:hidden}
.ask-progress-fill{height:100%;background:var(--gr);border-radius:var(--r0);transition:width .4s}
/* ── LOBBY DAY PLANNER ── */
.lobby-phase{background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:14px;margin-bottom:10px}
.lobby-phase-header{display:flex;align-items:center;gap:10px;margin-bottom:10px;cursor:pointer;user-select:none}
.lobby-phase-icon{width:36px;height:36px;border-radius:var(--r1);display:flex;align-items:center;justify-content:center;font-size:19px;flex-shrink:0}
.lobby-phase-title{font-size:16px;font-weight:700;color:var(--tx);line-height:1.3}
.lobby-phase-sub{font-size:11px;color:var(--di);margin-top:1px}
.lobby-phase-toggle{margin-left:auto;font-size:13px;color:var(--di);transition:transform .2s}
.lobby-phase-body{display:none}
.lobby-phase-body.open{display:block}
.lobby-item{display:flex;gap:10px;align-items:flex-start;padding:9px 0;border-bottom:1px solid var(--b1)}
.lobby-item:last-child{border:none;padding-bottom:0}
.lobby-item-check{width:18px;height:18px;border-radius:var(--r0);border:1.5px solid var(--b3);flex-shrink:0;margin-top:2px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}
.lobby-item-check.done{background:var(--gr);border-color:var(--gr)}
.lobby-item-text{font-size:13px;color:var(--mu);line-height:1.55;flex:1}
.lobby-item-text.done{color:var(--di);text-decoration:line-through}
.lobby-item-note{font-size:13px;color:#59677f;line-height:1.55;margin-top:3px}
.lobby-insight{background:linear-gradient(135deg,#4f8ef710,#9b6df708);border:1px solid var(--b2);border-radius:var(--r1);padding:10px 12px;margin-top:9px;font-size:13px;color:#5b6472;line-height:1.6}
.lobby-insight strong{color:var(--ac)}
.lobby-copy-block{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:11px 13px;font-size:13px;color:var(--mu);line-height:1.55;white-space:pre-wrap;margin-top:9px}
.lobby-tab-row{display:flex;gap:6px;margin-bottom:12px;flex-wrap:wrap}
.lobby-tab{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:6px 13px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);cursor:pointer;transition:all .2s}
.lobby-tab.active{background:#4f8ef720;border-color:#4f8ef750;color:var(--ac)}
/* ── COALITION FINDER ── */
.coalition-card{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:14px;margin-bottom:9px;transition:border-color .2s}
.coalition-card:hover{border-color:var(--b3)}
.coalition-card-header{display:flex;align-items:flex-start;gap:10px;margin-bottom:8px}
.coalition-logo{width:36px;height:36px;border-radius:var(--r1);background:linear-gradient(135deg,#4f8ef720,#9b6df715);border:1px solid var(--b2);display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:var(--ac);flex-shrink:0}
.coalition-name{font-size:16px;font-weight:700;color:var(--tx);line-height:1.3}
.coalition-url{font-size:11px;color:var(--di);margin-top:1px}
.coalition-role{font-size:13px;color:#5b6472;line-height:1.55;margin-bottom:9px}
.coalition-ask{background:linear-gradient(135deg,#4f8ef710,#9b6df708);border:1px solid var(--b2);border-radius:var(--r1);padding:9px 11px;font-size:13px;color:var(--mu);line-height:1.6}
.coalition-ask-label{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--ac);margin-bottom:4px}
.coalition-script{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:10px 12px;font-size:13px;color:var(--mu);line-height:1.55;margin-top:9px;white-space:pre-wrap;display:none}
.coalition-actions{display:flex;gap:7px;margin-top:9px;flex-wrap:wrap}
.coalition-visit-btn{background:#2563eb;color:#fff;border:2px solid #60a5fa;border-radius:var(--r1);padding:7px 13px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;gap:4px}
.coalition-copy-btn{background:transparent;color:var(--mu);border:1px solid var(--b2);border-radius:var(--r1);padding:7px 11px;font-family:var(--ss);font-size:13px;cursor:pointer}
.coalition-script-btn{background:transparent;color:var(--ac);border:1px solid #4f8ef730;border-radius:var(--r1);padding:7px 11px;font-family:var(--ss);font-size:13px;cursor:pointer}
/* ── MODE PATH SELECTOR ── */
.mode-path{background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);overflow:hidden;transition:border-color .2s;cursor:pointer}
.mode-path:hover{border-color:var(--b3)}
.mode-path.open{border-color:var(--b3);background:var(--s1)}
.mode-path-header{display:flex;align-items:center;gap:10px;padding:12px 13px}
.mode-path-icon{width:32px;height:32px;border-radius:var(--r1);display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0}
.mode-path-title{font-size:16px;font-weight:700;color:var(--tx);flex:1;line-height:1.3}
.mode-path-sub{display:block;font-size:11px;font-weight:400;color:var(--di);margin-top:1px}
.mode-path-arrow{font-size:13px;color:var(--di);transition:transform .25s;flex-shrink:0}
.mode-path.open .mode-path-arrow{transform:rotate(180deg)}
.mode-path-body{display:none;padding:0 13px 13px}
.mode-path.open .mode-path-body{display:block}
.mode-tool-btn{width:100%;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:10px 13px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--tx);cursor:pointer;text-align:left;transition:all .2s;display:block}
.mode-tool-btn:hover{border-color:var(--b3);background:var(--s1)}
.mode-tool-grn{color:var(--pu)}
.mode-tool-grn:hover{border-color:#9b6df740;background:#9b6df710}
.mode-tool-ac{color:var(--ac)}
.mode-tool-ac:hover{border-color:#4f8ef740;background:#4f8ef710}
/* ── CAMPAIGN STATE STRIP ── */
.camp-strip{background:linear-gradient(135deg,#ffffff,#f1f4f9);border-bottom:1px solid var(--b2);padding:8px 18px;display:flex;align-items:center;gap:10px;width:100%;box-sizing:border-box;max-width:720px;margin:0 auto}
.camp-strip-issue{font-size:13px;font-weight:600;color:var(--tx);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.camp-strip-stat{font-size:11px;color:var(--di);white-space:nowrap;display:flex;align-items:center;gap:3px}
.camp-strip-stat strong{color:var(--gr)}
.camp-strip-week{font-size:11px;font-weight:700;color:var(--ac);background:#4f8ef718;border:1px solid #4f8ef730;border-radius:var(--r0);padding:2px 7px;cursor:pointer;white-space:nowrap}
#hint-text{transition:opacity .3s}
.ls{display:flex;flex-direction:column;padding:54px 0;text-align:center}
.sp{width:38px;height:38px;border-radius:50%;border:2px solid var(--b3);border-top-color:var(--ac);animation:spin 1s linear infinite;margin:0 auto 16px}
@keyframes spin{to{transform:rotate(360deg)}}
/* Item 10 (2026-08-16): the progress LIST is a centred block, but its rows
   are left-aligned with the marker in a fixed-width column at the TOP of each
   row -- the old centred rows stranded a one-line step's circle inline and a
   two-line step's circle at the far left, vertically centred. */
.lsq{margin-top:14px;display:flex;flex-direction:column;gap:6px;align-items:stretch;max-width:330px;margin-left:auto;margin-right:auto}
.li{font-size:13px;color:var(--di);transition:all .3s;display:flex;align-items:flex-start;gap:8px;text-align:left}
.li::before{content:'○';font-size:11px;width:14px;flex-shrink:0;text-align:center;margin-top:3px}
.li.cur{color:var(--ac)}.li.cur::before{content:'●'}
.li.ok{color:var(--gr)}.li.ok::before{content:'✓'}
.restart{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r1);padding:12px 16px;display:flex;align-items:center;justify-content:space-between;margin-bottom:13px;gap:12px}
.restart p{font-size:13px;color:var(--mu);flex:1}
.restart button{background:#2563eb;color:#fff;border:2px solid #60a5fa;border-radius:var(--r1);padding:8px 14px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer;white-space:nowrap}
.mbg{position:fixed;inset:0;background:#00000090;z-index:9000;display:flex;align-items:center;justify-content:center;padding:20px}
@supports(padding-bottom:env(safe-area-inset-bottom)){#app{padding-bottom:calc(80px + env(safe-area-inset-bottom))}}

.upd-box{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:15px;margin-bottom:13px}
.upd-box h4{font-family:var(--sf);font-size:16px;margin-bottom:6px;color:var(--tx)}
.upd-entry{background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:11px 13px;margin-bottom:8px}
.upd-entry-date{font-size:11px;color:var(--di);margin-bottom:4px;font-weight:600;letter-spacing:0.02em;text-transform:uppercase}
.upd-entry-text{font-size:13px;color:var(--tx);line-height:1.6}
.del-btn{width:100%;background:linear-gradient(135deg,#10b98118,#4f8ef712);border:1.5px solid #10b98140;border-radius:var(--r1);padding:11px;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--gr);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:7px;transition:all .2s;margin-bottom:8px}
.del-btn:hover{background:linear-gradient(135deg,#10b98128,#4f8ef720)}

.vf{background:linear-gradient(135deg,var(--s1),var(--s2));border:1px solid var(--b2);border-radius:var(--r2);padding:16px 18px;margin-bottom:13px}
.vf-title{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--ac);margin-bottom:12px}
.vf-item{display:flex;gap:10px;align-items:flex-start;padding:9px 0;border-bottom:1px solid var(--b1)}
.vf-item:last-child{border-bottom:none;padding-bottom:0}
.vf-icon{font-size:19px;flex-shrink:0;margin-top:1px}
.vf-body{flex:1}
.vf-win{font-size:13px;font-weight:600;color:var(--tx);line-height:1.55;margin-bottom:2px}
.vf-detail{font-size:13px;color:var(--mu);line-height:1.5}
.vf-badge{display:inline-block;font-size:11px;font-weight:700;color:var(--gr);background:#10b98115;border:1px solid #10b98130;border-radius:var(--r0);padding:1px 6px;margin-left:6px;vertical-align:middle}

.track-box{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:14px 16px;margin-bottom:13px}
.track-title{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--mu);margin-bottom:11px}
.track-item{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid var(--b1);cursor:pointer}
.track-item:last-child{border-bottom:none;padding-bottom:0}
.track-check{width:20px;height:20px;border-radius:var(--r0);border:2px solid var(--b3);display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .2s;font-size:13px}
.track-check.done{background:var(--gr);border-color:var(--gr);color:#fff}
.track-label{font-size:13px;color:var(--mu);flex:1;line-height:1.4}
.track-label.done{color:var(--tx);text-decoration:line-through;opacity:.6}
.track-followup{display:none;background:#f5a62312;border:1px solid #f5a62330;border-radius:var(--r1);padding:9px 12px;font-size:13px;color:var(--am);line-height:1.55;margin-top:6px}

.camp-update-box{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r2);padding:14px 16px;margin-bottom:13px}
.camp-update-box textarea{width:100%;background:var(--s2);border:1px solid var(--b2);border-radius:var(--r1);padding:10px 12px;color:var(--tx);font-family:var(--ss);font-size:13px;line-height:1.55;resize:vertical;min-height:80px;outline:none;transition:border .2s;box-sizing:border-box}
.camp-update-box textarea:focus{border-color:#4f8ef760}


/* .hiw rules removed, markup migrated to .flow-section / .flow-strip / .flow-step */
/* Batch 28: the Take Action intake must show the ZIP field without scrolling
   at 390x844 in both languages. The chips auto-pack (flex-wrap) and compact
   modestly at phone width; !important because each chip carries inline
   styling from buildIssueChips. Spanish labels are longer and pack the same
   way because nothing is hand-paired. */
@media(max-width:600px){
  .seed-chip{padding:4px 9px !important;font-size:11px !important;border-radius:var(--r2)!important}
}
.proof-illustrative{display:inline-block;font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--am);background:#b86b0012;border:1px solid #b86b0033;border-radius:var(--r0);padding:2px 8px;margin:10px 0 0 14px}

.chip-section{margin-bottom:4px}
.chip-toggle{display:flex;align-items:center;justify-content:space-between;width:100%;background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:9px 14px;cursor:pointer;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);transition:all .2s;margin-bottom:4px}
.chip-toggle:hover{background:var(--b1);color:var(--tx)}
.chip-toggle.open{background:var(--ac);color:#fff;border-color:var(--ac)}
.chip-toggle.open .ct-arrow{transform:rotate(180deg)}
.ct-label{display:flex;align-items:center;gap:7px}
.ct-arrow{font-size:11px;transition:transform .2s}
.chip-drawer{display:none;flex-wrap:wrap;gap:6px;padding:8px 4px 10px}
.chip-drawer.open{display:flex}

.two-paths{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px}
.path-card{background:var(--s1);border:2px solid var(--b1);border-radius:var(--r2);padding:18px 16px;cursor:pointer;transition:all .2s;text-align:center}
.path-card:hover{border-color:var(--ac);transform:translateY(-2px);box-shadow:0 4px 20px #2563eb18}
.path-card.speak{border-color:var(--b1)}
.path-card.speak:hover{border-color:var(--pu)}
.path-icon{font-size:34px;margin-bottom:10px}
.path-title{font-family:var(--sf);font-size:16px;font-weight:700;color:var(--tx);margin-bottom:6px}
.path-desc{font-size:13px;color:var(--mu);line-height:1.55;margin-bottom:12px}
.path-time{font-size:11px;font-weight:600;color:var(--di);text-transform:uppercase;letter-spacing:0.08em}
.speak-form{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r2);padding:18px 16px;margin-bottom:16px;display:none}
.speak-form.active{display:block}
.speak-q{font-size:16px;font-weight:600;color:var(--tx);margin-bottom:10px}
.speak-opts{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.speak-opt{background:var(--s2);border:1.5px solid var(--b1);border-radius:var(--r1);padding:10px 14px;font-size:13px;color:var(--mu);cursor:pointer;transition:all .15s;text-align:left}
.speak-opt:hover{border-color:var(--pu);color:var(--tx)}
.speak-opt.sel{background:#7c3aed12;border-color:var(--pu);color:var(--tx);font-weight:600}
/* "I'm not sure" variant, soft / exploratory option, distinguished from real stances
   by dashed border, italic, and subtle separator. Kelly-feedback fix May 20, 2026. */
.speak-opt.unsure{border-style:dashed;font-style:italic;color:var(--di);margin-top:4px}
.speak-opt.unsure:hover{border-color:var(--ac);color:var(--ac);background:rgba(27,79,255,.03)}
.speak-opt.unsure.sel{background:rgba(27,79,255,.06);border-color:var(--ac);border-style:solid;color:var(--ac);font-weight:600;font-style:italic}
.speak-progress{display:flex;gap:4px;margin-bottom:16px}
.speak-dot{height:4px;flex:1;border-radius:var(--r0);background:var(--b2);transition:background .3s}
.speak-dot.done{background:var(--pu)}
.speak-dot.active{background:var(--ac)}
@media(max-width:480px){.two-paths{grid-template-columns:1fr}}

/* ══ SPEAK UP RESULTS ══════════════════════════════════════════════════════
   Everything submitSpeak() renders after a voice is recorded. These rules
   exist because the screen carried 48 inline style attributes and no
   stylesheet rule can reach an inline style, so the design system could not
   touch this surface at all. Reasoning:
   docs/design/interior-speak-up-results-hierarchy.md

   Measured before, matches case, EN, 390x844 on the fixture mirror: five
   filled controls with FOUR inside one 844px viewport, eleven elements in
   off-palette warm beige #e8e5dc and three in warm cream #f7f6f2. The app
   surface is --bg #f4f6f9 with cool-grey borders; those two warm values are
   from the old marketing palette. Three of them were written
   var(--b2,#e8e5dc), a token whose fallback is a DIFFERENT COLOUR from the
   token, so a failed resolve would silently change palette. ══ */

/* -- thank-you block ---------------------------------------------------- */
.su-ty{text-align:center;padding:30px 0 12px}
.su-ty-mark{font-size:52px;margin-bottom:16px}
.su-ty-title{font-family:var(--sf);font-size:22px;color:var(--civic);margin-bottom:10px}
.su-ty-body{font-size:16px;color:var(--mu);line-height:1.65;max-width:360px;margin:0 auto}
.su-ty-note{font-size:13px;color:var(--di);margin-top:12px}

/* -- what's next panel: the screen's ONE filled primary ------------------ */
.su-next{max-width:520px;margin:8px auto 0;padding:20px 22px;background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r2);box-shadow:0 2px 8px rgba(0,0,0,.04)}
.su-next-title{font-family:var(--sf);font-size:16px;font-weight:600;color:var(--civic);margin-bottom:14px;text-align:center}
.su-cta{width:100%;border-radius:var(--r1);font-family:var(--ss);cursor:pointer;text-align:left;display:flex;align-items:center;gap:10px;margin-bottom:10px}
.su-cta-icon{font-size:19px}
.su-cta-body{flex:1}
.su-cta-body b{display:block;font-weight:700}
.su-cta-sub{font-size:11px;font-weight:400;margin-top:2px}
.su-cta-arrow{font-size:16px}
/* --civic here, not --ac, and deliberately: --civic is already the filled
   button colour twelve times over in this file, so it is an established
   app-wide primary rather than a Speak Up anomaly. Redefining which token
   means primary is a system change, not a screen-group change. */
.su-cta-primary{background:var(--civic);color:#fff;border:none;padding:13px;font-size:16px;font-weight:600}
.su-cta-primary .su-cta-sub{opacity:.85}
.su-cta-secondary{background:var(--s2);color:var(--tx);border:1.5px solid var(--b1);padding:12px;font-size:16px;font-weight:600}
.su-cta-secondary .su-cta-sub{color:var(--mu)}
.su-cta-secondary .su-cta-arrow{color:var(--mu)}
.su-cta-tertiary{background:transparent;color:var(--mu);border:1px solid var(--b1);padding:11px;font-size:13px;font-weight:600;text-align:center;display:block;margin-bottom:0}
.su-next-note{text-align:center;margin-top:12px;font-size:11px;color:var(--di)}

/* -- campaign matches: secondary content, so no filled controls ---------- */
/* The strip is loaded asynchronously BELOW the primary CTAs and the code
   comment above it already says it is rendered there "so they remain the
   lead". It was contradicting itself: each card carried two filled buttons,
   one of them var(--pulse), whose only other button-fill use in the whole
   codebase is one line in this same file. Seven of eight were here. The three
   actions are now one tier of outlined chips; nothing about which actions
   exist changed and no handler changed. */
.su-matches{border-top:1px solid var(--b1);padding-top:16px;margin-top:4px}
.su-matches-title{font-family:var(--sf);font-size:16px;font-weight:600;color:var(--civic);margin-bottom:4px}
.su-matches-sub{font-size:13px;color:var(--mu);margin-bottom:12px}
.su-match{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r2);padding:14px;margin-bottom:10px}
.su-match-title{font-size:16px;font-weight:600;color:var(--civic);margin-bottom:4px}
.su-match-meta{font-size:13px;color:var(--mu);margin-bottom:10px}
.su-match-actions{display:flex;gap:6px;flex-wrap:wrap}
.su-match-btn{background:transparent;border:1.5px solid var(--b2);color:var(--tx);border-radius:var(--r1);padding:6px 12px;font-family:var(--ss);font-size:13px;font-weight:600;cursor:pointer;transition:border-color .2s,color .2s}
.su-match-btn:hover{border-color:var(--ac);color:var(--ac)}
/* Item 4b (Wave 13): the three match-card actions had no stated order --
   flagged, not built, in docs/design/interior-speak-up-results-hierarchy.md
   ("Not implemented in this pass", item 1). Now authorized, but NOT as a
   filled button: Decision 2 in that same doc already spent this screen's one
   filled-primary slot on "Build a campaign", and the R7 census in
   interior-artifact-render.js enforces at most one filled control per 844px
   window across the WHOLE screen, not per card -- two matched campaigns each
   carrying a filled "Write a Letter" would fail it on their own. So the
   primary/secondary split here stays inside the outlined tier already
   established by Decision 1 (background stays transparent, inherited from
   .su-match-btn): a coloured border and label mark Write a Letter, Acta's
   flagship action, as the recommended one, while Sign Petition and Add My
   Voice keep the neutral grey border. */
.su-match-btn-primary{border-color:var(--ac);color:var(--ac)}
.su-match-btn-primary:hover{border-color:var(--ac2);color:var(--ac2)}
.su-match-report{background:transparent;border:none;color:var(--di);font-family:var(--ss);font-size:11px;cursor:pointer;padding:6px 8px}
.su-match-report:hover{color:var(--mu)}
.su-nomatch{border-top:1px solid var(--b1);padding-top:14px;margin-top:4px;font-size:13px;color:var(--di);text-align:center}

/* -- related brief cross-link ------------------------------------------- */
/* Was a blue-to-purple gradient with a blue border, which made an
   asynchronously loaded suggestion the loudest block on the screen, above
   both the thank-you and the primary CTA. Quiet neutral card now. Same call
   already taken for .inf-questions in the Get Informed brief pass, taken the
   same way so the product has one answer to one question. */
.su-rb{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);padding:16px 18px;text-align:left;cursor:pointer}
.su-rb-label{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--mu);margin-bottom:6px}
.su-rb-title{font-size:16px;font-weight:700;color:var(--tx);line-height:1.65;margin-bottom:4px}
.su-rb-meta{font-size:11px;color:var(--mu);margin-bottom:6px}
.su-rb-summary{font-size:13px;color:var(--mu);line-height:1.55;margin-bottom:8px}
.su-rb-read{font-size:13px;font-weight:600;color:var(--ac)}

/* -- async slots -------------------------------------------------------- */
.su-slot{max-width:520px;margin:16px auto 0}
.su-slot-tight{max-width:520px;margin:8px auto 0}

.brief-edit-zone[contenteditable="true"]{
  outline:2px solid var(--ac);
  border-radius:var(--r1);
  padding:8px;
  background:var(--s2);
  cursor:text;
}

.champion-banner{background:linear-gradient(135deg,#f5a62320,#2563eb15);border:2px solid #f5a62340;border-radius:var(--r2);padding:16px 18px;margin-bottom:14px;display:none}
.champion-banner.earned{display:flex;align-items:center;gap:14px}
.champion-trophy{font-size:42px;flex-shrink:0}
.champion-text{flex:1}
.champion-title{font-family:var(--sf);font-size:19px;font-weight:700;color:var(--tx);margin-bottom:4px}
.champion-desc{font-size:13px;color:var(--mu);line-height:1.55;margin-bottom:8px}
.champion-share{display:inline-flex;align-items:center;gap:6px;background:var(--am);color:#fff;border:none;border-radius:var(--r1);padding:6px 13px;font-family:var(--ss);font-size:13px;font-weight:700;cursor:pointer}

/* == NEW DESIGN == */
.logo-dot{color:var(--ac)}
.stepbar,.steps{background:rgba(247,246,242,.95);border-bottom:1px solid var(--b1);display:flex;align-items:center;justify-content:center;padding:0 20px;height:40px;overflow-x:auto;scrollbar-width:none}
.st,.step{display:flex;align-items:center;gap:5px;padding:0 10px;font-size:11px;font-weight:600;color:var(--di);white-space:nowrap;opacity:.6;border-bottom:none}
.st.ac,.step.active{opacity:1;color:var(--ac)}
.sn,.step-num{width:16px;height:16px;border-radius:50%;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;background:var(--b1);color:var(--di);flex-shrink:0}
.st.ac .sn,.step.active .step-num{background:var(--ac);color:#fff}
.slb{display:none}
.sl,.step-div{font-size:11px;color:var(--b3);padding:0 2px;background:none;height:auto;flex:none;min-width:0}
/* NOTE: .hero, .ey, .h1, .hsb, and the legacy .hiw rules previously lived
   here as a "DESIGN SYSTEM 2, FINAL" middle layer. They've been removed.
   Single source of truth is now the "REDESIGNED HOME SCREEN" block below.
   The .hiw rules are dead code, the 6-step flow markup now uses
   .flow-section / .flow-strip / .flow-step. */

/* ── Trust line, sits inside .hero just below the subhead ──────────────
   Defuses AI skepticism in 13 words. Visible immediately to first-time
   visitors so the "AI + civic action" pairing doesn't trigger reflexive
   skepticism. Color/contrast tuned to read clearly on the hero gradient
   background without competing with the headline. */
.trust-line{
  display:block;text-align:center;
  font-size:16px;line-height:1.65;
  color:rgba(255,255,255,.92);
  margin:48px auto 0;
  max-width:560px;
}
.trust-line strong{color:#fff;font-weight:600}
/* One step above the surrounding text (14px -> 16px, same 2px increment the
   mobile override below uses), so the icon reads as a deliberately larger
   mark rather than same-size-as-text-by-coincidence. */
.trust-icon{font-size:16px}
/* white-space:nowrap on the whole link (2026-08-01, reverses the decision
   this comment used to describe). The nbsp-only-between-"more"/"mas"-and-
   the-arrow approach below still let "Learn"/"Conoce" split from "more
   &rarr;"/"mas &rarr;" onto the next line at 390px, which is a worse break
   than the one the nbsp-only approach was chosen to avoid: a single word
   left alone at the end of a line. nowrap makes "Learn more &rarr;"/
   "Conoce mas &rarr;" one atomic unit that can never split internally --
   it either sits on the current line or wraps down complete. The nbsp
   between "more"/"mas" and the arrow is now redundant (nowrap already
   forbids every break inside the link) but left in place since removing it
   changes content, not layout, and is not required for this fix. The
   space BEFORE "Learn"/"Conoce" (between the preceding sentence and the
   link) is NOT inside .trust-link, so it stays normally breakable -- the
   atomic link still flows up next to the preceding text whenever there is
   room, exactly as before; only the link's OWN internal wrapping changed. */
.trust-link{color:rgba(255,255,255,.85);text-decoration:underline;text-underline-offset:2px;margin-left:4px;white-space:nowrap}
.trust-link:hover{color:#fff}
@media(max-width:600px){
  .trust-line{font-size:13px;line-height:1.6}
  .trust-icon{font-size:16px}
}

/* ── Flow section, the 6-step product flow that replaces the old hiw ───
   Visual answer to "what does Acta actually do?". Six numbered steps with
   icons that make the flow Issue → Brief → Reps → Letter → Campaign →
   Share unmistakable. Horizontal on desktop, vertical on mobile. */
/* How Acta Works, DARK NAVY block.
   This is the most important section on the homepage, the visual answer
   to "what does Acta DO?". Dark navy gives it the same visual weight as
   the hero, creating the alternating dark/light rhythm that signals
   "the product flow IS the main story." */
.flow-section{
  margin:36px 0 32px;
  background:#0f2057;
  border-radius:var(--r2);
  padding:30px 28px 28px;
  position:relative;
  overflow:hidden;
}
.flow-section::before{
  content:'';
  position:absolute;
  inset:0;
  background:
    radial-gradient(ellipse at 30% 30%, rgba(27,79,255,.22) 0%, transparent 55%),
    radial-gradient(ellipse at 75% 70%, rgba(27,79,255,.14) 0%, transparent 50%);
  pointer-events:none;
}
.flow-label{
  font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;
  color:#7ba3ff;margin-bottom:18px;display:flex;justify-content:center;align-items:center;gap:10px;
  position:relative;z-index:1;
}
.flow-label::before,.flow-label::after{content:'';display:block;height:1px;width:28px;background:rgba(255,255,255,.2)}
.flow-strip{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:16px;
  background:transparent;
  border:none;
  border-radius:0;
  padding:0;
  box-shadow:none;
  position:relative;z-index:1;
}
.flow-phase{display:flex;flex-direction:column;gap:12px;position:relative;z-index:1}
.flow-phase-label{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:#9db4ff;text-align:center}
.flow-phase-steps{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.flow-step{
  text-align:center;padding:8px 6px;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  position:relative;
}
.flow-step:not(:last-child)::after{
  display:none;
  content:'→';
  position:absolute;
  right:-8px;top:28px;
  font-size:16px;
  color:rgba(255,255,255,.35);
  z-index:1;
}
.flow-num{
  width:26px;height:26px;
  display:flex;align-items:center;justify-content:center;
  background:#1b4fff;color:#fff;
  border-radius:50%;
  font-family:var(--ss);font-size:11px;font-weight:700;
  margin-bottom:10px;
  box-shadow:0 0 0 3px rgba(27,79,255,.18);
}
.flow-icon{margin-bottom:8px;line-height:0;opacity:.95}
.flow-icon svg{width:24px;height:24px;color:rgba(255,255,255,.92)}
.path-icon svg{width:38px;height:38px;display:block;margin:0 auto;color:var(--civic)}
.flow-title{
  font-family:var(--sf);font-size:19px;font-weight:400;
  color:#ffffff;margin-bottom:5px;line-height:1.6;
}
.flow-desc{font-size:13px;color:rgba(255,255,255,.72);line-height:1.5}
@media(max-width:760px){
  .flow-section{margin:40px 0 32px;padding:16px 18px;border-radius:var(--r2);min-height:84dvh;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center}
  .flow-strip{grid-template-columns:1fr;gap:24px;padding:0;border-radius:0}
  .flow-phase{gap:8px}
  .flow-phase-label{text-align:left;font-size:11px;margin-bottom:2px}
  .flow-phase-steps{grid-template-columns:1fr;gap:15px}
  .flow-step{
    text-align:left;
    display:grid;grid-template-columns:auto auto 1fr;
    grid-template-areas:"num icon text";
    align-items:start;
    column-gap:12px;
    padding:6px 4px;
  }
  .flow-step:last-child{border-bottom:none}
  .flow-step:not(:last-child)::after{display:none}
  .flow-num{margin-bottom:0;grid-area:num}
  .flow-icon{margin-bottom:0;font-size:28px;grid-area:icon}
  .flow-text{grid-area:text}
  .flow-title{font-size:16px;font-weight:600;margin-bottom:5px}
  .flow-desc{font-size:16px;line-height:1.5}
}

/* ── For Organizations callout, appears at the bottom of screen 1 ──────
   A quiet but visible bridge to the org product without disrupting the
   citizen-first hero flow. Subtle accent stripe rather than full color
   block so it doesn't compete with the path cards above. */
.org-callout{
  margin:32px 0 -48px;padding:24px 26px;
  background:var(--s1);
  border:1px solid var(--b1);
  border-radius:var(--r2);
  display:flex;flex-direction:column;align-items:flex-start;gap:6px;
}
.org-callout-label{
  font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;
  color:var(--ac);margin-bottom:4px;
}
.org-callout-title{
  font-family:var(--sf);font-size:22px;font-weight:400;
  color:var(--civic);line-height:1.45;
}
.org-callout-desc{
  font-size:16px;color:var(--mu);line-height:1.65;
  max-width:640px;margin-bottom:6px;
}
.org-callout-cta{
  display:inline-block;margin-top:4px;
  font-family:var(--ss);font-size:16px;font-weight:600;color:var(--ac);
  background:var(--s1);border:1.5px solid var(--ac);border-radius:var(--r1);
  padding:11px 22px;text-decoration:none;
  transition:background .15s ease,color .15s ease,box-shadow .15s ease;
}
.org-callout-cta:hover{background:var(--civic);color:#fff;box-shadow:0 4px 14px rgba(15,32,87,.22)}
@media(max-width:600px){
  .org-callout{padding:20px 18px}
  .org-callout-title{font-size:19px}
}

/* ── Proof section, real product screenshots on the homepage ───────────
   The reviewer's strongest single critique: Acta looks conceptual without
   product proof. This section addresses it directly with 3 product screens
   showing the actual product flow. Each screen is captioned with what it
   does so a skim-reader gets the value prop visually. */
.proof-section{
  margin:36px 0 28px;
}
.proof-label{
  font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;
  color:var(--ac);text-align:center;margin-bottom:8px;
}
.proof-title{
  font-family:var(--sf);font-size:28px;font-weight:400;line-height:1.3;
  color:var(--civic);text-align:center;margin:0 auto 22px;
  max-width:800px;
}
.proof-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:18px;
}
.proof-item{
  background:var(--s1);
  border:1px solid var(--b1);
  border-radius:var(--r2);
  overflow:hidden;
  display:flex;flex-direction:column;
  box-shadow:0 2px 12px rgba(15,32,87,.06);
  transition:transform .2s,box-shadow .2s;
}
.proof-item:hover{
  transform:translateY(-2px);
  box-shadow:0 8px 22px rgba(15,32,87,.1);
}
.proof-img{
  display:block;
  width:100%;
  height:auto;
  border-bottom:1px solid var(--b1);
  background:#f7f6f2;
  cursor:zoom-in;
}
.proof-caption{
  padding:14px 16px 16px;
}
.proof-caption-title{
  font-family:var(--sf);font-size:16px;font-weight:400;
  color:var(--civic);margin-bottom:4px;line-height:1.65;
}
.proof-caption-desc{
  font-size:13px;color:var(--mu);line-height:1.6;
}
@media(max-width:760px){
  .proof-grid{grid-template-columns:1fr;gap:14px}
  .proof-title{font-size:22px}
  .proof-section{margin:24px 0 16px}
}

/* Path cards */
.two-paths{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:20px}
.path-card{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r3);padding:24px 20px;cursor:pointer;transition:all .2s;position:relative;overflow:hidden;box-shadow:0 2px 10px rgba(15,32,87,.06);display:flex;flex-direction:column}
.path-card::before{content:none}
.path-card:hover{transform:translateY(-3px);box-shadow:0 8px 24px rgba(15,32,87,.12)}
.path-card.action:hover{border-color:rgba(27,79,255,.25)}
.path-card.informed:hover{border-color:rgba(10,124,82,.3)}
.path-card.speak:hover{border-color:rgba(234,88,12,.25)}
.path-icon{font-size:42px;margin-bottom:12px;display:block}
.path-title{font-family:var(--sf);font-size:22px;color:var(--civic);margin-bottom:8px;line-height:1.2}
.path-desc{font-size:13px;color:#2b3257;line-height:1.55;margin-bottom:14px;text-align:left}
.path-time{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;margin-top:auto}
/* Per-card duration colours REMOVED (component spec): three parallel cards
   in three colours read as a traffic-light status system, and on Take Action
   the duration was the same blue as the button, i.e. a second link. */

/* Inner screen cards */
.cd{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r3);padding:22px;margin-bottom:12px;box-shadow:0 2px 8px rgba(15,32,87,.05)}
.sc{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r3);padding:24px 28px;margin-bottom:16px;box-shadow:0 2px 8px rgba(15,32,87,.05)}

/* Primary button */
.ba{background:var(--civic);border-radius:var(--r2);box-shadow:0 4px 14px rgba(15,32,87,.22);font-family:var(--ss)}
.ba:hover{background:#0a1a40;transform:translateY(-1px)}

/* Chips */
.chip{background:var(--s1);border:1px solid var(--b2);border-radius:var(--r3);padding:5px 13px;font-size:13px;font-weight:600;color:var(--mu);cursor:pointer;transition:all .15s;-webkit-tap-highlight-color:rgba(27,79,255,.15)}
.chip:hover{border-color:var(--ac);color:var(--ac)}
.chip.sel{background:rgba(27,79,255,.08);border-color:var(--ac);color:var(--ac);font-weight:600}
/* May 20 2026, UX fix: explicit checkmark + ✕ affordance on selected chips
   so users see at a glance that the chip is selected AND that tapping
   again will deselect it. Previously the only signal was a subtle color
   change which was hard to read on small mobile chips, leading users to
   believe their second tap "wasn't working" when in fact it was. */
.chip.sel::before{content:'✓ ';font-weight:700}
.chip.sel::after{content:' ✕';opacity:.6;font-size:11px;margin-left:2px}
/* Bigger touch target on mobile, iOS HIG recommends 44px minimum.
   Default chip is ~28px tall which is too small for confident second-tap. */
@media(max-width:540px){
  .chip{padding:8px 14px;font-size:13px;min-height:36px;display:inline-flex;align-items:center}
}
.chip-toggle{display:flex;align-items:center;justify-content:space-between;width:100%;background:var(--s2);border:1px solid var(--b1);border-radius:var(--r1);padding:10px 14px;cursor:pointer;font-family:var(--ss);font-size:13px;font-weight:600;color:var(--mu);margin-bottom:5px;transition:all .15s}
.chip-toggle:hover{background:var(--s1);border-color:var(--b2)}
.chip-toggle.open{background:rgba(27,79,255,.05);border-color:rgba(27,79,255,.2);color:var(--ac)}
.ct-arrow{transition:transform .2s}
.chip-toggle.open .ct-arrow{transform:rotate(180deg)}
.chip-drawer{display:none;flex-wrap:wrap;gap:6px;padding:6px 0 10px}
.chip-drawer.open{display:flex}

/* Entry animation */
@keyframes fadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}
.pg{animation:fadeUp .3s ease both}

/* Onboard strip */
.os-num{width:20px;height:20px;border-radius:50%;background:var(--ac);color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.os-div,.os-arr{font-size:11px;color:var(--b3);padding:0 1px}

/* ── MOBILE OVERRIDES, must come last to override everything above ── */
@media(max-width:600px){
  .h1{font-size:42px;line-height:1.12;letter-spacing:-0.02em}
  .hsb{font-size:16px}
  .hiw{flex-direction:column;gap:0;border-radius:var(--r2)}
  .hiw-item{flex:none;width:100%;border-right:none;border-bottom:1px solid var(--b1);padding:14px 16px;text-align:left;flex-direction:row;align-items:center;gap:12px;justify-content:flex-start}
  .hiw-item:last-child{border-bottom:none}
  .hiw-icon{font-size:22px;flex-shrink:0;width:32px;height:32px;margin-bottom:0;display:flex;align-items:center;justify-content:center}
  .hiw-label{font-size:13px;font-weight:600;margin-bottom:2px;text-align:left}
  .hiw-desc{font-size:13px;text-align:left}
  .path-card{padding:18px 16px}
  .path-icon{font-size:28px;margin-bottom:8px}
  .path-title{font-size:19px}
  .two-paths{gap:10px}
}
@media(max-width:380px){
  .h1{font-size:34px;line-height:1.12}
  .two-paths{grid-template-columns:1fr}
}

/* ── REDESIGNED HOME SCREEN ─────────────────────────────────────────── */

/* CANONICAL HOME HERO, single source of truth.
   Dark navy block, viewport-edge full-bleed, with radial gradient.
   All font-family/size/layout properties live HERE, earlier duplicate
   layers were removed. min-height ensures visual parity with the other
   page heroes (FAQ, Contact, Organizations) which use .page-hero. */
.hero{
  background:var(--civic);
  border-radius:0;
  position:relative;
  width:100vw;
  margin-left:calc(50% - 50vw);
  padding:48px 28px 44px;
  min-height:248px;
  text-align:center;
  display:flex;
  flex-direction:column;
  justify-content:center;
  align-items:center;
  box-sizing:border-box;
}
.hero::before{
  content:'';
  position:absolute;
  inset:0;
  background:
    radial-gradient(ellipse at 30% 50%,rgba(27,79,255,.22) 0%,transparent 60%),
    radial-gradient(ellipse at 70% 20%,rgba(27,79,255,.14) 0%,transparent 50%);
  pointer-events:none;
}
.hero>*{position:relative;z-index:1}

/* Eyebrow label with decorative side rules */
.ey{
  display:inline-flex;
  align-items:center;
  gap:10px;
  font-size:13px;
  font-weight:700;
  letter-spacing:0.14em;
  text-transform:uppercase;
  /* Same accent as .h1 em ("Be heard"). 6.25:1 on --civic #0f2057. */
  color:#7ba3ff;
  margin-bottom:24px;
}
.ey::before,.ey::after{
  content:'';
  display:block;
  height:1px;
  width:28px;
  background:rgba(255,255,255,.2);
}

/* Hero headline, Instrument Serif Roman with italic accent on "amplified." */
.h1{
  font-family:var(--sf);
  font-size:52px;
  font-weight:400;
  line-height:1.06;
  /* -0.02em, the display step. The tracking snap first landed this rule on
     -0.01em (nearest to the legacy -0.5px at 42px) and the hero's first line,
     already borderline at 390px, wrapped mid-sentence. The static hero's own
     generated rule says -.02em for this element; the two now agree, and the
     line fits again with margin instead of by luck. */
  letter-spacing:-0.02em;
  color:#ffffff;
  max-width:720px;
  margin:0 auto 10px;
}
.h1 em{
  font-style:italic;
  /* identity: the thesis line is the page's human moment, in the warm
     amber role (light variant #f0c091, 9.27:1 on the navy field) */
  color:#f0c091;
}
/* identity ripple: one voice spreading outward, from the mark's rings.
   Heroes only on this page; animates once on load, still under
   prefers-reduced-motion. */
.hero{position:relative;overflow:hidden}
.hero::after{
  content:'';position:absolute;right:-140px;top:-140px;width:430px;height:430px;pointer-events:none;
  background:var(--ripple-rings) center/contain no-repeat;
  animation:ripple-in 1.4s ease-out both;
}
@keyframes ripple-in{from{transform:scale(.72);opacity:0}to{transform:scale(1);opacity:1}}
@media(prefers-reduced-motion:reduce){.hero::after{animation:none}}
/* Batch 34: the ring that actually travels. Resting field above is
   unchanged; this one starts at .22 white (measured: the .10 field peaks at
   a 24/255 delta, which reads as nothing in motion), expands past rest and
   fades to zero. Own element because both hero pseudo-elements are taken.
   CONTINUOUS, not one arrival: the element is a box and the two rings are its
   own ::before/::after, each running the same 2.2s flight on a 3.5s cycle with
   the second offset half a cycle (1.9s = .15 + 1.75), so one ring is always
   mid-flight. The flight is written as percentages of the cycle
   (2.2/3.5 = 62.86%) so the motion is identical to the arrival that measured a
   44/255 peak delta; only the repeat is new. ripple-motion.js adds .rp-paused
   when the hero leaves the viewport or the tab is hidden. */
/* Selectors are the CLASS alone, deliberately: the scoped .hero prefix carried
   enough specificity that the base rule's animation SHORTHAND (which resets
   animation-play-state to running) beat the .rp-paused override, so the pause
   silently did nothing. Measured, then fixed. */
.rp-travel{
  position:absolute;right:-140px;top:-140px;width:430px;height:430px;
  pointer-events:none;z-index:0;
}
.rp-travel::before,.rp-travel::after{
  content:'';position:absolute;left:0;top:0;right:0;bottom:0;opacity:0;
  background:var(--ripple-rings-travel) center/contain no-repeat;
  animation:ripple-travel 3.5s cubic-bezier(.22,.61,.36,1) .15s infinite;
}
.rp-travel::after{animation-delay:1.9s}
.rp-travel.rp-paused::before,.rp-travel.rp-paused::after{animation-play-state:paused}
@keyframes ripple-travel{0%{transform:scale(.17);opacity:0}4%{opacity:.22}62.86%{transform:scale(1.5);opacity:0}100%{transform:scale(1.5);opacity:0}}
@media(prefers-reduced-motion:reduce){.rp-travel{display:none}.rp-travel::before,.rp-travel::after{animation:none}}
/* Generation wait: while a brief is generating, rings emanate outward
   continuously BENEATH the existing stage copy (no new copy: the four
   stage lines and the long-wait line are exactly what shipped). Three rings
   on staggered delays read as a continuous emanation. The state resolves
   by itself: the screen swaps to the brief when it arrives. */
.ls{position:relative;overflow:hidden}
.ls>*{position:relative;z-index:1}
.ls::before,.ls::after{
  content:'';position:absolute;left:50%;top:96px;width:300px;height:300px;margin:-150px 0 0 -150px;
  pointer-events:none;z-index:0;
  background:var(--ripple-rings-travel-ink) center/contain no-repeat;
  animation:ls-emanate 2.8s ease-out infinite;
}
.ls::after{animation-delay:1.4s}
@keyframes ls-emanate{0%{transform:scale(.35);opacity:0}15%{opacity:.20}100%{transform:scale(1.5);opacity:0}}
@media(prefers-reduced-motion:reduce){.ls::before,.ls::after{animation:none;display:none}}

/* Hero subhead, wide enough to fit the four-sentence functional string
   on a single line at desktop. 720px is calibrated for the string
   "Describe an issue. Get a sourced brief. Find your representatives. Take action."
   at 17px line-height 1.6 to remain on one line through 1024px viewport.
   Vertical position: split 25px/23px rather than 0/48px so the subhead sits
   closer to the headline than to the button (roughly 60/40 of the 58px
   total span between the headline's bottom edge and the button's top edge:
   h1's own 10px margin-bottom + this 25px = 35px above, 23px below). The
   SUM stays 48px, same as before, so the hero's total content height and
   floor are unaffected -- only the split within it moved. */
.hsb{
  font-size:19px;
  color:rgba(255,255,255,.8);
  line-height:1.6;
  max-width:720px;
  margin:25px auto 23px;
}

@media(max-width:760px){
  .hero{padding:48px 20px 40px;min-height:92dvh}
  /* hero display role: 36/1.15. The hero is the site's single display
     moment, so it keeps its own named size above the interior H1 role
     (34); enforced by the checker's hero-display rule. */
  .h1{font-size:42px;line-height:1.12}
  .hsb{font-size:16px;max-width:none}
}

/* Item 7: fill the viewport on short screens (phones + tablets) with the
   dynamic viewport unit (dvh) so mobile browser chrome does not cause a jump.
   min-height only GROWS -- where hero content already exceeds the viewport it
   keeps its natural height. Desktop (>1024px) is intentionally EXCLUDED so its
   hero is unchanged and "How Acta works" stays partly visible above the fold. */
@media(min-width:761px) and (max-width:1024px){
  .hero{min-height:92dvh}
}

/* .hiw block removed, markup migrated to .flow-section */

/* Section label above path cards */
.paths-label{text-align:center;font-size:13px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--ac);margin:40px 0 8px}.paths-subtitle{text-align:center;font-size:16px;font-weight:600;color:var(--tx);margin:0 0 16px;line-height:1.65;max-width:600px;margin-left:auto;margin-right:auto}

/* Path cards: taller, bolder, more immersive */
.two-paths{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:20px}
.path-card{background:var(--s1);border:1.5px solid var(--b1);border-radius:var(--r3);padding:28px 22px 24px;cursor:pointer;transition:all .22s;position:relative;overflow:hidden;box-shadow:0 4px 16px rgba(15,32,87,.08)}
.path-card::before{content:none}
.path-card:hover{transform:translateY(-4px);box-shadow:0 12px 32px rgba(15,32,87,.15)}
.path-card.action:hover{border-color:rgba(27,79,255,.3)}
.path-card.informed:hover{border-color:rgba(10,124,82,.35)}
.path-card.speak:hover{border-color:rgba(234,88,12,.3)}
.path-icon{font-size:42px;margin-bottom:14px;display:block}
.path-title{font-family:var(--sf);font-size:22px;color:var(--civic);margin-bottom:8px;line-height:1.2}
.path-desc{font-size:13px;color:#2b3257;line-height:1.55;margin-bottom:16px}
.path-time{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;display:inline-flex;align-items:center;gap:6px}
/* Per-card duration colours REMOVED (component spec): three parallel cards
   in three colours read as a traffic-light status system, and on Take Action
   the duration was the same blue as the button, i.e. a second link. */
.path-arrow{font-size:16px;transition:transform .2s}
.path-card:hover .path-arrow{transform:translateX(3px)}
/* ── Inline path expansion: active-card highlight + entry panel ──────────── */
.three-paths.has-active .path-card:not(.is-active){opacity:1}
.path-card.action.is-active{box-shadow:0 10px 30px rgba(27,79,255,.20);border-color:var(--ac);background:rgba(27,79,255,.05)}
.path-card.informed.is-active{box-shadow:0 10px 30px rgba(10,124,82,.20);border-color:var(--gr);background:rgba(10,124,82,.05)}
.path-card.speak.is-active{box-shadow:0 10px 30px rgba(234,88,12,.20);border-color:#ea580c;background:rgba(234,88,12,.05)}
.path-card.is-active::before{height:6px}
.path-card.is-active .path-arrow{transform:rotate(90deg)}
.path-expand.is-open{margin-top:14px}
.path-expand.is-open > #take-action-section,
.path-expand.is-open > .speak-form.active{animation:pathExpandIn .24s ease both}
@keyframes pathExpandIn{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}

/* Mobile overrides for redesign */
@media(max-width:600px){
  .hero{width:100vw;margin-left:calc(50% - 50vw);padding:48px 20px 44px;min-height:92dvh}
  .hiw{flex-direction:column;overflow:visible}
  .hiw-item{flex:none;width:100%;border-right:none;border-bottom:1px solid rgba(255,255,255,.08);padding:16px 20px;flex-direction:row;align-items:center;text-align:left;gap:14px}
  .hiw-item:last-child{border-bottom:none}
  .hiw-emoji{width:38px;height:38px;font-size:19px;flex-shrink:0;margin:0}
  .hiw-text{flex:1;text-align:left}
  .hiw-label{font-size:16px;font-weight:600;margin-bottom:3px}
  .hiw-desc{font-size:13px}
  .path-card{padding:22px 18px 20px}
  .path-icon{font-size:34px;margin-bottom:10px}
  .path-title{font-size:19px}
  .two-paths{gap:12px}
}
@media(max-width:380px){
  .two-paths{grid-template-columns:1fr}
}

.badges-row{display:flex;gap:10px;flex-wrap:wrap;margin:16px 0}
.badge-pill{display:inline-flex;align-items:center;gap:6px;background:#fff;border:1.5px solid var(--b1);border-radius:var(--rp);padding:6px 14px;font-size:13px;font-weight:600;color:var(--mu);transition:all .2s}
.badge-pill.earned{border-color:var(--civic);color:var(--civic);background:rgba(15,32,87,.04)}
.badge-pill .badge-icon{font-size:16px}
.p2p-card{background:linear-gradient(135deg,var(--civic) 0%,#1b4fff 100%);border-radius:var(--r2);padding:20px;margin:16px 0;color:#fff}
.p2p-card h3{font-size:16px;font-weight:700;margin-bottom:6px}
.p2p-card p{font-size:13px;opacity:.8;margin-bottom:14px;line-height:1.4}
.p2p-ref-wrap{display:flex;gap:8px}
.p2p-ref-input{flex:1;background:rgba(255,255,255,.15);border:1px solid rgba(255,255,255,.3);border-radius:var(--r1);padding:9px 12px;font-size:13px;color:#fff;outline:none;min-width:0}
.p2p-copy-btn{background:#fff;color:var(--civic);border:none;border-radius:var(--r1);padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer;white-space:nowrap;flex-shrink:0}
.p2p-copy-btn.copied{background:#10b981;color:#fff}
/* A18: the only button-shaped element on a path card used to be the DURATION,
   so the thing that looked like the action was a time estimate. The verb is the
   button now; the duration is plain supporting text beside it. The whole card
   is still the click target (role=button on .path-card), so this changes what
   the eye lands on, not how it is operated. */
/* Component spec (docs/design/component-spec.md): the primary action is a
   full-bleed NAVY button inside the card padding -- never inline-flex, never
   flex-start, never the accent blue. */
.path-cta{font-size:14px;font-weight:700;font-family:var(--ss);color:#fff;background:var(--civic);border-radius:var(--r1);padding:0 16px;min-height:48px;margin-top:14px;display:flex;width:100%;justify-content:center;align-items:center;gap:6px;box-sizing:border-box}
.path-card:hover .path-cta{background:var(--civic-h)}
/* Component spec: the duration is a CAPTION -- small neutral grey, centred
   beneath the button, never bold, never colour-coded per card. */
.path-time{font-size:12px;color:var(--mu);margin-top:8px;font-weight:500;display:block;text-align:center;background:none;border-radius:0;padding:0;text-transform:none;letter-spacing:normal}

/* ───────────────────────────────────────────────────────────────────────────
   May 25 2026, MOBILE READABILITY PASS (tester feedback: text too small).
   Audit found body/reading copy clustered at 11-13px, below the 16px mobile
   norm (Apple HIG / Material / WCAG). This block lifts READING TEXT on phones
   only, base body to 16px and paragraph/body classes to ~15-16px, while
   deliberately leaving intentional chrome (uppercase eyebrows, badges, chips,
   pills, fine-print labels) at their designed sizes, since enlarging those
   would break tight layouts and read wrong. Desktop is untouched.
   ─────────────────────────────────────────────────────────────────────────── */
@media (max-width:600px){
  /* Base reading size clears the 16px floor. */
  body{font-size:16px;line-height:1.6}
  /* Body/paragraph copy a user actually reads, lift 13px→15.5px, 14px→15.5px. */
  .optin p, .ri p, .dest p,
  .leg-opt-text, .leg-output-text,
  .leg-showcase-desc, .leg-showcase-note,
  .path-desc{font-size:16px;line-height:1.6}
  /* Readable secondary/support text and links, lift 11-12px→14px. */
  .share-note, .optin-note, .ps-tip, .tip,
  .leg-showcase-note, .back-top, .path-time{font-size:16px}
  /* Inputs at 16px also prevent iOS Safari's auto-zoom-on-focus. */
  .optin-row input, .link-input{font-size:16px}
  /* NOTE: uppercase label/eyebrow/badge classes (.lb .stl .csec .rp .sll
     .leg-section-label .leg-output-label .tool-section-label .np .chip .cc)
     are intentionally left small. They are chrome, not reading text. */
}

    /* ── Three-path cards: container is class "three-paths" but only ".two-paths"
       was ever styled, so the cards weren't gridded and the per-card time labels
       floated to different heights. High-specificity + self-contained so it wins
       over the three legacy .path-card layers without depending on their cascade. */
    .three-paths{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:16px;align-items:stretch}
    .three-paths .path-card{display:flex;flex-direction:column;height:100%;justify-content:space-between}
    /* margin-top:0, not just "no auto": .path-time carries an authored
       margin-top:12px that the old margin-top:auto was silently overriding
       (auto resolves to 0 on the card that defines the height). Dropping the
       override without this let that 12px back in and grew EVERY card by 12px,
       measured. Zeroing it keeps the geometry the auto margin produced and
       leaves the distribution to justify-content. */
    /* 2026-08-16 component spec: 8px of breathing room between the full-bleed
       navy button and its centred caption. (The old margin-top:0 note above
       predates the button being full-width.) */
    .three-paths .path-time{align-self:center;margin-top:8px}
    /* justify-content:space-between instead of margin-top:auto on the time line.
       The auto margin collected the ENTIRE equalising slack into one gap, so the
       card that needed the least height showed all of its extra space in a
       single band above the time line: measured at 390px, Take Action's
       description-to-time gap ran 16px -> 41px in English and 16px -> 66px in
       Spanish, which is why a taller card read as an emptier one. Spreading it
       across the four internal gaps keeps the card balanced rather than
       bottom-weighted. The authored rhythm is untouched and still on the 8 grid;
       what the layout adds on top is computed slack, not an authored value, and
       it divides by the number of gaps rather than landing anywhere by hand. */
    /* grid-auto-rows:1fr is what makes the cards equal at EVERY width. Across
       three columns the single row already stretched them; stacked at <=760px
       each card sat in its OWN row, so the shortest copy (Take Action) rendered
       short. Equal rows fix it by layout: no fixed heights, no padding hacks,
       and the tallest card still defines the height at any breakpoint.

       SCOPED TO :not(.has-active), and that scope is the whole point.
       positionPathExpand() MOVES #path-expand INSIDE this grid at <=760px, so
       the opened intake panel becomes a grid ROW. With unconditional
       grid-auto-rows:1fr every row equalises to the tallest, and the tallest is
       then a ~390px panel: measured at 390x844, tapping Take Action inflated all
       three cards from 295px to 685px, two of them mostly empty. Equal heights
       are a property of the DEFAULT state; once a card is active the set sizes
       to its own content again. At >760px the panel is placed after the grid
       instead, so the single three-column row still stretches on its own and
       desktop keeps equal heights either way. */
    .three-paths:not(.has-active){grid-auto-rows:1fr}
    @media(max-width:760px){.three-paths{grid-template-columns:1fr;gap:12px}}

    /* ── Footer (unified across all pages) ─────────────────────────────── */
    footer{max-width:720px;margin:0 auto;padding:24px 20px 40px;border-top:1px solid var(--b1);text-align:center;font-size:13px;color:var(--mu);line-height:2}
    footer a{color:var(--mu);font-weight:600;text-decoration:none;margin:0 10px}
    footer a:hover{color:var(--ac)}
    footer span.divider{color:var(--b2)}
    footer span.copyright{margin:0 10px;white-space:nowrap}
    /* A4: on a phone every footer link became a full-width block, so 15 links
       stacked at ~26px each and the footer alone was 489 CSS px -- more than a
       tenth of the whole brief page, spent on site chrome the reader did not
       come for. Two columns halve the stack without shrinking any tap target
       (each cell is still a full row height), and the social row and copyright
       span both columns. Measured, not estimated: see the A4 note in the PR. */
    @media (max-width:600px){
      footer{display:grid;grid-template-columns:1fr 1fr;gap:0 10px;justify-items:center;padding:20px 20px 24px;line-height:1.7}
      footer a{display:block;margin:5px 0}
      footer span.divider{display:none}
      footer span.footer-social,footer span.copyright{grid-column:1 / -1;display:block;margin:8px 0 0}
    }

/* ═══════════════════════════════════════════════════════════════════════════
   INTERACTIVE AND NON-IDEAL STATES -- one definition, every surface
   ---------------------------------------------------------------------------
   Added 2026-08-14. NO new colour, font, radius or spacing value appears below:
   every value is an existing :root token or an existing pattern lifted from
   marketing-shell.css. This is the system that is already declared at the top of
   this file, applied to the states that were never written.

   WHAT WAS MEASURED, BEFORE ANY OF THIS WAS WRITTEN
   -------------------------------------------------
   This file carried 70 `:hover` rules across 56 distinct interactive elements
   and exactly ONE `:focus-visible` -- `.ta-skip`, the skip link. Zero `:active`.
   One `:disabled`. So every button, card, chip and option in the app responded
   to a mouse and to nothing else: a keyboard user could not see where they were,
   a press produced no acknowledgement, and a disabled control looked identical
   to a live one.

   Missing states are the most common reason working software reads as a
   prototype, and the focus half is also an accessibility requirement rather
   than a preference.

   `--focus-ring` is NOT invented here. marketing-shell.css already defines the
   pattern: it resolves to --civic by default and is overridden to #ffffff inside
   dark heroes so the ring stays visible on a dark ground. That override is
   repeated here for this file's dark surfaces. The only change is that the
   token is now declared rather than reached through nine copies of a fallback.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{ --focus-ring:var(--civic) }
.hero,.page-hero,.brief-hero{ --focus-ring:#ffffff }

/* FOCUS. :focus-visible only, so a mouse press never draws a ring the way a
   blanket :focus rule would -- that is why the pattern is worth copying rather
   than widening the seven existing :focus rules on inputs. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible{
  outline:2px solid var(--focus-ring,#0f2057);
  outline-offset:2px;
  border-radius:var(--r1)
}
/* The clickable cards. They are divs with onclick, so they take the same ring
   through [tabindex] above once they are focusable; until then this at least
   makes the ring correct wherever one IS reachable. The keyboard-reachability
   of 155 onclick handlers on non-button elements is a separate finding and is
   reported rather than silently half-fixed here. */
.path-card:focus-visible,.stance-opt:focus-visible,.speak-opt:focus-visible,
.act:focus-visible,.chip:focus-visible,.dp-option:focus-visible,
.leg-opt:focus-visible,.mode-path:focus-visible,.coalition-card:focus-visible{
  outline:2px solid var(--focus-ring,#0f2057);
  outline-offset:3px
}

/* ACTIVE. A press should be acknowledged. One response, applied to everything
   that already had a hover, so the whole product answers a tap the same way.
   Transform only: no colour moves, so nothing about the palette changes. */
button:active,
[role="button"]:active,
.path-card:active,.stance-opt:active,.speak-opt:active,.act:active,
.chip:active,.chip-toggle:active,.xpath-chip:active,.dp-option:active,
.leg-opt:active,.mode-path:active,.coalition-card:active,.proof-item:active,
.copy-btn:active,.optin-btn:active,.shrbt:active,.back-top:active,
.btn-mailto:active,.btn-copy-msg:active,.tool-copy-btn:active,
.tool-sec-btn:active,.leg-gen-btn:active,.su-match-btn:active,
.dp-addr-submit:active,.oc-confirm-btn:active,.ab-btn:active,
.mode-tool-btn:active,.del-btn:active,.ps-toggle:active{
  transform:translateY(1px)
}

/* DISABLED. Both spellings, because the app sets the attribute on real buttons
   and aria-disabled on the div-buttons. Without this a disabled control is
   indistinguishable from a live one, which is worse than no disabled state. */
button:disabled,
button[disabled],
input:disabled,
select:disabled,
textarea:disabled,
[aria-disabled="true"]{
  opacity:.55;
  cursor:not-allowed;
  box-shadow:none;
  filter:grayscale(.25)
}
button:disabled:hover,button[disabled]:hover,[aria-disabled="true"]:hover{
  transform:none;
  filter:grayscale(.25)
}
button:disabled:active,button[disabled]:active,[aria-disabled="true"]:active{
  transform:none
}

/* BUSY / LOADING. aria-busy was set nowhere and styled nowhere, so a control
   mid-request looked exactly like an idle one and people press twice. */
[aria-busy="true"]{
  cursor:progress;
  opacity:.75
}
[aria-busy="true"]:active{ transform:none }

/* ═══════════════════════════════════════════════════════════════════════════
   EMPTY, ERROR AND WAITING -- the three screens a demo always finds
   ---------------------------------------------------------------------------
   These states existed in the markup and had no styling, so they rendered as
   bare unstyled text in the middle of an otherwise finished page. Built from
   the same card the rest of the product uses: --s1 ground, --b1 hairline,
   --r2 radius, --mu text. Nothing new.
   ═══════════════════════════════════════════════════════════════════════════ */

.acta-empty,.acta-error,.acta-waiting{
  background:var(--s1);
  border:1px solid var(--b1);
  border-radius:var(--r2);
  padding:22px 20px;
  text-align:center;
  font-family:var(--ss);
  font-size:16px;
  line-height:1.65;
  color:var(--mu)
}
.acta-error{ border-color:var(--re); color:var(--tx) }
.acta-empty strong,.acta-error strong,.acta-waiting strong{
  display:block;
  font-size:16px;
  font-weight:600;
  color:var(--tx);
  margin-bottom:6px
}
.acta-waiting{ color:var(--di) }

@media (prefers-reduced-motion:reduce){
  button:active,[role="button"]:active,.path-card:active,.stance-opt:active,
  .speak-opt:active,.act:active,.chip:active,.dp-option:active{ transform:none }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SPACING SCALE AND VERTICAL RHYTHM -- the app half
   ---------------------------------------------------------------------------
   Added 2026-08-14. Same tokens as marketing-shell.css so the two halves of the
   product breathe identically; the selectors differ because the app's furniture
   does.

   Scoped tighter than the marketing block on purpose. The app is a dense tool
   with a lot of small controls, and blanket paragraph margins there would push
   the primary action below the fold. So this raises the SURFACES a reader dwells
   on -- the hero, the brief cards, the option lists -- and leaves the control
   chrome alone.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px;
  --sp-6:32px; --sp-7:48px; --sp-8:64px; --sp-9:96px
}

/* THE LANDING HERO. The h1 grew from 36 to 42, so the box it sits in has to
   grow with it or the pass makes the page look tighter rather than more
   finished. */
.hero{ padding-top:var(--sp-9); padding-bottom:var(--sp-8) }
.hero .ey{ margin-bottom:var(--sp-5) }
.hero .h1{ margin:0 0 var(--sp-5) }
.hero .hsb{ margin:0 0 var(--sp-6) }
.hero .trust-line{ margin-top:var(--sp-7) }
.hero .hero-stat{ margin-top:var(--sp-4) !important }

/* BRIEF AND CONTENT CARDS -- the surfaces a reader actually dwells on. */
.sc{ padding:var(--sp-6) !important; margin-bottom:var(--sp-5) !important }
.sc .stl{ margin-bottom:var(--sp-3) }
.sc p{ margin:0 0 var(--sp-3) }
.sc ul{ margin:0; padding-left:var(--sp-5) }
.sc li{ margin-bottom:var(--sp-2) }

/* THE OPTION AND PATH LISTS. These are the choices the product exists to offer,
   and they were the tightest thing on the screen. */
.path-card{ padding:var(--sp-5) }
.stance-opt,.speak-opt,.leg-opt,.dp-option{ padding:var(--sp-4) var(--sp-5) }
.act{ padding:var(--sp-4) }

/* SCREEN GUTTERS. One value rather than a per-screen choice. */
.pg{ padding-left:var(--sp-5); padding-right:var(--sp-5) }

/* WHAT THE SCALE EXPOSED (2026-08-14)
   ---------------------------------------------------------------------------
   A consistent scale reveals what was only ever readable by accident, and this
   is the first thing it revealed.

   The nav wordmark was 36px, which the type scale mapped to 42px along with
   every other display-sized thing. But the wordmark is a BRAND MARK, not display
   type: it sits in a fixed 3-column grid (1fr | auto | 1fr) beside the language
   toggle, and at 42px it needed 170px of a 144px column. Measured: `.logo-civic`
   ran 129-170 while `.lang-toggle` ran 154-236, a 16px overlap, and "Civic" was
   rendered underneath the toggle.

   THE OVERLAP PRE-DATES THIS PASS -- it is visible in the before screenshot at
   36px too, just smaller. The scale did not create it, it made it impossible to
   keep ignoring, which is the point.

   Fixed by taking the wordmark off the display scale (it is a logo, and 34px is
   what fits the column it lives in) and by making the column unable to spill
   again regardless of what any future size does. */
.logo{ min-width:0; max-width:100% } /* font-size removed 2026-08-17: this late rule silently overrode the masthead lockup size for two passes; the wordmark is now a locked SVG (header pass 3), so no font-size exists to shadow -- the rule stays only for the column-spill guarantee described above */
nav{ column-gap:14px }

/* ═══════════════════════════════════════════════════════════════════════════
   VISUAL IDENTITY -- the app half. Same tokens, same drawing, same decisions
   as the block at the end of marketing-shell.css; the selectors differ because
   the furniture does. No new colours, no new fonts, abstract geometry only.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --illus-constellation:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 480 480'><g fill='none' stroke-width='1.5'><circle cx='40' cy='460' r='110' stroke='rgba(255,255,255,0.14)'/><circle cx='40' cy='460' r='180' stroke='rgba(255,255,255,0.10)'/><circle cx='40' cy='460' r='255' stroke='rgba(255,255,255,0.065)'/><circle cx='40' cy='460' r='335' stroke='rgba(255,255,255,0.04)' stroke-dasharray='2 10'/></g></svg>");
  --illus-dots-ink:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 120'><g fill='rgba(15,32,87,0.10)'><circle cx='10' cy='10' r='1.6'/><circle cx='40' cy='10' r='1.6'/><circle cx='70' cy='10' r='1.6'/><circle cx='100' cy='10' r='1.6'/><circle cx='10' cy='40' r='1.6'/><circle cx='40' cy='40' r='1.6'/><circle cx='70' cy='40' r='1.6'/><circle cx='100' cy='40' r='1.6'/><circle cx='10' cy='70' r='1.6'/><circle cx='40' cy='70' r='1.6'/><circle cx='70' cy='70' r='1.6'/><circle cx='100' cy='70' r='1.6'/><circle cx='10' cy='100' r='1.6'/><circle cx='40' cy='100' r='1.6'/><circle cx='70' cy='100' r='1.6'/><circle cx='100' cy='100' r='1.6'/></g></svg>");
  --illus-state-empty:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='rgba(15,32,87,0.22)' stroke-width='2'><circle cx='48' cy='48' r='14'/><circle cx='48' cy='48' r='26'/><circle cx='48' cy='48' r='38' stroke-dasharray='3 9'/></g><circle cx='48' cy='48' r='4.5' fill='%231b4fff'/></svg>");
  --illus-state-error:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='rgba(214,63,63,0.5)' stroke-width='2'><circle cx='48' cy='48' r='14' stroke-dasharray='60 28'/><circle cx='48' cy='48' r='26' stroke-dasharray='120 46'/><circle cx='48' cy='48' r='38' stroke-dasharray='3 9'/></g><circle cx='48' cy='48' r='4.5' fill='%23d63f3f'/></svg>");
  --illus-state-waiting:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='rgba(123,130,160,0.55)' stroke-width='2'><circle cx='48' cy='48' r='14'/><circle cx='48' cy='48' r='26' stroke-dasharray='10 8'/><circle cx='48' cy='48' r='38' stroke-dasharray='2 10'/></g><circle cx='48' cy='48' r='4.5' fill='%237b82a0'/></svg>");
  --shadow-1:0 1px 3px rgba(15,32,87,.06),0 2px 8px rgba(15,32,87,.05);
  --shadow-2:0 4px 10px rgba(15,32,87,.08),0 10px 28px rgba(15,32,87,.10);
}

/* The landing hero: the ripple ring stays on ::after; the constellation
   answers it from the opposite corner, and a shallow blue wash gives the
   navy a horizon. All under the content, all existing colours. */
.hero{
  background-image:linear-gradient(180deg,rgba(27,79,255,.14),rgba(27,79,255,0) 55%),var(--illus-constellation);
  background-repeat:no-repeat;
  background-position:top,left -80px bottom -80px;
  background-size:100% 420px,440px 440px
}

/* Non-ideal states, drawn. */
.acta-empty::before,.acta-error::before,.acta-waiting::before{
  content:'';display:block;width:72px;height:72px;margin:0 auto 14px;
  background:var(--illus-state-empty) center/contain no-repeat
}
.acta-error::before{ background-image:var(--illus-state-error) }
.acta-waiting::before{ background-image:var(--illus-state-waiting) }

/* CARD identity: the brief cards and choice lists are paper above the ground. */
.sc{ box-shadow:var(--shadow-1) }
.path-card{ box-shadow:var(--shadow-1);transition:box-shadow .18s ease,transform .18s ease,border-color .18s ease }
.path-card:hover{ box-shadow:var(--shadow-2);transform:translateY(-2px) }
.stance-opt,.speak-opt,.leg-opt,.dp-option,.act{ transition:box-shadow .15s ease,border-color .15s ease }
.stance-opt:hover,.speak-opt:hover,.leg-opt:hover,.act:hover{ box-shadow:var(--shadow-1) }

/* BUTTON identity: every primary action is the same button. */
.hero-cta,.leg-gen-btn,.su-match-btn-primary,.dp-addr-submit,.oc-confirm-btn,
.btn-mailto,#ta-analyze,.path-cta{
  font-weight:700 !important;
  letter-spacing:0.02em;
  min-height:48px;
  box-shadow:0 2px 10px rgba(15,32,87,.25);
  transition:all .18s ease
}
.hero-cta:hover,.leg-gen-btn:hover,.su-match-btn-primary:hover,.dp-addr-submit:hover,
.oc-confirm-btn:hover,.btn-mailto:hover{
  box-shadow:0 6px 20px rgba(15,32,87,.32);
  transform:translateY(-1px)
}

/* INPUT identity: a place to write, not a grey slab. */
textarea,input[type="text"],input[type="email"],.sgr input,.link-input{
  background:#fff;
  border-radius:var(--r1);
  transition:border-color .15s ease
}

/* BADGE identity: every tag speaks in the same small caps. */
.jb,.tg{ font-weight:700;letter-spacing:0.08em;text-transform:uppercase }
.jb svg,.tg svg{ vertical-align:-0.13em }

/* The seed chips carry drawn icons now: give the icon the accent so the chip
   reads icon-first, and the check keeps the existing text colour. */
.seed-chip svg{ color:var(--ac) }

@media (prefers-reduced-motion:reduce){
  .path-card:hover,.hero-cta:hover,.leg-gen-btn:hover,.btn-mailto:hover{ transform:none }
}

/* A500: the Playbook spine. Steps are collapsed numbered rows; ONE step -- the
   next action -- is elevated and open. Rank is carried by weight and position,
   not by eleven different accent colors. */
.rstep{background:var(--s1);border:1px solid var(--b1);border-radius:var(--r1);margin-bottom:8px}
.rstep-sum{display:flex;align-items:center;gap:11px;padding:12px 14px;cursor:pointer;list-style:none}
.rstep-sum::-webkit-details-marker{display:none}
.rstep-n{flex:0 0 30px;height:30px;border-radius:50%;background:var(--s2);border:1px solid var(--b2);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;color:var(--mu)}
.rstep-t{display:flex;flex-direction:column;gap:1px;min-width:0}
.rstep-phase{font-size:10.5px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--di)}
.rstep-title{font-size:15px;font-weight:600;color:var(--tx);line-height:1.35}
.rstep-next-tag{margin-left:auto;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--ac);background:#4f8ef714;border:1px solid #4f8ef730;border-radius:var(--r0);padding:3px 8px;white-space:nowrap}
.rstep-body{padding:0 14px 12px 55px}
.rstep-body .rd{font-size:14px;color:var(--ink);line-height:1.6;margin-bottom:8px;max-width:62ch}
.rstep-next{border:1.5px solid #1b4fff35;box-shadow:0 3px 14px rgba(27,79,255,.08)}
.rstep-next .rstep-n{background:var(--ac);border-color:var(--ac);color:#fff}
@media(max-width:480px){.rstep-body{padding-left:14px}}

/* A504: the clarifying question -- a direct question to the reader where the
   old brief lectured them about what they did not specify. */
.br-question{font-style:italic;color:var(--tx);border-left:2.5px solid #4f8ef735;padding:6px 12px;margin-top:12px;background:#4f8ef706;border-radius:0 var(--r1) var(--r1) 0;max-width:68ch}
