/* ══════════════════════════════════════════════════════════════════════════
   FORTCALL operator console — UBT admissions & student services desk.

   Layout and accent follow the console reference the client chose: white
   ground, #F9FAFB banding, slate ink and hairlines, and blue-600 (#2563EB) as
   the single accent — the nav highlight, the dial, the one solid button.

   UBT's own colours are rationed to the one element that matters most. Its
   heading navy (#1F2850) is the dark surface of the privacy rail, and its
   maroon (#8B263A) tints a record that is locked to this caller. Everywhere
   else stays monochrome, so the live call and the gate are the only colour in
   the room.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Surfaces */
  --ground: #FFFFFF;
  --band: #F9FAFB;
  --panel: #FFFFFF;
  --panel-2: #F9FAFB;
  --line: #E1E7EF;
  --line-soft: #EDF1F6;

  /* Ink */
  --text: #0A182E;
  --dim: #4A5568;
  /* 4.80:1 on white. The dark theme's lighter grey measured 3.12:1 here and
     was carrying the 10px eyebrows, which is exactly the text that can least
     afford it. */
  --dimmer: #64748B;

  /* The dark feature surface, used exactly as the site uses it */
  /* UBT's navy — the privacy rail's surface */
  --ink: #1F2850;
  --ink-deep: #171E3E;
  --ubt-maroon-rgb: 139 38 58;
  --on-ink: #E8EEF6;
  --sky: #7DD3FC;

  /* Accent + status, as component triplets so every tint is one source */
  --accent-rgb: 37 99 235;
  --ok-rgb: 4 120 87;      /* emerald-700 — 5.56:1 on white */
  --warn-rgb: 180 83 9;    /* amber-700  — 5.14:1 on white */
  --bad-rgb: 220 38 38;    /* red-600    — 4.97:1 on white */
  --slate-rgb: 100 116 139;

  --accent: rgb(var(--accent-rgb));
  --executed: rgb(var(--ok-rgb));
  --approval: rgb(var(--warn-rgb));
  --blocked: rgb(var(--bad-rgb));

  --ui: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* The site rounds cards at 12, large panels at 16 and controls at 8. */
  --r: 12px;
  --r-sm: 8px;
  --shadow: 0 1px 2px rgb(var(--slate-rgb) / .06), 0 1px 3px rgb(var(--slate-rgb) / .05);
  --pad: clamp(16px, 2.6vw, 34px);
}

*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: var(--ui);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r);
}

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 9px; }
::-webkit-scrollbar-thumb:hover { background: #C6CEDA; }

/* ── Type system ─────────────────────────────────────────────────────────
   Small, wide, uppercase eyebrows introduce every section, as in the
   reference console. */
.eyebrow {
  margin: 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dimmer);
}

h1 {
  margin: 6px 0 0;
  font-size: clamp(23px, 3vw, 32px);
  font-weight: 600;
  letter-spacing: -0.024em;
  line-height: 1.15;
}

.lede {
  margin: 8px 0 0;
  max-width: 62ch;
  color: var(--dim);
  font-size: 14px;
}

/* Machine register: anything the control plane itself emits — references,
   ids, tool names, verdicts, counters. */
.mono, .lock-n, .boundary-verdict, .stats dd, .tool-name,
.kb-score, .ref { font-family: var(--mono); }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  padding: 9px 17px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color .16s, background .16s, color .16s;
  white-space: nowrap;
}
.btn:hover:not(:disabled) { border-color: rgb(var(--accent-rgb) / .45); background: rgb(var(--accent-rgb) / .05); }
.btn:disabled { opacity: .38; cursor: not-allowed; }

/* The site carries exactly one filled button — "Request Technical Specs" —
   with everything else outlined. Same rule here: one solid accent per surface. */
.btn-primary {
  border-color: var(--accent);
  background: var(--accent);
  color: #FFFFFF;
  font-weight: 600;
}
.btn-primary:hover:not(:disabled) { background: #1D4ED8; border-color: #1D4ED8; }

.btn-ghost { color: var(--dim); }

/* ── Wordmark ────────────────────────────────────────────────────────────
   FORTCALL is the console's own brand. The client's mark is never used. */
.wordmark {
  display: inline-flex;
  flex-direction: column;
  line-height: 1;
  font-weight: 800;
  font-style: italic;
  font-size: 21px;
  letter-spacing: -.02em;
  color: var(--text);
  flex-shrink: 0;
  user-select: none;
}
.wordmark b { color: var(--accent); font-weight: 800; }
.wordmark small {
  font-size: 7.5px;
  font-style: normal;
  font-weight: 600;
  letter-spacing: .22em;
  color: var(--dimmer);
  margin-top: 3px;
  align-self: flex-end;
}
.wordmark-lg { font-size: 30px; margin-bottom: 8px; align-self: flex-start; }
.wordmark-lg small { font-size: 9px; }

/* ── Sign in ─────────────────────────────────────────────────────────────── */
.login {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(120% 90% at 50% -10%, rgb(var(--accent-rgb) / .07), transparent 62%),
    var(--band);
}

.login-card {
  width: min(384px, 100%);
  padding: 34px 30px 30px;
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  background: var(--panel);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.login-sub {
  margin: 12px 0 20px;
  font-size: 13px;
  color: var(--dim);
  line-height: 1.5;
}

.login-card label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dimmer);
  margin-top: 9px;
}
.login-card input {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--band);
  font-family: var(--mono);
  font-size: 13px;
}
.login-card .btn { margin-top: 20px; padding: 11px; }

.login-error {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--blocked);
}

/* ── Frame ───────────────────────────────────────────────────────────────── */
.app { min-height: 100vh; display: flex; flex-direction: column; }

.topbar {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 var(--pad);
  height: 56px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  flex-shrink: 0;
}
.topbar-desk { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.desk-name { font-size: 13px; font-weight: 600; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }

.shell { flex: 1; display: flex; min-height: 0; }

.rail {
  width: 138px;
  flex-shrink: 0;
  border-right: 1px solid var(--line);
  padding: 14px 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--band);
}
.rail-btn {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 18px;
  border: 0;
  border-left: 2px solid transparent;
  background: transparent;
  color: var(--dim);
  font-size: 13px;
  cursor: pointer;
  text-align: left;
  transition: color .15s, border-color .15s, background .15s;
}
.rail-btn:hover { color: var(--text); background: rgb(var(--accent-rgb) / .04); }
.rail-btn.is-active { color: var(--accent); border-left-color: var(--accent); background: rgb(var(--accent-rgb) / .06); }
.rail-mark { font-family: var(--mono); font-size: 12px; width: 12px; }

.stage { flex: 1; min-width: 0; overflow-y: auto; padding: var(--pad); }

.view { display: none; }
.view.is-active { display: block; animation: rise .3s ease both; }
@keyframes rise { from { opacity: 0; transform: translateY(5px); } }

.view-head { margin-bottom: 26px; }

/* ══ THE DIAL ════════════════════════════════════════════════════════════════
   One button starts the call and ends it. It is the company's name made
   literal: a ball, sending out signal. Idle, it broadcasts slow rings; while
   connecting an arc chases round it; on the line it turns red, the handset
   rotates into the hang-up position, and the halo breathes with the caller's
   own microphone level (--level, 0–1, set from the audio worklet). The orb's
   blue is the site's single accent, so the button is also the one solid
   accent on the surface. */
.dial-stage {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 48px 20px 22px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background:
    radial-gradient(70% 100% at 50% 0%, rgb(var(--accent-rgb) / .08), transparent 70%),
    var(--panel);
  box-shadow: var(--shadow);
}
/* The static rings behind the orb, centred on it (48px padding + half the
   orb), fading out towards the edges of the stage. */
.dial-stage::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 104px;
  width: 680px;
  height: 680px;
  transform: translate(-50%, -50%);
  background: repeating-radial-gradient(circle,
    transparent 0 55px, rgb(var(--accent-rgb) / .1) 55px 56px);
  -webkit-mask-image: radial-gradient(circle, #000 18%, transparent 60%);
  mask-image: radial-gradient(circle, #000 18%, transparent 60%);
  pointer-events: none;
  transition: opacity .5s;
}
.dial-stage:has(.dial[data-state="live"])::before {
  background: repeating-radial-gradient(circle,
    transparent 0 55px, rgb(var(--bad-rgb) / .09) 55px 56px);
}

.dial {
  --glow-rgb: var(--accent-rgb);
  --level: 0;
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.dial:focus-visible { outline: none; }
.dial:focus-visible .dial-orb {
  outline: 3px solid rgb(var(--glow-rgb) / .45);
  outline-offset: 7px;
}
.dial:disabled { cursor: progress; }

.dial-orb {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  width: 112px;
  height: 112px;
  border-radius: 50%;
  color: #FFFFFF;
  background: radial-gradient(circle at 34% 28%, #7AB0FF 0%, #3B82F6 30%, #2563EB 58%, #1E3A8A 100%);
  box-shadow:
    0 1px 1px rgb(15 23 42 / .10),
    0 10px 22px -6px rgb(var(--glow-rgb) / .55),
    0 30px 60px -18px rgb(var(--glow-rgb) / .50),
    inset 0 1px 0 rgb(255 255 255 / .45),
    inset 0 -12px 24px rgb(10 24 46 / .28);
  transition:
    transform .45s cubic-bezier(.34, 1.56, .64, 1),
    box-shadow .45s ease;
}
/* Gloss: a soft specular highlight in the top-left, so it reads as a sphere
   rather than a flat disc. */
.dial-orb::before {
  content: "";
  position: absolute;
  inset: 7px 18px auto 14px;
  height: 46%;
  border-radius: 50%;
  background: linear-gradient(to bottom, rgb(255 255 255 / .42), rgb(255 255 255 / 0));
  z-index: 2;
  pointer-events: none;
}
/* The live colour lives on its own layer and fades in, because gradients
   cannot transition and a hard swap from blue to red reads as a glitch. */
.dial-orb::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, #FF9B9B 0%, #EF4444 30%, #DC2626 58%, #7F1D1D 100%);
  opacity: 0;
  z-index: 1;
  transition: opacity .5s ease;
}

.dial-icon {
  position: relative;
  z-index: 3;
  width: 40px;
  height: 40px;
  filter: drop-shadow(0 1px 1.5px rgb(10 24 46 / .35));
  transition: transform .55s cubic-bezier(.34, 1.56, .64, 1);
}

.dial-ring {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 50%;
  border: 1.5px solid rgb(var(--glow-rgb) / .55);
  opacity: 0;
  animation: ripple 3.6s cubic-bezier(.2, .6, .35, 1) infinite;
}
.dial-ring:nth-child(2) { animation-delay: 1.2s; }
.dial-ring:nth-child(3) { animation-delay: 2.4s; }
/* Most of the fade happens early, so a ring is nearly gone by the time it
   reaches the label beneath the orb. */
@keyframes ripple {
  0%   { transform: scale(1);    opacity: .85; }
  55%  { transform: scale(1.6);  opacity: .22; }
  100% { transform: scale(2.15); opacity: 0; }
}

.dial-halo {
  position: absolute;
  inset: -14px;
  z-index: -2;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--glow-rgb) / .34) 30%, rgb(var(--glow-rgb) / 0) 70%);
  opacity: .55;
  transform: scale(calc(1 + var(--level) * 1.1));
  transition: transform .09s linear, opacity .4s ease;
}

.dial-spin {
  position: absolute;
  inset: -8px;
  z-index: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, rgb(var(--glow-rgb) / 0) 0 62%, rgb(var(--glow-rgb) / .95) 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
  opacity: 0;
  transition: opacity .3s;
}

/* The label and status sit over the rings, so each carries a halo in the
   panel colour: a ring passes behind the letters rather than through them. */
.dial-label, .dial-status {
  position: relative;
  z-index: 1;
  text-shadow: 0 0 6px var(--panel), 0 0 12px var(--panel), 0 0 18px var(--panel);
}
.dial-label {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.012em;
  transition: color .3s;
}

.dial-status {
  margin: 4px 0 0;
  min-height: 1.5em;
  max-width: 60ch;
  text-align: center;
  font-size: 13px;
  color: var(--dim);
}

/* Idle: hover lifts the orb and rings the handset; press sinks it. */
.dial[data-state="idle"]:hover .dial-orb {
  transform: translateY(-4px) scale(1.035);
  box-shadow:
    0 2px 2px rgb(15 23 42 / .10),
    0 16px 30px -6px rgb(var(--glow-rgb) / .60),
    0 42px 76px -20px rgb(var(--glow-rgb) / .55),
    inset 0 1px 0 rgb(255 255 255 / .5),
    inset 0 -12px 24px rgb(10 24 46 / .28);
}
.dial[data-state="idle"]:hover .dial-icon { animation: jingle .85s ease-in-out; }
.dial[data-state="idle"]:hover .dial-ring { animation-duration: 2.4s; }
.dial:active .dial-orb {
  transform: translateY(0) scale(.94);
  transition-duration: .09s;
}
@keyframes jingle {
  0%, 100% { transform: rotate(0); }
  15%, 45% { transform: rotate(-14deg); }
  30%, 60% { transform: rotate(14deg); }
  75%      { transform: rotate(-6deg); }
}

/* Connecting: the broadcast stops and an arc chases round the orb. */
.dial[data-state="connecting"] .dial-ring { animation: none; opacity: 0; }
.dial[data-state="connecting"] .dial-spin { opacity: 1; animation: spin .9s linear infinite; }
.dial[data-state="connecting"] .dial-orb { transform: scale(.97); }
@keyframes spin { to { transform: rotate(1turn); } }

/* Live: red, handset down, halo on the caller's voice. */
.dial[data-state="live"] { --glow-rgb: var(--bad-rgb); }
.dial[data-state="live"] .dial-orb::after { opacity: 1; }
.dial[data-state="live"] .dial-icon { transform: rotate(135deg); }
.dial[data-state="live"] .dial-halo { opacity: 1; }
.dial[data-state="live"] .dial-ring { animation-duration: 2.6s; }
.dial[data-state="live"] .dial-label { color: var(--blocked); }
.dial[data-state="live"]:hover .dial-orb { transform: translateY(-3px) scale(1.03); }

/* Options sit under the dial and lock while a call is on. */
.dial-options {
  margin-top: 18px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 10px;
  transition: opacity .3s;
}
.dial-options.is-locked { opacity: .45; }

.pill-select {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 4px 3px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--band);
  font-size: 12.5px;
  color: var(--dimmer);
}
.pill-select select {
  appearance: none;
  -webkit-appearance: none;
  padding: 5px 26px 5px 6px;
  border: 0;
  border-radius: 999px;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2364748B' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")
    no-repeat right 10px center;
  color: var(--text);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  /* "Bahasa Indonesia — Indonesian" is the longest entry; past this the row
     wraps rather than the name being clipped to an ellipsis. */
  max-width: 260px;
}
.pill-select select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pill-select select:disabled { cursor: not-allowed; }

/* ── Errors ────────────────────────────────────────────────────────────────── */
.setup-error {
  margin: 14px 0 0;
  padding: 10px 14px;
  border: 1px solid rgb(var(--bad-rgb) / .4);
  border-left-width: 2px;
  border-radius: var(--r);
  background: rgb(var(--bad-rgb) / .07);
  color: var(--blocked);
  font-size: 13px;
}

/* ══ THE PRIVACY RAIL ═══════════════════════════════════════════════════════
   The desk's signature element. Three locks — record, identity, entitlement —
   light as the caller passes each. The seam to their right is a real edge: it
   opens only when all three pass, and seals in red when the caller is not the
   student and holds no release, hatching the record behind it in UBT maroon.
   The university's own colours become literally the thing a stranger cannot
   reach. */
.boundary {
  margin-top: 18px;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 6px 18px rgb(var(--slate-rgb) / .12);

  /* The site never uses its navy as a ground — it uses it for the one card it
     wants you to look at. That is this. Re-pointing the tokens inside this
     block flips the whole component to the dark surface without touching a
     single rule below, and switches the status triad to the lighter weights
     the site itself uses on navy. */
  --panel: var(--ink);
  --panel-2: var(--ink-deep);
  --text: var(--on-ink);
  --dim: #A7BACF;
  --dimmer: #7E93AC;
  --line: #2F3A6B;
  --line-soft: #283260;
  --accent-rgb: 125 211 252;
  --accent: var(--sky);
  --ok-rgb: 52 211 153;
  --warn-rgb: 251 191 36;
  --bad-rgb: 248 113 113;
  --slate-rgb: 148 163 184;
  --executed: rgb(var(--ok-rgb));
  --approval: rgb(var(--warn-rgb));
  --blocked: rgb(var(--bad-rgb));

  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
}
.boundary .eyebrow { color: var(--accent); }

.boundary-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
}

.boundary-verdict {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: 20px;
  color: var(--dim);
  white-space: nowrap;
}

.boundary-body {
  display: grid;
  grid-template-columns: 1fr 4px minmax(160px, 218px);
  align-items: stretch;
}

.locks {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.lock {
  position: relative;
  padding: 16px 16px 18px;
  border-right: 1px solid var(--line-soft);
  transition: background .2s;
}
.lock:last-child { border-right: 0; }

.lock-n {
  display: inline-grid;
  place-items: center;
  width: 21px; height: 21px;
  border: 1px solid var(--line);
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  color: var(--dimmer);
  transition: border-color .2s, color .2s, background .2s;
}
.lock-name {
  display: block;
  margin-top: 9px;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.lock-note { display: block; margin-top: 1px; font-size: 11.5px; color: var(--dimmer); }

.lock[data-passed="true"] { background: rgb(var(--ok-rgb) / .055); }
.lock[data-passed="true"] .lock-n {
  border-color: var(--executed);
  color: var(--executed);
  background: rgb(var(--ok-rgb) / .12);
}
.lock[data-passed="true"] .lock-name { color: var(--executed); }

.lock[data-failed="true"] { background: rgb(var(--bad-rgb) / .06); }
.lock[data-failed="true"] .lock-n { border-color: var(--blocked); color: var(--blocked); }
.lock[data-failed="true"] .lock-name { color: var(--blocked); text-decoration: line-through; }

/* The seam itself — the membrane. */
.seam { position: relative; background: var(--line); transition: background .35s; }
.seam span {
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform .45s cubic-bezier(.16,.84,.44,1), background .35s;
}

.closed-zone {
  padding: 14px 16px;
  background: repeating-linear-gradient(
    -45deg, transparent, transparent 6px,
    rgb(var(--slate-rgb) / .035) 6px, rgb(var(--slate-rgb) / .035) 12px);
  transition: background .35s, opacity .35s;
}
.closed-title {
  margin: 0 0 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dimmer);
}
.closed-list { margin: 0; padding: 0; list-style: none; }
.closed-list li {
  font-size: 12px;
  color: var(--dimmer);
  padding: 2.5px 0;
  text-decoration: line-through;
  text-decoration-color: rgb(var(--slate-rgb) / .45);
  transition: color .25s, text-decoration-color .25s;
}

.boundary-reason {
  margin: 0;
  padding: 11px 16px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--dim);
}

/* Stage: partially verified — the seam charges. */
.boundary[data-state="progress"] .seam span { transform: scaleY(.5); }
.boundary[data-state="progress"] .boundary-verdict { color: var(--accent); border-color: rgb(var(--accent-rgb) / .45); }

/* Stage: identity + institution, no NDA — held for human approval. */
.boundary[data-state="approval"] .seam { background: rgb(var(--warn-rgb) / .28); }
.boundary[data-state="approval"] .seam span { transform: scaleY(.82); background: var(--approval); }
.boundary[data-state="approval"] .boundary-verdict {
  color: var(--approval); border-color: rgb(var(--warn-rgb) / .5); background: rgb(var(--warn-rgb) / .08);
}

/* Stage: released — the seam opens and the closed zone becomes reachable. */
.boundary[data-state="released"] .seam { background: rgb(var(--ok-rgb) / .3); }
.boundary[data-state="released"] .seam span { transform: scaleY(1); background: var(--executed); }
.boundary[data-state="released"] .boundary-verdict {
  color: var(--executed); border-color: rgb(var(--ok-rgb) / .5); background: rgb(var(--ok-rgb) / .09);
}
.boundary[data-state="released"] .closed-zone { background: rgb(var(--ok-rgb) / .06); }
.boundary[data-state="released"] .closed-list li {
  color: var(--text);
  text-decoration-color: transparent;
}
.boundary[data-state="released"] .closed-title { color: var(--executed); }

/* Stage: blocked — the seam thickens and seals, and the locks above die. */
.boundary[data-state="blocked"] { border-color: rgb(var(--bad-rgb) / .55); box-shadow: 0 6px 20px rgb(var(--bad-rgb) / .18); }
.boundary[data-state="blocked"] .boundary-body { grid-template-columns: 1fr 7px minmax(160px, 218px); }
.boundary[data-state="blocked"] .seam { background: var(--blocked); }
.boundary[data-state="blocked"] .seam span { transform: scaleY(1); background: var(--blocked); }
.boundary[data-state="blocked"] .boundary-verdict {
  color: var(--blocked); border-color: rgb(var(--bad-rgb) / .55); background: rgb(var(--bad-rgb) / .1);
}
.boundary[data-state="blocked"] .lock:not([data-passed="true"]) { opacity: .42; }
.boundary[data-state="blocked"] .boundary-reason { color: var(--blocked); }
.boundary[data-state="blocked"] .closed-zone {
  background: repeating-linear-gradient(
    -45deg, rgb(var(--ubt-maroon-rgb) / .22), rgb(var(--ubt-maroon-rgb) / .22) 6px,
    rgb(var(--ubt-maroon-rgb) / .42) 6px, rgb(var(--ubt-maroon-rgb) / .42) 12px);
}

/* ── Call surfaces ───────────────────────────────────────────────────────── */
.call-grid {
  margin-top: 18px;
  display: grid;
  grid-template-columns: 1fr minmax(258px, 330px);
  gap: 18px;
  align-items: start;
}

.panel {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
}

.live { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--executed); }
.live em { font-family: var(--mono); font-style: normal; color: var(--dim); }
.live-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--executed);
  box-shadow: 0 0 0 0 rgb(var(--ok-rgb) / .55);
  animation: pulse 1.9s infinite;
}
@keyframes pulse {
  70% { box-shadow: 0 0 0 8px rgb(var(--ok-rgb) / .0); }
  100% { box-shadow: 0 0 0 0 rgb(var(--ok-rgb) / .0); }
}

.transcript {
  height: 380px;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 13px;
}

.turn { max-width: 88%; }
.turn.is-agent { align-self: flex-start; }
.turn.is-user { align-self: flex-end; }
.turn-who {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--dimmer);
  margin-bottom: 4px;
}
.turn.is-user .turn-who { text-align: right; }
.turn-text {
  padding: 9px 13px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  background: var(--panel-2);
  font-size: 13.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.turn.is-agent .turn-text { border-left: 2px solid rgb(var(--accent-rgb) / .5); }
.turn.is-user .turn-text { border-right: 2px solid var(--line); background: transparent; }

.empty { margin: 0; color: var(--dimmer); font-size: 13px; }

.whisper {
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid var(--line-soft);
}
.whisper input {
  flex: 1;
  min-width: 0;
  padding: 8px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--band);
  font-size: 13px;
}

.panel-side { max-height: 620px; }
.activity {
  flex: 1;
  min-height: 168px;
  max-height: 300px;
  overflow-y: auto;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.tool {
  padding: 8px 11px;
  border: 1px solid var(--line-soft);
  border-left: 2px solid var(--line);
  border-radius: var(--r);
  background: var(--panel-2);
  font-size: 12px;
}
.tool-name { font-size: 11.5px; font-weight: 500; color: var(--accent); }
.tool-detail { margin-top: 3px; color: var(--dim); font-size: 11.5px; line-height: 1.45; }
.tool.is-blocked { border-left-color: var(--blocked); background: rgb(var(--bad-rgb) / .06); }
.tool.is-blocked .tool-name { color: var(--blocked); }
.tool.is-pass { border-left-color: var(--executed); }
.tool.is-pass .tool-name { color: var(--executed); }
.tool.is-note { border-left-color: var(--approval); }
.tool.is-note .tool-name { color: var(--approval); }

.meters { padding: 12px 16px 14px; border-top: 1px solid var(--line-soft); }

.stats { margin: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.stats dt {
  font-size: 9px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--dimmer);
}
.stats dd { margin: 2px 0 0; font-size: 15px; font-weight: 500; }

/* ── Wrap-up ─────────────────────────────────────────────────────────────── */
.wrap {
  margin-top: 18px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--shadow);
  padding: 18px;
}
.wrap-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.wrap-head h2 { margin: 0; font-size: 17px; font-weight: 600; }
.verdict-pill {
  font-family: var(--mono);
  font-size: 10px; font-weight: 700; letter-spacing: 0.13em; text-transform: uppercase;
  padding: 3px 10px; border-radius: 20px; border: 1px solid var(--line); color: var(--dim);
}
.verdict-pill.is-success { color: var(--executed); border-color: rgb(var(--ok-rgb) / .5); background: rgb(var(--ok-rgb) / .08); }
.verdict-pill.is-miss { color: var(--dim); }
.verdict-pill.is-fail { color: var(--blocked); border-color: rgb(var(--bad-rgb) / .5); background: rgb(var(--bad-rgb) / .08); }

.wrap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.wrap-cell { padding: 11px 13px; border: 1px solid var(--line-soft); border-radius: var(--r); }
.wrap-cell dt {
  font-size: 9px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--dimmer);
}
.wrap-cell dd { margin: 4px 0 0; font-size: 17px; font-family: var(--mono); }
.wrap-cell small { display: block; margin-top: 2px; font-size: 11px; color: var(--dimmer); font-family: var(--ui); }

.score-section { margin-top: 14px; }
.score-row {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 0; border-bottom: 1px solid var(--line-soft);
  font-size: 13px;
}
.score-row:last-child { border-bottom: 0; }
.score-row b { flex: 1; font-weight: 500; }
.score-bar { width: 92px; height: 3px; background: var(--line-soft); border-radius: 3px; overflow: hidden; }
.score-bar i { display: block; height: 100%; background: var(--accent); }
.score-val { font-family: var(--mono); font-size: 12px; color: var(--dim); width: 34px; text-align: right; }

.coaching { margin: 12px 0 0; padding-left: 18px; font-size: 13px; color: var(--dim); }
.coaching li { margin-bottom: 5px; }

.breach-banner {
  margin: 12px 0 0;
  padding: 11px 14px;
  border: 1px solid var(--blocked);
  border-left-width: 3px;
  border-radius: var(--r);
  background: rgb(var(--bad-rgb) / .09);
  color: var(--blocked);
  font-size: 13px;
}

/* ── Knowledge ───────────────────────────────────────────────────────────── */
.kb-search { display: flex; gap: 10px; margin-bottom: 18px; }
.kb-search input {
  flex: 1;
  padding: 10px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--panel);
  font-size: 14px;
}

.kb-card {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--shadow);
  margin-bottom: 10px;
}
.kb-card h3 { margin: 0; font-size: 14px; font-weight: 600; }
.kb-meta { display: flex; align-items: center; gap: 10px; margin-top: 3px; }
.kb-page { font-size: 11px; color: var(--accent); }
.kb-source { font-size: 11px; color: var(--dimmer); }
.kb-score { font-size: 10.5px; color: var(--dimmer); }
.kb-card p { margin: 9px 0 0; font-size: 13px; color: var(--dim); line-height: 1.55; }
.kb-all { margin-top: 26px; }
.kb-all-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }

/* ── Playbook ────────────────────────────────────────────────────────────── */
.playbook { display: grid; gap: 16px; }
.pb-card {
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--shadow);
}
.pb-card h2 { margin: 7px 0 0; font-size: 17px; font-weight: 600; }
.pb-card > p { margin: 8px 0 0; font-size: 13.5px; color: var(--dim); max-width: 74ch; }
.pb-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr)); gap: 18px; margin-top: 16px; }
.pb-list { margin: 8px 0 0; padding-left: 17px; font-size: 13px; color: var(--dim); }
.pb-list li { margin-bottom: 4px; }
.pb-list.is-open li::marker { color: var(--executed); }
.pb-list.is-closed li::marker { color: var(--blocked); }

.pb-rules { margin: 14px 0 0; padding: 0; list-style: none; counter-reset: r; }
.pb-rules li {
  counter-increment: r;
  padding: 10px 0 10px 38px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 13.5px;
  position: relative;
}
.pb-rules li:last-child { border-bottom: 0; }
.pb-rules li::before {
  content: counter(r, decimal-leading-zero);
  position: absolute; left: 0; top: 11px;
  font-family: var(--mono); font-size: 11px; color: var(--dimmer);
}
.pb-rules span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--dimmer); }
/* Products are not a sequence, so they drop the counter. */
.pb-rules.is-plain li { padding-left: 0; font-weight: 600; }
.pb-rules.is-plain li::before { content: none; }
.pb-rules.is-plain span { font-weight: 400; }

.pb-note {
  margin-top: 14px;
  padding: 11px 14px;
  border-left: 2px solid var(--approval);
  background: rgb(var(--warn-rgb) / .06);
  font-size: 12.5px;
  color: var(--approval);
}

/* ── Desk ────────────────────────────────────────────────────────────────── */
.desk-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(152px, 1fr));
  gap: 12px;
  margin-bottom: 22px;
}
.stat-card {
  padding: 15px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--shadow);
}
.stat-card dt {
  font-size: 9px; font-weight: 700; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--dimmer);
}
.stat-card dd { margin: 6px 0 0; font-size: 25px; font-family: var(--mono); font-weight: 500; }
.stat-card.is-key dd { color: var(--accent); }
.stat-card.is-control dd { color: var(--executed); }

.call-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--shadow);
  margin-bottom: 8px;
  font-size: 13px;
  flex-wrap: wrap;
}
.call-row .who { flex: 1; min-width: 148px; font-weight: 500; }
.call-row .meta { color: var(--dimmer); font-size: 12px; font-family: var(--mono); }

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .call-grid { grid-template-columns: 1fr; }
  .panel-side { max-height: none; }
}

@media (max-width: 820px) {
  .shell { flex-direction: column; }
  .rail {
    width: 100%;
    flex-direction: row;
    overflow-x: auto;
    padding: 0;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .rail-btn {
    border-left: 0;
    border-bottom: 2px solid transparent;
    padding: 12px 15px;
    white-space: nowrap;
  }
  .rail-btn.is-active { border-left-color: transparent; border-bottom-color: var(--accent); }

  /* The boundary stacks: the seam becomes a horizontal edge, and the closed
     zone sits below it — still on the far side, still unreachable. */
  .boundary-body { grid-template-columns: 1fr; }
  .locks { grid-template-columns: 1fr; }
  .lock { border-right: 0; border-bottom: 1px solid var(--line-soft); }
  .seam { height: 4px; }
  .seam span { transform: scaleX(0); transform-origin: left; }
  .boundary[data-state="progress"] .seam span { transform: scaleX(.5) scaleY(1); }
  .boundary[data-state="approval"] .seam span { transform: scaleX(.82) scaleY(1); }
  .boundary[data-state="released"] .seam span,
  .boundary[data-state="blocked"] .seam span { transform: scaleX(1) scaleY(1); }
  .boundary[data-state="blocked"] .boundary-body { grid-template-columns: 1fr; }
  .boundary[data-state="blocked"] .seam { height: 7px; }

  .topbar { height: auto; padding: 10px var(--pad); flex-wrap: wrap; gap: 10px; }
  .dial-stage { padding: 44px 16px 20px; }
  .dial-stage::before { top: 100px; }
  .transcript { height: 300px; }
  .turn { max-width: 96%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  /* With motion off the seam still has to read as open or sealed, so it
     switches state instantly rather than sliding. */
  .seam span { transform: scaleY(1); }
  /* The dial keeps its states — blue, arc, red — without the broadcast. */
  .dial-ring { display: none; }
  .dial[data-state="connecting"] .dial-spin { opacity: .7; }
  .boundary[data-state="idle"] .seam span,
  .boundary[data-state="progress"] .seam span { opacity: .3; }
}

/* ══ Chat bubble ═════════════════════════════════════════════════════════════
   The text assistant. Same system prompt, same knowledge index and same gated
   tools as the voice agent — so it carries the same privacy rail, in miniature,
   in its header. */
.chat-fab {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 60;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 0;
  cursor: pointer;
  color: #fff;
  background: radial-gradient(circle at 32% 28%, #5B8DEF, var(--accent) 55%, #1D4ED8);
  box-shadow: 0 8px 22px rgb(var(--accent-rgb) / .38), 0 2px 4px rgb(var(--slate-rgb) / .2);
  display: grid;
  place-items: center;
  transition: transform .18s ease, box-shadow .18s ease;
}
.chat-fab:hover { transform: translateY(-2px); box-shadow: 0 12px 26px rgb(var(--accent-rgb) / .45); }
.chat-fab svg { width: 24px; height: 24px; }
.chat-fab .fab-close { display: none; }
.chat-fab[aria-expanded="true"] .fab-open { display: none; }
.chat-fab[aria-expanded="true"] .fab-close { display: block; }
.chat-fab:focus-visible { outline: 3px solid rgb(var(--accent-rgb) / .45); outline-offset: 3px; }

.chat-panel {
  position: fixed;
  right: 22px;
  bottom: 88px;
  z-index: 59;
  width: min(380px, calc(100vw - 32px));
  height: min(560px, calc(100vh - 120px));
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 18px 48px rgb(var(--slate-rgb) / .28);
  overflow: hidden;
  animation: rise .2s ease both;
}
.chat-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--band);
}
.chat-avatar {
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgb(var(--accent-rgb) / .1); color: var(--accent);
  font-weight: 700; font-size: 13px;
}
.chat-head > div:nth-child(2) { min-width: 0; }
.chat-title { font-size: 13px; font-weight: 600; line-height: 1.2; white-space: nowrap; }
.chat-sub { font-size: 11px; color: var(--dimmer); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-head-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
.chat-head-actions select { max-width: 92px; }
.chat-head select, .chat-head button {
  font: inherit; font-size: 11px; color: var(--dim);
  border: 1px solid var(--line); background: var(--panel);
  border-radius: 999px; padding: 4px 9px; cursor: pointer;
}
.chat-gate {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 14px; font-size: 11px; color: var(--dimmer);
  border-bottom: 1px solid var(--line-soft);
}
.chat-gate .pip {
  width: 18px; height: 5px; border-radius: 3px; background: var(--line);
  transition: background .2s;
}
.chat-gate .pip[data-passed="true"] { background: var(--executed); }
.chat-gate[data-state="blocked"] .pip:not([data-passed="true"]) { background: rgb(var(--ubt-maroon-rgb)); }
.chat-gate[data-state="blocked"] .chat-gate-label { color: rgb(var(--ubt-maroon-rgb)); font-weight: 600; }
.chat-gate[data-state="released"] .chat-gate-label { color: var(--executed); font-weight: 600; }
.chat-gate-label { margin-left: 4px; }

.chat-log {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--ground);
}
.msg {
  max-width: 86%;
  padding: 9px 12px;
  border-radius: 14px;
  font-size: 13.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.msg.is-bot { align-self: flex-start; background: var(--band); border: 1px solid var(--line-soft); border-bottom-left-radius: 4px; }
.msg.is-user { align-self: flex-end; background: var(--accent); color: #fff; border-bottom-right-radius: 4px; }
.msg.is-error { align-self: stretch; max-width: none; background: rgb(var(--bad-rgb) / .06); color: var(--blocked); border: 1px solid rgb(var(--bad-rgb) / .25); font-size: 12.5px; }
.msg-tools { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.msg-tools span {
  font-family: var(--mono); font-size: 10px; color: var(--dimmer);
  border: 1px solid var(--line); border-radius: 999px; padding: 1px 7px; background: var(--panel);
}
.msg-tools span.is-blocked { color: rgb(var(--ubt-maroon-rgb)); border-color: rgb(var(--ubt-maroon-rgb) / .4); }
.msg-tools span.is-pass { color: var(--executed); border-color: rgb(var(--ok-rgb) / .35); }
.typing { display: inline-flex; gap: 4px; }
.typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--dimmer); animation: blink 1.2s infinite both; }
.typing i:nth-child(2) { animation-delay: .2s; }
.typing i:nth-child(3) { animation-delay: .4s; }
@keyframes blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }

.chat-suggest { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 14px 10px; background: var(--ground); }
.chat-suggest button {
  font: inherit; font-size: 12px; color: var(--accent);
  border: 1px solid rgb(var(--accent-rgb) / .3); background: rgb(var(--accent-rgb) / .04);
  border-radius: 999px; padding: 5px 10px; cursor: pointer;
}
.chat-form { display: flex; gap: 8px; padding: 10px; border-top: 1px solid var(--line); background: var(--panel); }
.chat-form textarea {
  flex: 1; resize: none; font: inherit; font-size: 13.5px; color: var(--text);
  border: 1px solid var(--line); border-radius: 12px; padding: 9px 11px;
  max-height: 110px; min-height: 40px; background: var(--ground);
}
.chat-form textarea:focus { outline: 2px solid rgb(var(--accent-rgb) / .35); border-color: var(--accent); }
.chat-form button {
  border: 0; border-radius: 12px; padding: 0 14px; cursor: pointer;
  background: var(--accent); color: #fff; font-weight: 600; font-size: 13px;
}
.chat-form button:disabled { opacity: .5; cursor: default; }

@media (max-width: 520px) {
  .chat-panel { right: 16px; left: 16px; width: auto; bottom: 84px; height: calc(100vh - 110px); }
  .chat-fab { right: 16px; bottom: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .typing i { animation: none; opacity: .6; }
}

/* Rendered markdown in bot replies — normal wrapping instead of pre-wrap. */
.msg.is-md { white-space: normal; }
.msg.is-md p { margin: 0 0 8px; }
.msg.is-md p:last-child, .msg.is-md ul:last-child, .msg.is-md ol:last-child { margin-bottom: 0; }
.msg.is-md ul, .msg.is-md ol { margin: 0 0 8px; padding-inline-start: 18px; }
.msg.is-md li { margin: 2px 0; }
.msg.is-md li::marker { color: var(--dimmer); }
.msg.is-md strong { font-weight: 600; color: var(--text); }
.msg.is-md .msg-h { font-weight: 600; margin-top: 4px; }
.msg.is-md code {
  font-family: var(--mono); font-size: 12px;
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: 4px; padding: 0 4px;
}
.msg.is-md a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
