/* HBL Claude telemetry portal.
 *
 * The whole system comes off the logo: yellow #ffc20f, charcoal #424244, and
 * the cut those blocks are sliced at -- skewX(-10.94deg), measured from the
 * polygon coordinates in logo.svg rather than eyeballed. The cut is the
 * identity, so it appears on the active tab, the page tick, the avatar and the
 * token block, and NEVER on anything containing type that has to be read
 * straight.
 *
 * Two rules that are not taste:
 *
 *   - Yellow never carries text on a light surface. It measures 1.7:1 there,
 *     under the 3:1 a mark needs and nowhere near text contrast. It is a fill,
 *     an underline, a highlighted bar -- and one primary button per view.
 *   - Charts are charcoal, with the current bar in yellow and failures in red.
 *     Same reason: a data mark has to clear 3:1 against the surface it sits on.
 */

:root {
  color-scheme: light dark;
  --page: #f7f6f3;
  --card: #ffffff;
  --line: #e4e2dd;
  --line-soft: #f0efeb;
  --ink: #1c1c1e;
  --ink-2: #4a4a4f;
  --muted: #6b6b70;
  --faint: #94949a;
  --brand: #ffc20f;
  --brand-ink: #1c1c1e;      /* type that sits ON yellow */
  --brand-deep: #8a6200;     /* yellow's readable sibling, for links and hints */
  --charcoal: #424244;
  --charcoal-ink: #ffffff;
  --track: #efeee9;
  --bar: #424244;
  --ok: #1a7f37;
  --ok-bg: #f2f8f3;
  --ok-line: #cfe3d4;
  --warn: #8a5a00;
  --warn-bg: #fff8e6;
  --warn-line: #f3e2b0;
  --danger: #b3261e;
  --danger-line: #e0b4b0;
  --shadow: 0 16px 40px -22px rgba(28, 28, 30, .45);
}
/* Dark is declared TWICE, and both are needed. The media query serves everyone
   on the default "match my system" setting -- guarded with :not([data-theme=
   "light"]) so a person who explicitly picked light still gets light on a dark
   OS. The attribute rule serves an explicit choice, and comes second so it wins
   both ways. Settings writes the attribute; the cookie behind it is per browser.

   Chosen against the dark surface rather than flipped: the yellow is unchanged
   (it gains contrast on dark), the charcoal surfaces lift so they read as
   surfaces, and the chart bar inverts to a light neutral because a charcoal bar
   on a charcoal page is no bar at all. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page: #17171a;
    --card: #1f1f22;
    --line: #2e2e33;
    --line-soft: #26262a;
    --ink: #ececee;
    --ink-2: #c6c6cb;
    --muted: #a3a3a9;
    --faint: #85858c;
    --brand-deep: #f0b429;
    --charcoal: #2a2a2e;
    --track: #2e2e33;
    --bar: #cfcdc7;
    --ok: #4ec26a;
    --ok-bg: #182319;
    --ok-line: #2b4430;
    --warn: #d9a441;
    --warn-bg: #241f14;
    --warn-line: #453a22;
    --danger: #e66767;
    --danger-line: #4a2a2a;
    --shadow: 0 16px 40px -22px rgba(0, 0, 0, .7);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --page: #17171a;
  --card: #1f1f22;
  --line: #2e2e33;
  --line-soft: #26262a;
  --ink: #ececee;
  --ink-2: #c6c6cb;
  --muted: #a3a3a9;
  --faint: #85858c;
  --brand-deep: #f0b429;
  --charcoal: #2a2a2e;
  --track: #2e2e33;
  --bar: #cfcdc7;
  --ok: #4ec26a;
  --ok-bg: #182319;
  --ok-line: #2b4430;
  --warn: #d9a441;
  --warn-bg: #241f14;
  --warn-line: #453a22;
  --danger: #e66767;
  --danger-line: #4a2a2a;
  --shadow: 0 16px 40px -22px rgba(0, 0, 0, .7);
}
:root[data-theme="light"] { color-scheme: light; }

/* --- appearance settings ---------------------------------------------------- */
.modes { display: flex; gap: 10px; flex-wrap: wrap; margin: 14px 0 4px; }
.mode { display: flex; flex-direction: column; gap: 10px; width: 168px; padding: 14px;
  border: 1px solid var(--line); border-radius: 4px; cursor: pointer; background: var(--card); }
.mode:hover { border-color: var(--faint); }
.mode input { accent-color: var(--brand); }
.mode-name { display: flex; align-items: center; gap: 9px; font-size: 14px; font-weight: 600; }
.mode-note { font-size: 12px; color: var(--faint); line-height: 1.45; }
/* A picture of what each one does, so the choice is not three words. */
.swatch { height: 46px; border-radius: 3px; border: 1px solid var(--line); display: flex;
  align-items: flex-end; gap: 4px; padding: 7px; }
/* Three bars of different heights, so the swatch reads as a tiny chart on that
   theme's surface rather than as three dots. Heights are literal: a percentage
   would resolve against a flex line, not the box. */
.swatch span { display: block; width: 13px; border-radius: 2px; }
.swatch span:nth-child(1) { height: 12px; }
.swatch span:nth-child(2) { height: 21px; }
.swatch span:nth-child(3) { height: 30px; }
.swatch-light { background: #f7f6f3; }
.swatch-light span { background: #424244; }
.swatch-light span:last-child { background: #ffc20f; }
.swatch-dark { background: #17171a; border-color: #2e2e33; }
.swatch-dark span { background: #cfcdc7; }
.swatch-dark span:last-child { background: #ffc20f; }
.swatch-auto { background: linear-gradient(105deg, #f7f6f3 0 50%, #17171a 50% 100%); }
.swatch-auto span { background: #424244; }
.swatch-auto span:last-child { background: #ffc20f; }
.mode.is-current { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }

* { box-sizing: border-box; }
/* Must come before anything that sets `display`. The HTML `hidden` attribute is
   only a UA-stylesheet rule, so any class selector setting display beats it --
   which once showed the masked and unmasked token at the same time, i.e. the
   masking did nothing at all. !important is the point here, not laziness. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 15px/1.6 Barlow, "Helvetica Neue", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
code, pre, .mono, .key { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
a { color: var(--brand-deep); }
h1 { font-size: 30px; font-weight: 700; letter-spacing: -0.02em; margin: 0; }
h2 { font-size: 17px; font-weight: 600; margin: 0; }
h3 { font-size: 15px; font-weight: 600; margin: 26px 0 8px; }
p { margin: 8px 0; }
main { max-width: 1180px; margin: 0 auto; padding: 28px 24px 64px; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.right { text-align: right; }
.eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.section-title { font-size: 21px; font-weight: 700; letter-spacing: -0.01em; margin: 32px 0 4px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* --- shell ---------------------------------------------------------------- */
.topbar { background: var(--card); border-bottom: 1px solid var(--line); }
.topbar-row, .tabs { max-width: 1180px; margin: 0 auto; padding: 0 24px; }
.topbar-row { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding-top: 16px; flex-wrap: wrap; }
.topbar-right { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.brand { height: 30px; width: auto; display: block; }
.brand-text { font-size: 20px; font-weight: 700; letter-spacing: .04em; }
.topbar-bare { padding: 18px 24px; }

/* One line, always. The state ("Not connected yet") must never wrap: a pill that
   grows to three lines drags the whole header row taller and stops reading as a
   pill at all. So the state is nowrap and unshrinkable, and the sentence after
   it is the part that gives way -- min-width:0 is what lets a flex child shrink
   below its text width and actually ellipsize. */
.status { display: flex; align-items: center; gap: 9px; padding: 6px 14px; border-radius: 999px;
  background: var(--page); border: 1px solid var(--line); font-size: 13px;
  max-width: min(64ch, 52vw); min-width: 0; white-space: nowrap; }
.status strong { flex: none; }
.status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex: none; }
.status.is-good { background: var(--ok-bg); border-color: var(--ok-line); }
.status.is-good .dot { background: var(--ok); }
.status.is-warning { background: var(--warn-bg); border-color: var(--warn-line); }
.status.is-warning .dot { background: var(--warn); }
.status-detail { color: var(--muted); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; min-width: 0; flex-shrink: 1; }
/* The one state with something to do gets a link instead of a sentence about
   one: it survives a narrow window, and it works on a phone, where there is no
   hover to reveal the long version. */
.status-link { color: var(--brand-deep); font-weight: 600; text-decoration: none;
  white-space: nowrap; flex: none; }
.status-link:hover { text-decoration: underline; }

/* The account menu is a <details>: no script decides whether it is open, so it
   works with JavaScript blocked and closes on Escape without anyone writing
   that. */
.account { position: relative; }
/* Square, not a pill. The avatar is cut at the brand angle, so its top-right
   corner overhangs by 6px -- inside a 999px radius that overhang pokes out
   through the curve, which is what the header looked wrong for. Hard edges are
   the logo's own anyway; the cut stays on the avatar where it means something. */
.account-button { display: flex; align-items: center; gap: 10px; padding: 5px 8px 5px 12px;
  border: 1px solid var(--line); border-radius: 4px; cursor: pointer; list-style: none; }
.account-button::-webkit-details-marker { display: none; }
.account[open] .account-button { border-color: var(--faint); }
.account-name { font-size: 13px; font-weight: 500; color: var(--muted); }
.avatar { width: 28px; height: 28px; flex: none; background: var(--charcoal);
  transform: skewX(-10.94deg); display: flex; align-items: center; justify-content: center; }
.avatar span { transform: skewX(10.94deg); font-size: 12px; font-weight: 700; color: var(--brand); }
.avatar-lg { width: 34px; height: 34px; }
.avatar-lg span { font-size: 13px; }
.avatar-member, .avatar-manager { background: var(--track); }
.avatar-member span, .avatar-manager span { color: var(--muted); }
.account-menu { position: absolute; right: 0; top: calc(100% + 8px); width: 272px; z-index: 20;
  background: var(--card); border: 1px solid var(--line); border-radius: 4px; box-shadow: var(--shadow); }
.account-head { display: flex; gap: 12px; align-items: center; padding: 14px 16px; border-bottom: 1px solid var(--line-soft); }
.account-id { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.account-id .mono { font-size: 12px; overflow: hidden; text-overflow: ellipsis; }
.account-item { display: block; width: 100%; text-align: left; font: 600 14px inherit;
  padding: 12px 16px; border: 0; background: none; color: var(--ink);
  text-decoration: none; cursor: pointer; }
.account-item:hover { background: var(--line-soft); }
.account-item-danger { color: var(--danger); border-top: 1px solid var(--line-soft); }

.tabs { display: flex; gap: 28px; align-items: flex-end; overflow-x: auto; }
.tab { position: relative; font-size: 14px; font-weight: 600; color: var(--muted);
  text-decoration: none; padding: 13px 2px; white-space: nowrap; }
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--ink); font-weight: 700; }
/* The logo's cut, and the only place the brand shape touches navigation. */
.tab.is-active::after { content: ''; position: absolute; left: -6px; right: -6px; bottom: 0;
  height: 3px; background: var(--brand); transform: skewX(-10.94deg); }

/* --- page furniture -------------------------------------------------------- */
.page-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 22px; }
.page-head .role { margin-left: auto; flex: none; }
.tick { width: 10px; height: 40px; flex: none; margin-top: 5px; background: var(--brand); transform: skewX(-10.94deg); }
.signin { max-width: 46ch; margin: 40px auto; text-align: left; }

.card { background: var(--card); border: 1px solid var(--line); border-radius: 4px; padding: 22px 24px; margin-bottom: 18px; }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 10px; flex-wrap: wrap; }
.card-row { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.slab { background: var(--charcoal); color: var(--charcoal-ink); border-radius: 4px; padding: 18px 22px; margin-bottom: 18px; }
.slab h2 { font-size: 14px; margin-bottom: 6px; }
.slab p { color: #cfcdc7; font-size: 13px; margin: 0; }
.slab code { color: #ffffff; }
.note { border-radius: 4px; padding: 13px 16px; margin: 12px 0; font-size: 14px; }
.note-ok { background: var(--ok-bg); border: 1px solid var(--ok-line); }
.note-warn { background: var(--warn-bg); border: 1px solid var(--warn-line); color: var(--warn); }
.split { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 20px; align-items: start; }
.split-main, .split-rail { min-width: 0; }
/* Two columns, for a before/after pair: the file you already have beside the
   file you are about to write. Same shape as .three, and it collapses at the
   same breakpoint -- a side-by-side comparison that goes off the edge of a
   phone is worse than one stacked. */
.two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin: 14px 0; }
.two > div { display: flex; flex-direction: column; gap: 6px; font-size: 13px; min-width: 0; }
.two pre { margin: 2px 0 0; }
.two pre code { font-size: 12px; }
.three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin: 14px 0; }
.three div { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.three code { font-size: 12px; color: var(--muted); word-break: break-all; }

pre { background: var(--page); border: 1px solid var(--line); border-radius: 4px;
  padding: 14px 16px; overflow-x: auto; font-size: 13px; line-height: 1.8; }
code { font-size: .92em; }

/* --- controls -------------------------------------------------------------- */
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 14px; }
.inline { display: inline; }
button, .btn { font: 600 14px Barlow, "Helvetica Neue", Helvetica, Arial, sans-serif;
  padding: 9px 18px; border: 1px solid var(--line); border-radius: 4px;
  background: var(--card); color: var(--ink); cursor: pointer; text-decoration: none;
  display: inline-block; }
.btn:hover { border-color: var(--faint); }
.btn-primary { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
.btn-solid { background: var(--charcoal); border-color: var(--charcoal); color: var(--charcoal-ink); }
.btn-danger { color: var(--danger); border-color: var(--danger-line); }
button:disabled, .btn:disabled { opacity: .5; cursor: default; }
input[type="date"], input[type="file"], input[type="search"], select {
  font: inherit; font-size: 14px; padding: 8px 10px; border: 1px solid var(--line);
  border-radius: 4px; background: var(--card); color: var(--ink); }
.search { min-width: 240px; flex-grow: 1; max-width: 380px; }

.checks { display: flex; flex-direction: column; gap: 2px; }
.check { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 12px;
  align-items: start; padding: 12px; margin: 0 -12px; border-radius: 4px; cursor: pointer; }
.check:hover { background: var(--line-soft); }
.check input { margin-top: 3px; width: 16px; height: 16px; accent-color: var(--brand); }
.check-body { display: flex; flex-direction: column; gap: 3px; }
.check-title { font-size: 14px; font-weight: 600; }
.check-env { font-size: 11px; color: var(--faint); }
.optional { border-top: 1px solid var(--line); margin-top: 18px; padding-top: 16px; }

/* --- the token block ------------------------------------------------------- */
.keyline { display: flex; align-items: stretch; margin: 6px 0 4px; }
.keyline-cut { width: 8px; flex: none; margin-right: 10px; background: var(--brand); transform: skewX(-10.94deg); }
.key { flex-grow: 1; background: var(--charcoal); color: var(--charcoal-ink);
  border-radius: 4px; padding: 15px 18px; font-size: 14px; letter-spacing: .04em; word-break: break-all; }
.paths { margin: 12px 0 0; display: flex; flex-direction: column; gap: 12px; }
.paths dt { font-size: 13px; font-weight: 600; }
.paths dd { margin: 3px 0 0; font-size: 12px; color: var(--muted); word-break: break-all; }
.params { margin: 8px 0 0; }
.params dt { padding-top: 14px; border-top: 1px solid var(--line-soft); }
.params dt code { font-size: 12px; word-break: break-all; }
.params dd { margin: 4px 0 14px; font-size: 14px; color: var(--ink-2); line-height: 1.6; }
.steps { margin: 12px 0 0; padding-left: 20px; }
.steps li { margin: 8px 0; color: var(--ink-2); }

/* API tokens on the Access page. The tick boxes and the token block are the
   guide page's and the token page's own classes -- only the layout around them
   is new, so a change to how a scope or a secret looks lands in one place. */
.token-form { display: flex; flex-direction: column; gap: 4px; margin: 14px 0 6px; }
.token-form .eyebrow { margin: 14px 0 2px; }
.token-form .eyebrow:first-of-type { margin-top: 8px; }
.token-form .btn { align-self: flex-start; margin-top: 10px; }
.new-token { border: 1px solid var(--warn-line); background: var(--warn-bg);
  border-radius: 4px; padding: 4px 16px 14px; margin-bottom: 18px; }
.new-token h3 { margin-top: 14px; }

/* --- the settings precedence diagram on the guide page ---------------------
   Hand-drawn SVG, coloured from HERE rather than from fill= attributes on the
   markup: the portal has a light and a dark theme, and a hardcoded fill is
   invisible in one of them. Same reason the usage charts do it this way, and
   the same CSP constraint underneath -- a `style=` attribute on an element is
   blocked, a class is not. */
.prec { max-width: 100%; height: auto; }
.prec-bar { fill: var(--track); stroke: var(--line); stroke-width: 1; }
/* Charcoal for the level nobody can override, so the one that outranks
   everything reads as the heaviest thing on the page. */
.prec-bar.is-managed { fill: var(--charcoal); stroke: var(--charcoal); }
.prec-bar.is-yours { fill: var(--card); stroke: var(--line); }
/* The brand cut, at the logo's own angle, marking the row this portal fills in.
   Yellow as a FILL, never behind text -- it is 1.7:1 on a light surface. */
.prec-cut { fill: var(--brand); }
.prec-n { font-size: 12px; font-weight: 700; fill: var(--faint); }
.prec-name { font-size: 14px; font-weight: 600; fill: var(--ink); }
.prec-who { font-size: 11px; fill: var(--muted); }
.prec-n.is-on-dark, .prec-name.is-on-dark { fill: var(--charcoal-ink); }
.prec-who.is-on-dark { fill: var(--charcoal-ink); opacity: .75; }
.prec-file { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; fill: var(--muted); }
.prec-file.is-faint { fill: var(--faint); }
.prec-axis { stroke: var(--faint); stroke-width: 1.5; }
.prec-mark { fill: var(--faint); }
.prec-axis-label { font-size: 11px; font-weight: 600; fill: var(--faint);
  letter-spacing: .08em; text-transform: uppercase; }

/* --- the language picker ---------------------------------------------------
   It reuses .account and .account-menu wholesale, because it IS the same
   control as the avatar menu beside it: a <details>, no script, closes on
   Escape for free. Only the button face differs. */
.lang-menu .account-button { padding-left: 10px; padding-right: 10px; }
/* The 1px inset border is what keeps the Japanese flag from reading as a lone
   red dot: its field is white, and so is the card behind it in the light theme.
   Inset rather than a real border so all three stay exactly 24x16 and the menu
   rows line up. */
.flag { width: 24px; height: 16px; border-radius: 2px; flex: none;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18); }
.lang-menu .account-item { display: flex; align-items: center; gap: 10px; }
.account-menu-narrow { min-width: 168px; }
/* The tick goes AFTER the name here: the flag already occupies the gutter, and
   a marker in front of it would push the three flags out of line with each
   other -- which is the one thing a column of flags has to get right. */
.lang-menu .account-item.is-current::after { content: '\00a0\2713'; color: var(--brand-deep); }
.account-item.is-current { font-weight: 700; color: var(--ink); }
/* Visible to a screen reader, not on screen: the button face is two letters,
   which reads as an abbreviation rather than as "Language". */
.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; }
/* Shown above a page this language does not have a translation of yet. */
.note-lang { margin-bottom: 18px; }

.role { font-size: 12px; font-weight: 600; padding: 3px 10px; border-radius: 999px;
  background: var(--track); color: var(--muted); white-space: nowrap; }
.role-manager { background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-line); }
.role-admin { background: var(--charcoal); color: var(--brand); }
/* A turn that finished and one that did not, on the session screen. The word
   carries the meaning and the colour only reinforces it -- the same rule the
   norm colours follow, for the same reader. */
.role-ok { background: var(--ok-bg); color: var(--ok); border: 1px solid var(--ok-line); }
.role-error { background: var(--track); color: var(--danger); border: 1px solid var(--danger-line); }

/* --- tiles ---------------------------------------------------------------- */
.tiles { display: grid; gap: 12px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); }
.tiles-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tiles-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.tile { background: var(--card); border: 1px solid var(--line); border-radius: 4px;
  padding: 15px 18px; display: flex; flex-direction: column; gap: 3px; }
.tile-label { font-size: 12px; color: var(--faint); }
.tile-value { font-size: 24px; font-weight: 700; line-height: 1.15; }
.tile-note { font-size: 11px; color: var(--faint); line-height: 1.4; }
.is-ok { color: var(--ok); }
.is-warn, .is-warning { color: var(--warn); }
.is-critical { color: var(--danger); }
.is-good { color: var(--ok); }

/* Change against the previous window. Direction, not judgement: a cost that
   fell is not "good" on a page somebody reads to plan capacity, so both arrows
   are the same muted weight and only the glyph differs. */
.delta { font-size: 11px; color: var(--faint); }
.delta.up { color: var(--warn); }
.delta.down { color: var(--muted); }

/* The one line somebody repeats in a meeting, above the unused-seat table. */
.headline { margin: 0 0 12px; font-size: 15px; }
.headline .muted { display: block; }

/* Twenty-four hours of a day, folded in the browser because only it knows which
   hour a timestamp was where the reader sat. An empty hour keeps its column so
   the shape of a day stays readable. */
.hours { display: flex; align-items: flex-end; gap: 3px; height: 120px;
  margin-top: 6px; }
.hour { flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end;
  height: 100%; min-width: 0; }
.hour-fill { background: var(--bar); border-radius: 2px 2px 0 0; min-height: 2px; }
.hour-fill.is-empty { background: var(--track); }
.hour-label { font-size: 10px; color: var(--faint); text-align: center;
  padding-top: 4px; }

/* The tidy-up counts and the content-flag list: a label, a value, a caveat. */
.board { display: flex; flex-direction: column; }
.board-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 12px; align-items: center; padding: 9px 0;
  border-bottom: 1px solid var(--line-soft); }
.board-row:last-child { border-bottom: 0; }

/* --- dashboard ------------------------------------------------------------- */
.filters { display: flex; gap: 18px; align-items: flex-end; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line); border-radius: 4px;
  padding: 14px 18px; margin-bottom: 16px; }
.filters label { display: flex; flex-direction: column; gap: 6px; font-size: 11px;
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.filters .small { margin-left: auto; }
/* Who a drill is looking at, beside ‹ Back. Filled like a chip so it reads as
   state, not as one more label over a control. */
.drill-subject { display: inline-flex; align-items: baseline; gap: 8px; align-self: center;
  padding: 6px 12px; border-radius: 999px; background: var(--track); color: var(--ink-2);
  font-size: 13px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drill-subject[hidden] { display: none; }
.drill-subject-label { font-size: 11px; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint); }
.loading { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 14px; }
.spinner { width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--brand); animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* A refetch keeps its frame and grows a spinner in each heading, so the numbers
   on screen stay the ones that were true while the new ones are on their way. */
#tiles.is-loading, #panels.is-loading, .card.is-loading { opacity: .5; }
#panels.is-loading h2::after, .card.is-loading h2::after {
  content: ''; display: inline-block; vertical-align: -2px; margin-left: 8px;
  width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--brand); animation: spin .8s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .spinner, #panels.is-loading h2::after, .card.is-loading h2::after { animation: none; }
}

.chart { width: 100%; overflow-x: auto; }
.chart svg { display: block; }
.grid { stroke: var(--line); stroke-width: 1; }
.axis { fill: var(--faint); font-size: 11px; }
.bar { fill: var(--bar); }
.bar.is-current { fill: var(--brand); }
/* The same two colours the People table already gives a norm, so a day that
   reads red on one screen reads red on the other. A bar with neither class is
   a department with no allowance set -- neutral, deliberately: green would
   claim it is behaving and red would claim it is not. */
.bar.is-in-norm { fill: var(--ok); }
.bar.is-out-norm { fill: var(--danger); }
/* Behind the bars, and quiet: the band is the number being edited, not a
   measurement, so it must not compete with the days it is judging. */
.norm-band { fill: var(--ok-bg); stroke: var(--ok-line); stroke-width: 1; }
/* Transparent, and the full height of its band: a one-pixel bar is not
   something anyone can point at. */
.hit { fill: var(--ink); fill-opacity: 0; }
.hit:hover, .hit:focus { fill-opacity: .06; outline: none; }
.hit:focus-visible { outline: 2px solid var(--brand-deep); }
.table-view { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; }
.table-view summary { cursor: pointer; color: var(--muted); font-weight: 600; }

.rank { margin: 13px 0; }
.rank.is-muted { opacity: .7; }
.rank-head { display: flex; gap: 14px; justify-content: space-between; align-items: baseline; font-size: 14px; }
.rank-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
.rank-value { font-variant-numeric: tabular-nums; flex: none; font-weight: 600; }
.rank-track { display: flex; height: 10px; margin-top: 6px; background: var(--track); border-radius: 5px; overflow: hidden; }
.rank-fill { background: var(--bar); border-radius: 5px; min-width: 2px; }
/* The 2px surface gap is what separates the two segments -- never a border,
   which would add ink that is not data. */
.rank-fill.is-failed { background: var(--danger); margin-left: 2px; }
/* The allowance chart. Both ways OUT of a range wear the same red -- idle is a
   finding too -- and a bar with neither class is a department nobody has set an
   allowance for, which is not a claim about that person at all. */
.rank-fill.is-in-norm { background: var(--ok); }
.rank-fill.is-out-norm { background: var(--danger); }
.rank-note { font-size: 11px; color: var(--faint); }
.legend { display: flex; gap: 16px; align-items: center; }
.legend-item { display: flex; gap: 6px; align-items: center; font-size: 12px; color: var(--muted); }
.legend-key { width: 11px; height: 11px; border-radius: 2px; display: inline-block; }
.legend-key.is-ok { background: var(--bar); }
.legend-key.is-failed { background: var(--danger); }
.legend-key.is-in-norm { background: var(--ok); }
.legend-key.is-out-norm { background: var(--danger); }
.legend-key.is-band { background: var(--ok-bg); border: 1px solid var(--ok-line); }

/* --- tables and paging ------------------------------------------------------ */
.table-controls { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.table-scroll { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid var(--line-soft); }
.table thead th { font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); border-bottom: 1px solid var(--line); }
.table td.empty { text-align: center; color: var(--muted); padding: 28px 10px; }
/* The design's numeric column. .data-table gets this from its own rule; this
   card is a plain .table and the count would otherwise sit left of a heading
   that is right-aligned. */
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
/* The member list folds away behind the count, so a head scanning ten projects
   reads ten numbers rather than ten address lists. */
.table .num summary { cursor: pointer; }
.table .num details[open] { text-align: left; }
.person { display: flex; align-items: center; gap: 12px; min-width: 0; }
.person .mono { font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.data-table { width: 100%; max-width: 24rem; border-collapse: collapse; margin-top: 10px; font-size: 13px; }
.data-table th, .data-table td { padding: 5px 8px; border-top: 1px solid var(--line-soft); text-align: left; font-weight: 400; }
.data-table td { text-align: right; font-variant-numeric: tabular-nums; }
.pager { display: flex; align-items: center; gap: 14px; margin-top: 16px; padding-top: 14px;
  border-top: 1px solid var(--line); font-size: 13px; }
.pager .btn { padding: 6px 13px; font-size: 13px; }
.status-line { font-size: 13px; color: var(--muted); min-height: 1.4em; margin: 8px 0 0; }

footer { margin-top: 36px; padding-top: 16px; border-top: 1px solid var(--line); }

/* --- narrow ---------------------------------------------------------------- */
@media (max-width: 900px) {
  .split, .two, .three, .tiles-3, .tiles-4 { grid-template-columns: minmax(0, 1fr); }
  .status-detail { display: none; }
  main { padding: 20px 16px 56px; }
  h1 { font-size: 25px; }
  .btn, button { padding: 11px 18px; }
  .filters { gap: 12px; }
  .filters label { flex-grow: 1; }
}

/* --- the Usage sub-tabs and the session table ------------------------------ */
.subtabs { display: flex; gap: 6px; margin-bottom: 14px; }
.subtab { font-size: 13px; font-weight: 600; padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--muted); cursor: pointer; }
.subtab:hover { color: var(--ink); }
/* The Access page's tabs are links rather than buttons -- they are server-side,
   so there is nothing for a script to do. Same pill, minus the anchor styling. */
a.subtab { text-decoration: none; display: inline-block; }
.subtab.is-active { background: var(--charcoal); border-color: var(--charcoal); color: var(--charcoal-ink); }
/* Chips carry names a client chose (a skill, a model), so they wrap and
   truncate rather than pushing the table wider than the page. */
.chips { display: flex; gap: 5px; flex-wrap: wrap; align-items: center; }
.chip { display: inline-flex; align-items: center; gap: 6px; max-width: 22ch;
  padding: 2px 9px; border-radius: 999px; background: var(--track); color: var(--ink-2);
  font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chip-count { font-weight: 700; color: var(--faint); }
/* A department with nobody heading it. Amber rather than red on purpose: it is
   a gap to fill, not a fault -- a department created before HR files anybody
   under it starts here and is meant to. */
.chip-warn { background: var(--warn-bg); color: var(--warn);
  box-shadow: inset 0 0 0 1px var(--warn-line); }
/* A PM on the department-projects card. Like .chip, but it holds a form: the
   × that removes that PM is a submit button, because every write on this
   portal is a real form post with a CSRF token, not a fetch. */
.pm-chip { display: inline-flex; align-items: center; gap: 4px; max-width: 26ch;
  padding: 2px 4px 2px 9px; border-radius: 999px; background: var(--track);
  color: var(--ink-2); font-size: 12px; white-space: nowrap; }
.pm-chip form { display: inline-flex; }
.pm-chip button { padding: 0 5px; font-size: 12px; line-height: 1.4;
  border-radius: 999px; }
#sessions-table td, #session-turns td { vertical-align: top; }
#sessions-table .mono, #session-turns .mono { font-size: 11px; }

/* A cost that rose past insights.SPIKE_RATIO against the window before. A
   reading aid on one screen: nothing is sent anywhere and nobody is ranked. */
.spike { color: var(--warn); font-weight: 700; }

/* A named input inside a .row form. Every other form here labels its one field
   with a placeholder; /norms has four numbers that mean different things, and a
   placeholder disappears the moment somebody types. Same stacked label as the
   dashboard filter bar, narrower because these are numbers, not addresses. */
.field { display: flex; flex-direction: column; gap: 6px; font-size: 11px;
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); }
.field .search { min-width: 110px; max-width: 160px; }

/* Inside the department's daily allowance, and outside it. Both ends of the
   range are "outside": an idle seat and an expensive one are both worth a
   second look, which is why there is no third colour for "under". */
.is-in-norm  { color: var(--ok); font-weight: 600; }
.is-out-norm { color: var(--danger); font-weight: 700; }
