/* ============================================================
   NEO UI — black & white only. No header, no footer.
   Splash: black bg, yellow Bugonia logo (Kabisat), every load.
   ============================================================ */

@font-face{
  font-family:'Kabisat';
  src:url('/fonts/kabisat-demo.italic-tall.ttf') format('truetype');
  font-weight:normal;font-style:normal;font-display:swap;
}

:root{
   --bg:#0a0a0a;
   --fg:#e7e7e7;
   --p1:#0f0f0f;
   --p2:#141414;
   --p3:#1a1a1a;
   --line:#181818;
   --line2:#333;
   --dim:#4e4e4e;
   --muted:#8f8f8f;
   --hover:#101010;
   --yellow:#e7e7e7;
   --up:#e7e7e7;
/* tile transparency: fixed 25% background paint over the wallpaper */
   --tile-op:25;
    /* detail cards: 78% opaque + darker than the theme bg — solid enough to
       read over any wallpaper, dark enough to sit apart from console tiles.
       color-mix var(--bg) 78% + black 22%; light theme mixes toward black
       instead so cards still read darker than its white bg. */
    --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
   /* family accents: value color + label color + tinted box background */
   --c-teal:#4fa89b;   --c-teal-dim:#5c5c5c;
   --c-amber:#b39455;  --c-amber-dim:#8a6d2b;
   --c-magenta:#b06f8e; --c-magenta-dim:#8a5c6d;
   --c-blue:#7290c9;   --c-blue-dim:#5c6d8a;
   --c-green:#5fae7d;  --c-red:#c9776e; --c-red-dim:#8a5c5c;
   /* Category colors: Jobs (blue-green), People (warm), System (cool), Settings (neutral) */
   --gA:#0c0c0c;  /* Job counters - teal tint */
   --gB:#0e0e0e;  /* Scanning/monitoring - amber tint */
   --gC:#0c0c0c;  /* People & data - magenta tint */
   --gD:#0e0e0e;  /* System - blue tint */
   --gE:#0a0a0a;  /* Settings splits - neutral */
   /* Motion: one scale, one vocabulary for the whole app. Durations sit on
      the ~150ms responsiveness baseline and grow one step per distance
      travelled. Every curve decelerates — no bounce, no elastic, they read
      as toys. Movement is transform/opacity only, never layout. */
   --t1:.12s;                            /* press, tactile feedback */
   --t2:.2s;                             /* hover, focus, small state */
   --t3:.34s;                            /* tab panes, cards, menus */
   --t4:.5s;                             /* page content, coverflow travel */
   --t5:.62s;                            /* splash beat */
   --ease:cubic-bezier(.22,1,.36,1);     /* house curve: quick out, long settle */
   --ease-soft:cubic-bezier(.4,0,.2,1);  /* symmetric, for state swaps */
   --mono:ui-monospace,'SF Mono','Cascadia Mono','Roboto Mono',Menlo,Consolas,monospace;
 }
 html[data-theme="light"]{
   --bg:#fff;
   --fg:#000;
   --p1:#f5f5f5;
   --p2:#ececec;
   --p3:#e2e2e2;
   --line:#e4e4e4;
   --line2:#bdbdbd;
   --dim:#8a8a8a;
   --muted:#5f5f5f;
   --hover:#f2f2f2;
   --card:#f7f7f7;
   --c-teal:#5a8a84;   --c-teal-dim:#5c8a85;
   --c-amber:#997443;  --c-amber-dim:#8a6d2b;
   --c-magenta:#9c5f7a; --c-magenta-dim:#8a5c6d;
   --c-blue:#5f7ab8;   --c-blue-dim:#5c6d8a;
   --c-green:#4f8a63;  --c-red:#b05c52; --c-red-dim:#8a5c5c;
   --gA:#f4f7f7;  /* Job counters - teal tint */
   --gB:#f7f5f0;  /* Scanning/monitoring - amber tint */
   --gC:#f7f4f7;  /* People & data - magenta tint */
   --gD:#f3f5f8;  /* System - blue tint */
   --gE:#f6f6f6;  /* Settings splits - neutral */
 }

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  background:var(--bg);
  color:var(--fg);
  font:12px/1.45 var(--mono);
  overflow:hidden;
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
input,textarea,select{
  font:12px var(--mono);color:var(--fg);background:var(--p1);
  border:1px solid var(--line);border-radius:0;padding:6px 8px;outline:none;
}
input:focus,textarea:focus,select:focus{border-color:var(--line2)}
textarea{resize:vertical}
::placeholder{color:var(--dim)}
h2{font:600 13px var(--mono);letter-spacing:.06em;text-transform:uppercase}
h3{font:10px var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--dim)}

/* ---------- splash: every refresh, on the page's own background ----------
   Was hardcoded #000, which meant a white or sepia theme flashed a black
   screen. It now takes the theme's --bg and --fg, so the loading screen is
   the same surface the page will be. */
#splash{
  position:fixed;inset:0;z-index:1000;background:var(--bg);
  display:grid;place-items:center;
  overflow:hidden;
  transition:opacity var(--t4) var(--ease-soft),transform var(--t4) var(--ease-soft);
}
#splash.off{opacity:0;pointer-events:none;transform:scale(1.02)}
#splash .mark{
  color:var(--fg);
  font-size:clamp(30px,6vw,84px);
  line-height:1.6;
  padding:.1em .64em .25em .25em;
}
/* the wordmark settles in: fade plus a short rise. Never a pop from
   scale(0) — the mark starts close to its own size and eases home. */
@media (prefers-reduced-motion:no-preference){
  #splash .mark{animation:mark-in var(--t5) var(--ease) both}
}
@keyframes mark-in{from{opacity:0;transform:scale(.94) translateY(6px)}to{opacity:1;transform:none}}

/* ---------- console: simbio view ----------
   Centered column (max 760px): back link, small-caps tab row, one hero
   number, one ledger table, quiet footer. Perfect symmetry: every
   element centered, single hairline language, no tints, no pictures. */
#home{position:fixed;inset:0;display:flex;flex-direction:column;background:var(--bg);overflow:hidden}
#home[hidden]{display:none}
/* console = lobby backdrop: solid var(--bg), no image, no glass */
.console-shell,.console-foot{position:relative;z-index:1}
.console-inner{background:none}
.console-score,.console-upd,table.console-table td{text-shadow:none}
/* corner logo: home's top-right wordmark, mirrored top-LEFT on every other
   page — same Kabisat, same size, same vertical line — and it links home.
   Hidden while the lobby (home) is the active view. Vertically centered on
   the dock: the anchor stretches the dock's full height (top:14px + its
   own height) so the wordmark's midpoint always matches the dock's. */
:root{--dock-h:37px}
.corner-home{display:none;position:fixed;left:16px;top:14px;z-index:60;height:var(--dock-h);
  align-items:center;text-decoration:none;color:inherit;cursor:pointer}
#lobby[hidden]~.corner-home{display:inline-flex}
.corner-home .lobby-logout-logo{line-height:var(--dock-h)}
.corner-home:focus-visible{outline:1px solid var(--fg);outline-offset:2px}
.console-foot{background:transparent}
.console-shell{flex:1;min-height:0;overflow-y:auto;width:100%;
  display:flex;flex-direction:column;align-items:safe center;
  justify-content:safe start}
.console-inner{width:100%;max-width:1200px;padding:26px 28px 24px;font-size:12px;font-variant-numeric:tabular-nums}
/* console carousel: one card per destination, sized exactly like the scanner
   wheel (base .tw-card). A card is a headline number over the section name
   and nothing more — the breakdown belongs to the page it opens.
   Motion uses a snappy expo-out curve with brightness-only dimming
   (no blur) so the wheel glides instead of stepping. */
#home .tw-wrap{max-width:1120px;min-height:0;margin-top:0}
/* Nothing home-specific about the card any more. It sizes from the base
   .tw-card/.tw-track — so it IS a scanner card — and now takes the base
   centring and type too, because a console card is just a headline number
   over the section name: a doorway to one of those pages. Only the pointer
   differs, because this one opens. */
#home .tw-card.is-center{cursor:pointer}
.co-wrap{grid-column:1/-1}
.console-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:36px 30px;align-items:start;margin-top:8px}
@media (max-width:820px){.console-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:520px){.console-grid{grid-template-columns:1fr}}
.cnav{max-width:none;width:100%;display:flex;flex-direction:column}
.console-foot{flex:none;display:flex;justify-content:center;color:var(--dim);
  font-size:7px;letter-spacing:.2em;text-transform:uppercase;
  text-align:center;padding:14px 0 10px}
/* hero number; color = meaning:
   ▲ green = matches increased since last load, ▼ red = fell, plain = unchanged.
   (The Kabisat logo font has no digit glyphs — demo cut — so digits stay mono.) */
.console-hero{display:block;text-align:center;width:100%}
.console-index{font-size:10px;color:var(--dim);font-variant-numeric:tabular-nums;user-select:none}
.console-index:first-child{justify-self:start}
.console-index:last-child{justify-self:end}
.console-score{justify-self:center;font-size:62px;font-weight:200;color:var(--fg);text-align:center;margin-top:0;
  line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.console-score.up{color:var(--c-green)}
.console-score.down{color:var(--c-red)}
.console-delta{font-size:18px;font-weight:400;vertical-align:super;
  margin-right:.3em;letter-spacing:.02em}
.console-delta .tri-up,.console-delta .tri-dn{display:inline-block;width:0;height:0;
  border-left:4px solid transparent;border-right:4px solid transparent;margin-right:2px}
.console-delta .tri-up{border-bottom:6px solid currentColor}
.console-delta .tri-dn{border-top:6px solid currentColor}
.console-upd{text-align:center;color:var(--dim);font-size:8px;letter-spacing:.1em;
  text-transform:uppercase;margin:4px 0 40px}
/* one global footer everywhere (homepage line); per-page duplicates off */
#site-foot{position:fixed;left:0;right:0;bottom:0;z-index:41;background:var(--bg);
  text-align:center;color:var(--dim);font-size:7px;letter-spacing:.2em;text-transform:uppercase;
  padding:7px 0;pointer-events:none}
.page-scroll::after,.jobs-page::after,#lobby::after{display:none}
/* settings: coverflow picker on /settings, page-specific detail on ?tab= */
#page-body>.sec.set-page,#page-body>.sec.prof-edit.set-page{max-width:720px;padding-top:104px}
.set-page .det-mod{margin-bottom:10px}
.set-page .st-cathint{margin:2px 0 16px}
/* detail pages read like the stats page: hero title, compact quiet rows,
   centered small action bar — minimal hairlines */
.set-hero{display:flex;flex-direction:column;align-items:center;text-align:center;padding:0 0 10px}
.set-hero .console-score{font-size:min(9vw,46px)}
.set-hero .ca-tagline{color:var(--dim);font-size:11px;letter-spacing:.06em;margin-top:2px;text-align:center}
.set-page .det-mod-g{border-top:none}
.set-page .det-mod-g>*:last-child{border-bottom:none}
.set-page .det-mod-g .mini{padding:12px 8px;gap:12px}
.set-page .det-mod-g .mini .mini-v{font-size:15px;white-space:normal}
.set-page .det-mod-g .mini .mini-v b{font-size:15px}
.set-page .det-mod-g .prof-field{padding:11px 8px}
.set-page .det-mod-g .prof-field input{font-size:15px}
.set-page .prof-actions{grid-column:1/-1;justify-content:center;gap:12px;padding:16px 0 4px;border:none}
.set-page .det-status{grid-column:1/-1;justify-content:center;text-align:center}
/* logs: double width, bounded height so the pane never slides under the dock */
#page-body>.sec.prof-edit.logs-page{max-width:min(1280px,96vw);padding-top:96px}
/* console home: zoom the body only (bigger hero, rows, labels) — #home scope.
   Same top margin as every other page: the other pages pad 104px above
   their hero (set-page padding-top); the fixed dock is 37px tall at top 14px,
   so the hero's top edge lands at the same 104px line. Air below the hero
   before the wheel, so the number never touches the cards. */
#home .console-inner{max-width:1320px;font-size:14px;padding-top:104px}
#home .console-hero{margin-top:0}
#home .console-score{font-size:76px}
#home .console-upd{font-size:10px;margin-bottom:30px}
/* ---------- top dock: the section links, in the body's own language --------
   Flat and monochrome on the page background with a hairline edge. It used to
   be frosted glass over a 24s multi-hue gradient wash, which made the one
   control on screen the only tinted, layered thing in an otherwise flat
   black-and-white page. The dock is part of the page, not a widget floating
   above it. Only the indicator's transform animates, so switching sections
   never triggers layout. */
.neo-dock{
  position:fixed;top:14px;left:50%;transform:translateX(-50%);z-index:55;
  height:var(--dock-h);display:flex;gap:0;align-items:center;padding:0 6px;
  max-width:calc(100vw - 140px);box-sizing:border-box;overflow-x:auto;
  border:1px solid var(--line);border-radius:999px;background:var(--bg);
  box-shadow:none;scrollbar-width:none;
}
.neo-dock::-webkit-scrollbar{display:none}
.neo-dock a{
  position:relative;z-index:1;font:10px/1 var(--mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim);text-decoration:none;
  white-space:nowrap;padding:10px 13px;border-radius:999px;background:none;
  transition:color var(--t2) var(--ease-soft),transform var(--t2) var(--ease);
}
.neo-dock a:hover{color:var(--fg)}
.neo-dock a.on{color:var(--fg);background:none}
.neo-dock a:active{transform:scale(.94)}
.neo-dock a:focus-visible{outline:1px solid var(--fg);outline-offset:2px}
.neo-dock .dock-ind{position:absolute;left:0;top:4px;bottom:4px;width:0;border-radius:999px;
  background:var(--p2);opacity:0;pointer-events:none;z-index:0;
  transition:transform var(--t4) var(--ease),opacity var(--t2) var(--ease-soft)}
.console-nav{display:flex;flex-wrap:wrap;justify-content:center;gap:16px;margin:6px 0 10px;padding:0 12px}
.console-nav-a{font:7px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--dim);
  text-decoration:none;white-space:nowrap}
.console-nav-a:hover,.console-nav-a:focus{color:var(--fg);text-decoration:underline}
/* ---------- lobby: the new homepage — your wallpaper, four ways in ----------
   Personal background (or the frozen login wallpaper by default) with a
   dim shade so the wordmark and rows always read. The Console row is the
   fixed door to the blocks grid; the other three earn their place by
   answering "what needs me?" at a glance. */
#lobby{position:fixed;inset:0;overflow:hidden;background:var(--bg)}
#lobby[hidden]{display:none}
#lobby-logout{position:absolute;top:14px;right:16px;z-index:2;padding:8px 10px;border:none;background:none;cursor:pointer;opacity:.55}
#lobby-logout:hover{opacity:1}
#lobby-logout:focus-visible{outline:1px solid var(--fg);outline-offset:2px}
.lobby-logout-logo{font-family:'Kabisat',serif;font-style:italic;font-weight:400;font-size:22px;line-height:1;color:var(--fg);display:inline-block;padding:.1em .5em .2em .2em}
.lobby-card{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;padding:24px 16px}
.lobby-logo-wrap{display:grid;place-items:center;width:100%}
.lobby-logo{color:var(--fg);
  font-size:clamp(34px,7vw,64px);line-height:1.6;
  text-shadow:none;font-weight:400;
  padding:.15em .84em .3em .45em}
.lobby-sub{font-size:10px;color:var(--muted);letter-spacing:.02em;text-shadow:none;width:100%;max-width:640px;text-align:center;line-height:1.6;white-space:pre-line;min-height:calc(2 * 1.6em)}
.lobby-nav{width:100%;max-width:400px;display:flex;flex-direction:column;border-top:1px solid var(--line);background:none}
/* value | label | index on a strict 3-col grid: the label and index
   columns land on the same x in every row, in every cell */
.lobby-row{display:grid;grid-template-columns:1fr auto 36px;align-items:baseline;gap:10px;padding:6px 10px;cursor:pointer;border:none;border-bottom:1px solid var(--line)}
.lobby-row-l{font-size:10px;color:var(--dim);white-space:nowrap;justify-self:end;text-align:right}
.lobby-row .lobby-row-n{font-size:10px;color:var(--dim);text-align:right}
/* state colors for console values */
.st-ok{color:var(--c-green)!important}
.st-err{color:var(--c-red)!important}
.st-warn{color:var(--c-amber)!important}
.st-dim{color:var(--dim)!important}
.lobby-row:hover{background:var(--hover)}
.lobby-row:focus-visible{outline:1px solid var(--fg);outline-offset:-1px}
.lobby-row-v{font-size:12px;font-weight:400;color:var(--fg)}
.lobby-row:hover .lobby-row-v{color:var(--fg)}
.lobby-row.lobby-go{border-bottom:1px solid var(--line)}
.lobby-row.lobby-go .lobby-row-v{color:var(--fg)}
/* per-user profile checkboxes on the admin Users page */
.uprofs{display:flex;flex-wrap:wrap;gap:4px 16px;align-self:stretch;text-align:left}
.tile{
  background:var(--bg);display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:.4em;
  padding:.5em .4em;cursor:pointer;min-width:0;min-height:0;overflow:hidden;
  border:none;border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  transition:background .12s ease;
 }
 .tile.gA{background:var(--gA)}
 .tile.gB{background:var(--gB)}
 .tile.gC{background:var(--gC)}
 .tile.gD{background:var(--gD)}
 .tile.gE{background:var(--gE)}

.tile.stale{opacity:.38}
.tile.stale>.tile-v,.tile.stale>.tile-l{color:var(--dim)!important}
.tile:hover{background:var(--hover)}
.tile:active{background:var(--p2)}
.tile.gA>.tile-v,.tile.gB>.tile-v,.tile.gC>.tile-v,.tile.gD>.tile-v{color:var(--fg)}
.tile.gA>.tile-l,.tile.gB>.tile-l,.tile.gC>.tile-l,.tile.gD>.tile-l{color:var(--dim)}
.tile-v{
  /* single source of truth for cap: --tile-vmax clamps every tile at once,
     so one number (42px desktop) keeps value sizes consistent grid-wide */
  --tile-vmax:42px;
  /* scales with the row height (--rows is set by JS) so all tiles fit */
  font-size:min(3.2vw, calc(100vh / var(--rows, 9) * .30), var(--tile-vmax));
  font-weight:500;letter-spacing:-.02em;
  text-align:center;line-height:1.15;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  padding:0 .1em;
}
.tile-v.sm{font-size:min(2.2vw, calc(100vh / var(--rows, 9) * .21), 26px)}
.tile-v.xs{font-size:min(1.6vw, calc(100vh / var(--rows, 9) * .16), 18px);white-space:normal;line-height:1.3}
.tile-v.up{color:var(--up)}
.tile-v .arrow{font-size:.6em;vertical-align:.35em;margin-left:.15em}
/* persistent increase badge: small ↑N beside the settled value */
.tile-v .delta{font-size:.45em;font-weight:400;vertical-align:.5em;margin-left:.55em;color:var(--up);opacity:.9;white-space:nowrap}
.tile-v .delta b{font-weight:600;margin-left:.45em;letter-spacing:.02em}
.tile-v.up .delta{color:var(--up)}
.tile-l{font-size:min(9px, calc(100vh / var(--rows, 9) * .09));letter-spacing:.14em;text-transform:uppercase;color:var(--dim);text-align:center}
/* wide tiles: span 2 grid cells, paint a live picture under the value.
   Same transparent tile paint — the picture is strokes/bars only. */
.tile.wide{grid-column:span 2}
.tile-pic{display:flex;align-items:center;justify-content:center;gap:3px;height:min(34px, calc(100vh / var(--rows, 9) * .22));padding:0 14%;align-self:stretch;pointer-events:none;user-select:none}
.tile-pic i{flex:1;background:var(--muted);opacity:.55;min-width:3px;min-height:8%}

.tile-pic b{display:block;height:6px;border-radius:2px;opacity:.85}
.tile-pic .ptxt{font-size:min(10px, calc(100vh / var(--rows, 9) * .10));letter-spacing:.08em;color:var(--dim);white-space:nowrap}
.tile-pic .pdot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--dim);opacity:.6}
.tile-pic .pdot.on{background:var(--fg);opacity:1;box-shadow:none}
.tile-pic .pulse-line{display:block;width:100%;height:2px;background:var(--muted);opacity:.7;flex:none}
.tile-pic .pbars{display:flex;align-items:flex-end;gap:2px;height:100%;flex:1;max-width:45%}
.tile-pic .pbars i{flex:1;background:var(--muted);opacity:.55;min-width:2px}
.tile[data-key="pulse"] .pbars i{background:var(--fg);opacity:.8}
.tile-pic .qbar{display:block;height:6px;background:var(--p2);border-radius:3px;overflow:hidden;width:70%}
.tile-pic .qbar i{display:block;height:100%;background:var(--muted);opacity:.7}
/* live ASCII art line: inherits the tile's transparent paint (no background
   of its own), dim family color, tiny mono — decoration only */
.tile-art{display:block;font-size:min(11px, calc(100vh / var(--rows, 9) * .11));line-height:1.2;letter-spacing:.1em;color:var(--dim);opacity:.75;white-space:pre;pointer-events:none;user-select:none}
.tile.gA>.tile-art,.tile.gB>.tile-art,.tile.gC>.tile-art,.tile.gD>.tile-art,.tile.gE>.tile-art{color:var(--dim);opacity:.5}
.tile.stale>.tile-art{display:none}

/* ---------- sub pages: full-viewport, centered, no chrome ----------
   (no outer hairlines: the grid cells draw their own borders, so the page
   edges stay clean — this was the white frame around detail pages)
   BUGFIX: #view is animated (.pg-enter) on every navigation; an animated
   ancestor becomes the containing block for fixed descendants, so
   inset:0 resolved against the animating #view (height 0) and the whole
   page collapsed to 0px — "nothing loads". Height is now viewport-driven
   (100dvh) so the page never depends on its parent's geometry. */
.page{position:fixed;top:0;left:0;width:100vw;height:100dvh;background:var(--bg);display:flex;flex-direction:column;overflow:hidden}
.page[hidden]{display:none}
.page-scroll{position:relative;z-index:1;flex:1;overflow:auto;padding:0}
.page-scroll>*{margin-left:auto;margin-right:auto}
#page-body{
  min-height:100%;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  grid-auto-rows:minmax(140px,1fr);
  gap:0;align-items:stretch;width:100%;
}
/* wide sections span the full matrix; metric boxes take one cell;
   a lone box becomes one centered full-page cell */
#page-body>.sec{grid-column:1/-1}
#page-body>.dbox:only-child{grid-column:1/-1}
#page-body>.dbox{grid-column:span 1}
#page-body>.dbox.span2{grid-column:span 2}
#page-body>.dbox.span3{grid-column:span 3}
#page-body>.dbox.span-all{grid-column:1/-1}
#page-body>.dbox-row,#page-body>.stats-grid{grid-column:1/-1}

/* box style: like homepage tiles — grid of bordered sections */
.page-scroll>.page-grid,.page-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;margin:0 auto}
/* sections tile like homepage boxes; anything else (tables, logs) spans full width */
#page-body>.sec{
  border-right:1px solid var(--line);
  border-bottom:1px solid var(--line);
  min-width:0;min-height:0;overflow:hidden;
  align-items:center;text-align:center;
}
#page-body>*:not(.sec):not(.dbox):not(.dbox-row):not(.stats-grid){grid-column:1/-1}
#page-body>.sec>.actions,#page-body>.sec>form,#page-body>.sec>table,
#page-body>.sec>div[style*="overflow"],#page-body>.sec>.talent-table-scroll,
#page-body>.sec>label.f,#page-body>.sec>.row2,#page-body>.sec>.row3,
#page-body>.sec>.check,#page-body>.sec>.chips,#page-body>.sec>p.hint,
#page-body>.sec>.kr,#page-body>.sec>.kr-add,#page-body>.sec>.scan-modes,
#page-body>.sec>.scan-fields,#page-body>.sec>.theme-opts,#page-body>.sec>.emprof,
#page-body>.sec>.progress-box,#page-body>.sec>.cat-row,#page-body>.sec>select,
#page-body>.sec>input,#page-body>.sec>textarea{align-self:stretch;text-align:left}
.sec{
  background:var(--bg);display:flex;flex-direction:column;gap:.4em;
  padding:16px 14px;min-width:0;min-height:0;overflow:hidden;
}
.sec-t{
  font:10px var(--mono);font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dim);text-align:center;
}
.hint{font-size:10px;color:var(--dim);line-height:1.5;margin:4px 0 8px}
p.hint, .hint{scrollbar-gutter:stable}
.hint.loading{animation:pulse 1.2s ease-in-out infinite}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px}
.row3{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:10px}
label.f{display:flex;flex-direction:column;gap:4px;font-size:10px;color:var(--muted);margin-bottom:10px}
label.f input,label.f textarea,label.f select{width:100%}
.check{display:flex;align-items:center;gap:8px;font-size:11px;margin:8px 0;cursor:pointer}
.check input{width:14px;height:14px;accent-color:var(--fg)}
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  border:1px solid var(--line2);border-radius:0;background:var(--p2);color:var(--fg);
  padding:7px 14px;font-size:11px;cursor:pointer;transition:background .12s ease;
}
.btn:hover{background:var(--p3)}
.btn:active{transform:translateY(1px)}
.btn:focus-visible,.tile:focus-visible{outline:1px solid var(--fg);outline-offset:-1px}
.btn:disabled{opacity:.45;cursor:default}
.btn-acc{background:var(--fg);color:var(--bg);border-color:var(--fg)}
.btn-acc:hover{background:var(--muted)}
.btn-primary{border-color:var(--line2);color:var(--fg);font-weight:500}
.btn-primary:hover{background:var(--p2)}
.btn-danger{border-color:#555;color:var(--c-red)}
.btn,.btn-sm{border-radius:0}
.btn-sm{padding:4px 10px;font-size:10px}
.actions{display:flex;gap:8px;align-items:center;margin-top:10px;flex-wrap:wrap}
.spacer{flex:1}
.status{font-size:10px;color:var(--dim)}

/* ---------- jobs page: full viewport with scroll ---------- */
/* same 0-height bug as .page: #view is animated on navigation, so fixed
   children must size from the viewport, not inset:0 against #view */
.jobs-page{position:fixed;top:0;left:0;width:100vw;height:100dvh;display:flex;flex-direction:column;background:var(--bg);overflow:hidden;padding-top:56px}
.jobs-page-header{
  display:flex;align-items:center;gap:16px;padding:64px 20px 22px 170px;
  border-bottom:1px solid var(--line);flex-shrink:0;max-width:1100px;margin:0 auto;width:100%;
  flex-wrap:wrap;row-gap:8px;min-width:0;box-sizing:border-box;
}
.jobs-page-title{font-size:10px;font-weight:400;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);white-space:nowrap;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.jobs-count{margin-left:auto;font-size:10px;color:var(--c-teal);font-weight:500;letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
@media (max-width:900px){.jobs-page-header{padding-left:150px}}
@media (max-width:640px){.jobs-page-header{padding:60px 16px 16px}}
#jobswrap{flex:1;min-height:0;position:relative;overflow:auto;background:var(--bg)}
#jobswrap .jobs-scroll-wrap{overflow:visible}
#jobs-table tbody tr{cursor:pointer}
#jobs-table tbody tr:hover td{background:var(--hover)}
/* separate (not collapse): with collapse, Chrome paints scrolled row
   backgrounds/box-shadows OVER the sticky thead — labels get sliced and
   row edge-markers bleed through the top row. */
#jobs-table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}
#jobs-table th,#jobs-table td{
  border:none;padding:6px 12px;font-size:10px;line-height:1.5;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left;
}
#jobs-table thead th{
  position:sticky;top:0;background:var(--bg);color:var(--muted);z-index:2;
  font-weight:400;font-size:9px;line-height:1.4;letter-spacing:.08em;text-transform:uppercase;
  cursor:pointer;user-select:none;border-bottom:1px solid var(--line);
  padding:16px 12px 8px;vertical-align:middle;
}
#jobs-table thead th[data-sort]:hover{color:var(--fg)}
#jobs-table tbody tr{cursor:pointer}
#jobs-table tbody tr:hover{background:var(--hover)}
/* rows tint + color by score band; status tints the left edge marker.
   Highest band (gold) reads instantly; status stays visible as a marker. */
#jobs-table tbody tr{position:relative}
#jobs-table tbody tr td:first-child{box-shadow:inset 2px 0 0 transparent}
#jobs-table tbody tr.sc-top{background:rgba(231,231,231,.07)}
#jobs-table tbody tr.sc-top td:first-child{box-shadow:inset 2px 0 0 var(--fg)}
#jobs-table tbody tr.sc-top .score-cell{color:var(--fg);font-weight:500}
#jobs-table tbody tr.sc-high{background:rgba(231,231,231,.04)}
#jobs-table tbody tr.sc-high td:first-child{box-shadow:inset 2px 0 0 var(--muted)}
#jobs-table tbody tr.sc-high .score-cell{color:var(--fg);font-weight:400}
#jobs-table tbody tr.sc-mid{background:transparent}
#jobs-table tbody tr.sc-mid td:first-child{box-shadow:inset 2px 0 0 var(--dim)}
#jobs-table tbody tr.sc-mid .score-cell{color:var(--muted)}
#jobs-table tbody tr.sc-low .score-cell{color:var(--dim)}
#jobs-table tbody tr.st-saved td:first-child{box-shadow:inset 2px 0 0 var(--muted)}
#jobs-table tbody tr.st-dismissed{opacity:.55}
#jobs-table tbody tr.st-dismissed td:first-child{box-shadow:inset 2px 0 0 var(--dim)}
#jobs-table tbody tr.st-read{opacity:.55}
#jobs-table tbody tr.st-new td:first-child{box-shadow:inset 2px 0 0 var(--fg)}
#jobs-table tbody tr:nth-child(even):not(.sc-top):not(.sc-high):not(.sc-mid){background:var(--p1)}
#jobs-table .num{text-align:right;font-variant-numeric:tabular-nums}
.jobs-loading{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;color:var(--dim);animation:pulse 1.2s ease-in-out infinite;z-index:10}
@keyframes pulse{0%,100%{opacity:.45}50%{opacity:1}}
p.hint, .hint{scrollbar-gutter:stable}
.hint.loading{animation:pulse 1.2s ease-in-out infinite}

/* ---------- scan page: identical language to the homepage ---------- */
/* viewport-sized like .page/.jobs-page (animated #view ancestor bug) */
.scan-page{position:fixed;top:0;left:0;width:100vw;height:100dvh;background:var(--bg);overflow:hidden}
.scan-grid{
  position:fixed;top:0;left:0;width:100vw;height:100dvh;display:grid;
  grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,1fr);
  background:var(--bg);
}
.scan-tile{
  background:var(--bg);display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:.4em;
  padding:.5em .4em;cursor:pointer;min-width:0;min-height:0;overflow:hidden;
  border-right:1px solid var(--line);
  border-bottom:1px solid var(--line);
  transition:background .12s ease;
}
.scan-tile:hover{background:var(--hover)}
.scan-tile:active{background:var(--p2)}
.scan-tile-mode.active{box-shadow:inset 0 0 0 1px var(--fg)}
/* mode tiles carry a family tint; the Start tile stays the yellow accent */
.scan-tile[data-mode="age"],.scan-tile[data-mode="pages"],.scan-tile[data-mode="count"],.scan-tile[data-mode="auto"]{background:var(--bg)}
.scan-tile[data-mode="age"]>.scan-tile-v,.scan-tile[data-mode="pages"]>.scan-tile-v,.scan-tile[data-mode="count"]>.scan-tile-v,.scan-tile[data-mode="auto"]>.scan-tile-v{color:var(--fg)}
.scan-tile-wide{background:var(--bg)!important}
.scan-tile-v{
  font-size:min(2.6vw, 30px);font-weight:500;letter-spacing:-.02em;
  text-align:center;line-height:1.15;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.scan-tile-v-acc{color:var(--fg)}
.scan-tile.busy .scan-tile-v{color:var(--dim)}
.scan-tile-label{
  font-size:min(9px, 11px);letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);text-align:center;
}
.scan-tile-input{display:flex;flex-direction:column;gap:2px;width:60%;margin-top:.2em}
.scan-tile-input-2{flex-direction:row;width:80%;gap:8px}
.scan-tile-input label{display:flex;flex-direction:column;gap:2px;font-size:9px;text-align:center;flex:1;color:var(--dim)}
.scan-tile-input input{
  width:100%;text-align:center;font-size:14px;font-weight:500;padding:4px 6px;
  background:var(--p1);border:1px solid var(--line);border-radius:0;color:var(--fg);
}
.prof-field.dimmed{opacity:.42}
.scan-tile-wide{grid-column:span 2}
.scan-tile-progress{
  grid-column:1/-1;cursor:default;
}
.scan-tile-progress:hover{background:var(--bg)}
.scan-progress{
  overflow:auto;padding:6px 10px;display:flex;flex-direction:column;gap:2px;
  min-height:0;flex:1;align-self:stretch;width:100%;
  font-family:var(--mono);font-size:9px;color:var(--muted);
}
.scan-progress:empty::after{content:"waiting…";color:var(--dim)}
.scan-progress span{white-space:pre-wrap;word-break:break-all}

/* ---------- box language shared by every detail page ----------
   A box = large value + small uppercase label, hairline borders,
   no radius, no shadows. Merging = span2 / span3 / span-all.
   Family tint rotation: every untinted dbox cycles teal→amber→magenta→blue
   via :nth-of-type, so ALL detail pages get home-page-like color for free —
   explicit tb-* classes always win. */
#page-body>.dbox:nth-of-type(4n+1),#page-body>.dbox:nth-of-type(4n+2),#page-body>.dbox:nth-of-type(4n+3),#page-body>.dbox:nth-of-type(4n){background:var(--bg)}
#page-body>.dbox:nth-of-type(4n+1)>.dbox-v,#page-body>.dbox:nth-of-type(4n+2)>.dbox-v,#page-body>.dbox:nth-of-type(4n+3)>.dbox-v,#page-body>.dbox:nth-of-type(4n)>.dbox-v{color:var(--fg)}
#page-body>.dbox:nth-of-type(4n+1)>.dbox-l,#page-body>.dbox:nth-of-type(4n+2)>.dbox-l,#page-body>.dbox:nth-of-type(4n+3)>.dbox-l,#page-body>.dbox:nth-of-type(4n)>.dbox-l{color:var(--dim)}
#page-body>.dbox.tb-teal,#page-body>.dbox.tb-amber,
#page-body>.dbox.tb-magenta,#page-body>.dbox.tb-blue{background:var(--bg)}
.dbox{
  background:var(--bg);display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:.4em;
  padding:.5em .4em;min-width:0;min-height:0;overflow:hidden;
  border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  text-align:center;transition:background .12s ease;
}
/* console Home tile: the way back to the lobby — loud yellow, can't miss it.
   Same hairlines as every tile (top/left never draw: cells only paint
   right/bottom, so the grid edge stays clean on all four sides). */
.tile-back{background:transparent!important;border-right:1px solid var(--line)!important;border-bottom:1px solid var(--line)!important}
.tile-back:hover{background:var(--hover)!important}
.tile-back:focus-visible{outline:1px solid var(--fg);outline-offset:-2px}
.tile-back>.tile-v{color:var(--muted)}
.tile-back>.tile-l{color:var(--dim)!important}
/* clickable affordance: normal 1px border everywhere; only the primary
   action per page (Generate/Upload/Save/Console rows) gets the thicker
   2px action edge + yellow value. Everything else reads quiet. */
.dbox.click,a.dbox,button.dbox{border-bottom:1px solid var(--line);cursor:pointer}
.dbox.click:hover,a.dbox:hover,button.dbox:hover{background:var(--hover)}
button.dbox .dbox-v,.dbox.click>.dbox-v{color:var(--fg);font-weight:400}
.dbox.click.primary,button.dbox.primary{border-bottom:2px solid var(--line2)}
.dbox.click.primary>.dbox-v,button.dbox.primary .dbox-v{color:var(--fg);font-weight:500}
/* Save is a full-width box like every other action box — big "Save" value,
   yellow via .primary, same behavior everywhere. No nested button-in-a-box. */
#page-body button#page-save{border-bottom:2px solid var(--line2)}
#page-body button#page-save .dbox-v{color:var(--fg);font-weight:500;font-size:min(4vw,44px)}
.dbox.click:active,a.dbox:active,button.dbox:active{background:var(--p2)}
.dbox:focus-visible{outline:1px solid var(--fg);outline-offset:-1px}
.dbox-v{
  font-size:min(2.6vw,30px);font-weight:500;letter-spacing:-.02em;
  line-height:1.15;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;
}
.dbox-v.wrap{white-space:normal;line-height:1.3}
.dbox-l{
  font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);text-align:center;
}
.dbox-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.dbox-row>*{border-right:1px solid var(--line);border-bottom:1px solid var(--line)}
.dbox-row>*:last-child{border-right:1px solid var(--line)}
.dbox-pre{
  align-self:stretch;width:100%;flex:1;overflow:auto;text-align:left;
  font-family:var(--mono);font-size:9px;color:var(--muted);
  padding:8px 10px;display:flex;flex-direction:column;gap:2px;
}
.dbox-pre:empty::after{content:"waiting…";color:var(--dim)}
.dbox-pre span{white-space:pre-wrap;word-break:break-all}
.dbox.form{gap:1.1em;padding:1.2em 16%}
/* slim: short read-only boxes (settings cells, debug status tiles). Compacts
   the tall default padding per-box — never touches #page-body or .dbox,
   so no other page is affected. */
.dbox.slim{padding:.55em .4em;gap:.25em}
.dbox.form.slim{gap:.55em;padding:.7em 8%}
.dbox.form input{
  width:110px;text-align:center;font-size:14px;font-weight:500;
  background:var(--p1);border:1px solid var(--line);color:var(--fg);padding:5px 6px;
}
.dbox.form input[type=checkbox]{width:16px;height:16px;accent-color:var(--fg)}
.dbox.text{align-items:flex-start;justify-content:center;text-align:left;padding:1.4em 12%}
.dbox.text .hint{margin:0;text-align:left;line-height:1.8}
.mini-grid{
  grid-column:1/-1;display:grid;align-content:stretch;
  grid-template-columns:repeat(auto-fill,minmax(130px,1fr));
  grid-auto-rows:minmax(80px,1fr);gap:0;
  border-right:1px solid var(--line);border-bottom:1px solid var(--line);
}
.mini{
  background:var(--bg);display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:4px;padding:8px 6px;min-width:0;overflow:hidden;
  border-right:1px solid var(--line);border-bottom:1px solid var(--line);text-align:center;
}
/* detail-page compact chips: inherit the mini look but shrink to ~1/3
   height in a 6-across row (like the Stats Counts strip). Wide enough
   that 6 fit one row at any width; content clamps, never reflows. */
.mini-grid.chips.det-6{grid-template-columns:repeat(6,1fr);grid-auto-rows:minmax(26px,auto)}
.mini-grid.chips.det-6 .mini{padding:3px 4px;gap:1px}
.mini-grid.chips.det-6 .mini .mini-v{font-size:13px;font-weight:500;line-height:1.2;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:inherit}
.mini-grid.chips.det-6 .mini .mini-v .c-teal{color:var(--c-teal)}
.mini-grid.chips.det-6 .mini .mini-v .c-amber{color:var(--c-amber)}
.mini-grid.chips.det-6 .mini .mini-v .c-magenta{color:var(--c-magenta)}
.mini-grid.chips.det-6 .mini .mini-v .c-blue{color:var(--c-blue)}
.mini-grid.chips.det-6 .mini span:last-child{font-size:7px}
/* detail readout chips outside the 6-strip (health state, upkeep, scan
   scope…) use the same compact language: 3-across, ~1/3 height. */
/* detail readouts use the homepage row: value left, small-caps label right */
.det-mod-g .mini{padding:9px 12px;gap:12px;background:var(--bg);border:none;border-bottom:1px solid var(--line);display:grid;grid-template-columns:1fr auto;align-items:baseline;text-align:left;border-radius:0}
.det-mod-g .mini .mini-v{font-size:12px;font-weight:400;line-height:1.5;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--fg)}
.det-mod-g .mini .mini-v b{font-size:12px;font-weight:400;line-height:1.5;display:block;white-space:normal}
.det-mod-g .mini span{justify-self:end;text-align:right}
/* form controls are NOT chips: full-width field rows under the chip strip */
.det-mod-g .prof-field{grid-column:1/-1}
.det-mod-g .mini{grid-column:1/-1}
.det-mod-g .prof-check{grid-column:1/-1}
.mini b{font-size:18px;font-weight:500;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mini span{font-size:8px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mini .cat-bar{width:70%;height:5px;background:var(--p2);display:block;overflow:hidden}
.mini .cat-bar i{display:block;height:100%;background:currentColor;opacity:.7}
.uptime{display:flex;gap:3px;align-self:stretch;padding:8px 10%;min-height:30px;align-items:stretch}
.uptime i{flex:1;background:var(--p2);min-width:4px}
.uptime i.up{background:var(--fg)}
/* stacked uptime strips: hour / day / month in one box, decreasing heights */
.uptime-stack{display:flex;flex-direction:column;gap:5px;align-self:stretch;padding:8px 10% 4px}
.uptime-stack .uptime{padding:0;min-height:0}
.uptime-stack .uptime i{min-height:26px}
.uptime-stack .uptime + .uptime i{min-height:16px}
.uptime-stack .uptime.months i{min-height:9px}
/* ---------- matched: one column per profile, wraps past 4 ---------- */
.mcells{grid-column:1/-1;display:grid;grid-auto-rows:1fr;min-height:40vh}
.mcell{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
  padding:18px 12px;cursor:pointer;border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--gA)}
.mcell:nth-child(4n+2){background:var(--gB)}
.mcell:nth-child(4n+3){background:var(--gC)}
.mcell:nth-child(4n){background:var(--gD)}
.mcell:hover{background:var(--hover)}
.mcell:focus-visible{outline:1px solid var(--fg);outline-offset:-1px}
.mcell-name{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);text-align:center}
.mcell-n{font-size:min(5vw,44px);font-weight:500;font-variant-numeric:tabular-nums}
.mcell.top .mcell-n{color:var(--fg)}
.theme-half .dbox-v{font-size:min(4vw,44px)}
.theme-half{overflow:hidden}
/* themes page: fixed 5 cols x 2 rows — all 10 swatches, one screen */
#page-body>.theme-grid{grid-column:1/-1;display:grid;grid-template-columns:repeat(5,1fr);grid-template-rows:repeat(2,1fr);min-height:60vh}
#page-body>.theme-grid>.theme-half{min-height:0}
/* themes coverflow: centre swatch focused, sides peek. True 3D wheel —
   no strokes/rings anywhere (no edge lines), focus reads from depth +
   scale + light. Edges fade so clipped cards dissolve, never cut. */
.tw-wrap{grid-column:1/-1;display:flex;align-items:center;justify-content:center;gap:8px;width:100%;max-width:1120px;margin:0 auto;min-height:72vh}
/* The arrow is a glyph, not a button: hovering brightens the chevron and
   draws nothing else — no box, no fill, no outline. Its hit area is
   deliberately larger than the glyph (the ::before bleeds past the 34x64
   box), because a stage this wide with only two targets should answer a
   click NEAR the arrow, not only one dead on it. Keyboard focus still draws
   its ring, so the control stays reachable without a mouse. */
.tw-arrow{
  position:relative;flex:none;align-self:center;width:34px;height:64px;
  font-size:22px;line-height:1;color:var(--dim);border:none;background:none;
  cursor:pointer;user-select:none;
}
.tw-arrow::before{content:"";position:absolute;top:-30px;bottom:-30px;left:-16px;right:-16px}
.tw-arrow:hover{color:var(--fg)}
.tw-arrow:focus-visible{outline:1px solid var(--fg);outline-offset:6px}
.tw-viewport{flex:1 1 auto;min-width:0;max-width:980px;margin:0 auto;overflow:hidden;perspective:1400px;touch-action:pan-y;cursor:grab;outline:none;-webkit-mask-image:linear-gradient(to right,transparent 0,#000 64px,#000 calc(100% - 64px),transparent 100%);mask-image:linear-gradient(to right,transparent 0,#000 64px,#000 calc(100% - 64px),transparent 100%)}
.tw-viewport:active{cursor:grabbing}
.tw-track{position:relative;height:490px;transform-style:preserve-3d}
.tw-card{position:absolute;left:50%;top:30px;width:min(320px,74vw);height:380px;display:flex;flex-direction:column;align-items:center;justify-content:center;border:none;border-radius:18px;overflow:hidden;transition:transform var(--t4) var(--ease),opacity var(--t3) var(--ease-soft),filter var(--t3) var(--ease-soft);will-change:transform,opacity;box-sizing:border-box;cursor:pointer}
/* card text must resolve vars at text level so each swatch uses its OWN
   theme colors (inherited app color is invisible on contrasting cards) */
.tw-track .tw-card .dbox-v{color:var(--fg)}
.tw-track .tw-card .dbox-l{color:var(--dim)}
.tw-track .tw-card{border:none}
.tw-card.is-center{opacity:1;filter:brightness(1) saturate(1) blur(0px);z-index:30;cursor:default}
.tw-card.is-side{opacity:1;filter:brightness(.94) saturate(.94) blur(0px);z-index:20;cursor:pointer}
.tw-card.is-peek{opacity:.9;filter:brightness(.84) saturate(.9) blur(.3px);z-index:10;cursor:pointer}
.tw-card.is-far{opacity:0;filter:brightness(.7) saturate(.85) blur(6px);pointer-events:none;z-index:0}
/* kill the grid's inset selected-ring inside the wheel — selection is
   the dot only, so no ring fragments ever draw at the corners */
.tw-track .tw-card.theme-half.active{box-shadow:0 18px 50px rgba(0,0,0,.45)}
.tw-track .tw-card.theme-half.active.is-side{box-shadow:0 10px 28px rgba(0,0,0,.4)}
.tw-track .tw-card.theme-half.active.is-peek{box-shadow:0 6px 18px rgba(0,0,0,.35)}
.tw-card .dbox-v,.tw-card .dbox-l,.tw-card .ca-stat{position:relative;z-index:1}
/* per-card wash: distinct hue + distinct gradient shape per card, built
   from the active theme (var(--bg) + family color) so every theme reads
   differently yet stays quiet in both dark and light */
.tw-card[data-g="0"]{background:linear-gradient(145deg,color-mix(in srgb,var(--c-teal) 20%,var(--bg)),var(--bg) 70%)}
.tw-card[data-g="1"]{background:linear-gradient(35deg,color-mix(in srgb,var(--c-blue) 20%,var(--bg)),var(--bg) 70%)}
.tw-card[data-g="2"]{background:radial-gradient(120% 100% at 15% 0%,color-mix(in srgb,var(--c-magenta) 22%,var(--bg)),var(--bg) 70%)}
.tw-card[data-g="3"]{background:radial-gradient(120% 100% at 85% 100%,color-mix(in srgb,var(--c-amber) 22%,var(--bg)),var(--bg) 70%)}
.tw-card[data-g="4"]{background:linear-gradient(115deg,color-mix(in srgb,var(--c-green) 20%,var(--bg)),var(--bg) 70%)}
.tw-card[data-g="5"]{background:radial-gradient(120% 100% at 85% 0%,color-mix(in srgb,var(--c-red) 20%,var(--bg)),var(--bg) 70%)}
/* No dot indicators anywhere. A wheel of five or six cards already says where
   it is by which card is centred; the dots were a second, smaller statement of
   the same thing, under a carousel that fills the screen. */
/* competition picker: stat strip under the role line — same hairline
   language as the rest of the app (JSS / rate / earned when known) */
.tw-card .ca-stats{display:flex;justify-content:center;gap:26px;margin-top:20px;padding-top:16px;border-top:1px solid var(--line)}
.tw-card .ca-stat{display:flex;flex-direction:column;align-items:center;gap:3px;font-size:8px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
.tw-card .ca-stat b{font-size:15px;font-weight:500;letter-spacing:0;color:var(--fg);font-variant-numeric:tabular-nums}
.tw-card .dbox-v,.tw-card .dbox-l,.tw-card .ca-stat{position:relative;z-index:1}
/* ---------- competition: the rankings table + one entry ----------
   These were inline <style> blocks injected on every render. They are the same
   language as everything else, so they belong in one place with it — no page
   carries a private stylesheet any more. */
.ca-wrap{max-width:none;box-sizing:border-box;padding:84px 28px 12px}
.ca-wrap .jobs-page-header{padding-left:20px}
.ca-grid{width:100%;border-collapse:collapse;table-layout:fixed;border:1px solid var(--line2)}
.ca-grid th,.ca-grid td{border:none;padding:3px 8px;font-size:10px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left}
.ca-grid thead th{position:sticky;top:0;background:var(--bg);color:var(--muted);z-index:1;font-weight:400;font-size:9px;line-height:1.4;letter-spacing:.08em;text-transform:uppercase;border-bottom:1px solid var(--line);padding:10px 8px;white-space:normal;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;max-height:3em;vertical-align:bottom}
.ca-grid tbody tr{cursor:pointer}
.ca-grid tbody tr:hover td{background:var(--hover)}
.ca-grid td.ca-dup{font-weight:600;background:rgba(231,231,231,.07);box-shadow:inset 2px 0 0 var(--fg)}
.ca-grid tbody tr:hover td.ca-dup{background:rgba(231,231,231,.12)}
.ca-grid td.ca-linked{box-shadow:inset 0 0 0 1px var(--fg)}
.ca-grid td.ca-hot{box-shadow:inset 0 0 0 2px var(--fg)}
.ca-grid td .ca-tr{font-weight:800}
.ca-hero{text-align:center;padding:10px 0 4px}
.ca-hero .console-score{font-size:min(9vw,54px)}
.ca-badges{margin-top:8px}
/* square, like every other chip in the app — these were 4px and 20px pills */
.ca-badge{display:inline-block;border:1px solid var(--fg);padding:1px 8px;font-size:10px;letter-spacing:.08em;text-transform:uppercase;margin:0 3px}
.ca-chip{display:inline-block;border:1px solid var(--line2);padding:2px 10px;margin:2px;font-size:11px}
.ca-body{font-size:12px;line-height:1.7;white-space:pre-wrap;max-width:860px;margin:0 auto}
.ca-quote{border-left:2px solid var(--line2);padding-left:12px;margin:8px auto;max-width:860px}
@media (max-width:640px){.tw-track{height:440px}.tw-arrow{width:28px;height:52px}.tw-card{width:min(280px,80vw);height:340px}
  /* the arrows drop below the card here, so a deep vertical bleed would
     swallow whatever sits underneath them */
  .tw-arrow::before{top:-14px;bottom:-14px;left:-12px;right:-12px}}
/* ---------- scanner carousels: one big mode wheel + small preset wheels --
   Same 3D coverflow engine as themes, sized down. The mode wheel uses the
   full-size cards; the minis are single-line value chips (~1/3 height).
   Mini wheels are arrows only, to stay compact. */
.scn-wrap{grid-column:1/-1;display:flex;flex-direction:column;gap:4px;width:100%}
.scn-hint{font-size:7px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);text-align:center}
.scn-mini .tw-track{height:120px}
.scn-mini .tw-card{top:8px;width:min(200px,52vw);height:104px;border-radius:14px;gap:2px}
.scn-mini .tw-card .dbox-v{font-size:min(4vw,19px)}
.scn-mini .tw-card .dbox-l{font-size:8px}
.scn-mini .tw-arrow{width:30px;height:52px;font-size:18px}
.scn-inputs{display:grid;grid-template-columns:1fr 1fr;gap:0;border-top:1px solid var(--line);margin-top:6px}
@media (max-width:640px){
  .scn-mini .tw-track{height:110px}
  .scn-mini .tw-card{width:min(170px,60vw);height:94px}
  .scn-inputs{grid-template-columns:1fr}
}
.theme-half.dk{background:#000;color:#fff}
.theme-half.lt{background:#fff;color:#000}
.theme-half.lt .dbox-l{color:#555}
/* every theme swatch paints itself in its own palette (JS sets data-theme
   on each .theme-half); scoped to the themes page so nothing leaks */
#page-body .theme-half[data-theme="light"]{--bg:#fff;--fg:#000;--p1:#f5f5f5;--line:#e4e4e4;--line2:#bdbdbd;--dim:#8a8a8a;--muted:#5f5f5f;--card:#f7f7f7;color-scheme:light}
#page-body .theme-half[data-theme="dim"]{--bg:#101010;--fg:#e6e6e6;--p1:#161616;--line:#2a2a2a;--line2:#3a3a3a;--dim:#9a9a9a;--muted:#c0c0c0}
#page-body .theme-half[data-theme="sepia"]{--bg:#151210;--fg:#e8dcc8;--p1:#1c1815;--line:#3a332a;--line2:#4d4437;--dim:#a89a85;--muted:#c8bba6}
#page-body .theme-half[data-theme="slate"]{--bg:#0f1420;--fg:#dbe4f0;--p1:#141b2a;--line:#2a3650;--line2:#3a4a6a;--dim:#8b98ad;--muted:#b3c0d4}
#page-body .theme-half[data-theme="forest"]{--bg:#0b130d;--fg:#d7e4d9;--p1:#101a12;--line:#26382a;--line2:#37503a;--dim:#8ba38e;--muted:#b2c7b5}
#page-body .theme-half[data-theme="ocean"]{--bg:#04121f;--fg:#d3e2ee;--p1:#081a2b;--line:#1d3a55;--line2:#2c5070;--dim:#7f9db4;--muted:#a9c3d6}
#page-body .theme-half[data-theme="rose"]{--bg:#170a10;--fg:#ecd6de;--p1:#1e0e15;--line:#3a2230;--line2:#4d2f41;--dim:#a38491;--muted:#c9aeb9}
#page-body .theme-half[data-theme="mono"]{--bg:#0a0a0a;--fg:#e7e7e7;--p1:#0f0f0f;--line:#181818;--line2:#333;--dim:#4e4e4e;--muted:#8f8f8f}
#page-body .theme-half[data-theme="blood"]{--bg:#120606;--fg:#f0dfc8;--p1:#180909;--line:#3a1616;--line2:#521f1f;--dim:#a38686;--muted:#c9abab}
#page-body .theme-half[data-theme="dark"]{--bg:#0a0a0a;--fg:#e7e7e7;--p1:#0f0f0f;--line:#181818;--line2:#333;--dim:#4e4e4e;--muted:#8f8f8f;--card:#0d0d0d}


/* Theme swatches paint themselves: each theme-half (and the brand box)
   carries data-theme="<its own theme>", so it renders in that theme's
   colors no matter which theme is active. Scoped to the themes page only
   (#page-body) so data-theme elsewhere never leaks styling. */




















.theme-half.active{box-shadow:inset 0 0 0 2px var(--fg)}
.rowspan2{grid-row:span 2}
.span2{grid-column:span 2}
.span3{grid-column:span 3}
.span-all{grid-column:1/-1}

/* ---------- stats ---------- */
.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.stats-grid.one-row{grid-auto-flow:column}
.stats-grid.one-row>div{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;min-width:0}
.stats-grid.one-row b{font-size:min(2.2vw,26px);color:var(--fg)}
.stats-grid.one-row span{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.stats-grid>div{
  background:var(--bg);padding:20px 10px;display:flex;flex-direction:column;
  align-items:center;gap:6px;border-right:1px solid var(--line);border-bottom:1px solid var(--line);
}
.stats-grid b{font-size:min(2.6vw,30px);font-weight:500;font-variant-numeric:tabular-nums}
.stats-grid span{font-size:9px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.cat-row{display:grid;grid-template-columns:180px 1fr 70px;gap:10px;align-items:center;padding:4px 0}
.cat-row .bar{height:6px;background:var(--p2);border-radius:3px;overflow:hidden}
.cat-row .bar i{display:block;height:100%;background:var(--muted)}
.cat-row .n{font-size:10px;text-align:right;color:var(--muted)}

/* ---------- keyring ---------- */
.kr{border-bottom:1px solid var(--line);padding:10px 0 12px;margin-bottom:0}
.kr-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.kr-name{font-size:11px;font-weight:500}
.kr-count{font-size:9px;color:var(--dim);text-transform:uppercase;letter-spacing:.1em}
.kr-keys{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:8px}
.kr-key{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:0;padding:2px 8px;font-size:10px}
.kr-key.cooling{color:var(--dim);border-style:dashed}
.kr-key button{color:var(--dim);font-size:12px}
.kr-key button:hover{color:var(--fg)}
.kr-add{display:flex;gap:8px}
.kr-add input{flex:1}
.kr-empty{font-size:10px;color:var(--dim);margin-bottom:8px}

/* ---------- alerts: profile rows ---------- */
.emprof{display:grid;grid-template-columns:34px 1fr 220px 60px;gap:10px;align-items:center;border-bottom:1px solid var(--line);padding:8px 0}
.emprof .av{width:30px;height:30px;border:1px solid var(--line2);border-radius:4px;display:flex;align-items:center;justify-content:center;font-size:10px}
.emprof b{font-size:11px;font-weight:500;display:block}
.emprof small{color:var(--dim);font-size:9px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.emprof input[type=email]{font-size:10px}

/* ---------- themes ---------- */
.theme-opts{display:grid;grid-template-columns:1fr 1fr;gap:10px;max-width:480px}
.theme-opt{border:none;border-right:1px solid var(--line);border-bottom:1px solid var(--line);padding:14px;cursor:pointer;display:flex;flex-direction:column;gap:6px;background:transparent}
.theme-opt:hover{border-color:var(--line2)}
.theme-opt:has(input:checked){border-color:var(--fg)}
.theme-opt input{accent-color:var(--fg)}
.theme-opt b{font-size:12px;font-weight:500}
.theme-opt small{color:var(--dim);font-size:10px}
.sw{display:inline-block;width:14px;height:14px;border:1px solid var(--line2);vertical-align:-2px}

/* toast: the page's own surface, not an inverted sticker. Same background and
   hairline language as everything else, mono type, and the state rides a
   coloured hairline down the left edge — so a message about the page sits on
   the page instead of shouting over it. */
#toasts{position:fixed;bottom:calc(18px + env(safe-area-inset-bottom, 0px));left:50%;transform:translateX(-50%);z-index:900;display:flex;flex-direction:column;gap:6px;align-items:center;pointer-events:none;max-width:min(92vw,520px)}
#toasts div{
  position:relative;background:var(--bg);color:var(--fg);
  border:1px solid var(--line2);border-radius:0;
  padding:9px 14px 9px 16px;font:11px/1.45 var(--mono);letter-spacing:.02em;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;
  box-shadow:0 12px 32px rgba(0,0,0,.4);
}
#toasts div::before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--fg)}
@media (prefers-reduced-motion:no-preference){
  #toasts div{animation:toast-in var(--t2) var(--ease) both}
}
#toasts div.err{border-color:var(--c-red)}
#toasts div.err::before{background:var(--c-red)}
/* success and failure also leave a word behind, never colour alone */
.flash-ok .dbox-v::after,.flash-err .dbox-v::after{font-size:10px;margin-left:6px;letter-spacing:.08em;text-transform:uppercase}
.flash-ok .dbox-v::after{content:"done";color:var(--c-green)}
.flash-err .dbox-v::after{content:"failed";color:var(--c-red)}
@keyframes toast-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
#toasts div.out{opacity:0;transform:translateY(4px);transition:opacity var(--t2) var(--ease-soft),transform var(--t2) var(--ease-soft)}

/* ---------- polish: scrollbars, selection, numerals, motion ---------- */
*{scrollbar-width:thin;scrollbar-color:var(--line2) transparent}
*::-webkit-scrollbar{width:8px;height:8px}
*::-webkit-scrollbar-thumb{background:var(--line);border-radius:4px}
*::-webkit-scrollbar-thumb:hover{background:var(--line2)}
*::-webkit-scrollbar-track{background:transparent}
::selection{background:var(--fg);color:var(--bg)}
.tile-v,.stats-grid b,.cat-row .n,#jobs-table td.num{font-variant-numeric:tabular-nums}
html{color-scheme:dark}
html[data-theme="light"]{color-scheme:light}
html[data-theme="dim"]{
  --bg:#101010;--fg:#e6e6e6;--p1:#161616;--p2:#1d1d1d;--p3:#242424;
  --line:#2a2a2a;--line2:#3a3a3a;--dim:#9a9a9a;--muted:#c0c0c0;--hover:#1a1a1a;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="sepia"]{
  --bg:#151210;--fg:#e8dcc8;--p1:#1c1815;--p2:#242019;--p3:#2c2720;
  --line:#3a332a;--line2:#4d4437;--dim:#a89a85;--muted:#c8bba6;--hover:#1e1a15;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="slate"]{
  --bg:#0f1420;--fg:#dbe4f0;--p1:#141b2a;--p2:#1a2334;--p3:#202b40;
  --line:#2a3650;--line2:#3a4a6a;--dim:#8b98ad;--muted:#b3c0d4;--hover:#161e30;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="forest"]{
  --bg:#0b130d;--fg:#d7e4d9;--p1:#101a12;--p2:#152116;--p3:#1b291c;
  --line:#26382a;--line2:#37503a;--dim:#8ba38e;--muted:#b2c7b5;--hover:#122014;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="ocean"]{
  --bg:#04121f;--fg:#d3e2ee;--p1:#081a2b;--p2:#0c2237;--p3:#112a44;
  --line:#1d3a55;--line2:#2c5070;--dim:#7f9db4;--muted:#a9c3d6;--hover:#082032;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="rose"]{
  --bg:#170a10;--fg:#ecd6de;--p1:#1e0e15;--p2:#25131b;--p3:#2d1822;
  --line:#3a2230;--line2:#4d2f41;--dim:#a38491;--muted:#c9aeb9;--hover:#1d0f16;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="mono"]{
  --bg:#0a0a0a;--fg:#e7e7e7;--p1:#0f0f0f;--p2:#141414;--p3:#1a1a1a;
  --line:#181818;--line2:#333;--dim:#4e4e4e;--muted:#8f8f8f;--hover:#101010;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
html[data-theme="blood"]{
  --bg:#120606;--fg:#f0dfc8;--p1:#180909;--p2:#1e0d0d;--p3:#251111;
  --line:#3a1616;--line2:#521f1f;--dim:#a38686;--muted:#c9abab;--hover:#180a0a;
  --card:color-mix(in srgb,var(--bg) 78%,#000 22%);
  color-scheme:dark;
}
@media (max-width:640px){
  .page-scroll{padding:0}
  #page-body{grid-template-columns:repeat(2,1fr)}
  .span2,.span3{grid-column:span 2}
  .row2,.row3{grid-template-columns:1fr}
  .emprof{grid-template-columns:34px 1fr;grid-auto-rows:auto}
}
/* ---------- keyboard help overlay: one row of boxes, homepage language ---------- */
.help-overlay{position:fixed;inset:0;z-index:999;background:rgba(0,0,0,.7);display:flex;flex-direction:column;align-items:center;justify-content:center;backdrop-filter:blur(4px)}
.help-row-wrap{display:flex;align-items:stretch;justify-content:center;border-left:1px solid var(--line2)}
.help-box{
  background:var(--p1);border:1px solid var(--line2);border-left:none;
  padding:18px 20px;width:220px;display:flex;flex-direction:column;
}
.help-title{font-size:11px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid var(--line);text-align:center}
.help-row{display:flex;align-items:center;gap:10px;padding:5px 0;font-size:11px;justify-content:flex-start}
.help-row kbd{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:20px;padding:0 6px;background:var(--p2);border:1px solid var(--line2);border-radius:4px;font-family:var(--mono);font-size:10px;color:var(--fg)}
.help-row span{color:var(--muted)}
.help-close{margin-top:14px;font-size:10px;color:var(--dim);text-align:center}
.help-close kbd{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:20px;padding:0 6px;background:var(--p2);border:1px solid var(--line2);border-radius:4px;font-family:var(--mono);font-size:10px;color:var(--fg)}

/* ---------- mobile responsive ---------- */
@media (max-width:640px){
  .row2,.row3{grid-template-columns:1fr}
  .emprof{grid-template-columns:34px 1fr;grid-auto-rows:auto}
  #page-body{grid-template-columns:1fr}
  #page-body>.sec{border-right:none;border-bottom:1px solid var(--line)}
    #jobs-table{font-size:9px}
  #jobs-table th,#jobs-table td{padding:2px 4px}
  .help-row-wrap{flex-direction:column;border-left:none}
  .help-box{border-left:1px solid var(--line2);width:auto}
  .stats-grid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}
  .stats-grid b{font-size:20px}
}
@media (max-width:400px){
  .tile-l{font-size:7px}
  .tile.gA>.tile-v,.tile.gB>.tile-v,.tile.gC>.tile-v,.tile.gD>.tile-v{color:var(--fg)}
.tile.gA>.tile-l,.tile.gB>.tile-l,.tile.gC>.tile-l,.tile.gD>.tile-l{color:var(--dim)}
.tile-v{font-size:18px}
}

/* ---------- empty states ---------- */
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;text-align:center}
.empty-state-icon{font-size:48px;margin-bottom:16px;opacity:.5}
.empty-state-title{font-size:13px;font-weight:500;margin-bottom:8px}
.empty-state-desc{font-size:11px;color:var(--dim);max-width:280px;line-height:1.5}
.empty-state-action{margin-top:16px}

/* ---------- skeleton loading ---------- */
.skeleton{background:var(--p2);border-radius:4px;position:relative;overflow:hidden}
.skeleton::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.05),transparent);animation:skeleton-sweep 1.5s ease-in-out infinite}
@keyframes skeleton-sweep{to{transform:translateX(100%)}}
.skeleton-card{height:80px;margin-bottom:8px}
.skeleton-text{height:12px;margin-bottom:6px;border-radius:3px}
.skeleton-text:last-child{width:60%}

/* ---------- filter chips ---------- */
.filter-chips{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0}
.filter-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--p2);border:1px solid var(--line);border-radius:16px;font-size:10px;color:var(--muted);cursor:pointer}
.filter-chip:hover{border-color:var(--line2);color:var(--fg)}
.filter-chip-remove{color:var(--dim);font-size:12px;line-height:1}
.filter-chip-remove:hover{color:var(--fg)}

/* ---------- score indicator ---------- */
.score-badge{display:inline-flex;align-items:center;justify-content:center;min-width:28px;height:20px;padding:0 6px;border-radius:10px;font-size:9px;font-weight:500}
.score-high{background:rgba(34,197,94,.15);color:#22c55e}
.score-mid{background:rgba(245,158,11,.15);color:#f59e0b}
.score-low{background:rgba(239,68,68,.15);color:#ef4444}

/* ---------- connects badge ---------- */
.connects-badge{display:inline-flex;align-items:center;gap:4px;font-size:10px;color:var(--amber)}
.connects-badge.low{color:var(--red)}

/* ---------- pipeline ---------- */
.pipeline{display:flex;gap:0;margin:16px 0;overflow-x:auto;padding-bottom:8px}
.pipeline-stage{flex:1;min-width:120px;padding:12px 8px;text-align:center;border:1px solid var(--line);border-right:none;background:var(--p1);position:relative}
.pipeline-stage:last-child{border-right:1px solid var(--line)}
.pipeline-stage.active{border-color:var(--fg);background:var(--p2)}
.pipeline-stage-num{font-size:18px;font-weight:500;margin-bottom:4px}
.pipeline-stage-label{font-size:9px;color:var(--dim);text-transform:uppercase;letter-spacing:.06em}
.pipeline-arrow{position:absolute;right:-8px;top:50%;transform:translateY(-50%);color:var(--dim);font-size:12px;z-index:1}

/* ---------- LLM budget indicator ---------- */
.llm-budget{display:flex;align-items:center;gap:8px;background:var(--p1);border:1px solid var(--line);padding:8px 12px}
.llm-budget-bar{flex:1;height:6px;background:var(--p2);overflow:hidden;border-radius:0}
.llm-budget-fill{height:100%;background:var(--accent);transition:width .3s ease;border-radius:0}
.llm-budget-text{font-size:10px;color:var(--dim)}
.dbox.dimmed{opacity:.45}
.dbox-v-acc{color:var(--fg)}
.dbox.brand{overflow:visible}
.dbox.brand .dbox-v{overflow:visible;text-overflow:clip;white-space:nowrap;flex:none}
/* logo-only Bugonia: the Kabisat wordmark everywhere it stands for the app
   (console tile, About page, splash, lobby). Centering math is measured
   from the font file (advance 696.8, ink 0→736 @100px): ink center sits
   0.196em right of box center, so right-minus-left padding = 0.39em puts
   the *ink* dead-center. Glyph stays left-aligned — never clipped, never
   drifted — and no generic label sits beside it. */
.brand-logo,.tile-logo,#splash .mark,.lobby-logo{
  font-family:'Kabisat',serif;font-style:italic;font-weight:400;
  display:inline-block;text-align:left;white-space:nowrap;overflow:visible;
}
.brand-logo{font-size:min(2.4vw,24px);padding:.15em .84em .3em .45em}
.tile-logo{font-size:min(2.2vw,26px);color:var(--fg);padding:.1em .64em .22em .25em}
/* brand tiles center exactly like every other tile: keep the ink-centering
   padding but let the shared flex centering own the position — no extra
   justify, margin, or text-align overrides that shift the wordmark off the
   tile's optical center. */
.tile.brand{overflow:visible;display:flex;align-items:center;justify-content:center}
/* the wordmark is ~8em wide incl. padding — a fixed vw size always
   overflows narrow cells (About tile). Size it from the CELL instead. */
.dbox.brand,.tile.brand{container-type:inline-size}
@supports (font-size:1cqw){
  .dbox.brand .brand-logo{font-size:min(11cqw,24px)}
  .tile.brand .tile-logo{font-size:min(11cqw,26px)}
}
.dbox-v-sm{font-size:min(1.7vw,15px);line-height:1.35}
input::placeholder,textarea::placeholder{font-family:var(--mono);font-style:normal;color:var(--dim);opacity:1}
.jobs-ps{
  position:fixed;right:10px;bottom:8px;z-index:40;display:flex;gap:8px;align-items:center;
  font-size:9px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);
}
.jobs-ps select{background:var(--p1);border:1px solid var(--line);color:var(--fg);font-family:var(--mono);font-size:11px;padding:2px 4px}
.tb-teal{background:var(--gA)!important}
.tb-amber{background:var(--gB)!important}
.tb-magenta{background:var(--gC)!important}
.tb-blue{background:var(--gD)!important}
/* The job detail page used to have its own .jd-* sheet (title bar, fact
   strip, action cells, verdict box). It now speaks the shared detail
   language — .set-hero + detModT/detField — so those rules went with it. */
.flash-ok{background:#1a1a1a!important;box-shadow:inset 0 0 0 2px var(--fg)!important;transition:background .25s,box-shadow .25s}
.flash-err{background:#3d0d0d!important;box-shadow:inset 0 0 0 2px var(--c-red)!important;transition:background .25s,box-shadow .25s}
.c-teal{color:var(--c-teal)}
.c-amber{color:var(--c-amber)}
.c-magenta{color:var(--c-magenta)}
.c-blue{color:var(--c-blue)}
.c-red{color:var(--c-red)}
.c-green{color:var(--c-green)}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  .pg-enter,.pg-exit{animation:none!important}
  html{scroll-behavior:auto}
}

/* skip link: first Tab stop, visible only on keyboard focus */
.skip-link{position:absolute;inset-inline-start:-999px;top:8px;z-index:1001;
  background:var(--fg);color:var(--bg);padding:8px 14px;border-radius:4px;
  font-size:11px;text-decoration:none}
.skip-link:focus-visible{inset-inline-start:12px;outline:2px solid var(--fg);outline-offset:2px}

/* coarse pointers: larger targets, no hover-only meaning */
@media (pointer:coarse){
  .neo-dock a{min-height:44px;display:inline-flex;align-items:center}
  .lobby-row{min-height:44px}
  .btn,.prof-btn{min-height:40px}
  #jobs-table thead th{min-height:40px}
}
/* narrow screens: form fields stay at 16px so iOS Safari never auto-zooms */
@media (max-width:639px){
  input,select,textarea{font-size:16px}
}

/* form cells that need wider inputs / textareas */
.dbox.form input.full,.dbox.form select{width:min(100%,340px);text-align:left}
.dbox.form select{background:var(--p1);border:1px solid var(--line);color:var(--fg);padding:5px 6px;font-size:12px}
.dbox.grow{align-items:stretch;justify-content:flex-start;text-align:left;gap:.6em;padding:14px 18px}
.dbox.grow>.dbox-l{margin-bottom:.4em}
.dbox.grow>.dbox-l{text-align:center}
.dbox.form textarea{
  width:100%;flex:1;min-height:120px;background:var(--p1);
  border:1px solid var(--line);color:var(--fg);padding:6px 8px;
  font-size:12px;resize:vertical;font-family:var(--mono);
}
.subgrid{grid-column:1/-1;display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:minmax(110px,auto)}
.subgrid[hidden]{display:none}
.mini-grid.pcards{grid-template-columns:repeat(auto-fill,minmax(240px,1fr));grid-auto-rows:minmax(150px,auto)}
.pcard{
  background:var(--bg);display:flex;flex-direction:column;gap:5px;
  padding:12px;min-width:0;overflow:hidden;text-align:left;
  border-right:1px solid var(--line);border-bottom:1px solid var(--line);
}
.pcard b{font-size:14px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pcard small{font-size:8px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.pcard .hint{margin:0;font-size:9px}
.pcard .btns{display:flex;gap:6px;margin-top:auto;flex-wrap:wrap}
/* profile cards: actions in one compact row, half-height buttons — the
   vertical stack (Edit / Activate / Delete full-width) ate half the card */
.pcard-vert b{font-size:16px}
.btns-vert{flex-direction:row;align-items:center;justify-content:center;gap:4px;width:100%;max-width:none}
.btns-vert .btn{flex:1;width:auto;padding:2px 4px;font-size:9px;white-space:nowrap}
/* profiles page: New card + all profiles in ONE 5-col row — the row itself
   is the inner grid, so the parent grid stays a single cell wide.
   Same language as the home grid: translucent tinted boxes over the
   wallpaper, colored names, dim labels. */
.mini-grid.pcards.prof-row{position:relative;z-index:1;grid-template-columns:repeat(5,1fr);grid-auto-rows:minmax(150px,auto);border:none;background:transparent}
.mini-grid.pcards.prof-row .pcard{background:color-mix(in srgb,var(--bg) calc(var(--tile-op)*1%),transparent)}
.mini-grid.pcards.prof-row .pcard.pcard-c0,.mini-grid.pcards.prof-row .pcard.pcard-c1,.mini-grid.pcards.prof-row .pcard.pcard-c2,.mini-grid.pcards.prof-row .pcard.pcard-c3,.mini-grid.pcards.prof-row .pcard.pcard-c4{background:var(--bg)}
.mini-grid.pcards.prof-row .pcard b{color:var(--fg)}
.mini-grid.pcards.prof-row .pcard.pcard-c0 b{color:var(--c-teal)}
.mini-grid.pcards.prof-row .pcard.pcard-c1 b{color:var(--c-amber)}
.mini-grid.pcards.prof-row .pcard.pcard-c2 b{color:var(--c-magenta)}
.mini-grid.pcards.prof-row .pcard.pcard-c3 b{color:var(--c-blue)}
.mini-grid.pcards.prof-row .pcard.pcard-c4 b{color:var(--c-teal)}
.pr-list-contents{display:contents}
/* ---------- profile edit page: vertically centered, monochrome ----------
   One centered column on the wallpaper: quiet back link, plain title,
   hairline rows, quiet buttons. No color, no tint — clean and aesthetic.
   (ID-qualified: #page-body>.sec outranks plain classes, so the grid's
   hairlines would otherwise survive the border:none.)
   The sec is the grid's only child, so it stretches full height — the
   inner column centers itself vertically inside it. */
#page-body>.sec.prof-edit{background:none;border:none;box-shadow:none;width:100%;max-width:640px;margin:0 auto;padding:24px 20px 0;gap:0;overflow:visible;min-height:100%;display:flex;flex-direction:column}
/* themes coverflow gets the full width so the wheel is truly centred */
#page-body>.sec.prof-edit:has(.tw-wrap){max-width:1120px}
.prof-edit-inner{display:flex;flex-direction:column;align-items:stretch;text-align:left;width:100%;flex:1;justify-content:safe center}
/* short pages (stats) center their content like home does */
.prof-center{margin:auto 0;width:100%}
/* stats page: one detail per carousel card — value cards, graph cards,
   category cards. Graphs sit inside the card, scaled to fit. */
.st-page .console-score{font-size:42px}
.st-page .console-upd{margin-bottom:2px}
/* system page: one detail per carousel card — value cards + uptime-strip
   cards. Strips sit inside the card, scaled to fit. */
.st-card-graph{width:72%;height:64px}
.he-strip{width:72%;min-height:44px}
.tw-card svg{flex:none}
.st-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 30px;margin-top:24px}
.st-grid .lobby-row{cursor:default}
.st-grid .lobby-row[data-path]{cursor:pointer}
.st-grid .lobby-row[data-path]:hover{background:var(--hover)}
.st-graphs{display:grid;grid-template-columns:1fr 1fr;gap:0 30px;margin-top:18px}
.st-cathint{text-align:center;color:var(--dim);font-size:7px;letter-spacing:.14em;
  text-transform:uppercase;margin:22px 0 8px}
.st-cats{display:grid;grid-template-columns:repeat(3,1fr);gap:0 24px}
.st-cats .lobby-row{grid-template-columns:1fr auto 20px}
/* text heroes (scan summary, theme name, account name) sit in the same
   spot as the console score but smaller */
.st-hero-sm{font-size:26px !important}
.st-about{font-size:12px;line-height:1.9;color:var(--dim);max-width:420px;margin:20px auto 0;text-align:center}
.st-cathint+.prof-field,.st-cathint+.lobby-nav{margin-top:0}
@media (max-width:620px){
  .st-grid,.st-graphs{grid-template-columns:1fr}
  .st-cats{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:430px){.st-cats{grid-template-columns:1fr}}
.prof-back{align-self:center;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);padding:6px 0;margin-bottom:18px;background:none;border:none}
.prof-back:hover{color:var(--fg)}
/* icon-only back buttons: every "← label" back link is one quiet glyph */
.console-back,.jobs-back-btn,.prof-back{font-size:18px;line-height:1;letter-spacing:0;text-transform:none}
.console-back span,.jobs-back-btn span,.prof-back span{display:none}
.prof-title{font-size:22px;font-weight:500;letter-spacing:-.01em;margin-bottom:16px}
.prof-form{display:flex;flex-direction:column;gap:0;width:100%}
.prof-form[hidden]{display:none}
/* 2-col grid: everything visible at once, no scrolling. Paste box spans
   the full left column; fields stack on the right. Strict symmetry rules:
   - every row is exactly min-height:86px (one visual rhythm everywhere)
   - fields center their content vertically (label + control always aligned)
   - inputs/selects share one height (34px) so rows never wobble
   - buttons share one height (38px); the actions row is air, not a box */
.prof-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;text-align:left;align-items:stretch;border-top:1px solid var(--line)}
.prof-paste{display:flex;flex-direction:column;gap:8px;text-align:left;padding:14px 12px;border:none;border-bottom:1px solid var(--line);background:transparent;grid-row:span 5;min-height:0}
.prof-paste span{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.prof-paste textarea{background:transparent;border:1px solid var(--line);color:var(--fg);padding:8px;font-size:12px;resize:none;flex:1;min-height:120px;width:100%}
.prof-paste .prof-btn{flex:none}
.prof-field{display:grid;grid-template-columns:130px 1fr;gap:12px;align-items:baseline;text-align:left;padding:9px 12px;border:none;border-bottom:1px solid var(--line);background:transparent;min-height:0;overflow:hidden}
.prof-field span{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The row already carries a divider, so an input underline as well drew TWO
   lines through every row. The field's own line stays reserved until you are
   actually in it — the divider above separates, the underline confirms focus. */
.prof-field input{background:transparent;border:none;border-bottom:1px solid transparent;border-radius:0;padding:0 1px;font-size:14px;width:100%;height:34px;line-height:34px;min-width:0}
.prof-field input:focus{border-bottom-color:var(--fg)}
.prof-field input::placeholder{color:var(--dim);opacity:.5}
.prof-field select{background:transparent;border:1px solid var(--line);color:var(--fg);padding:0 8px;font-size:13px;width:100%;height:34px;border-radius:0;min-width:0}
.prof-field b{font-size:15px;font-weight:500;line-height:34px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
/* detail pages: same monochrome language, but SOLID — var(--p1) fills every
   box, one flat tone per theme (dark #0a0a0a, light #fafafa, dim #161616,
   sepia/slate/forest/ocean/rose/mono/blood each their own solid). The
   wallpaper still shows through the 10px grid gaps, so pages sit on it
   without the boxes going glassy. Modules group related rows: a dim
   section label + a 2-col row grid. No per-page titles — the back link
   is the only chrome. */
/* tabbed detail layout: left selector rail + right content pane.
   Rail: one quiet row per tab, active row inverted. Pane: modules stack.
   Solid monochrome per theme (var(--p1)); wallpaper shows in the gaps.
   STABILITY: the rail is a fixed 190px column, the pane never changes the
   rail's width; rows are fixed-height boxes with ellipsis, so toggling a
   checkbox / pressing a button / swapping tabs never reflows the page.
   Only the pane's innerHTML swaps — the rail, back link and column widths
   stay put. */
/* detail rail + pane: both pinned to the top row start, content grows
   DOWNWARD only — tab swaps never move the tops. */
.det-tabs{display:flex;flex-direction:column;width:100%;gap:0;align-items:stretch}
.det-rail{display:flex;flex-direction:row;justify-content:center;gap:4px;position:static;border:none;background:none;min-width:0;align-self:stretch;flex-wrap:wrap}
.det-rail.det-topbar{margin-bottom:18px}
.det-pane{min-width:0;min-height:0;width:100%;align-self:stretch}
.det-tab{text-align:center;padding:8px 14px;min-height:0;background:none;border:none;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);cursor:pointer;white-space:nowrap;flex:none;font-weight:400}
.det-tab:hover{color:var(--fg);background:none}
.det-tab.active{background:none;color:var(--c-teal);border:none;font-weight:500;box-shadow:none}
.det-pane .det-mod + .det-mod{margin-top:18px}
.det-grid{display:flex;flex-direction:column;gap:18px;width:100%}
.det-mod{display:flex;flex-direction:column;gap:10px;width:100%}
.det-mod-t{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);padding-left:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:16px;line-height:16px;flex:none}
.det-mod-g{display:grid;grid-template-columns:repeat(3,1fr);gap:0;align-items:stretch;border-top:1px solid var(--line)}
/* Identity row — a cell on the same hairline grid: square mark, name, and the
   role in the micro-label register. Part of the shared detail language rather
   than a per-page style block, so every page that shows a person looks alike. */
.det-id{grid-column:1/-1;display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:center;padding:16px 8px}
.det-id .saas-avatar,.det-id .saas-avatar-init{width:64px;height:64px;font-size:24px;border-radius:0}
.det-id-meta{display:flex;flex-direction:column;gap:3px;min-width:0}
.det-id-meta b{font-size:17px;font-weight:400;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.det-id-sub{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 6-up chips strip (Stats Counts): same language, tighter */
.mini-grid.chips.det-6 .mini{padding:2px 3px;gap:0}
.det-grid .span{grid-column:1/-1}
.det-grid .prof-actions{display:flex;gap:10px;background:transparent;border:none;padding:0;min-height:0}
.det-grid .prof-actions .prof-btn{height:38px}
.det-grid .prof-paste{background:transparent}
.det-grid .prof-paste textarea{background:transparent}
/* quiet status line: fixed height, truncated — text swaps never resize it */
.det-status{display:flex;align-items:center;justify-content:center;min-height:26px;height:26px;padding:0;font-size:12px;color:var(--dim);overflow:hidden}
.det-status span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.det-grid .prof-paste{grid-column:1/-1;grid-row:auto;min-height:0}
.det-grid .prof-paste textarea{min-height:76px}
.usr-idline{display:flex;align-items:center;gap:10px}
.usr-avatar{display:inline-grid;place-items:center;width:30px;height:30px;border:1px solid var(--line2);font-size:14px;font-weight:600;flex:none;overflow:hidden}
img.usr-avatar{padding:0;object-fit:cover}
.usr-actions{display:flex;gap:8px;flex-wrap:wrap;align-self:stretch}
.usr-actions .prof-btn{flex:1 1 90px;padding:0 8px;height:38px;line-height:38px;font-size:11px;background:transparent;text-align:center;display:inline-flex;align-items:center;justify-content:center}
.usr-detail{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.usr-detail[hidden]{display:none}
.usr-detail input{background:var(--p1);border:1px solid var(--line);color:var(--fg);padding:7px 8px;font-size:12px;width:100%}
.prof-check{display:grid;grid-template-columns:130px 1fr;gap:12px;align-items:center;font-size:12px;cursor:pointer;text-align:left;padding:9px 12px;border:none;border-bottom:1px solid var(--line);background:transparent;min-height:0;overflow:hidden}
.prof-check input{width:15px;height:15px;accent-color:var(--fg);flex:none}
.prof-check span{line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
/* tint cycles: kept for the PROFILES list cards only (prof-row). The
   edit page + all detail pages stay monochrome — these classes must not
   paint them. */
.prof-cycle-0{background:transparent} .prof-cycle-0 span{color:var(--dim)}
.prof-cycle-1{background:transparent} .prof-cycle-1 span{color:var(--dim)}
.prof-cycle-2{background:transparent} .prof-cycle-2 span{color:var(--dim)}
.prof-cycle-3{background:transparent} .prof-cycle-3 span{color:var(--dim)}
.mini-grid.pcards.prof-row .pcard-c0{background:var(--gA)}
.mini-grid.pcards.prof-row .pcard-c1{background:var(--gB)}
.mini-grid.pcards.prof-row .pcard-c2{background:var(--gC)}
.mini-grid.pcards.prof-row .pcard-c3{background:var(--gD)}
.mini-grid.pcards.prof-row .pcard-c4{background:var(--gA)}
.prof-actions{display:flex;gap:10px}
.prof-btn{flex:1;padding:0 10px;height:38px;line-height:36px;font-size:12px;letter-spacing:.06em;border:1px solid var(--line2);border-radius:0;transition:background .12s ease;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.det-grid .prof-actions .prof-btn:not(.prof-save):not(.prof-del){background:var(--p3);border-color:transparent}
.det-grid .prof-actions .prof-btn:not(.prof-save):not(.prof-del):hover{background:var(--hover)}
.prof-btn:hover{background:var(--hover)}
.prof-btn.prof-save{background:var(--fg);color:var(--bg);border-color:var(--fg);font-weight:600}
.prof-btn.prof-save:hover{opacity:.88;background:var(--fg)}
.prof-btn:disabled{opacity:.45;cursor:default}
.prof-danger{display:flex;gap:10px}
.prof-danger .prof-btn{color:var(--dim)}
.prof-danger .prof-btn:hover{color:var(--fg)}
.prof-btn.prof-del{color:var(--c-red)}
.prof-btn.prof-del:hover{background:rgba(255,95,82,.08);color:var(--c-red)}
.prof-btn.prof-del.arming{box-shadow:inset 0 0 0 2px var(--c-red)}
.pcard-new{cursor:pointer;text-align:left;font:inherit;color:inherit}
.pcard-new:hover{background:var(--hover)}
/* per-card buttons stacked one below another, full-width */
.btns-stack{flex-direction:column;align-items:center;gap:4px;width:100%;margin-top:auto}
.btns-stack .btn{width:auto;min-width:92px;max-width:80%;padding:2px 10px;font-size:9px;white-space:nowrap}
.mini.kw b{font-size:11px;font-weight:400;text-transform:none;letter-spacing:.02em;white-space:normal;line-height:1.4}
.slimrow{min-height:0!important;padding:7px 10px!important}
#page-body>.dbox.slimrow,#page-body>.sec.slimrow{grid-column:1/-1}
/* page-air: empty spacer so short pages ride in the lower half and the
   leftover wallpaper shows on top — same backdrop, same paint, so boxes
   read identically whether or not a page uses it. */
#page-body>.page-air{grid-column:1/-1;min-height:38vh;background:transparent;border:none;pointer-events:none}
/* debug strip: one row, six readouts + clear action. The cells live INSIDE
   a single grid cell, so the shared grid-auto-rows height can't stretch each
   one into a tall box — this stays scoped to #page-body children dbg-strip. */
#page-body>.dbox.dbg-strip{flex-direction:row;flex-wrap:wrap;align-items:stretch;gap:0;padding:0}
.dbg-cell{flex:1 1 90px;min-width:90px;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.25em;padding:.55em .4em;border-right:1px solid var(--line)}
.dbg-v{font-size:min(2.6vw,30px);font-weight:500;letter-spacing:-.02em;line-height:1.15}
.dbg-clear{flex:1 1 90px;min-width:90px;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.25em;padding:.55em .4em;background:transparent;border:none;cursor:pointer;color:var(--fg)}
.dbg-clear:hover{background:var(--hover)}
.dbg-clear.arming{box-shadow:inset 0 0 0 2px var(--c-red)}
.dbg-clear.arming .dbox-l{color:var(--c-red)}
.dbg-cell.tb-amber,.dbg-cell.tb-teal,.dbg-cell.tb-magenta,.dbg-cell.tb-blue{background:transparent!important}
.dbg-cell.tb-amber>.dbg-v{color:var(--c-amber)}
.dbg-cell.tb-amber>.dbox-l{color:var(--c-amber-dim)}
.dbg-cell.tb-teal>.dbg-v{color:var(--c-teal)}
.dbg-cell.tb-teal>.dbox-l{color:var(--c-teal-dim)}
.dbg-cell.tb-magenta>.dbg-v{color:var(--c-magenta)}
.dbg-cell.tb-magenta>.dbox-l{color:var(--c-magenta-dim)}
.dbg-cell.tb-blue>.dbg-v{color:var(--c-blue)}
.dbg-cell.tb-blue>.dbox-l{color:var(--c-blue-dim)}
.voc{flex-direction:column!important;align-items:stretch!important;padding:0!important}
.voc-strip{min-height:42px;display:flex;align-items:center;justify-content:center;padding:0 12%}
.voc-grid{flex:1;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));grid-auto-rows:minmax(52px,1fr);overflow:auto;align-content:stretch}
.voc-grid .mini{border-right:1px solid var(--line);border-bottom:1px solid var(--line)}
.mini-grid{grid-auto-rows:minmax(64px,1fr)}
.graph{display:flex;align-items:flex-end;gap:3px;align-self:stretch;height:72px;padding:0 12%}
.graph i{flex:1;background:var(--muted);opacity:.7;min-width:4px}
.uptime i.down{background:var(--c-red)}
.pcard{align-items:center;text-align:center;justify-content:center}
.pcard .btns{margin-top:.4em}
.dbox.grow{align-items:center;text-align:center}
.dbox.grow input,.dbox.grow select{width:100%;max-width:420px;text-align:left}
.dbox.grow textarea{width:100%;text-align:left}
.dbox.grow .actions{width:100%;justify-content:center}
.pcard .btns{justify-content:center}



















/* press-to-confirm: an armed destructive button glows red while counting down */
.dbox.arming{box-shadow:inset 0 0 0 2px var(--c-red)}
.dbox.arming .dbox-l{color:var(--c-red)}
.btn.arming{border-color:var(--c-red)!important;color:var(--c-red)}

/* ---------- account + users: SaaS settings card (after Bootdey's free
   "account settings" snippet layout: avatar row, form grid, save bar).
   Theme-aware, compact, no Bootstrap. */
.saas-card{background:var(--card);border:1px solid var(--line);padding:14px;display:flex;flex-direction:column;gap:12px}
.saas-avatar-row{display:flex;gap:12px;align-items:center;padding-bottom:12px;border-bottom:1px solid var(--line)}
.saas-avatar,.saas-avatar-init{width:64px;height:64px;border-radius:50%;flex:none;object-fit:cover}
.saas-avatar-init{display:inline-grid;place-items:center;font-size:24px;font-weight:600;background:var(--p3);color:var(--fg);border:1px solid var(--line2)}
.saas-avatar-meta{display:flex;flex-direction:column;gap:2px;min-width:0}
.saas-avatar-meta b{font-size:16px;font-weight:600}
.saas-role{font-size:11px;color:var(--dim)}
.saas-avatar-actions{display:flex;gap:8px;margin-top:6px;flex-wrap:wrap}
.saas-avatar-actions .prof-btn{flex:none;height:30px;line-height:28px;font-size:11px}
.saas-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.saas-field{display:flex;flex-direction:column;gap:5px;font-size:11px;color:var(--dim);min-width:0}
.saas-field>span{font-size:10px;letter-spacing:.1em;text-transform:uppercase}
.saas-field input{background:var(--p1);border:1px solid var(--line);color:var(--fg);padding:8px 10px;font-size:13px;width:100%}
.saas-field input:focus{border-color:var(--fg);outline:none}
.saas-savebar{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}
.saas-savebar .prof-btn{flex:none;min-width:140px}
.saas-sect{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);margin-top:10px}
.saas-cards{display:flex;flex-direction:column;gap:10px;margin-top:10px}
.usr-card .saas-avatar-row{padding-bottom:10px}
.usr-card .usr-detail{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid var(--line)}
.usr-card .usr-detail[hidden]{display:none}
.saas-chips{display:flex;flex-wrap:wrap;gap:6px}
.saas-chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;padding:6px 10px;border:1px solid var(--line);background:var(--p1);cursor:pointer;white-space:nowrap}
.saas-chip input{width:13px;height:13px;accent-color:var(--fg)}
.saas-chip:has(input:checked){border-color:var(--fg);background:var(--p3)}

/* --- users: ledger rows (collapsed) + detail drawer ---
   Kept from the experiments: compact row + drawer. All other
   experiment styles reverted to the symmetric grid. ---
.usr-row{grid-column:1/-1;display:grid;grid-template-columns:40px 1fr auto auto;gap:12px;align-items:center;
  padding:10px 14px;border-bottom:1px solid var(--line)}
.usr-avatar{width:32px;height:32px;display:grid;place-items:center;font-size:15px;font-weight:600;
  border:1px solid var(--line2);color:var(--muted)}
.usr-id{display:flex;flex-direction:column;gap:1px;min-width:0}
.usr-id b{font-size:13px;font-weight:600}
.usr-id small{font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim)}
.usr-meta{font-size:10px;color:var(--dim);font-variant-numeric:tabular-nums;white-space:nowrap}
.usr-actions{display:flex;gap:6px}
.usr-detail{grid-column:1/-1;display:flex;flex-direction:column;gap:8px;padding:12px 0 4px 52px}
.usr-detail[hidden]{display:none}
.usr-detail input{max-width:420px}

/* ---------- lobby polish: ink-centered logo, soft entry ---------- */
.lobby-logo{margin-left:-.39em;padding-right:.45em}
/* first paint soft entry: lobby fades in under the splash, rows stagger up */
#lobby.lobby-in .lobby-card{animation:lobby-in .45s ease-out both}
#lobby.lobby-in .lobby-nav>.lobby-row:nth-child(1){animation:row-up .4s .08s ease-out both}
#lobby.lobby-in .lobby-nav>.lobby-row:nth-child(2){animation:row-up .4s .16s ease-out both}
@keyframes lobby-in{from{opacity:0}to{opacity:1}}
@keyframes row-up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* small screens: narrower nav, smaller logo, keep one-screen fit */
@media (max-width:480px){
  .lobby-card{gap:10px;padding:16px 12px}
  .lobby-logo{font-size:clamp(38px,13vw,56px)}
  .lobby-nav{max-width:300px}
}

.page-scroll::after{content:"\00a9 2026 bugonia.org \00b7 all rights reserved";display:block;text-align:center;color:var(--dim);font-size:7px;letter-spacing:.2em;text-transform:uppercase;padding:14px 0 10px}
#lobby::after{content:"\00a9 2026 bugonia.org \00b7 all rights reserved";position:absolute;left:0;right:0;bottom:0;z-index:2;text-align:center;color:var(--dim);font-size:7px;letter-spacing:.2em;text-transform:uppercase;padding:10px 0}
.jobs-page{padding-bottom:30px}
.jobs-page::after{content:"\00a9 2026 bugonia.org \00b7 all rights reserved";position:fixed;left:0;right:0;bottom:0;z-index:41;background:var(--bg);text-align:center;color:var(--dim);font-size:7px;letter-spacing:.2em;text-transform:uppercase;padding:7px 0}
.jobs-page-header{border-bottom:1px solid var(--line)}
.prof-field>span{text-align:right;color:var(--dim);font-size:9px;letter-spacing:.12em;text-transform:uppercase}
.prof-field b{font-size:12px;font-weight:400;color:var(--fg)}
.prof-check>span{color:var(--fg)}

/* page transitions: content rises in with a tight stagger on every route.
   Shorter travel than before — the eye should read "settled", not "slid". */
@keyframes pgin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
#page-body > *{animation:pgin var(--t4) var(--ease) both}
#page-body > *:nth-child(2){animation-delay:.05s}
#page-body > *:nth-child(3){animation-delay:.1s}
#page-body > *:nth-child(4){animation-delay:.15s}
#page-body > *:nth-child(5){animation-delay:.2s}
#page-body > *:nth-child(n+6){animation-delay:.24s}
/* route transitions: the incoming page CONTENT rises into place while the
   outgoing one glides up + fades — every page change feels like a scroll,
   never a hard cut. Exits run ~70% of an entrance. Applied to .page (inside
   #view), never to #view itself: an animated ancestor would become the
   containing block for the fixed .page and collapse it to 0 height (the
   blank-pages bug). */
@keyframes pg-scroll-in{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
@keyframes pg-scroll-out{to{opacity:0;transform:translateY(-14px)}}
.pg-enter .page{animation:pg-scroll-in var(--t4) var(--ease) both}
.pg-exit .page{animation:pg-scroll-out var(--t3) var(--ease-soft) both}
#lobby.pg-enter,#home.pg-enter{animation:pg-scroll-in var(--t4) var(--ease) both}
#lobby.pg-exit,#home.pg-exit{animation:pg-scroll-out var(--t3) var(--ease-soft) both}
/* every control eases on one vocabulary: colour and border swap on the fast
   step, movement settles on the house curve, a press lands at .98 */
button,.btn{transition:opacity var(--t2) var(--ease-soft),transform var(--t2) var(--ease),background var(--t1) var(--ease-soft),border-color var(--t1) var(--ease-soft),color var(--t1) var(--ease-soft),box-shadow var(--t2) var(--ease-soft)}
button:active,.btn:active{transform:scale(.98)}
/* tab panes: a settings-style tab switch paints with the same soft stagger
   as a route change, so moving between tabs never reads as a hard cut.
   Applied only on a switch — the first paint rides the route transition. */
@keyframes pane-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:no-preference){
  .det-pane.pane-in .det-grid > *{animation:pane-in var(--t3) var(--ease) both}
  .det-pane.pane-in .det-grid > *:nth-child(2){animation-delay:.04s}
  .det-pane.pane-in .det-grid > *:nth-child(3){animation-delay:.08s}
  .det-pane.pane-in .det-grid > *:nth-child(n+4){animation-delay:.12s}
}

/* ============================================================
   DETAIL PAGES — one language for record views (/profile, /job and
   anything else that edits a single thing). A single readable
   column: micro label ABOVE its field, one hairline per section
   with a quiet header, one primary action at the end.
   Deliberately not the 2-column .prof-field grid: a 130px label
   column puts every label right beside its own value, which reads
   as a collision at 12px. .prof-field stays as-is for the pages
   that already use it.
   ============================================================ */
#page-body>.sec.dp-page{
  width:100%;max-width:720px;padding:56px 24px 20px;overflow:visible;
  justify-self:center;align-items:stretch;text-align:left;
  border-right:none;border-bottom:none;
}
.dp-inner{display:flex;flex-direction:column;gap:10px;width:100%;text-align:left}
.dp-back{align-self:flex-start;background:none;border:none;padding:4px 0;cursor:pointer;
  font:10px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.dp-back:hover{color:var(--fg)}
.dp-head{display:flex;flex-direction:column;gap:4px}
.dp-title{font:400 24px/1.15 var(--mono);letter-spacing:-.02em}
.dp-sub{color:var(--muted);font-size:12.5px;line-height:1.5}
.dp-loading{color:var(--dim);font-size:12px;min-height:1em}
.dp-loading:empty{display:none}
.dp-form{display:flex;flex-direction:column;gap:10px}
.dp-form[hidden]{display:none}
.dp-sec{display:flex;flex-direction:column;gap:8px;border-top:1px solid var(--line);padding-top:9px}
.dp-sec-t{font:10px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
/* short sibling fields share a row: the label stays ABOVE its input, so this
   is not the old label-beside-value collision */
.dp-row{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
.dp-f{display:flex;flex-direction:column;gap:5px}
.dp-f>span,.dp-f-lbl{font:10px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
.dp-f input,.dp-f textarea{width:100%;min-height:40px;padding:9px 12px;
  border:1px solid var(--line);border-radius:0;background:var(--p1);color:var(--fg);
  font:14px/1.4 var(--mono)}
.dp-f textarea{min-height:84px;line-height:1.55;resize:vertical}
.dp-f input:focus,.dp-f textarea:focus{border-color:var(--fg)}
.dp-f input::placeholder,.dp-f textarea::placeholder{color:var(--dim);opacity:.8}
.dp-f small{color:var(--dim);font-size:10.5px;line-height:1.5}
/* the paste panel: its header carries the field label AND the action on one
   line, so the button costs no extra row. The textarea is an inset well —
   panel and field would otherwise share --p1 and read as one flat block. */
.dp-assist{display:flex;flex-direction:column;gap:9px;padding:11px;
  border:1px solid var(--line);background:var(--p1)}
.dp-assist-h{display:flex;align-items:center;justify-content:space-between;gap:12px}
.dp-assist textarea{width:100%;min-height:64px;padding:9px 12px;
  border:1px solid var(--line2);border-radius:0;background:var(--bg);color:var(--fg);
  font:14px/1.5 var(--mono);resize:vertical}
.dp-assist textarea::placeholder{color:var(--dim);opacity:.8}
.dp-assist textarea:focus{border-color:var(--fg)}
.dp-check{display:flex;align-items:flex-start;gap:11px;min-height:30px;cursor:pointer;
  font-size:12.5px;line-height:1.5;color:var(--fg)}
.dp-check input{flex:none;width:16px;height:16px;margin-top:1px;accent-color:var(--fg)}
.dp-actions{display:flex;gap:9px;flex-wrap:wrap;padding-top:2px}
.dp-btn{height:40px;padding:0 18px;border:1px solid var(--line2);border-radius:0;
  background:transparent;color:var(--fg);cursor:pointer;white-space:nowrap;
  font:12px/1 var(--mono);letter-spacing:.08em}
.dp-btn-sm{height:32px;padding:0 12px;font-size:11px}
.dp-btn:hover{background:var(--hover);border-color:var(--fg)}
.dp-btn:focus-visible{outline:2px solid var(--fg);outline-offset:2px}
.dp-btn-primary{background:var(--fg);border-color:var(--fg);color:var(--bg);font-weight:600}
.dp-btn-primary:hover{background:var(--muted);border-color:var(--muted);color:var(--bg)}
.dp-btn-primary:disabled{opacity:.5;cursor:default}
.dp-btn-danger{color:var(--c-red);border-color:var(--c-red)}
.dp-btn-danger:hover{background:rgba(255,95,82,.08);border-color:var(--c-red);color:var(--c-red)}
.dp-btn-danger.arming{box-shadow:inset 0 0 0 2px var(--c-red)}
/* the dense desktop pass never shrinks a TOUCH target: coarse pointers get
   the full 44-46px back regardless of how tight the mouse layout is */
@media (pointer:coarse){
  .dp-f input,.dp-f textarea{min-height:46px}
  .dp-check{min-height:44px}
  .dp-btn,.dp-btn-sm{height:46px}
  .dp-car .dp-f input,.dp-car .dp-f textarea{min-height:44px}
}
@media (max-width:560px){
  #page-body>.sec.dp-page{padding:72px 16px 20px}
  .dp-title{font-size:20px}
  .dp-row{grid-template-columns:1fr}
  .dp-actions .dp-btn{flex:1 1 46%;min-width:0}
  /* the wheel drops to full width with its arrows beneath the card: the
     card is never clipped, and the controls stay thumb-sized */
  .dp-car .tw-wrap{flex-wrap:wrap;gap:0}
  .dp-car .tw-viewport{order:1;flex:0 0 100%;max-width:100%}
  .dp-car .tw-arrow{order:2;width:44px;height:44px;font-size:20px}
  /* 4vw is tuned for a desktop card; on a phone it shrinks the hero label
     below the field text, which inverts the hierarchy */
  .dp-car .dp-c .dbox-v{font-size:min(7.5vw,32px)}
}

/* ---------- profile: one section per carousel card ----------
   The console's coverflow is the app's signature interaction, so the
   profile form rides the same wheel: three cards, and only the CENTRE
   one is editable (the shared .tw-card state rules dim the rest). The
   page never scrolls — the profile is three taps wide. Copy is minimal
   on purpose: the card title names the section, the placeholder carries
   the example, and nothing else is written in the space. */
.dp-car{display:flex;flex-direction:column;align-items:center;width:100%;cursor:pointer}
/* the wheel is centred, so the page title is too — a left title over a
   centred carousel reads as a misalignment, not a hierarchy */
.dp-page:has(.dp-car) .dp-title{text-align:center}
/* The wheel owns the free space. Save/Cancel used to sit in the same block
   as the carousel, so centring that block lifted the wheel off centre by
   half the action bar's height. Now the inner fills the page, the carousel
   takes the slack (auto margins both sides), and the actions are pushed to
   the foot of the page — the same shape as the app's .saas-savebar. */
.dp-page:has(.dp-car) .dp-inner{flex:1;min-height:0}
.dp-page:has(.dp-car) .dp-form{flex:1;min-height:0}
.dp-page:has(.dp-car) .dp-car{margin:auto 0}
/* the carousel page is the console's full-width stage, not the 720px
   reading column — the wheel needs the same room the other pickers get.
   The deep bottom pad clears the fixed copyright line, which the pinned
   action bar would otherwise sit on. */
#page-body>.sec.dp-page:has(.dp-car){max-width:1120px;padding-bottom:72px}
.dp-car .tw-wrap{min-height:0;margin:0;max-width:1120px}
.dp-car .tw-viewport{max-width:980px}
.dp-car .tw-track{height:440px}
/* portrait hero card, same proportions as every other picker: a big
   centred value (.dbox-v) over a small sub-label (.dbox-l), fields below */
.dp-car .tw-card.dp-c{
  top:0;width:min(340px,78vw);height:380px;padding:24px 22px 18px;
  justify-content:flex-start;align-items:stretch;gap:0;
}
/* Only the centred card shows its fields. The neighbours stay pure hero
   label, the way every other picker's cards read, so the wheel is quiet
   and the form "opens" as it arrives. Clicks fall through (pointer-events)
   rather than landing on a field that is not really there. */
.dp-car .tw-card.dp-c .dp-c-b{
  opacity:0;pointer-events:none;transition:opacity var(--t3) var(--ease-soft);
}
.dp-car .tw-card.dp-c.is-center .dp-c-b{opacity:1;pointer-events:auto}
/* the band is one hit area split down the middle, so the cursor admits it
   everywhere except over a field, where the caret is the affordance */
.dp-car input,.dp-car textarea{cursor:text}
.dp-c-top{display:flex;flex-direction:column;align-items:center;gap:5px;
  margin-bottom:16px;position:relative;z-index:1}
.dp-c-b{display:flex;flex-direction:column;gap:10px;width:100%;flex:1;
  text-align:left;position:relative;z-index:1}
.dp-c-b .dp-f{gap:4px}
.dp-c-b .dp-f>span{font-size:9px;letter-spacing:.14em}
/* the fields are deliberately small: the card is the frame, the value is
   the content. Touch keeps the full target back (see pointer:coarse). */
.dp-c-b .dp-f input,.dp-c-b .dp-f textarea{
  min-height:32px;padding:6px 10px;font-size:12.5px;line-height:1.4;
  border:1px solid var(--line2);border-radius:0;
  background:color-mix(in srgb,var(--bg) 62%,transparent);color:var(--fg);
}
.dp-c-b .dp-f textarea{min-height:54px;line-height:1.45;resize:none}
.dp-c-b .dp-f input:focus,.dp-c-b .dp-f textarea:focus{
  border-color:var(--fg);background:var(--bg)}
.dp-c-b .dp-f input::placeholder,.dp-c-b .dp-f textarea::placeholder{color:var(--dim);opacity:.75}
.dp-c-meta{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:auto;padding-top:6px}
.dp-c-count{font:10px/1 var(--mono);letter-spacing:.1em;color:var(--dim)}
.dp-c-b .dp-check{min-height:24px;font-size:12px;gap:9px}
.dp-c-b .dp-check input{width:14px;height:14px}
/* auto-save readout: the profile form has no Save button, so this is the only
   confirmation there is. Quiet while nothing is happening, green on a commit,
   red only when the write actually failed. */
.dp-saved{min-height:14px;text-align:center;font:10px/1.4 var(--mono);
  letter-spacing:.14em;text-transform:uppercase;color:var(--dim);
  transition:color var(--t2) var(--ease-soft)}
.dp-saved.ok{color:var(--c-green)}
.dp-saved.err{color:var(--c-red)}
