/* DwellDelta — dwelldelta.com.au
 *
 * SITE-010. Written out rather than minified onto one line: this stylesheet is
 * part of the review package, and a page whose whole argument is "you can check
 * this" should not ship a stylesheet nobody can read.
 *
 * No @import, no font CDN, no external URL of any kind. `tools/browser_smoke.mjs`
 * asserts "no external URLs" and that is a property worth keeping, not a
 * limitation to work around: this page loads and renders with the network off.
 */

:root {
  --ink: #13241f;
  --ink-soft: #40544c;
  --ink-faint: #6b7d75;
  --green: #145c48;
  --green-bright: #1c7d61;
  --mint: #d9f0e6;
  --cream: #f6f1e7;
  --paper: #fffdf8;
  --coral: #e86e50;
  --line: #d9d1c4;
  --line-soft: #e8e1d5;

  /* System stacks only. A webfont would mean a network request. */
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --serif: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  font-family: var(--sans);
  color: var(--ink);
  background: var(--cream);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  line-height: 1.6;
  background:
    radial-gradient(circle at 88% -6%, #dff1e9 0, transparent 38rem),
    radial-gradient(circle at 4% 42%, #f3ece0 0, transparent 30rem),
    var(--cream);
}

a { color: inherit; }
:focus-visible { outline: 3px solid var(--coral); outline-offset: 4px; border-radius: 2px; }

.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: 1rem; top: 1rem; z-index: 20;
  background: var(--paper); padding: .75rem 1rem;
  border: 2px solid var(--green); border-radius: .5rem; font-weight: 700;
}

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

header {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: clamp(1rem, 4vw, 3rem);
  /* SITE-032: the header bar stays full-bleed so its bottom border spans the
     window, but its CONTENTS line up with the 1120px column `main` is centred
     in. Without this the wordmark sat far left of where the headline begins and
     the nav far right of where the text ends - invisible on a laptop, obvious
     on a wide monitor, and reported by a reader looking at one.

     `max()` keeps the original padding on narrow screens, where the column is
     already the full width and the calc goes negative. The 1.25rem matches
     `main`'s own inline padding, so the wordmark aligns with the first letter
     of the text rather than with the column edge. */
  padding: .85rem max(clamp(1.25rem, 6vw, 6rem), calc((100% - 1120px) / 2 + 1.25rem));
  border-bottom: 1px solid var(--line);
  background: rgba(246, 241, 231, .88);
  /* Prefixed FIRST. WAR-051 in the app repo shipped the reverse order and the
     rule did nothing on Safari and every browser on iOS. */
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
/* SITE-033: the mark and word are the return-home anchor and were smaller than
   the nav links they sit beside. `.mark` is 1.35em so it scales with this. */
.brand { display: flex; align-items: center; gap: .55rem; text-decoration: none; font-size: 1.3rem; }
/* SITE-012: the mark is an image now, not a text triangle. Sized in em so it
   tracks the type it sits beside, and vertically centred by the flex parent
   rather than by a magic offset. */
.mark { width: 1.35em; height: 1.35em; display: inline-block; vertical-align: -0.25em; }
footer .mark { width: 1.05em; height: 1.05em; }
.word { letter-spacing: -.01em; font-weight: 500; }
.word b { font-weight: 800; }

/* SITE-025: `flex-wrap` on the BASE rule, not only in the 900px block below.
   The nav grew past six links and stopped fitting on one row between the 900px
   breakpoint and about 1150px - the band where neither the desktop layout nor
   the wrapping mobile one applies.

   The first version of this comment said the overflow gave the document a
   horizontal scrollbar. MEASURED, AND THAT WAS FALSE: `scrollWidth` equals
   `clientWidth` at every width, with this line and without it. What actually
   happened is that the links, being flex items, shrank instead - so each LABEL
   broke inside itself. Measured through the DevTools protocol at 901px with the
   rule removed: every link 79px tall, three lines of text each, in a 107px
   header; at 1000px and 1100px, 56px tall, two lines each. With the rule, every
   link stays 34px and the NAV wraps instead - whole links move to a second row
   rather than each label being shredded.

   Recorded this way because it is the more useful failure to know about. A
   horizontal scrollbar is loud. "What this / is / not" stacked three deep in a
   header is not, and it is what a reader would actually have seen. */
/* SITE-033: tighter so nine links clear the 900-1150px band on ONE row.
   SITE-025 added flex-wrap to the base rule because the nav outgrew that band;
   the wrap stays as the safety net, but the gap and size now make it
   unnecessary above 900px. Measured at 960/1160/1440/2560 - see the lane. */
header nav { display: flex; flex-wrap: wrap; gap: clamp(.55rem, 1.15vw, 1.35rem); margin-left: auto; }
header nav a {
  text-decoration: none; font-size: .83rem; font-weight: 600; color: var(--ink-soft);
  padding: .3rem 0; border-bottom: 2px solid transparent;
}
header nav a:hover { color: var(--green); border-bottom-color: var(--green); }

.stamp {
  display: flex; align-items: center; gap: .45rem; margin: 0;
  font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--green); white-space: nowrap;
}
.dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--green-bright); }

/* --- rhythm ------------------------------------------------------------- */

main { max-width: 1120px; margin: auto; padding: clamp(2.5rem, 6vw, 5.5rem) 1.25rem; }
section { margin-bottom: clamp(4rem, 9vw, 8rem); }
/* The header is sticky, so an anchor jump lands with the heading UNDER it.
   Measured: the nav is ~61px tall, and without this "Ten measures and six
   context layers" arrived half-hidden behind it. */
section[id] { scroll-margin-top: 5rem; }

.eyebrow {
  text-transform: uppercase; font-size: .72rem; letter-spacing: .14em;
  color: var(--green); font-weight: 800; margin: 0 0 .35rem;
}

h1 {
  font: clamp(3rem, 9vw, 7rem)/.9 var(--serif);
  max-width: 14ch; margin: .3rem 0 1.75rem; letter-spacing: -.045em;
}
h2 {
  font: clamp(2rem, 4.4vw, 3.6rem)/1.03 var(--serif);
  margin: .2rem 0 1.25rem; letter-spacing: -.03em; max-width: 20ch;
}
h3 { font-size: 1.02rem; margin: 0 0 .5rem; letter-spacing: -.01em; }

.lead { font-size: clamp(1.1rem, 1.7vw, 1.45rem); max-width: 62ch; color: var(--ink-soft); margin: 0; }
.section-lead { max-width: 62ch; color: var(--ink-soft); margin: 0 0 2rem; }
.note { color: var(--ink-faint); font-size: .9rem; max-width: 70ch; }

/* --- hero --------------------------------------------------------------- */

.hero { padding-bottom: clamp(1rem, 3vw, 3rem); }

.status {
  display: flex; flex-wrap: wrap; gap: .35rem 1.25rem; align-items: baseline;
  background: var(--mint); border-left: 6px solid var(--green);
  padding: 1.1rem 1.35rem; margin: 2.25rem 0 0; border-radius: 0 .6rem .6rem 0;
}
.status strong { font-size: 1.02rem; }
.status span { color: var(--ink-soft); max-width: 72ch; }
/* SITE-107: the one action on the first screen. It takes the full width of the
   box so it reads as the box's conclusion rather than as a word in the sentence,
   and it is underlined in the site's green rather than restyled as a button -
   a button on a page with no script is a promise of behaviour it cannot keep. */
.status a { flex-basis: 100%; font-weight: 700; color: var(--green); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .22em; }
.status a:hover { color: var(--ink); }

/* The delta tape. Fixed numbers in the markup, drawn with CSS - no script and
   nothing fetched. Labelled synthetic in the header AND in the caption, because
   a chart is the element most likely to be screenshotted away from its page. */
.tape {
  margin: 2.5rem 0 0; padding: 0;
  background: var(--paper); border: 1px solid var(--line); border-radius: .9rem;
  overflow: hidden;
}
.tape-head {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: .8rem 1.1rem; border-bottom: 1px solid var(--line-soft);
  font-size: .8rem; font-weight: 700; color: var(--ink-soft);
}
.tag {
  font-family: var(--mono); font-size: .62rem; letter-spacing: .1em; text-transform: uppercase;
  background: var(--ink); color: var(--paper); padding: .2rem .5rem; border-radius: .3rem;
}
.bars { list-style: none; margin: 0; padding: .8rem 1.1rem 1rem; display: grid; gap: .5rem; }
.bars li {
  display: grid; grid-template-columns: 8.5rem 1fr 4.5rem; align-items: center; gap: .75rem;
  font-size: .85rem;
}
/* Name, then bar, then value - in that reading order.
   The bar is a pseudo-element, which grid places FIRST among its siblings, so
   the columns are assigned explicitly. Left implicit, the bar landed in column
   one and every city name sat to the right of its own bar. */
.bars span { grid-column: 1; color: var(--ink-soft); }
.bars li::before {
  grid-column: 2;
  content: ""; height: .55rem; border-radius: .3rem;
  background: var(--mint); box-shadow: inset 0 0 0 1px rgba(20, 92, 72, .2);
}
.bars b { grid-column: 3; font-family: var(--mono); font-size: .82rem;
  font-variant-numeric: tabular-nums; text-align: right; }

.bars .w4::before { width: 40%; } .bars .w5::before { width: 50%; }
.bars .w6::before { width: 60%; } .bars .w7::before { width: 70%; }
.bars .w8::before { width: 80%; } .bars .w9::before { width: 90%; }

/* Direction is carried by COLOUR as well as by the sign. A rise and a fall of
   the same magnitude draw the same length of bar, so a reader skimming the
   column would otherwise have to check every sign to see which way it went. */
.bars li:has(.down)::before { background: #fbe3dc; box-shadow: inset 0 0 0 1px rgba(232, 110, 80, .35); }
.bars .up { color: var(--green-bright); }
.bars .down { color: var(--coral); }
.tape figcaption {
  padding: .85rem 1.1rem; border-top: 1px solid var(--line-soft);
  font-size: .78rem; color: var(--ink-faint); background: #fbf8f1;
}

/* --- board captures ----------------------------------------------------- */

.shot-hero h1 { max-width: 12ch; }
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--line); border-radius: .9rem;
  background: #0a0a0a;               /* the board is dark; match while it decodes */
  box-shadow: 0 18px 50px -28px rgba(19, 36, 31, .55);
}
.shot.narrow img { max-width: 38rem; }
.shot figcaption { margin-top: .85rem; font-size: .85rem; color: var(--ink-faint); max-width: 62ch; }
.section-lead code, .limits li code {
  font-family: var(--mono); font-size: .88em;
  background: rgba(20, 92, 72, .09); padding: .05rem .3rem; border-radius: .25rem;
}
.limits li code { background: rgba(255, 255, 255, .1); }

/* --- layers ------------------------------------------------------------- */

.layers { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: .6rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.layers li {
  display: grid; grid-template-columns: 1fr auto; gap: .2rem .75rem;
  /* `start`, not `center`: the cards in a row share a height, and centring made
     a one-line card's sub-label drift down to meet a two-line neighbour's. */
  align-items: start; align-content: start;
  background: var(--paper); border: 1px solid var(--line); border-radius: .7rem;
  padding: .85rem 1rem;
}
.layers b { grid-column: 1; font-size: .98rem; }
.layers span { grid-column: 1; font-size: .82rem; color: var(--ink-faint); }
/* Column TWO, stated. `grid-row: 1 / span 2` alone put the tag in the explicit
   placement pass, where it claimed column one and every label sat to the right
   of its own tag. Both axes are named so the browser has nothing to guess. */
.layers i {
  grid-column: 2; grid-row: 1 / span 2; align-self: start;
  font-style: normal; font-family: var(--mono);
  font-size: .6rem; letter-spacing: .09em; text-transform: uppercase; white-space: nowrap;
  color: var(--coral); border: 1px solid currentColor; border-radius: .3rem; padding: .15rem .4rem;
}
.layers i.real { color: var(--green); }
.layers i.none { color: var(--ink-faint); }

/* --- chain -------------------------------------------------------------- */

.chain {
  display: grid; grid-template-columns: repeat(4, 1fr); counter-reset: step;
  list-style: none; padding: 0; margin: 0 0 1.25rem;
  border: 1px solid var(--line); border-radius: .9rem; overflow: hidden; background: var(--paper);
}
.chain li { padding: 1.4rem 1.25rem; border-right: 1px solid var(--line-soft); display: grid; gap: .4rem; align-content: start; }
.chain li:last-child { border-right: 0; }
.chain li::before {
  counter-increment: step; content: counter(step);
  font-family: var(--mono); font-size: .68rem; font-weight: 700; color: var(--green);
  width: 1.35rem; height: 1.35rem; display: grid; place-items: center;
  border: 1px solid var(--green); border-radius: 50%;
}
.chain b { font-size: 1.02rem; }
.chain span { font-size: .86rem; color: var(--ink-soft); }

.receipt { font-size: .78rem; color: var(--ink-faint); max-width: 100%; }
.receipt code, .limits code { font-family: var(--mono); font-size: .95em; overflow-wrap: anywhere; }

/* --- methodology -------------------------------------------------------- */

.grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: clamp(1.5rem, 4vw, 4rem); align-items: start; }
.grid p { color: var(--ink-soft); max-width: 54ch; }
.grid dl { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; margin: 0; }
.grid dl div, .cards article {
  background: var(--paper); border: 1px solid var(--line); border-radius: .8rem; padding: 1.2rem;
}
.grid dt { font-weight: 700; font-size: .82rem; color: var(--ink-faint); }
.grid dd { margin: .4rem 0 0; font: 1.5rem/1.15 var(--serif); letter-spacing: -.02em; }

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

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: .8rem; }
.cards p { margin: 0; font-size: .88rem; color: var(--ink-soft); }
.cards .proven { border-top: 5px solid var(--green); background: #f7fffb; }
.cards article:not(.proven) { border-top: 5px solid var(--coral); }
.cards.cov article { border-top: 5px solid var(--green); background: var(--paper); }
.cards.cov article + article { border-top-color: var(--coral); }
.cards.cov article + article + article { border-top-color: var(--ink); }

/* --- limits ------------------------------------------------------------- */

.limits {
  background: var(--ink); color: var(--paper);
  padding: clamp(2rem, 5vw, 3.75rem); border-radius: 1.2rem;
}
.limits .eyebrow { color: #9ee0c9; }
.limits h2 { max-width: 18ch; }
.limits ul { margin: 0 0 1.5rem; padding-left: 1.1rem; max-width: 62ch; }
.limits li { margin: .55rem 0; }
.limits .receipt { color: #a9bcb4; }

/* --- footer ------------------------------------------------------------- */

footer {
  padding: 2.5rem 1.25rem; text-align: center;
  border-top: 1px solid var(--line); font-size: .85rem;
}
footer p { margin: .3rem 0; }
footer .fine { color: var(--ink-faint); font-size: .78rem; }

/* --- responsive --------------------------------------------------------- */

@media (max-width: 900px) {
  header nav { display: none; }
  .grid { grid-template-columns: 1fr; }
  .chain { grid-template-columns: 1fr 1fr; }
  .chain li:nth-child(2) { border-right: 0; }
  .chain li:nth-child(-n+2) { border-bottom: 1px solid var(--line-soft); }
}
@media (max-width: 560px) {
  .chain { grid-template-columns: 1fr; }
  .chain li { border-right: 0; border-bottom: 1px solid var(--line-soft); }
  .chain li:last-child { border-bottom: 0; }
  .grid dl { grid-template-columns: 1fr; }
  .bars li { grid-template-columns: 6.5rem 1fr auto; font-size: .8rem; }
  .stamp { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; transition-duration: 0s !important; animation-duration: 0s !important; }
}

/* ==========================================================================
   SITE-013 — the polish pass.
   Before: eight structurally identical blocks, uniform spacing, and the content
   using half the page width. Honest and legible, but it read as a list rather
   than a document. Everything below adds ARCHITECTURE without changing a word.
   ========================================================================== */

/* --- 1. numbered sections, from a counter ---------------------------------
   No markup change: the numbers come from the document order, so a section
   inserted or moved cannot end up mislabelled - which a hand-typed "03" would. */
main { counter-reset: section; }
main > section { counter-increment: section; }
main > section > .eyebrow::before,
main > section > div > .eyebrow::before {
  content: counter(section, decimal-leading-zero);
  margin-right: .7rem; opacity: .45; font-variant-numeric: tabular-nums;
}
.hero > .eyebrow::before { content: none; }

/* --- 2. a hairline above each section -------------------------------------
   The rule spans the full content width while the text below it does not, so
   the page gains a visible measure - the thing that was missing when every
   block floated in its own whitespace. */
main > section:not(.hero):not(.limits) { border-top: 1px solid var(--line); padding-top: clamp(2rem, 4vw, 3.2rem); }
main > section { margin-bottom: clamp(3rem, 6vw, 5rem); }

/* --- 3. the hero earns its space ------------------------------------------ */
.hero h1 { max-width: 16ch; margin-bottom: 1.4rem; }
/* 62ch, not 54. Narrowing it to 54 wrapped the hero lead onto seven cramped
   lines directly under a two-line headline - measured by rendering it, and it
   read as a column of text rather than an opening paragraph. */
.hero .lead { font-size: clamp(1.15rem, 1.5vw, 1.4rem); max-width: 62ch; }
.hero .status { max-width: 62rem; }

/* --- 4. the tape reads as an instrument, not a decoration -----------------
   Denser rows, a real track behind each bar, and a hairline between rows. The
   bars were pale fills on nothing, which is why the block looked washed out at
   full width. */
.bars { gap: 0; padding: .35rem 1.1rem .7rem; }
.bars li { padding: .3rem 0; border-bottom: 1px solid var(--line-soft); }
.bars li:last-child { border-bottom: 0; }
.bars li::before {
  height: .5rem; border-radius: .25rem;
  background: linear-gradient(to right, var(--green-bright) 0 100%);
  box-shadow: none; opacity: .85;
}
.bars li:has(.down)::before { background: var(--coral); opacity: .8; }
.bars span { color: var(--ink); font-weight: 500; }
.tape { max-width: 46rem; }

/* --- 5. one card treatment, everywhere ------------------------------------ */
.layers li, .cards article, .grid dl div, .chain li {
  transition: border-color .16s ease, transform .16s ease;
}
.layers li:hover, .cards article:hover { border-color: var(--green); transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) {
  .layers li, .cards article { transition: none; }
  .layers li:hover, .cards article:hover { transform: none; }
}

/* --- 6. the methodology split stops floating ------------------------------ */
.grid { align-items: stretch; }
.grid dl { align-content: start; }

/* --- 7. a footer with weight ---------------------------------------------- */
footer { padding: clamp(3rem, 6vw, 4.5rem) 1.25rem; background: var(--paper); }
footer p:first-of-type { font-size: 1rem; font-weight: 500; }

/* ==========================================================================
   SITE-022 — the site became more than one document.
   Four pages were added, which turned two existing rules from harmless into
   broken, and needed three affordances that did not exist. Everything below is
   additive; nothing above was edited.
   ========================================================================== */

/* --- 1. the nav had to stop disappearing ----------------------------------
   `header nav { display: none }` under 900px shipped in SITE-013 and was
   CORRECT at the time: every link was a same-page anchor, so hiding them on a
   phone cost a reader nothing they could not get by scrolling.

   The moment those links point at other pages, the same rule is a dead end -
   a phone reader reaches index.html and can go nowhere. It wraps to its own
   row instead. No script, no disclosure widget, no hamburger: six links fit on
   two rows at 360px, and a control that has to be opened is a control that can
   fail to open. */
@media (max-width: 900px) {
  /* SITE-108: the header stops being sticky on narrow screens. Two rows of
     eleven links is 139px - measured 16-18% of every phone screen, at every
     scroll position, on every page - and `position: sticky` was written for
     the one-row desktop bar. The links stay (SITE-022 §1 and the nav contract
     refuse every alternative); the nav is at the top and again in the footer.
     Padding and gaps are tightened while it is here; nothing above 900px
     changes, and the 901-1014px two-row band is SITE-110's. */
  header { flex-wrap: wrap; row-gap: .35rem; position: static; padding-top: .6rem; padding-bottom: .6rem; }
  header nav {
    display: flex; flex-wrap: wrap;
    order: 3; width: 100%; margin-left: 0;
    gap: .2rem .8rem;
  }
  header nav a { font-size: .8rem; }
}

/* Which page you are on, marked in the markup and not by a hand-set class -
   `aria-current="page"` is the accessible signal and the visual one from the
   same attribute, so they cannot drift apart. */
header nav a[aria-current="page"] { color: var(--green); border-bottom-color: var(--green); }

/* --- 2. the source ledger -------------------------------------------------
   `.layers` carries label / sub-label / tag and is right for a coverage row.
   A source needs five paired facts and a note, which is a different shape, so
   this is a card with a definition list rather than a table: a table of five
   columns on a 360px screen is a horizontal scroll, and a licence obligation
   is the last thing that should be off-screen. */
.srcs { display: grid; gap: .8rem; margin: 0 0 1.25rem; }
.src {
  background: var(--paper); border: 1px solid var(--line); border-radius: .8rem;
  padding: 1.2rem 1.35rem; border-top: 5px solid var(--green);
}
.src > p { color: var(--ink-soft); margin: 0 0 1rem; max-width: 66ch; }
.src .note { margin: 1rem 0 0; }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .75rem; margin: 0; }
.facts div { border-left: 2px solid var(--line-soft); padding-left: .7rem; }
.facts dt {
  font-size: .68rem; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-faint);
}
.facts dd {
  margin: .2rem 0 0; font-family: var(--mono); font-size: .95rem;
  font-variant-numeric: tabular-nums; color: var(--ink);
}

/* --- 3. quoting the record, marked as a quote -----------------------------
   Several of the strongest sentences on this site are lifted from the
   product's own JSON. They are set apart so a reader can tell what this site
   WROTE from what it is REPORTING - the distinction the whole page rests on. */
.quote {
  margin: 0 0 1.5rem; padding: 1.15rem 1.35rem;
  background: var(--paper); border-left: 6px solid var(--green-bright);
  border-radius: 0 .6rem .6rem 0;
}
.quote p { margin: 0; color: var(--ink-soft); max-width: 64ch; font-size: 1.02rem; }
.quote cite {
  display: block; margin-top: .7rem; font-style: normal;
  font-size: .75rem; color: var(--ink-faint);
}
.quote cite code { font-family: var(--mono); }
.limits .quote { background: rgba(255, 255, 255, .06); border-left-color: #9ee0c9; }
.limits .quote p { color: var(--paper); }
.limits .quote cite { color: #a9bcb4; }

/* --- 4. cards that are not a verdict --------------------------------------
   `.cards article:not(.proven)` is coral-topped, because on index.html every
   such card IS a caution. On a page where the cards are neutral description,
   inheriting that reads as four warnings. */
.cards.plain article { border-top-color: var(--ink-faint); }

/* --- 5. the footer carries navigation and attribution ---------------------
   The nav is repeated here deliberately. A reader who has reached the bottom
   of a page is exactly the reader who needs the next one, and repetition costs
   nothing on a static document.

   `.attrib` carries the CC BY strings the licences ask for. Whether this SITE
   owes them is genuinely unsettled - it redistributes neither dataset, it
   publishes screenshots of a board that renders them - and the asymmetry
   settles it: one line of footer against a licence breach. */
.foot-nav {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: .4rem 1.25rem; margin: 1.1rem auto 0; max-width: 46rem;
}
.foot-nav a {
  font-size: .82rem; font-weight: 600; color: var(--ink-soft); text-decoration: none;
  border-bottom: 1px solid transparent; padding-bottom: .1rem;
}
.foot-nav a:hover { color: var(--green); border-bottom-color: var(--green); }

footer .attrib {
  margin: 1.4rem auto .3rem; max-width: 60ch;
  font-size: .72rem; line-height: 1.55; color: var(--ink-faint);
}

/* --- 6. long identifiers must not widen the page --------------------------
   A sha256 is 64 characters and `.receipt code` already wraps anywhere. The
   `<dd>` in `.facts` and the tags in `.layers i` are the two places a long
   string could still push the layout wider than the viewport. */
.facts dd, .src h3 { overflow-wrap: anywhere; }
@media (max-width: 560px) {
  .layers i { white-space: normal; }
  .facts { grid-template-columns: 1fr 1fr; }
}

/* ==========================================================================
   SITE-024 — the detail plate.

   The page's only figure was the delta tape, whose caption says every value in
   it is invented. This is its opposite: 496 surveyed lot rings and 98 road
   centrelines from the NSW cadastre, drawn as inline SVG by tools/plate_tool.py.
   Everything below is additive; nothing above was edited.
   ========================================================================== */

/* --- 1. the plate is an instrument, not a card ----------------------------
   `border-radius: 0` is WRITTEN OUT rather than left to the default, because on
   this stylesheet the default reading is "somebody forgot". Every other
   container here is rounded: .tape .9rem, .layers li .7rem, .cards article
   .8rem, .limits 1.2rem.

   The board this product actually renders is square by design - dwelldelta-app
   records `--wr-surface: #141414` and `--wr-border: #2a2a2a`, taken from World
   Monitor, with no radius and no blur on the map surface. This plate inverts
   that surface onto paper and keeps the discipline. Same reason there is no
   shadow and no gradient anywhere in it: a survey drawing that has been styled
   is a survey drawing somebody can no longer check. */
.plate {
  margin: 2.25rem 0 0; padding: 0; max-width: 62rem;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 0;
  overflow: hidden;
}
.plate-head {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: .8rem 1.1rem; border-bottom: 1px solid var(--line-soft);
  font-size: .8rem; font-weight: 700; color: var(--ink-soft);
}
/* The tape's tag is ink and says Synthetic; this one is green and says
   Measured. Same component, same position, opposite verdict - which is the
   whole point of the two figures being adjacent. */
.tag.real { background: var(--green); }

/* --- 2. hairlines that stay hairlines -------------------------------------
   `non-scaling-stroke` holds every boundary at 1 CSS pixel at any width. The
   alternative - letting strokes scale - fades the survey out on a phone, which
   is the device where it is already hardest to read.

   Colour is carried by ONE accent. Green is not the link colour on this site
   (`a { color: inherit }`, above), and it already means "measured" on this page
   via `.layers i.real`, so the surveyed centrelines and the Measured tag are the
   same encoding used twice rather than two meanings for one hue. */
.plate-svg { display: block; width: 100%; height: auto; }
.plate-ground { fill: #f2ece0; }
.plate-lots { fill: var(--paper); stroke: #c9bfae; stroke-width: 1; }
.plate-roads { fill: none; stroke: var(--green); stroke-width: 1.5; }
.plate-rule { fill: none; stroke: var(--ink); stroke-width: 1.5; }
.plate-frame { fill: none; stroke: var(--line); stroke-width: 1; }
/* SITE-109: the drawing's specification folds. The marker stays - it is the
   affordance - and the summary takes the site's green so it reads as a control
   on a page that has no buttons. */
.plate-how { margin: .6rem 0 0; }
.plate-how summary { cursor: pointer; font-size: .82rem; font-weight: 700; color: var(--green); }
.plate-how summary:hover { text-decoration: underline; }
.plate-how > p { margin: .5rem 0 0; }
.plate-lots, .plate-roads, .plate-rule, .plate-frame {
  vector-effect: non-scaling-stroke; stroke-linejoin: miter; stroke-linecap: butt;
}

/* Measured, not assumed: the plate was rendered at 360, 560 and 1072px with
   1px strokes before this rule existed. The parcels hold at 360px; the accent
   does not, because a 1.5px centreline over a 360px plate is three times the
   relative weight it carries at 1072px and starts to swamp the lots it is
   supposed to sit between. One rule, one reason. */
@media (max-width: 560px) { .plate-roads { stroke-width: 1.2; } }

/* --- 3. three registers in one caption ------------------------------------
   A caption carrying what-it-is, which postcode, how much of the file is drawn,
   the extent, the scale rule, the tolerance and the no-observation statement is
   a specification, and nobody finishes a specification. Sentences first, the
   machine-shaped numbers under them in mono, the licence line last. A reader who
   stops after the first paragraph has everything they need. */
.plate figcaption {
  padding: .9rem 1.1rem 1rem; border-top: 1px solid var(--line-soft);
  background: #fbf8f1;
}
.plate figcaption p { margin: 0 0 .65rem; font-size: .82rem; color: var(--ink-soft); max-width: 74ch; }
.plate figcaption .plate-meta {
  font-family: var(--mono); font-size: .72rem; line-height: 1.5;
  color: var(--ink-faint); max-width: 78ch;
}
/* The attribution the licence asks for, beside the work rather than only in the
   footer. This page no longer publishes a screenshot of a product that renders
   the dataset - it publishes an adaptation of the dataset's own coordinates - so
   the credit is owed here plainly rather than carried in case. */
.plate figcaption .attrib { margin: 0; font-size: .72rem; color: var(--ink-faint); max-width: 74ch; }

/* ==========================================================================
   SITE-042 — the first insight page.

   The site's ninth and tenth documents are a series index and a dated post, and
   they carry three shapes no existing page needed: a pull-quote built around
   one large number, a small comparison table, and a figure holding two crops of
   the same capture.

   The source artifact carried all of this in a `<style>` element. It could not
   come with it: the published policy is `style-src 'self'` with no
   `'unsafe-inline'`, so that element is BLOCKED in a browser - the page would
   have rendered unstyled at the domain while looking correct on disk, which no
   string guard in this repository would have caught. Recorded in
   03-debate.md R4.

   Everything below is additive; nothing above was edited. Components that
   already existed are reused rather than re-declared: `.shot` for the capture,
   `.tag` and `.tag.real` for synthetic against observed, `.limits`, `.eyebrow`,
   `.lead`, `.note`, `.receipt` and `.status` unchanged.
   ========================================================================== */

/* --- 1. body copy, which this site had never needed -----------------------
   Every page before this one was built from components - `.layers`, `.cards`,
   `.chain`, `.facts` - and its only running prose was `.section-lead` and
   `.note`. An analysis is prose first. Without a measure, paragraphs run the
   full 1120px of `main` and stop being readable at about 90 characters. */
.body-copy { max-width: 62ch; margin: 0 0 1.15rem; color: var(--ink-soft); }
.body-copy strong { color: var(--ink); font-weight: 700; }
.body-copy:last-child { margin-bottom: 0; }

.dateline {
  margin: 1.1rem 0 0; font-family: var(--mono); font-size: .72rem;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint);
}
.dateline a { color: var(--green); }

/* Tabular figures wherever a number is meant to be read as a number rather
   than as a word. `font-variant-numeric` keeps the digits in columns in the
   table, where four prices are compared down a column. */
.n {
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: .94em;
}

/* --- 2. the quotient nobody published -------------------------------------
   The page's whole argument is one division, and the sentence that qualifies it
   ("both inputs are published weekly, the quotient is not") has to sit beside
   the number rather than under a fold. `.quote` was the near-miss component:
   it sets a sentence apart as something REPORTED, and this figure is the
   opposite - it is the one number here that nobody else printed. */
.pull {
  margin: 2rem 0 0; padding: 1.35rem 1.5rem; max-width: 44rem;
  background: var(--paper); border: 1px solid var(--line);
  border-left: 6px solid var(--green); border-radius: 0 .6rem .6rem 0;
}
.pull .figure {
  display: block; font-family: var(--mono); font-weight: 700;
  font-size: clamp(1.75rem, 4.6vw, 2.4rem); line-height: 1.1;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; color: var(--green);
}
.pull .under { display: block; margin-top: .5rem; font-size: .9rem; color: var(--ink-soft); }

/* --- 3. a table, and the scroll container it needs ------------------------
   Four rows and three columns is below the width where `.srcs`' card-and-list
   treatment earns itself, and a comparison down a column is what the section
   is for. `.wrap` scrolls the table rather than the document: SITE-022 records
   why a five-column table at 360px was refused, and the answer there was to
   stop using a table. Three columns fits; the wrapper is the safety net. */
.wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: .6rem; max-width: 44rem; }
.stats { border-collapse: collapse; width: 100%; min-width: 27rem; font-size: .88rem; }
.stats caption {
  text-align: left; padding: .7rem .9rem;
  font-family: var(--mono); font-size: .66rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-faint); background: var(--cream); border-bottom: 1px solid var(--line);
}
.stats th, .stats td { padding: .55rem .9rem; text-align: left; border-bottom: 1px solid var(--line-soft); }
.stats th {
  font-family: var(--mono); font-size: .66rem; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint);
}
.stats th:not(:first-child), .stats td:not(:first-child) { text-align: right; }
.stats td:not(:first-child) { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.stats tbody tr:last-child td { border-bottom: 0; }
/* The row every other row is measured against, marked as such. */
.stats tbody tr:first-child td { background: var(--mint); }

/* --- 4. two crops of one capture ------------------------------------------
   Not the whole 3200x2000 dashboard: it is legible at source and illegible in a
   column, and every claim it evidences disappears at that scale. The banner
   states the provenance; the card shows it. `.shot` already gives both the
   border, the dark decode ground and the caption; these add the two widths and
   the caption's two-claim structure. */
.insight-board { display: flex; flex-direction: column; gap: .9rem; }
.insight-board .card { max-width: 21.25rem; margin-inline: auto; }
.insight-board figcaption { display: flex; flex-direction: column; gap: .7rem; max-width: 66ch; }
.insight-board .claim strong { color: var(--ink-soft); }
/* The tag sits inline with the sentence it labels, so it needs the baseline
   nudge the `.tape-head` version never did - there it is a flex item. */
.insight-board .tag { margin-right: .4rem; vertical-align: .07em; }

/* --- 5. sources as plain text, because a scheme is forbidden --------------
   `tests/site.test.js` forbids `https://` and `http://` on every page here, and
   that rule is what makes "this page renders with the network off" true rather
   than aspirational. Every licence URL on this site is already written this
   way. `code` because a path a reader has to retype should look like one. */
.srcs-plain { list-style: none; margin: 0 0 1.25rem; padding: 0; display: grid; gap: .85rem; max-width: 70ch; }
.srcs-plain li { font-size: .88rem; color: var(--ink-soft); }
.srcs-plain b { color: var(--ink); }
.srcs-plain code {
  display: inline-block; margin-top: .15rem;
  font-family: var(--mono); font-size: .78rem; color: var(--ink-faint);
  overflow-wrap: anywhere;
}

/* --- 6. the index, which is one entry long today --------------------------
   No card, no grid, no "featured" treatment. A list of one dressed as a
   magazine front page claims a back catalogue that does not exist. */
.posts { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.5rem; }
.posts li {
  background: var(--paper); border: 1px solid var(--line); border-radius: .8rem;
  border-top: 5px solid var(--green); padding: 1.35rem 1.5rem; max-width: 46rem;
}
.posts h3 { margin: .35rem 0 .6rem; font-size: 1.25rem; letter-spacing: -.015em; }
.posts h3 a { color: var(--ink); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.posts h3 a:hover { color: var(--green); }
.posts p { margin: 0; color: var(--ink-soft); font-size: .92rem; max-width: 58ch; }
.post-date {
  font-family: var(--mono); font-size: .68rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-faint);
}

/* SITE-134. The plain service site: four pages, one real chart, no script.
   Every colour comes from the variables above; selectors are scoped so the
   older .grid and .cards rules cannot reach into these components. */
header nav a.cta { background: var(--green); color: var(--paper); padding: 6px 14px; border-radius: 999px; text-decoration: none; }
header nav a.cta[aria-current="page"] { background: var(--green-bright); }
main .hero.hero-split { display: grid; grid-template-columns: 1.1fr 1fr; gap: 40px; align-items: center; }
main .actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; }
main a.button { display: inline-block; padding: 11px 20px; border-radius: 999px; background: var(--green); color: var(--paper); font-weight: 600; text-decoration: none; }
main a.button.ghost { background: transparent; color: var(--green); border: 1.5px solid var(--green); }
main a.button.light { background: var(--paper); color: var(--green); }
main a.button:focus-visible, header nav a:focus-visible { outline: 3px solid var(--coral); outline-offset: 2px; }
main section.band { padding-block: 44px; border-top: 1px solid var(--line-soft); }
main section.band h2 { margin-top: 4px; }
main .cards.three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin-block: 22px; }
main .cards.three .card { background: var(--paper); border: 1px solid var(--line); border-radius: 12px; padding: 20px; display: grid; gap: 10px; align-content: start; }
main .card h3 { margin: 0; }
main .for { color: var(--ink-faint); font-size: .9rem; }
main ol.steps { list-style: none; counter-reset: step; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
main ol.steps li { counter-increment: step; }
main ol.steps li::before { content: counter(step); display: block; font-family: var(--serif); font-size: 2.2rem; color: var(--coral); line-height: 1; margin-bottom: 6px; }
main ol.steps h3 { margin: 0 0 6px; }
main ul.ticks { padding-left: 20px; display: grid; gap: 6px; }
main section.contact-band { background: var(--green); color: var(--paper); border-radius: 16px; padding: 32px; margin-block: 30px; border-top: 0; }
main section.contact-band h2, main section.contact-band p { color: var(--paper); }
main figure.chart { margin: 0; background: var(--paper); border: 1px solid var(--line); border-radius: 14px; padding: 16px 18px; display: grid; gap: 10px; }
main figure.chart .chart-title { font-weight: 700; }
main figure.chart svg { width: 100%; height: auto; display: block; }
main figure.chart svg line.grid { stroke: var(--line-soft); stroke-width: 1; }
main figure.chart svg text.tick { fill: var(--ink-faint); font: 11px var(--mono); }
main figure.chart svg polyline.oo { stroke: var(--green); stroke-width: 2.6; }
main figure.chart svg polyline.inv { stroke: var(--coral); stroke-width: 2.6; }
main figure.chart svg circle.oo-end { fill: var(--green); }
main figure.chart svg circle.inv-end { fill: var(--coral); }
main figure.chart .legend { margin: 0; font-size: .88rem; color: var(--ink-soft); display: flex; gap: 16px; flex-wrap: wrap; }
main figure.chart .key::before { content: ""; display: inline-block; width: 16px; border-top: 3px solid var(--green); vertical-align: middle; margin-right: 6px; }
main figure.chart .key.inv::before { border-top-color: var(--coral); }
main figure.chart .chart-read { margin: 0; border-top: 1px solid var(--line-soft); padding-top: 8px; }
main figure.chart .chart-data table, main .table-wrap table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
main figure.chart .chart-data th, main figure.chart .chart-data td, main .table-wrap th, main .table-wrap td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
main figure.chart .source { margin: 0; font-size: .78rem; color: var(--ink-faint); }
main .table-wrap { overflow-x: auto; background: var(--paper); border: 1px solid var(--line); border-radius: 12px; }
/* The site-wide section numbering (01, 02...) marks a long argument; four short
   service pages are not one, so the numbers mean nothing here. */
main > section > .eyebrow::before, main > section > div > .eyebrow::before { content: none; }
/* The hero headline was sized for a full-width opening; beside the chart it
   wrapped a word per line (seen in the first render of this page). */
main .hero.hero-split h1 { font-size: clamp(2.1rem, 4vw, 3.3rem); line-height: 1.08; max-width: 20ch; }
main section.contact-band h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); }
@media (max-width: 820px) {
  main .hero.hero-split, main .cards.three, main ol.steps { grid-template-columns: 1fr; }
}
