/* AI Dialer — portal design system.
   One stylesheet, no framework, no CDN: the portal must load fast on a phone on
   Indian mobile data, and must never depend on a third-party host being up.
   Everything is driven by custom properties so light/dark and density changes
   happen in one place. */

/* ---------------------------------------------------------------- tokens */
:root {
  color-scheme: light dark;

  /* Brand: deep navy + a warm gold, carried over from the existing collateral */
  --brand-900: #0b1220;
  --brand-800: #0e182a;
  --brand-700: #16233c;
  --gold-500: #c9a24a;
  --gold-400: #d9b869;

  --ok-500: #1f9d63;
  --ok-100: #d8f3e4;
  --warn-500: #c98a19;
  --warn-100: #fdf0d5;
  --err-500: #cf3b3b;
  /* Red for words, as distinct from red for fills. The same in the light
     theme; lighter in the dark ones, where --err-500 on a dark surface
     measures 3.6:1 and text needs 4.5:1. */
  --err-text: #cf3b3b;
  --err-100: #fbdede;
  --info-500: #2f6fd0;
  --info-100: #dbe8fb;

  /* Light surfaces */
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f1f3f6;
  --surface-3: #e8ebf0;
  --border: #dfe3ea;
  --border-strong: #c6ccd8;
  --text: #16203a;
  --text-2: #5b667e;
  --text-3: #8792a8;

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 16px;
  --radius-full: 999px;

  /* A single shadow scale keeps elevation consistent */
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-2: 0 4px 12px rgba(16, 24, 40, .08);
  --shadow-3: 0 16px 40px rgba(16, 24, 40, .16);

  --sidebar-w: 248px;
  --header-h: 60px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
          Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Motion is subtle and respects the user's preference below */
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --fast: 120ms;
  --slow: 240ms;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0a0f1a;
    --surface: #111a2b;
    --surface-2: #16223a;
    --surface-3: #1d2b47;
    --border: #223350;
    --border-strong: #2e4267;
    --text: #e8edf7;
    --text-2: #9fadc6;
    /* Measured 13 Oct 2026: #6f7f9c was 4.3 to 1 on a card and 3.9 on a
       raised surface, under the 4.5 small text needs. This is 5.4 and 4.8. */
    --text-3: #8291ad;
    --ok-100: #10301f;
    --warn-100: #33280d;
    --err-100: #3a1717;
    --err-text: #f28b8b;
    --info-100: #121f38;
    --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow-2: 0 4px 14px rgba(0, 0, 0, .45);
    --shadow-3: 0 18px 44px rgba(0, 0, 0, .6);
  }
}

:root[data-theme="dark"] {
  --bg: #0a0f1a;
  --surface: #111a2b;
  --surface-2: #16223a;
  --surface-3: #1d2b47;
  --border: #223350;
  --border-strong: #2e4267;
  --text: #e8edf7;
  --text-2: #9fadc6;
  --text-3: #8291ad;
  --ok-100: #10301f;
  --warn-100: #33280d;
  --err-100: #3a1717;
  --err-text: #f28b8b;
  --info-100: #121f38;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 4px 14px rgba(0, 0, 0, .45);
  --shadow-3: 0 18px 44px rgba(0, 0, 0, .6);
}

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

html, body { height: 100%; }

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

h1, h2, h3, h4 { margin: 0; font-weight: 650; letter-spacing: -0.011em; line-height: 1.25; }
h1 { font-size: 26px; }
h2 { font-size: 19px; }
h3 { font-size: 16px; }
p { margin: 0; }
a { color: inherit; }

/* A visible focus ring everywhere — keyboard users are not an afterthought */
:focus-visible {
  outline: 2px solid var(--gold-500);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

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

/* Screen-reader only, for labels that would otherwise be visual-only */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- layout */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

.sidebar {
  background: var(--brand-800);
  color: #e9eefb;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  z-index: 40;
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 18px 20px;
  font-weight: 700; font-size: 16px; letter-spacing: -.01em;
  color: #fff;
}
.brand-mark {
  width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto;
  background: linear-gradient(135deg, var(--gold-500), var(--gold-600, #a97f2c));
  display: grid; place-items: center;
  color: var(--on-accent, var(--brand-900)); font-weight: 800; font-size: 15px;
}

.nav { padding: 6px 12px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; }
.nav-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: #7e8ba6; padding: 14px 10px 6px;
}
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--radius);
  color: #c3cde4; text-decoration: none; font-size: 14px; font-weight: 500;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.nav a:hover { background: rgba(255, 255, 255, .06); color: #fff; }
/* Tints of the accent are mixed from --gold-500 rather than written as gold
   rgba(), so a workspace's own colour (A8) carries into them too. */
.nav a[aria-current="page"] { background: color-mix(in srgb, var(--gold-500, #c9a24a) 16%, transparent); color: #fff; }
.nav a[aria-current="page"] .nav-icon { color: var(--gold-400); }
.nav-icon { width: 18px; height: 18px; flex: 0 0 auto; display: inline-flex; }
.nav a .nav-icon { color: #8d9bb8; }

.sidebar-foot { margin-top: auto; padding: 14px; border-top: 1px solid rgba(255,255,255,.08); }
/* The sidebar is dark in both themes; the ghost button's hover is made for a
   light surface and left these two as pale text on white. */
.sidebar-foot .btn-ghost:hover:not(:disabled),
.sidebar-foot a.btn-ghost[aria-current="page"] { background: rgba(255,255,255,.08); color: #fff !important; }

.main { display: flex; flex-direction: column; min-width: 0; }

.header {
  height: var(--header-h);
  display: flex; align-items: center; gap: 12px;
  padding: 0 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 30;
}
.header h1 { font-size: 17px; font-weight: 620; }
.header-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* Room at the foot of every page: the browser phone's launcher floats over the
   bottom-right corner, and without this it sat on top of the last control
   (the Join button on My status, 7 Oct 2026). */
.content { padding: 22px 22px 100px; max-width: 1240px; width: 100%; }

/* Mobile: the sidebar becomes a drawer */
.menu-btn { display: none; }
.scrim { display: none; }

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; width: 82vw; max-width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--slow) var(--ease);
    box-shadow: var(--shadow-3);
  }
  .app.nav-open .sidebar { transform: none; }
  .menu-btn { display: inline-grid; }
  .app.nav-open .scrim {
    display: block; position: fixed; inset: 0; z-index: 35;
    background: rgba(6, 10, 20, .5);
  }
  .content { padding: 16px 16px 96px; }
}

/* ---------------------------------------------------------------- cards */
.card {
  container-type: inline-size;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}
.card-head {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px; border-bottom: 1px solid var(--border);
}
.card-head h2 { font-size: 15px; }
.card-head .spacer { margin-left: auto; }
.card-body { padding: 18px; }
.card-body.tight { padding: 0; }

.grid { display: grid; gap: 16px; }
/* min() so the track can fall below its preferred floor on a narrow phone.
   A bare minmax(320px, 1fr) cannot shrink past 320px, so at 320px wide the
   Security screen pushed 35px off the side of the display. */
.grid.stats { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
/* Grid items default to min-width:auto, so a value longer than its track — an
   email address, a UUID — overflows instead of wrapping and lands on top of the
   next column. Seen on the mail console at a wide viewport: the SMTP username
   ran straight into "Sends from" with no gap between them. break-word rather
   than anywhere, so ordinary text still breaks at spaces. */
.grid.stats > * { min-width: 0; }
/* Six figures in even rows: three, then two, then one. */
.grid.stats.thirds { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .grid.stats.thirds { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .grid.stats.thirds { grid-template-columns: minmax(0, 1fr); } }
.grid.stats > * > * { overflow-wrap: break-word; }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }

/* Stat tile: the number is the hero, the label supports it */
.stat { padding: 16px 18px; }
.stat-label {
  font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-3);
  display: flex; align-items: center; gap: 6px;
}
.stat-value {
  font-size: 27px; font-weight: 680; letter-spacing: -.02em; margin-top: 6px;
  font-variant-numeric: tabular-nums;
}
.stat-sub { font-size: 13px; color: var(--text-2); margin-top: 2px; }

/* A quiet progress bar for "spend against cap" */
.meter { height: 6px; border-radius: var(--radius-full); background: var(--surface-3); margin-top: 12px; overflow: hidden; }
.meter > i { display: block; height: 100%; border-radius: inherit; background: var(--ok-500); transition: width var(--slow) var(--ease); }
.meter.warn > i { background: var(--warn-500); }
.meter.danger > i { background: var(--err-500); }

/* ---------------------------------------------------------------- tables */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th {
  text-align: left; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3);
  padding: 10px 18px; border-bottom: 1px solid var(--border); white-space: nowrap;
}
td { padding: 13px 18px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tr:last-child td { border-bottom: 0; }
tbody tr { transition: background var(--fast) var(--ease); }
tbody tr:hover { background: var(--surface-2); }
td.num { font-variant-numeric: tabular-nums; text-align: right; }
td .mono, .mono { font-family: var(--mono); font-size: 13px; }

/* Below this width a table cannot show its columns and its row actions at the
   same time, so it becomes stacked rows instead of hiding Delete behind a
   horizontal scroll nobody discovers.

   920px, not 660px: measured against the real tables rather than guessed. The
   widest (Agents) needs 913px to lay out its columns, so at 660 there was a
   260px band — every portrait tablet — where the table stayed tabular and
   pushed the actions column past the edge. Stacking a little early costs some
   density; the alternative hides Delete, which is the bug this rule exists to
   prevent. Re-measure if a column is added. */
@container (max-width: 920px) {
  table.stack thead { display: none; }
  table.stack tr {
    display: block; padding: 12px 14px; border-bottom: 1px solid var(--border);
  }
  table.stack td {
    display: flex; justify-content: space-between; gap: 16px;
    padding: 4px 0; border: 0; text-align: right;
  }
  table.stack td .inline { justify-content: flex-end; flex-wrap: wrap; }
  table.stack td:last-child { padding-top: 10px; }
  table.stack td::before {
    content: attr(data-label);
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-3); text-align: left;
  }
}

/* Fallback for browsers without container queries. */
@supports not (container-type: inline-size) {
  @media (max-width: 1180px) {
  table.stack thead { display: none; }
  table.stack tr {
    display: block; padding: 12px 14px; border-bottom: 1px solid var(--border);
  }
  table.stack td {
    display: flex; justify-content: space-between; gap: 16px;
    padding: 4px 0; border: 0; text-align: right;
  }
  table.stack td .inline { justify-content: flex-end; flex-wrap: wrap; }
  table.stack td:last-child { padding-top: 10px; }
  table.stack td::before {
    content: attr(data-label);
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-3); text-align: left;
  }
  }
}

/* ---------------------------------------------------------------- pills */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: var(--radius-full);
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill.ok { background: var(--ok-100); color: var(--ok-500); }
.pill.warn { background: var(--warn-100); color: var(--warn-500); }
.pill.err { background: var(--err-100); color: var(--err-500); }
.pill.info { background: var(--info-100); color: var(--info-500); }
.pill.mute { background: var(--surface-3); color: var(--text-2); }
.pill.plain::before { display: none; }

/* ---------------------------------------------------------------- forms */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field label { font-size: 13px; font-weight: 600; color: var(--text); }
.field .hint { font-size: 12.5px; color: var(--text-2); }
.field .err { font-size: 12.5px; color: var(--err-500); }
/* A field's heading where there is no input to label (the two-factor QR). */
.field .field-label { font-size: 13px; font-weight: 600; color: var(--text); }
/* The QR keeps its white ground in the dark theme too (see qrSvg). At 216 px
   each module of the ~45-module code an otpauth address makes (quiet zone
   included) is about 4 px, which phone cameras read off a laptop screen. */
.qr-tile { width: 216px; max-width: 100%; line-height: 0; border-radius: var(--radius-sm);
  overflow: hidden; border: 1px solid var(--border); }
.qr-tile .qr-code { width: 100%; height: auto; display: block; }
.qr-fallback > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--text-2);
  padding: 4px 0; width: max-content; max-width: 100%; }
.qr-fallback[open] > summary { margin-bottom: 8px; }
.qr-fallback .totp-key { margin-bottom: 6px; }
.totp-key { display: block; font-family: var(--mono); font-size: 15px; letter-spacing: .04em;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 9px 12px; user-select: all; overflow-wrap: anywhere; color: var(--text); }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="tel"], input[type="search"], select, textarea {
  width: 100%; padding: 10px 12px;
  font: inherit; font-size: 14px; color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
input:hover, select:hover, textarea:hover { border-color: var(--text-3); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--gold-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold-500, #c9a24a) 20%, transparent);
}
input[aria-invalid="true"] { border-color: var(--err-500); }
input::placeholder { color: var(--text-3); }
/* A select with no caret reads as a text box. The chevron is inlined as a data
   URI so it still renders under a CSP that blocks external images. */
select {
  appearance: none;
  cursor: pointer;
  padding-right: 34px;
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 15px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235b667e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239fadc6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

.row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 520px) { .row { grid-template-columns: 1fr; } }

/* Switch, for booleans that read better than a checkbox */
.switch { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 40px; height: 23px; border-radius: var(--radius-full);
  background: var(--surface-3); position: relative;
  transition: background var(--fast) var(--ease);
  flex: 0 0 auto;
}
.switch .track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 17px; height: 17px; border-radius: 50%; background: #fff;
  box-shadow: var(--shadow-1);
  transition: transform var(--slow) var(--ease);
}
.switch input:checked + .track { background: var(--ok-500); }
.switch input:checked + .track::after { transform: translateX(17px); }
.switch input:focus-visible + .track { outline: 2px solid var(--gold-500); outline-offset: 2px; }
.switch input:disabled + .track { opacity: .5; cursor: not-allowed; }

/* --------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  text-decoration: none;
  padding: 9px 15px; border-radius: var(--radius);
  font: inherit; font-size: 14px; font-weight: 600;
  border: 1px solid transparent; cursor: pointer;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

.btn-primary { background: var(--gold-500); color: var(--on-accent, var(--brand-900)); }
.btn-primary:hover:not(:disabled) { background: var(--gold-400); }

.btn-secondary { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.btn-secondary:hover:not(:disabled) { background: var(--surface-2); }

.btn-ghost { background: transparent; color: var(--text-2); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

.btn-danger { background: var(--err-500); color: #fff; }
.btn-danger:hover:not(:disabled) { filter: brightness(1.08); }

.btn .nav-icon { color: currentColor; }
.btn-icon { padding: 8px; border-radius: var(--radius); }
.btn-sm { padding: 6px 11px; font-size: 13px; }

/* A row's lesser-used actions (moreMenu in app.js). Fixed, and attached to the
   page: inside the table's scrolling wrapper it would be cut off at the edge.
   Above the page and the phone dock (50), below drawers (60) and toasts (80):
   choosing an item may open a drawer, which must cover it. */
.menu {
  position: fixed; z-index: 55; min-width: 168px; padding: 4px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-2);
}
.menu-item {
  display: block; width: 100%; padding: 8px 12px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text); font: inherit; font-size: 14px;
  text-align: left; cursor: pointer;
}
.menu-item:hover, .menu-item:focus-visible { background: var(--surface-2); }
.menu-item.danger { color: var(--err-text); }

/* A table row's actions that must stay on one line while the table is a
   table: the column then keeps the width its buttons need and the text
   columns give way, instead of every column shrinking a little and the
   buttons wrapping. Once the table is stacked (table.stack, above) its own
   rule lets them wrap again. */
.actions-line { justify-content: flex-end; flex-wrap: nowrap; }
.btn-block { width: 100%; }

/* Inline spinner used inside buttons during a request */
.spinner {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------- drawer */
.drawer-scrim {
  position: fixed; inset: 0; background: rgba(6, 10, 20, .55);
  z-index: 60; opacity: 0; animation: fade var(--fast) var(--ease) forwards;
}
@keyframes fade { to { opacity: 1; } }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 61;
  width: min(460px, 100vw);
  background: var(--surface); border-left: 1px solid var(--border);
  box-shadow: var(--shadow-3);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  animation: slide-in var(--slow) var(--ease) forwards;
}
@keyframes slide-in { to { transform: none; } }
.drawer-head {
  padding: 16px 18px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 12px;
}
.drawer-body { padding: 18px; overflow-y: auto; flex: 1; }
.drawer-foot {
  padding: 14px 18px; border-top: 1px solid var(--border);
  display: flex; gap: 10px; justify-content: flex-end;
  background: var(--surface);
}
@media (max-width: 560px) {
  .drawer { width: 100vw; }
  .drawer-foot .btn { flex: 1; }
}

/* --------------------------------------------------- read-only view (SA-2.4)
   The banner promises nothing on the screen can be changed. It was still
   offering every write control — an operator could fill in "Add trunk" in full
   and only then be told no by the server. The server refusal is the real
   protection and is unchanged; this stops the screen making an offer it cannot
   keep. Scoped to .content so the banner's own "Leave view" survives. */
body.vg .content .btn-primary,
body.vg .content .btn-danger { display: none; }

/* --------------------------------------------------------------- toasts */
/* Top right, under the header: the bottom-right corner belongs to the phone. */
.toasts {
  position: fixed; z-index: 80; right: 16px; top: calc(var(--header-h) + 12px);
  display: flex; flex-direction: column; gap: 8px; max-width: min(380px, calc(100vw - 32px));
}
.toast {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-2); font-size: 14px;
  animation: toast-in var(--slow) var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }
.toast.ok { border-left: 3px solid var(--ok-500); }
.toast.err { border-left: 3px solid var(--err-500); }
.toast.info { border-left: 3px solid var(--info-500); }
/* Ten callers used 'warn' with no rule for it, so a warning looked like any
   notice (found 24 Oct 2026 on the top-up's "do not pay again"). */
.toast.warn { border-left: 3px solid var(--warn-500); }
@media (max-width: 560px) { .toasts { left: 16px; right: 16px; max-width: none; } }

/* ------------------------------------------------------------ empty/skel */
.empty { padding: 44px 20px; text-align: center; color: var(--text-2); }
.empty h3 { color: var(--text); margin-bottom: 6px; }
.empty p { max-width: 380px; margin: 0 auto 16px; font-size: 14px; }
.empty-mark {
  width: 46px; height: 46px; border-radius: 14px; margin: 0 auto 14px;
  background: var(--surface-2); display: grid; place-items: center; color: var(--text-3);
}

.skel {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* ----------------------------------------------------------------- auth */
.auth {
  min-height: 100vh; min-height: 100dvh;
  display: grid; grid-template-columns: 1.05fr .95fr;
}
.auth-brand {
  background:
    radial-gradient(1100px 500px at 15% -10%, rgba(201,162,74,.22), transparent 60%),
    linear-gradient(160deg, var(--brand-800), var(--brand-900));
  color: #fff; padding: 44px; display: flex; flex-direction: column;
}
/* balance: "Sign in to AI Dialer." otherwise broke as "Sign in to AI / Dialer."
   on a workspace's own address (seen in the A8 custom-address browser run). */
.auth-brand .tagline { font-size: 30px; font-weight: 680; letter-spacing: -.02em; margin-top: auto; max-width: 15ch; text-wrap: balance; }
.auth-brand .sub { color: #a8b5cf; margin-top: 12px; max-width: 42ch; font-size: 15px; }
.auth-points { margin-top: 26px; display: flex; flex-direction: column; gap: 10px; }
.auth-point { display: flex; gap: 10px; align-items: flex-start; color: #cfd8ec; font-size: 14px; }
.auth-point svg { color: var(--gold-400); flex: 0 0 auto; margin-top: 2px; }

.auth-panel { display: grid; place-items: center; padding: 32px 22px; background: var(--bg); }
.auth-card { width: 100%; max-width: 400px; }
.auth-card h1 { margin-bottom: 6px; }
.auth-card .lede { color: var(--text-2); margin-bottom: 22px; font-size: 14.5px; }
.auth-alt { margin-top: 18px; font-size: 14px; color: var(--text-2); text-align: center; }
.auth-alt button {
  background: none; border: 0; padding: 0; font: inherit; font-weight: 600;
  color: var(--text); cursor: pointer; text-decoration: underline;
  text-underline-offset: 3px;
}

/* Shown at phone width only, where the brand panel is hidden. */
.auth-mobile-brand { display: none; }
@media (max-width: 880px) {
  .auth { grid-template-columns: 1fr; }
  .auth-brand { display: none; }
  .auth-panel { align-content: start; gap: 24px; }
  .auth-mobile-brand { display: block; width: 100%; max-width: 400px; }
}

/* Subdomain input renders as one control with a fixed suffix */
.subdomain { display: flex; align-items: stretch; }
.subdomain input { border-radius: var(--radius) 0 0 var(--radius); border-right: 0; }
.subdomain .suffix {
  display: flex; align-items: center; padding: 0 12px;
  background: var(--surface-2); border: 1px solid var(--border-strong);
  border-left: 0; border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--text-2); font-size: 14px; white-space: nowrap;
}

/* Password strength readout */
.strength { display: flex; gap: 4px; margin-top: 8px; }
.strength i { height: 3px; flex: 1; border-radius: var(--radius-full); background: var(--surface-3); }
.strength i.on-1 { background: var(--err-500); }
.strength i.on-2 { background: var(--warn-500); }
.strength i.on-3 { background: var(--ok-500); }

/* ------------------------------------------------------------- stages */
.stage {
  border: 1px solid var(--border); border-radius: var(--radius);
  margin-bottom: 10px; background: var(--surface);
}
.stage > summary {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 12px 14px; cursor: pointer; list-style: none;
  font-size: 14px; font-weight: 600;
}
.stage > summary::-webkit-details-marker { display: none; }
.stage > summary::before {
  content: ""; width: 0; height: 0; flex: 0 0 auto;
  border-left: 5px solid var(--text-3);
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform var(--fast) var(--ease);
}
.stage[open] > summary::before { transform: rotate(90deg); }
.stage > summary:hover { background: var(--surface-2); border-radius: var(--radius); }
.stage-title { margin-right: 2px; }
.stage-body { padding: 4px 14px 14px; border-top: 1px solid var(--border); }
.stage-body textarea { font-family: var(--mono); font-size: 12.5px; line-height: 1.5; }

/* ----------------------------------------------------------------- tabs */
.tabbar {
  display: flex; gap: 4px; margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.tabbar::-webkit-scrollbar { display: none; }
.tab {
  padding: 9px 14px; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--text-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  white-space: nowrap;
  transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.tab:hover { color: var(--text); }
.tab[aria-selected="true"] { color: var(--text); border-bottom-color: var(--gold-500); }

/* ---------------------------------------------------------------- misc */
.toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; flex-wrap: wrap; }
.toolbar .spacer { margin-left: auto; }
/* Filters in a toolbar are as wide as what they hold. Left at the form-field
   width of 100% each one took a row of its own (the Calls page, until 7 Oct
   2026), and a search box had no styling at all: type="search" was missing
   from the rule above. */
.toolbar select, .toolbar input[type="search"] { width: auto; flex: 0 1 auto; max-width: 100%; }
input[type="search"] { width: auto; max-width: 100%; }
.muted { color: var(--text-2); }
.small { font-size: 13px; }
.stack-sm { display: flex; flex-direction: column; gap: 3px; }
.inline { display: flex; align-items: center; gap: 8px; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch; }

.banner {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 13px 15px; border-radius: var(--radius); font-size: 14px;
  margin-bottom: 16px;
}
.banner.ok { background: var(--ok-100); color: var(--ok-500); }
.banner.warn { background: var(--warn-100); color: var(--warn-500); }
.banner.err { background: var(--err-100); color: var(--err-500); }
.banner.info { background: var(--info-100); color: var(--info-500); }
.banner strong { display: block; margin-bottom: 2px; }
/* A column, not a run of inline spans. The import report is the first banner
   with more than one line in its body, and inline spans butted straight up
   against each other — "3 could not be readNot usable: 12, 7". */
.banner .banner-body { color: var(--text); display: flex; flex-direction: column; gap: 2px; }

/* A short label/value list — call facts, and anywhere else a drawer needs to
   state a handful of fields without the weight of a table. */
.facts { display: grid; grid-template-columns: minmax(min(90px, 30%), auto) 1fr;
         gap: 8px 16px; margin: 0; }
.facts dt { color: var(--text-2); font-size: 13px; }
.facts dd { margin: 0; font-size: 14px; overflow-wrap: anywhere; }
@container (max-width: 380px) {
  .facts { grid-template-columns: 1fr; gap: 2px 0; }
  .facts dd { margin-bottom: 8px; }
}

/* Error text in a drawer, using the same tone as .pill.err so the two agree
   in both themes rather than each defining their own red. */
.err-text { color: var(--err-500); }

/* D5/D6 — the phone dock. A handset in the corner of every screen: always
   dark, in the portal's navy with brass for focus and the active tab, whatever
   the page's theme, because it stands in for a device on the desk. Colour on
   it means something: green answers, red ends, amber rings or waits. */
.phone-pill { border: 0; cursor: pointer; font: inherit; font-variant-numeric: tabular-nums; }
.phone-pill[hidden] { display: none; }

.ph-dock {
  --ph-bg: #0e182a; --ph-bg-2: #142039; --ph-key: #1a2944; --ph-key-hi: #22365a;
  --ph-line: rgba(255, 255, 255, .08); --ph-text: #eef2f9; --ph-muted: #8d9bb8;
  --ph-brass: var(--gold-500, #c9a24a); --ph-go: #1f9d63; --ph-go-hi: #26b573; --ph-stop: #e0484a;
  --ph-stop-hi: #ee5b5d; --ph-amber: #d99a1e;
  position: fixed; right: 24px; bottom: 24px; z-index: 50;
  display: flex; flex-direction: column; align-items: flex-end; gap: 14px;
  font-family: var(--font); color: var(--ph-text); pointer-events: none;
}
.ph-dock > * { pointer-events: auto; }
.ph-ic { display: inline-flex; line-height: 0; }

/* The launcher, and the capsule it becomes during a call. */
.ph-launch {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 60px; height: 60px; border-radius: 30px; cursor: pointer;
  background: linear-gradient(150deg, #1b2b4a, var(--ph-bg) 70%);
  border: 1px solid color-mix(in srgb, var(--gold-500, #c9a24a) 55%, transparent); color: var(--ph-brass);
  box-shadow: 0 12px 30px rgba(8, 14, 28, .35), inset 0 1px 0 rgba(255, 255, 255, .06);
  transition: width var(--slow) var(--ease), transform var(--fast) var(--ease), box-shadow var(--fast);
}
.ph-launch:hover { transform: translateY(-1px); box-shadow: 0 16px 36px rgba(8, 14, 28, .42); }
.ph-launch-dot {
  position: absolute; right: 7px; bottom: 7px; width: 12px; height: 12px; border-radius: 50%;
  background: #6b7892; box-shadow: 0 0 0 2px var(--ph-bg);
}
.ph-launch.is-ready .ph-launch-dot { background: var(--ph-go); }
.ph-launch.is-failed .ph-launch-dot { background: var(--ph-stop); }
.ph-launch.is-starting .ph-launch-dot { background: var(--ph-amber); }
.ph-badge {
  position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 10px; background: var(--ph-stop); color: #fff; font-size: 11px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 0 0 2px var(--bg);
}
.ph-launch.is-capsule {
  width: auto; min-width: 200px; max-width: min(320px, calc(100vw - 48px)); height: 56px;
  padding: 0 20px 0 8px; gap: 12px; justify-content: flex-start; color: var(--ph-text);
}
.ph-cap-dot {
  flex: none; width: 40px; height: 40px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; background: var(--ph-go); color: #fff;
}
.ph-launch.is-ringing .ph-cap-dot { background: var(--ph-amber); animation: ph-ring 1.2s ease-in-out infinite; }
.ph-launch.is-hold .ph-cap-dot { background: var(--ph-amber); }
.ph-launch.is-ringing.is-capsule { border-color: var(--ph-amber); }
.ph-cap-text { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.ph-cap-who { font-size: 14px; font-weight: 600; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ph-cap-state { font-size: 12px; color: var(--ph-muted); font-variant-numeric: tabular-nums; }
@keyframes ph-ring { 0%, 100% { transform: rotate(0); } 15% { transform: rotate(-14deg); } 30% { transform: rotate(12deg); } 45% { transform: rotate(-8deg); } 60% { transform: rotate(0); } }

/* The panel. */
.ph-panel {
  width: 360px; height: 580px; max-height: calc(100vh - 120px);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--ph-bg); border-radius: 22px;
  border: 1px solid color-mix(in srgb, var(--gold-500, #c9a24a) 22%, transparent);
  box-shadow: 0 30px 70px rgba(6, 11, 22, .45), 0 2px 0 rgba(255, 255, 255, .03) inset;
  transform: translate(var(--ph-dx, 0), var(--ph-dy, 0));
  animation: ph-rise var(--slow) var(--ease);
}
.ph-panel[hidden] { display: none; }
.ph-panel.is-dragging { user-select: none; box-shadow: 0 40px 90px rgba(6, 11, 22, .55); }
@keyframes ph-rise { from { opacity: 0; transform: translate(var(--ph-dx, 0), calc(var(--ph-dy, 0px) + 12px)) scale(.98); } }
.ph-head {
  display: flex; align-items: center; gap: 4px; padding: 14px 10px 12px 18px;
  border-bottom: 1px solid var(--ph-line); cursor: grab;
  background: linear-gradient(180deg, var(--ph-bg-2), var(--ph-bg));
}
.ph-panel.is-dragging .ph-head { cursor: grabbing; }
.ph-head-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ph-title { margin: 0; font-size: 10.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--ph-brass); }
.ph-status { font-size: 14px; font-weight: 600; display: inline-flex; align-items: center; gap: 7px; }
.ph-status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: #6b7892; }
.ph-status[data-state="ready"]::before { background: var(--ph-go); box-shadow: 0 0 0 3px rgba(31, 157, 99, .2); }
.ph-status[data-state="failed"]::before { background: var(--ph-stop); }
.ph-status[data-state="starting"]::before { background: var(--ph-amber); }
.ph-body { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
.ph-body::-webkit-scrollbar { width: 6px; } .ph-body::-webkit-scrollbar-thumb { background: var(--ph-line); border-radius: 3px; }

/* Buttons. */
.ph-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px;
  border-radius: 10px; border: 0; background: transparent; color: var(--ph-muted); cursor: pointer;
}
.ph-icon-btn:hover { background: var(--ph-key); color: var(--ph-text); }
.ph-dock button:focus-visible, .ph-dock input:focus-visible, .ph-dock select:focus-visible {
  outline: 2px solid var(--ph-brass); outline-offset: 2px;
}
.ph-btn {
  width: 100%; min-height: 44px; padding: 0 16px; border-radius: 12px; border: 1px solid transparent;
  font: 600 14px var(--font); cursor: pointer; color: var(--ph-text); background: var(--ph-key);
}
.ph-btn:hover { background: var(--ph-key-hi); }
.ph-btn:disabled { opacity: .6; cursor: default; }
.ph-btn-go { background: var(--ph-go); color: #fff; }
.ph-btn-go:hover { background: var(--ph-go-hi); }
.ph-btn-quiet { background: transparent; border-color: var(--ph-line); }
.ph-btn-danger-quiet { background: transparent; border-color: rgba(224, 72, 74, .35); color: #ff8a8b; margin-top: 8px; }
.ph-link { background: none; border: 0; padding: 0; color: var(--ph-brass); font: 600 13px var(--font); cursor: pointer; }
.ph-row { display: flex; gap: 10px; margin-top: auto; }
.ph-stack { display: flex; flex-direction: column; gap: 10px; margin-top: auto; }

/* Dialling. */
.ph-dial { display: flex; flex-direction: column; flex: 1; padding: 16px 22px 18px; }
.ph-display-row { display: flex; align-items: center; gap: 4px; border-bottom: 1px solid var(--ph-line); margin-bottom: 14px; }
/* Scoped past the portal's own input[type="tel"] rule, which would otherwise
   paint these as white form fields. */
.ph-dock input.ph-display {
  flex: 1; min-width: 0; height: 56px; padding: 0 4px; border: 0; border-radius: 0;
  background: transparent; box-shadow: none; color: var(--ph-text);
  font: 300 30px var(--font); letter-spacing: .04em; text-align: center; font-variant-numeric: tabular-nums;
}
.ph-dock input.ph-display::placeholder { color: #4d5b78; font-size: 18px; letter-spacing: 0; font-weight: 400; }
.ph-dock input.ph-display:focus { outline: none; box-shadow: none; }
.ph-keys { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px 18px; justify-items: center; }
.ph-key {
  width: 64px; height: 64px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--ph-key); color: var(--ph-text);
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  transition: background var(--fast), transform 80ms;
}
.ph-key:hover { background: var(--ph-key-hi); }
.ph-key:active { transform: scale(.94); background: #2a416b; }
.ph-key-d { font-size: 24px; font-weight: 450; line-height: 1; font-variant-numeric: tabular-nums; }
.ph-key-l { font-size: 9px; font-weight: 700; letter-spacing: .18em; color: var(--ph-muted); padding-left: .18em; }
.ph-dial-go { display: flex; justify-content: center; margin-top: 16px; }
.ph-round {
  width: 64px; height: 64px; border-radius: 50%; border: 0; cursor: pointer; color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform 80ms, background var(--fast), box-shadow var(--fast);
}
.ph-round:active { transform: scale(.94); }
.ph-round-go { background: var(--ph-go); box-shadow: 0 10px 24px rgba(31, 157, 99, .35); }
.ph-round-go:hover { background: var(--ph-go-hi); }
.ph-round-stop { background: var(--ph-stop); box-shadow: 0 10px 24px rgba(224, 72, 74, .35); }
.ph-round-stop:hover { background: var(--ph-stop-hi); }
.ph-round-wrap { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ph-round-label { font-size: 12px; color: var(--ph-muted); }

/* A call. */
.ph-call { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 26px 22px 22px; text-align: center; }
.ph-avatar {
  position: relative; width: 88px; height: 88px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, #253a61, #16233c); color: var(--ph-text);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold-500, #c9a24a) 35%, transparent);
}
.ph-avatar-ini { font-size: 30px; font-weight: 600; letter-spacing: .02em; }
.ph-avatar-rings { position: absolute; inset: 0; border-radius: 50%; }
.ph-avatar.is-live { box-shadow: 0 0 0 2px var(--ph-go); }
.ph-avatar.is-hold { box-shadow: 0 0 0 2px var(--ph-amber); }
.ph-avatar.is-ringing .ph-avatar-rings, .ph-avatar.is-calling .ph-avatar-rings {
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold-500, #c9a24a) 55%, transparent); animation: ph-pulse 1.6s ease-out infinite;
}
.ph-avatar.is-ringing .ph-avatar-rings { box-shadow: 0 0 0 0 rgba(217, 154, 30, .6); }
@keyframes ph-pulse { to { box-shadow: 0 0 0 26px color-mix(in srgb, var(--gold-500, #c9a24a) 0%, transparent); } }
.ph-name { margin: 18px 0 4px; font-size: 20px; font-weight: 600; line-height: 1.25; overflow-wrap: anywhere; text-wrap: balance; }
/* H6: who a campaign call is bringing, under the name. */
.ph-sub { margin: 0 0 6px; color: var(--ph-muted); font-size: 13px; }
.ph-campaign { margin: 14px 0 4px; display: grid; gap: 3px; font-size: 13px; color: var(--ph-muted);
  padding: 10px 14px; border-radius: 12px; background: color-mix(in srgb, var(--ph-muted) 10%, transparent); }
.ph-campaign strong { color: inherit; font-weight: 600; }
.ph-state { margin: 0; color: var(--ph-muted); font-size: 14px; font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: center; }
.ph-chip { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ph-amber); border: 1px solid rgba(217, 154, 30, .45); border-radius: 999px; padding: 1px 8px; }
.ph-ctls { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px 8px; width: 100%; margin: auto 0 0; padding-top: 20px; }
.ph-ctls-2 { grid-template-columns: repeat(2, 1fr); max-width: 200px; margin-left: auto; margin-right: auto; }
.ph-avatars { display: flex; }
.ph-avatars .ph-avatar { width: 72px; height: 72px; }
.ph-avatars .ph-avatar + .ph-avatar { margin-left: -16px; box-shadow: 0 0 0 3px var(--ph-bg), 0 0 0 5px var(--ph-go); }
.ph-avatars .ph-avatar-ini { font-size: 24px; }
/* Two classes: .ph-note's own margin: 0 comes later in the file and won. */
.ph-note.ph-center { text-align: center; margin-top: 22px; }
.ph-ctl { display: flex; flex-direction: column; align-items: center; gap: 7px; background: none; border: 0; color: var(--ph-text); cursor: pointer; font: 12px var(--font); padding: 0; }
.ph-ctl-ic { width: 56px; height: 56px; border-radius: 50%; background: var(--ph-key); display: inline-flex; align-items: center; justify-content: center; transition: background var(--fast); }
.ph-ctl:hover .ph-ctl-ic { background: var(--ph-key-hi); }
.ph-ctl.is-on .ph-ctl-ic { background: var(--ph-text); color: var(--ph-bg); }
.ph-ctl-l { color: var(--ph-muted); }
.ph-ctl.is-on .ph-ctl-l { color: var(--ph-text); }
.ph-incall-pad { width: 100%; margin-top: 18px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.ph-incall-pad .ph-key { width: 54px; height: 54px; }
.ph-end-row { display: flex; justify-content: center; margin-top: 22px; }
.ph-answer-row { display: flex; justify-content: space-around; width: 100%; margin-top: auto; padding-top: 24px; }
.ph-answer-row .ph-round { width: 70px; height: 70px; }

/* Warm transfer: the caller waiting, the colleague on the line. */
.ph-consult { align-items: stretch; text-align: left; gap: 10px; }
.ph-leg { display: flex; align-items: center; gap: 14px; padding: 12px; border-radius: 14px; background: var(--ph-bg-2); border: 1px solid var(--ph-line); }
.ph-leg .ph-avatar { width: 46px; height: 46px; }
.ph-leg .ph-avatar-ini { font-size: 16px; }
.ph-leg > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ph-leg strong { font-size: 15px; overflow-wrap: anywhere; }
.ph-leg span { font-size: 13px; color: var(--ph-muted); font-variant-numeric: tabular-nums; }
.ph-leg.is-hold span { color: var(--ph-amber); }
.ph-consult .ph-keys { margin: 4px 0; }
.ph-note { margin: 0; font-size: 13px; color: var(--ph-muted); line-height: 1.45; }
.ph-warn { margin: 0; font-size: 13px; color: #ffb4a8; line-height: 1.45; }
.ph-warn[hidden] { display: none; }

/* Panes: settings and transfer. */
.ph-pane { flex: 1; display: flex; flex-direction: column; gap: 14px; padding: 14px 18px 18px; }
.ph-pane-head { display: flex; align-items: center; gap: 6px; margin-left: -8px; }
.ph-pane-head h3 { margin: 0; font-size: 16px; font-weight: 600; overflow-wrap: anywhere; }
.ph-settings { display: flex; flex-direction: column; gap: 14px; }
.ph-field { display: flex; flex-direction: column; gap: 6px; font-size: 12px; font-weight: 600; letter-spacing: .02em; color: var(--ph-muted); }
.ph-dock select.ph-select, .ph-dock input.ph-input {
  width: 100%; height: 42px; border-radius: 10px; border: 1px solid var(--ph-line); padding: 0 12px;
  background-color: var(--ph-bg-2); color: var(--ph-text); font: 14px var(--font);
}
.ph-dock select.ph-select {
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238d9bb8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
.ph-dock select.ph-select option { background: #142039; color: #eef2f9; }
.ph-dock input.ph-input { font-size: 18px; letter-spacing: .03em; font-variant-numeric: tabular-nums; }
.ph-dock select.ph-select:hover, .ph-dock input.ph-input:hover { border-color: rgba(255, 255, 255, .2); }
.ph-dock select.ph-select:focus, .ph-dock input.ph-input:focus {
  border-color: var(--ph-brass); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold-500, #c9a24a) 20%, transparent);
}
.ph-note-row { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: baseline; margin-top: -6px; }

/* After a campaign call (migration 095): what happened, before the next one.
   The choices are the campaign's own words, one per row, so a long list
   scrolls in the pane rather than squeezing into chips. */
.ph-outcome { gap: 12px; }
.ph-outcome-who { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ph-outcome-who h3 { margin: 2px 0 0; font-size: 19px; font-weight: 600; overflow-wrap: anywhere; }
.ph-outcome-who .ph-sub { margin: 0; overflow-wrap: anywhere; }
.ph-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ph-amber); }
.ph-choices { display: flex; flex-direction: column; gap: 5px; }
.ph-choice {
  position: relative; display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 6px 12px;
  border-radius: 10px; border: 1px solid var(--ph-line); background: var(--ph-bg-2);
  color: var(--ph-text); font-size: 14px; font-weight: 500; letter-spacing: 0; cursor: pointer;
}
.ph-choice:hover { border-color: rgba(255, 255, 255, .2); }
.ph-choice input { flex: none; width: 16px; height: 16px; margin: 0; accent-color: var(--ph-brass); }
.ph-choice:has(input:checked) { border-color: var(--ph-brass); background: color-mix(in srgb, var(--gold-500, #c9a24a) 12%, var(--ph-bg-2)); }
.ph-choice:has(input:focus-visible) { outline: 2px solid var(--ph-brass); outline-offset: 2px; }
.ph-dock textarea.ph-textarea {
  width: 100%; min-height: 52px; padding: 8px 12px; resize: vertical; box-shadow: none;
  border-radius: 10px; border: 1px solid var(--ph-line); background: var(--ph-bg-2);
  color: var(--ph-text); font: 14px/1.4 var(--font); letter-spacing: 0;
}
.ph-dock textarea.ph-textarea:hover { border-color: rgba(255, 255, 255, .2); }
.ph-dock textarea.ph-textarea:focus {
  outline: none; border-color: var(--ph-brass);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold-500, #c9a24a) 20%, transparent);
}
.ph-toggle { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center; cursor: pointer; }
.ph-toggle-text { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.ph-toggle-text strong { font-size: 14px; font-weight: 600; color: var(--ph-text); }
.ph-toggle-text span { color: var(--ph-muted); line-height: 1.4; }
.ph-toggle input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ph-switch { width: 42px; height: 24px; border-radius: 12px; background: #2a3a5a; position: relative; transition: background var(--fast); }
.ph-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: transform var(--fast) var(--ease); }
.ph-toggle input:checked + .ph-switch { background: var(--ph-go); }
.ph-toggle input:checked + .ph-switch::after { transform: translateX(18px); }
.ph-toggle input:focus-visible + .ph-switch { outline: 2px solid var(--ph-brass); outline-offset: 2px; }
.ph-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: -4px; }
.ph-chips[hidden] { display: none; }
.ph-chip-btn { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border-radius: 15px; border: 1px solid var(--ph-line); background: var(--ph-bg-2); color: var(--ph-text); font: 12.5px var(--font); cursor: pointer; }
.ph-chip-btn:hover { border-color: color-mix(in srgb, var(--gold-500, #c9a24a) 50%, transparent); }

/* Lists: recent calls and the team. */
.ph-list { list-style: none; margin: 0; padding: 6px 8px; }
.ph-item { display: flex; align-items: center; gap: 12px; padding: 10px; border-radius: 12px; }
.ph-item:hover { background: var(--ph-bg-2); }
.ph-item-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ph-item-main strong { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ph-item-main > span { font-size: 12px; color: var(--ph-muted); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ph-ext { color: var(--ph-muted); font-weight: 400; }
.ph-dir { flex: none; width: 34px; height: 34px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--ph-key); color: var(--ph-muted); }
.ph-dir.is-ok { color: #5fd49a; } .ph-dir.is-err { color: #ff7b7c; background: rgba(224, 72, 74, .14); }
.ph-dir.is-warn { color: var(--ph-amber); } .ph-dir.is-info { color: #8fb3ec; }
.ph-item-act { flex: none; color: var(--ph-text); background: var(--ph-key); border-radius: 50%; }
.ph-item-act:hover { background: var(--ph-go); color: #fff; }
.team-acts { display: flex; gap: 6px; flex: none; }
.ph-pill-btn { height: 32px; padding: 0 14px; border-radius: 16px; border: 0; background: var(--ph-amber); color: #1a1204; font: 700 12.5px var(--font); cursor: pointer; }
.ph-pill-btn:hover { background: #e8ac33; }
.ph-codes { margin: 4px 18px 16px; font-size: 12px; color: var(--ph-muted); line-height: 1.5; }
.ph-codes b { color: var(--ph-text); font-family: var(--mono); font-weight: 600; }
.ph-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 30px; text-align: center; color: var(--ph-muted); font-size: 13px; }
.ph-empty strong { color: var(--ph-text); font-size: 15px; }
.lamp { flex: none; width: 10px; height: 10px; border-radius: 50%; background: #6b7892; }
.lamp.free { background: #26b573; box-shadow: 0 0 0 3px rgba(38, 181, 115, .18); }
.lamp.busy { background: var(--ph-stop, #e0484a); box-shadow: 0 0 0 3px rgba(224, 72, 74, .18); }
.lamp.ringing { background: var(--ph-amber, #d99a1e); animation: lamp-flash .9s steps(2, start) infinite; }
.lamp.offline { background: transparent; box-shadow: inset 0 0 0 2px #56637d; }
.lamp.dnd { background: #9b72e0; box-shadow: 0 0 0 3px rgba(155, 114, 224, .2); }
@keyframes lamp-flash { to { visibility: hidden; } }

/* The tab bar. */
.ph-tabs { display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1px solid var(--ph-line); background: var(--ph-bg-2); }
.ph-tabs[hidden] { display: none; }
.ph-tab { position: relative; height: 50px; border: 0; background: none; color: var(--ph-muted); font: 600 13px var(--font); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.ph-tab[aria-pressed="true"] { color: var(--ph-text); }
.ph-tab[aria-pressed="true"]::after { content: ""; position: absolute; top: 0; left: 28%; right: 28%; height: 2px; border-radius: 0 0 2px 2px; background: var(--ph-brass); }
.ph-tab-badge { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--ph-stop); color: #fff; font-size: 11px; display: inline-flex; align-items: center; justify-content: center; }

/* Off, connecting, not working. */
.ph-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 28px; text-align: center; }
.ph-hero h3 { margin: 6px 0 0; font-size: 18px; font-weight: 600; }
.ph-hero p { margin: 0; font-size: 14px; color: var(--ph-muted); line-height: 1.5; max-width: 34ch; }
.ph-hero .ph-btn { margin-top: 10px; }
.ph-hero-ic { width: 72px; height: 72px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: var(--ph-brass); background: var(--ph-bg-2); box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold-500, #c9a24a) 45%, transparent), 0 0 0 10px color-mix(in srgb, var(--gold-500, #c9a24a) 6%, transparent); }
.ph-hero-ic.is-busy { animation: ph-breathe 1.6s ease-in-out infinite; }
.ph-hero-ic.is-err { color: #ff8a8b; box-shadow: 0 0 0 1px rgba(224, 72, 74, .5), 0 0 0 10px rgba(224, 72, 74, .07); }
@keyframes ph-breathe { 50% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold-500, #c9a24a) 45%, transparent), 0 0 0 18px color-mix(in srgb, var(--gold-500, #c9a24a) 10%, transparent); } }

/* On a phone: the panel is a sheet across the bottom. */
@media (max-width: 640px) {
  .ph-dock { right: 16px; bottom: 16px; left: 16px; }
  .ph-panel { position: fixed; left: 0; right: 0; bottom: 0; width: auto; height: min(640px, 88vh); max-height: none;
    border-radius: 22px 22px 0 0; transform: none; }
  .ph-dock.is-open .ph-launch { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .ph-panel, .ph-launch, .ph-key, .ph-round { animation: none; transition: none; }
  .ph-avatar-rings, .ph-cap-dot, .ph-hero-ic.is-busy { animation: none !important; }
  .lamp.ringing { animation: none; box-shadow: 0 0 0 3px rgba(217, 154, 30, .35); }
}

/* A8 — a workspace's own brand. The accent arrives as --gold-500/400/600 and
   --on-accent (set from api/branding.py's palette); a logo sits on a white tile
   so a dark logo on a transparent background still shows on the navy. */
.brand-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand-logo { display: inline-grid; place-items: center; height: 32px; min-width: 32px; padding: 3px;
  border-radius: 8px; background: #fff; flex: 0 0 auto; box-shadow: 0 0 0 1px rgba(255, 255, 255, .08); }
.brand-logo img { display: block; max-height: 26px; max-width: 26px; object-fit: contain; }
.brand-logo.wide { padding: 3px 8px; }
.brand-logo.wide img { max-width: 170px; }
.br-logo-big { height: 64px; min-width: 64px; padding: 6px; box-shadow: 0 0 0 1px var(--border); }
.br-logo-big img { max-height: 52px; max-width: 220px; }
.br-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); gap: 24px; align-items: start; }
.br-picker { width: 46px; height: 40px; padding: 2px; border-radius: var(--radius); border: 1px solid var(--border-strong); background: var(--surface); cursor: pointer; }
.br-preview { display: grid; grid-template-columns: 150px 1fr; border-radius: var(--radius-lg); overflow: hidden; border: 1px solid var(--border); background: var(--surface); }
.br-side { background: var(--brand-800); color: #c3cde4; padding: 6px 0 12px; }
.br-side .brand { padding: 12px 12px; font-size: 14px; gap: 8px; }
.br-nav { display: flex; align-items: center; gap: 8px; margin: 2px 8px; padding: 7px 8px; border-radius: 8px; font-size: 13px; }
.br-nav.is-active { background: rgba(255, 255, 255, .08); color: #fff; }
.br-nav.is-active .nav-icon { color: var(--gold-400); }
.br-main { padding: 14px; display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
@media (max-width: 760px) { .br-grid { grid-template-columns: 1fr; } }

/* I2 queue trends. Series colours are the two validated categorical slots
   (blue, orange), redefined for the dark surface rather than inverted. */
.qt { --qt-1: #2a78d6; --qt-2: #eb6834; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .qt { --qt-1: #3987e5; --qt-2: #d95926; } }
:root[data-theme="dark"] .qt { --qt-1: #3987e5; --qt-2: #d95926; }
.qt-body { display: grid; gap: 18px; }
.qt-charts { display: grid; gap: 22px; }
.qt-figure { margin: 0; display: grid; gap: 6px; }
.qt-figure figcaption { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.qt-chart { position: relative; width: 100%; }
/* Grid items default to min-width:auto and so refused to shrink below the
   first 720px drawing: the chart never learnt its real width and the page
   scrolled sideways on a phone (365px too wide, caught by the browser test). */
.qt-body > *, .qt-charts > *, .qt-figure > * { min-width: 0; }
/* The portal has no global [hidden] rule, and display:grid below would show
   an empty tooltip box beside every chart heading (it did). */
.qt-tip[hidden] { display: none; }
.qt-tip {
  position: absolute; top: -6px; transform: translate(-50%, -100%); pointer-events: none;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1); padding: 7px 10px; font-size: 12.5px; display: grid; gap: 2px;
  white-space: nowrap; z-index: 2; font-variant-numeric: tabular-nums;
}
.qt-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12.5px; color: var(--text-2); margin-bottom: 4px; }
.qt-key { display: inline-flex; align-items: center; gap: 6px; }
.qt-swatch { width: 14px; height: 10px; border-radius: 3px; background: var(--c); display: inline-block; }
.qt-swatch.is-dashed { height: 0; border-radius: 0; border-top: 2px dashed var(--c); background: none; }
.qt-details > summary { cursor: pointer; font-size: 14px; font-weight: 600; width: max-content; }
.qt-details[open] > summary { margin-bottom: 10px; }
.qt-byqueue { display: grid; gap: 8px; }

/* The voice for spoken prompts: two voices side by side, each with its samples. */
.vc-body { display: grid; gap: 14px; }
.vc-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); gap: 12px; }
.vc-option { border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; display: grid; gap: 12px; background: var(--surface); }
.vc-option.is-chosen { border-color: var(--gold-500, #c9a24a); box-shadow: 0 0 0 1px var(--gold-500, #c9a24a) inset; }
.vc-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  /* The height of the Use button, so a card showing the In use badge instead
     keeps its Play buttons level with the other card's. */
  min-height: 34px; }
.vc-head strong { font-size: 16px; }
.vc-plays { display: flex; gap: 8px; flex-wrap: wrap; }
.vc-play { min-width: 112px; justify-content: center; }
/* Part 4: the language the samples speak, who speaks each, and Devanagari. */
.vc-hear { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.vc-hear select { width: auto; min-width: 0; max-width: 100%; }
.vc-speakers { margin: 0; line-height: 1.6; overflow-wrap: anywhere; }
.vc-speakers strong { color: var(--text); font-weight: 600; }
.vc-deva { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); }
.vc-deva > .stack-sm { flex: 1 1 260px; min-width: 0; }

/* A8: the workspace's own web address. DNS records are shown as Name / Value
   pairs with their own Copy buttons rather than as a table: a TXT value is
   48 characters of hex, and a table either scrolls sideways or wraps it into
   something nobody can copy correctly by eye on a phone. */
.dm-body { display: grid; gap: 16px; }
.dm-body .banner { margin: 0; }
.dm-body .banner .spinner { flex: none; margin-top: 2px; }
.dm-host { font-family: var(--mono); font-size: 16px; font-weight: 600; overflow-wrap: anywhere; }
.dm-connect-row { display: flex; gap: 8px; flex-wrap: wrap; }
.dm-connect-row input { flex: 1 1 260px; min-width: 0; }
.dm-connect .err:empty { display: none; }
.dm-recs { display: grid; gap: 12px; }
.dm-rec { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; background: var(--surface-2); }
.dm-rec-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.dm-type {
  font-family: var(--mono); font-size: 12px; font-weight: 600; letter-spacing: .03em;
  padding: 2px 9px; border-radius: var(--radius-full); background: var(--surface-3); color: var(--text);
}
.dm-kv { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; gap: 8px 10px; align-items: center; }
.dm-label { font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-3); }
.dm-val {
  font-family: var(--mono); font-size: 13px; line-height: 1.45; overflow-wrap: anywhere;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 7px 10px; user-select: all;
}
.dm-val wbr { display: inline; }
/* break-all for the token only: it wraps as even lines, not at its one hyphen
   ("aidialer-" alone on a line on a phone). On names it left a lone "n" of
   ".in" on the last line, so names break after their dots instead. */
.dm-token { word-break: break-all; }
.dm-copy { min-width: 64px; justify-content: center; }
.dm-hints { margin: 0; padding-left: 18px; display: grid; gap: 4px; max-width: 80ch; }
.dm-result { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; display: grid; gap: 10px; }
.dm-result-head { display: flex; align-items: baseline; gap: 10px; }
.dm-checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.dm-checks li { display: flex; gap: 10px; align-items: center; font-size: 14px; }
.dm-mark {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; font-size: 11px; font-weight: 700;
}
.dm-mark.ok { background: var(--ok-100); color: var(--ok-500); }
.dm-mark.no { background: var(--err-100); color: var(--err-500); }
.dm-problems { margin: 0; padding-left: 18px; display: grid; gap: 4px; color: var(--text-2); max-width: 80ch; }
.dm-details > summary { cursor: pointer; font-size: 14px; font-weight: 600; padding: 4px 0; width: max-content; }
.dm-details[open] > summary { margin-bottom: 10px; }
.dm-actions { display: flex; gap: 8px; flex-wrap: wrap; }
@media (max-width: 560px) {
  .dm-kv { grid-template-columns: minmax(0, 1fr) auto; }
  .dm-label { grid-column: 1 / -1; margin-top: 2px; }
}

/* Room under the last row of every page for the floating phone launcher (60 px
   plus its 24 px margin): without it, scrolled to the end, the launcher sat on
   top of the bottom-right controls (seen covering "Reset branding"). */
.app:has(.ph-dock) .content { padding-bottom: 104px; }

/* Your recordings (IVR menus tab) and the in-browser recorder. */
/* No global [hidden] rule, and .btn and .pill set their own display, so the
   recorder's Stop button and "Recording" pill would show while hidden. */
.rec-panel [hidden], .drawer-error[hidden] { display: none !important; }
.drawer-error {
  margin: 0 0 14px; padding: 10px 12px; border-radius: var(--radius);
  background: var(--err-100); color: var(--err-500); font-size: 13.5px; line-height: 1.45;
}
.rec-panel { display: grid; gap: 14px; }
/* A heading with several actions: on a phone the actions drop to their own
   line, kept to the right, instead of squeezing the title to one word a line
   and pushing the last button off the screen (3px over at 390px, seen in the
   browser test). */
.card-head.wrap { flex-wrap: wrap; row-gap: 10px; }
.card-head.wrap h2 { overflow-wrap: anywhere; }
.card-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }
.rec-body { padding-bottom: 6px; }
.rec-intro { max-width: 70ch; }
.rec-name { overflow-wrap: anywhere; }
.rec-stage {
  display: grid; gap: 14px; padding: 16px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
  transition: border-color var(--fast) var(--ease);
}
.rec-stage.is-recording { border-color: var(--err-500); }
.rec-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rec-timer { font-size: 24px; font-weight: 650; letter-spacing: -.01em; min-width: 4ch; font-variant-numeric: tabular-nums; }
.rec-level { flex: 1 1 120px; min-width: 0; height: 8px; border-radius: var(--radius-full); background: var(--surface-3); overflow: hidden; }
.rec-level > i { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--ok-500); transition: width 90ms linear; }
.rec-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--err-500); display: inline-block; flex: none; }
.btn-primary .rec-dot { background: currentColor; }
.rec-stage.is-recording .rec-live::before { animation: rec-blink 1.2s steps(2, start) infinite; }
@keyframes rec-blink { to { visibility: hidden; } }
.rec-preview { width: 100%; }
.rec-play { min-width: 62px; }
@media (prefers-reduced-motion: reduce) {
  .rec-level > i { transition: none; }
  .rec-stage.is-recording .rec-live::before { animation: none; }
}

/* H6 predictive dialling: the supervisor's live drawer and the agent's cards. */
/* max-content rows: the drawer body has a fixed height, and in a grid a
   scroll container (the agents' .table-wrap) may shrink to nothing, so once
   the content outgrew the drawer the agents table was cut in half (seen in
   the browser test's screenshot, 24 Sep 2026). */
.pd-live { display: grid; gap: 16px; align-content: start; grid-auto-rows: max-content; }
/* Three across, or one under another: auto-fit made two and one on a phone,
   with the last figure alone on its row. */
.pd-figures { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 560px) { .pd-figures { grid-template-columns: 1fr; } }
.pd-figures > * { min-width: 0; }
.pd-figure { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; background: var(--surface-2); }
.pd-value { font-size: 24px; font-weight: 680; letter-spacing: -.01em; margin-top: 4px; font-variant-numeric: tabular-nums; }
.pd-sub { font-size: 14px; margin-top: 4px; }
.pd-answer { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: space-between;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); }
.pd-answer > .stack-sm { min-width: 0; flex: 1 1 220px; }
.pd-quote { margin: 0; padding: 10px 14px; border-left: 3px solid var(--border-strong); background: var(--surface-2);
  border-radius: 0 var(--radius) var(--radius) 0; font-size: 14px; line-height: 1.5; }
/* My status. Two columns from 980px: the agent's own status and phone, then
   what it means for each queue and campaign. Rows, not tables: one fact and
   at most one control per line. */
.ms-page > :empty, .ms-col > :empty { display: none; }
.ms-grid { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 980px) { .ms-grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); } }
.ms-col { display: grid; gap: 16px; min-width: 0; }
.ms-now { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ms-state { display: inline-flex; align-items: center; gap: 10px; font-size: 26px; }
.ms-state::before { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--text-3); flex: none; }
.ms-state.ok::before { background: var(--ok-500); }
.ms-state.warn::before { background: var(--warn-500); }
.ms-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.ms-rows { border-top: 1px solid var(--border); }
.card-head + .ms-rows { border-top: 0; }
.ms-row { display: flex; align-items: center; gap: 12px; padding: 12px 18px; min-height: 60px; }
.ms-row + .ms-row { border-top: 1px solid var(--border); }
.ms-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.ms-row-main strong { overflow-wrap: break-word; }
/* On a phone the status buttons are a two-column grid, so none is left alone
   on a row: the one that matters now (or, with none, the last) takes a row. */
@media (max-width: 480px) {
  .ms-actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ms-actions .btn-primary,
  .ms-actions:not(:has(.btn-primary)) .btn:last-child { grid-column: 1 / -1; }
}
.ms-row .btn, .ms-row .pill { flex: none; }
/* Agent templates on Provider keys: on a phone the pill and button took the
   row and left each name a few letters wide (22 Oct 2026). The name takes the
   whole first line; the pill and button sit under it. */
@media (max-width: 640px) {
  .tpl-row { flex-wrap: wrap; }
  .tpl-row .ms-row-main { flex: 1 1 100%; }
}
.vo-list { border: 1px solid var(--border); border-radius: var(--radius); }
.pd-list { gap: 10px; }
.pd-row > .stack-sm { margin-right: auto; min-width: 0; }
.pd-call { border-color: var(--ok-500); }

/* C4 — renting a number. The kinds are picked like the prompt voices on the
   Branding page (.vc-option): one pattern for "choose one of these". */
/* The rent and verify drawers' contents: one gap between every block, so
   no paragraph runs into the heading or label after it. */
.num-flow { display: grid; gap: 14px; align-content: start; }
.num-flow > p, .num-flow > h3, .num-flow > .field { margin: 0; }
.num-kinds { display: grid; gap: 8px; }
.num-kind {
  display: grid; gap: 2px; text-align: left; padding: 12px 14px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
  color: var(--text); font: inherit;
}
.num-kind:hover { border-color: color-mix(in srgb, var(--gold-500, #c9a24a) 55%, var(--border)); }
.num-kind.is-on { border-color: var(--gold-500, #c9a24a); box-shadow: 0 0 0 1px var(--gold-500, #c9a24a) inset; }
.num-kind:focus-visible { outline: 2px solid var(--gold-500, #c9a24a); outline-offset: 2px; }
.num-verify { display: grid; gap: 8px; justify-items: start; padding: 14px;
  border-radius: var(--radius); background: var(--surface-2, var(--surface)); border: 1px solid var(--border); }
.num-verify p { margin: 0; max-width: 60ch; }
.num-search { display: flex; gap: 10px; align-items: flex-end; }
.num-results { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border);
  border-radius: var(--radius); }
.num-results li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 14px; }
.num-results li + li { border-top: 1px solid var(--border); }

/* An AI agent's hand-overs. Three lines a row, because the drawer is 460px
   and a name, a kind and "Front office (600)" side by side cut each other's
   text off: the name and its remove button; the kind and which one; then the
   line that tells the agent when to choose it. */
.handoff-row {
  display: grid;
  /* 172px: the widest kind, "External number", with the select's arrow. */
  grid-template-columns: minmax(172px, 2fr) minmax(0, 3fr) auto;
  gap: 8px;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.handoff-row > input:first-child { grid-column: 1 / 3; }
.handoff-row > .handoff-dest { grid-column: 2 / -1; }
.handoff-row > input[aria-label="When to use it"], .handoff-row > label { grid-column: 1 / -1; }
.handoff-row select, .handoff-row input:not([type="checkbox"]) { width: 100%; }
/* A setting of the row, not the name of a field. */
.field .handoff-row > label { font-weight: 500; }
@media (max-width: 560px) {
  .handoff-row > select, .handoff-row > .handoff-dest { grid-column: 1 / -1; }
}

/* Reports, by AI agent: the agent and its totals, then one bar per outcome.
   Each bar is a link to the calls behind it. */
.agent-report-head { display: flex; gap: 12px; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; }
.agent-report + .agent-report { margin-top: 24px; padding-top: 24px; border-top: 1px solid var(--border); }
.agent-outcomes { display: grid; gap: 16px; }
.agent-outcome { display: block; color: inherit; text-decoration: none; border-radius: 6px; }
.agent-outcome:hover .small:first-child, .agent-outcome:focus-visible .small:first-child { text-decoration: underline; }
.agent-outcome:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 4px; }

/* Add knowledge: the address-and-button, or the file chooser, under "Start from". */
.kb-source { display: flex; gap: 8px; align-items: center; }
.kb-source[hidden] { display: none; }
.kb-source input[type="text"] { flex: 1 1 auto; min-width: 0; }
.kb-source .btn { flex: 0 0 auto; }
.kb-source input[type="file"] { max-width: 100%; font-size: 13px; }
.kb-note-err { color: var(--err-text); }

/* Knowledge: the notice that the embeddings key no longer works, with its
   "Check again". The button drops under the words when there is no room. */
#kb_key_note .banner { flex-wrap: wrap; }
#kb_key_note .banner-body { flex: 1 1 260px; min-width: 0; }
#kb_key_note .btn { flex: 0 0 auto; }

/* A call's trace: time, what kind of step, what happened. */
.trace { border-top: 1px solid var(--border); }
.trace-turn { font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-2); padding: 12px 0 4px; }
.trace-row { display: grid; grid-template-columns: 58px 150px minmax(0, 1fr); gap: 10px; align-items: start;
  padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.trace-row .pill { white-space: nowrap; }
.trace-row .stack-sm > span { overflow-wrap: anywhere; }
/* --err-text, not --err-500: readable on the dark themes' surfaces too
   (3.6:1 with --err-500, measured by the browser test). */
.trace-bad { color: var(--err-text); }
@media (max-width: 560px) {
  .trace-row { grid-template-columns: 58px minmax(0, 1fr); }
  .trace-row > div { grid-column: 1 / -1; }
}

/* The countries a workspace may call: the chosen ones as a list, each with
   its own remove, above the menu that adds another. */
.country-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); }
.country-list[hidden] { display: none; }
.country-list li { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.country-list li > span { min-width: 0; overflow-wrap: anywhere; }

/* Verification: the form is one readable column; what was sent is a list of
   label and value that folds to one column on a phone. */
.kyc-page { display: grid; gap: 16px; max-width: 760px; }
.kyc-form { max-width: 560px; }
.kyc-form textarea { resize: vertical; }
.kyc-proof select { margin-bottom: 2px; }
.kyc-proof input[type="file"] { max-width: 100%; font-size: 13px; }
.kyc-facts { display: grid; gap: 0; }
.kyc-facts:not(:first-child) { margin-top: 14px; }
.kyc-fact { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 12px; align-items: center;
  padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.kyc-fact:last-child { border-bottom: 0; }
.kyc-fact > span:last-child { overflow-wrap: anywhere; white-space: pre-line; }
.kyc-doc { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
@media (max-width: 560px) {
  .kyc-fact { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* A trunk's rate card: the rows there are, then one line to add a rate. */
.trunk-rates { margin-top: 16px; }
.trunk-rates .table-wrap { margin-top: 6px; }
.rate-rows { list-style: none; margin: 0 0 16px; padding: 0; border-top: 1px solid var(--border); }
.rate-rows li { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 10px; align-items: center;
  padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13.5px; }
.rate-what { min-width: 0; overflow-wrap: anywhere; }
.rate-price { white-space: nowrap; font-variant-numeric: tabular-nums; }
.rate-add { border-top: 1px solid var(--border); padding-top: 14px; }
.rate-list:has(.rate-rows) + .rate-add { border-top: 0; padding-top: 0; }

/* The team report's drawers: outcomes with their share, and each one with
   its note under it. */
.outcome-shares, .outcome-notes { list-style: none; margin: 0; padding: 0; }
.outcome-shares li { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0;
  border-bottom: 1px solid var(--border); font-size: 13.5px; font-variant-numeric: tabular-nums; }
.outcome-notes li { padding: 9px 0; border-bottom: 1px solid var(--border); }
.outcome-line { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; align-items: baseline; }
.outcome-note { margin: 4px 0 0; font-size: 13.5px; overflow-wrap: anywhere; white-space: pre-line; }

/* The team report's day-by-day panel: a block per day, figures as pairs. */
.team-day { padding: 12px 0; border-top: 1px solid var(--border); }
.team-day-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.team-pairs { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px 14px; margin: 10px 0 0; }
.team-pair { min-width: 0; }
.team-pair dt { font-size: 12px; color: var(--text-2); }
.team-pair dd { margin: 2px 0 0; font-size: 14px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

/* The team report's tables: a name stays on one line, and the count that
   opens its outcomes is a small button, not a column. */
/* Room for an ordinary name on one line; a long one (an e-mail address
   standing in for a name) wraps inside it rather than widening the table. */
.report-who { min-width: 132px; }
/* Eight and nine columns in a card: the usual 18px a side per cell is what
   pushed the last column over the card's edge (measured in the browser
   test). 12px keeps every column inside it at a laptop's width. */
.team-table th, .team-table td { padding-left: 12px; padding-right: 12px; }
.team-table th:first-child, .team-table td:first-child { padding-left: 18px; }
.team-table th:last-child, .team-table td:last-child { padding-right: 18px; }
.report-who strong { overflow-wrap: anywhere; }
.team-breaks .stack-sm { align-items: flex-end; }
.team-breaks span { white-space: nowrap; }
.team-count { min-width: 40px; font-variant-numeric: tabular-nums; }

.team-sub { display: block; white-space: nowrap; }

/* People: six columns and up to five actions a row. Measured on 13 Oct 2026:
   with tighter cells and the actions on two lines it needs 1,040px, more than
   the 920px every other table stacks at, and at a 1,280px laptop its card is
   988px, so the last actions ran under the card's edge. It therefore stacks
   earlier than the rest. The min-width is a floor: without one a table
   shrinks a wrapping cell to a single button and piles all five up. */
.people-table th, .people-table td { padding-left: 10px; padding-right: 10px; }
.people-actions { gap: 4px 6px; justify-content: flex-end; flex-wrap: wrap; min-width: 232px; }
@container (max-width: 1060px) {
  table.people-table thead { display: none; }
  table.people-table tr {
    display: block; padding: 12px 14px; border-bottom: 1px solid var(--border);
  }
  table.people-table td {
    display: flex; justify-content: space-between; gap: 16px;
    padding: 4px 0; border: 0; text-align: right;
  }
  table.people-table td .stack-sm { align-items: flex-end; }
  table.people-table td:last-child { padding-top: 10px; }
  table.people-table td::before {
    content: attr(data-label);
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-3); text-align: left;
  }
  .people-actions { min-width: 0; }
}

/* A queue call's outcome form, when the queue lets it be skipped. */
.ph-outcome-actions { display: flex; gap: 8px; }
.ph-outcome-actions .ph-btn-go { flex: 1; }
.ph-outcome-actions .ph-btn:not(.ph-btn-go) { flex: 0 0 auto; width: auto; padding-left: 18px; padding-right: 18px; }
/* Save stays in view while the choices scroll: with a campaign's six (and up
   to twenty) outcomes it sat at the panel's edge on a laptop screen (19 Oct
   2026). The panel colour around it hides what scrolls beneath. */
.ph-outcome > .ph-btn-go,
.ph-outcome > .ph-outcome-actions {
  position: sticky; bottom: 10px; z-index: 1;
  box-shadow: 0 0 0 10px var(--ph-bg), 0 -18px 14px var(--ph-bg);
}

/* My calls: a note is a sentence somebody typed, and wraps inside its cell. */
.my-call-note { max-width: 34ch; overflow-wrap: anywhere; }

/* The queue and the caller's history on the phone panel. Left-aligned and
   allowed to wrap: these are sentences, and the notes keep their line breaks. */
.ph-context { text-align: left; width: 100%; max-height: 132px; overflow-y: auto; }
.ph-context span { overflow-wrap: anywhere; }
.ph-context-notes { white-space: pre-line; color: var(--ph-text); }
/* A call with the queue's notes showing: the same controls in less air, so
   Hang up stays inside the panel at a laptop's height. */
.ph-call-tight { padding-top: 14px; padding-bottom: 16px; }
.ph-call-tight .ph-name { margin-top: 4px; }
.ph-call-tight .ph-context { margin: 10px 0 0; }
.ph-call-tight .ph-ctls { padding-top: 14px; gap: 10px 8px; }
.ph-call-tight .ph-end-row { margin-top: 12px; }
/* Ringing with a campaign's script: the room the picture had goes to the
   script, the queue's notes and the history, so all of it is read before
   Answer is pressed. */
.ph-call-tight .ph-context-ringing { max-height: 290px; }

/* Callbacks to make, on My status. The four actions sit under the number,
   at the left: the phone panel opens over the right of the page. */
.cb-row { flex-direction: column; align-items: flex-start; gap: 8px; }
.cb-row .ms-row-main { flex: none; width: 100%; }
.cb-actions { gap: 6px; flex-wrap: wrap; }
.cb-note { overflow-wrap: anywhere; }
.ph-callback input[type="datetime-local"] { width: 100%; color-scheme: dark; }

/* My calls: the two things to do about a call, one under the other so the
   table keeps its width; and a voicemail row with its player. */
.my-call-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
/* Lined up with the words on the buttons above it, not with their edges. */
.my-call-listed { padding: 4px 12px; }
.vm-row { flex-wrap: wrap; }
.vm-audio { width: min(320px, 100%); height: 36px; }

/* A campaign's report. */
.cr-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.cr-name { margin: 0; font-size: 18px; overflow-wrap: anywhere; }
.cr-two { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); align-items: start; }
.cr-facts { grid-template-columns: minmax(min(150px, 45%), auto) 1fr; }
.cr-share { display: flex; align-items: center; gap: 8px; min-width: 96px; }
.cr-outcomes th, .cr-outcomes td { padding-left: 14px; padding-right: 14px; }
.cr-outcomes td:first-child { overflow-wrap: anywhere; }
.cr-bar { flex: 1; height: 6px; border-radius: var(--radius-full); background: var(--surface-3); overflow: hidden; }
.cr-bar i { display: block; height: 100%; background: var(--gold-500, #c9a24a); border-radius: inherit; }
.cr-table th, .cr-table td { padding-left: 12px; padding-right: 12px; }
.cr-foot { max-width: 90ch; margin: 0; }
/* B4. Six figures in whole rows: three across, two on a tablet, one on a
   phone. auto-fit left one figure alone on a row at common widths. */
.ib-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .ib-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .ib-stats { grid-template-columns: minmax(0, 1fr); } }
.ib-section { display: grid; gap: 12px; margin-top: 28px; }
.ib-title { margin: 0; font-size: 18px; }
.ib-note { max-width: 40ch; overflow-wrap: anywhere; }
.ib-day { white-space: nowrap; }
/* Nine columns of figures: a two-word heading may take two lines, so the
   last column stays inside its card at a laptop's width. */
.ib-report-table th { white-space: normal; vertical-align: bottom; }
/* The script on the phone panel: what the agent reads aloud, so it keeps
   its line breaks and stands apart from the history lines under it. */
.ph-context-script { white-space: pre-line; color: var(--ph-text); padding: 6px 0 8px;
                     border-bottom: 1px solid var(--ph-line); margin-bottom: 4px; }


/* Monthly fees (migration 142): the Billing page's card and the console's
   plans. Amounts line up on the right, as on an invoice. */
.fee-table { width: 100%; border-collapse: collapse; }
.fee-table td, .fee-table th { padding: 10px 0; border-bottom: 1px solid var(--border); text-align: left; font-weight: 400; }
.fee-table td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; padding-left: 16px; }
.fee-table tfoot th, .fee-table tfoot td { border-bottom: 0; font-weight: 600; padding-top: 12px; }
/* A total, not a column heading: the page's th style (capitals, small, grey)
   made it read as one (browser test, 14 Oct 2026). */
.fee-table th { text-transform: none; letter-spacing: normal; font-size: inherit; color: var(--text); background: none; }
.fee-history { margin-top: 18px; display: grid; gap: 6px; }
.fee-history h4 { margin: 0 0 4px; font-size: 13px; color: var(--text-2); font-weight: 600; }
.fee-month { display: grid; grid-template-columns: minmax(0, 9rem) minmax(0, 1fr) auto; gap: 12px; align-items: baseline; font-size: 14px; }
.fee-month .num { font-variant-numeric: tabular-nums; }
/* On a phone the detail takes its own line under the month and amount. */
@media (max-width: 560px) {
  .fee-month { grid-template-columns: minmax(0, 1fr) auto; row-gap: 2px; }
  .fee-month > :nth-child(2) { grid-column: 1 / -1; grid-row: 2; }
}
.pf-actions { justify-content: flex-end; flex-wrap: nowrap; gap: 6px; }
.pf-note { max-width: 32ch; overflow-wrap: anywhere; }
.pr-loss { color: var(--err-500, #c0392b); }
/* Four figures: four across, two on a tablet, one on a phone. */
.pr-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1000px) { .pr-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .pr-stats { grid-template-columns: minmax(0, 1fr); } }
#pr_missing .banner-body { display: grid; gap: 4px; }
/* B7: a campaign's script on the agent's lead card: read aloud, so it keeps
   its line breaks and has room. */
.lead-script { display: grid; gap: 4px; margin-top: 12px; padding: 12px 14px; border-radius: 10px;
               background: var(--surface-2); border: 1px solid var(--border); }
.lead-script p { margin: 0; white-space: pre-line; max-width: 70ch; }
/* Migration 146: the balance notice above every page, and add-on prices. */
.balance-banner { margin-bottom: 16px; }
.balance-banner .banner-body { display: grid; gap: 2px; }
.pf-addons { white-space: nowrap; }
.pf-table td:first-child { min-width: 170px; }
.pf-plan-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }

/* G11: an agent's versions (portal route /agents/<id>/versions). */
.vd-stack { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.vd-change { display: flex; flex-direction: column; gap: 6px; }
.vd-step { margin: 0; font-size: 14px; display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.vd-diff { margin: 0; padding: 8px 0; border-radius: var(--radius-sm); background: var(--surface-2);
  font-family: var(--mono); font-size: 12.5px; line-height: 1.5; overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere; }
.vd-diff span { display: block; padding: 0 10px; color: var(--text); }
.vd-diff b { display: inline-block; width: 1.5ch; font-weight: 600; user-select: none; }
.vd-add { background: var(--ok-100); }
.vd-del { background: var(--err-100); }
.vd-diff .vd-ctx { color: var(--text-2); }
.vd-open { text-align: left; white-space: normal; max-width: 34ch; }
#ab_results td.num, #versions_table td.num { font-variant-numeric: tabular-nums; }
#ab_results th.num, #versions_table th.num { text-align: right; }
#customers_table th.num { text-align: right; }
#customers_table td.num { font-variant-numeric: tabular-nums; }
/* Each line of "In use" is short; wrapped, they read as a stack of fragments. */
#customers_table td[data-label="In use"] span { white-space: nowrap; }
/* A9 step 3: "Powered by AI Dialer" under a partner's brand, if it chose it. */
.brand-wrap { display: flex; flex-direction: column; gap: 6px; }
.brand-powered { font-size: 11px; letter-spacing: .02em; opacity: .72; padding-left: 2px; }

/* ------------------------------------------------------------ invoices */
/* An invoice is a document: a white page with dark ink in either theme, as it
   prints and as the customer files it. Its colours are set here, not taken
   from the theme. */
.invoice-doc { background: #fff; color: #17202f; border: 1px solid var(--border); border-radius: var(--radius);
  padding: 36px 40px; max-width: 920px; width: 100%; font-size: 13.5px; line-height: 1.5; position: relative;
  /* min-width 0: as a grid item it otherwise grew to its line table's width
     and pushed the page 17px past a phone's screen. */
  min-width: 0;
  font-variant-numeric: tabular-nums; }
.invoice-doc .inv-stamp { margin: -12px 0 20px; padding: 8px 12px; border: 1px dashed #b4532a; color: #8a3a17;
  background: #fff6ef; border-radius: 6px; font-weight: 600; font-size: 13px; }
.invoice-doc .inv-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 300px); gap: 28px;
  padding-bottom: 20px; border-bottom: 2px solid #17202f; }
.invoice-doc .inv-meta h2 { margin: 0 0 10px; font-size: 22px; letter-spacing: .01em; color: #17202f; text-align: right; }
.invoice-doc .inv-meta dl { display: grid; grid-template-columns: auto auto; gap: 3px 14px; margin: 0; justify-content: end; }
.invoice-doc .inv-meta dt { color: #5a6578; }
.invoice-doc .inv-meta dd { margin: 0; text-align: right; font-weight: 600; }
.invoice-doc .inv-party { display: flex; flex-direction: column; gap: 1px; min-width: 0; overflow-wrap: anywhere; }
.invoice-doc > .inv-party { margin: 18px 0 20px; }
.invoice-doc .inv-label { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #5a6578; margin-bottom: 3px; }
.invoice-doc .inv-party strong { font-size: 15px; color: #17202f; }
.invoice-doc table { width: 100%; border-collapse: collapse; color: #17202f; }
.invoice-doc .inv-lines th { text-align: left; font-size: 11.5px; font-weight: 700; color: #5a6578; text-transform: uppercase;
  letter-spacing: .05em; border-bottom: 1px solid #c9d0db; padding: 8px 6px; }
.invoice-doc .inv-lines td { border-bottom: 1px solid #e4e8ee; padding: 9px 6px; vertical-align: top; }
.invoice-doc .num { text-align: right; white-space: nowrap; }
.invoice-doc .inv-totals { width: min(340px, 100%); margin: 14px 0 0 auto; }
.invoice-doc .inv-totals th { text-align: left; font-weight: 500; color: #3d4757; padding: 4px 6px; }
.invoice-doc .inv-totals td { padding: 4px 6px; }
.invoice-doc .inv-totals tfoot th, .invoice-doc .inv-totals tfoot td { border-top: 2px solid #17202f; font-weight: 700;
  font-size: 15px; padding-top: 8px; color: #17202f; }
.invoice-doc .inv-words { margin: 14px 0 0; font-style: italic; color: #3d4757; text-align: right; }
.invoice-doc .inv-notes { margin: 18px 0 0; color: #3d4757; }
.invoice-doc .inv-foot { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-top: 32px;
  padding-top: 12px; border-top: 1px solid #e4e8ee; color: #5a6578; font-size: 12px; }
.invoice-doc.is-void { opacity: .75; }
@media (max-width: 640px) {
  .invoice-doc { padding: 20px 16px; }
  .invoice-doc .inv-head { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .invoice-doc .inv-meta h2, .invoice-doc .inv-meta dd { text-align: left; }
  .invoice-doc .inv-meta dl { justify-content: start; }
  /* The lines keep their columns, in a scroller of their own, like the paper. */
  .invoice-doc .inv-lines { display: block; overflow-x: auto; }
}

/* Printing an invoice prints the invoice: no menu, header, buttons, phone or
   toasts, and the page's own margins. */
@media print {
  .sidebar, .header, .no-print, .toasts, .ph-launch, .ph-dock, .drawer, .drawer-scrim { display: none !important; }
  html, body, .app, .main, .content { background: #fff !important; }
  .app { display: block !important; }
  .content { padding: 0 !important; max-width: none !important; }
  .invoice-doc { border: 0; border-radius: 0; padding: 0; max-width: none; }
  @page { size: A4; margin: 16mm 14mm; }
}
