/* ============================================================
   UVU Local AI — A Build Guide · Prepared by Utlyze
   Design system: UVU-grounded — Green #185C33 and white lead;
   Legacy Gold and Heritage Brick as accents (≤20% of any surface);
   Rajdhani (display) + Source Sans 3 (body/UI), UVU's own free
   web-safe replacements for its licensed Stratum/Proxima Nova.
   Every hex traces to findings/48-uvu-brand-imagery.md §1.1/1.2;
   contrast ratios computed and listed in BRAND-NOTES.md.
   ============================================================ */


/* ---------- fallback faces, so the web-font swap costs no layout ----------
   The three families load from Google Fonts with `display=swap`, which
   paints a local face first and swaps when the real one arrives. Arial is
   9% wider than Source Sans 3 and sets a much tighter line, so on a cold
   load every wrapped block re-wrapped and re-flowed underneath the reader.

   These faces are the same local Arial and Courier New with their metrics
   overridden to the real face's, so the swap changes the letterforms and
   nothing else. Every number was measured in this browser against the real
   face — canvas measureText for the advance width, fontBoundingBoxAscent
   and Descent for the line box — not taken from a table:

     Source Sans 3   ascent 102.4%  descent 40%    (widths per weight below)
     Rajdhani        ascent 90%     descent 25%
     IBM Plex Mono   ascent 102.5%  descent 27.5%

   One face per weight, because the ratio is not one number: Source Sans 3
   grows 5.3% from regular to bold and Rajdhani's bold is *narrower* than
   its regular. A single fallback tuned on the regular weight left every
   bold run mismatched, and one wrap flip in the appendices' opening block
   cost a 0.125 layout shift when the real face arrived — the last shift on
   the site, found by loading each of the three families on its own.

   A fallback face declared AT a weight is used as it is at that weight —
   the browser does not synthesise bold on top of it — so each size-adjust
   below is that weight's real face measured against the local face's own
   *regular*, and each ascent/descent override is the real face's figure
   divided by that size-adjust, so the line box comes out the same too.
   Italic gets its own faces as well as its own ratio, but only for Source
   Sans 3: it is the one of the three that ships an italic, and italic is
   used on every page — forty times in the appendices alone. Its local
   italic is a different set of glyph widths, and a fallback naming plain
   Arial would render italic text upright. Rajdhani and IBM Plex Mono have
   no italic of their own, so the browser slants their roman; declaring an
   italic fallback for them would stop it slanting the fallback's roman
   too, which is the thing being matched. Sixteen faces in all.
   `tests/font-fallbacks.mjs` regenerates them and checks them.

   ------------------------------------------------------------ */

@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: normal;
  font-weight: 400;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 91.97%;
  ascent-override: 111.34%;
  descent-override: 43.49%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: normal;
  font-weight: 500;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 92.98%;
  ascent-override: 110.13%;
  descent-override: 43.02%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: normal;
  font-weight: 600;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 95.53%;
  ascent-override: 107.19%;
  descent-override: 41.87%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: normal;
  font-weight: 700;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 95.53%;
  ascent-override: 107.19%;
  descent-override: 41.87%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: italic;
  font-weight: 400;
  src: local("Arial Italic"), local("Helvetica Neue Italic"), local("Liberation Sans Italic");
  size-adjust: 90.77%;
  ascent-override: 112.81%;
  descent-override: 44.07%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: italic;
  font-weight: 500;
  src: local("Arial Italic"), local("Helvetica Neue Italic"), local("Liberation Sans Italic");
  size-adjust: 90.77%;
  ascent-override: 112.81%;
  descent-override: 44.07%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: italic;
  font-weight: 600;
  src: local("Arial Italic"), local("Helvetica Neue Italic"), local("Liberation Sans Italic");
  size-adjust: 93.26%;
  ascent-override: 109.80%;
  descent-override: 42.89%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 fallback";
  font-style: italic;
  font-weight: 700;
  src: local("Arial Italic"), local("Helvetica Neue Italic"), local("Liberation Sans Italic");
  size-adjust: 93.26%;
  ascent-override: 109.80%;
  descent-override: 42.89%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Rajdhani fallback";
  font-style: normal;
  font-weight: 400;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 88.60%;
  ascent-override: 101.57%;
  descent-override: 28.22%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Rajdhani fallback";
  font-style: normal;
  font-weight: 500;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 88.60%;
  ascent-override: 101.57%;
  descent-override: 28.22%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Rajdhani fallback";
  font-style: normal;
  font-weight: 600;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 89.36%;
  ascent-override: 100.72%;
  descent-override: 27.98%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Rajdhani fallback";
  font-style: normal;
  font-weight: 700;
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 90.23%;
  ascent-override: 99.75%;
  descent-override: 27.71%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono fallback";
  font-style: normal;
  font-weight: 400;
  src: local("Courier New"), local("Liberation Mono"), local("Menlo");
  size-adjust: 77.17%;
  ascent-override: 132.83%;
  descent-override: 35.64%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono fallback";
  font-style: normal;
  font-weight: 500;
  src: local("Courier New"), local("Liberation Mono"), local("Menlo");
  size-adjust: 77.17%;
  ascent-override: 132.83%;
  descent-override: 35.64%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono fallback";
  font-style: normal;
  font-weight: 600;
  src: local("Courier New"), local("Liberation Mono"), local("Menlo");
  size-adjust: 80.16%;
  ascent-override: 127.88%;
  descent-override: 34.31%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono fallback";
  font-style: normal;
  font-weight: 700;
  src: local("Courier New"), local("Liberation Mono"), local("Menlo");
  size-adjust: 80.16%;
  ascent-override: 127.88%;
  descent-override: 34.31%;
  line-gap-override: 0%;
}

:root {
  --paper: #FFFFFF;        /* UVU White — primary field, leads with green */
  --paper-2: #F2F0EB;      /* UVU "Warm" secondary neutral */
  --paper-3: #E7E1D3;      /* deeper warm neutral for banding */
  --ink: #161A17;          /* near-black body text (AAA on white/warm) */
  --ink-soft: #3E4A44;
  --ink-faint: #5C6863;
  --ever: #185C33;         /* UVU Green — primary identity color */
  --ever-2: #1B6B3D;       /* link/hover green, AA on white */
  --ever-deep: #0E3A22;    /* dark green for deep cards/buttons */
  --brass: #8A6423;        /* dark gold — TEXT on light backgrounds only (AA) */
  --brass-bright: #D2AC5F; /* Legacy Gold — decorative accents, and text on --ever-deep (5.95:1) */
  --brass-on-green: #E3C387; /* Legacy Gold lifted for TEXT on --ever #185C33:
                                the book value is 3.75:1 there and fails AA;
                                this is 4.75:1. Same value as --inst-accent. */
  --copper: #B45336;       /* Heritage Brick */
  --sky: #B45336;          /* was an off-brand blue; folded into Heritage Brick */
  --line: rgba(22, 26, 23, 0.14);
  --line-strong: rgba(22, 26, 23, 0.32);
  --card: #FCFBF8;
  --good: #1B6B3D;         /* FACT tag — reuses the link green */
  --warn: #B45336;

  /* Rajdhani and Source Sans 3 are UVU's own documented free web-safe
     substitutes for its licensed Stratum/Proxima Nova (brand guide, 2025;
     findings §1.2). --serif keeps its old name (~90 references site-wide)
     but now points at Source Sans 3 — UVU's body face is sans, not serif. */
  --serif: "Source Sans 3", "Source Sans 3 fallback", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --display: "Rajdhani", "Rajdhani fallback", "Arial Narrow", Arial, sans-serif;
  --sans: "Source Sans 3", "Source Sans 3 fallback", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", "IBM Plex Mono fallback", "SF Mono", Menlo, monospace;

  --measure: 70ch;
  --pad: clamp(1.1rem, 4vw, 2.4rem);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1.075rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* faint paper grain */
body::before {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.09 0 0 0 0 0.13 0 0 0 0 0.09 0 0 0 0.025 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

main, header, footer, nav { position: relative; z-index: 1; }

/* ---------- typography ---------- */
h1, h2, h3 { font-family: var(--display); font-weight: 600; line-height: 1.06; letter-spacing: -0.006em; margin: 0; }
h1 { font-size: clamp(2.4rem, 6.4vw, 4.6rem); }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); }
h3 { font-size: clamp(1.18rem, 2.2vw, 1.45rem); }
p { margin: 0 0 1.05em; max-width: var(--measure); }
strong { font-weight: 600; }
a { color: var(--ever-2); text-decoration-color: rgba(28,74,51,.4); text-underline-offset: 2px; }
a:hover { color: var(--brass); text-decoration-color: var(--brass-bright); }

.kicker {
  font-family: var(--sans); font-weight: 700; font-size: .74rem;
  letter-spacing: .22em; text-transform: uppercase; color: var(--brass);
}
.lede { font-size: clamp(1.16rem, 2vw, 1.34rem); line-height: 1.55; color: var(--ink-soft); }
.small { font-size: .9rem; color: var(--ink-faint); }
.mono, .num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* A bare URL, a long checkpoint name or a hyphenless identifier is one word to
   the line-breaker, and at 200% text it is wider than a phone. `break-word`
   only breaks a word that does not fit on a line of its own, so ordinary prose
   wraps exactly as before — found by extending the 200%-text check from four
   pages to all nine (run 6). */
p, li, td, th, dd, dt, figcaption, blockquote,
.src, .tfoot, .small, small, .five-v { overflow-wrap: break-word; }

/* ---------- evidence chips: the signature ---------- */
.tag {
  display: inline-block; vertical-align: 2px;
  font-family: var(--mono); font-size: .6rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  padding: .14em .5em .1em; border-radius: 2px;
  border: 1px solid currentColor;
  margin-left: .35em; white-space: nowrap;
}
.tag.fact { color: var(--good); background: rgba(46,107,69,.07); }
.tag.est  { color: var(--brass); background: rgba(143,106,30,.08); }
.tag.unk  { color: var(--copper); background: rgba(168,78,30,.07); }

/* ---------- layout shell ---------- */
.shell { max-width: 1080px; margin: 0 auto; padding: 0 var(--pad); }

/* ---------- the bar (rebuilt for the owner review, 2026-09-03) ----------
   One line from 900px up, and it never wraps: the wordmark is nowrap and
   unshrinkable, the labels are short, and the destination that used to be a
   filled green box is now a text link with a small arrow over a 2px green
   rule. Below 900px the whole nav folds into the Menu button. */
.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 1.1rem;
  padding: .82rem var(--pad);
  /* `width: 100%` matters: the instrument pages lay their body out as a
     column flex, and auto margins on the cross axis make a flex item
     shrink to its content instead of stretching. On a phone, where the
     nav is folded into the Menu button, that left the bar 190px wide and
     floating in the middle of a 390px screen. */
  width: 100%; max-width: 1080px; margin: 0 auto;
  flex-wrap: nowrap;
}
.wordmark {
  font-family: var(--sans); font-weight: 700; letter-spacing: .05em;
  font-size: .82rem; text-transform: uppercase;
  color: var(--ink); text-decoration: none; white-space: nowrap; flex: 0 0 auto;
}
.wordmark b { color: var(--brass); font-weight: 700; }
.wordmark .wm-of { font-weight: 500; letter-spacing: .015em; text-transform: none; color: var(--ink-soft); }
/* The long form used to show above 1150px. The bar is capped at 1080px wide,
   so once the walkthrough pill joined the row there is no window width at
   which "for Utah Valley University" fits beside thirteen destinations — it
   overlapped "Costs" by 9px even at 1440. The short form is now the only one
   in the bar; the full name still leads the hero, the print cover, and the
   standing notice on every page. */
.wordmark .wm-long { display: none; }
.wordmark .wm-short { display: inline; }
.topnav {
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-end;
  gap: clamp(.4rem, 1.12vw, .92rem); min-width: 0;
}
.topnav a {
  font-family: var(--sans); font-size: clamp(.73rem, .8vw, .8rem); font-weight: 600;
  text-decoration: none; color: var(--ink-soft); white-space: nowrap;
  padding-bottom: 2px; border-bottom: 2px solid transparent;
  transition: color .14s ease, border-color .14s ease;
}
.topnav a:hover { color: var(--ever); border-bottom-color: rgba(24,92,51,.4); }
.topnav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--ever); }
/* the indicator that replaced the filled green button */
.topnav a.nav-go { color: var(--ever); font-weight: 700; border-bottom-color: var(--ever); }
.topnav a.nav-go:hover { color: var(--ever-deep); border-bottom-color: var(--ever-deep); }
.topnav a.nav-go .arw { font-size: .8em; margin-left: .16em; }
.topnav .btn { color: var(--paper); }

/* the same bar on the dark instrument grounds */
.instrument .topbar { border-bottom: 1px solid var(--inst-line, rgba(231,226,211,.14)); }
.instrument .wordmark { color: var(--inst-fg, #F4EFE1); }
.instrument .wordmark b { color: var(--inst-accent, #E3C387); }
.instrument .wordmark .wm-of { color: var(--inst-dim, #A9B3A2); }
.instrument .topnav a { color: var(--inst-dim, #A9B3A2); }
.instrument .topnav a:hover { color: var(--inst-fg, #F4EFE1); border-bottom-color: rgba(227,195,135,.45); }
.instrument .topnav a[aria-current="page"] { color: var(--inst-fg, #F4EFE1); border-bottom-color: var(--inst-accent, #E3C387); }
.instrument .topnav a.nav-go { color: var(--g-mini, #7BC97F); border-bottom-color: var(--g-mini, #7BC97F); }
.instrument .topnav a.nav-go:hover { color: #A6DDA8; border-bottom-color: #A6DDA8; }
.instrument .menu-btn { color: var(--inst-fg, #F4EFE1); border-color: var(--inst-line-2, rgba(231,226,211,.3)); }

.menu-btn {
  display: none; appearance: none; -webkit-appearance: none;
  font-family: var(--sans); font-weight: 700; background: transparent;
  border: 1px solid var(--line-strong); border-radius: 3px;
  padding: .42em .75em; font-size: .8rem; color: var(--ink); cursor: pointer; flex: none;
}
.menu-btn:focus-visible { outline: 2px solid var(--ever); outline-offset: 2px; }
/* below 900px the twelve destinations fold into the Menu button */
@media (max-width: 899.98px) {
  .topbar { position: relative; flex-wrap: wrap; }
  .topnav { display: none; }
  .topnav.open {
    display: grid; gap: .55rem; position: absolute; right: var(--pad); top: 3.4rem;
    background: var(--card); border: 1px solid var(--line-strong);
    padding: 1rem 1.2rem; border-radius: 4px; z-index: 40;
    box-shadow: 0 10px 30px rgba(24,34,24,.18);
  }
  .instrument .topnav.open { background: var(--inst-panel, #10281B); border-color: var(--inst-line-2, rgba(231,226,211,.3)); }
  .topnav.open a { font-size: .92rem; border-bottom: none; }
  .menu-btn { display: inline-block; }
}

/* ---------- the (i) affordance and its panel (help.js) ----------
   A real button, not a title= attribute: reachable by keyboard, operable by
   touch (the hit area is 44px even though the disc is 20px), and tied to its
   panel by aria-controls / aria-describedby. */
.hbtn {
  position: relative; display: inline-grid; place-items: center;
  width: 20px; height: 20px; padding: 0; margin-left: .45em;
  vertical-align: -3px; flex: none;
  font-family: var(--display); font-weight: 700; line-height: 1;
  color: var(--ever); background: transparent;
  border: 1.4px solid rgba(24,92,51,.45); border-radius: 50%;
  cursor: pointer; transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.hbtn::after { content: ""; position: absolute; inset: -12px; }   /* 44px touch target */
.hbtn > span[aria-hidden] { font-size: 12px; font-style: italic; }
.hbtn:hover, .hbtn[aria-expanded="true"] { color: var(--paper); background: var(--ever); border-color: var(--ever); }
.hbtn:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.hpanel {
  margin: .6rem 0 .15rem; padding: .62rem .8rem;
  border-left: 3px solid var(--ever); background: var(--paper-2);
  border-radius: 0 4px 4px 0;
  font-family: var(--sans); font-size: .8rem; line-height: 1.52; color: var(--ink-soft);
  max-width: 48em; text-transform: none; letter-spacing: 0; font-weight: 400;
}
.hpanel p { margin: 0 0 .45em; max-width: none; }
.hpanel p:last-child { margin-bottom: 0; }
.hpanel .hp-from b { color: var(--ink); font-weight: 700; }
.hpanel a { color: var(--ever-2); }

.instrument .hbtn { color: var(--inst-accent, #E3C387); border-color: rgba(227,195,135,.5); }
.instrument .hbtn:hover, .instrument .hbtn[aria-expanded="true"] { color: #0B2116; background: var(--inst-accent, #E3C387); border-color: var(--inst-accent, #E3C387); }
.instrument .hbtn:focus-visible { outline-color: var(--inst-accent, #E3C387); }
.instrument .hpanel {
  border-left-color: var(--inst-accent, #E3C387);
  background: rgba(227,195,135,.09);
  color: var(--inst-fg-2, #D6D0BF);
}
.instrument .hpanel .hp-from b { color: var(--inst-fg, #F4EFE1); }
.instrument .hpanel a { color: var(--inst-accent, #E3C387); }

/* "How to use this page" — two sentences at the top of every instrument */
.howto {
  display: flex; gap: .7rem; align-items: flex-start;
  margin: .2rem 0 1.1rem; padding: .62rem .85rem;
  border: 1px solid var(--line); border-left: 3px solid var(--ever);
  border-radius: 0 4px 4px 0; background: var(--paper-2);
  font-family: var(--sans); font-size: .84rem; line-height: 1.5; color: var(--ink-soft);
  max-width: 78ch;
}
.howto b { color: var(--ink); font-weight: 700; }
.instrument .howto {
  border-color: var(--inst-line, rgba(231,226,211,.14));
  border-left-color: var(--inst-accent, #E3C387);
  background: rgba(227,195,135,.07); color: var(--inst-fg-2, #D6D0BF);
}
.instrument .howto b { color: var(--inst-fg, #F4EFE1); }

/* the printed footnote list help.js renders */
.hfoot { display: none; }
@media print {
  .hfoot { display: block !important; margin-top: .8rem; border-top: .5pt solid #C9D0CA; padding-top: .5rem; }
  .hfoot h4 { font-family: var(--sans); font-size: 8.4pt; text-transform: uppercase; letter-spacing: .09em; color: #444; margin: 0 0 .3rem; }
  .hfoot ol { font-family: var(--sans); font-size: 7.8pt; line-height: 1.42; color: #333; margin: 0; padding-left: 1.1rem; }
  .hfoot li { margin-bottom: .22rem; }
  .hfoot i { color: #555; }
  .hbtn, .hpanel, .howto { display: none !important; }
}

.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;
}

.btn {
  display: inline-block; font-family: var(--sans); font-weight: 700; font-size: .88rem;
  background: var(--ever); color: var(--paper); text-decoration: none;
  padding: .62em 1.15em; border-radius: 3px; border: 1px solid var(--ever-deep);
  box-shadow: 0 1px 0 rgba(10,32,21,.4);
  transition: background .18s ease, transform .12s ease;
}
.btn:hover { background: var(--ever-2); color: #fff; transform: translateY(-1px); }
.btn.ghost { background: transparent; color: var(--ever); border-color: var(--line-strong); box-shadow: none; }
.btn.ghost:hover { color: var(--brass); border-color: var(--brass); }

/* ---------- hero ---------- */
.hero { padding: clamp(2.4rem, 7vh, 5rem) 0 2.6rem; border-bottom: 3px double var(--line-strong); }
.hero .shell { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(220px, 1fr); gap: 2.5rem; align-items: end; }
.hero h1 em { font-style: normal; color: var(--ever-2); }
.hero-side {
  border-left: 1px solid var(--line-strong); padding-left: 1.4rem;
  font-family: var(--sans); font-size: .9rem; color: var(--ink-soft);
  display: grid; gap: .8rem;
}
.hero-side .row b { display: block; font-family: var(--mono); font-size: .68rem; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: .15rem; }

/* ---------- hero-cover: the branded title-page treatment (index.html only) ----------
   Concept B from concepts.html — a full-height UVU Green field carries the title,
   a duotone campus photo runs alongside it. Chosen over a full-bleed photo (too
   close to the anniversary in findings/48-uvu-brand-imagery.md §5.3, and less
   print-reliable) and over white-only (undersells the ask). Opt-in modifier so
   appendices.html/scenarios.html's plain .hero is untouched. */
.hero.hero-cover {
  padding: 0; border-bottom: none; display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(240px, 1fr);
  min-height: min(78vh, 660px); background: var(--ever); overflow: hidden;
}
.hero-cover .hero-copy { position: relative; z-index: 1; display: flex; flex-direction: column; justify-content: center; padding: clamp(2.2rem, 6vw, 4.2rem) clamp(1.4rem, 4.5vw, 3.2rem); color: #fff; }
.hero-cover .kicker { color: var(--brass-on-green); }
.hero-cover h1 { color: #fff; }
.hero-cover h1 em { font-style: normal; color: #9FDDB4; }
.hero-cover .lede { color: #E3EFE7; }
.hero-cover .hero-notice { font-family: var(--sans); font-size: .76rem; color: rgba(255,255,255,.8); margin-top: 1.15rem; padding-top: .9rem; border-top: 1px solid rgba(255,255,255,.28); max-width: 46ch; line-height: 1.5; }
.hero-media { position: relative; overflow: hidden; background: var(--ever-deep); }
.hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 32% 42%; display: block; filter: grayscale(1) contrast(1.08) brightness(.82); }
.hero-media::before { content: ""; position: absolute; inset: 0; background: linear-gradient(160deg, rgba(24,92,51,.7), rgba(14,58,34,.88)); mix-blend-mode: multiply; }
.hero-media::after { content: ""; position: absolute; inset: 0; background: rgba(24,92,51,.46); }

/* the standing independence notice, on a light ground (appendices, scenarios) */
.indep-notice {
  font-family: var(--sans); font-size: .8rem; line-height: 1.5; color: var(--ink-faint);
  max-width: 54ch; margin-top: 1.2rem; padding-top: .8rem; border-top: 1px solid var(--line-strong);
}

/* The standing independence notice, on every page including the instruments.
   It has to survive the dark grounds and it has to print. */
.standing-notice {
  font-family: var(--sans); font-size: .76rem; line-height: 1.5;
  color: var(--ink-faint); max-width: 78ch;
  margin: 1.6rem 0 0; padding-top: .7rem; border-top: 1px solid var(--line);
}
.instrument .standing-notice {
  color: var(--inst-dim, #A9B3A2); border-top-color: rgba(231, 226, 211, .18);
}
@media print {
  .standing-notice { color: #555 !important; border-top-color: #C9D0CA !important;
                     font-size: 7.6pt; break-inside: avoid; }
}

.hero-meta { background: var(--paper-2); border-bottom: 1px solid var(--line-strong); }
.hero-meta .hm-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: .9rem 2rem; padding: 1.05rem var(--pad); font-family: var(--sans); font-size: .87rem; color: var(--ink-soft); max-width: 1080px; margin: 0 auto; }
.hero-meta .row b { display: block; font-family: var(--mono); font-size: .66rem; letter-spacing: .17em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: .15rem; }

/* `screen and`: a printed page is laid out in an ~816px viewport, and the
   cover is a two-column spread on paper whatever a phone does with it. */
@media screen and (max-width: 900px) {
  .hero.hero-cover { grid-template-columns: 1fr; min-height: auto; }
  .hero-cover .hero-media { order: -1; height: 42vh; min-height: 240px; }
  .hero-cover .hero-copy { padding: 1.7rem 1.2rem 2.1rem; }
}

/* ---------- stat band ---------- */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1px; background: var(--line); border-block: 1px solid var(--line);
  margin: 0;
}
.stat { background: var(--paper); padding: 1.2rem var(--pad) 1.3rem; }
.stat .v { font-family: var(--mono); font-size: clamp(1.5rem, 2.8vw, 2.1rem); font-weight: 600; color: var(--ever); letter-spacing: -.02em; }
.stat .v small { font-size: .55em; color: var(--ink-faint); font-weight: 500; }
.stat .k { font-family: var(--sans); font-size: .8rem; font-weight: 600; color: var(--ink-soft); margin-top: .3rem; line-height: 1.35; }

/* ---------- sections ---------- */
section.part { padding: clamp(2.6rem, 6vh, 4.2rem) 0 1.4rem; }
.part-head { display: flex; align-items: baseline; gap: 1.1rem; margin-bottom: 1.6rem; border-bottom: 1px solid var(--line); padding-bottom: .9rem; }
.part-num {
  font-family: var(--display); font-style: normal; font-weight: 700;
  font-size: clamp(2.2rem, 5vw, 3.4rem); color: var(--brass);
  line-height: 1; min-width: 1.4em;
}
.part-head .sub { font-family: var(--sans); font-size: .92rem; color: var(--ink-faint); margin-top: .45rem; }

/* callout cards */
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 4px;
  padding: 1.15rem 1.3rem; margin: 1.3rem 0;
  box-shadow: 0 1px 2px rgba(24,34,24,.05);
}
.card.accent { border-left: 4px solid var(--brass-bright); }
.card.deep { background: var(--ever-deep); color: #E9E4D6; border-color: var(--ever-deep); }
.card.deep p { color: #E9E4D6; }
.card.deep .kicker { color: var(--brass-bright); }
.card.warn { border-left: 4px solid var(--copper); }
.card h3 { margin-bottom: .5rem; }
.card p:last-child { margin-bottom: 0; }

/* ---------- "In five lines": the decision summary at the head of an appendix ----------
   Every appendix A–Z opens with the same five rows — the question it
   answers, the answer, the numbers the answer turns on with their grades,
   what the plan does about it, and what is still unknown. A reader who
   reads nothing else on the page has read the decision.

   It is a card, not a table: the label column is a fixed measure so all
   twenty-six line up down the page, and it collapses to stacked labels
   below 620px where 8.5rem of label would leave the text four words wide.
   It prints — it is part of the appendix — so the rows, not the card, are
   what may not break across a page.
   ------------------------------------------------------------ */
.five {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 4px solid var(--brass-bright);
  border-radius: 4px;
  padding: .95rem 1.25rem 1.05rem;
  margin: 0 0 1.7rem;
  box-shadow: 0 1px 2px rgba(24,34,24,.05);
}
.five-kicker {
  font-family: var(--sans); font-weight: 700; font-size: .74rem;
  letter-spacing: .2em; text-transform: uppercase; color: var(--brass);
  margin: 0;
}
.five-kicker .sep { color: var(--line-strong); margin: 0 .25em; }
.five-list {
  list-style: none; max-width: none;
  margin: .55rem 0 0; padding: 0;
}
.five-list > li {
  display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); gap: 0 1.2rem;
  align-items: baseline;
  margin: 0; padding: .52rem 0;
  border-top: 1px solid var(--line);
  font-family: var(--sans); font-size: .95rem; line-height: 1.5;
}
.five-list > li:first-child { border-top: none; padding-top: .2rem; }
.five-list > li:last-child { padding-bottom: 0; }
.five-list > li::marker { content: ""; }
.five-k {
  font-family: var(--mono); font-size: .68rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint);
}
.five-v { color: var(--ink); }
.five-a .five-v { font-weight: 600; color: var(--ever); }
.five-u .five-v { color: var(--ink-soft); }
/* the deciding numbers read as a list, separated rather than punctuated,
   so a chip never has to sit next to a comma it does not belong to */
.five-n + .five-n::before {
  content: "·"; color: var(--line-strong); font-weight: 600;
  margin: 0 .5em 0 .35em;
}
/* the pointer above the appendix index, in the same gold register as the card */
.five-lead {
  font-family: var(--sans); font-size: 1rem; line-height: 1.55; color: var(--ink-soft);
  border-left: 4px solid var(--brass-bright); padding: .1rem 0 .1rem 1rem;
  margin: 0 0 1.5rem; max-width: 46em;
}
.five-lead b { color: var(--ink); }

/* pull quote / verdict */
.verdict {
  font-family: var(--display); font-size: clamp(1.35rem, 2.8vw, 1.9rem); font-weight: 600;
  font-style: normal; line-height: 1.3; color: var(--ever);
  border-left: 3px solid var(--brass-bright);
  padding: .4rem 0 .4rem 1.3rem; margin: 1.8rem 0; max-width: 46ch;
}

/* ---------- tables ---------- */
.tablewrap { overflow-x: auto; margin: 1.4rem 0; border: 1px solid var(--line); border-radius: 4px; background: var(--card); }
table { border-collapse: collapse; width: 100%; font-size: .92rem; }
caption { text-align: left; font-family: var(--sans); font-weight: 700; font-size: .82rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft); padding: .8rem 1rem .35rem; }
th {
  font-family: var(--sans); font-size: .72rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-faint); text-align: left;
  padding: .6rem .9rem; border-bottom: 2px solid var(--line-strong); white-space: nowrap;
}
td { padding: .58rem .9rem; border-bottom: 1px solid var(--line); vertical-align: top; }
tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
tbody tr:hover { background: rgba(143,106,30,.045); }
.tfoot { font-size: .8rem; color: var(--ink-faint); padding: .55rem 1rem .8rem; font-family: var(--sans); }

/* ---------- figures / charts ---------- */
figure { margin: 1.6rem 0; }
figcaption { font-family: var(--sans); font-size: .82rem; color: var(--ink-faint); margin-top: .5rem; max-width: var(--measure); }
.chart { width: 100%; height: auto; display: block; }

/* ---------- lists ---------- */
ul, ol { max-width: var(--measure); padding-left: 1.3rem; margin: 0 0 1.1em; }
li { margin-bottom: .45em; }
li::marker { color: var(--brass); font-weight: 600; }

/* two-column feature grid */
.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 1.1rem; margin: 1.3rem 0; }
.grid3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1.1rem; margin: 1.3rem 0; }
.grid2 .card, .grid3 .card { margin: 0; }

/* layer diagram rows */
.layer { display: grid; grid-template-columns: 84px 1fr; gap: 1.1rem; align-items: start; padding: 1rem 0; border-bottom: 1px dashed var(--line); max-width: 46rem; }
.layer:last-of-type { border-bottom: none; }
.layer .badge {
  font-family: var(--mono); font-weight: 600; font-size: .78rem; text-align: center;
  background: var(--ever); color: var(--paper); border-radius: 3px; padding: .5em .3em;
}
.layer.l0 .badge { background: var(--ink-faint); }
.layer.l2 .badge { background: var(--sky); }
.layer h3 { font-size: 1.08rem; margin-bottom: .25rem; }
.layer p { margin-bottom: 0; font-size: .98rem; }

/* footnote-ish source line */
.src { font-family: var(--sans); font-size: .78rem; color: var(--ink-faint); max-width: var(--measure); }
.src a { color: inherit; }

/* footer */
footer.colophon {
  margin-top: 3.5rem; border-top: 3px double var(--line-strong);
  padding: 2rem 0 3rem; font-family: var(--sans); font-size: .85rem; color: var(--ink-faint);
}
footer .shell { display: grid; gap: .4rem; }

/* toc rail (desktop) */
.toc {
  position: sticky; top: 0; align-self: start;
  font-family: var(--sans); font-size: .8rem; line-height: 1.4;
  padding: 1.2rem 0 1.2rem 1rem; border-left: 1px solid var(--line);
  display: none;
}
.toc a { display: block; color: var(--ink-faint); text-decoration: none; padding: .22rem 0; }
.toc a:hover, .toc a.on { color: var(--brass); }
.toc .n { font-family: var(--mono); font-size: .68rem; margin-right: .45em; color: var(--brass); }

@media (min-width: 1240px) {
  .withrail { display: grid; grid-template-columns: 1fr 200px; gap: 2rem; max-width: 1320px; margin: 0 auto; padding: 0 var(--pad); }
  .withrail > .content { min-width: 0; max-width: 1080px; }
  .toc { display: block; }
}

/* reveal on scroll (subtle, print-safe) */
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s ease, transform .6s ease; }
  .reveal.in { opacity: 1; transform: none; }
}

/* ---------- mobile ---------- */
@media (max-width: 760px) {
  .hero .shell { grid-template-columns: 1fr; gap: 1.6rem; }
  .hero-side { border-left: none; border-top: 1px solid var(--line-strong); padding: 1.1rem 0 0; }
}

/* ============================================================
   PRINT — the guide becomes a clean PDF
   ============================================================ */
@media print {
  :root { --paper: #fff; --card: #fff; }
  body { font-size: 10.4pt; line-height: 1.5; background: #fff; }
  body::before { display: none; }
  .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
  .stats { background: transparent; }
  .tablewrap { overflow: visible; }
  table { font-size: 8.4pt; }
  th, td { white-space: normal !important; padding: .38rem .5rem; }
  td.num, th.num { white-space: nowrap !important; }
  .topbar, .toc, .no-print, .menu-btn, .btn { display: none !important; }
  .hero { padding: 0 0 1.2rem; }
  /* the branded title page becomes a full-bleed cover: image, title, date, one
     prepared-by line; the stat band is the very next thing on page 2 (owner ask). */
  .hero.hero-cover {
    height: 100vh; min-height: 100vh; page-break-after: always; break-after: page;
    display: grid; grid-template-columns: 1fr; grid-template-rows: 43% 1fr;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .hero-cover .hero-media, .hero-cover .hero-media img, .hero-cover .hero-media::before, .hero-cover .hero-media::after {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .hero-cover .hero-media { order: -1; height: auto; min-height: 0; }
  .hero-cover .lede { display: none; }
  /* the copy block sits on the lower green field: title optically centered,
     the standing notice and the three cover lines along the foot */
  .hero-cover .hero-copy { padding: 15mm 16mm 14mm; justify-content: center; }
  .hero-cover .kicker { font-size: 8.4pt; letter-spacing: .26em; }
  .hero-cover h1 { font-size: 34pt; line-height: 1.05; margin: .3em 0 0; }
  .hero-cover .hero-notice { font-size: 8.4pt; max-width: 62ch; margin-top: 1.2rem; }
  .hero-cover .print-only.cover-foot { margin-top: 1.5rem; }
  .hero-meta { display: none; }
  @page :first { margin: 0; }
}
/* screen: hidden by .print-only. print: the three cover lines, in a grid. */
.hero-cover .print-only.cover-foot {
  font-family: var(--sans); font-size: 8.2pt; line-height: 1.45; color: rgba(255,255,255,.9);
  margin-top: .8rem; padding-top: .7rem; border-top: 1px solid rgba(255,255,255,.28);
  gap: .18rem;
}
@media print { .hero-cover .print-only.cover-foot { display: grid; } }
.hero-cover .print-only.cover-foot b {
  font-family: var(--mono); font-size: 6.6pt; letter-spacing: .19em; text-transform: uppercase;
  color: var(--brass-on-green); margin-right: .5em;
}
@media print {
  a { color: inherit; text-decoration: none; }
  section.part { padding: 1.1rem 0 .4rem; break-inside: auto; }
  .part-head { break-after: avoid; }
  /* owner ask 2026-09-03 (2): no half-empty pages — tall tables and long cards may break
     across pages (rows stay whole, headers repeat); only small blocks stay unbreakable */
  .tablewrap, .tablewrap table, .card { break-inside: auto; }
  thead { display: table-header-group; }
  tr, .stat, figure, .layer, .grid3 .card { break-inside: avoid; }
  .grid2 .card { break-inside: auto; }   /* long two-column card grids may split at a page edge instead of leaving half a page empty */
  .card h3, caption, h3, h4 { break-after: avoid; }
  p, li { orphans: 3; widows: 3; }
  footer.colophon { margin-top: 1rem; padding: .8rem 0 0; break-inside: avoid; }
  .card.deep { background: #fff; color: var(--ink); border: 1.5px solid var(--ever); }
  .card.deep p { color: var(--ink); }
  .stats { border: 1px solid var(--line-strong); }
  h2 { break-after: avoid; }
  .print-only { display: block !important; }
  /* owner ask 2026-09-03: use the page width — the 70ch screen measure left a third of
     every printed page empty. Text runs margin to margin; pull quotes keep a measure. */
  p, ul, ol, figcaption, .src, .lede, .layer, .part-head .sub { max-width: none; }
  .verdict { max-width: 60ch; }
  .shell, .topbar { max-width: none; padding-left: 0; padding-right: 0; }
  .hero .shell { grid-template-columns: minmax(0, 2.2fr) minmax(200px, 1fr); }
  @page { margin: 14mm 13mm; }
}
.print-only { display: none; }

/* print: very wide tables shrink to fit the page instead of clipping */
@media print {
  .tablewrap table.wide { table-layout: fixed; width: 100%; font-size: 6.2pt; line-height: 1.25; }
  .tablewrap table.wide th, .tablewrap table.wide td { padding: .18em .25em; word-break: break-word; overflow-wrap: anywhere; hyphens: auto; }
  .tablewrap table.wide a { word-break: break-all; }
  .tablewrap table.wide .tag { font-size: 5.2pt; padding: 0 .2em; }
}

/* the five-line summary is part of the appendix, so it prints: tighter, and
   breakable between rows rather than shunted whole onto the next page */
@media print {
  .five {
    background: #fff; padding: .5rem .7rem .55rem; margin: 0 0 .9rem;
    border-color: #C9D0CA; border-left: 2pt solid var(--brass-bright);
    box-shadow: none; break-inside: auto;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .five-kicker { font-size: 7.4pt; letter-spacing: .16em; }
  .five-list { margin-top: .3rem; }
  .five-list > li {
    grid-template-columns: 7rem minmax(0, 1fr); gap: 0 .7rem;
    font-size: 8.6pt; line-height: 1.4; padding: .26rem 0;
    border-top-color: #DBE0DC; break-inside: avoid;
  }
  .five-k { font-size: 6.4pt; }
  .five .tag { font-size: 5.6pt; padding: 0 .25em; }
}

/* appendix sub-headings and compact lists (Appendix O) */
h4 { font-family: var(--sans); font-size: .95rem; font-weight: 700; letter-spacing: .02em; color: var(--ink); margin: 1.3rem 0 .45rem; }
ul.tight { margin: .4rem 0 1rem 1.3rem; padding: 0; }
ul.tight li { margin: .3rem 0; }

/* ============================================================
   INSTRUMENT SURFACES — one home for the dark pages
   (simulator · configurator · campus map · scaling · topology)
   ============================================================ */
:root {
  --inst-bg:     #0B2116;   /* dark UVU green, not a neutral black */
  --inst-panel:  #10281B;
  --inst-well:   #0A1C13;
  --inst-line:   rgba(231,226,211,.14);
  --inst-line-2: rgba(231,226,211,.28);
  --inst-fg:     #F4EFE1;
  --inst-fg-2:   #D6D0BF;
  --inst-dim:    #A9B3A2;
  --inst-accent: #E3C387;  /* Legacy Gold, brightened for AAA on dark green */

  /* graph tones — one per machine tier, reused by every graph page.
     Every hue maps back to the approved UVU accent set (findings §1.1);
     the two off-brand hues (a purple lab tone, a blue cloud tone) were
     folded into Heritage Brick and Lake Calm. All pass AA+ on --inst-bg
     and --inst-panel (BRAND-NOTES.md). */
  --g-mini:   #7BC97F;   /* Valley-Rise family */
  --g-studio: #E3C387;   /* Legacy Gold, same as --inst-accent */
  --g-ultra:  #E0A45C;   /* warm amber, Legacy-Gold-adjacent */
  --g-lab:    #C97A56;   /* Heritage Brick, lightened for a dark ground */
  --g-spare:  #8FA598;   /* neutral grey-green */
  --g-cond:   #CFE0D2;   /* pale Sea-Haze family */
  --g-cloud:  #87C7BA;   /* Lake Calm */
}

/* ============================================================
   THE SYSTEM GRAPH — drawn by graph.js, shared by both pages
   ============================================================ */
.topo { display: block; width: 100%; height: auto; overflow: visible; }
/* .fit lets the graph fill a bounded stage instead of setting its own height */
.topo.fit { height: 100%; width: 100%; overflow: hidden; }
.topo text { font-family: var(--sans); fill: var(--inst-fg); }

.topo .wire { fill: none; stroke: rgba(231,226,211,.26); stroke-linecap: round; }
.topo .wire.dash { stroke-dasharray: 5 5; stroke: rgba(135,199,186,.46); }  /* Lake Calm */
.topo .wire.rail { stroke: rgba(231,226,211,.16); stroke-width: 1; stroke-dasharray: 2 5; }

/* Traffic is a dot travelling the wire. offset-distance is a compositor
   property — stroke-dashoffset is not — so a hundred dots cost the main
   thread nothing while the budget slider is moving. The dot's path and
   speed arrive as custom properties on its group, so a redraw is one
   style write per line, never a rebuilt element. */
.topo .flowgrp { fill: var(--inst-accent); }
.topo .pk { opacity: 0; }
@supports (offset-path: path("M 0 0 L 1 1")) {
  .topo .pk {
    opacity: .9; offset-path: var(--fd); offset-rotate: 0deg;
    animation: pk-run var(--fdur, 4s) linear infinite;
  }
}
@keyframes pk-run { from { offset-distance: 0%; } to { offset-distance: 100%; } }
.topo.still .flowgrp { display: none; }
/* motion reduced: the dots stay, spread along each line by their own
   offset-distance, and simply stop travelling */
@media (prefers-reduced-motion: reduce) { .topo .pk { animation: none; opacity: .5; } }

/* ---------- the topology drawing (infra.js) ----------
   Same tokens and the same motion machinery as the request graph; what
   differs is that this one draws a room with bays in it. */
.topo.infra .roombox {
  fill: rgba(11,33,22,.42); stroke: var(--inst-line-2); stroke-width: 1.2;
  stroke-dasharray: 3 4;
}
.topo.infra .roomt {
  font-family: var(--sans); font-size: 12px; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; fill: var(--inst-dim);
}
.topo.infra .rooms { font-family: var(--mono); font-size: 10.5px; fill: var(--inst-dim); }
.topo.infra .node.k-room { cursor: pointer; }
.topo.infra .node.k-room:hover .roombox, .topo.infra .node.k-room:focus .roombox { stroke: var(--inst-accent); }
.topo.infra .node.k-bay .box { fill: rgba(23,57,38,.72); stroke: var(--tone, var(--inst-line-2)); stroke-width: 1.3; }
.topo.infra .node.k-bay.hollow .box { fill: none; stroke-dasharray: 4 4; }
.topo.infra .unit { fill: var(--tone, var(--g-mini)); opacity: .92; }
.topo.infra .node.hollow .unit { display: none; }
.topo.infra .more { font-family: var(--mono); font-size: calc(10px * var(--ts, 1) * 1.35); fill: var(--tone, var(--inst-dim)); }
.topo.infra .node.k-door .box { stroke: var(--g-cloud); }
.topo.infra .node.k-infra .box { stroke: var(--inst-line-2); }
.topo.infra .elabel {
  font-family: var(--sans); font-size: 11px; font-weight: 600;
  letter-spacing: .02em; fill: var(--inst-dim); opacity: .92;
  paint-order: stroke; stroke: var(--inst-bg); stroke-width: 3.2px; stroke-linejoin: round;
}
.topo.infra .elabel.rail { font-weight: 500; opacity: .7; }
/* a wire nothing flows down yet — drawn, but plainly not carrying anything */
.topo.infra .wire.idle { stroke: rgba(231,226,211,.11); }
.topo.infra .wire.dash.idle { stroke: rgba(135,199,186,.16); }
@media print {
  .topo.infra .roombox { fill: #fff !important; stroke: #A9B4AC !important; }
  .topo.infra .roomt, .topo.infra .rooms { fill: #55605A !important; }
  .topo.infra .node.k-bay .box { fill: #fff !important; }
  .topo.infra .unit { fill: #6B7A70 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .topo.infra .elabel { fill: #55605A !important; stroke: #fff !important; }
  .topo.infra .more { fill: #55605A !important; }
}

.topo .node .box {
  fill: var(--inst-panel); stroke: var(--tone, var(--inst-line-2)); stroke-width: 1.2;
  transition: fill .16s ease, stroke-width .16s ease;
}
.topo .node .disc { fill: var(--tone, var(--g-mini)); stroke: rgba(11,33,22,.7); stroke-width: 1.5; }
/* --ts is set on the <svg> by graph.js / infra.js: 1 on a wide screen, and
   on a phone however much bigger these have to be set in user units for the
   drawing's own scaling to land them at a readable size on the glass. The
   sub-line's own floor is a little higher than a plain multiple, because at
   10.5px it starts furthest below where it has to end up. */
.topo .node .t { font-size: calc(13px * var(--ts, 1)); font-weight: 700; fill: var(--inst-fg); }
.topo .node .s { font-size: calc(10.5px * var(--ts, 1) * 1.28); font-weight: 500; fill: var(--inst-dim); }
.topo .node .b { font-family: var(--mono); font-size: calc(9.5px * var(--ts, 1) * 1.28); fill: var(--tone, var(--inst-accent)); }
.topo .node .cap { font-family: var(--mono); font-size: calc(13px * var(--ts, 1)); font-weight: 600; fill: var(--inst-accent); }
.topo .node .cap .capu { font-size: calc(9px * var(--ts, 1) * 1.4); fill: var(--inst-dim); font-weight: 500; }
.topo .grp {
  font-size: calc(10px * var(--ts, 1) * 1.28); font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; fill: var(--inst-dim);
}

.topo .node.hollow .box { fill: none; stroke-dasharray: 4 4; stroke: rgba(231,226,211,.34); }
.topo .node.hollow .disc { fill: none; stroke: rgba(231,226,211,.45); stroke-dasharray: 3 3; }
.topo .node.hollow .t { fill: var(--inst-dim); }
.topo .node.dashed .box { stroke-dasharray: 6 4; }
.topo .node.muted .t { fill: var(--inst-fg-2); }
.topo .node.k-gate .box { fill: var(--inst-well); stroke: var(--g-cloud); stroke-dasharray: 3 3; }
.topo .node.k-router .box { stroke: var(--inst-accent); }
.topo .node.k-rail .box { fill: none; stroke: rgba(231,226,211,.2); }
.topo .node.k-rail .t { font-size: calc(11.5px * var(--ts, 1)); fill: var(--inst-dim); }

.topo .node { cursor: pointer; }
.topo .node:hover .box, .topo .node:focus .box { fill: #173926; stroke-width: 2.2; }
.topo .node:hover .disc, .topo .node:focus .disc { stroke: var(--inst-accent); stroke-width: 2.5; }
.topo .node:focus { outline: none; }
.topo .node:focus .box, .topo .node:focus .disc { stroke: var(--inst-accent); }
.topo .node.sel .box { fill: #1B4630; stroke: var(--inst-accent); stroke-width: 2.4; }
.topo .node.sel .disc { stroke: var(--inst-accent); stroke-width: 3; }

@media print {
  .topo .flows { display: none !important; }
  .topo text { fill: #182218 !important; }
  .topo .node .s, .topo .grp { fill: #55605A !important; }
  .topo .node .box { fill: #fff !important; stroke: #7C8A80 !important; }
  .topo .node.k-router .box { stroke: #123524 !important; }
  .topo .wire { stroke: #9AA79E !important; }
  .topo .wire.dash { stroke: #9AA79E !important; }
  .topo .node .b, .topo .node .cap { fill: #6B5A22 !important; }
}
