/* APX Simulator UI. Plain CSS, no build step, no external assets: it has to
   work offline at a meeting. Colours, spacing and type are tokens on :root;
   the dark palette follows the OS unless the header's theme button pins one. */
:root {
  color-scheme: light;
  --bg: #f5f6f8;
  --panel: #ffffff;
  --panel-2: #f0f2f5;
  --border: #d6dbe2;
  --text: #1c2330;
  --muted: #586374;
  --accent: #1f6feb;
  --accent-soft: #e3edfd;
  --btn: #1f6feb;
  --btn-text: #ffffff;
  --focus: #1f6feb;
  --ok: #1a7f37;
  --ok-soft: #dcf3e3;
  --warn: #8a5c00;
  --warn-soft: #fbefd0;
  --bad: #c62828;
  --bad-soft: #fde2e1;
  --event: #6f42c1;
  --event-soft: #ece2fd;
  --code-bg: #f6f8fa;
  --json-key: #0550ae;
  --json-str: #0a3069;
  --json-num: #953800;
  --json-lit: #8250df;
  --json-punct: #57606a;
  --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .08);

  --radius: 8px;
  --radius-sm: 6px;
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 40px;
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-md: 14px;
  --fs-lg: 17px;
  --fs-xl: 20px;
  --fs-2xl: 26px;
  --mono: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0f1419; --panel: #161b22; --panel-2: #1c232c; --border: #2d3540; --text: #e6edf3; --muted: #9aa6b5;
    --accent: #6ea2ff; --accent-soft: #1b2a44; --btn: #2f6fe0; --btn-text: #ffffff; --focus: #6ea2ff;
    --ok: #3fb950; --ok-soft: #12301c; --warn: #d29922; --warn-soft: #33270b;
    --bad: #f85149; --bad-soft: #3a1414; --event: #d2a8ff; --event-soft: #2a1f3d; --code-bg: #0d1117;
    --json-key: #79c0ff; --json-str: #a5d6ff; --json-num: #ffa657; --json-lit: #d2a8ff; --json-punct: #8b949e;
    --shadow: 0 1px 3px rgba(0, 0, 0, .4);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f1419; --panel: #161b22; --panel-2: #1c232c; --border: #2d3540; --text: #e6edf3; --muted: #9aa6b5;
  --accent: #6ea2ff; --accent-soft: #1b2a44; --btn: #2f6fe0; --btn-text: #ffffff; --focus: #6ea2ff;
  --ok: #3fb950; --ok-soft: #12301c; --warn: #d29922; --warn-soft: #33270b;
  --bad: #f85149; --bad-soft: #3a1414; --event: #d2a8ff; --event-soft: #2a1f3d; --code-bg: #0d1117;
  --json-key: #79c0ff; --json-str: #a5d6ff; --json-num: #ffa657; --json-lit: #d2a8ff; --json-punct: #8b949e;
  --shadow: 0 1px 3px rgba(0, 0, 0, .4);
}

* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body { background: var(--bg); color: var(--text); font: var(--fs-md)/1.45 var(--sans); }
button, input, select, textarea { font: inherit; color: inherit; }
button {
  background: var(--btn); color: var(--btn-text); border: 1px solid transparent; border-radius: var(--radius-sm);
  padding: 5px 11px; cursor: pointer; white-space: nowrap;
}
button:hover:not(:disabled) { filter: brightness(1.1); }
button:disabled { opacity: .5; cursor: default; }
button.ghost { background: transparent; color: var(--text); border-color: var(--border); }
button.ghost:hover:not(:disabled) { background: var(--panel-2); filter: none; }
button.danger { background: transparent; color: var(--bad); border-color: var(--border); }
button.danger:hover:not(:disabled) { background: var(--bad-soft); filter: none; }
button.small { padding: 2px 7px; font-size: var(--fs-xs); }
button.busy { cursor: progress; }
input, select, textarea { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 5px 8px; min-width: 0; }
textarea { font-family: var(--mono); font-size: 12.5px; width: 100%; resize: vertical; min-height: 60px; }
textarea.prose { font-family: var(--sans); font-size: var(--fs-md); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: 0; border-color: var(--focus); }
summary:focus-visible { outline-offset: 1px; border-radius: 3px; }
.invalid { border-color: var(--bad) !important; background: var(--bad-soft) !important; }
h1, h2, h3 { margin: 0; line-height: 1.25; }
code, .mono { font-family: var(--mono); font-size: 12.5px; }
.muted { color: var(--muted); }
.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; }

/* ---------- top bar ---------- */
.topbar {
  z-index: 10; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-2) var(--sp-3); background: var(--panel); border-bottom: 1px solid var(--border); box-shadow: var(--shadow);
}
.brand { display: flex; align-items: center; gap: var(--sp-2); font-weight: 600; font-size: 16px; }
.logo { background: var(--btn); color: var(--btn-text); border-radius: var(--radius-sm); padding: 2px 7px; font-weight: 700; letter-spacing: .5px; }
.edition {
  font-size: var(--fs-xs); font-weight: 600; color: var(--muted); border: 1px solid var(--border); border-radius: 999px;
  padding: 1px 8px; white-space: nowrap; font-family: var(--mono);
}
.edition:empty { display: none; }
.tabs { display: flex; gap: var(--sp-1); background: var(--panel-2); padding: 3px; border-radius: var(--radius); }
.tabs button { background: transparent; color: var(--muted); padding: 5px 10px; }
.tabs button:hover:not(.active) { color: var(--text); filter: none; }
.tabs button.active { background: var(--panel); color: var(--text); box-shadow: var(--shadow); font-weight: 600; }
.world { display: flex; align-items: center; gap: 6px; }
.world label { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: var(--fs-sm); }
.world select { max-width: 190px; color: var(--text); }
.clock { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.clock-face { display: flex; align-items: center; gap: var(--sp-2); padding: 3px 10px 3px 8px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel-2); }
.clock-now { font-family: var(--mono); font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.clock-buttons { display: flex; gap: 0; }
.clock-buttons button { padding: 3px 6px; font-size: var(--fs-xs); background: transparent; color: var(--text); border-color: var(--border); border-radius: 0; margin-left: -1px; }
.clock-buttons button:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); margin-left: 0; }
.clock-buttons button:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.clock-buttons button:hover:not(:disabled) { background: var(--panel-2); filter: none; }
.run-state { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
.run-state::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
.run-state.live::before { background: var(--ok); }
.run-state.busy { color: var(--accent); }
.run-state.busy::before { background: var(--accent); animation: pulse 1s ease-in-out infinite; }
.run-state.offline { color: var(--bad); }
.run-state.offline::before { background: var(--bad); }
@keyframes pulse { 50% { opacity: .3; } }
.header-end { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; flex-wrap: wrap; }
.pills { display: flex; gap: 6px; flex-wrap: wrap; }
.pill { background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; }
.pill b { color: var(--text); font-variant-numeric: tabular-nums; }
.pill.bad { background: var(--bad-soft); color: var(--bad); border-color: transparent; }
.theme-toggle { min-width: 48px; }
.offline-banner { background: var(--bad-soft); color: var(--bad); padding: var(--sp-2) var(--sp-4); font-weight: 600; text-align: center; border-bottom: 1px solid var(--border); }
.offline-banner[hidden] { display: none; }
/* Only in the static build (web/build.mjs): the page runs the simulator itself. */
.static-banner { background: var(--accent-soft); color: var(--text); padding: var(--sp-2) var(--sp-4); text-align: center; border-bottom: 1px solid var(--border); font-size: 0.9em; }
.static-banner a { color: var(--accent); }
.presenting .static-banner { display: none; }

main { padding: var(--sp-4); max-width: 2200px; margin: 0 auto; }
.view { display: none; }
.view.active { display: block; }

/* ---------- shared pieces ---------- */
.panel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); min-width: 0; }
.panel-head { display: flex; align-items: center; gap: var(--sp-2); padding: 10px 14px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.panel-body { padding: var(--sp-3) 14px; }
.stack { display: flex; flex-direction: column; gap: 10px; }
.row { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.grow { flex: 1; }
.badge { display: inline-block; border-radius: 5px; padding: 1px 7px; font-size: var(--fs-xs); font-weight: 600; font-family: var(--mono); flex: none; }
.badge.k-request { background: var(--accent-soft); color: var(--accent); }
.badge.k-inject { background: var(--warn-soft); color: var(--warn); }
.badge.k-events, .badge.k-deliveries { background: var(--event-soft); color: var(--event); }
.badge.k-clock, .badge.k-note, .badge.k-state, .badge.k-receiver, .badge.k-reset { background: var(--panel-2); color: var(--muted); }
.status { font-family: var(--mono); font-weight: 700; border-radius: 5px; padding: 1px 7px; }
.status.s2, .status.s3 { background: var(--ok-soft); color: var(--ok); }
.status.s4 { background: var(--warn-soft); color: var(--warn); }
.status.s5 { background: var(--bad-soft); color: var(--bad); }
.verdict-ok { color: var(--ok); font-weight: 700; }
.verdict-bad { color: var(--bad); font-weight: 700; }
.mark-ok, .mark-bad, .mark-next, .mark-none {
  display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%;
  font-size: 11px; font-weight: 700; line-height: 1; flex: none;
}
.mark-ok { background: var(--ok-soft); color: var(--ok); }
.mark-bad { background: var(--bad-soft); color: var(--bad); }
.mark-next { background: var(--accent-soft); color: var(--accent); }
.mark-none { border: 1px solid var(--border); }
details > summary { cursor: pointer; color: var(--muted); user-select: none; }
.field { display: flex; flex-direction: column; gap: 3px; }
.field > span { font-size: var(--fs-xs); color: var(--muted); font-weight: 600; }
.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
.empty { padding: var(--sp-6) 20px; text-align: center; color: var(--muted); }
.empty h2 { color: var(--text); margin-bottom: var(--sp-2); }
.empty p { max-width: 640px; margin: var(--sp-2) auto; }
.loading { padding: var(--sp-5); color: var(--muted); display: flex; align-items: center; gap: 10px; justify-content: center; }
.loading::before {
  content: ""; width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.error-box { padding: var(--sp-3) 14px; background: var(--bad-soft); color: var(--bad); border-radius: var(--radius-sm); font-weight: 600; }
.toasts { position: fixed; bottom: var(--sp-4); right: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2); z-index: 50; }
.toast { background: var(--text); color: var(--bg); padding: var(--sp-2) 14px; border-radius: var(--radius-sm); box-shadow: var(--shadow); max-width: 420px; }
.toast.bad { background: var(--bad); color: #fff; }
.event-row { display: grid; grid-template-columns: 70px 1fr; gap: var(--sp-1) 10px; padding: 6px 0; border-top: 1px dashed var(--border); }
.event-row:first-child { border-top: 0; }
.ev { padding: 6px 0; border-top: 1px dashed var(--border); }
.ev:first-child { border-top: 0; }
.ev > summary { overflow-wrap: anywhere; }
.ev .json-box { margin-top: 6px; }
.event-type { font-family: var(--mono); font-size: 12.5px; font-weight: 600; color: var(--event); }

/* ---------- JSON viewer ---------- */
.json-box { position: relative; min-width: 0; }
.json-tools { position: absolute; top: 6px; right: 18px; display: flex; gap: var(--sp-1); opacity: .55; transition: opacity .15s; z-index: 1; }
.json-box:hover .json-tools, .json-tools:focus-within { opacity: 1; }
.json-tools button { background: var(--panel); color: var(--muted); border-color: var(--border); padding: 1px 7px; font-size: 11px; }
.json-tools button:hover:not(:disabled) { color: var(--text); filter: none; }
pre.json {
  margin: 0; padding: 10px 12px; background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  font: 12px/1.5 var(--mono); overflow: auto; max-height: 420px; white-space: pre;
}
.json-box.tall pre.json { max-height: none; }
.json .k { color: var(--json-key); }
.json .s { color: var(--json-str); }
.json .n { color: var(--json-num); }
.json .l { color: var(--json-lit); }
.json .p { color: var(--json-punct); }
.jt-kids { padding-left: 2ch; }
.json details { display: block; }
.json details > summary { list-style: none; color: inherit; position: relative; user-select: text; display: block; }
.json details > summary::-webkit-details-marker { display: none; }
.json details > summary::before {
  content: "▾"; position: absolute; left: -1.6ch; color: var(--json-punct); font-size: 10px; top: 1px; user-select: none;
}
.json details:not([open]) > summary::before { content: "▸"; }
.json details > summary:hover { background: var(--panel-2); }
.json .fold { display: none; color: var(--muted); font-style: italic; }
.json details:not([open]) > summary .fold { display: inline; }
pre.json.tree { padding-left: calc(12px + 1.6ch); }

/* ---------- build ---------- */
.build { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--sp-4); align-items: start; }
.build > .main { min-width: 0; }
.side .item { padding: var(--sp-2) var(--sp-3); border-top: 1px solid var(--border); cursor: pointer; }
.side .item:hover { background: var(--panel-2); }
.side .item.active { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.side .item .t { font-weight: 600; font-size: var(--fs-sm); }
.side .item .m { font-size: var(--fs-xs); color: var(--muted); overflow-wrap: anywhere; }
.steps { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-3); }
.step { border-left: 4px solid var(--border); }
.step.ok { border-left-color: var(--ok); }
.step.bad { border-left-color: var(--bad); }
.step.next { border-left-color: var(--accent); }
.step-head { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3); cursor: pointer; min-width: 0; }
.step-head:hover { background: var(--panel-2); }
.step-head .idx { color: var(--muted); font-family: var(--mono); width: 26px; text-align: right; flex: none; }
.step-head .name { font-weight: 600; flex: none; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.step-head .sum { color: var(--muted); font-family: var(--mono); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.step-head .tools { margin-left: auto; display: flex; gap: var(--sp-1); flex: none; align-items: center; }
.step-body { padding: var(--sp-1) var(--sp-3) var(--sp-3) 46px; display: flex; flex-direction: column; gap: 10px; }
.result { background: var(--panel-2); border-radius: var(--radius-sm); padding: var(--sp-2) 10px; display: flex; flex-direction: column; gap: 6px; }
.add-bar { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; align-items: center; }
.run-summary { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; margin-top: var(--sp-3); }
.meter { flex: 0 1 220px; height: 6px; background: var(--panel-2); border-radius: 3px; overflow: hidden; display: flex; }
.meter > .ok { background: var(--ok); }
.meter > .bad { background: var(--bad); }

/* ---------- present ---------- */
.present { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: var(--sp-4); align-items: start; }
.timeline { position: sticky; top: var(--sp-4); max-height: calc(100vh - 2 * var(--sp-4)); overflow: auto; }
.timeline .tl {
  display: flex; gap: var(--sp-2); align-items: flex-start; padding: 7px var(--sp-3); border-top: 1px solid var(--border);
  font-size: var(--fs-sm); background: none; color: inherit; border-radius: 0; width: 100%; text-align: left; white-space: normal;
  border-left: 0; border-right: 0; border-bottom: 0;
}
.timeline .tl:not(:disabled):hover { background: var(--panel-2); filter: none; }
.timeline .tl:disabled { opacity: 1; cursor: default; color: var(--muted); }
.timeline .tl.current { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); color: var(--text); }
.timeline .tl .n { color: var(--muted); font-family: var(--mono); width: 22px; flex: none; text-align: right; padding-top: 1px; }
.stage { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.stage-intro { display: flex; flex-direction: column; gap: 10px; }
.stage-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.stage-title { font-size: var(--fs-2xl); font-weight: 700; line-height: 1.2; }
.narration { font-size: var(--fs-lg); line-height: 1.55; max-width: 900px; margin: 0; }
.actor { display: inline-flex; align-items: center; gap: 6px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px; font-size: var(--fs-sm); }
.call { font-family: var(--mono); font-size: 16px; font-weight: 600; word-break: break-all; }
.big-status { font-size: var(--fs-xl); }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 14px; align-items: start; }
.kbd { font-family: var(--mono); font-size: 11px; border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px; color: var(--muted); }
.progress { height: 4px; background: var(--panel-2); border-radius: 2px; overflow: hidden; }
.progress > div { height: 100%; background: var(--accent); transition: width .3s; }
.finished { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; padding: var(--sp-3) 14px; border-radius: var(--radius); font-weight: 600; }
.finished.ok { background: var(--ok-soft); color: var(--ok); }
.finished.bad { background: var(--bad-soft); color: var(--bad); }
.picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--sp-3); margin-top: var(--sp-4); text-align: left; }
.scenario-card {
  display: flex; flex-direction: column; gap: 6px; align-items: stretch; text-align: left; white-space: normal;
  background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px;
}
.scenario-card:hover:not(:disabled) { border-color: var(--accent); filter: none; box-shadow: var(--shadow); }
.scenario-card .t { font-weight: 700; font-size: 15px; line-height: 1.3; }
.scenario-card .d { color: var(--muted); font-size: var(--fs-sm); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.scenario-card .m { font-size: var(--fs-xs); color: var(--muted); font-family: var(--mono); }
.world-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2); margin-top: var(--sp-4); }
.world-chip { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); border-radius: 999px; padding: 4px 12px; font-size: var(--fs-sm); font-family: var(--mono); }
.world-chip:hover { border-color: var(--accent); filter: none; }
.world-chip.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.no-demo { margin-top: var(--sp-5); }
.no-demo .world-desc { font-size: var(--fs-sm); }
.picker-section { text-align: left; margin-top: var(--sp-5); }
.picker-section h3 { font-size: 17px; margin: 0; }
.picker-section .section-note { margin: var(--sp-1) 0 0; max-width: none; font-size: var(--fs-sm); }
.picker-section .picker { margin-top: var(--sp-3); }
.world-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-2); margin-top: var(--sp-3); }
.world-tile { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; text-align: left; white-space: normal; background: var(--panel-2); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); }
.world-tile:hover { border-color: var(--accent); filter: none; }
.world-tile .t { font-family: var(--mono); font-weight: 700; }
.world-tile .m { font-size: var(--fs-sm); }
.world-tile .d { font-size: var(--fs-xs); color: var(--muted); }
.kind-group { margin-top: var(--sp-3); }
.kind-group h4 { margin: 0 0 var(--sp-1); font-size: var(--fs-sm); color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
.vet-rows { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.vet-row { display: flex; align-items: baseline; gap: var(--sp-3); text-align: left; background: var(--panel); color: var(--text); border: 0; border-bottom: 1px solid var(--border); border-radius: 0; padding: 7px var(--sp-3); }
.vet-row:last-child { border-bottom: 0; }
.vet-row:hover { background: var(--accent-soft); filter: none; }
.vet-row .vid { font-family: var(--mono); font-size: var(--fs-sm); color: var(--muted); min-width: 64px; }
.vet-row .vt { flex: 1 1 0; min-width: 0; }
.vet-row .vm { font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; }

/* Expected vs actual: one row per assertion a step makes. */
.mark-warn { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; font-size: 11px; font-weight: 700; line-height: 1; flex: none; background: var(--warn-soft); color: var(--warn); }
.checks-box { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--panel-2); padding: var(--sp-2) var(--sp-3); }
.checks-title { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; margin-bottom: var(--sp-1); }
.checks-title .verdict-ok, .checks-title .verdict-bad { text-transform: none; letter-spacing: 0; }
.checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.check { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; padding: 3px 6px; border-radius: 4px; font-family: var(--mono); font-size: 13px; }
.check > [role="img"], .check > .mark-none { align-self: center; }
.check .want { flex: 1 1 0; overflow-wrap: anywhere; min-width: 0; } /* basis 0: a long line wraps beside its mark, not under it */
.check.pending .want { color: var(--text); }
.check.bad { background: var(--bad-soft); }
.check.bad .want { color: var(--text); }
.check .got { color: var(--bad); overflow-wrap: anywhere; min-width: 0; }
.check .got b { font-weight: 700; }
.check .got.allowed { color: var(--warn); font-family: var(--sans); font-size: var(--fs-xs); }

/* ---------- presenter mode ----------
   F in Present: the app chrome goes, the stage takes the screen, and type is
   sized for a shared screen at 1280-1920 px. Toggled by .presenting on <html>. */
.presenting .topbar { display: none; }
.presenting main { padding: 0 clamp(16px, 3vw, 56px) var(--sp-5); max-width: 1680px; }
.present.presenter { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-4); }
.pbar { position: sticky; top: 0; z-index: 10; background: var(--bg); padding-top: var(--sp-3); }
.pbar-row { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; padding-bottom: var(--sp-2); }
.pbar .logo { font-size: var(--fs-sm); }
.pbar-name { color: var(--muted); font-weight: 600; font-size: var(--fs-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; max-width: 60vw; }
.pbar-clock { color: var(--muted); font-family: var(--mono); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.pbar-nav { display: inline-flex; align-items: center; gap: var(--sp-1); }
.pbar-count { font-family: var(--mono); font-size: var(--fs-md); font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 5ch; text-align: center; }
.pbar .ghost { opacity: .7; }
.pbar .ghost:hover:not(:disabled), .pbar .ghost:focus-visible { opacity: 1; }
.pbar-progress { height: 3px; }
.presenter .stage { gap: var(--sp-4); }
.presenter .stage-intro { padding: var(--sp-4) clamp(16px, 2.5vw, 40px) var(--sp-5); gap: var(--sp-3); }
.presenter .stage-title { font-size: clamp(30px, 3.1vw, 54px); line-height: 1.15; letter-spacing: -.01em; }
.presenter .narration { font-size: clamp(19px, 1.65vw, 29px); line-height: 1.5; max-width: 70ch; }
.presenter .stage-head { font-size: var(--fs-md); }
.presenter .call { font-size: clamp(17px, 1.4vw, 24px); }
.presenter .actor { font-size: var(--fs-md); padding: 3px 12px; }
.presenter .panel-head b { font-size: var(--fs-lg); }
.presenter .big-status { font-size: clamp(18px, 1.4vw, 24px); }
.presenter .status { font-size: 16px; }
.presenter pre.json { font-size: clamp(13px, .95vw, 16px); max-height: 46vh; }
.presenter .check { font-size: clamp(14px, 1.05vw, 18px); padding: 4px 8px; }
.presenter .checks-title { font-size: var(--fs-sm); }
.presenter .event-type, .presenter .ev .mono { font-size: clamp(13px, .95vw, 16px); }
.presenter .finished { font-size: var(--fs-lg); }
.p-col { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.p-exchange { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 520px), 1fr)); gap: var(--sp-4); align-items: start; }

/* ---------- explore ---------- */
.explore { display: flex; flex-direction: column; gap: var(--sp-3); }
.subtabs { display: flex; gap: var(--sp-1); flex-wrap: wrap; }
.subtabs button { background: transparent; color: var(--muted); border: 1px solid var(--border); }
.subtabs button:hover:not(.active) { color: var(--text); background: var(--panel-2); filter: none; }
.subtabs button.active { background: var(--btn); color: var(--btn-text); border-color: transparent; }
table.ops { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
table.ops td, table.ops th { padding: 5px var(--sp-2); border-top: 1px solid var(--border); text-align: left; vertical-align: top; }
table.ops th { color: var(--muted); font-weight: 600; font-size: var(--fs-xs); border-top: 0; }
table.ops tr.click:hover { background: var(--panel-2); cursor: pointer; }
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.split.side-split { grid-template-columns: 260px minmax(0, 1fr); }

/* Laptop and up: the bar stays in view while scrolling. */
@media (min-width: 901px) {
  .topbar { position: sticky; top: 0; }
  .timeline { top: calc(var(--sp-4) + 64px); max-height: calc(100vh - 64px - 2 * var(--sp-4)); }
}
/* Laptop widths: keep the bar on one row by dropping the least useful bits. */
@media (max-width: 1699px) {
  .pill.secondary { display: none; }
}
@media (max-width: 1499px) {
  .run-state .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .world .world-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .world select { max-width: 150px; }
  .brand { font-size: 15px; }
  .brand > span:not(.logo):not(.edition) { display: none; } /* the APX mark stays */
  .clock-buttons button[data-advance="PT15M"] { display: none; }
}
/* Projector / large screens: a little larger, so the back of the room can read it. */
@media (min-width: 1800px) {
  body { font-size: 15px; }
  .stage-title { font-size: 32px; }
  .narration { font-size: 20px; }
  .call { font-size: 18px; }
  pre.json { font-size: 13px; }
}
@media (max-width: 900px) {
  main { padding: var(--sp-3); }
  .build, .present, .split, .split.side-split { grid-template-columns: minmax(0, 1fr); }
  .header-end { margin-left: 0; }
  .cards { grid-template-columns: minmax(0, 1fr); }
  .step-body { padding-left: var(--sp-3); }
  .step-head { flex-wrap: wrap; }
  .step-head .name { max-width: 100%; flex: 1 1 auto; }
  .step-head .sum { flex-basis: 100%; order: 5; }
  .timeline { position: static; max-height: 240px; }
  .stage-title { font-size: 22px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before { animation: none !important; transition: none !important; }
}

/* Frozen | Live clock switch (header, next to the clock). */
.clock-mode { display: inline-flex; border: 1px solid var(--border); border-radius: 999px; padding: 2px; background: var(--panel-2); }
.clock-mode button { padding: 2px 10px; font-size: var(--fs-xs); font-weight: 600; background: transparent; color: var(--muted); border: 0; border-radius: 999px; }
.clock-mode button:hover:not(:disabled):not(.active) { color: var(--text); filter: none; }
.clock-mode button.active { background: var(--accent-soft); color: var(--accent); }
.clock-mode button[data-realtime="true"].active { background: var(--ok-soft); color: var(--ok); }

/* ---------- fabric ----------
   The delivery fabric, live (ui/js/fabric.js). Sized to read on a shared
   screen at 125-150 % zoom: one line per event, cards that wrap. */
.fabric { display: flex; flex-direction: column; gap: var(--sp-3); }
.fabric-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-5); padding: var(--sp-3) var(--sp-4); }
.fabric-title { display: flex; flex-direction: column; gap: 2px; }
.fabric-title h2 { font-size: var(--fs-xl); }
.fabric-title .muted { font-size: var(--fs-xs); font-family: var(--mono); }
.fabric-traffic { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
.traffic-state { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.traffic-state::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--border); flex: none; }
.traffic-state.on { color: var(--text); }
.traffic-state.on::before { background: var(--ok); animation: pulse 1.2s ease-in-out infinite; }
.traffic-state.paused { color: var(--warn); }
.traffic-state.paused::before { background: var(--warn); }
.fabric-rate { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); }
.fabric-rate input[type="range"] { width: 140px; padding: 0; accent-color: var(--accent); }
.fabric-rate output { min-width: 7ch; }
.fabric-mix { display: inline-flex; gap: var(--sp-1); flex-wrap: wrap; }
.chip { background: transparent; color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px; font-size: var(--fs-xs); font-weight: 600; }
.chip:hover:not(:disabled) { color: var(--text); filter: none; background: var(--panel-2); }
.chip.active { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.fabric-totals { display: flex; gap: var(--sp-4); margin-left: auto; }
.fabric-total, .sub-stat { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.fabric-total b { font-size: var(--fs-2xl); font-variant-numeric: tabular-nums; }
.fabric-total span, .sub-stat span { font-size: var(--fs-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
.t-ok b { color: var(--ok); }
.t-warn b { color: var(--warn); }
.t-bad b { color: var(--bad); }
.t-event b { color: var(--event); }
.t-muted b { color: var(--muted); }
.fabric-add { gap: var(--sp-2); }
.fabric-empty { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--warn-soft); border-color: transparent; }
.fabric-grid { display: grid; grid-template-columns: minmax(360px, 5fr) minmax(0, 7fr); gap: var(--sp-3); align-items: start; }

/* the event stream */
.fabric-stream { position: sticky; top: calc(var(--sp-4) + 64px); }
.stream-rows { max-height: calc(100vh - 260px); min-height: 240px; overflow: auto; padding: var(--sp-1) 0; }
.ev-line {
  display: grid; grid-template-columns: 9ch minmax(0, 1.4fr) minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center;
  padding: 5px 14px; border-top: 1px solid var(--border); font-size: var(--fs-md);
}
.ev-line:first-child { border-top: 0; }
.ev-line.fresh { animation: arrive .7s ease-out, glow 2.5s ease-out; }
.ev-time { color: var(--muted); font-variant-numeric: tabular-nums; }
.ev-type { font-family: var(--mono); font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--event); }
.ev-type.d-data { color: var(--accent); }
.ev-type.d-control { color: var(--warn); }
.ev-type.d-alert { color: var(--bad); }
.ev-type.d-accounts { color: var(--ok); }
.ev-type.d-apds { color: var(--muted); }
.ev-place { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: var(--fs-sm); }
.ev-fan { display: inline-flex; gap: 3px; align-items: center; justify-content: flex-end; font-size: var(--fs-xs); min-width: 5ch; }
@keyframes arrive { from { opacity: 0; transform: translateY(-8px); } }
@keyframes glow { from { background: var(--event-soft); } to { background: transparent; } }

/* subscriber colours: dots in the stream, the stripe on each card */
.dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--sub); flex: none; }
.dot.big { width: 14px; height: 14px; }
.sub-c0 { --sub: #1f6feb; }
.sub-c1 { --sub: #d4600f; }
.sub-c2 { --sub: #1a7f37; }
.sub-c3 { --sub: #8250df; }
.sub-c4 { --sub: #bf3989; }
.sub-c5 { --sub: #0a8a8a; }
.sub-c6 { --sub: #9a6700; }
.sub-c7 { --sub: #6e7781; }

/* subscribers */
.fabric-subs { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.fabric-schedule { font-size: var(--fs-sm); padding: 0 var(--sp-1); }
.fabric-schedule b { color: var(--text); font-weight: 600; }
.sub-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 400px), 1fr)); gap: var(--sp-3); align-items: start; }
.sub-card { border-top: 4px solid var(--sub); display: flex; flex-direction: column; }
.sub-card.failed { background: var(--bad-soft); }
.sub-head { display: flex; align-items: center; gap: var(--sp-2); padding: 10px 14px 4px; }
.sub-name { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.sub-name b { font-size: var(--fs-lg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sub-name .mono { font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.badge.tr-webhook { background: var(--accent-soft); color: var(--accent); }
.badge.tr-sse { background: var(--event-soft); color: var(--event); }
.sub-status { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .4px; border-radius: 999px; padding: 1px 8px; }
.st-active { background: var(--ok-soft); color: var(--ok); }
.st-paused { background: var(--warn-soft); color: var(--warn); }
.st-failed { background: var(--bad); color: #fff; }
.sub-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); padding: 4px 14px 8px; font-size: var(--fs-sm); }
.health { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.health::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--muted); flex: none; }
.health.ok::before { background: var(--ok); }
.health.warn { color: var(--warn); }
.health.warn::before { background: var(--warn); }
.health.bad { color: var(--bad); }
.health.bad::before { background: var(--bad); animation: pulse 1s ease-in-out infinite; }
.sub-body { border-top: 1px solid var(--border); padding: var(--sp-2) 14px var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); }
.sub-stats { display: flex; gap: var(--sp-5); }
.sub-stat b { font-size: var(--fs-xl); font-variant-numeric: tabular-nums; }
.sub-none { font-size: var(--fs-sm); }
.deliveries { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.delivery {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "type status next" "attempts attempts attempts";
  gap: 2px var(--sp-2); align-items: center; padding: 4px 6px; border-radius: 4px;
}
.delivery .ev-type { grid-area: type; }
.delivery .attempts { grid-area: attempts; display: flex; flex-wrap: wrap; gap: 3px; }
.delivery .dl-status { grid-area: status; }
.delivery .next { grid-area: next; font-size: var(--fs-xs); color: var(--warn); font-variant-numeric: tabular-nums; }
.delivery.dl-retrying { background: var(--warn-soft); }
.delivery.dl-failed { background: var(--bad-soft); }
.dl-status { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .3px; }
.s-delivered { color: var(--ok); }
.s-retrying { color: var(--warn); }
.s-failed { color: var(--bad); }
.attempt { font-family: var(--mono); font-size: 12px; font-weight: 700; border-radius: 4px; padding: 0 6px; }
.attempt.ok { background: var(--ok-soft); color: var(--ok); }
.attempt.bad { background: var(--bad-soft); color: var(--bad); }
.delivery.dl-failed .attempt.bad, .delivery.dl-retrying .attempt.bad { background: var(--panel); }
.attempt.fresh { animation: pop .6s ease-out; }
@keyframes pop { 0% { transform: scale(.6); opacity: 0; } 60% { transform: scale(1.15); } }
@media (max-width: 1199px) {
  .fabric-grid { grid-template-columns: minmax(0, 1fr); }
  .fabric-stream { position: static; }
  .stream-rows { max-height: 360px; }
  .fabric-totals { margin-left: 0; }
}
.ev-line.unmatched { opacity: .55; }
