/* Platform widget styles + dashboard tokens.
 *
 * The 2026-05-27 refresh: JetBrains Mono across the board — display,
 * body, and code. The earlier Fraunces + Inter Tight pair (2026-05-23)
 * was the user's call to roll back; the system reads more coherent
 * with one typeface and weight + size variations doing the hierarchy
 * work that two families used to do. Mono-only also reinforces the
 * "tooling, not lifestyle brand" character of the platform.
 *
 * Tokens still drive every value so per-campaign themes + dark mode
 * keep working. The three font slots remain so we can pivot the
 * display+body slots back to a serif/sans pair later without
 * touching usage sites.
 */

@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&display=swap');

:root {
    /* Theme tokens — defaults are LIGHT mode. Campaign.theme overrides
     * per-campaign via the Jinja-injected <style> in campaign.html.j2.
     * Dark mode is the same names with different values (below). */
    /* Tell the browser this is a light surface so it does NOT dark-invert
     * native form controls / scrollbars / autofill on a dark-mode OS. The
     * [data-theme="dark"] block flips this to `dark` when the in-app toggle is
     * on. Without this, a dark-OS visitor got UA-darkened chrome on the
     * otherwise-light page (#dark-mode-readability fix, 2026-06-24). */
    color-scheme: light;

    --sc-primary: #1E3A5F;   /* deep navy — headings, primary type */
    --sc-accent:  #2563EB;   /* vivid blue — accents, CTA fill */
    --sc-paper:   #F4F7FB;   /* cool paper — the page ground */
    --sc-surface: #FFFFFF;   /* card / form ground (was hardcoded cream) */
    /* Warm cream panel ground used by the dashboard nav/cards. Pulled into a
     * variable so the in-app dark theme can flip it — dash.css used to hardcode
     * #FFFCF3, which stayed cream in dark mode while the text flipped to light
     * = light-on-light, unreadable (2026-06-24 fix). */
    --sc-panel:   #FFFCF3;
    --sc-ink:     #0F1F36;   /* readable body ink */
    /* slate-blue muted secondary text. Darkened 2026-06-04 (#30) from the
     * old #5B7796 (4.32:1 on --sc-paper — failed WCAG AA 4.5:1 for the
     * small body-text roles it drives: field hints, share label, trust
     * note, footer). #506B89 measures 5.14:1 on paper / 5.52:1 on the
     * surface card, clearing AA while keeping the same slate hue. */
    --sc-moss:    #506B89;
    --sc-rule:    #D8E2EE;   /* light blue-gray hairline */
    --sc-stamp:   #0A4FB3;   /* deep ink for accents */
    --sc-pulse:   #3B82F6;   /* call-to-action blue */
    --sc-highlight: rgba(37, 99, 235, 0.16);  /* dek <strong> underline */

    /* All three slots resolve to JetBrains Mono. Distinct names retained
       so hierarchy work happens via weight + size + letter-spacing at
       the usage sites, and so we can pivot display/body to other faces
       later without renaming every rule. */
    --sc-font-display: 'JetBrains Mono', 'Menlo', monospace;
    --sc-font-body:    'JetBrains Mono', 'Menlo', monospace;
    --sc-font-mono:    'JetBrains Mono', 'Menlo', monospace;

    --sc-max-w: 720px;
    /* Soft, modern scale. sm is for chips/pills; md for inputs + small buttons;
     * lg for cards, the hero CTA, MP reveal, donation block. */
    --sc-radius-sm: 6px;
    --sc-radius-md: 12px;
    --sc-radius-lg: 20px;
    --sc-radius-pill: 999px;

    --sc-shadow-paper: 0 1px 0 rgba(10,26,47,0.04), 0 6px 18px -8px rgba(30,58,95,0.12);
    --sc-shadow-card:  0 2px 0 rgba(10,26,47,0.04), 0 14px 32px -16px rgba(30,58,95,0.22);
    --sc-shadow-btn:   0 8px 22px -10px rgba(10, 79, 179, 0.55);
    --sc-shadow-btn-hover: 0 14px 32px -12px rgba(10, 79, 179, 0.65);

    /* Body-noise overlay — set as a variable so dark mode can swap density. */
    --sc-noise: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0.04  0 0 0 0 0.10  0 0 0 0 0.20  0 0 0 0.025 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* Dark palette — opt-in only. Light is the default, so the OS-pref
 * @media block is intentionally absent: a dark-OS user still lands on
 * the light scheme until they pick Dark from the in-app toggle. */
:root[data-theme="dark"] {
    color-scheme: dark;       /* match native controls to the dark theme */
    --sc-primary: #93BFEA;
    --sc-accent:  #60A5FA;
    --sc-paper:   #0B1A2F;
    --sc-surface: #162840;
    --sc-panel:   #162840;    /* dashboard panels flip to the dark surface */
    --sc-ink:     #E8F0FA;
    --sc-moss:    #7C9AB8;
    --sc-rule:    #1E3A5F;
    --sc-stamp:   #93BFEA;
    --sc-pulse:   #60A5FA;
    --sc-highlight: rgba(96, 165, 250, 0.22);
    --sc-shadow-paper: 0 1px 0 rgba(255,255,255,0.04), 0 6px 18px -8px rgba(0,0,0,0.45);
    --sc-shadow-card:  0 2px 0 rgba(255,255,255,0.05), 0 14px 32px -16px rgba(0,0,0,0.6);
    --sc-shadow-btn:   0 10px 26px -10px rgba(96, 165, 250, 0.45);
    --sc-shadow-btn-hover: 0 16px 36px -12px rgba(96, 165, 250, 0.6);
    --sc-noise: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0.58  0 0 0 0 0.75  0 0 0 0 0.92  0 0 0 0.04 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--sc-paper);
    color: var(--sc-ink);
    font-family: var(--sc-font-body);
    font-size: 18px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

body {
    /* Subtle paper-grain texture — variable lets dark mode swap to a
     * lighter noise so it shows up against the dark ground. */
    background-image: var(--sc-noise);
    background-size: 240px 240px;
    background-repeat: repeat;
}

/* -----------------------------------------------------------------
 * Global keyboard focus ring (#30 — WCAG 2.4.7 Focus Visible).
 *
 * Before this, only the masthead wordmark had a focus style; every
 * other interactive control (the CTA, share buttons, the "Wrong MP?"
 * link, inputs, the select, footer links) relied on the browser
 * default — which several controls suppress via `outline: none` on
 * their :focus rule (e.g. .sc-input). A keyboard or screen-reader
 * user could tab through the whole widget with no visible focus.
 *
 * :focus-visible (not :focus) means mouse clicks don't draw the ring —
 * only keyboard / programmatic focus does, so the visual stays clean
 * for pointer users while remaining fully navigable by keyboard.
 *
 * The ring is a 3px solid accent outline + 2px offset (so it sits
 * just outside rounded corners and pill buttons). A faint box-shadow
 * halo keeps it legible where the outline rides a same-coloured edge.
 * ----------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--sc-accent);
    outline-offset: 2px;
    border-radius: var(--sc-radius-sm);
    box-shadow: 0 0 0 5px var(--sc-highlight);
}

/* Text inputs / select already carry their own rounded corners and an
 * inset focus glow; keep their native radius and just layer the ring
 * so the corners don't get clipped to the small radius above. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    border-radius: var(--sc-radius-md);
}

/* The view-heading focus target (#30 — focus moves here on each state
 * transition). It's a non-interactive <h1>/<h2> made focusable with
 * tabindex="-1"; we DON'T want the big control ring on a heading, just
 * a quiet confirmation that focus landed for sighted keyboard users. */
.sc-focus-heading:focus-visible,
.lw-focus-heading:focus-visible {
    outline: 2px dashed var(--sc-accent);
    outline-offset: 4px;
    box-shadow: none;
    border-radius: var(--sc-radius-sm);
}

/* -----------------------------------------------------------------
 * User menu — <details> dropdown attached to the masthead user chip.
 * Hosts the theme switcher (and is the obvious slot for future
 * per-user settings).
 * ----------------------------------------------------------------- */
.sc-user-menu {
    position: relative;
    display: inline-block;
}
.sc-user-menu > summary {
    list-style: none;            /* no native disclosure triangle */
    cursor: pointer;
    user-select: none;
}
.sc-user-menu > summary::-webkit-details-marker { display: none; }
.sc-user-menu__caret {
    display: inline-block;
    margin-left: 6px;
    font-size: 10px;
    opacity: 0.7;
    transition: transform 120ms ease-out;
}
.sc-user-menu[open] .sc-user-menu__caret { transform: rotate(180deg); }
.sc-user-menu__panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 220px;
    background: var(--sc-paper);
    color: var(--sc-ink);
    border: 1px solid var(--sc-rule);
    border-radius: var(--sc-radius-md);
    box-shadow: var(--sc-shadow-card);
    padding: 14px;
    z-index: 1000;
    font-family: var(--sc-font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
    text-transform: none;
}
.sc-user-menu__label {
    margin: 0 0 8px;
    font-size: 10px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--sc-moss);
}
.sc-user-menu__link {
    display: block;
    margin: 0 0 14px;
    color: var(--sc-ink);
    text-decoration: none;
    font-weight: 600;
}
.sc-user-menu__link:hover {
    text-decoration: underline;
}

/* Segmented theme toggle — lives inside the user-menu panel now. */
.sc-theme-toggle {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--sc-rule);
    border-radius: var(--sc-radius-md);
    background: var(--sc-paper);
    font-family: var(--sc-font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    overflow: hidden;
}
.sc-theme-toggle__btn {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--sc-moss);
    padding: 6px 12px;
    cursor: pointer;
    font-family: inherit;
    font-size: inherit;
    letter-spacing: inherit;
    text-transform: uppercase;
}
.sc-theme-toggle__btn + .sc-theme-toggle__btn {
    border-left: 1px solid var(--sc-rule);
}
.sc-theme-toggle__btn:hover { color: var(--sc-primary); }
.sc-theme-toggle__btn[aria-pressed="true"] {
    background: var(--sc-accent);
    color: var(--sc-paper);
}

/* -----------------------------------------------------------------
 * Masthead — typed memo header
 * ----------------------------------------------------------------- */
.sc-masthead {
    background: var(--sc-primary);
    color: var(--sc-surface);
    padding: 14px 24px;
    font-family: var(--sc-font-body);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}
.sc-masthead__wordmark {
    font-weight: 700;
    font-family: var(--sc-font-mono);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    /* When the wordmark is an <a> (dashboard masthead links it to /dash/),
       neutralize the default link styling so it still reads as a wordmark
       rather than navigation. Hover gets a subtle color shift as the only
       affordance — the cursor change does most of the discoverability work. */
    color: inherit;
    text-decoration: none;
    transition: color 140ms ease;
}
a.sc-masthead__wordmark:hover,
a.sc-masthead__wordmark:focus-visible {
    color: var(--sc-accent, currentColor);
    text-decoration: none;
    outline: none;
}
.sc-masthead__wordmark::before {
    content: '◆ ';
    color: var(--sc-pulse);
    margin-right: 2px;
}
.sc-masthead__filed {
    opacity: 0.7;
    font-size: 12.5px;
}

@keyframes sc-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.55); }
    70%  { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
    100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}

/* -----------------------------------------------------------------
 * Main column
 * ----------------------------------------------------------------- */
.sc-shell {
    max-width: var(--sc-max-w);
    margin: 0 auto;
    padding: 56px 28px 96px;
}

/* -----------------------------------------------------------------
 * Campaign owner's logo (#116)
 *
 * Sits above the kicker, inside the chrome, so it rides along with the hero on
 * BOTH the standalone page and the ?embed=1 iframe. See the comment in
 * letter.html.j2 for why it is here and not in the masthead.
 * ----------------------------------------------------------------- */
.sc-owner-logo {
    margin: 0 0 28px;
    line-height: 0;          /* no descender gap under the image */
}
.sc-owner-logo a {
    display: inline-block;
    /* The mark is the link's whole content, so the sheet's underlined-link
       treatment would draw a rule under the logo. */
    text-decoration: none;
    border-bottom: 0;
}
.sc-owner-logo img {
    display: block;
    /* HEIGHT, not width, is the control here: a wordmark is sized by its cap
       height against the type around it, and every client's mark has a
       different aspect ratio. `width: auto` lets a tall badge and a wide
       wordmark both land at the same optical weight. */
    height: 44px;
    width: auto;
    max-width: 100%;
}
@media (max-width: 560px) {
    .sc-owner-logo { margin-bottom: 20px; }
    .sc-owner-logo img { height: 34px; }
}
/* Light/dark asset swap. Both <img> tags are in the DOM and CSS picks one, so
   the swap costs no JS and cannot flash the wrong mark: the theme attribute is
   applied before first paint by the inline script in the template <head>.
   A campaign that sets only `owner_logo_url` renders one <img> with neither
   class, which both rules below leave alone, so it shows in both themes,
   unchanged.

   Note the `img` in each selector below. It is not decoration: `.sc-owner-logo
   img` above is (0,1,1) and a bare `.sc-owner-logo__img--dark` is (0,1,0), so
   the block rule would WIN and both marks would render, stacked. Caught in a
   screenshot, not by a test. */
.sc-owner-logo img.sc-owner-logo__img--dark { display: none; }
:root[data-theme="dark"] .sc-owner-logo img.sc-owner-logo__img--light { display: none; }
:root[data-theme="dark"] .sc-owner-logo img.sc-owner-logo__img--dark { display: block; }

/* -----------------------------------------------------------------
 * Hero — editorial display headline
 * ----------------------------------------------------------------- */
.sc-kicker {
    font-family: var(--sc-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--sc-accent);
    margin: 0 0 24px;
    padding-left: 0;
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Hero image — campaign-author-uploaded photo or illustration that sits
 * between the kicker and the headline. Full-width within sc-shell, soft
 * rounded corners that match the rest of the surface scale. */
.sc-hero-image {
    margin: 0 0 32px;
    padding: 0;
    border-radius: var(--sc-radius-lg);
    overflow: hidden;
    box-shadow: var(--sc-shadow-paper);
    background: var(--sc-surface);
    aspect-ratio: 2 / 1;
}
.sc-hero-image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* Hero attribution (#113). Only for a campaign that sets page_slots.hero_credit;
   every other hero keeps the rules above exactly.

   The modifier exists because the base rule pins the 2:1 ratio and clips
   overflow on the FIGURE, which would swallow a <figcaption> whole. Here the
   ratio moves to the image and the clip is released, so the credit sits under
   the picture instead of inside it. */
.sc-hero-image--credited {
    aspect-ratio: auto;
    overflow: visible;
    background: none;
    box-shadow: none;
    border-radius: 0;
}
.sc-hero-image--credited img {
    /* NO forced aspect-ratio here, unlike the base rule.
       The base 2:1 crop is fine for a landscape photo, and wrong for a subject
       whose SIZE is the point: a loaded tanker is only legible as enormous when
       the whole hull is in frame, and a forced crop would take off the bow.
       `height: auto` keeps whatever ratio the asset was authored at, so a
       credited hero is never silently cropped. Deliberately no number here: the
       tanker hero has already been re-framed once (~3:1, then ~2:1), and a
       ratio quoted in a comment goes stale the next time. */
    height: auto;
    border-radius: var(--sc-radius-lg);
    box-shadow: var(--sc-shadow-paper);
}
.sc-hero-image__credit {
    /* A photo credit competing with the CTA (operator, 2026-08-23). It was
       reading as page content rather than as a caption, for two reasons.

       It was 13px, which is this sheet's body-small tier, the same size as the
       field hints. A credit belongs at the bottom of the scale, so it drops to
       11px, alongside the other genuinely-fine print here.

       And `var(--sc-muted)` WAS NEVER DEFINED. It is used exactly once, here.
       An undefined custom property makes the declaration invalid at computed
       value time, so the element fell back to INHERITING full body ink: the
       credit has been rendering at 15.4:1 against the page, more contrast than
       most real copy. `--sc-moss` is the muted token that actually exists in
       both themes.

       FLOOR, not a preference: the image is CC BY 3.0, so attribution is a
       licence condition. It has to stay legible. 11px on --sc-moss measures
       5.1:1 light and 6.0:1 dark, both clear of the 4.5:1 AA bar for small
       text. Do not shrink it further, drop the colour to a lighter token, or
       hide it on mobile. */
    margin: 6px 2px 0;
    font-size: 11px;
    line-height: 1.45;
    color: var(--sc-moss);
}
.sc-kicker::before {
    content: '';
    display: inline-block;
    width: 26px;
    height: 1.5px;
    background: var(--sc-accent);
    border-radius: 1px;
}

.sc-headline {
    font-family: var(--sc-font-display);
    font-size: clamp(40px, 6.8vw, 64px);
    font-weight: 460;
    line-height: 1.02;
    letter-spacing: -0.022em;
    color: var(--sc-primary);
    margin: 0 0 22px;
    font-variation-settings: "opsz" 144, "SOFT" 60;
    position: relative;
    padding-left: 0;
}
.sc-headline em {
    font-style: italic;
    font-variation-settings: "opsz" 144, "SOFT" 100, "WONK" 1;
    color: var(--sc-stamp);
}
/* Long headlines (sentence-style titles, 60+ chars — the template adds the
   modifier from the slot length) step down so they hold 3-4 lines instead of
   towering over the page. Tightens line-height a touch for the same reason. */
.sc-headline--long {
    font-size: clamp(30px, 4.6vw, 44px);
    line-height: 1.08;
}

.sc-dek {
    font-family: var(--sc-font-body);
    font-size: 19px;
    line-height: 1.55;
    color: var(--sc-ink);
    max-width: 580px;
    margin: 0 0 36px;
    font-weight: 400;
}
.sc-dek strong {
    background: linear-gradient(to top, var(--sc-highlight) 0%, var(--sc-highlight) 38%, transparent 38%, transparent 100%);
    padding: 0 2px;
    font-weight: 600;
    color: var(--sc-primary);
}

/* -----------------------------------------------------------------
 * Stat callout — typewriter sidebar inset
 * ----------------------------------------------------------------- */
.sc-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 0;
    margin: 40px 0 56px;
    border-top: 1px solid var(--sc-rule);
    border-bottom: 1px solid var(--sc-rule);
    padding: 22px 0;
}
.sc-stat {
    padding: 0 16px;
    border-right: 1px solid var(--sc-rule);
}
.sc-stat:last-child { border-right: none; }
.sc-stat__value {
    font-family: var(--sc-font-display);
    font-size: 38px;
    font-weight: 480;
    color: var(--sc-primary);
    letter-spacing: -0.02em;
    line-height: 1;
    margin-bottom: 6px;
    font-variation-settings: "opsz" 96, "SOFT" 60;
}
.sc-stat__value-unit {
    font-family: var(--sc-font-mono);
    font-size: 14px;
    color: var(--sc-moss);
    margin-left: 4px;
    letter-spacing: 0.04em;
}
.sc-stat__label {
    font-family: var(--sc-font-body);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--sc-moss);
    line-height: 1.35;
}

/* -----------------------------------------------------------------
 * Section header — "PROCEDURE" / "TALKING POINTS" with rule
 * ----------------------------------------------------------------- */
/* Section header — the ONE remaining uppercase-mono accent role.
   Used for dividers like "HOW IT WORKS" only. Reduces label-shouting
   noise everywhere else (fields, steps, cards now use sentence case). */
.sc-section-head {
    font-family: var(--sc-font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--sc-moss);
    margin: 0 0 20px;
    display: flex;
    align-items: center;
    gap: 14px;
}
.sc-section-head::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--sc-rule);
}

/* -----------------------------------------------------------------
 * Numbered steps
 * ----------------------------------------------------------------- */
.sc-steps {
    list-style: none;
    padding: 0;
    margin: 0 0 48px;
    counter-reset: sc-step;
}
.sc-step {
    counter-increment: sc-step;
    display: grid;
    grid-template-columns: 44px 1fr;
    gap: 18px;
    padding: 18px 0;
    border-bottom: 1px dashed var(--sc-rule);
}
.sc-step:last-child { border-bottom: none; }
.sc-step__num {
    font-family: var(--sc-font-mono);
    font-size: 13px;
    font-weight: 700;
    color: var(--sc-paper);
    background: var(--sc-primary);
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 2px;
}
.sc-step__num::before {
    content: counter(sc-step, decimal-leading-zero);
}
.sc-step__title {
    font-family: var(--sc-font-body);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--sc-primary);
    margin: 0 0 4px;
}
.sc-step__body {
    font-family: var(--sc-font-body);
    font-size: 15px;
    line-height: 1.5;
    color: var(--sc-ink);
    opacity: 0.8;
    margin: 0;
}

/* -----------------------------------------------------------------
 * Form card
 * ----------------------------------------------------------------- */
.sc-card {
    background: var(--sc-surface);
    border: 1px solid var(--sc-rule);
    border-radius: var(--sc-radius-lg);
    padding: 28px 28px 24px;
    box-shadow: var(--sc-shadow-card);
    position: relative;
}
.sc-card__head {
    font-family: var(--sc-font-body);
    font-size: 15px;
    font-weight: 500;
    color: var(--sc-moss);
    margin: 0 0 18px;
    letter-spacing: 0;
    text-transform: none;
}

.sc-field {
    display: block;
    margin-bottom: 16px;
}
.sc-field__label {
    font-family: var(--sc-font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--sc-primary);
    margin-bottom: 6px;
    display: block;
    letter-spacing: 0;
    text-transform: none;
}
.sc-field__hint {
    font-family: var(--sc-font-body);
    font-size: 12.5px;
    color: var(--sc-moss);
    margin: 6px 2px 0;
    letter-spacing: 0;
    line-height: 1.4;
}

/* Message-writer parity (migration 0018): preset reasons, the bundled consent
 * box, and the election-advertising sponsor line. */

/* Checkbox row shared by the preset reasons + the consent box. 44px min touch
 * target (#30 a11y) and a top-aligned box so multi-line labels read cleanly. */
.sc-check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-height: 44px;
    font-family: var(--sc-font-body);
    font-size: 15px;
    line-height: 1.4;
    color: var(--sc-ink);
    cursor: pointer;
    padding: 4px 0;
}
.sc-check input[type="checkbox"] {
    width: 20px;
    height: 20px;
    margin-top: 2px;
    flex: 0 0 auto;
    accent-color: var(--sc-primary);
    cursor: pointer;
}
.sc-check input[type="checkbox"]:disabled { cursor: not-allowed; }
.sc-check input[type="checkbox"]:disabled + span { color: var(--sc-moss); }

/* Preset reasons "Select up to N" group — borderless fieldset. */
.lw-reasons { border: 0; padding: 0; margin: 0 0 16px; }
.lw-reasons__hint { margin: 0 0 8px; }
.lw-reason-own-text { margin-top: 8px; }
.lw-reasons__error {
    font-family: var(--sc-font-body);
    font-size: 12.5px;
    color: #b3261e;
    margin: 6px 2px 0;
}
.sc-field__error[hidden], .lw-reason-own-text[hidden] { display: none; }

/* Bundled consent + newsletter opt-in. */
.lw-consent { margin: 4px 0 16px; }
.lw-consent__title { font-weight: 600; color: var(--sc-primary); }
.lw-consent__copy {
    font-family: var(--sc-font-body);
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--sc-moss);
    margin: 8px 0 0 30px;
}

/* Election-advertising sponsor attribution under the form. */
.sc-form__authorization {
    font-family: var(--sc-font-body);
    font-size: 11.5px;
    font-style: italic;
    line-height: 1.45;
    color: var(--sc-moss);
    text-align: center;
    margin: 12px 4px 0;
}
.sc-input {
    width: 100%;
    border: 1.5px solid var(--sc-rule);
    background: var(--sc-paper);
    font-family: var(--sc-font-body);
    font-size: 17px;
    font-weight: 500;
    color: var(--sc-ink);
    padding: 13px 16px;
    letter-spacing: 0;
    border-radius: var(--sc-radius-md);
    outline: none;
    transition: border-color 160ms ease, background 160ms ease, box-shadow 160ms ease;
}
.sc-input::placeholder { color: var(--sc-moss); font-style: normal; opacity: 0.65; }
.sc-input:focus {
    border-color: var(--sc-accent);
    background: var(--sc-surface);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
}
.sc-input--code {
    font-family: var(--sc-font-mono);
    font-size: 17px;
    font-weight: 500;
    letter-spacing: 0.14em;
    /* Note: NOT text-transform: uppercase. The class is reused across
     * many wizard fields (slug, URL, secret, hex color, font stack,
     * postal code). Uppercase belongs only on the postal input via
     * the .sc-input--postal modifier below. */
}
.sc-input--postal {
    text-transform: uppercase;
}

/* Honeypot — hidden from humans, present for bots */
.sc-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* -----------------------------------------------------------------
 * Buttons
 * ----------------------------------------------------------------- */
.sc-btn {
    appearance: none;
    border: none;
    cursor: pointer;
    font-family: var(--sc-font-body);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    padding: 16px 26px;
    border-radius: var(--sc-radius-md);
    transition: transform 140ms ease, background 200ms ease, color 200ms ease, box-shadow 220ms ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    text-decoration: none;
    line-height: 1;
}
.sc-btn--primary {
    background: linear-gradient(180deg, var(--sc-accent) 0%, var(--sc-stamp) 100%);
    color: #fff;
    box-shadow: var(--sc-shadow-btn);
}
.sc-btn--primary::after {
    content: '→';
    font-size: 18px;
    transition: transform 220ms cubic-bezier(0.34, 1.56, 0.4, 1);
    margin-left: 2px;
}
.sc-btn--primary:hover {
    transform: translateY(-2px);
    box-shadow: var(--sc-shadow-btn-hover);
}
.sc-btn--primary:hover::after { transform: translateX(5px); }
.sc-btn--primary:active {
    transform: translateY(0);
    box-shadow: var(--sc-shadow-btn);
}
.sc-btn--primary:disabled {
    background: var(--sc-rule);
    color: var(--sc-moss);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.sc-btn--block { width: 100%; }

/* Loading spinner — used on buttons mid-request (.is-loading) and inline in
   progress messages (.lw-msg--progress). Drafting is an OpenAI round-trip with
   no determinate duration, so this is an indeterminate spinner, not a bar. */
.sc-spinner {
    display: inline-block;
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    vertical-align: -0.15em;
    animation: sc-spin 0.7s linear infinite;
    flex: 0 0 auto;
}
.sc-btn.is-loading {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.55em;
}
.lw-msg--progress {
    display: flex;
    align-items: center;
    gap: 0.6em;
}
@keyframes sc-spin {
    to { transform: rotate(360deg); }
}
/* Respect reduced-motion: drop the spin, keep a static ring as a "busy" cue. */
@media (prefers-reduced-motion: reduce) {
    .sc-spinner { animation: none; border-top-color: currentColor; opacity: 0.5; }
}

.sc-btn--ghost {
    background: transparent;
    color: var(--sc-primary);
    padding: 12px 18px;
    border: 1.5px solid var(--sc-rule);
    border-radius: var(--sc-radius-md);
}
.sc-btn--ghost:hover {
    background: var(--sc-primary);
    color: var(--sc-surface);
    border-color: var(--sc-primary);
}

/* -----------------------------------------------------------------
 * MP reveal card — appears after postal lookup
 * ----------------------------------------------------------------- */
.sc-mp {
    background: var(--sc-surface);
    border: 1px solid var(--sc-rule);
    border-left: 4px solid var(--sc-accent);
    border-radius: var(--sc-radius-lg);
    padding: 24px 26px;
    margin-bottom: 24px;
    position: relative;
    animation: sc-slide-in 380ms cubic-bezier(0.2, 0.65, 0.3, 1);
    box-shadow: var(--sc-shadow-paper);
}
.sc-mp__label {
    font-family: var(--sc-font-body);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--sc-moss);
    margin: 0 0 6px;
}
.sc-mp__name {
    font-family: var(--sc-font-display);
    font-size: 30px;
    font-weight: 480;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: var(--sc-primary);
    margin: 0 0 6px;
    font-variation-settings: "opsz" 72, "SOFT" 40;
}
.sc-mp__riding {
    font-family: var(--sc-font-body);
    font-style: normal;
    font-size: 16px;
    color: var(--sc-ink);
    margin: 0 0 14px;
    opacity: 0.78;
}
.sc-mp__party {
    display: inline-block;
    font-family: var(--sc-font-mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    padding: 4px 9px;
    margin-left: 8px;
    vertical-align: middle;
    border-radius: var(--sc-radius-sm);
}
.sc-mp__party--LIB    { background: rgba(213, 22, 26, 0.12); color: #b50d10; }
.sc-mp__party--CPC    { background: rgba(20, 41, 87, 0.12); color: #142957; }
.sc-mp__party--NDP    { background: rgba(255, 130, 0, 0.16); color: #c25a00; }
.sc-mp__party--GREEN  { background: rgba(60, 130, 60, 0.14); color: #2c6a2c; }
.sc-mp__party--OTHER  { background: rgba(111, 127, 106, 0.18); color: var(--sc-moss); }
.sc-mp__office {
    font-family: var(--sc-font-mono);
    font-size: 12px;
    color: var(--sc-moss);
    letter-spacing: 0.04em;
    margin: 0 0 4px;
}
/* Shown only when the postal hit the campaign's `default` fallback rule —
   i.e. the result is NOT the supporter's own MP. widget.js toggles [hidden]. */
.sc-mp__note {
    font-family: var(--sc-font-body);
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--sc-stamp);
    background: rgba(37, 99, 235, 0.07);
    border-left: 2px solid var(--sc-stamp);
    border-radius: var(--sc-radius-sm);
    padding: 10px 14px;
    margin: 10px 0 4px;
}
.sc-mp__changeable {
    font-family: var(--sc-font-body);
    font-size: 13px;
    color: var(--sc-primary);
    background: none;
    border: none;
    /* Keep the underline affordance on the text only — an inline-flex box
     * with vertical padding gives the control a >=44px tap target (#30 —
     * WCAG 2.5.5 Target Size) without drawing a full-width underline. The
     * inner span carries the hairline so it underlines just the words. */
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    cursor: pointer;
    padding: 4px 0;
    margin-top: 6px;
    letter-spacing: 0;
    text-align: left;
    transition: border-color 160ms ease, color 160ms ease;
}
.sc-mp__changeable .sc-mp__changeable-text {
    border-bottom: 1px solid var(--sc-rule);
    padding-bottom: 2px;
    transition: border-color 160ms ease;
}
.sc-mp__changeable:hover { color: var(--sc-stamp); }
.sc-mp__changeable:hover .sc-mp__changeable-text {
    border-bottom-color: var(--sc-stamp);
}

@keyframes sc-slide-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* -----------------------------------------------------------------
 * Script panel — talking points
 * ----------------------------------------------------------------- */
.sc-script {
    background: var(--sc-surface);
    border: 1px solid var(--sc-rule);
    border-radius: var(--sc-radius-lg);
    padding: 26px 28px 22px;
    margin: 24px 0;
    font-family: var(--sc-font-body);
    font-size: 16px;
    line-height: 1.65;
    color: var(--sc-ink);
    position: relative;
    box-shadow: var(--sc-shadow-paper);
}
.sc-script::before {
    content: '✎  What to say';
    position: absolute;
    top: -11px;
    left: 22px;
    background: var(--sc-paper);
    padding: 2px 10px;
    font-family: var(--sc-font-body);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--sc-primary);
    border-radius: var(--sc-radius-pill);
    border: 1px solid var(--sc-rule);
}
.sc-script p { margin: 0 0 12px; }
.sc-script p:last-child { margin-bottom: 0; }
.sc-script strong {
    font-weight: 700;
    color: var(--sc-stamp);
}

/* -----------------------------------------------------------------
 * Ringing state — quiet pulse
 * ----------------------------------------------------------------- */
.sc-ringing {
    text-align: center;
    padding: 56px 28px;
}
.sc-ringing__dot {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--sc-pulse);
    margin: 0 auto 24px;
    animation: sc-heartbeat 1.4s ease-in-out infinite;
    box-shadow: 0 0 0 0 var(--sc-pulse);
}
@keyframes sc-heartbeat {
    0%, 100% { transform: scale(1);   box-shadow: 0 0 0 0   rgba(59, 130, 246, 0.5); }
    50%      { transform: scale(1.4); box-shadow: 0 0 0 18px rgba(59, 130, 246, 0); }
}
.sc-ringing__title {
    font-family: var(--sc-font-body);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--sc-moss);
    margin: 0 0 10px;
}
.sc-ringing__mp {
    font-family: var(--sc-font-display);
    font-size: 30px;
    font-weight: 480;
    color: var(--sc-primary);
    margin: 0 0 20px;
    font-variation-settings: "opsz" 72, "SOFT" 40;
}
.sc-ringing__status {
    font-family: var(--sc-font-body);
    font-size: 14.5px;
    color: var(--sc-moss);
    letter-spacing: 0;
}
.sc-ringing__status span {
    display: inline-block;
    animation: sc-blink 1.4s steps(1) infinite;
}
.sc-ringing__status span:nth-child(2) { animation-delay: 0.2s; }
.sc-ringing__status span:nth-child(3) { animation-delay: 0.4s; }
@keyframes sc-blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0; }
}

/* -----------------------------------------------------------------
 * Thank-you state — rubber stamp graphic
 * ----------------------------------------------------------------- */
.sc-thanks {
    /* The confirmation keeps the SAME box the supporter has been looking at
     * through the earlier stages (#98, client ask). Before this it set only
     * padding + centring, so at the moment of completion the card vanished and
     * the text floated on the page ground — or, embedded, straight on the
     * client's own background, which read as the app ending mid-flow. Same
     * tokens as .sc-card on purpose: the container should look unchanged, only
     * its contents. */
    background: var(--sc-surface);
    border: 1px solid var(--sc-rule);
    border-radius: var(--sc-radius-lg);
    box-shadow: var(--sc-shadow-card);
    text-align: center;
    padding: 48px 28px 28px;
    animation: sc-fade-up 420ms cubic-bezier(0.2, 0.65, 0.3, 1);
}
/* Celebratory mark — concentric pulse around a check icon. Replaces
   the rubber-stamp metaphor with something warmer + still distinct. */
.sc-stamp {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 84px;
    height: 84px;
    margin: 0 auto 24px;
    color: var(--sc-stamp);
    background: var(--sc-surface);
    border: 2px solid var(--sc-accent);
    border-radius: 50%;
    font-family: var(--sc-font-body);
    font-size: 0;
    box-shadow: 0 0 0 6px rgba(37, 99, 235, 0.08), 0 0 0 14px rgba(37, 99, 235, 0.04);
    position: relative;
    animation: sc-stamp-drop 700ms cubic-bezier(0.34, 1.56, 0.4, 1);
}
.sc-stamp::before {
    content: '';
    width: 30px;
    height: 16px;
    border-left: 3.5px solid var(--sc-accent);
    border-bottom: 3.5px solid var(--sc-accent);
    transform: rotate(-45deg) translate(2px, -4px);
    border-radius: 2px;
}
/* The data-date attribute is still set for analytics + tests but no
   longer rendered as a stamp footer. */
@keyframes sc-stamp-drop {
    0%   { transform: scale(0.4); opacity: 0; }
    60%  { transform: scale(1.08); opacity: 1; }
    100% { transform: scale(1); }
}
@keyframes sc-fade-up {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

.sc-thanks__headline {
    font-family: var(--sc-font-display);
    font-size: clamp(28px, 4.5vw, 42px);
    font-weight: 480;
    line-height: 1.12;
    color: var(--sc-primary);
    margin: 0 0 14px;
    font-variation-settings: "opsz" 96, "SOFT" 60;
}
.sc-thanks__headline em {
    font-style: italic;
    color: var(--sc-stamp);
    font-variation-settings: "opsz" 144, "SOFT" 100, "WONK" 1;
}
.sc-thanks__body,
.sc-thanks__limit-banner {
    font-family: var(--sc-font-body);
    font-size: 17px;
    line-height: 1.55;
    color: var(--sc-ink);
    max-width: 480px;
    margin: 0 auto 36px;
}

/* Optional follow-up note — rendered when page_slots.thanks_followup_md is set
 * (e.g. "we're drafting a letter version — check your email"). Slim and quiet
 * — not a card, just a tinted reading band. Hidden entirely if the slot is empty. */
.sc-thanks__followup {
    font-family: var(--sc-font-body);
    font-size: 14.5px;
    line-height: 1.55;
    color: var(--sc-primary);
    background: var(--sc-highlight, rgba(37, 99, 235, 0.07));
    border-left: 2px solid var(--sc-accent);
    border-radius: 0 var(--sc-radius-md) var(--sc-radius-md) 0;
    max-width: 480px;
    margin: -16px auto 32px;
    padding: 12px 16px;
    text-align: left;
}
.sc-thanks__followup p { margin: 0; }
.sc-thanks__followup p + p { margin-top: 6px; }

/* Issue #22 — "send it yourself" mailto fallback on the thanks view.
 * Hidden (via the [hidden] attribute set in the template) until
 * letter-widget.js fills the href from the /submit response. Styled as a
 * quiet centred band with a ghost button so it reads as an optional extra,
 * not a competing primary CTA against the donate/share blocks below it. */
.lw-mailto-fallback {
    max-width: 480px;
    margin: 0 auto 32px;
    text-align: center;
}
.lw-mailto-fallback[hidden] { display: none; }
.lw-mailto-fallback__label {
    font-family: var(--sc-font-body);
    font-size: 14.5px;
    line-height: 1.5;
    color: var(--sc-moss, #5a6b5a);
    margin: 0 0 10px;
}

/* -----------------------------------------------------------------
 * Next-step block: donate + share
 * ----------------------------------------------------------------- */
.sc-next {
    display: grid;
    gap: 24px;
    margin-top: 32px;
}
.sc-next__donate {
    background: linear-gradient(135deg, var(--sc-primary) 0%, var(--sc-stamp) 100%);
    color: var(--sc-surface);
    padding: 28px;
    border-radius: var(--sc-radius-lg);
    text-align: left;
    position: relative;
    overflow: hidden;
    /* No shadow: since #98 this panel is NESTED inside the confirmation card,
     * and a card shadow inside a card shadow reads muddy. The gradient already
     * separates it from the surface. */
}
.sc-next__donate::before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: 60%;
    background:
        radial-gradient(circle at 90% 50%, rgba(96, 165, 250, 0.25) 0%, transparent 55%);
    pointer-events: none;
}
.sc-next__donate-label {
    font-family: var(--sc-font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--sc-pulse);
    margin: 0 0 8px;
}
.sc-next__donate-headline {
    font-family: var(--sc-font-display);
    font-size: 24px;
    font-weight: 480;
    line-height: 1.2;
    margin: 0 0 16px;
    font-variation-settings: "opsz" 72, "SOFT" 50;
}
.sc-next__donate .sc-btn--primary {
    margin-top: 8px;
}

.sc-share {
    padding: 14px 0 4px;
    text-align: left;
}
.sc-share__label {
    font-family: var(--sc-font-body);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--sc-primary);
    margin: 0 0 14px;
}
.sc-share__buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.sc-share__btn {
    appearance: none;
    border: 1px solid var(--sc-rule);
    background: var(--sc-surface);
    color: var(--sc-primary);
    font-family: var(--sc-font-body);
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    /* >=44px tap target (#30 — WCAG 2.5.5). min-height + min-width plus
     * centred content keeps the pills compact for short labels ("X")
     * while still clearing the 44px touch floor on phones. */
    padding: 11px 18px;
    min-height: 44px;
    min-width: 44px;
    border-radius: var(--sc-radius-pill);
    cursor: pointer;
    transition: all 160ms ease;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.sc-share__btn:hover {
    background: var(--sc-primary);
    color: var(--sc-paper);
    border-color: var(--sc-primary);
}
.sc-share__btn svg { width: 13px; height: 13px; }

/* -----------------------------------------------------------------
 * Inline error / status messages
 * ----------------------------------------------------------------- */
.sc-msg {
    font-family: var(--sc-font-body);
    font-size: 14px;
    padding: 11px 14px;
    border-radius: var(--sc-radius-md);
    margin: 14px 0 6px;
    letter-spacing: 0;
    line-height: 1.45;
}
.sc-msg--error {
    color: #b3261e;
    background: rgba(179, 38, 30, 0.06);
    border-left: 3px solid #b3261e;
}
.sc-msg--info {
    color: var(--sc-primary);
    background: rgba(37, 99, 235, 0.06);
    border-left: 3px solid var(--sc-primary);
}

/* -----------------------------------------------------------------
 * Footer — typed credits
 * ----------------------------------------------------------------- */
.sc-footer {
    margin-top: 64px;
    padding-top: 24px;
    border-top: 1px solid var(--sc-rule);
    font-family: var(--sc-font-body);
    font-size: 13px;
    line-height: 1.6;
    color: var(--sc-moss);
    letter-spacing: 0;
}
.sc-footer a {
    color: var(--sc-primary);
    text-decoration: none;
    border-bottom: 1px solid var(--sc-rule);
}
.sc-footer a:hover { border-bottom-color: var(--sc-primary); }
.sc-footer__row {
    display: flex;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

/* -----------------------------------------------------------------
 * "How it works" — moved below the form as post-context, lighter weight.
 * ----------------------------------------------------------------- */
.sc-how {
    margin: 56px 0 16px;
}
.sc-how__head {
    font-family: var(--sc-font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--sc-moss);
    margin: 0 0 18px;
    display: flex;
    align-items: center;
    gap: 12px;
}
.sc-how__head::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--sc-rule);
}

/* -----------------------------------------------------------------
 * Form helpers — quiet privacy/trust note under the CTA
 * ----------------------------------------------------------------- */
.sc-form__trust {
    font-family: var(--sc-font-body);
    font-size: 12.5px;
    color: var(--sc-moss);
    text-align: center;
    margin: 12px 0 2px;
    line-height: 1.5;
}

/* -----------------------------------------------------------------
 * View state switching — driven by data-state on .sc-widget
 * ----------------------------------------------------------------- */
.sc-view { display: none; }
/* New collapsed-flow states (default). The old `postal` / `form` states are
   kept as fallbacks for tests / preview that still drive them by hand. */
.sc-widget[data-state="form"]    .sc-view--form    { display: block; }
.sc-widget[data-state="postal"]  .sc-view--form    { display: block; }
.sc-widget[data-state="call"]    .sc-view--call    { display: block; }
.sc-widget[data-state="ringing"] .sc-view--call    { display: block; }
.sc-widget[data-state="thanks"]  .sc-view--thanks  { display: block; }

/* -----------------------------------------------------------------
 * Page-load reveal staggering (progressive enhancement)
 * Base: visible. Animation added only when motion is allowed.
 * ----------------------------------------------------------------- */
.sc-reveal { opacity: 1; transform: none; }
@media (prefers-reduced-motion: no-preference) {
    .sc-reveal {
        opacity: 0;
        transform: translateY(10px);
        animation: sc-fade-up 500ms cubic-bezier(0.2, 0.65, 0.3, 1) forwards;
    }
    .sc-reveal[data-delay="1"] { animation-delay: 80ms; }
    .sc-reveal[data-delay="2"] { animation-delay: 180ms; }
    .sc-reveal[data-delay="3"] { animation-delay: 300ms; }
    .sc-reveal[data-delay="4"] { animation-delay: 440ms; }
}

/* -----------------------------------------------------------------
 * Goal meter (#2 — T1.7e frontend). A quiet progress band above the
 * widget. The whole section carries [hidden] in the template and is
 * un-hidden by widget.js only when the goal endpoint returns a
 * configured goal — so campaigns without a goal show nothing rather
 * than an empty bar. All values come from the --sc-* tokens so per-
 * campaign themes + dark mode keep working.
 * ----------------------------------------------------------------- */
.sc-goal {
    margin: 0 0 40px;
}
.sc-goal[hidden] { display: none; }
.sc-goal__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin: 0 0 10px;
}
/* The big "current" number borrows the stat-callout display treatment so
 * the meter reads as a sibling of the hero stat, not a new visual idiom. */
.sc-goal__current {
    font-family: var(--sc-font-display);
    font-size: 30px;
    font-weight: 480;
    color: var(--sc-primary);
    letter-spacing: -0.02em;
    line-height: 1;
    font-variation-settings: "opsz" 72, "SOFT" 50;
}
.sc-goal__total {
    font-family: var(--sc-font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--sc-moss);
}
/* The track is the ARIA progressbar; the fill width is set inline by JS. */
.sc-goal__track {
    height: 12px;
    background: var(--sc-rule);
    border-radius: var(--sc-radius-pill);
    overflow: hidden;
}
.sc-goal__fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--sc-accent) 0%, var(--sc-stamp) 100%);
    border-radius: var(--sc-radius-pill);
    /* Animate the fill on first paint so the bar "fills up" to its value;
     * disabled under prefers-reduced-motion via the global reduce block. */
    transition: width 700ms cubic-bezier(0.2, 0.65, 0.3, 1);
}
.sc-goal__percent {
    font-family: var(--sc-font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--sc-moss);
    margin: 8px 0 0;
}

/* -----------------------------------------------------------------
 * Activity stream (#2 — T1.7f frontend). A short feed of recent,
 * already-redacted supporter actions below the widget. Hidden by the
 * template's [hidden] attribute until widget.js confirms the endpoint
 * is enabled AND returned >=1 event. Renders only first name + city +
 * action + relative time — no client-side PII is added.
 * ----------------------------------------------------------------- */
.sc-activity {
    margin: 8px 0 16px;
}
.sc-activity[hidden] { display: none; }
.sc-activity__head {
    font-family: var(--sc-font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--sc-moss);
    margin: 0 0 14px;
    display: flex;
    align-items: center;
    gap: 12px;
}
.sc-activity__head::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--sc-rule);
}
.sc-activity__list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.sc-activity__item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px dashed var(--sc-rule);
    font-family: var(--sc-font-body);
    font-size: 14px;
    color: var(--sc-ink);
}
.sc-activity__item:last-child { border-bottom: none; }
/* The actor + action phrase; the name gets the campaign primary ink so the
 * "<Name> just called" line has a quiet emphasis on who acted. */
.sc-activity__who { color: var(--sc-primary); font-weight: 600; }
.sc-activity__when {
    font-family: var(--sc-font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--sc-moss);
    flex: 0 0 auto;
    white-space: nowrap;
}

/* -----------------------------------------------------------------
 * Responsive — mobile-first; tighten the spacing on small screens
 * ----------------------------------------------------------------- */
@media (max-width: 540px) {
    .sc-shell { padding: 40px 20px 72px; }
    .sc-card { padding: 24px 20px; }
    /* Matches the .sc-card tightening now that the thanks view is also a card;
     * keeps a little extra headroom for the celebratory stamp. */
    .sc-thanks { padding: 32px 20px 24px; }
    .sc-next__donate { padding: 22px 20px; }
    .sc-mp { padding: 22px 20px; }
    .sc-mp__name { font-size: 26px; }
    .sc-stats {
        grid-template-columns: 1fr 1fr;
    }
    .sc-stat { border-right: none; border-bottom: 1px solid var(--sc-rule); padding: 10px 14px; }
    .sc-stat:nth-last-child(-n+2) { border-bottom: none; }
    .sc-headline { font-size: 36px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
    .sc-stamp { transform: rotate(-6deg); }
}

/* -----------------------------------------------------------------
 * Letter-writer widget (.lw-*) — supporter form for kind=letter
 * campaigns. Shares all tokens with the call widget; only the bits
 * the letter flow needs differently live here. State machine:
 *   form (default) -> review (edit AI draft) -> thanks
 * ----------------------------------------------------------------- */
.lw-view { display: none; }
.lw-widget[data-state="form"]   .lw-view--form   { display: block; }
.lw-widget[data-state="review"] .lw-view--review { display: block; }
.lw-widget[data-state="thanks"] .lw-view--thanks { display: block; }

/* Draft-revision badge — small pill counter next to "Your draft". */
.lw-draft__revision {
    display: inline-block;
    font-family: var(--sc-font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sc-moss);
    background: var(--sc-paper);
    border: 1px solid var(--sc-rule);
    border-radius: var(--sc-radius-pill);
    padding: 3px 9px;
    margin-left: 10px;
    vertical-align: middle;
}

/* Card spacing for the review state — the form card already has its
 * own header padding, so the draft card sits below the MP card with
 * a generous gap. */
.lw-draft {
    margin-top: 24px;
}

/* Trix editor — match the sc-input look so the editor blends with the
 * rest of the form. Trix's default min-height is generous; pin it to
 * something readable on phones. */
trix-editor.lw-body-editor {
    width: 100%;
    min-height: 280px;
    border: 1.5px solid var(--sc-rule);
    background: var(--sc-paper);
    font-family: var(--sc-font-body);
    font-size: 16px;
    line-height: 1.55;
    color: var(--sc-ink);
    padding: 14px 16px;
    border-radius: var(--sc-radius-md);
    outline: none;
    transition: border-color 160ms ease, background 160ms ease, box-shadow 160ms ease;
}
trix-editor.lw-body-editor:focus {
    border-color: var(--sc-accent);
    background: var(--sc-surface);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
}

/* Action row — Regenerate + Submit side-by-side, stacks on mobile. */
.lw-actions {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 18px;
}
.lw-actions .sc-btn { flex: 1 1 0; min-width: 160px; }

/* Inline message slot — reuses sc-msg base. Stays display:none until
 * the JS shows it. */
.lw-msg { margin: 14px 0 6px; }

/* The MP card on the letter review screen — same look as the call
 * widget's .sc-mp, but no party chip / office line / "Wrong MP?"
 * button (those are call-specific). The lw-mp modifier exists for any
 * letter-only tweaks future commits might want. */
.lw-mp { /* shares all .sc-mp styles via the underlying class */ }
