/* ==========================================================================
   subnet-calculator.theme.css — IPv4 subnet calculator + VLSM addressing plan

   Loaded AFTER styles.css and tool-base.css. Wrapper is
   `<div class="tool-app sn-app">` — `.tool-app` is what pulls in the shared
   print invariants; this file owns everything else.

   VAR INDIRECTION (same pattern as the other four themes, on purpose)
   The block below re-declares the TOOL's own variable names on `.sn-app` and
   maps each onto a site token. tool-base.css overrides those same names inside
   @media print. Do not "simplify" it by inlining site tokens into the rules —
   the indirection is what lets the print block re-theme the whole tool by
   changing ten values.

   DO NOT re-declare here what tool-base.css already owns in print: the body
   reset, `color-scheme: light` + the ten light vars, `.wrap`, the `.print-only`
   masthead, the `.grid` flex fix, the page-break atoms, or print-color-adjust
   on `.chart-track`/`.chart-fill`. This file adds only what is specific to this
   tool.

   NO PRINT MIRRORS, AND THAT IS STRUCTURAL — not an omission.
   Every form control on this page sits inside a `.no-print` block: the
   calculator's own input row, and the whole segment editor. What prints is
   built from state as plain text (`.cidr-head`, `.facts`, the plan table, the
   free-block list, the chart). There is not one `input`/`select`/`button` in
   the printed area, so the mirror contract in CLAUDE.md does not apply. The QA
   suite asserts that count is zero. If you ever print the editor, it applies —
   add mirrors, do not add a control width.

   ONE HUE. The allocation chart is a single-hue bar list per DESIGN.md: the
   segments are nominal categories, so colouring by segment would spend the
   identity channel re-encoding what bar length already shows. A second series
   colour for "allocated vs free" was considered and declined — see the
   2026-08-10 row in DESIGN.md's decisions log.

   TOUCH: this tool ships WITH the 44px pass rather than joining the debt pile
   the four older tools carry. Sizes are `px`, never `rem` — styles.css:1142
   drops `:root { font-size: 15px }` at 480px, so a rem-based 44px target
   renders 41px on exactly the phones that need it most.
   ========================================================================== */

.sn-app {
    /* screen palette → site tokens */
    --bg: var(--color-bg-primary);
    --card: var(--color-surface);
    --raised: var(--color-raised);
    --ink: var(--color-text-primary);
    --dim: var(--color-text-secondary);
    --muted: var(--color-text-muted);
    --line: var(--color-border);
    --line-strong: var(--color-border-strong);
    --accent: var(--color-primary);
    --accent-soft: rgba(229, 163, 68, 0.12);
    --bad: var(--color-error);

    font-family: var(--font-primary);
    font-size: 14px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--bg);
}

/* styles.css styles h1-h3/p for editorial page copy. Inside an app they fight
   the tool's own scale. `color: inherit` here is also half of why this tool's
   print masthead comes out dark — see the tool-base comment on .print-only h1. */
.sn-app h1,
.sn-app h2,
.sn-app h3,
.sn-app p {
    font-family: inherit;
    color: inherit;
    margin: 0;
    letter-spacing: normal;
}

/* The UA `[hidden]` rule is only `display: none`, so it LOSES to any author
   rule that sets a display — and this tool hides a flex row (`.warn-line`) and
   a grid (`.facts` error state). In the pro/con list that exact gap left a
   blank-state element rendering on screen while the test asserting
   `.hidden === true` passed the whole time. Assert computed display, never the
   property. */
.sn-app [hidden] {
    display: none !important;
}

.sn-app .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.sn-app .wrap {
    max-width: 1180px;
    margin: 0 auto;
    /* 112px clears the fixed navbar. */
    padding: 112px 2rem 96px;
}

/* ---------- layout: two columns, the block summary sticky ---------- */

.sn-app .grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 26px;
    align-items: start;
}

.sn-app .col-side .panel {
    position: sticky;
    top: 92px;
}

/* ---------- cards ---------- */

.sn-app .panel {
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    margin-bottom: 18px;
}

.sn-app .panel > h2 {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-weight: 500;
    color: var(--muted);
    padding: 14px 18px;
    border-bottom: 1px solid var(--line);
}

.sn-app .panel > .body {
    padding: 18px;
}

.sn-app .note {
    color: var(--dim);
    font-size: 0.86rem;
    line-height: 1.55;
}

.sn-app .footnote {
    color: var(--muted);
    font-size: 0.78rem;
    line-height: 1.5;
    margin-top: 14px;
}

/* styles.css styles no `code` element at all, so without this the inline
   examples and the free-block list fall back to the UA's monospace face — a
   different typeface from every other figure on the page. */
.sn-app code {
    font-family: var(--font-mono);
    font-size: 0.95em;
    color: var(--ink);
}

.sn-app .sub-head {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--muted);
    margin: 20px 0 8px;
}

.sn-app .sub-head:first-child {
    margin-top: 0;
}

/* ---------- app header ---------- */

.sn-app header.app {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-end;
    justify-content: space-between;
    margin-bottom: 20px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--line);
}

.sn-app .doc-title {
    display: block;
    width: 100%;
    max-width: 420px;
    background: transparent;
    border: 0;
    border-bottom: 1px dashed var(--line-strong);
    border-radius: 0;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 1.55rem;
    font-weight: 700;
    padding: 2px 0 6px;
    min-height: 44px;
}

.sn-app .doc-title:focus {
    outline: 0;
    border-bottom-color: var(--accent);
}

.sn-app header.app .sub {
    color: var(--muted);
    font-size: 0.8rem;
    margin-top: 6px;
}

.sn-app header.app .actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.sn-app button.primary {
    min-height: 44px;
    padding: 0 16px;
    background: var(--accent);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    color: #14100a;
    font-family: var(--font-primary);
    font-size: 0.86rem;
    font-weight: 500;
    cursor: pointer;
}

/* ---------- closing CTA ---------- */

.sn-app .tool-cta {
    margin-top: 32px;
    padding-top: 24px;
    border-top: 1px solid var(--line);
    text-align: center;
}

.sn-app .tool-cta p {
    color: var(--dim);
    font-size: 0.88rem;
    max-width: 62ch;
    margin: 0 auto 16px;
}

/* ---------- controls ---------- */

.sn-app .field {
    margin-bottom: 16px;
}

.sn-app .field:last-child {
    margin-bottom: 0;
}

.sn-app .field > label {
    display: block;
    font-size: 0.82rem;
    color: var(--dim);
    margin-bottom: 6px;
}

/* Labels stay visible when the field has content — a placeholder is never the
   only label. */
.sn-app input[type="number"],
.sn-app input[type="text"],
.sn-app select {
    width: 100%;
    background: var(--raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 15px;
    padding: 9px 11px;
    min-height: 44px;
}

.sn-app input::placeholder {
    color: var(--muted);
}

.sn-app input:focus-visible,
.sn-app select:focus-visible,
.sn-app button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* The address + prefix pair. The prefix column is wide enough for the longest
   option label ("/24 · 255.255.255.0") without truncating — measured, not
   eyeballed, same rule as the estimator's table widths. */
.sn-app .addr-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 232px;
    gap: 12px;
    align-items: end;
}

/* ---------- address-family toggle ---------- */
/* Safe to call this `.seg` here: the estimator's print block hides that class
   outright, but that rule lives in `it-budget.theme.css` and cannot reach this
   scope. It never prints from here either way — the whole block is `.no-print`. */

.sn-app .seg-label {
    display: block;
    font-size: 0.82rem;
    color: var(--dim);
    margin-bottom: 6px;
}

.sn-app .seg {
    display: flex;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    overflow: hidden;
    max-width: 260px;
}

.sn-app .seg button {
    flex: 1;
    min-height: 44px;
    background: var(--raised);
    border: none;
    border-right: 1px solid var(--line);
    color: var(--dim);
    font-family: var(--font-mono);
    font-size: 0.84rem;
    letter-spacing: 0.04em;
    cursor: pointer;
}

.sn-app .seg button:last-child {
    border-right: none;
}

.sn-app .seg button.on {
    background: var(--accent);
    color: #14100a;
}

.sn-app .err {
    color: var(--bad);
    font-size: 0.8rem;
    margin-top: 8px;
}

.sn-app button.ghost {
    min-height: 44px;
    padding: 0 16px;
    background: var(--raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    color: var(--dim);
    font-family: var(--font-primary);
    font-size: 0.86rem;
    cursor: pointer;
}

/* Every :hover is gated. Repo-wide there were zero such gates before the
   pro/con touch pass, so hover fired on tap and stuck until the next tap
   elsewhere. The :active rules are the deliberate replacement for the press
   feedback that removes. */
@media (hover: hover) {

    .sn-app button.ghost:hover {
        border-color: var(--line-strong);
        color: var(--ink);
    }

    .sn-app .sn-del:hover {
        color: var(--bad);
        border-color: var(--bad);
    }
}

.sn-app button.ghost:active {
    background: var(--card);
}

/* Kills the 300ms double-tap-zoom delay. Must stay BEFORE any rule that needs
   to beat it. */
.sn-app button {
    touch-action: manipulation;
}

/* ---------- the calculator readout ---------- */

/* Separates the calculator's input block from its result. Without it the
   readout butts straight up against the help text above and reads as part of
   it. Written as `.body > .no-print` rather than a margin on .cidr-head so it
   costs nothing on paper: the input block is `display: none` there, and a
   margin on the readout would have left a gap at the top of the report. It
   matches only the calculator — the segment editor carries `.no-print` on its
   whole <section>, not on a child of `.body`. */
.sn-app .panel > .body > .no-print {
    margin-bottom: 18px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--line);
}

/* The CIDR as text, not as a control — this is what carries the calculator's
   input onto paper, since the input row itself is .no-print. */
.sn-app .cidr-head {
    font-family: var(--font-mono);
    font-size: 1.35rem;
    letter-spacing: -0.01em;
    color: var(--ink);
    padding-bottom: 12px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 14px;
}

.sn-app .cidr-head .scope {
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--muted);
    margin-left: 10px;
    white-space: nowrap;
}

.sn-app .facts {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1px;
    background: var(--line);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.sn-app .fact {
    background: var(--card);
    padding: 10px 13px;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.sn-app .fact .lab {
    font-family: var(--font-mono);
    font-size: 0.64rem;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--muted);
}

.sn-app .fact .val {
    font-family: var(--font-mono);
    font-size: 0.95rem;
    color: var(--ink);
    text-align: right;
    /* Long values (a usable range is 33 characters) wrap rather than clipping —
       the same rule the chart labels follow. */
    word-break: break-word;
}

.sn-app .fact.wide {
    grid-column: 1 / -1;
}

/* ---------- the binary strip ---------- */
/* The one thing a dotted-quad readout cannot show: where the prefix actually
   falls inside the address. aria-hidden, with an .sr-only sentence beside it —
   32 individually announced digits is noise, and the bit counts are already
   stated as text above. */

.sn-app .bits {
    margin-top: 16px;
    padding: 12px 13px;
    background: var(--raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: 0.82rem;
    line-height: 1.9;
    /* The strip is 32 digits + 3 dots + a rule. It wraps on a phone rather than
       scrolling — a horizontal scrollbar on a value this short reads as broken. */
    word-break: break-all;
}

.sn-app .bits .b {
    letter-spacing: 0.06em;
}

.sn-app .bits .n {
    color: var(--accent);
}

.sn-app .bits .h {
    color: var(--muted);
}

/* The one nibble a non-nibble-aligned IPv6 prefix splits down the middle — it
   is part network and part interface, and there is no honest way to paint it
   as either. Accent (it IS partly prefix) plus a dotted underline that says
   "this one is not clean", with the exact bit count spelled out in the key
   below. Contrast is unchanged from `.n`, so the marking costs no legibility. */
.sn-app .bits .p {
    color: var(--accent);
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}

/* --muted, NOT --line-strong. The octet dots are the only thing grouping 32
   digits into readable bytes, so they are text, not a hairline: at
   --line-strong (#3a3a40 on the #1A1A1D strip) they were invisible on screen
   and the strip read as one 32-digit run. Caught by looking at the screenshot,
   not the CSS — they render fine on paper, where the variables are inverted. */
.sn-app .bits .dot {
    color: var(--muted);
    padding: 0 2px;
}

/* The prefix boundary. An inline-block rather than a border on the last network
   bit: at /0 and /32 the boundary sits outside every digit, and a border has
   nothing to hang on. */
.sn-app .bits .brk {
    display: inline-block;
    width: 2px;
    height: 0.95em;
    vertical-align: -0.12em;
    margin: 0 3px;
    background: var(--ink);
}

.sn-app .bits-key {
    color: var(--muted);
    font-size: 0.72rem;
    margin-top: 8px;
}

.sn-app .bits-key b {
    color: var(--accent);
    font-weight: 500;
}

/* ---------- the segment editor ---------- */

.sn-app .seg-rows {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.sn-app .seg-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 120px 44px;
    gap: 10px;
    align-items: center;
}

/* Destructive control: muted at rest, red only on hover/press. A permanently
   red delete reads as an error state on the page and contradicts red's
   demotion to semantic error — DESIGN.md ratified this on Classified Doc. */
.sn-app .sn-del {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    /* The hairline is not decoration. Without it a borderless glyph on its own
       44px box reads as adrift with nothing showing the target — the pro/con
       finding, written into DESIGN.md's Spacing section. */
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    color: var(--muted);
    font-size: 15px;
    cursor: pointer;
}

.sn-app .sn-del:active {
    color: var(--bad);
}

.sn-app .add-row {
    margin-top: 14px;
}

.sn-app .cap-note {
    color: var(--muted);
    font-size: 0.76rem;
    margin-top: 10px;
}

/* ---------- the plan table ---------- */

.sn-app .table-scroll {
    overflow-x: auto;
    /* Firefox needs this explicitly; color-scheme: dark alone leaves a solid
       white bar across the dark card. */
    scrollbar-color: var(--line-strong) var(--card);
}

.sn-app table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.83rem;
    /* Must clear the sum of the column widths below (600px), or auto table
       layout shrinks every column proportionally and the declared widths become
       suggestions — that is how the estimator ended up clipping option labels
       mid-word inside their own controls. Re-measure when adding a column. */
    min-width: 600px;
}

.sn-app th {
    text-align: left;
    font-family: var(--font-mono);
    font-size: 0.64rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-weight: 500;
    color: var(--muted);
    padding: 8px 10px;
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}

.sn-app td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--line);
    font-family: var(--font-mono);
    vertical-align: top;
}

/* Column widths live here, NOT as inline style= attrs on the <th>s. An inline
   declaration outranks any selector, so the estimator's print override needed
   `width: auto !important` to do anything at all. A class cannot have that
   problem.

   THE FOUR MONO COLUMNS SIZE THEMSELVES — `width: 1%` + `nowrap` is the auto-
   table-layout idiom for shrink-to-content, and the name column (the only one
   holding free text) absorbs the rest. This replaced hard-coded pixel widths,
   which is worth explaining because the hard-coded version LOOKED fine:
   measured on paper, `.c-range` was 188px against 196px of content, so every
   single row wrapped to two lines and the table ran a page longer than it
   needed to. Any fixed number here is only correct for the address lengths it
   was measured against — "10.20.4.129 – 10.20.4.158" needs 196px but
   "192.168.100.129 – 192.168.100.190" needs 252px, and a plan in 192.168 space
   would have silently gone back to wrapping. Self-measuring columns cannot
   drift that way. */
.sn-app .c-name { width: auto; min-width: 150px; }
.sn-app .c-need,
.sn-app .c-cidr,
.sn-app .c-range,
.sn-app .c-spare {
    width: 1%;
    white-space: nowrap;
}

.sn-app td.num,
.sn-app th.num {
    text-align: right;
}

/* The segment name is the one column that carries free text, so it is the one
   column that wraps rather than staying mono-nowrap. */
.sn-app td.c-name {
    font-family: var(--font-primary);
    color: var(--ink);
    word-break: break-word;
}

.sn-app tr.unfit td {
    color: var(--muted);
}

.sn-app .pill {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    padding: 2px 7px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-full);
    color: var(--muted);
    white-space: nowrap;
}

.sn-app .table-empty {
    color: var(--muted);
    font-size: 0.86rem;
    padding: 22px 0;
    text-align: center;
}

/* A warning names a cause; it never carries a coloured left border, which is an
   AI-slop pattern and appears in zero shipped tools here. */
.sn-app .warn-line {
    margin-top: 14px;
    padding: 11px 13px;
    border-radius: var(--radius-md);
    background: var(--raised);
    border: 1px solid var(--line);
    color: var(--dim);
    font-size: 0.84rem;
    line-height: 1.6;
}

.sn-app .warn-line b {
    color: var(--ink);
    font-family: var(--font-mono);
    font-weight: 500;
}

/* ---------- block summary ---------- */

.sn-app .stat {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 0;
    border-bottom: 1px solid var(--line);
}

.sn-app .stat:last-of-type {
    border-bottom: none;
}

.sn-app .stat-lab {
    font-size: 0.82rem;
    color: var(--dim);
}

.sn-app .stat-val {
    font-family: var(--font-mono);
    font-size: 0.92rem;
    color: var(--ink);
    text-align: right;
}

.sn-app .stat-sub {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--muted);
    min-width: 5ch;
    text-align: right;
}

/* ---------- allocation chart (single-hue bar list) ---------- */

.sn-app .chart {
    display: flex;
    flex-direction: column;
    gap: 11px;
}

.sn-app .chart-row {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.sn-app .chart-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.sn-app .chart-label {
    color: var(--dim);
    font-size: 0.8rem;
    /* Wraps rather than truncating. A truncated label makes the row
       unidentifiable, and identity is the only thing the label carries. */
    word-break: break-word;
}

.sn-app .chart-val {
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 0.74rem;
    white-space: nowrap;
}

.sn-app .chart-line {
    display: flex;
    align-items: center;
    gap: 8px;
}

.sn-app .chart-track {
    flex: 1;
    height: 8px;
    border-radius: 2px;
    background: var(--raised);
    overflow: hidden;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

/* Square at the baseline, rounded at the data end — the house mark. */
.sn-app .chart-fill {
    display: block;
    height: 100%;
    border-radius: 0 3px 3px 0;
    background: var(--accent);
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

.sn-app .chart-share {
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: 0.72rem;
    min-width: 5ch;
    text-align: right;
}

.sn-app .chart-empty {
    color: var(--muted);
    font-size: 0.84rem;
    padding: 22px 0;
    text-align: center;
}

/* ---------- free blocks ---------- */

.sn-app .free-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.sn-app .free-list li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--ink);
}

.sn-app .free-n {
    color: var(--muted);
    font-size: 0.72rem;
    white-space: nowrap;
}

/* ---------- touch / small viewports ---------- */
/* px throughout — see the header note. */

@media (max-width: 900px) {

    .sn-app .grid {
        display: flex;
        flex-direction: column;
        /* LOAD-BEARING, and the exact trap tool-base.css documents for print.
           The screen rule above sets `align-items: start` so the sticky sidebar
           hugs its content. On a COLUMN flex box that same declaration is the
           CROSS axis, so it shrink-wraps every panel to its content width and
           the inputs overflow the viewport. Caught by screenshotting at 390px,
           not by reading the CSS. */
        align-items: stretch;
    }

    .sn-app .col-side .panel {
        position: static;
    }

    .sn-app .wrap {
        padding: 96px 1rem 72px;
    }
}

@media (max-width: 620px) {

    /* 16px minimum on anything typed into: below that, iOS Safari zooms the
       viewport on focus and does not zoom back out. */
    .sn-app input[type="number"],
    .sn-app input[type="text"],
    .sn-app select {
        font-size: 16px;
        min-height: 44px;
        padding: 10px 12px;
    }

    /* The address and its prefix stack. At 320px the two-column form leaves the
       prefix select 88px wide, which clips "/24 · 255.255.255.0" — the
       estimator's clipped-option-label defect, one breakpoint away. */
    .sn-app .addr-row {
        grid-template-columns: 1fr;
    }

    /* Two lines, not three. Measured at 320px: the wrap is 16px each side and
       the panel 18px each side, leaving 252px of row — enough for a full-width
       name on line 1, then a 198px host count beside a 44px delete on line 2.
       Three zones on one line needs 294px and does not fit until ~383px. Do not
       tighten this back without re-measuring, and do not shave the targets. */
    .sn-app .seg-row {
        grid-template-columns: minmax(0, 1fr) 44px;
    }

    .sn-app .seg-row .sn-name {
        grid-column: 1 / -1;
    }

    .sn-app .facts {
        grid-template-columns: 1fr;
    }

    .sn-app .cidr-head {
        font-size: 1.15rem;
    }

    .sn-app .cidr-head .scope {
        display: block;
        margin-left: 0;
        margin-top: 6px;
    }
}

/* ---------- print ---------- */
/* tool-base.css owns the reset, the light vars, .wrap, the masthead, the .grid
   flex fix and the page-break atoms. Only tool-specific rules live here.

   No `input`/`select` hiding block, deliberately: every control on this page is
   inside a `.no-print` ancestor, which tool-base already hides outright. A
   blanket hide here would silently swallow a control that leaked into the
   printed area instead of the QA suite catching it. */

@media print {

    /* All three carry `.no-print` in the markup already, which tool-base hides
       outright. Named again as belt-and-braces, exactly as the readiness check
       does — and they are the reason this tool needs no print mirrors: every
       form control on the page is inside one of them. */
    .sn-app header.app,
    .sn-app .tool-cta,
    .sn-app .no-print {
        display: none !important;
    }

    .sn-app .col-side .panel {
        position: static;
    }

    /* Cards may split across sheets; only the atoms may not. `break-inside:
       avoid` on a CARD sends any card too tall for the remaining space to a
       fresh sheet — that is how the estimator printed 4 pages with two of them
       half empty. tool-base covers .chart-row/.stat/.field/tr; these are this
       tool's own atoms. */
    .sn-app .warn-line,
    .sn-app .fact,
    .sn-app .free-list li {
        break-inside: avoid;
    }

    /* The strip is the one block on the sheet whose meaning is carried by
       colour, so it needs its own exact-colour grant: tool-base only covers
       .chart-track/.chart-fill and says explicitly that a new fill is not
       inherited. The .bits-key sentence below it names both halves in words, so
       a reader with background graphics off still gets the split. */
    .sn-app .bits,
    .sn-app .bits .n,
    .sn-app .bits .p,
    .sn-app .bits .brk {
        print-color-adjust: exact;
        -webkit-print-color-adjust: exact;
    }

    .sn-app .bits {
        background: #f4f4f5;
    }

    .sn-app .bits .n,
    .sn-app .bits .p {
        color: #8a6420;
    }

    .sn-app .bits .brk {
        background: #111;
    }

    /* `overflow: hidden`/`auto` on screen AMPUTATES anything wider than the box
       on paper — no scrollbar, no ellipsis, just a missing column. */
    .sn-app .table-scroll {
        overflow: visible;
    }

    .sn-app table {
        min-width: 0;
    }

    /* Repeating the header on every sheet is the point; the pairing is not
       optional. `thead { display: table-header-group }` silently turns tfoot
       into a REPEATING FOOTER, because tfoot defaults to table-footer-group —
       which is how "Total IT budget" once printed after two line items as if
       that were the whole budget. This table has no tfoot today; the rule is
       here so adding one cannot reintroduce the defect. */
    .sn-app thead {
        display: table-header-group;
    }

    .sn-app tfoot {
        display: table-row-group;
    }

    .sn-app .panel {
        border-color: var(--line);
        margin-bottom: 14px;
    }
}
