/* App surfaces (admin.html, client.html, status.html, map.html): the white
   SaaS console. Pure white canvas, white cards with a hairline and a
   barely-there shadow, a light rail with small line icons, ink as the only
   accent (no violet) on the primary button, the selected nav item and links.
   Red and amber mean state and are never the accent. Headings in the app are
   Instrument Sans (Lee's choice 2026-09-18, after Plex and Source Sans 3 were tried and rejected); Fraunces stays on the
   letter (read.html and client.html)
   only. (Lee's direction, 2026-09-10.)

   ---- The type scale (2026-09-18, readability pass; Lee: "the contrast is
   so bad and the text so small across the tool") -------------------------
   Five sizes and nothing else. Weight carries the hierarchy, not size. The
   whole scale moved up one step and the two greys moved two steps darker,
   because 83 of ~145 declarations were 14px, 31 were 12px, and most
   secondary text sat in a 4.6:1 grey; the IBM Plex swap (smaller x-height
   than Instrument Sans) made it read smaller still.

     13px  labels, meta, column headers, footnotes   (was 12)
     15px  secondary text: table cells, captions, controls   (was 14)
     16px  body, and anything a person reads in sentences   (was 15)
     17px  the lead sentence and section headings   (was 16)
     24px  display numbers and the page title

   Greys: --muted #374151 (10.3:1 on white), --faint #4B5563 (7.4:1). Dark
   mode: --muted #C4C9D2, --faint #9CA3AF. Nothing a person reads sits
   below 7:1.

   One label system: sentence case, normal tracking, everywhere. There is no
   tracked uppercase label anywhere in the app.

   ---- Score ----------------------------------------------------------------
   One component draws every score: GPScore.score(n, size) in scorecard.js,
   which owns one continuous colour rule (red below 34, amber 34 to 66, ink
   above 66) and the unit. The thresholds are published in the words of "How
   this score is made", so they are a rule rather than a house secret. Here
   there is only .sco: three sizes, the unit to the right of the number on its
   baseline at .6 of it, floored at 12px, and said once per surface — a list of
   scores passes an empty unit and lets its column header carry it. There is no
   green; a healthy score is simply not coloured. */

/* All tokens (colors, both themes, type scale, spacing, radius, shadow,
   fonts) moved to web/tokens.css, which every page that loads this file
   links first. Nothing below should introduce a new one-off value; add it
   to tokens.css instead. */

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { background: var(--canvas); }
body { margin: 0; color: var(--text); font-family: var(--sans); font-size: var(--fs-16); line-height: 1.55; -webkit-font-smoothing: antialiased; font-variant-numeric: tabular-nums; }
a { color: var(--text); text-decoration: underline; text-decoration-color: var(--rule); text-underline-offset: 2px; }
a:hover { text-decoration-color: var(--text); }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
::placeholder { color: var(--faint); }
h1, h2, h3, h4, p { margin: 0; }

.app { display: flex; min-height: 100vh; }

/* ---- rail ---- */
.rail { width: var(--rail-w); flex: 0 0 auto; border-right: 1px solid var(--hairline); background: var(--rail); padding: var(--sp-20) var(--sp-12) var(--sp-16); position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; }
/* The brand block is its own thing and gets a clear 24px of air under it
   before the workspace switcher, so the two never read as one stack. */
.rail .brand { display: block; color: var(--text); text-decoration: none; font-size: var(--fs-15); font-weight: 600; padding: var(--sp-2) var(--sp-12) var(--sp-2); letter-spacing: -.01em; }
.rail .brand small { display: block; font-weight: 400; color: var(--muted); font-size: var(--fs-13); margin-top: 1px; }
.rail .workspace { display: flex; align-items: center; gap: var(--sp-6); margin: var(--sp-24) var(--sp-6) var(--sp-16); padding: var(--sp-8) var(--sp-8); border: 1px solid var(--hairline); border-radius: var(--radius-ctl); background: var(--card); font-size: var(--fs-15); color: var(--muted); }
.rail .workspace b { color: var(--text); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail .workspace svg { margin-left: auto; flex: 0 0 auto; color: var(--faint); }
/* Sentence case: the one tracked uppercase label on a page is "The scorecard". */
.rail .section { font-size: var(--fs-13); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--faint); padding: var(--sp-12) var(--sp-12) var(--sp-6); }
.rail nav { display: flex; flex-direction: column; gap: 1px; }
/* The company rows and the nav rows share one left edge: a 16px slot (an icon
   up top, the needs-a-hand dot down here) and then the name. The dot sits to
   the left of the name, exactly where it sits in the companies list. */
.rail .tenant-link { text-decoration: none; display: grid; grid-template-columns: 16px minmax(0, 1fr); align-items: center; gap: var(--sp-8); padding: var(--sp-8) var(--sp-12); border-radius: var(--radius-ctl); cursor: pointer; border: 0; background: none; text-align: left; width: 100%; }
.rail .tenant-link:hover { background: var(--accent-tint); }
.rail .tenant-link.on { background: var(--accent-tint); }
.rail .tenant-link.on .name { color: var(--text); font-weight: 600; }
.rail .tenant-link .name { font-size: var(--fs-15); font-weight: 400; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail .tenant-link .meta { font-size: var(--fs-13); color: var(--muted); white-space: nowrap; }
/* One dot palette, three colours and nothing else: --dot-ok, --dot-warn,
   --dot-bad. The rail's flag is the failed red, the same token the alert and
   the sources table use. */
.rail .tenant-link .flag { display: block; width: 7px; height: 7px; border-radius: 50%; background: var(--dot-bad); justify-self: center; align-self: center; }
.rail .tenant-link .flag.none { background: none; }
.rail .tenant-link .flag.setup { background: none; border: 1.5px solid var(--faint); }
.rail .total { display: none; }

.rail .spacer { flex: 1; }
/* The icon sits in a 16px slot at the same left edge and the same vertical
   centre as the status dot on a company row, so the two line up down one x. */
.rail .rail-link { text-decoration: none; display: flex; align-items: center; gap: var(--sp-8); padding: var(--sp-8) var(--sp-12); border-radius: var(--radius-ctl); font-size: var(--fs-15); color: var(--text); text-decoration: none; }
.rail .rail-link svg { flex: 0 0 16px; width: 16px; height: 16px; color: var(--faint); }
.rail .rail-link .meta { margin-left: auto; }
.rail .rail-link:hover { background: var(--accent-tint); }
/* Only the deepest item is ever marked: the root link drops its tint the
   moment a company is open, so two rows never read as selected at once. */
.rail .rail-link.on { background: var(--accent-tint); color: var(--text); font-weight: 600; }
.rail .rail-link.on svg { color: var(--text); }
.rail .rail-link .meta { color: var(--muted); font-size: var(--fs-13); }
/* How many companies need a hand: a badge, in the one red token. */
.rail .rail-link .count { margin-left: auto; min-width: 20px; height: 20px; padding: 0 var(--sp-6); border-radius: var(--radius-pill); background: var(--bad-bg); color: var(--bad); font-size: var(--fs-13); font-weight: 600; display: inline-flex; align-items: center; justify-content: center; font-variant-numeric: tabular-nums; }
.rail .rail-link .count:empty { display: none; }
.rail .empty { padding: var(--sp-8) var(--sp-12); color: var(--muted); font-size: var(--fs-15); }

/* ---- main ---- */
main { flex: 1; min-width: 0; padding: var(--sp-32) var(--sp-40) var(--sp-96); }
.column { max-width: 980px; margin: 0 auto; }

/* ---- rail + main: phone width (S6) ---------------------------------------
   At 390px .app's flex row can't fit a 234px rail beside any usable main
   column, so below 700px the rail stops being a sticky side column and
   becomes a top strip: full width, no fixed height, no longer sticky. Its
   own contents (nav links, the company list, the add-a-client form) keep
   their normal vertical stacking, just narrower. Placed after the base
   main/.rail rules above so the padding override actually wins (same
   specificity, later wins). Nothing here touches the desktop layout above
   the breakpoint. */
@media (max-width: 700px) {
  .app { flex-direction: column; }
  .rail { width: 100%; height: auto; max-height: 60vh; overflow-y: auto; position: static; border-right: 0; border-bottom: 1px solid var(--hairline); }
  main { padding: var(--sp-20) var(--sp-16) var(--sp-64); }
}
.head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-24); margin-bottom: var(--sp-16); }
.head h1 { font-family: var(--sans); font-weight: 600; font-size: var(--fs-24); letter-spacing: -.02em; line-height: 1.2; }
/* One toolbar, two controls: a secondary outlined button out to the client
   page, and Rescan, the only primary control on the page. Both are buttons of
   the same height, so the toolbar has one shape instead of a link, an icon and
   a button jostling at three weights. */
/* Rename in place (LEE-382): the Edit button shows on hover and focus, always
   under 700px; the edit form replaces the name and the sub line. */
.name-row { display: flex; align-items: center; gap: var(--sp-8); }
.name-row .edit-name { height: 28px; padding: 0 var(--sp-8); color: var(--muted); border-color: var(--rule); opacity: 0; }
.name-row:hover .edit-name, .name-row:focus-within .edit-name, .edit-name:focus-visible { opacity: 1; }
.name-edit { width: 100%; max-width: 480px; margin-bottom: var(--sp-8); }
.name-edit input { width: 100%; box-sizing: border-box; }
#tenant-view .head.editing > div:first-child { flex: 1 1 auto; min-width: 0; }
.name-edit-actions { display: flex; gap: var(--sp-8); }
@media (max-width: 900px) { .name-row .edit-name { opacity: 1; } }
/* Wraps, right-aligned, rather than running past the page edge when a long
   name meets a published read's four actions (LEE-494). */
.head .actions { display: flex; gap: var(--sp-12); align-items: center; margin-top: var(--sp-2); flex-wrap: wrap; justify-content: flex-end; }
.head .actions .btn { height: var(--ctl-h); font-size: var(--fs-15); padding: 0 var(--sp-16); }
/* ---- company head: phone and tablet width (2026-09-27 responsive sweep) ---
   At 768px .head .actions (Report page, Published date, Rescan or Approve)
   is one row that does not wrap, so it runs past the page edge. Placed
   after the unconditional .head/.head .actions rules above (same
   specificity, later wins), or the nowrap above would keep beating it. The
   title and the actions row both wrap below 900px, the actions dropping
   under the title instead of pushing the page wider. */
@media (max-width: 900px) {
  .head { flex-wrap: wrap; }
  .head .actions { flex-wrap: wrap; justify-content: flex-start; }
  /* Every real control gets a 44px tap target at phone and tablet width
     without touching the desktop density above 900px: min-height leaves
     the declared height/padding alone and only raises the floor. */
  /* .conn-name is excluded: its whole row is the click target
     (.conn-list tr.rowlink, wired in connections.js), already well past
     44px via the row's own padding, so bumping the link itself would only
     force it out of its block layout for no gain. */
  .head .actions .btn, .btn, .chipc, .howlink, .back-link { min-height: var(--tap); display: inline-flex; align-items: center; }
  input[type="text"], input[type="number"], input[type="email"], input[type="url"], select { min-height: var(--tap); }
  .companies td .co { min-height: var(--tap); display: inline-flex; align-items: center; }
  .catrow { min-height: var(--tap); }
  /* The side rail's own nav links are still the tall sidebar (that switch
     to a wrapped top strip happens below 700px), so between 700 and 900
     they need the same floor the wrapped version already gets at 911. */
  .rail .rail-link { min-height: var(--tap); }
  /* People's company link and any other plain <a> sitting alone in a
     table cell (no .co/.vac wrapper) is two pixels short of 44px at the
     row's normal 12px padding; nudging the whole table's row padding
     clears it without a one-off class. */
  table.tbl td { padding: var(--sp-12) var(--sp-12); }
  /* The read tab's own fold controls (Details, Not checked) are real
     tap targets, same as web/read.html's .fold summary, just narrower.
     .formula counts too, since client.html shows it to clients. .rowdet
     summaries are left alone: they sit in the dense audit/job log, a
     power-user reading context rather than something tapped in the
     normal flow. */
  .card details > summary, details.card > summary, details.notchecked summary, .fix details > summary, .formula summary { min-height: var(--tap); }
  .people-search { min-height: var(--tap); }
  .include-test { display: inline-flex; align-items: center; min-height: var(--tap); }
  /* Company chips stay small pills; the tap area reaches 44px around them. */
  .co-chip { position: relative; }
  .co-chip::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: var(--tap); transform: translateY(-50%); }
}

/* Where you are: underline tabs under the title, in the same hairline
   vocabulary as every other rule on the page. The rule under the tabs is the
   tab row's own, so the subhead does not draw a second one. */
.subhead { margin-bottom: 0; }
.subhead .tabs { margin-bottom: 0; }
.head .sub { color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-4); max-width: 64ch; }
/* The caption under a page title: where a standing figure lives when it is
   context for the page rather than a row in the table below it. */
.head .cap { color: var(--faint); font-size: var(--fs-15); margin-top: var(--sp-4); max-width: 78ch; }
.head .sub a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--rule); }
.head .sub a:hover { color: var(--accent); }
.head .sub a:hover { color: var(--text); }
.chip { display: inline-flex; align-items: center; gap: var(--sp-8); height: 30px; padding: 0 var(--sp-12); border-radius: var(--radius-pill); border: 1px solid var(--hairline); background: var(--card); font-size: var(--fs-15); color: var(--muted); white-space: nowrap; margin-top: var(--sp-4); }
.chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dot-ok); }
.chip.bad { color: var(--bad); border-color: var(--bad-border); background: var(--bad-bg); } .chip.bad .dot { background: var(--dot-bad); }
.chip.warn { color: var(--warn); border-color: var(--warn-border); background: var(--warn-bg); } .chip.warn .dot { background: var(--dot-warn); }

/* ---- tabs ---- */
.tabs { display: flex; gap: var(--sp-2); border-bottom: 1px solid var(--hairline); margin-bottom: var(--sp-24); }
.tab { display: inline-flex; align-items: center; gap: var(--sp-8); padding: var(--sp-12); white-space: nowrap; font-size: var(--fs-15); font-weight: 500; color: var(--muted); background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer; margin-bottom: -1px; }
.tab:hover { color: var(--text); }
.tab.on { color: var(--text); border-bottom-color: var(--accent); font-weight: 500; }
.tab .badge { min-width: 18px; height: 18px; padding: 0 var(--sp-6); border-radius: var(--radius-pill); font-size: var(--fs-13); font-weight: 600; display: inline-flex; align-items: center; justify-content: center; background: var(--bad-bg); color: var(--bad); }
.tab .badge.warn { background: var(--warn-bg); color: var(--warn); }
.tab .badge.neutral { background: var(--accent-tint); color: var(--muted); }
/* LEE-480: People and Invitations counts are plain numbers, not chips (WorkOS). */
.tab .badge.plain { background: none; min-width: 0; padding: 0; font-weight: 400; font-size: var(--fs-15); color: var(--muted); }
.panel { display: none; } .panel.on { display: block; padding-top: var(--sp-24); }

/* ---- attention list ---- */
.attention { margin-bottom: var(--sp-20); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.attention .item { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-16); align-items: center; padding: var(--sp-12) var(--sp-16) var(--sp-12) var(--sp-16); border-bottom: 1px solid var(--hairline); min-height: 56px; box-shadow: inset 3px 0 0 var(--bad); }
.attention .item.warn { box-shadow: inset 3px 0 0 var(--warn); }
.attention .item.neutral { box-shadow: inset 3px 0 0 var(--rule); }
.attention .item.child { padding-left: var(--sp-40); box-shadow: none; min-height: var(--tap); }
.attention .item.child .what { color: var(--muted); }
.attention .item.compact { min-height: 40px; padding-top: var(--sp-8); padding-bottom: var(--sp-8); }
.attention .item:last-child { border-bottom: 0; }
.attention .bar { display: none; }
.attention .item.compact { min-height: var(--tap); }
.attention .what { font-size: var(--fs-15); }
.attention .what small { display: block; color: var(--muted); font-size: var(--fs-15); margin-top: 1px; }
.attention .what small.next { color: var(--ink); }
.attention .item.target, .card.target, section.target, .conn-links.target, #tenant-actions-decision.target { background: var(--accent-tint); }
#tenant-actions-decision.target { display: inline-flex; gap: var(--sp-8); align-items: center; padding: var(--sp-8); border-radius: var(--radius-sm); }
/* LEE-497: a row with two buttons puts them under its text on a phone, so the
   sentence keeps the full width. */
@media (max-width: 700px) {
  .attention .item:has(.row-actions .btn + .btn) { grid-template-columns: minmax(0, 1fr); gap: var(--sp-8); }
  .attention .item:has(.row-actions .btn + .btn) .row-actions { justify-content: flex-start; }
}
.attention .allclear { padding: var(--sp-16) var(--sp-16); color: var(--muted); font-size: var(--fs-15); display: flex; align-items: center; gap: var(--sp-12); }
.attention .allclear .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dot-ok); }

/* ---- key line: the counts as one sentence, judgment in colour ---- */
.kline { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-6) var(--sp-24); padding: var(--sp-4) 0 var(--sp-20); font-size: var(--fs-15); color: var(--muted); }
.kline .k { display: inline-flex; align-items: baseline; gap: var(--sp-6); }
.kline .k b { font-size: var(--fs-24); font-weight: 600; color: var(--text); letter-spacing: -.01em; }
.kline .k.bad b { color: var(--bad); } .kline .k.warn b { color: var(--warn); } .kline .k.zero b { color: var(--faint); }
.kline .sep { color: var(--rule); }

/* ---- stat strip (legacy, unused after iteration 3) ---- */
.strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; margin-bottom: var(--sp-20); }
.strip .stat { background: var(--card); padding: var(--sp-16) var(--sp-16); min-height: 84px; }
.strip .stat .n { font-size: var(--fs-24); font-weight: 600; letter-spacing: -.01em; line-height: 1.1; }
.strip .stat .n.bad { color: var(--bad); } .strip .stat .n.warn { color: var(--warn); } .strip .stat .n.zero { color: var(--faint); }
.strip .stat .l { font-size: var(--fs-15); color: var(--muted); margin-top: var(--sp-6); }
.strip .stat .l b { color: var(--text); font-weight: 500; }
.strip.five { grid-template-columns: repeat(5, 1fr); }
.strip.three { grid-template-columns: repeat(3, 1fr); }
.asof { font-size: var(--fs-13); color: var(--faint); margin: calc(var(--sp-12) * -1) 0 var(--sp-20); }

/* ---- cards ---- */
.card { background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow); padding: var(--pad-card-dense); margin-bottom: var(--sp-16); }
.card > h2 { font-size: var(--fs-16); font-weight: 600; letter-spacing: -.005em; margin-bottom: var(--sp-12); }
.card > h2 .n { color: var(--muted); font-weight: 400; margin-left: var(--sp-8); font-size: var(--fs-15); }
.card .cardhead { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-16); margin-bottom: var(--sp-12); }
.card .cardhead h2 { margin: 0; }
.card .cardhead .hint { color: var(--muted); font-size: var(--fs-15); }
.card .under { color: var(--muted); font-size: var(--fs-15); margin: calc(var(--sp-6) * -1) 0 var(--sp-16); }
.card p.lead { color: var(--muted); font-size: var(--fs-15); margin-bottom: var(--sp-12); max-width: 70ch; }
.grid2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-16); align-items: start; }
.grid-main-side { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--sp-16); align-items: start; }
@media (max-width: 1100px) { .grid2, .grid-main-side { grid-template-columns: 1fr; } }
.group-title { font-size: var(--fs-13); font-weight: 600; color: var(--faint); letter-spacing: 0; text-transform: none; margin: var(--sp-24) 0 var(--sp-8); }
.group-title:first-child { margin-top: 0; }

/* ---- tables ---- */
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-15); }
table.tbl th { text-align: left; font-size: var(--fs-13); color: var(--faint); font-weight: 600; padding: var(--sp-8) var(--sp-12); border-bottom: 1px solid var(--rule); white-space: nowrap; background: var(--card); }
/* No height on a cell. A cell shorter than its row used to paint its own
   border-bottom part-way up, which is the stray underline that appeared
   beneath every score in the companies list. Padding sets the rhythm now. */
table.tbl td { padding: var(--sp-12) var(--sp-12); border-bottom: 1px solid var(--hairline); vertical-align: middle; }
/* The header stays put while a long table scrolls past it. Needs a table that
   is not inside .tbl-wrap, since that wrapper is its own scroll box. */
table.tbl.stick th { position: sticky; top: 0; z-index: 2; box-shadow: inset 0 -1px 0 var(--rule); }
table.tbl tr:last-child td { border-bottom: 0; }
table.tbl tr:hover td { background: var(--rail); }
/* Figures line up in a column: tnum is asked for explicitly, because the body
   rule alone does not survive every face's default figure set. */
table.tbl td.num, table.tbl th.num { text-align: right; font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1, "lnum" 1; }
table.tbl td.id { font-family: var(--mono); font-size: var(--fs-15); }
table.tbl td.dim { color: var(--muted); }
table.tbl td.nw { white-space: nowrap; }
table.tbl tr.is-bad td:first-child { box-shadow: inset 3px 0 0 var(--bad); }
table.tbl tr.is-warn td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
table.tbl td .note { color: var(--muted); font-size: var(--fs-15); display: block; margin-top: var(--sp-2); max-width: 60ch; white-space: normal; }
.tbl-wrap { overflow-x: auto; }
.rowactions { display: flex; gap: var(--sp-4); justify-content: flex-end; }

/* ---- status: one chip everywhere (a dot, then a word) ----
   Fixed width wherever chips stack, so the dots line up in a column and the
   eye reads down them instead of hunting. */
.pill { display: inline-flex; align-items: center; gap: var(--sp-6); font-size: var(--fs-15); white-space: nowrap; }
.tbl .pill, .cardhead .pill { min-width: 148px; }
.pill .dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--dot-none); }
.pill.neutral .dot { background: var(--dot-none); }
.pill.good .dot { background: var(--dot-ok); }
.pill.warn .dot { background: var(--dot-warn); } .pill.warn { color: var(--warn); }
.pill.bad .dot { background: var(--dot-bad); } .pill.bad { color: var(--bad); }
.pill.neutral { color: var(--muted); }

/* ---- buttons: primary, secondary, destructive (text), link ---- */
.btn { height: var(--ctl-h); padding: 0 var(--sp-16); border-radius: var(--radius-ctl); font-size: var(--fs-15); font-weight: 500; cursor: pointer; border: 1px solid transparent; background: none; white-space: nowrap; display: inline-flex; align-items: center; gap: var(--sp-6); text-decoration: none; }
.btn.primary { background: var(--accent); color: var(--on-accent); }
.btn.primary:hover { background: var(--accent-hover); }
.btn.secondary { border-color: var(--rule); color: var(--text); background: var(--card); }
.btn.secondary:hover { border-color: var(--faint); }
.btn.destructive { color: var(--bad); border-color: var(--bad-border); }
.btn.primary.danger { background: var(--bad); }
.btn.destructive:hover { background: var(--bad-bg); }
.btn.link { color: var(--muted); padding: 0 var(--sp-6); height: var(--ctl-h-sm); }
.btn.link:hover { color: var(--text); background: var(--accent-tint); }
.btn.sm { height: var(--ctl-h-sm); padding: 0 var(--sp-12); font-size: var(--fs-15); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btnrow { display: flex; align-items: center; gap: var(--sp-8); margin-top: var(--sp-16); }

/* ---- forms ---- */
label { display: block; font-size: var(--fs-15); color: var(--muted); margin-bottom: var(--sp-6); }
input[type="text"], input[type="number"], input[type="email"], input[type="url"], textarea, select { width: 100%; background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-ctl); padding: var(--sp-8) var(--sp-12); font: inherit; color: var(--text); font-size: var(--fs-15); }
/* A one-line box is exactly as tall as the button beside it. */
input[type="text"], input[type="number"], input[type="email"], input[type="url"], select { height: var(--ctl-h); padding-top: 0; padding-bottom: 0; }
textarea { font-family: var(--mono); font-size: var(--fs-15); min-height: 120px; resize: vertical; line-height: 1.5; }
textarea.tall { min-height: 200px; }
textarea.csv { min-height: 140px; }
input:focus, textarea:focus, select:focus { border-color: var(--faint); }
.field { margin-bottom: var(--sp-12); }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-12); }
.error-text { color: var(--bad); font-size: var(--fs-15); margin-top: var(--sp-8); white-space: pre-wrap; }
.help { color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-6); line-height: 1.5; }
.phrase { font-size: var(--fs-15); }
.phrase code { font-family: var(--mono); font-size: var(--fs-15); background: var(--accent-tint); padding: 1px var(--sp-6); border-radius: var(--radius-sm); }

/* ---- list rows ---- */
.rows { display: flex; flex-direction: column; }
.rows .r { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); padding: var(--sp-8) 0; border-bottom: 1px solid var(--hairline); font-size: var(--fs-15); }
.rows .r:last-child { border-bottom: 0; }
.rows .r .k { color: var(--muted); }

/* ---- score ---- */
.score { display: flex; align-items: baseline; gap: var(--sp-12); }
.score .big { font-size: var(--fs-24); font-weight: 600; letter-spacing: -.01em; }
.score .of { color: var(--faint); font-size: var(--fs-15); }
.meter { height: 6px; border-radius: var(--radius-sm); background: var(--accent-tint); margin: var(--sp-8) 0 var(--sp-6); overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--good); }
.meter i.warn { background: var(--warn); } .meter i.bad { background: var(--bad); }

/* ---- reports ---- */
.report-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-16); align-items: center; padding: var(--pad-card-dense); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow); background: var(--card); margin-bottom: var(--sp-12); }
.report-card .t { font-size: var(--fs-15); font-weight: 500; }
.report-card .m { color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-2); display: flex; gap: var(--sp-12); align-items: center; }
.reading { margin-top: var(--sp-16); }
.reading .verdict { font-size: var(--fs-16); line-height: 1.6; max-width: 70ch; margin-bottom: var(--sp-16); }
.reading textarea.verdict-edit { font-family: var(--sans); font-size: var(--fs-16); line-height: 1.6; min-height: 140px; }
.reading .decide { display: flex; align-items: center; gap: var(--sp-8); padding-top: var(--sp-16); margin-top: var(--sp-16); border-top: 1px solid var(--hairline); }
.reading .decide .fill { flex: 1; }
.callout { border-left: 3px solid var(--ink); padding: var(--sp-4) var(--sp-16); font-size: var(--fs-15); margin: var(--sp-16) 0; }
.callout.bad { border-left-color: var(--bad); }

/* ---- checklist (empty tenant) ---- */
.checklist { display: flex; flex-direction: column; }
.checklist .step { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: var(--sp-16); align-items: center; padding: var(--sp-16) 0; border-bottom: 1px solid var(--hairline); }
.checklist .step:last-child { border-bottom: 0; }
.checklist .num { width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--rule); display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-13); color: var(--muted); }
.checklist .num.done { background: var(--good); border-color: var(--good); color: var(--on-accent); }
.checklist .step .t { font-size: var(--fs-15); font-weight: 500; }
.checklist .step .d { color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-2); }
.checklist .step.later { opacity: .55; }
.checklist .step.current .num { border-color: var(--accent); color: var(--text); font-weight: 600; }

/* ---- misc ---- */
.muted { color: var(--muted); } .faint { color: var(--faint); } .mono { font-family: var(--mono); }
.empty { color: var(--muted); font-size: var(--fs-15); padding: var(--sp-20) 0; }
.empty b { color: var(--text); font-weight: 500; }
.toast { position: fixed; left: 50%; bottom: var(--sp-24); transform: translateX(-50%); background: var(--ink); color: var(--canvas); padding: var(--sp-12) var(--sp-16); border-radius: var(--radius-pill); font-size: var(--fs-15); opacity: 0; transition: opacity .15s; pointer-events: none; }
.toast.on { opacity: 1; }
.toast.err { background: var(--bad); }
.toast.act { pointer-events: auto; }
.toast-action { background: none; border: 0; color: inherit; font: inherit; font-weight: 600; text-decoration: underline; cursor: pointer; padding: 0 var(--sp-4); }
.person-remove-all { margin: var(--sp-12) 0 0; }
.member-role { min-width: 96px; }
.loading { color: var(--faint); font-size: var(--fs-15); padding: var(--sp-24) 0; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); }
.row { display: flex; align-items: center; gap: var(--sp-8); }

/* ---- file drop zone ---- */
.drop { border: 1px dashed var(--rule); border-radius: var(--radius); padding: var(--sp-20); text-align: center; color: var(--muted); font-size: var(--fs-15); cursor: pointer; background: var(--canvas); }
.drop:hover, .drop.over { border-color: var(--faint); background: var(--accent-tint); }
.drop b { color: var(--text); font-weight: 500; }
.drop input { display: none; }
.drop .picked { color: var(--text); }
/* ---- settings rows ---- */
.setting { display: grid; grid-template-columns: 150px minmax(0, 1fr) auto; gap: var(--sp-16); align-items: center; padding: var(--sp-12) 0; border-bottom: 1px solid var(--hairline); font-size: var(--fs-15); }
.setting:last-child { border-bottom: 0; }
.setting .k { color: var(--muted); }
.setting .v { font-family: var(--mono); font-size: var(--fs-15); overflow-wrap: anywhere; cursor: copy; line-height: 1.4; }
.setting.flagged { box-shadow: inset 3px 0 0 var(--bad); padding-left: var(--sp-12); }
.setting.flagged .k { color: var(--bad); }
.setting .v.none { font-family: var(--sans); color: var(--faint); }
.setting input { max-width: 360px; }

/* ---- offer ladder row editor (the .setting row that holds #pf-offer-ladder-tbl) ---- */
.setting.ladder-row .v { font-family: var(--sans); cursor: default; }
.setting.ladder-row table.tbl { margin-bottom: var(--sp-12); }
.setting.ladder-row table.tbl input, .setting.ladder-row table.tbl select { max-width: none; width: 100%; font-size: var(--fs-15); }
.setting.ladder-row table.tbl td:first-child { width: auto; }
.setting.ladder-row table.tbl td:nth-child(2) { width: 110px; }
.setting.ladder-row table.tbl td:nth-child(3) { width: 140px; }
.setting.ladder-row table.tbl td:last-child { width: 1%; white-space: nowrap; }

/* ---- profile field rows (web/profile.js's card/fieldRow; PLAN.md E21
   readability pass, 2026-09-18 — Lee: "the tool is hard to read"). A
   profile field's value is prose (what it sells, who pays, the offer
   ladder, evidence sentences), never a short copyable id, so it overrides
   .setting .v's monospace/copy-cursor back to the sans at body size — the
   same override pattern .setting.ladder-row .v above already uses, kept
   its own block because a profile row stacks three lines (the humanised
   value, its evidence, its source) instead of holding one value. */
.setting.profile-field { align-items: start; }
.setting.profile-field .v { font-family: var(--sans); font-size: var(--fs-16); line-height: 1.55; color: var(--text); cursor: auto; overflow-wrap: anywhere; display: flex; flex-direction: column; gap: var(--sp-4); }
.setting .v .pf-check { display: block; font-family: var(--sans); font-size: var(--fs-16); color: var(--text); cursor: auto; }
.profile-field .pf-lead { font-weight: 500; }
.profile-field .pf-ladder { display: flex; flex-direction: column; gap: var(--sp-2); }
.profile-field .pf-evidence { font-weight: 400; color: var(--muted); font-size: var(--fs-15); line-height: 1.5; }
.profile-field .pf-source { font-size: var(--fs-13); color: var(--faint); }
.profile-field .pf-source a { color: inherit; }
.profile-field .pill.sm { font-size: var(--fs-13); padding: 1px var(--sp-8); border-radius: var(--radius-pill); background: var(--accent-tint); margin-left: var(--sp-2); }
.profile-field .pill.warn.sm { background: var(--warn-bg); }

/* ---- all-clear line ---- */
.clear { display: flex; align-items: center; gap: var(--sp-12); padding: var(--pad-card); background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow); font-size: var(--fs-15); margin-bottom: var(--sp-20); }
.clear .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dot-ok); }
.clear .rest { color: var(--muted); }
/* ---- reorder arrows ---- */
.arrows { display: inline-flex; gap: var(--sp-2); }
.arrows button { width: 24px; height: 24px; border: 1px solid var(--hairline); background: var(--card); border-radius: var(--radius-ctl); cursor: pointer; color: var(--muted); font-size: var(--fs-13); line-height: 1; }
.arrows button:hover { color: var(--text); border-color: var(--rule); }
.arrows button:disabled { opacity: .3; cursor: default; }
/* ---- steps (instructions) ---- */
ol.steps { margin: var(--sp-8) 0 0; padding-left: var(--sp-20); color: var(--muted); font-size: var(--fs-15); }
ol.steps li { margin-bottom: var(--sp-4); }

/* ---- the root view ---- */
.who { font-size: var(--fs-15); color: var(--muted); margin-bottom: var(--sp-2); }
.trend { color: var(--muted); font-size: var(--fs-15); }
.trend.up { color: var(--good); } .trend.down { color: var(--bad); }
.chips { display: flex; gap: var(--sp-8); flex-wrap: wrap; }
.chipc { font-size: var(--fs-15); color: var(--muted); border: 1px solid var(--hairline); border-radius: var(--radius-pill); padding: var(--sp-4) var(--sp-12); background: none; cursor: pointer; font-family: inherit; }
.chipc.on { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.chipc:disabled { cursor: default; }
.chipc b { color: var(--text); font-weight: 500; }

/* ---- headline numbers (report figures on overview and client) ---- */
.figures { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); margin: var(--sp-4) 0 var(--sp-20); }
.figures .f { padding: var(--sp-16) var(--sp-16) var(--sp-16) 0; }
.figures .f + .f { padding-left: var(--sp-16); border-left: 1px solid var(--hairline); }
.figures .f .n { font-size: var(--fs-24); font-weight: 600; letter-spacing: -.01em; line-height: 1.1; }
.figures .f.lead .n { font-size: var(--fs-24); }
.figures .f.bad .n { color: var(--bad); }
.figures .f .l { font-size: var(--fs-15); color: var(--muted); margin-top: var(--sp-4); }
.figures .f .d { font-size: var(--fs-15); margin-top: var(--sp-2); }
.figures .f .d.up { color: var(--good); } .figures .f .d.down { color: var(--muted); }
.sticky { position: sticky; top: 0; background: var(--canvas); z-index: 2; }

/* ---- pull quote (next move) ---- */
.pull { font-size: var(--fs-17); line-height: 1.45; letter-spacing: -.005em; padding: var(--sp-16) 0 var(--sp-16) var(--sp-20); border-left: 3px solid var(--ink); margin: var(--sp-20) 0; max-width: 64ch; }
.pull small { display: block; font-family: var(--sans); font-size: var(--fs-15); color: var(--muted); margin-top: var(--sp-6); letter-spacing: 0; }
/* ---- skeleton ---- */
.skel { height: 12px; border-radius: var(--radius-sm); background: linear-gradient(90deg, var(--accent-tint), var(--hairline), var(--accent-tint)); background-size: 200% 100%; animation: sk 1.2s linear infinite; margin: var(--sp-12) 0; }
@keyframes sk { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }
/* ---- callout with a title, a sentence, and a button ---- */
.fix { border-left: 3px solid var(--bad); padding: var(--sp-6) 0 var(--sp-6) var(--sp-16); margin: var(--sp-12) 0 var(--sp-16); }
.fix .t { font-weight: 600; font-size: var(--fs-15); }
.fix .s { color: var(--muted); font-size: var(--fs-15); margin: var(--sp-2) 0 var(--sp-12); max-width: 70ch; }
.fix details summary { cursor: pointer; color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-8); }
/* ---- chip groups ---- */
.chipgroup { display: flex; align-items: center; gap: var(--sp-6); margin-right: var(--sp-20); flex-wrap: wrap; }
.chipgroup .lbl { font-size: var(--fs-13); color: var(--faint); margin-right: var(--sp-2); }
/* ---- id with copy ---- */
.idc { font-family: var(--mono); font-size: var(--fs-13); color: var(--muted); cursor: copy; }
/* ---- rail: add a client ---- */
.rail form { padding: var(--sp-8) var(--sp-12); }
.rail form input { font-size: var(--fs-15); padding: var(--sp-6) var(--sp-8); }
.rail form input::placeholder { font-size: var(--fs-13); }
/* ---- the site tag's install snippet (PLAN.md E9) ---- */
.card details > summary { cursor: pointer; color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-12); }
.snippet { font-family: var(--mono); font-size: var(--fs-13); line-height: 1.55; background: var(--accent-tint); border: 1px solid var(--hairline); border-radius: var(--radius-ctl); padding: var(--sp-12) var(--sp-12); margin: var(--sp-12) 0 var(--sp-6); white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- the header's decision, U3 goal 2 --------------------------------------
   The confirm step replaces the primary button in place: no browser
   confirm() dialog, just the question and Approve/Cancel where the button
   was. */
.confirm-inline { display: inline-flex; align-items: center; gap: var(--sp-12); flex-wrap: wrap; }
.confirm-inline .q { font-size: var(--fs-15); color: var(--muted); max-width: 42ch; }
#tenant-actions-decision { display: contents; }
.head .actions .muted { font-size: var(--fs-15); white-space: nowrap; }
#panel-read .g-state { margin-bottom: var(--sp-20); }
#panel-read .g-lead { margin-bottom: var(--sp-32); }

/* ---- the read's state line, U3 goal 3 --------------------------------------
   One line, top of the tab: what state the read is in, and how much of the
   check set is answered. Everything the old header's KPI stack led with. */
.g-state { font-size: var(--fs-15); color: var(--muted); display: flex; align-items: center; gap: var(--sp-8); margin-bottom: var(--sp-4); }
.g-state .st { font-weight: 600; color: var(--text); }
.g-state .sep { color: var(--faint); }

/* ---- the read as a scorecard (PLAN.md E13) ---------------------------------
   One grid for the whole company page, five parts to seven, and every block on
   it starts on one of its two columns. Row one is the two tiles beside what
   matters most; row two the scorecard's own header across both; row three the
   ranked list beside the checks; row four the moves across the foot. Nothing
   is left with a blank right third. */
.pagegrid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--sp-32); row-gap: var(--sp-24); align-items: start; }
.g-tiles { grid-column: 1; grid-row: 1; align-self: start; }
.g-lead { grid-column: 2; grid-row: 1; }
.g-scorehead { grid-column: 1 / -1; grid-row: 2; }
.g-list { grid-column: 1; grid-row: 3; }
.g-pane { grid-column: 2; grid-row: 3; }
/* The moves carry the same section marker as the scorecard: one label system,
   one size, one case, a rule underneath. */
.g-moves { grid-column: 1 / -1; grid-row: 4; }
.g-moves .scorehead { margin-bottom: var(--sp-20); }
@media (max-width: 900px) {
  .pagegrid { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-20); }
  .g-tiles, .g-lead, .g-scorehead, .g-list, .g-pane, .g-moves { grid-column: 1; grid-row: auto; }
  .g-lead { order: -1; }
}
/* What matters most: the sentence the whole page exists to deliver, set in the
   right column's own measure. Regular weight with the first sentence bold, so
   the paragraph stops competing with the alert and the Overall tile for the
   eye and instead hands it one line to read first. (Size stays 16: Lee's
   floor is that nothing gets smaller than it is today.) */
.onething { margin: 0; }
.onething p { font-size: var(--fs-17); font-weight: 400; line-height: 1.55; letter-spacing: -.005em; max-width: 68ch; }
.onething p b { font-weight: 600; }
.onething small { display: block; font-size: var(--fs-13); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--faint); margin-bottom: var(--sp-8); }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---- the score, one component, three sizes --------------------------------
   Number then unit, always in that order and always on one baseline. The unit
   is .6 of the number, and 12px is the floor because nothing in this app is
   smaller than 12px. Colour comes from GPScore.scoreTone and nowhere else. */
.sco { display: inline-flex; align-items: baseline; gap: var(--sp-6); font-variant-numeric: tabular-nums; color: var(--text); white-space: nowrap; }
.sco b { font-weight: 600; letter-spacing: -.02em; line-height: 1; }
.sco small { color: var(--faint); font-weight: 400; letter-spacing: 0; }
.sco-hero b { font-size: var(--fs-24); } .sco-hero small { font-size: var(--fs-15); }
.sco-row b { font-size: var(--fs-24); } .sco-row small { font-size: var(--fs-13); }
.sco-inline b { font-size: var(--fs-17); } .sco-inline small { font-size: var(--fs-13); }
.sco.warn b { color: var(--warn); } .sco.bad b { color: var(--bad); }
.sco.nil b { color: var(--rule); font-weight: 400; }

/* The alert: the only red line on the page, and it is meant to be absent. It
   stays inside the content column — the old band bled 14px past it on both
   sides — and it says the plain error, because the page's own subtitle is
   where the phrase "needs a hand" lives, once. Its dot is the failed red from
   the one dot palette. */
.alert { display: flex; align-items: baseline; gap: var(--sp-12); padding: var(--sp-12) var(--sp-16); border: 1px solid var(--bad-border); background: var(--bad-bg); border-radius: var(--radius); font-size: var(--fs-15); color: var(--bad); margin: 0 0 var(--sp-24); }
.alert .dot { display: block; width: 7px; height: 7px; border-radius: 50%; background: var(--dot-bad); flex: 0 0 auto; position: relative; top: -1px; }
.alert .w { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alert a { color: var(--bad); margin-left: auto; white-space: nowrap; font-weight: 600; }

/* The scorecard's own header: its name on the left, and on the right the date
   it was scored — which is also the control for reading the two first-party
   categories from an earlier week. Sentence case, like every other label. */
.scorehead { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16); padding-bottom: var(--sp-12); border-bottom: 1px solid var(--hairline); }
.scorehead .t { font-size: var(--fs-13); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--faint); }
.scorehead .scored { font-size: var(--fs-13); color: var(--faint); }

/* The category tiles: a titled header band (Lee's reference dashboard), the
   score below it. The letter and the client page lay them out as a grid; the
   admin uses exactly two of them, Overall and Checked, above its list. */
.cstrip { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: var(--sp-12); margin: 0 0 var(--sp-12); }
/* The admin's two: they hold the top of the left column, on the same line the
   paragraph beside them starts on. Overall is the wider of the pair because
   its header band also carries the link to how the score is made — beside the
   label it explains, not orphaned under the tiles. The band stays (Lee's
   reference dashboard) and is simply tighter. */
.cstrip.duo { grid-template-columns: 1.4fr 1fr; gap: var(--sp-12); margin: 0; }
.cstrip.duo .ctile .h { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-12); padding: var(--sp-8) var(--sp-12); }
.cstrip.duo .ctile .b { padding: var(--sp-12) var(--sp-12) var(--sp-16); }
.howlink { font-size: var(--fs-13); font-weight: 400; color: var(--muted); background: none; border: 0; border-bottom: 1px solid var(--rule); padding: 0; cursor: pointer; white-space: nowrap; font-family: inherit; line-height: 1.2; }
.howlink:hover { color: var(--text); border-bottom-color: var(--text); }
.howtext { color: var(--muted); font-size: var(--fs-15); line-height: 1.6; margin: var(--sp-12) 0 0; max-width: 76ch; }
.ctile { text-decoration: none; background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow); display: flex; flex-direction: column; min-width: 0; overflow: hidden; }
a.ctile:hover { border-color: var(--rule); }
a.ctile:hover .h { background: var(--accent-tint); }
.ctile .h { display: block; padding: var(--sp-8) var(--sp-12); background: var(--rail); border-bottom: 1px solid var(--hairline); font-size: var(--fs-13); font-weight: 600; color: var(--muted); line-height: 1.35; }
.cstrip:not(.duo) .ctile .h { font-weight: 500; min-height: 38px; }
.ctile .b { display: block; padding: var(--sp-12) var(--sp-12) var(--sp-16); }
.ctile .n { display: block; font-size: var(--fs-24); font-weight: 600; letter-spacing: -.02em; line-height: 1; color: var(--text); }
.ctile.warn .n { color: var(--warn); } .ctile.bad .n { color: var(--bad); }
.ctile .m { display: block; font-size: var(--fs-13); color: var(--muted); margin-top: var(--sp-8); }
/* A number we do not have is quieter and smaller than one we do. */
.nil { font-size: var(--fs-17); font-weight: 400; color: var(--rule); letter-spacing: 0; }
td.score .nil { font-size: var(--fs-15); }

/* ---- the scorecard: a ranked list, and the pane it drives ------------------
   Neither side is a card. Both are bare panels on the white canvas, separated
   by one hairline rule down the gutter, and their headers share a top edge and
   a baseline so the two columns read as one table with a spine.

   The numeral is the truth; the bar is only a comparison device, so it is a
   quiet 4px track along the full width of the row's bottom edge rather than a
   120px widget arguing with the number beside it. One ink fill at one opacity,
   red only on a row that is actually failing. How many of a row's checks were
   checked is said once, in the Checked tile, and not again per row. */
.listhead, .panehead { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-16); min-height: 40px; padding-bottom: var(--sp-12); border-bottom: 1px solid var(--hairline); }
.panehead h2 { font-family: var(--sans); font-size: var(--fs-17); font-weight: 600; letter-spacing: -.01em; }
.listhead .t { font-size: var(--fs-13); font-weight: 600; color: var(--faint); line-height: 1.4; }

.catlist { border: 0; background: none; box-shadow: none; }
.catrow { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; column-gap: var(--sp-12); width: 100%; padding: var(--sp-12) var(--sp-12) var(--sp-16); border: 0; background: none; text-align: left; cursor: pointer; font: inherit; color: var(--text); }
.catlist .catrow + .catrow { border-top: 1px solid var(--hairline); }
.catrow:hover { background: var(--rail); }
/* Selected: a tint and a 2px ink rule down the left edge. */
.catrow.on { background: var(--accent-tint); box-shadow: inset 2px 0 0 var(--ink); }
.catrow.on .nm { font-weight: 600; }
.catrow:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.catrow .nm { grid-column: 1; font-size: var(--fs-15); line-height: 1.3; min-width: 0; }
.catrow .sco { grid-column: 2; justify-self: end; }
.catrow .track { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: var(--accent-tint); }
.catrow.on .track { background: var(--card); }
.catrow .track i { display: block; height: 100%; background: var(--ink); opacity: .5; }
.catrow .track i.bad { background: var(--bad); opacity: 1; }
.catrow.unscored .nm { color: var(--muted); }
.catrow .nsy { grid-column: 2; justify-self: end; font-size: var(--fs-13); color: var(--faint); }

/* The pane: the hairline down the gutter is the only thing dividing the two
   columns, and it is drawn on the pane so row one above it stays untouched. */
.g-pane { position: relative; }
.g-pane::before { content: ""; position: absolute; left: calc(var(--sp-16) * -1); top: 0; bottom: 0; width: 1px; background: var(--hairline); }

/* The Sources list the pane's reference numerals point at. Without it the
   numerals are decoration; with it they are a claim a reader can check. */
.sources { margin-top: var(--sp-24); padding-top: var(--sp-12); border-top: 1px solid var(--hairline); }
.sources .t { display: block; font-size: var(--fs-13); font-weight: 600; color: var(--faint); margin-bottom: var(--sp-8); }
.sources .s { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: var(--sp-8); font-size: var(--fs-15); color: var(--muted); line-height: 1.5; padding: var(--sp-4) 0; overflow-wrap: anywhere; }
.sources .n { color: var(--faint); font-variant-numeric: tabular-nums; }
.sources a { color: var(--text); text-decoration-color: var(--rule); overflow-wrap: anywhere; }
.grp { margin-top: var(--sp-20); }
.gl { display: inline-flex; align-items: center; gap: var(--sp-6); font-size: var(--fs-13); font-weight: 600; color: var(--muted); }
.gl .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dot-none); flex: 0 0 auto; }
.gl.good .dot { background: var(--dot-ok); } .gl.warn .dot { background: var(--dot-warn); } .gl.bad .dot { background: var(--dot-bad); }
details.notchecked summary { cursor: pointer; color: var(--muted); }
.checks.plain { border-top: 0; margin-top: var(--sp-4); }
.chkp { padding: var(--sp-8) 0; border-bottom: 1px solid var(--hairline); }
.chkp:last-child { border-bottom: 0; }
.chkp .l { display: block; font-size: var(--fs-16); font-weight: 600; line-height: 1.4; }
.chkp .e { display: block; font-size: var(--fs-16); color: var(--muted); margin-top: var(--sp-2); line-height: 1.55; max-width: 72ch; }
/* The fix is a plain muted second line behind one small wrench. Four bold
   "Fix:" labels stacked down a pane read as something a machine stamped on. */
.chkp .f { display: grid; grid-template-columns: 14px minmax(0, 1fr); gap: var(--sp-8); align-items: start; font-size: var(--fs-16); color: var(--muted); margin-top: var(--sp-6); line-height: 1.55; max-width: 72ch; }
.chkp .f .wr { color: var(--faint); margin-top: var(--sp-6); }
.chkp.neutral .l { color: var(--muted); font-weight: 400; }

/* Narrow: the list stacks above the pane and its rows become tabs. */
@media (max-width: 900px) {
  #tenant-site, #tenant-address { display: inline-flex; align-items: center; min-height: var(--tap); }
  #tenant-oneline-part { display: block; }
  #tenant-oneline-part .sep { display: none; }
  .viewas-banner.on { padding-top: 0; padding-bottom: 0; }
  .g-pane::before { display: none; }
  .listhead { display: none; }
  .catlist { display: flex; flex-wrap: wrap; gap: var(--sp-6); border: 0; background: none; box-shadow: none; overflow: visible; }
  .catlist .catrow + .catrow { border-top: 0; }
  .catrow { width: auto; grid-template-columns: auto auto; gap: var(--sp-8); padding: var(--sp-8) var(--sp-12); border: 1px solid var(--hairline); border-radius: var(--radius-ctl); background: var(--card); }
  .catrow .track, .catrow .nsy { display: none; }
  .catrow .sco b { font-size: var(--fs-15); }
  .catrow.on { box-shadow: inset 0 -2px 0 var(--ink); }
}

/* ---- disclosures ----------------------------------------------------------
   No native triangle anywhere: it is a different shape in every browser and it
   is never the size we want. One 12px chevron, rotated when the thing opens. */
details > summary { list-style: none; display: flex; align-items: center; gap: var(--sp-8); }
details > summary::-webkit-details-marker { display: none; }
details > summary::marker { content: ""; }
.chev { flex: 0 0 auto; color: var(--faint); transition: transform .15s ease; }
details[open] > summary .chev { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .chev { transition: none; } }

/* We publish the formula; the lead-magnet graders do not. */
.formula { margin: 0 0 var(--sp-24); }
.formula summary { cursor: pointer; color: var(--muted); font-size: var(--fs-15); }
.formula p { color: var(--muted); font-size: var(--fs-15); line-height: 1.6; margin-top: var(--sp-8); max-width: 76ch; }

/* Which week the two first-party categories are read from. A button that
   opens a small list, not the operating system's own select box. In the
   scorecard's header it is the date itself, with a chevron: "Scored 8 Sep". */
.picker { position: relative; }
.picker > button { display: inline-flex; align-items: center; gap: var(--sp-12); height: var(--ctl-h); padding: 0 var(--sp-12) 0 var(--sp-12); border: 1px solid var(--rule); border-radius: var(--radius-ctl); background: var(--card); color: var(--text); font-size: var(--fs-15); cursor: pointer; min-width: 200px; justify-content: space-between; }
.picker > button:hover { border-color: var(--faint); }
.picker > button .caret { display: inline-flex; color: var(--faint); flex: 0 0 auto; }
.picker > button .caret .chev { transform: rotate(90deg); }
.picker.inline > button { min-width: 0; height: 24px; padding: 0 var(--sp-6) 0 var(--sp-8); gap: var(--sp-6); border-color: transparent; background: none; font-size: var(--fs-13); color: var(--faint); }
.picker.inline > button:hover { border-color: var(--rule); background: var(--card); color: var(--text); }
.picker.inline ul { left: auto; right: 0; }
.picker ul { position: absolute; z-index: 5; top: calc(100% + var(--sp-4)); left: 0; min-width: 100%; margin: 0; padding: var(--sp-4); list-style: none; background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-ctl); box-shadow: var(--shadow-md); max-height: 280px; overflow-y: auto; }
.picker li { padding: var(--sp-8) var(--sp-12); border-radius: var(--radius-ctl); font-size: var(--fs-15); color: var(--text); white-space: nowrap; cursor: pointer; }
.picker li[aria-selected="true"] { font-weight: 600; }
.picker li.here, .picker li:hover { background: var(--accent-tint); }

/* A category and its checks. */
.cat { border-top: 1px solid var(--hairline); padding-top: var(--sp-16); margin-top: var(--sp-24); scroll-margin-top: var(--sp-16); }
.cat .cathead { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-16); margin-bottom: var(--sp-6); }
.cat .cathead h2 { font-family: var(--sans); font-size: var(--fs-17); font-weight: 600; letter-spacing: -.01em; }
.checks { border-top: 1px solid var(--hairline); }
/* Every row is the same two slots: a 90px status column, then the label, the
   evidence and the fix stacked in one block. Nothing is ever centred against
   a taller neighbour, so the rows keep a rhythm. */
.chk { display: grid; grid-template-columns: 90px minmax(0, 1fr); gap: var(--sp-16); padding: var(--sp-12) var(--sp-2); border-bottom: 1px solid var(--hairline); align-items: start; }
.chk:last-child { border-bottom: 0; }
.chk > .s { padding-top: 1px; }
.chk .l { display: block; font-size: var(--fs-16); font-weight: 600; line-height: 1.4; }
.chk .e { display: block; font-size: var(--fs-16); color: var(--muted); margin-top: var(--sp-4); line-height: 1.55; max-width: 74ch; }
/* The fix is a second line of the same block, in ink, named as a fix. No
   quote rule: it is ours, not something pasted in. */
.chk .f { display: block; font-size: var(--fs-16); margin-top: var(--sp-6); color: var(--text); max-width: 74ch; line-height: 1.55; }
.chk .f::before { content: "Fix: "; font-weight: 600; }
.chk.neutral .l { color: var(--muted); font-weight: 400; }
/* Footnotes, everywhere the same: a real <sup> reference numeral, linked, at
   11px. The pill version read as a stray chip because nothing on the page
   listed what the numbers meant; the pane now ends in a Sources list, so the
   numerals can go back to being footnote markers. */
.srcs { display: inline; margin-left: 1px; }
.src { font-size: var(--fs-13); line-height: 0; color: var(--faint); padding: 0 1px; font-variant-numeric: tabular-nums; }
.src a { color: inherit; text-decoration: none; }
.src a:hover { color: var(--text); text-decoration: underline; }

/* The moves. Each one is shaped the same way: what to do, why it should work,
   and one inline meta line. The two-cell table this used to be left a void
   down its right side and made two short facts look like a report. */
ol.moves { padding-left: var(--sp-20); margin: 0; max-width: 68ch; }
ol.moves li { margin-bottom: var(--sp-20); font-size: var(--fs-16); line-height: 1.55; }
ol.moves li:last-child { margin-bottom: 0; }
ol.moves b { display: block; font-weight: 600; }
ol.moves span { display: block; color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-4); }
ol.moves .meta { display: block; margin-top: var(--sp-6); color: var(--muted); font-size: var(--fs-15); }

/* The root: one row per company. The read is capped at two lines with a clean
   ellipsis, so five rows keep one rhythm instead of ranging from one line to
   five. The unit is said once, in the column header, not after every numeral. */
table.tbl.companies td { vertical-align: top; }
.companies td .co { font-size: var(--fs-16); font-weight: 600; text-decoration: none; color: var(--text); }
.companies td .co:hover, .companies tr.rowlink:hover td .co { text-decoration: underline; }
.companies tr.rowlink { cursor: pointer; }
.companies td .lead { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; color: var(--muted); font-size: var(--fs-15); max-width: 62ch; white-space: normal; line-height: 1.5; }
.companies td .mark { color: var(--bad); font-size: var(--fs-15); display: flex; align-items: center; gap: var(--sp-6); margin-top: var(--sp-4); }
.companies td .mark i { width: 7px; height: 7px; border-radius: 50%; background: var(--dot-bad); flex: 0 0 auto; }
/* display is restated because the legacy .score rule further up this file
   turns anything with that class into a flex box. A flex table cell stops
   filling its row and paints its border-bottom half way up it, which is the
   stray line that used to sit under every score. */
.companies th.score, .companies td.score { display: table-cell; width: 104px; }
.companies td.score { text-align: right; font-variant-numeric: tabular-nums; }
.companies th.auto, .companies td.auto { width: 132px; }
.companies td.auto { font-size: var(--fs-15); color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.companies td.auto b { font-weight: 600; color: var(--text); }
.companies td.auto .of { color: var(--faint); }
/* A column that says the same thing on every row is not carrying information
   at this scale: it collapses to one check, and the tooltip holds the detail
   until the numbers actually differ. */
.companies td.auto .tick { display: inline-flex; color: var(--faint); }

/* One card header for every card on the Data tab: a label, a caption under it,
   and the card's own 16px padding. The three cards used to carry three
   different header shapes. */
.chead { padding: 0 0 var(--sp-12); }
.chead .lbl { display: block; font-size: var(--fs-16); font-weight: 600; letter-spacing: -.005em; }
.chead .cap { display: block; font-size: var(--fs-15); color: var(--muted); margin-top: var(--sp-2); max-width: 76ch; }

/* The drop zone takes the card's width and its caption sits under it, so the
   zone and the note about the last upload stop competing side by side. */
.upcard .drop { padding: var(--sp-16); }
.upcard .drop + .help { margin-top: var(--sp-8); }

/* A note that would wreck a table row goes behind a one-line disclosure in the
   cell instead, so the row keeps the height of every other row. */
.rowdet { margin-top: var(--sp-2); }
.rowdet > summary { font-size: var(--fs-13); color: var(--faint); cursor: pointer; }
.rowdet > summary:hover { color: var(--text); }
.rowdet .d { display: block; font-size: var(--fs-15); color: var(--muted); margin-top: var(--sp-6); max-width: 56ch; white-space: normal; line-height: 1.5; }

/* A Runs ledger row's own scrape audit (worker/src/admin/server.ts's
   GET /jobs/:id/audit): the summary is the row's own title, not a small
   "Details" aside, so it reads at the same size as the rest of the table;
   the audit's pages and observations tables get room to breathe below it. */
.rowdet.audit > summary { font-size: var(--fs-15); color: var(--text); }
.rowdet.audit > summary:hover { color: var(--accent); }
.run-audit { margin-top: var(--sp-12); }

/* Source cards: name, state, when it was last used. */
.card .cardhead .srcname { display: flex; flex-direction: column; gap: var(--sp-2); }
.card .cardhead .srcname .ago { font-size: var(--fs-15); color: var(--faint); font-weight: 400; }
.pill.on-pill { font-weight: 500; }

/* The scan card (docs/scan-progress.md, docs/scan-ux.md). While a scan runs
   this is the whole page: a header that names the company and says where the
   scan is, a bar that moves continuously, a live feed of what is happening,
   and the ten steps as a backbone beside it. */
.card.scan { padding: var(--sp-20) var(--sp-24) var(--sp-20); }
.card.scan .scanhead { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-16); }
.card.scan .scanhead h2 { font-size: var(--fs-17); font-weight: 500; color: var(--muted); letter-spacing: -.01em; }
.card.scan .scanhead h2 .who { font-weight: 600; color: var(--text); }
.card.scan .scanmeta { font-size: var(--fs-15); color: var(--faint); font-variant-numeric: tabular-nums; }
.card.scan .scanwhy { font-size: var(--fs-16); color: var(--text); margin: 0 0 var(--sp-16); max-width: 62ch; }

.card.scan .bar { height: 6px; background: var(--accent-tint); border-radius: var(--radius-pill); overflow: hidden; margin: 0 0 var(--sp-16); }
/* linear, not eased: an eased bar looks like it is stalling at the end of
   every poll. The duration matches the tick so the fill is always catching a
   target it is about to be given again. */
.card.scan .bar i { display: block; height: 100%; background: var(--text); border-radius: var(--radius-pill); transition: width .16s linear; }
.card.scan.failed .bar i { background: var(--bad); }

.scanbody { display: grid; grid-template-columns: minmax(0, 1fr) 268px; gap: var(--sp-32); align-items: start; }

/* The feed: newest at the bottom, the current line held apart from the rest.
   The mask gradient's #000 is alpha only (mask-image reads luminance/alpha,
   never paints a color) so it stays literal in both themes; a documented
   exception. */
.scanfeed { list-style: none; margin: 0; padding: 0 var(--sp-4) 0 0; height: 236px; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; mask-image: linear-gradient(to bottom, transparent 0, #000 22px); -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22px); }
.scanfeed li { display: grid; grid-template-columns: 38px minmax(0, 1fr); gap: var(--sp-12); padding: var(--sp-4) 0; font-size: var(--fs-15); line-height: 1.45; color: var(--faint); }
.scanfeed li .t { font-family: var(--mono); font-size: var(--fs-13); color: var(--faint); opacity: .6; text-align: right; padding-top: var(--sp-2); font-variant-numeric: tabular-nums; }
.scanfeed li .x { min-width: 0; overflow-wrap: anywhere; }
.scanfeed li code { font-family: var(--mono); font-size: var(--fs-15); background: var(--accent-tint); border-radius: var(--radius-sm); padding: 1px var(--sp-6); color: var(--text); }
.scanfeed li:nth-last-child(2) { color: var(--muted); }
.scanfeed li.now { color: var(--text); font-weight: 500; }
.scanfeed li.now .t { opacity: 1; }
.scanfeed li.now .x::after { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--text); margin-left: var(--sp-8); vertical-align: baseline; animation: scanpulse 1.2s ease-in-out infinite; }
.scanfeed li:last-child { padding-bottom: var(--sp-4); }

/* The backbone: where the scan is in the ten steps, at a glance. */
.scansteps { list-style: none; margin: 0; padding: 0 0 0 var(--sp-20); border-left: 1px solid var(--hairline); display: grid; gap: 1px; }
.scansteps li { display: grid; grid-template-columns: 12px minmax(0, 1fr); gap: var(--sp-12); align-items: baseline; padding: var(--sp-4) 0; font-size: var(--fs-15); color: var(--faint); }
.scansteps li .d { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--rule); background: transparent; position: relative; top: -1px; }
.scansteps li.done .d, .scansteps li.skipped .d { background: var(--dot-ok); border-color: var(--dot-ok); }
.scansteps li.skipped .d { background: var(--faint); border-color: var(--faint); }
.scansteps li.failed .d { background: var(--dot-bad); border-color: var(--dot-bad); }
.scansteps li.running .d { border-color: var(--text); background: var(--text); animation: scanpulse 1.2s ease-in-out infinite; }
.scansteps li.done .l { color: var(--muted); }
.scansteps li.now .l, .scansteps li.running .l { color: var(--text); font-weight: 600; }
.scansteps li .n { display: block; grid-column: 2; font-size: var(--fs-13); color: var(--faint); opacity: .8; margin-top: -1px; }
.scansteps li .n:empty { display: none; }
.scansteps li.now .n { opacity: 1; }

.card.scan.failed { border-color: var(--bad-border); }
.card.scan .btnrow { margin: var(--sp-16) 0 0; }
.card.scan .help { margin: var(--sp-16) 0 0; }

@keyframes scanpulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ink) 25%, transparent); } 50% { box-shadow: 0 0 0 var(--sp-4) transparent; } }
@media (prefers-reduced-motion: reduce) {
  .scansteps li.running .d, .scanfeed li.now .x::after { animation: none; }
  .card.scan .bar i { transition: none; }
}
@media (max-width: 900px) { .scanbody { grid-template-columns: 1fr; gap: var(--sp-20); } .scansteps { padding-left: 0; border-left: 0; } }

/* The read arriving after a scan: the one thing, then the tiles one at a
   time, then the rest (docs/scan-ux.md, principle 5). Motion is the only
   thing staged here — with reduced motion the whole page is simply there. */
@media (prefers-reduced-motion: no-preference) {
  .reveal-on .rv { opacity: 0; animation: revealin .34s cubic-bezier(.2, .7, .3, 1) both; }
}
@keyframes revealin { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* View as (docs/client-surface.md section 5, web/admin/viewas.js): the
   persistent banner and the role-preview panel. The preview itself is
   styled with "vp-" classes that mirror web/app.html's own Home layout
   closely enough to read as the same page, without pulling that page's
   inline stylesheet into admin.html — see viewas.js's header for why it
   is a parallel render rather than a shared one. */
.viewas-banner { display: none; align-items: center; justify-content: space-between; gap: var(--sp-16); position: fixed; top: 0; left: 0; right: 0; z-index: 60; padding: var(--sp-8) var(--sp-20); background: var(--warn-bg); border-bottom: 1px solid var(--warn); color: var(--text); font-size: var(--fs-15); }
.viewas-banner.on { display: flex; }
.viewas-banner span { font-weight: 500; }
body.viewas-active { padding-top: var(--sp-40); }

.viewas-role-row { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin: var(--sp-4) 0 var(--sp-20); }
.people-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-8); margin-top: var(--sp-12); }
.people-form input[type="text"] { width: auto; flex: 1 1 220px; }
.people-form select { width: auto; flex: 0 0 auto; }
.vp-intro { color: var(--muted); font-size: var(--fs-15); line-height: 1.6; max-width: 640px; margin-bottom: var(--sp-4); }
.invite-card { margin-top: var(--sp-16); max-width: 560px; }
table.tbl td.nowrap { white-space: nowrap; }
.invite-card h3 { font-size: var(--fs-15); font-weight: 600; margin-bottom: var(--sp-8); }
.invite-card textarea { margin-bottom: var(--sp-12); }
#tenant-note .invite-card { margin: 0 0 var(--sp-16); }
#ready-note .muted { margin-bottom: var(--sp-8); }
.invite-check, .people-add-form .invite-check { display: flex; flex-direction: row; align-items: center; gap: var(--sp-8); font-size: var(--fs-15); color: var(--muted); }
.invite-check input { width: auto; margin: 0; }
.head .sub .addr-btn { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; font-family: var(--mono); color: var(--muted); }
.head .sub .addr-btn:hover { color: var(--text); }
.head .sub .sep { margin: 0 var(--sp-8); color: var(--muted); }
.head .sub #tenant-address-part { white-space: nowrap; }
.addr-row { display: flex; align-items: center; gap: var(--sp-4); }
.addr-row input { flex: 1; min-width: 0; }
.addr-prefix { color: var(--muted); font-family: var(--mono); }
.invite-warn { color: var(--warn); font-size: var(--fs-15); line-height: 1.5; margin-bottom: var(--sp-12); }
.viewas-frame { border: 1px solid var(--rule); border-radius: var(--radius-ctl); padding: var(--sp-32); background: var(--card); max-width: 720px; }

.vp-wrap h1 { font-family: var(--sans); font-weight: 600; font-size: var(--fs-24); letter-spacing: -.02em; margin-bottom: var(--sp-4); }
.vp-wrap .vp-who { color: var(--muted); font-size: var(--fs-13); margin-bottom: var(--sp-24); }
.vp-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; margin-bottom: var(--sp-16); }
.vp-kpis .stat { background: var(--card); padding: var(--sp-12) var(--sp-16); }
.vp-kpis .stat .n { font-size: var(--fs-24); font-weight: 600; letter-spacing: -.01em; line-height: 1.1; }
.vp-kpis .stat .l { font-size: var(--fs-13); color: var(--muted); margin-top: var(--sp-4); }
.vp-sec { background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); padding: var(--pad-card); margin-bottom: var(--sp-12); }
.vp-sec h2 { font-size: var(--fs-13); font-weight: 600; letter-spacing: .02em; color: var(--muted); margin-bottom: var(--sp-12); }
.vp-sec .vp-note-body { font-size: var(--fs-15); line-height: 1.6; white-space: pre-wrap; }
.vp-sec .vp-src { color: var(--faint); font-size: var(--fs-13); margin-top: var(--sp-8); }
.vp-row { font-size: var(--fs-15); padding: var(--sp-4) 0; display: flex; justify-content: space-between; gap: var(--sp-16); max-width: 420px; }
.vp-row .k { color: var(--muted); }
.vp-row .v { font-weight: 500; }
.vp-rls { color: var(--faint); font-size: var(--fs-13); margin-top: var(--sp-20); border-top: 1px solid var(--hairline); padding-top: var(--sp-12); }

.vp-status .line { display: grid; grid-template-columns: 14px 100px minmax(0, 1fr); gap: var(--sp-12); align-items: baseline; padding: var(--sp-8) 0; font-size: var(--fs-15); }
.vp-status .line .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); position: relative; top: -1px; }
.vp-status .line .dot.good { background: var(--good); }
.vp-status .line .who { font-weight: 500; }
.vp-status .line .what { color: var(--muted); }
.vp-status .line .what.good { color: var(--text); }

/* ---- Connections (U5, 2026-09-27): a compact list, then one detail page
   per row. Each row is its own line, not a card, so six rows and two links
   fit one 1280 screen with room to spare. ---- */
.conn-list td { padding: var(--sp-16) var(--sp-16); }
.conn-list tr.rowlink { cursor: pointer; }
.conn-name { font-size: var(--fs-16); font-weight: 600; text-decoration: none; color: var(--text); display: block; }
.conn-name:hover { text-decoration: underline; }
.conn-line { display: block; color: var(--muted); font-size: var(--fs-15); margin-top: var(--sp-2); }
.conn-links { display: flex; gap: var(--sp-20); margin-top: var(--sp-4); }
.back-link { display: inline-block; color: var(--muted); font-size: var(--fs-15); text-decoration: none; margin-bottom: var(--sp-16); }
.back-link:hover { color: var(--text); }
.person-role { width: auto; }
.person-co { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-12) var(--sp-16); padding: var(--sp-8) 0; border-bottom: 1px solid var(--hairline); }
.person-co:last-of-type { border-bottom: 0; }
.person-co-name { flex: 1 1 160px; font-weight: 600; }
.person-confirm { margin-top: var(--sp-12); }
.person-history { list-style: none; margin: 0; padding: 0; }
.person-history li { display: flex; justify-content: space-between; gap: var(--sp-16); flex-wrap: wrap; padding: var(--sp-8) 0; border-bottom: 1px solid var(--hairline); font-size: var(--fs-15); }
.person-history li:last-child { border-bottom: 0; }
.conn-head { display: flex; align-items: center; gap: var(--sp-12); margin-bottom: var(--sp-6); }
.conn-head h1 { font-size: var(--fs-24); font-weight: 600; letter-spacing: -.02em; margin: 0; }
.conn-lead { color: var(--muted); font-size: var(--fs-15); margin: 0 0 var(--sp-20); }

/* ---- The admin rebuild (2026-09-27, ADMIN.md) -------------------------- */
/* Side menu by job. The Build group sits at the bottom, quieter, because
   it describes the product rather than the business. */
.rail .rail-group { display: flex; flex-direction: column; gap: 1px; margin-top: var(--sp-16); }
.rail .brand + .rail-group { margin-top: var(--sp-24); }
.rail .rail-group.quiet .rail-link { color: var(--muted); font-size: var(--fs-15); }
.rail .rail-group.quiet .section { padding-top: 0; }
/* Companies: the add form is the screen's one action. */
#add-client { margin: 0; }
#add-client input { height: var(--ctl-h); font-size: var(--fs-15); padding: 0 var(--sp-12); border: 1px solid var(--rule); border-radius: var(--radius-ctl); background: var(--card); color: var(--text); width: 200px; }
.empty-line { color: var(--muted); font-size: var(--fs-15); margin: 0; }
#people-none { padding: var(--sp-20) var(--sp-16); }
/* View as client: a bar of controls over the framed client app. */
.va-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-12); margin-bottom: var(--sp-16); }
.va-field { display: flex; flex-direction: column; gap: var(--sp-4); font-size: var(--fs-13); color: var(--muted); }
.va-field select { height: var(--ctl-h); font-size: var(--fs-15); padding: 0 var(--sp-8); border: 1px solid var(--rule); border-radius: var(--radius-ctl); background: var(--card); color: var(--text); min-width: 200px; }
.va-width { display: inline-flex; gap: var(--sp-4); }
.va-width .btn.on { background: var(--accent-tint); color: var(--text); border-color: var(--accent); }
.va-exit { margin-left: auto; }
.va-frame { border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; background: var(--card); margin: 0 auto; }
.va-frame iframe { display: block; width: 100%; height: 78vh; border: 0; }
.va-frame.phone { width: 390px; max-width: 100%; }
@media (max-width: 700px) {
  /* UM4: the menu is one row that scrolls sideways, brand first, so it stays
     under about 100px tall. The Inbox badge stays in its link. */
  .rail { max-height: none; padding: var(--sp-8) var(--sp-12); display: flex; flex-direction: row; align-items: center; gap: var(--sp-8); overflow-x: auto; overflow-y: hidden; }
  .rail .brand { flex: 0 0 auto; padding-right: var(--sp-8); min-height: var(--tap); display: flex; align-items: center; }
  .rail .brand small, .rail .env-switch { display: none; }
  .rail .rail-group, .rail .brand + .rail-group { flex: 0 0 auto; flex-direction: row; flex-wrap: nowrap; gap: var(--sp-4); margin-top: 0; }
  .rail .spacer, .rail .rail-group .section { display: none; }
  .rail .rail-link { min-height: var(--tap); white-space: nowrap; flex: 0 0 auto; }
  .rail .rail-signout { flex: 0 0 auto; }
  #add-client { width: 100%; display: flex; gap: var(--sp-8); }
  #add-client input { flex: 1; width: auto; min-width: 0; }
  .va-field, .va-field select { width: 100%; min-width: 0; }
  .va-exit { margin-left: 0; }
}

/* Hosted admin (HA3): the sign-in gate, the environment label, and the muted
   line that stands in for a laptop-only action. */
.laptop-note { color: var(--muted); font-size: var(--fs-15); }
.rail .env-label { display: inline-block; margin: var(--sp-4) var(--sp-12) 0; padding: 0 var(--sp-8); border: 1px solid var(--hairline); border-radius: var(--radius-pill); font-size: var(--fs-13); color: var(--muted); background: var(--card); }
.rail .env-label.env-staging { color: var(--warn); background: var(--warn-bg); border-color: var(--warn-border); }
.rail .env-label.env-live { color: var(--good); background: var(--good-bg); border-color: var(--good); }
.rail .env-label.env-laptop-staging { color: var(--accent); background: var(--accent-tint); border-color: var(--accent); }
.rail .env-label.env-laptop-live { color: var(--bad); background: var(--bad-bg); border-color: var(--bad-border); font-weight: 600; }
.rail .env-switch { display: inline-block; margin: var(--sp-4) var(--sp-12) 0; font-size: var(--fs-13); color: var(--muted); text-decoration: underline; }
.rail .env-switch:hover { color: var(--text); }
.rail .rail-signout { border: 0; background: none; cursor: pointer; width: 100%; text-align: left; color: var(--muted); }
.rail .rail-signout:hover { background: var(--accent-tint); color: var(--text); }
.gate { position: fixed; inset: 0; z-index: 50; background: var(--card); overflow-y: auto; }
.gate .gate-card { width: 100%; }
.gate label { display: block; font-size: var(--fs-15); color: var(--muted); margin-bottom: var(--sp-4); }
.gate .btn.wide { width: 100%; justify-content: center; }
.gate .gate-or { text-align: center; color: var(--faint); font-size: var(--fs-15); margin: var(--sp-12) 0; }
.gate .gate-lead, .gate .gate-note { color: var(--muted); font-size: var(--fs-15); margin-bottom: var(--sp-12); }
.gate .gate-msg { color: var(--bad); font-size: var(--fs-15); margin-top: var(--sp-12); }
.gate .gate-msg.ok { color: var(--muted); }
.gate .gate-qr { display: block; margin: var(--sp-8) auto var(--sp-12); border: 1px solid var(--hairline); border-radius: var(--radius-ctl); background: white; } /* a QR code needs a white field in any theme */
.gate .gate-key { color: var(--muted); font-size: var(--fs-15); margin-bottom: var(--sp-12); overflow-wrap: anywhere; }
.gate .gate-key code { font-family: var(--mono); color: var(--text); }

/* UM2: People list filters and the person header status line. */
.people-filters { display: flex; flex-wrap: wrap; gap: var(--sp-12) var(--sp-16); margin-bottom: var(--sp-12); }
.people-filters label { display: flex; align-items: center; gap: var(--sp-8); font-size: var(--fs-15); color: var(--muted); }
.people-filters select { width: auto; }
.person-status { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-4); }

/* UM3: Add person on People. */
.people-add-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-12) var(--sp-16); }
.people-add-form label { margin-bottom: 0; display: flex; flex-direction: column; gap: var(--sp-4); font-size: var(--fs-15); color: var(--muted); }
.people-add-form input[type="text"] { width: 260px; max-width: 100%; }
.people-add-form select { width: auto; }
#people-add { margin-bottom: var(--sp-12); }
#people-add .msg { margin-top: var(--sp-12); }
#people-add .msg { font-size: var(--fs-15); color: var(--muted); }
#people-add .msg.error { color: var(--bad); }

/* ---- UM4: add to company, padding and readability ------------------------ */
/* Plain-text stand-in for a missing email: muted, not underlined. */
a.no-email { color: var(--muted); text-decoration: none; }
a.no-email:hover { color: var(--text); }
.empty-cell { color: var(--muted); font-size: var(--fs-15); }
/* Pill dot and text sit on the row's centre line. */
.tbl td .pill { display: flex; align-items: center; line-height: var(--lh-normal); }
.pill .dot { position: static; }
.tbl td .op-pill { display: inline-flex; min-width: 0; margin-left: var(--sp-8); }
.tbl.stack td.c-person .op-pill { font-weight: 400; }
.person-status .op-pill { margin-left: var(--sp-8); }
.head #person-operator-note { margin: var(--sp-4) 0 0; font-size: var(--fs-15); }
.spend-note { margin: var(--sp-16) 0 0; padding: 0 var(--sp-4); }
#panel-inbox .attention .what, #panel-inbox .attention .what small { font-size: var(--fs-body); }
/* Add person: controls share one height and one baseline. */
.people-add-form { align-items: flex-end; }
.people-add-form input[type="text"], .people-add-form select, .people-add-form .btn { height: var(--ctl-h); box-sizing: border-box; }
.people-add-form input[type="text"], .people-add-form select { padding-top: 0; padding-bottom: 0; }
/* Company People tab: the add row does not stretch. */
.people-form input[type="text"] { flex: 0 1 320px; max-width: 320px; }
.people-form input[type="text"], .people-form select, .people-form .btn { height: var(--ctl-h); box-sizing: border-box; }
.people-form .btn { padding-top: 0; padding-bottom: 0; }
table.tbl td.c-inv { min-width: 110px; }
/* Person page: Add to company row. */
.person-add { margin-top: var(--sp-12); }
.person-add-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-8) var(--sp-12); }
.person-add-row select { width: auto; max-width: 100%; height: var(--ctl-h); padding-top: 0; padding-bottom: 0; box-sizing: border-box; }
.person-add .msg { margin: var(--sp-8) 0 0; font-size: var(--fs-15); color: var(--muted); }
.person-add .msg.error { color: var(--bad); }
#pac-none { margin-top: var(--sp-16); }

@media (max-width: 900px) {
  /* Tables that carry class "stack" become one card per row, on phones and
     on tablets, where the sidebar leaves too little width for five columns. */
  table.tbl.stack, table.tbl.stack tbody { display: block; }
  table.tbl.stack thead { display: none; }
  table.tbl.stack tr { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-12); padding: var(--sp-12) 0; border-bottom: 1px solid var(--hairline); }
  table.tbl.stack tr:last-child { border-bottom: 0; }
  table.tbl.stack td { display: block; padding: 0; border: 0; min-width: 0; }
  table.tbl.stack tr:hover td { background: none; }
  table.tbl .pill, .tbl.stack .pill { min-width: 0; }
  table.tbl.stack td.c-person { flex: 1 0 100%; font-weight: 600; overflow-wrap: anywhere; }
  table.tbl.stack td.c-person a.no-email { font-weight: 400; }
  table.tbl.stack td.c-role, table.tbl.stack td.c-inv { color: var(--muted); }
  table.tbl.stack td.c-status { margin-left: 0; }
  table.tbl.stack td.c-seen { color: var(--muted); }
  table.tbl.stack td.nowrap { margin-left: auto; }
  /* People page: company and role share line 2, status and last seen line 3. */
  table.tbl.stack td.c-co { flex: 0 1 auto; }
  /* Companies table: name, read, then the two figures with their labels. */
  table.tbl.companies.stack td { width: 100%; }
  table.tbl.companies.stack td.num { width: auto; text-align: left; }
  table.tbl.companies.stack td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
  .companies td .lead { max-width: none; }
  /* Person page Companies rows: name alone on line 1, then role, Added, Remove. */
  .person-co-name { flex: 1 0 100%; }
  .person-co { gap: var(--sp-8) var(--sp-12); align-items: center; }
  .person-add-row select, .person-add-row .btn { flex: 1 1 100%; }
  .people-form input[type="text"] { flex: 1 1 100%; max-width: none; }
  .people-add-form label, .people-add-form input[type="text"], .people-add-form select { width: 100%; }
}

/* UM4 part D and E: role hint line, and People table column widths. */
.role-hint { margin: var(--sp-8) 0 0; color: var(--muted); font-size: var(--fs-15); }
.people-form .role-hint { flex: 1 0 100%; margin: 0; }
table.people-stack .pill { min-width: 0; }
@media (min-width: 901px) {
  table.people-stack th:nth-child(1), table.people-stack td:nth-child(1) { width: 38%; }
  table.people-stack td.c-person { white-space: nowrap; }
  table.people-stack th:last-child, table.people-stack td:last-child { width: 1%; white-space: nowrap; }
}

/* ---- UM5: People directory, one row per person ---------------------------- */
.people-filters { align-items: center; }
.people-search { width: 260px; max-width: 100%; background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-ctl); padding: var(--sp-8) var(--sp-12); font: inherit; font-size: var(--fs-15); color: var(--text); box-sizing: border-box; }
.people-search:focus { border-color: var(--faint); }
.co-chips { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-8); }
.co-chip { display: inline-block; padding: var(--sp-2) var(--sp-8); border: 1px solid var(--hairline); border-radius: var(--radius-pill); font-size: var(--fs-13); color: var(--text); text-decoration: none; white-space: nowrap; }
.co-chip:hover { border-color: var(--faint); }
tr.row-open { cursor: pointer; }
tr.row-open:hover td { background: var(--bg-page); }
@media (max-width: 900px) {
  .people-search { width: 100%; }
  table.tbl.stack td.c-co { flex: 1 0 100%; }
}

/* Fix plan card (LEE-454) */
.fixplan .fp-meta { font-size: var(--fs-13); margin: calc(var(--sp-6) * -1) 0 var(--sp-12); }
.fixplan .fp-fix { border-top: 1px solid var(--hairline); padding: var(--sp-12) 0; }
.fixplan .fp-fix h3 { font-size: var(--fs-15); font-weight: 600; margin-bottom: var(--sp-4); }
.fixplan .fp-checks { font-size: var(--fs-13); margin-bottom: var(--sp-8); }
.fixplan .fp-copy { margin: var(--sp-8) 0; }
.fixplan .fp-copy ul, .fixplan .fp-rej ul, .fixplan .fp-more ol { margin: var(--sp-4) 0 0 var(--sp-16); padding: 0; }
.fixplan .fp-page { font-size: var(--fs-13); color: var(--muted); }
.fixplan .fp-more { margin-top: var(--sp-8); }
.fixplan .fp-more summary { cursor: pointer; color: var(--muted); }
.fixplan .fp-rej { border-top: 1px solid var(--hairline); padding-top: var(--sp-12); font-size: var(--fs-13); }
.fixplan .confirm-inline input[type="text"] { width: 280px; max-width: 100%; }

/* LEE-456: sign-in split. Shared by the client /app sign-in and every operator
   gate screen: form on the left, a static Fixes preview on the right (hidden
   under 900px). The preview is decoration only: aria-hidden, no links. */
.signin-split { display: grid; grid-template-columns: 1fr; min-height: 100vh; background: var(--card); }
.signin-left { display: flex; flex-direction: column; min-height: 100vh; padding: var(--sp-24) var(--sp-16) var(--sp-16); box-sizing: border-box; }
.signin-icon { width: 28px; height: 28px; display: block; }
/* wordmark goes here once named */
.signin-block { width: 100%; max-width: 400px; margin: auto; padding: var(--sp-32) 0; }
.signin-block h1 { font-family: var(--sans); font-weight: 600; font-size: var(--fs-24); letter-spacing: -.02em; line-height: 1.2; margin: 0 0 var(--sp-8); }
.signin-block .lead, .signin-block .gate-lead, .signin-block .gate-note { color: var(--muted); font-size: var(--fs-body); line-height: 1.6; margin: 0 0 var(--sp-24); }
/* LEE-456: operator gate controls match the client sign-in (web/app.html). */
.signin-block .btn-google { gap: var(--sp-12); }
.signin-block .btn-google svg { flex: none; }
.signin-block .or-divider { display: flex; align-items: center; gap: var(--sp-12); margin: var(--sp-16) 0; color: var(--faint); font-size: var(--fs-small); }
.signin-block .or-divider::before, .signin-block .or-divider::after { content: ""; flex: 1; border-top: 1px solid var(--hairline); }
.gate input[type="text"] { box-sizing: border-box; padding: 0 var(--sp-12); font-size: var(--fs-body); }
.gate input[type="text"]:focus, .gate input[type="text"]:focus-visible { border-color: var(--rule); outline: 2px solid var(--accent); outline-offset: 1px; }
.gate .btnrow { margin-top: var(--sp-16); }
.gate .gate-signout { display: block; background: none; border: 0; padding: 0; margin: var(--sp-16) 0 0; font: inherit; font-size: var(--fs-body); color: var(--muted); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.gate .gate-signout:hover { color: var(--text); }
@media (max-width: 900px) { .signin-block .btn-google, .gate .gate-signout { min-height: var(--tap); } }
.signin-legal { margin: 0; color: var(--faint); font-size: var(--fs-small); }
.signin-legal a { color: var(--faint); }
.signin-preview { display: none; }
@media (min-width: 900px) {
  .signin-split { grid-template-columns: 1fr 1fr; }
  .signin-left { padding: var(--sp-32) var(--sp-32) var(--sp-24); }
  .signin-block h1 { font-size: var(--fs-30); }
  .signin-preview { display: block; position: relative; overflow: hidden; margin: var(--sp-16); border-radius: var(--radius); background: var(--accent-tint); pointer-events: none; user-select: none; }
}
.signin-fixes { position: absolute; left: 14%; top: 38%; width: 560px; transform: rotate(-4deg); transform-origin: left bottom; background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow-md); }
.signin-fixes-head { padding: var(--sp-16) var(--sp-20); border-bottom: 1px solid var(--hairline); font-size: var(--fs-body); font-weight: 600; color: var(--text); }
.signin-fix { display: flex; align-items: center; gap: var(--sp-12); padding: var(--sp-16) var(--sp-20); border-bottom: 1px solid var(--hairline); }
.signin-fix:last-child { border-bottom: 0; }
.signin-fix-text { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.signin-fix-title { font-size: var(--fs-body); font-weight: 500; color: var(--text); }
.signin-fix-cat { font-size: var(--fs-small); color: var(--muted); }
.signin-chip { flex: none; min-width: 72px; box-sizing: border-box; text-align: center; font-size: var(--fs-13); font-weight: 600; line-height: 1.5; padding: var(--sp-2) var(--sp-8); border-radius: var(--radius-pill); }
.signin-chip.high { background: var(--chip-high-bg); color: var(--chip-high-fg); }
.signin-chip.medium { background: var(--chip-med-bg); color: var(--chip-med-fg); }

/* LEE-381: Activity card on the person page (grouped by local day). */
.activity-day-head { margin: var(--sp-12) 0 var(--sp-4); font-size: var(--fs-13); font-weight: 600; color: var(--muted); }
.activity-day[hidden] { display: none; }
.activity-time { display: inline-block; min-width: 72px; font-size: var(--fs-13); }

/* ---- LEE-480: shared data table (.dt), toolbar, +N cell, dialog, avatar ----
   Slice B (Companies) reuses all of these. Every row one height, one line per
   cell, no pills, actions as plain text links at the far right. */
.avatar { display: inline-flex; align-items: center; justify-content: center; width: var(--sp-24); height: var(--sp-24); flex: 0 0 auto; border-radius: 50%; background: var(--accent-tint); color: var(--muted); font-size: var(--fs-13); font-weight: 600; box-sizing: content-box; padding: var(--sp-2); }
.dt .who { display: inline-flex; align-items: center; gap: var(--sp-12); min-width: 0; max-width: 100%; }
.dt .who a, .dt .who .who-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; color: var(--text); text-decoration: none; }
.dt .who a:hover { text-decoration: underline; }
.dt .who a.no-email { color: var(--muted); }
.dt-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-8) var(--sp-12); margin-bottom: var(--sp-12); }
.dt-toolbar .people-search, .dt-toolbar input[type="search"] { flex: 1 1 240px; max-width: 360px; width: auto; }
.dt-toolbar select { width: auto; flex: 0 0 auto; color: var(--text); }
/* Search and filters are one family: same height, border and radius, and the
   filters lose the browser's own arrow for a drawn muted chevron (DoorDash). */
.dt-toolbar .people-search, .dt-toolbar select { height: calc(var(--ctl-h) + var(--sp-6)); }
.dt-toolbar select {
  appearance: none; -webkit-appearance: none; min-width: 160px; padding-right: calc(var(--sp-12) * 2 + var(--sp-8));
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - var(--sp-16) - var(--sp-4)) 50%, calc(100% - var(--sp-12) - var(--sp-4)) 50%;
  background-size: var(--sp-4) var(--sp-4), var(--sp-4) var(--sp-4); background-repeat: no-repeat;
}
.dt-toolbar .btn.primary { margin-left: auto; }
.dt .dot-status { display: inline-flex; align-items: center; gap: var(--sp-6); }
.dt .dot-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--dot-none); }
.dt .dot-status.good::before { background: var(--dot-ok); }
.dt .dot-status.warn::before { background: var(--dot-warn); }
.dt .dot-status.bad::before { background: var(--dot-bad); }
.link-action { background: none; border: 0; padding: 0 var(--sp-4); font: inherit; font-size: var(--fs-15); color: var(--accent); cursor: pointer; text-decoration: none; }
.link-action:hover { text-decoration: underline; }
.link-action.quiet { color: var(--muted); }
.link-action.quiet:hover { color: var(--text); }
.link-action:disabled { opacity: .5; cursor: default; }
.link-action:focus-visible, .more-btn:focus-visible, .th-sort:focus-visible { outline: 2px solid var(--faint); outline-offset: 2px; border-radius: var(--radius-sm); }
.th-sort { background: none; border: 0; padding: 0; font: inherit; font-weight: inherit; color: inherit; cursor: pointer; }
.th-sort:hover { color: var(--text); }
.row-actions { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--sp-12); }
.row-actions .q { color: var(--muted); font-size: var(--fs-15); }
/* LEE-496: a longer question sits on its own line above its two buttons. */
.row-actions.confirm.two-line { flex-wrap: wrap; row-gap: var(--sp-4); }
.row-actions.confirm.two-line .q { flex: 1 0 100%; text-align: right; }
.more { position: relative; display: inline-flex; align-items: center; gap: var(--sp-6); max-width: 100%; min-width: 0; }
.more-first { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.more-first a { color: var(--text); text-decoration: none; }
.more-first a:hover { text-decoration: underline; }
.more-btn { background: none; border: 0; padding: 0 var(--sp-4); font: inherit; font-size: var(--fs-13); color: var(--muted); cursor: pointer; flex: 0 0 auto; }
.more-btn:hover { color: var(--text); }
.more-pop { display: none; position: fixed; z-index: 30; min-width: 200px; max-width: 280px; padding: var(--sp-8) var(--sp-12); background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow-md); font-size: var(--fs-15); }
.more.open .more-pop { display: block; }
/* The popover sits 6px below the +N; this strip bridges the gap so hover holds. */
.more-pop::before { content: ""; position: absolute; left: 0; right: 0; top: calc(var(--sp-6) * -1); height: var(--sp-6); }
.more-item { display: flex; justify-content: space-between; gap: var(--sp-12); padding: var(--sp-4) 0; white-space: nowrap; }
.more-item a { color: var(--text); text-decoration: none; }
.more-item a:hover { text-decoration: underline; }
dialog.dlg { width: min(520px, calc(100vw - var(--sp-32))); max-height: calc(100vh - var(--sp-32)); overflow: auto; padding: var(--pad-card); background: var(--card); color: var(--text); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow-md); }
dialog.dlg::backdrop { background: rgba(17, 24, 39, .4); }
.dlg-title { font-size: var(--fs-17); font-weight: 600; margin: 0 0 var(--sp-16); overflow-wrap: anywhere; }
.dlg-foot { display: flex; justify-content: flex-end; gap: var(--sp-8); margin-top: var(--sp-16); }
.dlg-foot[hidden] { display: none; }
.dlg .people-add-form { flex-direction: column; align-items: stretch; }
.dlg .people-add-form input[type="text"], .dlg .people-add-form select { width: 100%; }
.dlg .people-add-form .btn { align-self: flex-start; }
.dlg .people-add-form .dlg-foot { margin-top: 0; }
.dlg .people-add-form .pa-notes .msg:empty { margin-top: 0; }
.edit-row { display: flex; align-items: center; gap: var(--sp-12); padding: var(--sp-8) 0; border-bottom: 1px solid var(--hairline); }
.edit-row:last-of-type { border-bottom: 0; }
.edit-co { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edit-row select { width: auto; flex: 0 0 auto; }
.edit-role-text { color: var(--muted); }
.edit-confirm[hidden] { display: none; }
/* LEE-493: the Remove question fills the dialog on its own. */
.edit-q { font-size: var(--fs-15); color: var(--text); margin: 0 0 var(--sp-8); max-width: 52ch; }
.edit-warn { color: var(--bad); }
.dlg-foot .dlg-lead { margin-right: auto; }
/* Add person: fields match the page's search and filters; the sent state
   replaces the form. */
.dlg .people-add-form input[type="text"], .dlg .people-add-form select { height: calc(var(--ctl-h) + var(--sp-6)); }
.dlg .people-add-form select, .edit-row select {
  appearance: none; -webkit-appearance: none; padding-right: calc(var(--sp-12) * 2 + var(--sp-8));
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - var(--sp-16) - var(--sp-4)) 50%, calc(100% - var(--sp-12) - var(--sp-4)) 50%;
  background-size: var(--sp-4) var(--sp-4), var(--sp-4) var(--sp-4); background-repeat: no-repeat;
}
.pa-done-head { margin: 0; font-size: var(--fs-15); font-weight: 500; }
.pa-done-note { margin: var(--sp-8) 0 0; font-size: var(--fs-15); color: var(--muted); }
.pa-done-note .sep { margin: 0 var(--sp-6); }
.pa-done .dlg-foot .btn:first-child { margin-right: auto; }
.dlg .msg { font-size: var(--fs-15); color: var(--muted); margin-top: var(--sp-8); }
.dlg .msg.error { color: var(--bad); }
.invite-link { display: flex; gap: var(--sp-8); align-items: center; margin-top: var(--sp-8); }
.invite-link input { flex: 1 1 auto; min-width: 0; }
.tbl .pill.inv-pill { min-width: 0; }
@media (min-width: 901px) {
  table.tbl.dt { table-layout: fixed; }
  table.tbl.dt td { height: calc(var(--sp-48) + var(--sp-8)); padding-top: 0; padding-bottom: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  table.tbl.dt .dt-actions { width: 168px; text-align: right; overflow: visible; }
  table.tbl.dt.dt-one-action .dt-actions { width: var(--sp-64); }
  table.tbl.dt .c-role { width: 96px; }
  table.tbl.dt .c-seen { width: 140px; }
  table.tbl.dt .c-inv { width: 112px; }
  table.tbl.dt .c-days { width: 120px; }
  table.tbl.dt .c-co { width: 24%; }
  table.tbl.dt .c-person { width: 32%; }
  /* LEE-485: the Invitations tab adds Status and two more actions. Invited by
     lives in the Sent cell's title: a seventh column truncated every email. */
  table.tbl.dt.dt-inv .c-person { width: auto; }
  table.tbl.dt.dt-inv .c-co { width: 152px; }
  table.tbl.dt.dt-inv .c-role { width: 76px; }
  table.tbl.dt.dt-inv .c-inv { width: 120px; min-width: 0; }
  table.tbl.dt.dt-inv .c-status { width: 140px; }
  table.tbl.dt.dt-inv .dt-actions { width: 240px; }
  /* Round 2: rules run to the card's edges (WorkOS, n8n); text keeps its inset. */
  .card.people-card { padding: var(--sp-4) 0; overflow: hidden; }
  .people-card table.tbl.dt th:first-child, .people-card table.tbl.dt td:first-child { padding-left: var(--pad-card); }
  .people-card table.tbl.dt th:last-child, .people-card table.tbl.dt td:last-child { padding-right: var(--pad-card); }
}
@media (max-width: 900px) {
  .link-action, .more-btn, .th-sort { min-height: var(--tap); }
  .dt-toolbar .people-search, .dt-toolbar input[type="search"] { flex: 1 0 100%; max-width: none; }
  table.tbl.dt.stack td.dt-actions { margin-left: auto; }
  table.tbl.dt.stack td.c-person .who { max-width: 100%; }
  /* Phones: the list spans the screen (no card around it), and every line
     stays one line. People rows are two lines: email and Edit, then
     "Harbor Goods +2 · Owner · Oct 2, 2026" in muted text. Days active lives
     on the person page. */
  .card.people-card { background: none; border: 0; box-shadow: none; padding: 0; }
  table.tbl.dt.stack td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  table.tbl.dt.stack:not(.dt-inv) tr { column-gap: var(--sp-8); }
  table.tbl.dt.stack:not(.dt-inv) td.c-person { flex: 1 0 calc(100% - var(--sp-64)); order: 0; }
  table.tbl.dt.stack:not(.dt-inv) td.dt-actions { order: 1; flex: none; margin-left: 0; }
  /* Basis 0 capped at its own width: the company shrinks (and ellipsizes) on a
     narrow screen instead of pushing the date onto a third line. */
  table.tbl.dt.stack:not(.dt-inv) td.c-co { order: 3; flex: 1 1 0; max-width: max-content; color: var(--muted); }
  table.tbl.dt.stack:not(.dt-inv) td.c-role { order: 4; flex: none; margin-left: 0; color: var(--muted); }
  table.tbl.dt.stack:not(.dt-inv) td.c-role::before { content: "\B7"; margin-right: var(--sp-8); }
  /* Round 2: the date sits at the right edge under Edit, labelled. */
  table.tbl.dt.stack:not(.dt-inv) td.c-seen { order: 5; flex: none; margin-left: auto; padding-left: var(--sp-8); color: var(--muted); }
  table.tbl.dt.stack:not(.dt-inv) td.c-seen.has-date::before { content: "Active "; }
  table.tbl.dt.stack:not(.dt-inv) td.c-days { display: none; }
  table.tbl.dt.stack:not(.dt-inv):not(.companies) tr::after { content: ""; order: 2; flex: 1 0 100%; height: 0; }
  /* No avatars on phones, so both lines start at the same edge. */
  table.tbl.dt.stack .avatar { display: none; }
  /* Invitations: three lines. Email; "Company · Role · Sent Oct 2, 2026";
     status at the left with the actions at the right. tr::after is the line break. */
  table.tbl.dt.stack.dt-inv tr { column-gap: var(--sp-8); }
  table.tbl.dt.stack.dt-inv td.c-person { order: 0; flex: 1 0 100%; }
  table.tbl.dt.stack.dt-inv td.c-co { order: 1; flex: 1 1 0; max-width: max-content; color: var(--muted); }
  table.tbl.dt.stack.dt-inv td.c-role, table.tbl.dt.stack.dt-inv td.c-inv { order: 2; flex: none; margin-left: 0; color: var(--muted); }
  table.tbl.dt.stack.dt-inv td.c-role::before { content: "\B7"; margin-right: var(--sp-8); }
  table.tbl.dt.stack.dt-inv td.c-inv::before { content: "\B7\2002Sent\00A0"; }
  table.tbl.dt.stack.dt-inv tr::after { content: ""; order: 3; flex: 1 0 100%; height: 0; }
  table.tbl.dt.stack.dt-inv td.c-status { order: 4; flex: none; }
  table.tbl.dt.stack.dt-inv td.dt-actions { order: 5; flex: none; margin-left: auto; }
  /* The +2 keeps a full-size tap area (drawn by ::after, outside its box) without
     making its row taller than the rest, so that cell may not clip. */
  table.tbl.dt.stack td.c-co:has(.more-btn) { overflow: visible; }
  table.tbl.dt.stack td.c-co .more-btn { position: relative; min-height: 0; }
  table.tbl.dt.stack td.c-co .more-btn::after { content: ""; position: absolute; inset: calc(var(--sp-12) * -1) calc(var(--sp-8) * -1); }
  .row-actions.confirm { flex-wrap: wrap; justify-content: flex-start; }
  table.tbl.dt.stack.dt-inv td.dt-actions:has(.two-line) { flex: 1 0 100%; margin-left: 0; }
  .row-actions.confirm.two-line .q { text-align: left; }
}

/* ---- LEE-480 B: Companies in the .dt pattern ---- */
table.tbl.dt.companies td { vertical-align: middle; }
.companies td .co-name { display: flex; flex-direction: column; min-width: 0; line-height: var(--lh-normal); }
.companies td .co-name .co { display: block; min-height: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-15); }
.companies td .co-domain { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: var(--fs-13); }
.companies td.c-status .dot-status { display: flex; max-width: 100%; min-width: 0; }
.companies td.c-status .dot-status::before { flex: none; }
.companies td.c-status .ds-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.companies td.c-type { color: var(--muted); }
.companies .row-actions a.link-action { display: inline-flex; align-items: center; }
@media (min-width: 901px) {
  table.tbl.dt.companies .c-name { width: 21%; }
  table.tbl.dt.companies .c-status { width: 19%; }
  table.tbl.dt.companies .c-type { width: 88px; }
  table.tbl.dt.companies .c-ppl { width: 12%; }
  table.tbl.dt.companies .c-chk { width: 96px; text-align: right; font-variant-numeric: tabular-nums; }
  table.tbl.dt.companies .c-auto { width: 128px; text-align: right; }
  /* The two count headers are longer than their numbers (LEE-494 names): they wrap rather than collide. */
  table.tbl.dt.companies th.c-chk, table.tbl.dt.companies th.c-auto { white-space: normal; vertical-align: bottom; }
  table.tbl.dt.companies .dt-actions { width: 132px; }
}
@media (max-width: 900px) {
  table.tbl.dt.companies.stack td { width: auto; }
  table.tbl.dt.companies.stack td.c-name { flex: 1 0 100%; }
  table.tbl.dt.companies.stack td.c-ppl { flex: 1 0 100%; }
  table.tbl.dt.companies.stack td.num { text-align: left; }
  table.tbl.dt.companies.stack td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
  /* Phones: Edit and View as always get their own line, right-aligned, so every card ends the same way. */
  table.tbl.dt.companies.stack td.dt-actions { flex: 1 0 100%; width: 100%; text-align: right; margin-left: 0; }
}

/* LEE-564 rescan agent */
.agent-switch-row { display: flex; align-items: center; gap: var(--sp-12); margin-bottom: var(--sp-8); }
.agent-switch { position: relative; width: 44px; height: 24px; padding: 0; border: 0; border-radius: var(--radius-pill); background: var(--rule); cursor: pointer; flex: none; }
.agent-switch span { position: absolute; top: var(--sp-2); left: var(--sp-2); width: 20px; height: 20px; border-radius: 50%; background: var(--card); transition: transform .15s; }
.agent-switch[aria-checked="true"] { background: var(--good); }
.agent-switch[aria-checked="true"] span { transform: translateX(20px); }
.agent-switch:disabled { opacity: .6; cursor: default; }
.agent-sentence { margin: 0 0 var(--sp-24); max-width: 60ch; }
#agent-switch-err:empty, #agent-form-err:empty { display: none; }
.agent-limits { max-width: 640px; margin-bottom: var(--sp-32); }
.agent-limit { margin-bottom: var(--sp-24); }
.agent-limit h2 { font-size: var(--fs-17); font-weight: 600; margin: 0 0 var(--sp-8); }
.agent-bar { height: var(--sp-8); border-radius: var(--radius-pill); background: var(--hairline); overflow: hidden; }
.agent-bar span { display: block; height: 100%; background: var(--faint); border-radius: var(--radius-pill); }
.agent-bar.warn span { background: var(--warn); }
.agent-bar.bad span { background: var(--bad); }
.agent-limit-foot { display: flex; justify-content: space-between; gap: var(--sp-16); margin-top: var(--sp-8); font-size: var(--fs-15); color: var(--muted); }
.agent-limit-foot b { color: var(--text); font-weight: 600; }
.agent-limits #agent-runs { margin: 0 0 var(--sp-16); }
.agent-form { display: grid; gap: var(--sp-12); max-width: 320px; }
.agent-form .btnrow { display: flex; gap: var(--sp-8); }
.agent-table td.agent-why { max-width: 0; }
@media (min-width: 901px) {
  .agent-table .c-name { width: 22%; }
  .agent-table .c-dec { width: 168px; }
  .agent-table .c-when { width: 136px; }
  .agent-table .c-cost { width: 88px; }
}
.agent-table td.agent-why span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-table tr.agent-row { cursor: pointer; }
.agent-table tr.agent-detail td { background: var(--canvas); padding: var(--sp-12) var(--sp-16); }
.agent-day { padding: var(--sp-8) 0; }
.agent-day-head { display: flex; align-items: center; gap: var(--sp-12); font-size: var(--fs-15); }
.agent-reasons { margin: var(--sp-6) 0 0 var(--sp-20); padding: 0; color: var(--muted); font-size: var(--fs-15); }
.agent-table .co-name { display: flex; flex-direction: column; min-width: 0; }
.agent-table .co-domain { color: var(--muted); font-size: var(--fs-13); overflow: hidden; text-overflow: ellipsis; }
#agent-decisions .cardhead h2 { white-space: nowrap; }
.agent-left { margin: var(--sp-12) 0 0; }
.companies td.c-agent { color: var(--muted); font-size: var(--fs-15); }
.agent-card .agent-note { margin: var(--sp-8) 0 0; }
.agent-card select { max-width: 280px; }
.agent-card #agent-latest { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-6); }
@media (min-width: 901px) {
  table.tbl.dt.companies .c-agent { width: 148px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
@media (max-width: 900px) {
  table.tbl.dt.companies.stack td.c-agent { flex: 1 0 100%; }
  table.tbl.dt.companies.stack td.c-agent:empty { display: none; }
  table.tbl.agent-table.stack td.agent-why { max-width: none; width: 100%; flex: 1 0 100%; }
  table.tbl.agent-table.stack td.agent-why span { white-space: normal; }
  table.tbl.agent-table.stack tr.agent-detail { display: block; }
  table.tbl.agent-table.stack tr.agent-detail td { display: block; }
}

/* LEE-578: the Digest screen. On phones each row stacks (see .stack above):
   issue id and title first, then the labelled extras. */
@media (max-width: 900px) {
  table.tbl.digest td { width: 100%; }
  table.tbl.digest td.num { width: auto; text-align: left; }
  table.tbl.digest td.id { width: auto; }
  table.tbl.digest td[data-label]:not(.id):not([data-label="Title"]):not([data-label="Milestone"])::before { content: attr(data-label) ": "; color: var(--muted); }
  table.tbl.digest td[data-label="Title"], table.tbl.digest td[data-label="Milestone"] { font-weight: 600; }
}
