/* ═══════════════════════════════════════════════════════════════════════════
   Slate — tokens, reset, base
   Paste this first. Every component sheet depends on these variables.

   This site has two themes. Light is the default and lives on :root, so it
   also covers the moment before the theme is stamped. Dark is an explicit
   choice, stamped as data-theme="dark" on <html>. The OS setting is
   deliberately ignored.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  color-scheme:light;

  /* Grounds. --bg is the page, --surface is a raised object (card, menu,
     input), --surface-2 is a recessed or secondary band (group headers). */
  --bg:#f4f4f5;
  --surface:#ffffff;
  --surface-2:#f8f8f9;
  --hover:rgba(20,20,26,.045);

  /* Text. Three steps only. Resist adding a fourth — the restraint is what
     makes emphasis mean something. */
  --text:#1b1b1f;
  --text-2:#6e6e77;
  --text-3:#a1a1a9;

  /* Hairlines. --line is a quiet divider, --line-2 is an active or hovered
     edge. Both are alpha so they composite over any ground. */
  --line:rgba(20,20,26,.08);
  --line-2:rgba(20,20,26,.16);

  /* Inversion. This is the accent. There is no accent hue — the primary
     action is the one painted in reverse. */
  --inv:#1b1b1f;
  --inv-text:#ffffff;
  --inv-hover:#2c2c32;

  /* Elevation ladder. 1 rest, 2 hover, 3 floating (menus, drag ghosts),
     4 modal. Spend these by role, not decoration. */
  --sh-1:0 1px 2px rgba(20,20,26,.05);
  --sh-2:0 2px 6px rgba(20,20,26,.06),0 1px 2px rgba(20,20,26,.05);
  --sh-3:0 20px 40px -12px rgba(20,20,26,.28),0 6px 14px -6px rgba(20,20,26,.14);
  --sh-4:0 32px 64px -16px rgba(20,20,26,.3),0 0 0 1px rgba(20,20,26,.06);

  --overlay:rgba(20,20,26,.32);

  /* Focus ring: a gap in page colour, then the ring. Reads on any surface. */
  --ring:0 0 0 2px var(--bg),0 0 0 4px rgba(20,20,26,.4);

  /* One typeface for everything. Commit Mono is monospaced throughout, so
     --sans and --mono are the same family; .mono still adds tabular figures. */
  --mono:"Commit Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --sans:var(--mono);

  /* The one easing used everywhere. Consistency of motion matters as much
     as consistency of colour. */
  --ease:cubic-bezier(.2,0,0,1);
}

/* Explicit dark. Same values, so the toggle wins in both directions. */
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0c0c0e;
  --surface:#151517;
  --surface-2:#1b1b1e;
  --hover:rgba(255,255,255,.055);
  --text:#ececee;
  --text-2:#8e8e96;
  --text-3:#5a5a62;
  --line:rgba(255,255,255,.08);
  --line-2:rgba(255,255,255,.17);
  --inv:#ececee;
  --inv-text:#0c0c0e;
  --inv-hover:#ffffff;
  --sh-1:0 1px 2px rgba(0,0,0,.4);
  --sh-2:0 2px 6px rgba(0,0,0,.45),0 1px 2px rgba(0,0,0,.3);
  --sh-3:0 20px 40px -12px rgba(0,0,0,.7),0 6px 14px -6px rgba(0,0,0,.5);
  --sh-4:0 32px 64px -16px rgba(0,0,0,.8),0 0 0 1px rgba(255,255,255,.08);
  --overlay:rgba(0,0,0,.6);
  --ring:0 0 0 2px var(--bg),0 0 0 4px rgba(255,255,255,.5);
}

/* ── Reset and base ───────────────────────────────────────────────────── */

*{box-sizing:border-box}
html,body{height:100%}

body{
  margin:0;
  background:var(--bg);          /* explicit — a transparent body borrows the host's ground */
  color:var(--text);
  font:13px/1.45 var(--sans);    /* 13px base. The whole scale assumes it. */
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

/* Buttons do NOT inherit text-align, and the browser default of `center`
   will centre labels inside any flex child that grows. Setting it here
   saves a class of bug that is very hard to spot. */
button{
  font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;
  cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent;
}
input,textarea{font:inherit;color:inherit}
input::placeholder,textarea::placeholder{color:var(--text-3);opacity:1}
svg{display:block;flex:none}

/* The UA rule for [hidden] is display:none, which any display declaration
   beats. Without this, toggling `el.hidden` silently does nothing on a
   flex or grid element. */
[hidden]{display:none!important}

:focus-visible{outline:none;box-shadow:var(--ring)}

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

/* Key cap. The asymmetric padding is deliberate and measured: with
   line-height 1 the font's own metrics park short lowercase text low in the
   box, so the top padding is reduced and the bottom increased to bring the
   ink back to centre. See references/gotchas.md before changing it. */
kbd{
  font-family:var(--mono);font-size:10.5px;line-height:1;color:var(--text-3);
  border:1px solid var(--line);border-radius:4px;
  padding:2.5px 5px;background:var(--surface);
}

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

/* Slate components — taken verbatim from components.css */
/* ── Buttons ──────────────────────────────────────────────────────────── */

.btn{
  height:30px;padding:0 12px;border-radius:7px;font-weight:500;
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  transition:background .15s,border-color .15s,color .15s,opacity .15s;
}
/* The primary action is the inverted one. This is the accent — there is no
   accent hue. Use exactly one per view. */
.btn-primary{background:var(--inv);color:var(--inv-text);padding-left:10px}
.btn-primary:hover{background:var(--inv-hover)}
.btn-primary:disabled{opacity:.4;cursor:not-allowed}
.btn-ghost{border:1px solid var(--line);background:var(--surface)}
.btn-ghost:hover{border-color:var(--line-2);background:var(--surface-2)}
.btn-text{color:var(--text-2);padding:0 8px}
.btn-text:hover{color:var(--text);background:var(--hover)}

.icon-btn{
  width:30px;height:30px;border-radius:7px;display:grid;place-items:center;
  color:var(--text-2);transition:background .15s,color .15s;
}
.icon-btn:hover{background:var(--hover);color:var(--text)}
.icon-btn.sm{width:26px;height:26px;border-radius:6px}

/* Segmented control for mutually exclusive views. Icon-only by design —
   label it with title and aria-label. */
.seg{display:flex;gap:2px;padding:2px;border:1px solid var(--line);border-radius:8px;background:var(--surface)}
.seg-btn{
  width:26px;height:24px;border-radius:5px;display:grid;place-items:center;
  color:var(--text-3);transition:background .15s,color .15s;
}
.seg-btn:hover{color:var(--text-2)}
.seg-btn[aria-pressed="true"]{background:var(--hover);color:var(--text)}

/* ── Small indicators ─────────────────────────────────────────────────── */

.chip{
  font-size:11px;color:var(--text-2);border:1px solid var(--line);border-radius:999px;
  padding:0 7px 0 6px;line-height:17px;display:inline-flex;align-items:center;gap:5px;
  white-space:nowrap;
}
.chip i{width:6px;height:6px;border-radius:50%;background:currentColor}

.avatar{
  width:18px;height:18px;border-radius:50%;background:var(--surface-2);
  border:1px solid var(--line);font-size:8px;font-weight:600;letter-spacing:.03em;
  display:grid;place-items:center;color:var(--text-2);line-height:1;flex:none;
}
/* Reserve the slot when there is no value, or neighbouring columns drift. */
.avatar.none{visibility:hidden}

/* Status pill. The four steps are the house way of showing urgency without
   a colour: contrast, then a border, then a fill, then weight. */
.pill{
  display:inline-flex;align-items:center;gap:4px;white-space:nowrap;flex:none;
  font-size:11px;line-height:17px;padding:0 6px;border-radius:999px;
  border:1px solid transparent;color:var(--text-3);font-variant-numeric:tabular-nums;
}
.pill[data-t="2"]{color:var(--text-2)}
.pill[data-t="3"]{color:var(--text);border-color:var(--line-2)}
.pill[data-t="4"]{color:var(--text);background:var(--hover);border-color:var(--line-2);font-weight:500}

/* ── Tooltip ──────────────────────────────────────────────────────────────
   Inverted, like the toast: a transient label painted in reverse reads as
   not part of the page. One element, mounted once and moved between
   anchors, positioned with fixed coordinates like every popover.          */

.tip{
  position:fixed;left:0;top:0;z-index:500;pointer-events:none;
  display:flex;align-items:center;gap:6px;max-width:240px;
  padding:4px 7px;border-radius:6px;background:var(--inv);color:var(--inv-text);
  font-size:11.5px;line-height:1.35;box-shadow:var(--sh-2);
  opacity:0;translate:0 3px;transition:opacity .12s,translate .14s var(--ease);
}
.tip[data-side="below"]{translate:0 -3px}
.tip.show{opacity:1;translate:0 0}
/* Key caps on the inverted ground. A half-grey edge reads on both inks. */
.tip kbd{background:transparent;color:inherit;border-color:rgba(128,128,128,.45);opacity:.8}
.tip kbd + kbd{margin-left:-3px}

/* ── Command palette ──────────────────────────────────────────────────────
   The modal's frame and entrance, a 52px input row that matches every other
   header, and a listbox with one highlight moved by keys and hover alike.
   Group labels use the nav label's type so the two read as one system.    */

.palette{
  position:fixed;left:50%;top:12vh;z-index:201;width:min(560px,calc(100vw - 32px));
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--surface);border-radius:12px;box-shadow:var(--sh-4);
  opacity:0;pointer-events:none;transform:translate(-50%,8px) scale(.985);
  transition:opacity .18s,transform .22s var(--ease);
}
.palette.open{opacity:1;pointer-events:auto;transform:translate(-50%,0) scale(1)}

.palette-head{
  display:flex;align-items:center;gap:10px;height:52px;flex:none;padding:0 14px 0 17px;
  border-bottom:1px solid var(--line);color:var(--text-3);
}
.palette-input{flex:1;min-width:0;height:100%;border:0;background:none;outline:none;font-size:14px;color:var(--text)}
.palette-input:focus-visible{box-shadow:none}

/* position:relative makes offsetTop measure from the list, for keeping the
   highlight in view. */
.palette-list{position:relative;max-height:min(360px,50vh);overflow-y:auto;padding:6px}
.palette-group{
  padding:8px 10px 4px;font-size:10.5px;font-weight:500;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-3);
}
.palette-item{
  display:flex;align-items:center;gap:10px;height:38px;padding:0 10px;border-radius:7px;
  cursor:pointer;color:var(--text-2);
}
.palette-item .ic{width:20px;height:20px;flex:none;display:grid;place-items:center}
.palette-item .label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.palette-item .keys{display:flex;gap:3px;flex:none}
.palette-item.active{background:var(--hover)}
.palette-item.active .ic{color:var(--text)}
.palette-empty{padding:22px 10px;text-align:center;font-size:12.5px;color:var(--text-3)}

.palette-foot{
  display:flex;align-items:center;gap:14px;height:34px;flex:none;padding:0 14px;
  border-top:1px solid var(--line);background:var(--surface-2);font-size:11.5px;color:var(--text-3);
}
.palette-foot > span{display:inline-flex;align-items:center;gap:5px}
.palette-foot kbd + kbd{margin-left:-2px}

/* ── Toast ────────────────────────────────────────────────────────────── */

.toast{
  position:fixed;left:50%;bottom:22px;translate:-50% 10px;z-index:400;
  background:var(--inv);color:var(--inv-text);padding:7px 7px 7px 14px;border-radius:8px;
  display:flex;align-items:center;gap:12px;font-size:12.5px;box-shadow:var(--sh-3);
  opacity:0;pointer-events:none;transition:opacity .18s,translate .22s var(--ease);
}
.toast.show{opacity:1;translate:-50% 0;pointer-events:auto}
.toast button{padding:4px 9px;border-radius:5px;font-weight:500;background:rgba(128,128,128,.28);transition:background .15s}
.toast button:hover{background:rgba(128,128,128,.42)}

.overlay{
  position:fixed;inset:0;background:var(--overlay);opacity:0;pointer-events:none;
  transition:opacity .18s;z-index:200;
}
.overlay.open{opacity:1;pointer-events:auto}

/* Stat tiles, progress meters, thin scrollbars — from components.css. Stat value re-set for a mono face. */
/* ── Thin scrollbars ──────────────────────────────────────────────────── */

.scroll-thin{scrollbar-width:thin;scrollbar-color:var(--line-2) transparent}
.scroll-thin::-webkit-scrollbar{width:8px;height:8px}
.scroll-thin::-webkit-scrollbar-thumb{
  background:var(--line-2);border-radius:8px;
  border:2px solid transparent;background-clip:padding-box;
}
.scroll-thin::-webkit-scrollbar-track{background:transparent}
/* ── Stat tiles ───────────────────────────────────────────────────────────
   Headline numbers sharing one frame, divided by hairlines rather than
   boxed as separate cards, because they are read together. Direction is
   carried by the sign; whether a change is good or bad is carried by the
   pill's emphasis step. Never green and red.                              */

.stats{
  display:flex;flex-wrap:wrap;min-width:0;overflow:hidden;
  background:var(--surface);border:1px solid var(--line);border-radius:8px;
}
/* Each tile draws the rule on its left and top edges. The frame's overflow
   clips the ones on the outside, so a wrapped row still gets one line. */
.stat{
  flex:1 1 170px;min-width:0;display:flex;flex-direction:column;gap:4px;padding:12px 16px 13px;
  box-shadow:-1px 0 0 var(--line),0 -1px 0 var(--line);
}
.stat-label{font-size:12px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stat-main{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;min-width:0}
/* Sans at 600 with proportional figures. Tabular figures give every digit
   the width of a zero, which looks loose at this size; they are for columns
   that must align, not a number that stands alone. */
.stat-value{font-size:20px;font-weight:400;letter-spacing:-.02em;line-height:1.25;color:var(--text);white-space:nowrap}
.stat-value .unit{margin-left:1px;font-size:12px;font-weight:400;letter-spacing:0;color:var(--text-3)}
/* A glance, not a chart: the line recedes and only the current point is in
   full ink. No axes, no hover. */
.stat-spark{flex:none;margin-bottom:5px;color:var(--text-3)}
.stat-spark .now{fill:var(--text)}
.stat-foot{display:flex;align-items:center;gap:6px;min-height:18px;font-size:12px;color:var(--text-3);white-space:nowrap}
/* ── Loading and progress ─────────────────────────────────────────────────
   A meter for a known amount, a spinner for a short unknown wait, and a
   skeleton for content on its way. All three stay in the grey ramp: the
   track is --line and the fill a text step, so a meter near its limit
   climbs to --text the same way a pill climbs the emphasis ladder.        */

.progress{position:relative;height:4px;min-width:0;overflow:hidden;border-radius:999px;background:var(--line)}
/* Set the width as a literal percentage in the inline style, not through a
   variable. A var-driven width is the one that refuses to animate. */
.progress > i{display:block;height:100%;border-radius:inherit;background:var(--text-2);transition:width .24s var(--ease)}
.progress[data-t="4"] > i{background:var(--text)}
.progress.indeterminate > i{width:35%;animation:slate-slide 1.3s var(--ease) infinite}
@keyframes slate-slide{from{translate:-100% 0}to{translate:290% 0}}

.meter{display:flex;flex-direction:column;gap:6px;min-width:0}
.meter-head{display:flex;align-items:baseline;gap:8px;font-size:12.5px}
.meter-label{flex:1;min-width:0;color:var(--text)}
.meter-value{font-family:var(--mono);font-size:11.5px;color:var(--text-2);font-variant-numeric:tabular-nums;white-space:nowrap}

