/* CMC control site.
 *
 * Palette and type roles come from docs/control-plane.html so the site and the
 * architecture docs read as one system. No webfonts: this is the control
 * surface for a machine in a shop, and it must never wait on fonts.gstatic.com.
 *
 * Colour is semantic. One hue, one meaning:
 *   ok      green   the machine is permitting / a swipe was granted
 *   bad     red     locked, denied, failed
 *   accent  amber   attention, and the site's own chrome accent
 *   info    blue    an administrative fact, not a machine state
 *   over    violet  a human has overridden the machine's own rules
 * The first three are the colours of the real status lamps on the wall.
 */

:root {
  --bg:#EFF1F4; --surface:#FFFFFF; --surface-2:#E7EAEE; --sunk:#F6F7F9;
  --ink:#151A21; --ink-2:#3F4954; --muted:#6B7684; --line:#D6DBE2;
  --accent:#B26F12; --accent-ink:#8A5309; --accent-soft:#F7EEDC;
  --ok:#2C7A4F; --bad:#B93B31; --info:#2C6AA8; --over:#6B4FA8;
  --ok-soft:#E4F1E9; --bad-soft:#FAE6E4; --info-soft:#E3EDF7; --over-soft:#EEE9F7;
  --focus:#2C6AA8;
  --sign:"Barlow Condensed","Roboto Condensed","Liberation Sans Narrow",
         "Arial Narrow",system-ui,sans-serif;
  --body:"IBM Plex Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark) {
  :root:not([data-theme="light"]) {
    --bg:#0F131A; --surface:#161B23; --surface-2:#1D242E; --sunk:#12171E;
    --ink:#E3E8EE; --ink-2:#B2BCC8; --muted:#828D9C; --line:#29313C;
    --accent:#E8A33D; --accent-ink:#F0BC70; --accent-soft:#2A2013;
    --ok:#4FB380; --bad:#E4655A; --info:#5E9DD9; --over:#B08BE0;
    --ok-soft:#14251C; --bad-soft:#2A1715; --info-soft:#131F2C; --over-soft:#1E1830;
    --focus:#5E9DD9;
  }
}
:root[data-theme="dark"] {
  --bg:#0F131A; --surface:#161B23; --surface-2:#1D242E; --sunk:#12171E;
  --ink:#E3E8EE; --ink-2:#B2BCC8; --muted:#828D9C; --line:#29313C;
  --accent:#E8A33D; --accent-ink:#F0BC70; --accent-soft:#2A2013;
  --ok:#4FB380; --bad:#E4655A; --info:#5E9DD9; --over:#B08BE0;
  --ok-soft:#14251C; --bad-soft:#2A1715; --info-soft:#131F2C; --over-soft:#1E1830;
  --focus:#5E9DD9;
}

* { box-sizing:border-box; }
html, body { height:100%; }
body {
  margin:0; background:var(--bg); color:var(--ink);
  font:13.5px/1.5 var(--body); -webkit-font-smoothing:antialiased;
  display:flex; flex-direction:column; overflow:hidden;
}
[hidden] { display:none !important; }
:focus-visible { outline:2px solid var(--focus); outline-offset:2px; border-radius:3px; }
@media (prefers-reduced-motion:reduce) { *{transition:none!important; animation:none!important} }

.mono { font-family:var(--mono); font-variant-numeric:tabular-nums; }

/* ---------------------------------------------------------------- masthead */

.top {
  flex:0 0 auto; display:flex; align-items:stretch; gap:0;
  background:var(--surface); border-bottom:1px solid var(--line);
  padding-left:16px; min-height:50px;
}
.brand {
  display:flex; align-items:center; gap:9px; padding-right:18px;
  font-family:var(--sign); font-weight:700; font-size:19px;
  letter-spacing:.06em; color:var(--ink); white-space:nowrap;
}
.brand .rule { width:3px; height:17px; background:var(--accent); border-radius:1px; }
.brand small {
  font-family:var(--body); font-size:10.5px; font-weight:500; letter-spacing:.04em;
  color:var(--muted); text-transform:none;
}
@media (max-width:820px) { .brand small { display:none; } }

/* Tabs sit on the header's bottom rule and the active one breaks it, so the
   selected tab reads as continuous with the panel below -- browser-tab
   semantics, which everybody already knows how to read. */
.tabs { display:flex; align-items:stretch; gap:2px; margin-bottom:-1px; }
.tab {
  display:flex; align-items:center; gap:8px; padding:0 17px;
  font-family:var(--sign); font-size:15px; font-weight:600; letter-spacing:.045em;
  color:var(--muted); text-decoration:none; white-space:nowrap;
  border:1px solid transparent; border-bottom-color:var(--line);
  border-radius:5px 5px 0 0; background:transparent;
}
.tab:hover { color:var(--ink); background:var(--sunk); }
.tab[aria-current="page"] {
  color:var(--ink); background:var(--bg);
  border-color:var(--line); border-bottom-color:var(--bg);
  box-shadow:inset 0 2px 0 var(--accent);
}
.tab.planned { color:var(--muted); opacity:.72; }
.tab .badge {
  font-family:var(--body); font-size:9.5px; font-weight:600; letter-spacing:.03em;
  padding:1px 5px; border-radius:3px; background:var(--surface-2); color:var(--muted);
}
.top .spacer { flex:1 1 auto; }
.actions { display:flex; align-items:center; gap:8px; padding:0 14px 0 10px; }
.actions form { margin:0; display:flex; }

/* ------------------------------------------------------------ status pill */

.state {
  display:flex; align-items:center; gap:8px; padding:5px 13px 5px 10px;
  border-radius:100px; font-size:12.5px; font-weight:600; white-space:nowrap;
  background:var(--bad-soft); color:var(--bad); border:1px solid transparent;
}
.state.on   { background:var(--ok-soft);     color:var(--ok); }
.state.low  { background:var(--accent-soft); color:var(--accent-ink); }
.state.over { background:var(--over-soft);   color:var(--over); }
.lamp { width:8px; height:8px; border-radius:50%; background:currentColor; flex:0 0 auto; }
.state.over .lamp { animation:pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.25} }
.state .glyph { font-family:var(--mono); font-size:11px; opacity:.85; }

.meta { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--muted);
  white-space:nowrap; }
.meta .dot { width:6px; height:6px; border-radius:50%; background:var(--ok); }
.meta .dot.off { background:var(--bad); }

/* ---------------------------------------------------------------- controls */

button, input, textarea, select { font:inherit; color:var(--ink); }
button { cursor:pointer; }

.ghost {
  background:transparent; border:1px solid var(--line); color:var(--ink-2);
  border-radius:5px; padding:5px 11px; font-size:12px; white-space:nowrap;
}
.ghost:hover { color:var(--ink); border-color:var(--muted); background:var(--sunk); }
.ghost.icon { padding:5px 8px; font-family:var(--mono); }

.btn {
  padding:7px 14px; font-size:13px; font-weight:600; border-radius:5px;
  background:var(--ink); color:var(--bg); border:1px solid var(--ink);
}
.btn:hover { background:var(--ink-2); border-color:var(--ink-2); }
.btn:disabled { opacity:.45; cursor:default; }

.ovbtn {
  border:1px solid var(--over); color:var(--over); background:transparent;
  border-radius:5px; padding:5px 12px; font-size:12px; font-weight:600;
  white-space:nowrap;
}
.ovbtn:hover { background:var(--over-soft); }
.ovbtn.active { background:var(--over); color:var(--surface); }

input[type=text], input[type=password], input[type=search], input[type=email], textarea, select {
  background:var(--surface); border:1px solid var(--line); border-radius:5px;
  padding:7px 10px; width:100%;
}
input:focus, textarea:focus, select:focus {
  outline:none; border-color:var(--focus); box-shadow:0 0 0 3px color-mix(in srgb,var(--focus) 18%,transparent);
}
input::placeholder, textarea::placeholder { color:var(--muted); }
textarea { min-height:128px; resize:vertical; font-family:var(--mono); font-size:12.5px; }

.row { display:flex; gap:9px; align-items:center; margin-top:9px; }
.note { font-size:12px; color:var(--muted); flex:1; }
.note.bad { color:var(--bad); }
.note.ok  { color:var(--ok); }

/* ------------------------------------------------------------------ panels */

main { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }

.grid {
  flex:1 1 auto; min-height:0; display:grid; gap:1px; background:var(--line);
  grid-template-columns:minmax(270px,.85fr) minmax(360px,1.25fr) minmax(260px,.8fr);
}
.col { background:var(--bg); display:flex; flex-direction:column; min-height:0; min-width:0; }
.panel { display:flex; flex-direction:column; min-height:0; flex:1 1 auto; }
.panel + .panel { border-top:1px solid var(--line); }
.phead { flex:0 0 auto; display:flex; align-items:center; gap:9px; padding:11px 15px 7px; }
.ptitle {
  font-family:var(--sign); font-size:13px; font-weight:600; letter-spacing:.11em;
  text-transform:uppercase; color:var(--muted); white-space:nowrap;
}
.count {
  font-family:var(--mono); font-size:11px; font-variant-numeric:tabular-nums;
  color:var(--muted); background:var(--surface-2); padding:1px 6px; border-radius:3px;
}
.pbody { flex:1 1 auto; min-height:0; overflow-y:auto; padding:0 9px 12px; }
.pfixed { flex:0 0 auto; padding:0 15px 12px; }
input.search { margin:0 15px 8px; width:auto; }

/* ------------------------------------------------------------------- lists */

ul.list { list-style:none; margin:0; padding:0; }
ul.list li { display:flex; align-items:center; gap:10px; padding:6px 7px; border-radius:4px; }
ul.list li + li { margin-top:1px; }
li.pick { cursor:pointer; }
li.pick:hover { background:var(--surface); }
li.sel { background:var(--info-soft); box-shadow:inset 2px 0 0 var(--info); }
.cuid { font-family:var(--mono); font-size:12.5px; font-variant-numeric:tabular-nums; flex:0 0 auto; }
.who { color:var(--ink-2); flex:1 1 auto; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; font-size:12.5px; }
.who i { color:var(--muted); }
.when { color:var(--muted); font-size:11.5px; white-space:nowrap; flex:0 0 auto;
  font-family:var(--mono); font-variant-numeric:tabular-nums; }
.empty { padding:14px 8px; color:var(--muted); font-size:12.5px; }

.tag {
  font-family:var(--mono); font-size:9.5px; font-weight:500; letter-spacing:.04em;
  padding:2px 5px; border-radius:3px; flex:0 0 auto; width:78px; text-align:center;
  background:var(--surface-2); color:var(--muted);
}
.tag.GRANTED { background:var(--ok-soft); color:var(--ok); }
.tag.DENIED, .tag.ERROR, .tag.LOGIN_FAIL { background:var(--bad-soft); color:var(--bad); }
.tag.EXPIRED, .tag.REVOKED { background:var(--accent-soft); color:var(--accent-ink); }
.tag.LOGIN, .tag.RENAMED { background:var(--info-soft); color:var(--info); }
.tag.OVERRIDE_ON, .tag.OVERRIDE_OFF { background:var(--over-soft); color:var(--over); }

/* ------------------------------------------------------------ user detail */

.detail { padding:0 15px 13px; }
.dhead { display:flex; align-items:center; gap:10px; margin-bottom:11px; }
.dcuid { font-family:var(--mono); font-size:19px; font-weight:500; letter-spacing:.01em; }
.stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(88px,1fr));
  gap:7px; margin-bottom:13px; }
.stat { background:var(--surface); border:1px solid var(--line); border-radius:5px;
  padding:8px 10px; }
.stat b { display:block; font-family:var(--mono); font-size:17px; font-weight:500;
  font-variant-numeric:tabular-nums; }
.stat b.sm { font-size:12.5px; }
.stat span { font-family:var(--sign); font-size:11.5px; letter-spacing:.09em;
  text-transform:uppercase; color:var(--muted); }
.nameedit { display:flex; gap:8px; margin-bottom:13px; }
.nameedit input { flex:1; }

/* ----------------------------------------------------------------- banner */

.banner {
  flex:0 0 auto; display:flex; align-items:center; gap:10px;
  padding:8px 16px; font-size:12.5px; font-weight:500;
  background:var(--over-soft); color:var(--over);
  border-bottom:1px solid var(--line);
}
.banner.warn { background:var(--accent-soft); color:var(--accent-ink); }
.banner .glyph { font-family:var(--mono); }

/* ---------------------------------------------------------------- scroller */

::-webkit-scrollbar { width:9px; height:9px; }
::-webkit-scrollbar-thumb { background:var(--line); border-radius:5px;
  border:2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background:var(--muted); }

/* ------------------------------------------------------------ page shells */

.sheet { flex:1 1 auto; min-height:0; overflow-y:auto; }
.wrap { max-width:1180px; margin:0 auto; padding:26px 22px 60px; }
.wrap.wide { max-width:1500px; }

h1.page {
  font-family:var(--sign); font-weight:700; font-size:30px; letter-spacing:.01em;
  margin:0 0 6px; line-height:1.1;
}
p.lede { font-size:15px; color:var(--ink-2); max-width:64ch; margin:0 0 22px; }
.prose { max-width:64ch; }
.prose p { margin:0 0 13px; color:var(--ink-2); }
.prose h2 { font-family:var(--sign); font-weight:600; font-size:19px; letter-spacing:.02em;
  margin:26px 0 7px; color:var(--ink); }
.prose ul { margin:0 0 13px; padding-left:19px; color:var(--ink-2); }
.prose li { margin-bottom:6px; }
.prose code { font-family:var(--mono); font-size:.88em; background:var(--surface-2);
  padding:.1em .36em; border-radius:3px; }
.prose a { color:var(--accent-ink); }

.callout {
  border-left:3px solid var(--accent); background:var(--accent-soft);
  padding:13px 16px; margin:0 0 18px; border-radius:0 4px 4px 0; max-width:64ch;
}
.callout .lbl {
  display:block; margin-bottom:4px; font-family:var(--sign); font-weight:700;
  font-size:12.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--accent-ink);
}
.callout p { margin:0; color:var(--ink-2); }
.callout p + p { margin-top:8px; }
.callout.info { border-left-color:var(--info); background:var(--info-soft); }
.callout.info .lbl { color:var(--info); }

/* --------------------------------------------------------------- responsive */

/* Below this the panes stop being viewport-height panels that scroll
   internally and become a page that scrolls, or the lower panes get squeezed
   to nothing by the taller ones above them. */
@media (max-width:1080px) {
  html, body { height:auto; min-height:100%; }
  body { overflow:auto; }
  main, .grid, .sheet { flex:0 0 auto; }
  .sheet { overflow-y:visible; }
  .grid { grid-template-columns:1fr 1fr; }
  .panel { flex:0 0 auto; }
  .pbody { max-height:330px; }
}
@media (max-width:760px) {
  .grid { grid-template-columns:1fr; }
  .top { flex-wrap:wrap; align-items:center; padding:0 12px; min-height:0; }
  .brand { padding:10px 10px 10px 0; }
  .top .spacer { display:none; }
  .actions { flex:1 1 auto; flex-wrap:wrap; justify-content:flex-end;
    gap:7px; padding:8px 0; }
  .tabs { order:4; width:100%; overflow-x:auto; scrollbar-width:none;
    padding-top:2px; }
  .tabs::-webkit-scrollbar { display:none; }
  .tab { padding:7px 13px; }
  .wrap { padding:18px 14px 50px; }
  .lhead .modes { margin-left:0; }
  .seg .lbl { display:none; }
  .seg .lbln { display:block; }
  .masterbar { gap:14px 18px; }
}

/* ================================================================= lights */

.banner.inline { border:1px solid var(--line); border-radius:5px; margin-bottom:20px; }
.banner.inline a { color:inherit; }
.banner.inline code { font-family:var(--mono); font-size:.9em; }

.lhead { display:flex; align-items:flex-start; gap:20px; flex-wrap:wrap; }
.lhead .lede { margin-bottom:18px; }
.modes { display:flex; margin-left:auto; border:1px solid var(--line);
  border-radius:6px; overflow:hidden; background:var(--surface); }
.mode { border:0; background:transparent; padding:7px 16px; color:var(--muted);
  font-family:var(--sign); font-size:14px; font-weight:600; letter-spacing:.04em; }
.mode + .mode { border-left:1px solid var(--line); }
.mode[aria-selected="true"] { background:var(--ink); color:var(--bg); }

/* ---- the chain, drawn to scale ---- */

.chainbox { margin:0 0 26px; }
.chain {
  position:relative; height:52px; background:var(--sunk);
  border:1px solid var(--line); border-radius:5px; overflow:hidden;
}
.seg {
  position:absolute; top:0; bottom:0; display:flex; align-items:center;
  justify-content:center; overflow:hidden;
  border-right:1px solid color-mix(in srgb,var(--ink) 22%,transparent);
}
.seg:last-child { border-right:0; }
.seg .lbl {
  font-family:var(--sign); font-size:12.5px; font-weight:600; letter-spacing:.05em;
  color:#151A21; padding:0 6px; white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; text-shadow:0 1px 0 rgba(255,255,255,.35);
}
.seg.dark .lbl, .seg.dark .lbln { color:#F2F5F8; text-shadow:0 1px 2px rgba(0,0,0,.5); }
/* Six names do not fit on a phone; the number plus the ruler is enough to tell
   which block is which, and the cards below carry the names. */
.lbln { display:none; font-family:var(--mono); font-size:13px; color:#151A21; }
/* Not physically mounted: hatched, so "planned" is never mistaken for "off". */
.seg.absent {
  background-image:repeating-linear-gradient(135deg,
    color-mix(in srgb,var(--muted) 26%,transparent) 0 5px,
    transparent 5px 11px) !important;
}
.seg.absent .lbl, .seg.absent .lbln { color:var(--muted); text-shadow:none; }
.seg.off { opacity:.34; }
.seg.sel { box-shadow:inset 0 0 0 2px var(--focus); }

.chain.editing .seg { cursor:grab; }
.handle { position:absolute; top:0; bottom:0; width:11px; cursor:ew-resize; z-index:2; }
.handle::after {
  content:""; position:absolute; top:9px; bottom:9px; left:4px; width:3px;
  border-radius:2px; background:var(--ink); opacity:.55;
}
.handle:hover::after, .handle.live::after { opacity:1; background:var(--focus); }
.handle.l { left:-5px; } .handle.r { right:-5px; }

.ruler { position:relative; height:16px; margin-top:4px; }
.ruler span {
  position:absolute; top:0; transform:translateX(-50%);
  font-family:var(--mono); font-size:10.5px; color:var(--muted);
}
.ruler span:first-child { transform:none; }
.ruler span:last-child { transform:translateX(-100%); }

/* ---- master bar ---- */

.masterbar {
  display:flex; align-items:center; gap:22px; flex-wrap:wrap;
  background:var(--surface); border:1px solid var(--line); border-radius:6px;
  padding:14px 18px; margin-bottom:8px;
}
.power {
  display:flex; align-items:center; gap:10px; padding:8px 16px 8px 9px;
  border:1px solid var(--line); border-radius:100px; background:var(--sunk);
  font-size:13.5px; font-weight:600; color:var(--muted); white-space:nowrap;
}
.power .knob {
  width:26px; height:15px; border-radius:100px; background:var(--line);
  position:relative; flex:0 0 auto;
}
.power .knob::after {
  content:""; position:absolute; top:2px; left:2px; width:11px; height:11px;
  border-radius:50%; background:var(--surface); transition:left .14s ease;
}
.power[aria-pressed="true"] { color:var(--ok); border-color:var(--ok); background:var(--ok-soft); }
.power[aria-pressed="true"] .knob { background:var(--ok); }
.power[aria-pressed="true"] .knob::after { left:13px; }

.slab { flex:1 1 260px; min-width:220px; }
.slab-h { display:flex; align-items:baseline; gap:10px; margin-bottom:5px; }
.slab-h b { font-size:14px; }

.draw { text-align:right; white-space:nowrap; }
.draw b { display:block; font-size:26px; font-weight:500; line-height:1.05;
  font-family:var(--mono); font-variant-numeric:tabular-nums; }
.draw span { font-family:var(--sign); font-size:12px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); }

input[type=range] { -webkit-appearance:none; appearance:none; width:100%;
  height:20px; background:transparent; }
input[type=range]::-webkit-slider-runnable-track { height:5px; border-radius:3px;
  background:var(--surface-2); }
input[type=range]::-moz-range-track { height:5px; border-radius:3px; background:var(--surface-2); }
input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none;
  width:15px; height:15px; margin-top:-5px; border-radius:50%;
  background:var(--ink); border:2px solid var(--surface); }
input[type=range]::-moz-range-thumb { width:15px; height:15px; border-radius:50%;
  background:var(--ink); border:2px solid var(--surface); }
input[type=range]:disabled { opacity:.4; }

/* ---- scenes ---- */

.scenes { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:6px; }
.scene {
  display:flex; align-items:center; gap:9px; padding:7px 14px 7px 8px;
  border:1px solid var(--line); border-radius:5px; background:var(--surface);
  font-size:13px; font-weight:500; color:var(--ink-2);
}
.scene:hover { border-color:var(--muted); }
.scene[aria-pressed="true"] { border-color:var(--ink); color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink); }
.swatch { display:flex; width:22px; height:22px; border-radius:4px; overflow:hidden;
  border:1px solid color-mix(in srgb,var(--ink) 18%,transparent); flex:0 0 auto; }
.swatch i { flex:1; }

/* ---- segment cards ---- */

.segs { display:grid; gap:10px; margin-bottom:6px;
  grid-template-columns:repeat(auto-fill,minmax(290px,1fr)); }
.card { background:var(--surface); border:1px solid var(--line); border-radius:6px;
  padding:13px 15px 15px; }
.card.absent { background:var(--sunk); }
.card-h { display:flex; align-items:center; gap:9px; margin-bottom:11px; }
.card-h .nm { font-family:var(--sign); font-size:16px; font-weight:600;
  letter-spacing:.03em; flex:1 1 auto; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.card-h .rng { font-family:var(--mono); font-size:11px; color:var(--muted); }
.chip { font-family:var(--sign); font-size:11.5px; font-weight:600; letter-spacing:.08em;
  text-transform:uppercase; padding:2px 6px; border-radius:3px;
  background:var(--surface-2); color:var(--muted); }

.field { margin-bottom:10px; }
.field:last-child { margin-bottom:0; }
.field label { display:block; font-family:var(--sign); font-size:12px;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted); margin-bottom:4px; }
.field .inline-h { display:flex; align-items:baseline; justify-content:space-between; }
.field .inline-h label { margin-bottom:0; }
.field .inline-h b { font-family:var(--mono); font-size:12.5px; font-variant-numeric:tabular-nums; }
.duo { display:flex; gap:9px; }
.duo > * { flex:1; min-width:0; }

.colorbox { display:flex; gap:8px; align-items:center; }
.colorbox .dab { width:34px; height:34px; border-radius:5px; flex:0 0 auto;
  border:1px solid color-mix(in srgb,var(--ink) 20%,transparent); }
.colorbox input { font-family:var(--mono); font-size:12.5px; }

.togglerow { display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:11px;
  padding-top:11px; border-top:1px solid var(--line); }
.check { display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--ink-2); }
.check input { width:auto; }

/* ---- configure table ---- */

.cfg { display:flex; flex-direction:column; gap:8px; max-width:900px; }
.cfgrow {
  display:grid; gap:10px; align-items:end;
  grid-template-columns:minmax(150px,1fr) 88px 88px auto auto auto;
  background:var(--surface); border:1px solid var(--line); border-radius:6px;
  padding:11px 14px;
}
.cfgrow.absent { background:var(--sunk); }
.cfgrow .field { margin:0; }
@media (max-width:820px) {
  .cfgrow { grid-template-columns:1fr 1fr; }
  .cfgrow .wide2 { grid-column:1 / -1; }
  .masterbar { gap:14px; }
  .draw { text-align:left; }
}

/* ------------------------------------------------------------- printers */
/* The Printers tab. Colour is semantic here as everywhere else: green means
 * the job is authorized, red means it is not and something will happen about
 * it, amber means attention -- nothing is being enforced. Grey is `unknown`,
 * which is the verdict that never acts and so must never look alarming.
 *
 * The shell is the Laser tab's: a full-height .grid of .col panels that
 * scroll on their own. Machines on the left, access on the right.
 *
 * One vertical scale inside a card: 6px within a block, 10px between
 * blocks. */

.chip.ok   { background:var(--ok-soft);   color:var(--ok); }
.chip.bad  { background:var(--bad-soft);  color:var(--bad); }
.chip.warn { background:var(--accent-soft); color:var(--accent-ink); }
.chip.info { background:var(--info-soft); color:var(--info); }
.chip.over { background:var(--over-soft); color:var(--over); }
.chip.dim  { background:var(--surface-2); color:var(--muted); }
/* A chip is a label, not a sentence: "Not authorized" on two lines reads as
   two chips. */
.chip { white-space:nowrap; flex:0 0 auto; }

/* ---- the shell: two columns, machines wider than access ---- */
.grid.two { grid-template-columns:minmax(0,1.35fr) minmax(360px,1fr); }
.panel.fixed { flex:0 0 auto; }
/* The roster is as tall as its names, up to about a quarter of the screen;
   the decision log, which is read far more often, takes the rest. */
.panel.roster { flex:0 1 auto; }
.panel.roster .pbody { max-height:26vh; }
.panel.decisions { flex:1 1 0; container-type:inline-size; }
.psum { flex:0 0 auto; margin:-2px 15px 10px; }
.panel.printers { container-type:inline-size; }

/* The header pill that says whether the shop is enforcing. It is a link to
   Settings, not a switch. */
a.state { text-decoration:none; }
a.state:hover { box-shadow:inset 0 0 0 1px currentColor; }
/* That pill makes this tab's header the widest in the site, so the brand's
   subtitle gives way sooner here than on the other tabs. */
@media (max-width:1000px) { body[data-tab="printers"] .brand small { display:none; } }
/* The last few pixels before the header wraps: the pill keeps its state and
   drops the word "Printers", which the active tab already says. */
@media (760px < width <= 820px) {
  #enfpill .pfx { display:none; }
  #enfpillTxt { display:inline-block; }
  #enfpillTxt::first-letter { text-transform:uppercase; }
}

/* ---- folded panels: the explainer and Settings ---- */
.fold > summary {
  display:flex; align-items:center; gap:9px; padding:11px 15px; cursor:pointer;
  list-style:none; user-select:none;
}
.fold > summary::-webkit-details-marker { display:none; }
.fold > summary::before {
  content:""; width:0; height:0; flex:0 0 auto;
  border-left:5px solid var(--muted); border-top:4px solid transparent;
  border-bottom:4px solid transparent; transition:transform .12s ease;
}
.fold[open] > summary::before { transform:rotate(90deg); }
.fold > summary:hover .ptitle { color:var(--ink-2); }
.foldbody { padding:0 15px 14px; }
.foldbody.prose { max-height:40vh; overflow-y:auto; }
.foldbody.prose p { font-size:12.5px; }

.setrow { display:flex; align-items:flex-start; gap:12px 16px; flex-wrap:wrap;
  background:var(--surface); border:1px solid var(--line); border-radius:6px;
  padding:11px 13px; }
.setlbl { flex:1 1 240px; min-width:0; }
.setlbl > b { font-size:13px; }
.setlbl .note { display:block; margin:3px 0 0; line-height:1.45; }
.setlbl .note b { color:var(--ink-2); }
#enfnote b { color:var(--accent-ink); }
.setrow .ghost { flex:0 0 auto; padding:6px 12px; }

/* ---- printers: one row each, every row the same shape ----
   Columns: machine | what is printing | verdict | progress | cancel. */

.plist { background:var(--surface); border:1px solid var(--line); border-radius:6px;
  margin:0 6px; }
.plist > .empty { margin:0; }
.pr {
  display:grid; align-items:center; gap:6px 16px; min-height:72px; padding:11px 16px;
  grid-template-columns:minmax(100px,130px) minmax(0,1fr) 130px 150px 64px;
  grid-template-areas:"id job v prog x";
}
.pr + .pr { border-top:1px solid var(--line); }
.pr.stale { background:var(--sunk); }
.pr-id { grid-area:id; display:flex; flex-direction:column; min-width:0; }
.pr-nm { font-family:var(--sign); font-size:16px; font-weight:600; letter-spacing:.03em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pr-sub { font-size:11.5px; color:var(--muted); white-space:nowrap; }
.pr-sub .bad { color:var(--bad); }
.pr-ams { display:flex; flex-wrap:wrap; gap:3px; margin-top:4px; }
.pr-ams i { width:10px; height:10px; border-radius:50%; box-shadow:inset 0 0 0 1px var(--line); }
.pr-ams i.vacant { background:none; box-shadow:inset 0 0 0 1px var(--muted); opacity:.5; }
.pr-job { grid-area:job; display:flex; flex-direction:column; gap:1px; min-width:0; }
.pr-title { font-size:13.5px; font-weight:500; color:var(--ink); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.pr-file { font-size:11.5px; color:var(--muted); overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }
.pr-none { font-size:12.5px; color:var(--muted); }
.pr-v { grid-area:v; display:flex; flex-wrap:wrap; align-items:center; gap:4px; }
.pr-prog { grid-area:prog; min-width:0; }
.pr-prog-h { display:flex; align-items:baseline; justify-content:space-between; gap:8px;
  font-size:11.5px; color:var(--muted); margin-bottom:5px; }
.pr-prog-h b { font-size:12.5px; font-weight:500; color:var(--ink); }
.pr-x { grid-area:x; display:flex; justify-content:flex-end; }

/* ---- sending a print: a form in the Settings register ---- */
.sendf { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr) 84px; gap:10px 14px;
  align-items:start; }
.sendf .span2 { grid-column:span 2; }
.sendf .field { margin:0; min-width:0; }
.sendf .wide2 { grid-column:1 / -1; }
.sendf .row { margin-top:0; }
.sendf .note { margin:0; line-height:1.45; }
.sendf .note b { color:var(--ink-2); }
.sendf .warnt, .sendf .warnt b { color:var(--accent-ink); }
#send { container-type:inline-size; }
.sendf input[type=number] { width:100%; background:var(--surface); border:1px solid var(--line);
  border-radius:5px; padding:7px 10px; }
.sendf input[type=file] { width:100%; font-size:12.5px; color:var(--ink-2); }
.sendf input[type=file]::file-selector-button {
  font:inherit; margin-right:10px; padding:5px 11px; border-radius:5px; cursor:pointer;
  background:transparent; border:1px solid var(--line); color:var(--ink-2); }
.sendf input[type=file]::file-selector-button:hover { border-color:var(--muted); color:var(--ink); }
/* Once the file has reached the Pi there is nothing to measure until the
   printer answers, so the bar says "working" instead of standing still. */
.sendbar { grid-column:1 / -1; }
.sendbar.wait i { width:30% !important; animation:sendwait 1.1s ease-in-out infinite alternate; }
@keyframes sendwait { from { margin-left:0; } to { margin-left:70%; } }
@container (max-width:520px) {
  .sendf { grid-template-columns:minmax(0,1fr) 84px; }
  .sendf .f-printer, .sendf .f-netid { grid-column:1 / -1; }
  .sendf .f-file { grid-column:1; }
}

/* Progress. Deliberately flat -- it is information, not decoration. */
.bar { height:6px; border-radius:3px; background:var(--surface-2); overflow:hidden; }
.bar i { display:block; height:100%; background:var(--info); }

.ghost.danger { color:var(--bad); border-color:color-mix(in srgb,var(--bad) 40%,transparent); }
.ghost.danger:hover:not(:disabled) { color:var(--surface); background:var(--bad); border-color:var(--bad); }
.ghost:disabled { opacity:.4; cursor:default; }
.ghost.sm, .btn.sm { padding:3px 8px; font-size:12px; }

.dim { color:var(--muted); }
.sm { font-size:11.5px; }

ul.list .nid { font-size:12.5px; flex:0 0 64px; }
ul.list .rname { flex:1 1 auto; min-width:0; font-size:12.5px; color:var(--ink-2);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
ul.list .rname i { color:var(--muted); }
#roster li { gap:12px; padding:5px 7px; }
#roster li:not(.empty):hover { background:var(--sunk); }
#roster .ghost { opacity:.75; }
#roster li:hover .ghost { opacity:1; }

/* The decision log is a log viewer: fixed time and verdict columns, so the
   eye runs down the verdicts; the job on one line and who judged it on the
   next. Rows are grouped under a day. */
#log { display:grid; grid-template-columns:max-content max-content minmax(0,1fr);
  column-gap:10px; }
#log li { grid-column:1 / -1; }
#log li.dec { display:grid; grid-template-columns:subgrid; align-items:start;
  gap:0 10px; padding:6px 7px; border-radius:4px; }
#log li.dec + li.dec { border-top:1px solid color-mix(in srgb,var(--line) 60%,transparent);
  border-radius:0; }
#log li.dec:hover { background:var(--sunk); }
@supports not (grid-template-columns:subgrid) {
  #log li.dec { grid-template-columns:5em 8.8em minmax(0,1fr); }
}
#log li.day {
  display:block; padding:12px 7px 4px; font-family:var(--sign); font-size:12px;
  font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
}
#log li.day:first-child { padding-top:2px; }
#log .when { padding-top:1px; }
.dv { display:flex; flex-direction:column; align-items:flex-start; gap:3px; }
.dm { display:flex; flex-direction:column; gap:2px; min-width:0; }
#log .jobname { font-size:12.5px; color:var(--ink); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.dsub { display:flex; align-items:center; gap:6px; min-width:0; font-size:11.5px;
  color:var(--muted); }
.dsub b { font-weight:600; color:var(--ink-2); flex:0 0 auto; }
.dsub .chip { font-size:10.5px; padding:0 5px; }
.dsub .reason { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.panel.roster textarea { min-height:84px; }

/* The cards are the page's main content and flow at every width; only the
   lists cap. The shared <=1080 rule caps every .pbody, so it is undone here. */
@media (max-width:1080px) {
  .grid.two { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
  #pbody-printers { max-height:none; }
  .panel.roster, .panel.decisions { flex:0 0 auto; }
  .panel.roster .pbody { max-height:330px; }
  .panel.decisions .pbody { max-height:440px; }
}
@media (max-width:760px) {
  .grid.two { grid-template-columns:minmax(0,1fr); }
  .plist { margin:0; }
}
/* A narrow column (a phone, or the two-column page at tablet width) cannot
   hold five columns, so a row folds to three lines: machine and verdict,
   then the job, then progress and cancel. */
@container (max-width:760px) {
  .pr {
    grid-template-columns:minmax(0,1fr) max-content 64px;
    grid-template-areas:"id v v" "job pct x" "bar bar bar";
    gap:6px 12px; min-height:94px; align-content:center;
  }
  .pr-id { flex-direction:row; align-items:baseline; gap:8px; }
  /* The name is the one thing that must survive; the AMS dots stay on one line. */
  .pr-nm { flex-shrink:0; }
  .pr-ams { flex-wrap:nowrap; margin-top:0; align-self:center; }
  .pr-file { display:none; }
  .pr-v { justify-content:flex-end; }
  .pr-prog { display:contents; }
  .pr-prog-h { grid-area:pct; margin:0; gap:8px; }
  .pr-prog .bar { grid-area:bar; }
}
/* In a narrow column the verdict column would leave the job name a hundred
   pixels, so a row stacks: when and what was decided, then the job, then
   why. Keyed on the panel's width, not the window's. */
@container (max-width:480px) {
  #log { display:block; }
  #log li.dec { display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; }
  #log li.dec .dv { flex-direction:row; align-items:center; gap:6px; }
  #log li.dec .dm { flex:1 0 100%; }
}

/* Tiers: admin-only controls are rendered hidden for eboard. Author `display`
   rules would otherwise beat the hidden attribute. The server's 403 is the
   real gate; this only spares eboard a button that cannot work. */
.admin-only[hidden] { display: none !important; }
.whoami { font-size: 12px; color: var(--muted, inherit); text-transform: uppercase; letter-spacing: .06em; }

/* Printers -> Settings -> Bambu cloud: the re-login form. It sits under the
   enforcement row; the fields swap for a code field when Bambu wants one. */
.cloudrow { margin-top:14px; padding-top:14px; border-top:1px solid var(--line, rgba(127,127,127,.25)); }
.cloudrow .setlbl > .chip { margin-left:6px; vertical-align:1px; }
.cloudf { flex:1 1 240px; min-width:0; display:flex; flex-direction:column; gap:8px; }
.cloudf .field { margin:0; }
.cloudf .field[hidden], .cloudf .ghost[hidden] { display:none; }
.cloudf input { width:100%; box-sizing:border-box; }
.cloudf .row { margin-top:2px; flex-wrap:wrap; }
.cloudf .note { overflow-wrap:anywhere; }

/* Printers: blocks whose visibility follows printerd's reported policy, and
   the shelved Send-a-print fold. `hidden` must win over panel/fold display. */
#sendpanel[hidden], .foldbody[data-policy][hidden], .rosterrule[hidden] { display:none !important; }
.rosterrule { margin:0 15px 10px; line-height:1.45; color:var(--accent-ink); }
#rosteredit[hidden], #roster[hidden] { display:none !important; }

/* Under the current readout: says the frame is being scaled to the supply. */
.drawnote { display:block; max-width:22em; margin-top:4px; font-size:12px;
  line-height:1.3; color:var(--muted); white-space:normal; }

/* The device is a by-id path with no spaces; on a phone it pushed the page
   wider than the screen. Let it break anywhere. */
#chainsum { overflow-wrap:anywhere; }
