/* Zillow Floorplan Agent — Dashboard (Phase-5 T4 frontend)
   Layout/IA carried faithfully from the client-signed mockup (mockup WINS on layout/IA
   per SPEC 10-authority). Data is NEVER in CSS; all values arrive from real endpoints. */
:root{
  --canvas:#eaeef2; --panel:#ffffff; --panel-2:#f6f8fa;
  --ink:#15202e; --muted:#5f6c7b; --faint:#8a96a3;
  --line:#e0e6ec; --line-2:#eef2f6;
  --wire:#0e7c86; --wire-bright:#0fa3ad; --wire-tint:#e5f4f4;
  --pass:#167a5b; --pass-tint:#e6f3ee;
  --review:#b7791f; --review-tint:#f9f0dd;
  --fail:#c0392b; --fail-tint:#fbe9e6;
  /* Matched to Post-Processing so the two agent boards in one shell read as one
     product. The system stack stays as the fallback, so a blocked font host degrades
     to exactly what this board looked like before rather than to anything broken. */
  --sans:'Inter',-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --display:'Space Grotesk','Inter',-apple-system,"Segoe UI",sans-serif;
  --mono:ui-monospace,"SF Mono","JetBrains Mono",Menlo,Consolas,monospace;
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{background:var(--canvas);color:var(--ink);font-family:var(--sans);font-size:13px;line-height:1.45;-webkit-font-smoothing:antialiased}
.app{max-width:1180px;margin:0 auto;padding:18px 20px 40px}

header{display:flex;align-items:center;gap:16px;flex-wrap:wrap;padding-bottom:14px;border-bottom:1px solid var(--line)}
.brand{display:flex;flex-direction:column;gap:1px}
.brand .ey{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--wire);font-weight:700}
.brand h1{font-size:17px;font-weight:700;letter-spacing:-.01em}
.brand .mode{font-size:11px;color:var(--muted)}
.brand .mode b{color:var(--review);font-weight:700}
.spacer{flex:1}

/* help affordance */
.help{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;border:1px solid var(--faint);color:var(--faint);font-size:9px;font-style:italic;font-weight:700;font-family:Georgia,serif;cursor:help;position:relative;vertical-align:middle;margin-left:5px;flex:none}
.help:hover,.help:focus{background:var(--wire);border-color:var(--wire);color:#fff;outline:none}
.help::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);background:var(--ink);color:#fff;font-size:11px;font-weight:400;font-style:normal;font-family:var(--sans);line-height:1.45;letter-spacing:0;text-transform:none;padding:8px 10px;border-radius:7px;width:230px;text-align:left;opacity:0;visibility:hidden;transition:.12s;z-index:60;box-shadow:0 8px 24px rgba(0,0,0,.28);pointer-events:none}
.help::before{content:"";position:absolute;bottom:calc(100% + 3px);left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--ink);opacity:0;visibility:hidden;transition:.12s;z-index:60}
.help:hover::after,.help:focus::after,.help:hover::before,.help:focus::before{opacity:1;visibility:visible}
.help.hl::after{left:auto;right:-4px;transform:none}
.help.hl::before{left:auto;right:6px;transform:none}

/* wiring badge + toggle */
.integrity{display:flex;align-items:center;gap:10px}
.badge{display:flex;align-items:center;gap:8px;background:var(--wire-tint);border:1px solid #bfe3e2;border-radius:8px;padding:6px 11px;cursor:pointer;transition:.15s}
.badge:hover{background:#d7eeed}
.badge .dot{width:9px;height:9px;border-radius:50%;background:var(--wire);box-shadow:0 0 0 3px rgba(14,124,134,.18)}
.badge .txt{font-size:11px;font-weight:700;color:#0b5b62}
.badge .txt span{font-family:var(--mono);font-weight:600}
.toggle{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--muted);cursor:pointer;user-select:none}
.toggle input{display:none}
.toggle .sw{width:32px;height:18px;border-radius:9px;background:#c6d0da;position:relative;transition:.15s}
.toggle .sw::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#fff;transition:.15s;box-shadow:0 1px 2px rgba(0,0,0,.2)}
.toggle input:checked + .sw{background:var(--wire)}
.toggle input:checked + .sw::after{left:16px}
/* ⛔ THE BAR MUST NOT OUTGROW THE PAGE (Jason, 2026-08-26: "the signout bar is
   overhanging the page width"). `#whoRole` renders the full 32-character session id,
   which is unbreakable text in a fixed-height flex row -- so it pushed the row past the
   viewport instead of shrinking. `min-width:0` is the part that actually lets a flex
   child shrink below its content; without it `text-overflow` never engages. The Sign
   out button is `flex:none` so the id gives way and the button never does: an operator
   losing the end of an opaque hex string costs nothing, losing the sign-out control
   costs them the session. */
.who{font-size:11px;color:var(--muted);display:flex;align-items:center;gap:8px;
  min-width:0;overflow:hidden}
.who #whoRole{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.who b{flex:none}
.who b{color:var(--ink)}
.who .signout{flex:none;appearance:none;border:1px solid var(--line);background:var(--panel-2);font-family:inherit;font-size:10.5px;font-weight:600;color:var(--muted);border-radius:6px;padding:4px 9px;cursor:pointer}
.who .signout:hover{border-color:var(--wire);color:var(--wire)}

nav.tabs{display:flex;gap:2px;margin:14px 0 10px;border-bottom:1px solid var(--line)}
nav.tabs button{appearance:none;border:0;background:none;font-family:inherit;font-size:13px;color:var(--muted);padding:9px 15px;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;font-weight:600;display:flex;align-items:center;gap:7px}
nav.tabs button .c{font-family:var(--mono);font-size:10px;background:var(--panel-2);border:1px solid var(--line);border-radius:20px;padding:0 6px;color:var(--faint)}
nav.tabs button:hover{color:var(--ink)}
nav.tabs button[aria-selected="true"]{color:var(--wire);border-bottom-color:var(--wire)}
nav.tabs button[aria-selected="true"] .c{background:var(--wire-tint);border-color:#bfe3e2;color:#0b5b62}
nav.tabs button:focus-visible{outline:2px solid var(--wire);outline-offset:2px;border-radius:4px}
nav.tabs button[hidden]{display:none}

.cap{font-size:12px;color:var(--muted);margin:8px 0 15px;padding:9px 12px;background:var(--panel-2);border:1px solid var(--line-2);border-left:3px solid var(--wire);border-radius:0 7px 7px 0}
.cap b{color:var(--ink)}

.panel{display:none}
.panel.active{display:block}

.winbar{display:flex;flex-wrap:wrap;align-items:center;gap:9px;margin-bottom:12px}
.seg{display:inline-flex;flex-wrap:wrap;background:var(--panel-2);border:1px solid var(--line);border-radius:8px;padding:2px}
.seg button{appearance:none;border:0;background:none;font-family:inherit;font-size:11.5px;font-weight:600;color:var(--muted);padding:5px 12px;border-radius:6px;cursor:pointer}
.seg button[aria-pressed="true"]{background:var(--wire);color:#fff}
.winlbl{font-size:11px;color:var(--faint);font-weight:600}

.grid{display:grid;gap:12px}
.g6{grid-template-columns:repeat(6,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
.g2{grid-template-columns:2fr 1fr}
@media(max-width:900px){.g6,.g4{grid-template-columns:repeat(3,1fr)}.g2,.g3{grid-template-columns:1fr}}

.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:13px 14px;position:relative}
.card .k{font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);font-weight:700;margin-bottom:6px;display:flex;align-items:center}
.stat .v{font-size:26px;font-weight:700;letter-spacing:-.02em;line-height:1}
.stat .v small{font-size:13px;color:var(--muted);font-weight:600}
.stat .sub{font-size:11px;color:var(--muted);margin-top:5px}
.v.pass{color:var(--pass)} .v.review{color:var(--review)} .v.fail{color:var(--fail)}
.v.empty{color:var(--faint);font-size:18px;font-weight:600}

.sec{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:15px 16px;margin-top:12px;position:relative}
.sec > h2{font-family:var(--display);font-size:14px;font-weight:600;letter-spacing:-.01em;margin-bottom:2px;display:flex;align-items:center}
.sec > .desc{font-size:11.5px;color:var(--muted);margin-bottom:12px}

.w > .wdot{position:absolute;top:8px;right:9px;width:7px;height:7px;border-radius:50%;background:var(--wire);opacity:.45;transition:.15s}
.w > .wtrace{display:none}
body.wiring .w > .wdot{opacity:1;box-shadow:0 0 0 3px var(--wire-tint)}
body.wiring .w > .wtrace{display:block;margin-top:9px;padding-top:9px;border-top:1px dashed #cfe4e3;font-family:var(--mono);font-size:10px;line-height:1.5;color:#0b5b62}
.wtrace .row{display:flex;gap:6px}
.wtrace .lbl{color:var(--faint);min-width:52px;text-transform:uppercase;letter-spacing:.03em;font-family:var(--sans);font-size:9px;font-weight:700;padding-top:1px}
.wtrace .val{flex:1}
.wtrace .m{color:var(--wire)} .wtrace .src{color:#7a4bd0} .wtrace .fx{color:var(--ink)}
.wtrace .st{color:var(--muted)}
.wtrace .st.live{color:var(--pass);font-weight:700} .wtrace .st.empty{color:var(--faint);font-weight:700}
.wtrace .st.refused{color:var(--fail);font-weight:700}
.wtrace .st.not_wired{color:var(--fail);font-weight:700}

/* honest empty-state (rendered when a real endpoint returns nothing) */
/* ONE EMPTY STATE, ONE WIDTH. This component sits inside flex parents on some cards,
   grid parents on others (the 6-column KPI row) and plain blocks elsewhere, and it
   rendered at a different width in each -- a 120px stub in the KPI row above a
   full-width panel two cards down, which reads as a broken page rather than an empty
   one. `grid-column:1/-1` is what the grid case needs; `flex:1 1 100%` the flex case;
   neither harms the other. */
.empty-state{grid-column:1/-1;flex:1 1 100%;width:100%;box-sizing:border-box;font-size:11.5px;color:var(--faint);font-style:italic;padding:14px 4px;text-align:center;border:1px dashed var(--line);border-radius:8px;background:var(--panel-2)}

/* ROUTING 157: a control whose round-trip succeeds but resolves to no recognized
   runtime consumer, rendered inert, never as a blank editable input, so it cannot
   be mistaken for a live control that merely has nothing in it yet. */
.not-wired-state{font-size:11.5px;color:var(--fail);padding:10px 12px;border:1px dashed var(--fail);border-radius:8px;background:var(--panel-2)}
.not-wired-state b{font-weight:700}
.load-err{font-size:11.5px;color:var(--fail);padding:12px 4px;border:1px dashed #e6c3bd;border-radius:8px;background:var(--fail-tint)}
.load-err button{margin-left:8px;appearance:none;border:1px solid #e6c3bd;background:#fff;border-radius:6px;padding:2px 8px;font-size:10.5px;font-weight:600;color:var(--fail);cursor:pointer}

.bars{display:flex;flex-direction:column;gap:7px}
.bar{display:grid;grid-template-columns:190px 1fr 60px;align-items:center;gap:10px;font-size:11.5px}
.bar .nm{color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar .track{background:var(--panel-2);border-radius:5px;height:12px;overflow:hidden;border:1px solid var(--line-2)}
.bar .fill{height:100%;border-radius:5px;background:var(--wire)}
.bar .fill.rev{background:var(--review)} .bar .fill.fl{background:var(--fail)}
.bar .n{font-family:var(--mono);font-size:10px;color:var(--muted);text-align:right}

.dist{display:flex;gap:8px;flex-wrap:wrap}
.chip{border:1px solid var(--line);border-radius:8px;padding:7px 10px;background:var(--panel-2);min-width:96px}
.chip .cn{font-size:10px;color:var(--faint);text-transform:uppercase;letter-spacing:.04em;font-weight:700}
.chip .cv{font-family:var(--mono);font-size:17px;font-weight:700;margin-top:2px}
.chip.state-processing .cv{color:var(--wire)} .chip.state-rendered .cv{color:var(--ink)}
.chip.state-error .cv{color:var(--fail)} .chip.state-complete .cv{color:var(--pass)}
.chip.state-resubmitted .cv{color:var(--review)} .chip.state-not_ordered .cv{color:var(--faint)}
/* qa_review and pending had NO colour rule, so the two states this projection
   emits most often rendered in default ink beside colour-coded siblings -- the
   row looked half-styled. Same semantics as everywhere else on the board:
   review is amber, and pending is faint because it is an absence of a verdict,
   not a result. Added 2026-08-27 with the QA relabel. */
.chip.state-qa_review .cv{color:var(--review)} .chip.state-pending .cv{color:var(--faint)}
/* The lifecycle panel's scope line: it sits ABOVE the chips and spans the whole
   row, so the denominator and the date are read before the four numbers rather
   than hunted for afterwards. */
.dist-scope{flex-basis:100%;font-size:11px;color:var(--faint);margin:0 0 8px}

.chart{height:130px;display:flex;align-items:flex-end;gap:5px;padding-top:8px}
.chart .col{flex:1;display:flex;flex-direction:column;justify-content:flex-end;gap:2px}
.chart .seg2{border-radius:2px 2px 0 0}
.chart .seg2.p{background:var(--wire)} .chart .seg2.r{background:var(--review)} .chart .seg2.f{background:var(--fail)}
.chart .xl{font-family:var(--mono);font-size:8px;color:var(--faint);text-align:center;margin-top:5px}
.legend{display:flex;gap:14px;flex-wrap:wrap;font-size:10px;color:var(--muted);margin-top:8px}
.legend span{display:inline-flex;align-items:center;gap:5px}
.legend .d{width:8px;height:8px;border-radius:50%}

/* per-check performance */
table.perf{width:100%;border-collapse:collapse;font-size:11.5px}
table.perf th{text-align:left;font-size:9px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);border-bottom:1.5px solid var(--line);padding:6px 8px;font-weight:700}
table.perf td{padding:6px 8px;border-bottom:1px solid var(--line-2)}
table.perf td.id{font-family:var(--mono);color:var(--muted);width:30px}
table.perf .spark{display:inline-flex;align-items:flex-end;gap:1.5px;height:18px}
table.perf .spark i{width:4px;background:var(--wire);border-radius:1px;display:inline-block}
.agree{font-family:var(--mono);font-weight:700}
.agree.hi{color:var(--pass)} .agree.mid{color:var(--review)} .agree.lo{color:var(--fail)}

/* calibration matrix */
.cal{display:grid;grid-template-columns:auto 1fr 1fr;gap:2px;font-size:11.5px;max-width:560px}
.cal .h{font-size:9px;letter-spacing:.04em;text-transform:uppercase;color:var(--faint);font-weight:700;padding:7px 9px;display:flex;align-items:center}
.cal .rh{font-weight:600;padding:11px 9px;background:var(--panel-2);border-radius:6px 0 0 6px;display:flex;align-items:center}
.cal .cell{padding:11px 9px;border-radius:4px;text-align:center}
.cal .cell .num{font-family:var(--mono);font-size:17px;font-weight:700;line-height:1}
.cal .cell .tag{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;margin-top:3px;display:block}
.cal .good{background:var(--pass-tint);color:var(--pass)}
.cal .bad{background:var(--fail-tint);color:var(--fail)}
.cal .neu{background:var(--panel-2);color:var(--muted)}
.calrates{display:flex;gap:10px;flex-wrap:wrap;margin-top:12px}
.rate{border:1px solid var(--line);border-radius:8px;padding:8px 12px;background:var(--panel-2);min-width:120px}
.rate .rn{font-size:10px;color:var(--faint);text-transform:uppercase;letter-spacing:.03em;font-weight:700;display:flex;align-items:center}
.rate .rv{font-family:var(--mono);font-size:19px;font-weight:700;margin-top:3px}
.rate .rv.pass{color:var(--pass)} .rate .rv.fail{color:var(--fail)} .rate .rv.review{color:var(--review)}

/* controls */
.ctrl-row{display:flex;align-items:flex-start;gap:14px;padding:11px 0;border-bottom:1px solid var(--line-2)}
.ctrl-row:last-child{border-bottom:0}
/* Stacked layout for a wide multi-line editor (label above, full-width textarea
   below) instead of the default side-by-side row -- the horizontal layout above
   crams a .listedit textarea into a narrow flex column otherwise. */
.ctrl-row.col{flex-direction:column;align-items:stretch;gap:6px}
.ctrl-row.col .ctrl-val{width:100%}
.ctrl-main{flex:1}
.ctrl-main .cl{font-size:12.5px;font-weight:600;display:flex;align-items:center}
.ctrl-main .cd{font-size:11px;color:var(--muted);margin-top:2px}
.ctrl-val{flex:none;display:flex;align-items:center;gap:8px}
.ctrl-val.col{flex-direction:column;align-items:stretch}
.pill{font-family:var(--mono);font-size:11px;background:var(--panel-2);border:1px solid var(--line);border-radius:6px;padding:4px 9px}
.pill.on{background:var(--pass-tint);border-color:#bfe0d3;color:var(--pass);font-weight:700}
.mini-toggle{width:34px;height:19px;border-radius:10px;background:var(--pass);position:relative;flex:none;cursor:pointer;border:0;padding:0}
.mini-toggle::after{content:"";position:absolute;top:2px;left:17px;width:15px;height:15px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}
.mini-toggle.off{background:#c6d0da}.mini-toggle.off::after{left:2px}
.mini-toggle:disabled{opacity:.5;cursor:progress}
.numedit{width:74px;font-family:var(--mono);font-size:11px;border:1px solid var(--line);border-radius:6px;padding:4px 7px;background:var(--panel)}
.numedit:focus{outline:2px solid var(--wire);outline-offset:-1px;border-color:var(--wire)}
.unit{font-size:10.5px;color:var(--faint)}
.listedit{width:100%;font-family:var(--mono);font-size:11px;border:1px solid var(--line);border-radius:6px;padding:6px 8px;background:var(--panel);resize:vertical;min-height:34px}
.saverow{display:flex;align-items:center;gap:8px;margin-top:8px}
.saved-tick{font-size:10.5px;color:var(--pass);font-weight:700;opacity:0;transition:.2s}
.saved-tick.show{opacity:1}

/* Zillow safety state bar (mockup, 2026-08-25) */
.safety-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 13px;margin-bottom:14px;background:var(--panel);border:1px solid var(--line);border-radius:10px}
/* Hidden entirely when the reads are not permitted: a strip of dashes is worse than
   no strip, because it looks like the gates are unreadable rather than unavailable. */
.safety-bar[hidden]{display:none}
.safety-ey{font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);font-weight:700;margin-right:2px}
.safety-pill{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--muted);background:var(--panel-2);border:1px solid var(--line);border-radius:20px;padding:4px 11px 4px 8px}
.safety-pill .dot{width:7px;height:7px;border-radius:50%;background:var(--faint);flex:none}
/* ⛔ ON IS GREEN, OFF IS RED, UNIFORMLY (Jason, 2026-08-27). Previously OFF rendered
   as neutral grey, which reads as "no information" rather than "this is switched off" --
   and an operator scanning the strip could not tell a disabled gate from one that had
   failed to load. The colour now carries the state.

   Note the deliberate flatness: "PlanoQ writes OFF" is a SAFE condition, not a fault,
   and it still shows red. That is the point -- red here means NOT RUNNING, and whether
   that is good or bad depends on what the operator intended. A strip that editorialised
   would need the operator to remember which switches invert, which is exactly the
   memory load the colour is meant to remove. */
.safety-pill.on{background:var(--pass-tint);border-color:#bfe0d3;color:var(--ink)}
.safety-pill.on .dot{background:var(--pass)}
.safety-pill.off{background:var(--fail-tint);border-color:#f0c9c4;color:var(--ink)}
.safety-pill.off .dot{background:var(--fail)}
/* Unknown stays GREY on purpose: a read that failed must not be painted as either
   state. Claiming "off" when we could not read it is the false-safety failure this
   board has shipped before. */
.safety-pill.unknown{background:var(--panel-2);border-color:var(--line)}
.safety-pill.unknown .dot{background:var(--faint)}
.safety-pill b{color:var(--ink);font-weight:700}

/* Rollout mode segmented control (mockup, 2026-08-25) */
.rollout-seg{display:flex;gap:10px;margin-top:10px}
.rollout-seg button{flex:1;text-align:left;padding:12px 14px;border-radius:9px;border:1.5px solid var(--line);background:var(--panel-2);cursor:pointer;font-family:inherit}
.rollout-seg button:hover:not(.on):not(:disabled){border-color:var(--faint)}
.rollout-seg button:disabled{cursor:progress;opacity:.65}
.rollout-seg button.on{border-color:var(--wire);background:var(--wire-tint)}
.rollout-seg button b{display:block;font-size:13px;color:var(--ink)}
.rollout-seg .cap-sm{display:block;font-size:10.5px;color:var(--muted);margin-top:2px;font-weight:400}

/* Warning tag under a Master Controls row (mockup, 2026-08-25) */
.warn-tag{display:inline-block;margin-top:5px;font-size:10px;color:var(--review);background:var(--review-tint);border-radius:5px;padding:2px 7px;font-weight:600}

table.checks{width:100%;border-collapse:collapse;font-size:11.5px}
table.checks th{text-align:left;font-size:9px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);border-bottom:1.5px solid var(--line);padding:6px 8px;font-weight:700}
table.checks td{padding:6px 8px;border-bottom:1px solid var(--line-2);vertical-align:middle}
table.checks td.id{font-family:var(--mono);color:var(--muted);width:34px}
.sevtog{display:inline-flex;border:1px solid var(--line);border-radius:6px;overflow:hidden}
.sevtog button{appearance:none;border:0;background:var(--panel-2);font-family:var(--mono);font-size:9.5px;font-weight:700;color:var(--muted);padding:3px 8px;cursor:pointer}
.sevtog button.on-f{background:var(--fail);color:#fff}
.sevtog button.on-r{background:var(--review);color:#fff}
.sevtog.locked{opacity:.55;pointer-events:none}
.human{font-size:8.5px;font-weight:700;letter-spacing:.03em;color:var(--faint);border:1px solid var(--line);border-radius:4px;padding:1px 5px;text-transform:uppercase;margin-left:5px}

/* HITL */
.esc{display:flex;align-items:flex-start;gap:12px;padding:12px;border:1px solid var(--line);border-radius:9px;margin-bottom:9px;background:var(--panel)}
.esc .kind{flex:none;width:120px}
.esc .kind .kt{font-size:9px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:2px 7px;border-radius:5px;display:inline-block}
.kt.addr{background:var(--review-tint);color:var(--review)} .kt.err{background:var(--fail-tint);color:var(--fail)}
.kt.amb{background:var(--wire-tint);color:#0b5b62} .kt.unc{background:#ece9f5;color:#6b46c1}
.esc .body{flex:1}
.esc .body .ttl{font-weight:600;font-size:12.5px}
.esc .body .meta{font-family:var(--mono);font-size:10px;color:var(--muted);margin-top:3px}
.esc .body .why{font-size:11px;color:var(--muted);margin-top:5px}
.esc .acts{flex:none;display:flex;flex-direction:column;gap:6px;align-items:flex-end}
.btn{appearance:none;border:1px solid var(--line);background:var(--panel-2);font-family:inherit;font-size:11px;font-weight:600;color:var(--ink);border-radius:7px;padding:6px 12px;cursor:pointer;white-space:nowrap}
.btn:hover{border-color:var(--wire);color:var(--wire)}
.btn.pri{background:var(--wire);border-color:var(--wire);color:#fff}
.btn.pri:hover{background:var(--wire-bright);color:#fff}
.btn:focus-visible{outline:2px solid var(--wire);outline-offset:2px}
.btn:disabled{opacity:.55;cursor:progress}
.sumbar{font-size:10.5px;color:var(--muted);font-family:var(--mono);margin-top:2px}
.lifebar{display:flex;align-items:center;gap:7px;font-size:10px;color:var(--muted);margin-bottom:14px;flex-wrap:wrap}
.lifebar .st{font-weight:700;padding:2px 8px;border-radius:5px;background:var(--panel-2);border:1px solid var(--line)}
.lifebar .st.a{background:var(--review-tint);color:var(--review);border-color:#f0dcae}
.lifebar .st.m{background:#eef1f4;color:var(--muted)}
.lifebar .st.r{background:var(--pass-tint);color:var(--pass);border-color:#bfe0d3}
.lifebar .ar{color:var(--faint)}
.subnav{display:inline-flex;background:var(--panel-2);border:1px solid var(--line);border-radius:8px;padding:2px;margin-bottom:13px}
.subnav button{appearance:none;border:0;background:none;font-family:inherit;font-size:11.5px;font-weight:600;color:var(--muted);padding:5px 13px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.subnav button[aria-pressed="true"]{background:var(--wire);color:#fff}
.subnav button .cc{font-family:var(--mono);font-size:9px;background:rgba(0,0,0,.08);border-radius:10px;padding:0 5px}
.subnav button[aria-pressed="true"] .cc{background:rgba(255,255,255,.28)}
.subview{display:none} .subview.on{display:block}

/* ---- Landing page (Jason, 2026-08-27). SENTINEL: home-block-present ----
   Restrained on purpose. This is the first thing anyone sees, including a client over
   someone's shoulder, and it carries NO live data -- so there is nothing on it that can
   be wrong. PlanOmatic's own mark in their own orange; everything else is the product's
   existing palette, because a landing page in a different visual language would read as
   a different product from the board behind it. */
.home-hero{background:var(--panel);border:1px solid var(--line);border-radius:12px;
  padding:38px 34px 32px;margin-bottom:18px}
.pm-logo{display:block;width:220px;height:auto;color:#ef4423;margin-bottom:22px}
.home-title{font-family:var(--display);font-size:26px;font-weight:600;letter-spacing:-.02em;
  color:var(--ink);margin:0 0 6px}
.home-sub{font-size:14px;color:var(--muted);margin:0}

.home-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
.home-card{appearance:none;font-family:inherit;text-align:left;cursor:pointer;
  background:var(--panel);border:1px solid var(--line);border-radius:11px;
  padding:18px 20px;display:flex;flex-direction:column;gap:6px;
  transition:border-color .12s, transform .12s}
.home-card:hover{border-color:var(--wire);transform:translateY(-1px)}
.home-card:focus-visible{outline:2px solid var(--wire);outline-offset:2px}
.hc-dot{width:9px;height:9px;border-radius:50%;flex:none}
.hc-dot.zil{background:var(--wire)}
.hc-dot.pp{background:#6b46c1}
.hc-name{font-family:var(--display);font-size:16px;font-weight:600;color:var(--ink)}
.hc-desc{font-size:13px;color:var(--muted);line-height:1.5}
.hc-go{font-size:12px;font-weight:600;color:var(--wire);margin-top:4px}
.home-note{margin-top:16px;font-size:13px;color:var(--muted);background:var(--panel-2);
  border:1px solid var(--line-2);border-radius:10px;padding:14px 16px}
.home-note b{color:var(--ink)}
.nav-i.home{font-weight:700;color:var(--ink)}
/* HITL rework (Jason, approved 2026-08-27). SENTINEL: escpill-block-present
   Pills filter the table and their counts come from the same payload as the rows. */
#bucketCards{display:flex;flex-wrap:wrap;gap:8px;align-items:stretch}
.escpill{appearance:none;font-family:inherit;cursor:pointer;text-align:left;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;
  padding:9px 13px;display:flex;align-items:baseline;gap:9px;color:var(--ink);
  transition:border-color .12s, background .12s}
.escpill:hover{border-color:var(--wire)}
.escpill:focus-visible{outline:2px solid var(--wire);outline-offset:2px}
.escpill .n{font-family:var(--display);font-size:17px;font-weight:600;
  font-variant-numeric:tabular-nums}
.escpill .l{font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);font-weight:600}
.escpill[aria-pressed="true"]{background:var(--wire-tint);border-color:var(--wire)}
.escpill[aria-pressed="true"] .l{color:var(--wire)}
.escpill.all .n{color:var(--wire)}
.escpill.fail[aria-pressed="true"]{background:var(--fail-tint);border-color:var(--fail)}
.escpill.fail[aria-pressed="true"] .l{color:var(--fail)}
.escpill.review[aria-pressed="true"]{background:var(--review-tint);border-color:var(--review)}
.escpill.review[aria-pressed="true"] .l{color:var(--review)}
.escpill.triage[aria-pressed="true"]{background:#f0eaf7;border-color:#6b46c1}
.escpill.triage[aria-pressed="true"] .l{color:#6b46c1}
.escpill.vendor[aria-pressed="true"]{background:#eef1f4;border-color:var(--muted)}
.escpill.vendor[aria-pressed="true"] .l{color:var(--muted)}
.escrecon{flex-basis:100%;font-family:var(--mono);font-size:11px;color:var(--faint);
  padding:2px 2px 0}

.esctablewrap{overflow-x:auto;border:1px solid var(--line);border-radius:9px;
  background:var(--panel)}
/* ⛔ NARROWER THAN THE PANEL ON PURPOSE. At 880px this table overflowed its container
   and the right-hand column -- which held the only way to open a row -- sat off-screen
   behind a horizontal scrollbar. Jason reported the page as having lost every action.
   The columns now compress instead of pushing a control out of reach. */
table.esctable{width:100%;min-width:720px;border-collapse:collapse;font-size:12.5px;
  table-layout:auto}
.esctable td:nth-child(4){min-width:150px}
.esctable .caretcell{padding-right:0;color:var(--faint);user-select:none}
.esccaret{display:inline-block;font-size:10px;line-height:1}
.esctable tr.escrow{cursor:pointer}
.esctable tr.escrow:focus-visible{outline:2px solid var(--wire);outline-offset:-2px}
.esctable tr.escrow.open{background:var(--wire-tint)}
.esctable tr.escrow.open .esccaret{color:var(--wire)}
.esctable th{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.07em;
  color:var(--faint);background:var(--panel-2);padding:9px 12px;
  border-bottom:1px solid var(--line);white-space:nowrap;font-weight:700}
.esctable td{padding:9px 12px;border-bottom:1px solid var(--line-2);vertical-align:top}
.esctable tr.escrow:hover{background:var(--panel-2)}
.esctable .needcell{color:var(--muted);max-width:36ch}
.esctable .wait{white-space:nowrap;color:var(--muted);font-variant-numeric:tabular-nums}
.esctable .wait.aging{color:var(--review);font-weight:600}
.esctable .faint{color:var(--faint)}
.esctable tr.escdetail>td{background:var(--panel-2);padding:12px}
.kchip{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;padding:3px 8px;border-radius:999px;white-space:nowrap}
.k-needs_match,.k-needs_address{background:var(--wire-tint);color:var(--wire)}
.k-no_match{background:var(--panel-2);color:var(--muted);border:1px solid var(--line)}
/* Grouped by purpose, not severity: bindings teal, verdicts red/amber, vendor grey.
   The colour carries the same grouping the labels do. */
.k-qa_failed,.k-fp_error{background:var(--fail-tint);color:var(--fail)}
.k-qa_review{background:var(--review-tint);color:var(--review)}
.k-zillow_error{background:#eef1f4;color:#5f6c7b;border:1px solid var(--line)}
.k-triage{background:#f0eaf7;color:#6b46c1}

/* HITL queue search (Jason, 2026-08-27). SENTINEL: escsearch-block-present */
.escsearchwrap{margin:0 0 12px}
.escsearch{width:100%;box-sizing:border-box;padding:8px 12px;font:inherit;font-size:13px;
  color:var(--ink);background:var(--panel);border:1px solid var(--line);border-radius:8px}
.escsearch::placeholder{color:var(--faint)}
.escsearch:focus{outline:2px solid var(--wire);outline-offset:1px;border-color:var(--wire)}
/* First-seen range filter. SENTINEL: escrange-block-present */
.escrange{display:flex;align-items:center;gap:7px;margin-top:8px;flex-wrap:wrap}
.escrange .rl{font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);font-weight:600}
.escdate{font-family:inherit;font-size:12px;color:var(--ink);background:var(--panel);
  border:1px solid var(--line);border-radius:7px;padding:5px 8px}
.escdate:focus{outline:2px solid var(--wire);outline-offset:1px;border-color:var(--wire)}
/* The QA verdict's own reason, split into its clauses. SENTINEL: qareason-block-present */
.qareason{margin:8px 0 0;padding-left:11px;border-left:2px solid var(--line)}
.qareason .qrl{font-size:12px;color:var(--muted);margin-bottom:3px}
.qareason .qrl:first-child{color:var(--ink);font-weight:600}
/* type=search paints its own clear affordance; Escape clears it too, and both are kept. */
.escsearch::-webkit-search-cancel-button{cursor:pointer}
.esc .ts{font-family:var(--mono);font-size:9.5px;color:var(--faint);margin-top:6px;display:flex;gap:14px;flex-wrap:wrap}
.esc .ts b{color:var(--muted);font-weight:700}
.links{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}
.linkout{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:600;color:var(--wire);background:var(--wire-tint);border:1px solid #bfe3e2;border-radius:6px;padding:3px 9px;text-decoration:none;cursor:pointer}
.linkout:hover{background:#d7eeed}
.linkout::before{content:"\2197";font-size:9px}
.linkout.off{color:var(--faint);background:var(--panel-2);border-color:var(--line);cursor:not-allowed;pointer-events:none}
.agebadge{font-family:var(--mono);font-size:9px;font-weight:700;padding:1px 6px;border-radius:4px;margin-left:6px}
.agebadge.warn{background:var(--review-tint);color:var(--review)} .agebadge.ok{background:var(--pass-tint);color:var(--pass)}
.resline{font-size:10.5px;color:var(--pass);margin-top:5px;font-weight:600}
.selfnote{font-size:10px;color:var(--faint);margin-top:6px;font-style:italic}

/* access & roles */
.accbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
/* ⛔ `min-width:0` IS THE PART THAT ACTUALLY LETS THIS SCROLL. `overflow-x:auto` was
   already here and was not enough: a flex/grid child's default `min-width:auto` refuses
   to shrink below its content, so the grid pushed its own section wider than the
   viewport instead of scrolling inside it -- measured at 900px, where the section's
   wiring dot rendered 110px past the right edge. Same root cause as the header fix, one
   component over: a box that cannot shrink does not overflow its parent, it WIDENS it. */
.grantgrid{width:100%;min-width:0;max-width:100%;border-collapse:collapse;font-size:11.5px;margin-top:4px;overflow-x:auto;display:block}
.sec{min-width:0}
.grantgrid table{border-collapse:collapse;width:100%}
table.rolemx{border-collapse:collapse;font-size:11.5px;margin-top:4px;min-width:100%}
table.rolemx th{font-size:9px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);font-weight:700;padding:7px 14px;border-bottom:1.5px solid var(--line);text-align:center;white-space:nowrap}
table.rolemx th.rl{text-align:left}
table.rolemx td{padding:9px 14px;border-bottom:1px solid var(--line-2);text-align:center}
table.rolemx td.rl{text-align:left;font-weight:600}
table.rolemx td.rl small{display:block;font-weight:400;color:var(--faint);font-size:10px;margin-top:1px}
.gck{width:18px;height:18px;border-radius:5px;border:1.5px solid var(--wire);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;background:var(--wire);color:#fff;font-size:11px;font-weight:700;padding:0}
.gck.off{background:#fff;border-color:#c6d0da;color:transparent}
.gck:disabled{opacity:.5;cursor:progress}
.runstate-box{display:flex;align-items:center;gap:14px;margin-top:6px}
.runstate-current{font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;border:1.5px solid var(--line)}
.runstate-current.running{color:#166534;background:#f0fdf4;border-color:#bbf7d0}
.runstate-current.stopped{color:#991b1b;background:#fef2f2;border-color:#fecaca}
.runstate-current.unknown{color:#92400e;background:#fffbeb;border-color:#fde68a}
.rolehead{display:inline-flex;flex-direction:column;align-items:center;gap:3px}
.rolehead .rn{font-weight:700;color:var(--ink);text-transform:none;letter-spacing:0;font-size:11px}
.rolehead .redit{display:flex;gap:3px}
.icon-btn{appearance:none;border:1px solid var(--line);background:var(--panel-2);border-radius:5px;font-size:9px;font-weight:700;color:var(--muted);padding:1px 5px;cursor:pointer}
.icon-btn:hover{border-color:var(--wire);color:var(--wire)}
.icon-btn.danger:hover{border-color:var(--fail);color:var(--fail)}
.urow{display:flex;align-items:center;gap:12px;padding:9px 0;border-bottom:1px solid var(--line-2)}
.urow:last-child{border-bottom:0}
.uav{width:26px;height:26px;border-radius:50%;background:var(--wire-tint);color:#0b5b62;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;flex:none}
.uname{flex:1;font-weight:600;font-size:12.5px}
.uname small{display:block;font-weight:400;color:var(--faint);font-size:10.5px}
.uname.deact{opacity:.5;text-decoration:line-through}
.roleselect{font-family:inherit;font-size:11px;border:1px solid var(--line);border-radius:7px;padding:5px 8px;background:var(--panel);color:var(--ink)}
.adminbadge{font-size:9px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:#6b46c1;background:#ece9f5;border:1px solid #d9cff0;border-radius:4px;padding:1px 6px;margin-left:6px}
.txtin{font-family:inherit;font-size:11.5px;border:1px solid var(--line);border-radius:7px;padding:6px 9px;background:var(--panel);color:var(--ink)}
.txtin:focus{outline:2px solid var(--wire);outline-offset:-1px;border-color:var(--wire)}

/* toast */
.toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--ink);color:#fff;font-size:12px;padding:10px 16px;border-radius:9px;box-shadow:0 10px 30px rgba(0,0,0,.3);opacity:0;transition:.2s;z-index:120;pointer-events:none;max-width:80vw}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
.toast.err{background:var(--fail)}

/* ledger modal */
.overlay{position:fixed;inset:0;background:rgba(20,28,40,.5);display:none;align-items:flex-start;justify-content:center;padding:40px 20px;z-index:80;overflow:auto}
.overlay.open{display:flex}
.modal{background:var(--panel);border-radius:12px;max-width:1040px;width:100%;box-shadow:0 20px 60px rgba(0,0,0,.3)}
.modal .mh{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--line)}
.modal .mh h2{font-family:var(--display);font-size:15px;font-weight:600;letter-spacing:-.01em}
.modal .mh .sum{font-family:var(--mono);font-size:11px;color:var(--pass);background:var(--pass-tint);border:1px solid #bfe0d3;border-radius:7px;padding:3px 9px;font-weight:700}
.modal .mh .x{margin-left:auto;cursor:pointer;border:1px solid var(--line);background:var(--panel-2);border-radius:7px;width:30px;height:30px;font-size:16px;color:var(--muted)}
.modal .mb{padding:6px 20px 20px;max-height:70vh;overflow:auto}
table.ledger{width:100%;border-collapse:collapse;font-size:11px}
table.ledger th{position:sticky;top:0;background:var(--panel);text-align:left;font-size:9px;letter-spacing:.04em;text-transform:uppercase;color:var(--faint);border-bottom:1.5px solid var(--line);padding:8px;font-weight:700}
table.ledger td{padding:7px 8px;border-bottom:1px solid var(--line-2);vertical-align:top}
table.ledger td.el{font-weight:600;width:150px}
table.ledger td.mono{font-family:var(--mono);font-size:10px}
table.ledger td.mono.m{color:var(--wire)} table.ledger td.mono.s{color:#7a4bd0}
table.ledger .st{font-family:var(--mono);font-size:9px;font-weight:700;white-space:nowrap}
table.ledger .st.live{color:var(--pass)} table.ledger .st.empty{color:var(--faint)}
table.ledger .st.pending{color:var(--muted)} table.ledger .st.refused{color:var(--fail)}
table.ledger .st.not_wired{color:var(--fail)}
.tabgroup{font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--wire);padding:12px 8px 4px}

/* login gate */
.gate{position:fixed;inset:0;background:var(--canvas);display:flex;align-items:center;justify-content:center;z-index:100;padding:20px}
.gate[hidden]{display:none}
.gate .box{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:26px 26px 22px;width:100%;max-width:360px;box-shadow:0 20px 60px rgba(0,0,0,.12)}
.gate .ey{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--wire);font-weight:700}
.gate h1{font-size:18px;font-weight:700;margin:2px 0 14px}
.gate label{display:block;font-size:11px;font-weight:700;color:var(--muted);margin:10px 0 4px;text-transform:uppercase;letter-spacing:.03em}
.gate input{width:100%;font-family:inherit;font-size:13px;border:1px solid var(--line);border-radius:8px;padding:9px 11px;background:var(--panel)}
.gate input:focus{outline:2px solid var(--wire);outline-offset:-1px;border-color:var(--wire)}
.gate .btn.pri{width:100%;justify-content:center;margin-top:16px;padding:10px;text-align:center;display:block}
.gate .msg{font-size:11.5px;color:var(--fail);margin-top:10px;min-height:16px}
.gate .note{font-size:11px;color:var(--faint);margin-top:12px;line-height:1.5}

footer{margin-top:20px;padding-top:12px;border-top:1px solid var(--line);font-size:10.5px;color:var(--faint);display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}

/* ---------- Audit tab (Block B browse-all table; read-only) ---------- */
.aud-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 0}
.aud-ctl{font:inherit;font-size:12px;padding:5px 8px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--ink)}
.aud-check{width:110px}
.aud-sep{width:1px;height:20px;background:var(--line)}
.aud-dash{color:var(--faint);font-size:11px}
.btn.aud-fp{border-color:#e8c9c9;color:var(--fail)}
.btn.aud-fp.on{background:var(--fail-tint);font-weight:700}
table.audit{width:100%;border-collapse:collapse;font-size:12px;margin-top:4px}
table.audit th{position:relative;text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);padding:7px 8px;border-bottom:1px solid var(--line)}
table.audit th.aud-th{cursor:pointer;user-select:none}
table.audit th.aud-th.on{color:var(--ink)}
table.audit td{padding:7px 8px;border-bottom:1px solid var(--line-2);vertical-align:top}
table.audit .aud-fired{font-size:11px;color:var(--muted)}
.obadge{display:inline-block;padding:2px 8px;border-radius:999px;font-size:10.5px;font-weight:600;border:1px solid var(--line)}
.obadge.ok{background:var(--pass-tint);color:var(--pass);border-color:#cfe6dd}
.obadge.fp{background:var(--fail-tint);color:var(--fail);border-color:#e8c9c9;font-weight:700}
.obadge.ff{background:var(--review-tint);color:#9a4b1f;border-color:#eccfae}
.obadge.rev{background:var(--review-tint);color:var(--review);border-color:#f0dcae}
.obadge.pend{background:var(--panel-2);color:var(--muted)}
.aud-pager{display:flex;align-items:center;gap:10px;padding:8px 0}
.aud-count{font-size:11.5px;color:var(--muted)}
.aud-rate{font-size:12px;color:var(--muted);padding:2px 0 6px}
.aud-selflabel{font-size:11px;color:var(--review);font-weight:600}
.aud-sortnote{font-size:10.5px;color:var(--faint);padding:4px 0 2px;font-style:italic}

/* Explicit permission state (ROUTING 49 R-3): never a silent empty shell. */
.permnotice{margin:16px;padding:14px 16px;border:1px solid var(--line,#3a3a3a);border-radius:8px;background:rgba(255,255,255,.04);line-height:1.5;max-width:70ch}

/* ROUTING 79: the orphan row's real work, styled so the useful action looks useful.
   The prominent element is the INSTRUCTION (add the tour to its listing); the issue-id
   bind is a deliberate disclosure beneath it; "Mark addressed" is demoted to secondary
   on these rows because it is the soft annotation that auto-returns. */
.esc .pathone{font-size:11.5px;line-height:1.45;padding:8px 10px;margin-bottom:6px;
  border-left:3px solid var(--accent,#6b8afd);border-radius:4px;
  background:rgba(107,138,253,.10);max-width:60ch}
.esc .candidatelist{font-size:11.5px;line-height:1.6;margin:0 0 8px 18px;padding:0;max-width:60ch}
/* Candidate rows: a comparison, so each side gets its own address + created date.
   SENTINEL: candrow-block-present */
.esc .candidatelist li{margin-bottom:7px}
.esc .candidatelist li:last-child{margin-bottom:0}
.esc .candlink{font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--wire);
  text-decoration:none;border-bottom:1px solid transparent}
.esc .candlink:hover{border-bottom-color:var(--wire)}
.esc .candaddr{color:var(--ink);font-size:11.5px}
.esc .candfacts{color:var(--muted);font-size:11px}
.esc .candfacts.bad{color:var(--review)}
.esc .bindctl{margin-bottom:6px;font-size:11px}
.esc .bindctl .bindsummary{cursor:pointer;color:var(--muted);padding:2px 0}
.esc .bindctl .bindwhy{color:var(--muted);line-height:1.45;margin:4px 0 6px;max-width:60ch}
.esc .bindctl .bindinput{font-family:var(--mono);font-size:11px;padding:4px 6px;
  margin-right:6px;min-width:14ch}
.esc .bindctl .boundnote{color:var(--warn,#e0a458);margin:4px 0}

/* ============================================================================
   UNIFIED LEFT-NAV SHELL (item: shell rebuild, 2026-08-24).
   Layout/IA carried from the client-reviewed `ops-dashboard-unified.html`
   mockup (per SPEC 10-authority, mockup wins on layout/IA). Everything below
   is PURE LAYOUT: no id or data-attribute app.js/ledger.js depend on has
   moved or changed -- #tabnav, button[data-tab]/[data-page], .panel,
   #whoName/#whoRole/#modePosture/#ledgerBtn/#wireToggle/#signout are all
   still exactly where the JS expects them, just re-parented into this shell.
   ============================================================================ */
.shell-bar{position:sticky;top:0;z-index:40;background:var(--panel);border-bottom:1px solid var(--line)}
.shell-bar .shell-in{max-width:1400px;margin:0 auto;padding:0 20px;height:52px;display:flex;align-items:center;gap:18px;overflow:hidden}
.shell-bar .brand{flex-direction:row;align-items:center;gap:9px}
.shell-bar .brand .dot{width:8px;height:8px;border-radius:50%;background:var(--wire);box-shadow:0 0 0 3px rgba(14,124,134,.18);flex:none}
.shell-bar .brand h1{font-size:15px}
.shell-bar .mode{margin-left:4px}
.shell-right{margin-left:auto;display:flex;align-items:center;gap:14px;min-width:0}

.layout{max-width:1400px;margin:0 auto;display:flex;align-items:flex-start}
.sidebar{width:212px;flex-shrink:0;background:var(--panel);border-right:1px solid var(--line);position:sticky;top:52px;min-height:calc(100vh - 52px);padding:14px 0;display:flex;flex-direction:column;gap:1px}
.sidebar .side-ey{font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);padding:0 18px;margin:16px 0 6px;border-top:1px solid var(--line-2);padding-top:13px}
.sidebar .side-ey:first-child{margin-top:2px;border-top:0;padding-top:0}
.sidebar .agent-h{display:flex;align-items:center;gap:9px;padding:10px 18px 5px;font-size:13px;font-weight:700;color:var(--ink);letter-spacing:.01em}
.sidebar .agent-h .adot{width:8px;height:8px;border-radius:50%;flex:none}
.nav-i{appearance:none;border:0;background:none;font-family:inherit;text-align:left;display:flex;align-items:center;gap:9px;padding:9px 18px 9px 33px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;border-left:3px solid transparent;width:100%}
.nav-i.app{padding-left:18px}
.nav-i:hover{background:var(--panel-2);color:var(--ink)}
.nav-i[aria-selected="true"]{background:var(--wire-tint);color:var(--wire);border-left-color:var(--wire)}
.nav-i .c{margin-left:auto;font-family:var(--mono);font-size:10px;background:var(--panel-2);border:1px solid var(--line);border-radius:20px;padding:0 6px;color:var(--faint)}
.nav-i[aria-selected="true"] .c{background:#fff;border-color:#bfe3e2;color:#0b5b62}
.nav-i .admin-tag{margin-left:auto;font-size:10px;font-weight:700;background:#ece9f5;border:1px solid #d9cff0;color:#6b46c1;border-radius:20px;padding:1px 7px}
.nav-i:focus-visible{outline:2px solid var(--wire);outline-offset:-2px}

.content{flex:1;min-width:0}
/* ⛔ THE SIDE PADDING WAS RECLAIMED (Jason, 2026-08-27). He had been reading the gap
   beside the Sign out button as an overflow bug; it was working padding. Since the
   tables are what actually run out of room -- PP's Data table has overflowed three
   times today and the Zillow HITL expander was pushed off-screen entirely -- the
   horizontal space is worth more to the content than to the margin. 20px -> 8px each
   side gives every table 24px it did not have. */
.content .app-inner{max-width:1180px;margin:0 auto;padding:14px 8px 40px}

@media(max-width:900px){
  .shell-bar .shell-in{gap:10px;flex-wrap:wrap;height:auto;padding:8px 14px}
  .shell-bar .mode{display:none}
  .shell-right{gap:9px}
  .layout{flex-direction:column}
  .sidebar{width:100%;position:static;min-height:0;border-right:none;border-bottom:1px solid var(--line);flex-direction:row;overflow-x:auto;padding:8px 12px;gap:8px}
  .sidebar .side-ey,.sidebar .agent-h{display:none}
  .nav-i,.nav-i.app{width:auto;padding:7px 12px;border-left:none;border-radius:7px;flex-shrink:0;white-space:nowrap;gap:6px}
  .nav-i[aria-selected="true"]{border-left:none}
  .nav-i .c,.nav-i .admin-tag{margin-left:0}
}
.btn.tiny{font-size:10px;padding:1px 6px;margin-left:8px;vertical-align:baseline}

/* Data tab (item, 2026-08-24) -- same idiom as .chip/table.perf/table.checks above,
   not the mockup's unrelated .tbl/.chip/.badge-s classes. */
.data-filters{display:flex;gap:6px;margin-bottom:12px}
.data-chip{appearance:none;border:1px solid var(--line);border-radius:8px;padding:6px 12px;background:var(--panel-2);font-family:inherit;font-size:12px;font-weight:600;color:var(--muted);cursor:pointer}
.data-chip .n{font-family:var(--mono);margin-left:5px;color:var(--faint)}
.data-chip.on{background:var(--ink);color:#fff;border-color:var(--ink)}
.data-chip.on .n{color:#cfd6dc}
table.jobs{width:100%;border-collapse:collapse;font-size:12px}
table.jobs th{text-align:left;font-size:9px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);border-bottom:1.5px solid var(--line);padding:7px 8px;font-weight:700}
table.jobs td{padding:7px 8px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.data-status{display:inline-block;font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:10px;background:var(--panel-2);color:var(--muted);text-transform:capitalize}
.data-status.pass{background:var(--pass-tint);color:var(--pass)}
.data-status.fail{background:var(--fail-tint);color:var(--fail)}

/* Data-tab toolbar: search / date range / status / page size (2026-08-25, status
   dropdown added 2026-08-26) */
.data-toolbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:10px}
.data-search{font-family:inherit;font-size:12px;border:1px solid var(--line);border-radius:7px;padding:6px 10px;background:var(--panel);min-width:220px}
.data-search:focus{outline:2px solid var(--wire);outline-offset:-1px;border-color:var(--wire)}
.data-daterange{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted)}
.data-daterange input[type=date]{font-family:inherit;font-size:11.5px;border:1px solid var(--line);border-radius:6px;padding:4px 6px;background:var(--panel)}
.data-statusfilter{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted);margin-left:auto}
.data-statusfilter select{font-family:inherit;font-size:11.5px;border:1px solid var(--line);border-radius:6px;padding:4px 6px;background:var(--panel);max-width:180px}
.data-pagesize{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted)}
.data-pagesize select{font-family:inherit;font-size:11.5px;border:1px solid var(--line);border-radius:6px;padding:4px 6px;background:var(--panel)}

/* Sortable column headers */
table.data-sortable th[data-sort]{cursor:pointer;user-select:none;position:relative;padding-right:16px}
table.data-sortable th[data-sort]:hover{color:var(--wire)}
table.data-sortable th[data-sort]::after{content:"";position:absolute;right:4px;top:50%;transform:translateY(-50%);border:4px solid transparent;border-top-color:var(--line);opacity:.6}
table.data-sortable th[data-sort].sorted::after{border-top-color:var(--wire);opacity:1}
table.data-sortable th[data-sort].sorted.desc::after{transform:translateY(-50%) rotate(180deg)}

/* Expandable rows */
tr.data-row{cursor:pointer}
tr.data-row:hover{background:var(--panel-2)}
tr.data-row.open{background:var(--wire-tint)}
/* `.data-caret` removed with its markup (Jason, 2026-08-27): an inline glyph before the
   issue link shifted the column and changed width when a row opened. Rule kept out
   rather than left dangling -- a style for an element nothing renders is dead code the
   next person has to disprove. Row affordance is `.data-row` cursor + `.open`. */
tr.data-expand td{padding:0;border-bottom:1px solid var(--line-2)}
.data-expand-box{padding:14px 16px;background:var(--panel-2)}
.data-expand-grid{display:grid;grid-template-columns:180px 1fr;gap:6px 12px;font-size:11.5px;margin-bottom:12px}
.data-expand-grid .lbl{color:var(--faint);font-size:10px;text-transform:uppercase;letter-spacing:.04em}
.data-expand-grid .val{color:var(--ink)}
.data-expand-sub{font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);font-weight:700;margin:10px 0 6px}
.data-tour-row{display:flex;align-items:center;gap:10px;font-size:11.5px;padding:4px 0}
.data-tour-row .mono{font-family:var(--mono);color:var(--muted)}
.data-expand-links{margin-top:12px}

/* Pager */
.data-pagerow{display:flex;align-items:center;gap:12px;margin-top:10px}

/* Post-Processing tabs (item, 2026-08-24). `pp-` prefixed throughout, deliberately
   distinct from this file's own .card/.pill/.tbl-shaped names above (checked before
   adding: .card and .pill already exist here with DIFFERENT structure/semantics --
   reusing those names would either override this file's existing rules or silently
   mis-style PP's markup with the wrong assumptions). Reuses this file's own tokens
   (--panel/--line/--muted/--wire/--pass/--fail/--mono/--sans) rather than importing
   PP's own :root palette, which itself collides on --ink/--muted with slightly
   different values -- one token set, not two that could drift apart. */
.pp-pill{display:inline-flex;align-items:center;font-size:11.5px;font-weight:700;padding:4px 11px;border-radius:14px;background:var(--panel-2);color:var(--muted)}
.pp-pill.off{background:var(--panel-2);color:var(--muted)}
.pp-pill.crit{background:var(--fail-tint);color:var(--fail)}
.pp-ctrl{display:flex;align-items:center;gap:16px;padding:12px 2px;border-top:1px solid var(--line);flex-wrap:wrap}
.pp-ctrl-meta{flex:1;min-width:220px}
.pp-ctrl-name{font-weight:600;font-size:12.5px}
.pp-ctrl-desc{color:var(--muted);font-size:11.5px;margin-top:2px}
.pp-ctrl-fields{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:12px;color:var(--muted)}
.pp-ctrl-fields input[type=text]{font-family:inherit;font-size:12px;padding:5px 8px;border:1px solid var(--line);border-radius:6px;width:8rem}
table.pp-tbl{width:100%;border-collapse:collapse;font-size:12px;margin-top:8px}
table.pp-tbl th{text-align:left;font-size:9px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);border-bottom:1.5px solid var(--line);padding:7px 8px;font-weight:700}
table.pp-tbl td{padding:7px 8px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.pp-readonly{color:var(--faint);font-size:11px}
.pp-edit-input{font-family:var(--mono);font-size:11.5px;padding:4px 7px;border:1px solid var(--line);border-radius:6px;width:9rem;margin-right:6px}

/* ⛔ THE WIRING LEDGER IS BUILD INSTRUMENTATION, NOT AN OPERATOR METRIC.
   Jason, 2026-08-26: "6/75 wired" makes it look like most of the dashboard is not
   wired, and that is alarming to leave in front of operators.

   It is ACCURATE and it is measuring the wrong thing for that audience. `wired`
   counts regions that have completed a live round-trip IN THIS BROWSER SESSION, so a
   freshly-loaded board shows a low number simply because most tabs have not been
   opened yet -- it is a per-session progress counter, not a health score. The nav
   chips are the same data: the number of ledger-tracked ELEMENTS on that tab, which
   is why Post-Processing has none (its embed registers nothing) and why the numbers
   have no operational meaning at all -- they are not jobs, escalations or alerts.

   So both are hidden unless "Show wiring" is on. The tool is kept in full for the
   team (the toggle is right there, and the Wiring Integrity Gate depends on it); it
   just stops presenting developer instrumentation as operator information. Hiding it
   changes NOTHING about what is measured or enforced. */
.badge{display:none}
body.wiring .badge{display:flex}
.nav-i .c{display:none}
body.wiring .nav-i .c{display:inline-block}

/* Cutover date control (Jason, 2026-08-26): a real picker, sized like a date and not
   like a paragraph. The textarea it replaced was 854px wide and 66px tall for a ten
   character value, which is what made it read as a free-form field. */
.dateedit{font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--panel);
  border:1px solid var(--line);border-radius:7px;padding:6px 9px;min-height:30px}
.dateedit:focus{outline:none;border-color:var(--wire)}
.lnk-btn{appearance:none;background:none;border:0;font-family:inherit;font-size:11.5px;
  color:var(--muted);text-decoration:underline;cursor:pointer;padding:4px 6px;min-height:28px}
.lnk-btn:hover{color:var(--ink)}
.ctrl-val{display:flex;align-items:center;gap:8px;flex-wrap:wrap}

/* == DATA-TAB FIRE FILTER + INLINE NOTES (2026-08-26) == */
/* ⛔ `.note` EXISTS BECAUSE `.cap` IS A PANEL, NOT A TEXT STYLE. `.cap` carries a
   background, a border, a 3px teal left accent and a 15px bottom margin -- it is the
   "What this tab is for" callout. The fire bar's labels and the pager were reusing it
   for a run of inline text, so each rendered as its own floating bordered box
   overlapping the table. Reusing a panel class for text is the defect; scoping
   overrides onto `.cap` would have hidden it rather than removed it.

   ⛔ AND THIS BLOCK WENT MISSING ONCE ALREADY. Its first version was appended behind a
   `'.note{' not in css` guard, which matched the UNRELATED `.gate .note{` rule and
   skipped the whole append -- and the substring greps used to verify the deploy matched
   `.aud-selflabel` and `.selfnote`, so it read as shipped. The markup moved to `.note`
   regardless, so the floating boxes did disappear, by accident rather than by design.
   Hence the sentinel comment above: a token that exists nowhere else. */
.note{font-size:11.5px;color:var(--muted);line-height:1.45}
.note b{color:var(--ink);font-family:var(--mono);font-weight:700}

/* The two Data-tab containers that previously had NO rules of their own, which is why
   their children fell back to whatever class they happened to borrow. */
.filters{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:0 0 11px}
.filters .flabel{font-size:10px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint);margin-right:3px;white-space:nowrap}

/* Separated from the table below: it was running straight into the header row. */
.fire-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 12px;
  margin:0 0 14px;background:var(--panel-2);border:1px solid var(--line-2);
  border-radius:8px}
/* ONLY the hint takes the free space. `.note` is on the "0 selected" label too, so a
   blanket rule made THAT grow and shoved the button into the middle of the bar. */
.fire-bar .note{flex:none}
.fire-bar #dataFireHint{flex:1 1 240px;min-width:0}

/* Fire-status filter pills. Kept as pills WITH their counts (Jason's call): the counts
   are the reason the filter exists at all -- "I want to investigate the high count of
   'No tour bound to this job'". They were inheriting `.chip`, the 96px-wide metric-card
   style, so they rendered as read-only stat tiles rather than controls. Scoped under
   `.filters` so the metric `.chip` elsewhere on the board is untouched. */
.filters .chip{min-width:0;display:inline-flex;align-items:center;gap:6px;
  padding:5px 10px 5px 11px;border-radius:999px;font-size:11.5px;font-weight:600;
  line-height:1.3;color:var(--muted);background:var(--panel-2);
  border:1px solid var(--line);cursor:pointer;min-height:27px;
  transition:background .12s,border-color .12s,color .12s}
.filters .chip:hover{border-color:var(--wire);color:var(--wire);background:var(--panel)}
.filters .chip:focus-visible{outline:2px solid var(--wire);outline-offset:2px}
.filters .chip.on{background:var(--wire);border-color:var(--wire);color:#fff}
/* The count sits in its own tinted capsule so the label and the number read as two
   things, not one run-on string. Tabular figures so the pills do not resize as counts
   change and reflow the row under the operator's cursor. */
.filters .chip .num{font-family:var(--mono);font-weight:700;font-size:11px;
  font-variant-numeric:tabular-nums;color:var(--muted);background:rgba(0,0,0,.055);
  border-radius:999px;padding:1px 6px;min-width:18px;text-align:center}
.filters .chip.on .num{color:#fff;background:rgba(255,255,255,.22)}
.filters .chip:hover .num{color:var(--wire)}
.filters .chip.on:hover .num{color:#fff}

/* Two-line filter layout (Jason, 2026-08-26). The multi-selects sit together on the
   second line; `size=1` keeps them the height of an ordinary control rather than an
   open list box, and the browser handles multi-selection natively. */
.data-multi{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--muted)}
.data-multi select{font-family:inherit;font-size:12px;color:var(--ink);
  background:var(--panel);border:1px solid var(--line);border-radius:7px;
  padding:5px 8px;min-height:30px;min-width:190px;max-width:280px}
.data-multi select:focus{outline:none;border-color:var(--wire)}

/* Pager: rows-per-page coupled to Prev/Next, rendered above AND below the table. */
.data-pagerow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px}
.data-pagerow + table{margin-top:0}
.data-pagerow .pagesize-lab{font-size:11px;color:var(--faint);margin-left:4px}
.data-pagerow .pagesize{font-family:inherit;font-size:12px;color:var(--ink);
  background:var(--panel);border:1px solid var(--line);border-radius:7px;padding:4px 7px;
  min-height:28px}

/* ⛔ THE FILTER SITS IN ITS OWN COLUMN HEADER. A separated bar drifts from its column by
   NAME -- a bar labelled "Status" filtered a column labelled "Card status", which is how
   the mismatch got shipped. A control inside its header cannot disagree with it. */
.th-f{white-space:nowrap;vertical-align:top}
.th-f select{display:block;margin-top:4px;font-family:inherit;font-size:11px;
  font-weight:400;color:var(--ink);background:var(--panel);border:1px solid var(--line);
  border-radius:6px;padding:3px 5px;min-height:24px;width:100%;min-width:104px;
  /* `text-transform:none` matters: the header cell uppercases its label, and without
     this the option text inherited it and read "0 SELECTED". */
  text-transform:none;letter-spacing:0}
.th-f select:focus{outline:none;border-color:var(--wire)}

/* Timezone field: wider than the number inputs beside it, an IANA name is not short. */
.tzedit{font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--panel);
  border:1px solid var(--line);border-radius:7px;padding:6px 9px;min-height:30px;width:170px}
.tzedit:focus{outline:none;border-color:var(--wire)}

/* ⛔ 194-FE. THE FIRE RESULT HAD NO CSS AT ALL -- `data-fire-result` and `data-fire-list`
   matched nothing in this file, so the browser's default `ul` bullets and margins rendered
   it as a bare list wedged against the pager. Jason's words: "badly formatted so that it
   looked like a bug not intentional". It looked like debug output because it WAS unstyled.
   It is a receipt for writes to live client cards, so it is styled as a result panel. */
.data-fire-result{position:relative;margin:10px 0 4px;padding:11px 34px 11px 13px;
  border:1px solid var(--line);border-left:3px solid var(--review);border-radius:8px;
  background:var(--card)}
.data-fire-result.allok{border-left-color:var(--pass)}
.data-fire-result.fail{border-left-color:var(--fail)}
.data-fire-close{position:absolute;top:6px;right:8px;width:22px;height:22px;padding:0;
  line-height:1;font-size:15px;cursor:pointer;color:var(--muted);
  background:transparent;border:1px solid transparent;border-radius:5px}
.data-fire-close:hover{color:var(--ink);border-color:var(--line)}
/* ⛔ NO BULLETS AND NO DEFAULT INDENT: that pair is what made it read as debug output. */
.data-fire-list{list-style:none;margin:7px 0 0;padding:0;display:grid;gap:3px}
.data-fire-list li{font-size:11.5px;line-height:1.45;color:var(--ink);
  padding-left:15px;position:relative}
/* ⛔ A PARTIAL BATCH IS EXACTLY WHEN THIS MATTERS, so written and not-written are told
   apart by a MARK as well as a colour -- an operator who cannot see the colour still has
   to be able to find the row that did not land. */
.data-fire-list li.ok::before{content:"\2713";position:absolute;left:0;color:var(--pass);font-weight:700}
.data-fire-list li.no::before{content:"\00d7";position:absolute;left:0;color:var(--fail);font-weight:700}
.data-fire-list li.no{color:var(--fail)}

