/* ===========================================================================
   Mel admin — design system.

   Visual language borrowed from the Mel5 operator console: near-black ground,
   hairline borders, a single green accent, and no rounded corners anywhere.
   Depth comes from a background ladder plus 1px rules — never from shadow.

   Three deliberate departures from the source:
     1. The fonts are actually loaded. Mel5 names Inter, IBM Plex Mono and
        Space Grotesk but ships none of them, so it silently falls back to
        system faces. Copying that stylesheet verbatim reproduces the bug
        rather than the design. They are self-hosted here, not pulled from a
        CDN — this panel should not report every page view to a third party.
     2. There is a responsive layer. The source has no viewport tag and not one
        media query. The owner will open this on a phone while pairing WhatsApp.
     3. Focus is visible and the accent passes contrast on buttons (dark text on
        accent, not white). The source fails both.
   ======================================================================== */

/* --- fonts ------------------------------------------------------------- */
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/admin/static/fonts/inter-400.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/admin/static/fonts/inter-500.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/admin/static/fonts/inter-600.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/admin/static/fonts/plexmono-400.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/admin/static/fonts/plexmono-500.woff2") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/admin/static/fonts/grotesk-500.woff2") format("woff2"); }

/* --- tokens ------------------------------------------------------------ */
:root {
  --bg:            #0b0b0c;
  --panel:         #15151a;
  --surface-alt:   #101015;
  --recessed:      #08080a;
  --border:        #262630;
  --border-strong: #34343f;
  --text:          #e8e6e3;
  --muted:         #9aa1a8;
  --accent:        #1d9e75;
  --accent-hover:  #0f6e56;
  --warn:          #e8b84e;
  --err:           #e87474;
  --in:            #7aa6e8;   /* inbound  */
  --out:           #9be8a8;   /* outbound */

  --ui:   "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --disp: "Space Grotesk", "Inter", sans-serif;

  --gap: 1rem;
  --max: 1400px;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* The three geometry rules that carry most of the character. */
*, button, input, select, textarea { border-radius: 0; }
* { box-shadow: none; }
@media (prefers-reduced-motion: no-preference) { * { transition: none; } }

h1, h2, h3 { font-family: var(--disp); font-weight: 500; letter-spacing: -0.01em; margin: 0 0 .5rem; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 .75rem; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

code, .mono, kbd { font-family: var(--mono); font-size: .86em; }

/* Every ID, timestamp and path is monospaced — the instrument-panel tell. */
.muted { color: var(--muted); }
.small { font-size: .82rem; }

/* The label tier. One rule, applied everywhere, does most of the work. */
.label, th, .kpi-label, .eyebrow {
  font-family: var(--mono);
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 500;
  color: var(--muted);
}

/* --- focus (absent in the source) --------------------------------------- */
:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- top bar ------------------------------------------------------------ */
.topbar {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
  padding: 0 1.25rem;
  min-height: 52px;
  flex-wrap: wrap;
}
.topbar .brand {
  font-family: var(--disp);
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--text);
  letter-spacing: .02em;
  padding: .85rem 0;
}
.topbar .brand:hover { color: var(--accent); text-decoration: none; }
.topbar .brand .dot { color: var(--accent); }

.topbar nav { display: flex; gap: .25rem; flex: 1; flex-wrap: wrap; }
.topbar nav a {
  color: var(--muted);
  font-size: .82rem;
  padding: .5rem .7rem;
  border: 1px solid transparent;
}
.topbar nav a:hover { color: var(--text); background: var(--panel); text-decoration: none; }
.topbar nav a.active {
  color: var(--accent);
  border-color: var(--border);
  background: var(--panel);
}

.topbar .session { display: flex; align-items: center; gap: .6rem; }
.topbar .session .who { font-family: var(--mono); font-size: .74rem; color: var(--muted); }
.topbar .session .account-link { color: var(--muted); font-size: .82rem; padding: .5rem .7rem;
                                 border: 1px solid transparent; }
.topbar .session .account-link:hover { color: var(--text); background: var(--panel); text-decoration: none; }
.topbar .session .account-link.active { color: var(--accent); border-color: var(--border); background: var(--panel); }

/* --- layout ------------------------------------------------------------- */
main { max-width: var(--max); margin: 0 auto; padding: 1.5rem 1.25rem 4rem; }

.page-head { margin-bottom: 1.25rem; }
.page-head .eyebrow { display: block; margin-bottom: .25rem; }

.row { display: flex; gap: var(--gap); flex-wrap: wrap; }
.col { flex: 1; min-width: 0; }
.grid { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

/* --- panel -------------------------------------------------------------- */
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 1.1rem 1.25rem;
  margin-bottom: var(--gap);
}
.panel > :last-child { margin-bottom: 0; }
.panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; margin-bottom: .85rem; flex-wrap: wrap;
}
.panel-head h2, .panel-head h3 { margin: 0; }
/* Tables sit flush inside their panel — the panel's own border is the frame. */
.panel.flush { padding: 0; }
.panel.flush .panel-head { padding: 1rem 1.25rem 0; margin-bottom: .75rem; }

/* --- KPI ---------------------------------------------------------------- */
.kpi {
  background: var(--panel);
  border: 1px solid var(--border);
  padding: .9rem 1rem;
}
.kpi-value {
  font-family: var(--disp);
  font-size: 1.6rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  display: block;
  margin-bottom: .3rem;
}
.kpi-value.ok   { color: var(--accent); }
.kpi-value.warn { color: var(--warn); }
.kpi-value.err  { color: var(--err); }
.kpi-label { display: block; }

/* --- tables ------------------------------------------------------------- */
/* Wide tables scroll in their own container so the page body never does. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { border-collapse: collapse; width: 100%; font-size: .86rem; }
th {
  text-align: left;
  background: var(--surface-alt);
  padding: .55rem .8rem;
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
}
td {
  padding: .6rem .8rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--surface-alt); }
td.mono, td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Empty states name the next action rather than saying "no data". */
.empty { color: var(--muted); text-align: right; font-size: .84rem; padding: 1rem .8rem; }

/* --- tags --------------------------------------------------------------- */
/* Semantics are explicit. The source overloaded one "open" class to mean
   thread-open, exit-ok, systemd-active and port-open all at once. */
.tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: .12rem .45rem;
  border: 1px solid var(--border-strong);
  color: var(--muted);
  white-space: nowrap;
}
.tag-ok      { color: var(--accent); border-color: var(--accent); }
.tag-warn    { color: var(--warn);   border-color: var(--warn); }
.tag-err     { color: var(--err);    border-color: var(--err); }
.tag-pending { color: var(--muted);  border-color: var(--border-strong); }
.tag-in      { color: var(--in);     border-color: var(--in); }
.tag-out     { color: var(--out);    border-color: var(--out); }

.dot-status { display: inline-block; width: .5rem; height: .5rem; margin-right: .4rem; background: var(--muted); }
.dot-status.ok  { background: var(--accent); }
.dot-status.err { background: var(--err); }

/* --- forms -------------------------------------------------------------- */
label { display: block; font-size: .84rem; margin-bottom: .9rem; }
label > .label { display: block; margin-bottom: .3rem; }

input[type=text], input[type=email], input[type=password], input[type=number],
select, textarea {
  width: 100%;
  background: var(--recessed);
  border: 1px solid var(--border-strong);
  color: var(--text);
  font-family: var(--mono);
  font-size: .86rem;
  padding: .5rem .6rem;
}
input:focus, select:focus, textarea:focus { border-color: var(--accent); }
input::placeholder { color: #5c6268; }
input[readonly] { color: var(--muted); }

.hint { font-size: .78rem; color: var(--muted); margin-top: .3rem; }

.btn {
  display: inline-block;
  font-family: var(--ui);
  font-size: .84rem;
  font-weight: 500;
  padding: .5rem 1rem;
  border: 1px solid var(--accent);
  background: var(--accent);
  /* Dark text on the accent, not white — white fails contrast at this hue. */
  color: #0b0b0c;
  cursor: pointer;
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; text-decoration: none; }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--border-strong); }
.btn-ghost:hover { background: var(--panel); color: var(--text); border-color: var(--accent); }
.btn-danger { background: transparent; color: var(--err); border-color: var(--err); }
.btn-danger:hover { background: var(--err); color: #0b0b0c; }
.btn:disabled { opacity: .45; cursor: not-allowed; }

.form-actions { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin-top: .25rem; }

/* --- alerts ------------------------------------------------------------- */
/* In the content flow, after a write. Never floating, never auto-dismissing. */
.alert {
  border: 1px solid var(--border-strong);
  border-left-width: 3px;
  background: var(--panel);
  padding: .8rem 1rem;
  margin-bottom: var(--gap);
  font-size: .88rem;
}
.alert-ok   { border-left-color: var(--accent); }
.alert-warn { border-left-color: var(--warn); }
.alert-err  { border-left-color: var(--err); color: var(--err); }
.alert pre { margin: .5rem 0 0; }

/* --- secrets ------------------------------------------------------------ */
/* A configured secret is never rendered, masked or revealed — only its
   presence is reported. The backend must never serialise the value either,
   or this is merely cosmetic. */
.secret-state { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.secret-name { font-family: var(--mono); font-size: .84rem; }

/* --- code / logs -------------------------------------------------------- */
pre, .code-block {
  background: var(--recessed);
  border: 1px solid var(--border);
  padding: .7rem .8rem;
  font-family: var(--mono);
  font-size: .78rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 50vh;
  overflow: auto;
  margin: 0;
}

/* --- numbered steps ----------------------------------------------------- */
/* Square counters, not circles — a radius here would break the language. */
.steps { list-style: none; padding: 0; margin: 0; display: grid; gap: .9rem; }
.step { display: grid; grid-template-columns: 1.65rem 1fr; gap: .75rem; align-items: start; }
.step-num {
  width: 1.65rem; height: 1.65rem;
  display: grid; place-items: center;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-family: var(--mono);
  font-size: .78rem;
}
.step-done .step-num { background: var(--accent); color: #0b0b0c; }
.step-body { padding-top: .1rem; }
.step-body strong { font-weight: 600; display: block; margin-bottom: .1rem; }

/* --- QR / pairing ------------------------------------------------------- */
.qr-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--gap); }
.qr-box {
  background: #fff;           /* a QR must be dark-on-light to scan reliably */
  padding: 1rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
}
.qr-box img { display: block; width: 100%; max-width: 300px; height: auto; }

/* --- auth --------------------------------------------------------------- */
.auth {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 1.25rem;
}
.auth-card { width: 100%; max-width: 340px; }
.auth-card .brand {
  font-family: var(--disp);
  font-size: 1.35rem;
  display: block;
  margin-bottom: .25rem;
}
.auth-card .brand .dot { color: var(--accent); }
.auth-card .btn { width: 100%; text-align: center; }

/* --- responsive (absent in the source) ---------------------------------- */
@media (max-width: 720px) {
  body { font-size: 14px; }
  main { padding: 1rem .85rem 3rem; }
  .topbar { padding: 0 .85rem; gap: .5rem; }
  .topbar nav { order: 3; width: 100%; border-top: 1px solid var(--border); padding: .35rem 0; }
  .topbar nav a { padding: .4rem .55rem; }
  .topbar .session { margin-left: auto; }
  .topbar .session .who { display: none; }
  .kpi-value { font-size: 1.35rem; }
  .step { grid-template-columns: 1.4rem 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* --- header switch ------------------------------------------------------ */
/* The stop switch sits in the header of every page, so it is never more than
   one click away and never needs looking for. The red band is the persistent
   signal: a floating badge would be the only moving thing in the product. */
.control-switch { display: flex; align-items: center; gap: .5rem; }
.stop-form { display: flex; gap: .35rem; align-items: center; }
.stop-reason { width: 9rem; font-size: .78rem; padding: .3rem .45rem; }
.is-stopped .topbar { border-top: 3px solid var(--err); }

/* --- brain chip --------------------------------------------------------- */
/* Whether the model server is answering, on every page. A word, not a colour
   alone: "unknown" (the probe has not answered yet) must not read as "down". */
.brain-chip { display: flex; align-items: center; padding: .25rem .5rem;
              border: 1px solid var(--border); color: var(--muted);
              font-family: var(--mono); font-size: .72rem; text-transform: uppercase;
              letter-spacing: .05em; white-space: nowrap; }
.brain-chip:hover { border-color: var(--border-strong); color: var(--text); text-decoration: none; }
.brain-chip.brain-up   { color: var(--text); }
.brain-chip.brain-down { border-color: var(--err); color: var(--err); }

/* Summed rows are ruled off rather than coloured — a sum, not a verdict. */
.totals td { border-top: 1px solid var(--border-strong); font-weight: 500; }
.sub-head { font-size: .95rem; margin: 1.1rem 0 .5rem; }

/* --- tool trace --------------------------------------------------------- */
/* One line per tool call: what ran, on what, how long, and the receipt when
   there is one. Arguments are masked by the writer, never here — a mask
   applied at render time is a mask that the next view forgets. */
.trace { list-style: none; margin: .5rem 0 0; padding: 0; display: grid; gap: .25rem; }
.trace-row { display: grid; grid-template-columns: 1.1rem 9rem 1fr 4rem;
             gap: .5rem; align-items: baseline; font-size: .78rem;
             border-left: 1px solid var(--border); padding-left: .55rem; }
.trace-row .t-tool { font-family: var(--mono); color: var(--text); }
.trace-row .t-args { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trace-row .t-dur  { font-family: var(--mono); font-variant-numeric: tabular-nums;
                     text-align: right; color: var(--muted); }
.trace-row.running .t-mark { color: var(--warn); }
.trace-row.ok      .t-mark { color: var(--accent); }
.trace-row.err     .t-mark, .trace-row.err .t-args { color: var(--err); }
/* A WhatsApp progress line: the code speaking for her while she worked. Muted
   and italic so the tape reads as steps she took plus asides she did not. */
.trace-row.progress .t-mark,
.trace-row.progress .t-tool,
.trace-row.progress .t-args { color: var(--muted); font-style: italic; }
/* A static character, not an animation: the stylesheet disables transitions
   globally and a blinking cursor would be the one moving thing here. */
.turn-live .turn-body::after { content: "▌"; color: var(--accent); }
.trace-expander summary { font-size: .78rem; color: var(--muted); cursor: pointer; }
.trace-slot { padding-top: .35rem; }

@media (max-width: 720px) {
  .stop-reason { display: none; }          /* the reason is optional; the switch is not */
  .trace-row { grid-template-columns: 1.1rem 1fr 3.5rem; }
  .trace-row .t-args { grid-column: 1 / -1; white-space: normal; }
}


/* --- learning ------------------------------------------------------------ */
/* Six panels of things she wrote. Everything here is read-only, so nothing is
   styled as a control: values are set in the recessed ground the code blocks
   use, and provenance reuses the contacts tier colours rather than inventing a
   second vocabulary for the same four words. */
.learning-memory td { vertical-align: top; }
.mem-value { margin: 0; background: var(--recessed); border: 1px solid var(--border);
             padding: .4rem .55rem; font-size: .76rem; max-height: 12rem; overflow: auto;
             white-space: pre-wrap; word-break: break-word; }
.soul-line { margin-bottom: .75rem; padding: 0 1.25rem; }
.dream-kpis { margin: .85rem 0; }
/* Her own wrap-up line, quoted rather than paraphrased. */
.dream-wrap { margin: .85rem 0 0; padding-left: .8rem; border-left: 2px solid var(--border-strong);
              color: var(--muted); }
.dream-history { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: .3rem;
                 font-size: .82rem; }
.lint-group { border-top: 1px solid var(--border); padding: .6rem 0; }
.lint-group summary { cursor: pointer; display: flex; align-items: baseline; gap: .5rem;
                      flex-wrap: wrap; }
.lint-hits { list-style: none; margin: .5rem 0 0; padding: 0 0 0 .8rem;
             border-left: 1px solid var(--border); display: grid; gap: .6rem; }
.lint-hits .preview { word-break: break-word; }

/* ===========================================================================
   Legacy class bridge.

   The views carried over from upstream use an older vocabulary (.card, .compact,
   .state-*, .cta ...). Rather than leave those pages half-styled, each legacy
   name is mapped onto the primitive it corresponds to. New markup should use the
   primitives above; this block exists so nothing renders unstyled in the interim.
   ======================================================================== */

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 1.1rem 1.25rem;
  margin-bottom: var(--gap);
}
.card > :last-child { margin-bottom: 0; }
.card h2 { font-size: 1rem; margin-bottom: .7rem; }

.grid.two { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid.full { grid-template-columns: 1fr; }

/* Dense label/value tables inside cards: no header row, so the first cell
   carries the label tier instead. */
table.compact { font-size: .84rem; }
table.compact td { padding: .35rem 0; border-bottom: 1px solid var(--border); }
table.compact tr:last-child td { border-bottom: 0; }
table.compact tr:hover td { background: transparent; }
table.compact td:first-child {
  color: var(--muted);
  font-family: var(--mono);
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding-right: 1rem;
  /* Wrap rather than nowrap: a unit name such as mel-gmail-bridge.service
     in uppercase mono is wider than half a 320px card, and with nowrap the
     whole table ran out of the card (Overview, 2026-09-10). */
  white-space: normal;
  overflow-wrap: anywhere;
}
table.compact td:nth-child(2) { white-space: nowrap; }
table.compact td + td + td { padding-left: .6rem; }
/* Grid children may shrink below their content width; without this a wide
   table inside a card forces the card past its column instead of wrapping. */
.grid > * { min-width: 0; }

/* State words rendered as bare text upstream. Give them the tag treatment so
   status reads at a glance instead of being one more grey string. */
[class*="state-"] {
  font-family: var(--mono);
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.state-open, .state-active, .state-running, .state-sent, .state-done, .state-ok { color: var(--accent); }
.state-qr, .state-reconnecting, .state-pending, .state-locked, .state-activating { color: var(--warn); }
.state-disconnected, .state-failed, .state-error, .state-inactive, .state-dead { color: var(--err); }
.state-init, .state-loading, .state-unknown { color: var(--muted); }

/* Message direction, mirroring the inbound/outbound tokens. */
.role-user, .role-in { color: var(--in); }
.role-assistant, .role-out { color: var(--out); }
.role-tag {
  font-family: var(--mono);
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .05em;
}

.error { color: var(--err); border-left: 3px solid var(--err); background: var(--panel);
         padding: .7rem .9rem; margin-bottom: var(--gap); font-size: .88rem; }
.warn  { color: var(--warn); }

/* Upstream's call-to-action link. Same affordance as .btn. */
.cta {
  display: inline-block;
  font-size: .84rem;
  font-weight: 500;
  padding: .45rem .9rem;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #0b0b0c;
}
.cta:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; text-decoration: none; }

.tabs { display: flex; gap: .25rem; border-bottom: 1px solid var(--border); margin-bottom: var(--gap); flex-wrap: wrap; }
.tabs a { padding: .45rem .8rem; color: var(--muted); font-size: .84rem; border: 1px solid transparent; border-bottom: 0; }
.tabs a:hover { color: var(--text); text-decoration: none; }
.tabs a.active { color: var(--accent); border-color: var(--border); background: var(--panel); }

.inline-form { display: inline; }
.inline-form button { font-size: .74rem; padding: .2rem .5rem; background: transparent;
                      border: 1px solid var(--border-strong); color: var(--muted); cursor: pointer; }
.inline-form button:hover { border-color: var(--accent); color: var(--accent); }

.preview { color: var(--muted); font-size: .82rem; }
.thread, .msg, .content { min-width: 0; }
.msg { border-bottom: 1px solid var(--border); padding: .6rem 0; }
.msg:last-child { border-bottom: 0; }

/* --- auth pages --------------------------------------------------------- */
/* The layout renders no wrapper when there is no session, so the card centres
   itself. Radius stays 0 here — the upstream login screen used rounded corners,
   which contradicted every other surface in the product. */
.auth-card {
  width: 100%;
  max-width: 340px;
  margin: 12vh auto 0;
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 1.5rem;
}
.auth-card h1 { font-size: 1.25rem; margin-bottom: 1rem; }
.auth-card button, .auth-card .btn { width: 100%; }
.auth-card > :last-child { margin-bottom: 0; }

/* Any button not explicitly given .btn still reads as a control. */
button:not(.btn):not(.inline-form button) {
  font-family: var(--ui);
  font-size: .84rem;
  font-weight: 500;
  padding: .5rem 1rem;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #0b0b0c;
  cursor: pointer;
}
button:not(.btn):not(.inline-form button):hover {
  background: var(--accent-hover); border-color: var(--accent-hover); color: #fff;
}

/* Collapsible reference blocks (the Google console checklist). Sharp, no marker
   rotation tricks — just a clear affordance. */
details > summary {
  cursor: pointer;
  list-style: none;
  padding: .2rem 0;
  color: var(--text);
  font-size: .95rem;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before { content: "▸ "; color: var(--accent); }
details[open] > summary::before { content: "▾ "; }
details > summary:hover { color: var(--accent); }

/* --- contacts ------------------------------------------------------------ */
/* The access tier is the only thing on this page worth colour. Everything else
   is an address, and addresses are for reading, not for ranking. */
.tier-operator { color: var(--in);     border-color: var(--in); }
.tier-trusted  { color: var(--accent); border-color: var(--accent); }
.tier-unknown  { color: var(--muted);  border-color: var(--border-strong); }
.tier-blocked  { color: var(--err);    border-color: var(--err); }

.filters {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gap); flex-wrap: wrap; margin-bottom: .85rem;
}
.tier-filter { display: flex; gap: .4rem; flex-wrap: wrap; }
.pill {
  font-family: var(--mono); font-size: .7rem; text-transform: uppercase;
  letter-spacing: .05em; padding: .25rem .55rem;
  border: 1px solid var(--border); color: var(--muted);
}
.pill:hover { border-color: var(--border-strong); text-decoration: none; }
/* The selected filter is filled, not merely tinted — at this size a border
   colour alone is not a strong enough "you are here". */
.pill.on { background: var(--surface-alt); border-color: currentColor; }

.count { opacity: .6; margin-left: .3rem; font-variant-numeric: tabular-nums; }

.search { display: flex; gap: .5rem; align-items: center; margin: 0; }
.search input[type=search] {
  width: 16rem; background: var(--recessed); border: 1px solid var(--border-strong);
  color: var(--text); font-family: var(--mono); font-size: .82rem; padding: .4rem .6rem;
}
.search input[type=search]:focus { border-color: var(--accent); }
.search .btn { padding: .4rem .8rem; }

.contacts td { vertical-align: top; }
.contacts .empty { text-align: left; }
.contacts .cname { font-weight: 500; }
.contacts .addr { font-family: var(--mono); font-size: .8rem; word-break: break-all; }
.contacts .num { text-align: right; font-variant-numeric: tabular-nums; }
.contacts .preview { max-width: 22rem; }
/* A blocked row should read as switched off without becoming unreadable — this
   is a list you scan to find the one you want to unblock. */
.contacts .row-blocked .cname, .contacts .row-blocked .addr { color: var(--muted); }

.contacts .actions { white-space: nowrap; text-align: right; }
.contacts .actions form { display: inline; }
.btn.tiny { padding: .2rem .5rem; font-size: .74rem; }

.contact-form { max-width: 900px; }
.contact-form textarea { font-family: var(--ui); }

/* The one question the panel cannot answer for itself. Marked with the accent
   rather than a warning colour: nothing is broken, something is unanswered. */
.setup-prompt { border-left: 3px solid var(--accent); }
.setup-prompt table { margin-top: .6rem; }
.setup-prompt .actions { text-align: right; white-space: nowrap; }
.setup-prompt .actions form { display: inline; }
.setup-prompt .actions .btn { padding: .3rem .7rem; font-size: .8rem; }

/* --- model page ---------------------------------------------------------- */
/* A hint inside a label is its own line under the control, as it is when it
   follows one. */
label > .hint { display: block; }

/* A checkbox is the one control that reads left-to-right, so it opts out of the
   block layout every other label uses. */
.check { display: flex; align-items: flex-start; gap: .55rem; margin: 1rem 0; }
.check input[type=checkbox] { width: auto; margin-top: .2rem; flex: none; }
.check > span { display: block; }
.check .hint { display: block; }

/* A secondary panel. One step down the background ladder rather than greyed
   out — it is not disabled, just not the main thing on the page. */
.panel.secondary { background: var(--surface-alt); }
.panel.secondary > summary { font-family: var(--disp); font-size: 1.05rem; }
.panel.secondary > summary .tag { margin-left: .5rem; }
.panel.secondary[open] > summary { margin-bottom: .85rem; }

.rule { border: 0; border-top: 1px solid var(--border); margin: 1.1rem 0; }

/* Files page. Everything else on it reuses the panel's existing classes. */
.file-preview img,
.file-preview audio,
.file-preview video { max-width: 480px; max-height: 320px; }
.file-abs { word-break: break-all; }
.origin-inferred { font-style: italic; }

/* ─── Workspaces ──────────────────────────────────────────────────────────── */

.ws-list .ws-slug { font-family: var(--mono, monospace); }

/* The file tree. Nesting comes from <details> elements the route emits as a
   flat open/close list, so the indent has to come from the element itself
   rather than from a per-row depth class. */
.ws-tree { font-size: .86rem; }
.ws-tree details { margin: .15rem 0; }
.ws-tree details > summary {
  cursor: pointer;
  padding: .2rem 0;
  font-family: var(--mono, monospace);
  color: var(--fg, inherit);
}
.ws-tree details details,
.ws-tree details > .ws-file { margin-left: 1.1rem; }

.ws-file {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .2rem 0;
  border-bottom: 1px solid var(--border, rgba(255,255,255,.06));
}
.ws-file:last-child { border-bottom: 0; }
.ws-file .ws-name { font-family: var(--mono, monospace); flex: 1 1 auto; min-width: 8rem; }
.ws-file .ws-meta { flex: 0 0 auto; white-space: nowrap; }
.ws-file .ws-actions { flex: 0 0 auto; display: flex; gap: .3rem; align-items: center; }
.ws-file .ws-actions form { display: inline; }
