/* ============================================================================
   HSCScience worksheet — SHARED STRUCTURAL LAYER
   ----------------------------------------------------------------------------
   One structure, four skins. This file owns GEOMETRY, TYPE SCALE and PRINT
   BEHAVIOUR and knows nothing about any individual variant's colours.
   `worksheet-variants.css` owns the four skins and is loaded after this file.

   A worksheet selects its skin with ONE attribute on <body>:

       <body data-ws-variant="a">   exam paper
       <body data-ws-variant="b">   editorial workbook   (also the default)
       <body data-ws-variant="c">   engineering pad
       <body data-ws-variant="d">   two-column compact

   A worksheet with NO attribute renders as B. That is deliberate: the default
   is a property of the stylesheet, not of the script that assigns variants, so
   a file the assignment script never reached still prints correctly.

   ----------------------------------------------------------------------------
   STRUCTURAL ROLES

   Three worksheet families with three different class vocabularies live in this
   estate. Rather than fork the system three ways, each family's classes are
   mapped onto one set of roles here, and the variants only ever style roles.

     role            shared-classic     junior-shared        print-theme
     ------------    ----------------   ------------------   ---------------
     sheet           .ws-sheet          .page                .page
     question block  .ws-box            .ws-q                .q
     answer space    .ws-work           .ws-work             (JS-paginated)
     answer key      .ws-answers        .ws-answers          .answer-key
     marks           .ws-marks          .ws-badge-marks      .q-marks

   ----------------------------------------------------------------------------
   PRINT TYPE FLOOR — the reason this file exists at all

   Students print these and write on them. The previous shared stylesheet set
   `body { font: 14px/1.55 }`, i.e. 10.5pt body copy, with hints at 11px (8.25pt)
   and marks at 10px (7.5pt). That is below every legibility guideline for a
   printed worksheet and it is a large part of why the old sheets read as
   machine output.

   Rule enforced here:
     - BODY COPY never below 16px. At the CSS 96dpi reference that is exactly
       12pt on paper. Question stems, part text, hints and answer prose are all
       body copy.
     - SHORT LABELS may go to 12px (9pt) but no lower. Kickers, marks badges,
       name/date captions, footers. Never a sentence.
     - No hairlines. Every printed rule is >= 1px; structural rules are >= 1.5px.
       Sub-pixel borders drop out on consumer inkjets.
   ============================================================================ */

/* ---------------------------------------------------------------- tokens -- */

:root {
  /* Type scale. Do not lower --ws-body or --ws-label without re-reading the
     PRINT TYPE FLOOR note above; `npm run audit:worksheet-type-floor` enforces
     both numbers and will fail the build. */
  --ws-body: 16px;          /* 12pt — the floor for anything that is a sentence */
  --ws-body-lead: 1.5;
  --ws-label: 12px;         /* 9pt — the floor for anything that is not */
  --ws-title: 30px;
  --ws-h2: 19px;
  --ws-meta: 13px;

  /* Rules. Named by weight so variants can restate colour without restating
     thickness and accidentally reintroducing a hairline. */
  --ws-rule-hair: 1px;
  --ws-rule-structural: 1.5px;
  --ws-rule-heavy: 2.5px;

  /* Answer-space geometry. 5mm is the graph-paper pitch variant C draws on, so
     every variant rules at 5mm and C's grid lands on the same baseline as
     A's ruled lines. One rhythm, four surfaces. */
  --ws-rule-pitch: 5mm;

  /* Page. */
  --ws-page-pad-y: 4mm;
  --ws-page-pad-x: 15mm;
}

/* ------------------------------------------------------------- structure -- */

/* Body copy floor, applied at the sheet so it cascades to every family.

   NOT applied to `.worksheet` — that is the print-theme (exam practice) family,
   which paginates in JavaScript into `.page` boxes that are `height: 297mm`
   with `overflow: hidden`. Enlarging type inside a fixed-height clipping box
   drops the overflow silently, and the paginator does not re-run. That family
   is excluded from this system entirely (it is also never sent the stylesheet
   links) — see the note in scripts/assign-worksheet-variants.js. */
.ws-sheet,
[data-ws-variant]:not(:has(.sheet-wrap)) .page {
  font-size: var(--ws-body);
  line-height: var(--ws-body-lead);
}

/* Anything that is a sentence gets body size, explicitly, because each family
   stylesheet sets these smaller and would otherwise win on specificity. */
[data-ws-variant] .ws-purpose,
[data-ws-variant] .ws-hint,
[data-ws-variant] .ws-box p,
[data-ws-variant] .ws-q-stem,
[data-ws-variant] .ws-answer p,
[data-ws-variant] .ws-instruction,
[data-ws-variant] .ws-table td,
[data-ws-variant] .ws-table th,
[data-ws-variant] .ws-label-list,

/* The junior family carries its own prose classes, and every one of them sat
   between 12px and 14px. Listing them here rather than relying on a blanket
   `p, li` selector keeps the floor off the elements that are legitimately
   labels (`.ws-stimulus-label` at 10px, `.ws-goals-title` at 11px), which a
   blanket rule would inflate and break the junior layout. Found by rendering a
   junior worksheet and measuring — the shared-classic path alone reported a
   clean 16px floor while 930 junior sheets were still printing prose at 13px. */
[data-ws-variant] .ws-q,
[data-ws-variant] .ws-tf-statement,
[data-ws-variant] .ws-tf-correction,
[data-ws-variant] .ws-cloze,
[data-ws-variant] .ws-chain-cell,
[data-ws-variant] .ws-stimulus,
[data-ws-variant] .ws-wrapup p,
[data-ws-variant] .ws-goals li,
[data-ws-variant] .ws-sort-box,
[data-ws-variant] .ws-item-chip,
[data-ws-variant] .ws-activity-title {
  font-size: var(--ws-body);
  line-height: var(--ws-body-lead);
}

/* Anything that is a label gets label size — never smaller. */
[data-ws-variant] .ws-kicker,
[data-ws-variant] .ws-marks,
[data-ws-variant] .ws-band,
[data-ws-variant] .ws-badge,
[data-ws-variant] .ws-badge-marks,
[data-ws-variant] .ws-field,
[data-ws-variant] .ws-footer,
[data-ws-variant] .ws-reflect-row label {
  font-size: var(--ws-label);
}

[data-ws-variant] .ws-title { font-size: var(--ws-title); line-height: 1.08; }
[data-ws-variant] .ws-section h2 { font-size: var(--ws-h2); }

/* ------------------------------------------------------- the answer space --

   `.ws-work` is the one structural addition this system makes to the markup.
   It wraps the run of `.ws-line` spans that previously sat loose inside a
   `.ws-box`, giving the answer area a single addressable container.

   That container is what makes one structure carry four skins:
     A  ruled lines on the page
     B  a white card, ruled
     C  5mm graph paper
     D  a column of its own, beside the question rather than beneath it

   Without it, D is not expressible in CSS at all: loose `.ws-line` siblings
   cannot be moved into a second grid column that spans the question's rows,
   because their row index depends on how many `<p>` elements precede them.
   ------------------------------------------------------------------------- */

.ws-work {
  /* Hidden by default, exactly like the loose `.ws-line` spans it replaces.
     The answer-space toggle reveals it. Keeping the default in the same state
     as before means a worksheet that is never toggled prints identically to
     the way it did before this change. */
  display: none;
  margin-top: 10px;
}

.ws-work .ws-line {
  display: block;
  height: var(--ws-rule-pitch);
  border-bottom: var(--ws-rule-hair) solid var(--ws-work-rule, #c9cfda);
}

/* Reveal, mirroring the existing `:has()` toggle contract in worksheet.css. */
body:has(.ws-toggle-answer-space:checked) .ws-work { display: block; }

/* When there is no toolbar at all (print-only exports, and the junior family),
   the answer space is always on — there is nothing to toggle it with. */
body:not(:has(.ws-toggle-answer-space)) .ws-work { display: block; }

/* -------------------------------------------------------------- sections -- */

[data-ws-variant] .ws-section { break-inside: avoid; }

/* A question block should not be split across a page break if it fits on one.
   `avoid` is advisory, but Chromium honours it for blocks shorter than a page,
   which is the case that matters. */
[data-ws-variant] .ws-box,
[data-ws-variant] .ws-q { break-inside: avoid; }

/* ------------------------------------------------------------ answer key -- */

/* The key starts a new page in every variant. What makes it *visually*
   distinct is the variant's job; that it is unmistakably a separate artefact
   is this file's job. */
[data-ws-variant] .ws-answers { break-before: page; }
[data-ws-variant] .ws-answer { break-inside: avoid; }

/* ----------------------------------------------------------------- print -- */

@page { size: A4; margin: 12mm 0; }

@media print {
  /* Backgrounds and fills are load-bearing here — the SOLUTIONS band in A, the
     cream in B, the grid in C. Without this they are dropped by default and
     the answer key stops being distinguishable from the questions. */
  [data-ws-variant] {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  [data-ws-variant] .ws-toolbar,
  [data-ws-variant] .toolbar,
  [data-ws-variant] .ws-page-nav { display: none !important; }

  /* Re-assert the floor. Some family stylesheets drop type inside their own
     print blocks, which would otherwise land under 12pt on paper only — the
     worst failure mode, because it is invisible on screen. */
  .ws-sheet,
  [data-ws-variant]:not(:has(.sheet-wrap)) .page {
    font-size: var(--ws-body);
    line-height: var(--ws-body-lead);
  }
}
