/* app/styles/print.css — the worksheet sheet itself.
 *
 * IMPORTANT — this file is loaded TWICE, on purpose:
 *   1. worksheet.html   <link rel="stylesheet" href="app/styles/print.css" media="print">
 *   2. worksheet.css    @import url("print.css") screen;   (first line of that file)
 *
 * So every top-level rule below styles BOTH the printed page and the on-screen
 * A4 preview from one source — the preview cannot drift from the printout.
 * The `@media print` block at the bottom only ever matches through route (1);
 * inside route (2) it evaluates to `screen and print`, i.e. never.
 *
 * Conversely, app/styles/worksheet.css wraps ALL of its own rules in
 * `@media screen`, so none of the builder chrome (grid panes, overflow,
 * transforms, shadows) exists in the print cascade at all.
 *
 * Target engine: Chromium.
 */

/* =========================================================================
   THE PAGE BOX — one set of numbers, declared once, used by both media.
   Chromium will not resolve var() inside @page, so the four numbers are
   written out literally there and mirrored into custom properties directly
   below. Nothing else in either stylesheet may hard-code them: the screen
   preview builds its page box out of --page-* (see worksheet.css), and
   app/worksheet.js measures --page-w / --page-pitch off a probe element
   rather than carrying its own copy. So there is exactly one place to edit,
   and the preview cannot drift away from the printer.
   CHANGE THE @page RULE AND THE CUSTOM PROPERTIES TOGETHER.
   ========================================================================= */

@page {
  size: A4;
  margin: 13mm 12mm;
}

:root {
  --page-w: 210mm;             /* A4 short edge  */
  --page-h: 297mm;             /* A4 long edge   */
  --page-mx: 12mm;             /* @page margin, left/right */
  --page-my: 13mm;             /* @page margin, top/bottom */
  --page-cw: calc(var(--page-w) - 2 * var(--page-mx));   /* 186mm */
  --page-ch: calc(var(--page-h) - 2 * var(--page-my));   /* 271mm */
}

/* =========================================================================
   Sheet frame + base typography (screen preview AND print)
   Body text is a system sans at 10.5pt: school printers and PDF viewers
   render it consistently, and it sits well next to the KaTeX math faces.
   ========================================================================= */

.print-root {
  /* The base size lives in a custom property because the two-column question
     layout has to switch font-size OFF on the list and back ON inside each
     cell (see .ws-questions.cols-2) — one declaration, not two copies that
     can drift. */
  --ws-fs: 10.5pt;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: var(--ws-fs);
  line-height: 1.35;
  color: #000;
  orphans: 2;
  widows: 2;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.print-root h1,
.print-root h2,
.print-root p,
.print-root ol,
.print-root li,
.print-root div {
  margin: 0;
  padding: 0;
}

.print-root ol {
  list-style: none;
}

/* Math inherits the sheet colour; MathLive static markup supplies the fonts. */
.print-root .ML__latex {
  color: inherit;
}

/* A LaTeX failure must never blank a worksheet (see core/render.js fallback). */
.print-root .math-error {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 9pt;
  outline: 1px dashed #999;
}

/* =========================================================================
   Version section + header block
   No flex / no grid anywhere in the print flow — the meta stamp is floated,
   which fragments predictably across pages.
   ========================================================================= */

.ws-version + .ws-version {
  break-before: page;
  page-break-before: always;
}

.ws-head {
  border-bottom: 1px solid #000;
  padding-bottom: 2mm;
  margin-bottom: 1mm;
  break-inside: avoid;
  page-break-inside: avoid;
  break-after: avoid;
  page-break-after: avoid;
}

.ws-head::after {
  content: "";
  display: table;
  clear: both;
}

.ws-meta {
  float: right;
  margin-left: 6mm;
  padding-top: 1.2mm;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
  font-size: 8.5pt;
  line-height: 1.2;
  text-align: right;
  white-space: nowrap;
  color: #000;
}

.ws-title {
  font-size: 15pt;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.ws-vtag {
  display: inline-block;
  margin-left: 2.5mm;
  padding: 0.2mm 1.6mm;
  border: 1px solid #000;
  border-radius: 1.2mm;
  font-size: 9pt;
  font-weight: 600;
  letter-spacing: 0;
  vertical-align: 1.5pt;
  white-space: nowrap;
}

.ws-skills {
  margin-top: 1mm;
  font-size: 8.5pt;
  line-height: 1.3;
  color: #333;
}

/* Name / Class / Date rule line ----------------------------------------- */

.ws-fields {
  margin: 3mm 0 1mm;
  font-size: 10pt;
  break-inside: avoid;
  page-break-inside: avoid;
  break-after: avoid;
  page-break-after: avoid;
}

.ws-field {
  margin-right: 7mm;
  white-space: nowrap;
}

.ws-rule {
  display: inline-block;
  height: 1em;
  border-bottom: 1px solid #000;
  vertical-align: baseline;
}

.ws-rule--name  { width: 52mm; }
.ws-rule--class { width: 20mm; }
.ws-rule--date  { width: 28mm; }

/* =========================================================================
   Questions
   .ws-questions is a WRAPPER (a div, not the <ol>): with section headings on
   it holds alternating <h2 class="ws-part"> and <ol class="ws-part__list">,
   because an <ol> may only contain <li>. With headings off it holds exactly
   one <ol> and no heading — same shape, one code path, one set of rules.
   The counter reset stays on the wrapper, so question numbering runs
   CONTINUOUSLY across the inner lists (1..N, never restarting per part) and
   the answer key stays aligned with the question sheet. Each version has its
   own wrapper, so numbering does restart at 1 on version B.
   The number is an absolutely-positioned ::before rather than a list marker:
   outside markers get clipped at column edges in Chromium multicol, and the
   whole sheet still lives inside one (worksheet.css's .ws-flow fragmentainer),
   so this is not a trap the two-column rewrite below made go away.
   .ws-q never fragments (break-inside: avoid in one column, and an atomic
   inline-block in two), so the absolute number can never be orphaned from
   its question.
   ========================================================================= */

.ws-questions {
  counter-reset: q;
  margin-top: 2.5mm;
}

/* ------------------------------------------------------------ two columns
   ROW-MAJOR, not newspaper. Questions read 1 2 / 3 4 / 5 6 across the sheet,
   so the questions of one learning outcome sit next to each other instead of
   being flung half a page apart down two columns.

   This used to be `columns: 2` on the wrapper. CSS multicol fills COLUMN-MAJOR
   by definition — 1..k down the left, k+1..n down the right — and there is no
   switch for the other order, so the mechanism itself had to go.

   WHAT REPLACES IT: each .ws-q becomes an INLINE-BLOCK half-width cell, so a
   pair of them shares ONE LINE BOX and the next pair wraps to the next line.
   Not flex and not grid: this whole sheet is nested inside the screen
   preview's fragmentainer (worksheet.css turns .ws-flow into a multicol one
   page's content box in size, so preview column k IS printed page k+1), and
   Chromium fragments flex and grid containers across multicol and pages
   unreliably. A line box, by contrast, is ATOMIC — it is never split across a
   fragmentainer — which is exactly the "a row is never torn across a page
   break" rule, for free and from the engine rather than from a hint.

   Pairing restarts at every part heading with no extra work: each part is its
   own <ol>, a block box, so it starts a fresh line. A part with an odd number
   of questions ends with a half-empty row and the next part begins a new one.
   The heading itself stays a full-width block across both cells.

   THE GEOMETRY: body column 186mm = 89 + 8 gutter + 89. The gutter is a
   margin on the LEFT cell of each pair only; a trailing margin on the right
   cell would count towards the line and push its partner onto the next row.
   The pair fills the line EXACTLY, which looks like it should be one
   LayoutUnit away from wrapping — it is not: Chromium rounds the calc down,
   so at 186mm the row measures 702.953125px against 702.984375px available.
   Swept 150-220mm in 0.005mm steps, 14001 widths, zero wraps. Don't "fix"
   this with a fudge factor. */

.ws-questions.cols-2 .ws-part__list {
  /* font-size: 0 is the classic inline-block whitespace guard. Today
     worksheet.js joins the <li>s with ''.join() so there is no text node
     between them — but a single space here is ~1mm wide, 89 + 1 + 8 + 89 no
     longer fits 186mm, and EVERY row would silently collapse to one question.
     Pretty-printing that markup must not be able to do that. (Measured: with
     this line deleted, four indented cells lay out as four rows, all flush
     left.) It also zeroes
     the line box's strut, so a row is exactly as tall as its taller question.
     --ws-fs is restored on the cell below; it is declared once, on
     .print-root, so the base size is not written down twice. */
  font-size: 0;
  /* One "line" here is one ROW of questions, not a line of prose. The
     inherited orphans/widows: 2 would insist two whole rows travel together
     and leave up to 50mm of a page blank to honour it. Each .ws-q was an
     independent block before this change, with no such rule; 1/1 keeps the
     old packing. (Inheriting into the cells is harmless: an inline-block is
     atomic, so its own contents can never be split across a page anyway.) */
  orphans: 1;
  widows: 1;
}

.ws-questions.cols-2 .ws-q {
  display: inline-block;
  vertical-align: top;
  width: calc((100% - 8mm) / 2);   /* 89mm */
  font-size: var(--ws-fs);
}

/* The gutter. :nth-child(odd) is the LEFT cell of each pair — and because
   each part is its own <ol>, "odd" restarts per part, which is the pairing
   rule itself. */
.ws-questions.cols-2 .ws-q:nth-child(odd) {
  margin-right: 8mm;
}

/* The inner list is pure structure: no box of its own, so the questions sit
   exactly where they did when .ws-questions was itself the <ol>. (The
   .print-root ol reset above already zeroes these — restated because this
   one is load-bearing rather than incidental.) */
.ws-questions .ws-part__list {
  margin: 0;
  padding: 0;
}

/* NOTE: .ws-q is now a GRANDCHILD of .ws-questions, so this can no longer be
   a child combinator — but it must stay at (0,2,0) or above so the padding
   survives the .print-root li (0,1,1) typography reset above.
   .ws-questions .ws-q is (0,2,0): same specificity as before. */
.ws-questions .ws-q {
  counter-increment: q;
  position: relative;
  box-sizing: border-box;
  padding: 2.5mm 0 2.5mm 8mm;
  break-inside: avoid;
  page-break-inside: avoid;
}

.ws-questions .ws-q::before {
  content: counter(q) ".";
  position: absolute;
  left: 0;
  top: 2.5mm;
  width: 6mm;
  text-align: right;
  font-weight: 700;
}

/* -------------------------------------------------------- part headings
   Shared by the question sheet and the answer key.
   (0,2,0) via .print-root, because .print-root h2 (0,1,1) zeroes h2 margins.
   A stranded heading — one left at the foot of a column or page with its
   questions overleaf — is the failure mode to design out, hence the whole
   break-* family: break-after on the heading, break-before on the list that
   follows it AND on that list's first question, so whichever break point
   Chromium's multicol actually evaluates, one of them says "not here". */
.print-root .ws-part {
  margin: 5mm 0 1.5mm;
  padding-bottom: 1mm;
  /* 1px like every other rule on the sheet (sub-pixel mm widths render
     inconsistently once the screen preview is scaled down); subordinate to
     .ws-head / .ws-key__title by COLOUR, #999 against their #000. */
  border-bottom: 1px solid #999;
  font-size: 11.5pt;
  font-weight: 700;
  line-height: 1.25;
  break-inside: avoid;
  page-break-inside: avoid;
  break-after: avoid;
  page-break-after: avoid;
}

/* First part sits under the header/fields rule, which already spaces it. */
.print-root .ws-part:first-child {
  margin-top: 1mm;
}

.print-root .ws-part + .ws-part__list,
.print-root .ws-part + .ws-part__list > .ws-q:first-child,
.print-root .ws-part + .ws-part__list > .ws-key__item:first-child {
  break-before: avoid;
  page-break-before: avoid;
}

.ws-stem {
  line-height: 1.5;
}

.ws-note {
  margin-top: 0.8mm;
  font-size: 8.5pt;
  line-height: 1.3;
  color: #333;
}

/* -------------------------------------------------------------- diagrams
   app/components/figure.js writes <figure class="ws-fig"> holding the SVG and
   a <figcaption>. The SVG is self-contained — hairlines, dashes, grey fills
   and text are all presentation attributes, nothing here can switch them off,
   and nothing about it is screen-only.

   PADDING, NOT MARGIN, top and bottom. worksheet.js measures this block's
   offsetHeight to work out how much taller a figure makes its question (see
   --fig-h below); padding is inside offsetHeight and cannot collapse into a
   neighbour, so the measurement is the whole truth. A margin would be neither.

   Centred, as diagrams are on a printed paper. (0,2,0) via .print-root so the
   `.print-root div { margin: 0; padding: 0 }` typography reset above — which is
   (0,1,1) and matches nothing here, but would match a future <div> variant —
   can never quietly flatten the box. Same trap as .ws-questions .ws-q. */
.print-root .ws-fig {
  margin: 0;
  padding: 2mm 0 0.5mm;
  text-align: center;
  break-inside: avoid;
  page-break-inside: avoid;
}

/* max-width, so two columns scale the picture down instead of overflowing;
   height:auto so it scales rather than squashing. The widest archetype is
   279px = 73.8mm and the narrowest box a figure ever sits in is a two-column
   cell: 89mm wide less the 8mm reserved for the question number = 81mm of
   usable width. (Unchanged by the row-major rewrite — the old multicol column
   was 89mm too.) So in practice nothing shrinks — this is the guarantee, not
   the everyday case. */
.print-root .ws-fig svg {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  height: auto;
}

.print-root .ws-fig__cap {
  margin: 0.8mm 0 0;
  font-size: 8.5pt;
  font-style: italic;
  line-height: 1.3;
  color: #222;
}

/* Working space — total height of the question block, border-box.
   The stem eats into it: a block asking for 45mm is 45mm tall in total, so a
   two-line stem leaves rather less than 45mm to write in. That is the existing
   behaviour and it is deliberate — the number a teacher picks is how much of
   the PAGE each question is given.

   A FIGURE IS ADDED ON TOP OF IT, not taken out of it. --fig-h is the measured
   height of this question's .ws-fig block, written inline on the <li> by
   worksheet.js's sizeFigures(); the working space is then exactly what it
   would have been had the question carried no diagram at all. The alternative —
   letting the figure eat the space, as the stem does — leaves a 45mm question
   with a 49mm diagram no room to answer in at all, which is not a choice any
   teacher would make on purpose.

   Non-figure questions are untouched: no .ws-q--fig class, no --fig-h, the
   same three numbers as before, so no existing worksheet repaginates. */
.ws-questions.space-none .ws-q { min-height: 0; }
.ws-questions.space-S    .ws-q { min-height: 25mm; }
.ws-questions.space-M    .ws-q { min-height: 45mm; }
.ws-questions.space-L    .ws-q { min-height: 70mm; }

.ws-questions.space-S .ws-q--fig { min-height: calc(25mm + var(--fig-h, 0px)); }
.ws-questions.space-M .ws-q--fig { min-height: calc(45mm + var(--fig-h, 0px)); }
.ws-questions.space-L .ws-q--fig { min-height: calc(70mm + var(--fig-h, 0px)); }

/* =========================================================================
   Answer key
   ========================================================================= */

.ws-key {
  break-before: page;
  page-break-before: always;
}

.ws-key__title {
  margin-bottom: 3mm;
  padding-bottom: 1.5mm;
  border-bottom: 1px solid #000;
  font-size: 12pt;
  font-weight: 700;
  break-after: avoid;
  page-break-after: avoid;
}

/* Same wrapper shape as .ws-questions — a div holding optional <h2
   class="ws-part"> headings and <ol class="ws-part__list"> lists — so the key
   mirrors the question sheet's parts. counter k stays here on the wrapper:
   key numbering runs continuously across the parts and therefore keeps
   matching the question numbers. */
.ws-key__list {
  counter-reset: k;
}

.ws-key__list .ws-part__list {
  margin: 0;
  padding: 0;
}

.ws-key__item {
  counter-increment: k;
  break-inside: avoid;
  page-break-inside: avoid;
}

.ws-key__item::before {
  content: counter(k) ")\00a0";
  font-weight: 700;
}

/* 'separate' — compact three-column list of answers only. */
.ws-key--compact .ws-key__list {
  columns: 3;
  column-gap: 8mm;
}

.ws-key--compact .ws-key__item {
  padding: 1mm 0;
  font-size: 10pt;
  line-height: 1.4;
}

/* 'solutions' — full width, one question per row, worked lines beneath. */
.ws-key--solutions .ws-key__list {
  columns: 1;
}

.ws-key--solutions .ws-key__item {
  padding: 1.8mm 0 2.2mm 8mm;
  text-indent: -8mm;
  border-bottom: 1px solid #ccc;
}

.ws-key--solutions .ws-key__answer {
  font-weight: 600;
}

.ws-key__sol {
  margin: 1.2mm 0 0 1mm;
  text-indent: 0;
  font-size: 9.5pt;
  line-height: 1.45;
  color: #222;
}

.ws-key__line {
  padding: 0.3mm 0;
}

/* =========================================================================
   Print-only: hide the builder and neutralise every screen-side geometry
   rule that could survive into the print cascade.
   ========================================================================= */

@media print {
  html,
  body {
    margin: 0 !important;
    padding: 0 !important;
    background: #fff !important;
    height: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
  }

  /* Everything that is not the sheet. */
  .builder-ui,
  .screen-only {
    display: none !important;
  }

  /* The preview chain: .builder > .preview-pane > .sheet-frame > .sheet-scaler
     > .print-root. worksheet.css only styles these inside @media screen, so
     normally there is nothing to undo — this is the belt-and-braces pass that
     guarantees no scroll clipping and, above all, NO transform in print. */
  .builder,
  .preview-pane,
  .sheet-frame,
  .sheet-scaler {
    display: block !important;
    position: static !important;
    overflow: visible !important;
    transform: none !important;
    zoom: 1 !important;
    filter: none !important;
    contain: none !important;
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    box-shadow: none !important;
  }

  .print-root {
    display: block !important;
    position: static !important;
    transform: none !important;
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;   /* page margins come from @page, not from padding */
    border: 0 !important;
    background: #fff !important;
    box-shadow: none !important;
  }

  /* .ws-flow is the sheet's one and only wrapper. On screen it is turned into
     a multi-column fragmentainer 186 x 271 mm — one column per printed page —
     which is how the preview reproduces the printer's page breaks exactly.
     On paper the PRINTER is the fragmentainer, so the wrapper must collapse
     back to a plain block: a multicol here would fragment the sheet twice.
     worksheet.css only styles it inside @media screen, so normally there is
     nothing to undo; this is the belt-and-braces pass. */
  .print-root > .ws-flow {
    display: block !important;
    columns: auto !important;
    column-width: auto !important;
    column-count: auto !important;
    column-fill: balance !important;
    width: auto !important;
    height: auto !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
  }
}
