/* ══════════════════════════════════════════════════════════════════════════
   digitalumbrella.io, in the Drafted identity.

   Every value is a token from drafted/tokens.css (ZynoStack/brand
   digital-umbrella-next, vendored unedited), and every moving part is the
   kit's pen from drafted/drafted.css. This file is only the site's layout.
   Three rules, from the kit: one pen draws everything, in order; amber marks
   only what does the work; results are written in the margin on a leader line.
   Dark everywhere; paper for print. No shadow, no blur, no glow, no fill that
   lifts a card: containers are outlines and rows are ruled.
   ══════════════════════════════════════════════════════════════════════════ */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink-2);
  font: 400 var(--fs-body)/var(--lh-body) var(--font);
  overflow-wrap: break-word;
}
h1, h2, h3 { color: var(--ink); font-weight: 600; margin: 0; text-wrap: balance; }
h1 { font-size: var(--fs-h1); line-height: 1.15; letter-spacing: -.02em; }
h2 { font-size: var(--fs-h2); line-height: 1.25; letter-spacing: -.01em; }
h3 { font-size: var(--fs-h3); line-height: 1.35; }
p, ul, ol, dl, dd, figure { margin: 0; }
/* no paragraph or phone note ends on one word ("company.", "inside.", "band") */
p, .notes li, .menu-list span, .ticks li { text-wrap: pretty; }
img { max-width: 100%; }
/* the kit's own link rule (drafted.css) already sets text-decoration-line to
   none on every anchor here, classed or not, so a color/thickness/offset set
   on the shorthand's line never draws: confirmed live, both were dead. */
a { color: var(--ink); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 2px; }
/* the hidden attribute beats any display rule an author writes */
[hidden] { display: none !important; }
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }

.wrap { max-width: calc(1240px + 2 * var(--s-5)); margin: 0 auto; padding-inline: var(--s-5); }
@media (max-width: 600px) { .wrap { padding-inline: var(--s-4); } }

.skip { position: absolute; left: var(--s-4); top: -100px; z-index: 10; padding: var(--s-2) var(--s-4); background: var(--bg); color: var(--ink); border: 1px solid var(--edge); border-radius: var(--r); }
.skip:focus { top: var(--s-2); }

/* ── the header: identical on every page ─────────────────────────────── */
.top { --top-h: 72px; border-bottom: 1px solid var(--rule); }
.top .wrap { display: flex; align-items: center; gap: var(--s-4); min-height: var(--top-h); }
.home { display: inline-flex; align-items: center; min-height: var(--target); flex: none; }
/* the site header: the full strip at 34px (30 reads light beside the bold
   menu); the <picture> already swaps to the mark below 480px (B7, 30 Sep
   2026), so its own height moves with it. */
.top .home img { display: block; height: 34px; width: auto; }
@media (max-width: 479px) { .top .home img { height: 30px; } }
.nav { margin-left: auto; display: flex; align-items: center; gap: var(--s-5); }
/* Every header link is a bare anchor, with no class and no .du-link, so the
   kit's own rule for a link in navigation applies to all of them alike: no
   resting line, and the pen draws the ink one on hover and focus. A class
   would take an anchor out of that rule, so the two this file must pick out
   are chosen without one: Services by [data-wide], the plain Products link as
   the .menu's one direct anchor. */
.nav > a, .menu > a, .menu > .menu-btn {
  display: inline-flex; align-items: center; min-height: var(--target); white-space: nowrap;
  color: var(--ink-2); font-size: 15px; font-weight: 500; text-decoration: none;
}
.nav > a:hover, .menu > a:hover, .menu > .menu-btn:hover { color: var(--ink); }
/* the page you are on is underlined like a selected tab, never by colour
   alone; background-image:none keeps the kit's own classless-link underline
   (drawn from zero specificity) from doubling this one, since both would
   otherwise sit at nearly the same baseline (web-verification: a site rule
   that sets an underline draws two next to the kit's). */
/* the same mechanism as the kit's own link underline (a background line at
   the box's bottom edge), not text-decoration: a text-underline-offset sits
   above the kit's drawn line beside it, about 6px off at 1280. */
/* Scoped to the top row: inside the Products column the same bar read as a
   selected row (30 Sep 2026 review). */
.nav > [aria-current="page"] { color: var(--ink); text-decoration: none; background: linear-gradient(var(--amber-line), var(--amber-line)) 0 100% / 100% 2px no-repeat; }
.nav > [data-wide] { display: none; }
@media (min-width: 820px) { .nav > [data-wide] { display: inline-flex; } .menu-list .menu-custom { display: none; } }
@media (max-width: 600px) { .nav { gap: var(--s-4); } .nav > a, .menu > a { font-size: 14px; } }
@media (max-width: 380px) { .top .wrap { gap: var(--s-3); } .nav { gap: var(--s-3); } }

/* Products is the kit's menu (DESIGN.md 4.16; the products' bar uses the same
   contract). From 700px, once site.js has run (du-js is set in <head>), a
   button opens the list on a click; under 700px, or with no script at all,
   the plain link to /products.html is the only Products control and the list
   never shows, because it keeps its hidden attribute until the button takes
   it off. One tier, never a mega menu, and no hover: click is the contract.
   Screen only: print keeps the plain link, never the button or the list. */
.menu { position: relative; display: inline-flex; }
.menu > .menu-btn { display: none; gap: 6px; padding: 0; background: none; border: 0; font-family: inherit; line-height: inherit; cursor: pointer; }
.menu-btn svg { flex: none; }
.menu-btn[aria-expanded="true"] svg { transform: rotate(180deg); }
@media screen and (min-width: 700px) {
  .du-js .menu > a { display: none; }
  .du-js .menu > .menu-btn { display: inline-flex; }
}
/* The list is the kit's .du-menu (its --raise ground, radius and 1.5px
   outline, and the frame the kit primes at load), opened under the button:
   right-aligned to it, its top 6px below the header's bottom rule. The button
   is centred in the header's row, so the rule sits (row height - target) / 2
   + 1px below it. site.js calls DU.reset then DU.draw on every open, because
   the kit does not watch the hidden attribute. */
.menu-list {
  position: absolute; z-index: 5; right: 0; width: 22rem;
  top: calc(100% + (var(--top-h) - var(--target)) / 2 + 1px + 6px);
  list-style: none; margin: 0;
}
/* The kit gives .du-menu li and [role="menuitem"] each a 44px height and a
   horizontal padding, which would stack on a two-line item: here the li is
   only a wrapper, and the link carries the one padding, name over line. */
.menu-list li { display: block; min-height: 0; padding: 0; }
.menu-list [role="menuitem"] { flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px; padding: var(--s-3) var(--s-4); }
.menu-list b { color: var(--ink); font-size: 15px; font-weight: 600; }
.menu-list span { color: var(--ink-2); font-size: var(--fs-ui); line-height: 1.4; }

/* ── the page's opening screen ───────────────────────────────────────── */
.hero { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-5); align-items: center; padding-block: var(--s-7); }
.hero-copy { display: grid; justify-items: start; }
.slogan { color: var(--amber-text); font-weight: 700; font-size: 17px; margin-bottom: var(--s-4); }
.hero h1 { margin-bottom: var(--s-5); }
.hero h1.display { font-size: var(--fs-display); line-height: var(--lh-tight); letter-spacing: -.035em; }
.lead { font-size: var(--fs-lead); max-width: 36ch; margin-bottom: var(--s-6); }
.ctas { display: flex; flex-wrap: wrap; gap: var(--s-3); }
@media (max-width: 420px) { .ctas .du-btn { padding: 0 var(--s-4); } }
/* the hero with no drawing: pricing and company */
.hero.solo { grid-template-columns: minmax(0, 1fr); padding-bottom: var(--s-6); }
.hero.solo .lead { max-width: 44ch; margin-bottom: 0; }
.hero.solo .ctas { margin-top: var(--s-6); }
@media (max-width: 979px) {
  .hero { grid-template-columns: minmax(0, 1fr); gap: var(--s-6); padding-top: var(--s-6); }
}
@media (max-width: 600px) {
  .hero { padding-block: var(--s-5); gap: var(--s-5); }
  .slogan { margin-bottom: var(--s-3); }
  .hero h1 { margin-bottom: var(--s-4); }
  .lead { margin-bottom: var(--s-5); }
}

/* the eyebrow a product page opens with: its name, who it is for */
.who { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-4); color: var(--ink); font-weight: 600; font-size: 15px; }

/* what we sell, under the homepage buttons: two by two at every width, so the
   fourth never wraps onto a line of its own. Custom builds is written like
   the three products: links are never amber (DESIGN.md 7).
   The list sits in a <nav> and its anchors carry no class, so the kit's own
   rule for a link in navigation applies: no resting line, and the pen draws
   the ink one on hover and focus. Not a site rule: a second explicit one here
   used to draw twice. */
.prods { display: grid; grid-template-columns: repeat(2, max-content); align-items: center; gap: var(--s-2) var(--s-5); list-style: none; padding: 0; margin: var(--s-6) 0 0; }
.prods a { display: inline-flex; align-items: center; gap: var(--s-2); min-height: var(--target); color: var(--ink); font-weight: 700; font-size: 15px; text-decoration: none; }

/* ── the drawing ─────────────────────────────────────────────────────── */
.drawing { display: block; width: 100%; height: auto; overflow: visible; }
.drawing text { fill: var(--ink); font: 500 18px var(--font); }
.drawing .lead-line { stroke: var(--amber-line); stroke-width: 1.4; }
.drawing-wrap { min-width: 0; }
/* a product hero's in-and-out flow: the same drawing convention (data-draw,
   .du-pen/.du-after, pathLength 100), its own text sizes only */
.flow .in { font-size: 20px; font-weight: 600; }
.flow .out { font-size: 18px; font-weight: 600; }
.flow .small { font-size: 13px; fill: var(--ink-3); }
/* on a phone the notes leave the drawing and sit under it, in words; the
   drawing's own label already carries them for a screen reader */
.notes { display: none; }
@media (max-width: 600px) {
  .drawing { max-width: 240px; margin-inline: auto; }
  .prods { margin-top: var(--s-5); }
  .drawing text, .drawing .lead-line { display: none; }
  /* the in-and-out flow is nothing but its words once they are hidden, and at
     this width they would fall under the 12px floor: the notes below carry it */
  .drawing.flow { display: none; }
  .notes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-4); list-style: none; margin: var(--s-3) 0 0; padding: 0; font-size: var(--fs-ui); color: var(--ink); }
  .notes li { display: flex; align-items: baseline; gap: var(--s-2); }
  .notes li::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--amber-line); transform: translateY(-2px); }
  .notes.one { grid-template-columns: minmax(0, 1fr); }
}
/* Nothing is hidden unless the script that draws it has run (25 S22): the
   kit hides strokes once drafted.js marks the page (du-js) until data-pen is
   set, and site.js is what sets it, so without site.js the drawing is shown
   finished even when drafted.js ran. */
html:not(.pen) .du-pen { stroke-dashoffset: 0; }
html:not(.pen) .du-after { opacity: 1; }

/* ── sections: ruled from each other, never boxed ─────────────────────
   the rule between sections is now a real .du-rule element (it draws itself
   in as it scrolls into view), not a border a section drew for itself. The
   sections either side keep the same padding they always had, which is what
   gave the border-top its clearance, so the sibling <hr> needs none of its
   own; adding any here would double it on one side. */
.sec { padding: var(--s-7) 0; }
.sec > .wrap > h2 { margin-bottom: var(--s-5); max-width: 32ch; }
.sec .intro { max-width: 48ch; margin: calc(-1 * var(--s-3)) 0 var(--s-5); }
.measure { max-width: 48ch; }
/* align-content: a stack stretched to its neighbour's height keeps its gaps
   instead of spreading the spare height between them */
.stack { display: grid; gap: var(--s-4); align-content: start; }
@media (max-width: 600px) { .sec { padding: var(--s-5) 0; } .hero.solo { padding-bottom: var(--s-8); } }

/* ruled rows, now the kit's own .du-rows: it draws the rule under each row
   and fades its words in as it scrolls into view (drafted.js's automatic
   AUTO selector), so the per-list --i bookkeeping and the [data-pen] rules
   that used to live here are gone with it. What is left is only this site's
   shape for a row: li.rows > li and .rows.split > li match .du-rows > li's
   own specificity (one class, one type) so they still win the display
   property on source order, instead of the kit's dense flexed data-row
   layout leaking into a marketing row of a heading and a paragraph. */
.rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-2); }
.rows > li { position: relative; display: block; padding: var(--s-5) 0; font-size: var(--fs-body); }
.rows h3 { margin-bottom: var(--s-2); }
.rows p { max-width: 48ch; color: var(--ink-2); }
@media (min-width: 900px) {
  .rows.split > li { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-5); align-items: baseline; }
  .rows.split h3 { margin: 0; }
}
@media (max-width: 600px) { .rows > li { padding: var(--s-4) 0; } }

/* a product in a list: its name, what it is, and the way in.
   li.prod (not .prod) for the same reason as .rows > li above: one class
   plus the row's own type ties .du-rows > li's specificity, so the site's
   grid wins instead of the kit's flex. */
li.prod { display: grid; grid-template-columns: 220px minmax(0, 1fr) auto; gap: var(--s-5); align-items: start; }
.prod-name { display: flex; align-items: center; gap: var(--s-3); }
.prod-name h2, .prod-name h3 { font-size: var(--fs-h3); }
.prod .price { color: var(--ink); font-weight: 600; margin-top: var(--s-2); }
.prod .go { justify-self: end; }
.prod p { max-width: 48ch; }
/* the hover underline is the kit's automatic one (these anchors carry no
   class): a site rule that also drew one here used to draw two. */
.prod-name a { display: inline-flex; align-items: center; min-height: var(--target); text-decoration: none; }
/* one line across the row: a one-line name sits centred on the row's 44px
   touch target, as the way in does, so the description drops to it; a name
   with a price under it sits at the top, so the way in rises to it. Each was
   10px off the other. */
@media (min-width: 900px) {
  .prod:not(:has(.price)) > p { margin-top: calc((var(--target) - 1lh) / 2); }
  .prod:has(.price) > .go { margin-top: calc((1lh - var(--target)) / 2); }
}
@media (max-width: 899px) {
  li.prod { grid-template-columns: minmax(0, 1fr); gap: var(--s-3); }
  .prod .go { justify-self: start; }
}
/* On a phone the homepage's short list keeps its height down: the product's
   name is the link. It sits in a heading, so the kit's rule for a link in a
   heading applies: no resting line, and the pen draws the ink one on hover
   and focus (before brand 299d5ac it rested underlined, and this was the way
   in). */
@media (max-width: 600px) {
  .rows.brief .go { display: none; }
  .rows.brief .prod-name a { display: inline-flex; align-items: center; min-height: var(--target); }
}

/* a prose link that is a row's way in: a real 44px target */
.go { display: inline-flex; align-items: center; min-height: var(--target); font-weight: 600; white-space: nowrap; }

/* the FAQ's question is the kit's disclosure summary (14px/600, line-height 1
   from drafted.css:269), a step down from the 18px h3 it used to be; raised
   back to h3 size, with room to wrap without its own lines touching (a
   line-height of 1 collides at 320px: "Can we buy through AWS Marketplace?"). */
.qa2 details.du-more > summary { font-size: var(--fs-h3); line-height: 1.35; }
/* SIMPLIFIED: Chromium keeps no before-change style for content inside a
   closed <details>, so the kit's own opacity/scale transition on open never
   starts. This gives it one to start from. NOT the same rule upstream: the
   kit's only @starting-style (drafted.css:306) is `dialog.du-dialog::backdrop`,
   a different element; corrected 30 Sep 2026 round 2, a prior comment here
   claimed this one already existed there too. Pending upstream, see README
   "Brand #5" pending kit fixes. */
@starting-style {
  details.du-more[open] > summary + * { opacity: 0; }
  details.du-more[open] > summary + *::before { transform: scaleX(0); }
}
/* the page's measure, which a column only keeps while there are two of them */
.qa2 p { max-width: 48ch; }

/* ── pricing: one "Questions" heading, two labelled columns (rule 6), each a
   stack of its own two-question .qa group ──────────────────────────────── */
.qa2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-6) var(--s-7); margin-top: var(--s-5); }
/* its group labels (.qa2 h3) are the .skim label: one rule, further down */
@media (max-width: 899px) { .qa2 { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); } }

/* ticks are drawn marks, not icons. .ticks li never set its own font-size or
   padding, so when du-rows > li supplied the row draw it also supplied its
   14px --fs-ui and --s-3/2px padding uncontested (no specificity war: the
   properties simply were not there to lose). Set both back explicitly, and
   zero the list's own gap so the row padding is the only spacing (it used to
   stack on top of it). */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.ticks.du-rows { gap: 0; }
.ticks li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: var(--s-3); align-items: start; color: var(--ink); font-size: var(--fs-body); }
.ticks li::before { content: ""; width: 12px; height: 7px; margin-top: .45em; border-left: 1.5px solid var(--pen); border-bottom: 1.5px solid var(--pen); transform: rotate(-45deg); }

.strong { color: var(--ink); font-weight: 600; }

/* ── scanning pattern: a small label above a heading, and a two-column
   problem statement (text plus a drawing, rule 3) ───────────────────────── */
/* The kit's label, and the one place this site sets it (a section's .skim and
   the pricing page's .qa2 h3 group labels): sentence case with no tracking,
   12px, 600, --ink-3. It was capitals with .02em; the kit has no all-caps
   label. */
.skim, .qa2 h3 { font: 600 var(--fs-label) var(--font); text-transform: none; letter-spacing: normal; color: var(--ink-3); margin-bottom: var(--s-2); }
.skim { display: block; }
.gap { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-6); align-items: center; margin-top: var(--s-4); }
.gap-draw { display: block; width: 100%; height: auto; overflow: visible; }
.fine-line { font-size: var(--fs-ui); color: var(--ink-3); margin-top: var(--s-2); max-width: 46ch; }
@media (max-width: 820px) { .gap { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); } }

/* ── scanning pattern: two consultants' diagrams that disagree (Blueprint's
   problem), the same .gap layout as TNA's two-estimate drawing ────────────── */
.two-diag { display: block; width: 100%; height: auto; overflow: visible; }
.two-diag text { font-size: 14px; font-weight: 600; fill: var(--ink-2); }
.two-diag text.warn { fill: var(--amber-text); }

/* ── scanning pattern: what a product replaces, struck through by the pen,
   ending on what replaces it (Workmap's problem) ───────────────────────────
   Reuses the kit's own du-rule keyframe (drafted.css), the same draw-in a
   .du-rows row's underline uses, so no new animation is defined here. */
.struck { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.struck li { font-size: var(--fs-body); color: var(--ink-2); }
.struck li span { position: relative; }
.struck li span::after { content: ""; position: absolute; left: -4px; right: -4px; top: 54%; height: 1.5px; background: var(--pen-2); transform-origin: 0 50%; }
.struck[data-pen="drawn"] li span::after { animation: du-rule var(--pen-stroke) var(--ease-pen) both; animation-delay: calc(var(--i, 0) * 160ms + 200ms); }
.struck .now { color: var(--ink); font-weight: 600; font-size: var(--fs-h3); padding-top: var(--s-2); }
.struck .now span::after { background: var(--amber-line); top: auto; bottom: -6px; height: 2px; }
/* the same pre-hide this site already needed for .du-rows > li::after (see
   the SIMPLIFIED comment below .prods-full): the du-rule keyframe's "both"
   fill mode only applies once [data-pen="drawn"] exists, so a list already on
   screen at load would show every line struck before it ever draws in. */
@media screen and (prefers-reduced-motion: no-preference) {
  .du-js .struck:not([data-pen]) li span::after { transform: scaleX(0); }
}
@media (prefers-reduced-motion: reduce) { .struck[data-pen="drawn"] li span::after { animation: none; } }

/* ── scanning pattern: what goes in, what comes out, drawn (25-SCAN rule 4) ──
   The label and the fact are written inside the one svg, joined by the pen's
   amber arrow, same drawing convention as the hero (data-draw, .du-pen/
   .du-after, pathLength 100), so it draws in on scroll and shows finished
   under reduced motion like everything else the kit animates. One size: a
   homepage row and a products-index card. */
.io { display: block; width: 100%; max-width: 380px; margin-top: var(--s-5); }
.io svg { display: block; width: 100%; height: auto; overflow: visible; }
.io text { font-size: var(--fs-ui); font-weight: 600; fill: var(--ink-2); font-family: var(--font); }
.io text.o { fill: var(--ink); }

/* ── scanning pattern: a 4-stage sequence on one line (rule 6) ────────────
   The kit's .rows.split already stacks a number, a label and a line of
   support; .seq adds the single ruled line that ties the stages together
   as one dimension, drawn once with the kit's own pen classes. */
.seq { position: relative; margin-top: var(--s-6); }
.seq-line { position: absolute; top: 0; left: 0; width: 100%; height: 14px; overflow: visible; }
.seq-line path { fill: none; stroke: var(--rule-2); }
.seq ol { list-style: none; margin: 0; padding: var(--s-5) 0 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-5); border-top: none; }
.seq li { padding: 0; }
.seq b { display: block; color: var(--ink); font-size: var(--fs-h3); font-weight: 600; margin-bottom: var(--s-1); }
.seq b span { color: var(--ink-3); font-weight: 600; margin-right: 4px; }
.seq p { color: var(--ink-2); max-width: 28ch; }
@media (max-width: 820px) {
  .seq ol { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-5) var(--s-4); }
}
@media (max-width: 600px) {
  .seq-line { display: none; }
  .seq ol { grid-template-columns: minmax(0, 1fr); padding-top: 0; gap: var(--s-4); }
}
/* a 3-item sequence (company's "what goes wrong"): three columns until it
   collapses, never the 4-column default with an empty fourth slot. */
@media (min-width: 601px) { .seq.cols-3 ol { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ── scanning pattern: a short list of what you get, ruled above (rule 3) ──
   Three columns on a wide screen, one rule each, collapsing to a stack. */
.three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5); margin-top: var(--s-5); border-top: 1px solid var(--rule-2); padding-top: var(--s-4); }
.three > div { padding-top: var(--s-3); border-top: 1px solid var(--rule-2); }
.three b { display: block; color: var(--ink); font-size: var(--fs-h3); font-weight: 600; margin-bottom: var(--s-1); }
.three span { color: var(--ink-2); }
@media (min-width: 601px) { .three { border-top: none; padding-top: 0; } .three > div:first-child { border-top: 1px solid var(--rule-2); } }
@media (max-width: 600px) { .three { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); } }
/* column-count modifiers: a real grid column count at each width, never an
   inline style (an inline grid-template-columns beats the max-width:600px
   rule above at any width, so a phone would keep a desktop column count). */
@media (min-width: 601px) { .three.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ── scanning pattern: price bands, the figure first (rule 5) ────────────── */
.bands { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5); margin: var(--s-5) 0 var(--s-2); max-width: 56ch; }
.bands b { display: block; color: var(--ink); font-size: clamp(28px, 4vw, 40px); line-height: 1; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; margin-bottom: var(--s-1); }
.bands span { color: var(--ink-2); font-size: var(--fs-ui); }
@media (max-width: 600px) { .bands { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-3); } }

/* ── scanning pattern: proofs side by side, not stacked (rule 6) ─────────── */
.holds { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-5); margin-top: var(--s-5); }
.holds > div { padding-top: var(--s-6); position: relative; }
.holds svg { position: absolute; top: 0; left: 0; width: 32px; height: 26px; overflow: visible; }
.holds svg path { fill: none; stroke: var(--amber-line); stroke-width: 2.5; stroke-linecap: round; }
.holds b { display: block; color: var(--ink); font-size: var(--fs-h3); font-weight: 600; margin-bottom: var(--s-1); }
.holds span { color: var(--ink-2); }
@media (max-width: 820px) { .holds { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .holds { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); } }

/* ── scanning pattern: a product row, label plus in/out, not a paragraph ── */
/* Each row: the name, its one-line job, its in-and-out drawn, and
   the way in, side by side (rule 6), not stacked. Four children, four
   columns; a row with no job (none today) still lays out, the job column
   simply empty. */
.prods-full { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-2); }
.prods-full > li { padding: var(--s-5) 0; display: grid; grid-template-columns: minmax(0, 220px) minmax(0, 1fr) minmax(0, 320px) auto; gap: var(--s-4); align-items: center; }
.prods-full .job, .job { color: var(--ink); font-size: var(--fs-body); max-width: 30ch; }
.prods-full .io { margin: 0; }
.prods-full .go { justify-self: end; }
.prods-full .price { color: var(--ink); font-weight: 600; margin-top: var(--s-1); }
@media (max-width: 979px) {
  .prods-full > li { grid-template-columns: minmax(0, 220px) minmax(0, 1fr); gap: var(--s-3) var(--s-4); }
  .prods-full .io { grid-column: 1 / -1; }
  .prods-full .go { grid-column: 1 / -1; justify-self: start; }
}
@media (max-width: 600px) {
  .prods-full > li { grid-template-columns: minmax(0, 1fr); }
  .prods-full .io { grid-column: auto; }
  .prods-full .go { grid-column: auto; }
}

/* ── the ending: one action, with a price or an honest date ──────────── */
.end, .list { padding-bottom: var(--s-7); }
@media (max-width: 600px) { .end, .list { padding-bottom: var(--s-5); } }
/* the outlined box, now the kit's own .du-outline: it traces its frame in
   and fades the heading, price and button behind it as it scrolls into view,
   in place of the static border this used to draw for itself. */
.ending { padding: var(--s-6); display: grid; justify-items: start; gap: var(--s-3); }
.ending p { max-width: 46ch; }
.ending .price { color: var(--ink); font-weight: 600; }
.ending .du-btn { margin-top: var(--s-3); }
@media (max-width: 600px) { .ending { padding: var(--s-5) var(--s-4); } }

/* ── the price table ─────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; }
.prices { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
.prices th, .prices td { padding: var(--s-4) var(--s-3) var(--s-4) 0; border-bottom: 1px solid var(--rule-2); text-align: left; vertical-align: baseline; }
.prices thead th { color: var(--ink-2); font-size: var(--fs-ui); font-weight: 600; }
.prices tbody th { color: var(--ink); font-weight: 600; }
.prices tbody th img { display: block; height: 30px; width: auto; }
.prices td { color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 500; }
.prices .together th, .prices .together td { border-top: 1px solid var(--pen-2); }
/* rule 5: prices are set large, the label stays with the table, not the figure. */
.prices.num td { font-size: clamp(22px, 2.6vw, 28px); font-weight: 600; letter-spacing: -.01em; }
.prices.num td small { display: block; font-size: var(--fs-small); font-weight: 500; color: var(--ink-3); letter-spacing: normal; }
.note-line { font-size: var(--fs-ui); margin-top: var(--s-3); }
.price-note { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-top: var(--s-3); }
.price-note .note-line { margin-top: 0; }
@media (max-width: 600px) {
  .prices { font-size: 15px; }
  .prices th, .prices td { padding: var(--s-3) var(--s-2) var(--s-3) 0; }
  .prices thead th { font-size: var(--fs-label); }
  .prices.num td { font-size: 19px; }
  /* the strips keep 22px, their size in the products' own menus, at their own
     proportions (TNA 36 wide, Blueprint 83, Workmap 77). An auto-layout table
     gives the first column only what it must, so it squeezed them to about
     17px high; the column holds 96px (Blueprint plus the cell's gap) and no
     strip is capped by it. */
  .prices tbody th { min-width: 96px; }
  .prices tbody th img { height: 22px; max-width: none; }
}

/* ── pricing: four pen-drawn ticks, side by side (rule 3, "every band has
   all of it"). Ink, not amber: a tick confirms a feature, it is not the
   action or the measure (rule 6). Layout matches .holds; the stroke and
   the draw-on-view differ, so it is its own rule rather than a modifier
   that would have to override both. ────────────────────────────────────── */
.ticks4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-5); margin-top: var(--s-5); }
.ticks4 > div { padding-top: var(--s-6); position: relative; }
.ticks4 svg { position: absolute; top: 0; left: 0; width: 26px; height: 26px; overflow: visible; }
.ticks4 svg path { fill: none; stroke: var(--ink); }
.ticks4 b { display: block; color: var(--ink); font-size: var(--fs-h3); font-weight: 600; margin-bottom: var(--s-1); }
.ticks4 span { color: var(--ink-2); }
@media (max-width: 820px) { .ticks4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .ticks4 { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); } }

/* ── company: the definitions ────────────────────────────────────────── */
.defs { margin: 0; border-top: 1px solid var(--rule-2); }
.defs > div { padding: var(--s-4) 0; border-bottom: 1px solid var(--rule-2); }
.defs dt { color: var(--ink); font-weight: 600; }
.defs dd { margin: var(--s-1) 0 0; max-width: 48ch; }

/* ── the legal pages: a document, at a reading measure ───────────────── */
/* A contents rail in the margin (sticky), and a short-version callout above
   the document, each a sentence the document already makes (spec: legal
   pages keep every word; these are reading aids, not a rewrite). The rail
   is real anchors, not the mockup's plain <span> list: a legal page is the
   one place a reader actually wants to jump to a section. Current section
   gets the 2px amber rule via .on, set by the IntersectionObserver in
   site.js; nothing breaks without JS, the rail just never updates .on. */
.docwrap { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: var(--s-7); align-items: start; }
.rail { position: sticky; top: var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-7) 0; font-size: var(--fs-small); max-height: calc(100vh - var(--s-6)); overflow-y: auto; }
.rail a { color: var(--ink-3); border-left: 2px solid transparent; padding: 2px 0 2px var(--s-3); text-decoration: none; }
.rail a:hover, .rail a:focus-visible { color: var(--ink); }
.rail a.on { color: var(--ink); border-left-color: var(--amber-line); font-weight: 600; }
@media (max-width: 820px) {
  .docwrap { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .rail { position: static; flex-direction: row; flex-wrap: wrap; gap: var(--s-1) var(--s-4); padding: var(--s-5) 0 0; max-height: none; overflow: visible; order: 2; }
  .doc { order: 1; }
}
.short { padding: var(--s-5); margin: var(--s-5) 0 var(--s-6); }
.short h2 { margin-top: 0; }
.short ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.short li { display: flex; gap: var(--s-3); align-items: flex-start; color: var(--ink-2); }
/* Scoped to the list items, not ".short svg": that also matched the kit's own
   svg.du-frame (inserted as the first child of any .du-outline box by
   drafted.js's frame()), shrinking its 100%/100% rect to 16x17 and tracing a
   small circle in the corner instead of the card's border. Found by looking
   at the rendered page, not by reading the CSS: a screenshot showed a stray
   circle beside "The short version" and element-from-point named the rect. */
.short li svg { flex: none; width: 16px; height: 17px; margin-top: 3px; overflow: visible; }
.short li svg path { fill: none; stroke: var(--ink); }
.doc { max-width: 52ch; padding: var(--s-7) 0; }
.doc h1 { margin-bottom: var(--s-2); }
.doc .dated { font-size: var(--fs-small); color: var(--ink-3); margin-bottom: var(--s-6); }
.doc h2 { font-size: var(--fs-h3); margin: var(--s-6) 0 var(--s-3); scroll-margin-top: var(--s-5); }
.doc p { margin-bottom: var(--s-3); }
.doc code { font: 500 .95em var(--font); color: var(--ink); }
.doc strong { color: var(--ink); }

/* ── the footer: identical on every page ─────────────────────────────── */
.foot { border-top: 1px solid var(--rule); padding: var(--s-6) 0 var(--s-7); font-size: var(--fs-ui); }
.foot .wrap { display: grid; gap: var(--s-4); }
.foot-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-6); }
.foot-row .home img { height: 26px; }
.foot nav { display: flex; flex-wrap: wrap; gap: 0 var(--s-5); }
.foot nav a, .foot .mail { display: inline-flex; align-items: center; min-height: var(--target); color: var(--ink-2); text-decoration: none; }
/* .mail carries .du-link, which keeps a resting line anywhere (drafted.css),
   so unlike the footer links beside it (bare anchors in a nav, which the kit
   already rests without one) it is set here to the same state: no resting
   line, and the pen draws the ink one on hover and focus. The sizes are the
   kit's own two layers, ink then edge; a second drawn line here would double
   it. */
.foot .mail { background-size: 0% 1px, 0% 1px; }
.foot .mail:hover, .foot .mail:focus-visible { background-size: 100% 1px, 0% 1px; }
.foot nav a:hover { color: var(--ink); }
.foot .mail:hover { color: var(--ink); }
.foot .fine { color: var(--ink-3); }
@media (min-width: 900px) { .foot nav { margin-left: auto; } }

/* SIMPLIFIED: the kit writes a .du-rows row in with du-write (from opacity 0)
   when its observer fires at threshold .2 (drafted.js:67), but nothing hides
   an undrawn row first, so a row already on screen blinked off and back
   (measured 30 Sep 2026 on index, products and workmap at 390, blueprint and
   workmap at 1280). Pre-hiding undrawn rows removes the blink: zero blinks on
   all ten page and width pairs. Screen and full motion only: print must show
   every row, and under reduced motion the kit draws without animating, so
   there is no blink to remove. Ceiling: a list taller than five viewports
   never reaches the .2 threshold and would stay hidden; this site's longest
   is 872px. Upgrade: the kit fix (this pre-hide plus threshold 0 and
   rootMargin 0 0 -10% 0) in ZynoStack/brand, then delete this block on the
   next re-vendor. site.js marks rows drawn when the kit never loads. */
@media screen and (prefers-reduced-motion: no-preference) {
  .du-js .du-rows:not([data-pen]) > li > * { opacity: 0; }
  .du-js .du-rows:not([data-pen]) > li::after { transform: scaleX(0); }
}

/* Reduced motion and print for .rows, .ending and the Products list are the
   kit's own rules now (drafted.css: .du-rows, .du-outline and .du-menu all
   reach their drawn state at once under prefers-reduced-motion, and
   .du-pen/.du-after are forced drawn under print); nothing site-specific is
   left to repeat here. */

/* ── paper: tokens.css switches to the paper values; the dark logo files
   are drawn in near-white and would vanish, so the light ones take over ── */
@media print {
  .skip, .menu-btn, .menu-list, .nav > [data-wide], .notes, .ctas .du-btn--quiet { display: none !important; }
  .top .home img { content: url(drafted/logo/logo-light.svg); height: 26px; width: auto; }
  .foot .home img { content: url(drafted/logo/logo-light.svg); }
  .hero { grid-template-columns: minmax(0, 1fr); }
  .drawing text, .drawing .lead-line { display: inline; }
  .sec, .ending, .rows > li, .prices tr { break-inside: avoid; }
  a { text-decoration-color: currentColor; }
  /* SIMPLIFIED: a closed <details> renders no content, and the kit's print
     block (opacity:1 !important) cannot open what the browser never lays
     out; the FAQ printed its four questions with no answers. NOT upstream:
     the kit's print block (drafted.css:328-338) has no `::details-content`
     line at all; corrected 30 Sep 2026 round 2, a prior comment here claimed
     it did. Pending upstream, see README "Brand #5" pending kit fixes. */
  details.du-more::details-content { content-visibility: visible; }
}
