:root {
  color-scheme: light dark;
  --bg: #f4f3ef; --card: #ffffff; --ink: #1d2320; --mute: #66706b; --line: #dfe0da;
  --rail: #14302c; --rail-ink: #cfe3de; --accent: #0f766e; --accent-ink: #ffffff; --accent-soft: #e2f1ee;
  --ok: #15803d; --warn: #b45309; --bad: #b91c1c; --cue: #0f5f8a;
}
@media (prefers-color-scheme: dark) {
  :root { --bg: #131614; --card: #1b1f1d; --ink: #e8ece9; --mute: #97a19c; --line: #2c322f; --rail: #0d1f1c; --rail-ink: #b7d0ca; --accent: #2dd4bf; --accent-ink: #062521; --accent-soft: #143530; --ok: #4ade80; --warn: #f59e0b; --bad: #f87171; --cue: #7cc4ee; }
}
* { box-sizing: border-box; }
body { margin: 0; font: 15px/1.45 system-ui, sans-serif; background: var(--bg); color: var(--ink); }
.shell { display: grid; grid-template-columns: 13rem 1fr; min-height: 100vh; }
#rail { background: var(--rail); color: var(--rail-ink); padding: 1rem .75rem; display: flex; flex-direction: column; gap: 1.25rem; }
.brand { font-weight: 700; letter-spacing: .02em; padding: 0 .5rem; color: #fff; }
#rail nav { display: grid; gap: .15rem; }
#rail a { display: flex; align-items: center; gap: .6rem; padding: .5rem .6rem; border-radius: .4rem; color: inherit; text-decoration: none; }
#rail a svg { width: 1.1rem; height: 1.1rem; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
#rail a:hover { background: rgb(255 255 255 / .07); }
#rail a[aria-current] { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
.content { min-width: 0; }
header { display: flex; align-items: baseline; gap: 1rem; padding: .75rem 1.5rem; border-bottom: 1px solid var(--line); background: var(--card); }
h1 { margin: 0; font-size: 1.05rem; }
#status { color: var(--mute); font-size: .85rem; }
.range { margin-left: auto; font-size: .85rem; color: var(--mute); }
select, textarea, button { font: inherit; }
select { margin-left: .35rem; }
main { display: grid; gap: 1rem; padding: 1.25rem 1.5rem; max-width: 72rem; }
main.live { grid-template-columns: minmax(0, 1fr) 19rem; align-items: start; max-width: none; }
@media (max-width: 900px) { .shell { grid-template-columns: 1fr; } #rail { flex-direction: row; align-items: center; } #rail nav { display: flex; } main.live { grid-template-columns: 1fr; } }

.call, .tile, .panel, .pinned { background: var(--card); border: 1px solid var(--line); border-radius: .6rem; padding: 1rem; box-shadow: 0 1px 2px rgb(0 0 0 / .04); }
.feed { display: grid; gap: 1rem; }
.call h2 { margin: 0 0 .5rem; font-size: .95rem; display: flex; justify-content: space-between; }
.badge { font-size: .75rem; padding: .1rem .55rem; border-radius: 1rem; border: 1px solid var(--line); color: var(--mute); background: var(--card); }
.badge.live { color: var(--ok); border-color: var(--ok); }
.badge.warn { color: var(--warn); border-color: var(--warn); }
.badge.bad { color: var(--bad); border-color: var(--bad); }
.cues { display: grid; gap: .4rem; margin: .5rem 0; }
.cue { border-left: 4px solid var(--cue); padding: .4rem .6rem; background: color-mix(in srgb, var(--cue) 9%, transparent); border-radius: 0 .3rem .3rem 0; }
.cue.missing { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 11%, transparent); }
.cue.done { border-color: var(--ok); background: color-mix(in srgb, var(--ok) 9%, transparent); }
.lines { margin: .5rem 0 0; padding: 0; list-style: none; display: grid; gap: .25rem; }
.lines li { display: grid; grid-template-columns: 5.5rem 1fr; gap: .5rem; }
.who { color: var(--mute); font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; padding-top: .15rem; }
.summary { margin-top: .6rem; color: var(--mute); font-size: .85rem; }
.shaky { text-decoration: underline dotted var(--warn); }

.pinned { position: sticky; top: 1rem; }
.pinned h2 { margin: 0; font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; color: var(--mute); display: flex; justify-content: space-between; }
.progress { height: .4rem; background: var(--line); border-radius: .2rem; margin: .6rem 0; overflow: hidden; }
.progress > div { height: 100%; background: var(--accent); transition: width .3s; }
.items { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
.items li { display: flex; gap: .55rem; align-items: flex-start; padding: .35rem .25rem; border-radius: .3rem; }
.items li::before { content: ""; flex: none; width: 1rem; height: 1rem; margin-top: .1rem; border: 2px solid var(--line); border-radius: .25rem; }
.items li.done { color: var(--mute); text-decoration: line-through; }
.items li.done::before { background: var(--accent); border-color: var(--accent); }
.muted, .tile-note { color: var(--mute); font-size: .8rem; }

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 1rem; }
.tile-label { color: var(--mute); font-size: .8rem; }
.tile-value { font-size: 1.8rem; font-weight: 600; }
.panel h2 { margin: 0 0 .6rem; font-size: .95rem; }
table { width: 100%; border-collapse: collapse; font-size: .9rem; }
th { text-align: left; color: var(--mute); font-weight: 500; font-size: .8rem; }
th, td { padding: .3rem .5rem .3rem 0; border-bottom: 1px solid var(--line); }
.bar { width: 8rem; height: .5rem; background: var(--line); border-radius: .25rem; overflow: hidden; }
.bar-fill { height: 100%; background: var(--accent); }
details { border-top: 1px solid var(--line); padding: .4rem 0; }
summary { cursor: pointer; display: flex; gap: .6rem; align-items: baseline; }
.detail { padding: .5rem 0 .25rem; }
.checks { list-style: none; padding: 0; margin: 0 0 .6rem; display: grid; gap: .2rem; font-size: .85rem; }
.res-pass strong { color: var(--ok); } .res-fail strong { color: var(--bad); } .res-unverified strong { color: var(--warn); } .res-na strong { color: var(--mute); }

.tabs { display: flex; gap: .4rem; }
.tab { border: 1px solid var(--line); background: var(--card); color: var(--ink); border-radius: 1rem; padding: .25rem .8rem; cursor: pointer; }
.tab[aria-selected="true"] { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.issue { background: var(--card); border: 1px solid var(--line); border-radius: .6rem; padding: 1rem; }
.issue h3 { margin: 0 0 .25rem; font-size: 1rem; }
.issue .kind { color: var(--accent); font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; }
.issue p { margin: .25rem 0 .75rem; color: var(--mute); }
.row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.row .spacer { flex: 1; }
.btn { border: 1px solid var(--line); background: var(--card); color: var(--ink); border-radius: .4rem; padding: .3rem .8rem; cursor: pointer; }
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.issue .more { margin-top: .75rem; border-top: 1px solid var(--line); padding-top: .75rem; display: grid; gap: .6rem; }
textarea { width: 100%; min-height: 4.5rem; border: 1px solid var(--line); border-radius: .4rem; padding: .5rem; background: var(--card); color: var(--ink); }

.col { display: grid; gap: 1rem; min-width: 0; }
.askform { display: flex; gap: .5rem; }
.askform input, #insight-q { flex: 1; font: inherit; padding: .5rem .7rem; border: 1px solid var(--line); border-radius: .4rem; background: var(--card); color: var(--ink); }
.call.ai { border-left: 4px solid var(--accent); }
.call.ai.unknown { border-left-color: var(--line); }
.call.ai p { margin: .25rem 0; }
.notes { background: var(--accent-soft); border-radius: .5rem; padding: .7rem .9rem; margin-bottom: .7rem; }
.notes p { margin: .35rem 0; }
.notes .kv { color: var(--mute); font-size: .9rem; margin: .15rem 0; }
.coaching { margin-top: .5rem; border-top: 1px dashed var(--line); padding-top: .4rem; }
.theme { border-top: 1px solid var(--line); padding: .6rem 0; }
.theme p { margin: .25rem 0; }
blockquote { margin: .25rem 0; padding-left: .7rem; border-left: 3px solid var(--line); color: var(--mute); }
.seg { display: flex; gap: .3rem; }
.seg .tab[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
main.live[data-layout="narrow"] { grid-template-columns: 1fr; max-width: 34rem; }
main.live[data-layout="standard"] { max-width: 62rem; }

[hidden] { display: none !important; }

.pbmain { display: grid; grid-template-columns: 16rem minmax(0, 1fr); gap: 1rem; max-width: 80rem; align-items: start; }
@media (max-width: 900px) { .pbmain { grid-template-columns: 1fr; } }
.pblist { display: grid; gap: .75rem; }
.pbul { list-style: none; margin: 0; padding: 0; display: grid; gap: .4rem; }
.pbul li { background: var(--card); border: 1px solid var(--line); border-radius: .5rem; padding: .6rem .75rem; cursor: pointer; display: grid; }
.pbul li.sel { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.pbeditor { display: grid; gap: 1rem; min-width: 0; }
.pbtop h2 { margin: 0; font-size: 1.1rem; }
.pbtop .spacer { flex: 1; }
.pbsec { display: grid; gap: .6rem; }
.pbitem { border: 1px solid var(--line); border-radius: .5rem; padding: .7rem; display: grid; gap: .5rem; background: var(--bg); }
.fld { display: grid; gap: .2rem; }
.fld.inline { display: flex; gap: .5rem; align-items: center; }
.fld-l { color: var(--mute); font-size: .8rem; }
.fld input:not([type="checkbox"]), .fld select, .fld textarea { font: inherit; padding: .4rem .55rem; border: 1px solid var(--line); border-radius: .4rem; background: var(--card); color: var(--ink); width: 100%; }
.pbitem .btn { justify-self: start; }
.errbox { border: 1px solid var(--bad); background: color-mix(in srgb, var(--bad) 8%, transparent); border-radius: .5rem; padding: .6rem .8rem; }
.errbox ul { margin: .3rem 0 0; padding-left: 1.2rem; }
.testout h3 { margin: .8rem 0 .2rem; font-size: .85rem; }
.testout ul { margin: 0; padding-left: 1.2rem; }
pre.tok { background: var(--bg); border: 1px solid var(--line); border-radius: .4rem; padding: .5rem .7rem; overflow-x: auto; white-space: pre-wrap; word-break: break-all; font-size: .8rem; }

.scoreline { display: flex; gap: .6rem; align-items: baseline; margin: .3rem 0; }
.sechead { display: flex; justify-content: space-between; margin: .8rem 0 .2rem; font-size: .85rem; border-bottom: 1px solid var(--line); }
.res-pending strong { color: var(--warn); }
.taskbtns { display: flex; gap: .5rem; flex-wrap: wrap; }
.btn.pass { border-color: var(--ok); color: var(--ok); } .btn.fail { border-color: var(--bad); color: var(--bad); }

svg.trend { width: 100%; height: auto; max-height: 16rem; }
svg.trend .grid { stroke: var(--line); stroke-width: 1; }
svg.trend .axis { fill: var(--mute); font-size: 10px; }
svg.trend .callbar { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1; }
svg.trend .scoreline-svg { fill: none; stroke: var(--ok); stroke-width: 2; }
svg.trend .scoredot { fill: var(--ok); }
th.sortable { cursor: pointer; user-select: none; }
td a { color: var(--accent); }
.filters { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .6rem; align-items: end; }

.callmeta { margin: 0 0 .4rem; }
.chat { margin-top: .6rem; border-top: 1px dashed var(--line); padding-top: .5rem; display: grid; gap: .4rem; }
.chatline { padding: .3rem .5rem; border-radius: .4rem; background: var(--card); border: 1px solid var(--line); font-size: .9rem; }
.chatline.supervisor { border-left: 3px solid var(--accent); }
.chatline.agent { border-left: 3px solid var(--cue); }
.chatline.flagged { border-left-color: var(--warn); background: color-mix(in srgb, var(--warn) 10%, transparent); }

.trendrow { display: flex; gap: .6rem; align-items: center; padding: .2rem 0; }
.trendlabel { flex: 0 0 12rem; text-transform: capitalize; }
svg.spark { height: 1.8rem; flex: 1; max-width: 18rem; }
svg.spark .sparkline { fill: none; stroke: var(--accent); stroke-width: 1.5; }
svg.spark .sparkdot { fill: var(--accent); }
details.theme { border-top: 1px solid var(--line); padding: .5rem 0; }
.evidence { margin: .4rem 0 .4rem .8rem; padding: .4rem .6rem; border-left: 3px solid var(--line); }
.evidence p { margin: .2rem 0; }

.recording audio{width:100%;margin:6px 0}
.lines li.seekable{cursor:pointer}.lines li.seekable:hover{background:rgba(127,127,127,.15)}
.listenbtn{margin-left:auto}

/* The rail's footer is pushed to the bottom so sign out is never adjacent
   to the navigation an agent uses during a call. */
.rail-foot { margin-top: auto; }

/* The new-playbook wizard. */
dialog.wiz { border: 0; border-radius: 10px; padding: 1.25rem 1.4rem; min-width: 26rem; max-width: 32rem; }
dialog.wiz::backdrop { background: rgba(0,0,0,.45); }
dialog.wiz h2 { margin: 0 0 .15rem; font-size: 1.05rem; }
dialog.wiz .wiz-body { margin: .9rem 0; display: flex; flex-direction: column; gap: .5rem; }
dialog.wiz .wiz-body input { width: 100%; padding: .45rem .55rem; box-sizing: border-box; }
dialog.wiz label { font-weight: 600; }
dialog.wiz .wiz-opt { display: grid; grid-template-columns: auto 1fr; gap: .2rem .55rem; align-items: start;
  border: 1px solid #d6dae1; border-radius: 8px; padding: .6rem .7rem; font-weight: 400; cursor: pointer; }
dialog.wiz .wiz-opt:has(input:checked) { border-color: #2563eb; background: #f5f8ff; }
dialog.wiz .wiz-opt input { width: auto; grid-row: span 2; margin-top: .15rem; }
dialog.wiz .wiz-err { color: #b91c1c; margin: .2rem 0 0; }
dialog.wiz .wiz-foot { display: flex; gap: .5rem; justify-content: flex-end; margin-top: 1rem; }
/* oa-mobile-layer */

/* ===========================================================================
   Mobile.
   The existing rules stopped at one 900px breakpoint that only collapsed a
   couple of grids. On an actual phone the result still broke in four ways:
   the rail turned into a row of ten items that ran off the screen, the new
   playbook dialog was 416px wide on a 375px device, transcript lines kept a
   fixed 5.5rem speaker column, and the JS-built tables had nothing to scroll
   inside. Each is handled below.
   =========================================================================== */

/* Nothing should ever cause the page itself to scroll sideways. */
html, body { max-width: 100%; overflow-x: hidden; }
* { -webkit-text-size-adjust: 100%; }

/* Wide content scrolls inside its own box rather than stretching the page. */
.table-scroll, table { max-width: 100%; }

@media (max-width: 900px) {
  /* The rail becomes a horizontal strip. It has ten destinations plus sign
     out, so it must be allowed to scroll rather than squeeze or wrap into
     something unusable. Sticky so navigation is always reachable. */
  #rail {
    position: sticky; top: 0; z-index: 20;
    flex-direction: row; align-items: center; gap: .5rem;
    padding: .5rem .6rem;
    overflow-x: auto; overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  #rail::-webkit-scrollbar { display: none; }
  #rail .brand { flex: none; padding: 0 .4rem 0 0; font-size: .9rem; }
  #rail nav { display: flex; flex-direction: row; gap: .2rem; flex: none; }
  #rail a { flex: none; white-space: nowrap; padding: .55rem .7rem; }
  /* Sign out is pushed to the far end, away from the destinations, so it is
     not caught by a thumb scrolling the strip. */
  .rail-foot { margin-top: 0; margin-left: auto; flex: none; }

  header { padding: .6rem .9rem; flex-wrap: wrap; gap: .35rem 1rem; }
  main { padding: .9rem; gap: .75rem; }
  main.live, main.live[data-layout="standard"], .pbmain { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  /* Speaker above the text instead of beside it: a 5.5rem label column eats
     a third of a narrow screen and leaves transcripts unreadable. */
  .lines li { grid-template-columns: 1fr; gap: .1rem; }
  .lines li > :first-child { font-size: .75rem; color: var(--mute); }

  /* Tables are built in JS with however many columns the data needs, so give
     them somewhere to scroll instead of forcing the page wide. */
  table { display: block; overflow-x: auto; white-space: nowrap; }

  .tiles { grid-template-columns: 1fr; gap: .6rem; }
  .tabs { overflow-x: auto; }
  .tabs > * { flex: none; }

  /* Touch targets. Anything tappable gets to a comfortable size. */
  #rail a, .tabs button, button, summary { min-height: 2.75rem; }
  button { padding-inline: .9rem; }

  h1 { font-size: 1.15rem; }
  main { padding: .75rem .7rem; }
}

/* The wizard, at any width. min-width: 26rem is 416px, wider than a 375px
   phone, so the dialog hung off the edge and its buttons were unreachable. */
dialog.wiz {
  min-width: 0;
  width: min(32rem, calc(100vw - 1.5rem));
  max-width: calc(100vw - 1.5rem);
  max-height: calc(100dvh - 3rem);
  overflow-y: auto;
  box-sizing: border-box;
}
@media (max-width: 640px) {
  dialog.wiz { padding: 1rem; }
  /* Stacked, full-width buttons: three side by side on a narrow screen end
     up too small to hit accurately. */
  dialog.wiz .wiz-foot { flex-direction: column-reverse; }
  dialog.wiz .wiz-foot button { width: 100%; min-height: 2.75rem; }
}

/* Inputs at 16px or larger, otherwise iOS zooms the whole page in on focus
   and the user is left scrolled sideways with no obvious way back. */
@media (max-width: 900px) {
  input, select, textarea, button { font-size: max(1rem, 16px); }
}

/* Respect a reduced-motion preference. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

@media (max-width: 640px) {
  /* auto-fit tries for two 11rem columns at 375px, which leaves the labels
     clipped and the Search button hard to hit. One column instead. */
  .filters { grid-template-columns: 1fr; gap: .5rem; }
  .filters .btn, .filters button { width: 100%; min-height: 2.75rem; }
  .filters .fld.inline { flex-direction: row; align-items: center; gap: .5rem; }
  /* Call rows: the summary line carries a date, agent and up to three
     badges, which wraps badly on a narrow screen. */
  #results summary { display: flex; flex-wrap: wrap; gap: .3rem .5rem; align-items: center; }
}

/* Live page at volume: dense rows that open one at a time. */
.call { padding: .5rem .7rem; }
.call h2 { cursor: pointer; align-items: center; gap: .5rem; }
.call h2:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.call-latest { margin: .15rem 0 0; font-size: .85rem; color: var(--mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.call.open { box-shadow: 0 0 0 2px var(--accent) inset; }
.call.open .call-latest { display: none; }
/* A call that needs a supervisor should be findable without reading. */
.call.attention { border-left: 3px solid var(--bad, #b91c1c); }
#livecount { font-size: .85rem; color: var(--mute); }

/* Horizontal bars for bucketed analytics. */
.hbars { list-style: none; margin: .5rem 0 0; padding: 0; display: grid; gap: .35rem; }
.hbars li { display: grid; grid-template-columns: 7rem 1fr 6rem; gap: .6rem; align-items: center; font-size: .9rem; }
.hbar-track { background: var(--line); border-radius: .2rem; height: .9rem; overflow: hidden; }
.hbar-fill { display: block; height: 100%; background: var(--accent); }
.hbar-v { color: var(--mute); font-variant-numeric: tabular-nums; }
svg .callbar.peak { opacity: 1; }
@media (max-width: 640px) {
  .hbars li { grid-template-columns: 5.5rem 1fr 4.5rem; gap: .4rem; font-size: .8rem; }
}

/* AI agent configuration lists. */
.phrases { display: grid; gap: .4rem; margin: .5rem 0 0; }
.phrase-row { display: grid; grid-template-columns: 1fr auto; gap: .4rem; }
.phrase-row input { padding: .4rem .5rem; }
.panel.attention { border-left: 3px solid #b91c1c; }
@media (max-width: 640px) { .phrase-row { grid-template-columns: 1fr; } }


/* ============================================================================
   Modernisation layer, 2026-11-12.
   Appended rather than merged: later declarations win at equal specificity, so
   the tokens below replace the ones at the top of the file and every page
   picks them up from this one stylesheet. Reversible by truncating from here.

   What was dated was not the structure - it was a flat type scale, 4px radii,
   outline-only badges, a bottle-green rail, and no depth or motion anywhere.
   ========================================================================= */
:root {
  /* The All My Sons palette, taken from allmysons.com rather than guessed:
     #255134 is their theme-color, #143f23 the darker green, #c1ff6a the lime
     accent and #fdf5ec the cream. The modern part is the scale and the depth
     below, not a different brand. */
  --brand-forest: #255134; --brand-dark: #143f23; --brand-lime: #c1ff6a; --brand-cream: #fdf5ec;

  --bg: #fdf5ec; --card: #ffffff; --ink: #13261a; --mute: #6b7a6f; --line: #e7ddd0;
  --rail: #143f23; --rail-ink: #cfe0cd; --accent: #255134; --accent-ink: #ffffff; --accent-soft: #e8f0e6;
  --ok: #15803d; --warn: #b45309; --bad: #b91c1c; --cue: #0f5f8a;

  /* New: a spacing and elevation scale, so padding stops being 1rem everywhere. */
  --s1: .25rem; --s2: .5rem; --s3: .75rem; --s4: 1rem; --s5: 1.5rem; --s6: 2rem;
  --r-sm: .5rem; --r: .75rem; --r-lg: 1rem; --r-full: 999px;
  --shadow-1: 0 1px 2px rgb(15 23 42 / .04), 0 1px 3px rgb(15 23 42 / .06);
  --shadow-2: 0 2px 4px rgb(15 23 42 / .04), 0 8px 16px -4px rgb(15 23 42 / .10);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
  --fast: 120ms cubic-bezier(.4, 0, .2, 1);
}
@media (prefers-color-scheme: dark) {
  :root {
    /* On dark, the lime carries the brand better than the forest green, which
       goes muddy; the forest green becomes the rail instead. */
    --bg: #0d1510; --card: #141f17; --ink: #e6ede7; --mute: #8fa094; --line: #223029;
    --rail: #0a1410; --rail-ink: #c2d6c4; --accent: #c1ff6a; --accent-ink: #10220c; --accent-soft: #1b2a16;
    --ok: #4ade80; --warn: #f59e0b; --bad: #f87171; --cue: #7cc4ee;
    --shadow-1: 0 1px 2px rgb(0 0 0 / .4);
    --shadow-2: 0 2px 4px rgb(0 0 0 / .3), 0 10px 20px -5px rgb(0 0 0 / .5);
  }
}

/* Type: a real scale, and numbers that line up in tables. */
body {
  font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}
h1 { font-size: 1.15rem; font-weight: 650; letter-spacing: -.011em; }
h2 { font-size: .95rem; font-weight: 640; letter-spacing: -.006em; }
h3 { font-size: .875rem; font-weight: 620; }

/* A sticky, slightly translucent header reads as current and keeps the range
   picker reachable on a long page. */
header {
  position: sticky; top: 0; z-index: 20;
  padding: var(--s3) var(--s5);
  background: color-mix(in srgb, var(--card) 86%, transparent);
  backdrop-filter: saturate(1.6) blur(10px);
  align-items: center;
}

/* The rail: near-black rather than green, with the accent used only for the
   current page. */
#rail { padding: var(--s4) var(--s3); gap: var(--s5); }
.brand { font-size: .95rem; letter-spacing: -.01em; padding: var(--s2) var(--s2) 0; }
#rail a {
  border-radius: var(--r-sm); padding: .45rem .6rem; font-size: .9rem;
  transition: background var(--fast), color var(--fast);
}
#rail a:hover { background: rgb(255 255 255 / .06); color: #fff; }
#rail a[aria-current] { background: var(--accent); box-shadow: var(--shadow-1); }

/* Surfaces: larger radii and layered shadow instead of a hairline box. */
.call, .tile, .panel, .pinned {
  border-radius: var(--r); padding: var(--s4) var(--s5);
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--fast), border-color var(--fast);
}
.call:hover { box-shadow: var(--shadow-2); }

/* Badges: soft fills. An outline pill on an outline card was the single most
   dated thing on the page. */
.badge {
  border: 0; border-radius: var(--r-full); padding: .15rem .6rem;
  font-size: .75rem; font-weight: 560;
  background: color-mix(in srgb, var(--mute) 14%, transparent);
  color: var(--mute);
}
.badge.live { background: color-mix(in srgb, var(--ok) 16%, transparent); color: var(--ok); }
.badge.warn { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
.badge.bad  { background: color-mix(in srgb, var(--bad) 16%, transparent); color: var(--bad); }

/* Buttons and inputs: a consistent control height, a real focus ring. */
.btn {
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: var(--r-sm); padding: .4rem .8rem; font-size: .875rem; font-weight: 550;
  cursor: pointer; transition: background var(--fast), border-color var(--fast), box-shadow var(--fast);
}
.btn:hover { background: color-mix(in srgb, var(--ink) 4%, var(--card)); border-color: color-mix(in srgb, var(--ink) 18%, var(--line)); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); box-shadow: var(--shadow-1); }
.btn.primary:hover { background: color-mix(in srgb, #000 10%, var(--accent)); }
.btn:disabled { opacity: .5; cursor: default; }
input, select, textarea {
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: .4rem .55rem;
  background: var(--card); color: var(--ink); transition: border-color var(--fast), box-shadow var(--fast);
}
:is(input, select, textarea, .btn, #rail a, summary):focus-visible {
  outline: none; box-shadow: var(--ring); border-color: var(--accent);
}

/* Cues keep their left bar but lose the hard corner. */
.cue { border-radius: var(--r-sm); border-left-width: 3px; padding: .45rem .65rem; }

/* Tables: lighter rules, a quiet header, and a hover row. */
table { border-collapse: separate; border-spacing: 0; }
th {
  font-size: .75rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--mute); font-weight: 600;
}
td, th { border-bottom: 1px solid var(--line); padding: .5rem .6rem; }
tbody tr { transition: background var(--fast); }
tbody tr:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }

/* Horizontal bars, used by the direction and branch panels. */
.hbars { display: grid; gap: var(--s2); margin: var(--s3) 0 0; padding: 0; list-style: none; }
.hbars li { display: grid; grid-template-columns: 9rem 1fr auto; align-items: center; gap: var(--s3); }
.hbar-track { background: color-mix(in srgb, var(--ink) 7%, transparent); border-radius: var(--r-full); height: .5rem; overflow: hidden; }
.hbar-fill {
  display: block; height: 100%; border-radius: var(--r-full);
  background: linear-gradient(90deg, var(--brand-forest), var(--brand-lime));
  transition: width 400ms cubic-bezier(.4, 0, .2, 1);
}
.hbar-l { font-size: .85rem; color: var(--ink); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.hbar-l:hover { color: var(--accent); text-decoration: underline; }
.hbar-v { font-size: .8rem; color: var(--mute); }

main { gap: var(--s5); padding: var(--s5); }
.feed { gap: var(--s4); }
.muted { color: var(--mute); }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* The live board: traffic shape above the call feed. */
.liveboard { display: grid; gap: var(--s4); }
.livetiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); gap: var(--s2); }
.livetile {
  display: grid; gap: .1rem; padding: var(--s3);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.livetile strong { font-size: 1.5rem; font-weight: 640; letter-spacing: -.02em; line-height: 1.1; }
.livetile span { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; color: var(--mute); }
.livetile.warn { background: color-mix(in srgb, var(--warn) 12%, transparent); }
.livetile.warn strong { color: var(--warn); }
.liveboard-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: var(--s5); }
.liveboard-chart h3 { margin: 0 0 var(--s1); color: var(--mute); font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; }
.liveboard-chart .hbars li { grid-template-columns: 7rem 1fr auto; }

.spark { display: flex; align-items: flex-end; gap: 2px; height: 3rem; position: relative; }
.spark-bar {
  flex: 1; min-width: 2px; border-radius: 2px 2px 0 0;
  background: linear-gradient(180deg, var(--brand-lime), var(--brand-forest));
  transition: height 300ms cubic-bezier(.4, 0, .2, 1);
}
.spark-peak { position: absolute; top: -.2rem; right: 0; font-size: .7rem; }
@media (max-width: 640px) {
  .liveboard-charts { grid-template-columns: 1fr; }
  .livetile strong { font-size: 1.25rem; }
}

/* A live call is the brand green on cream, and the lime on dark, so "live"
   reads as the house colour rather than a generic success green. */
.badge.live { background: color-mix(in srgb, var(--brand-forest) 14%, transparent); color: var(--brand-forest); }
@media (prefers-color-scheme: dark) {
  .badge.live { background: color-mix(in srgb, var(--brand-lime) 18%, transparent); color: var(--brand-lime); }
}
.livetile { background: color-mix(in srgb, var(--brand-forest) 7%, transparent); }
.livetile strong { color: var(--brand-forest); }
@media (prefers-color-scheme: dark) { .livetile strong { color: var(--brand-lime); } }
.livetile.warn strong { color: var(--warn); }

/* Direction and connected time on each live row. */
.dirbadge { text-transform: capitalize; }
.dirbadge.inbound  { background: color-mix(in srgb, var(--cue) 15%, transparent); color: var(--cue); }
.dirbadge.outbound { background: color-mix(in srgb, var(--brand-forest) 16%, transparent); color: var(--brand-forest); }
.dirbadge.internal { background: color-mix(in srgb, var(--mute) 16%, transparent); color: var(--mute); }
@media (prefers-color-scheme: dark) {
  .dirbadge.outbound { background: color-mix(in srgb, var(--brand-lime) 18%, transparent); color: var(--brand-lime); }
}
.dur { font-variant-numeric: tabular-nums; min-width: 3.4rem; text-align: center; }
.dur.warn { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }

/* The hub and spokes: the PBX at the centre, a node per branch with calls up. */
.hub { margin: var(--s2) 0; }
.hubsvg { width: 100%; height: auto; display: block; max-height: 62vh; }
.hub-core { fill: var(--brand-forest); stroke: color-mix(in srgb, var(--brand-lime) 55%, transparent); stroke-width: 2; }
.hub-core.idle { fill: color-mix(in srgb, var(--ink) 12%, transparent); stroke: none; }
.hub-core-n { fill: #fff; font-size: 30px; font-weight: 650; text-anchor: middle; }
.hub-core-label { fill: color-mix(in srgb, #fff 78%, transparent); font-size: 12px; text-anchor: middle;
                  text-transform: uppercase; letter-spacing: .06em; }
.hub-core.idle + .hub-core-label { fill: var(--mute); }
.hub-spoke { stroke: color-mix(in srgb, var(--brand-forest) 45%, transparent); stroke-linecap: round;
             stroke-dasharray: 5 7; animation: hubflow 1.4s linear infinite; }
@keyframes hubflow { to { stroke-dashoffset: -12; } }
.hub-dot { fill: var(--card); stroke: var(--brand-forest); stroke-width: 2.5;
           transition: fill var(--fast), stroke var(--fast); }
.hub-dot.attention { stroke: var(--warn); fill: color-mix(in srgb, var(--warn) 16%, var(--card)); }
.hub-dot-n { fill: var(--ink); font-size: 13px; font-weight: 640; text-anchor: middle; }
.hub-label { fill: var(--mute); font-size: 12px; }
.hub-node { cursor: pointer; }
.hub-node:hover .hub-dot { fill: color-mix(in srgb, var(--brand-lime) 30%, var(--card)); }
.hub-node:focus-visible { outline: none; }
.hub-node:focus-visible .hub-dot { stroke: var(--accent); stroke-width: 4; }
.hub-note { margin: 0; font-size: .8rem; text-align: center; }
@media (prefers-color-scheme: dark) {
  .hub-dot { stroke: var(--brand-lime); }
  .hub-spoke { stroke: color-mix(in srgb, var(--brand-lime) 40%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .hub-spoke { animation: none; stroke-dasharray: none; } }
/* An ended row fades back rather than vanishing under the pointer. */
.call.ended { opacity: .55; }

/* Drill-down hub: a call node carries its own running time. */
.hub-sublabel { fill: var(--mute); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; }
.hub-centre { cursor: default; }
.hub-node.hub-centre { cursor: pointer; }
.hub-node.hub-centre:hover .hub-core { stroke: var(--brand-lime); stroke-width: 4; }
.hub-node.hub-centre:focus-visible .hub-core { stroke: var(--accent); stroke-width: 4; }
.hub-core-label.idle { fill: var(--mute); }
.hub-dot.dir-inbound { stroke: var(--cue); }
.hub-dot.dir-outbound { stroke: var(--brand-forest); }
.hub-dot.dir-internal { stroke: var(--mute); }
.hub-dot.attention { stroke: var(--warn); fill: color-mix(in srgb, var(--warn) 16%, var(--card)); }
@media (prefers-color-scheme: dark) {
  .hub-dot.dir-outbound { stroke: var(--brand-lime); }
}
/* A card held out of the document until its node is picked. */
.call.detached { display: none; }
#calldetail .call { margin-top: var(--s2); }
