/* ═══════════════════════════════════════════════════════════════════════
   DESK — Jura Control

   Not a dashboard. A dashboard is a grid of equal cards, and a grid of
   equal cards cannot be beautiful: every element claims the same
   importance, so nothing has any. That is a filing cabinet with rounded
   corners.

   This is a COMPOSITION. One screen, no scrolling, deliberately asymmetric:

     left    air. Type set directly on the blurred footage, at real size.
             The verdict, the money, the vitals. Nothing between the reader
             and the material.
     right   matter. One tall glass ledger holding what needs him, who is
             working, what is running, and what the workers last said.

   Air against matter is the whole composition. Six equal panes is not a
   composition, it is a spreadsheet.

   Depth is not a modal. Click anything and it EXPANDS IN PLACE into a
   full-canvas plate that grows out of exactly what you clicked, while the
   composition behind recedes and goes out of focus. Close it and it
   collapses back to where it came from. You never lose your place because
   your place never went anywhere.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  --rail-h: 54px;
  --pad-x: 40px;
  --hair: rgba(160, 130, 118, 0.16);

  /* Written by stage.js while a plate is open. The composition reads it and
     recedes; one number, one paint, no per-element work. */
  --recede: 0;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100%; overflow: hidden;
  font-family: var(--font-ui);
  color: var(--ink-1);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* The gradient lives on html as the pre-decode fallback. body MUST stay
   transparent or it paints straight over #videobg and the footage is lost —
   which is exactly what happened once already. */
html { background: var(--paper-warm); }
body { background: transparent; }

button { -webkit-appearance: none; appearance: none; background: none;
         border: none; color: inherit; font: inherit; cursor: pointer; text-align: left; }
input, textarea, select { font: inherit; color: inherit; }

::selection { background: rgba(196,120,112,0.22); }

.scroll { overflow-y: auto; overflow-x: hidden; scrollbar-width: thin;
          scrollbar-color: rgba(170,142,128,0.28) transparent; }
.scroll::-webkit-scrollbar { width: 9px; height: 9px; }
.scroll::-webkit-scrollbar-thumb {
  background: rgba(170,142,128,0.26); border-radius: 99px;
  border: 3px solid transparent; background-clip: content-box;
}
.scroll::-webkit-scrollbar-track { background: transparent; }

/* ═══════════════════════════════════════════════════════════════════════
   SHELL
   ═══════════════════════════════════════════════════════════════════════ */
#shell {
  position: fixed; inset: 0; z-index: 10;
  display: flex; flex-direction: column;
  transform-origin: 50% 46%;
}
/* The recede — everything that is not the open plate steps back and goes
   soft, so the plate is not floating ON the app, the app is BEHIND it.

   Applied ONLY while a plate is actually open. A filter, even blur(0px),
   forces the browser to promote this element and run a filter pass on
   every frame for the whole lifetime of the page; against a playing video
   that is a permanent tax paid for an effect used a few seconds at a time.
   The same goes for will-change. This was the lag. */
#shell.receding {
  transform: scale(calc(1 - 0.028 * var(--recede)));
  filter: blur(calc(7px * var(--recede)))
          brightness(calc(1 - 0.13 * var(--recede)));
  will-change: transform, filter;
}

/* ── Top rail ──────────────────────────────────────────────────────────
   One hairline of chrome. Everything that used to live in a header full of
   competing chips is either in the composition or behind ⌘K.            */
/* Search is the one control here, so it goes in the middle where a control
   belongs. The wordmark and the clock are positioned off the edges rather
   than laid out in flow, so the search field is centred on the VIEWPORT and
   not on whatever space happens to be left between them. */
.rail {
  flex: 0 0 auto; height: var(--rail-h); position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 0 var(--pad-x);
  border-bottom: 1px solid var(--hair);
}
.rail .wordmark { position: absolute; left: var(--pad-x); top: 50%; transform: translateY(-50%); }
.rail .rail-clock { position: absolute; right: var(--pad-x); top: 50%; transform: translateY(-50%); }
.wordmark {
  font-family: var(--font-display);
  font-size: 1.42rem; font-weight: 600; letter-spacing: 0.02em;
  color: var(--ink-1); line-height: 1;
}
.rail-clock {
  font-size: 0.72rem; color: var(--ink-3);
  font-variant-numeric: tabular-nums; letter-spacing: 0.03em;
}
.rail-k {
  display: flex; align-items: center; gap: 9px;
  height: 34px; padding: 0 22px;
  border-radius: var(--r-pill);
  font-size: 0.775rem; color: var(--ink-2); letter-spacing: -0.005em;
  transition: color var(--t-fast) var(--snap), border-color var(--t-fast) var(--snap);
}
.rail-k svg { color: var(--ink-4); flex: 0 0 auto;
              transition: color var(--t-fast) var(--snap); }
.rail-k:hover { color: var(--ink-1); }
.rail-k:hover svg { color: var(--rose-deep); }

/* ── Canvas ────────────────────────────────────────────────────────────
   The asymmetry is the point. 1.5 to 0.85 is close enough to the golden
   section to feel composed and far enough from 1:1 to never read as two
   columns of the same thing.                                             */
#canvas {
  flex: 1 1 auto; min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(370px, 0.85fr);
  gap: 34px;
  padding: 30px var(--pad-x) 34px;
}

/* ═══════════════════════════════════════════════════════════════════════
   LEFT — AIR
   Three blocks, pushed apart to the full height. This is a spread, not a
   stack: the space between them is doing as much work as the type.
   ═══════════════════════════════════════════════════════════════════════ */
.air {
  display: flex; flex-direction: column; justify-content: space-between;
  min-width: 0; min-height: 0;
  /* Without a ceiling the composition sprawls on a wide monitor: the
     vitals stretch to a metre apart and the verdict floats in a field of
     nothing. Type has a comfortable measure and so does a layout. */
  max-width: 860px;
}

.block { min-width: 0; }

/* The rules are flex children, so space-between distributes the gaps around
   them and each line lands centred in its own gap rather than clinging to
   the block beneath it. They separate three unrelated readings — a verdict,
   a figure and a set of instruments — and without them the column reads as
   one long run of text. */
.rule {
  flex: 0 0 auto; height: 1px; align-self: stretch;
  background: linear-gradient(90deg,
    rgba(160,130,118,0.30) 0%, rgba(160,130,118,0.16) 62%, transparent 100%);
}
.eyebrow {
  font-size: 0.56rem; font-weight: 600; letter-spacing: 0.28em;
  text-transform: uppercase; color: var(--ink-4);
  margin-bottom: 14px;
}

/* ── The verdict ───────────────────────────────────────────────────────
   The only sentence in this app that is always worth reading, set at the
   size that claim deserves.                                              */
.verdict {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 4.4vw, 4.15rem);
  font-weight: 500; line-height: 0.98; letter-spacing: -0.018em;
  color: var(--ink-1);
  /* The container clips, so an exchanged sentence travels like the leaf of a
     departures board. The padding is descender clearance — "needs you" has a
     y, and Cormorant's descenders are long. */
  position: relative; overflow: hidden; padding-bottom: 0.16em;
  transition: color var(--t-slow) var(--glide);
}
.verdict .v-now { display: block; }
.verdict .v-out {
  display: block; position: absolute; left: 0; right: 0; top: 0;
  white-space: nowrap; pointer-events: none;
}
.verdict.warn { color: #8a6432; }
.verdict.bad  { color: #9c433e; }

.verdict-sub {
  margin-top: 18px;
  display: flex; align-items: center; gap: 0;
  flex-wrap: wrap;
  font-size: 0.795rem; color: var(--ink-2);
  letter-spacing: -0.004em;
}
.vs-item { display: inline-flex; align-items: baseline; gap: 6px; }
.vs-item + .vs-item::before {
  content: ''; display: inline-block;
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--ink-4); margin: 0 13px 0 0;
  transform: translateY(-3px);
}
.vs-n { font-variant-numeric: tabular-nums; font-weight: 550; color: var(--ink-1); }

/* ── The money ─────────────────────────────────────────────────────────
   One figure, enormous, in the display face. It is the number the whole
   company is about; everything else on this screen is a reading.         */
.money-fig {
  font-family: var(--font-display);
  font-size: clamp(3.2rem, 6.2vw, 5.6rem);
  font-weight: 500; line-height: 0.92; letter-spacing: -0.022em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-1);
}
.money-meta {
  margin-top: 20px; display: flex; gap: 44px; flex-wrap: wrap;
}
.mm { min-width: 0; }
.mm-l {
  font-size: 0.555rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-4); margin-bottom: 6px;
}
.mm-v {
  font-size: 1.02rem; font-weight: 550; letter-spacing: -0.016em;
  font-variant-numeric: tabular-nums;
}
.mm-v.zero { color: var(--ok); }
.mm-v.spend { color: var(--danger); }
.mm-v.unknown { color: var(--warn); }

/* ── The vitals ────────────────────────────────────────────────────────
   Hairline instruments, not chunky progress bars. A 3px track with a
   tabular figure above it reads as a measurement; a 10px rounded bar with
   a gradient reads as a download.                                        */
.vitals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 26px; }
.vital { min-width: 0; }
.vital-h {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 9px;
}
.vital-l {
  font-size: 0.555rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vital-v {
  font-size: 0.895rem; font-weight: 550; letter-spacing: -0.018em;
  font-variant-numeric: tabular-nums; flex: 0 0 auto;
}
.vital-t {
  height: 3px; border-radius: 99px; overflow: hidden;
  background: rgba(160,130,118,0.19);
}
.vital-f { height: 100%; border-radius: 99px; width: 0; }
.vital-f.ok   { background: #5c9b64; }
.vital-f.warn { background: #b8894f; }
.vital-f.bad  { background: #bf5852; }
.vital-n {
  margin-top: 8px; font-size: 0.635rem; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════
   RIGHT — MATTER
   One ledger. Sections separated by hairlines, never by more boxes.
   ═══════════════════════════════════════════════════════════════════════ */
.ledger {
  border-radius: var(--r-2xl);
  padding: 4px 26px;
  display: flex; flex-direction: column;
  min-height: 0;
}
.ledger-scroll { overflow-y: auto; overflow-x: hidden; scrollbar-width: none; margin: 0 -4px; padding: 0 4px; }
.ledger-scroll::-webkit-scrollbar { width: 0; }

.sect { padding: 22px 0; border-top: 1px solid var(--hair); }
.sect:first-child { border-top: 0; }
.sect-h {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 15px;
}
.sect-t {
  flex: 1; font-size: 0.555rem; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-3);
}
.sect-x {
  font-size: 0.63rem; color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

/* Anything that opens a plate. The lift is small and the shadow does most
   of the work — a big translate on hover is a tell that nobody tuned it. */
.tap {
  cursor: pointer; border-radius: var(--r-md);
  margin: 0 -12px; padding: 0 12px;
  transition: background var(--t-fast) var(--snap);
}
.tap:hover { background: rgba(255,255,255,0.42); }

/* ── Needs you ─────────────────────────────────────────────────────────── */
.need {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 11px 12px; margin: 0 -12px;
  border-radius: var(--r-sm); cursor: pointer;
  transition: background var(--t-fast) var(--snap);
}
.need:hover { background: rgba(255,255,255,0.5); }
.need-t {
  flex: 0 0 auto; margin-top: 2px;
  font-size: 0.5rem; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; padding: 4px 8px; border-radius: 7px;
}
.need-t.act  { background: rgba(191,88,82,0.14);  color: #9c433e; }
.need-t.warn { background: rgba(184,137,79,0.17); color: #86602f; }
.need-m { flex: 1; min-width: 0; font-size: 0.83rem; line-height: 1.45; }
.need-m b { font-weight: 600; }
.need-w {
  flex: 0 0 auto; margin-top: 2px;
  font-size: 0.63rem; color: var(--ink-4); font-variant-numeric: tabular-nums;
}
.allclear { display: flex; align-items: baseline; gap: 10px; font-size: 0.86rem; color: var(--ink-2); }
.allclear b { color: var(--ok); font-weight: 550; }

/* ── Workers ───────────────────────────────────────────────────────────── */
.worker {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 12px; margin: 0 -12px;
  border-radius: var(--r-sm); cursor: pointer;
  transition: background var(--t-fast) var(--snap);
}
.worker:hover { background: rgba(255,255,255,0.5); }
.worker + .worker { margin-top: 2px; }
.worb {
  width: 38px; height: 38px; border-radius: 13px; flex: 0 0 auto;
  display: grid; place-items: center; color: #fff;
  font-family: var(--font-display); font-size: 1.28rem; font-weight: 600;
  line-height: 1; padding-bottom: 2px;
}
.worb.bing { background: linear-gradient(140deg, #a3bc9e, #6f8a69);
             box-shadow: 0 2px 10px rgba(111,138,105,0.3); }
.worb.bong { background: linear-gradient(140deg, #e2a9a2, #c0716b);
             box-shadow: 0 2px 10px rgba(192,113,107,0.3); }
.wk-main { flex: 1; min-width: 0; }
.wk-n { font-size: 0.855rem; font-weight: 560; letter-spacing: -0.014em; }
.wk-s {
  margin-top: 3px; font-size: 0.665rem; color: var(--ink-3);
  display: flex; align-items: center; gap: 7px;
}
.wk-d { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; background: var(--ok); }
.wk-d.idle    { background: #a5bda8; }
.wk-d.working { background: var(--ok); animation: wk-breathe 2.3s ease-in-out infinite; }
.wk-d.stale   { background: var(--danger); }
.wk-d.failing { background: var(--warn); }
@keyframes wk-breathe {
  0%,100% { box-shadow: 0 0 0 0 rgba(92,155,100,0.42); }
  50%     { box-shadow: 0 0 0 6px rgba(92,155,100,0); }
}

/* ── Services ──────────────────────────────────────────────────────────── */
.svc-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
.svc {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: var(--r-xs);
  background: rgba(255,255,255,0.4);
  border: 1px solid rgba(255,255,255,0.5);
  font-size: 0.685rem; cursor: pointer; min-width: 0;
  transition: background var(--t-fast) var(--snap), border-color var(--t-fast) var(--snap);
}
.svc:hover { background: rgba(255,255,255,0.78); border-color: rgba(255,255,255,0.9); }
.svc i { width: 5px; height: 5px; border-radius: 50%; flex: 0 0 auto; }
.svc i.up { background: var(--ok); }
.svc i.dn { background: var(--danger); }
/* min-width:0 or the ellipsis can never engage — a flex item defaults to
   "never smaller than my content" and the chip grows out of its column. */
.svc span {
  min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Digest ────────────────────────────────────────────────────────────
   The workers write short prose full of figures. Left as plain body text
   it is a grey slab you skip; the numbers are the only part anyone reads
   at a glance, so they are set as numbers — tabular, heavier, in full ink
   — and the prose recedes around them.                                   */
.dig { max-height: 300px; overflow: hidden; }

/* ── The digest as a presentation ─────────────────────────────────────
   A verdict that leads, the readings as a table, the rest as notes. See
   digestModel() in control.js for how the paragraph is read back into
   these three parts. */
.dg { min-width: 0; }
.dg-verdict {
  font-family: var(--font-display);
  font-size: 1.32rem; line-height: 1.32; letter-spacing: -0.008em;
  color: var(--ink-1); margin-bottom: 18px;
}
.dg-full .dg-verdict { font-size: 1.74rem; line-height: 1.28; margin-bottom: 26px; }

.dg-lbl {
  font-size: 0.535rem; font-weight: 600; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-4);
  margin: 20px 0 9px;
}

/* Three columns, so the eye can run down the values without reading the
   labels — which is the entire reason to make this a table. */
.dg-rows .row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.3fr);
  gap: 14px; align-items: baseline;
  padding: 11px 14px; font-size: 0.79rem;
}
.dg-k { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dg-v {
  font-variant-numeric: tabular-nums; font-weight: 620;
  color: var(--ink-1); letter-spacing: -0.014em; text-align: right;
  font-size: 0.855rem;
}
.dg-n {
  font-size: 0.685rem; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dg-n i {
  font-style: normal; font-weight: 700; margin-right: 5px;
  display: inline-block; width: 0.7em;
}
.dg-n.down i { color: var(--ok); }
.dg-n.up   i { color: var(--amber); }
.dg-n.flag i { color: var(--danger); }

.dg-notes { margin: 0; padding: 0; list-style: none; }
.dg-notes li {
  position: relative; padding-left: 17px; margin-bottom: 6px;
  font-size: 0.755rem; color: var(--ink-3); line-height: 1.5;
}
.dg-notes li::before {
  content: ''; position: absolute; left: 3px; top: 0.58em;
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--ink-5);
}
.digest-body {
  font-size: 0.815rem; line-height: 1.72; color: var(--ink-2);
  letter-spacing: -0.002em;
}
.digest-body .rich-p { margin-bottom: 10px; }
.digest-body .rich-p:last-child { margin-bottom: 0; }

/* The emoji the agent opens with, lifted out of the text. Inline at body
   size it reads as a typo; given its own optical slot it reads as a mark. */
.dig-mark {
  float: left; margin: 1px 11px 0 0;
  font-size: 1.4rem; line-height: 1;
  filter: saturate(0.82);
}

/* Figures. This is what makes a digest skimmable: tabular so columns of
   them line up, heavier and in full ink so the eye finds them first. */
.fig {
  font-variant-numeric: tabular-nums;
  font-weight: 600; color: var(--ink-1);
  letter-spacing: -0.012em;
}

.dig-more {
  margin-top: 13px; font-size: 0.7rem; font-weight: 550; color: var(--rose-deep);
  transition: transform var(--t-fast) var(--glide);
}
.sect.tap:hover .dig-more { transform: translateX(3px); }

/* ═══════════════════════════════════════════════════════════════════════
   PLATES — the expansion

   The plate is composed of two layers on purpose. The GLASS animates from
   the bounds of whatever you clicked to the full canvas; because it is a
   plain rounded rectangle, scaling it distorts nothing you can see. The
   CONTENT does not scale at all — it fades and rises into place once the
   glass has nearly arrived. Scaling live text is what makes cheap zoom
   transitions look like a video call freezing.
   ═══════════════════════════════════════════════════════════════════════ */
#plate {
  position: fixed; z-index: 60;
  display: none; flex-direction: column;
  border-radius: var(--r-2xl);
  overflow: hidden;
}
#plate.on { display: flex; }
#plate-glass {
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  transform-origin: top left;
  will-change: transform;
  /* Driven per frame by stage.js — see the note on .g in surface.css. */
  transition: none;
}

/* ── The title space ───────────────────────────────────────────────────
   The header floats OVER the body rather than sitting above it, and the
   body is padded to start beneath. Content therefore passes under the
   title and stays faintly visible through it, which is what tells you the
   list is still there and still moving rather than being replaced.

   Two layers, deliberately: the blur and the wash live on a ::before that
   is masked to fade out at the bottom, so the bar has a soft lower edge
   instead of a hard cut. The title and the close button sit above that,
   unmasked — masking them would fade the button's lower half.            */
#plate { --hh: 92px; }
#plate.in-ledger { --hh: 76px; }

.plate-h {
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  height: var(--hh);
  display: flex; align-items: center; gap: 16px;
  padding: 0 34px;
  pointer-events: none;
}
.plate-h > * { pointer-events: auto; }
.plate-h::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg,
    rgba(255,253,251,0.62) 0%, rgba(255,253,251,0.40) 58%, rgba(255,253,251,0) 100%);
  -webkit-backdrop-filter: blur(9px) saturate(1.2);
          backdrop-filter: blur(9px) saturate(1.2);
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
}

/* A plate confined to the ledger is a column, not a canvas: the padding
   and the title come down to the panel's own scale so it reads as the
   panel having turned over rather than as a small window. */
#plate.in-ledger .plate-h { padding: 0 24px; gap: 11px; }
#plate.in-ledger .plate-t { font-size: 1.5rem; }
#plate.in-ledger .plate-b { padding: var(--hh) 24px 24px; }
#plate.in-ledger .lbl { margin: 20px 0 10px; }
#plate.in-ledger .row { gap: 11px; padding: 11px 2px; font-size: 0.79rem; }
#plate.in-ledger .row.tapper { margin: 0 -10px; padding: 11px 10px; }
#plate.in-ledger .btn { padding: 9px 14px; font-size: 0.72rem; }
.plate-t {
  flex: 1; min-width: 0;
  font-family: var(--font-display);
  font-size: 2.1rem; font-weight: 600; letter-spacing: -0.012em; line-height: 1.05;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.plate-sub {
  font-size: 0.7rem; color: var(--ink-3); font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}
.plate-x {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(160,130,118,0.13); color: var(--ink-2);
  transition: background var(--t-fast) var(--snap), transform var(--t-med) var(--glide);
}
.plate-x:hover { background: rgba(160,130,118,0.24); transform: rotate(90deg); }
.plate-b {
  flex: 1 1 auto; min-height: 0;
  padding: var(--hh) 34px 30px;   /* clears the floating title space */
}
.plate-b.flat { display: flex; flex-direction: column; }

/* Content rises in after the glass lands. */
#plate-content { display: contents; }
.plate-in { will-change: transform, opacity; }

/* ── Plate furniture ───────────────────────────────────────────────────── */
.lbl {
  font-size: 0.555rem; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-3);
  margin: 26px 0 12px;
}
.lbl:first-child { margin-top: 0; }

/* ── Rows ──────────────────────────────────────────────────────────────
   Zebra rather than rules. A hairline between every row draws thirty lines
   to separate thirty things; banding separates them with no lines at all,
   and it is the only thing that makes a long column of figures trackable
   across its width. The search results are deliberately excluded — they
   are a selection list with a moving highlight, and banding underneath a
   highlight just fights it. */
.rows {
  display: flex; flex-direction: column;
  border-radius: var(--r-sm); overflow: hidden;
}
.row {
  display: flex; align-items: center; gap: 15px;
  padding: 13px 14px;
  font-size: 0.825rem;
}
.rows > .row:nth-child(odd) { background: rgba(255,255,255,0.34); }
.rows > .row:nth-child(even) { background: rgba(160,130,118,0.045); }
.row-n { flex: 1; min-width: 0; font-weight: 500; letter-spacing: -0.008em; }
.row-n.wrap { white-space: normal; }
.row-s { font-size: 0.665rem; color: var(--ink-3); margin-top: 3px; line-height: 1.45; }
.row-v {
  flex: 0 0 auto; font-size: 0.735rem; color: var(--ink-2);
  font-variant-numeric: tabular-nums; text-align: right;
}
.row.tapper { cursor: pointer; }
.rows > .row.tapper:hover { background: rgba(196,120,112,0.11); }

.tag {
  flex: 0 0 auto;
  font-size: 0.52rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; padding: 4px 9px; border-radius: 99px;
}
.tag.up   { background: rgba(92,155,100,0.15); color: #3f7346; }
.tag.dn   { background: rgba(191,88,82,0.15);  color: #9c433e; }
.tag.warn { background: rgba(184,137,79,0.17); color: #86602f; }
.tag.info { background: rgba(160,130,118,0.15); color: var(--ink-3); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px; border-radius: var(--r-pill);
  font-size: 0.755rem; font-weight: 520; letter-spacing: -0.004em;
  background: rgba(255,255,255,0.55);
  border: 1px solid rgba(190,166,154,0.28);
  color: var(--ink-1);
  transition: background var(--t-fast) var(--snap),
              transform var(--t-fast) var(--spring),
              border-color var(--t-fast) var(--snap);
}
.btn:hover { background: rgba(255,255,255,0.85); border-color: rgba(190,166,154,0.4); }
.btn:active { transform: scale(0.968); }
.btn.primary {
  background: linear-gradient(140deg, var(--rose), var(--rose-deep));
  color: #fff; border-color: transparent;
  box-shadow: 0 3px 14px rgba(158,85,80,0.28);
}
.btn.primary:hover { box-shadow: 0 5px 20px rgba(158,85,80,0.34); }
.btn.danger { background: rgba(191,88,82,0.1); color: #9c433e;
              border-color: rgba(191,88,82,0.24); }
.btn.danger:hover { background: rgba(191,88,82,0.18); }
.btn:disabled { opacity: 0.4; transform: none; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

.field {
  padding: 12px 17px; border-radius: var(--r-md);
  background: rgba(255,255,255,0.58);
  border: 1px solid rgba(190,166,154,0.3);
  outline: none; color: var(--ink-1); font-size: 0.85rem;
  transition: border-color var(--t-fast) var(--snap), box-shadow var(--t-fast) var(--snap);
}
.field:focus { border-color: var(--rose); box-shadow: 0 0 0 3px rgba(196,120,112,0.12); }

.seg {
  display: inline-flex; gap: 3px; padding: 4px;
  border-radius: var(--r-pill); background: rgba(160,130,118,0.1);
  max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
.seg::-webkit-scrollbar { display: none; }
.seg button {
  padding: 7px 16px; border-radius: var(--r-pill);
  font-size: 0.735rem; color: var(--ink-2); white-space: nowrap;
  transition: background var(--t-fast) var(--snap), color var(--t-fast) var(--snap);
}
.seg button:hover { color: var(--ink-1); }
.seg button.on { background: rgba(255,255,255,0.92); color: var(--rose-deep); font-weight: 550; }

.logpane {
  font-family: var(--font-num); font-size: 0.7rem; line-height: 1.68;
  white-space: pre-wrap; word-break: break-word;
  background: rgba(255,255,255,0.42);
  border-radius: var(--r-md); padding: 16px 18px;
}
.logline.err  { color: var(--danger); }
.logline.warn { color: var(--amber); }

.empty { text-align: center; color: var(--ink-3); font-size: 0.8rem;
         line-height: 1.65; padding: 40px 20px; }

.sk {
  border-radius: 7px; height: 12px; margin-bottom: 10px;
  background: linear-gradient(90deg, rgba(160,130,118,0.09) 25%,
    rgba(160,130,118,0.19) 50%, rgba(160,130,118,0.09) 75%);
  background-size: 200% 100%;
  animation: sk-sweep 1.5s linear infinite;
}
@keyframes sk-sweep { to { background-position: -200% 0; } }

/* ── Agent prose inside a plate ────────────────────────────────────────── */
.prose { font-size: 0.845rem; line-height: 1.68; color: var(--ink-2); max-width: 74ch; }
.prose .rich-h1, .prose .rich-h2, .prose .rich-h3, .prose .rich-h4 {
  font-family: var(--font-display);
  font-weight: 600; color: var(--ink-1); letter-spacing: -0.008em;
  margin: 22px 0 9px; line-height: 1.2;
}
.prose .rich-h1 { font-size: 1.42rem; }
.prose .rich-h2 { font-size: 1.24rem; }
.prose .rich-h3, .prose .rich-h4 { font-size: 1.06rem; }
.prose .rich-p { margin-bottom: 11px; }
.prose .rich-list { margin: 6px 0 12px 20px; }
.prose .rich-list li { margin-bottom: 5px; }
.prose .rich-hr { border: 0; border-top: 1px solid var(--hair); margin: 20px 0; }
.prose code {
  font-family: var(--font-num); font-size: 0.88em;
  background: rgba(160,130,118,0.13); padding: 2px 6px; border-radius: 6px;
}
.prose .rich-pre {
  font-family: var(--font-num); font-size: 0.715rem; overflow-x: auto;
  background: rgba(255,255,255,0.5); padding: 14px 16px;
  border-radius: var(--r-sm); margin: 12px 0;
}
/* A table that is pinned to width:100% cannot scroll — it squashes, and six
   columns of figures turn into six columns of wrapped fragments. Letting it
   take its natural width and scrolling the wrapper keeps every row readable
   and every column aligned. The right edge is faded so it is visible that
   there is more, and the scrollbar is left showing on the desktop because
   it is the affordance that says "drag me". */
.rich-table-wrap {
  overflow-x: auto; margin: 14px 0; border-radius: var(--r-sm);
  border: 1px solid var(--hair);
  max-width: 100%;
  scrollbar-width: thin;
  overscroll-behavior-x: contain;
}
.rich-table-wrap::-webkit-scrollbar { height: 8px; }
.rich-table-wrap::-webkit-scrollbar-thumb {
  background: rgba(170,142,128,0.32); border-radius: 99px;
  border: 2px solid transparent; background-clip: content-box;
}
.rich-table {
  border-collapse: collapse;
  width: auto; min-width: 100%;
  font-size: 0.755rem;
}
.rich-table th, .rich-table td { white-space: nowrap; }
.rich-table th {
  text-align: left; font-size: 0.575rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-3);
  padding: 10px 13px; background: rgba(160,130,118,0.10); white-space: nowrap;
}
.rich-table td { padding: 10px 13px; }
.rich-table tbody tr:nth-child(odd)  { background: rgba(255,255,255,0.34); }
.rich-table tbody tr:nth-child(even) { background: rgba(160,130,118,0.045); }
.rich-table .num { text-align: right; font-variant-numeric: tabular-nums;
                   font-family: var(--font-num); }
.rich-chart { margin: 16px 0; }
.rc-title { font-size: 0.575rem; font-weight: 600; text-transform: uppercase;
            letter-spacing: 0.14em; color: var(--ink-3); margin-bottom: 11px; }
.rc-bar-row { display: grid; grid-template-columns: 118px 1fr 58px; gap: 12px;
              align-items: center; margin-bottom: 8px; }
.rc-bar-label { font-size: 0.715rem; color: var(--ink-2); overflow: hidden;
                text-overflow: ellipsis; white-space: nowrap; }
.rc-bar-track { height: 4px; border-radius: 99px; background: rgba(160,130,118,0.17); overflow: hidden; }
.rc-bar-fill { height: 100%; border-radius: 99px; }
.rc-bar-val { font-size: 0.715rem; text-align: right;
              font-variant-numeric: tabular-nums; color: var(--ink-2); }
.rc-svg { width: 100%; height: 108px; display: block; }
.rc-axis { display: flex; justify-content: space-between; font-size: 0.6rem; color: var(--ink-4); }
.rc-gauge { margin-bottom: 12px; }
.rc-gauge-head { display: flex; justify-content: space-between; font-size: 0.715rem;
                 color: var(--ink-2); margin-bottom: 6px; }
.rc-gauge-track { height: 4px; border-radius: 99px; background: rgba(160,130,118,0.17); overflow: hidden; }
.rc-gauge-fill { height: 100%; border-radius: 99px; }

/* ── Chat inside a plate ───────────────────────────────────────────────── */
.chat { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.chat-log { flex: 1 1 auto; min-height: 0; padding-right: 10px; }
/* An agent reply is a report, not a remark — it carries tables and charts
   and needs the width. Only the operator's own messages stay narrow. */
.bub { max-width: 76%; margin-bottom: 18px; min-width: 0; }
.bub.them { max-width: 94%; }
.bub.me { max-width: 68%; margin-left: auto; }
.bub-b {
  padding: 13px 18px; border-radius: var(--r-lg);
  font-size: 0.845rem; line-height: 1.62;
  min-width: 0; max-width: 100%;
}
/* The prose measure is for reading paragraphs; inside a bubble it was also
   capping the tables, which is why they had nowhere to scroll. */
.bub .prose { max-width: 100%; }
.bub.them .bub-b {
  background: rgba(255,255,255,0.6);
  border: 1px solid rgba(255,255,255,0.6);
  border-bottom-left-radius: var(--r-xs);
}
.bub.me .bub-b {
  background: linear-gradient(138deg, var(--rose), var(--rose-deep));
  color: #fff; border-bottom-right-radius: var(--r-xs);
  box-shadow: 0 3px 14px rgba(158,85,80,0.22);
}
.bub.me .bub-b .prose { color: #fff; }
.bub-m { font-size: 0.585rem; color: var(--ink-4); margin: 6px 4px 0; }
.bub.me .bub-m { text-align: right; }
.chat-in { flex: 0 0 auto; display: flex; gap: 12px; padding-top: 18px; align-items: flex-end; }
.chat-in textarea {
  flex: 1; resize: none; max-height: 160px; min-height: 50px;
  padding: 14px 19px; border-radius: var(--r-lg); line-height: 1.5;
  background: rgba(255,255,255,0.6);
  border: 1px solid rgba(190,166,154,0.28);
  outline: none; font-size: 0.855rem;
  transition: border-color var(--t-fast) var(--snap);
}
.chat-in textarea:focus { border-color: var(--rose); }
.send {
  flex: 0 0 auto; width: 50px; height: 50px; border-radius: 50%;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(138deg, var(--rose), var(--rose-deep));
  box-shadow: 0 3px 14px rgba(158,85,80,0.3);
  transition: transform var(--t-fast) var(--spring), box-shadow var(--t-fast) var(--snap);
}
.send:hover { transform: scale(1.06); box-shadow: 0 5px 20px rgba(158,85,80,0.38); }
.send:active { transform: scale(0.94); }
.send:disabled { opacity: 0.36; transform: none; box-shadow: none; }
.typing { display: flex; gap: 5px; padding: 15px 18px; width: fit-content;
          background: rgba(255,255,255,0.6); border-radius: var(--r-lg);
          border-bottom-left-radius: var(--r-xs);
          border: 1px solid rgba(255,255,255,0.6); }
.typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--rose);
            animation: t-bob 1.25s ease-in-out infinite; }
.typing i:nth-child(2) { animation-delay: 0.14s; }
.typing i:nth-child(3) { animation-delay: 0.28s; }
@keyframes t-bob {
  0%,60%,100% { transform: translateY(0); opacity: 0.4; }
  30%         { transform: translateY(-6px); opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════════
   COMMAND — ⌘K
   ═══════════════════════════════════════════════════════════════════════ */
.scrim {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(52,38,32,0.14);
  opacity: 0; pointer-events: none;
}
.scrim.on { pointer-events: auto; }

/* Centred with auto margins, never translateX(-50%): the open/close
   animation owns `transform`, and a centring translate inside it gets
   replaced, leaving the panel permanently offset by half its width. */
/* Same top and the same centring as a plate, so a result opening from here
   reads as this window growing rather than as a new one arriving. */
.cmd {
  position: fixed; z-index: 70;
  top: 11vh; left: 0; right: 0; margin-inline: auto;
  width: min(660px, calc(100vw - 48px));
  max-height: 62vh;
  border-radius: var(--r-xl);
  display: none; flex-direction: column; overflow: hidden;
}
.cmd.on { display: flex; }
.cmd-in {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 15px;
  padding: 21px 26px;
  border-bottom: 1px solid var(--hair);
}
.cmd-in input {
  flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
  font-size: 1.06rem; letter-spacing: -0.014em; color: var(--ink-1);
}
.cmd-in input::placeholder { color: var(--ink-4); }
.cmd-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 10px;
            scrollbar-width: none; }
.cmd-list::-webkit-scrollbar { width: 0; }
.cmd-sec {
  font-size: 0.53rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--ink-4); padding: 13px 15px 7px;
}
.cmd-i {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 15px; border-radius: var(--r-md);
  cursor: pointer; font-size: 0.865rem;
}
.cmd-i.sel { background: rgba(196,120,112,0.14); }
.cmd-i.sel .cmd-d { color: var(--rose-deep); }
.cmd-n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmd-d { flex: 0 0 auto; font-size: 0.685rem; color: var(--ink-4); }

/* ═══════════════════════════════════════════════════════════════════════
   TOASTS · GATE
   ═══════════════════════════════════════════════════════════════════════ */
.toasts {
  position: fixed; z-index: 90; bottom: 30px; left: 0; right: 0;
  margin-inline: auto; width: fit-content; max-width: calc(100vw - 40px);
  display: flex; flex-direction: column-reverse; gap: 10px; align-items: center;
  pointer-events: none;
}
.toast {
  padding: 13px 24px; border-radius: var(--r-pill);
  font-size: 0.815rem; color: var(--ink-1); white-space: nowrap;
}
.toast.ok   { border-bottom-color: rgba(92,155,100,0.42); }
.toast.bad  { border-bottom-color: rgba(191,88,82,0.42); color: #9c433e; }
.toast.warn { border-bottom-color: rgba(184,137,79,0.42); }

.gate {
  position: fixed; inset: 0; z-index: 100;
  display: none; align-items: center; justify-content: center; padding: 30px;
}
.gate.on { display: flex; }
.gate-c { width: min(400px, 100%); padding: 40px 34px; border-radius: var(--r-xl);
          text-align: center; }
.gate-t {
  font-family: var(--font-display);
  font-size: 2.5rem; font-weight: 600; letter-spacing: -0.012em; line-height: 1;
}
.gate-s {
  font-size: 0.56rem; color: var(--ink-3); text-transform: uppercase;
  letter-spacing: 0.24em; margin: 10px 0 28px;
}
.gate .field { width: 100%; text-align: center; margin-bottom: 12px; }
.gate .btn { width: 100%; padding: 13px; }

/* ═══════════════════════════════════════════════════════════════════════
   NARROW / SHORT
   The composition needs width. Below 1080 the two columns stack and the
   canvas is allowed to scroll — a squeezed composition is worse than an
   honest list.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1080px) {
  #canvas { grid-template-columns: 1fr; gap: 26px; overflow-y: auto; }
  .air { gap: 34px; justify-content: flex-start; }
  .ledger { padding: 4px 22px; }
  :root { --pad-x: 26px; }
}
@media (max-height: 760px) {
  .verdict { font-size: clamp(2.2rem, 3.6vw, 3.1rem); }
  .money-fig { font-size: clamp(2.6rem, 4.6vw, 4rem); }
  .money-meta { margin-top: 14px; }
  .vitals { gap: 20px; }
  #canvas { padding-top: 22px; padding-bottom: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  #shell { transform: none; filter: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   MAIL
   ═══════════════════════════════════════════════════════════════════════ */
.mail-line { display: flex; align-items: baseline; gap: 12px; font-size: 0.85rem; color: var(--ink-2); }
.mail-count {
  font-family: var(--font-display); font-size: 2.1rem; font-weight: 500;
  line-height: 1; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.mail-count.on { color: var(--rose-deep); }

/* The list is a grid, not a flex row: sender and subject need fixed
   proportions or a long sender name shunts every subject out of alignment
   and the column stops being scannable. */
.rows > .row.tapper:has(.mail-subj),
.mail-list .row {
  display: grid;
  grid-template-columns: 8px minmax(120px, 0.9fr) minmax(0, 2.6fr) auto;
  gap: 14px; align-items: baseline;
}
.mail-dot {
  width: 7px; height: 7px; border-radius: 50%; align-self: center;
  background: transparent;
}
.mail-dot.new { background: var(--rose); box-shadow: 0 0 0 3px rgba(196,120,112,0.16); }
.mail-from {
  font-size: 0.79rem; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mail-subj { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mail-head { padding-bottom: 20px; border-bottom: 1px solid var(--hair); margin-bottom: 22px; }
.mail-subject {
  font-family: var(--font-display);
  font-size: 1.72rem; font-weight: 600; letter-spacing: -0.01em; line-height: 1.18;
}
/* Mail arrives as text, so it is set as text: preserved breaks, a readable
   measure, and no HTML from a stranger anywhere near this document. */
.mail-body {
  white-space: pre-wrap; word-break: break-word;
  font-size: 0.875rem; line-height: 1.72; color: var(--ink-2);
  max-width: 74ch;
  -webkit-user-select: text; user-select: text;
}
