/* phasma-one — the `phasma` theme (design §8): the base token sheet + the
 * shell's component CSS. Loads always. Non-default themes (e.g. nonprofit)
 * add only their tokens.css AFTER this file.
 *
 * v0.4 design pass — "design the identity, not a recolor." Token VALUES trace
 * to phasma-design/tokens/*.css; the prism palette is unchanged. What this pass
 * adds over the shipped 1A base: a distinct phasma.one type voice (IBM Plex),
 * a more generous spatial rhythm, the prism ray promoted to a real persona
 * device, and a heavily-polished chat surface. Self-contained (no cross-repo
 * @import), plain custom properties only, no framework. One deviation sanctioned
 * in 1A approval: props live on :root (One is not wp-admin).
 */

:root {
  /* Tokens added by the 2026-07-30 consistency sweep (docs/ui-rules.md §2) — values
     are the exact hex the component rules carried inline, so rendering is unchanged. */
  --one-ink-contrast: #e6edf3;
  --one-on-primary: #fff;
  --one-success-soft: #dcedd8;
  --one-success-strong: #0a7d28;
  /* NOTE: --one-text-faint was ALSO declared here (#9aa4ae) by the 2026-07-30 sweep, and
     lost to the prism-palette declaration further down (#78848f) — same :root, later wins.
     The sweep's own comment says "rendering is unchanged", and for this token that was not
     true: the components it de-inlined render the darker #78848f. Removed rather than
     resolved, because #78848f is what has actually been shipping and changing it now would
     be a real visual change disguised as a cleanup. (CSS audit 2026-08-04.) */
  --one-warn: #8a6100;
  --one-success: #1c6b3c;
  /* Nav redesign: the on-ink hairlines and the drawer scrim. These are the only
     alpha-on-ink values in the sheet; naming them keeps the header chrome from
     re-deriving "a bit lighter than the bar" per component. */
  --one-hairline: rgba(255, 255, 255, 0.10);
  --one-hairline-strong: rgba(255, 255, 255, 0.24);
  --one-scrim: rgba(17, 24, 39, 0.5);
  /* ---- Brand: the prism palette (tokens/colors.css) ------------------ */
  --one-ink: #1a192e;              /* --ink */
  --one-ink-2: #232238;           /* raised ink (header controls) */
  --one-primary: #0891b2;         /* --primary  (cyan ray, tuned) */
  --one-primary-dark: #0e7490;    /* --primary-dark */
  --one-primary-tint: #ecf7fa;    /* --primary-tint */
  --one-violet: #7c3aed;          /* --violet / operator accent */
  --one-violet-dark: #6d28d9;     /* --violet-dark */
  --one-violet-bg: #f3eefe;       /* --violet-bg */
  /* One Analytics (T-AX2): the five-step violet ramp that shades a retention table, light to full */
  --one-ax-shade-1: #f3eefe; --one-ax-shade-2: #e2d6fc; --one-ax-shade-3: #c9b2f8; --one-ax-shade-4: #a07ef2; --one-ax-shade-5: #7c3aed;
  --one-ax-shade-ink: #3b1d7a;
  --one-amber: #f59e0b;           /* --amber / portal accent */
  --one-amber-deep: #b45309;      /* --amber-deep */
  --one-amber-bg: #fdf3e0;        /* --amber-bg */
  --one-ray-cyan: #06b6d4;        /* --ray-cyan */
  --one-ray-violet: #7c3aed;      /* --ray-violet */
  --one-ray-amber: #f59e0b;       /* --ray-amber */

  /* ---- Surfaces / text (tokens/colors.css) -------------------------- */
  --one-canvas: #eef2f5;          /* --canvas (cool paper) */
  --one-canvas-2: #e7edf1;        /* deeper canvas (board / rails) */
  --one-card: #ffffff;            /* --surface-card */
  --one-tile: #f7fafb;            /* --surface-tile */
  --one-sunken: #f1f5f8;          /* --surface-sunken */
  --one-line: #dde4e9;            /* --line */
  --one-line-soft: #eaeff3;       /* --line-soft */
  --one-field-border: #9aa7b2;    /* --field-border */
  --one-text: #1a192e;            /* --text */
  --one-text-muted: #55636f;      /* --text-muted */
  --one-text-faint: #78848f;      /* --text-faint */
  --one-text-fainter: #98a2ac;
  --one-text-invert: #ffffff;     /* --text-invert */
  --one-text-invert-dim: #b9c1cb; /* muted-on-ink */

  /* ---- Status (tokens/colors.css triads) ---------------------------- */
  --one-ok-bg: #ecfaef;   --one-ok-text: #0a7d28;  --one-ok-border: #b8e6c2;
  --one-warn-bg: #fdf3e0; --one-warn-text: #8a5a00; --one-warn-border: #f5dfae;
  --one-info-bg: #e6f5f9; --one-info-text: #0a5c70; --one-info-border: #b6e2ec;
  --one-danger: #b02a2c;  --one-danger-border: #d8a3a4; --one-danger-tint: #fcebec;

  /* ---- Type: the phasma.one voice — IBM Plex (webfont, system fallback) */
  --one-font-sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --one-font-mono: "IBM Plex Mono", Menlo, Consolas, Monaco, monospace;

  --one-text-3xl: 30px;   /* door / hero title */
  --one-text-2xl: 22px;   /* page H1 */
  --one-text-xl: 18px;    /* card lead */
  --one-text-md: 15px;    /* section header */
  --one-text-base: 14px;  /* body */
  --one-text-sm: 13px;    /* secondary */
  --one-text-2xs: 11px;   /* the signature uppercase label */

  --one-weight-regular: 400;
  --one-weight-medium: 500;
  --one-weight-semibold: 600;
  --one-leading-normal: 1.5;
  --one-leading-chat: 1.6;
  --one-tracking-kpi: 0.6px;      /* uppercase label tracking */
  --one-tracking-tight: -0.01em;  /* display tightening */

  /* ---- Rhythm (tokens/spacing.css — roomier than 1A) ---------------- */
  --one-space-2: 4px;
  --one-space-4: 8px;
  --one-space-5: 10px;
  --one-space-6: 12px;
  --one-space-7: 16px;
  --one-space-8: 20px;
  --one-space-10: 28px;
  --one-space-12: 40px;
  --one-card-pad-y: 20px;
  --one-card-pad-x: 24px;
  --one-stack-gap: 20px;

  /* ---- Corners & elevation (tokens/radius.css) --------------------- */
  --one-radius-xs: 6px;    /* inputs / buttons */
  --one-radius-sm: 8px;
  --one-radius-lg: 12px;   /* cards */
  --one-radius-xl: 16px;
  --one-radius-pill: 999px;
  --one-radius-bubble: 16px;
  --one-radius-tail: 5px;

  /* Referenced with fallbacks since their components shipped, but never defined — so the
     fallback was ALWAYS what rendered and no theme could touch them. Defined here so they
     are real tokens rather than decorative syntax (CSS audit, 2026-08-04). */
  --one-surface-2: #f2f5f8;         /* a half-step above the card, for inset rows */
  --one-accent-soft: #eef2f5;       /* quiet chip/badge fill */
  --one-chat-font-scale: 1;         /* per-user chat type scale knob */
  --one-shadow-card: 0 1px 2px rgba(16, 24, 40, 0.05), 0 1px 3px rgba(16, 24, 40, 0.04);
  --one-shadow-raise: 0 4px 16px rgba(16, 24, 40, 0.08);
  --one-shadow-modal: 0 18px 50px rgba(9, 12, 28, 0.30);
  --one-ring: 0 0 0 3px rgba(8, 145, 178, 0.22);
  --one-ring-violet: 0 0 0 3px rgba(124, 58, 237, 0.22);
  --one-dur-fast: 0.12s;

  /* ---- Chat (tokens/colors.css) ------------------------------------ */
  --one-bubble-user: #0891b2;
  --one-bubble-user-text: #ffffff;
  --one-bubble-assistant: #f4f7f9;
  --one-bubble-assistant-text: #1a192e;
  --one-bubble-error-bg: #fcf0f1;
  --one-bubble-error-text: #8a1f11;
  --one-bubble-error-border: #f0c4c0;
  --one-wisp-bg: #f3eefe;
}

/* ==== Base ================================================================ */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body.one-body {
  margin: 0;
  background: var(--one-canvas);
  color: var(--one-text);
  font-family: var(--one-font-sans);
  font-size: var(--one-text-base);
  line-height: var(--one-leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3 { font-weight: var(--one-weight-semibold); letter-spacing: var(--one-tracking-tight); }

a { color: var(--one-primary); text-decoration: none; }
a:hover { color: var(--one-primary-dark); text-decoration: underline; text-underline-offset: 2px; }

.one-mono { font-family: var(--one-font-mono); }

/* The signature uppercase micro-label */
.one-eyebrow {
  font-size: var(--one-text-2xs);
  font-weight: var(--one-weight-semibold);
  letter-spacing: var(--one-tracking-kpi);
  text-transform: uppercase;
  color: var(--one-text-muted);
}

/* ==== Header: brand + plane nav + persona ==================================
 *
 * The nav redesign moved navigation INTO this bar. One header everywhere; only the
 * accent and the links change (ui-rules §3/§4). The rules below are the whole of it:
 * the bar, the two nav renderings (desktop groups, mobile drawer), the persona
 * switcher, and the accent strip that carries plane identity.
 *
 * All disclosure is native <details>/<summary> — One's CSP has no unsafe-inline, and a
 * menu that needs JS is a menu that breaks before the bundle loads.
 */

.one-header {
  display: flex;
  align-items: center;
  gap: var(--one-space-4);
  padding: 0 var(--one-space-8);
  height: 52px;
  background: var(--one-ink);
  color: var(--one-text-invert);
  /* the open dropdowns hang out of this bar */
  position: relative;
  z-index: 20;
}

.one-brand {
  display: inline-flex; align-items: center; gap: var(--one-space-4);
  margin-right: var(--one-space-8);
  color: var(--one-text-invert);
  font-size: var(--one-text-md);
  font-weight: var(--one-weight-semibold);
  letter-spacing: 0.2px;
  text-decoration: none;
  flex: none;
}
.one-brand:hover { text-decoration: none; color: var(--one-text-invert); }
.one-mark { display: block; flex: none; }
.one-wordmark-text { display: inline-flex; align-items: baseline; }
.one-wordmark-one { color: var(--one-ray-cyan); font-weight: var(--one-weight-medium); }

/* The stacked three-ray glyph is RETIRED (nav redesign): the prism now states itself
   as the accent strip under the header — one ray inside a plane, all three on the
   plane-less surfaces — and the tab icon carries the mark. A 16px glyph beside a
   wordmark that already reads "phasma one" was the third brand device in one bar. */

.one-header-actions { margin-left: auto; display: flex; align-items: center; gap: var(--one-space-6); flex: none; }
.one-header-user { color: var(--one-text-invert-dim); font-size: var(--one-text-sm); }

/* ---- The plane menu (desktop) ------------------------------------------- */

.one-topnav { display: flex; align-items: center; height: 52px; min-width: 0; }
/* The plane's accent, declared ONCE per bar and consumed by the active underline
   below — a plane is an accent, not a dialect (ui-rules §4). */
.one-topnav--cyan { --one-plane-accent: var(--one-ray-cyan); }
.one-topnav--violet { --one-plane-accent: var(--one-ray-violet); }
.one-topnav--amber { --one-plane-accent: var(--one-ray-amber); }

/* One link shape for both a bare item and a group's summary, so a group does not
   read as a different KIND of destination than its neighbours. */
.one-topnav-link {
  display: inline-flex; align-items: center; gap: 5px;
  height: 50px; padding: 2px var(--one-space-6) 0;
  border-bottom: 2px solid transparent;
  color: var(--one-text-invert-dim);
  font-size: var(--one-text-sm); font-weight: var(--one-weight-medium);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  list-style: none; /* kills the <summary> marker */
  transition: color var(--one-dur-fast) ease, background var(--one-dur-fast) ease;
}
.one-topnav-link::-webkit-details-marker { display: none; }
.one-topnav-link:hover { color: var(--one-text-invert); text-decoration: none; }
.one-topnav-link:focus-visible { outline: 2px solid var(--one-ray-cyan); outline-offset: -2px; }
.one-topnav-link.is-active,
.one-topnav-group.is-active > .one-topnav-link { color: var(--one-text-invert); }
.one-caret { font-size: 9px; line-height: 1; }

/* The active underline IS the plane accent — set once on <body> by the accent class
   below, so a plane never restates its colour per link. */
.one-topnav-link.is-active,
.one-topnav-group.is-active > .one-topnav-link { border-bottom-color: var(--one-plane-accent, var(--one-ray-cyan)); }

.one-topnav-group { position: relative; }
.one-topnav-group[open] > .one-topnav-link { background: var(--one-ink-2); color: var(--one-text-invert); }
.one-topnav-menu {
  position: absolute; top: 52px; left: 0; min-width: 200px;
  background: var(--one-card);
  border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm);
  box-shadow: var(--one-shadow-raise);
  padding: var(--one-space-2);
  z-index: 30;
}

/* ---- Menu rows (shared by the nav groups, the persona panel, the drawer) --- */

.one-menu-item {
  display: flex; align-items: center; gap: var(--one-space-5);
  width: 100%; padding: var(--one-space-4) var(--one-space-6);
  border-radius: var(--one-radius-xs);
  color: var(--one-text); font-size: var(--one-text-sm);
  text-decoration: none; white-space: nowrap;
}
.one-menu-item:hover { background: var(--one-sunken); color: var(--one-text); text-decoration: none; }
.one-menu-item--lg { padding: var(--one-space-5) var(--one-space-6); font-size: var(--one-text-base); min-height: 44px; }
.one-menu-item-label { flex: 1; min-width: 0; }
.one-menu-item-note { color: var(--one-text-faint); font-size: var(--one-text-2xs); }
.one-menu-item-note--warn { color: var(--one-warn-text); }
.one-menu-item--current { background: var(--one-primary-tint); font-weight: var(--one-weight-medium); }
.one-menu-item--current.one-menu-item--violet { background: var(--one-violet-bg); }
.one-menu-item--current.one-menu-item--amber { background: var(--one-amber-bg); }
.one-menu-item--lg.is-active { background: var(--one-primary-tint); color: var(--one-primary-dark); font-weight: var(--one-weight-medium); }
.one-menu-divider { border-top: 1px solid var(--one-line-soft); margin: var(--one-space-2) 0; }

/* The persona dot — the prism ray, shrunk to a status bead. */
.one-dot { flex: none; width: 8px; height: 8px; border-radius: var(--one-radius-pill); }
.one-dot--violet { background: var(--one-ray-violet); }
.one-dot--cyan { background: var(--one-ray-cyan); }
.one-dot--amber { background: var(--one-ray-amber); }

/* ---- The persona switcher ----------------------------------------------- */

.one-persona-menu { position: relative; flex: none; }
.one-persona-chip {
  display: inline-flex; align-items: center; gap: var(--one-space-4);
  padding: 5px var(--one-space-6) 5px var(--one-space-5);
  background: var(--one-ink-2);
  border: 1px solid var(--one-hairline);
  border-radius: var(--one-radius-pill);
  color: var(--one-text-invert);
  font-size: var(--one-text-sm);
  cursor: pointer; list-style: none;
  max-width: 260px;
  transition: border-color var(--one-dur-fast) ease;
}
.one-persona-chip::-webkit-details-marker { display: none; }
.one-persona-chip:hover { border-color: var(--one-hairline-strong); }
.one-persona-chip:focus-visible { outline: 2px solid var(--one-ray-cyan); outline-offset: 2px; }
.one-persona-chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.one-persona-chip-short { display: none; white-space: nowrap; }
.one-persona-menu[open] > .one-persona-chip { border-color: var(--one-ray-cyan); }

.one-persona-panel {
  position: absolute; top: calc(100% + var(--one-space-4)); right: 0; width: 320px;
  background: var(--one-card);
  border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm);
  box-shadow: var(--one-shadow-raise);
  padding: var(--one-space-2);
  z-index: 30;
}
.one-persona-signed { margin: 0; padding: var(--one-space-4) var(--one-space-6) var(--one-space-2); font-size: var(--one-text-2xs); color: var(--one-text-faint); }
.one-persona-signed strong { color: var(--one-text); }
.one-persona-eyebrow { display: block; padding: var(--one-space-4) var(--one-space-6) var(--one-space-2); color: var(--one-text-fainter); }

/* ---- The mobile drawer --------------------------------------------------- */

.one-navdrawer { display: none; }
.one-navdrawer-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin-left: calc(var(--one-space-8) * -1);
  cursor: pointer; list-style: none;
}
.one-navdrawer-toggle::-webkit-details-marker { display: none; }
.one-burger { display: inline-flex; flex-direction: column; gap: 4px; width: 20px; }
.one-burger i { height: 2px; border-radius: 2px; background: var(--one-ink-contrast); }
.one-navdrawer[open] > .one-navdrawer-toggle::after {
  content: ""; position: fixed; inset: 0; z-index: 40;
  background: var(--one-scrim);
}
.one-navdrawer-panel {
  position: fixed; top: 0; bottom: 0; left: 0; width: 300px; max-width: 86vw; z-index: 41;
  display: flex; flex-direction: column;
  background: var(--one-card);
  box-shadow: var(--one-shadow-modal);
}
.one-navdrawer-head { background: var(--one-ink); color: var(--one-ink-contrast); padding: var(--one-space-7); }
.one-navdrawer-head .one-brand { margin: 0 0 var(--one-space-5); }
.one-navdrawer-persona {
  display: flex; align-items: center; gap: var(--one-space-4);
  padding: var(--one-space-4) var(--one-space-5);
  background: var(--one-ink-2); border: 1px solid var(--one-hairline);
  border-radius: var(--one-radius-sm);
  color: var(--one-ink-contrast); font-size: var(--one-text-sm); text-decoration: none;
}
.one-navdrawer-persona:hover { color: var(--one-text-invert); text-decoration: none; }
.one-navdrawer-persona-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.one-navdrawer-persona-switch { color: var(--one-text-invert-dim); font-size: var(--one-text-2xs); }
.one-navdrawer-body { flex: 1; overflow: auto; padding: var(--one-space-5) var(--one-space-4); }
.one-navdrawer-section { margin: var(--one-space-6) var(--one-space-6) var(--one-space-2); font-size: 10.5px; font-weight: var(--one-weight-semibold); letter-spacing: var(--one-tracking-kpi); text-transform: uppercase; color: var(--one-text-fainter); }
.one-navdrawer-foot { border-top: 1px solid var(--one-line-soft); padding: var(--one-space-5) var(--one-space-4); }

/* ---- The accent strip ---------------------------------------------------- */

.one-accent { height: 2px; }
.one-accent--cyan { background: var(--one-ray-cyan); }
.one-accent--violet { background: var(--one-ray-violet); }
.one-accent--amber { background: var(--one-ray-amber); }
/* Plane-less surfaces (login, the launcher) carry the whole prism instead of one ray:
   three planes, one product — the same idea the tab icon states. */
.one-accent--prism { display: flex; height: 3px; }
.one-accent--prism i { flex: 1; }
.one-accent--prism i:nth-child(1) { background: var(--one-ray-cyan); }
.one-accent--prism i:nth-child(2) { background: var(--one-ray-violet); }
.one-accent--prism i:nth-child(3) { background: var(--one-ray-amber); }

/* ==== Layout ============================================================== */

.one-main {
  flex: 1;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: var(--one-space-10) var(--one-space-8);
  display: flex;
  flex-direction: column;
  gap: var(--one-stack-gap);
}

.one-footer {
  text-align: center;
  color: var(--one-text-fainter);
  font-size: var(--one-text-2xs);
  padding: var(--one-space-8);
  letter-spacing: 0.2px;
}
.one-footer .one-status-dot { color: var(--one-ok-text); }
.one-footer-link { color: inherit; text-decoration: underline; }

.one-card {
  background: var(--one-card);
  border: 1px solid var(--one-line);
  border-radius: var(--one-radius-lg);
  box-shadow: var(--one-shadow-card);
  padding: var(--one-card-pad-y) var(--one-card-pad-x);
}

/* Card with an attached header bar (the signature panel) */
.one-card--paneled { padding: 0; overflow: hidden; }
.one-card--paneled > .one-panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-6);
  padding: var(--one-space-6) var(--one-card-pad-x);
  border-bottom: 1px solid var(--one-line);
  background: var(--one-tile);
}
.one-card--paneled > .one-panel-head h2 { margin: 0; font-size: var(--one-text-md); }
.one-card--paneled > .one-panel-body { padding: var(--one-card-pad-y) var(--one-card-pad-x); }

.one-section-title { margin: 0 0 var(--one-space-6); font-size: var(--one-text-md); font-weight: var(--one-weight-semibold); }
/* A second heading inside a card that already opened with one (e.g. the operator
   health pane's Components table under its checks table) — needs the top gap the
   first title does not. */
.one-section-title--sub { margin-top: var(--one-space-10); }
.one-muted { color: var(--one-text-muted); }
.one-hint { color: var(--one-text-faint); font-size: var(--one-text-sm); margin: var(--one-space-4) 0 0; }
/* T-RB6 — a question's `links` (R-Y): a short list, styled like `.one-hint` beside it. */
.one-question-links { list-style: none; margin: var(--one-space-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-2); font-size: var(--one-text-sm); }

/* ==== The door (login & friends) ========================================= */

.one-body--door { background: var(--one-canvas); }
.one-body--door .one-main { justify-content: center; max-width: 424px; }

/* The gateway (cyan admin) plane is data tables, not prose — it gets the full
   viewport width; the 760px reading column stays the default for every
   prose/reading plane (shell, invites, custody, chat keeps its own 1120px). */
.one-body--gateway .one-main { max-width: none; }

/* Seat-plane DATA pages (wisps, later seat KBs): wider than the reading
   column, capped like chat (the S1 width ruling: 1120px). */
.one-body--seatdata .one-main { max-width: 1120px; }

/* The LAUNCHER (/shell): a wider column than the reading default, because a door
   grid of two is the content. */
.one-body--launcher .one-main { max-width: 920px; }
.one-launcher-head { display: flex; flex-direction: column; gap: var(--one-space-2); }
.one-page-title { margin: 0; font-size: var(--one-text-2xl); font-weight: var(--one-weight-semibold); }
.one-num { font-variant-numeric: tabular-nums; }

.one-door-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--one-space-7); }
.one-door-card {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--one-space-4);
  border-top: 3px solid var(--one-primary);
}
.one-door-card--violet { border-top-color: var(--one-violet); }
.one-door-card--cyan { border-top-color: var(--one-primary); }
.one-door-card--amber { border-top-color: var(--one-amber); }
.one-door-card--degraded { background: var(--one-warn-bg); border-color: var(--one-warn-border); }
.one-door-card-title { margin: 0; font-size: var(--one-text-xl); font-weight: var(--one-weight-semibold); }
.one-door-card-blurb { margin: 0 0 var(--one-space-5); color: var(--one-text-muted); font-size: var(--one-text-sm); }
.one-door-card-actions { margin-top: auto; display: flex; align-items: center; gap: var(--one-space-6); flex-wrap: wrap; }

/* 2FA + session hygiene: one quiet row under the doors, not two more cards
   competing with the choice the page exists to offer. */
.one-launcher-foot {
  display: flex; align-items: center; gap: var(--one-space-7); flex-wrap: wrap;
  padding-top: var(--one-space-8); border-top: 1px solid var(--one-line);
}
.one-launcher-foot-note { flex: 1; margin: 0; font-size: var(--one-text-sm); min-width: 20ch; }

.one-door-brand { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: var(--one-space-8); }
.one-door-brand .one-wordmark-text { color: var(--one-ink); font-size: var(--one-text-xl); font-weight: var(--one-weight-semibold); letter-spacing: var(--one-tracking-tight); }
.one-door-brand .one-wordmark-one { color: var(--one-primary); }

.one-door-title { margin: 0 0 var(--one-space-4); font-size: var(--one-text-3xl); font-weight: var(--one-weight-semibold); letter-spacing: var(--one-tracking-tight); }
.one-door-title--center { text-align: center; font-size: var(--one-text-2xl); }
.one-door-sub { margin: 0 0 var(--one-space-8); color: var(--one-text-muted); }
.one-door-sub--center { text-align: center; font-size: var(--one-text-sm); }
.one-door-alt { margin: var(--one-space-8) 0 0; text-align: center; font-size: var(--one-text-sm); }
.one-door-alt a { color: var(--one-text-muted); }

.one-door--violet { border-top: 3px solid var(--one-violet); }
.one-door--amber { border-top: 3px solid var(--one-amber); }
.one-door-accent { position: absolute; top: 0; left: 0; right: 0; height: 3px; display: flex; border-top-left-radius: var(--one-radius-lg); border-top-right-radius: var(--one-radius-lg); overflow: hidden; }
.one-door-accent i { flex: 1; }
.one-door-accent i:nth-child(1) { background: var(--one-ray-cyan); }
.one-door-accent i:nth-child(2) { background: var(--one-ray-violet); }
.one-door-accent i:nth-child(3) { background: var(--one-ray-amber); }

.one-door-divider {
  display: flex; align-items: center; gap: var(--one-space-6);
  color: var(--one-text-fainter); font-size: var(--one-text-2xs);
  text-transform: uppercase; letter-spacing: var(--one-tracking-kpi);
  margin: var(--one-space-6) 0;
}
.one-door-divider::before, .one-door-divider::after { content: ""; flex: 1; border-top: 1px solid var(--one-line-soft); }

.one-breakglass { margin-top: var(--one-space-7); }
.one-breakglass summary { color: var(--one-text-faint); font-size: var(--one-text-sm); cursor: pointer; list-style: none; }
.one-breakglass summary:hover { color: var(--one-text-muted); }

/* OAuth provider button */
.one-oauth {
  display: flex; align-items: center; justify-content: center; gap: var(--one-space-6);
  width: 100%; padding: 11px var(--one-space-6);
  border: 1px solid var(--one-field-border); border-radius: var(--one-radius-xs);
  background: var(--one-card); color: var(--one-text);
  font: inherit; font-weight: var(--one-weight-medium); cursor: pointer;
  transition: background var(--one-dur-fast) ease, box-shadow var(--one-dur-fast) ease;
}
.one-oauth:hover { background: var(--one-sunken); }
.one-oauth .g-mark { width: 18px; height: 18px; }

/* the "signing you in" moment */
.one-handoff { text-align: center; padding: var(--one-space-10) 0; }
.one-handoff .one-spinner {
  width: 34px; height: 34px; margin: 0 auto var(--one-space-8);
  border: 3px solid var(--one-line); border-top-color: var(--one-primary);
  border-radius: 50%; animation: one-spin 0.8s linear infinite;
}
@keyframes one-spin { to { transform: rotate(360deg); } }
.one-handoff-title { margin: 0 0 var(--one-space-4); font-size: var(--one-text-xl); font-weight: var(--one-weight-semibold); }

/* ==== Forms =============================================================== */

.one-form { display: flex; flex-direction: column; gap: var(--one-space-6); margin: var(--one-space-7) 0 0; }
.one-field { display: flex; flex-direction: column; gap: var(--one-space-4); }
.one-inline-form { display: flex; gap: var(--one-space-4); }
.one-inline-form .one-input { flex: 1; }

.one-label {
  font-size: var(--one-text-2xs); font-weight: var(--one-weight-semibold);
  letter-spacing: var(--one-tracking-kpi); text-transform: uppercase; color: var(--one-text-muted);
}

.one-input {
  font: inherit;
  width: 100%;
  padding: 10px var(--one-space-6);
  border: 1px solid var(--one-field-border);
  border-radius: var(--one-radius-xs);
  background: var(--one-card);
  color: var(--one-text);
  transition: border-color var(--one-dur-fast) ease, box-shadow var(--one-dur-fast) ease;
}
.one-input::placeholder { color: var(--one-text-fainter); }
.one-input:focus { outline: none; border-color: var(--one-primary); box-shadow: var(--one-ring); }
.one-input--code { font-family: var(--one-font-mono); letter-spacing: 6px; text-align: center; font-size: var(--one-text-xl); }
.one-input--narrow { max-width: 128px; }

/* ==== Buttons ============================================================= */

.one-btn {
  font: inherit; font-weight: var(--one-weight-medium);
  padding: 10px var(--one-space-7);
  border: 1px solid var(--one-field-border);
  border-radius: var(--one-radius-xs);
  background: var(--one-card); color: var(--one-text);
  cursor: pointer; text-decoration: none; display: inline-flex;
  align-items: center; justify-content: center; gap: var(--one-space-4);
  transition: background var(--one-dur-fast) ease, color var(--one-dur-fast) ease,
    border-color var(--one-dur-fast) ease, box-shadow var(--one-dur-fast) ease;
}
.one-btn:hover { background: var(--one-sunken); color: var(--one-text); text-decoration: none; }
.one-btn:focus-visible { outline: none; box-shadow: var(--one-ring); }

.one-btn--primary { background: var(--one-primary); border-color: var(--one-primary); color: var(--one-text-invert); }
.one-btn--primary:hover { background: var(--one-primary-dark); border-color: var(--one-primary-dark); color: var(--one-text-invert); }

.one-btn--violet { background: var(--one-violet); border-color: var(--one-violet); color: var(--one-text-invert); }
.one-btn--violet:hover { background: var(--one-violet-dark); border-color: var(--one-violet-dark); color: var(--one-text-invert); }
.one-btn--violet:focus-visible { box-shadow: var(--one-ring-violet); }
.one-btn--amber { background: var(--one-amber); border-color: var(--one-amber); color: var(--one-text-invert); }
.one-btn--amber:hover { background: var(--one-amber-deep); border-color: var(--one-amber-deep); color: var(--one-text-invert); }

.one-btn--ghost-line { background: transparent; border-color: var(--one-line); color: var(--one-text-muted); }
.one-btn--ghost-line:hover { background: var(--one-sunken); color: var(--one-text); }

.one-btn--danger { background: var(--one-card); border-color: var(--one-danger-border); color: var(--one-danger); }
.one-btn--danger:hover { background: var(--one-danger-tint); color: var(--one-danger); }

.one-btn--ghost { background: transparent; border-color: transparent; color: var(--one-text-muted); }
.one-btn--ghost:hover { background: var(--one-sunken); color: var(--one-text); }
/* Inside the dark header chrome the ghost inverts — the pre-v0.79.1 colors, which were
   the DEFAULT and therefore invisible on light surfaces (white-alpha hover on a white
   card: the ~140 nav/card uses vanished on hover; only the header's Sign out was ever
   actually dark-context). Scope follows context, not the other way around. */
.one-header .one-btn--ghost { color: var(--one-text-invert-dim); }
.one-header .one-btn--ghost:hover { background: rgba(255, 255, 255, 0.12); color: var(--one-text-invert); }
/* …but the Help panel opens a LIGHT card inside the header, so its buttons are light-context
   again (2026-10-06: "Ask Cheshire" rendered light grey on white and went white on hover). */
.one-header .one-help-body .one-btn--ghost { color: var(--one-text-muted); }
.one-header .one-help-body .one-btn--ghost:hover { background: var(--one-sunken); color: var(--one-text); }

.one-btn--full { display: flex; width: 100%; }
.one-btn--sm { padding: 6px var(--one-space-6); font-size: var(--one-text-sm); }

/* Outlined primary — the secondary action on the sign-in door, where a filled
   second button would make two equal first choices. */
.one-btn--outline { background: var(--one-sunken); border-color: var(--one-primary); color: var(--one-primary); }
.one-btn--outline:hover { background: var(--one-primary-tint); color: var(--one-primary-dark); }

/* A button that must READ as a link because it only exists to carry a CSRF token
   (the persona-scoped 'Buy credits' door). Same affordance as an <a>, same POST
   discipline as a form. */
.one-btn--link { background: transparent; border-color: transparent; color: var(--one-primary); padding: 10px var(--one-space-4); }
.one-btn--link:hover { background: transparent; color: var(--one-primary-dark); text-decoration: underline; text-underline-offset: 2px; }

/* A button rendered as a MENU ROW (the persona switcher, the drawer's sign-out).
   ui-rules §1 requires every <button> to wear one-btn; inside a menu the kit's
   default chrome would make each row look like a card of buttons, so this variant
   strips the frame and adopts the .one-menu-item geometry. */
.one-btn--menu {
  display: flex; justify-content: flex-start; width: 100%;
  gap: var(--one-space-5);
  padding: var(--one-space-4) var(--one-space-6);
  background: transparent; border-color: transparent;
  border-radius: var(--one-radius-xs);
  font-weight: var(--one-weight-regular); font-size: var(--one-text-sm);
  text-align: left;
}
.one-btn--menu:hover { background: var(--one-sunken); }
.one-btn--menu-danger { color: var(--one-danger); }
.one-btn--menu-danger:hover { background: var(--one-danger-tint); color: var(--one-danger); }

/* ==== Flash + notices ===================================================== */

.one-flash {
  margin: 0; padding: 11px var(--one-space-7);
  border-radius: var(--one-radius-sm); border: 1px solid;
  font-size: var(--one-text-sm);
  display: flex; align-items: flex-start; gap: var(--one-space-6);
}
.one-flash .i { flex: none; width: 16px; height: 16px; margin-top: 1px; }
.one-flash--info { background: var(--one-info-bg); color: var(--one-info-text); border-color: var(--one-info-border); }
.one-flash--warn { background: var(--one-warn-bg); color: var(--one-warn-text); border-color: var(--one-warn-border); }
.one-flash--ok { background: var(--one-ok-bg); color: var(--one-ok-text); border-color: var(--one-ok-border); }
.one-flash--danger { background: var(--one-danger-tint); color: var(--one-danger); border-color: var(--one-danger-border); }

.one-notice { display: flex; align-items: center; gap: var(--one-stack-gap); justify-content: space-between; }
.one-notice p { margin: 0; }

/* Big worded empty / error state (the app never white-screens) */
.one-state {
  text-align: center; padding: var(--one-space-12) var(--one-space-8);
  display: flex; flex-direction: column; align-items: center; gap: var(--one-space-6);
}
.one-state-badge {
  width: 44px; height: 44px; border-radius: var(--one-radius-lg);
  display: flex; align-items: center; justify-content: center;
  background: var(--one-sunken); color: var(--one-text-muted);
}
.one-state-title { margin: 0; font-size: var(--one-text-xl); font-weight: var(--one-weight-semibold); }
.one-state-body { margin: 0; color: var(--one-text-muted); max-width: 42ch; }
.one-state-list { text-align: left; margin: 0; padding-left: var(--one-space-8); color: var(--one-text-muted); font-size: var(--one-text-sm); display: flex; flex-direction: column; gap: var(--one-space-4); }

/* ==== Personas & the switcher (§7 — the prism made product-real) ========== */

.one-current-persona {
  display: flex; align-items: center; gap: var(--one-space-6);
  margin: 0; padding: var(--one-space-6) var(--one-space-7);
  border: 1px solid var(--one-line);
  border-left: 3px solid var(--one-primary);
  background: var(--one-card);
  border-radius: var(--one-radius-sm);
}
.one-current-persona--violet { border-left-color: var(--one-violet); }
.one-current-persona--cyan { border-left-color: var(--one-ray-cyan); }
.one-current-persona--amber { border-left-color: var(--one-amber); }

.one-persona-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-6); }

.one-persona {
  display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-7);
  padding: var(--one-space-7);
  border: 1px solid var(--one-line);
  border-left-width: 3px;
  border-radius: var(--one-radius-sm);
  background: var(--one-card);
  transition: box-shadow var(--one-dur-fast) ease, border-color var(--one-dur-fast) ease;
}
.one-persona:hover { box-shadow: var(--one-shadow-card); }
.one-persona--violet { border-left-color: var(--one-violet); }
.one-persona--cyan { border-left-color: var(--one-ray-cyan); }
.one-persona--amber { border-left-color: var(--one-amber); }
.one-persona--active { border-color: var(--one-primary); background: var(--one-primary-tint); }
.one-persona--active.one-persona--violet { border-color: var(--one-violet); background: var(--one-violet-bg); }
.one-persona--active.one-persona--amber { border-color: var(--one-amber); background: var(--one-amber-bg); }
.one-persona--degraded { background: var(--one-warn-bg); border-color: var(--one-warn-border); }

.one-persona-info { display: flex; align-items: center; gap: var(--one-space-6); flex-wrap: wrap; min-width: 0; }
.one-persona-glyph {
  width: 34px; height: 34px; border-radius: var(--one-radius-sm); flex: none;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--one-font-mono); font-size: var(--one-text-sm); font-weight: var(--one-weight-semibold);
}
.one-persona-glyph--violet { background: var(--one-violet-bg); color: var(--one-violet-dark); }
.one-persona-glyph--cyan { background: var(--one-primary-tint); color: var(--one-primary-dark); }
.one-persona-glyph--amber { background: var(--one-amber-bg); color: var(--one-amber-deep); }
/* One /store — product thumbnail (operator-managed R2 asset; CSP img-src allowlisted). */
.one-store-image { width: 72px; height: 72px; object-fit: cover; border-radius: var(--one-radius-sm); flex: 0 0 auto; }
.one-store-image--lg { width: 100%; max-width: 320px; height: auto; }
.one-persona-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.one-persona-label { font-weight: var(--one-weight-semibold); }
.one-persona-actions { display: flex; align-items: center; gap: var(--one-space-6); flex: none; }
.one-persona-meta { color: var(--one-text-faint); font-size: var(--one-text-sm); }
.one-persona-meta--warn { color: var(--one-warn-text); }
/* Inline warn text inside a table cell — the same token as the flash/meta warns,
   so a row-level caution reads as the same severity as a page-level one. */
.one-warn-inline { color: var(--one-warn-text); }

/* 0.153.0 — the Auto top-up page's department row: a header line, then a WRAPPING form. The one-line
   .one-persona flex card squeezed the form between the name and the links until labels overlapped
   the name on a phone (found by the 2026-10-12 billing walk). */
.one-autotopup-list { display: flex; flex-direction: column; gap: var(--one-space-6); }
.one-autotopup-row {
  display: flex; flex-direction: column; gap: var(--one-space-6);
  padding: var(--one-space-7);
  border: 1px solid var(--one-line); border-left: 3px solid var(--one-amber);
  border-radius: var(--one-radius-sm); background: var(--one-card);
}
.one-autotopup-row > p { margin: 0; }
.one-autotopup-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--one-space-4) var(--one-space-6); }
.one-autotopup-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--one-space-6); }
.one-autotopup-form .one-field { margin: 0; }
.one-autotopup-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--one-space-6); }
.one-autotopup-actions p { margin: 0; }

/* "Ask Cheshire" (C-2) — the Help panel's bot affordance. */
.one-help-cheshire { margin-bottom: var(--one-space-6); padding-bottom: var(--one-space-6); border-bottom: 1px solid var(--one-line); }
.one-help-cheshire-lead { margin: 0 0 var(--one-space-4); font-weight: var(--one-weight-medium); color: var(--one-text); }
.one-help-cheshire-btn { width: 100%; }
.one-help-cheshire-note { margin: var(--one-space-4) 0 0; color: var(--one-text-muted); font-size: var(--one-text-sm); }
.one-persona-key { font-family: var(--one-font-mono); font-size: var(--one-text-sm); color: var(--one-text-faint); }

.one-plane-badge {
  font-size: var(--one-text-2xs); font-weight: var(--one-weight-semibold);
  letter-spacing: var(--one-tracking-kpi); text-transform: uppercase;
  padding: 2px var(--one-space-5); border-radius: var(--one-radius-pill); border: 1px solid;
  white-space: nowrap;
}
.one-plane-badge--violet { color: var(--one-violet-dark); background: var(--one-violet-bg); border-color: rgba(124,58,237,0.35); }
.one-plane-badge--cyan { color: var(--one-primary-dark); background: var(--one-primary-tint); border-color: rgba(6,182,212,0.4); }
.one-plane-badge--amber { color: var(--one-amber-deep); background: var(--one-amber-bg); border-color: rgba(245,158,11,0.45); }

.one-status-pill {
  font-size: var(--one-text-2xs); font-weight: var(--one-weight-semibold);
  padding: 2px var(--one-space-5); border-radius: var(--one-radius-pill); border: 1px solid;
  display: inline-flex; align-items: center; gap: 5px;
}
/* vNEXT (platform T-RV1 follow-up) — the approval page's image thumbnails (/a/{token}). */
.one-approval-thumb {
  display: block; max-width: 160px; height: auto; margin-bottom: var(--one-space-5);
  border: 1px solid var(--one-field-border); border-radius: var(--one-radius-sm);
}
/* vNEXT (platform T-CR2, L5) — the member update-link page (/u/{token}): a `this`-scope field's
   languages side by side (stacked on a phone), and the honeypot kept off-screen and unfocusable. */
.one-update-langs { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--one-space-6); }
.one-hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.one-status-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; }
.one-status-pill--ok { color: var(--one-ok-text); background: var(--one-ok-bg); border-color: var(--one-ok-border); }
.one-status-pill--ok::before { background: var(--one-ok-text); }
.one-status-pill--warn { color: var(--one-warn-text); background: var(--one-warn-bg); border-color: var(--one-warn-border); }
.one-status-pill--warn::before { background: var(--one-warn-text); }
.one-status-pill--off { color: var(--one-text-faint); background: var(--one-sunken); border-color: var(--one-line); }
.one-status-pill--off::before { background: var(--one-text-faint); }
/* In-progress: work that is still moving (queued / running / parked). Deliberately a
   FOURTH state rather than reusing --off, because "cancelled" must not look like
   "queued" — and it is the plane accent, not ok/warn, since nothing has gone right or
   wrong yet. Tokens only; no new token is introduced. */
.one-status-pill--busy { color: var(--one-primary-dark); background: var(--one-primary-tint); border-color: var(--one-line); }
.one-status-pill--busy::before { background: var(--one-primary-dark); }

/* ==== Shell — direction A: the console (persistent left rail) ============= */

.one-shell { display: flex; flex: 1; min-height: 0; }
.one-rail {
  width: 232px; flex: none; background: var(--one-canvas-2);
  border-right: 1px solid var(--one-line);
  padding: var(--one-space-8) var(--one-space-6);
  display: flex; flex-direction: column; gap: var(--one-space-8);
}
.one-rail-group { display: flex; flex-direction: column; gap: var(--one-space-4); }
.one-rail-title { padding: 0 var(--one-space-6); }
.one-rail-item {
  display: flex; align-items: center; gap: var(--one-space-6);
  padding: 9px var(--one-space-6); border-radius: var(--one-radius-xs);
  color: var(--one-text-muted); font-size: var(--one-text-sm); cursor: pointer;
  border-left: 3px solid transparent;
}
.one-rail-item:hover { background: var(--one-sunken); color: var(--one-text); }
.one-rail-item .swatch { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.one-rail-item .swatch--violet { background: var(--one-violet); }
.one-rail-item .swatch--cyan { background: var(--one-ray-cyan); }
.one-rail-item .swatch--amber { background: var(--one-amber); }
.one-rail-item--active { background: var(--one-card); color: var(--one-text); font-weight: var(--one-weight-medium); border-left-color: var(--one-primary); box-shadow: var(--one-shadow-card); }
.one-rail-item--active.is-violet { border-left-color: var(--one-violet); }
.one-rail-item--active.is-amber { border-left-color: var(--one-amber); }
.one-rail-foot { margin-top: auto; }
.one-rail-user {
  display: flex; align-items: center; gap: var(--one-space-6);
  padding: var(--one-space-6); border-radius: var(--one-radius-sm); background: var(--one-card); border: 1px solid var(--one-line);
}
.one-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--one-ink); color: var(--one-text-invert);
  font-size: var(--one-text-sm); font-weight: var(--one-weight-semibold);
}

.one-workarea { flex: 1; min-width: 0; padding: var(--one-space-10) var(--one-space-10); overflow-y: auto; }
.one-workarea-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--one-space-7); margin-bottom: var(--one-space-8); }
.one-workarea-head h1 { margin: 0; font-size: var(--one-text-2xl); }

/* Plane cards grid (both shell directions) */
.one-plane-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(224px, 1fr)); gap: var(--one-space-7); }
.one-plane-card {
  display: flex; flex-direction: column; gap: var(--one-space-6);
  padding: var(--one-space-8);
  border: 1px solid var(--one-line); border-radius: var(--one-radius-lg);
  background: var(--one-card); box-shadow: var(--one-shadow-card);
  position: relative; overflow: hidden;
  transition: box-shadow var(--one-dur-fast) ease, transform var(--one-dur-fast) ease;
}
.one-plane-card:hover { box-shadow: var(--one-shadow-raise); }
.one-plane-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; }
.one-plane-card--violet::before { background: var(--one-violet); }
.one-plane-card--cyan::before { background: var(--one-ray-cyan); }
.one-plane-card--amber::before { background: var(--one-amber); }
.one-plane-card--muted { opacity: 0.62; }
.one-plane-card-title { display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-6); }
.one-plane-card-title h3 { margin: 0; font-size: var(--one-text-md); }
.one-plane-card-desc { margin: 0; color: var(--one-text-muted); font-size: var(--one-text-sm); }
.one-plane-card-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-6); padding-top: var(--one-space-4); }

/* ==== Chat island — heavily polished (both directions share bubbles) ====== */

/* Chat spans the full viewport (Jer, 2026-07-09 — 1120px read too cramped);
   matches the gateway plane's full-width idiom. */
.one-body--chat .one-main { max-width: none; }

/* Scroll containment (Jer, 2026-07-09): only the messages log should scroll —
   NOT the whole page. .phasma-query-ng-messages already has overflow-y:auto;
   it only engages once the height chain is bounded, so lock the chat plane to
   the viewport and put min-height:0 on every flex ancestor (the classic fix —
   flex items default to min-height:auto and refuse to shrink below content). */
.one-body--chat { height: 100vh; height: 100dvh; overflow: hidden; }
.one-body--chat .one-main { min-height: 0; overflow: hidden; }
.one-body--chat .one-chat { flex: 1; min-height: 0; }
.one-body--chat .phasma-query-ng-main { min-height: 0; }

/* Text-size adjuster — scales the messages log ONLY (the button row lives
   above the log; the scale rides --one-chat-font-scale, multiplied into
   .phasma-query-ng-messages font-size so bubble text inherits + scales). */
.one-chat-fontbar { display: flex; align-items: center; justify-content: flex-end; gap: var(--one-space-4); padding: 0 var(--one-space-2) var(--one-space-4); color: var(--one-text-faint); font-size: var(--one-text-sm); }
.one-chat-fontbar-label { margin-right: var(--one-space-2); }
.one-chat-fontbtn, .one-chat-fontbar-readout {
  font: inherit; cursor: pointer; color: var(--one-text-muted);
  background: var(--one-card); border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm); padding: 2px 8px; line-height: 1.4;
}
.one-chat-fontbtn { min-width: 28px; font-weight: var(--one-weight-semibold); }
.one-chat-fontbar-readout { min-width: 46px; text-align: center; font-variant-numeric: tabular-nums; }
.one-chat-fontbtn:hover:not(:disabled), .one-chat-fontbar-readout:hover { background: var(--one-sunken); }
.one-chat-fontbtn:disabled { opacity: 0.45; cursor: default; }

.one-chat { display: flex; gap: var(--one-stack-gap); min-height: 72vh; align-items: stretch; }

/* Conversation rail (direction A / console chat) */
.phasma-query-ng-sidebar {
  width: 248px; flex: none; display: flex; flex-direction: column; gap: var(--one-space-6);
}
.phasma-query-ng-new {
  display: flex; align-items: center; justify-content: center; gap: var(--one-space-4);
  padding: 10px var(--one-space-6); border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm); background: var(--one-card); color: var(--one-text);
  font: inherit; font-weight: var(--one-weight-medium); cursor: pointer;
}
.phasma-query-ng-new:hover { background: var(--one-sunken); }
.phasma-query-ng-conversations { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-4); overflow-y: auto; }
.phasma-query-ng-conversation {
  position: relative;
  font: inherit; font-size: var(--one-text-sm); width: 100%; text-align: left;
  padding: var(--one-space-6); padding-right: 46px; border: 1px solid transparent; border-radius: var(--one-radius-sm);
  background: transparent; color: var(--one-text-muted); cursor: pointer;
  display: flex; flex-direction: column; gap: 2px; overflow: hidden;
  /* 0.151.0 — never shrink: overflow:hidden zeroes a flex item's min-height, so once the list
     overflowed (~20 conversations) every card collapsed to 26px and its title vanished. */
  flex-shrink: 0;
}
.phasma-query-ng-conversation:hover { background: var(--one-sunken); }
.phasma-query-ng-conversation.is-active { border-color: var(--one-line); background: var(--one-card); color: var(--one-text); box-shadow: var(--one-shadow-card); }
.phasma-query-ng-conversation .c-title { font-weight: var(--one-weight-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--one-text); }
.phasma-query-ng-conversation .c-meta { font-size: var(--one-text-2xs); color: var(--one-text-fainter); }
/* Per-card rename (pencil) + hide (✕): subtle by default (faint), brighter on
   card hover/focus. Absolutely placed in the reserved right gutter. */
.phasma-query-ng-conversation .c-actions { position: absolute; top: 6px; right: 6px; display: flex; gap: 2px; }
.phasma-conv-action {
  display: inline-flex; align-items: center; justify-content: center; line-height: 0;
  width: 24px; height: 24px; padding: 0; margin: 0; border: none; border-radius: var(--one-radius-sm);
  background: transparent; color: var(--one-text-fainter); cursor: pointer; opacity: 0.55;
  transition: opacity .12s ease, background .12s ease, color .12s ease;
}
.phasma-query-ng-conversation:hover .phasma-conv-action,
.phasma-query-ng-conversation:focus-within .phasma-conv-action { opacity: 1; }
.phasma-conv-action:hover { background: var(--one-line); color: var(--one-text); }
.phasma-conv-rename {
  font: inherit; font-size: var(--one-text-sm); font-weight: var(--one-weight-medium);
  width: 100%; box-sizing: border-box; padding: 1px 5px; margin: 0;
  border: 1px solid var(--one-line); border-radius: var(--one-radius-sm);
  background: var(--one-card); color: var(--one-text);
}
.phasma-conv-rename:focus { outline: none; border-color: var(--one-text-muted); }

/* Main column */
.phasma-query-ng-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.one-chat-head { display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-6); padding: 0 var(--one-space-2) var(--one-space-6); }
.one-chat-head h2 { margin: 0; font-size: var(--one-text-md); }
.one-chat-scope { display: inline-flex; align-items: center; gap: var(--one-space-4); color: var(--one-text-faint); font-size: var(--one-text-sm); }

.phasma-query-ng-messages {
  flex: 1; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--one-space-8);
  padding: var(--one-space-8);
  background: var(--one-card);
  border: 1px solid var(--one-line); border-radius: var(--one-radius-lg);
  /* the text-size adjuster scales this log ONLY; bubbles inherit + follow */
  font-size: calc(var(--one-text-base) * var(--one-chat-font-scale, 1));
}
.phasma-query-ng-status { min-height: 18px; color: var(--one-text-faint); font-size: var(--one-text-sm); padding: var(--one-space-2) var(--one-space-4); }

/* Focused single-column chat (direction B) */
.one-chat--focus { display: block; }
.one-chat--focus .phasma-query-ng-messages { max-width: 760px; margin: 0 auto; width: 100%; border: none; background: transparent; padding: var(--one-space-8) 0; }
.one-chat--focus .phasma-query-ng-composer { max-width: 760px; margin: var(--one-space-6) auto 0; }
.one-chat--focus .one-chat-head { max-width: 760px; margin: 0 auto; width: 100%; }

/* ---- Bubbles ---- */
.phasma-query-ng-bubble {
  max-width: 74%;
  padding: 12px 16px;
  border-radius: var(--one-radius-bubble);
  line-height: var(--one-leading-chat);
  overflow-wrap: break-word;
}
.phasma-query-ng-user {
  align-self: flex-end;
  background: var(--one-bubble-user); color: var(--one-bubble-user-text);
  border-bottom-right-radius: var(--one-radius-tail);
  white-space: pre-wrap;
}
.phasma-query-ng-assistant {
  align-self: flex-start;
  background: var(--one-bubble-assistant); color: var(--one-bubble-assistant-text);
  border: 1px solid var(--one-line-soft);
  border-bottom-left-radius: var(--one-radius-tail);
}
/* Platform #80 (0.145.0) — a job this conversation ordered reported back on its own: the row is
   an ordinary assistant bubble (the model remembers it too) with a quiet eyebrow and a left
   accent, so it reads as an update that arrived rather than an answer to a question. */
.phasma-query-ng-assistant.one-delivery { border-left: 3px solid var(--one-primary); }
.one-delivery-eyebrow {
  display: block;
  font-size: 0.72em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--one-text-faint);
  margin-bottom: 4px;
}
.phasma-query-ng-assistant.phasma-thinking { color: var(--one-text-faint); font-style: italic; display: inline-flex; align-items: center; gap: var(--one-space-6); }
.one-think-dots { display: inline-flex; gap: 3px; }
.one-think-dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--one-text-fainter); animation: one-pulse 1.2s ease-in-out infinite; }
.one-think-dots i:nth-child(2) { animation-delay: 0.2s; }
.one-think-dots i:nth-child(3) { animation-delay: 0.4s; }
@keyframes one-pulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }
.one-think-elapsed { font-style: normal; font-variant-numeric: tabular-nums; color: var(--one-text-fainter); }
@media (prefers-reduced-motion: reduce) {
  .one-think-dots i { animation: none; opacity: 0.6; }
}

.phasma-query-ng-error {
  align-self: flex-start; max-width: 74%;
  background: var(--one-bubble-error-bg); color: var(--one-bubble-error-text);
  border: 1px solid var(--one-bubble-error-border);
  border-radius: var(--one-radius-bubble); border-bottom-left-radius: var(--one-radius-tail);
  padding: 12px 16px;
}
.phasma-query-ng-assistant p { margin: 0 0 10px; }
.phasma-query-ng-assistant p:first-child { margin-top: 0; }
.phasma-query-ng-assistant p:last-child { margin-bottom: 0; }
.phasma-query-ng-assistant strong { font-weight: var(--one-weight-semibold); }
.phasma-query-ng-assistant pre {
  background: var(--one-ink); color: var(--one-ink-contrast);
  padding: var(--one-space-7); border-radius: var(--one-radius-sm);
  overflow-x: auto; position: relative; font-size: var(--one-text-sm);
  font-family: var(--one-font-mono); margin: 10px 0;
}
.phasma-query-ng-assistant code { font-family: var(--one-font-mono); font-size: 0.92em; }

/* ---- Composer (the pill) ---- */
.phasma-query-ng-composer {
  display: flex; gap: var(--one-space-6); align-items: flex-end;
  margin-top: var(--one-space-7);
  padding: var(--one-space-5);
  background: var(--one-card);
  border: 1px solid var(--one-line);
  border-radius: var(--one-radius-xl);
  box-shadow: var(--one-shadow-card);
  transition: border-color var(--one-dur-fast) ease, box-shadow var(--one-dur-fast) ease;
}
.phasma-query-ng-composer:focus-within { border-color: var(--one-primary); box-shadow: var(--one-ring); }
.phasma-query-ng-attach {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--one-text-faint); cursor: pointer;
}
.phasma-query-ng-attach:hover { background: var(--one-sunken); color: var(--one-text-muted); }
.phasma-query-ng-input {
  flex: 1; resize: none; font: inherit; line-height: 1.5;
  padding: 9px var(--one-space-4); border: none; background: transparent;
  max-height: 168px; color: var(--one-text);
}
.phasma-query-ng-input:focus { outline: none; }
.phasma-query-ng-input::placeholder { color: var(--one-text-fainter); }
.phasma-query-ng-send {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; background: var(--one-primary); color: var(--one-on-primary); cursor: pointer;
  transition: background var(--one-dur-fast) ease;
}
.phasma-query-ng-send:hover { background: var(--one-primary-dark); }
.phasma-query-ng-send:disabled { background: var(--one-line); color: var(--one-text-fainter); cursor: default; }
.phasma-query-ng-send.is-stop { background: var(--one-card); border: 1px solid var(--one-field-border); color: var(--one-text-muted); }
.phasma-input-note { color: var(--one-text-fainter); font-size: var(--one-text-2xs); margin: var(--one-space-4) 0 0; text-align: center; }

/* ---- Answer tail: receipt / stepper / sources / stopped ---- */
.phasma-answer-meta { align-self: flex-start; color: var(--one-text-fainter); font-size: var(--one-text-2xs); padding-left: var(--one-space-4); display: flex; gap: var(--one-space-6); }

/* The honest stepper — past tense, sources consulted */
.phasma-stepper {
  align-self: flex-start; max-width: 74%;
  padding: var(--one-space-6) var(--one-space-7);
  background: var(--one-violet-bg);
  border: 1px solid rgba(124,58,237,0.18);
  border-radius: var(--one-radius-sm);
  display: flex; flex-direction: column; gap: var(--one-space-4);
}
.phasma-stepper-title { font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-violet-dark); font-weight: var(--one-weight-semibold); }
.phasma-stage {
  font-size: var(--one-text-sm); color: var(--one-text-muted);
  display: flex; align-items: center; gap: var(--one-space-6);
  opacity: 0; animation: one-stage-in 0.35s ease forwards;
}
.phasma-stage .chk {
  flex: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--one-success-soft); color: var(--one-success-strong);
  display: flex; align-items: center; justify-content: center; font-size: 10px;
}
.phasma-stage--active .chk { background: transparent; border: 2px solid var(--one-violet); box-shadow: none; animation: one-spin 0.8s linear infinite; }
.phasma-stage--active { color: var(--one-violet-dark); }
@keyframes one-stage-in { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .phasma-stage { animation: none; opacity: 1; }
  .phasma-stage--active .chk { animation: none; }
}

/* Platform T-SA1 — the act receipt: what the platform saw the turn do (never the model's word). */
.phasma-acts { align-self: flex-start; max-width: 74%; font-size: var(--one-text-sm); color: var(--one-text-muted); }
.phasma-acts--none { font-size: var(--one-text-2xs); color: var(--one-text-fainter); padding-left: var(--one-space-4); }
.phasma-acts-summary { cursor: pointer; list-style: none; font-size: var(--one-text-2xs); color: var(--one-text-fainter); padding-left: var(--one-space-4); }
.phasma-acts-summary::-webkit-details-marker { display: none; }
.phasma-act { display: flex; align-items: baseline; gap: var(--one-space-4); padding: var(--one-space-2) var(--one-space-4); word-break: break-word; }
.phasma-act .mark { flex: none; color: var(--one-success-strong); }
.phasma-act--failed .mark { color: var(--one-danger); }

.phasma-sources { align-self: flex-start; max-width: 74%; font-size: var(--one-text-sm); width: 100%; }
.phasma-sources-summary {
  cursor: pointer; color: var(--one-text-muted); list-style: none;
  display: inline-flex; align-items: center; gap: var(--one-space-4);
  padding: var(--one-space-4) 0;
}
.phasma-sources-summary::-webkit-details-marker { display: none; }
.phasma-sources-summary .tw { transition: transform var(--one-dur-fast) ease; }
.phasma-sources[open] .phasma-sources-summary .tw { transform: rotate(90deg); }
.phasma-sources-body {
  border: 1px solid var(--one-line); border-radius: var(--one-radius-sm);
  padding: var(--one-space-6) var(--one-space-7); background: var(--one-tile);
  margin-top: var(--one-space-4);
}
.phasma-sources-group { margin: var(--one-space-4) 0; }
.phasma-sources-group:first-child { margin-top: 0; }
.phasma-sources-group-title { font-weight: var(--one-weight-semibold); font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-text-muted); margin-bottom: var(--one-space-4); }
.phasma-source { margin: var(--one-space-4) 0; display: flex; gap: var(--one-space-6); align-items: baseline; }
.phasma-source-badge {
  flex: none; display: inline-block; font-size: var(--one-text-2xs);
  background: var(--one-wisp-bg); color: var(--one-violet-dark);
  border-radius: var(--one-radius-pill); padding: 1px var(--one-space-5);
  font-weight: var(--one-weight-medium);
}
.phasma-source-badge--cyan { background: var(--one-primary-tint); color: var(--one-primary-dark); }
.phasma-source-excerpt { color: var(--one-text-muted); }

/* Truncated / stopped-partial */
.phasma-answer-truncated, .phasma-answer-stopped {
  align-self: flex-start; max-width: 74%; font-size: var(--one-text-sm);
  color: var(--one-warn-text); background: var(--one-warn-bg);
  border: 1px solid var(--one-warn-border); border-radius: var(--one-radius-sm);
  padding: var(--one-space-6) var(--one-space-7);
  display: flex; align-items: center; gap: var(--one-space-6);
}
.phasma-answer-stopped .one-btn { margin-left: auto; }

/* Claim gate (T-GG1) — a small chip in the answer tail */
.phasma-answer-claim {
  align-self: flex-start; font-size: var(--one-text-2xs);
  font-weight: var(--one-weight-medium);
  border-radius: var(--one-radius-pill); padding: 1px var(--one-space-5);
  color: var(--one-text-muted); border: 1px solid var(--one-line);
}
.phasma-answer-claim--annotate {
  color: var(--one-warn-text); background: var(--one-warn-bg); border-color: var(--one-warn-border);
}

/* Regenerate / edit-resend (T-SU2) — the rows a superseding turn is replacing dim while it runs;
   the audit view's replaced rows stay dimmed under the delivery eyebrow's pattern ("Replaced").
   A refusal (turn_has_acts …) is a quiet note, not an error. */
.one-superseding { opacity: 0.45; }
.phasma-query-ng-bubble.one-replaced { opacity: 0.55; border-style: dashed; }
.one-supersede-note {
  align-self: flex-start; max-width: 74%; font-size: var(--one-text-sm);
  color: var(--one-text-muted); background: var(--one-sunken);
  border: 1px solid var(--one-line-soft); border-radius: var(--one-radius-sm);
  padding: var(--one-space-6) var(--one-space-7);
}
.phasma-query-ng-user.one-editing { min-width: min(480px, 74%); }
.one-edit-input {
  display: block; width: 100%; box-sizing: border-box; resize: vertical; font: inherit; line-height: 1.5;
  color: var(--one-text); background: var(--one-card);
  border: 1px solid var(--one-line); border-radius: var(--one-radius-xs); padding: var(--one-space-4);
}
.one-edit-input:focus { outline: none; border-color: var(--one-text-muted); }
.one-edit-bar { display: flex; justify-content: flex-end; gap: var(--one-space-4); margin-top: var(--one-space-4); }

/* Copy / retry rows */
.phasma-copy-row, .phasma-retry-row { display: flex; gap: var(--one-space-4); align-self: flex-start; }
.phasma-copy-row.user { justify-content: flex-end; align-self: flex-end; }
.phasma-copy-action, .phasma-retry-action, .phasma-code-copy, .phasma-capture-action {
  font: inherit; font-size: var(--one-text-2xs);
  display: inline-flex; align-items: center; gap: 5px;
  border: none; background: transparent; color: var(--one-text-faint);
  cursor: pointer; padding: var(--one-space-2) var(--one-space-4); border-radius: var(--one-radius-xs);
}
.phasma-copy-action:hover, .phasma-retry-action:hover, .phasma-capture-action:hover { color: var(--one-primary-dark); background: var(--one-sunken); }
.phasma-copy-action svg, .phasma-code-copy svg, .phasma-capture-action svg { width: 13px; height: 13px; }
.phasma-code-copy { position: absolute; top: 6px; right: 6px; color: var(--one-text-faint); }
.phasma-retry-action { color: var(--one-primary); font-weight: var(--one-weight-medium); }

/* Elicitation chips */
.phasma-elicitation { align-self: flex-start; max-width: 74%; display: flex; flex-direction: column; gap: var(--one-space-6); }
.phasma-elicit-prompt { color: var(--one-text-muted); font-size: var(--one-text-sm); }
.phasma-elicit-chips { display: flex; flex-wrap: wrap; gap: var(--one-space-4); }
.phasma-elicit-chip {
  font: inherit; font-size: var(--one-text-sm);
  border: 1px solid rgba(6,182,212,0.5); border-radius: var(--one-radius-pill);
  background: var(--one-primary-tint); color: var(--one-primary-dark);
  padding: 6px var(--one-space-7); cursor: pointer;
  transition: background var(--one-dur-fast) ease, color var(--one-dur-fast) ease;
}
.phasma-elicit-chip:hover { background: var(--one-primary); color: var(--one-text-invert); border-color: var(--one-primary); }
.phasma-elicitation.is-answered { opacity: 0.5; }

/* Capture / wisp modal */
.phasma-capture-modal {
  position: fixed; inset: 0; background: rgba(17, 24, 39, 0.5);
  display: flex; align-items: center; justify-content: center; z-index: 40;
}
.phasma-capture-panel {
  background: var(--one-card); border-radius: var(--one-radius-lg);
  box-shadow: var(--one-shadow-modal);
  padding: var(--one-card-pad-y) var(--one-card-pad-x);
  width: min(480px, 92vw);
  display: flex; flex-direction: column; gap: var(--one-space-6);
}
.phasma-capture-title { margin: 0; font-size: var(--one-text-xl); }
.phasma-capture-done { align-self: flex-start; font-size: var(--one-text-2xs); color: var(--one-ok-text); display: inline-flex; align-items: center; gap: 5px; }

/* ---- NG toolbar: workspace + model + manage (v1.19–v1.22) --------------- */
.one-chat-toolbar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--one-space-6) var(--one-space-10);
  padding: 0 var(--one-space-2) var(--one-space-7); border-bottom: 1px solid var(--one-line-soft);
  margin-bottom: var(--one-space-7);
}
.one-chat--focus .one-chat-toolbar { max-width: 760px; margin: 0 auto var(--one-space-7); width: 100%; }
.phasma-query-ng-workspace, .phasma-query-ng-model { display: flex; align-items: flex-end; gap: var(--one-space-6); flex-wrap: wrap; }
.phasma-query-ng-workspace-label, .phasma-query-ng-model-label {
  display: flex; flex-direction: column; gap: var(--one-space-2);
  font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi);
  color: var(--one-text-faint); font-weight: var(--one-weight-semibold);
}
.phasma-query-ng-workspace-select, .phasma-query-ng-model-select {
  font: inherit; font-size: var(--one-text-sm); color: var(--one-text); text-transform: none; letter-spacing: 0;
  padding: 6px var(--one-space-6); border: 1px solid var(--one-field-border);
  border-radius: var(--one-radius-xs); background: var(--one-card); min-width: 150px;
}
.phasma-query-ng-workspace-select:focus, .phasma-query-ng-model-select:focus { outline: none; border-color: var(--one-primary); box-shadow: var(--one-ring); }
/* The active-workspace chip (v0.78.0): the answer to "which workspace am I on",
   permanently visible beside the Manage door — the state was invisible before. */
.phasma-query-ng-workspace-current {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  background: var(--one-surface-2, rgba(0,0,0,.06));
  color: var(--one-text-muted); font-size: 0.85em; font-weight: 600;
  max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The workspace's effective model, beside the workspace chip — the same chip, one fact over. */
.phasma-query-ng-model-current {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  background: var(--one-primary-tint); color: var(--one-primary-dark);
  font-size: 0.85em; font-weight: 600;
  max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The superseded-model notice above the chat log — the kit's info flash (informational
   tone, not an error), made slim: one line of text, Switch + dismiss on the right. */
.one-chat-model-notice {
  align-items: center; flex-wrap: wrap;
  padding: var(--one-space-4) var(--one-space-6);
  margin: 0 var(--one-space-2) var(--one-space-6);
}
.one-chat--focus .one-chat-model-notice { max-width: 760px; margin: 0 auto var(--one-space-6); width: 100%; }
.one-chat-model-notice__text { margin: 0; flex: 1 1 260px; }
.one-chat-model-notice__actions { display: flex; align-items: center; gap: var(--one-space-2); margin-left: auto; }
.one-chat-model-notice__close { padding: var(--one-space-2); color: var(--one-info-text); }
.one-chat-model-notice__error { flex-basis: 100%; font-size: var(--one-text-2xs); color: var(--one-danger); }
.phasma-query-ng-workspace-manage {
  font: inherit; font-size: var(--one-text-sm); font-weight: var(--one-weight-medium);
  padding: 7px var(--one-space-7); border: 1px solid var(--one-primary); color: var(--one-primary-dark);
  background: var(--one-primary-tint); border-radius: var(--one-radius-xs); cursor: pointer; align-self: flex-end;
  transition: background var(--one-dur-fast) ease, color var(--one-dur-fast) ease;
}
.phasma-query-ng-workspace-manage:hover { background: var(--one-primary); color: var(--one-text-invert); }
.phasma-query-ng-model-status { font-size: var(--one-text-2xs); color: var(--one-ok-text); align-self: center; }
.phasma-query-ng-model-note { font-size: var(--one-text-2xs); color: var(--one-text-fainter); flex-basis: 100%; margin-top: -4px; }

/* ---- Composer icon buttons: camera / mic / speaker (v1.30 / Speak v1) --- */
.phasma-query-ng-camera, .phasma-query-ng-mic, .phasma-query-ng-speaker {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--one-text-faint); cursor: pointer;
  transition: background var(--one-dur-fast) ease, color var(--one-dur-fast) ease;
}
.phasma-query-ng-camera:hover, .phasma-query-ng-mic:hover, .phasma-query-ng-speaker:hover { background: var(--one-sunken); color: var(--one-text-muted); }
.phasma-query-ng-speaker.is-on { color: var(--one-primary-dark); background: var(--one-primary-tint); }
.phasma-query-ng-mic.is-recording { color: var(--one-text-invert); background: var(--one-danger); animation: one-pulse-rec 1.4s ease-in-out infinite; }
@keyframes one-pulse-rec { 0%,100% { box-shadow: 0 0 0 0 rgba(176,42,44,0.45); } 50% { box-shadow: 0 0 0 6px rgba(176,42,44,0); } }

/* ---- Attached-image chip + in-bubble indicator (v1.30) ----------------- */
.phasma-attach-image-chip {
  align-self: flex-start; display: inline-flex; align-items: center; gap: var(--one-space-6);
  padding: var(--one-space-4) var(--one-space-6); margin-top: var(--one-space-4);
  background: var(--one-card); border: 1px solid var(--one-line); border-radius: var(--one-radius-pill); max-width: 100%;
}
.one-chat--focus .phasma-attach-image-chip { max-width: 760px; margin-left: auto; margin-right: auto; }
.phasma-attach-image-thumb { width: 34px; height: 34px; border-radius: var(--one-radius-xs); object-fit: cover; flex: none; border: 1px solid var(--one-line); }
.phasma-attach-image-name { font-size: var(--one-text-sm); color: var(--one-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 220px; }
.phasma-attach-image-remove { flex: none; border: none; background: transparent; color: var(--one-text-faint); font-size: 18px; line-height: 1; cursor: pointer; padding: 0 4px; }
.phasma-attach-image-remove:hover { color: var(--one-danger); }
.phasma-attach-image-indicator { display: block; margin-top: 5px; font-size: var(--one-text-2xs); opacity: 0.85; font-style: italic; }

/* ---- Rich markdown in assistant answers (lists / table / code copy) ----- */
.phasma-query-ng-assistant ul, .phasma-query-ng-assistant ol { margin: 8px 0; padding-left: 20px; }
.phasma-query-ng-assistant li { margin: 3px 0; }
.phasma-query-ng-assistant blockquote { margin: 8px 0; padding: 4px 12px; border-left: 3px solid var(--one-line); color: var(--one-text-muted); }
.phasma-query-ng-assistant :not(pre) > code { background: var(--one-sunken); border: 1px solid var(--one-line); border-radius: var(--one-radius-xs); padding: 0 4px; }
.phasma-query-ng-assistant pre { position: relative; overflow-x: auto; }
.phasma-query-ng-assistant table { border-collapse: collapse; width: 100%; margin: 10px 0; font-size: var(--one-text-sm); }
.phasma-query-ng-assistant th, .phasma-query-ng-assistant td { border: 1px solid var(--one-line); padding: 6px 10px; text-align: left; }
.phasma-query-ng-assistant th { background: var(--one-sunken); font-weight: var(--one-weight-semibold); font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-text-muted); }
.phasma-query-ng-assistant td { font-variant-numeric: tabular-nums; }

/* ---- Manage modal (workspace management, v1.22) ------------------------ */
.one-modal-scrim { position: absolute; inset: 0; background: rgba(17,24,39,0.5); display: flex; align-items: center; justify-content: center; padding: var(--one-space-8); }
.one-modal-panel {
  background: var(--one-card); border-radius: var(--one-radius-lg); box-shadow: var(--one-shadow-modal);
  padding: var(--one-card-pad-y) var(--one-card-pad-x); width: min(600px, 96%);
  max-height: 100%; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; gap: var(--one-space-7);
}
.one-modal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-6); }
.one-modal-title { margin: 0; font-size: var(--one-text-xl); }
.one-modal-close { border: none; background: transparent; color: var(--one-text-faint); font-size: 20px; line-height: 1; cursor: pointer; }
.one-ws-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-6); }
.one-ws { border: 1px solid var(--one-line); border-radius: var(--one-radius-sm); background: var(--one-tile); padding: var(--one-space-7); }
.one-ws-head { display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-6); }
.one-ws-name { font-weight: var(--one-weight-semibold); display: flex; align-items: center; gap: var(--one-space-6); }
.one-ws-body { margin-top: var(--one-space-6); display: flex; flex-direction: column; gap: var(--one-space-6); }
.one-kb-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-4); }
.one-kb { display: flex; align-items: center; gap: var(--one-space-6); font-size: var(--one-text-sm); color: var(--one-text-muted); }
.one-kb input { flex: none; }
.one-check { flex: none; width: 16px; height: 16px; border-radius: 4px; border: 1.5px solid var(--one-field-border); background: var(--one-card); display: inline-flex; align-items: center; justify-content: center; }
.one-check.is-on { background: var(--one-primary); border-color: var(--one-primary); }
.one-check.is-on::after { content: ""; width: 4px; height: 8px; border: solid var(--one-on-primary); border-width: 0 2px 2px 0; transform: rotate(45deg); margin-top: -2px; }
.one-module-chips { display: flex; flex-wrap: wrap; gap: var(--one-space-4); }
.one-ws-create { display: flex; gap: var(--one-space-6); align-items: flex-end; flex-wrap: wrap; padding-top: var(--one-space-6); border-top: 1px solid var(--one-line-soft); }

/* ==== Security: TOTP / recovery codes ==================================== */

.one-qr {
  display: flex; justify-content: center; padding: var(--one-space-7);
  background: var(--one-card); border: 1px solid var(--one-line); border-radius: var(--one-radius-sm);
}
.one-qr svg, .one-qr img { width: 176px; height: 176px; display: block; }

.one-recovery-codes {
  list-style: none; margin: var(--one-space-6) 0; padding: var(--one-space-7);
  background: var(--one-tile); border: 1px dashed var(--one-line);
  border-radius: var(--one-radius-sm);
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--one-space-4) var(--one-space-8);
}
.one-recovery-codes li { display: flex; align-items: center; gap: var(--one-space-6); }
.one-recovery-codes .n { color: var(--one-text-fainter); font-size: var(--one-text-2xs); width: 16px; }
.one-recovery-codes code { font-family: var(--one-font-mono); font-size: var(--one-text-sm); color: var(--one-text); letter-spacing: 0.5px; }
.one-recovery-codes li.is-used code { text-decoration: line-through; color: var(--one-text-fainter); }

.one-stepnum {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--one-violet-bg); color: var(--one-violet-dark);
  font-size: var(--one-text-2xs); font-weight: var(--one-weight-semibold);
  font-family: var(--one-font-mono);
}

/* ==== Invites (1B) ======================================================= */

.one-invite-fresh { border-left: 3px solid var(--one-ok-border); }
.one-invite-link code {
  display: block; padding: var(--one-space-6);
  background: var(--one-tile); border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm);
  font-family: var(--one-font-mono); font-size: var(--one-text-sm);
  overflow-wrap: anywhere; user-select: all; color: var(--one-text);
}
.one-invite-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-6); }
.one-invite {
  display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-7);
  padding: var(--one-space-7); border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm); background: var(--one-card);
}
.one-invite--dead { opacity: 0.55; }
.one-invite-info { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.one-invite-email { font-weight: var(--one-weight-medium); }
.one-invite-caps { display: flex; flex-wrap: wrap; gap: var(--one-space-4); margin-top: var(--one-space-4); }
/* store-admin — the package capability tick-list (violet). */
.one-cap-ticklist { list-style: none; margin: 0 0 var(--one-space-6); padding: 0; columns: 2; max-width: 900px; }
.one-cap-ticklist li { break-inside: avoid; margin-bottom: var(--one-space-4); }
.one-cap-chip {
  font-family: var(--one-font-mono); font-size: var(--one-text-2xs);
  background: var(--one-sunken); border: 1px solid var(--one-line);
  border-radius: var(--one-radius-xs); padding: 1px var(--one-space-5); color: var(--one-text-muted);
}

.one-consent { display: flex; gap: var(--one-space-6); align-items: flex-start; font-size: var(--one-text-sm); color: var(--one-text-muted); padding: var(--one-space-6) 0; }
.one-consent input { margin-top: 3px; flex: none; }

/* Small helpers */
.one-row { display: flex; align-items: center; gap: var(--one-space-6); }
.one-row--between { justify-content: space-between; }
.one-stack { display: flex; flex-direction: column; gap: var(--one-space-6); }
.one-divider { border: none; border-top: 1px solid var(--one-line-soft); margin: var(--one-space-4) 0; }

/* ==== Lead tracker (T-LT2) — /gateway/leads board + list + detail, /chat/leads ============== */
.one-lead-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--one-space-6); margin: var(--one-space-6) 0 0; }
.one-lead-filters .one-field { min-width: 150px; }
.one-lead-board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--one-space-6); align-items: start; margin: var(--one-space-7) 0 0; }
@media (max-width: 1100px) { .one-lead-board { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .one-lead-board { grid-template-columns: minmax(0, 1fr); } }
.one-lead-col { background: var(--one-surface-2); border: 1px solid var(--one-line-soft); border-radius: var(--one-radius-lg); padding: var(--one-space-6); display: flex; flex-direction: column; gap: var(--one-space-5); min-width: 0; }
.one-lead-col-head { display: flex; justify-content: space-between; align-items: baseline; margin: 0; font-size: var(--one-text-sm); font-weight: var(--one-weight-semibold); }
.one-lead-count { color: var(--one-text-faint); font-variant-numeric: tabular-nums; }
.one-lead-closed { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--one-space-6); margin: var(--one-space-7) 0 0; }
.one-lead-closed summary { cursor: pointer; font-size: var(--one-text-sm); font-weight: var(--one-weight-semibold); }
.one-lead-card { background: var(--one-card); border: 1px solid var(--one-line); border-radius: var(--one-radius-sm); padding: var(--one-space-5) var(--one-space-6); display: flex; flex-direction: column; gap: var(--one-space-2); min-width: 0; overflow-wrap: anywhere; }
.one-lead-card-title { font-weight: var(--one-weight-semibold); }
.one-lead-meta { display: flex; flex-wrap: wrap; gap: var(--one-space-2) var(--one-space-4); color: var(--one-text-faint); font-size: var(--one-text-sm); }
.one-lead-chip { display: inline-block; padding: 1px var(--one-space-4); border: 1px solid var(--one-line); border-radius: var(--one-radius-pill); background: var(--one-sunken); color: var(--one-text-faint); font-size: var(--one-text-2xs); }
.one-lead-move { display: flex; gap: var(--one-space-4); align-items: center; margin-top: var(--one-space-2); }
.one-lead-move .one-input { padding-top: 4px; padding-bottom: 4px; }
.one-lead-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--one-space-4) var(--one-space-7); margin: var(--one-space-6) 0 0; }
.one-lead-facts dt { color: var(--one-text-faint); font-size: var(--one-text-sm); }
.one-lead-facts dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 640px) { .one-lead-facts { grid-template-columns: minmax(0, 1fr); } .one-lead-facts dd { margin-bottom: var(--one-space-4); } }
.one-lead-notes { list-style: none; margin: var(--one-space-7) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-6); }
.one-lead-note { border-left: 3px solid var(--one-line); padding: 0 0 0 var(--one-space-6); white-space: pre-wrap; overflow-wrap: anywhere; }
.one-lead-note-meta { display: block; color: var(--one-text-faint); font-size: var(--one-text-sm); white-space: normal; }

/* Mobile drawer chrome (chat) — display:none at ALL widths by default; the
   ≤760px block below reveals it. Desktop DOM behavior stays byte-identical.
   Pass 2 adds the composer "+" disclosure to the same default-hidden set (its
   Options + speaker siblings live INSIDE the mobilebar, so they need no own
   base rule). */
.one-chat-mobilebar { display: none; }
.one-drawer-backdrop { display: none; }

/* 0.154.0 — a menu too long for the bar gives way to the drawer BEFORE it runs under the Help control and the
   account chip (the org-admin bar overlapped them at 1280–1440 px; 2026-10-12 billing walk). The server picks the
   breakpoint from the menu as filtered for this login (Navigation::collapseBelow); each class switches at its own
   width, the same two rules the phone breakpoint uses. */
@media (max-width: 1023px) { .one-header--fit--1024 .one-topnav { display: none; } .one-header--fit--1024 .one-navdrawer { display: block; order: -1; } }
@media (max-width: 1179px) { .one-header--fit--1180 .one-topnav { display: none; } .one-header--fit--1180 .one-navdrawer { display: block; order: -1; } }
@media (max-width: 1279px) { .one-header--fit--1280 .one-topnav { display: none; } .one-header--fit--1280 .one-navdrawer { display: block; order: -1; } }
@media (max-width: 1365px) { .one-header--fit--1366 .one-topnav { display: none; } .one-header--fit--1366 .one-navdrawer { display: block; order: -1; } }
@media (max-width: 1439px) { .one-header--fit--1440 .one-topnav { display: none; } .one-header--fit--1440 .one-navdrawer { display: block; order: -1; } }
@media (max-width: 1599px) { .one-header--fit--1600 .one-topnav { display: none; } .one-header--fit--1600 .one-navdrawer { display: block; order: -1; } }
.one-composer-plus { display: none; }

@media (max-width: 760px) {
  /* ---- Header: the plane bar becomes the drawer ---------------------------
     Same `nav` data, same components, no layout fork — CSS decides which of the
     two renderings in _topnav.html.twig is visible. The persona chip stays in the
     bar (it is the one control a small screen still needs at a glance) and keeps a
     TRUNCATED label — shedding it left a bare dot that said nothing about which hat
     was on (the 2026-10-12 billing walk); the drawer carries the persona block in full. */
  .one-topnav { display: none; }
  .one-navdrawer { display: block; order: -1; }
  .one-header { gap: var(--one-space-6); padding: 0 var(--one-space-7); }
  .one-brand { margin-right: 0; }
  /* The chip names the PLANE in one word ("Billing", "Admin", "Seat", "Operator") — a truncated full label read
     "One …" at 320 px and cut the very part that names the hat. The actions group and the menu may still shrink,
     so nothing pushes past the edge. Measured 0.153.1: 0 overflow at 390 and 320 px. */
  .one-header-actions { flex: 0 1 auto; min-width: 0; }
  .one-persona-menu { flex: 0 1 auto; min-width: 0; }
  .one-persona-chip { max-width: 100%; min-width: 0; }
  .one-persona-chip-label { display: none; }
  .one-persona-chip-short { display: inline; }
  /* Help keeps its "?" mark; the word goes (the summary's title stays its accessible name). */
  .one-help-label { display: none; }
  .one-persona-panel { width: min(320px, calc(100vw - var(--one-space-12))); }

  /* The launcher's doors stack; the footer row unstacks into two lines. */
  .one-door-grid { grid-template-columns: 1fr; }
  .one-launcher-foot { align-items: flex-start; }

  .one-chat { flex-direction: column; }

  /* ---- The chat drawer (mobile-layout audit §7) ---------------------------
     The old stack-only rule (sidebar width:100%) put the FULL-HEIGHT sidebar
     above the chat inside the .one-body--chat viewport lock (one.css "Scroll
     containment") — main was squeezed to a sliver and the composer was clipped
     unreachable. Fix: the sidebar hides by default so MAIN owns the locked
     column (the lock now PINS the composer instead of clipping it); the
     sidebar opens as a bounded overlay drawer with its own scroll. */
  .phasma-query-ng-sidebar { display: none; }
  .phasma-query-ng-sidebar.is-open {
    display: flex;
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 35;
    width: min(320px, 85vw);
    background: var(--one-canvas);
    border-right: 1px solid var(--one-line);
    padding: var(--one-space-8) var(--one-space-6);
    overflow-y: auto; /* bounded height → the conversation list finally scrolls */
    box-shadow: var(--one-shadow-card);
  }
  .one-drawer-backdrop.is-open {
    display: block;
    position: fixed; inset: 0; z-index: 30; /* under the drawer (35) + modals (40) */
    background: rgba(15, 18, 20, 0.45);
  }
  .one-chat-mobilebar {
    display: flex; align-items: center; gap: var(--one-space-4);
    padding: 0 var(--one-space-2) var(--one-space-4);
  }
  .one-drawer-toggle,
  .one-options-toggle {
    font: inherit; font-size: var(--one-text-sm); font-weight: var(--one-weight-medium);
    padding: 6px var(--one-space-6);
    border: 1px solid var(--one-line); border-radius: var(--one-radius-xs);
    background: var(--one-card); color: var(--one-text); cursor: pointer;
  }
  .one-drawer-toggle:hover,
  .one-options-toggle:hover { background: var(--one-sunken); }
  .one-drawer-toggle[aria-expanded='true'],
  .one-options-toggle[aria-expanded='true'] { background: var(--one-sunken); }
  .one-mobile-speaker { margin-left: auto; } /* the mode toggle sits at the bar's right edge */

  /* ---- Pass 2: settings disclosure (Options) ------------------------------
     The Text-size row + workspace/model toolbar leave the flow by default —
     the message log gets their vertical space — and reveal unchanged behind
     the Options toggle. `:not([hidden])` preserves the toolbar's
     usable-or-absent rule (an empty toolbar stays hidden even when open). */
  .one-chat-fontbar { display: none; }
  .one-chat-toolbar { display: none; }
  .one-chat.one-options-open .one-chat-fontbar { display: flex; }
  .one-chat.one-options-open .one-chat-toolbar:not([hidden]) { display: flex; }

  /* ---- Pass 2: composer economy (the ~35-char text-entry bar) -------------
     At 380px the row is [+][textarea][mic][send] — attach + image hide behind
     the "+" disclosure; the composer's SPEAKER copy hides (the mode toggle
     moved to the head bar above). Spacing/button compression here is
     PLACEMENT-REQUIRED width economy (380 − page/composer chrome − 3×32px
     buttons − gaps ≈ 254px ≈ 35ch) — the Design pass owns final aesthetics. */
  .one-composer-plus {
    display: flex; flex: none; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 50%;
    border: 1px solid var(--one-line); background: var(--one-card);
    color: var(--one-text-muted); cursor: pointer;
    font: inherit; font-size: var(--one-text-md); line-height: 1;
  }
  .one-composer-plus[aria-expanded='true'] { background: var(--one-sunken); }
  .phasma-query-ng-composer .phasma-query-ng-attach,
  .phasma-query-ng-composer .phasma-query-ng-camera { display: none; }
  .phasma-query-ng-composer.is-plus-open .phasma-query-ng-attach,
  .phasma-query-ng-composer.is-plus-open .phasma-query-ng-camera { display: flex; }
  .phasma-query-ng-composer > .phasma-query-ng-speaker { display: none; }
  .one-body--chat .one-main { padding-left: var(--one-space-2); padding-right: var(--one-space-2); }
  .phasma-query-ng-composer { gap: var(--one-space-2); padding: var(--one-space-2); }
  .phasma-query-ng-composer .phasma-query-ng-attach,
  .phasma-query-ng-composer .phasma-query-ng-camera,
  .phasma-query-ng-composer .phasma-query-ng-mic,
  .phasma-query-ng-composer .phasma-query-ng-send,
  .phasma-query-ng-composer .phasma-query-ng-speaker { width: 32px; height: 32px; }

  /* ---- Shell header at phone widths (mobile-layout audit §3) --------------
     The wrap-to-two-rows rule this replaces existed because the header carried
     every plane link as a chip and overflowed the right edge. The nav redesign
     removed the cause: the links live in the drawer now, so the bar is back to
     brand + burger + persona and stays ONE fixed-height row. Truncation of the
     persona label is still needed and still here. */
  .one-header-user {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    max-width: 45vw;
  }

  .one-shell { flex-direction: column; }
  .one-rail { width: 100%; border-right: none; border-bottom: 1px solid var(--one-line); }
}

/* ==== Carry-forward: surfaces added AFTER the v0.4 design pass (C1/C2) ======
 * The design pass predates the C1 model-config note, the C2 upload "system"
 * bubble, and the capture-modal input fields + elicitation freeform field.
 * These small rules keep those surfaces styled and inherit every token above
 * (nothing here re-defines a class the design pass already styles). When a
 * future design pass covers them, delete this block. */

/* the transient "Uploading …" / system bubble */
.phasma-query-ng-system {
  align-self: flex-start; color: var(--one-text-muted); font-style: italic;
  background: var(--one-tile); border: 1px solid var(--one-line);
}

/* capture-to-Business-State modal — the panel/title/done are designed; these
 * are its form fields + action row */
.phasma-capture-panel label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: var(--one-text-2xs); font-weight: var(--one-weight-semibold);
  text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-text-faint);
}
.phasma-capture-kind, .phasma-capture-statement, .phasma-capture-tags, .phasma-capture-review-after {
  font: inherit; font-size: var(--one-text-base); text-transform: none; letter-spacing: 0;
  color: var(--one-text); padding: var(--one-space-4);
  border: 1px solid var(--one-field-border); border-radius: var(--one-radius-xs); background: var(--one-card);
}
.phasma-capture-kind:focus, .phasma-capture-statement:focus, .phasma-capture-tags:focus, .phasma-capture-review-after:focus {
  outline: none; border-color: var(--one-primary); box-shadow: var(--one-ring);
}
.phasma-capture-actions { display: flex; gap: var(--one-space-6); justify-content: flex-end; }
.phasma-capture-message { font-size: var(--one-text-sm); color: var(--one-text-muted); min-height: 18px; }
.phasma-capture-message.error { color: var(--one-danger); }
.phasma-capture-row { display: flex; }

/* elicitation freeform field (the chips are designed; this is the "type your
 * own" input beside them) */
.phasma-elicit-freeform { display: flex; gap: var(--one-space-4); margin-top: var(--one-space-4); }
.phasma-elicit-input {
  flex: 1; font: inherit; font-size: var(--one-text-sm);
  padding: 6px var(--one-space-6); border: 1px solid var(--one-field-border);
  border-radius: var(--one-radius-xs); background: var(--one-card); color: var(--one-text);
}
.phasma-elicit-input:focus { outline: none; border-color: var(--one-primary); box-shadow: var(--one-ring); }
.phasma-elicit-freeform-go {
  font: inherit; font-size: var(--one-text-sm); font-weight: var(--one-weight-medium);
  padding: 6px var(--one-space-7); border: 1px solid var(--one-field-border);
  border-radius: var(--one-radius-xs); background: var(--one-card); color: var(--one-text-muted); cursor: pointer;
}
.phasma-elicit-freeform-go:hover { background: var(--one-sunken); color: var(--one-text); }

/* ==== Manage-workspaces modal — live-editor affordances =====================
 * The static board mockup shows configured state only; the live editor adds a
 * few controls (a chip remove ×, an add-module row, a prompt textarea). These
 * translate the board's inline-styled bits into classes (CSP forbids inline
 * style) and inherit the board's tokens. */
.one-cap-chip { display: inline-flex; align-items: center; gap: var(--one-space-4); }
.one-cap-chip.is-empty { font-style: italic; }
.one-cap-chip-remove {
  border: none; background: none; cursor: pointer; padding: 0; line-height: 1;
  color: var(--one-text-fainter); font-size: var(--one-text-sm);
}
.one-cap-chip-remove:hover { color: var(--one-text); }
.one-ws-addrow { display: flex; gap: var(--one-space-6); align-items: center; flex-wrap: wrap; }
.one-textarea { width: 100%; min-height: 68px; resize: vertical; font-family: inherit; }

/* ==== [hidden] honored (root-cause fix) =====================================
 * The design sheet sets display:flex/inline-flex on toolbar groups and the
 * attach chip, which OVERRODE the [hidden] attribute — leaving empty selects
 * and the chip floating. Make the semantic hidden attribute win everywhere;
 * the island toggles [hidden] to show/absent per the render rules. */
[hidden] { display: none !important; }

/* ---- G2.1 carry-forward: functional table grammar (gateway plane) --------
   Minimal + token-only (no new design): the cyan views' tables
   (.one-table) fill the card with scannable row heights and the existing
   hairlines. The nested variant is a seat's expandable capability panel. */
.one-table { width: 100%; border-collapse: collapse; font-size: var(--one-text-sm); }
.one-table th, .one-table td { text-align: left; vertical-align: top; padding: 8px 12px; border-bottom: 1px solid var(--one-line-soft); }
.one-table thead th { border-bottom: 1px solid var(--one-line); }
.one-table tr:last-child > td,
.one-table tr:last-child > th { border-bottom: 0; }  /* a row-header column kept its rule (2026-10-12 walk) */
.one-gw-panel-row > td { padding: 0 12px 10px; }
.one-gw-panel-row summary { cursor: pointer; }
/* The capability panel is a tight two-column list — each capability's control
   (☐ Grant, or ✓ Granted + Revoke) sits in the SAME slot directly beside its
   name; width:auto beats the base width:100% so the table shrink-wraps
   instead of stranding controls at the card's far edge. */
.one-table--nested { width: auto; max-width: 560px; margin-top: 4px; }
.one-table--nested td { padding: 6px 0; vertical-align: baseline; }
.one-table--nested td.one-cap-name { padding-right: 24px; }
.one-cap-name .one-persona-meta--warn { display: block; max-width: 34ch; }
.one-gw-cap-ctl { white-space: nowrap; }
.one-gw-cap-ctl form { display: inline-block; }
.one-gw-cap-held { margin-right: 8px; }

/* ---- O-3: a wide table scrolls ITSELF, never the shell ---------------------
   The WP channel pane grew to ten columns when the site telemetry landed, and
   there was no responsive idiom in this sheet for a table that outgrows its
   card — only the two `max-width: 760px` blocks. Wrap the table and the
   overflow stays inside the card: the page body never gains a horizontal
   scrollbar (which moves the nav and the header out from under the reader's
   thumb), and the columns keep their readable widths instead of being crushed
   into two-character wraps. `max-width: 100%` is what actually arms it — a
   grid/flex child's default `min-width: auto` would otherwise let the table
   push the card wider than the viewport before `overflow-x` ever applies. */
.one-table-scroll { overflow-x: auto; max-width: 100%; }

/* ---- W3.1: a multisite subsite sits UNDER its network ----------------------
   Token-only, and deliberately two signals rather than one: the indent alone
   reads as a rendering accident on a table that already wraps, and the sunken
   ground alone reads as a disabled row. Together they say "this belongs to the
   row above". The left border is the spine the indent hangs off; it uses the
   same hairline every other grouping in this sheet does, so nothing new is
   being introduced visually — only a relationship being drawn. */
.one-wp-row--subsite > td { background: var(--one-sunken); }
.one-wp-row--subsite > td:first-child {
  padding-left: 32px;
  border-left: 3px solid var(--one-line);
}

/* ---- The generated-image GALLERY (T-IMG3) — seat /images + cyan /gateway/images -
   One card, one responsive grid, token-only (no design pass): the same hairlines,
   badges and .one-btn set every other seat-data surface uses. The image is the row's
   subject, so it leads; the prompt is its caption and stays readable at 60ch. */
.one-gallery {
  list-style: none; margin: var(--one-space-6) 0 0; padding: 0;
  display: grid; gap: var(--one-space-6);
  /* auto-fill, not auto-fit: a single image keeps its natural column width instead of
     stretching across the whole card like a hero it is not. */
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.one-gallery-item {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px; border: 1px solid var(--one-line-soft); border-radius: var(--one-radius-lg);
  background: var(--one-tile);
}
.one-gallery-image {
  display: block; width: 100%; height: auto;
  /* A fixed box so a slow or refused image never reflows the grid under the reader,
     and so tall/wide/square images sit in one tidy row rather than a ragged one. */
  aspect-ratio: 1 / 1; object-fit: cover;
  border: 1px solid var(--one-line); border-radius: var(--one-radius-sm);
  background: var(--one-surface-2);
}
.one-gallery-noimage {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1 / 1; margin: 0;
  border: 1px dashed var(--one-line); border-radius: var(--one-radius-sm);
  text-align: center;
}
.one-gallery-prompt {
  margin: 0; max-width: 60ch; color: var(--one-text);
  font-size: var(--one-text-sm); overflow-wrap: anywhere;
}
.one-gallery-meta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 0;
  color: var(--one-text-faint); font-size: var(--one-text-2xs);
}
.one-gallery-badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--one-line); background: var(--one-tile);
  color: var(--one-text-muted); font-size: var(--one-text-2xs);
  letter-spacing: var(--one-tracking-kpi); text-transform: uppercase;
}
.one-gallery-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-top: auto; }
.one-gallery-inline { display: inline-block; }
/* Text-action verbs, matching the wisps row grammar rather than adding new chrome. */
.one-gallery-actions .one-btn {
  border: 0; background: transparent; padding: 4px 0;
  color: var(--one-primary-dark); font-size: var(--one-text-sm); cursor: pointer;
}
.one-gallery-actions .one-btn:hover { text-decoration: underline; }

/* ---- Generated VIDEOS (T-VID3) — the /videos pages reuse the gallery grid; the chat answer
   embeds a door link as a player (markdown.js embedVideos). Token-only. A clip is wide by
   default, so its box is 16:9 and `contain` keeps a tall or square clip whole inside it. */
.one-gallery-video {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: contain;
  border: 1px solid var(--one-line); border-radius: var(--one-radius-sm);
  background: var(--one-surface-2);
}
.one-video { margin: var(--one-space-4) 0; max-width: 100%; }
.one-video video {
  display: block; width: 100%; max-width: 640px; height: auto;
  border: 1px solid var(--one-line); border-radius: var(--one-radius-sm);
  background: var(--one-surface-2);
}
.one-video-download { display: inline-block; margin-top: var(--one-space-2); font-size: var(--one-text-sm); }

/* ---- Seat plane S1: the Wisps page (memory surface) ----------------------
   Server-rendered list + <details> action panels, token-only (no design
   pass): existing hairlines, badges in the plane-badge grammar, buttons from
   the shared .one-btn set. Statements are the readable heart of each row. */
.one-wisps-tabs { display: flex; gap: var(--one-space-4); margin: var(--one-space-6) 0; }
.one-wisps { list-style: none; margin: 0; padding: 0; }
.one-wisp { padding: 12px 0; border-bottom: 1px solid var(--one-line-soft); }
.one-wisp:last-child { border-bottom: 0; }
.one-wisp-statement { margin: 0 0 6px; max-width: 90ch; }
.one-wisp-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; margin: 0 0 6px; color: var(--one-text-faint); font-size: var(--one-text-sm); }
.one-wisp-badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--one-line); background: var(--one-tile);
  color: var(--one-text-muted); font-size: var(--one-text-2xs);
  letter-spacing: var(--one-tracking-kpi); text-transform: uppercase;
}
/* A "worked out" wisp is an inference the platform derived, not something anyone said.
   It carries a left rule + a filled badge so it is distinguishable at a GLANCE from a
   remembered fact — the human deciding whether the reasoning holds has to spot it before
   they read it, not after. The derivation sits inline, indented under the claim, because
   the judgement is worthless without the sources in the same eyeful. */
.one-wisp--worked-out { border-left: 2px solid var(--one-wisp-bg); padding-left: 12px; }
.one-wisp-badge--worked-out {
  background: var(--one-wisp-bg); color: var(--one-violet-dark);
  border-color: var(--one-wisp-bg); font-weight: 600;
}
.one-wisp-derivation { margin: 0 0 8px; padding-left: 12px; border-left: 1px dashed var(--one-line); }
.one-wisp-derivation-lead {
  margin: 0 0 4px; color: var(--one-text-faint); font-size: var(--one-text-sm);
}
.one-wisp-derivation-list {
  list-style: disc; margin: 0; padding-left: 18px;
  color: var(--one-text-muted); font-size: var(--one-text-sm); max-width: 80ch;
}
.one-wisp-derivation-list li { margin: 0 0 2px; }
.one-wisp-keeper { color: var(--one-text-muted); max-width: 70ch; }
.one-wisp-actions { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 14px; }
.one-wisp-inline { display: inline-block; }
/* Inline verb buttons read like the panel summaries — one consistent row of
   text actions, not a mix of chrome (functional consistency, no design pass). */
.one-wisp-inline .one-btn {
  border: 0; background: transparent; padding: 4px 0;
  color: var(--one-primary-dark); font-size: var(--one-text-sm); cursor: pointer;
}
.one-wisp-inline .one-btn:hover { text-decoration: underline; }
.one-wisp-panel > summary { cursor: pointer; color: var(--one-primary-dark); font-size: var(--one-text-sm); padding: 4px 0; }
.one-wisp-panel[open] {
  flex-basis: 100%; padding: 10px 12px; margin-top: 4px;
  background: var(--one-tile); border: 1px solid var(--one-line-soft); border-radius: 8px;
}
.one-wisp-panel form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-top: 8px; }
.one-wisp-panel textarea { width: 100%; max-width: 70ch; font: inherit; padding: 6px 8px; border: 1px solid var(--one-field-border); border-radius: 6px; }
.one-wisp-panel label { display: block; font-size: var(--one-text-sm); color: var(--one-text-muted); }
.one-wisp-panel input[type="text"] { display: block; margin-top: 4px; min-width: 260px; font: inherit; padding: 5px 8px; border: 1px solid var(--one-field-border); border-radius: 6px; }
.one-wisp-panel select { font: inherit; padding: 5px 8px; border: 1px solid var(--one-field-border); border-radius: 6px; }
.one-wisp-check { display: flex; align-items: center; gap: 6px; }
.one-wisp-panel--danger > summary { color: var(--one-danger); }
.one-wisp-preview { margin: 8px 0 0; max-width: 70ch; color: var(--one-text-muted); font-size: var(--one-text-sm); }

/* ---- Seat plane S2: the seat-settings page (custom prompt) ---------------- */
.one-seat-prompt { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-top: var(--one-space-6); }
.one-seat-prompt label { font-weight: var(--one-weight-semibold); }
.one-seat-prompt textarea { width: 100%; max-width: 68ch; font: inherit; padding: 8px 10px; border: 1px solid var(--one-field-border); border-radius: 6px; }
.one-seat-prompt .one-prompt-count, .one-seat-prompt .one-prompt-note { margin: 0; max-width: 68ch; }
.one-prompt-count { font-variant-numeric: tabular-nums; }
.one-prompt-count--near { color: var(--one-warn-text); }
.one-prompt-count--over { color: var(--one-danger); font-weight: var(--one-weight-semibold); }
.one-seat-prompt textarea[aria-invalid="true"] { border-color: var(--one-danger); }

/* ---- Seat specialists: the built-in prompt presets (seat-personas.md) -----
   Token-only, server-rendered, no JS. The picker sits ABOVE the editor it fills
   because that is the reading order of the act: choose, then read, then save. */
.one-specialists { margin-top: var(--one-space-6); }
.one-specialists-title { font-size: var(--one-text-md); font-weight: var(--one-weight-semibold); margin: 0 0 var(--one-space-2); }
.one-specialists-list { list-style: none; margin: var(--one-space-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--one-space-2); }
.one-specialist { border: 1px solid var(--one-line-soft); border-radius: var(--one-radius-sm); padding: var(--one-space-2); }
.one-specialist--applied { border-color: var(--one-accent-soft); }
.one-specialist-head { display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-2); }
.one-specialist-head form { margin: 0; }
.one-specialist p { margin: var(--one-space-4) 0 0; }
.one-specialist details { margin-top: var(--one-space-2); }
.one-specialist pre { white-space: pre-wrap; max-width: 68ch; }

/* ---- Seat plane S3: the seat Knowledge Bases page ------------------------
   Server-rendered list + <details> panels, token-only — the wisps grammar
   applied to the seat's own KBs and their documents. */
.one-seatkbs, .one-seatkb-docs { list-style: none; margin: 0; padding: 0; }
.one-seatkb { padding: 12px 0; border-bottom: 1px solid var(--one-line-soft); }
.one-seatkb:last-child { border-bottom: 0; }
.one-seatkb--selected { background: var(--one-primary-tint); margin: 0 -12px; padding: 12px; border-radius: 8px; }
.one-seatkb-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; margin: 0 0 6px; }
.one-seatkb-name { font-weight: var(--one-weight-semibold); color: var(--one-primary-dark); text-decoration: none; }
.one-seatkb-name:hover { text-decoration: underline; }
.one-seatkb-actions { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 14px; }
.one-seatkb-doc { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; padding: 8px 0; border-bottom: 1px solid var(--one-line-soft); }
.one-seatkb-doc:last-child { border-bottom: 0; }
.one-seatkb-doc-title { font-weight: var(--one-weight-medium); }
.one-seatkb-panel > summary { cursor: pointer; color: var(--one-primary-dark); font-size: var(--one-text-sm); padding: 4px 0; }
.one-seatkb-panel--danger > summary { color: var(--one-danger); }
.one-seatkb-panel[open] {
  flex-basis: 100%; padding: 10px 12px; margin-top: 4px;
  background: var(--one-tile); border: 1px solid var(--one-line-soft); border-radius: 8px;
}
.one-seatkb-panel form, .one-seatkb-ingest { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin-top: 8px; }
.one-seatkb-panel label, .one-seatkb-ingest label { display: block; font-size: var(--one-text-sm); color: var(--one-text-muted); width: 100%; max-width: 68ch; }
.one-seatkb-panel input[type="text"], .one-seatkb-ingest input[type="text"] { display: block; margin-top: 4px; width: 100%; max-width: 48ch; font: inherit; padding: 5px 8px; border: 1px solid var(--one-field-border); border-radius: 6px; }
.one-seatkb-ingest textarea { display: block; margin-top: 4px; width: 100%; max-width: 68ch; font: inherit; padding: 6px 8px; border: 1px solid var(--one-field-border); border-radius: 6px; }
.one-seatkb-ingest input[type="file"] { display: block; margin-top: 4px; font: inherit; }
.one-seatkb-ingest h3 { margin: 8px 0 0; font-size: var(--one-text-md); }

/* ---- Hands-free loop v1 (voice-loop.md §3, island chat) --------------------
   The toggle mirrors the composer icon-button family (camera/mic/speaker) and
   the speaker's two-copy pattern: composer copy on desktop, head-bar copy at
   ≤760px. The indicator is the mic light — visible in EVERY non-idle state,
   naming the §3 state (armed / capturing / transcribing / querying /
   speaking); `capturing` pulses like the dictation mic. */
.phasma-query-ng-handsfree {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--one-text-faint); cursor: pointer;
  transition: background var(--one-dur-fast) ease, color var(--one-dur-fast) ease;
}
.phasma-query-ng-handsfree:hover { background: var(--one-sunken); color: var(--one-text-muted); }
.phasma-query-ng-handsfree.is-on { color: var(--one-primary-dark); background: var(--one-primary-tint); }
.one-handsfree-indicator {
  align-self: flex-start;
  margin: 0 0 var(--one-space-2);
  padding: 3px var(--one-space-6);
  border-radius: var(--one-radius-pill);
  font-size: var(--one-text-2xs);
  font-weight: var(--one-weight-medium);
  letter-spacing: var(--one-tracking-kpi);
  text-transform: uppercase;
  background: var(--one-primary-tint); color: var(--one-primary-dark);
  border: 1px solid var(--one-line);
}
.one-handsfree-indicator[data-state='capturing'] { background: var(--one-danger); color: var(--one-text-invert); border-color: var(--one-danger); animation: one-pulse-rec 1.4s ease-in-out infinite; }
.one-handsfree-indicator[data-state='speaking'] { background: var(--one-primary); color: var(--one-text-invert); border-color: var(--one-primary); }
@media (max-width: 760px) {
  /* Like the speaker: the composer copy yields to the head-bar copy (the
     mobile row stays [+][textarea][mic][send] — no width regression). */
  .phasma-query-ng-composer > .phasma-query-ng-handsfree { display: none; }
}

/* ── Help panel (capability-docs H-2) ──────────────────────────────────────
   A server-rendered <details> in the global header — no JS, so it needs no
   bundle and satisfies the strict CSP (script-src 'self', no inline). The body
   is absolutely positioned so opening it overlays the page instead of shoving
   the header's layout around. */
.one-help { margin-left: auto; position: relative; }
.one-help-summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  list-style: none;
  color: var(--one-text-invert-dim);
  font-size: var(--one-text-sm);
}
.one-help-summary::-webkit-details-marker { display: none; }
.one-help-summary:hover { color: var(--one-text-invert); }
.one-help-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 11px;
  line-height: 1;
  /* C-1: the `?` and the smile are stacked in this box and cross-faded, so the mark
     keeps its footprint and the header never reflows when the smile arrives. */
  position: relative;
}
.one-help-mark-glyph,
.one-help-mark-smile {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 420ms ease;
}
.one-help-mark-smile { width: 100%; height: 100%; padding: 2px; opacity: 0; }
.one-help[data-cheshire="smiling"] .one-help-mark-glyph { opacity: 0; }
.one-help[data-cheshire="smiling"] .one-help-mark-smile { opacity: 1; }
/* A SLOW pulse — it is an invitation, not an alarm. The mark is in the header of every
   page, so anything faster reads as an error badge and earns itself dismissed. */
.one-help[data-cheshire="smiling"] .one-help-mark {
  animation: one-cheshire-pulse 3.2s ease-in-out infinite;
}
@keyframes one-cheshire-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(124, 58, 237, 0); }
  50%      { box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.28); }
}
/* An animated invitation is exactly what a motion-sensitive user asked not to receive.
   The smile still appears — only the pulse and the cross-fade stop. */
@media (prefers-reduced-motion: reduce) {
  .one-help-mark-glyph,
  .one-help-mark-smile { transition: none; }
  .one-help[data-cheshire="smiling"] .one-help-mark { animation: none; }
}
.one-help-body {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 40;
  width: min(420px, calc(100vw - 32px));
  max-height: min(70vh, 640px);
  overflow-y: auto;
  padding: var(--one-space-6);
  background: var(--one-card);
  color: var(--one-text);
  border: 1px solid var(--one-line);
  border-radius: 8px;
  box-shadow: 0 8px 28px rgb(0 0 0 / 18%);
  text-align: left;
}
.one-help-heading {
  margin: var(--one-space-6) 0 var(--one-space-4);
  font-size: var(--one-text-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--one-text-muted);
}
.one-help-heading:first-child { margin-top: 0; }
.one-help-entry { margin-bottom: var(--one-space-6); }
.one-help-name { margin: 0 0 4px; font-size: var(--one-text-base); }
.one-help-badge {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 10px;
  background: var(--one-accent-soft, rgb(0 0 0 / 6%));
  color: var(--one-text-muted);
  font-size: 11px;
  font-weight: 400;
}
.one-help-entry p { margin: 0 0 4px; font-size: var(--one-text-sm); line-height: 1.45; }
.one-help-where, .one-help-why { color: var(--one-text-muted); }
.one-help-example { color: var(--one-text-muted); }
.one-help-gap, .one-help-empty { color: var(--one-text-muted); font-size: var(--one-text-sm); }

/* Migration upload (v0.77.0): a progress element wide enough to read a 292 MB
   upload against, and a status line that carries its own tone. */
.one-upload { margin: 0 0 18px; }
.one-upload__bar { width: 100%; max-width: 640px; height: 14px; }
.one-upload__status[data-tone="error"] { color: var(--one-danger); }
.one-upload__status[data-tone="warn"] { color: var(--one-warn); }
.one-upload__status[data-tone="ok"] { color: var(--one-success); }
.one-upload[data-upload-done] { opacity: .8; }

/* A block of literal text a human copies — a curl command, a captured payload. Used in
   three templates since v0.77.0 and defined in NO stylesheet until now (F11.5, counted in
   TemplateContractTest's phantom-class debt): the markup asked for a code block and got
   default UA styling that overflowed its card, because a presigned URL is one unbreakable
   ~700-character word. Scrolling is the fix that keeps the text COPYABLE — wrapping a
   signed URL mid-token is how a pasted command silently fails. */
.one-pre {
  margin: var(--one-space-4) 0 0;
  padding: var(--one-space-6);
  background: var(--one-sunken);
  border: 1px solid var(--one-line);
  border-radius: var(--one-radius-sm);
  font-family: var(--one-font-mono);
  font-size: var(--one-text-sm);
  line-height: 1.5;
  overflow-x: auto;
}

/* Seat Versions → Compare (0.142.0): a line diff of two prompt versions. */
.one-pre--wrap { white-space: pre-wrap; word-break: break-word; }
.one-diff { border: 1px solid var(--one-line); border-radius: var(--one-radius-sm); font-family: var(--one-font-mono); font-size: var(--one-text-sm); line-height: 1.5; overflow-x: auto; }
.one-diff-line { padding: 2px var(--one-space-4); white-space: pre-wrap; word-break: break-word; }
.one-diff-line--add { background: var(--one-ok-bg); color: var(--one-ok-text); }
.one-diff-line--del { background: var(--one-danger-tint); color: var(--one-danger); text-decoration: line-through; }
.one-diff-mark { display: inline-block; width: 1.5em; user-select: none; font-weight: var(--one-weight-medium); }
.one-diff-key { display: inline-block; padding: 0 var(--one-space-4); border-radius: var(--one-radius-xs); margin-right: var(--one-space-4); }
.one-diff-key--add { background: var(--one-ok-bg); color: var(--one-ok-text); }
.one-diff-key--del { background: var(--one-danger-tint); color: var(--one-danger); }

/* --- consistency-sweep utilities (docs/ui-rules.md §1) — the closed set the retired
   inline styles mapped to. Additions are KIT changes: CSS here + the inventory row in
   the rules doc, same commit. ------------------------------------------------------ */
.one-inline { display: inline; }
.one-inline-block { display: inline-block; }
.one-inline-block + .one-inline-block { margin-left: var(--one-space-4); }
.one-report-box { white-space: pre-wrap; max-height: 320px; overflow-y: auto; }
/* The RENDERED report (0.105.0): `island/report.js` replaces the escaped <pre> above with
   this once marked → DOMPurify has succeeded. Same height budget and same scroll as the
   fallback it replaces, so upgrading does not move the page under the reader. */
.one-report { max-height: 320px; overflow-y: auto; max-width: 74ch; }
.one-report > :first-child { margin-top: 0; }
.one-report > :last-child { margin-bottom: 0; }
.one-report h1, .one-report h2, .one-report h3 { font-size: var(--one-text-md); font-weight: var(--one-weight-semibold); margin: var(--one-space-6) 0 var(--one-space-2); }
.one-report p, .one-report ul, .one-report ol { margin: 0 0 var(--one-space-4); }
.one-report ul, .one-report ol { padding-left: var(--one-space-8); }
.one-report li { margin: 0 0 var(--one-space-2); }
.one-report code { font-size: var(--one-text-sm); }
.one-report pre { white-space: pre-wrap; overflow-x: auto; }
.one-report table { border-collapse: collapse; width: 100%; font-size: var(--one-text-sm); }
.one-report th, .one-report td { border: 1px solid var(--one-line-soft); padding: var(--one-space-2) var(--one-space-4); text-align: left; }
.one-report blockquote { margin: 0 0 var(--one-space-4); padding-left: var(--one-space-6); border-left: 2px solid var(--one-line-soft); color: var(--one-text-muted); }
.one-thumb { max-width: 120px; max-height: 120px; border: 1px solid var(--one-line); }
.one-stack { margin-top: var(--one-space-6); }
.one-input--medium { max-width: 260px; }

/* ==== Design two-pane (T-DS4) ============================================ */

/* The design surface gets real width: preview + inspector side by side. */
.one-body--designpane .one-main { max-width: 1520px; }

/* The split component: preview pane (fluid) beside the dial inspector (fixed
   rail), collapsing to a stack under the pane's own useful minimum. */
.one-designpane { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--one-space-7); margin-top: var(--one-space-7); }
.one-designpane__preview { min-width: 0; }
.one-designpane__frame { width: 100%; height: 78vh; border: 1px solid var(--one-line); border-radius: var(--one-radius-xs); background: var(--one-card); }
.one-designpane__inspector { min-width: 0; }
@media (max-width: 920px) {
  .one-designpane { grid-template-columns: 1fr; }
  .one-designpane__frame { height: 60vh; }
}

/* The color dial: a swatch box, not a text field — the browser paints the value. */
.one-input--color { padding: 2px; height: 40px; max-width: 128px; cursor: pointer; }

/* Dial rows: the customised marker + the read-only (never-editable) value. */
.one-dial-mark { color: var(--one-primary); }
.one-dial-readonly { font-family: var(--one-font-mono); overflow-wrap: anywhere; }
.one-dial-status { min-height: 1.2em; color: var(--one-text-muted); }
.one-dial-status--error { color: var(--one-warn-text); }

/* phasma-code T7 — the pairing code on the Devices approval card (DD-4). Large on purpose: the
   person matches it against their own terminal at a glance, and that match is the anti-phishing
   step. Token-only. */
.one-pair-code {
  margin: var(--one-space-6) 0; padding: var(--one-space-6) var(--one-space-7);
  font-family: var(--one-font-mono); font-size: calc(var(--one-text-xl) * 2);
  font-weight: var(--one-weight-semibold); letter-spacing: 0.18em; text-align: center;
  background: var(--one-tile); border: 1px dashed var(--one-line); border-radius: var(--one-radius-sm);
  overflow-wrap: anywhere;
}

/* W11′ — the proposal inbox's word diff (src/Support/WordDiff.php): removed words struck
   through on the danger tint, added words on the success tint. */
.one-word-diff { white-space: normal; }
.one-word-diff del { text-decoration: line-through; background: var(--one-danger-tint); color: var(--one-danger); }
.one-word-diff ins { text-decoration: none; background: var(--one-success-soft); color: var(--one-success-strong); }
/* vNEXT (platform T-BS1) — a byte-safe edit's exact replacements, one per line, page context kept as typed. */
.one-replacements { list-style: none; margin: 0 0 var(--one-space-6); padding: 0; display: grid; gap: 6px; }
.one-replacements li { white-space: pre-wrap; overflow-wrap: anywhere; }

/* 0.152.0 — the no-payment-method banner: the top of every billing page until a card is on file. */
.one-pm-banner {
  display: flex; align-items: center; justify-content: space-between; gap: var(--one-space-8); flex-wrap: wrap;
  margin: 0 0 var(--one-space-8); padding: var(--one-space-8) var(--one-space-10);
  border: 2px solid var(--one-warn-border); border-radius: var(--one-radius-lg);
  background: var(--one-warn-bg); color: var(--one-warn-text);
}
.one-pm-banner__text { flex: 1 1 320px; }
.one-pm-banner__title { margin: 0 0 var(--one-space-2); font-size: var(--one-text-xl); font-weight: var(--one-weight-semibold); color: inherit; }
.one-pm-banner p { margin: 0; }
.one-pm-banner__cta { white-space: nowrap; }

/* ==== One Analytics viewing pages (0.157.0, T-AX2 — docs/design/one-analytics.md §5) =========
   The operator plane's first charts. KPI tiles reuse the card grammar (white, 1 px line, 8 px radius,
   11 px uppercase label); the marks themselves are drawn by /assets/ax-view.js onto <canvas>. Shading
   is by class, never an inline style — the CSP forbids inline styles. */
.one-ax-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--one-space-6); margin: 0 0 var(--one-space-8); }
.one-ax-tabs { display: flex; flex-wrap: wrap; gap: var(--one-space-2); }
.one-ax-tabs a { padding: 6px 12px; border-radius: var(--one-radius-xs); color: var(--one-text-muted); font-size: var(--one-text-sm); font-weight: var(--one-weight-medium); }
.one-ax-tabs a:hover { background: var(--one-violet-bg); color: var(--one-violet-dark); text-decoration: none; }
.one-ax-tabs a[aria-current="page"] { background: var(--one-violet-bg); color: var(--one-violet-dark); }
.one-ax-filters { display: flex; flex-wrap: wrap; align-items: center; gap: var(--one-space-4); }
.one-ax-filters .one-input { width: auto; padding: 6px 10px; }
.one-ax-period { display: inline-flex; border: 1px solid var(--one-line); border-radius: var(--one-radius-xs); overflow: hidden; }
.one-ax-period a { padding: 6px 12px; font-size: var(--one-text-sm); color: var(--one-text-muted); border-left: 1px solid var(--one-line); }
.one-ax-period a:first-child { border-left: 0; }
.one-ax-period a[aria-current="true"] { background: var(--one-violet); color: var(--one-text-invert); }
.one-ax-period a:hover { text-decoration: none; }
.one-ax-range { color: var(--one-text-faint); font-size: var(--one-text-2xs); letter-spacing: var(--one-tracking-kpi); text-transform: uppercase; }

.one-ax-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--one-space-6); margin: 0 0 var(--one-space-8); }
.one-ax-kpi { background: var(--one-card); border: 1px solid var(--one-line); border-radius: var(--one-radius-lg); padding: var(--one-space-6) var(--one-space-7); }
.one-ax-kpi-value { margin: var(--one-space-2) 0; font-size: 26px; font-weight: var(--one-weight-semibold); font-variant-numeric: tabular-nums; letter-spacing: var(--one-tracking-tight); }
.one-ax-delta { font-size: var(--one-text-2xs); color: var(--one-text-faint); font-variant-numeric: tabular-nums; }
.one-ax-delta--up { color: var(--one-ok-text); }
.one-ax-delta--down { color: var(--one-danger); }
.one-ax-spark { display: block; width: 100%; height: 34px; margin-top: var(--one-space-4); }

.one-ax-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--one-space-8); align-items: start; }
@media (max-width: 960px) { .one-ax-grid { grid-template-columns: minmax(0, 1fr); } }
.one-ax-grid > .one-card { margin: 0; }
.one-ax-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.one-table th.one-ax-num, .one-table td.one-ax-num { text-align: right; }
.one-ax-masked { color: var(--one-text-faint); }
.one-ax-el { font-family: var(--one-font-mono); font-size: 12px; overflow-wrap: anywhere; }
.one-ax-empty { margin: 0; padding: var(--one-space-8) 0; color: var(--one-text-muted); text-align: center; }
.one-ax-note { margin: var(--one-space-4) 0 0; color: var(--one-text-faint); font-size: var(--one-text-2xs); }
.one-ax-sortable th { cursor: pointer; user-select: none; }
.one-ax-sortable th[aria-sort="ascending"]::after { content: " ▲"; font-size: 9px; }
.one-ax-sortable th[aria-sort="descending"]::after { content: " ▼"; font-size: 9px; }

.one-ax-bars { display: block; width: 100%; }
.one-ax-line { display: block; width: 100%; height: 180px; }
.one-ax-funnel { margin: 0 0 var(--one-space-10); }
.one-ax-funnel:last-child { margin-bottom: 0; }
.one-ax-funnel h3 { margin: 0 0 var(--one-space-2); font-size: var(--one-text-md); }

/* the page view: heatmap left, figures right */
.one-ax-page { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(300px, 1fr); gap: var(--one-space-8); align-items: start; }
@media (max-width: 1100px) { .one-ax-page { grid-template-columns: minmax(0, 1fr); } }
.one-ax-heat-tools { display: flex; flex-wrap: wrap; gap: var(--one-space-4); align-items: center; margin: 0 0 var(--one-space-6); }
.one-btn.one-ax-toggle { padding: 5px 12px; border: 1px solid var(--one-line); border-radius: 999px; background: var(--one-card); color: var(--one-text-muted); font: inherit; font-size: var(--one-text-sm); cursor: pointer; }
.one-btn.one-ax-toggle[aria-pressed="true"] { border-color: var(--one-violet); background: var(--one-violet-bg); color: var(--one-violet-dark); }
a.one-ax-toggle:hover { text-decoration: none; }
.one-ax-heat { position: relative; max-height: 1400px; overflow: auto; border: 1px solid var(--one-line); border-radius: var(--one-radius-xs); background: var(--one-surface-2); }
.one-ax-heat img { display: block; width: 100%; height: auto; }
.one-ax-heat canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.one-ax-heat--blank canvas { position: static; display: block; height: auto; }
.one-ax-legend { display: flex; align-items: center; gap: var(--one-space-4); margin: var(--one-space-4) 0 0; font-size: var(--one-text-2xs); color: var(--one-text-faint); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); }
.one-ax-legend i { display: inline-block; width: 18px; height: 10px; border-radius: 2px; }
.one-ax-legend .h1 { background: rgba(8, 145, 178, .35); }
.one-ax-legend .h2 { background: rgba(124, 58, 237, .55); }
.one-ax-legend .h3 { background: rgba(185, 108, 124, .65); }
.one-ax-legend .h4 { background: rgba(245, 158, 11, .75); }
.one-ax-flow { margin: 0; padding: 0; list-style: none; }
.one-ax-flow li { display: flex; justify-content: space-between; gap: var(--one-space-4); padding: 6px 0; border-bottom: 1px solid var(--one-line-soft); font-size: var(--one-text-sm); }
.one-ax-flow li:last-child { border-bottom: 0; }

/* retention: a shaded table, five steps of the violet ramp, chosen by data-shade (never an inline style) */
.one-ax-cohorts td[data-shade="1"] { background: var(--one-ax-shade-1); }
.one-ax-cohorts td[data-shade="2"] { background: var(--one-ax-shade-2); }
.one-ax-cohorts td[data-shade="3"] { background: var(--one-ax-shade-3); color: var(--one-ax-shade-ink); }
.one-ax-cohorts td[data-shade="4"] { background: var(--one-ax-shade-4); color: var(--one-text-invert); }
.one-ax-cohorts td[data-shade="5"] { background: var(--one-ax-shade-5); color: var(--one-text-invert); }
.one-section-title.one-ax-flow-gap { margin-top: var(--one-space-8); }

/* ==== Live chat (T-LC3) — the seat inbox (/chat/live) and the cyan settings page ============ */

.one-body--live .one-main { max-width: none; }
.one-live-pagehead { align-items: center; gap: var(--one-space-6); flex-wrap: wrap; }
.one-live-pagehead h1 { margin: 0; }

.one-live-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--one-space-6); margin: var(--one-space-6) 0; }
.one-live-presence { display: inline-flex; gap: var(--one-space-2); }
.one-live-notice { margin: 0 0 var(--one-space-6); }

.one-live-grid { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr) minmax(240px, 320px); gap: var(--one-space-7); align-items: start; }
@media (max-width: 1100px) { .one-live-grid { grid-template-columns: minmax(200px, 260px) minmax(0, 1fr); } .one-live-visitor { grid-column: 1 / -1; } }
@media (max-width: 760px) { .one-live-grid { grid-template-columns: minmax(0, 1fr); } }

.one-live-list { list-style: none; margin: 0 0 var(--one-space-7); padding: 0; display: flex; flex-direction: column; gap: var(--one-space-2); }
.one-live-entry { display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left; padding: var(--one-space-4) var(--one-space-5); border: 1px solid var(--one-line); border-radius: var(--one-radius-sm); background: var(--one-tile); color: var(--one-text); font: inherit; cursor: pointer; }
.one-live-entry:hover { border-color: var(--one-primary); }
.one-live-entry:focus-visible { outline: 2px solid var(--one-ray-cyan); outline-offset: 2px; }
.one-live-entry.is-selected { border-color: var(--one-primary); background: var(--one-primary-tint); }
.one-live-entry-site { font-weight: var(--one-weight-semibold); }
.one-live-entry-page { font-size: var(--one-text-sm); color: var(--one-text-muted); overflow-wrap: anywhere; }
.one-live-entry-meta { font-size: var(--one-text-2xs); }

.one-live-convo { display: flex; flex-direction: column; gap: var(--one-space-6); min-width: 0; }
.one-live-convo-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--one-space-6); }
.one-live-convo-head .one-section-title { margin: 0; overflow-wrap: anywhere; }
.one-live-actions { display: flex; flex-wrap: wrap; gap: var(--one-space-4); }
.one-live-transcript { display: flex; flex-direction: column; gap: var(--one-space-5); max-height: 60vh; min-height: 200px; overflow-y: auto; padding: var(--one-space-6); border: 1px solid var(--one-line-soft); border-radius: var(--one-radius-sm); background: var(--one-surface-2); }
.one-live-msg { max-width: 80%; padding: var(--one-space-4) var(--one-space-6); border-radius: var(--one-radius-bubble); }
.one-live-msg-who { display: block; font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-text-faint); margin-bottom: 2px; }
.one-live-msg-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.one-live-msg--user { align-self: flex-start; background: var(--one-card); border: 1px solid var(--one-line); border-bottom-left-radius: var(--one-radius-tail); }
.one-live-msg--assistant { align-self: flex-end; background: var(--one-bubble-assistant); color: var(--one-bubble-assistant-text); border-bottom-right-radius: var(--one-radius-tail); }
.one-live-msg--staff { align-self: flex-end; background: var(--one-primary-tint); border: 1px solid var(--one-primary); border-bottom-right-radius: var(--one-radius-tail); }
.one-live-msg--staff .one-live-msg-who { color: var(--one-primary-dark); }
.one-live-stream-state { margin: 0; }
.one-live-composer { display: flex; flex-direction: column; gap: var(--one-space-4); }
.one-live-input { width: 100%; box-sizing: border-box; padding: var(--one-space-4) var(--one-space-5); border: 1px solid var(--one-field-border); border-radius: var(--one-radius-xs); font: inherit; resize: vertical; }
.one-live-composer-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--one-space-4); }
.one-live-suggestion { padding: var(--one-space-4) var(--one-space-5); border: 1px dashed var(--one-primary); border-radius: var(--one-radius-sm); background: var(--one-tile); }
.one-live-suggestion p { margin: var(--one-space-2) 0; white-space: pre-wrap; }
.one-live-label { font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-text-faint); }

.one-live-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--one-space-2) var(--one-space-6); margin: 0; font-size: var(--one-text-sm); }
.one-live-facts dt { color: var(--one-text-muted); }
.one-live-facts dd { margin: 0; overflow-wrap: anywhere; }
.one-live-prior { margin: var(--one-space-4) 0 0; padding-left: var(--one-space-7); }
.one-live-lead { margin-top: var(--one-space-7); }
.one-live-field { display: flex; flex-direction: column; gap: var(--one-space-2); font-size: var(--one-text-sm); }
.one-live-field input, .one-live-field textarea { font: inherit; padding: var(--one-space-2) var(--one-space-4); border: 1px solid var(--one-field-border); border-radius: var(--one-radius-xs); }

/* the cyan settings page */
.one-live-tabs { display: flex; flex-wrap: wrap; gap: var(--one-space-4); }
.one-live-fieldset { border: 1px solid var(--one-line); border-radius: var(--one-radius-sm); padding: var(--one-space-6) var(--one-space-7); display: flex; flex-direction: column; gap: var(--one-space-4); min-width: 0; }
.one-live-fieldset legend { font-weight: var(--one-weight-semibold); padding: 0 var(--one-space-2); }
.one-live-texts input { width: 100%; box-sizing: border-box; min-width: 160px; }
.one-live-agent-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--one-space-4); }
.one-live-agent-form label { display: flex; flex-direction: column; gap: 2px; font-size: var(--one-text-sm); }
.one-live-grant-list { display: flex; flex-wrap: wrap; gap: var(--one-space-4); }
.one-live-range { flex-wrap: wrap; align-items: flex-end; gap: var(--one-space-6); }
.one-live-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--one-space-6); }
.one-live-tile { display: flex; flex-direction: column; gap: var(--one-space-2); padding: var(--one-space-6) var(--one-space-7); border: 1px solid var(--one-line); border-radius: var(--one-radius-sm); background: var(--one-tile); }
.one-live-tile-label { font-size: var(--one-text-2xs); text-transform: uppercase; letter-spacing: var(--one-tracking-kpi); color: var(--one-text-faint); }
.one-live-tile-value { font-size: var(--one-text-xl); font-weight: var(--one-weight-semibold); }
.one-live-total th, .one-live-total td { font-weight: var(--one-weight-semibold); border-top: 2px solid var(--one-line); }
.one-live-kit { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: var(--one-space-8); }
@media (max-width: 760px) { .one-live-kit { grid-template-columns: minmax(0, 1fr); } }
.one-live-kit pre { max-height: 420px; overflow: auto; }
.one-live [hidden] { display: none !important; }
