/* baseline.css 1.9.1: the shared stylesheet of the project sites (the Atrium direction).
   Newsreader for text and headings, Public Sans for labels and navigation, JetBrains Mono for code,
   Dancing Script for the signature; the fonts are declared in fonts.css.
   Scale: perfect fourth (1.333) on a 1.1875rem base. No rules except the table header hairline.
   Colour comes only from the tokens in palettes.css, the family tokens and the component tokens below; the site
   class on <html> is the only per-site switch. From 1.9.1 the family and component tokens are declared inside
   :where(), with no specificity, so that a site's own site-palette.css (loaded before this file) overrides any
   of them; tools/check_palette.py checks every override. Specification: docs/site-template-spec.md in jposluns/posluns_site. */

/* Family signature tokens (the link-preview cards): gold and silver, checked at 4.5:1 or better on every site background in each mode;
   the 3 ordering colours for aiqt are the text-safe accents of the green, orange and red sites from palettes.css. */
:where(:root) { --gold-rule: #d4a52a; --gold: #8a6a0a; --silver: #6a6a6a; --ord-progress: #3b752e; --ord-speed: #a25100; --ord-cost: #bc3732; }
/* Print tokens (from 1.7.0): paper and ink for matrix tables on paper, the same in both schemes (the print rules at the end). */
:root { --print-paper: #ffffff; --print-ink: #000000; }
/* Layout tokens: the page gutter, the hero logo column, the rail column, the label column of the document and
   region grids, and the footer's band, tile, logo and mark sizes. */
:root { --pad: clamp(1rem, 3vw, 3.2rem); --art: clamp(11rem, 22vw, 30rem); --railw: clamp(13rem, 13vw, 17rem); --label-col: 9rem; --band: 0.4rem; --tile: 2.75rem; --tile-logo: 1.9rem; --mark: 1.5rem; }
@media (prefers-color-scheme: dark) { :where(:root:not([data-scheme="light"])) { --gold: #e6c15a; --silver: #cfcfcf; --ord-progress: #6faa62; --ord-speed: #e1791b; --ord-cost: #ef675c; } }
:where(:root[data-scheme="dark"]) { --gold: #e6c15a; --silver: #cfcfcf; --ord-progress: #6faa62; --ord-speed: #e1791b; --ord-cost: #ef675c; }
/* Component tokens (from 1.9.1): the colours of the controls a site most often wants to restyle, each defaulting
   to a palette token, so the template's look is unchanged unless a site overrides one in its site-palette.css
   (light and dark forms, as for palette tokens). check_palette.py resolves them and checks each pair it lists.
   Chips (facet, preset and toggle chips), from 1.9.1: an available chip reads in --text with a --text-muted border.
   An unavailable chip is greyed out so the eye skips it: its word is struck through (the count is not), and in
   light mode it sits on a --rule fill with --text-muted text and no visible border; in dark mode it keeps no
   fill, --text-muted text and a dashed --rule-strong border. An inactive control is exempt from the 4.5:1 text
   rule; the gate holds the unavailable text at 3:1 on its fill. */
:where(:root) {
  --chip-fg: var(--text); --chip-border: var(--text-muted); --chip-hover-fg: var(--text); --chip-hover-border: var(--text);
  --chip-pressed-fg: var(--accent); --chip-pressed-border: var(--accent);
  --chip-unavailable-fg: var(--text-muted); --chip-unavailable-bg: var(--rule); --chip-unavailable-border: var(--rule);
  --button-fg: var(--text-muted); --button-border: var(--rule-strong); --button-hover-fg: var(--text); --button-hover-border: var(--text);
  --nav-fg: var(--text-muted); --nav-hover-fg: var(--text); --nav-current-fg: var(--accent);
  --rail-fg: var(--text-muted); --rail-hover-fg: var(--text); --rail-current-fg: var(--accent);
  --picker-fg: var(--text-muted); --picker-hover-fg: var(--text); --picker-current-fg: var(--accent); --picker-current-rule: var(--brand);
  --input-fg: var(--text); --input-bg: var(--surface-raised); --input-border: var(--rule-strong); --input-placeholder: var(--text-muted);
  --tag-fg: var(--text-muted); --tag-border: var(--rule-strong); --tag-accent-fg: var(--accent); --tag-accent-border: var(--brand);
  --th-fg: var(--text-muted); --th-rule: var(--rule-strong);
  --band-tint-bg: var(--surface-sunken);
  --pair-before-bg: var(--surface-sunken); --pair-before-bg-on-tint: var(--bg); --pair-after-bg: var(--surface-raised); --pair-panel-bg: var(--code-bg);
  --box-bg: var(--surface-raised); --box-border: var(--rule);
  --band-dark-bg: var(--text); --band-dark-fg: var(--bg); --band-dark-heading: var(--glow); --band-dark-link: var(--glow); --band-dark-focus: var(--bg);
}
@media (prefers-color-scheme: dark) { :where(:root:not([data-scheme="light"])) { --chip-unavailable-bg: var(--bg); --chip-unavailable-border: var(--rule-strong); } }
/* From 1.11.0, the dark band in dark mode: a well below the page in --surface-sunken, with the page's own text colours. */
@media (prefers-color-scheme: dark) { :where(:root:not([data-scheme="light"])) { --band-dark-bg: var(--surface-sunken); --band-dark-fg: var(--text); --band-dark-heading: var(--accent); --band-dark-link: var(--link); --band-dark-focus: var(--focus); } }
:where(:root[data-scheme="dark"]) { --band-dark-bg: var(--surface-sunken); --band-dark-fg: var(--text); --band-dark-heading: var(--accent); --band-dark-link: var(--link); --band-dark-focus: var(--focus); }
:where(:root[data-scheme="dark"]) { --chip-unavailable-bg: var(--bg); --chip-unavailable-border: var(--rule-strong); }
*, *::before, *::after { box-sizing: border-box; }
/* Hidden means hidden, whatever display a component gives the element: `.doc section` and `.doc article` are
   `display: contents`, which overrode the browser's own [hidden] rule and kept every section the install
   selector hid on screen (1.0.0 to 1.5.0). The older per-component [hidden] rules below are kept. */
[hidden] { display: none !important; }
:root { color-scheme: light dark; }
/* A forced scheme (the switch in the top bar, scheme.js) also sets the browser's own colours: scrollbars and form controls. */
:root[data-scheme="light"] { color-scheme: light; }
:root[data-scheme="dark"] { color-scheme: dark; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 1.25rem/1.6 "Newsreader", Georgia, "Times New Roman", serif;
  font-variant-numeric: oldstyle-nums proportional-nums;
  font-feature-settings: "kern", "liga";
  text-rendering: optimizeLegibility;
}
::selection { background: var(--selection); color: var(--text); }

/* Links */
a { color: var(--link); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.18em; text-decoration-color: var(--rule-strong); }
a:hover { color: var(--link-hover); text-decoration-color: currentColor; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 2px; }
.vh { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Skip link */
.skip { position: absolute; left: 1rem; top: -4rem; z-index: 50; background: var(--surface-raised); color: var(--text); padding: 0.6rem 1rem; border-radius: 0.3rem; font: 500 0.78rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.14em; text-transform: uppercase; text-decoration: none; }
.skip:focus { top: 1rem; }

/* The label voice of the direction: tracked uppercase Public Sans */
.lbl, .label {
  font: 500 0.72rem/1.4 "Public Sans", system-ui, sans-serif;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 0.6rem;
  font-variant-numeric: lining-nums tabular-nums;
}
.lbl.accent, .label.accent { color: var(--accent); }
.lbl.file { text-transform: none; letter-spacing: 0.06em; font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 0.74rem; }
.lbl .n { font-family: "JetBrains Mono", ui-monospace, monospace; letter-spacing: 0.08em; }
.lbl a { color: inherit; text-decoration: none; }
.lbl a:hover { color: var(--text); }

/* Page container: the widest of the 3 directions */
.wrap { margin: 0; padding: 0 var(--pad); }

/* Masthead: no rule under it; the entrance field below gives it its edge. 2 columns: the wordmark and the site's
   page links on 1 row, right-aligned, GitHub last where the site has a public repository. Nothing wraps: when the
   row cannot hold the links it scrolls sideways, and a shadow at the scrolled edge (background-attachment: local,
   no script) shows that more links follow. Disclosure and Licence are not in the bar; the landing page's
   "About this project" line links them. The bar is positioned so that the visually hidden "(opens in a new tab)"
   span of the GitHub link is clipped inside the scrolling row instead of widening the page. From 1.6.0 a 3rd
   column holds the light and dark switch (button.scheme, scheme.js) after the links, outside the scrolling row,
   so it never scrolls away. The gap after the wordmark is its margin, not a column gap, so that the 3rd column
   takes no space when the switch is absent or hidden (no script, or a page on 1.5.1 markup). */
.mast { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "brand pages scheme"; align-items: center; column-gap: 0; padding: 1rem var(--pad) 0.9rem; }
/* The wordmark, in the style of the link-preview cards: bold name, gold .ai, gold rule beneath */
.brand { grid-area: brand; margin-right: clamp(1.2rem, 2.5vw, 2.5rem); display: inline-grid; gap: 0.3rem; color: var(--text); text-decoration: none; font: 700 clamp(1.6rem, 1.9vw, 2.2rem)/1 "Public Sans", system-ui, sans-serif; letter-spacing: -0.015em; padding: 0.35rem 0 0.1rem; white-space: nowrap; }
.brand .tld { color: var(--gold); }
.brand .rule { display: block; height: 3px; background: var(--gold-rule); border-radius: 2px; }
.brand:hover .name { color: var(--text); }
.nav { grid-area: pages; position: relative; display: flex; flex-wrap: nowrap; justify-content: flex-end; gap: 0 clamp(1rem, 1.6vw, 2rem); overflow-x: auto; scrollbar-width: thin; min-width: 0; font: 500 clamp(0.66rem, 0.45vw + 0.36rem, 0.74rem)/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.16em; text-transform: uppercase;
  background: linear-gradient(90deg, var(--bg) 40%, transparent) left / 2.4rem 100% no-repeat local, linear-gradient(270deg, var(--bg) 40%, transparent) right / 2.4rem 100% no-repeat local,
    linear-gradient(90deg, color-mix(in srgb, var(--rule-strong) 55%, transparent), transparent) left / 0.9rem 100% no-repeat scroll, linear-gradient(270deg, color-mix(in srgb, var(--rule-strong) 55%, transparent), transparent) right / 0.9rem 100% no-repeat scroll; }
.nav a { color: var(--nav-fg); text-decoration: none; padding: 0.7rem 0; display: inline-block; white-space: nowrap; }
.nav a:hover { color: var(--nav-hover-fg); }
.nav a[aria-current="page"] { color: var(--nav-current-fg); }
/* The light and dark switch: a 24 px sun or moon glyph (inline SVG in the markup) in a 44 by 44 px target,
   --text-muted at rest and --text on hover, the standard focus ring. The glyph shows the scheme a press leads to:
   the moon while light shows, the sun while dark shows; aria-pressed carries the state. The negative right margin
   lines the glyph up with the gutter while the target reaches into it; the negative block margins keep the bar at
   its 1.5.1 height. */
.scheme { grid-area: scheme; position: relative; display: inline-grid; place-items: center; width: 2.75rem; height: 2.75rem; margin: -0.25rem -0.625rem -0.25rem 0.6rem; padding: 0; border: 0; border-radius: 0.3rem; background: transparent; color: var(--nav-fg); cursor: pointer; }
.scheme:hover { color: var(--nav-hover-fg); }
.scheme svg { display: block; width: 1.5rem; height: 1.5rem; }
.scheme .sun { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-scheme="light"]) .scheme .sun { display: block; }
  :root:not([data-scheme="light"]) .scheme .moon { display: none; }
}
[data-scheme="dark"] .scheme .sun { display: block; }
[data-scheme="dark"] .scheme .moon { display: none; }

/* Hero: 1 section. The logo sits beside the title block, over a soft glow, at a size that supports the heading. */
.hero { display: grid; grid-template-columns: minmax(0, 1fr) var(--art); grid-template-areas: "text art"; column-gap: clamp(2.5rem, 5vw, 6rem); align-items: center; padding: 1.2rem max(0px, calc(var(--art) * 0.5 - var(--pad))) 2.4rem 0; }
.hero-text { grid-area: text; container-type: inline-size; min-width: 0; }
.hero .lbl { grid-area: kicker; margin-bottom: 0.4rem; }
.hero .lbl.gold { color: var(--gold); }
.hero-art { grid-area: art; align-self: center; justify-self: end; width: 100%; aspect-ratio: 1; display: grid; place-items: center; background: radial-gradient(closest-side, var(--glow) 0%, var(--glow) 38%, transparent 100%); animation: field-in 400ms ease-out both; }
.hero-art img { width: 84%; height: auto; display: block; }
@keyframes field-in { from { opacity: 0; } to { opacity: 1; } }
/* The statement sits on 1 line whenever it fits the text column at 2.6rem or more (--sw is the statement's
   1-line width in em, measured per site and scheme); the size scales between the floor and 5rem to achieve that. Below
   the floor it breaks once, at the meaningful point: the emphasized part never splits, so a 1-sentence statement breaks
   before it and a 2-sentence statement breaks between the sentences. README: re-measure --sw when a statement changes (tools/measure.js). */
.statement { grid-area: title; font-weight: 300; font-size: clamp(2.6rem, 98cqw / var(--sw), 5rem); line-height: 1.06; letter-spacing: -0.015em; margin: 0 0 1rem; --sw: 20; }
.statement em { font-style: italic; font-weight: 300; color: var(--accent); white-space: nowrap; }
.site-secureconfig .statement { --sw: 13.712; } .site-opfiles .statement { --sw: 15.070; } .site-auditthis .statement { --sw: 12.562; }
.site-cleanlanguage .statement { --sw: 12.824; } .site-aiqt .statement { --sw: 19.868; } .site-grclibrary .statement { --sw: 13.069; }
/* The dark widths apply in system dark mode (sites never set data-scheme) and under a forced dark scheme. */
@media (prefers-color-scheme: dark) {
  .site-secureconfig:not([data-scheme="light"]) .statement { --sw: 14.612; } .site-opfiles:not([data-scheme="light"]) .statement { --sw: 16.070; } .site-auditthis:not([data-scheme="light"]) .statement { --sw: 13.337; }
  .site-cleanlanguage:not([data-scheme="light"]) .statement { --sw: 13.724; } .site-aiqt:not([data-scheme="light"]) .statement { --sw: 21.218; } .site-grclibrary:not([data-scheme="light"]) .statement { --sw: 13.894; }
}
.site-secureconfig[data-scheme="dark"] .statement { --sw: 14.612; } .site-opfiles[data-scheme="dark"] .statement { --sw: 16.070; } .site-auditthis[data-scheme="dark"] .statement { --sw: 13.337; }
.site-cleanlanguage[data-scheme="dark"] .statement { --sw: 13.724; } .site-aiqt[data-scheme="dark"] .statement { --sw: 21.218; } .site-grclibrary[data-scheme="dark"] .statement { --sw: 13.894; }
.hero .intro { grid-area: intro; font-size: clamp(1.35rem, 1.35vw, 1.8rem); line-height: 1.5; max-width: 68ch; margin: 0 0 1.4rem; }
.hero .intro .ordering { font-size: 1.2rem; margin: 0.6rem 0 0; }
.lead { font-size: 1.333rem; line-height: 1.5; max-width: var(--measure-lead, 52ch); margin: 0 0 2rem; }
.start { grid-area: start; justify-self: start; display: inline-flex; align-items: baseline; gap: 1rem; font: 500 0.78rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text); text-decoration: none; border-bottom: 2px solid var(--brand); padding: 0.4rem 0 0.55rem; }
.start:hover { color: var(--text); }
.start .arrow { font-family: "Newsreader", serif; font-size: 1.2rem; color: var(--accent); transition: transform 150ms ease-out; display: inline-block; }
.start:hover .arrow { transform: translateX(0.25rem); }

/* Labelled regions: the label column at the left, content at the right.
   Used by the site plan, the family footer, the scope paragraph and every stand-alone block. */
.region { display: grid; grid-template-columns: var(--label-col) minmax(0, 1fr); gap: 0.4rem 2.5rem; padding: 0 0 2.6rem; align-items: start; }
.region > .lbl { padding-top: 0.5rem; }
.region.narrow > div { max-width: 72ch; }
.region p { margin: 0 0 1.1rem; }
.region p:last-child { margin-bottom: 0; }

/* Index lists: 2 columns, serif title, mono count or type at the right, no rules */
.plan { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 3rem; }
.plan.three { columns: 3; column-gap: 2.5rem; }
.plan li { break-inside: avoid; padding: 0.3rem 0; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1rem; align-items: baseline; }
.plan li a { text-decoration: none; color: var(--text); }
.plan li a:hover { color: var(--link-hover); }
.plan li .n, .plan li .t { font: 400 0.82rem/1.8 "JetBrains Mono", ui-monospace, monospace; color: var(--text-muted); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap; }
.plan.one { columns: 1; }
.plan li small { display: block; font: 400 1rem/1.45 "Public Sans", system-ui, sans-serif; color: var(--text-muted); grid-column: 1 / -1; margin-top: 0; }
.plan.described li { padding: 0.35rem 0 1.15rem; row-gap: 0.05rem; }
.plan.described li a, .plan.described li .n { line-height: 1.35; }

/* Document page: label column, text column, contents rail */
.doc { display: grid; grid-template-columns: var(--label-col) minmax(0, 1fr) var(--railw); gap: 0 clamp(2rem, 3vw, 4rem); padding: 0.6rem 0 2rem; align-items: start; }
:is(.doc, .doc > section, .doc > article) > :is(p, h1, h2, h3, ul, ol.num, dl.record:not(.cols), blockquote, .callout, .download, details, .pair, .search) { max-width: var(--measure, 72ch); }
/* Line width (from 1.11.0, owner, 2026-11-06). The reading widths above stay the default. A page, a section or any
   single text block can choose another by class, which sets --measure (and --measure-lead for .lead): .measure-full
   (no limit: the text runs to the edge of its column), .measure-wide (96 characters, a lead 72), .measure-narrow (60,
   a lead 44), and .measure-read (the default widths, to restore them inside a wider page). On <body>, <main> or .doc
   the class applies to everything inside; on a paragraph, heading or box it applies to that block alone. */
.measure-full { --measure: none; --measure-lead: none; }
.measure-wide { --measure: 96ch; --measure-lead: 72ch; }
.measure-narrow { --measure: 60ch; --measure-lead: 44ch; }
.measure-read { --measure: 72ch; --measure-lead: 52ch; }
/* From 1.8.0: a token in a document's text blocks that is longer than the line (a URL as link text or as plain
   text, a long identifier or hash) may break where nothing else fits, so a document page never scrolls sideways at
   320 px. A break inside a word happens only when that word alone is wider than the line, so ordinary words still
   wrap at spaces. Table cells keep their own rules: a wide table scrolls inside its .tablewrap. */
.doc :is(p, li, dt, dd, h1, h2, h3, h4, blockquote, figcaption, .callout) { overflow-wrap: anywhere; }
:is(.doc, .doc > section, .doc > article) > .steps { max-width: var(--measure, 84ch); }
.rail-logo { width: 100%; height: auto; display: block; margin: 0.3rem 0 1.2rem; }
:is(.doc, .doc > section, .doc > article) > * { grid-column: 2; min-width: 0; }
:is(.doc, .doc > section, .doc > article) > .lbl { grid-column: 1; padding-top: 0.55rem; margin: 0; }
:is(.doc, .doc > section, .doc > article) > .lbl.first { padding-top: 0.9rem; }
:is(.doc, .doc > section, .doc > article) > .rail { grid-column: 3; grid-row: 1 / span 200; position: sticky; top: 1.5rem; align-self: start; }
:is(.doc, .doc > section, .doc > article) > .wide { grid-column: 2; }
:is(.doc, .doc > section, .doc > article) > .full { grid-column: 1 / 4; }
.doc section, .doc article { display: contents; }
.doc h1 { font-weight: 300; font-size: 2.8rem; line-height: 1.1; margin: 0 0 0.5rem; letter-spacing: -0.012em; }
.doc h2 { font-weight: 400; font-size: 2rem; line-height: 1.18; margin: 2rem 0 0.7rem; }
.doc h3 { font-weight: 500; font-size: 1.45rem; line-height: 1.35; margin: 1.6rem 0 0.5rem; }
:is(.doc, .doc > section, .doc > article) > .lbl + h1, :is(.doc, .doc > section, .doc > article) > .lbl + h3 { margin-top: 0; }
:is(.doc, .doc > section, .doc > article) > .lbl + h2 { margin-top: 1.2rem; }
:is(.doc, .doc > section, .doc > article) > .lbl.sec { padding-top: 1.8rem; }
:is(.doc, .doc > section, .doc > article) > .lbl.blk { padding-top: 1.75rem; }
:is(.doc, .doc > section, .doc > article) > .lbl.first { padding-top: 0.9rem; }
:is(.doc, .doc > section, .doc > article) > .lbl + .tablewrap { margin-top: 0.4rem; }
:is(.doc, .doc > section, .doc > article) > .lbl + .tablewrap + * { margin-top: 0; }
:is(.doc, .doc > section, .doc > article) > .lbl.blk + .tablewrap { margin-top: 1.35rem; }
:is(.doc, .doc > section, .doc > article) > .lbl + .picker { margin-top: 1.1rem; }
:is(.doc, .doc > section, .doc > article) > .lbl + .chips { margin-top: 1.4rem; }
:is(.doc, .doc > section, .doc > article) > .lbl + .search { margin-top: 1.2rem; }
:is(.doc, .doc > section, .doc > article) > .side { grid-column: 1; grid-row: span 7; align-self: start; padding-top: 0.6rem; }
:is(.doc, .doc > section, .doc > article) > .side dd { font-size: 0.9rem; }
:is(.doc, .doc > section, .doc > article) > .lead + .side { margin-top: 0; }
.lbl.size { color: var(--text-muted); margin: 0.3rem 0 0.9rem; }
.ordering { font: 400 1.777rem/1.25 "Newsreader", serif; margin: 0 0 1rem; letter-spacing: -0.005em; }
.ordering .tier { color: var(--gold); }
.ordering .p { color: var(--ord-progress); }
.ordering .s { color: var(--ord-speed); }
.ordering .c { color: var(--ord-cost); }
.hero .intro .ordering { display: block; font: 400 1.25rem/1.35 "Newsreader", serif; }
.callout .ordering { font-size: 1.5rem; }
.region ol.num { padding-left: 0; list-style: none; counter-reset: c; margin: 0; }
.region ol.num > li { counter-increment: c; position: relative; padding-left: 2.6rem; margin-bottom: 0.9rem; }
.region ol.num > li::before { content: counter(c); position: absolute; left: 0; top: 0.12rem; font: 400 0.95rem/1.6 "Newsreader", serif; color: var(--accent); font-variant-numeric: lining-nums; }
:is(.doc, .doc > section, .doc > article) > details { margin: 0 0 1.1rem; }
details summary { cursor: pointer; font-weight: 600; padding: 0.4rem 0; }
details p, details ul { margin: 0.4rem 0 0.8rem; }
details ul ul { margin: 0.2rem 0 0.4rem; }
.doc p, .doc ul, .doc ol, .doc dl { margin: 0 0 1.1rem; }
.doc .meta { font: 400 1.05rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin: 0 0 1.6rem; max-width: var(--measure, 66ch); }
.doc .lead { margin-bottom: 1.4rem; }
.doc ul { padding-left: 1.2rem; }
/* From 1.8.0: a chip list is a row of controls, not a bulleted list, so it starts at the text edge (.doc ul indented
   it by 1.2rem). */
.doc ul.chips { padding-left: 0; }
.doc li { margin-bottom: 0.45rem; }
.doc ol.num { padding-left: 0; list-style: none; counter-reset: c; }
.doc ol.num > li { counter-increment: c; position: relative; padding-left: 2.6rem; margin-bottom: 0.9rem; }
.doc ol.num > li::before { content: counter(c); position: absolute; left: 0; top: 0.12rem; font: 400 0.95rem/1.6 "Newsreader", serif; color: var(--accent); font-variant-numeric: lining-nums; }
.doc ol.num ol { list-style: lower-alpha; padding-left: 1.4rem; margin-top: 0.5rem; }
.doc blockquote { margin: 0 0 1.1rem; padding-left: 1.4rem; font-style: italic; color: var(--text-muted); }

/* Contents rail */
.rail { font: 400 0.95rem/1.5 "Public Sans", system-ui, sans-serif; --logo-inset: 0.115; }
/* The rail text starts under the visible left edge of the logo artwork: each SVG's internal left margin, measured as a fraction of its box (README, tools/measure.js). */
.site-opfiles .rail { --logo-inset: 0.1225; } .site-auditthis .rail { --logo-inset: 0.2075; } .site-cleanlanguage .rail { --logo-inset: 0.185; } .site-aiqt .rail { --logo-inset: 0.0975; } .site-grclibrary .rail { --logo-inset: 0.115; }
.rail .lbl { margin: 0.6rem 0 0.8rem; }
.rail ol, .rail ul { list-style: none; margin: 0; padding: 0; counter-reset: r; }
.rail li { margin: 0; }
.rail li a { display: grid; grid-template-columns: 1.4rem 1fr; gap: 0.2rem; color: var(--rail-fg); text-decoration: none; padding: 0.22rem 0; }
.rail ol li a::before { counter-increment: r; content: counter(r); font: 400 0.8rem/1.6 "Newsreader", serif; color: var(--accent); font-variant-numeric: lining-nums; }
.rail ul li a { grid-template-columns: 1fr; }
.rail li a:hover { color: var(--rail-hover-fg); }
/* rail.js marks the section on screen with aria-current="location"; the "true" form is kept for pages built on 1.2.1 and earlier. */
.rail li a[aria-current="location"], .rail li a[aria-current="true"] { color: var(--rail-current-fg); }
.rail > .lbl, .rail > ol, .rail > ul { margin-left: calc(100% * var(--logo-inset)); }

/* Left-rail page (from 1.5.0): .doc.left-rail replaces the label column and the right rail with 1 side list on the
   left, .lrail, so the main column gains their width (for a wide table). The list stays in view while the page
   scrolls, at the right rail's offset and in its type; labels sit above their content, as at 1000 px and below.
   rail.js reads only nav.rail, so it leaves the left list alone. */
.doc.left-rail { grid-template-columns: var(--railw) minmax(0, 1fr); }
/* .doc.no-rail (from 1.11.0): a document page with no "On this page" rail gives the rail's column to the content. Without
   the class the column stays reserved, as it was until 1.10.0. */
.doc.no-rail { grid-template-columns: var(--label-col) minmax(0, 1fr); }
:is(.doc.no-rail, .doc.no-rail > section, .doc.no-rail > article) > .full { grid-column: 1 / -1; }
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > *,
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl,
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .wide,
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .next { grid-column: 2; }
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .full { grid-column: 1 / 3; }
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl,
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl.sec,
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl.blk { padding-top: 1.4rem; margin-bottom: 0.4rem; }
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl.first { padding-top: 0.9rem; }
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl + h2 { margin-top: 0; }
:is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl.blk + .tablewrap { margin-top: 0.2rem; }
.doc.left-rail > .lrail { grid-column: 1; grid-row: 1 / span 200; align-self: stretch; font: 400 0.95rem/1.5 "Public Sans", system-ui, sans-serif; --logo-inset: 0.115; }
.site-opfiles .lrail { --logo-inset: 0.1225; } .site-auditthis .lrail { --logo-inset: 0.2075; } .site-cleanlanguage .lrail { --logo-inset: 0.185; } .site-aiqt .lrail { --logo-inset: 0.0975; } .site-grclibrary .lrail { --logo-inset: 0.115; }
.lrail > nav { position: sticky; top: 1.5rem; max-height: calc(100vh - 3rem); overflow-y: auto; padding-left: calc(100% * var(--logo-inset)); }
.lrail .lbl { margin: 0.6rem 0 0.8rem; }
.lrail ul { list-style: none; margin: 0; padding: 0; }
.lrail li { margin: 0; }
.lrail li a, .lrail li button { display: block; width: 100%; text-align: left; font: inherit; color: var(--rail-fg); text-decoration: none; padding: 0.22rem 0; background: transparent; border: 0; cursor: pointer; }
.lrail li a:hover, .lrail li button:hover { color: var(--rail-hover-fg); }
.lrail li [aria-current="true"], .lrail li [aria-pressed="true"] { color: var(--rail-current-fg); font-weight: 600; }

/* Callouts: no border, label in the label column */
.callout { background: var(--callout-bg); padding: 1.2rem 1.4rem; margin: 0.4rem 0 1.6rem; border-radius: 0.3rem; font-size: 1.15rem; line-height: 1.55; }
.callout.rule { box-shadow: inset 4px 0 0 var(--brand); }
.callout p { margin: 0 0 0.8rem; }
.callout p:last-child, .callout ul:last-child, .callout ol:last-child { margin-bottom: 0; }

/* Code and prompt blocks */
pre, .code { font: 400 0.95rem/1.55 "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--code-bg); color: var(--text); padding: 1.3rem 1.4rem; border-radius: 0.3rem; margin: 0.4rem 0 1.6rem; position: relative; white-space: pre-wrap; overflow-wrap: anywhere; font-variant-numeric: lining-nums tabular-nums; }
pre.hascopy { padding-top: 3.2rem; }
code { font: 400 0.9em/1.4 "JetBrains Mono", ui-monospace, monospace; background: var(--code-bg); padding: 0.1em 0.35em; border-radius: 0.2rem; overflow-wrap: anywhere; }
pre code { background: none; padding: 0; font-size: inherit; }
.copy, .btn { position: absolute; top: 0.8rem; right: 0.8rem; font: 500 0.7rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.16em; text-transform: uppercase; background: transparent; color: var(--button-fg); border: 1px solid var(--button-border); border-radius: 999px; padding: 0.55rem 0.9rem; cursor: pointer; }
.copy:hover, .btn:hover { color: var(--button-hover-fg); border-color: var(--button-hover-border); }
.copy[hidden] { display: none; }
.btn.inline { position: static; display: inline-block; text-decoration: none; margin: 0 0.6rem 0.6rem 0; }
.btn.inline:hover { color: var(--button-hover-fg); }
.code-note { font: 400 0.95rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin: -0.8rem 0 1.6rem; }
.prompt-block { max-height: 36rem; overflow: auto; }
/* The flowing variant: the whole text in the page flow, no cap and no inner scroll, for a portable text the reader reads in place. */
.prompt-flow { max-height: none; overflow: visible; }

/* Tables: header hairline only, tracked header, 0.6rem row padding. A table wider than its wrapper scrolls inside it;
   a long token wraps inside its own cell only in a fixed-layout table (table.fixed with colgroup widths). */
/* position: relative makes the wrapper the containing block of visually hidden text (.vh) inside cells, so that
   text is clipped by the wrapper and cannot widen the page (from 1.5.0). */
.tablewrap { position: relative; overflow-x: auto; margin: 0.4rem 0 1.6rem; -webkit-overflow-scrolling: touch; }
.tablewrap:focus-visible { outline-offset: 4px; }
table { border-collapse: collapse; width: 100%; font-size: 1.05rem; line-height: 1.45; font-variant-numeric: lining-nums tabular-nums; }
th { text-align: left; font: 500 0.68rem/1.4 "Public Sans", system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--th-fg); padding: 0 1.2rem 0.6rem 0; border-bottom: 1px solid var(--th-rule); vertical-align: bottom; white-space: nowrap; }
td { padding: 0.6rem 1.2rem 0.6rem 0; vertical-align: top; overflow-wrap: break-word; }
td code { white-space: normal; overflow-wrap: break-word; }
td.id code { white-space: nowrap; }
table.fixed { table-layout: fixed; min-width: 56rem; }
table.fixed th { white-space: normal; }
/* Column widths for fixed tables: col.w<N> for N in steps of 5, plus the 5 widths the framework registry uses. */
.fixed col.w5 { width: 5%; } .fixed col.w10 { width: 10%; } .fixed col.w15 { width: 15%; } .fixed col.w20 { width: 20%; } .fixed col.w25 { width: 25%; } .fixed col.w30 { width: 30%; } .fixed col.w35 { width: 35%; } .fixed col.w40 { width: 40%; } .fixed col.w45 { width: 45%; } .fixed col.w50 { width: 50%; } .fixed col.w55 { width: 55%; } .fixed col.w60 { width: 60%; } .fixed col.w65 { width: 65%; } .fixed col.w70 { width: 70%; } .fixed col.w75 { width: 75%; } .fixed col.w80 { width: 80%; } .fixed col.w85 { width: 85%; } .fixed col.w90 { width: 90%; } .fixed col.w95 { width: 95%; }
.fixed col.w11 { width: 11%; } .fixed col.w14 { width: 14%; } .fixed col.w16 { width: 16%; } .fixed col.w17 { width: 17%; } .fixed col.w26 { width: 26%; }
th:last-child, td:last-child { padding-right: 0; }
/* Sticky tables (from 1.5.0). A sticky header can stick only to its nearest scroll container, and .tablewrap is one,
   so the wrapper of a sticky table is a bounded box that scrolls in both directions: the header row stays at the
   box's top while the reader scrolls inside it. Mark the wrapper .bounded; 1.4.1 markup (.tablewrap holding
   table.sticky) is bounded through :has() where the browser supports it, and elsewhere renders as in 1.4.1.
   The 2 selectors stay in separate rules, so a browser without :has() still applies the first.
   table.sticky-col keeps the first column at the box's left edge. Sticky cells take the page background, so
   scrolled content never shows through, and the top-left cell sits above both the header row and the column. */
.tablewrap.bounded { max-height: 75vh; max-height: 75svh; overflow: auto; overscroll-behavior: contain; }
.tablewrap:has(> table.sticky) { max-height: 75vh; max-height: 75svh; overflow: auto; overscroll-behavior: contain; }
.register .tablewrap.bounded { padding-top: 0; }
.register .tablewrap:has(> table.sticky) { padding-top: 0; }
table.sticky, table.sticky-col { border-collapse: separate; border-spacing: 0; }
.sticky thead th { position: sticky; top: 0; z-index: 2; background: var(--bg); }
table.sticky-col th:first-child, table.sticky-col td:first-child { position: sticky; left: 0; z-index: 1; background: var(--bg); }
table.sticky-col thead th:first-child { z-index: 3; }
table [hidden] { display: none; }
/* Matrix (from 1.5.0, matrix.js): a row header per row in the text voice, short identifiers and count links in the cells,
   the instrument's organization under each column heading. */
table.matrix tbody th { font: 600 1rem/1.45 "Public Sans", system-ui, sans-serif; letter-spacing: 0; text-transform: none; color: var(--text); padding: 0.6rem 1.2rem 0.6rem 0; border-bottom: 0; vertical-align: top; white-space: nowrap; }
table.matrix td { white-space: nowrap; }
table.matrix td code { white-space: nowrap; }
table.matrix th .org { display: block; font: 400 0.72rem/1.4 "JetBrains Mono", ui-monospace, monospace; letter-spacing: 0.02em; text-transform: none; margin-top: 0.15rem; }
table.matrix td a { margin-left: 0.4rem; }
.matrix-status { font: 400 0.85rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin: 0 0 0.6rem; min-height: 1.3rem; }
td .sub { display: block; font: 400 0.95rem/1.45 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin-top: 0.15rem; }
td.id, .mono { font: 400 0.8rem/1.6 "JetBrains Mono", ui-monospace, monospace; white-space: nowrap; }
td.num { text-align: right; font-variant-numeric: lining-nums tabular-nums; }
.tag { display: inline-block; font: 500 0.66rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tag-fg); padding: 0.35rem 0.55rem; border: 1px solid var(--tag-border); border-radius: 999px; white-space: nowrap; }
.tag.accent { color: var(--tag-accent-fg); border-color: var(--tag-accent-border); }
.tag.fill { background: var(--surface-sunken); border-color: transparent; }

/* Large matrix tables (from 1.7.0, specification 7.34): opt-in classes and attributes; markup without them renders
   as in 1.6.1.
   Column widths in rem for fixed-layout tables: col.r6 to col.r24 (steps of 2) set --colw, and 1 rule applies it,
   so a table whose columns add up to more than the page grows past it and scrolls inside .tablewrap. A col without
   a width class leaves --colw unset, so its width stays auto, and the col.w<N> percentages outrank this rule. */
col.r6 { --colw: 6rem; } col.r8 { --colw: 8rem; } col.r10 { --colw: 10rem; } col.r12 { --colw: 12rem; } col.r14 { --colw: 14rem; }
col.r16 { --colw: 16rem; } col.r18 { --colw: 18rem; } col.r20 { --colw: 20rem; } col.r22 { --colw: 22rem; } col.r24 { --colw: 24rem; }
.fixed col { width: var(--colw); }
/* Wrapping cells: table.matrix.cells-wrap lets data cells wrap inside their column; headers keep their rules;
   td.nowrap (and td.id) stay on 1 line, for example a count-only column. */
td.nowrap, td.nowrap code { white-space: nowrap; }
table.matrix.cells-wrap td:not(.nowrap, .id), table.matrix.cells-wrap td:not(.nowrap, .id) code { white-space: normal; }
/* The capped pinned column, opt-in: table.sticky-col.pin-cap gives the first column a capped width, overridable with
   --pin-col (the pin-r<N> classes set it), and lets its labels wrap. table.sticky-col without pin-cap renders as in
   1.6.1. The default's 8rem minimum keeps half of a 320 px window for data. */
table.sticky-col.pin-cap :is(th, td):first-child { width: var(--pin-col, clamp(8rem, 30vw, 15rem)); white-space: normal; overflow-wrap: break-word; }
table.pin-cap.pin-r6 { --pin-col: 6rem; } table.pin-cap.pin-r8 { --pin-col: 8rem; }
table.pin-cap.pin-r10 { --pin-col: clamp(8rem, 30vw, 10rem); } table.pin-cap.pin-r12 { --pin-col: clamp(8rem, 30vw, 12rem); }
table.pin-cap.pin-r14 { --pin-col: clamp(8rem, 30vw, 14rem); } table.pin-cap.pin-r16 { --pin-col: clamp(8rem, 30vw, 16rem); }
table.pin-cap.pin-r18 { --pin-col: clamp(8rem, 30vw, 18rem); } table.pin-cap.pin-r20 { --pin-col: clamp(8rem, 30vw, 20rem); }
/* Row guides: table.zebra tints even body rows, table.rowhover the row under the pointer. The tints are opaque
   palette tokens and reach every cell of the row, sticky cells included, so a pinned cell keeps the row's colour
   and scrolled content never shows through. No transition. */
table.zebra tbody tr:nth-child(even) > * { background: var(--row-tint); }
table.rowhover tbody tr:hover > * { background: var(--row-hover); }
/* Column highlight (matrix.js, data-col-highlight on the table): every cell of the hovered or focused column. */
table.matrix tr > :is(th, td).colhl { background: var(--row-hover); }
/* An empty cell: the word stays in the cell, centred, in muted text (4.5:1 on every surface and row tint). */
table td.na { color: var(--text-muted); text-align: center; }
/* Heat shading: td[data-heat="0"] to "4" in a matrix, 5 steps per site and scheme from palettes.css. The count stays
   printed; the cell's own text is --text (links keep --link), the colours each step is checked against. A heat
   cell keeps its step under the row and column tints. */
table.matrix tbody tr > td[data-heat], table.matrix tbody tr > td[data-heat] :is(.sub, .n) { color: var(--text); }
table.matrix tbody tr > td[data-heat="0"], .tag[data-heat="0"] { background: var(--heat-0); }
table.matrix tbody tr > td[data-heat="1"], .tag[data-heat="1"] { background: var(--heat-1); }
table.matrix tbody tr > td[data-heat="2"], .tag[data-heat="2"] { background: var(--heat-2); }
table.matrix tbody tr > td[data-heat="3"], .tag[data-heat="3"] { background: var(--heat-3); }
table.matrix tbody tr > td[data-heat="4"], .tag[data-heat="4"] { background: var(--heat-4); }
/* From 1.8.0: the focus ring inside a heat cell (on its count link, or on the cell) is drawn in --text, which every
   heat step holds at 4.5:1, so the ring keeps 3:1 on any step and --focus no longer limits the light ramp. */
table.matrix td[data-heat] :focus-visible, table.matrix td[data-heat]:focus-visible { outline-color: var(--text); }
/* The heat legend: <ul class="chips heat-legend"> of .tag swatches, each with its step's words. */
ul.chips.heat-legend { align-items: center; padding-left: 0; }
.heat-legend .tag { color: var(--text); border-color: var(--rule-strong); }
/* Rotated column headers: th.rot sets the header text vertically, read from the bottom up, capped at 11rem (it
   wraps to a 2nd line beyond that). The text is unchanged, so screen readers read it as written. */
table th.rot { writing-mode: vertical-rl; white-space: normal; max-height: 11rem; text-align: left; vertical-align: bottom; padding: 0.6rem 0.4rem 0.6rem 0; }
@supports (writing-mode: sideways-lr) { table th.rot { writing-mode: sideways-lr; } }
table.matrix th.rot .org, table.matrix th.rot .grp { margin: 0 0 0 0.15rem; }
/* Column groups: a tag line naming the group (.grp) under the heading and a 3px accent under the header cell
   (th[data-grp="1"] to "6", the family's 6 hues made text-safe on each site). The group is named in text; the
   colour only reinforces it. */
/* From 1.8.0: while every visible column belongs to 1 group, matrix.js sets data-one-grp on the table and the tags,
   which would repeat 1 name and only add width, are not shown; the accent under each header stays. */
table.matrix[data-one-grp] th .grp { display: none; }
table.matrix th .grp { display: block; font: 600 0.62rem/1.4 "Public Sans", system-ui, sans-serif; letter-spacing: 0.14em; text-transform: uppercase; margin-top: 0.2rem; }
table.matrix thead th[data-grp="1"] { border-bottom: 3px solid var(--grp-1); } table.matrix thead th[data-grp="1"] .grp { color: var(--grp-1); }
table.matrix thead th[data-grp="2"] { border-bottom: 3px solid var(--grp-2); } table.matrix thead th[data-grp="2"] .grp { color: var(--grp-2); }
table.matrix thead th[data-grp="3"] { border-bottom: 3px solid var(--grp-3); } table.matrix thead th[data-grp="3"] .grp { color: var(--grp-3); }
table.matrix thead th[data-grp="4"] { border-bottom: 3px solid var(--grp-4); } table.matrix thead th[data-grp="4"] .grp { color: var(--grp-4); }
table.matrix thead th[data-grp="5"] { border-bottom: 3px solid var(--grp-5); } table.matrix thead th[data-grp="5"] .grp { color: var(--grp-5); }
table.matrix thead th[data-grp="6"] { border-bottom: 3px solid var(--grp-6); } table.matrix thead th[data-grp="6"] .grp { color: var(--grp-6); }
/* Column toggles (matrix.js): groups of chips as buttons, hidden until the script reveals them. */
.matrix-toggles { margin: 0 0 0.8rem; }
.matrix-toggles .lbl { margin: 0 0 0.4rem; }
.matrix-toggles .chips { margin: 0 0 0.8rem; }

/* Definition lists: tracked dt, serif dd */
dl.record { margin: 0; }
dl.record dt { font: 500 0.68rem/1.4 "Public Sans", system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); margin: 0 0 0.15rem; }
dl.record dd { margin: 0 0 0.9rem; font-size: 1.05rem; line-height: 1.45; }
dl.record dd:last-child { margin-bottom: 0; }
dl.record.cols { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 0.6rem 2rem; }
dl.record.cols div { break-inside: avoid; }

/* Before and after */
.pair { display: grid; grid-template-columns: 1fr; gap: 1rem; margin: 0.4rem 0 1.6rem; }
.pair > div { padding: 1.2rem 1.4rem; border-radius: 0.3rem; font-size: 1.15rem; line-height: 1.5; }
.pair > div p { margin: 0; }
.pair .before { background: var(--pair-before-bg); }
.pair .after { background: var(--pair-after-bg); }
.pair pre { background: var(--pair-panel-bg); }
/* On a tinted band (from 1.11.0) the before box would match the band, so it takes the page background. */
.band-tint .pair .before { background: var(--pair-before-bg-on-tint); }
.pair .lbl { margin-bottom: 0.5rem; }
.pair .after .lbl { color: var(--accent); }
/* .pair-stack (from 1.11.0, owner, 2026-11-06): the 2 boxes one above the other at every width, each as tall as its own
   content, for a short original and a long answer (an inbound message and a reply). A code block in a stacked box
   takes the box's width with no extra margin. Without the class a pair is side by side from 1001 px, as before. */
@media (min-width: 1001px) { .pair.pair-stack { grid-template-columns: minmax(0, 1fr); gap: 1rem; } }
.pair-stack > div > pre { margin: 0.4rem 0 0; }
/* A message in a box (from 1.11.0): <div class="msg"> holds quoted text on the same inner panel as a code block, in
   the page's text face, so an original and a code-set answer read as 2 framed messages. In a stacked pair the
   before box then takes the after box's surface, so the 2 frames match. */
.pair .msg { margin: 0.4rem 0 0; padding: 1.1rem 1.3rem; background: var(--pair-panel-bg); border-radius: 0.3rem; }
.pair .msg p { margin: 0 0 0.6rem; }
.pair .msg p:last-child { margin-bottom: 0; }
.pair-stack .before:has(> .msg) { background: var(--pair-after-bg); }

/* Download and checksum block */
.download { margin: 0.4rem 0 1.6rem; }
.download .file { font-size: 1.333rem; line-height: 1.4; }
.download .file a { text-decoration-color: var(--brand); text-decoration-thickness: 2px; }
.download .size { margin: 0.3rem 0 0.9rem; }
.download code.sum { display: block; background: var(--code-bg); padding: 0.9rem 1rem; border-radius: 0.3rem; font-size: 0.85rem; overflow-wrap: anywhere; white-space: normal; margin: 0 0 0.9rem; }
.download pre { margin: 0; font-size: 0.8rem; padding: 0.9rem 1rem; }

/* Install selector: 6 tracked labels in a row */
.picker { display: flex; flex-wrap: wrap; gap: 0.4rem 1.8rem; margin: 0.4rem 0 1.4rem; padding: 0; list-style: none; }
.picker a { display: inline-block; font: 500 0.74rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--picker-fg); text-decoration: none; padding: 0.7rem 0; border-bottom: 1px solid transparent; }
.picker a:hover { color: var(--picker-hover-fg); }
.picker a[aria-current="true"] { color: var(--picker-current-fg); border-bottom-color: var(--picker-current-rule); border-bottom-width: 2px; }
.picker-reset { position: static; margin: 0 0 1.6rem; }
.picker-reset[hidden] { display: none; }
.verified { font: 400 0.95rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin: -0.4rem 0 1rem; }

/* Search: progressive enhancement, all content visible without script */
.search { margin: 0.4rem 0 1.6rem; }
.search label { display: block; }
.search input { width: 100%; max-width: 40rem; font: 400 1.1875rem/1.4 "Newsreader", serif; padding: 0.7rem 1rem; border: 1px solid var(--input-border); border-radius: 0.3rem; background: var(--input-bg); color: var(--input-fg); }
.search input::placeholder { color: var(--input-placeholder); opacity: 1; }
.search .status { font: 400 0.85rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin: 0.6rem 0 0; min-height: 1.3rem; }
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 0 0 1.6rem; padding: 0; }
.chips a { display: inline-block; font: 500 0.7rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--chip-fg); text-decoration: none; padding: 0.55rem 0.8rem; border: 1px solid var(--chip-border); border-radius: 999px; }
.chips a:hover { color: var(--chip-hover-fg); border-color: var(--chip-hover-border); }
.chips a .n, .chips button .n { font-family: "JetBrains Mono", ui-monospace, monospace; letter-spacing: 0.04em; margin-left: 0.4rem; }
/* Chips as buttons, and the chosen chip (from 1.5.0): search.js marks an active facet with aria-pressed="true";
   matrix.js marks the chosen preset with aria-pressed="true" on a button or aria-current="true" on a link.
   The chosen chip takes a 2px border in --accent, so the state does not rest on colour alone. */
.chips button { display: inline-block; font: 500 0.7rem/1 "Public Sans", system-ui, sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--chip-fg); background: transparent; padding: 0.55rem 0.8rem; border: 1px solid var(--chip-border); border-radius: 999px; cursor: pointer; }
.chips button:hover { color: var(--chip-hover-fg); border-color: var(--chip-hover-border); }
.chips [aria-pressed="true"], .chips [aria-current="true"] { color: var(--chip-pressed-fg); border-color: var(--chip-pressed-border); box-shadow: inset 0 0 0 1px var(--chip-pressed-border); }
.plan li[hidden] { display: none; }
/* A chip that would show no documents (from 1.7.0, search.js with data-filter-empty="disable"): aria-disabled="true",
   still focusable. A dashed border in place of the solid one and the not-allowed cursor, with no hover change; the
   text and border keep the chip's colours (--text-muted, --rule-strong), with no fading and no transition. */
.chips a[aria-disabled="true"], .chips button[aria-disabled="true"] { color: var(--chip-unavailable-fg); background: var(--chip-unavailable-bg); border-color: var(--chip-unavailable-border); border-style: dashed; cursor: not-allowed; text-decoration: line-through; text-decoration-thickness: 1px; }
.chips [aria-disabled="true"] .n { display: inline-block; text-decoration: none; }
.chips a[aria-disabled="true"]:hover, .chips button[aria-disabled="true"]:hover { color: var(--chip-unavailable-fg); background: var(--chip-unavailable-bg); border-color: var(--chip-unavailable-border); }

/* Diagram: 3 rounded nodes, currentColor strokes, brand-coloured arrows */
.figure { margin: 0.4rem 0 1.6rem; }
.figure svg { width: 100%; height: auto; display: block; color: var(--text); font-family: "Public Sans", system-ui, sans-serif; }
.figure svg .node { fill: var(--surface-raised); stroke: currentColor; stroke-width: 1; }
.figure svg .arrow { stroke: var(--brand); stroke-width: 2; fill: none; }
.figure svg .head { fill: var(--brand); }
.figure svg .t { font-size: 11px; letter-spacing: 2.2px; text-transform: uppercase; fill: var(--text-muted); font-weight: 500; }
.figure svg .t.accent { fill: var(--accent); }
.figure svg .m { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 12.5px; fill: var(--text); }
.figure svg .s { font-family: "Newsreader", serif; font-size: 14px; fill: var(--text); }
.figure .stack { display: none; }
.figure figcaption { font: 400 0.95rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin-top: 0.8rem; }

/* Source and view, side by side on wide screens */
.srcview { display: grid; grid-template-columns: 1fr; gap: 1rem; margin: 0.4rem 0 1.6rem; }
.srcview pre { margin: 0; }
.srcview .view { background: var(--surface-raised); border-radius: 0.3rem; padding: 1.3rem 1.4rem; font-size: 0.95rem; }
.srcview .view .gen { font: 400 0.78rem/1.5 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin: 0 0 0.8rem; }
.srcview .view h4 { font: 500 0.72rem/1.4 "Public Sans", system-ui, sans-serif; letter-spacing: 0.2em; text-transform: uppercase; margin: 0 0 0.6rem; color: var(--text); }
.srcview .view ul { margin: 0; padding: 0; list-style: none; }
.srcview .view li { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.srcview .lbl { margin-bottom: 0.5rem; }

/* The value paragraph of the landing page, and the "About this project" line beneath it: Disclosure, Licence,
   Privacy and Security as 1 line of links separated by middle dots. */
.region .value { max-width: 68ch; margin: 0; }
.region .about { margin: 0; font: 500 0.8rem/1.6 "Public Sans", system-ui, sans-serif; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-muted); }
.region .about a { color: var(--text-muted); text-decoration: none; }
.region .about a:hover { color: var(--text); }
.region .about .dot { padding: 0 0.5rem; }
/* From 1.7.0 the markup has 1 space after each dot, so the line breaks only after a dot; the dot's right padding
   gives up the space's width (0.36em: the space and its 0.12em tracking in Public Sans), so the gaps either side
   of a dot are equal. */
.region .about .dot { padding-right: calc(0.5rem - 0.36em); }
/* A safety net for pages still on the older markup, whose links and dots touch: it lets the line break inside a word, which happens
   only when nothing else fits (at 320 px the older line was 379 px wide). */
.region .about { overflow-wrap: anywhere; }

/* Bands (from 1.11.0, owner, 2026-11-06): full-width sections that give a page an alternating rhythm. A band is a
   direct child of <main> and holds its own .wrap: <section class="band band-tint"><div class="wrap">...</div></section>.
   .band is plain (the page background), .band-tint sits on --band-tint-bg (by default --surface-sunken), and
   .band-dark inverts the colours: in light mode --text becomes the ground and --bg the text, in dark mode the band
   sits below the page on --surface-sunken in the page's own colours. A dark band holds headings, paragraphs, lists and
   links only; its colours are component tokens the palette gate checks on every site.
   Colours a site may set in site-palette.css with no template change (from 1.11.0, owner, 2026-11-06), each checked
   by the palette gate: the bands (--band-tint-bg, --band-dark-*), the banner frame (--banner-from, --banner-to), the
   before-and-after boxes (--pair-before-bg, --pair-before-bg-on-tint for a before box on a tinted band, --pair-after-bg,
   --pair-panel-bg for the inner message or code panel) and the card grid (--box-bg, --box-border). */
/* --band-pad (from 1.11.1, requested by vendorreplies.ai): a site may set the bands' top and bottom spacing in its
   site.css; unset, the 1.11.0 spacing applies. */
.band { padding: var(--band-pad, clamp(2.2rem, 5vw, 4rem)) 0; }
.band + .band { border-top: 0; }
.band-tint { background: var(--band-tint-bg); }
.band-dark { background: var(--band-dark-bg); color: var(--band-dark-fg); }
.band-dark h2, .band-dark h3 { color: var(--band-dark-heading); }
.band-dark .lbl, .band-dark .meta { color: var(--band-dark-fg); }
.band-dark a { color: var(--band-dark-link); }
.band-dark a:focus-visible { outline-color: var(--band-dark-focus); }
.band > .wrap > :first-child, .band .doc > :first-child { margin-top: 0; }

/* Card grid (from 1.11.0, owner, 2026-11-06): a list of short boxes set side by side, as many as fit at 15rem or wider
   (3 on a desktop column), stacking on phones. <ul class="boxes">, or <ol class="boxes boxes-numbered"> for numbered
   steps; each <li> may open with an <h3>. */
.boxes { list-style: none; margin: 0.4rem 0 1.6rem; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); gap: 1rem; counter-reset: bx; }
.doc ul.boxes, .doc ol.boxes { padding-left: 0; }
.boxes > li { margin: 0; padding: 1.1rem 1.2rem; background: var(--box-bg); border: 1px solid var(--box-border); border-radius: 0.5rem; font-size: 1.05rem; line-height: 1.55; }
.boxes > li > :first-child { margin-top: 0; }
.boxes > li > :last-child { margin-bottom: 0; }
.boxes h3 { margin: 0 0 0.4rem; font: 700 1.1rem/1.3 "Public Sans", system-ui, sans-serif; color: var(--text); }
.boxes-numbered > li { counter-increment: bx; }
.boxes-numbered > li::before { content: counter(bx); display: inline-block; min-width: 1.9rem; margin-bottom: 0.5rem; padding: 0.15rem 0.5rem; border: 1px solid var(--rule-strong); border-radius: 999px; font: 700 0.95rem/1.4 "Public Sans", system-ui, sans-serif; color: var(--accent); text-align: center; }

/* Banner (from 1.11.0, owner, 2026-11-06): an optional full-width picture at the top of a page, under the masthead,
   with the page's title and a tagline set over it. Markup:
     <header class="banner" data-text="start|centre|end"><picture>...<img src="..." alt="..." width="..." height="..."></picture>
       <div class="banner-text"><h1>Title</h1><p class="banner-tagline">Tagline</p></div></header>
   The picture is framed by a band in --banner-from and --banner-to (component tokens, by default the site's --brand
   and --accent; a site may set its own in site-palette.css). The text sits over the picture in the third that
   data-text names (start by default), in white with a dark shadow, so it reads on any picture dark enough to carry
   it: the site checks that with the overflow and contrast review of its banner. Below 52rem of width the text moves
   under the picture, on a --surface-raised panel inside the frame, in --text. A page with a banner keeps its <h1> in the banner and has no .hero. */
:where(:root) { --banner-from: var(--brand); --banner-to: var(--accent); }
.banner { position: relative; margin: 0; padding: clamp(0.6rem, 1.6vw, 1.2rem); background: linear-gradient(135deg, var(--banner-from) 0%, var(--banner-to) 100%); }
.banner picture, .banner img { display: block; width: 100%; height: auto; border-radius: 0.5rem; }
.banner img { aspect-ratio: auto; object-fit: cover; max-height: 34rem; }
.banner-text { position: absolute; inset: clamp(0.6rem, 1.6vw, 1.2rem); display: flex; flex-direction: column; justify-content: center; padding: clamp(1rem, 4vw, 3.5rem); width: 66%; color: #fff; text-shadow: 0 2px 14px rgba(0, 0, 0, 0.75), 0 1px 3px rgba(0, 0, 0, 0.9); pointer-events: none; }
.banner[data-text="centre"] .banner-text { width: auto; align-items: center; text-align: center; }
.banner[data-text="end"] .banner-text { left: auto; align-items: flex-end; text-align: end; }
.banner-text h1 { margin: 0; font: 800 clamp(2.2rem, 6vw, 4.6rem)/1.02 "Public Sans", system-ui, sans-serif; letter-spacing: -0.02em; }
.banner-tagline { margin: 0.6rem 0 0; font: 600 clamp(1.05rem, 2.1vw, 1.6rem)/1.3 "Public Sans", system-ui, sans-serif; max-width: 32ch; }
/* .banner-fill on the banner: the title filled with the frame's gradient instead of white, with a dark drop shadow
   (vendorreplies.ai's look). On the narrow layout's panel the title is in --text, because a light gradient end can
   fall under 3:1 there. */
.banner-fill .banner-text h1 { background: linear-gradient(135deg, var(--banner-from) 0%, var(--banner-to) 100%); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: none; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.85)); }
@media (max-width: 52rem) {
  .banner-text { position: static; width: auto; margin-top: clamp(0.6rem, 1.6vw, 1.2rem); padding: 0.9rem 1rem; border-radius: 0.5rem; background: var(--surface-raised); color: var(--text); text-shadow: none; }
  .banner[data-text] .banner-text { align-items: flex-start; text-align: start; }
  .banner-fill .banner-text h1 { background: none; color: var(--text); filter: none; }
}

/* Family footer: 1 bar at the content width. The 6 project cards, current site first, on the rotated
   spectrum, and from 1.11.0 vendorreplies.ai's card last on silver; then the GitHub, LinkedIn and ORCID tiles under a grey tail of the band; then the signature tile as the
   posluns.ca link. The footer is a size container, so the bar responds to its own width and never wraps:
   stage A (>= 1160 px of content width, from 1.11.1; >= 1500 in 1.11.0; >= 1400 until 1.10.0) names shown, the 3 marks
   grouped beside the signature, the signature without "A" and "Project" below 1240; stage C (< 1160) names visually
   hidden, equal tiles that shrink to fit; the signature shrinks below 750,
   loses "A" and "Project" below 650, and shrinks again below 450. Below 600 the marks and the signature drop to a
   second line under the grey band (phones). The bar is contiguous: no gaps between tiles. */
.family { padding: 1.6rem var(--pad) 2.2rem; font: 400 0.9rem/1.4 "Public Sans", system-ui, sans-serif; color: var(--text-muted); container: footer / inline-size; }
.site-secureconfig .family { --tail-from: var(--rainbow-6); } .site-opfiles .family { --tail-from: var(--rainbow-1); } .site-auditthis .family { --tail-from: var(--rainbow-2); }
.site-cleanlanguage .family { --tail-from: var(--rainbow-3); } .site-aiqt .family { --tail-from: var(--rainbow-4); } .site-grclibrary .family { --tail-from: var(--rainbow-5); }
.family .bar { display: flex; flex-wrap: nowrap; align-items: stretch; gap: 0; width: 100%; border-radius: 0.5rem; overflow: hidden; }
.family .cards, .family .tail { display: flex; flex-wrap: nowrap; list-style: none; margin: 0; padding: 0; min-width: 0; }
.family .cards { flex: 6 1 auto; gap: 0; }
.family .tail { flex: none; gap: 0; }
.family .slice, .family .tile { display: flex; min-width: 0; padding: var(--band) 0 0; }
.family .slice { flex: 1 1 auto; }
.family .sigtile { flex: none; }
.family .tail .tile-1 { background: linear-gradient(90deg, var(--tail-from) 0%, var(--band-grey) 20%); }
.family .tail .tile-2, .family .tail .tile-3, .family .sigtile { background: var(--band-grey); }
/* The first card starts on its own hue and the last ends on it, so the bar's ends and the grey tail take a clean colour. */
.family .slice-1:first-child { background: linear-gradient(90deg, var(--rainbow-1) 0%, var(--rainbow-1) 80%, var(--rainbow-join-1) 100%); } .family .slice-1:last-child { background: linear-gradient(90deg, var(--rainbow-join-6) 0%, var(--rainbow-1) 20%, var(--rainbow-1) 100%); }
.family .slice-2:first-child { background: linear-gradient(90deg, var(--rainbow-2) 0%, var(--rainbow-2) 80%, var(--rainbow-join-2) 100%); } .family .slice-2:last-child { background: linear-gradient(90deg, var(--rainbow-join-1) 0%, var(--rainbow-2) 20%, var(--rainbow-2) 100%); }
.family .slice-3:first-child { background: linear-gradient(90deg, var(--rainbow-3) 0%, var(--rainbow-3) 80%, var(--rainbow-join-3) 100%); } .family .slice-3:last-child { background: linear-gradient(90deg, var(--rainbow-join-2) 0%, var(--rainbow-3) 20%, var(--rainbow-3) 100%); }
.family .slice-4:first-child { background: linear-gradient(90deg, var(--rainbow-4) 0%, var(--rainbow-4) 80%, var(--rainbow-join-4) 100%); } .family .slice-4:last-child { background: linear-gradient(90deg, var(--rainbow-join-3) 0%, var(--rainbow-4) 20%, var(--rainbow-4) 100%); }
.family .slice-5:first-child { background: linear-gradient(90deg, var(--rainbow-5) 0%, var(--rainbow-5) 80%, var(--rainbow-join-5) 100%); } .family .slice-5:last-child { background: linear-gradient(90deg, var(--rainbow-join-4) 0%, var(--rainbow-5) 20%, var(--rainbow-5) 100%); }
.family .slice-6:first-child { background: linear-gradient(90deg, var(--rainbow-6) 0%, var(--rainbow-6) 80%, var(--rainbow-join-6) 100%); } .family .slice-6:last-child { background: linear-gradient(90deg, var(--rainbow-join-5) 0%, var(--rainbow-6) 20%, var(--rainbow-6) 100%); }
/* The seventh card (from 1.11.0, owner, 2026-11-06): vendorreplies.ai, <li class="slice slice-vr">, is always the last
   project card, after the 6 rotated rainbow cards, on every site including its own. Its band is CONAN's silver: the
   last rainbow card fades into it, it carries a highlight, and the grey tail starts from it. The :has() rules need
   Chromium 105, Safari 15.4 or Firefox 121; an older browser keeps the 1.10.0 colours, with the seventh card's band in
   plain silver. */
.family .slice-1:has(+ .slice-vr) { background: linear-gradient(90deg, var(--rainbow-join-6) 0%, var(--rainbow-1) 20%, var(--rainbow-1) 80%, var(--band-silver) 100%); }
.family .slice-2:has(+ .slice-vr) { background: linear-gradient(90deg, var(--rainbow-join-1) 0%, var(--rainbow-2) 20%, var(--rainbow-2) 80%, var(--band-silver) 100%); }
.family .slice-3:has(+ .slice-vr) { background: linear-gradient(90deg, var(--rainbow-join-2) 0%, var(--rainbow-3) 20%, var(--rainbow-3) 80%, var(--band-silver) 100%); }
.family .slice-4:has(+ .slice-vr) { background: linear-gradient(90deg, var(--rainbow-join-3) 0%, var(--rainbow-4) 20%, var(--rainbow-4) 80%, var(--band-silver) 100%); }
.family .slice-5:has(+ .slice-vr) { background: linear-gradient(90deg, var(--rainbow-join-4) 0%, var(--rainbow-5) 20%, var(--rainbow-5) 80%, var(--band-silver) 100%); }
.family .slice-6:has(+ .slice-vr) { background: linear-gradient(90deg, var(--rainbow-join-5) 0%, var(--rainbow-6) 20%, var(--rainbow-6) 80%, var(--band-silver) 100%); }
.family .slice-vr { background: var(--band-silver); background: linear-gradient(90deg, var(--band-silver) 0%, var(--band-sheen) 35%, var(--band-silver) 60%, var(--band-silver-deep) 85%, var(--band-silver) 100%); }
.family .bar:has(.slice-vr) .tail .tile-1 { background: linear-gradient(90deg, var(--band-silver) 0%, var(--band-grey) 20%); }
.family .card, .family .sig { display: flex; align-items: center; flex: 1 1 auto; min-width: 0; min-height: var(--tile); background: var(--surface-raised); color: var(--text); text-decoration: none; white-space: nowrap; }
.family .card { gap: 0.4rem; padding: 0.2rem 0.45rem; font: 600 0.85rem/1.2 "Public Sans", system-ui, sans-serif; letter-spacing: -0.015em; }
.family .card:hover, .family .sig:hover { box-shadow: inset 0 -3px 0 var(--gold-rule); }
.family .card img { width: var(--tile-logo); height: var(--tile-logo); display: block; flex: none; }
.family .card .tld { color: var(--gold); }
/* The current site's tile carries the gold line under its whole width at every stage (owner, 2026-11-06, from 1.11.1;
   until 1.11.0 a 2 px line under the name alone while the names showed). */
.family .card[aria-current="page"] { box-shadow: inset 0 -3px 0 var(--gold-rule); }
.family .tail .card { width: var(--tile); justify-content: center; padding: 0.3rem; }
.family .tail .card img { width: var(--mark); height: var(--mark); object-fit: contain; }
.sig { margin: 0; font: 400 1.5rem/1 "Dancing Script", cursive; color: var(--silver); white-space: nowrap; }
.sig .pre, .sig .post { font-size: 0.78em; white-space: pre; }
.sig .gold { color: var(--gold); }
.family .sig { padding: 0 0.5rem; justify-content: center; font-size: 1.25rem; }
/* Stage B (1.0.0 to 1.10.0: names kept at scaled sizes from 1040 to 1399 px) is removed in 1.11.0: 7 names clip at
   every scaled size below 1493 px of content width. From 1.11.1 the bar is compact (2.75rem tiles, so every target stays
   44 px tall; 1.9rem logos; 0.85rem names) and stage A starts at 1160 px, which a 1280 px window gives even with a
   scroll bar (owner, 2026-11-06: names on desktop screens from 1280 px). In stage A the 3 marks sit close together
   beside the signature under 1 band that fades from the last project card's colour to grey, and the signature drops
   "A" and "Project" until 1240 px; in stage C they share the width equally with the project tiles, as in 1.11.0.
   Stage A is written as (width > 1159px), the exact complement of stage C's (max-width: 1159px), so that a fractional
   width such as 1159.02 px (a 1233 px window) falls in exactly 1 stage. */
@container footer (width > 1159px) {
  .family .tail { background: linear-gradient(90deg, var(--tail-from) 0%, var(--band-grey) 60%); }
  .family .bar:has(.slice-vr) .tail { background: linear-gradient(90deg, var(--band-silver) 0%, var(--band-grey) 60%); }
  .family .tail .tile-1, .family .tail .tile-2, .family .tail .tile-3, .family .bar:has(.slice-vr) .tail .tile-1 { background: transparent; }
  .family .tail .card { width: auto; padding: 0.2rem 0.15rem; }
  .family .tail .tile-1 .card { padding-left: 0.4rem; }
  .family .tail .tile-3 .card { padding-right: 0.3rem; }
  .family .tail .card img { width: 1.35rem; height: 1.35rem; }
  .family .sig .pre, .family .sig .post { display: none; }
}
@container footer (min-width: 1240px) { .family .sig .pre, .family .sig .post { display: inline; } }
@container footer (max-width: 1159px) {
  .family .cards { flex: 7 1 0; }
  .family .tail { flex: 3 1 0; }
  .family .slice, .family .tail .tile { flex: 1 1 0; }
  .family .card { justify-content: center; padding: 0.3rem 0.2rem; gap: 0; }
  .family .cards .cname { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
  .family .card[aria-current="page"] { box-shadow: inset 0 -3px 0 var(--gold-rule); }
  .family .cards .card img { width: 100%; max-width: var(--tile-logo); height: auto; aspect-ratio: 1 / 1; }
  .family .tail .card { width: auto; padding: 0.3rem 0.2rem; }
  .family .tail .card img { width: 72%; max-width: var(--mark); height: auto; aspect-ratio: 1 / 1; }
  .family .sig { font-size: 1.5rem; padding: 0 0.5rem; }
}
@container footer (max-width: 749px) { .family .sig { font-size: clamp(1.05rem, 7.2cqw - 30px, 1.5rem); } }
@container footer (max-width: 649px) { .family .sig .pre, .family .sig .post { display: none; } .family .sig { padding: 0 0.4rem; } }
@container footer (max-width: 449px) { .family .sig { font-size: clamp(0.85rem, 4.6cqw - 4px, 1.05rem); padding: 0 0.3rem; } .family .card { padding: 0.3rem 0.1rem; } }
/* Phones (< 600 px of content width): the 3 marks and the signature drop to a second line, under a solid grey
   band that separates them from the project cards; logos and marks return to full size. */
@container footer (max-width: 599px) {
  .family .bar { flex-wrap: wrap; row-gap: 0; }
  .family .cards { flex: 1 1 100%; }
  .family .tail { flex: none; }
  .family .sigtile { flex: 1 1 auto; }
  .family .tail .tile-1 { background: var(--band-grey); }
  .family .bar:has(.slice-vr) .tail .tile-1 { background: var(--band-grey); }
  .family .card { padding: 0.3rem 0.2rem; }
  .family .tail .card { width: var(--tile); }
  .family .tail .card img { width: var(--mark); max-width: var(--mark); }
  .family .sig { font-size: clamp(1.05rem, 4.2cqw, 1.5rem); padding: 0 0.4rem; }
}
@container footer (min-width: 420px) and (max-width: 599px) { .family .sig .pre, .family .sig .post { display: inline; } }

/* Scheme-specific marks (GitHub's black and white Invertocat). The generic .only-* rules serve any element; the
   .family .card img.only-* forms (0,3,1) outrank .family .card img { display: block } (0,2,1), so inside a footer tile
   the off-scheme mark is removed from the layout and never takes a tile's width. */
img.only-dark, .only-dark { display: none; }
.family .card img.only-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-scheme="light"]) img.only-light, :root:not([data-scheme="light"]) .family .card img.only-light { display: none; }
  :root:not([data-scheme="light"]) img.only-dark, :root:not([data-scheme="light"]) .family .card img.only-dark { display: block; }
}
[data-scheme="dark"] img.only-light, [data-scheme="dark"] .family .card img.only-light { display: none; }
[data-scheme="dark"] img.only-dark, [data-scheme="dark"] .family .card img.only-dark { display: block; }
[data-scheme="light"] img.only-light, [data-scheme="light"] .family .card img.only-light { display: block; }
[data-scheme="light"] img.only-dark, [data-scheme="light"] .family .card img.only-dark { display: none; }

/* Standard-document elements (aiqt.ai): document control strip, numbered clauses, framed notes, framed registers */
.control { display: flex; flex-wrap: wrap; gap: 0.3rem 2rem; margin: 0 0 1.6rem; padding: 0.6rem 0; border-top: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong); font: 400 0.8rem/1.5 "JetBrains Mono", ui-monospace, monospace; color: var(--text-muted); max-width: none; }
.control div { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.control dt { text-transform: uppercase; letter-spacing: 0.08em; }
.control dd { margin: 0; color: var(--text); }
.doc h2.clause { display: grid; grid-template-columns: 2.6rem minmax(0, 1fr); column-gap: 0.4rem; align-items: baseline; }
h2.clause .num { font: 400 1.1rem/1.5 "JetBrains Mono", ui-monospace, monospace; color: var(--accent); }
ol.clauses { list-style: none; margin: 0 0 1.4rem; padding: 0; max-width: var(--measure, 72ch); }
ol.clauses > li { display: grid; grid-template-columns: 2.8rem minmax(0, 1fr); margin-bottom: 0.7rem; }
ol.clauses .n { font: 400 0.85rem/1.7 "JetBrains Mono", ui-monospace, monospace; color: var(--text-muted); }
ol.clauses p { margin: 0; }
.note { display: grid; grid-template-columns: 5.2rem minmax(0, 1fr); border: 1px solid var(--rule-strong); border-left: 4px solid var(--brand); background: var(--callout-bg); margin: 0.4rem 0 1.6rem; max-width: var(--measure, 72ch); }
.note > .label { font: 600 0.68rem/1.45 "Public Sans", system-ui, sans-serif; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); padding: 0.85rem 0.6rem 0.8rem 0.8rem; border-right: 1px solid var(--rule-strong); }
.note > div { padding: 0.75rem 1rem; font-size: 1.1rem; line-height: 1.55; }
.note p { margin: 0 0 0.8rem; }
.note p:last-child { margin-bottom: 0; }
.register { border: 1px solid var(--rule-strong); margin: 0.4rem 0 1.6rem; }
.reg-cap { margin: 0; display: flex; flex-wrap: wrap; gap: 0.3rem 1rem; align-items: baseline; padding: 0.6rem 1rem; background: var(--surface-sunken); border-bottom: 1px solid var(--rule-strong); box-shadow: inset 4px 0 0 var(--brand); font: 500 0.68rem/1.4 "Public Sans", system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); }
.reg-cap b { color: var(--text); font-weight: 600; }
.reg-cap .count { margin-left: auto; font: 400 0.8rem/1.4 "JetBrains Mono", ui-monospace, monospace; letter-spacing: 0.04em; text-transform: none; }
.register .tablewrap { margin: 0; padding: 0.2rem 1rem 0.4rem; }
@media (max-width: 600px) { .note { grid-template-columns: minmax(0, 1fr); } .note > .label { border-right: 0; border-bottom: 1px solid var(--rule-strong); padding: 0.5rem 0.8rem; } .doc h2.clause { grid-template-columns: 2.2rem minmax(0, 1fr); } }

/* Spacing between page regions: 4rem; inside the text: the 0.6rem grid */
.pagehead { padding: 1rem 0 0; }
.region + .region { padding-top: 0; }
hr.space { border: 0; margin: 0; height: 2.4rem; }

/* Entry points: 1 row of equal tiles, numeral above title, metadata under the title; the landing page's only navigation list */
.entries { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 1rem 2.2rem; counter-reset: e; }
.entries li { counter-increment: e; }
.entries a { display: flex; flex-direction: column; align-items: flex-start; text-decoration: none; color: var(--text); padding: 0.3rem 0; }
.entries a::before { content: counter(e); font: 300 2.3rem/1 "Newsreader", serif; color: var(--accent); font-variant-numeric: lining-nums; margin-bottom: 0.45rem; }
.entries .t { font: 600 1.4rem/1.2 "Newsreader", serif; }
.entries .n { font: 400 0.8rem/1.6 "JetBrains Mono", ui-monospace, monospace; color: var(--text-muted); margin-top: 0.15rem; }
.entries .d { font: 400 1.05rem/1.45 "Public Sans", system-ui, sans-serif; color: var(--text-muted); margin-top: 0.4rem; }
.entries:has(li:nth-child(5)) .t { font-size: 1.2rem; }
.entries:has(li:nth-child(5)) .d { font-size: 0.95rem; }
.entries a:hover .t { color: var(--link-hover); }

/* Figures: a row of large numbers, the visual anchor of a reference page */
.figures { display: flex; flex-wrap: wrap; gap: 1rem 3rem; margin: 0.2rem 0 1.4rem; }
.fig { display: grid; gap: 0.2rem; padding-top: 0.4rem; border-top: 3px solid var(--brand); min-width: 7rem; }
.fig .num { font: 300 3rem/1 "Newsreader", serif; color: var(--accent); font-variant-numeric: lining-nums; }
.fig .cap { font: 500 0.72rem/1.4 "Public Sans", system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); }

/* Compact figures (1.4.0): up to 6 figures on 1 line in the text column, smaller numerals, equal shares of the width;
   at 900 px and below, rows of 3. Markup: <div class="figures compact"> with the usual .fig children. */
.figures.compact { flex-wrap: nowrap; gap: 0.8rem 1.6rem; }
.figures.compact .fig { flex: 1 1 0; min-width: 0; }
.figures.compact .num { font-size: 2.2rem; }
.figures.compact .cap { letter-spacing: 0.08em; }
@media (max-width: 900px) { .figures.compact { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem 1.2rem; } }

/* Figure beside text (1.4.0): 1 figure and a short paragraph side by side, stacked at 600 px and below.
   Markup: <div class="fig-aside"><div class="fig">...</div><p>...</p></div>. */
.fig-aside { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.6rem 1.6rem; align-items: start; margin: 0.2rem 0 1.4rem; }
.fig-aside > p { margin: 0.4rem 0 0; }
@media (max-width: 600px) { .fig-aside { grid-template-columns: minmax(0, 1fr); } }

/* Inline accent (1.4.0): a number or key term in running text in the site's --accent (a text-safe colour,
   4.5:1 or more on every surface, per contrast-report.txt). Emphasis only: the sentence reads the same without it,
   so no meaning depends on colour (WCAG 2.2, 1.4.1). Markup: <span class="accent">28</span>. */
span.accent { color: var(--accent); font-variant-numeric: lining-nums; }

/* Brand marker (1.4.0), <mark class="marker">: emphasis in the site's rainbow colour that leaves the text in --text. A band of --brand
   behind the lower part of the line; --brand stays decorative and never colours text (section 6.1). Underlining
   was not used, because links are underlined. Browsers without color-mix() draw a thin solid --brand band. */
mark.marker { color: inherit; padding: 0 0.08em; background: linear-gradient(transparent 82%, var(--brand) 82%); }
@supports (background: color-mix(in srgb, red 50%, transparent)) {
  mark.marker { background: linear-gradient(transparent 58%, color-mix(in srgb, var(--brand) 38%, transparent) 58%); }
}

/* Steps: large brand-coloured numerals */
.steps { list-style: none; margin: 0 0 1.4rem; padding: 0; counter-reset: st; }
.steps li { counter-increment: st; display: grid; grid-template-columns: 3.2rem minmax(0, 1fr); column-gap: 0.6rem; align-items: start; margin-bottom: 1.1rem; }
.steps li::before { content: counter(st); font: 300 2.6rem/1 "Newsreader", serif; color: var(--accent); font-variant-numeric: lining-nums; padding-top: 0.1rem; }
.steps li > span { padding-top: 0.25rem; }

/* Next step: closes every inner page */
.next { margin: 2.4rem 0 0.6rem; padding-top: 1.2rem; border-top: 3px solid var(--brand); }
.next p { margin: 0 0 0.6rem; color: var(--text-muted); font-size: 1.1rem; }
:is(.doc, .doc > section, .doc > article) > .next { grid-column: 2; }

/* iPad portrait and narrower: 1 column, labels above content, rail under the h1 */
@media (max-width: 1000px) {
  .mast { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "brand scheme" "pages pages"; row-gap: 0.2rem; }
  .brand { margin-right: 0; }
  .nav { justify-content: flex-start; padding-bottom: 0.1rem; }
  .doc { grid-template-columns: minmax(0, 1fr); gap: 0; }
  :is(.doc, .doc > section, .doc > article) > *, :is(.doc, .doc > section, .doc > article) > .lbl, :is(.doc, .doc > section, .doc > article) > .wide, :is(.doc, .doc > section, .doc > article) > .full { grid-column: 1; }
  :is(.doc, .doc > section, .doc > article) > .lbl, :is(.doc, .doc > section, .doc > article) > .lbl.sec, :is(.doc, .doc > section, .doc > article) > .lbl.blk { padding-top: 1.4rem; margin-bottom: 0.4rem; }
  :is(.doc, .doc > section, .doc > article) > .lbl.first { padding-top: 0; }
  :is(.doc, .doc > section, .doc > article) > .lbl + h2 { margin-top: 0; }
  :is(.doc, .doc > section, .doc > article) > .lbl.blk + .tablewrap { margin-top: 0.2rem; }
  :is(.doc, .doc > section, .doc > article) > .side { grid-row: auto; padding-top: 0; margin: 0 0 1.6rem; }
  :is(.doc, .doc > section, .doc > article) > .side dd { font-size: 0.95rem; }
  :is(.doc, .doc > section, .doc > article) > .rail { grid-column: 1; grid-row: auto; position: static; margin: 0.4rem 0 1.6rem; max-width: 62ch; }
  .rail ol { columns: 2; column-gap: 2rem; }
  .rail li { break-inside: avoid; }
  :is(.doc, .doc > section, .doc > article) > h1 + .rail { order: 0; }
  .region { grid-template-columns: minmax(0, 1fr); gap: 0.2rem; padding-bottom: 2.2rem; }
  .region > .lbl { padding-top: 0; }
  .doc { grid-template-columns: minmax(0, 1fr); }
  .rail-logo { max-width: 7rem; margin: 0.6rem 0 0.8rem; }
  .rail > .lbl, .rail > ol, .rail > ul { margin-left: calc(7rem * var(--logo-inset)); }
  .hero { grid-template-columns: minmax(0, 1fr) clamp(9rem, 24vw, 13rem); column-gap: 2rem; padding: 1rem 0 2.2rem; }
  .hero { padding-right: 0; }
  .statement { font-size: clamp(2.4rem, 98cqw / var(--sw), 3.2rem); }
  .plan.three { columns: 2; }
  .entries { grid-auto-flow: row; grid-template-columns: minmax(0, 1fr); gap: 0.6rem 0; }
  .entries a { display: grid; grid-template-columns: 2.6rem minmax(0, 1fr); grid-template-areas: "n t" "n m" "n d"; column-gap: 0.4rem; }
  .entries a::before { grid-area: n; margin: 0; }
  .entries .t { grid-area: t; } .entries .n { grid-area: m; } .entries .d { grid-area: d; max-width: 62ch; }
  :is(.doc, .doc > section, .doc > article) > .next { grid-column: 1; }
}
@media (min-width: 1001px) {
  .pair { grid-template-columns: 1fr 1fr; gap: 2rem; }
  .srcview { grid-template-columns: 1fr 1fr; gap: 2rem; }
}
@media (max-width: 600px) {
  .plan, .plan.three { columns: 1; }
  .rail ol { columns: 1; }
  .hero { grid-template-columns: minmax(0, 1fr) 5.5rem; grid-template-areas: "kicker art" "title title" "intro intro" "start start"; column-gap: 1rem; row-gap: 0; padding: 0.6rem 0 2rem; }
  .hero-art { align-self: start; }
  .hero-art img { width: 86%; }
  .hero .lbl { align-self: center; }
  .hero-text { display: contents; }
  .figure .wide { display: none; }
  .figure .stack { display: block; max-width: 20rem; margin: 0 auto; }
  body { font-size: 1.125rem; }
  .statement { font-size: 2.2rem; margin-bottom: 0.8rem; }
  .statement.two em { display: block; white-space: normal; text-wrap: balance; }
  .lead, .hero .intro { font-size: 1.2rem; }

  .doc h1 { font-size: 2.2rem; }
  .doc h2 { font-size: 1.7rem; }
  .fig .num { font-size: 2.4rem; }
  .mast { padding-top: 1.1rem; padding-bottom: 1rem; }
  pre, .code { padding: 1rem 1rem; }
  pre.hascopy { padding-top: 3rem; }
  dl.record.cols { grid-template-columns: 1fr 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-art { animation: none; }
  .start .arrow { transition: none; }
  .start:hover .arrow { transform: none; }
}

/* Dark mode: thin headings gain a little tracking; the field becomes the lit object */
@media (prefers-color-scheme: dark) {
  :root:not([data-scheme="light"]) .statement, :root:not([data-scheme="light"]) .doc h1 { letter-spacing: 0.01em; }
}
[data-scheme="dark"] .statement, [data-scheme="dark"] .doc h1 { letter-spacing: 0.01em; }


/* Left-rail page at 1000 px and below: 1 column, the left list under the h1 as the right rail sits there, not sticky. */
@media (max-width: 1000px) {
  .doc.left-rail, .doc.no-rail { grid-template-columns: minmax(0, 1fr); }
  :is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > *,
  :is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl,
  :is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .wide,
  :is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .next,
  :is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .full { grid-column: 1; }
  :is(.doc.left-rail, .doc.left-rail > section, .doc.left-rail > article) > .lbl.first { padding-top: 0; }
  .doc.left-rail > .lrail { grid-row: auto; align-self: start; margin: 0.4rem 0 1.6rem; max-width: 62ch; }
  .lrail > nav { position: static; max-height: none; overflow: visible; padding-left: calc(7rem * var(--logo-inset)); }
  .lrail .rail-logo { max-width: 7rem; margin: 0.6rem 0 0.8rem; }
  .lrail ul { columns: 2; column-gap: 2rem; }
  .lrail li { break-inside: avoid; }
}
@media (max-width: 600px) { .lrail ul { columns: 1; } }

/* Fallback for browsers without container queries (before Chromium 105, Safari 16, Firefox 110): the footer bar
   wraps instead of overflowing, so the page never scrolls sideways. */
@supports not (container-type: inline-size) {
  .family .bar { flex-wrap: wrap; }
  .family .cards { flex: 1 1 100%; flex-wrap: wrap; }
}

/* Tables on paper. From 1.7.0 a matrix printed its full height; from 1.8.0 every table prints whole, in both
   directions. Every .tablewrap loses its height cap and its scrolling, sticky cells stay in place, the header row
   repeats on each page and a row is kept on 1 page where it fits. Each table fits the page width: it takes the
   page's width; a fixed table drops its 56rem minimum and its rem column widths and is laid out by its content
   (a matrix keeps its fixed layout; col.w<N> percentages stay); and every cell wraps, a long token breaking
   anywhere, so no column runs past the paper's edge. A matrix with many columns becomes narrow per column on
   paper: print a preset view, which keeps only its columns. A rotated header runs its organization and group on
   after its name, so it stays 1 line wide. For matrix tables the column controls are hidden, and every cell is
   black text on white, with no tint or heat. table.matrix.matrix doubles the class so that these rules outrank
   the heat steps and the group tags; the preset selectors name the contexts whose display rules they must
   outrank. */
@media print {
  .tablewrap, .tablewrap.bounded, .tablewrap:has(> table.sticky) { max-height: none; overflow: visible; }
  table.sticky thead th, table.sticky-col :is(th, td):first-child { position: static; }
  table thead { display: table-header-group; }
  table tr { break-inside: avoid; }
  table, table.fixed { width: 100%; min-width: 0; table-layout: auto; }
  table.matrix.fixed { table-layout: fixed; }
  .fixed col { width: auto; }
  :is(table, table.matrix.matrix) :is(th, td), :is(table, table.matrix.matrix) :is(th, td) :is(code, .mono, .hash) { white-space: normal; overflow-wrap: anywhere; }
  table.matrix th.rot .org, table.matrix:not([data-one-grp]) th.rot .grp { display: inline; margin: 0 0 0 0.4em; }
  [data-col-toggles], .lrail li [data-preset], .chips [data-preset], [data-preset] { display: none; }
  table.matrix.matrix :is(thead, tbody) tr > :is(th, td) { background: var(--print-paper); color: var(--print-ink); }
  table.matrix.matrix :is(thead, tbody) tr > :is(th, td) :is(a, code, .org, .grp, .sub, .n) { color: var(--print-ink); background: var(--print-paper); }
  .heat-legend .tag { background: var(--print-paper); color: var(--print-ink); }
}
