/* ===========================================================================
   ADRI OS Design Standard — v1.0.0
   The one stylesheet every ADRI OS product is built from.

   Canon: the LC Brief (cloud/lc-brief-web). This file is that design language
   given names, made portable, and made platform-independent. It is NOT a
   reinterpretation — every value here traces to a line in the Brief's source.

   Binding: .claude/rules/design-standard.md
   Spec:    plugins/system/knowledge/KNW_2026-08-03_OS_MB_Design-Standard.md
   Guide:   design/README.md

   THREE TIERS
     1. Foundations (tokens, type, severity)  — mandatory, no exceptions
     2. Principles (see the spec)             — mandatory
     3. Components (below the fold here)      — use when the pattern applies

   A product is not required to look like the LC Brief. It is required to be
   built from the same material. If it renders a table, it renders THIS table.

   Deviation requires a written approval marker from Mak or Miron. See the rule.
   ======================================================================== */


/* ── Type ────────────────────────────────────────────────────────────────
   Self-hosted, latin-subset, ~180 KB once and cached forever.

   WHY SELF-HOSTED: until 2026-08-03 the Brief declared 'Inter' and never
   shipped it, so every role fell through to a system font and the two
   platforms rendered three different typefaces each:
       UI      declared Inter  → Mac: SF Pro     Windows: Segoe UI
       Serif   declared New York → Mac: New York  Windows: Georgia
       Mono    declared SF Mono → Mac: SF Mono    Windows: Consolas
   ADRI is a Windows-first shop. The design language had therefore never
   actually shipped to the people who use it. Never reintroduce a system-font
   stack: it silently forks the product by platform.

   All three families are SIL Open Font License 1.1. See fonts/LICENSES.md. */

@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 800;
  font-display: swap; src: url('fonts/inter-var-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Literata'; font-style: normal; font-weight: 400 700;
  font-display: swap; src: url('fonts/literata-var-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('fonts/plexmono-400-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600;
  font-display: swap; src: url('fonts/plexmono-600-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 700;
  font-display: swap; src: url('fonts/plexmono-700-latin.woff2') format('woff2');
}


/* ── Tokens ─────────────────────────────────────────────────────────────
   Every value a product may use. Hardcoding a hex in a component is a
   standard violation — the hook blocks it. If a value you need is missing,
   that is a gap in the standard: raise it, do not invent locally. */

:root {
  /* Families. Three, each with one job. Never mix the jobs. */
  --ui:    'Inter', system-ui, sans-serif;              /* interface       */
  --serif: 'Literata', Georgia, serif;                  /* titles + prose  */
  --mono:  'IBM Plex Mono', Consolas, monospace;        /* numbers + IDs   */

  /* Ground and paper. The warm room (Brief, 2026-07-03: "the warm room is
     the whole app — paper, ink, deep green"). Surfaces are never pure white. */
  --ground:      #f3efe7;
  --ground-glow: #faf6ed;   /* radial highlight, see .adri-ground */
  --surface:     #fffdf8;   /* cards, tables, panels                   */
  --surface-2:   #fbf8f1;   /* panel heads, insets, hover              */
  --surface-3:   #faf7ef;   /* table head                              */
  --surface-4:   #f2ece0;   /* pressed, deep inset                     */

  /* Lines, lightest to heaviest. */
  --divider: #f0e9db;   /* inside a card, between sections */
  --rule:    #ece5d7;   /* table row rules                 */
  --border:  #e7e1d5;   /* card and panel edges            */
  --border-2:#ded5c4;   /* control edges                   */
  --border-3:#c9bca4;   /* control hover, emphasis         */

  /* Ink, darkest to faintest.

     THE QUIET RAMP HAS ONE RUNG, NOT THREE (2026-08-11). --muted, --faint and
     --label were three steps of quietness below --ink-3. Measured against this
     file's own paper they scored 3.29, 2.00 and 2.25 — all under the 4.5 WCAG AA
     floor, and all used at the SMALLEST sizes in the system (--t-xs 11.5px,
     --t-label 10.5px, --t-micro 9.5px), where the large-text exemption cannot
     apply because nothing here reaches 24px.

     The minimum AA-passing value for each lands on #746a5e, #716a5d and
     #716a5b — one colour with three names. The floor simply does not permit a
     three-rung quiet ramp on warm paper. So there is now ONE quiet text value,
     and the roles that used to be separated by ever-lighter grey are separated
     by type instead — which is what "type has three jobs" already asked for.
     A 10.5px uppercase label with tracking is unmistakable without also being
     too pale to read. */
  --ink:    #241f18;   /* primary text                         */
  --ink-2:  #45403a;   /* body prose                           */
  --ink-3:  #6b6153;   /* secondary, captions                  */
  --muted:  #746a5e;   /* labels, metadata, hints, placeholders */
  --label:  var(--muted);  /* uppercase micro-labels — same ink, told apart by type */

  /* NEVER TEXT. Disabled controls only, which WCAG 1.4.3 exempts from the
     contrast floor, plus purely decorative marks that carry no meaning. At 2.31
     on paper this clears neither the 4.5 text floor nor the 3.0 non-text floor,
     so any informational use is a defect — including an icon that tells the
     user something is available. Both of this file's own uses were exactly that
     and have been moved to --muted. */
  --faint:  #b3a894;

  /* Accent. Deep green. Identity is not the same value as action. */
  --accent:     #166b45;   /* identity: links, job numbers, brand mark */
  /* Darkened 2026-08-11 from #1f8a43. That value carried a white label at 4.40
     and read as text on the pressed surface at 3.74 — the ONE primary control
     in the system, below the floor in both directions. Its own hover state
     (--action-h) already passed at 5.77, so the button only became readable
     once you moused over it: an oversight rather than an intent. */
  --action:     #1c7b3c;   /* the ONE primary control on a surface     */
  --action-h:   #17753a;   /* its hover                                */
  --accent-sub: #eaf4ec;   /* accent-tinted fill                       */
  --accent-line:#c5e0cf;   /* accent-tinted border                     */

  /* Armed. A destructive or irreversible confirm, never a resting state. */
  --armed:   #b3460e;
  --armed-h: #9c3c0a;

  /* Severity. SIX tiers, in urgency order. This vocabulary is closed: a
     product may not add a seventh tier or re-map an existing one. Compute the
     tier once in the data layer, then let the UI render it. */
  --off:  #86181d; --off-bg:  #86181d; --off-tx:  #ffffff;  /* turned off   */
  --crit: #86181d; --crit-bg: #fff1f0; --crit-tx: #86181d;  /* critical     */
  --need: #a9740f; --need-bg: #fff8eb; --need-tx: #7a4d00;  /* needs action */
  --mon:  #35688f; --mon-bg:  #eef4fb; --mon-tx:  #0a4a8f;  /* monitor      */
  --ok:   #1f6b34; --ok-bg:   #e8f5ec; --ok-tx:   #1f6b34;  /* on track     */
  --wait: #8b8071; --wait-bg: #f5f5f7; --wait-tx: #6e6e73;  /* waiting      */

  /* Materials. A material is what a thing is MADE OF, never what state it is
     in — which is why these sit outside the closed severity vocabulary above
     and may never be used to mean anything. The test: if removing the colour
     would lose information, it is a severity and belongs in that block; if it
     would only lose the object's identity, it is a material and belongs here.

     Sticky-note paper (AI-1052, Valerie Card, 2026-08-18: "is there a way for
     it to look like a yellow sticky note so can see it as soon as open the
     file"). A pinned note that a person chose to put on a record, rendered as
     the paper it is named after. More saturated than --need-bg on purpose so it
     never reads as "needs action": #fff3bd vs #fff8eb. Its edge is the only
     value the high-contrast mode moves — the yellow is the point. */
  --sticky-paper:  #fff3bd;   /* the note                            */
  --sticky-gum:    #ffe994;   /* the gummed strip along its top edge */
  --sticky-line:   #ecd681;   /* its edge                            */
  --sticky-ink:    #4a3d12;   /* body ink on paper — 9.6:1           */
  --sticky-by:     #6d5d24;   /* byline and controls — 5.6:1         */
  --sticky-shadow: rgba(120,96,20,.16);

  /* System accents. For naming an external system, never for status.
     Used as a 7px dot on a secondary control, never as a filled slab. */
  --sys-dash:      #33456b;
  --sys-symbility: #1a8a96;
  --sys-xactimate: #3a5a86;
  --sys-alacrity:  #6d5bd0;
  --sys-comms:     #1e6fd9;

  /* Radius. Five steps. Nothing between them. */
  --r-xs: 6px;    /* chips, micro-controls        */
  --r-sm: 8px;    /* inputs, buttons, small cards */
  --r-md: 11px;   /* cards, panels                */
  --r-lg: 16px;   /* hero cards, popovers         */
  --r-pill: 999px;

  /* Elevation. Two resting, one lifted. Shadows are warm, never neutral grey. */
  --shadow:    0 1px 2px rgba(60,45,25,.04), 0 8px 24px rgba(60,45,25,.05);
  --shadow-md: 0 8px 28px rgba(40,30,15,.14);
  --shadow-lg: 0 18px 60px rgba(40,30,15,.28);

  /* Type scale. Fixed. Density changes spacing, never type size — that is
     what keeps a dense board and a light form recognisably one system. */
  --t-micro: 9.5px;   /* stat labels                 */
  --t-label: 10.5px;  /* uppercase labels, chips     */
  --t-xs:    11.5px;  /* metadata, claim numbers     */
  --t-sm:    12.5px;  /* table body, captions        */
  --t-base:  13px;    /* interface default           */
  --t-md:    15px;    /* stat values, emphasis       */
  --t-prose: 15.5px;  /* serif narrative             */
  --t-lg:    17px;    /* section heads               */
  --t-xl:    22px;    /* page titles                 */
  --t-2xl:   24px;    /* record name (the hero)      */

  /* Density. The two knobs a product may turn. Default is compact: these are
     working tools and more rows on screen beats airy cards (Brief, 2026-07-03,
     Mak: "so much blank space"). Use .adri-comfortable only on low-frequency
     surfaces — intake forms, portals, onboarding. */
  --cell-y: 6px;  --cell-x: 12px;
  --gap:    8px;
  --pad:    16px;

  /* Motion. .12s is the house transition. Celebration is the only exception
     and lives in its own component. */
  --fast: .12s;
  --base: .18s;
  --ease: cubic-bezier(.4, 0, .2, 1);
}

.adri-comfortable { --cell-y: 10px; --cell-x: 16px; --gap: 12px; --pad: 22px; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}


/* ── Base ──────────────────────────────────────────────────────────────── */

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

body {
  font-family: var(--ui);
  font-size: var(--t-base);
  color: var(--ink);
  min-height: 100vh;
  background: radial-gradient(1100px 600px at 85% -10%, var(--ground-glow) 0%, transparent 55%), var(--ground);
  /* NOTE: no -webkit-font-smoothing. It thins text on macOS only and does
     nothing on Windows, which widens the gap between the two platforms.
     Omitting it makes both converge. Do not add it back. */
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
button, input, select, textarea { font-family: inherit; font-size: inherit; }
button { cursor: pointer; }

/* Focus is always visible and always the accent. Never remove it. */
:focus-visible { outline: 2px solid var(--action); outline-offset: 2px; border-radius: var(--r-xs); }

/* Type helpers */
.mono   { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.num    { font-variant-numeric: tabular-nums; }
.title  { font-family: var(--serif); font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.prose  { font-family: var(--serif); font-size: var(--t-prose); line-height: 1.55; color: var(--ink-2); max-width: 58ch; }
.label  { font-size: var(--t-micro); font-weight: 800; letter-spacing: .08em;
          text-transform: uppercase; color: var(--label); }
.clamp2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }


/* ═══════════════════════════════════════════════════════════════════════
   TIER 3 — COMPONENTS
   Use when the pattern applies. A product with no table owes nobody a table.
   But a product that renders a table renders this one.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Shell ─────────────────────────────────────────────────────────────── */

.adri-topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 0 20px; height: 52px;
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 100;
}
/* Ink base is explicit so the mark reads the same whether it is a <div> or an
   <a> linking home — as an anchor it would otherwise inherit the global accent
   link colour and the whole mark, em included, would come out one flat colour. */
.adri-topbar .brand { font-weight: 700; font-size: var(--t-md); letter-spacing: -.3px; color: var(--ink); }
.adri-topbar .brand:hover { text-decoration: none; }
.adri-topbar .brand em { font-style: normal; color: var(--accent); }
.adri-spring { flex: 1 1 auto; }
.adri-app { max-width: 1440px; margin: 0 auto; padding: var(--pad) 20px 60px; }
.adri-app.reading { max-width: 1100px; }

/* Ecosystem nav. The apps behind brief.advanceddri.com are one product, so the
   link set in the topbar is the same component everywhere: quiet pills, the
   current page filled with the identity accent. Nothing else belongs in the
   topbar — a page's own action buttons go in .page-toolbar, below it, or the nav
   stops being recognisable from one page to the next. */
.navlink {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--border-2); background: var(--surface);
  color: var(--ink-3); font-size: var(--t-sm); font-weight: 600;
  text-decoration: none; white-space: nowrap;
}
.navlink:hover { border-color: var(--border-3); color: var(--ink); text-decoration: none; }
.navlink.active,
.navlink[aria-current="page"] { background: var(--accent); border-color: var(--accent); color: var(--surface); }
.navlink.active:hover,
.navlink[aria-current="page"]:hover { background: var(--action-h); border-color: var(--action-h); color: var(--surface); }

/* Page toolbar. A page's own actions live here, never in the topbar. */
.page-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 16px; }
.page-toolbar .adri-spring { flex: 1 1 auto; }

/* The two other things a topbar carries: a count of what is on screen, and who
   you are signed in as. Both belong to the shell, not to a page. */
.count  { color: var(--muted); font-size: var(--t-sm); font-variant-numeric: tabular-nums; }
.whoami { font-size: var(--t-sm); color: var(--muted); text-align: right; line-height: 1.3; }
.whoami b { display: block; color: var(--ink); font-weight: 600; }


/* ── Severity chip. The six-tier vocabulary, rendered. ─────────────────── */

.chip {
  display: inline-block; padding: 2px 8px; border-radius: 5px;
  font-size: var(--t-label); font-weight: 700; letter-spacing: .2px; white-space: nowrap;
}
.chip.off  { background: var(--off-bg);  color: var(--off-tx);  }
.chip.crit { background: var(--crit-bg); color: var(--crit-tx); }
.chip.need { background: var(--need-bg); color: var(--need-tx); }
.chip.mon  { background: var(--mon-bg);  color: var(--mon-tx);  }
.chip.ok   { background: var(--ok-bg);   color: var(--ok-tx);   }
.chip.wait { background: var(--wait-bg); color: var(--wait-tx); }

/* Tier text colour. The same six tiers for a severity word set in running prose
   rather than in a chip ("This job's risk is CRITICAL"). Takes the same tier
   class, so a sentence and a chip cannot disagree. */
.tx-off  { color: var(--off-tx); }
.tx-crit { color: var(--crit-tx); }
.tx-need { color: var(--need-tx); }
.tx-mon  { color: var(--mon-tx); }
.tx-ok   { color: var(--ok-tx); }
.tx-wait { color: var(--wait-tx); }

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--surface-4); color: var(--muted);
  font-size: var(--t-xs); font-weight: 800; letter-spacing: .3px;
}
.pill.need { background: var(--need-bg); color: var(--need-tx); }
.pill.crit { background: var(--crit-bg); color: var(--crit-tx); }


/* ── Board. The dense data table. ──────────────────────────────────────── */

.board {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow); overflow: hidden;
}
/* Wide content scrolls inside its own box. The page body NEVER scrolls
   sideways — that is a hard layout invariant, not a preference. */
.board .scroll { overflow: auto; max-height: calc(100vh - 210px); }
.board table { border-collapse: collapse; width: 100%; }
.board thead th {
  text-align: left; padding: 7px var(--cell-x);
  font-size: var(--t-label); font-weight: 700; letter-spacing: .5px;
  text-transform: uppercase; color: #7d7360; background: var(--surface-3);
  border-bottom: 1px solid #e0d8c8; white-space: nowrap;
  position: sticky; top: 0; z-index: 2;
}
.board tbody td {
  padding: var(--cell-y) var(--cell-x); border-bottom: 1px solid var(--rule);
  vertical-align: middle; font-size: var(--t-sm); line-height: 1.35;
}
.board tbody tr:last-child td { border-bottom: none; }
.board tbody tr[data-row] { cursor: pointer; }
.board tbody tr[data-row]:hover td { background: rgba(22,107,69,.045); }
/* While a wheel scroll is in flight the pointer sits still and the ROWS move
   under it, so :hover repaints every row in turn and reads as the colors
   changing on their own. Add .scrolling for ~140ms during scroll. */
.board .scroll.scrolling tbody tr[data-row]:hover td { background: none; }

.board .cell-id   { font-family: var(--mono); color: var(--accent); font-weight: 700; }
.board .cell-name { font-weight: 600; color: var(--ink); white-space: nowrap; }
.board .cell-num  { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.board .cell-meta { font-family: var(--mono); color: var(--muted); font-size: var(--t-xs); }

/* Severity spine. A 3px inset marker plus a wash on the first cell, so a row's
   tier is readable while scanning a long board without hunting for its chip.
   Put .spine on the FIRST cell and a t-<tier> class on the row; the tier is the
   same closed six-tier vocabulary as .chip, so a row and its chip can never
   disagree. Compute the tier in the data layer, never per page.

   This is a genuine addition to the standard rather than a local invention: the
   risk board's whole job is triage by severity, and the system had no row-level
   severity treatment. Any product with a severity-ranked table should use it. */
.board tbody tr.t-off  td.spine { box-shadow: inset 3px 0 0 var(--off);  background: var(--off-bg);  }
.board tbody tr.t-crit td.spine { box-shadow: inset 3px 0 0 var(--crit); background: var(--crit-bg); }
.board tbody tr.t-need td.spine { box-shadow: inset 3px 0 0 var(--need); background: var(--need-bg); }
.board tbody tr.t-mon  td.spine { box-shadow: inset 3px 0 0 var(--mon);  background: var(--mon-bg);  }
.board tbody tr.t-ok   td.spine { box-shadow: inset 3px 0 0 var(--ok);   background: var(--ok-bg);   }
.board tbody tr.t-wait td.spine { box-shadow: inset 3px 0 0 var(--wait); background: var(--wait-bg); }
/* The off tier is a solid dark fill, so its spine text needs the light ink. */
.board tbody tr.t-off td.spine { color: var(--off-tx); }

/* Chunky always-visible scrollbars. Overlay scrollbars hide until you scroll,
   which made the horizontal bar impossible to find on a wide board. */
.board .scroll::-webkit-scrollbar { height: 14px; width: 14px; -webkit-appearance: none; }
.board .scroll::-webkit-scrollbar-track { background: #efe9dd; }
.board .scroll::-webkit-scrollbar-thumb { background: #cbc0aa; border-radius: 7px; border: 3px solid #efe9dd; }
.board .scroll::-webkit-scrollbar-thumb:hover { background: #b3a78c; }


/* ── Stat strip. One segmented unit, not loose tiles of ragged widths. ─── */

.stats {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(96px, max-content);
  border: 1px solid #e9e2d2; border-radius: var(--r-md);
  background: var(--surface); overflow: hidden; width: max-content;
}
.stat { padding: 9px 16px; border-left: 1px solid var(--divider); min-width: 0; }
.stat:first-child { border-left: none; }
.stat .k { font-size: var(--t-micro); font-weight: 800; letter-spacing: .08em;
           text-transform: uppercase; color: var(--label); }
.stat .v { margin-top: 2px; font-family: var(--mono); font-size: var(--t-md);
           font-weight: 600; letter-spacing: -.2px; color: var(--ink);
           font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 760px) {
  .stats { grid-auto-flow: row; width: 100%; }
  .stat { border-left: none; border-top: 1px solid var(--divider); }
  .stat:first-child { border-top: none; }
}


/* ── Filter chips. The counts ARE the filters. ─────────────────────────── */

.fchips { display: flex; gap: 6px; flex-wrap: wrap; }
.fchip {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 6px 12px; border-radius: var(--r-pill);
  border: 1px solid #ddd4c2; background: var(--surface);
  font-size: 12px; font-weight: 600; color: var(--ink-2);
  cursor: pointer; transition: all var(--fast);
}
.fchip b { font-size: var(--t-base); font-weight: 700; }
.fchip:hover { border-color: #b3a78c; }
.fchip.crit { color: var(--crit-tx); }
.fchip.need { color: var(--need-tx); }
.fchip.mon  { color: var(--mon-tx);  }
.fchip[aria-pressed="true"].crit { background: var(--crit); border-color: var(--crit); color: #fff; }
.fchip[aria-pressed="true"].need { background: var(--need); border-color: var(--need); color: #fff; }
.fchip[aria-pressed="true"].mon  { background: var(--mon);  border-color: var(--mon);  color: #fff; }
.fchip[aria-pressed="true"]      { background: var(--ink);  border-color: var(--ink);  color: var(--surface); }


/* ── Buttons. ONE primary per surface. ─────────────────────────────────────
   Everything else is a calm paper button. A secondary that names an external
   system carries a 7px color DOT, never a filled slab — six competing tints
   made the rail read as noise (Brief, 2026-07-27).

   A control must do what it says. If a move has no instrument behind it, it
   renders as a directive line, not a button. A button that does not do what
   it says is a broken promise. */

.btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 16px; border-radius: var(--r-sm);
  border: 1px solid var(--border-2); background: var(--surface);
  color: var(--ink); font-size: var(--t-base); font-weight: 600;
  transition: background var(--fast), border-color var(--fast);
}
.btn:hover { background: var(--surface-2); border-color: var(--border-3); }
.btn.primary { background: var(--action); border-color: var(--action); color: #fff; font-weight: 700; }
.btn.primary:hover { background: var(--action-h); border-color: var(--action-h); }
/* Armed = one tap from irreversible. Never a resting state. */
.btn.primary.armed { background: var(--armed); border-color: var(--armed); }
.btn.primary.armed:hover { background: var(--armed-h); border-color: var(--armed-h); }
.btn.quiet { border-color: transparent; background: none; color: var(--muted); }
.btn.quiet:hover { background: var(--surface-2); color: var(--ink); }
.btn:disabled { opacity: .55; cursor: default; }
.btn .kbd { font-size: var(--t-xs); opacity: .55; font-weight: 500; }

.btn.dot { position: relative; padding-left: 26px; }
.btn.dot::before {
  content: ''; position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 7px; height: 7px; border-radius: 50%; background: var(--border-3);
}
.btn.dot.dash::before      { background: var(--sys-dash); }
.btn.dot.symbility::before { background: var(--sys-symbility); }
.btn.dot.xactimate::before { background: var(--sys-xactimate); }
.btn.dot.alacrity::before  { background: var(--sys-alacrity); }
.btn.dot.comms::before     { background: var(--sys-comms); }

/* The directive line: the move stated, when there is no in-app instrument. */
.directive {
  background: #f3f8f1; border: 1px solid #dcead6; border-left: 3px solid var(--action);
  border-radius: var(--r-md); padding: 13px 16px;
}
.directive .move { font-size: var(--t-md); font-weight: 650; color: #123c22; line-height: 1.4; }
.directive .why  { margin-top: 7px; font-size: 12px; color: var(--muted); line-height: 1.45; }


/* ── Form controls ─────────────────────────────────────────────────────── */

.field, .input, .select, .textarea {
  width: 100%; padding: 8px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--border-2); background: var(--surface);
  color: var(--ink); font-size: var(--t-base); line-height: 1.4;
}
.textarea { min-height: 64px; resize: vertical; }
.field:focus, .input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--action);
}
.input.bad, .textarea.bad { border-color: #c0392b; background: #fdf3f2; }
.search { border-radius: var(--r-pill); background: var(--surface-4); padding: 0 15px; height: 34px; }
.search:focus { background: var(--surface); box-shadow: 0 0 0 3px rgba(22,107,69,.10); }


/* ── Slide-in record panel ─────────────────────────────────────────────── */

.adri-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.28);
  opacity: 0; pointer-events: none; transition: opacity var(--base); z-index: 200;
}
.adri-overlay.open { opacity: 1; pointer-events: auto; }

.panel {
  position: fixed; top: 0; right: 0; height: 100vh;
  width: 940px; max-width: 96vw; background: var(--surface);
  box-shadow: -8px 0 30px rgba(40,30,15,.14); z-index: 201;
  transform: translateX(100%); transition: transform .2s ease;
  display: flex; flex-direction: column;
}
.panel.open { transform: translateX(0); }
/* Head is wayfinding chrome in ONE fixed row. It never scrolls away, and the
   body below opens with the RECORD — serial position: the record opens the
   surface, navigation is chrome. */
.panel-head {
  display: flex; align-items: center; gap: var(--gap);
  padding: 11px 16px; border-bottom: 1px solid var(--border); background: var(--surface-2);
  flex: 0 0 auto;
}
.panel-body { overflow-y: auto; padding: var(--pad) 20px 28px; flex: 1 1 auto; }
.panel-cols { display: grid; grid-template-columns: 1.08fr .92fr; gap: 0 26px; align-items: start; }
.panel-cols > .ref { border-left: 1px solid var(--divider); padding-left: 24px; }
@media (max-width: 1000px) {
  .panel-cols { grid-template-columns: 1fr; }
  .panel-cols > .ref { border-left: none; padding-left: 0; }
}


/* ── Record masthead. Name is the hero, state sits beside it. ──────────── */

.mast-id { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.mast-name { font-size: var(--t-2xl); font-weight: 650; letter-spacing: -.5px; color: var(--ink); }
.mast-sub {
  margin-top: 7px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: var(--t-sm); color: var(--muted);
}
.mast-sub .mono { color: var(--accent); font-weight: 700; }


/* ── Collapsible section ───────────────────────────────────────────────── */

.section { margin-top: 18px; border-top: 1px solid var(--divider); padding-top: 13px; }
.section > .head {
  display: flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: #9b9078;
}
.section > .head .chev { font-size: 10px; transition: transform .15s; }
.section.open > .head .chev { transform: rotate(90deg); }
.section > .body { display: none; margin-top: 10px; }
.section.open > .body { display: block; }

/* Key/value ledger. Anything retyped elsewhere is click-to-copy —
   interaction cost is a bug. */
.kv { display: grid; grid-template-columns: 108px 1fr; gap: 5px 12px; font-size: var(--t-base); }
.kv .k { color: var(--muted); }
.kv .v { color: var(--ink); }
.copyable { cursor: copy; }
.copyable:hover { color: var(--accent); }
/* --muted, not --faint: this glyph is the affordance telling the user the value
   can be copied, so it is informational and owes the 3:1 non-text floor at
   minimum. --faint cleared neither floor. */
.copyable:hover::after { content: '⧉'; margin-left: 5px; color: var(--muted); font-size: 11px; }


/* ── Timeline / note item ──────────────────────────────────────────────── */

.note {
  padding: 10px 12px; background: #faf6ec; border-left: 2px solid #e0d5c1;
  border-radius: var(--r-xs); margin-bottom: var(--gap);
}
.note .meta { font-size: 12px; color: var(--muted); margin-bottom: 3px; }
.note .meta strong { color: var(--ink); }
.note .body { font-size: var(--t-base); line-height: 1.45; color: #39322a; }
/* Borrowed context. Visibly indented and tagged so it can never be mistaken
   for the record you opened. */
.note.foreign { border-left-color: #c9b896; background: #f7f2e6; margin-left: 14px; }
.note .tag {
  font-size: 11px; font-weight: 700; letter-spacing: .03em; padding: 1px 6px;
  border-radius: 4px; background: #e3d6b8; color: #5c5343; margin-left: 6px;
}


/* ── Sticky note ───────────────────────────────────────────────────────────
   A short fact a PERSON chose to pin to a record so the next person does not
   have to read its whole history. Distinct from .note above, which is a system
   record of something that happened: a sticky is disposable, authored, and
   removable, and it looks like paper because that is what it is standing in
   for. Never a status, never a task, never a system message.

   Three cues, so the object survives a colourblind eye and a bad monitor: the
   paper, the gummed strip across the top, and the lift. Hue alone is never the
   signal. Near-square corners on purpose — paper is cut, not rounded. */

.sticky {
  display: flex; align-items: flex-start; gap: 8px; border-radius: 3px;
  background: linear-gradient(var(--sticky-gum) 0 7px, var(--sticky-paper) 7px);
  border: 1px solid var(--sticky-line); padding: 12px 10px 9px 11px;
  box-shadow: 0 1px 2px var(--sticky-shadow);
}
.sticky .body {
  flex: 1; min-width: 0; font-size: var(--t-base); line-height: 1.45;
  color: var(--sticky-ink); overflow-wrap: anywhere; white-space: pre-wrap;
}
/* Attribution is quiet by default: the note is the point, the byline is the
   audit. */
.sticky .by { display: block; font-size: var(--t-label); color: var(--sticky-by); margin-top: 3px; }
/* Remove. Reads against the PAPER, never against the surface behind it. */
.sticky .x {
  flex: 0 0 auto; border: 1px solid transparent; background: none; padding: 0 5px;
  border-radius: var(--r-xs); font-size: 12px; line-height: 1.5; font-family: var(--ui);
  color: var(--sticky-by); cursor: pointer;
  transition: background var(--fast), color var(--fast), border-color var(--fast);
}
.sticky .x:hover { background: #fff8dc; color: var(--armed); border-color: #e6cf7a; }


/* ── Modal ─────────────────────────────────────────────────────────────── */

.modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.35);
  display: none; align-items: center; justify-content: center; z-index: 300;
}
.modal-overlay.open { display: flex; }
.modal {
  background: var(--surface); width: 460px; max-width: 92vw; max-height: 88vh;
  overflow-y: auto; border-radius: 12px; padding: 20px; box-shadow: var(--shadow-lg);
}
.modal.wide { width: min(820px, 95vw); }
.modal .modal-title { font-family: var(--serif); font-size: var(--t-lg); font-weight: 600; margin-bottom: 12px; }
.modal label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-3); margin: 12px 0 6px; }
.modal-actions { display: flex; justify-content: flex-end; gap: var(--gap); margin-top: 18px; }


/* ── Toast ─────────────────────────────────────────────────────────────── */

.toast {
  position: fixed; bottom: 24px; left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: #1d1d1f; color: #fff; padding: 11px 18px; border-radius: 10px;
  font-size: var(--t-base); font-weight: 500; opacity: 0; pointer-events: none;
  transition: opacity .2s, transform .2s; z-index: 400; box-shadow: 0 6px 24px rgba(0,0,0,.25);
}
.toast.open { opacity: 1; transform: translateX(-50%) translateY(0); }


/* ── Banners and states ────────────────────────────────────────────────────
   Empty is an ANSWER, not a spinner. A known-empty state says so and says
   when it was checked. A spinner that can never resolve is a defect. */

.banner { border-radius: var(--r-sm); padding: 9px 13px; font-size: 12px; margin-bottom: 12px; }
.banner.info { background: #eef6ff; border: 1px solid #cde3fb; color: #0040a8; }
.banner.warn { background: #fff8e6; border: 1px solid #f0e0a8; color: #8a6d00; }
.banner.err  { background: var(--crit-bg); border: 1px solid #f5c2c0; color: var(--crit-tx); }
.banner.ok   { background: var(--ok-bg); border: 1px solid #b9e3c6; color: var(--ok-tx); }

.empty { text-align: center; padding: 40px 24px; color: var(--muted); font-size: var(--t-base); }
.empty .h { font-family: var(--serif); font-size: var(--t-lg); font-weight: 600; color: var(--ink); margin-bottom: 5px; }
/* --muted, not --faint: "an empty state says WHEN it was checked" is the whole
   point of this line — it is the evidence, not decoration. */
.empty .checked { display: block; margin-top: 9px; font-size: var(--t-xs); color: var(--muted); }

.spinner {
  display: inline-block; width: 18px; height: 18px;
  border: 2px solid var(--border-2); border-top-color: var(--action);
  border-radius: 50%; animation: adri-spin .7s linear infinite;
  vertical-align: middle; margin-right: var(--gap);
}
@keyframes adri-spin { to { transform: rotate(360deg); } }


/* ── Combobox. Use over a <select> once a list passes ~15 items. ───────── */

.combo { position: relative; }
.combo-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 50;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-md);
  max-height: 280px; overflow-y: auto; display: none;
}
.combo-list.open { display: block; }
.combo-row { padding: 9px 12px; cursor: pointer; border-bottom: 1px solid var(--rule); }
.combo-row:last-child { border-bottom: none; }
.combo-row:hover, .combo-row.on { background: #f1f8f3; }
.combo-row .c { float: right; color: var(--muted); font-size: var(--t-xs); }


/* ── Help affordance. Every product carries the route to the AI team. ──── */

.help-fab {
  position: fixed; right: 22px; bottom: 22px; z-index: 200;
  height: 50px; max-width: 50px; overflow: hidden;
  display: inline-flex; align-items: center; gap: 9px; padding: 0 16px;
  border: none; border-radius: var(--r-pill);
  background: var(--accent); color: #fff; font-size: 14px; font-weight: 600;
  text-decoration: none; white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0,0,0,.20);
  transition: max-width .34s var(--ease), box-shadow var(--base), background var(--base);
}
.help-fab:hover { max-width: 190px; background: #12583a; text-decoration: none; }
.help-fab .fab-label { opacity: 0; transition: opacity .2s ease .04s; }
.help-fab:hover .fab-label { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .help-fab { transition: none; } }


/* ── Count badge. A small numeric bubble that attaches to a nav link or a
   button, showing how many things need attention right now (unread notes,
   promises due, files past SLA). It is not the same thing as .btn.dot: the
   dot names an external system on a secondary control, this badge counts
   items needing action on whatever it is pinned to.

   Only two severity states exist, because a count badge answers one
   question, "does this need attention today or is it already late," and
   that maps directly onto two rungs of the closed six-tier vocabulary: NEEDS
   ACTION (--need, due today, a warning) and CRITICAL (--crit, overdue, the
   most urgent state the system has). No third tier is introduced, and the
   tokens are the same ones every chip and spine already use, so a badge and
   a chip for the same job can never disagree.

   ZERO STATE: when the count is 0, do not render a badge showing "0". Remove
   the element from the DOM entirely. An empty state is an answer, per the
   standard, and a bubble reading "0" is noise sitting on a control that has
   nothing to report.

   ONE-SHOT ATTENTION, NEVER A PULSE: a badge that animates forever asks for
   an exemption the standard does not grant, since .12s is the house
   transition and celebration is the only named exception to it. Instead the
   badge plays a single settle-and-pop once, the moment it first appears, via
   the .pop class the consuming app adds on first render (and may remove once
   the animation ends, since a finished one-shot needs no class to hold it
   steady). The keyframes run with the default iteration count of one and
   never repeat, so this rule must never gain an unbounded repeat count. */

.count-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 5px; box-sizing: border-box;
  border-radius: var(--r-pill);
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  line-height: 1; letter-spacing: 0; white-space: nowrap;
  font-variant-numeric: tabular-nums; /* numerals stay mono and tabular, never proportional */
}
.count-badge.need { background: var(--need); color: #fff; }
.count-badge.crit { background: var(--crit); color: #fff; }

/* Overflow. The app caps the label at "99+" (or similar) before handing it to
   the badge; this component never truncates or does the math itself. The
   rule below keeps 1, 2, or 3 characters legible and keeps the badge from
   stretching the control it sits on: it stays a circle at one digit and
   grows into a short pill at two or three, never wider than it needs to be. */
.count-badge { max-width: 34px; overflow: hidden; text-overflow: clip; }

/* Attachment. Give the host (a .navlink, a .btn, any inline control) its own
   `position: relative`, then add `.corner` to lift the badge out of the flow
   and pin it to the host's top-right corner. The 2px border, in the colour
   of whatever surface the host sits on, reads as a notch cut into the host
   rather than a shape floating beside it. */
.count-badge.corner {
  position: absolute; top: -7px; right: -7px;
  border: 2px solid var(--surface);
}

/* The one-shot settle: a quick overshoot-and-rest, not a loop. */
@keyframes adri-badge-pop {
  0%   { transform: scale(.4); opacity: 0; }
  55%  { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
.count-badge.pop { animation: adri-badge-pop .32s var(--ease); }
@media (prefers-reduced-motion: reduce) {
  .count-badge.pop { animation: none; }
}
