/* ============================================================
   BLUE INK INTERFACE — PRIMITIVES
   Requires tokens.css. Prefix: .bi-
   Three inks on one sheet of paper. Black ink is content, blue
   ink is structure, paper is the ground. One line weight. Corners
   are 0 or infinite. Whitespace does the work a box would do.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

body.bi-body {
  margin: 0;
  background: var(--bi-paper);
  color: var(--bi-on-paper);
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-md);
  line-height: 1.5;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ============================================================
   STRUCTURE — sheet, region, block, spine, rules, nav, footer
   ============================================================ */

/* ---- SHEET (the page) ------------------------------------------
   Paper with a generous margin and hairline-divided regions. The
   default answer to "sheet, card or block?".                      */
.bi-sheet {
  min-width: 0;
  padding: var(--bi-pad);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 0;                         /* regions touch; the rule divides them */
}
.bi-sheet--margin { padding: var(--bi-pad-lg); }
.bi-sheet--flush  { padding: 0; }

/* ---- REGION (a rule-divided region with a caption slot) -------
   Two regions that touch are divided by exactly one hairline (rule
   2). A region is a container, so its children respond to the
   space they are actually in.                                     */
.bi-region {
  min-width: 0;
  position: relative;
  padding: var(--bi-pad) 0;
  border-top: var(--bi-rule) solid var(--bi-line);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--bi-gap);
}
.bi-region:first-child,
.bi-region--open { border-top: 0; }
.bi-region--blue { border-top-color: var(--bi-line-blue); }
.bi-region--faint { border-top-color: var(--bi-line-faint); }
.bi-region--pad { padding-inline: var(--bi-pad); }

/* The caption slot: a mono caption, optionally with a trailing hint
   or count. Sits at the region's top-left, above the content.     */
.bi-region__head {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px var(--bi-gap);
}

/* ---- BLOCK (the one solid region per screen) -------------------
   Holds the index and the title — it is where the eye lands first.
   In blueprint mode it becomes paper-white with cobalt text; the
   tokens do that, the component does not know.                    */
.bi-block {
  min-width: 0;
  container-type: inline-size;
  container-name: bi-block;
  background: var(--bi-blue);
  color: var(--bi-on-blue);
  --bi-line: var(--bi-on-blue);   /* hairlines inside the block are drawn in its ink */
  --bi-line-blue: var(--bi-on-blue);
  --bi-line-faint: var(--bi-on-blue-dim);
  --bi-dim: var(--bi-on-blue-dim);
  --bi-faint: var(--bi-on-blue-dim);
  --bi-ink: var(--bi-on-blue);
  --bi-on-paper: var(--bi-on-blue);
  /* carriers, so descendants can swap the two block inks (below) */
  --_bi-block-bg: var(--bi-blue);
  --_bi-block-ink: var(--bi-on-blue);
  padding: var(--bi-pad);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--bi-gap);
}
/* Inside the block the structural ink IS the block's ink: captions,
   marks, stamps, outlines, hairline buttons and links all keep working
   with no special case. A solid element inside inverts (paper fill,
   cobalt text) — but rule 3 says there is no second solid region.   */
.bi-block > * {
  --bi-blue: var(--_bi-block-ink);
  --bi-blue-2: var(--_bi-block-ink);
  --bi-on-blue: var(--_bi-block-bg);
  --bi-tint: var(--bi-on-blue-dim);
  --bi-on-tint: var(--_bi-block-bg);
}
.bi-block--lg { padding: var(--bi-pad-lg) var(--bi-pad); }

/* index + title + aside on one line; the aside (a single big letter
   or number) sits at the right and drops beneath when it must.   */
.bi-block__head {
  min-width: 0;
  display: grid;
  /* index and aside are single short tokens; the title takes the rest
     and wraps inside its own column, so S1 and A stay on its first line. */
  grid-template-columns: max-content minmax(0, 1fr) max-content;
  align-items: baseline;
  gap: var(--bi-gap) calc(var(--bi-gap) * 1.5);
}
.bi-block__index {
  min-width: 0;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  /* Fluid against the BLOCK, not the viewport: a block in a half-width
     column must not break "Modular" into "Modul-ar". */
  font-size: min(var(--bi-t-2xl), 13cqi);
  letter-spacing: var(--bi-track-display);
  line-height: 1;
}
.bi-block__title {
  min-width: 0;
  overflow-wrap: anywhere;
  margin: 0;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: min(var(--bi-t-2xl), 13cqi);
  letter-spacing: var(--bi-track-display);
  line-height: 1;
}
.bi-block__aside {
  min-width: 0;
  justify-self: end;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: min(var(--bi-t-2xl), 13cqi);
  letter-spacing: var(--bi-track-display);
  line-height: 1;
}

/* ---- SPINE (a tall vertical block for a rail) ------------------
   Rotated mono text. Drops to a horizontal band under 720px.      */
.bi-spine {
  min-width: 0;
  background: var(--bi-blue);
  color: var(--bi-on-blue);
  --bi-line: var(--bi-on-blue);
  --bi-dim: var(--bi-on-blue-dim);
  --bi-ink: var(--bi-on-blue);
  width: var(--bi-spine-w);
  min-height: 100%;
  padding: var(--bi-pad) 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: var(--bi-pad);
}
.bi-spine__text {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  white-space: nowrap;
}
.bi-spine__text--down { transform: none; }
.bi-spine__mark {                 /* a small glyph or stamp at one end */
  display: grid; grid-template-columns: minmax(0, 1fr); place-items: center;
  width: var(--bi-tap); height: var(--bi-tap);
}

/* A sheet with a spine at the left. The spine is a fixed narrow
   column; everything else is fluid. Below 720px the spine becomes
   a horizontal band above the content (see RESPONSE).            */
.bi-sheet--spined {
  padding: 0;
  grid-template-columns: var(--bi-spine-w) minmax(0, 1fr);
  gap: 0;
}
.bi-sheet--spined > .bi-spine { grid-row: 1 / -1; }
.bi-sheet--spined > .bi-sheet__page {
  min-width: 0;
  padding: var(--bi-pad);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
}

/* ---- RULE (a hairline, on its own) ----------------------------- */
.bi-rule {
  display: block;
  border: 0;
  margin: 0;
  height: 0;
  width: 100%;
  border-top: var(--bi-rule) solid var(--bi-line);
}
.bi-rule--blue  { border-top-color: var(--bi-line-blue); }
.bi-rule--faint { border-top-color: var(--bi-line-faint); }
.bi-rule--v {
  width: 0;
  height: auto;
  align-self: stretch;
  border-top: 0;
  border-left: var(--bi-rule) solid var(--bi-line);
}
.bi-rule--v.bi-rule--blue  { border-left-color: var(--bi-line-blue); }
.bi-rule--v.bi-rule--faint { border-left-color: var(--bi-line-faint); }

/* ---- NAV (top bar) ---------------------------------------------
   Mark left, centered links, action right. A hairline below. Wraps
   under 720px — never a hamburger (rule 13, and a spec sheet shows
   its contents).                                                   */
.bi-nav {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bi-gap) var(--bi-pad);
  padding: var(--bi-gap) 0;
  border-bottom: var(--bi-rule) solid var(--bi-line);
}
.bi-nav__mark {
  flex: 0 1 auto;
  min-width: 0;
  display: inline-flex; align-items: center;
  min-height: var(--bi-tap);
}
.bi-nav__links {
  flex: 1 1 20ch;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 var(--bi-gap);
  list-style: none;
  margin: 0; padding: 0;
}
.bi-nav__link {
  display: inline-flex; align-items: center;
  min-height: var(--bi-tap);
  padding: 0 4px;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-sm);
  color: var(--bi-on-paper);
  text-decoration: none;
  border-bottom: var(--bi-rule) solid transparent;
  cursor: pointer;
}
.bi-nav__link:hover { color: var(--bi-blue); }
.bi-nav__link[aria-current="page"],
.bi-nav__link[aria-current="true"] { border-bottom-color: var(--bi-line-blue); }
.bi-nav__action {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: auto;
  display: inline-flex; align-items: center; gap: var(--bi-gap);
}

/* ---- FOOTER (colophon row) ------------------------------------- */
.bi-footer {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px var(--bi-pad);
  padding: var(--bi-gap) 0;
  border-top: var(--bi-rule) solid var(--bi-line);
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
}
.bi-footer > * { min-width: 0; overflow-wrap: anywhere; }

/* ---- LAYOUT HELPERS -------------------------------------------- */
/* Spare height collects at the end (align-content: start), so a
   short column does not spread its rows apart.                    */
.bi-stack { display: grid; grid-template-columns: minmax(0, 1fr);
            align-content: start; gap: var(--bi-gap); min-width: 0; }
.bi-row   { display: flex; flex-wrap: wrap; align-items: center;
            gap: var(--bi-gap); min-width: 0; }
.bi-row--between { justify-content: space-between; }
.bi-row--end     { justify-content: flex-end; }
.bi-split { display: grid; gap: var(--bi-pad); min-width: 0;
            grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
.bi-cols  { display: grid; gap: var(--bi-gap) var(--bi-pad); min-width: 0;
            grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); }
.bi-cols--tight { grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr)); }
.bi-fill  { flex: 1 1 0; min-width: 0; }
.bi-scroll-x {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  min-width: 0;
}
.bi-tight { gap: 4px; }

/* ============================================================
   TYPE — two roles. The grotesque for what a human reads; the
   monospace for what the system labels. Size carries hierarchy,
   never weight.
   ============================================================ */

.bi-display {
  margin: 0;
  overflow-wrap: anywhere;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  letter-spacing: var(--bi-track-display);
  line-height: 1.04;
}
.bi-display--md  { font-size: var(--bi-t-md);  line-height: 1.3; letter-spacing: -0.005em; }
.bi-display--lg  { font-size: var(--bi-t-lg);  line-height: 1.25; letter-spacing: -0.01em; }
.bi-display--xl  { font-size: var(--bi-t-xl);  line-height: 1.12; }
.bi-display--2xl { font-size: var(--bi-t-2xl); }
.bi-display--3xl { font-size: var(--bi-t-3xl); line-height: 0.95; }
.bi-display--blue { color: var(--bi-blue); }

.bi-lede {
  margin: 0;
  max-width: 44ch;
  overflow-wrap: anywhere;
  font-size: var(--bi-t-lg);
  line-height: 1.4;
  letter-spacing: -0.01em;
}
.bi-prose {
  max-width: 64ch;
  min-width: 0;
  font-size: var(--bi-t-md);
  line-height: 1.55;
  overflow-wrap: anywhere;
}
.bi-prose > * { margin: 0; }
.bi-prose > * + * { margin-top: 0.9em; }
.bi-prose--sm { font-size: var(--bi-t-sm); }

/* A caption: mono, uppercase, tracked, small. Structure's voice.  */
.bi-caption {
  margin: 0;
  font-family: var(--bi-face-data);
  font-weight: 400;
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--bi-dim);
  overflow-wrap: anywhere;
}
.bi-caption--blue  { color: var(--bi-blue); }
.bi-caption--ink   { color: var(--bi-on-paper); }
.bi-caption--faint { color: var(--bi-faint); }

/* Anything the system wrote: values, units, timestamps, IDs.      */
.bi-data {
  font-family: var(--bi-face-data);
  font-weight: 400;
  font-size: var(--bi-t-sm);
  letter-spacing: 0;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  text-transform: none;
}
.bi-data--xs { font-size: var(--bi-t-xs); }
.bi-data--unit { text-transform: uppercase; letter-spacing: var(--bi-track-caption); }

/* ---- INDEX (the S1 / S2 / S3 stack) ---------------------------- */
.bi-index {
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 0;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-3xl);
  letter-spacing: var(--bi-track-display);
  line-height: 0.9;
  color: var(--bi-on-paper);
}
.bi-index__alt { color: var(--bi-faint); }
.bi-index--inline {
  display: flex; flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.35em;
  font-size: var(--bi-t-xl);
  line-height: 1;
}
.bi-index--sm { font-size: var(--bi-t-xl); line-height: 1; }

/* ---- COUNT (203/234) ------------------------------------------- */
.bi-count {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-sm);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  white-space: nowrap;
}
.bi-count--lg { font-size: var(--bi-t-lg); }

/* ---- LINK ------------------------------------------------------ */
/* The underline is a text-decoration, not a border, so the vertical
   padding that gives an inline link its hit area (see RESPONSE) never
   moves the rule away from the baseline.                          */
.bi-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--bi-line-blue);
  text-decoration-thickness: var(--bi-rule);
  text-underline-offset: 0.2em;
  cursor: pointer;
}
.bi-link:hover { color: var(--bi-blue); }
.bi-link--blue { color: var(--bi-blue); }
.bi-link--blue:hover { color: var(--bi-blue-2); text-decoration-color: var(--bi-blue-2); }

/* ---- WORDMARK -------------------------------------------------- */
.bi-wordmark {
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-medium);
  font-size: var(--bi-t-sm);
  letter-spacing: -0.01em;
  color: var(--bi-on-paper);
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex; align-items: center; gap: 8px;
}
.bi-wordmark sup {
  font-family: var(--bi-face-data);
  font-size: 0.7em;
  letter-spacing: var(--bi-track-caption);
  color: var(--bi-blue);
  vertical-align: super;
  line-height: 0;
}

/* ============================================================
   CONTENT — list, spec, key/value, log, stat, figure, delta,
   card, media, drawing, plan, target, crosshair
   ============================================================ */

/* ---- LIST (the "Details" list) ---------------------------------
   Rows divided by hairlines. Mono key at left, title, action at
   right. Repeating keys are usually written once per group.     */
.bi-list {
  list-style: none;
  margin: 0; padding: 0;
  min-width: 0;
  border-top: var(--bi-rule) solid var(--bi-line);
  container-type: inline-size;
  container-name: bi-list;
}
.bi-list--flush { border-top: 0; }
.bi-list__row {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) auto;
  align-items: center;
  gap: var(--bi-gap);
  min-height: var(--bi-row);
  padding: 6px 0;
  border-bottom: var(--bi-rule) solid var(--bi-line);
}
.bi-list__row--nokey { grid-template-columns: minmax(0, 1fr) auto; }
.bi-list__key {
  min-width: 0;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
  overflow-wrap: anywhere;
}
.bi-list__title {
  min-width: 0;
  font-size: var(--bi-t-sm);
  overflow-wrap: anywhere;
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
}
.bi-list__action {
  justify-self: end;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  white-space: nowrap;
}
.bi-list__row[aria-current="true"] .bi-list__title { font-weight: var(--bi-weight-medium); }

/* ---- SPEC (spec table) -----------------------------------------
   A caption-bar header — the ONLY filled strip that appears inside
   a region. It counts as the screen's block: if a .bi-block exists
   elsewhere on the screen, use .bi-spec--plain and the header
   becomes a hairline + caption. Mono keys, grotesque values.     */
.bi-spec {
  min-width: 0;
  margin: 0;
  container-type: inline-size;
  container-name: bi-spec;
}
.bi-spec__head,
.bi-spec__row {
  min-width: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--bi-gap);
  align-items: baseline;
  padding: 8px 0;
  border-bottom: var(--bi-rule) solid var(--bi-line);
}
.bi-spec__head {
  background: var(--bi-blue);
  color: var(--bi-on-blue);
  border-bottom: 0;
  padding: 6px 8px;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
}
.bi-spec--plain .bi-spec__head {
  background: transparent;
  color: var(--bi-dim);
  padding: 6px 0;
  border-top: var(--bi-rule) solid var(--bi-line);
  border-bottom: var(--bi-rule) solid var(--bi-line);
}
.bi-spec__key {
  min-width: 0;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
  overflow-wrap: anywhere;
}
.bi-spec__head .bi-spec__key { color: inherit; }
.bi-spec__val {
  min-width: 0;
  font-size: var(--bi-t-sm);
  overflow-wrap: anywhere;
}
.bi-spec__val--data { font-family: var(--bi-face-data); font-size: var(--bi-t-xs); text-transform: uppercase; letter-spacing: 0.04em; }

/* ---- KEY / VALUE ----------------------------------------------- */
.bi-kv {
  margin: 0;
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}
.bi-kv > div {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 4px var(--bi-gap);
  padding: 6px 0;
  border-bottom: var(--bi-rule) solid var(--bi-line-faint);
}
.bi-kv > div:last-child { border-bottom: 0; }
.bi-kv dt {
  margin: 0;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
  overflow-wrap: anywhere;
}
.bi-kv dd {
  margin: 0;
  min-width: 0;
  font-size: var(--bi-t-sm);
  overflow-wrap: anywhere;
}
.bi-kv dd.bi-data { font-size: var(--bi-t-xs); }
.bi-kv--stack > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }

/* ---- LOG (dated rows) ------------------------------------------ */
.bi-log {
  list-style: none;
  margin: 0; padding: 0;
  min-width: 0;
  border-top: var(--bi-rule) solid var(--bi-line);
  container-type: inline-size;
  container-name: bi-log;
}
.bi-log__row {
  min-width: 0;
  display: grid;
  grid-template-columns: 11ch minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--bi-gap);
  min-height: var(--bi-row);
  padding: 4px 0;
  border-bottom: var(--bi-rule) solid var(--bi-line-faint);
}
.bi-log__date {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  font-variant-numeric: tabular-nums;
  color: var(--bi-dim);
  white-space: nowrap;
}
.bi-log__msg {
  min-width: 0;
  font-size: var(--bi-t-sm);
  overflow-wrap: anywhere;
}
.bi-log__end { justify-self: end; }

/* ---- STAT (mark + label + n/N) ---------------------------------- */
.bi-stat {
  min-width: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 2px 10px;
  align-items: start;
}
.bi-stat > .bi-mark { margin-top: 4px; grid-row: 1 / span 2; }
.bi-stat__label {
  min-width: 0;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
  overflow-wrap: anywhere;
}
.bi-stat__value {
  min-width: 0;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-sm);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.bi-stat--current .bi-stat__label { color: var(--bi-blue); }
.bi-stat--current .bi-stat__value { font-weight: var(--bi-weight-medium); }
.bi-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: var(--bi-pad) var(--bi-gap);
  min-width: 0;
}

/* ---- FIGURE (a large light number with a mono unit) ------------ */
.bi-figure {
  min-width: 0;
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 8px;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-xl);
  letter-spacing: var(--bi-track-display);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.bi-figure--lg { font-size: var(--bi-t-2xl); }
.bi-figure--sm { font-size: var(--bi-t-lg); }
.bi-figure__unit {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
}

/* ---- DELTA (a change, with a glyph — never color alone) --------
   Up/down is direction, not status, so it stays in ink. The glyph
   carries it; the alert ink is not for arrows.                    */
.bi-delta {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bi-delta--up::before   { content: "\2191\00a0"; }   /* ↑ */
.bi-delta--down::before { content: "\2193\00a0"; }   /* ↓ */
.bi-delta--flat::before { content: "\2192\00a0"; }   /* → */
.bi-delta--up   { color: var(--bi-blue); }
.bi-delta--down { color: var(--bi-dim); }

/* ---- CARD (a grey-paper inset, for a SET of parallel things) ---
   The stronger claim than a sheet. Use for tiles, tiers, results.
   One card style. Cards are containers.                           */
.bi-card {
  min-width: 0;
  background: var(--bi-paper-2);
  color: var(--bi-on-paper-2);
  border-top: var(--bi-rule) solid var(--bi-line);
  padding: var(--bi-pad);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--bi-gap);
  container-type: inline-size;
  container-name: bi-card;
}
.bi-card--deep { background: var(--bi-paper-3); color: var(--bi-on-paper-3); }
.bi-card--tint { background: var(--bi-tint); color: var(--bi-on-tint); --bi-dim: var(--bi-on-tint); }
.bi-card--outline { background: transparent; border: var(--bi-rule) solid var(--bi-line); }
.bi-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: var(--bi-gap);
  min-width: 0;
}
.bi-card-grid--tight { gap: var(--bi-rule); background: var(--bi-line); }
.bi-card-grid--tight > .bi-card { border-top: 0; }

/* ---- MEDIA (hairline frame + caption) -------------------------- */
.bi-media {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
}
.bi-media__frame {
  position: relative;
  border: var(--bi-rule) solid var(--bi-line);
  background: var(--bi-paper-2);
  overflow: hidden;
  display: block;
}
.bi-media__frame > img,
.bi-media__frame > video { display: block; width: 100%; height: 100%; object-fit: cover; }
.bi-media--wide   .bi-media__frame { aspect-ratio: 16 / 9; }
.bi-media--photo  .bi-media__frame { aspect-ratio: 4 / 3; }
.bi-media--square .bi-media__frame { aspect-ratio: 1; }
.bi-media--tall   .bi-media__frame { aspect-ratio: 3 / 4; }
.bi-media__caption {
  min-width: 0;
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 12px;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
}

/* ---- DRAWING (a frame for SVG line art) ------------------------
   Single weight, non-scaling, in the current ink. Set `color` to
   choose blue or black. Add .bi-draw to the frame to wipe it in;
   the stroke stays 1px throughout.                                 */
.bi-drawing {
  min-width: 0;
  color: var(--bi-blue);
  display: block;
}
.bi-drawing--ink { color: var(--bi-on-paper); }
.bi-drawing > svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.bi-drawing svg * {
  stroke: currentColor;
  fill: none;
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.bi-drawing svg text,
.bi-drawing svg .bi-fill { fill: currentColor; stroke: none; }
.bi-drawing svg .bi-fill-paper { fill: var(--bi-paper); stroke: currentColor; }

/* ---- PLAN (crosshair / dot-grid substrate) --------------------- */
.bi-plan {
  min-width: 0;
  position: relative;
  background-color: var(--bi-paper);
  background-image: radial-gradient(var(--bi-line-faint) 0.6px, transparent 0.9px);
  background-size: 24px 24px;
  background-position: 12px 12px;
}
.bi-plan--lines {
  background-image:
    linear-gradient(to right,  var(--bi-line-faint) var(--bi-rule), transparent var(--bi-rule)),
    linear-gradient(to bottom, var(--bi-line-faint) var(--bi-rule), transparent var(--bi-rule));
  background-size: 48px 48px;
  background-position: 0 0;
}
.bi-plan--card { background-color: var(--bi-paper-2); }

/* ---- TARGET (concentric rings + three spokes) ------------------
   The one decorative motif. Pure CSS: the element is the outer
   ring, ::before the inner ring, ::after the hub; spokes are three
   children rotated by --i. Size it with width.                   */
.bi-target {
  --_bi-target-size: 160px;
  position: relative;
  width: min(var(--_bi-target-size), 100%);
  aspect-ratio: 1;
  border-radius: 50%;
  border: var(--bi-rule) solid currentColor;
  color: var(--bi-blue);
  flex: 0 1 auto;                 /* may shrink: nothing has a fixed minimum width */
  min-width: 0;
}
.bi-target--ink { color: var(--bi-on-paper); }
.bi-target::before,
.bi-target::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  border-radius: 50%;
  border: var(--bi-rule) solid currentColor;
  transform: translate(-50%, -50%);
}
.bi-target::before { width: 43%; height: 43%; }
.bi-target::after  { width: 15%; height: 15%; background: var(--bi-paper); }
.bi-target__spoke {
  position: absolute;
  left: calc(50% - 0.5px);
  bottom: 50%;
  width: var(--bi-rule);
  height: 42%;
  background: currentColor;
  transform-origin: 50% 100%;
  transform: rotate(calc(var(--i, 0) * 120deg));
}
.bi-target--ring2::before { width: 70%; height: 70%; }

/* ---- CROSSHAIR (grid with a blue square) ----------------------- */
.bi-crosshair {
  --_bi-crosshair-size: 48px;
  position: relative;
  width: var(--_bi-crosshair-size);
  height: var(--_bi-crosshair-size);
  flex: 0 0 auto;
  background-image:
    linear-gradient(to right,  var(--bi-line-faint) var(--bi-rule), transparent var(--bi-rule)),
    linear-gradient(to bottom, var(--bi-line-faint) var(--bi-rule), transparent var(--bi-rule));
  background-size: calc(100% / 3) calc(100% / 3);
  background-position: -0.5px -0.5px;
}
.bi-crosshair::after {
  content: "";
  position: absolute;
  left: calc(100% / 3); top: calc(100% / 3);
  width: calc(100% / 3); height: calc(100% / 3);
  border: var(--bi-rule) solid var(--bi-blue);
  background: var(--bi-paper);
}

/* ============================================================
   STAMPS — outlined shapes carrying an uppercase label.
   Rectangle, pill, oval, circle. Corners are 0 or infinite.
   ============================================================ */

.bi-stamp {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 4px 12px;
  border: var(--bi-rule) solid currentColor;
  border-radius: var(--bi-radius);
  color: var(--bi-blue);
  background: transparent;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  vertical-align: middle;
}
.bi-stamp--pill   { border-radius: var(--bi-radius-full); padding-inline: 14px; }
.bi-stamp--oval   { border-radius: 50%; padding-inline: 18px; min-height: 32px; }
.bi-stamp--circle { border-radius: 50%; aspect-ratio: 1; padding: 6px; min-width: 40px; min-height: 40px; }
.bi-stamp--solid  { background: var(--bi-blue); color: var(--bi-on-blue); border-color: var(--bi-blue); }
.bi-stamp--ink    { background: var(--bi-ink); color: var(--bi-paper); border-color: var(--bi-ink); }
.bi-stamp--faint  { color: var(--bi-faint); }
.bi-stamp--ink-line { color: var(--bi-on-paper); }
.bi-stamp--fault  { color: var(--bi-alert); }
.bi-stamp--lg     { font-size: var(--bi-t-sm); min-height: 36px; padding-inline: 16px; }
.bi-stamp--grot   { font-family: var(--bi-face-display); text-transform: none; letter-spacing: -0.01em; font-size: var(--bi-t-sm); }
.bi-stamps {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* Text on a circle. Put the class on the SVG <text> and give it a
   <textPath href="#…">; the circle path itself is a .bi-drawing.  */
.bi-ring-text {
  font-family: var(--bi-face-data);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: currentColor;
  stroke: none;
}

/* ============================================================
   STATUS — a mark plus a word, never a color.
   Filled = live/done. Hollow = waiting. Slashed = fault.
   ============================================================ */

.bi-mark {
  display: inline-block;
  flex: 0 0 auto;
  width: var(--bi-mark);
  height: var(--bi-mark);
  border-radius: 50%;
  border: var(--bi-rule) solid var(--bi-blue);
  background: transparent;
  vertical-align: -1px;
  position: relative;
}
.bi-mark--on   { background: var(--bi-blue); }
.bi-mark--off  { background: transparent; }
.bi-mark--ink  { background: var(--bi-on-paper); border-color: var(--bi-on-paper); }
.bi-mark--faint { border-color: var(--bi-faint); }
.bi-mark--fault {
  border-color: var(--bi-alert);
  background: linear-gradient(135deg,
    transparent calc(50% - 0.5px), var(--bi-alert) calc(50% - 0.5px),
    var(--bi-alert) calc(50% + 0.5px), transparent calc(50% + 0.5px));
}
.bi-mark--sq { border-radius: 0; }

.bi-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-on-paper);
  white-space: nowrap;
}
.bi-status--fault { color: var(--bi-alert); }
.bi-status--dim   { color: var(--bi-dim); }

/* ---- SPOT INKS ---------------------------------------------------
   A spot ink re-inks the structural line inside one scope: put
   .bi-spot--green on a button, a stamp, a mark, a meter, a chip
   strip or a small group, and everything there that would be blue
   (rules, fills, marks, links, focus rings, the s1 series) takes the
   spot instead; ink and paper are unchanged. For identity and
   emphasis on request. Never a region (rule 3), at most two per
   screen, never the only signal of status or category (rules 9, 10). */
.bi-spot--green {
  --bi-blue: var(--bi-spot-green); --bi-blue-2: var(--bi-spot-green); --bi-line-blue: var(--bi-spot-green);
  --bi-on-blue: var(--bi-on-spot-green); --bi-tint: var(--bi-spot-green-tint); --bi-s1: var(--bi-spot-green);
}
.bi-spot--amber {
  --bi-blue: var(--bi-spot-amber); --bi-blue-2: var(--bi-spot-amber); --bi-line-blue: var(--bi-spot-amber);
  --bi-on-blue: var(--bi-on-spot-amber); --bi-tint: var(--bi-spot-amber-tint); --bi-s1: var(--bi-spot-amber);
}
.bi-spot--red {
  --bi-blue: var(--bi-spot-red); --bi-blue-2: var(--bi-spot-red); --bi-line-blue: var(--bi-spot-red);
  --bi-on-blue: var(--bi-on-spot-red); --bi-tint: var(--bi-spot-red-tint); --bi-s1: var(--bi-spot-red);
}
.bi-spot--violet {
  --bi-blue: var(--bi-spot-violet); --bi-blue-2: var(--bi-spot-violet); --bi-line-blue: var(--bi-spot-violet);
  --bi-on-blue: var(--bi-on-spot-violet); --bi-tint: var(--bi-spot-violet-tint); --bi-s1: var(--bi-spot-violet);
}
.bi-spot--teal {
  --bi-blue: var(--bi-spot-teal); --bi-blue-2: var(--bi-spot-teal); --bi-line-blue: var(--bi-spot-teal);
  --bi-on-blue: var(--bi-on-spot-teal); --bi-tint: var(--bi-spot-teal-tint); --bi-s1: var(--bi-spot-teal);
}
.bi-spot--magenta {
  --bi-blue: var(--bi-spot-magenta); --bi-blue-2: var(--bi-spot-magenta); --bi-line-blue: var(--bi-spot-magenta);
  --bi-on-blue: var(--bi-on-spot-magenta); --bi-tint: var(--bi-spot-magenta-tint); --bi-s1: var(--bi-spot-magenta);
}

/* ============================================================
   INTERACTION — buttons, tabs, fields, toggles, chips, choices
   ============================================================ */

/* ---- BUTTON ----------------------------------------------------
   Default: text with a hairline beneath. --outline: a pill stamp.
   --key: the solid blue pill — one per screen; it is the block if
   nothing else is. --fault: the fourth ink.                       */
.bi-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--bi-tap);
  padding: 4px 2px;
  margin: 0;
  background: transparent;
  color: var(--bi-on-paper);
  border: 0;
  border-bottom: var(--bi-rule) solid var(--bi-line-blue);
  border-radius: 0;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-sm);
  letter-spacing: -0.005em;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: none var(--bi-snap);   /* state changes snap */
  white-space: nowrap;
}
.bi-btn:hover  { color: var(--bi-blue); }
.bi-btn:active { color: var(--bi-blue-2); border-color: var(--bi-blue-2); }
.bi-btn--outline,
.bi-btn--key {
  padding: 4px 18px;
  border: var(--bi-rule) solid var(--bi-blue);
  border-radius: var(--bi-radius-full);
}
.bi-btn--outline:hover { color: var(--bi-blue); }
.bi-btn--key {
  background: var(--bi-blue);
  color: var(--bi-on-blue);
}
.bi-btn--key:hover  { background: var(--bi-blue-2); border-color: var(--bi-blue-2); color: var(--bi-on-blue); }
.bi-btn--key:active { background: var(--bi-blue-2); }
.bi-btn--fault { color: var(--bi-alert); border-color: var(--bi-alert); }
.bi-btn--fault:hover { color: var(--bi-alert); }
.bi-btn--fault.bi-btn--key { background: var(--bi-alert); color: var(--bi-on-alert); }
.bi-btn--mono {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
}
.bi-btn--sm { font-size: var(--bi-t-xs); padding-inline: 12px; }
.bi-btn--wide { width: 100%; }
.bi-btn[disabled] {
  color: var(--bi-faint);
  border-color: var(--bi-faint);
  background: transparent;
  cursor: not-allowed;
}
.bi-btn-row {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bi-gap) var(--bi-pad);
}
.bi-btn-row--bank { gap: 8px; }
.bi-btn-row--bank > .bi-btn { flex: 1 1 120px; }

/* A control is a control whether it is a <button> or an <a>. */
a.bi-btn, a.bi-tab, a.bi-chip, a.bi-option, a.bi-stamp, a.bi-nav__link, a.bi-wordmark {
  text-decoration: none;
}

/* Focus: a hairline ring in the structural ink, offset so it never
   merges with the element's own rule. Never removed.             */
.bi-btn:focus-visible,
.bi-tab:focus-visible,
.bi-chip:focus-visible,
.bi-link:focus-visible,
.bi-nav__link:focus-visible,
.bi-input:focus-visible,
.bi-select:focus-visible,
.bi-textarea:focus-visible,
.bi-option:focus-visible,
.bi-duo__side:focus-visible,
.bi-stamp:focus-visible,
.bi-list__row:focus-visible {
  outline: var(--bi-rule) solid var(--bi-blue);
  outline-offset: 3px;
}

/* ---- TABS ------------------------------------------------------ */
.bi-tabs {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0 var(--bi-pad);
  border-bottom: var(--bi-rule) solid var(--bi-line);
}
.bi-tab {
  flex: 0 1 auto;
  display: inline-flex; align-items: center;
  min-height: var(--bi-tap);
  padding: 4px 0;
  margin-bottom: calc(var(--bi-rule) * -1);
  background: transparent;
  border: 0;
  border-bottom: var(--bi-rule) solid transparent;
  color: var(--bi-dim);
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  cursor: pointer;
  transition: none var(--bi-snap);   /* state changes snap */
}
.bi-tab:hover { color: var(--bi-on-paper); }
.bi-tab[aria-selected="true"] {
  color: var(--bi-on-paper);
  border-bottom-color: var(--bi-line-blue);
}

/* ---- FIELDS (underline only; caption above; no box) ------------ */
.bi-field {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 4px;
}
.bi-field__hint {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  color: var(--bi-dim);
}
.bi-field--fault .bi-field__hint,
.bi-field--fault .bi-caption { color: var(--bi-alert); }
.bi-field--fault .bi-input,
.bi-field--fault .bi-select,
.bi-field--fault .bi-textarea { border-bottom-color: var(--bi-alert); }

.bi-input, .bi-select, .bi-textarea {
  width: 100%;
  min-width: 0;
  min-height: var(--bi-tap);
  margin: 0;
  padding: 6px 0;
  background: transparent;
  color: var(--bi-on-paper);
  border: 0;
  border-bottom: var(--bi-rule) solid var(--bi-line);
  border-radius: 0;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-md);
  line-height: 1.3;
}
.bi-input--data, .bi-select--data { font-family: var(--bi-face-data); font-size: var(--bi-t-sm); }
.bi-input::placeholder, .bi-textarea::placeholder { color: var(--bi-faint); }
.bi-input:focus, .bi-select:focus, .bi-textarea:focus { border-bottom-color: var(--bi-line-blue); outline: none; }
.bi-textarea { resize: vertical; min-height: 88px; }
.bi-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 24px;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 10px) 50%, calc(100% - 5px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

/* ---- TOGGLE (hollow circle → filled blue circle) ---------------
   Square variant for checkboxes. The visually hidden input is a
   delegate: the label carries the hit area.                       */
.bi-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: var(--bi-tap);
  padding-block: 4px;
  font-size: var(--bi-t-sm);
  cursor: pointer;
}
.bi-toggle input { position: absolute; opacity: 0; pointer-events: none; width: 1px; height: 1px; }
.bi-toggle__dot {
  flex: 0 0 auto;
  width: 16px; height: 16px;
  border-radius: 50%;
  border: var(--bi-rule) solid var(--bi-blue);
  background: transparent;
}
.bi-toggle--square .bi-toggle__dot { border-radius: 0; }
.bi-toggle input:checked + .bi-toggle__dot { background: var(--bi-blue); }
.bi-toggle input:focus-visible + .bi-toggle__dot { outline: var(--bi-rule) solid var(--bi-blue); outline-offset: 3px; }
.bi-toggle input:disabled + .bi-toggle__dot { border-color: var(--bi-faint); }
.bi-toggle__label--mono {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
}

/* ============================================================
   CHOICE & TALLY — chips, duo, outcome, option
   Domain-neutral on purpose: polls, approvals, plan pickers,
   moderation queues and filter strips are the same four shapes.
   ============================================================ */

/* ---- CHIPS (small pill stamps; selected = solid) --------------- */
.bi-chips {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.bi-chips--scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 4px;
  scrollbar-width: thin;
}
.bi-chip {
  flex: 0 0 auto;
  display: inline-flex; align-items: center;
  min-height: var(--bi-tap);
  padding: 4px 14px;
  margin: 0;
  background: transparent;
  color: var(--bi-on-paper);
  border: var(--bi-rule) solid var(--bi-line);
  border-radius: var(--bi-radius-full);
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: none var(--bi-snap);   /* state changes snap */
}
.bi-chip:hover { color: var(--bi-blue); border-color: var(--bi-blue); }
.bi-chip[aria-pressed="true"],
.bi-chip[aria-selected="true"] {
  background: var(--bi-blue);
  color: var(--bi-on-blue);
  border-color: var(--bi-blue);
}

/* ---- DUO (two-sided commit) ------------------------------------
   Colorless. The words carry the choice; the selected side fills. */
.bi-duo {
  min-width: min(160px, 100%);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 0;
  border: var(--bi-rule) solid var(--bi-line);
  border-radius: var(--bi-radius-full);
  overflow: hidden;
}
.bi-duo__side {
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--bi-tap);
  padding: 4px 12px;
  margin: 0;
  background: transparent;
  color: var(--bi-on-paper);
  border: 0;
  border-left: var(--bi-rule) solid var(--bi-line);
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}
.bi-duo__side:first-child { border-left: 0; }
.bi-duo__side[aria-pressed="true"] { background: var(--bi-blue); color: var(--bi-on-blue); }
.bi-duo__tick { font-variant-numeric: tabular-nums; }

/* ---- OUTCOME (label → magnitude → action) ---------------------- */
.bi-outcome {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--bi-gap);
  min-height: var(--bi-row);
  padding: 6px 0;
  border-bottom: var(--bi-rule) solid var(--bi-line-faint);
}
.bi-outcome__name { min-width: 0; font-size: var(--bi-t-sm); overflow-wrap: anywhere; }
.bi-outcome__value {
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-sm);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* ---- OPTION (a labeled choice carrying a value) ----------------
   Identity is series ink and line style, never a hue to decode.  */
.bi-option {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: var(--bi-tap);
  padding: 8px 14px;
  margin: 0;
  background: transparent;
  color: var(--bi-on-paper);
  border: var(--bi-rule) solid var(--bi-line);
  border-radius: 0;
  font-family: var(--bi-face-display);
  font-weight: var(--bi-weight-display);
  font-size: var(--bi-t-sm);
  text-align: left;
  cursor: pointer;
}
.bi-option__value { font-family: var(--bi-face-data); font-size: var(--bi-t-xs); font-variant-numeric: tabular-nums; }
.bi-option[aria-pressed="true"],
.bi-option[aria-checked="true"] { background: var(--bi-blue); color: var(--bi-on-blue); border-color: var(--bi-blue); }
.bi-option--s1 { border-color: var(--bi-s1); }
.bi-option--s2 { border-style: dashed; }
.bi-option--s3 { border-style: dotted; }
.bi-option--s4 { background: var(--bi-tint); color: var(--bi-on-tint); }
.bi-option--s5 { background: var(--bi-hatch); }
.bi-option--flat { border-color: var(--bi-line-faint); color: var(--bi-dim); }
.bi-option-set {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.bi-option-set > .bi-option { flex: 1 1 120px; }
.bi-option-set > .bi-option--flat { flex: 0 1 auto; }

/* ============================================================
   FEEDBACK — meter, ticks, notice, caret
   ============================================================ */

/* ---- METER (hairline track, filled blue segment, tick marks) ---
   Drive with --_bi-meter-val (0–100%). Always pair with a .bi-count
   or .bi-data readout: a bar without a number is decoration.     */
.bi-meter {
  --_bi-meter-val: 0%;
  position: relative;
  min-width: 0;
  height: 12px;
  border-bottom: var(--bi-rule) solid var(--bi-line);
  background:
    repeating-linear-gradient(to right,
      var(--bi-line) 0 var(--bi-rule), transparent var(--bi-rule) 10%)
    bottom / 100% 4px no-repeat;
}
.bi-meter__fill {
  position: absolute;
  left: 0; bottom: 0;
  height: 6px;
  width: var(--_bi-meter-val);
  max-width: 100%;
  background: var(--bi-blue);
}
.bi-meter--fault .bi-meter__fill { background: var(--bi-alert); }
.bi-meter--tall { height: 20px; }
.bi-meter--tall .bi-meter__fill { height: 12px; }
.bi-meter--outline .bi-meter__fill { background: transparent; border: var(--bi-rule) solid var(--bi-blue); }

/* Ticks on their own — a ruler, a scale under a chart, a step count. */
.bi-ticks {
  min-width: 0;
  height: 8px;
  border-bottom: var(--bi-rule) solid var(--bi-line);
  background: repeating-linear-gradient(to right,
    var(--bi-line) 0 var(--bi-rule), transparent var(--bi-rule) 10%);
}
.bi-ticks--faint { border-bottom-color: var(--bi-line-faint);
  background: repeating-linear-gradient(to right,
    var(--bi-line-faint) 0 var(--bi-rule), transparent var(--bi-rule) 10%); }
.bi-ticks__labels {
  min-width: 0;
  display: flex; justify-content: space-between;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  color: var(--bi-dim);
  font-variant-numeric: tabular-nums;
}

/* ---- NOTICE (a hairline-above, hairline-below strip) -----------
   Mark + caption + message. --fault brings the alert ink to the
   rules and the mark; the word still does the work.              */
.bi-notice {
  min-width: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: 4px 10px;
  padding: 10px 0;
  border-top: var(--bi-rule) solid var(--bi-line);
  border-bottom: var(--bi-rule) solid var(--bi-line);
}
.bi-notice > .bi-mark { align-self: center; }
.bi-notice__body {
  min-width: 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--bi-gap);
}
.bi-notice__msg { min-width: 0; font-size: var(--bi-t-sm); overflow-wrap: anywhere; }
.bi-notice__action { margin-left: auto; }
.bi-notice--fault { border-color: var(--bi-alert); }
.bi-notice--fault .bi-caption { color: var(--bi-alert); }
.bi-notice--blue  { border-color: var(--bi-line-blue); }
.bi-notice--blue  .bi-caption { color: var(--bi-blue); }

/* ---- CARET (a thin blinking 1px caret for loading) ------------- */
.bi-caret {
  display: inline-block;
  width: var(--bi-rule);
  height: 1em;
  margin-left: 0.2em;
  vertical-align: -0.15em;
  background: currentColor;
  animation: bi-blink var(--bi-blink) steps(1) infinite;
}
@keyframes bi-blink { 50% { opacity: 0; } }

/* ============================================================
   MOTION — reveals draw. Nothing slides, bounces or scales.
   State changes are instant. Nothing here reflows: dashoffset,
   transform and opacity only.
   ============================================================ */

/* Draw-in: add .bi-draw to a .bi-drawing (or any element) and it is
   revealed left to right, the way a plotter head crosses the sheet.
   A clip-path wipe, not stroke-dashoffset: dash-based reveals depend
   on pathLength, which some engines ignore (leaving a dotted drawing
   behind), and they force the stroke to scale with the viewBox. The
   wipe leaves every hairline exactly 1px and never reflows.
   Stagger a reveal with the local hook --_bi-delay on the element
   (style="--_bi-delay:120ms"); it defaults to 0ms.                  */
.bi-draw {
  clip-path: inset(0 100% 0 0);
  animation: bi-draw var(--bi-draw) var(--bi-plotter) forwards;
  animation-delay: var(--_bi-delay, 0ms);
}
@keyframes bi-draw { to { clip-path: inset(0 0 0 0); } }

/* A hairline that extends from 0 to full width. */
.bi-rule--draw {
  transform-origin: left center;
  transform: scaleX(0);
  animation: bi-extend var(--bi-draw) var(--bi-plotter) forwards;
  animation-delay: var(--_bi-delay, 0ms);
}
@keyframes bi-extend { to { transform: scaleX(1); } }

/* Explode: the layers of an exploded view travel apart along their
   axis as the drawing enters view, while .bi-draw wipes it in. Give
   each layer <g class="bi-explode__layer" style="--_bi-i:N;
   --_bi-from:Ypx">: --_bi-i orders the stagger (--bi-stagger apart),
   --_bi-from is where the layer starts, collapsed onto the stack.
   Transform only, so nothing reflows; the finished drawing is the
   resting state, which is what reduced motion shows.               */
.bi-explode .bi-explode__layer {
  animation: bi-explode var(--bi-draw) var(--bi-plotter) both;
  animation-delay: calc(var(--_bi-i, 0) * var(--bi-stagger));
}
@keyframes bi-explode { from { transform: translateY(var(--_bi-from, 0)); } }

/* Reveal on view (optional, assets/blue-ink-reveal.js): the script
   marks <html> .bi-reveal-ready, holds every [data-bi-reveal] drawing
   at its start, and adds .bi-draw / .bi-explode once it is in view.
   Without the script, or under reduced motion, drawings are simply
   there, finished.                                                  */
.bi-reveal-ready [data-bi-reveal~="draw"]:not(.bi-draw) > * { clip-path: inset(0 100% 0 0); }   /* the child, so the drawing itself stays observable */
.bi-reveal-ready [data-bi-reveal~="explode"]:not(.bi-explode) .bi-explode__layer { transform: translateY(var(--_bi-from, 0)); }

/* Ink fading in. */
.bi-fade {
  opacity: 0;
  animation: bi-fade var(--bi-fade) linear forwards;
  animation-delay: var(--_bi-delay, 0ms);
}
@keyframes bi-fade { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .bi-draw, .bi-rule--draw, .bi-fade, .bi-caret, .bi-explode .bi-explode__layer {
    animation: none;
    clip-path: none;
    transform: none;
    opacity: 1;
  }
  .bi-caret { opacity: 1; }
}

/* ============================================================
   CHARTS
   Series are --bi-s1..--bi-s5 in fixed order, never cycled, told
   apart by ink AND line style, always with a direct label. Status
   (the alert ink) never encodes a series. A 6th folds into OTHER.
   ============================================================ */

.bi-plot {
  position: relative;
  min-width: 0;
  background: var(--bi-paper);
  padding: var(--bi-gap) 0 0;
}
.bi-plot--card { background: var(--bi-paper-2); padding: var(--bi-gap); }
.bi-plot > svg { display: block; width: 100%; height: auto; overflow: visible; }

.bi-plot__grid line,
.bi-plot__grid path { stroke: var(--bi-line-faint); stroke-width: 1; fill: none; stroke-dasharray: 1 4; vector-effect: non-scaling-stroke; }
.bi-plot__axis { stroke: var(--bi-line); stroke-width: 1; fill: none; vector-effect: non-scaling-stroke; }
.bi-plot__tick {
  font-family: var(--bi-face-data);
  font-size: 10px;
  fill: var(--bi-dim);
  letter-spacing: 0.04em;
}
.bi-plot__label {                 /* a direct label at the end of a line */
  font-family: var(--bi-face-data);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  fill: var(--bi-on-paper);       /* text wears text ink, never series ink */
}
.bi-plot__line {
  fill: none;
  stroke-width: 1;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.bi-plot__area { stroke: none; }
.bi-plot__dot  { r: 3; stroke: var(--bi-paper); stroke-width: 1; }

/* Series: ink AND line style. The dash tokens live in tokens.css. */
.bi-s1 { color: var(--bi-s1); stroke: var(--bi-s1); fill: var(--bi-s1); --bi-dash: var(--bi-dash-s1); }
.bi-s2 { color: var(--bi-s2); stroke: var(--bi-s2); fill: var(--bi-s2); --bi-dash: var(--bi-dash-s2); }
.bi-s3 { color: var(--bi-s3); stroke: var(--bi-s3); fill: var(--bi-s3); --bi-dash: var(--bi-dash-s3); }
.bi-s4 { color: var(--bi-s4); stroke: var(--bi-s4); fill: var(--bi-s4); --bi-dash: var(--bi-dash-s4); }
.bi-s5 { color: var(--bi-s5); stroke: var(--bi-line); fill: var(--bi-s5); --bi-dash: var(--bi-dash-s5); }
/* Two classes, so the line style — and fill: none — outrank the bare
   series class above whatever order they are declared in.        */
.bi-plot__line.bi-s1 { fill: none; stroke-dasharray: none; }
.bi-plot__line.bi-s2 { fill: none; stroke-dasharray: 6 4; }
.bi-plot__line.bi-s3 { fill: none; stroke-dasharray: 1 4; }
.bi-plot__line.bi-s4 { fill: none; stroke-dasharray: none; stroke-width: 0.5; }
.bi-plot__line.bi-s5 { fill: none; stroke-dasharray: 8 3 1 3; }
.bi-plot .bi-plot__line { fill: none; }
/* An area in s5 is hatched: the page supplies <pattern id="bi-hatch">
   (see demo-console.html); s4 is the tint fill; s1–s3 areas are the
   ink at low weight, so the line above them stays legible.      */
.bi-plot__area.bi-s1 { fill: var(--bi-tint); }
.bi-plot__area.bi-s2 { fill: var(--bi-paper-3); }
.bi-plot__area.bi-s3 { fill: var(--bi-paper-2); }
.bi-plot__area.bi-s4 { fill: var(--bi-tint); }
.bi-plot__area.bi-s5 { fill: url(#bi-hatch); }
.bi-plot__hatch-line { stroke: var(--bi-line); stroke-width: 1; }

/* Legend is mandatory at 2+ series. The swatch shows ink AND line
   style; the text wears text ink.                                 */
.bi-legend {
  min-width: 0;
  display: flex; flex-wrap: wrap; gap: 6px var(--bi-pad);
  margin-top: var(--bi-gap);
}
.bi-legend__item {
  min-width: 0;
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-on-paper);
}
.bi-legend__swatch {              /* a 20px line in the series style */
  flex: 0 0 auto;
  width: 20px; height: 0;
  border-top: var(--bi-rule) solid currentColor;
}
.bi-legend__swatch.bi-s2 { border-top-style: dashed; }
.bi-legend__swatch.bi-s3 { border-top-style: dotted; }
.bi-legend__swatch.bi-s5 { border-top-style: dashed; border-top-color: var(--bi-line); }
.bi-legend__swatch--fill {        /* a 12px square in the series fill */
  width: 12px; height: 12px;
  border: var(--bi-rule) solid var(--bi-line);
  background: currentColor;
}
.bi-legend__swatch--fill.bi-s5 { background: var(--bi-hatch); }
.bi-legend__swatch--fill.bi-s4 { background: var(--bi-tint); }

/* Crosshair + tooltip. An HTML chart is interactive by default. */
.bi-plot__crosshair { stroke: var(--bi-line); stroke-width: 1; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.bi-tip {
  position: absolute;
  pointer-events: none;
  z-index: 2;
  background: var(--bi-paper);
  color: var(--bi-on-paper);
  border: var(--bi-rule) solid var(--bi-line);
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  line-height: 1.5;
  padding: 6px 10px;
  white-space: pre;
}
.bi-tip[hidden] { display: none; }

/* ---- BARS (hairline-outlined, filled by series ink, 2px gap) --- */
.bi-bars { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--bi-gap); }
.bi-bars__row { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; }
.bi-bars__label {
  min-width: 0;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-family: var(--bi-face-data);
  font-size: var(--bi-t-xs);
  letter-spacing: var(--bi-track-caption);
  text-transform: uppercase;
  color: var(--bi-dim);
}
.bi-bars__value { color: var(--bi-on-paper); font-variant-numeric: tabular-nums; }
.bi-bars__track {
  min-width: 0;
  display: flex;
  gap: 2px;                       /* mandatory paper gap */
  height: 14px;
}
.bi-bars__seg {
  min-width: 3px;
  border: var(--bi-rule) solid var(--bi-line);
  background: currentColor;       /* set via .bi-s1 … .bi-s5 */
}
.bi-bars__seg.bi-s5 { background: var(--bi-hatch); }
.bi-bars__seg.bi-s4 { background: var(--bi-tint); }
.bi-bars__seg--rest { background: transparent; border-color: var(--bi-line-faint); }
.bi-bars--tall .bi-bars__track { height: 22px; }

/* ============================================================
   RESPONSE
   WIDTH governs layout. POINTER governs ergonomics. See tokens.css.
   ============================================================ */

/* --- Regions and cards are containers, so a component responds to
       the space it is actually in, not to the viewport. -------- */
.bi-region { container-type: inline-size; container-name: bi-region; }
.bi-region--nocq, .bi-card--nocq { container-type: normal; }   /* escape hatch */

/* --- Hit sizes. Driven by --bi-tap, which grows under a coarse
       pointer. Hairlines keep their 1px; the hit area is the box. */
.bi-btn, .bi-tab, .bi-chip, .bi-option, .bi-duo__side,
.bi-input, .bi-select, .bi-nav__link, .bi-toggle,
.bi-list__row, .bi-log__row, .bi-outcome { min-height: var(--bi-tap); }
/* An inline link stays inline (so it wraps mid-sentence) and grows its
   hit box with vertical padding: on an inline box, block padding is
   part of the hit rectangle but takes no part in line layout, so the
   prose does not move. The em term is the glyph box, ~1.15em in most
   faces; subtracting 1em leaves a margin over the target size.     */
.bi-link,
.bi-footer a { padding-block: calc((var(--bi-tap) - 1em) / 2); }
.bi-stamp:is(a, button),
.bi-wordmark { min-height: var(--bi-tap); }

/* --- Below the stack breakpoint. ------------------------------- */
@media (max-width: 720px) {

  /* The nav wraps: mark and action on the first line, links beneath.
     No hamburger. */
  .bi-nav__links { flex: 1 1 100%; order: 3; justify-content: flex-start; }
  .bi-nav__action { margin-left: auto; }

  /* The spine turns into a horizontal band above the page. */
  .bi-sheet--spined { grid-template-columns: minmax(0, 1fr); }
  .bi-sheet--spined > .bi-spine {
    grid-row: auto;
    width: 100%;
    min-height: var(--bi-tap);
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--bi-gap);
    padding: 4px var(--bi-pad);
  }
  .bi-spine__text {
    writing-mode: horizontal-tb;
    transform: none;
    white-space: normal;            /* the band wraps; the spine never had to */
    min-width: 0;
    flex: 1 1 12ch;
    overflow-wrap: anywhere;
  }

  /* The big index letter drops beneath the title. */
  .bi-block__head  { grid-template-columns: max-content minmax(0, 1fr); }
  .bi-block__aside { grid-column: 1 / -1; justify-self: start; }

  /* Generous margins are a desktop luxury. */
  .bi-sheet--margin { padding: var(--bi-pad); }
  .bi-block--lg { padding: var(--bi-pad); }
}

/* --- Narrow containers. Container queries, not viewport: a list in
       a sidebar needs this at 1400px too. ------------------------- */
@container bi-list (max-width: 440px) {
  .bi-list__row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "key action" "title title";
    row-gap: 2px;
    padding-block: 8px;
  }
  .bi-list__key    { grid-area: key; }
  .bi-list__title  { grid-area: title; }
  .bi-list__action { grid-area: action; }
  .bi-list__row--nokey { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title action"; }
}

@container bi-log (max-width: 400px) {
  .bi-log__row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "date end" "msg msg";
    row-gap: 2px;
    padding-block: 8px;
  }
  .bi-log__date { grid-area: date; }
  .bi-log__msg  { grid-area: msg; }
  .bi-log__end  { grid-area: end; }
}

@container bi-spec (max-width: 420px) {
  .bi-spec__row  { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .bi-spec__head { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .bi-spec__head > :not(:first-child) { display: none; }   /* column heads are meaningless once stacked */
  .bi-spec__val::before {
    content: attr(data-col) " ";
    font-family: var(--bi-face-data);
    font-size: var(--bi-t-xs);
    letter-spacing: var(--bi-track-caption);
    text-transform: uppercase;
    color: var(--bi-dim);
  }
}

/* A narrow block (a half-width column, a sidebar) gives the title the
   whole width and drops the letter beneath it — container, not viewport. */
@container bi-block (max-width: 480px) {
  .bi-block__head  { grid-template-columns: max-content minmax(0, 1fr); }
  .bi-block__aside { grid-column: 1 / -1; justify-self: start; }
}

@container bi-region (max-width: 360px) {
  .bi-kv > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .bi-outcome {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name value" "action action";
    row-gap: 6px;
  }
  .bi-outcome__name  { grid-area: name; }
  .bi-outcome__value { grid-area: value; }
  .bi-outcome > .bi-duo, .bi-outcome > .bi-btn { grid-area: action; }
  .bi-option-set { flex-direction: column; }
  .bi-option-set > .bi-option { flex: 1 1 auto; }
}
@container bi-card (max-width: 360px) {
  .bi-kv > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* --- Sideways scrolling is a BUG, not something to hide. ---------
   `overflow-x: hidden` on html/body silences the symptom and makes
   scrollWidth report clean, so the audit passes while content is
   clipped off-screen. Fix the cause. Anything that genuinely
   scrolls sideways opts in with .bi-scroll-x, inside its own box. */
