/* ==========================================================================
   print.css — Analytics report print stylesheet
   Linked as: <link rel="stylesheet" href="print.css" media="print">

   Everything is nested in @media print per project convention, even though
   the media="print" attribute on the <link> already scopes the whole file.

   Source page structure (see comments inline for why each override exists):
     body (flex row, height:100vh, overflow:hidden, centered via negative
           margin for a 1440px layout)
       ├─ a.btn-nav        "Back" link, position:absolute
       ├─ aside            side nav — overflow-y:auto, flex-basis:398px
       └─ main              overflow-y:auto, dark panel
           └─ … content …, including div.chart-wrapper > svg (fixed
               width/height attributes, no viewBox — CSS width/height alone
               cannot rescale these; only `zoom` or `transform: scale()` can,
               see section 4 below for why this file uses `zoom`)

   Print budget assumed: A4 portrait, 15mm margins → ~680px usable width
   (180mm × 96dpi/25.4mm-per-inch ≈ 680px). Chart-scaling math below targets
   670px to leave a ~10px safety buffer against print rounding.
   ========================================================================== */

@media print {

  /* --------------------------------------------------------------------
     0. Page setup
     -------------------------------------------------------------------- */
  @page {
    size: A4 portrait;
    margin: 15mm;
  }

  /* --------------------------------------------------------------------
     1. Kill the app-shell layout that causes the clipped/partial print
        (problem #4) and the off-page content (part of problem #1).

     body was: display:flex (row); height:100vh; overflow:hidden;
     max-width:1440px; margin:0 calc((100% - 1440px)/2).

     On a print page (~680px), that margin formula resolves to a large
     *negative* left margin, shoving the whole layout off-page — and the
     100vh + overflow:hidden on body, combined with overflow-y:auto on
     main, is what turns main into a scroll container whose off-screen
     content never reaches the printer. None of these are needed once
     this is a normal flowing document instead of a fixed-viewport app.
     -------------------------------------------------------------------- */
  body {
    display: block !important;
    height: auto !important;
    overflow: visible !important;
    max-width: none !important;
    margin: 0 !important;
    padding: 0 !important; /* was 80px top, reserved only for .btn-nav */
    background: #fff !important;
    color: #000 !important;
  }

  main {
    overflow: visible !important;
    height: auto !important;
    background: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    /* Original padding (81px 88px 88px 88px) would eat ~176px of the
       ~680px print width on its own — drop it and let @page's 15mm
       margins provide the page-level whitespace instead. */
    padding: 0 !important;
  }

  /* --------------------------------------------------------------------
     2. Hide non-print UI (problem #2 + agreed scope additions)
     -------------------------------------------------------------------- */
  aside,                 /* side nav — stable element selector, not fragile */
  .btn-nav,               /* "Back" link; position:absolute with no positioned
                             ancestor, would otherwise float over the title
                             once body's own layout is unlocked above */
  .download-btn,          /* "Download chart" buttons — interactive-only */
  .tooltip {               /* d3 hover tooltip, JS-driven, no use on paper */
    display: none !important;
  }

  /* --------------------------------------------------------------------
     3. Text color: black on white (problem #3)

     body's color:#000 above covers everything that inherits color
     normally. These are the spots with an explicit *lighter* color of
     their own (via class or inline style) that would otherwise stay
     light-on-white and wash out.
     -------------------------------------------------------------------- */
  section.summary,
  .key-audiences-feature {
    background: none !important;
    color: #000 !important;
  }

  /* Now that section.summary and .key-audiences-feature have no
     background of their own to set them apart, their padding (48px and
     40px, from the base stylesheet) just knocks their content out of
     alignment with every other section's flush-left text. Zero both out
     so everything lines up. */
  section.summary,
  .key-audiences-feature {
    padding: 0 !important;
  }

  .legend-label {
    color: #000 !important;
  }

  /* Legend swatches (the small dot next to "Sample audience" / "General
     audience") are a plain <span class="legend-circle"> colored via an
     inline style="background-color: rgb(...)" — not text, not SVG, just
     a normal HTML background-color. If the browser's own print dialog
     has "background graphics" turned off (Chrome's default), every
     background-color on the page is dropped, and since this element has
     no visible border or content of its own, it disappears entirely
     rather than just losing a tint. Force it to print regardless of that
     toggle — this is the one non-SVG spot in the page where an inline
     background-color actually carries information. */
  .legend-circle {
    print-color-adjust: exact !important;
    -webkit-print-color-adjust: exact !important;
  }

  /* SVG chart text: some tick/label <text> elements use the
     fill="currentColor" presentation attribute (follows `color`, already
     fixed by body's color:#000 above), others carry an inline
     style="fill: rgb(255,255,255)" (.bar-label, .group-label,
     .x-axis-title, and a couple of unclassed axis-title text elements).
     Inline styles beat inherited `color`, so this needs !important — one
     blanket rule covers every case regardless of class. */
  main svg text {
    fill: #000 !important;
  }

  /* Axis domain line: .domain is D3's own stable class name (always
     present on every chart, not generated/fragile). Some domain paths
     carry an inline style="stroke: rgb(...)" in a pale accent color (e.g.
     rgb(239,172,168)) that has poor contrast on white paper, especially
     on a black-and-white printer — force a legible neutral instead.
     Decorative gradient gridlines (stroke="url(#...)") are deliberately
     NOT touched here — they're low-information background rungs, not
     text, and matching every per-chart gradient id isn't worth the
     complexity. Note this means targeting ".tick line" is NOT safe: the
     gridlines' own <g> also carries class="tick" (reused from the axis
     ticks), so a ".tick line" rule would repaint them solid black too —
     the real axis tick lines are 0-length by design (invisible either
     way), so there's nothing to gain from matching them regardless. */
  main svg .domain {
    stroke: #000 !important;
  }

  /* Make sure the above (and the charts' own data-color fills, which are
     intentional and untouched) actually reach the printer regardless of
     the user's own "background graphics" print setting. */
  main svg {
    print-color-adjust: exact !important;
    -webkit-print-color-adjust: exact !important;
  }

  /* Section-divider <hr>s (main hr, not the hidden aside's menu hr): the
     base stylesheet already sets border-top-color: #707070, a genuine
     mid-grey, but at 1px it reads as near-black on paper. Override to a
     lighter, unambiguous grey. */
  main hr {
    border-top-color: #ccc !important;
  }

  /* --------------------------------------------------------------------
     4. Chart width (problem #1, chart-specific part)

     SVGs have fixed width/height attributes and no viewBox, so CSS
     width/height on the <svg> itself does not rescale their contents —
     it only changes the viewport and clips. transform: scale() is the
     only way to shrink them; it's a visual-only transform, so the
     wrapper's own box width has to be reduced separately or its
     (unscaled) layout box still overflows the page.
     -------------------------------------------------------------------- */

  /* Safety net for every chart: never let a chart wrapper's box exceed
     the printable width, regardless of its inline width. This is what
     clips the three charts that are 85%+ over budget (genres,
     avoidance-topics, topics) — scaling those down to fit would shrink
     their labels to roughly a third of size and stop being legible, so
     per the brief they're clipped instead. Also acts as a fallback for
     any future chart this stylesheet doesn't know about yet. */
  .chart-wrapper {
    max-width: 680px !important;
    overflow: hidden !important;
  }

  /* Charts 17% or less over budget (702–795px wide): scale down to fit
     rather than clip. Each block below is one chart because the scale
     factor depends on that chart's own (D3-computed) width — there's no
     shared class to hang a single rule on.

     This uses `zoom` rather than `transform: scale()`. transform is
     paint-only — it doesn't change the element's layout box, so the
     wrapper's box stays at its original (oversized) width/height and has
     to be corrected separately with explicit width/height. That mismatch
     between an element's pre-transform layout size and its post-transform
     painted size is exactly what Chrome's print pagination measures
     against, and when one of these charts landed near a page break it
     visibly tore mid-chart (the top-left portion of the rotated axis
     labels — closest to the break — went missing on one test render).
     `zoom` instead scales the box model itself, so layout and paint agree
     and there's nothing for pagination to get wrong. It's a de facto
     standard (Chrome/Edge/Safari) but not in Firefox until v126 (2024);
     given this is a Chrome print-to-PDF workflow, that's an acceptable
     trade — flagging it in case the report is ever printed from Firefox. */

  #audience-religious-chart-container svg {          /* 702×440 → ×0.954 */
    zoom: 0.954;
  }

  #audience-sexual-orientation-chart-container svg,  /* 795×440 → ×0.843 */
  #tones-chart-container svg,
  #character-age-chart-container svg {
    zoom: 0.843;
  }

  #audience-ethnicity-chart-container svg,           /* 795×450 → ×0.843 */
  #character-personality-chart-container svg,
  #location-setting-chart-container svg,
  #regions-chart-container svg {
    zoom: 0.843;
  }

  /* --------------------------------------------------------------------
     5. Pagination niceties (not one of the 4 problems, low-risk to add)
     -------------------------------------------------------------------- */
  h1, h2, h3, h4 {
    break-after: avoid-page; /* don't strand a heading at the bottom of a page */
  }

  .chart-wrapper {
    break-inside: avoid-page; /* every chart, scaled or not, is well under
                                  one page tall, so this is always safe */
  }

  /* Note: section.summary intentionally NOT given break-inside:avoid-page
     — it wraps "Executive summary" + "Key audiences" + "Key hooks",
     including the 740px-tall key-hooks chart, and is comfortably taller
     than one printed page. Forcing it to stay together would just
     produce a large blank gap instead of a clean page break. */
}

/* ==========================================================================
   FRAGILE-SELECTOR SUMMARY

   The DOM here is unusually clean (semantic <aside>/<main>, stable D3 class
   names, descriptive per-chart ids) so there was no need for nth-child,
   positional, or generated-class selectors anywhere in this file. The one
   real fragility is the hardcoded scale factor for the 8 scaled charts,
   each computed as 670 ÷ that chart's own inline width:

     #audience-religious-chart-container            702px wide → zoom: 0.954
     #audience-sexual-orientation-chart-container    795px wide → zoom: 0.843
     #tones-chart-container                          795px wide → zoom: 0.843
     #character-age-chart-container                  795px wide → zoom: 0.843
     #audience-ethnicity-chart-container             795px wide → zoom: 0.843
     #character-personality-chart-container          795px wide → zoom: 0.843
     #location-setting-chart-container               795px wide → zoom: 0.843
     #regions-chart-container                        795px wide → zoom: 0.843

   These ids and the general "chart-wrapper" clipping/color rules are stable
   and will keep working on the live page. But if the underlying report data
   changes enough that D3 recomputes a different width for any of these
   charts (e.g. more/fewer categories), its zoom factor above goes stale —
   a chart could end up clipped when it should scale, scaled by the wrong
   factor (too small/too large for its new width), or — if a chart not
   currently in this list grows past ~795px — need adding to this list
   instead of just falling through to the generic clip-at-680px safety net.
   Re-check chart widths (via the Playwright script) whenever chart data
   changes materially.
   ========================================================================== */
