:root {
  --navy: #12263a; --amber: #e8a33d; --green: #177e63;
  /* ⚠️ --muted was #7c8890, which is 3.55:1 on white — BELOW the 4.5:1 AA
     floor for the body-size text it is used on, in fourteen places including
     every field description and every column heading. #5b6770 is 5.80:1.
     Measured, not eyeballed; design-gui-flow.md §4 calls this one of two
     corrections "worth taking even if nothing else lands".
     ⚠️ This is the FOURTH contrast defect found in this stylesheet by
     measuring — after two invisible buttons in S5 and .vname navy-on-navy in
     S4 — and the first that was never a button, so no amount of clicking
     would have found it. */
  --line: #d8dde0; --paper: #f5f8fa; --ink: #26282b; --muted: #5b6770;
  --red: #a3231b;
}
* { box-sizing: border-box; }
body {
  margin: 0; font: 14px/1.5 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  color: var(--ink); background: #fff;
}
header {
  background: var(--navy); color: #fff; padding: 14px 20px;
  display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap;
}
.wordmark { font-weight: 700; letter-spacing: 4px; }
.wordmark .dot { color: var(--amber); }
.strap { font-size: 10px; letter-spacing: 3px; color: #9fb0bd; flex: 1; }
.who { font-size: 12px; display: flex; align-items: center; gap: 8px; }
.who .tag { text-transform: uppercase; letter-spacing: 1px; }

/* The login pane. Same column width as the verb pane so signing in does not
   move the page about. */
#login { max-width: 420px; margin: 32px auto; }
#login .field { margin-bottom: 12px; }
#login input { width: 100%; padding: 6px 8px; }

/* The show/hide control on a password box. ⚠️ `--muted` on white is 5.80:1 —
   it is a real control and must not join the three invisible ones this
   stylesheet has already shipped. It sits INSIDE the field's box rather than
   over the text, so it never covers what it is revealing. */
.pw-wrap { position: relative; display: flex; align-items: stretch; }
.pw-wrap input { flex: 1; min-width: 0; }
button.pw-peek {
  font: inherit; font-size: 12px; padding: 0 10px; cursor: pointer;
  background: var(--paper); color: var(--muted);
  border: 1px solid var(--line); border-left: 0;
}
button.pw-peek:hover { color: var(--ink); background: #eaeff2; }
button.pw-peek:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }
/* Pressed means the password is VISIBLE — worth looking different, because
   walking away from a screen showing a plaintext password is the risk this
   control introduces. */
button.pw-peek[aria-pressed="true"] { background: #fdf3e2; color: #7a5312;
                                      border-color: var(--amber); }
input[readonly] { opacity: 0.7; cursor: not-allowed; }
[hidden] { display: none !important; }

.warn {
  margin: 0; padding: 8px 20px; background: #fff3b8; color: #5a5000;
  border-bottom: 1px solid #c9a400; font-size: 12px;
}
main { display: flex; align-items: flex-start; gap: 0; }
nav {
  width: 340px; min-width: 300px; border-right: 1px solid var(--line);
  padding: 10px 0; min-height: 80vh;
}
nav .group { padding: 10px 16px 4px; font-size: 11px; letter-spacing: 2px;
             color: var(--muted); text-transform: uppercase; }
nav button {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  padding: 8px 16px; cursor: pointer; font: inherit; border-left: 3px solid transparent;
}
nav button:hover { background: var(--paper); }
nav button[aria-current="true"] { background: var(--paper); border-left-color: var(--green); }
nav button[disabled] { opacity: .45; cursor: not-allowed; }
nav .vname { font-weight: 600; color: var(--navy); }
nav .vsum { font-size: 12px; color: var(--muted); }
.tag {
  font-size: 10px; letter-spacing: 1px; padding: 1px 5px; border: 1px solid;
  border-radius: 2px; margin-left: 6px; vertical-align: 1px;
}
/* ⚠️ THIS WAS `color: var(--amber)` ON WHITE — 2.16:1, at 10px, on the one
   label whose entire job is warning that an action CHANGES THE RECORD. §4 of
   the design says amber is "never body text on light" and `contrast.test.mjs`
   asserts that rule about the token; nothing asserted it about a RULE using
   the token, so this sat in plain sight through four contrast sweeps. It is
   now the same amber tint the `warn` tone uses — a filled chip, dark text —
   which measures 6.21:1, and the guard that would have caught it is in
   `contrast.test.mjs` under "amber is never used AS TEXT". */
.tag.mut { color: #7a5312; background: #fdf3e2; border-color: var(--amber); }
.tag.no { color: var(--red); border-color: var(--red); }

/* ---------------------------------------------------------------- the shell
   design-gui-flow.md §7 step 3: three derived surfaces, a Browse drawer and
   an omnibox. The drawer is a bare `<details>` — no JS behind it, so the
   open/close, the keyboard reachability and the announcement are the
   browser's, not this file's.
   =========================================================================== */
.drawer { border-top: 1px solid var(--line); margin-top: 8px; padding-top: 4px; }
.drawer > summary {
  list-style: none; cursor: pointer; padding: 10px 16px 6px;
  font-size: 11px; letter-spacing: 2px; color: var(--muted);
  text-transform: uppercase;
}
.drawer > summary::-webkit-details-marker { display: none; }
/* The fold marker, drawn rather than relying on the platform triangle so it
   sits where the label is. `▸` rotates to `▾` when open. */
.drawer > summary::before {
  content: "▸"; display: inline-block; width: 1em; transition: transform .12s;
}
.drawer[open] > summary::before { transform: rotate(90deg); }
.drawer > summary:hover { background: var(--paper); }
.drawer > summary:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }

/* Tabs, for when two verbs declare one surface's kind. Only reachable once a
   second calendar or a second board exists. */
.tabs { display: flex; gap: 4px; margin: 10px 0 4px; flex-wrap: wrap; }
.tab {
  font: inherit; font-size: 12.5px; padding: 4px 10px; cursor: pointer;
  background: none; border: 1px solid var(--line); border-radius: 4px;
  color: var(--navy);
}
.tab[aria-selected="true"] { background: var(--navy); color: #fff;
                             border-color: var(--navy); }

/* ---- the omnibox ---- */
.omni { flex: 1 1 320px; min-width: 0; position: relative; display: flex;
        align-items: center; max-width: 460px; }
.omni input {
  width: 100%; font: inherit; font-size: 13px; padding: 5px 30px 5px 10px;
  border: 1px solid #4a627a; border-radius: 4px;
  /* ⚠️ A LIGHT FIELD IN THE NAVY BAR, not navy-on-navy. `.vname` shipped
     navy-on-navy in S4 and this is the same rule with the same colours the
     other way round: --ink on white is 13.9:1, and a search box a person
     cannot see they are typing into is the invisible control this stylesheet
     keeps producing. */
  background: #fff; color: var(--ink);
}
.omni input::placeholder { color: var(--muted); }
.omni input:focus { outline: 2px solid var(--amber); outline-offset: 1px; }
/* The `/` hint.
   ⚠️ WRITTEN AS `color: var(--amber)` AND CAUGHT BY THE GUARD ADDED THIS
   MORNING, within the hour. The reasoning behind the amber was "it sits in the
   navy bar, where amber is 7.11:1" — and it does not: it is `position:
   absolute` inside `.omni`, so it overlaps the WHITE input's right padding,
   where amber is 2.16:1. That is the fifth time this stylesheet has put a
   colour on a background nobody checked, and the first time something other
   than a person found it. --muted is 5.80:1 on white. */
.omni-key {
  position: absolute; right: 8px; font-size: 11px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 3px; padding: 0 4px;
  pointer-events: none; font-family: inherit;
}
/* Hidden once the box has anything in it — a keyboard hint over a person's own
   text is a hint that has outstayed its usefulness. */
.omni input:not(:placeholder-shown) + .omni-key { display: none; }

/* ⚠️ CAPPED AND SCROLLED. Without the cap, 35 results pushed the rail and the
   whole pane off the bottom of the screen — a search that hides the
   application is disorienting rather than helpful, and you cannot see what you
   are searching FROM. Found by looking at it with real data; a short query
   would never have shown it. Same class as S8's finding 8, where a lane grew
   past the fold and took its scrollbar with it. */
.omni-results { border-bottom: 1px solid var(--line); background: var(--paper);
                max-height: 60vh; overflow-y: auto; }
.omni-inner { max-width: 1240px; margin: 0 auto; padding: 12px 20px; }
.omni-group { margin-bottom: 10px; }
.omni-group h3 {
  font-size: 11px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--muted); margin: 0 0 4px;
}
.omni-list { list-style: none; margin: 0; padding: 0; }
.omni-hit {
  display: block; width: 100%; text-align: left; font: inherit;
  background: #fff; border: 1px solid var(--line); border-radius: 4px;
  padding: 5px 8px; margin-bottom: 4px; cursor: pointer;
}
.omni-hit:hover { border-color: var(--navy); }
.omni-hit[disabled] { cursor: not-allowed; background: var(--muted-bg); }
.omni-label { font-weight: 600; color: var(--navy); }
.omni-sub { display: block; font-size: 12px; color: var(--muted); }
.omni-none { font-size: 12.5px; color: var(--muted); margin: 0 0 4px; }
.omni-foot { font-size: 12px; color: var(--muted); margin: 8px 0 0; }

/* ⚠️ `min-width: 0` — the SAME trap named at `td.cal-day` below, and the fix
   had been applied to the two leaves while their container kept the default.
   A flex item's `min-width` is `auto`, meaning "never shrink below my content",
   so the board's row of lanes pushed this pane wider than its own `max-width`
   and the PAGE scrolled sideways: measured 315px of overflow at a 900px
   viewport, 825px at 375px. Nothing inside was at fault — every child that
   could overflow already declares `min-width: 0`. **The fix belongs on the one
   flex item in the chain that had not been told, which was this one.** */
section#pane { flex: 1; min-width: 0; padding: 18px 24px; max-width: 900px; }
h1 { font-size: 18px; color: var(--navy); margin: 0 0 2px; }
h2 { font-size: 13px; letter-spacing: 1px; text-transform: uppercase;
     color: var(--muted); margin: 22px 0 8px; }
.muted { color: var(--muted); }
.schemaid { font-family: ui-monospace, Menlo, monospace; font-size: 12px; color: var(--green); }

fieldset { border: 1px solid var(--line); margin: 8px 0; padding: 8px 12px 12px; }
legend { font-size: 12px; color: var(--navy); font-weight: 600; }
.field { margin: 10px 0; }
.field > label { display: block; font-weight: 600; font-size: 13px; color: var(--navy); }
.field .desc { font-size: 12px; color: var(--muted); margin-bottom: 3px; }
.field input[type=text], .field input[type=number], .field select, .field textarea {
  width: 100%; padding: 5px 7px; border: 1px solid var(--line); font: inherit;
}
.field textarea { min-height: 150px; font-family: ui-monospace, Menlo, monospace; font-size: 12px; }
.req { color: var(--red); }
.row { display: flex; gap: 8px; align-items: flex-start; }
.row .field { flex: 1; }

button.act {
  background: var(--navy); color: #fff; border: 0; padding: 8px 16px;
  font: inherit; cursor: pointer; margin-right: 8px;
}
button.act.confirm { background: var(--green); }
button.act[disabled] { background: #b9c2c9; cursor: not-allowed; }
/* ⚠️ NO `color` HERE, DELIBERATELY, AND THE REASON COST A ROUND TRIP.
   A bare `<button class="small">Log out</button>` lives in the NAVY header and
   takes its white from there. Setting a colour on this rule to fix the
   `act small` case below turned that one dark-on-navy — trading one invisible
   button for another. The fix belongs on the combination that is actually
   broken, not on the modifier in general. See `button.act.small`. */
button.small { font-size: 12px; padding: 3px 8px; background: none;
               border: 1px solid var(--line); cursor: pointer; }

/* ⚠️ A THIRD INVISIBLE CONTROL, and this one was NOT introduced by the fix
   above — it has been here since the header was written. `header` sets
   `color: #fff`, but a <button> does not inherit it: the UA stylesheet gives
   every button `color: buttontext`, which is near-black. So "Log out" has
   always been dark text on the navy header. Measured contrast 1.36:1 against
   a 4.5:1 floor.

   It survived because it is the one control nobody looks for until they want
   it, and because reading the CSS shows a header that says `color: #fff` — the
   rule is there, it simply does not reach the button. Found by computing the
   contrast of every visible button on the page rather than by trusting the
   two this session had touched. */
header button.small { color: #fff; border-color: rgba(255, 255, 255, .55); }
header button.small:hover { background: rgba(255, 255, 255, .12); }

/* The share picker. It sits under the text input it fills and never replaces
   it — the field stays typeable, which is what makes an unmounted share a
   degraded experience rather than a blocked one. */
.pickbar { margin: 4px 0 0; }
.picker {
  border: 1px solid var(--line); border-top: 2px solid var(--navy);
  background: var(--paper); padding: 10px 12px; margin: 6px 0 0;
}
.picker .crumbs { margin: 0 0 8px; font-size: 12px; }
.picker .crumbs .sep { color: var(--muted); margin: 0 2px; }
.picker button.crumb-btn {
  border: 0; background: none; font: inherit; font-size: 12px; padding: 1px 3px;
  color: var(--navy); text-decoration: underline; cursor: pointer;
}
.picker ul.dirs {
  list-style: none; margin: 0; padding: 0; max-height: 260px; overflow: auto;
  background: #fff; border: 1px solid var(--line);
}
.picker ul.dirs li { border-bottom: 1px solid var(--line); }
.picker ul.dirs li:last-child { border-bottom: 0; }
.picker button.dir {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  font: inherit; padding: 6px 10px; cursor: pointer;
}
.picker button.dir::before { content: "📁"; margin-right: 8px; }
.picker button.dir:hover { background: var(--paper); }
.picker .actions { margin: 10px 0 0; display: flex; align-items: center; gap: 10px; }
.picker .chosen { font-size: 12px; }

/* The entity picker's result list reuses .picker/.dirs, but a property is not
   a folder — the 📁 that button.dir carries would be a lie about what was
   found. */
.entity-results button.dir::before { content: "🏠"; }
.entity-results button.dir .muted { margin-left: 8px; font-size: 12px; }
/* The confirmation under a chosen entity: the NAME is what a person reads and
   the uuid is small — present so it can be quoted, never the thing that has to
   be understood. */
.field > p.pickbar .chosen { font-weight: 600; }
.tiny { font-size: 11px; font-family: var(--mono, ui-monospace, monospace); }

pre {
  background: var(--paper); border: 1px solid var(--line); padding: 10px;
  overflow: auto; max-height: 460px; font-size: 12px;
}
.diff { border-left: 4px solid var(--amber); background: #fffaf0;
        padding: 8px 12px; margin: 8px 0; }
/* ⚠️ The old `.diff th { background: navy }` rule was written for the union
   table that used to live here, and it silently swallowed the row labels of
   the key/value table that replaced it — white-on-navy in a cell whose text is
   a heading, not a column. Diff tables are `table.kv` now and are styled in
   one place, below. */
.err { border-left: 4px solid var(--red); background: #fdf2f1; padding: 8px 12px; }
.err h3 { margin: 0 0 4px; color: var(--red); font-size: 14px; }
.ok { border-left: 4px solid var(--green); background: #eef4f2; padding: 8px 12px; }

/* ------------------------------------------------------------------ 2026-08-10
   Making the daily surface calmer. Nothing here is decoration: each rule is
   either "the plumbing is out of the way" or "a person can read the result".  */

.linkish { background: none; border: 0; padding: 0; font: inherit;
           color: #5a5000; text-decoration: underline; cursor: pointer; }
.explain { background: #fffdf2; border-bottom: 1px solid #e6dfae;
           padding: 8px 20px; font-size: 13px; }
.explain p { margin: 4px 0; max-width: 70ch; }

nav .group { padding: 14px 16px 2px; }
nav .glabel { font-size: 12px; letter-spacing: 1px; color: var(--navy);
              text-transform: uppercase; font-weight: 700; }
/* ⚠️ text-transform and letter-spacing are reset explicitly: the older
   `nav .group` rule uppercases and tracks out its whole subtree, which is fine
   for a three-word heading and unreadable for a sentence. */
nav .gdesc { font-size: 11px; color: var(--muted); margin-top: 2px;
             text-transform: none; letter-spacing: 0; line-height: 1.4; }
nav button.askbtn { border-bottom: 1px solid var(--line); padding: 12px 16px; }
nav button.askbtn .vname { color: var(--green); }

.crumb { font-size: 11px; letter-spacing: 2px; text-transform: uppercase;
         color: var(--muted); margin: 0 0 2px; }
.lede { margin: 0 0 10px; max-width: 70ch; }
.willchange { background: #fffaf0; border-left: 4px solid var(--amber);
              padding: 6px 10px; max-width: 70ch; }
.fromagent { background: #eef4f2; border-left: 4px solid var(--green);
             padding: 6px 10px; max-width: 70ch; }
.attrib { max-width: 70ch; font-size: 12px; }
.actions { margin: 16px 0 4px; }

/* The plumbing lives here: schema ids, verb names, raw JSON. Present for the
   person who wants it, out of the way of the person who does not. */
details.tech { margin: 12px 0; font-size: 12px; }
details.tech > summary { cursor: pointer; color: var(--muted); }
details.tech p { margin: 6px 0; }
details.optional { margin: 12px 0; border: 1px solid var(--line);
                   padding: 6px 12px 10px; }
details.optional > summary { cursor: pointer; font-weight: 600;
                             color: var(--navy); }
.req { color: var(--muted); font-weight: 400; font-size: 11px;
       text-transform: uppercase; letter-spacing: 1px; }

/* A diff a person can read: one statement per change, not a union of columns. */
.diff .change { margin: 8px 0; }
table.kv { border-collapse: collapse; width: 100%; font-size: 12px;
           margin: 4px 0 10px; background: #fff; }
table.kv th { text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--line);
              color: var(--navy); font-weight: 600; width: 30%; }
table.kv thead th { background: var(--navy); color: #fff; width: auto; }
table.kv td { padding: 3px 6px; border-bottom: 1px solid var(--line);
              font-family: ui-monospace, Menlo, monospace; }
.fromto { margin: 4px 0; font-family: ui-monospace, Menlo, monospace; }
.fromto .from { color: var(--red); }
.fromto .to { color: var(--green); font-weight: 700; }
.fromto .arrow { color: var(--muted); margin: 0 6px; }
.do-next { margin: 6px 0 0; }

/* The assistant. */
.rails { background: var(--paper); border: 1px solid var(--line);
         padding: 8px 12px; margin: 10px 0; font-size: 13px; }
.rails p { margin: 0 0 6px; max-width: 75ch; }
.rails ul { margin: 4px 0; padding-left: 18px; }
#chat { margin: 14px 0; }
.turn { margin: 10px 0; padding: 8px 12px; border-left: 3px solid var(--line); }
.turn > b { font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
            color: var(--muted); }
.turn p { margin: 4px 0; max-width: 75ch; white-space: pre-wrap; }
.turn.you { background: var(--paper); }
.turn.bot { border-left-color: var(--green); }
details.working { font-size: 12px; margin-top: 8px; }
details.working > summary { cursor: pointer; color: var(--muted); }
.step { margin: 6px 0; }
.step code { color: var(--navy); font-weight: 600; }
.bad-step .refused { color: var(--red); }
.step .args { margin-left: 12px; }
.proposal { border: 1px solid var(--amber); background: #fffaf0;
            padding: 8px 12px; margin: 8px 0; }
form.ask { display: flex; gap: 8px; align-items: flex-start; }
form.ask textarea { flex: 1; padding: 6px 8px; border: 1px solid var(--line);
                    font: inherit; }
button.small-act { padding: 5px 10px; font-size: 13px; }

/* The model-backend switch. Folded by default when something IS answering —
   it is a setting, not a daily control — and open when nothing is, because
   then it is the only thing on the page worth touching. */
details.backend { margin: 12px 0; border: 1px solid var(--line);
                  padding: 6px 12px 10px; max-width: 70ch; }
details.backend > summary { cursor: pointer; font-weight: 600;
                            color: var(--navy); }
.bgrid { display: grid; grid-template-columns: max-content 1fr; gap: 8px 12px;
         align-items: center; margin: 10px 0; }
.bgrid label { font-size: 12px; color: var(--muted); }
.bgrid select, .bgrid input { padding: 5px 8px; width: 100%; }
/* ⚠️ Amber, not grey: "this changes it for everyone" is not a footnote. */
.warn-inline { background: #fff3b8; border-left: 4px solid var(--amber);
               padding: 6px 10px; margin: 8px 0; font-size: 12px; }
ul.alts { margin: 4px 0 8px; padding-left: 18px; font-size: 12px; }

/* The answer as it arrives. ⚠️ The steps appear while the model is still
   working — that is most of what "fluid" means here, and it is why the panel
   streams rather than waiting for one JSON object at the end. */
ul.livesteps { margin: 4px 0 8px; padding-left: 18px; font-size: 12px; }
.caret { opacity: 0.55; animation: blink 1s step-start infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ---------------------------------------------------------------- work list
   ⚠️ Three tones and no more, matching control/verbs/result.py's closed TONES.
   The adapter decides which bucket is which; this file only knows how each of
   the three should look. A fourth tone would need a change in both places,
   which is the point of closing the set. */
.chips { margin: .4rem 0 .8rem; display: flex; flex-wrap: wrap; gap: .4rem; }
.chip {
  display: inline-block; padding: .12rem .5rem; border-radius: 999px;
  font-size: .82rem; line-height: 1.5; white-space: nowrap;
  border: 1px solid transparent;
}
.chip b { font-weight: 700; }
/* Colour is never the only signal — each tone also differs in weight and
   border, so the list still reads on a monochrome print or to a colour-blind
   reader. */
.tone-alert { background: #fdecea; border-color: #e5534b; color: #7d1f19; font-weight: 600; }
.tone-warn  { background: #fdf3e2; border-color: #e8a33d; color: #7a5312; }
.tone-ok    { background: #eef4f0; border-color: #cfe0d6; color: #2f5d47; }

.headline { font-size: 1.15rem; margin: .2rem 0 .1rem; }
.headline b { color: #7d1f19; }

/* ⚠️ The empty state is a sentence the adapter wrote, not "no results". It
   gets room to be read rather than being tucked under the table. */
.emptynote {
  padding: .9rem 1rem; background: #f7f7f5; border-left: 3px solid #cfcfc8;
  color: #444; margin: .6rem 0;
}

table.worklist { width: 100%; border-collapse: collapse; margin: .5rem 0; }
table.worklist th {
  text-align: left; font-size: .78rem; letter-spacing: .04em;
  text-transform: uppercase; color: #666; border-bottom: 1px solid #ddd;
  padding: .35rem .5rem;
}
table.worklist td { padding: .4rem .5rem; border-bottom: 1px solid #f0f0ee; }
table.worklist tr.row-alert td:first-child { box-shadow: inset 3px 0 0 #e5534b; }
table.worklist tr.row-warn  td:first-child { box-shadow: inset 3px 0 0 #e8a33d; }

/* ------------------------------------------------------------ sections/tiles
   ⚠️ The left column is now TEN sections, not 38 verbs. Ben: "task oriented,
   settings/account in separate section, pretty standard but it has to flow
   nicely for a human who is non technical". */
.sectionbtn[aria-current] { background: #12263a; color: #fff; }
.sectionbtn[aria-current] .vsum { color: #c9d4e0; }

/* Tiles, per Ben's "like tiles, and expand/reduce what we see". A section
   shows only its own actions — that is the reduction — and they sit as cards
   rather than as another vertical list to scan. */
.tiles {
  display: grid; gap: .7rem; margin: 1rem 0;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
.tile {
  text-align: left; padding: .8rem .9rem; border: 1px solid #e2e2dd;
  border-radius: 6px; background: #fff; cursor: pointer; font: inherit;
  display: flex; flex-direction: column; gap: .3rem;
}
.tile:hover:not(:disabled) { border-color: #12263a; background: #fbfbfa; }
.tile:disabled { opacity: .55; cursor: default; }
.tname { font-weight: 600; }
.tsum { font-size: .86rem; color: #555; line-height: 1.35; }

.todaylist { margin: 0 0 2rem; }
.todaylist h2 { font-size: 1rem; font-weight: 600; margin: 0 0 .3rem; }
/* ⚠️ `color` HERE IS LOAD-BEARING, and its absence was a live INVISIBLE BUTTON
   on the screen the app opens on. `button.act` sets `background: var(--navy);
   color: #fff`; `button.small` sets `background: none` and, matching at equal
   specificity but later in the file, wins the background. A button carrying
   BOTH — `<button class="act small">Open the full list</button>` under every
   work list on Today — was therefore white text on the white page. The label
   was in the DOM and the button was clickable; a screenshot showed an empty
   rectangle.

   This rule is the right home for the fix because it is the only selector that
   matches exactly the broken combination: `.act` supplies a foreground whose
   background `.small` has just taken away. Putting it on `button.small`
   instead breaks the bare `.small` in the navy header — measured, not guessed.

   ⚠️ THE SECOND TIME THIS EXACT SHAPE HAS BEEN FOUND BY LOOKING RATHER THAN BY
   READING; the first was `.vname` navy-on-navy, just below. Neither is
   reachable by any test in this repo — `tests/js/render.test.mjs` can prove the
   label is in the HTML, and it IS in the HTML. Only a screenshot shows the
   colour. */
button.act.small { font-size: .85rem; padding: .3rem .7rem; color: var(--ink); }

/* ⚠️ Caught by looking at it, not by reading the CSS: `.vname` carries the
   navy brand colour, so on the selected section — which is navy — the label
   disappeared entirely and only its description showed. The one section a
   person is looking at was the one they could not read. */
.sectionbtn[aria-current] .vname { color: #fff; }

/* The work-list heading was inheriting the uppercase section-header style and
   shouting a verb summary at the reader. It is a sentence, so it reads as one. */
.todaylist h2 {
  text-transform: none; letter-spacing: 0; font-size: .95rem;
  color: #555; font-weight: 500;
}

/* Clickable rows — the difference between a report and a step. */
table.worklist tr.clickable { cursor: pointer; }
table.worklist tr.clickable:hover td { background: #f4f7fa; }
table.worklist tr.clickable:focus { outline: 2px solid #12263a; outline-offset: -2px; }
/* ⚠️ #9aa5b1 measured 2.50:1 on white — the SECOND correction
   design-gui-flow.md §4 calls "worth taking even if nothing else lands", and
   the same class as the three invisible controls this repo has already
   shipped. A chevron is the affordance that says a row opens something, so an
   invisible one makes a whole work list look like a dead table. --muted is
   5.80:1 and is the token this belongs to. */
table.worklist td.go { color: var(--muted); text-align: right; width: 1.5rem; }

/* A record reads as a thing, not as a row dump. */
.fact { display: flex; gap: .8rem; padding: .3rem 0; border-bottom: 1px solid #f2f2ef; }
.flabel { flex: 0 0 9rem; color: #666; font-size: .86rem; padding-top: .1rem; }
.fval { font-size: 1.02rem; }

/* ===================================================================
   The two result kinds added in S8 — design-gui-flow.md §7 steps 2, 5.
   Colours are the prototypes' (`docs/gui-prototypes/proto.css`), which
   were swept for contrast across ~580 element-states.
   ⚠️ Every one of them is a token, so `tests/js/contrast.test.mjs`
   can see it. A literal typed in here is how #9aa5b1 reached 2.50:1.
   =================================================================== */
:root {
  --plan-bg:  #e8eef5; --plan-bd:  #9db2c6; --plan-ink:  #12263a;
  --muted-bg: #f0f1f2; --muted-bd: #c9ced2; --muted-ink: #5b6770;
}

/* ⚠️ WITHOUT THESE TWO, EVERY CALENDAR ENTRY RENDERS AS NOTHING. A tone
   the stylesheet does not know is not a fallback — it is a class with no
   rule, which is exactly how this repo shipped three invisible controls.
   The tone vocabulary and the stylesheet grow together or not at all. */
.tone-plan  { background: var(--plan-bg);  border-color: var(--plan-bd);
              color: var(--plan-ink); }
.tone-muted { background: var(--muted-bg); border-color: var(--muted-bd);
              color: var(--muted-ink); }

/* ---- calendar ---- */
table.calendar { width: 100%; border-collapse: collapse; table-layout: fixed; }
table.calendar caption { font-size: 16px; font-weight: 600; text-align: left;
                         padding: 8px 0; color: var(--navy); }
table.calendar th { font-size: 11px; text-transform: uppercase;
                    letter-spacing: 1px; color: var(--muted);
                    padding: 4px; text-align: left; border-bottom: 1px solid var(--line); }
/* ⚠️ `min-width: 0` is not decoration. The prototype overflowed the viewport
   because a grid column defaults to min-content and an address will not
   shrink; §4's verification note names it as one of two defects found by
   looking. */
td.cal-day { vertical-align: top; border: 1px solid var(--line);
             height: 92px; padding: 3px; min-width: 0; overflow: hidden;
             background: #fff; }
td.cal-outside { background: var(--paper); }
td.cal-outside .cal-daynum { color: var(--muted); }
td.cal-today { box-shadow: inset 0 0 0 2px var(--navy); }
.cal-daynum { font-size: 12px; color: var(--ink); display: flex;
              justify-content: space-between; align-items: center; }
.cal-entries { list-style: none; margin: 2px 0 0; padding: 0; }
.cal-entry { font-size: 11px; border: 1px solid; border-radius: 3px;
             padding: 1px 3px; margin-bottom: 2px; cursor: pointer;
             white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Void but on the record — struck, not removed. */
.cal-entry.cal-void { text-decoration: line-through; }
.cal-more { font-size: 11px; color: var(--muted); cursor: pointer; }
.cal-book { border: 1px dashed var(--plan-bd); background: none;
            border-radius: 3px; font-size: 11px; line-height: 1;
            padding: 1px 4px; color: var(--navy); cursor: pointer; }
.cal-book:hover { background: var(--plan-bg); }

/* ---- board ---- */
.board { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 8px; }
.board .lane { flex: 0 0 220px; background: var(--paper);
               border: 1px solid var(--line); border-radius: 6px;
               padding: 8px; min-width: 0; }
.board .lane h3 { font-size: 12.5px; margin: 0 0 6px; color: var(--navy);
                  text-transform: uppercase; letter-spacing: 1px; }
/* Folded lanes are terminal states — context, not work. Narrow, never gone.
   ⚠️ THIS USED `opacity: 0.85` AND THAT IS THE FINDING, not the ratio it
   produced. `getComputedStyle(el).color` reports the colour BEFORE alpha is
   composited, so the browser DOM sweep and `contrast.test.mjs` both read the
   passing token and neither could see the 4.15:1 that reached the screen.
   **In a stylesheet whose contrast is verified by computing it, `opacity` is
   the one de-emphasis that makes text unmeasurable — so de-emphasis here is
   spelled with colours instead**: a flatter surface and a quieter heading,
   both of which every sweep can read. Measured: --muted on --muted-bg 5.13:1. */
.board .lane-folded { flex-basis: 120px; background: var(--muted-bg);
                      border-color: var(--muted-bd); }
.board .lane-folded h3 { color: var(--muted); }
.board .lane-stray { flex-basis: 260px; border-color: var(--amber);
                     border-style: dashed; }
.board .cards { list-style: none; margin: 0; padding: 0; }
.board .card { background: #fff; border: 1px solid var(--line);
               border-radius: 4px; padding: 6px; margin-bottom: 6px;
               cursor: pointer; display: flex; flex-direction: column;
               gap: 2px; }
.board .card:hover { border-color: var(--navy); }
.board .card-key { font-weight: 600; font-size: 12.5px; color: var(--navy); }
.board .card-f { font-size: 12px; color: var(--muted); }
