/* =============================================================================
   print.css — ballot-card print stylesheet
   -----------------------------------------------------------------------------
   Loaded via <link rel="stylesheet" href="print.css" media="print"> AFTER
   styles.css, so its rules win the cascade when (and only when) printing.
   Even though the <link media="print"> already scopes this file to print, the
   whole file is ALSO wrapped in `@media print`. That is deliberate: it makes the
   file self-contained and portable — if someone later inlines it, drops the
   media attribute, or reorders the <link>s, the print scoping still holds.
   Strategy (why this file is short):
     1. Override the DESIGN TOKENS to a black-on-white print palette. Because
        every component in styles.css references tokens (never raw colors), the
        entire ballot card re-colors itself for print with no per-component work.
        Pass 3 added a brand-primitive and derived-color layer UPSTREAM of the
        semantic roles, so those primitives must be overridden here too —
        otherwise brand blue/green leak onto paper through the semantic tokens.
     2. Hide the app chrome (header, nav, buttons, export fallbacks, footer) —
        export is the card alone.
     3. Add print-only concerns tokens can't express: @page margins, physical
        type sizes, page-break control, and QR sizing.
   Page budget: a typical card (nine answers, a few short notes) fits one
   Letter/A4 page. Nine long notes are allowed to run onto a second page;
   the type is NOT shrunk to prevent that. Rows never split across pages.
   Constraints honored:
     - No fixed positioning and NO viewport units (vw/vh) anywhere below. Physical
       units (cm/mm/pt) are used instead — mobile print engines choke on vw/vh.
     - Choice state prints as TEXT ("YES"/"NO"/"UNDECIDED"), never color alone,
       so the card is fully legible in grayscale.
   ========================================================================== */
@media print {
  /* ==========================================================================
     1. PRINT TOKEN OVERRIDES — the single seam for print theming
     ======================================================================== */
  :root {
    /* --- Brand primitives and derived ramps → ink. These sit upstream of the
       semantic roles, so overriding them here is what actually stops color
       reaching the page. --- */
    --brand-blue:  #000;  --brand-green: #000;  --brand-gray:  #000;
    --blue-ink:  #000;  --blue-deep: #000;  --blue-mid: #000;  --blue-tint: #fff;
    --green-ink: #000;  --green-mid: #000;  --green-tint: #fff;
    --gray-ink:  #000;  --gray-mid:  #000;
    --gray-line: #000;  --gray-line-strong: #000;
    /* --- Semantic roles --- */
    --color-bg:          #fff;
    --color-surface:     #fff;
    --color-border:      #000;   /* hairlines print as crisp black rules */
    --color-border-ui:   #000;
    --color-text:        #000;
    --color-text-muted:  #000;   /* muted grays vanish on paper; force black */
    /* Accents collapse to ink — no colored fills, no wasted toner. */
    --color-accent:      #000;
    --color-accent-ink:  #000;
    --color-accent-weak: #fff;
    --color-brand-green:     #000;
    --color-brand-green-ink: #000;
    /* Choice colors collapse to black: the WORD carries the meaning, so
       grayscale/mono printers lose nothing. */
    --color-choice-yes:        #000;
    --color-choice-no:         #000;
    --color-choice-undecided:  #000;
    --color-choice-yes-ink:        #000;
    --color-choice-no-ink:         #000;
    --color-choice-undecided-ink:  #000;
    /* Notice/warn tints → ink. The inversion note stays black + bold. */
    --color-notice-bg:   #fff;  --color-notice-ink:  #000;
    --color-warn-bg:     #fff;  --color-warn-ink:    #000;
    --shadow-card: none;        /* box-shadows don't print; drop it explicitly */
  }
  /* ==========================================================================
     2. PAGE BOX & BASE
     ======================================================================== */
  @page {
    /* Physical margins keep the card off the paper edge on every printer.
       `portrait` matches the single-column card; a typical card fits one
       page at these sizes, and long notes may spill to a second. */
    size: portrait;
    margin: 1cm;
  }
  html, body {
    background: #fff;
    color: #000;
    /* Defensive and explicit: state the family here so the print renderer
       resolves the same system stack the screen does, even if it evaluates the
       cascade differently. (There is no webfont to fail to embed — typography
       is a pure system stack — but being explicit costs nothing.) */
    font-family: var(--font-body);
    font-size: 11pt;
    line-height: 1.35;
  }
  /* Full-bleed content column: the @page margin (above) is the only inset. */
  .main {
    max-width: none;
    margin: 0;
    padding: 0;
  }
  /* ==========================================================================
     3. HIDE APP CHROME — the card is the product, everything else is UI
     `!important` guarantees we beat any [hidden]/display rules from styles.css.
     ======================================================================== */
  .skip-link,
  .site-header,
  .app-status,
  .site-footer,
  .noscript-msg,
  .progress-bar,                 /* progress bar is UI, not part of the card */
  .banner,                       /* order / webview notices */
  .ballot-card__view-control,    /* compact/detailed screen toggle */
  .ballot-card__actions,         /* Print / Image / Copy buttons */
  .hint--saved,                  /* where-your-notes-live line */
  .ballot-card__manage,          /* erase control + its confirm step */
  .confirm,
  .copy-fallback,                /* tier-3 copy box, if it happens to be open */
  .image-fallback,               /* tier-3 image preview, if it happens to be open */
  .image-overlay,                /* press-and-hold overlay, if it happens to be open */
  [data-action="image"],
  [data-action="review-undecided"] {
    display: none !important;
  }
  /* Any view that isn't the ballot card is already [hidden] by app.js at print
     time; this is a belt-and-suspenders guard if someone prints mid-flow. */
  .view--welcome,
  .view--question,
  .view--privacy,
  .view--howto {
    display: none !important;
  }
  /* Draft watermark (meta.draft; [hidden] otherwise). On screen it is a fixed
     layer; here it is absolutely positioned onto the first page, in physical
     units, so it prints faintly across the card without touching the flow.
     Text ink survives "no background graphics" mode, unlike a background. */
  .watermark {
    position: absolute;
    inset: auto;
    top: 8cm;
    left: 0;
    right: 0;
    height: auto;
    display: block;
    overflow: visible;
    text-align: center;
    pointer-events: none;
  }
  .watermark__text {
    display: inline-block;
    font-size: 110pt;
    color: #000;
    opacity: 0.08;
    transform: rotate(-30deg);
  }
  /* ==========================================================================
     4. THE BALLOT CARD
     ======================================================================== */
  .ballot-card {
    border: none;                /* @page provides the frame; no boxed border */
    border-radius: 0;
    box-shadow: none;
    padding: 0;
  }
  .ballot-card__head {
    border-bottom: 1.5pt solid #000;
    padding-bottom: 6pt;
    /* Keep the header glued to the first row — never orphan the title. */
    break-after: avoid-page;
  }
  /* Screen headings are serif under the cSPA theme; the printed card keeps
     the body sans (and its tracking) so paper output is unchanged. */
  .ballot-card__head h1  {
    font-size: 20pt;
    margin: 0;
    font-family: var(--font-body);
    letter-spacing: -0.011em;
  }
  .ballot-card__date     { font-size: 10pt; margin: 2pt 0 0; }
  .ballot-card__sub      { font-size: 10pt; margin: 0; }
  /* --- Rows --- */
  .ballot-card__rows { margin: 6pt 0; }
  .ballot-row {
    grid-template-columns: 4rem minmax(0, 1fr);
    gap: 1pt 7pt;
    padding: 4pt 0;
    border-bottom: 0.5pt solid #000;
    box-shadow: none;            /* the screen-only left bar stays off paper */
    /* A row (with its note/inversion line) must never split across pages. */
    break-inside: avoid;
    page-break-inside: avoid;    /* legacy alias for older print engines */
  }
  .ballot-row__lead, .ballot-row__body { gap: 1pt; }
  .ballot-row__num    { font-weight: 700; font-size: 14pt; }
  .ballot-row__title  { font-size: 13pt; }
  .ballot-row__choice {
    font-size: 16pt;
    font-weight: 700;
    text-align: left;
  }  /* the answer, beneath the Q# in the lead column */
  /* Skipped questions print empty boxes to mark by hand. */
  .ballot-row.is-undecided .ballot-row__choice { display: block; }
  .ballot-row.is-undecided .ballot-row__choice::before {
    content: "□ Yes\A□ No";
    white-space: pre;
    font-size: 12pt;
    font-weight: 400;
  }
  .ballot-row__note   { font-size: 11pt; }
  .ballot-row__meaning { display: none !important; } /* print is always compact */
  .ballot-row__inversion {
    font-size: 11pt;
    font-weight: 700;            /* an inverted question's warning survives to paper */
  }
  /* Keep the status block (the all-set line; the review button is hidden here)
     with what follows, not stranded alone. */
  .ballot-card__status { font-size: 10pt; break-inside: avoid; }
  .ballot-card__status.is-complete p { font-weight: 700; color: #000; }
  /* ==========================================================================
     5. QR CODE
     Currently moot: app.js keeps .ballot-card__qr [hidden] while QR generation
     is paused, and [hidden]{display:none !important} wins here too — so nothing
     below renders until a real generator is vendored in. Kept ready, because
     these are exactly the rules that make a printed code scannable:
     ≥2cm spec (we use 3cm for reliability), and print-color-adjust stops
     "economy"/grayscale modes from lightening the modules into a smear.
     ======================================================================== */
  .ballot-card__qr {
    background: #fff;
    padding: 0;
    margin-top: 8pt;
    break-inside: avoid;         /* label + code stay together */
    -webkit-print-color-adjust: exact;
            print-color-adjust: exact;
  }
  .qr {
    width: 3cm;
    height: 3cm;
    border: 0.5pt solid #000;
    -webkit-print-color-adjust: exact;
            print-color-adjust: exact;
  }
  /* The vendored lib renders a canvas/img/svg; make it fill the 3cm box.
     QR is square, so uniform scaling won't distort it. */
  .qr canvas,
  .qr img,
  .qr svg {
    width: 100% !important;
    height: 100% !important;
    -webkit-print-color-adjust: exact;
            print-color-adjust: exact;
  }
  .qr__label { font-size: 9pt; }
  /* ==========================================================================
     6. FOOTER (attribution + "not an official ballot" + fallback resume URL)
     ======================================================================== */
  .ballot-card__foot {
    margin-top: 6pt;
    padding-top: 4pt;
    border-top: 0.5pt solid #000;
    font-size: 9pt;
    break-inside: avoid;
  }
  /* Resume URL: paper is the only carrier of the choices when local storage is
     unavailable, so app.js un-hides this in that mode only. It stays
     display:none on screen (styles.css), and [hidden] still overrides this in
     the normal, storage-backed case. */
  .resume-print {
    display: block;
    margin-top: 4pt;
    font-family: var(--font-mono);
    font-size: 8pt;
    word-break: break-all;       /* a long fragment must not run off the page */
  }
}
