/* print.css — PAPER IS WHITE, WHATEVER THEME IS ON SCREEN.
   ===========================================================================
   A SEPARATE FILE, LOADED AFTER EVERY THEME, and that placement is the reason
   it is a file at all. This started life at the end of chrome.css and broke a
   rule the package enforces: "chrome.css uses !important — the base must be
   overridable by every theme. Source order is the whole mechanism."
   (test/themes.test.js). That rule is right, and print is the one thing it does
   not cover: a theme MUST NOT be able to override the print medium, because
   nobody picks a theme for their printer.

   So this loads last, after the theme files, where it wins on source order the
   way the rest of the layer does — and the `!important` it still carries is for
   beating a theme's higher-specificity `:root[data-palette="x"] h1` selectors,
   not for beating the base. themes.test.js names this file as the one exemption
   and says why, so the exemption is deliberate rather than an oversight nobody
   noticed.
   =========================================================================== */

/* ===========================================================================
   PRINT: PAPER IS WHITE, WHATEVER THEME IS ON SCREEN
   ===========================================================================
   Reported 2026-09-16: saving a report as PDF in Cyberpunk produced blank
   pages. "The content is there, but invisible due to poor colour choice."
   Exactly right — measured under print media, Cyberpunk's body text came out at
   1.22:1 against white and its <h1> at 1.00:1, which is white ink on white
   paper.

   WHY ONLY CYBERPUNK, AND WHY THE FIX IS STILL GLOBAL. Measured across all
   seven themes: the other five dark ones print at 15-18:1 because they put
   their dark colours behind `@media (prefers-color-scheme: dark)`, which does
   not apply to the print medium, so paper got their light defaults by accident.
   Cyberpunk sets `--pico-color` and `--pico-h1-color: #fff` unconditionally on
   `:root[data-palette="cyberpunk"]`, so the dark ink followed it onto the page.

   So five themes print correctly BY LUCK, not by design, and any new theme that
   declares its colours the way Cyberpunk does would arrive with the same bug.
   Fixing cyberpunk.css alone would leave that trap set. This block makes print
   colour a property of the MEDIUM rather than of the theme, which is what it
   always was: nobody chooses a theme for their printer.

   Structure stays where it lives — the layout side of printing (hiding the
   sidebar and topbar, freeing the width) is already in the Asset Manager's
   styles.css and is untouched here.

   test/printContrast.test.js measures every theme under print media and fails
   below 4.5:1, so this cannot rot and a new theme cannot reintroduce it. */
@media print {
  /* The tokens first, so anything reading them inherits paper colours rather
     than being overridden element by element. Every palette and both explicit
     variants are named: a theme sets these at `:root[data-palette="x"]`, which
     out-specifies a bare `:root`. */
  :root,
  :root[data-palette],
  :root[data-theme="light"],
  :root[data-theme="dark"],
  :root[data-palette][data-theme="light"],
  :root[data-palette][data-theme="dark"] {
    --pico-background-color: #ffffff;
    --pico-color: #111111;
    --pico-h1-color: #000000;
    --pico-h2-color: #000000;
    --pico-h3-color: #000000;
    --pico-h4-color: #000000;
    --pico-h5-color: #000000;
    --pico-h6-color: #000000;
    --pico-muted-color: #444444;
    --pico-muted-border-color: #bbbbbb;
    --pico-border-color: #999999;
    --pico-primary: #000000;
    --pico-table-border-color: #999999;
    --pico-table-row-stripped-background-color: transparent;
  }

  /* Then EVERY element, not a list of them, because a theme may set `color`
     directly on anything at all. The first version of this block named html,
     body, main, tables and headings — and a screenshot showed the report's
     caption still pale cyan, because it is a <strong> that carries its own
     colour. Measuring the worst contrast of every text-bearing element in the
     content found it at 1.22:1 while the three elements the first test sampled
     all passed.
     A blanket override is right for print specifically: paper has one
     background, so there is no palette left to preserve. Meaning that was
     carried by colour is re-carried by the border on .status-badge below. */
  html,
  body,
  .app-shell,
  .content,
  .content.container,
  main,
  main *,
  .content * {
    background-color: transparent !important;
    background-image: none !important;
    color: #111111 !important;
    text-shadow: none !important;
    -webkit-text-fill-color: #111111 !important;
    box-shadow: none !important;
  }
  html,
  body {
    background-color: #ffffff !important;
  }

  /* After the blanket rule above, so headings keep full-black ink. */
  main h1, main h2, main h3, main h4, main h5, main h6,
  .content h1, .content h2, .content h3, .content h4, .content h5, .content h6,
  h1, h2, h3, h4, h5, h6 {
    color: #000000 !important;
    -webkit-text-fill-color: #000000 !important;
    /* A theme may paint a heading with a clipped gradient, which prints as
       nothing at all because backgrounds are not printed. */
    background: none !important;
    -webkit-text-fill-color: #000000 !important;
    text-shadow: none !important;
  }

  table, th, td, caption {
    background: transparent !important;
    color: #111111 !important;
    border-color: #999999 !important;
    text-shadow: none !important;
  }
  th { border-bottom: 1px solid #333333 !important; }

  /* STATUS BADGES KEEP THEIR MEANING WITHOUT THEIR FILL. They are a coloured
     pill on screen; browsers do not print the fill, so the light text inside
     would vanish on its own. An outline plus dark ink keeps the distinction
     legible in a way that survives a monochrome printer too — which a colour
     difference alone never would. */
  main .status-badge,
  .content .status-badge,
  .status-badge {
    background: transparent !important;
    color: #000000 !important;
    -webkit-text-fill-color: #000000 !important;
    border: 1px solid #333333 !important;
    text-shadow: none !important;
  }

  /* Links are printed text, not something anybody can click. */
  a, a:visited { color: #111111 !important; text-decoration: none !important; }

  /* ===================================================================
     NOTHING MAY SCROLL ON PAPER — the bug that printed a BLANK SINGLE PAGE
     ===================================================================
     Reported: "when I click 'Print / PDF' in Chrome I get a blank single page
     where I should have 29 pages of assets", while Safari printed all 29.

     `.table-wrap` becomes `overflow: auto` below 768px so a wide table scrolls
     inside its box instead of stretching the page. THE PRINTED PAGE IS NARROWER
     THAN THAT BREAKPOINT: A4 is 794px at 96dpi, and Chrome's default print
     margins take the content box to roughly 718px. So printing silently entered
     the narrow layout, the table became a scroll container, and Chrome printed
     only the slice that was "in view" — one page, and effectively blank because
     the visible slice starts above the rows.

     Safari expands overflow when printing, which is why it was fine, and why
     this looked like a Chrome bug rather than a layout one.

     IT ALSO EXPLAINS WHY IT TOOK SO LONG TO REPRODUCE: Playwright's page.pdf()
     defaults to ZERO margins, which keeps the page at 794px — above the
     breakpoint — so every automated PDF came out correct while the real print
     dialog failed. The margin is the variable, not the browser. The repo already
     knew this container clips: core-assumptions.md E7 records that the asset
     list "cannot be screenshotted at all without unclipping .table-wrap".

     So: on paper, nothing scrolls. A scroll container is a screen affordance and
     there is no way to scroll a sheet of paper — anything it hides is simply
     lost. This is written broadly on purpose, because the next scroll pane
     somebody adds will have the same problem and should not need its own fix. */
  /* THE HEIGHT LOCK STARTS AT <html>, WHICH IS WHY UNCLIPPING THE TABLE WAS NOT
     ENOUGH. Measured at print width with the ancestor chain printed out:

       html / body / .app-shell / .app-main / main   all exactly 1000px (the viewport)
       .table-wrap / table / tbody / tr              all 0px

     The app shell is a viewport-height flex column so the sidebar can stay put
     while the content pane scrolls — correct on screen, fatal on paper. `main`
     is `flex: 1 1 0%`, so its height comes from the container rather than from
     its content, and the table inside collapses to nothing. There is no content
     height, so there is nothing to paginate: one page, blank.

     So the shell stops being a shell when printing. Block layout, automatic
     heights, no scroll containers, starting at the root — anything less leaves
     the lock in place one level up, which is exactly the mistake the first
     attempt at this made. */
  html,
  body {
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow: visible !important;
  }

  .app-shell,
  .app-main {
    display: block !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow: visible !important;
  }

  .table-wrap,
  main,
  .content,
  [class*="scroll"],
  [style*="overflow"] {
    overflow: visible !important;
    overflow-x: visible !important;
    overflow-y: visible !important;
    max-height: none !important;
    height: auto !important;
    min-height: 0 !important;
    flex: none !important;
  }

  /* Sticky headers are the other thing that confuses print pagination: a sticky
     <th> can repeat or vanish once the table crosses a page boundary. Static is
     what a printed table wants — the header prints once, at the top. */
  thead th,
  .topbar,
  .sidebar {
    position: static !important;
  }

  /* Decoration that only costs ink. phosphorRain.js's canvas is the loud one, and
     several themes lay a grid or scanline PATTERN over the page through a
     pseudo-element — which `*` does not reach, so it survived the blanket rule
     above and printed as faint vertical banding across every page. */
  canvas, .phosphor-rain { display: none !important; }
  html::before, html::after,
  body::before, body::after,
  .app-shell::before, .app-shell::after,
  main::before, main::after,
  .content::before, .content::after {
    display: none !important;
    background: none !important;
  }
}

/* The shared footer, added 2026-09-17. A version string and a charity
   registration number are exactly what somebody printing an asset report for a
   funder does not need underneath it, and the privacy link is not actionable on
   paper. It lives here rather than in chrome.css because print.css loads after
   the themes; test/themes.test.js enforces that split and caught the rule in
   the wrong file on its first run.
   **AND IT MUST BE INSIDE @media print.** This file is linked as an ORDINARY
   stylesheet with no `media="print"` attribute — the medium is scoped by the
   blocks inside it, not by the link. A bare rule here therefore applies to the
   screen as well: the first version of this hid the footer on every page of
   both apps, in every theme, while all 2015 tests passed. Found by taking a
   screenshot, which is the entire argument for the project's own rule about
   screenshots. */
@media print {
  .scp-footer { display: none !important; }
}

/* THE HELP PAGES, PRINTED (2026-09-21). A printed help page is a handout, and a
   handout that breaks a step away from its picture is the prose it replaced. The
   task cards at the top are navigation and mean nothing on paper.
   In THIS file and not chrome.css: print rules load after the themes, and
   test/themes.test.js refuses an @media print block in chrome.css — it caught
   this one on its first run, which is the rule working. */
@media print {
  .help-step { break-inside: avoid; }
  .help-figure { break-inside: avoid; }
  .help-tasks { display: none !important; }
  .help-others[open] { break-before: page; }
}
