/* DZC print sheet.
 *
 * The printed sheet IS the deployment plan, so the Group nesting tree is the
 * point of it: a Condor carrying two Bear APCs carrying six Legionnaires tells
 * you what arrives, aboard what, in one glance. A flat roster loses that.
 *
 * Rules that hold here:
 *   - a Group never splits across a page
 *   - rules text never breaks mid-sentence
 *   - no chrome, no art, no colour that costs ink for nothing
 *   - the ARMY is a single column. Two-column print of the list was tried and
 *     removed; do not bring it back. The Group nesting tree is tall and narrow
 *     and splitting it puts a Condor at the foot of one column and its cargo at
 *     the head of the next, which loses the one thing the sheet is for.
 *     The rules appendix IS two columns, and that is not the same rule being
 *     bent: it is a hundred short independent entries, the shape columns exist
 *     for, and nothing in it can be separated from anything else.
 *
 * The sheet's own rules are NOT inside @media print any more. The preview has
 * to show the same document on screen, and a rule that only exists at print
 * time is a preview that lies. Which is the one thing a preview may not do.
 * They are scoped to the two places the sheet is ever rendered: the hidden
 * print container and the preview's paper. Only the page-level rules, hiding
 * the app, the paper size, stay in @media print, because those have no
 * meaning on screen.
 */

#dzc-print { display: none; }

@media print {
  /* Hide the app entirely; the sheet is its own document. The preview overlay
     goes with it: it is chrome, and chrome never prints.
     ONLY WHEN THERE IS A SHEET. `.is-sheet` is put on the body by the
     beforeprint handler and only when an army is open. Unconditional, this
     rule hid whatever page you were on and printed the empty container in its
     place -- one blank sheet from Ctrl+P anywhere in the app. */
  body.is-sheet > *:not(#dzc-print) { display: none !important; }
  body.is-sheet #dzc-print { display: block; }
  @page { margin: 12mm 10mm; }
}

:is(#dzc-print, .pp-paper) {
  font: 10pt/1.4 'Jost', system-ui, sans-serif;
  color: #000;
  background: #fff;
}
/* The sheet is a piece of paper whatever theme the app is wearing, and paper
   is white. app.css colours every heading with var(--ink), a rule, which
   beats the inheritance above, so in the dark theme the army name, every
   Group name and "Rules used" came out near-white on white, in the preview and
   on the printed page both. */
:is(#dzc-print, .pp-paper) :is(h1, h2, h3, h4, h5, h6) { color: #000; }

:is(#dzc-print, .pp-paper) .pr-head { border-bottom: 2px solid #000; padding-bottom: 5pt; margin-bottom: 9pt; }
:is(#dzc-print, .pp-paper) .pr-title { font: 700 17pt/1.15 'Roboto Slab', Georgia, serif; margin: 0 0 2pt; }
:is(#dzc-print, .pp-paper) .pr-sub { font-size: 9pt; margin: 0; }
:is(#dzc-print, .pp-paper) .pr-sub b { font-size: 11pt; }

/* A Group is a unit of meaning; it must not be torn across a page.
   NO BOX. Jet, 2026-08-13: "group boxes no need border". The heading and the
   rule under it already say where a Group starts, and a full border round
   every one of nine Groups is nine rectangles of toner drawing what the
   whitespace was drawing for free. break-inside still keeps it whole -- that
   was never the border's job. */
:is(#dzc-print, .pp-paper) .pr-group {
  break-inside: avoid; page-break-inside: avoid;
  padding: 0; margin-bottom: 6pt;
}
:is(#dzc-print, .pp-paper) .pr-g-head {
  display: flex; justify-content: space-between; align-items: baseline;
  border-bottom: .75pt solid #000; padding-bottom: 2pt; margin-bottom: 3pt;
}
:is(#dzc-print, .pp-paper) .pr-g-name {
  font: 700 11pt/1.1 'Roboto Slab', Georgia, serif; margin: 0;
  color: var(--acc-text, var(--acc, #000));
}
:is(#dzc-print, .pp-paper) .pr-g-cost { font-weight: 700; font-size: 9pt; }

/* Nesting, drawn. The rule that runs down the left of a carried Squad is
   what makes "these arrive aboard that" readable without a caption. */
:is(#dzc-print, .pp-paper) .pr-squad { margin-left: calc(var(--depth) * 12pt); padding: 2.5pt 0; }
/* In the faction's colour, like the carry line on screen. It is the one rule
   on the sheet that means something rather than divides something. */
:is(#dzc-print, .pp-paper) .pr-squad--nested {
  border-left: 1.5pt solid var(--acc, #666); padding-left: 6pt;
}
:is(#dzc-print, .pp-paper) .pr-sq-line {
  display: flex; align-items: center; flex-wrap: wrap; gap: 2pt 6pt;
}
:is(#dzc-print, .pp-paper) .pr-sq-n { font-weight: 700; }
:is(#dzc-print, .pp-paper) .pr-sq-name { font-weight: 600; }
:is(#dzc-print, .pp-paper) .pr-sq-cost { margin-left: auto; font-weight: 700; white-space: nowrap; }
/* Capacity and cargo, as the symbols themselves. Sized down to sit on an 8.5pt
   line without pushing the row apart. The glyph has to be small enough to be
   a note beside the name and big enough to still read its digit. */
/* RM aboard a Genitor. Bold because it is a setup instruction rather than a
   stat: this many tokens go on the model before Round 1. */
/* Both ride on the Squad's own line now, so neither opens one. */
:is(#dzc-print, .pp-paper) .pr-rm { font-size: 8pt; font-weight: 700; white-space: nowrap; }
:is(#dzc-print, .pp-paper) .pr-cap { display: inline-flex; align-items: center; gap: 3pt; }
:is(#dzc-print, .pp-paper) .pr-cap .dzc-badge { --badge-px: 13pt; --cargo-px: 11pt; }
:is(#dzc-print, .pp-paper) .pr-cap .dzc-sep { font-size: 8pt; color: #333; }
:is(#dzc-print, .pp-paper) .pr-variants { font-size: 8pt; color: #222; }
:is(#dzc-print, .pp-paper) .pr-cmdr { font-size: 8pt; font-weight: 700; }

/* ── the sheet looks like the app ──
   Jet, 2026-08-13: "I'd like if print mode could resemble all the nice work
   (with icons and shit) we put into builder mode."

   Every renderer below is the SCREEN's, not a paper copy of it: statsHtml,
   rulesHtml, DZCIcon.arc and transportHtml all come straight out of the
   builder. What is set here is only what paper needs -- points instead of
   pixels, and ink that survives a laser printer. A second set of markup for
   print is how the two drift apart, and the shape renderer already proved the
   point: the sheet spent months printing "carries 2 square" in words because
   it had its own idea of what a capacity looked like. */
:is(#dzc-print, .pp-paper) .pr-stats { font-size: 8pt; margin: 1.5pt 0; }
:is(#dzc-print, .pp-paper) .pr-stats b { font-weight: 700; }
/* The builder's stat grid, at paper scale. Fixed columns so two Squads can be
   read against each other down the page, which is the whole reason it is a
   grid on screen. */
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stats {
  display: flex; gap: 8pt; background: none; padding: 0; border: 0;
}
/* VERTICAL. Jet, 2026-08-13: "I want the stats vertical in print." Icon, then
   the number, then what it is -- the same stack the app draws, and the reason
   is the same on paper: a column of five stats laid on its side is five
   label-value pairs to parse left to right, where stacked they are five
   numbers on one baseline that the eye reads across in one go. Each stack is
   narrow, so the whole block is still ONE line of the sheet. */
/* The screen's compact stat is a 2x2 grid -- icon and number on one row, the
   label spanning underneath -- so the grid placements have to be undone here,
   not just the direction set. Written against .is-compact so it outranks
   them rather than tying on specificity and losing to source order. */
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stats.is-compact .dzc-stat {
  display: flex; flex-direction: column; align-items: center; gap: 0;
  background: none; border: 0; padding: 0; min-width: 0;
}
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stats.is-compact :is(.dzc-stat-i, .dzc-stat-v, .dzc-stat-k) {
  grid-column: auto; grid-row: auto;
}
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stat-i { display: inline-flex; }
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stat-i svg { width: 9pt; height: 9pt; }
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stats.is-compact .dzc-stat-v {
  font-weight: 700; font-size: 9pt; line-height: 1.05; text-align: center;
}
:is(#dzc-print, .pp-paper) .pr-stats .dzc-stats.is-compact .dzc-stat-k {
  font-size: 6.5pt; line-height: 1.1; text-transform: uppercase;
  letter-spacing: .04em; color: #444; white-space: nowrap; text-align: center;
}
/* The stats and the Squad's own rules share a line. The rules take whatever
   is left and wrap within it rather than pushing the stats around. */
:is(#dzc-print, .pp-paper) .pr-statline {
  display: flex; align-items: flex-start; gap: 10pt; margin: 1.5pt 0;
}
:is(#dzc-print, .pp-paper) .pr-statline .pr-stats { flex: 0 0 auto; margin: 0; }
:is(#dzc-print, .pp-paper) .pr-statline .pr-rules-row { flex: 1 1 auto; margin: 0; }
/* Rule chips, on the Squad and in the weapon table's Special column. Outlined
   rather than filled -- a filled chip is a solid block of toner per keyword,
   and a stat card is mostly keywords. */
:is(#dzc-print, .pp-paper) :is(.pr-rules-row, .pr-wpn) .dzc-rule {
  display: inline-block; font-size: 6.5pt; line-height: 1.35;
  padding: 0 2.5pt; margin: 0 2pt 1pt 0;
  border: .5pt solid var(--acc, #666); border-radius: 2pt;
  background: none; color: #000; text-decoration: none;
}
:is(#dzc-print, .pp-paper) .pr-rules-row { margin: 1pt 0; }
/* The arc drawn, then named. */
:is(#dzc-print, .pp-paper) .dzc-arc-cell { white-space: nowrap; }
:is(#dzc-print, .pp-paper) .dzc-arc-cell svg { width: 10pt; height: 10pt; vertical-align: -1.5pt; }
:is(#dzc-print, .pp-paper) .dzc-arc-cell span { margin-left: 2pt; }
/* A variant's own photograph, beside the count of it. */
:is(#dzc-print, .pp-paper) .pr-mix {
  display: inline-flex; align-items: center; gap: 3pt; margin-right: 8pt;
}
:is(#dzc-print, .pp-paper) .pr-vart { width: 34pt; height: 22pt; object-fit: contain; }
:is(#dzc-print, .pp-paper) .pr-desc {
  margin: 2pt 0 0; font-size: 8pt; font-style: italic; color: #333;
}
:is(#dzc-print, .pp-paper) .pr-g-carry {
  margin-left: 8pt; font-size: 8pt; color: var(--acc, #444);
}

:is(#dzc-print, .pp-paper) .pr-wpn { width: 100%; border-collapse: collapse; font-size: 8pt; margin: 2pt 0 1pt; }
:is(#dzc-print, .pp-paper) .pr-wpn th { text-align: left; font-size: 6.5pt; text-transform: uppercase; letter-spacing: .04em; border-bottom: .5pt solid #999; padding: 1pt 4pt 1pt 0; }
/* NO RULE PER ROW. Jet, 2026-08-13: "less row rules". A line under every
   weapon on every Squad was most of the 247 borders on a three-page sheet,
   drawing a grid the columns already align without. The header keeps its rule
   because that one separates two different KINDS of row. */
:is(#dzc-print, .pp-paper) .pr-wpn td { padding: 1pt 4pt 1pt 0; vertical-align: top; }

/* Rules appendix, in TWO COLUMNS and starting wherever the army finished.
   Jet, 2026-08-13: "make rules glossary not need a break and be way more
   tightly spaced overall and make it 2 columns."

   The single-column rule at the top of this file is about the ARMY -- the
   Group nesting tree is a tall narrow structure and splitting it puts a
   Condor at the foot of one column and its cargo at the head of the next.
   The glossary is the opposite shape: a hundred short independent entries,
   which is what columns are for. Nothing about the list itself changes.

   The forced page break went with it. It bought a clean start for the
   appendix and cost, on a three-page army, most of a sheet of white paper.

   A rule still must not break mid-sentence: break-inside on the entry keeps
   each one whole, and in a multi-column box that moves it to the next COLUMN
   rather than the next page, which is cheaper again. */
:is(#dzc-print, .pp-paper) .pr-rules {
  columns: 2; column-gap: 7mm; column-rule: .5pt solid #ddd;
  margin-top: 5pt;
}
:is(#dzc-print, .pp-paper) .pr-rules h2 {
  font: 700 11pt/1.2 'Roboto Slab', Georgia, serif;
  border-bottom: 1pt solid #000; padding-bottom: 2pt; margin: 0 0 4pt;
  column-span: all;
}
:is(#dzc-print, .pp-paper) .pr-rule {
  break-inside: avoid; page-break-inside: avoid; margin-bottom: 2.5pt;
}
/* The keyword and its text read as one paragraph rather than a heading over a
   block: at this size a line to itself per name was a third of the appendix
   spent on names. */
:is(#dzc-print, .pp-paper) .pr-rule h3 {
  display: inline; font: 700 8pt/1.35 'Jost', sans-serif; margin: 0;
}
:is(#dzc-print, .pp-paper) .pr-rule h3::after { content: '. '; }
:is(#dzc-print, .pp-paper) .pr-rule p {
  display: inline; margin: 0; font-size: 8pt; line-height: 1.35;
}
:is(#dzc-print, .pp-paper) .pr-rule .pr-src { font-size: 6.5pt; color: #555; }
:is(#dzc-print, .pp-paper).is-ink .pr-rules { column-rule-color: #000; }

/* Commanders, and the numbers that come off Commander Level. Kept whole like a
   Group, because it is the block you look at between Rounds. */
:is(#dzc-print, .pp-paper) .pr-cmdrs {
  break-inside: avoid; page-break-inside: avoid;
  border: 1pt solid #000; padding: 4pt 7pt; margin-bottom: 7pt;
}
:is(#dzc-print, .pp-paper) .pr-cmdrs-head {
  font: 700 9pt/1.1 'Roboto Slab', Georgia, serif; margin: 0 0 3pt;
  border-bottom: 1pt solid #999; padding-bottom: 2pt;
}
:is(#dzc-print, .pp-paper) .pr-cmdr-row { display: flex; align-items: baseline; gap: 8pt; font-size: 9pt; padding: 1pt 0; }
:is(#dzc-print, .pp-paper) .pr-cmdr-name { font-weight: 700; }
:is(#dzc-print, .pp-paper) .pr-cmdr-pts { margin-left: auto; font-weight: 700; white-space: nowrap; }
/* The four numbers a Commander's Level buys, each one its own cell. They are
   looked up one at a time in the middle of a Round, so they are set as a stat
   block rather than as a sentence: the figure large, what it is under it, when
   you use it under that. */
:is(#dzc-print, .pp-paper) .pr-cmdr-play {
  display: flex; flex-wrap: wrap; gap: 4pt 16pt; margin: 5pt 0 0;
  border-top: .5pt solid #999; padding-top: 4pt;
}
:is(#dzc-print, .pp-paper) .pr-cmdr-play > div {
  display: flex; align-items: baseline; gap: 4pt;
}
:is(#dzc-print, .pp-paper) .pr-cmdr-play b {
  font: 700 11pt/1 'Roboto Slab', Georgia, serif; white-space: nowrap;
}
:is(#dzc-print, .pp-paper) .pr-cmdr-play span {
  display: flex; flex-direction: column; font-size: 8pt; line-height: 1.2;
}
:is(#dzc-print, .pp-paper) .pr-cmdr-play i {
  font-style: normal; font-size: 6.5pt; color: #555;
}
:is(#dzc-print, .pp-paper).is-ink .pr-cmdr-play i { color: #000; }
:is(#dzc-print, .pp-paper).is-ink .pr-cmdrs { border-width: .25pt; }
:is(#dzc-print, .pp-paper).is-ink .pr-cmdrs-head { border-bottom-color: #000; border-bottom-width: .25pt; }

:is(#dzc-print, .pp-paper) .pr-warn { font-size: 8pt; margin: 0 0 6pt; padding: 3pt 5pt; border-left: 2pt solid #666; }

/* -------------------------------------------------------- how it is printed
 *
 * Three decisions about this printout, made in the preview where you can see
 * what each costs you in pages.
 */

/* Compact. Everything shrinks together. The sheet is already sized in points
   so one step down the type scale takes the spacing with it. */
:is(#dzc-print, .pp-paper).is-compact { font-size: 8pt; line-height: 1.3; }
:is(#dzc-print, .pp-paper).is-compact .pr-group { padding: 3pt 5pt; margin-bottom: 4pt; }
:is(#dzc-print, .pp-paper).is-compact .pr-title { font-size: 11pt; }
:is(#dzc-print, .pp-paper).is-compact .pr-g-name { font-size: 11pt; }
:is(#dzc-print, .pp-paper).is-compact .pr-squad { padding: 1pt 0; }
:is(#dzc-print, .pp-paper).is-compact .pr-wpn { font-size: 6.5pt; }
:is(#dzc-print, .pp-paper).is-compact .pr-rule p { font-size: 8pt; line-height: 1.3; }

/* Ink-saver. The rules stay. The nesting rule down the left of a carried
   Squad is what makes the tree readable, and losing it would cost the sheet
   its whole point. But they go hairline and every grey goes black, because
   grey text is the thing a cheap printer renders worst and it is not saving
   ink to print it twice. */
:is(#dzc-print, .pp-paper).is-ink .pr-group { border-width: .25pt; }
:is(#dzc-print, .pp-paper).is-ink .pr-head { border-bottom-width: .5pt; }
:is(#dzc-print, .pp-paper).is-ink .pr-g-head { border-bottom-color: #000; border-bottom-width: .25pt; }
:is(#dzc-print, .pp-paper).is-ink .pr-squad--nested { border-left-width: .5pt; border-left-color: #000; }
/* Ink saver takes the colour back out of everything the accent reached, and
   flattens the new glyphs to black. The option means one ink, not one ink
   except where the pretty parts are. */
:is(#dzc-print, .pp-paper).is-ink :is(.pr-g-name, .pr-g-carry) { color: #000; }
:is(#dzc-print, .pp-paper).is-ink :is(.pr-rules-row, .pr-wpn) .dzc-rule {
  border-color: #000; border-width: .25pt;
}
:is(#dzc-print, .pp-paper).is-ink :is(.pr-stats .dzc-stat-i svg, .dzc-arc-cell svg) {
  color: #000; fill: #000;
}
/* Every stat cell to black, value and label both. The value inherits --ink,
   which is the app's text colour and not black, so a measured sheet in ink
   mode still had 59 cells of off-black on it. The cargo badge's digit is the
   last coloured thing left and it stays: that colour IS which shape it is. */
:is(#dzc-print, .pp-paper).is-ink .pr-stats :is(.dzc-stat-k, .dzc-stat-v) { color: #000; }
:is(#dzc-print, .pp-paper).is-ink .pr-desc { color: #000; }
:is(#dzc-print, .pp-paper).is-ink .pr-wpn th { border-bottom-width: .25pt; border-bottom-color: #000; }
:is(#dzc-print, .pp-paper).is-ink :is(.pr-cap, .pr-variants, .pr-rule .pr-src) { color: #000; }
/* Ink-saver: the shapes go black-on-white. Shape alone carries the meaning
   (3.2.4.2), the colour is 1:1 with it and therefore redundant, and a solid
   coloured fill is the most expensive thing on the sheet. Cargo stays solid so
   the "drops into the hollow" grammar survives; the digit inside it flips to
   white against that black. */
:is(#dzc-print, .pp-paper).is-ink .pr-cap .dzc-badge path { stroke: #000; }
:is(#dzc-print, .pp-paper).is-ink .pr-cap .dzc-badge:not(.is-cargo) path { fill: none; }
:is(#dzc-print, .pp-paper).is-ink .pr-cap .dzc-badge.is-cargo path { fill: #000; }
:is(#dzc-print, .pp-paper).is-ink .pr-cap .dzc-badge:not(.is-cargo) .dzc-badge-n { color: #000 !important; }
:is(#dzc-print, .pp-paper).is-ink .pr-cap .dzc-badge.is-cargo .dzc-badge-n { color: #fff !important; }
:is(#dzc-print, .pp-paper).is-ink .pr-art { display: none; }

/* Art. Off unless asked for: it is what a printer makes the worst mess of, the
   sheet is a deployment plan rather than a display piece, and it is the single
   biggest thing between a two-page list and a four-page one. Floated so a
   Squad's text still fills the line beside it. */
:is(#dzc-print, .pp-paper) .pr-art {
  float: right; width: 22mm; height: auto; margin: 0 0 2pt 4pt;
}
:is(#dzc-print, .pp-paper).is-compact .pr-art { width: 16mm; }
:is(#dzc-print, .pp-paper) .pr-squad::after { content: ''; display: block; clear: both; }

/* ------------------------------------------------------------- the preview
 *
 * A sheet of A4 at its real size, with the page boundaries drawn on it. mm and
 * pt are absolute CSS units, so 210mm on screen is 210mm of paper and 10pt of
 * body text is 10pt. The preview is to scale rather than an impression of one.
 */
.pp-overlay {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; flex-direction: column;
  background: rgba(20, 17, 13, .82);
}
/* The bar is chrome, not paper, so it follows the theme. --surface-1 is
   defined nowhere in the project, so it always fell back to cream while the
   text on it inherited the theme's ink: in the dark theme the whole toolbar.
   Title, page count, all three toggles, was near-white on cream. */
.pp-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; background: var(--surface-2, #fdfaf3);
  color: var(--ink, #24201c);
  border-bottom: 1px solid var(--stroke, #d9d0be);
}
.pp-title { font-family: 'Roboto Slab', Georgia, serif; font-weight: 700; font-size: 15px; }
.pp-count { font-family: 'Outfit', system-ui, sans-serif; font-size: 13px; color: var(--ink-2, #6b6459); }
.pp-spacer { margin-left: auto; }
.pp-opt {
  display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  font-size: 12.5px; white-space: nowrap;
}
.pp-opt input { margin: 0; }
/* align-items: flex-start, because the default is stretch and a stretched sheet
   is a sheet as tall as your window. The page count is measured off the paper's
   own height, so on a phone, where the shrunk sheet is shorter than the scroll
   box, the paper was being pulled down to fill it and the same one-page army
   read as three. */
.pp-scroll {
  flex: 1; overflow: auto; padding: 16px 8px 40px;
  display: flex; justify-content: center; align-items: flex-start;
}

/* The paper. Padding matches @page's 12mm/10mm margins so a line that fits
   here fits there. */
.pp-paper {
  position: relative;
  width: 210mm;
  min-height: 297mm;
  padding: 12mm 10mm;
  box-sizing: border-box;
  background: #fff;
  box-shadow: 0 6px 28px rgba(0, 0, 0, .45);
  /* A4 is wider than a phone. The sheet shrinks WHOLE rather than reflowing.
     A preview that reflows is showing you a page you are not going to get.
     zoom rather than transform because zoom changes the layout box, so the
     shrunk sheet stops overflowing instead of merely looking smaller. The
     measurement reads mm off the rendered width, so it follows this down. */
  zoom: var(--pp-zoom, 1);
}

/* Where the printer will actually cut. Drawn from the same measurement that
   produces the page count, so the two can never disagree. */
.pp-break {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 1px dashed #b3382c; pointer-events: none;
}
.pp-break-n {
  position: absolute; right: 2mm; top: 2px;
  font: 600 9px/1 'Jost', sans-serif; letter-spacing: .06em;
  text-transform: uppercase; color: #b3382c; background: #fff; padding: 1px 4px;
}
/* Blank space a block is pushed down by, exactly as print would push it. */
.pp-spacer-gap { pointer-events: none; }

@media (max-width: 700px) {
  .pp-scroll { padding: 8px 0 32px; }
}

/* A Behemoth's Gear on the printed sheet: what its Power may be spent on and
   what each costs, which is read every activation. */
.pr-gear { font-size: 8pt; margin-top: 1mm; }
.pr-gear b { font-weight: 700; }

