/* ============================================================================
   ljlr.css — the LJLR interface stylesheet · CERBERUS and NEST, one file
   v0.5.1 · 2026-09-29 · Owner: JW Dimock
   v0.5.1: status is a traffic light (JW, 2026-09-29: "should be traffic
           light - green yellow red or off"): green good, yellow needs you /
           working, red broken, gray off. Blue left status; the Monitor's
           series took it, and gold left the series.
   v0.5.0: the BDAW Console look (JW, 2026-09-29: "pull the design elements
           for BDAW-console ... add the elements and the plan for the
           conversion"; the console release, NEXT item 32). Values copied from
           BDAW Console 0.10.0-rc.2 (BDAW\bdaw-console\BUILDS\current\:
           theme.json, assets/css/bdaw-console.css); the theme is not changed.
           Ink ground, gold accent, paper / body / dim inks, square HUD panels
           with corner brackets, buttons drawn as panels, mono caps labels,
           the four faces vendored (section 11), a frame at the corners of the
           window, a top bar with the date and the clock, a menu whose groups
           fold, and the Actions area under it.
           Status is never style (JW, 2026-09-29: "status is never
           style"): the theme's palette sets none of the status colors.
           One file, byte-identical in CERBERUS and NEST.
   v0.4.0: color and depth (JW, 2026-09-10: "monitor looks stupid - it needs
           color and depth with consistent design"). Six series colors, one
           per line on the Monitor; healthy is a color, not gray.
   v0.3.2: the wizard's step markers are links (JW, 2026-09-10).
   v0.3.1: the default look is gray at 50% brightness (JW, 2026-09-10).
   v0.3.0: the apply dial and the on-page log (section 10).
   Governed by LJLR-UI-Tech-Doctrine v0.1.0 and LJLR-Design-Guidelines v0.1.0.

   THE ACCENT RULE (RULED 2026-09-05), as it stands after v0.5.1:
     THE ACCENT (gold since v0.5.0) means exactly two things: you can ACT on
     it, or it is WHERE YOU ARE. Paper is content. Body and dim are chrome.
     STATUS is a traffic light, fixed: GREEN good · YELLOW needs you /
     working · RED broken · GRAY off. No picker and no theme changes a status
     color. The gold accent is deeper than status yellow (#E6B319 against
     #FDE047), and a status always carries its dot and its word.
     The six SERIES colors belong to the Monitor's lines and nothing else.

   ONE FILE. NO BUILD STEP. NO IMPORTS. The faces are files beside it.
       <link rel="stylesheet" href="/static/ljlr.css">

   Sections
     1  Tokens                 7  Forms and buttons
     2  Reset and base         8  Status, badges, alerts
     3  App shell              9  Dialog, tabs, empty states
     4  Layout and grid       10  HTMX states, utilities, print
     5  Panels and stats      11  v0.5.0 — BDAW Console: faces, frame,
     6  Tables                    top bar, menu, Actions, components
   ========================================================================= */

/* == 1 · TOKENS ============================================================
   Semantic names only. A screen never hard-codes a color or a pixel.
   Change a value here and every LJLR surface changes with it.
   The dimmer and every derived line/glow color use color-mix(); every
   browser LJLR supports (2023+) has it. No fallback is shipped on purpose —
   a fallback is a second palette to keep honest.                          */

:root {
  color-scheme: dark;

  /* -- THE DIMMER. 1 = full brightness, .2 = the floor. Set it on <html>:
        <html style="--dim:.6"> or data-dim="night". Nothing else changes. -- */
  --dim: .5;                 /* JW, 2026-09-10: default brightness 50% */

  /* -- THE GLOW, on its own knob. It used to ride the dimmer, so the only way
        to quiet a halo around a button was to dim the hairlines and the
        secondary ink with it - and a screen you turned down to read became a
        screen you could not read. 1 = as drawn, 0 = no halo at all, and the
        text under it stays exactly as bright either way.
        JW, 2026-09-08: "the button glow is making it hard to read the text -
        too much". -- */
  --glow-k: 0;               /* v0.5.0: BDAW draws no glow; the knob stays */

  /* -- ground. BDAW Console's ink (v0.5.0). -- */
  --c-bg:          #07080A;   /* ink */
  --c-surface:     #0F1115;   /* ink-2: a panel */
  --c-surface-2:   #171A20;   /* ink-3: raised */
  --c-surface-3:   #1E222A;   /* ink-3, lifted */

  /* -- ink. Paper is content; body and dim are chrome. Dim (3.6:1 on ink)
        never carries data - labels and hairline words only. -- */
  --c-ink:    #FBF6EC;   /* paper */
  --c-ink-2:  #B4AC9E;   /* body */
  --c-ink-3:  #6E685E;   /* dim */
  --c-ink-on-accent: #07080A;

  /* -- the highlight. THE only color that means "act here / you are here". -- */
  --c-accent:       #E6B319;   /* BDAW gold (v0.5.0). It was #d8dee9, gray at 50% (JW, 2026-09-10). */
  /* Derived, not literal. It was #7dff9e - so setting --c-accent to anything
     else left this green, and one nav item stayed the old color while the
     rest of the screen changed. Anything that is "the accent, lighter" is
     computed from the accent. */
  --c-accent-hover: color-mix(in srgb, var(--c-accent) 72%, #ffffff);
  --c-focus:        var(--c-accent);

  /* -- derived from the accent through the dimmer. Never set these directly. -- */
  --c-line:        color-mix(in srgb, var(--c-accent) calc(8% * var(--dim)), #24241F);   /* BDAW hairline #2A2A24 at .5 */
  --c-line-strong: color-mix(in srgb, var(--c-accent) calc(40% * var(--dim)), #24241F);
  --c-bracket:     color-mix(in srgb, var(--c-accent) calc(30% + 30% * var(--dim)), transparent);   /* BDAW gold-soft */
  --c-accent-soft: color-mix(in srgb, var(--c-accent) calc(9% * var(--dim)), transparent);
  --c-accent-dim:  color-mix(in srgb, var(--c-accent) calc(60% + 40% * var(--dim)), #000);
  --glow-c:        color-mix(in srgb, var(--c-accent) calc((10% + 70% * var(--dim)) * var(--glow-k)), transparent);
  --glow-c2:       color-mix(in srgb, var(--c-accent) calc((3% + 30% * var(--dim)) * var(--glow-k)), transparent);
  --glow-r:        calc((2px + 30px * var(--dim)) * var(--glow-k));
  --glow-r2:       calc((1px + 14px * var(--dim)) * var(--glow-k));
  --glow:          0 0 var(--glow-r) var(--glow-c);
  --glow-soft:     0 0 var(--glow-r) var(--glow-c2);
  --glow-text:     0 0 var(--glow-r2) var(--glow-c);

  /* -- status. A TRAFFIC LIGHT (v0.5.1, JW, 2026-09-29: "should be traffic
        light - green yellow red or off"): ok = green (good) · warn = yellow
        (needs you, or working) · bad = red (broken) · unknown = gray (off).
        Fixed, never from the style — the dimmer touches their glow, not their
        hue. Blue is not a status. -- */
  --c-ok:      var(--c-good);    --c-ok-soft:      var(--c-good-soft);
  --c-warn:    #FDE047;          --c-warn-soft:    color-mix(in srgb, #FDE047 10%, transparent);   /* YELLOW: needs you / working (v0.5.1; v0.5.0 had blue) - lemon, lighter than the gold accent */
  --c-bad:     #f85149;          --c-bad-soft:     color-mix(in srgb, #f85149 10%, transparent);
  --c-unknown: var(--c-ink-3);   --c-unknown-soft: transparent;

  /* -- HEALTHY IS A COLOR (v0.4.0). "ok = gray" left every good thing on
        the Monitor invisible. JW, 2026-09-10: "it needs color". Good is its
        own green-teal, distinct from the accent, which still means act/here. -- */
  --c-good:      #34d399;
  --c-good-soft: color-mix(in srgb, #34d399 12%, transparent);
  --glow-good:   0 0 var(--glow-r2) color-mix(in srgb, #34d399 calc((8% + 40% * var(--dim)) * var(--glow-k)), transparent);

  /* -- THE SERIES. One color per line on the Monitor, the same color in
        its tile, its ring and its chart, so a color means one thing across
        the screen. Fixed, like warn and bad: the dimmer touches their tint,
        not their hue. s1 cpu · s2 memory · s3 load · s4 disk · s5 network ·
        s6 servers. -- */
  /* No series wears a status hue (JW, 2026-09-29: "status is never style").
        rc.57, the traffic light: green, yellow, red and gray are status, so
        the series are blue, violet, magenta, paper, indigo and orchid. -- */
  --c-s1: #4AA3FF;  --c-s2: #B48CFF;  --c-s3: #FF6BCB;
  --c-s4: #EDE6D8;  --c-s5: #818CF8;  --c-s6: #D8A6E8;
  --glow-warn: 0 0 var(--glow-r2) color-mix(in srgb, #FDE047 calc((8% + 50% * var(--dim)) * var(--glow-k)), transparent);
  --glow-bad:  0 0 var(--glow-r2) color-mix(in srgb, #f85149 calc((8% + 50% * var(--dim)) * var(--glow-k)), transparent);

  /* -- type. System stacks — no CDN, no build (UI-Tech-Doctrine).
        A vendored display face for the band/labels is a SUGGEST, not here. -- */
  --f-ui:      "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --f-mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --f-display: "Poppins", "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
  --f-serif:   "Fraunces", Georgia, serif;
  --t-xs:  11px;
  --t-sm:  12.5px;
  --t-md:  14px;
  --t-lg:  16px;
  --t-xl:  20px;
  --t-2xl: 26px;
  --lh-tight: 1.25;
  --lh-body:  1.5;
  --track: .14em;               /* letter-spacing for uppercase labels */

  /* -- space. One scale. Nothing between the steps. -- */
  --s-0: 0;     --s-1: 4px;   --s-2: 8px;   --s-3: 12px;
  --s-4: 16px;  --s-5: 24px;  --s-6: 32px;  --s-7: 48px;  --s-8: 64px;

  /* -- shape. Square. A HUD has corners, not pills. -- */
  --r-sm: 0;  --r-md: 0;  --r-lg: 0;  --r-pill: 0;   /* v0.5.0: square everywhere */
  --bd: 1px solid var(--c-line);
  --bd-strong: 1px solid var(--c-line-strong);
  --shadow: 0 1px 2px rgba(0,0,0,.6), 0 8px 24px rgba(0,0,0,.4);
  /* Depth on a card: a hairline of light along the top edge, a shadow under it. */
  --shadow-card: inset 0 1px 0 rgba(255,255,255,.035), 0 6px 18px rgba(0,0,0,.45);

  /* -- density. Set data-density="compact" on <html> or on one panel. -- */
  --row-y: 8px;
  --row-x: 12px;

  /* -- motion. Respect the user; see the reduced-motion block below. -- */
  --ease: cubic-bezier(.2,.7,.3,1);
  --dur:  .14s;

  /* -- the shell -- */
  --band-h: 48px;
  --rail-w: 224px;
  --rail-strip: 56px;
  --measure: 68ch;
}

/* Dimmer presets. Any value between .2 and 1 is valid inline. */
[data-dim="day"]   { --dim: 1; }
[data-dim="dusk"]  { --dim: .7; }
[data-dim="night"] { --dim: .4; }

/* Light theme: NOT RULED. Kept only so print and a future ruling have a
   starting point. Nothing in LJLR sets it.                                */
[data-theme="light"] {
  color-scheme: light;
  --c-bg:#f4f6f5; --c-surface:#ffffff; --c-surface-2:#eef1ef; --c-surface-3:#e3e8e5;
  --c-ink:#101412; --c-ink-2:#556059; --c-ink-3:#7c867f; --c-ink-on-accent:#ffffff;
  --c-accent:#0f7a1e; --c-accent-hover:#0a5c16;
  --c-warn:#9a6700; --c-bad:#cf222e;
  --shadow: 0 1px 2px rgba(0,0,0,.06), 0 8px 24px rgba(0,0,0,.07);
}

[data-density="compact"] { --row-y: 5px; --row-x: 9px; }
[data-density="cozy"]    { --row-y: 12px; --row-x: 14px; }

/* == 2 · RESET AND BASE ================================================== */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--c-bg);
  color: var(--c-ink);
  font: var(--t-md)/var(--lh-body) var(--f-ui);
  min-height: 100dvh;
}
h1,h2,h3,h4 { margin: 0 0 var(--s-2); line-height: var(--lh-tight); font-weight: 650; color: var(--c-ink); }
h1 { font-size: var(--t-2xl); letter-spacing: .04em; text-transform: uppercase; }
h2 { font-size: var(--t-xl); letter-spacing: .03em; }
h3 { font-size: var(--t-lg); }
h4 { font-size: var(--t-md); }
p  { margin: 0 0 var(--s-3); max-width: var(--measure); }
ul, ol { margin: 0 0 var(--s-3); padding-left: var(--s-5); }
li { margin: var(--s-1) 0; }
small { font-size: var(--t-sm); }
hr { border: 0; border-top: var(--bd); margin: var(--s-5) 0; }
code, kbd, samp, pre { font-family: var(--f-mono); font-size: .92em; }
code { background: var(--c-surface-2); border: var(--bd); border-radius: var(--r-sm); padding: 1px 5px; }
pre  { background: var(--c-surface-2); border: var(--bd); border-radius: var(--r-md);
       padding: var(--s-3) var(--s-4); overflow-x: auto; margin: 0 0 var(--s-3); }
pre code { background: none; border: 0; padding: 0; }
kbd { background: var(--c-surface-3); border: var(--bd-strong); border-bottom-width: 2px;
      border-radius: var(--r-sm); padding: 1px 6px; font-size: var(--t-xs); }

/* Links are green because you can act on them. That is the whole rule. */
a { color: var(--c-accent); text-decoration: none; }
a:hover { color: var(--c-accent-hover); text-decoration: underline; }

/* One focus ring. Everywhere. Never remove it — keyboard users and
   scanner-gun users are the same people. Green: it is where you are. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 2px;
  border-radius: var(--r-sm);
  box-shadow: var(--glow);
}

::selection { background: var(--c-accent); color: var(--c-ink-on-accent); }

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

/* The label voice: mono, small, uppercase, tracked, gray. Chrome, not content. */
.lbl { font-family: var(--f-mono); font-size: 10px; letter-spacing: .18em;
       text-transform: uppercase; color: var(--c-ink-3); }
.tick { font-family: var(--f-mono); font-size: 10px; letter-spacing: var(--track);
        color: var(--c-ink-3); font-variant-numeric: tabular-nums; }


/* == 3 · APP SHELL ======================================================= */
/* <body class="app"> <header class="band"> <nav class="rail"> <main class="main"> */

.app {
  display: grid;
  grid-template-areas: "band band" "rail main";
  grid-template-columns: var(--rail-w) 1fr;
  grid-template-rows: var(--band-h) 1fr;
  min-height: 100dvh;
}

.band {
  grid-area: band;
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--s-4);
  padding: 0 var(--s-5);
  background: var(--c-bg);
  border-bottom: 1px solid var(--c-line-strong);
}
/* The mark is green: it is the one link that always takes you home. */
.band .mark { font-weight: 700; letter-spacing: .34em; font-size: 13px;
              text-transform: uppercase; color: var(--c-accent); text-shadow: var(--glow-text); }
.band .where { color: var(--c-ink-2); font-family: var(--f-mono); font-size: var(--t-xs);
               letter-spacing: .08em; text-transform: uppercase; }
.band .spacer { flex: 1 1 auto; }

/* The band's two menus: the color/brightness dot, and the name.
   JW, 2026-09-09: "give me a color and brightness dot near my username and
   have a drop down for a slider to adjust ... click name in top right and
   have User Profile and Log Out in the drop down".

   <details> and <summary>, so they work with no script at all - the panel's
   Content-Security-Policy would not run an inline one anyway. The open menu's
   summary casts a fixed, invisible pane behind its panel, so a click anywhere
   else on the page hits the summary and closes the menu. */
.band .menu { position: relative; margin-left: var(--s-3); }
.band .menu > summary { list-style: none; cursor: pointer; display: flex; align-items: center;
                        gap: var(--s-2); padding: 5px 10px; min-height: 30px; border-radius: var(--r-md);
                        color: var(--c-ink-2); font-size: var(--t-sm); }
.band .menu > summary::-webkit-details-marker { display: none; }
.band .menu > summary:hover { background: var(--c-surface-2); color: var(--c-ink); }
.band .menu[open] > summary { background: var(--c-surface-2); color: var(--c-ink); }
.band .menu[open] > summary::before { content: ""; position: fixed; inset: 0; z-index: 30; }
/* The dot IS the color, the way a swatch is. */
.band .menu > summary .chip { width: 14px; height: 14px; border-radius: 50%;
                              background: var(--c-accent); box-shadow: var(--glow-soft);
                              border: 1px solid var(--c-line-strong); }
.band .menu > .pop { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
                     min-width: 200px; padding: var(--s-3); display: flex; flex-direction: column;
                     gap: var(--s-2); background: var(--c-surface); border: var(--bd-strong);
                     border-radius: var(--r-lg); box-shadow: var(--shadow); }
.band .menu > .pop.wide { min-width: 300px; }
/* EVERY ITEM IN THIS MENU IS THE SAME SHAPE. The link had `padding: 4px 0`
   and the sign-out button carried .btn's own padding, so the two sat at
   different left edges - and the one flush against the wall read as a
   heading rather than something to click. JW, 2026-09-11: "fix the indent on
   signout - that's why i don't see users as clickable". */
.band .menu > .pop .item { display: block; width: 100%; text-align: left;
                           padding: 6px 10px; border: 0; border-radius: var(--r-sm);
                           background: none; color: var(--c-accent); font: inherit;
                           font-size: var(--t-sm); font-weight: 600; cursor: pointer; }
.band .menu > .pop .item:hover { background: var(--c-surface-2); color: var(--c-ink); }
.band .menu > .pop .item:focus-visible { outline: 2px solid var(--c-accent); outline-offset: -2px; }
.band .menu > .pop > form { margin: 0; }
.band .menu > .pop .who { padding: 0 10px; }
.band .menu > .pop .field { margin-bottom: var(--s-2); }
/* The name is the control, so it never collapses away - the menu under it is
   the only way out of the panel. */
@media (max-width: 700px) { .band .where { display: none; } }

.rail {
  grid-area: rail;
  background: var(--c-bg);
  border-right: var(--bd);
  padding: var(--s-4) var(--s-2);
  overflow-y: auto;
}
.rail .group { font-family: var(--f-mono); font-size: 10px; letter-spacing: .18em;
               text-transform: uppercase; color: var(--c-ink-3); padding: var(--s-4) var(--s-3) var(--s-2); }
.rail a {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 9px var(--s-3); border-left: 2px solid transparent;
  color: var(--c-ink-2); font-size: 13px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; text-decoration: none;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.rail a:hover { background: var(--c-surface-2); color: var(--c-ink); text-decoration: none; }
/* A component that is not installed anywhere. Named, so the shape of the
   system is still legible, but not a link, because there is nothing to open. */
.rail .off {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 9px var(--s-3); border-left: 2px solid transparent;
  color: var(--c-ink-3, var(--c-ink-2)); opacity: .45;
  font-size: 13px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; cursor: default;
}
/* "You are here" — green, with the bar and the glow. The only green in the rail. */
.rail a[aria-current="page"] { color: var(--c-accent-hover); border-left-color: var(--c-accent);
                               background: linear-gradient(90deg, var(--c-accent-soft), transparent);
                               text-shadow: var(--glow-text); }
.rail svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.5;
            stroke-linecap: round; stroke-linejoin: round; flex: 0 0 auto; }

.main { grid-area: main; padding: var(--s-5); min-width: 0; }
/* First run: the wizard takes the page - no rail column at all (JW, 2026-09-23). */
.app.takeover { grid-template-areas: "band" "main"; grid-template-columns: 1fr; }
.app.takeover .main { max-width: 900px; width: 100%; justify-self: center; }

/* Below 900px the shell is one column and the rail becomes a strip under the
   band that scrolls sideways. It used to disappear entirely, which left a
   phone with no way to any screen but the one it was on (v0.4.0). */
@media (max-width: 900px) {
  .app { grid-template-areas: "band" "rail" "main"; grid-template-columns: 1fr;
         grid-template-rows: var(--band-h) auto 1fr; }
  .rail { display: flex; align-items: center; gap: 0; overflow-x: auto; overflow-y: hidden;
          padding: 0 var(--s-2); border-right: 0; border-bottom: var(--bd); white-space: nowrap;
          scrollbar-width: none; }
  .rail::-webkit-scrollbar { display: none; }
  .rail .group { padding: 0 var(--s-2); }
  .rail a, .rail .off { padding: 11px var(--s-2); border-left: 0; border-bottom: 2px solid transparent; font-size: 12px; }
  .rail a[aria-current="page"] { border-bottom-color: var(--c-accent); background: none; }
  .main { padding: var(--s-4) var(--s-3); }
}

/* Page header inside .main. The title is content: white, bracketed. */
.page-head { display: flex; align-items: flex-start; gap: var(--s-4);
             flex-wrap: wrap; margin-bottom: var(--s-5); }
.page-head .grow { flex: 1 1 320px; min-width: 0; }
.page-head h1 { display: inline-block; padding: 4px 14px; border: var(--bd); border-width: 1px 0;
                position: relative; }
.page-head h1::before, .page-head h1::after { content: ""; position: absolute; top: -1px; bottom: -1px;
                width: 10px; border: 1px solid var(--c-line-strong); }
.page-head h1::before { left: 0; border-right: 0; } .page-head h1::after { right: 0; border-left: 0; }
.page-head p { color: var(--c-ink-2); margin: var(--s-2) 0 0; }
.crumbs { font-family: var(--f-mono); font-size: var(--t-xs); letter-spacing: .08em;
          text-transform: uppercase; color: var(--c-ink-3); margin-bottom: var(--s-2); }
.crumbs a { color: var(--c-ink-2); }
.crumbs span { padding: 0 var(--s-1); }


/* == 4 · LAYOUT AND GRID ================================================= */
/* The proportion rule: a container is sized to its content. A grid does not
   stretch two cards across a 1600px screen — it stops growing.            */

.grid { display: grid; gap: var(--s-4); }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

/* Named-area command-center layout. Override the areas per screen. */
.grid.command {
  grid-template-columns: 2fr 1fr;
  grid-template-areas: "primary side" "wide wide";
}
.grid.command > .a-primary { grid-area: primary; }
.grid.command > .a-side    { grid-area: side; }
.grid.command > .a-wide    { grid-area: wide; }
@media (max-width: 900px) {
  .grid.command { grid-template-columns: 1fr;
                  grid-template-areas: "primary" "side" "wide"; }
}

.stack   { display: flex; flex-direction: column; gap: var(--s-3); }
.row     { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
/* A field in a row takes its share of the row, not the whole width. */
.row > input:not([type="checkbox"]):not([type="radio"]), .row > select { width: auto; flex: 1 1 160px; }
.row.tight { gap: var(--s-1); }
.grow    { flex: 1 1 auto; min-width: 0; }

/* The container that does NOT stretch — a login box, a single form. */
.contain    { max-width: 460px; margin-inline: auto; }
.contain-md { max-width: 720px; margin-inline: auto; }
.contain-lg { max-width: 1100px; margin-inline: auto; }

/* The HUD frame: a bordered region with corner marks and a ruler. Wrap .main's
   content in it when a screen wants the full instrument look. Optional. */
.hudframe { position: relative; border: var(--bd); padding: var(--s-5); }
.hudframe > .k { position: absolute; width: 22px; height: 22px; border: 0 solid var(--c-accent);
                 pointer-events: none; filter: drop-shadow(var(--glow-text)); }
.hudframe > .k.tl { left: -1px; top: -1px; border-width: 2px 0 0 2px; }
.hudframe > .k.tr { right: -1px; top: -1px; border-width: 2px 2px 0 0; }
.hudframe > .k.bl { left: -1px; bottom: -1px; border-width: 0 0 2px 2px; }
.hudframe > .k.br { right: -1px; bottom: -1px; border-width: 0 2px 2px 0; }


/* == 5 · PANELS AND STATS ================================================ */
/* A panel is a hairline box on the ground with a gray mono heading. It does
   not glow — a panel is chrome, not something you act on.                 */

.panel {
  position: relative;
  background: linear-gradient(180deg, var(--c-surface-2), var(--c-surface) 60%);
  border: var(--bd);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  container-type: inline-size;      /* panels size their own contents */
}
/* corner marks, top two */
.panel::before, .panel::after { content: ""; position: absolute; top: -1px; width: 16px; height: 16px;
  border: 0 solid var(--c-line-strong); pointer-events: none; z-index: 1; }
.panel::before { left: -1px; border-width: 1.5px 0 0 1.5px; }
.panel::after  { right: -1px; border-width: 1.5px 1.5px 0 0; }
.panel > .hd {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 9px var(--s-4);
  background: transparent;
  border-bottom: var(--bd);
}
.panel > .hd h3 { margin: 0; font-family: var(--f-mono); font-size: var(--t-xs); font-weight: 500;
                  letter-spacing: .2em; text-transform: uppercase; color: var(--c-ink-2); }
.panel > .hd .sub { color: var(--c-ink-3); font-family: var(--f-mono); font-size: 10px; letter-spacing: .08em;
                    text-transform: uppercase; margin-left: auto; }
/* Fields that belong on one line. A number is narrow; giving each its own
   full-width row makes a short form look like a long one. */
/* A unit or a rule belongs ON the label, not on a line of its own under the
   field. "Storage GB" and "Limits  empty = unlimited" cost no height. */
.field label .suffix { color: var(--c-ink-3); font-weight: 400; text-transform: none;
                       letter-spacing: 0; margin-left: 6px; }

/* An empty count is not blank - it reads as the infinity sign, so the box
   always says either a number or "no limit" without anyone deciding which
   blank means what. Brighter than a normal placeholder because here it IS
   the value, not a hint about what to type. */
input.inf::placeholder { color: var(--c-ink-2); opacity: 1; font-size: 1.15em; }
input.inf:focus::placeholder { color: var(--c-ink-3); }
.limits b { color: var(--c-ink); font-weight: 600; }
.limits { color: var(--c-ink-3); }

.row2, .row3 { display: grid; gap: 0 var(--s-4); }
.row2 { grid-template-columns: 1fr 1fr; }
.row3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 640px) { .row2, .row3 { grid-template-columns: 1fr; } }

/* A list of values, one row each, added and removed - never one text box
   holding several things separated by something you have to remember. */
.rowlist .lrow { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.rowlist .lrow input { flex: 1 1 auto; }
.rowlist .drop { flex: 0 0 auto; width: 32px; height: 32px; padding: 0; line-height: 1; }

.scroll-260 { max-height: 260px; overflow: auto; }
.pick { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.pick input { accent-color: var(--c-accent); width: 15px; height: 15px; margin: 0; }

.checks { display: flex; flex-wrap: wrap; gap: 8px 18px; padding: 2px 0; }
.checks .check { display: inline-flex; align-items: center; gap: 7px; font-size: var(--t-sm);
                 color: var(--c-ink-2); cursor: pointer; }
.checks .check input { accent-color: var(--c-accent); width: 15px; height: 15px; margin: 0; }
.checks .check:hover { color: var(--c-ink); }

.panel > .hd .info { display: inline-flex; align-items: center; justify-content: center;
                    width: 14px; height: 14px; margin-left: 6px; border-radius: 50%;
                    border: 1px solid var(--c-ink-3); color: var(--c-ink-3);
                    font-family: var(--f-mono); font-size: 9px; font-style: italic;
                    line-height: 1; cursor: help; flex: 0 0 auto; }
.panel > .hd .info:hover, .panel > .hd .info:focus { border-color: var(--c-ink-1); color: var(--c-ink-1); }
.panel > .hd .spacer { flex: 1 1 auto; }
.panel > .bd { padding: var(--s-4); }
.panel > .bd.flush { padding: 0; }
.panel > .ft {
  padding: var(--s-2) var(--s-4);
  background: var(--c-surface-2);
  border-top: var(--bd);
  font-size: var(--t-sm); color: var(--c-ink-2);
  display: flex; align-items: center; gap: var(--s-3);
}

/* A stat. Big number (content: white), small label (chrome: gray). */
.stat { padding: var(--s-4); }
.stat .label { font-family: var(--f-mono); font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
               color: var(--c-ink-3); }
.stat .value { font-size: var(--t-2xl); font-weight: 700; line-height: 1.1; color: var(--c-ink);
               margin-top: var(--s-1); font-variant-numeric: tabular-nums; font-family: var(--f-mono); }
.stat .value.ok  { color: var(--c-ink); }          /* good is not green. good is just the number. */
.stat .value.warn { color: var(--c-warn); text-shadow: var(--glow-warn); }
.stat .value.bad { color: var(--c-bad); text-shadow: var(--glow-bad); }
.stat .foot { font-size: var(--t-sm); color: var(--c-ink-2); margin-top: var(--s-1); }
.stat svg.spark { display: block; margin-top: var(--s-2); width: 100%; height: 34px; }
.stat svg.spark path { fill: none; stroke: var(--c-ink-2); stroke-width: 1.5;
                       stroke-linejoin: round; stroke-linecap: round; }

/* Below 240px of panel width a stat drops its sparkline rather than squashing it. */
@container (max-width: 240px) { .stat svg.spark { display: none; } }

/* Definition list for detail panes — the most-used dense layout we have.
   Keys are chrome (mono, gray); values are content (mono, white).         */
.facts { display: grid; grid-template-columns: minmax(118px, 34%) 1fr;
         gap: 0; margin: 0; font-size: var(--t-md); }
.facts dt { font-family: var(--f-mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
            color: var(--c-ink-3); padding: var(--row-y) var(--row-x) var(--row-y) 0;
            border-bottom: 1px dashed var(--c-line); }
.facts dd { margin: 0; padding: calc(var(--row-y) - 1px) 0; border-bottom: 1px dashed var(--c-line);
            font-family: var(--f-mono); font-size: var(--t-sm); color: var(--c-ink);
            font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.facts dt:last-of-type, .facts dd:last-of-type { border-bottom: 0; }
@container (max-width: 340px) { .facts { grid-template-columns: 1fr; }
  .facts dt { border-bottom: 0; padding-bottom: 0; }
  .facts dd { padding-top: 2px; } }


/* == 6 · TABLES ==========================================================
   Hard limit: never render more than 100 rows. Chrome's own DOM budget
   warns at 800 elements — a 10-column table crosses that between 70 and
   130 rows. Paginate on the server. This is not a preference.           */

/* Every table on the panel, not only one marked .data: the screens write
   plain <table> inside .table-wrap and were getting the browser's own. (v0.4.0) */
.table-wrap { overflow-x: auto; }
:is(table.data, .table-wrap > table) {
  width: 100%; border-collapse: collapse;
  font-size: var(--t-md); font-variant-numeric: tabular-nums;
}
:is(table.data, .table-wrap > table) th, :is(table.data, .table-wrap > table) td {
  padding: var(--row-y) var(--row-x);
  text-align: left; vertical-align: top;
  border-bottom: 1px dashed var(--c-line);
}
:is(table.data, .table-wrap > table) thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--c-surface);
  font-family: var(--f-mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--c-ink-3); font-weight: 500; white-space: nowrap;
  border-bottom: var(--bd-strong);
}
:is(table.data, .table-wrap > table) tbody tr:hover { background: var(--c-surface-2); }
/* A selected row is where you are: green edge, soft green ground. */
:is(table.data, .table-wrap > table) tbody tr[aria-selected="true"] { background: var(--c-accent-soft);
                                            box-shadow: inset 2px 0 0 var(--c-accent); }
:is(table.data, .table-wrap > table) tbody tr:last-child td { border-bottom: 0; }
:is(table.data, .table-wrap > table) td.num, :is(table.data, .table-wrap > table) th.num { text-align: right; }
:is(table.data, .table-wrap > table) td.mono { font-family: var(--f-mono); font-size: var(--t-sm); }
:is(table.data, .table-wrap > table) td.nowrap, :is(table.data, .table-wrap > table) th.nowrap { white-space: nowrap; }
:is(table.data, .table-wrap > table) td.shrink { width: 1%; white-space: nowrap; }
/* A whole row can be a link target for HTMX. */
:is(table.data, .table-wrap > table) tr[hx-get], :is(table.data, .table-wrap > table) tr[data-href] { cursor: pointer; }

.pager { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
         font-family: var(--f-mono); font-size: var(--t-xs); letter-spacing: .08em; color: var(--c-ink-2); }
.pager .grow { flex: 1 1 auto; }


/* == 7 · FORMS AND BUTTONS =============================================== */

.field { display: block; margin-bottom: var(--s-4); }
.field > label, label.lab {
  display: block; font-family: var(--f-mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; margin-bottom: var(--s-2); color: var(--c-ink-2);
}
.field .help { display: block; font-size: var(--t-sm); color: var(--c-ink-3); margin-top: var(--s-1); }
.field .err  { display: block; font-size: var(--t-sm); color: var(--c-bad); margin-top: var(--s-1); }

/* input:not([type]) - a text box written without type="text" is a text box.
   Missing here, S11's Name and Location, W2's Name and every other untyped
   input drew at the browser's own width and cut its example off (Walkthrough
   v0.1.7; Readiness plan, Narrow Fields). */
input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="password"],
input[type="number"], input[type="date"], input[type="datetime-local"], input[type="url"],
input[type="tel"], select, textarea {
  width: 100%;
  font: var(--t-md)/1.4 var(--f-ui);
  color: var(--c-ink);
  background: var(--c-bg);
  border: var(--bd);
  border-radius: var(--r-md);
  padding: 8px 11px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* 16px on touch keeps iOS from zooming the whole page on focus. */
@media (pointer: coarse) {
  input, select, textarea { font-size: var(--t-lg); padding: 10px 12px; }
}
input:hover, select:hover, textarea:hover { border-color: var(--c-line-strong); }
/* The field you are in is where you are: green edge and glow. */
input:focus, select:focus, textarea:focus { border-color: var(--c-accent); outline-offset: 1px; box-shadow: var(--glow-soft); }
input[aria-invalid="true"], select[aria-invalid="true"] { border-color: var(--c-bad); box-shadow: var(--glow-bad); }
input:disabled, select:disabled, textarea:disabled { opacity: .5; cursor: not-allowed; }
input::placeholder, textarea::placeholder { color: var(--c-ink-3); }
textarea { min-height: 90px; resize: vertical; }
select { appearance: none; padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--c-ink-2) 50%),
                    linear-gradient(135deg, var(--c-ink-2) 50%, transparent 50%);
  background-position: right 15px center, right 10px center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }

.check { display: flex; align-items: flex-start; gap: var(--s-2); margin-bottom: var(--s-2);
         font-size: var(--t-md); cursor: pointer; }
.check input { width: auto; margin: 3px 0 0; accent-color: var(--c-accent); }

/* Buttons are green because you can press them. Every button. The rule. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  font: 600 13px/1 var(--f-ui); letter-spacing: var(--track); text-transform: uppercase;
  color: var(--c-accent-hover);
  background: var(--c-accent-soft);
  border: var(--bd-strong);
  border-radius: var(--r-md);
  padding: 10px 16px;
  min-height: 38px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn:hover { border-color: var(--c-accent); box-shadow: var(--glow-soft); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .4; cursor: not-allowed; transform: none; box-shadow: none; }
/* The primary: the one thing most people came here to press. Full glow. */
/* rc.47, JW's rc.46 notes: "Make primary action buttons visually
   dominant." Filled with the accent, dark label; every other button stays
   outlined, so the one to press is the one that is solid. */
.btn.primary { border-color: var(--c-accent); color: var(--c-ink-on-accent); background: var(--c-accent);
               box-shadow: var(--glow); text-shadow: none; }
.btn.primary:hover { background: color-mix(in srgb, var(--c-accent) 85%, #fff); color: var(--c-ink-on-accent); }
/* Danger is red because it breaks something. Outlined, never filled: a red slab reads as "already broken". */
.btn.danger  { background: transparent; border-color: var(--c-bad); color: var(--c-bad); }
.btn.danger:hover { box-shadow: var(--glow-bad); }
/* Warn (amber) — the action a "needs you" state offers. */
.btn.warn { background: transparent; border-color: var(--c-warn); color: var(--c-warn); }
.btn.warn:hover { box-shadow: var(--glow-warn); }
/* Quiet is still green — it is still a button. Just no box. */
.btn.quiet   { background: transparent; border-color: transparent; color: var(--c-accent); }
.btn.quiet:hover { background: var(--c-accent-soft); box-shadow: none; }
.btn.sm { min-height: 30px; padding: 5px 10px; font-size: var(--t-xs); }
/* rc.54: Copy beside a hostname or an address - small, never the loudest thing. */
.btn.xs { min-height: 22px; padding: 1px 7px; font-size: 10px; vertical-align: middle; }
/* A hostname is a link that opens it (rc.54, JW: "Visible. Copyable. Clickable."). */
a.hostlink { color: var(--c-ink); border-bottom: 1px dotted var(--c-ink-2); }
a.hostlink:hover { color: var(--c-accent-hover); text-decoration: none; border-bottom-color: currentColor; }
/* Advanced (rc.54, JW: "Keep advanced actions under Advanced"): the actions a
   day does not need, one click away. */
details.adv { border-top: 1px dashed var(--c-line); padding-top: var(--s-2); }
details.adv > summary { cursor: pointer; font-size: var(--t-xs); letter-spacing: .12em; text-transform: uppercase;
                        color: var(--c-ink-2); list-style: none; }
details.adv > summary::-webkit-details-marker { display: none; }
details.adv > summary::before { content: "+ "; }
details.adv[open] > summary::before { content: "\2212 "; }
details.adv > .stack { margin-top: var(--s-2); }
dl.facts.urls dd { overflow-wrap: anywhere; }

/* A color, offered as itself. The swatch IS the color - there is nothing to
   read, so the label is for a screen reader and the title is for a mouse. */
.swatch { width: 26px; height: 26px; padding: 0; cursor: pointer; border-radius: var(--r-md);
          border: 1px solid var(--c-line-strong); }
.swatch:hover { transform: translateY(-1px); }
.swatch[aria-pressed="true"] { outline: 2px solid var(--c-ink); outline-offset: 2px; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Sliders. The track is the panel's own hairline; the thumb is the accent. */
input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 22px;
                      background: transparent; cursor: pointer; }
input[type="range"]::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: var(--c-line-strong); }
input[type="range"]::-moz-range-track { height: 4px; border-radius: 2px; background: var(--c-line-strong); }
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; margin-top: -6px;
  width: 16px; height: 16px; border-radius: 50%; background: var(--c-accent); border: 0; box-shadow: var(--glow-soft); }
input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%;
  background: var(--c-accent); border: 0; box-shadow: var(--glow-soft); }
input[type="range"]:focus-visible { outline: 2px solid var(--c-focus); outline-offset: 3px; }
input[type="color"] { cursor: pointer; }
.btn svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.75;
           stroke-linecap: round; stroke-linejoin: round; }
/* Touch targets: 44px minimum on a coarse pointer. Gloves exist. */
@media (pointer: coarse) { .btn { min-height: 44px; padding: 11px 17px; } }

.btn-group { display: inline-flex; }
.btn-group .btn { border-radius: 0; margin-left: -1px; }
.btn-group .btn:first-child { border-radius: var(--r-md) 0 0 var(--r-md); margin-left: 0; }
.btn-group .btn:last-child  { border-radius: 0 var(--r-md) var(--r-md) 0; }

.toolbar { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
           padding: var(--s-2) var(--s-4); background: transparent;
           border-bottom: var(--bd); }
.toolbar .grow { flex: 1 1 auto; }
.toolbar input[type="search"] { max-width: 320px; }


/* == 8 · STATUS, BADGES, ALERTS ==========================================
   THE GREEN RULE, applied to status:
     ok      = GRAY.  Nothing for you to do. (v0.1.0 said green. Superseded.)
     warn    = AMBER. Needs you.
     bad     = RED.   Broken.
     unknown = faint gray, dashed border. We do not know, and saying so is the point.
   Put a "✓" in an ok badge's text so gray-good and gray-unknown never read alike. */

.dot { display: inline-block; width: 9px; height: 9px; border-radius: 999px;
       background: var(--c-unknown); flex: 0 0 auto; }
.dot.ok { background: var(--c-ok); box-shadow: var(--glow-good); } .dot.warn { background: var(--c-warn); box-shadow: var(--glow-warn); }
.dot.bad { background: var(--c-bad); box-shadow: var(--glow-bad); } .dot.unknown { background: var(--c-unknown); }

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 10px/1 var(--f-mono); letter-spacing: .16em; text-transform: uppercase;
  padding: 5px 9px; border-radius: var(--r-pill);
  border: 1px solid var(--c-line);
  color: var(--c-ink-2); background: transparent;
}
.badge.ok      { color: var(--c-ok);   border-color: color-mix(in srgb, var(--c-good) 45%, transparent); background: var(--c-good-soft); }
.badge.warn    { color: var(--c-warn); border-color: var(--c-warn); }
.badge.bad     { color: var(--c-bad);  border-color: var(--c-bad); }
.badge.unknown { color: var(--c-unknown); border-style: dashed; }
.badge.neutral { color: var(--c-ink-2); border-color: var(--c-line); }
/* A badge you can act on (a filter chip, a "+ tag", an open collection) is green. */
.badge.act, a.badge { color: var(--c-accent-hover); border-color: var(--c-line-strong); background: var(--c-accent-soft); }

.alert { display: flex; gap: var(--s-3); padding: var(--s-3) var(--s-4);
         border: var(--bd); border-left-width: 3px; border-radius: var(--r-md);
         background: var(--c-surface); margin-bottom: var(--s-4); font-size: var(--t-md); }
.alert p:last-child { margin-bottom: 0; }
.alert.ok   { border-left-color: var(--c-good); background: var(--c-good-soft); }
.alert.warn { border-left-color: var(--c-warn); background: var(--c-warn-soft); box-shadow: var(--glow-warn); }
.alert.bad  { border-left-color: var(--c-bad);  background: var(--c-bad-soft); box-shadow: var(--glow-bad); }
.alert .t { font-weight: 700; display: block; margin-bottom: 2px; }

/* A bar meter — capacity, progress, utilization. Green when it is something
   you drive (a scrubber, a progress you started); gray when it is just a level. */
.meter { position: relative; height: 8px; border: var(--bd); background: var(--c-accent-soft); overflow: visible; }
.meter > span { display: block; height: 100%; background: linear-gradient(90deg, transparent, var(--c-accent));
                box-shadow: var(--glow); }
.meter.level > span { background: var(--c-ink-2); box-shadow: none; }
.meter.ok > span   { background: var(--c-ink-2); box-shadow: none; }
.meter.warn > span { background: var(--c-warn); box-shadow: var(--glow-warn); }
.meter.bad > span  { background: var(--c-bad);  box-shadow: var(--glow-bad); }
/* The knob on a meter you can drag. */
.meter > b { position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px;
             border-radius: 999px; background: #fff; box-shadow: 0 0 var(--glow-r) 3px var(--glow-c); }

/* A ring gauge: <svg class="ring" viewBox="0 0 48 48"> track + progress circle + text.
   The color is the series it belongs to, set on the tile around it. */
.ring { width: 50px; height: 50px; flex: none; }
.ring circle.t { fill: none; stroke: var(--c-surface-3); stroke-width: 4; }
.ring circle.p { fill: none; stroke: var(--c-series, var(--c-ink-2)); stroke-width: 4; stroke-linecap: round;
                 transform: rotate(-90deg); transform-origin: 50% 50%;
                 filter: drop-shadow(0 0 3px color-mix(in srgb, var(--c-series, var(--c-ink-2)) 60%, transparent)); }
.ring text { fill: var(--c-ink); font-family: var(--f-mono); font-size: 11px; font-weight: 600;
             text-anchor: middle; dominant-baseline: central; }


/* == 9 · DIALOG, TABS, EMPTY STATES ======================================
   Native elements. <dialog> and <details> are real components now — this
   is why we do not install a component library.                         */

dialog {
  border: var(--bd-strong); border-radius: var(--r-lg);
  background: var(--c-surface); color: var(--c-ink);
  padding: 0; max-width: min(560px, 92vw); box-shadow: var(--shadow), var(--glow-soft);
}
dialog::backdrop { background: rgba(0,0,0,.72); }
dialog .hd { padding: var(--s-4); border-bottom: var(--bd); }
dialog .hd h3 { margin: 0; font-family: var(--f-mono); font-size: var(--t-xs); letter-spacing: .2em;
                text-transform: uppercase; color: var(--c-ink-2); font-weight: 500; }
dialog .bd { padding: var(--s-4); }
dialog .ft { padding: var(--s-3) var(--s-4); border-top: var(--bd);
             background: var(--c-surface-2); display: flex; gap: var(--s-2); justify-content: flex-end; }

details.disclose { border: var(--bd); border-radius: var(--r-md); background: var(--c-surface);
                   margin-bottom: var(--s-3); }
details.disclose > summary { padding: var(--s-3) var(--s-4); cursor: pointer; color: var(--c-accent);
                             font-weight: 600; font-size: var(--t-md); list-style-position: inside; }
details.disclose > summary:hover { background: var(--c-surface-2); }
details.disclose[open] > summary { border-bottom: var(--bd); }
details.disclose > .bd { padding: var(--s-4); }

.tabs { display: flex; gap: var(--s-1); border-bottom: var(--bd); margin-bottom: var(--s-4);
        overflow-x: auto; }
.tabs a, .tabs button {
  padding: var(--s-2) var(--s-3); font: 600 13px/1.4 var(--f-ui); letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--c-ink-2); background: none; border: 0; border-bottom: 2px solid transparent;
  cursor: pointer; white-space: nowrap;
}
.tabs a:hover, .tabs button:hover { color: var(--c-ink); text-decoration: none; }
/* The current tab is where you are. */
.tabs [aria-current="true"], .tabs [aria-selected="true"] {
  color: var(--c-accent-hover); border-bottom-color: var(--c-accent); text-shadow: var(--glow-text); }

/* Empty state. Start with nothing and still look deliberate. */
.empty { text-align: center; padding: var(--s-7) var(--s-4); color: var(--c-ink-2); }
.empty h3 { color: var(--c-ink); margin-bottom: var(--s-2); }
.empty p { margin-inline: auto; max-width: 46ch; }
.empty .actions { margin-top: var(--s-4); }


/* == 10 · HTMX STATES, UTILITIES, PRINT ==================================
   Every request must show it is happening. A screen that looks frozen is
   a screen someone clicks twice.                                        */

.htmx-indicator { opacity: 0; transition: opacity var(--dur) var(--ease); }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }
[aria-busy="true"] { cursor: progress; }
.htmx-swapping { opacity: .5; transition: opacity var(--dur) var(--ease); }
.htmx-settling { opacity: 1; }

/* A thin top progress bar for long fetches. Pure CSS. Green: it is the platform doing what you asked. */
.busy-bar { height: 2px; background: var(--c-line); overflow: hidden; }
.busy-bar > span { display: block; height: 100%; width: 30%; background: var(--c-accent); box-shadow: var(--glow-text);
                   animation: busy 1.1s var(--ease) infinite; }
@keyframes busy { 0% { transform: translateX(-100%); } 100% { transform: translateX(400%); } }

/* The apply dial. A ring that fills stage by stage - the arc is the work
   done, the thin outer ring turns while anything is running. Green, because
   it is the platform doing what you asked. */
.dial { display: flex; align-items: center; gap: 18px; padding: 6px 0; }
.dial svg { flex: none; }
.dial-track { fill: none; stroke: var(--c-line); stroke-width: 6; }
.dial-arc   { fill: none; stroke: var(--c-accent); stroke-width: 6; stroke-linecap: round;
              transform: rotate(-90deg); transform-origin: 50% 50%;
              transition: stroke-dashoffset .6s var(--ease); filter: drop-shadow(0 0 4px var(--c-accent)); }
.dial-spin  { fill: none; stroke: var(--c-accent); stroke-width: 1.5; stroke-dasharray: 40 250; opacity: .7;
              transform-origin: 50% 50%; animation: dial-turn 1.6s linear infinite; }
.dial-n     { fill: var(--c-ink); font: 600 15px var(--f-mono); }
.dial-stage { font-weight: 600; }
@keyframes dial-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .dial-spin { animation: none; } }

/* A log shown on a page: the end of a file, as it is. */
pre.log { max-height: 320px; overflow: auto; font-size: var(--t-xs); white-space: pre; }

/* A pressed button, working. busy.js swaps the label for this ring and a
   word the moment the click lands, and it stays until the next page. JW,
   2026-09-10: "run again? i clicked it and nothing happened". */
.btn.busy { cursor: progress; opacity: .85; }
.btn .ring { display: inline-block; width: 13px; height: 13px; border-radius: 50%;
             border: 2px solid var(--c-line-strong); border-top-color: var(--c-accent);
             animation: dial-turn .8s linear infinite; }
.btn.sm .ring { width: 11px; height: 11px; }
.btn.primary .ring { border-top-color: var(--c-ink-on-accent); }
@media (prefers-reduced-motion: reduce) { .btn .ring { animation: none; border-top-color: var(--c-line-strong); } }

/* Done. A machine that is set up says so, in the place the button was. */
.done { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; color: var(--c-ink-2); }
.done .badge { font-size: var(--t-xs); padding: 6px 11px; }

/* Centered frames (NEST's sign-in and first run). */
.center > p, p.center { margin-inline: auto; }
.center .panel { text-align: start; }

/* Utilities. This list is closed — do not add a utility framework. */
.muted     { color: var(--c-ink-2); }
.faint     { color: var(--c-ink-3); }
.mono      { font-family: var(--f-mono); }
.num       { font-variant-numeric: tabular-nums; }
.right     { text-align: right; }
.center    { text-align: center; }
.nowrap    { white-space: nowrap; }
.truncate  { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-xs { font-size: var(--t-xs); } .t-sm { font-size: var(--t-sm); }
.t-lg { font-size: var(--t-lg); } .t-xl { font-size: var(--t-xl); }
.hide      { display: none !important; }
.sr-only   { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
             overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-4 { margin-top: var(--s-4); } .mb-4 { margin-bottom: var(--s-4); }

@media print {
  :root { color-scheme: light; --dim: 1; }
  .band, .rail, .toolbar, .pager, .btn, .htmx-indicator, .busy-bar { display: none !important; }
  .app { display: block; }
  .main { padding: 0; }
  body { background: #fff; color: #000; }
  .panel { border: 1px solid #999; break-inside: avoid; background: #fff; box-shadow: none; }
  .panel::before, .panel::after { display: none; }
  .panel > .hd { background: #f2f2f2; }
  .panel > .hd h3, .facts dt, .facts dd, .stat .value { color: #000; }
  table.data thead th { position: static; background: #f2f2f2; color: #000; }
  a { color: #000; text-decoration: underline; }
}

/* ============================================================================
   CHARTS AND TILES (v0.4.0). Drawn as SVG from the numbers, with no library
   and no script - the panel's CSP allows neither. Each carries a series
   class (s1..s6) that sets --c-series; the shapes take that. Warn and bad
   still mean what they mean.
   ========================================================================= */
.s1 { --c-series: var(--c-s1); } .s2 { --c-series: var(--c-s2); } .s3 { --c-series: var(--c-s3); }
.s4 { --c-series: var(--c-s4); } .s5 { --c-series: var(--c-s5); } .s6 { --c-series: var(--c-s6); }
.good { --c-series: var(--c-good); } .tile.warn { --c-series: var(--c-warn); } .tile.bad { --c-series: var(--c-bad); }

/* The tiles: the number now. Six across, wrapping to three, then two. */
.tiles { display: grid; gap: var(--s-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); }
.tile { padding: 0; }
.tile::before, .tile::after { display: none; }
.tile .tile-b { display: flex; align-items: center; gap: var(--s-2); padding: 12px 10px 10px 14px; min-height: 92px;
                border-left: 3px solid var(--c-series);
                background: radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--c-series) 14%, transparent), transparent 55%); }
.tile .label { font-family: var(--f-mono); font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--c-ink-3); }
.tile .value { font-size: 24px; font-weight: 700; line-height: 1.15; color: var(--c-ink); margin-top: 2px;
               font-variant-numeric: tabular-nums; font-family: var(--f-mono); }
.tile .value .unit, .chart-card .now .unit { font-size: .5em; font-weight: 500; color: var(--c-ink-2); margin-left: 2px; }
.tile .foot { font-size: 10.5px; line-height: 1.3; color: var(--c-ink-2); margin-top: 3px; }
.tile .grow { min-width: 0; }
.tile.warn .value, .tile.bad .value { color: var(--c-series); text-shadow: 0 0 10px color-mix(in srgb, var(--c-series) 50%, transparent); }

/* The charts: what has been happening. Three across, then two, then one. */
.charts { display: grid; gap: var(--s-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.chart-card { padding: 0; }
.chart-card::before, .chart-card::after { display: none; }
.chart-hd { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3);
            padding: 12px 14px 4px; }
.chart-hd .label { font-family: var(--f-mono); font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--c-ink-3); }
.chart-card .now { font: 700 22px/1 var(--f-mono); color: var(--c-series); font-variant-numeric: tabular-nums;
                   text-shadow: 0 0 12px color-mix(in srgb, var(--c-series) 45%, transparent); white-space: nowrap; }
/* The y scale in a gutter of its own, beside the drawing, not over it. */
.chart-wrap { display: grid; grid-template-columns: 44px 1fr; gap: 6px; padding: 4px 14px 12px 10px; }
.chart-y { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end;
           font: 9px/1 var(--f-mono); color: var(--c-ink-3); padding: 2px 0 1px; white-space: nowrap; }
.chart { display: block; width: 100%; height: 110px; overflow: visible; min-width: 0; }
.chart .stop-a { stop-color: var(--c-series); stop-opacity: .55; }
.chart .stop-b { stop-color: var(--c-series); stop-opacity: .02; }
.chart-area { stroke: none; }
.chart-line { fill: none; stroke: var(--c-series); stroke-width: 1.75;
              stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke;
              filter: drop-shadow(0 0 4px color-mix(in srgb, var(--c-series) 70%, transparent)); }
.chart-line2 { fill: none; stroke: var(--c-series); stroke-width: 1.25; stroke-dasharray: 4 3; opacity: .7;
               vector-effect: non-scaling-stroke; }
.chart-dot  { fill: var(--c-series); stroke: var(--c-bg); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.chart-grid { stroke: var(--c-line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.chart-rule { stroke: var(--c-warn); stroke-width: 1; stroke-dasharray: 3 3; opacity: .7; vector-effect: non-scaling-stroke; }
.chart-empty { padding: 18px 14px 22px; }
@media (max-width: 560px) { .chart { height: 84px; } }

/* A number with a ceiling, drawn against it. Amber at 80, red at 92. */
.gauges { display: grid; gap: 10px; margin-bottom: 4px; }
.gauge-t { display: flex; justify-content: space-between; font-size: var(--t-sm); color: var(--c-ink-2); }
.gauge-bar { height: 6px; margin-top: 4px; border-radius: 3px; background: var(--c-surface-3); overflow: hidden; }
.gauge-bar i { display: block; height: 100%; border-radius: 3px; }
.gauge-bar i.ok   { background: var(--c-good); box-shadow: var(--glow-good); }
.gauge-bar i.warn { background: var(--c-warn); }
.gauge-bar i.bad  { background: var(--c-bad); }

/* THE CLUSTER. One Authority, its components, the organizations under it. It
   is a tree because that is the shape of the thing: a component can move to
   its own machine, and a unit belongs to exactly one organization. */
.cluster { display: block; width: 100%; height: auto; }
.cluster .edge { fill: none; stroke: var(--c-line-strong); stroke-width: 1; }
.cluster .node rect { fill: var(--c-surface-3); stroke: var(--c-line-strong); stroke-width: 1;
                      filter: drop-shadow(0 3px 6px rgba(0,0,0,.5)); }
.cluster .node .n-t { fill: var(--c-ink); font: 600 13px var(--f-ui); }
.cluster .node .n-s { fill: var(--c-ink-3); font: 11px var(--f-mono); }
.cluster .root rect { stroke: var(--c-accent); fill: color-mix(in srgb, var(--c-accent) 10%, var(--c-surface-3)); filter: drop-shadow(var(--glow-soft)); }
.cluster .root .n-t { fill: var(--c-accent); }
.cluster .ok   rect { stroke: color-mix(in srgb, var(--c-good) 60%, var(--c-line-strong)); }
.cluster .ok   .n-s { fill: var(--c-good); }
.cluster .warn rect { stroke: var(--c-warn); }
.cluster .warn .n-s { fill: var(--c-warn); }
.cluster .bad  rect { stroke: var(--c-bad); }
.cluster .bad  .n-s { fill: var(--c-bad); }
.cluster .off  rect { stroke-dasharray: 4 3; }
.cluster .off  .n-t { fill: var(--c-ink-3); }

/* The wizard's own chrome: where you are in it, and how far there is to go.
   It lives in the panel BODY - panel()'s note is escaped, and rendered there
   this row came out as its own source code across the top of every step. */
.steps { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.steps .step { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 4px;
               border: 1px solid var(--c-line); border-radius: 999px;
               font-size: var(--t-xs); color: var(--c-ink-3); white-space: nowrap; }
.steps .step i { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
                 font-style: normal; font: 600 10px var(--f-mono);
                 background: var(--c-surface-3); color: var(--c-ink-3); }
/* rc.47: completed steps read as completed - bright, accent ring and a
   filled number (JW's rc.46 notes). The current step keeps its glow. */
.steps .done { color: var(--c-ink); border-color: color-mix(in srgb, var(--c-accent) 60%, transparent); }
.steps .done i { background: var(--c-accent); color: var(--c-ink-on-accent); }
.steps .now { color: var(--c-ink); border-color: var(--c-accent); box-shadow: var(--glow-soft); }
.steps .now i { background: var(--c-accent); color: var(--c-ink-on-accent); }
/* The markers are links (v0.3.2): a step opens when it is picked. */
.steps a.step { text-decoration: none; cursor: pointer; }
.steps a.step:hover { border-color: var(--c-accent); color: var(--c-ink); }
.steps a.step:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* Checkboxes and radios follow the accent like everything else. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--c-accent); width: 15px; height: 15px; }

/* The install dial's bar. One rule, and a red state for a run that stopped. */
.bar { height: 6px; background: var(--c-line, #222830); border-radius: 3px; overflow: hidden; margin: 6px 0; }
.bar > span { display: block; height: 100%; background: var(--c-accent); transition: width .4s ease; }
.bar.bad > span { background: var(--c-bad, #e05260); }
#idlog { white-space: pre-wrap; word-break: break-word; background: var(--c-card, #12151a);
         border: 1px solid var(--c-line, #222830); padding: 10px; border-radius: 4px; margin: 0; }

/* hidden means hidden. The attribute only works through the user-agent sheet's
   [hidden]{display:none}, which any author rule on the same element outranks -
   .stack, .field and .btn all set display, so five of the six things
   install.js hides stayed on screen: Back, Next and Install together over a
   dial that had never started (fresh review of rc.27, loop 3, finding 1). */
[hidden] { display: none !important; }


/* == rc.29 · the band in the rail, green Install, named steps, tables that sort ==
   JW, 2026-09-13: "roll the banner at the top to the side bar ... less space
   less bloat" · "move the NEXT/INSTALL to the right and leave BACK to the left
   - when you get to 'INSTALL' highlight it green" · "a table has clickable
   titles so they sort and a search box above each to filter". */
.app { grid-template-areas: "rail main"; grid-template-rows: 1fr; }
.rail { display: flex; flex-direction: column; position: sticky; top: 0; max-height: 100dvh; padding-top: 0; }
.rail .brand { display: block; padding: 14px var(--s-3) 10px; border-left: 0; border-bottom: var(--bd);
               font-weight: 700; letter-spacing: .3em; font-size: 12px; text-transform: uppercase;
               color: var(--c-accent); text-shadow: var(--glow-text); text-decoration: none; }
.rail .brand:hover { background: none; color: var(--c-accent-hover); }
.rail .band.side { position: static; margin-top: auto; display: flex; flex-direction: column; align-items: stretch;
                   gap: 2px; padding: var(--s-2); border-bottom: 0; border-top: var(--bd); height: auto; }
.band.side .clock { padding: 4px 10px; }
.band.side .menu { margin-left: 0; }
.band.side .menu > summary { padding: 5px 10px; }
.band.side .menu > summary.who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
.band.side .menu > .pop { left: 0; right: auto; top: auto; bottom: calc(100% + 6px); }
@media (max-width: 900px) {
  .app { grid-template-areas: "rail" "main"; grid-template-rows: auto 1fr; }
  .rail { position: static; max-height: none; flex-direction: row; }
  .rail .brand { border-bottom: 0; padding: 11px var(--s-2); }
  .rail .band.side { margin-top: 0; flex-direction: row; align-items: center; border-top: 0; padding: 0 var(--s-2); }
  /* The strip clips overflow; a menu inside it must escape the clip (loop 2, F-01). */
  .band.side .menu > .pop { position: fixed; left: auto; right: 8px; top: 48px; bottom: auto; max-height: calc(100dvh - 60px); overflow: auto; }
}
/* Back left, Next/Install right; Install is green whatever the accent. */
.wiznav { display: flex; align-items: center; gap: 8px; }
.wiznav .grow { flex: 1 1 auto; }
/* Done: an action already taken - green, and not pressable (rc.47). */
.btn.done, .btn.done[disabled] { opacity: 1; cursor: default; border-color: var(--c-good); color: var(--c-good);
               background: var(--c-good-soft); box-shadow: none; }
.facts.cfstate { margin: 4px 0 12px; }
/* rc.50, JW's rc.49 review: Connect → Assign → Route. "Always reserve three
   positions. Same position. Same width. States change. Buttons do not move."
   Each button carries its own state; the word, then one line under it. */
.tsteps { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; gap: 10px; align-items: stretch; margin: 6px 0 8px; }
.btn.tstep { flex-direction: column; align-items: center; justify-content: center; gap: 6px;
             width: 100%; min-height: 66px; padding: 10px 14px; text-align: center; }
.btn.tstep .tstep-w { display: inline-flex; align-items: center; gap: 8px; }
.btn.tstep .tstep-s { font: 400 12px/1.2 var(--f-mono); text-transform: none; letter-spacing: 0;
                      max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: .9; }
.btn.tstep[disabled]:not(.done) { opacity: .4; }
.btn.tstep .ok { color: var(--c-good); }
.btn.tstep .warn { color: var(--c-warn); }
.btn.tstep .bad { color: var(--c-bad); }
.tstep-a { align-self: center; color: var(--c-ink-3); font-size: 18px; }
/* rc.52, JW's RC.51 Tunnel Workflow Review: Hostnames -> Zones -> Tunnel ->
   Routes. The zone count reads as an Authority of any number of brands; what
   a press did is said beside it; Next waits, and says for what. */
.zcount { display: flex; align-items: baseline; gap: 10px; margin: 2px 0 12px; }
.zcount-n { font: 700 26px/1 var(--f-mono); color: var(--c-ink); }
.zcount-w { font-family: var(--f-mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--c-ink-3); }
.alert.beside { margin: 10px 0 0; }
#cfhint.beside:empty { display: none; }
#cfhint.beside { margin-top: 8px; }
.row.tact { align-items: center; gap: 10px; margin-top: 12px; }
.wiznav .owed { margin-right: 4px; }
table.zones td:last-child { text-align: right; }
.facts .ok { color: var(--c-good); } .facts .warn { color: var(--c-warn); } .facts .bad { color: var(--c-bad); }
@media (max-width: 640px) { .tsteps { grid-template-columns: 1fr; } .tstep-a { display: none; } }
.btn.go { border-color: var(--c-good); color: var(--c-good); background: var(--c-good-soft);
          box-shadow: var(--glow-good), inset 0 0 14px var(--c-good-soft); font-weight: 700; }
.btn.go:hover { background: color-mix(in srgb, var(--c-good) 22%, transparent); color: #fff; }
/* The dial's named steps, and the one that stopped. */
.steps.stagebar { margin-bottom: 8px; }
.steps .bad { color: var(--c-bad); border-color: var(--c-bad); }
.steps .bad i { background: var(--c-bad); color: #fff; }
/* One dot per way of reaching the panel, at the end of its row. */
.pick.reach { display: flex; align-items: center; gap: 8px; flex: 1 1 100%; }
/* rc.51: New Server's License step - one row per license, then None. */
.picks { display: flex; flex-direction: column; gap: 10px; margin: 8px 0 12px; }
.picks .pick { display: flex; gap: 10px; align-items: baseline; }
.picks .pick .muted { margin-left: 4px; }
.pick.reach .muted { flex: 1 1 auto; }
.pick.reach .ready { flex: 0 0 auto; }
/* Titles that sort, a filter row that reads as a filter row. */
table.sortable thead th[data-sort] { cursor: pointer; user-select: none; }
table.sortable thead th[data-sort]:hover { color: var(--c-ink); }
table.sortable thead th[aria-sort="ascending"]::after { content: " \2191"; color: var(--c-accent); }
table.sortable thead th[aria-sort="descending"]::after { content: " \2193"; color: var(--c-accent); }
table.sortable thead tr.filters th { top: 30px; padding: 3px 6px; border-bottom: var(--bd); }
table.sortable thead tr.filters input { width: 100%; min-width: 48px; padding: 3px 6px; font-size: var(--t-xs);
                                          font-family: var(--f-mono); letter-spacing: 0; text-transform: none; }
.group-title { font-family: var(--f-mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
               color: var(--c-ink-3); margin: var(--s-3) 0 var(--s-2); }

/* == rc.30 · the account at the top, the statuses in the rail ==
   JW, 2026-09-13: "you put my account info in the side bar - leave it at the
   top - just move the statuses". The band is back over both columns, thin,
   carrying the mark and the two menus; the rail's foot keeps the clock. */
.app { grid-template-areas: "band band" "rail main"; grid-template-rows: var(--band-h) 1fr; }
.band { min-height: 0; height: var(--band-h); padding: 0 var(--s-4); gap: var(--s-3); }
.band .mark { text-decoration: none; }
.band .mark:hover { color: var(--c-accent-hover); text-decoration: none; }
.band .menu > .pop { left: auto; right: 0; top: calc(100% + 6px); bottom: auto; }
.rail { top: var(--band-h); max-height: calc(100dvh - var(--band-h)); padding-top: var(--s-2); }
.rail .band.side { padding: var(--s-2) var(--s-2); }
@media (max-width: 900px) {
  .app { grid-template-areas: "band" "rail" "main"; grid-template-rows: var(--band-h) auto 1fr; }
  .rail { top: auto; max-height: none; }
  .band .menu > .pop { position: absolute; right: 0; top: calc(100% + 6px); max-height: calc(100dvh - 60px); overflow: auto; }
}
/* The tunnel row's Add sits in the row; "kept" reads as a state, not a hint. */
.pick.reach [data-tunnel-add] { margin-left: 6px; }
input[data-kept]::placeholder, textarea[data-kept]::placeholder { color: var(--c-ink-2); opacity: 1; font-style: normal; letter-spacing: .15em; }
.band .mark { white-space: nowrap; }
@media (max-width: 700px) { .band .mark { letter-spacing: .18em; font-size: 12px; } }
/* The typed confirmation (rc.33): a small dialog of the page's own. */
dialog.confirm { background: var(--c-surface); color: var(--c-ink); border: var(--bd-strong); border-radius: var(--r-lg);
                 box-shadow: var(--shadow); padding: var(--s-4); min-width: 320px; max-width: 92vw; }
dialog.confirm::backdrop { background: rgba(0,0,0,.6); }
dialog.confirm label { display: block; margin-bottom: var(--s-2); font-size: var(--t-sm); color: var(--c-ink-2); }
dialog.confirm label code { color: var(--c-ink); font-family: var(--f-mono); }
dialog.confirm input { width: 100%; margin-bottom: var(--s-3); font-family: var(--f-mono); letter-spacing: 0; text-transform: none; }
dialog.confirm .row { display: flex; align-items: center; gap: 8px; }
dialog.confirm .row .grow { flex: 1 1 auto; }
/* An organization's Cloudflare (rc.36): one block per domain, lines that
   wrap - a table with a form in a cell ran wider than the panel. The token
   box has its own labelled line. */
.cfdoms { display: flex; flex-direction: column; gap: var(--s-2); margin-top: var(--s-3); }
.cfdom { border-top: var(--bd); padding-top: var(--s-2); min-width: 0; }
.cfline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; padding: 3px 0; }
.cfline .lab { font-family: var(--f-mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
               color: var(--c-ink-3); flex: 0 0 76px; }
.cfline .grow { flex: 1 1 auto; }
.cfline > input[type="password"] { flex: 1 1 200px; min-width: 160px; width: auto; }
.cfline > select { width: auto; flex: 0 1 240px; }
.cfline form { display: inline; }
.cftoken { background: var(--c-surface-2); padding: 6px 8px; margin-top: 4px; }
/* rc.52: Settings -> Backup. Restore, then Download; the passphrase form
   opens under Download and moves nothing. */
.bkacts { display: flex; flex-wrap: nowrap; align-items: flex-start; gap: 6px; }
.bkact > summary { list-style: none; }
.bkact > summary::-webkit-details-marker { display: none; }
.bkact[open] form { display: grid; gap: 6px; margin-top: 6px; min-width: 220px; }
/* rc.53: Tunnel - the primary first, Choose New Name after it, Refresh last,
   whatever order the form needs them in. */
.row.tact > details.bkact { order: 5; }
.row.tact > a.btn.quiet { order: 6; }
.zstate { margin-right: 8px; }
/* rc.55 (JW's RC.54 corrections: the server page restructured; MORE; the
   five sync states; sections to jump to). */
/* MORE in a page's head: the band's menu, in the page. */
.hmenu { position: relative; }
.hmenu > summary { list-style: none; cursor: pointer; }
.hmenu > summary::-webkit-details-marker { display: none; }
.hmenu[open] > summary::before { content: ""; position: fixed; inset: 0; z-index: 30; cursor: default; }
.hmenu > .pop { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; min-width: 220px;
                padding: var(--s-2); display: flex; flex-direction: column; gap: 2px;
                background: var(--c-surface); border: var(--bd-strong); border-radius: var(--r-lg); box-shadow: var(--shadow); }
.hmenu > .pop form { margin: 0; display: block !important; }
.hmenu > .pop .item { display: block; width: 100%; text-align: left; padding: 6px 10px; border: 0;
                      border-radius: var(--r-sm); background: none; color: var(--c-accent); font: inherit;
                      font-size: var(--t-sm); font-weight: 600; cursor: pointer; }
.hmenu > .pop .item:hover { background: var(--c-surface-2); color: var(--c-ink); }
.hmenu > .pop .item.danger { color: var(--c-bad); }
.hmenu > .pop .sep { border-top: var(--bd); margin: 4px 0; }
/* The line under a server's name: what it is, at a glance. */
.hstat { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: -6px 0 var(--s-3);
         font-size: var(--t-sm); color: var(--c-ink-2); }
.hstat .mono { color: var(--c-ink); }
/* Sections of a long page, to jump to. */
.tabs.secnav { position: sticky; top: 0; z-index: 5; background: var(--c-bg, var(--c-surface)); }
section.panel[id] { scroll-margin-top: 56px; }
/* The five sync states, in order, each with its time. */
ol.pipe { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
ol.pipe li { display: grid; grid-template-columns: 14px 1fr auto; align-items: center; gap: 8px;
             padding: 6px 8px; border: var(--bd); border-radius: var(--r-md); font-size: var(--t-sm); }
ol.pipe li.done { border-color: color-mix(in srgb, var(--c-accent) 45%, transparent); }
ol.pipe li.wait { color: var(--c-ink-3); }
ol.pipe li.bad { border-color: var(--c-bad); }
ol.pipe li .at { font-family: var(--f-mono); font-size: 11px; color: var(--c-ink-2); white-space: nowrap; }
/* A table's selection, said under it (Assign Licenses). */
.picksum { margin: var(--s-2) 0 0; font-size: var(--t-sm); color: var(--c-ink-2); }
.picksum b { color: var(--c-ink); }
/* A card's purpose line under its title (the New Server cards). */
.purpose { margin: 0 0 var(--s-3); color: var(--c-ink-2); font-size: var(--t-sm); }
/* The install's heartbeat and its last message. */
.beat { font-size: var(--t-sm); color: var(--c-ink-2); }
.beat.quiet { color: var(--c-warn); }
dl.facts.op dd { overflow-wrap: anywhere; }
/* Setup code: large enough to read out, copy beside it. */
.code-big { font: 600 18px/1.3 var(--f-mono); letter-spacing: .08em; color: var(--c-ink); }
/* A check in a table row, for choosing rows. */
td.pick input[type="checkbox"] { width: 16px; height: 16px; }


/* == 11 · v0.5.0 — BDAW CONSOLE ==========================================
   JW, 2026-09-29: the console release (NEXT item 32). Values from BDAW
   Console 0.10.0-rc.2; nothing of the website's theater (boot, cursor,
   parallax, snap screens, sphere, radar). Every class name before this
   section is unchanged - no screen is re-marked; this section restyles them
   and adds the frame, the top bar, the folding menu and the Actions area. */

/* -- the faces, vendored (JW: "whatever is needed without having to go get
      it"). IBM's own Latin-1 files, unmodified (IBM Plex carries a Reserved
      Font Name); Poppins and Fraunces cut to Latin. SIL OFL 1.1 - the
      licenses are ljlr-fonts-LICENSE.txt beside this file. -- */
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
             src: url("ljlr-font-plex-sans-400.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap;
             src: url("ljlr-font-plex-sans-500.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600 700; font-display: swap;
             src: url("ljlr-font-plex-sans-600.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
             src: url("ljlr-font-plex-mono-400.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500 700; font-display: swap;
             src: url("ljlr-font-plex-mono-500.woff2") format("woff2"); }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 600 700; font-display: swap;
             src: url("ljlr-font-poppins-600.woff") format("woff"); }
@font-face { font-family: "Fraunces"; font-style: italic; font-weight: 500; font-display: swap;
             src: url("ljlr-font-fraunces-500i.woff") format("woff"); }

/* -- corner brackets, drawn in CSS (BDAW adds four <i> by script; here four
      pairs of one-pixel gradients do it, so no screen carries markup for
      decoration). --brk is the arm length, --bri the inset. -- */
.panel, .btn, .railtop, dialog, .hmenu > .pop, .band .menu > .pop {
  --brk: 12px; --bri: 6px; --bkc: var(--c-bracket);
}
.panel, .btn:not(.quiet):not(.sm):not(.xs):not(.tstep), dialog {
  background-image:
    linear-gradient(var(--bkc), var(--bkc)), linear-gradient(var(--bkc), var(--bkc)),
    linear-gradient(var(--bkc), var(--bkc)), linear-gradient(var(--bkc), var(--bkc)),
    linear-gradient(var(--bkc), var(--bkc)), linear-gradient(var(--bkc), var(--bkc)),
    linear-gradient(var(--bkc), var(--bkc)), linear-gradient(var(--bkc), var(--bkc));
  background-repeat: no-repeat;
  background-size:
    var(--brk) 1px, 1px var(--brk), var(--brk) 1px, 1px var(--brk),
    var(--brk) 1px, 1px var(--brk), var(--brk) 1px, 1px var(--brk);
  background-position:
    left var(--bri) top var(--bri), left var(--bri) top var(--bri),
    right var(--bri) top var(--bri), right var(--bri) top var(--bri),
    left var(--bri) bottom var(--bri), left var(--bri) bottom var(--bri),
    right var(--bri) bottom var(--bri), right var(--bri) bottom var(--bri);
}

/* -- base: the faces and the headings -- */
body { font-family: var(--f-ui); background: var(--c-bg); color: var(--c-ink-2); }
h1, h2, h3, h4 { color: var(--c-ink); }
h1, h2 { font-family: var(--f-display); font-weight: 600; letter-spacing: -.01em; text-transform: none; }
h1 { font-size: 26px; line-height: 1.12; }
h2 { font-size: 19px; }
h3 { font-family: var(--f-ui); font-weight: 600; }
.page-head em, .lede em { font-family: var(--f-serif); font-style: italic; font-weight: 500; color: var(--c-accent); }
a:focus-visible, button:focus-visible, summary:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--c-accent); outline-offset: 3px; box-shadow: none; }
code { background: var(--c-surface-2); border-color: var(--c-line); }
p, li, dd, td { color: inherit; }
.main { color: var(--c-ink-2); }
.main strong, .main b { color: var(--c-ink); font-weight: 600; }

/* -- the frame: four brackets at the corners of the window (BDAW's .frame) -- */
.frame { position: fixed; inset: 5px; pointer-events: none; z-index: 60; }
.frame i { position: absolute; width: 18px; height: 18px; border: 0 solid var(--c-bracket); }
.frame .tl { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.frame .tr { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.frame .bl { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }
.frame .br { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }

/* -- the top bar (the band, restyled): MARK · page · live dot ... date · clock · menus -- */
.band { background: color-mix(in srgb, var(--c-bg) 88%, transparent); backdrop-filter: blur(12px);
        border-bottom: 1px solid var(--c-line); padding: 0 28px; gap: 14px;
        font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--c-ink-3); }
.band .mark { font: 500 11px/1 var(--f-mono); letter-spacing: .26em; color: var(--c-accent); text-shadow: none; }
.band .mark:hover { color: var(--c-ink); }
.band .where { color: var(--c-ink-2); font-size: 10.5px; letter-spacing: .14em; white-space: nowrap;
               overflow: hidden; text-overflow: ellipsis; max-width: 38vw; }
.band .where::before { content: "\00B7"; color: var(--c-ink-3); margin-right: 12px; }
/* The live dot is a status, so it is a status color (JW: "status is never
   style"): green while the panel answers, red when it stops, gray before the
   first answer. It pulses on each answer, so a quiet page still says it is
   alive - JW, 2026-09-29: "so i ... know it's not dead". */
.band .live { display: inline-flex; align-items: center; gap: 7px; color: var(--c-ink-3); white-space: nowrap; }
.band .live::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--c-unknown); }
.band .live.ok::before { background: var(--c-good); }
.band .live.bad::before { background: var(--c-bad); }
.band .live.beat::before { animation: livebeat 1.2s ease-out 1; }
@keyframes livebeat { 0% { transform: scale(1.9); opacity: .4; } 100% { transform: none; opacity: 1; } }
.band .stamp { color: var(--c-ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.band .stamp b { color: var(--c-ink); font-weight: 500; }
.band .menu > summary { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .12em; text-transform: none; }
.band .menu > .pop, .hmenu > .pop { border-radius: 0; background: var(--c-surface); border: 1px solid var(--c-line-strong);
        box-shadow: 0 18px 40px -12px rgba(0,0,0,.7); }
.band .menu > .pop .item, .hmenu > .pop .item { border-radius: 0; font-family: var(--f-mono); font-size: 11px;
        letter-spacing: .12em; text-transform: uppercase; font-weight: 500; }
@media (max-width: 1100px) { .band .stamp .dt { display: none; } }
@media (max-width: 760px)  { .band .stamp, .band .live span { display: none; } }

/* -- the menu (the rail): BDAW's index rail - mono caps, a dash that grows
      under the page you are on, gold where you are. Groups fold. -- */
.rail { background: var(--c-bg); border-right: 1px solid var(--c-line); padding: 0 0 var(--s-3); }
.rail a, .rail .off { font: 500 11px/1.25 var(--f-mono); letter-spacing: .13em; text-transform: uppercase;
        color: var(--c-ink-2); padding: 6px 12px 6px 16px; border-left: 0; gap: 10px; background: none; text-shadow: none; }
.rail a::before, .rail .off::before { content: ""; flex: 0 0 auto; width: 9px; height: 1px; background: currentColor; opacity: .7;
        transition: width var(--dur) var(--ease); }
.rail a:hover { color: var(--c-ink); background: none; }
.rail a:hover::before { width: 14px; }
.rail a[aria-current="page"] { color: var(--c-accent); background: none; border-left: 0; text-shadow: none; }
.rail a[aria-current="page"]::before { width: 20px; opacity: 1; }
.rail .group { font: 500 9.5px/1 var(--f-mono); letter-spacing: .2em; color: var(--c-ink-3); padding: 16px 12px 6px 16px; }
/* The top of the menu: Collapse (to a strip) and Expand All / Collapse All.
   They are forms, so they work with no script; ljlr-shell.js does them in
   place and saves them to the account. */
.railtop { display: flex; align-items: center; gap: 2px; padding: 6px 8px 6px 6px; border-bottom: 1px solid var(--c-line);
           position: sticky; top: 0; z-index: 2; background: var(--c-bg); }
.railtop form { display: contents; }
.railbtn { font: 500 9px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--c-ink-3);
           background: none; border: 1px solid transparent; padding: 6px 5px; cursor: pointer; white-space: nowrap; }
.railbtn:hover { color: var(--c-accent); border-color: var(--c-line); }
.railbtn.ico { font-size: 13px; letter-spacing: 0; padding: 3px 8px; }
.railtop .grow { flex: 1 1 auto; }
details.grp { border-bottom: 1px solid color-mix(in srgb, var(--c-line) 60%, transparent); }
details.grp > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
        padding: 12px 12px 8px 16px; font: 500 9.5px/1 var(--f-mono); letter-spacing: .2em; text-transform: uppercase;
        color: var(--c-ink-3); user-select: none; }
details.grp > summary::-webkit-details-marker { display: none; }
details.grp > summary .gt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
details.grp > summary .gn { font-variant-numeric: tabular-nums; color: var(--c-ink-3); opacity: .8; }
details.grp > summary::after { content: "\25B8"; font-size: 10px; letter-spacing: 0; color: var(--c-ink-3);
        transition: transform var(--dur) var(--ease); }
details.grp[open] > summary::after { transform: rotate(90deg); }
details.grp > summary:hover, details.grp > summary:hover .gn, details.grp > summary:hover::after { color: var(--c-ink); }
details.grp.here > summary .gt { color: var(--c-ink-2); }
details.grp[open] { padding-bottom: 8px; }
/* Collapsed to a strip: 56px; each group shows its two letters; the whole
   menu opens over the page while the pointer or focus is in it. */
html[data-rail="strip"] { --rail-w: var(--rail-strip); }
html[data-rail="strip"] .rail { width: var(--rail-strip); overflow-x: hidden; }
html[data-rail="strip"] .rail:hover, html[data-rail="strip"] .rail:focus-within {
  width: 244px; z-index: 25; box-shadow: 14px 0 32px -12px rgba(0,0,0,.8); overflow-y: auto; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .railtop .grow,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .railtop .railbtn:not(.ico),
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) details.grp > summary .gt,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) details.grp > summary .gn,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) details.grp > summary::after,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .rail-t,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts .act-m,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts .act-s { display: none; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) details.grp > summary::before {
  content: attr(data-ab); color: var(--c-ink-2); letter-spacing: .12em; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) a, html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .off {
  padding-left: 18px; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts .act-n { font-size: 0; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts .act-n::first-letter { font-size: 11px; }
html[data-rail="strip"] .app:not(.takeover) { grid-template-columns: var(--rail-strip) 1fr; }
@media (max-width: 900px) {
  .railtop, details.grp > summary::after { display: none; }
  details.grp { display: contents; }
  details.grp > summary { padding: 0 var(--s-2); }
  details.grp:not([open]) > a, details.grp:not([open]) > .off { display: flex; }
  .rail a::before, .rail .off::before { display: none; }
  html[data-rail="strip"] .rail { width: auto; }
}

/* -- the Actions area, under the menu (NEXT item 30; JW, 2026-09-29: "use
      the space below the side menu for queued actions so i can move around
      the panel as it's working and i know it's not dead"). Each action:
      name, stage, last message, elapsed, and a heartbeat. Yellow while it
      runs, green done, red failed, gray queued - the traffic light. -- */
.acts { margin: var(--s-3) 10px 0; padding-top: 10px; border-top: 1px solid var(--c-line); }
.acts-hd { display: flex; align-items: baseline; gap: 8px; font: 500 9.5px/1 var(--f-mono); letter-spacing: .2em;
              text-transform: uppercase; color: var(--c-ink-3); padding: 0 6px 8px; }
.acts-hd .grow { flex: 1 1 auto; }
.acts-hd .n { font-variant-numeric: tabular-nums; }
.acts .none { font: 400 10.5px/1.4 var(--f-mono); color: var(--c-ink-3); padding: 0 6px 4px; letter-spacing: .06em; }
.act { display: block; position: relative; padding: 8px 8px 8px 12px; margin-bottom: 6px; border: 1px solid var(--c-line);
       border-left: 2px solid var(--c-unknown); background: color-mix(in srgb, var(--c-surface) 80%, transparent);
       color: var(--c-ink-2); text-decoration: none; }
a.act:hover { border-color: var(--c-line-strong); text-decoration: none; color: var(--c-ink); }
.act.running { border-left-color: var(--c-warn); }
.act.done    { border-left-color: var(--c-good); }
.act.failed  { border-left-color: var(--c-bad); }
.act-n { display: block; font: 500 11.5px/1.3 var(--f-ui); color: var(--c-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.act-s { display: flex; align-items: center; gap: 6px; margin-top: 3px; font: 500 9.5px/1.2 var(--f-mono); letter-spacing: .14em;
         text-transform: uppercase; color: var(--c-ink-2); }
.act-s .st { color: var(--c-unknown); }
.act.running .act-s .st { color: var(--c-warn); }
.act.done .act-s .st    { color: var(--c-good); }
.act.failed .act-s .st  { color: var(--c-bad); }
.act-s .el { margin-left: auto; color: var(--c-ink-3); font-variant-numeric: tabular-nums; letter-spacing: .06em; }
.act-m { display: block; margin-top: 3px; font: 400 10.5px/1.35 var(--f-mono); color: var(--c-ink-3);
         overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The heartbeat: a dot that pulses each time the action says something. */
.act .hb { width: 6px; height: 6px; border-radius: 50%; background: var(--c-unknown); flex: 0 0 auto; }
.act.running .hb { background: var(--c-warn); animation: hb 1.6s ease-in-out infinite; }
.act.running.quiet .hb { animation: none; opacity: .5; }
.act.done .hb { background: var(--c-good); }
.act.failed .hb { background: var(--c-bad); }
@keyframes hb { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .act .hb, .band .live::before { animation: none !important; } }
@media (max-width: 900px) { .acts { display: none; } }

/* -- the page head: a crumb line in gold (they are links), the title in the
      display face, no bracket box -- */
.page-head h1 { display: block; padding: 0; border: 0; font: 600 26px/1.12 var(--f-display); letter-spacing: -.01em;
                text-transform: none; color: var(--c-ink); }
.page-head h1::before, .page-head h1::after { display: none; }
.page-head p { color: var(--c-ink-2); }
.crumbs { font: 500 10.5px/1.4 var(--f-mono); letter-spacing: .2em; color: var(--c-ink-3); }
.crumbs a { color: var(--c-accent); }
.crumbs a:hover { color: var(--c-ink); text-decoration: none; }

/* -- panels: BDAW's HUD panel - ink-2, one hairline, four brackets, no
      gradient, no shadow -- */
.panel { background-color: color-mix(in srgb, var(--c-surface) 82%, transparent); border: 1px solid var(--c-line);
         border-radius: 0; box-shadow: none; }
.panel::before, .panel::after { display: none; }
.panel > .hd { padding: 11px 22px; border-bottom: 1px solid var(--c-line); }
.panel > .hd h3 { font: 500 10.5px/1.2 var(--f-mono); letter-spacing: .2em; color: var(--c-ink-2); }
.panel > .hd .sub { font-size: 10px; letter-spacing: .12em; color: var(--c-ink-3); }
.panel > .bd { padding: 16px 22px 18px; }
.panel > .bd.flush { padding: 0 0 8px; }
.panel > .bd.flush :is(table.data, .table-wrap > table) :is(th, td):first-child { padding-left: 22px; }
.panel > .bd.flush :is(table.data, .table-wrap > table) :is(th, td):last-child { padding-right: 22px; }
.panel > .ft { background: transparent; border-top: 1px solid var(--c-line); padding: 8px 22px; }
.tile, .chart-card { background-image: none; }
.tile .tile-b { border-left-width: 2px; }
.stat .value, .tile .value { font-family: var(--f-display); font-weight: 600; letter-spacing: -.01em; }
.hudframe { border-color: var(--c-line); }
.hudframe > .k { border-color: var(--c-bracket); filter: none; }

/* -- facts: the key in mono caps (chrome), the value in paper -- */
.facts dt { color: var(--c-ink-2); border-bottom: 1px solid var(--c-line); font-weight: 500; }
.facts dd { color: var(--c-ink); border-bottom: 1px solid var(--c-line); }

/* -- tables: hairlines, mono heads. A head is chrome, so it is not gold;
      gold is kept for what you can act on (a head that sorts, on hover). -- */
:is(table.data, .table-wrap > table) th, :is(table.data, .table-wrap > table) td { border-bottom: 1px solid var(--c-line); }
:is(table.data, .table-wrap > table) thead th { background: var(--c-surface); color: var(--c-ink-2);
        font: 500 10px/1.2 var(--f-mono); letter-spacing: .16em; border-bottom: 1px solid var(--c-line-strong); }
:is(table.data, .table-wrap > table) tbody tr:hover { background: color-mix(in srgb, var(--c-surface-2) 70%, transparent); }
:is(table.data, .table-wrap > table) td { color: var(--c-ink); }
table.sortable thead th[data-sort]:hover { color: var(--c-accent); }

/* -- forms: mono caps labels, ink fields, square, a gold edge on the one you are in -- */
.field > label, label.lab { color: var(--c-ink-2); font-weight: 500; }
input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="password"],
input[type="number"], input[type="date"], input[type="datetime-local"], input[type="url"],
input[type="tel"], select, textarea { background: var(--c-bg); border: 1px solid var(--c-line); border-radius: 0; color: var(--c-ink); }
input:hover, select:hover, textarea:hover { border-color: var(--c-line-strong); }
input:focus, select:focus, textarea:focus { border-color: var(--c-accent); box-shadow: none; }

/* -- buttons, drawn as panels (BDAW 0.9.0-rc.2): square, one hairline,
      mono caps, four small brackets. The primary is still the one that is
      filled (JW's rc.46 notes: "Make primary action buttons visually
      dominant"); Install is still green (JW, 2026-09-13). -- */
.btn { --brk: 8px; --bri: 3px; border-radius: 0; font: 500 11px/1 var(--f-mono); letter-spacing: .16em;
       color: var(--c-ink); background-color: color-mix(in srgb, var(--c-surface) 82%, transparent);
       border: 1px solid var(--c-line-strong); padding: 11px 18px; min-height: 36px; box-shadow: none; text-shadow: none;
       transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background-color var(--dur) var(--ease), transform var(--dur) var(--ease); }
.btn:hover { border-color: var(--c-accent); color: var(--c-accent); box-shadow: none; transform: translateY(-1px); }
.btn:active { transform: none; }
.btn.primary { --bkc: color-mix(in srgb, var(--c-ink-on-accent) 40%, transparent);
               background-color: var(--c-accent); border-color: var(--c-accent); color: var(--c-ink-on-accent); box-shadow: none; }
.btn.primary:hover { background-color: var(--c-ink); border-color: var(--c-ink); color: var(--c-ink-on-accent); }
.btn.go { --bkc: color-mix(in srgb, var(--c-good) 60%, transparent); background-color: var(--c-good-soft);
          border-color: var(--c-good); color: var(--c-good); box-shadow: none; }
.btn.go:hover { background-color: var(--c-good); color: var(--c-ink-on-accent); }
.btn.danger { --bkc: color-mix(in srgb, var(--c-bad) 55%, transparent); background-color: transparent; border-color: color-mix(in srgb, var(--c-bad) 70%, transparent); color: var(--c-bad); }
.btn.danger:hover { border-color: var(--c-bad); color: var(--c-bad); background-color: var(--c-bad-soft); }
.btn.warn { --bkc: color-mix(in srgb, var(--c-warn) 55%, transparent); background-color: transparent; border-color: var(--c-warn); color: var(--c-warn); }
.btn.quiet { background: transparent; border-color: transparent; color: var(--c-accent); }
.btn.quiet:hover { background: var(--c-accent-soft); border-color: transparent; transform: none; }
.btn.sm { min-height: 28px; padding: 6px 11px; font-size: 10px; }
.btn.xs { min-height: 22px; padding: 2px 8px; font-size: 9.5px; }
.btn.done, .btn.done[disabled] { background-color: var(--c-good-soft); border-color: var(--c-good); color: var(--c-good); transform: none; }
.btn[disabled], .btn[aria-disabled="true"] { transform: none; }
.btn-group .btn, .btn-group .btn:first-child, .btn-group .btn:last-child { border-radius: 0; }

/* -- tabs: mono caps, a gold edge under the one you are on. Not pills. -- */
.tabs { border-bottom: 1px solid var(--c-line); }
.tabs a, .tabs button { font: 500 11px/1.4 var(--f-mono); letter-spacing: .16em; color: var(--c-ink-2); }
.tabs [aria-current="true"], .tabs [aria-selected="true"] { color: var(--c-accent); text-shadow: none; }

/* -- badges and steps: square, mono, bordered in their own color -- */
.badge { border-radius: 0; font: 500 9.5px/1 var(--f-mono); letter-spacing: .14em; padding: 4px 7px; }
.steps .step { border-radius: 0; font-family: var(--f-mono); letter-spacing: .08em; }
.steps .step i { border-radius: 0; }
.dot { box-shadow: none !important; }

/* -- alerts: a callout - one hairline, the status color on the left edge -- */
.alert { border: 1px solid var(--c-line); border-left: 2px solid var(--c-line-strong); border-radius: 0;
         background: color-mix(in srgb, var(--c-surface) 86%, transparent); box-shadow: none; color: var(--c-ink); }
.alert.ok   { border-left-color: var(--c-good); background: color-mix(in srgb, var(--c-good) 6%, var(--c-surface)); box-shadow: none; }
.alert.warn { border-left-color: var(--c-warn); background: color-mix(in srgb, var(--c-warn) 6%, var(--c-surface)); box-shadow: none; }
.alert.bad  { border-left-color: var(--c-bad);  background: color-mix(in srgb, var(--c-bad) 6%, var(--c-surface)); box-shadow: none; }

/* -- dialogs: BDAW's modal - a veil with blur, a square panel with brackets -- */
dialog, dialog.confirm { border-radius: 0; border: 1px solid var(--c-line-strong); background-color: var(--c-surface);
         box-shadow: 0 30px 60px -20px rgba(0,0,0,.8); }
dialog::backdrop, dialog.confirm::backdrop { background: color-mix(in srgb, var(--c-bg) 82%, transparent); backdrop-filter: blur(6px); }

/* -- work in progress is a status: yellow while it runs, green when done,
      red when it stopped (JW: "should be traffic light - green yellow red or off").
      The dial, the bar and the busy line were the accent before v0.5.0. -- */
.dial-arc, .dial-spin { stroke: var(--c-warn); }
.busy-bar > span, .meter > span { background: var(--c-warn); box-shadow: none; }
ol.pipe li.done { border-color: color-mix(in srgb, var(--c-good) 45%, transparent); }
ol.pipe li.bad { border-color: var(--c-bad); }

/* -- small things that were rounded or glowing -- */
.steps .now { box-shadow: none; }
ol.pipe li { border-radius: 0; }
details.disclose { border-radius: 0; }
pre, #idlog { border-radius: 0; background: var(--c-bg); }
.bar { border-radius: 0; }
.bar > span { background: var(--c-warn); }
.gauge-bar, .gauge-bar i { border-radius: 0; }
.dial-arc { filter: none; }
.swatch { border-radius: 0; }
.cluster .node rect { filter: none; }
.cluster .root rect { filter: none; }

/* -- Desk (NEST): the Pin column in one place in every table
      (JW's 2026-09-29 screenshot: four positions). -- */
table.desk { table-layout: fixed; width: 100%; }
table.desk th:last-child, table.desk td:last-child { width: 112px; text-align: right; }
table.desk td form { display: inline; }

@media print {
  .frame, .acts, .railtop { display: none !important; }
}

/* -- NEST's Modules (rc.38): a tick per module that can be installed, Select
      All in the head, Install Selected and Install All under the table. -- */
table.mods th.pick, table.mods td:first-child { width: 40px; }
table th.pick input[type="checkbox"], td.pick input[type="checkbox"] { width: 16px; height: 16px; }
.mods-go { gap: 10px; }
table.mods td:nth-child(3) { white-space: nowrap; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts-hd,
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts .none { display: none; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .acts { margin-inline: 6px; }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) .act { padding: 6px 4px 6px 6px; }
/* The Actions area stays in sight at the foot of the menu, however long the
   menu is (JW: "so i can move around the panel as it's working"). */
.rail > .acts { position: sticky; bottom: 0; z-index: 2; background: var(--c-bg); margin: var(--s-3) 0 0;
                padding: 10px 10px 8px; box-shadow: 0 -12px 16px -12px rgba(0,0,0,.9); }

/* -- A number, a size, a version or a time is read whole (rc.56): cells that
      hold one do not break across lines ("0.1.0-dev.11-" / "rc.35"). -- */
:is(table.data, .table-wrap > table) :is(td.num, td.mono, td.when) { white-space: nowrap; }
:is(table.data, .table-wrap > table) td.wrap { white-space: normal; }

/* -- The file picker (rc.56): the browser's gray button, dressed as ours. -- */
input[type="file"] { font: 400 var(--t-sm) var(--f-ui); color: var(--c-ink-2); }
input[type="file"]::file-selector-button {
  font: 500 10.5px/1 var(--f-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--c-ink);
  background: color-mix(in srgb, var(--c-surface) 82%, transparent); border: 1px solid var(--c-line-strong);
  border-radius: 0; padding: 9px 14px; margin-right: 12px; cursor: pointer; }
input[type="file"]::file-selector-button:hover { border-color: var(--c-accent); color: var(--c-accent); }

/* -- An action in the menu is a card, not a menu link (rc.56 walk: `.rail a`
      took its padding, its dash and its left edge - the state's stripe - and
      laid it out in one row, "P. · FAILED 0S SYST..."). -- */
.rail a.act { display: block; font: inherit; letter-spacing: normal; text-transform: none; gap: 0;
              padding: 8px 8px 8px 12px; border: 1px solid var(--c-line); border-left: 2px solid var(--c-unknown);
              color: var(--c-ink-2); background: color-mix(in srgb, var(--c-surface) 80%, transparent); }
.rail a.act::before { content: none; display: none; }
.rail a.act:hover { border-color: var(--c-line-strong); border-left-color: var(--c-unknown); color: var(--c-ink); }
.rail a.act.running, .rail a.act.running:hover { border-left-color: var(--c-warn); }
.rail a.act.done, .rail a.act.done:hover       { border-left-color: var(--c-good); }
.rail a.act.failed, .rail a.act.failed:hover   { border-left-color: var(--c-bad); }
html[data-rail="strip"] .rail:not(:hover):not(:focus-within) a.act { padding: 6px 4px 6px 6px; }
/* A row in a panel's foot spans it, so its .grow pushes the go button right. */
.panel > .ft > .row { flex: 1 1 auto; }
