/* Print / "Save as PDF" stylesheet for the whole marketing site.
   Linked from Base.astro as <link rel="stylesheet" href="/print.css"
   media="print">, so every rule here only ever applies to a printed page —
   it never sits in the render-blocking path of a screen visit.

   Lives in public/, NOT inside src/styles/global.css, for two reasons:
     1. check-left-margin.mjs, check-measure.mjs and check-reflow.mjs all
        walk dist/_astro/*.css with no media awareness. A print rule bundled
        into global.css (e.g. `.wrap { max-width: none }`) would land in
        that file and could be misread as a screen rule. public/print.css
        builds straight through to dist/print.css, which none of the three
        ever opens.
     2. global.css is render-blocking on all 96 indexable pages. Print
        bytes have no business sitting in first paint.

   scripts/check-print.mjs is the build gate that keeps this file (and the
   selectors it targets) honest.

   CASCADE ORDER — read this before adding a rule here. Astro injects its
   bundle <link>s AFTER the hand-written ones in Base.astro's <head>, so the
   built order is always:

       <link rel="stylesheet" href="/print.css" media="print">
       <link rel="stylesheet" href="/_astro/Base.<hash>.css">

   This file therefore LOSES every equal-specificity fight with global.css
   and tokens.css. A plain `body { color: … }` here is silently inert. Every
   declaration that overrides a screen rule needs `!important` (or a genuinely
   higher-specificity selector). That includes the custom-property block
   below: `:root[data-theme="dark"]` here and in tokens.css have identical
   specificity, so only `!important` wins. check-print.mjs rule G asserts
   this, because the failure mode is invisible — the rule looks right and
   does nothing. */

@page {
  margin: 18mm;
}

/* Paper is a light surface, so the whole site prints on the light palette
   whatever theme the reader chose on screen. `[data-theme]` is an attribute
   on :root and survives into print media, so a reader who has ever tapped
   the theme toggle used to print body text at #dcd8cc on white — 1.2:1, a
   near-blank page. Measured before this block: 91% of print words across 8
   representative routes fell under 3:1 in the dark theme, against 1% in the
   light theme.

   Neutralising the TOKENS, rather than fighting each property that reads
   one, is what makes that whole class of defect go away at once: every
   component stylesheet on the site colours itself from these, so none of
   them needs its own print override.

   Values are the light theme's own (tokens.css :root), which
   check-contrast.mjs already holds to AA on paper-like surfaces — with one
   necessary exception: the --night-* inks are light-on-charcoal by design,
   and a night band prints white, so they have to flip dark here.

   Selector covers all three places tokens.css sets a palette: :root
   (light), :root[data-theme="dark"], and the html.no-js +
   prefers-color-scheme: dark block at tokens.css:207. */
:root,
:root[data-theme="light"],
:root[data-theme="dark"],
html.no-js {
  /* Surfaces: everything to white paper. */
  --bg: #fff !important;
  --bg-tint: #fff !important;
  --bg-tint-2: #fff !important;
  --surface: #fff !important;
  --surface-2: #fff !important;
  --bubble-bg: #fff !important;

  /* Ink hierarchy — the light palette, verbatim. */
  --ink: #1e2426 !important;
  --ink-soft: #343c3f !important;
  --text: #2a3134 !important;
  --text-dim: #5c6568 !important;
  --text-faint: #686e71 !important;
  --bubble-ink: #1e2426 !important;

  /* Links. The dark theme's light-honey accent is 1.5:1 on white. */
  --accent: #8b5e08 !important;
  --accent-deep: #6e4a04 !important;

  /* Night bands print white, so their light-on-charcoal inks must flip.
     These are the one place the light palette is NOT the right answer. */
  --night: #fff !important;
  --night-2: #fff !important;
  --night-3: #fff !important;
  --night-ink: #1e2426 !important;
  --night-text: #2a3134 !important;
  --night-dim: #5c6568 !important;

  /* Honey fills and tints: the light values, so a highlight or an
     underline colour reads the same on paper in either theme. */
  --honey: #ffc514 !important;
  --honey-deep: #f2ac00 !important;
  --honey-bright: #ffd75e !important;
  --honey-tint: #fff3cd !important;
  --honey-tint-2: #ffe9a3 !important;
  --on-honey: #1e2426 !important;

  /* Signal colours: light values are dark enough for white paper; the dark
     theme's are not (--green #6fc78f is 2.0:1). Tints go pale so they stay
     readable for a reader who prints WITH background graphics on. */
  --green: #297249 !important;
  --green-tint: #e3f1e8 !important;
  --flag: #a04527 !important;
  --flag-tint: #f6e9e3 !important;
  --sky: #3d6ea5 !important;
  --sky-tint: #e6eef7 !important;

  /* Hairlines: a mid grey survives a printer that would drop the light
     theme's near-cream borders altogether. */
  --border: #c4c4c4 !important;
  --border-strong: #9a9a9a !important;
  --night-border: #9a9a9a !important;

  /* Shadows print as a grey haze around every card. */
  --shadow-sm: none !important;
  --shadow-md: none !important;
  --shadow-lg: none !important;
  --shadow-ring: none !important;

  /* Stops the UA painting dark form controls and default text under a
     theme the page no longer uses on paper. */
  color-scheme: light !important;
}

html,
body {
  background: #fff !important;
  color: #1e2426 !important;
}

/* 12pt body type and a tighter leading for paper. Both need !important:
   `var(--fs-body)` (16.32px) and `line-height: 1.65` are declared on
   `body` in global.css, which wins on order otherwise. */
body {
  font-size: 12pt !important;
  line-height: 1.5 !important;
}

/* Free the reading column from the on-screen max-width — paper has its own
   margin, set by @page above. */
.wrap {
  max-width: none !important;
  width: auto !important;
  padding-inline: 0 !important;
}

p,
li,
blockquote {
  orphans: 3;
  widows: 3;
}

/* The main defect this file exists to fix: [data-reveal] elements sit at
   opacity: 0 until an IntersectionObserver adds .is-in as the reader
   scrolls past them (see global.css). Nothing fires that observer during a
   print, so 85% of the site's words print blank without this rule.
   Base.astro's beforeprint handler also adds .is-in directly — belt and
   braces, since Safari doesn't fire beforeprint/afterprint reliably. */
[data-reveal] {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* A handful of components animate a real snippet of copy in on a timer or a
   staggered delay rather than on scroll — Hero's "this morning, while you
   slept" inbox mockup and VoiceDemo's typing caret. Printing is a snapshot
   at t=0, before any delay elapses, so these need the same treatment as
   [data-reveal] above. .heading-anchor/.anchor-mark (the hover-only "#"
   permalink icons next to headings) ride along here too — harmless to show
   statically on paper, and it keeps every opacity: 0 element in <main>
   accounted for by name rather than by a blanket main * selector.
   DELIBERATELY NOT included: .billing-option input (PricingTeaser) — that
   opacity: 0 is a permanently visually-hidden native radio behind a custom
   label, never shown on screen either; forcing it visible would paint a
   raw radio button on top of the label text instead of restoring content. */
.triage-row,
.row-chip,
.triage-foot,
.caret,
.anchor-mark,
.heading-anchor {
  opacity: 1 !important;
  animation: none !important;
  transform: none !important;
}

/* Closed <details> print closed — 7,849 words across 65 pages. Base.astro's
   beforeprint handler opens every <details> element in the DOM; these two
   rules are the no-JS fallback (a script blocked by policy, or a print
   triggered before the handler runs).

   BOTH rules are needed, and the `display` one alone is NOT enough on a
   current engine: Chromium hides a closed <details>'s content through
   `content-visibility` on the internal ::details-content slot, not through
   `display` on the children, so `details:not([open]) > *` is inert there.
   Measured with JS off on /faq: 4 pages and 1,594 chars (the 25 questions,
   none of the answers) before the ::details-content rule; 6 pages and
   6,051 chars after it. The `display` rule stays for older engines that
   have no ::details-content pseudo-element. */
details:not([open]) > * {
  display: block !important;
}
details::details-content {
  content-visibility: visible !important;
}

/* .night pairs a dark gradient background with light ink (PageHero, Hero,
   BlogPost/Guide post headers, /404, the closing CTA band and three
   callouts). Browsers drop background graphics in print by default, so
   without this the h1/dek prints as pale text on white paper.

   The named descendants below are the documented ones (check-print.mjs
   rule D asserts each). `.night *` then catches every component that
   colours its own text for a charcoal band without going through a
   --night-* token — e.g. /trust's `.silo-chip`, honey-on-charcoal at
   1.7:1 once the band prints white. A night band is white paper here, so
   uniform dark ink is right for everything inside it. */
.night {
  background: #fff !important;
}
.night,
.night *,
.night h1,
.night h2,
.night h3,
.night .lead,
.night .eyebrow {
  color: #1e2426 !important;
}

/* Chrome: none of it belongs on paper. */
.site-header,
.site-footer,
.cta,
.jump-nav-section,
.search-overlay,
.reading-progress,
[data-read-next],
.theme-toggle,
.skip-link {
  display: none !important;
}

/* Print-only identity block (Base.astro): hidden on screen by a plain rule
   in global.css, shown here. */
.print-only {
  display: block !important;
}

/* Freshness reach (lens 15): the "Last updated" line (global.css's
   .page-updated, rendered by Base.astro) is content, not chrome — a printed
   page with no date is the same defect as a screen page with none. Named
   explicitly so a future broad chrome selector above can't sweep it up by
   accident. */
.page-updated {
  display: block !important;
}

/* Reading cost (scripts/stamp-reading-time.mjs): content, not chrome —
   named explicitly for the same reason .page-updated is above, so a future
   broad chrome selector can't sweep it up by accident. */
.reading-cost {
  display: inline !important;
}

/* Page-break hygiene. `[class*="card"]` is deliberately broad — the site
   has a dozen distinct card components (StatCard, PostCard, PlanMatrix
   rows, ReadNext's .related-card, …) and a name-based match keeps this
   rule from going stale every time a new one ships. */
h2,
h3 {
  break-after: avoid;
}
table,
figure,
pre,
[class*="card"] {
  break-inside: avoid;
}
thead {
  display: table-header-group !important;
}
tr {
  break-inside: avoid;
}
img {
  max-width: 100% !important;
}

/* /handover's worksheet lines: a ruled blank the reader writes an answer
   on, in the browser and on paper. Explicit here rather than left to the
   --border-strong token above, because this is the exact defect class
   this file exists to catch (see the [data-reveal] comment further up):
   a class that looks right on screen and needs a border on PAPER
   specifically to be usable at all. Both properties need !important —
   handover.astro's own <style> block sets border-bottom from a
   custom-property and this file must win regardless of cascade order. */
.fill-line {
  border-bottom: 1px solid #1e2426 !important;
  color: #1e2426 !important;
  background: transparent !important;
}

/* Printed links are ink, and underlined so they still read as links once
   the colour is gone. Both need !important: global.css declares `color:
   var(--accent)` and `text-decoration: none` on `a`, and this file loses on
   order. The URL itself is deliberately NOT printed (no
   `a::after { content: attr(href) }`) — on a site this densely
   cross-linked that prints as noise, and the print-only identity block
   carries the canonical address instead. */
a {
  color: #1e2426 !important;
  text-decoration: underline !important;
}
