/* platform/pulse.css — the founders' Pulse board.
   Lives inside the console frame and borrows its tokens (--font-family,
   --text-*, --card-border, --radius-*). Everything here is prefixed `pulse-`
   so nothing leaks into the other sections. One accent: ink. Status colours
   are reserved for status and always travel with a word. */

.pulse {
  --pulse-ink: var(--text-primary, #363636);
  /* Soft ink, tertiary text and the warning tone are set to clear 4.5:1 on white AND on the wash surfaces they sit
     on (WCAG 1.4.3); at 0.62, #7A7F88 and #A06200 they measured 3.6-4.2 there. */
  --pulse-ink-soft: rgba(54, 54, 54, 0.74);
  --pulse-ink-deep: #1F1F1F;
  --text-tertiary: #676C75;
  --pulse-hair: var(--card-border, #E5E5EA);
  --pulse-hair-strong: var(--border-color, #9E9E9E);
  --pulse-wash: rgba(0, 0, 0, 0.035);
  --pulse-wash-strong: rgba(0, 0, 0, 0.07);
  --pulse-good: #1B6E30;
  --pulse-good-wash: rgba(27, 110, 48, 0.10);
  --pulse-warn: #8A5400;
  --pulse-warn-wash: rgba(138, 84, 0, 0.12);
  --pulse-bad: #B3261E;
  --pulse-bad-wash: rgba(179, 38, 30, 0.10);
  --pulse-radius: var(--radius-xl, 12px);
  font-family: var(--font-family);
  color: var(--pulse-ink);
  font-feature-settings: "kern" 1, "liga" 1;
  text-rendering: optimizeLegibility;
  padding-bottom: 48px;
}
.pulse * { box-sizing: border-box; }
.pulse a { color: inherit; }
.pulse button { font-family: inherit; }
.pulse code, .pulse .pulse-mono { font-family: var(--font-mono); font-size: 12px; }
.pulse .pulse-num { font-variant-numeric: tabular-nums lining-nums; }

/* ---- Head ---------------------------------------------------------------- */
.pulse-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 24px;
  margin-bottom: 20px;
}
.pulse-title { font-size: 22px; font-weight: 400; margin: 0 0 4px; letter-spacing: -0.01em; }
.pulse-sub { font-size: 13px; color: var(--text-secondary); margin: 0; max-width: 62ch; line-height: 1.45; }
.pulse-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.pulse-seg {
  display: inline-flex; padding: 2px; gap: 2px; border-radius: 999px;
  background: rgba(120, 120, 128, 0.12);
}
.pulse-seg button {
  border: 0; background: transparent; border-radius: 999px; cursor: pointer;
  padding: 6px 12px; font-size: 12.5px; font-weight: 500; color: var(--text-secondary);
  transition: color .15s, background .15s, box-shadow .15s;
}
.pulse-seg button:hover { color: var(--pulse-ink); }
.pulse-seg button[aria-pressed="true"] { background: #FFFFFF; color: var(--pulse-ink); box-shadow: 0 1px 3px rgba(0,0,0,0.10); }
.pulse-seg button:focus-visible, .pulse button:focus-visible, .pulse [tabindex]:focus-visible {
  outline: 2px solid var(--accent-blue, #007AFF); outline-offset: 2px;
}
.pulse-toggle {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-secondary);
  cursor: pointer; user-select: none; padding: 6px 10px; border: 1px solid var(--pulse-hair); border-radius: 999px;
  background: #FFFFFF;
}
.pulse-toggle input { accent-color: var(--pulse-ink); margin: 0; }
.pulse-live {
  display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--pulse-hair); background: #FFFFFF; color: var(--text-secondary);
  font-size: 12.5px; cursor: pointer; transition: border-color .15s, color .15s;
}
.pulse-live:hover { border-color: var(--pulse-hair-strong); color: var(--pulse-ink); }
.pulse-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--pulse-good); box-shadow: 0 0 0 2px var(--pulse-good-wash); }
.pulse-live[data-state="loading"] .pulse-live-dot { background: var(--pulse-warn); box-shadow: 0 0 0 2px var(--pulse-warn-wash); animation: pulse-blink 1.1s ease-in-out infinite; }
/* stale: the numbers are real but old (a failed recompute, or a copy painted from this browser). */
.pulse-live[data-state="stale"] .pulse-live-dot { background: var(--pulse-warn); box-shadow: 0 0 0 2px var(--pulse-warn-wash); }
.pulse-live[data-state="stale"] { color: var(--pulse-warn); border-color: rgba(138, 84, 0, 0.35); }
.pulse-live[data-state="error"] .pulse-live-dot { background: var(--pulse-bad); box-shadow: 0 0 0 2px var(--pulse-bad-wash); }
.pulse-live[data-state="error"] { color: var(--pulse-bad); border-color: rgba(179, 38, 30, 0.35); }
@keyframes pulse-blink { 50% { opacity: 0.35; } }

/* ---- Health strip ------------------------------------------------------- */
.pulse-health { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 20px; }
.pulse-health-tile {
  display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px;
  border: 1px solid var(--pulse-hair); border-radius: var(--pulse-radius); background: #FFFFFF;
  text-align: left; cursor: pointer; transition: border-color .15s, background .15s; width: 100%;
}
.pulse-health-tile:hover { border-color: var(--pulse-hair-strong); background: rgba(0,0,0,0.008); }
.pulse-health-mark {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; margin-top: 1px;
}
.pulse-health-mark svg { width: 14px; height: 14px; }
.pulse-health-tile[data-state="good"] .pulse-health-mark { background: var(--pulse-good-wash); color: var(--pulse-good); }
.pulse-health-tile[data-state="warn"] .pulse-health-mark { background: var(--pulse-warn-wash); color: var(--pulse-warn); }
.pulse-health-tile[data-state="bad"]  .pulse-health-mark { background: var(--pulse-bad-wash);  color: var(--pulse-bad); }
.pulse-health-body { min-width: 0; }
.pulse-health-name { display: flex; align-items: baseline; gap: 8px; font-size: 13px; font-weight: 500; }
.pulse-health-state { font-size: 11px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; }
.pulse-health-tile[data-state="good"] .pulse-health-state { color: var(--pulse-good); }
.pulse-health-tile[data-state="warn"] .pulse-health-state { color: var(--pulse-warn); }
.pulse-health-tile[data-state="bad"]  .pulse-health-state { color: var(--pulse-bad); }
.pulse-health-summary { font-size: 13px; color: var(--text-secondary); margin-top: 3px; line-height: 1.4; }

/* ---- KPI row ------------------------------------------------------------ */
.pulse-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
.pulse-kpi {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px; align-content: start;
  padding: 16px 16px 14px; border: 1px solid var(--pulse-hair); border-radius: var(--pulse-radius);
  background: #FFFFFF; min-width: 0; overflow: hidden;
}
.pulse-kpi-label { grid-column: 1 / -1; }
.pulse-kpi-value, .pulse-kpi-row, .pulse-kpi-foot { grid-column: 1; min-width: 0; }
.pulse-kpi-label { font-size: 13px; color: var(--text-secondary); margin-bottom: 8px; display: flex; justify-content: space-between; gap: 8px; }
.pulse-kpi-scope { font-size: 11px; color: var(--text-tertiary); letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; }
.pulse-kpi-value { font-size: 30px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.05; }
.pulse-kpi-row { display: flex; align-items: center; gap: 10px; margin-top: 8px; min-height: 20px; flex-wrap: wrap; }
.pulse-kpi-foot { font-size: 12px; color: var(--text-tertiary); margin-top: 8px; line-height: 1.5; }
.pulse-kpi-foot b { font-weight: 500; color: var(--text-secondary); }
.pulse-kpi-spark { grid-column: 2; grid-row: 2 / span 3; align-self: end; width: 96px; height: 34px; opacity: 0.9; }
.pulse-kpi-spark svg { width: 100%; height: 100%; display: block; overflow: visible; }

.pulse-delta {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 999px;
  font-size: 12px; font-weight: 500; line-height: 16px; white-space: nowrap; background: var(--pulse-wash); color: var(--pulse-ink-soft);
}
.pulse-delta svg { width: 9px; height: 9px; }
.pulse-delta[data-tone="good"] { background: var(--pulse-good-wash); color: var(--pulse-good); }
.pulse-delta[data-tone="bad"]  { background: var(--pulse-bad-wash);  color: var(--pulse-bad); }
.pulse-delta-vs { font-size: 12px; color: var(--text-tertiary); }

/* ---- Cards -------------------------------------------------------------- */
.pulse-card { border: 1px solid var(--pulse-hair); border-radius: var(--pulse-radius); background: #FFFFFF; margin-bottom: 12px; min-width: 0; }
.pulse-card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--pulse-hair);
}
.pulse-card-title { font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 8px; }
.pulse-card-meta { font-size: 12px; color: var(--text-tertiary); }
.pulse-card-body { padding: 16px; }
.pulse-card-flush { padding: 0; }
.pulse-link {
  background: none; border: 0; padding: 0; font-size: 12.5px; color: var(--text-secondary); cursor: pointer;
  text-decoration: none; border-bottom: 1px solid transparent; transition: color .15s, border-color .15s;
}
.pulse-link:hover { color: var(--pulse-ink); border-bottom-color: var(--pulse-hair-strong); }
.pulse-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.pulse-grid-2 > .pulse-card { margin-bottom: 0; }
.pulse-section-gap { height: 0; margin-bottom: 12px; }

/* ---- Day charts ----------------------------------------------------------- */
.pulse-chart { position: relative; }
.pulse-chart svg { width: 100%; height: 148px; display: block; overflow: visible; }
.pulse-chart-bar { fill: var(--pulse-ink); }
.pulse-chart-bar.is-soft { fill: rgba(54, 54, 54, 0.28); }
/* Today is still being counted: an outline, never a fill that reads as a series (it read as "all linked"). */
.pulse-chart-bar.is-today { stroke: var(--pulse-ink); stroke-width: 1.2; stroke-dasharray: 3 2; }
.pulse-chart-hit { fill: transparent; cursor: crosshair; }
/* Everything drawn over a hit area lets the pointer through to it: a bar, a dot or a number on top of its slot used to
   swallow the hover, so pointing AT a bar showed nothing and only the empty space above it had a tooltip. */
.pulse-chart .pulse-chart-bar, .pulse-chart .pulse-mline-dot, .pulse-chart .pulse-mline-path, .pulse-chart .pulse-mline-area,
.pulse-chart .pulse-chart-val, .pulse-chart .pulse-chart-axis, .pulse-chart .pulse-chart-grid { pointer-events: none; }
.pulse-chart-hit:hover + .pulse-chart-bar, .pulse-chart-bar.is-hover { opacity: 0.72; }
.pulse-chart-axis { fill: var(--text-tertiary); font-size: 10.5px; font-family: var(--font-family); }
/* The number on every cap: the per-day count is the point of the chart. */
.pulse-chart-val { fill: var(--text-secondary); font-size: 11px; font-weight: 500; font-family: var(--font-family); font-variant-numeric: tabular-nums; pointer-events: none; }
.pulse-chart-val.is-zero { fill: var(--text-tertiary); font-weight: 400; opacity: 0.7; }
.pulse-chart-grid { stroke: var(--pulse-hair); stroke-width: 1; }
.pulse-chart-tip {
  position: absolute; pointer-events: none; z-index: 3; transform: translate(-50%, calc(-100% - 10px));
  background: var(--pulse-ink); color: #FFFFFF; border-radius: 8px; padding: 6px 9px; font-size: 12px; white-space: nowrap;
  box-shadow: 0 6px 20px rgba(0,0,0,0.16); opacity: 0; transition: opacity .12s;
}
.pulse-chart-tip.is-on { opacity: 1; }
.pulse-chart-tip b { font-weight: 600; font-variant-numeric: tabular-nums; }
.pulse-chart-tip span { opacity: 0.72; }
.pulse-chart-table { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 10px; }
.pulse-chart-table th, .pulse-chart-table td { padding: 4px 8px; text-align: right; border-top: 1px solid var(--pulse-hair); }
.pulse-chart-table th:first-child, .pulse-chart-table td:first-child { text-align: left; }

/* ---- Tables -------------------------------------------------------------- */
.pulse-table-wrap { overflow-x: auto; }
.pulse-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pulse-table th {
  text-align: left; font-size: 11px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-tertiary); padding: 10px 12px; border-bottom: 1px solid var(--pulse-hair); white-space: nowrap;
}
.pulse-table th:first-child, .pulse-table td:first-child { padding-left: 16px; }
.pulse-table th:last-child, .pulse-table td:last-child { padding-right: 16px; }
.pulse-table td { padding: 10px 12px; border-bottom: 1px solid var(--pulse-hair); vertical-align: middle; }
.pulse-table tr:last-child td { border-bottom: 0; }
.pulse-table th.is-num, .pulse-table td.is-num { text-align: right; font-variant-numeric: tabular-nums lining-nums; }
.pulse-table tbody tr { transition: background .12s; }
.pulse-table tbody tr:hover { background: rgba(0,0,0,0.015); }
.pulse-table tbody tr.is-clickable { cursor: pointer; }
.pulse-table tbody tr.is-selected { background: rgba(0,0,0,0.035); }
.pulse-table .is-muted { color: var(--text-tertiary); }
.pulse-empty { padding: 36px 16px; text-align: center; font-size: 13px; color: var(--text-tertiary); }
.pulse-card-foot { padding: 10px 16px; border-top: 1px solid var(--pulse-hair); font-size: 12.5px; }

/* platform cell */
.pulse-plat { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pulse-plat-mark {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;
  background: var(--pulse-wash); color: var(--pulse-ink); font-size: 11px; font-weight: 600; overflow: hidden;
}
.pulse-plat-mark img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pulse-plat-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
.pulse-plat-dev { font-size: 12px; color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pulse-tag {
  display: inline-block; font-size: 10.5px; font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 4px; border: 1px solid var(--pulse-hair); color: var(--text-tertiary); margin-left: 6px; vertical-align: 1px;
}

/* rate bar (converted vs unlinked share) */
.pulse-rate { display: flex; align-items: center; gap: 8px; min-width: 96px; }
.pulse-rate-bar { flex: 1; height: 6px; border-radius: 3px; background: rgba(0,0,0,0.10); overflow: hidden; }
.pulse-rate-fill { height: 100%; background: var(--pulse-ink); border-radius: 3px; }
.pulse-rate-val { font-size: 12px; color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }

/* sparkline cell */
.pulse-spark { width: 84px; height: 26px; display: block; }
.pulse-spark svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* status chips */
.pulse-chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 999px;
  font-size: 12px; line-height: 16px; background: var(--pulse-wash); color: var(--pulse-ink-soft); white-space: nowrap;
}
.pulse-chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: 0.75; }
.pulse-chip[data-tone="good"] { background: var(--pulse-good-wash); color: var(--pulse-good); }
.pulse-chip[data-tone="warn"] { background: var(--pulse-warn-wash); color: var(--pulse-warn); }
.pulse-chip[data-tone="bad"]  { background: var(--pulse-bad-wash);  color: var(--pulse-bad); }
.pulse-chip[data-tone="none"]::before { display: none; }

/* person cell */
.pulse-person { min-width: 0; }
.pulse-person-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 240px; }
.pulse-person-sub { font-size: 12px; color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }

/* filter banner */
.pulse-filter {
  display: inline-flex; align-items: center; gap: 8px; padding: 4px 6px 4px 10px; border-radius: 999px;
  background: var(--pulse-ink); color: #FFFFFF; font-size: 12px;
}
.pulse-filter button { border: 0; background: rgba(255,255,255,0.18); color: #FFFFFF; border-radius: 999px; width: 18px; height: 18px; cursor: pointer; font-size: 12px; line-height: 18px; padding: 0; }
.pulse-filter button:hover { background: rgba(255,255,255,0.32); }

/* ---- People card tabs ---------------------------------------------------- */
.pulse-tabs { display: flex; align-items: center; gap: 2px; padding: 2px; border-radius: 999px; background: rgba(120, 120, 128, 0.12); }
.pulse-tab {
  appearance: none; border: 0; background: transparent; border-radius: 999px; cursor: pointer;
  padding: 5px 12px; font-size: 13px; font-weight: 500; color: var(--text-secondary);
  display: inline-flex; align-items: center; gap: 6px; transition: color .15s, background .15s, box-shadow .15s;
}
.pulse-tab:hover { color: var(--pulse-ink); }
.pulse-tab[aria-selected="true"] { background: #FFFFFF; color: var(--pulse-ink); box-shadow: 0 1px 3px rgba(0,0,0,0.10); }
.pulse-tab-count { font-size: 11.5px; font-weight: 500; color: var(--text-secondary); padding: 1px 6px; border-radius: 999px; background: rgba(0,0,0,0.05); }
.pulse-tab[aria-selected="true"] .pulse-tab-count { color: var(--pulse-ink); }

/* ---- Synthesis + errors panels ------------------------------------------ */
.pulse-stats { display: flex; flex-wrap: wrap; gap: 8px 18px; padding: 12px 16px; border-bottom: 1px solid var(--pulse-hair); }
.pulse-stat { display: flex; align-items: baseline; gap: 6px; font-size: 13px; color: var(--text-secondary); }
.pulse-stat b { font-weight: 500; color: var(--pulse-ink); font-variant-numeric: tabular-nums; }
.pulse-list { list-style: none; margin: 0; padding: 0; }
.pulse-list li { display: flex; align-items: flex-start; gap: 12px; padding: 10px 16px; border-bottom: 1px solid var(--pulse-hair); font-size: 13px; }
.pulse-list li:last-child { border-bottom: 0; }
.pulse-list-main { flex: 1; min-width: 0; }
.pulse-list-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pulse-list-msg { color: var(--text-secondary); font-size: 12.5px; margin-top: 2px; line-height: 1.4; overflow-wrap: anywhere; }
.pulse-list-when { flex: 0 0 auto; font-size: 12px; color: var(--text-tertiary); white-space: nowrap; }
.pulse-errbar { display: flex; align-items: center; gap: 10px; }
.pulse-errbar-track { flex: 1; height: 5px; background: rgba(0,0,0,0.06); border-radius: 3px; overflow: hidden; }
.pulse-errbar-fill { height: 100%; background: var(--pulse-bad); opacity: 0.75; }

.pulse-defs { font-size: 12px; color: var(--text-tertiary); line-height: 1.55; max-width: 92ch; margin-top: 16px; }
.pulse-defs b { font-weight: 500; color: var(--text-secondary); }

/* ---- States -------------------------------------------------------------- */
/* Dimming while a slice loads says "these numbers are on their way out". It
   must not say it about the CONTROLS: those are how you change what is
   loading, and a 55%-opacity pill reads as disabled even though it still
   responds. Dimmed controls plus dropdowns that emptied themselves mid-load
   is what made the panel feel frozen - you could not tell that clicking would
   do anything. The numbers fade; the things you steer with do not. */
.pulse.is-loading .pulse-body { opacity: 0.55; transition: opacity .2s; }
.pulse.is-loading .pulse-cohorts,
.pulse.is-loading .pulse-head { opacity: 1; }
.pulse-body { transition: opacity .2s; }
.pulse-error {
  padding: 14px 16px; border: 1px solid var(--pulse-bad); border-radius: var(--pulse-radius); background: var(--pulse-bad-wash);
  color: var(--pulse-bad); font-size: 13px; margin-bottom: 12px;
}
/* A refresh failure with a board still on screen is a note, not an alarm. */
.pulse-error.is-soft { border-color: rgba(138, 84, 0, 0.35); background: var(--pulse-warn-wash); color: var(--pulse-warn); }
.pulse-skeleton { padding: 48px 16px; text-align: center; color: var(--text-tertiary); font-size: 13px; }

/* ---- Motion -------------------------------------------------------------- */
@keyframes pulse-rise { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.pulse-body > * { animation: pulse-rise .28s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
/* ...but NOT the chrome. render() replaces the panel's markup wholesale, so
   every slice change and every background refresh restarted this entrance on
   the toolbar too - and `both` holds the `from` frame, which is opacity 0.
   Measured in the browser mid-change: the filter bar computed to opacity 0
   while somebody was using it. Content arriving deserves a fade; the controls
   you are mid-click on do not move or blink. */
.pulse-body > .pulse-head,
.pulse-body > .pulse-cohorts { animation: none; }
.pulse-body > *:nth-child(2) { animation-delay: .04s; }
/* A background refresh of the same view repaints without the entrance (render/paint in pulse.js): replaying it
   every few seconds was the flashing. */
.is-quiet .pulse-body > * { animation: none; }
.pulse-body > *:nth-child(3) { animation-delay: .08s; }
.pulse-body > *:nth-child(4) { animation-delay: .12s; }
.pulse-body > *:nth-child(5) { animation-delay: .16s; }
.pulse-body > *:nth-child(6) { animation-delay: .20s; }
@media (prefers-reduced-motion: reduce) {
  .pulse-body > * { animation: none; }
  .pulse-live[data-state="loading"] .pulse-live-dot { animation: none; }
}

/* ---- Responsive ---------------------------------------------------------- */
@media (max-width: 1180px) {
  .pulse-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pulse-grid-2 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 820px) {
  .pulse-head { flex-direction: column; }
  .pulse-controls { justify-content: flex-start; }
  .pulse-health { grid-template-columns: minmax(0, 1fr); }
  .pulse-kpi-spark { display: none; }
}

/* ---- Hosted flow panel --------------------------------------------------- */
.pulse-cohorts {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px; margin-bottom: 14px;
  border-radius: 999px; background: rgba(120, 120, 128, 0.12);
}
.pulse-cohorts .pulse-tab { padding: 7px 16px; font-size: 13.5px; }

.pulse-head--sub { margin-bottom: 14px; }
.pulse-head--sub .pulse-title { font-size: 19px; }

/* ---------------------------------------------------------------------------
   The filter menus
   ---------------------------------------------------------------------------
   These are real <select> elements. A native select's popup is drawn by the
   operating system, outside the page, which is why no amount of CSS ever
   reached it and why every product eventually ships a hand-built one — and
   with it fourteen keyboard behaviours, a focus model where DOM focus must
   stay on the trigger, and a new set of bugs.
   `appearance: base-select` opts the same element into being drawn by the
   browser instead, so the menu below is ours to style while the browser keeps
   every keyboard behaviour, the top-layer placement and the accessibility
   tree. Both the control and its ::picker must opt in; opting one in alone
   does nothing.
   Where it is not supported the rules below are simply ignored and a correct,
   keyboard-accessible native select is what renders. That is the fallback. */
.pulse-select {
  font: inherit; font-size: 12.5px; color: var(--pulse-ink); background: #FFFFFF;
  border: 1px solid var(--pulse-hair); border-radius: 999px; padding: 6px 10px; cursor: pointer;
  max-width: 210px;
}
.pulse-select:hover { border-color: var(--pulse-hair-strong); }

.pulse-select, .pulse-select::picker(select) { appearance: base-select; }

.pulse-select {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px 6px 12px; text-align: left; white-space: nowrap;
  transition: border-color 0.15s linear, box-shadow 0.15s linear;
}
.pulse-select:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
.pulse-select:open { border-color: var(--pulse-hair-strong); box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
.pulse-select::picker-icon {
  color: var(--pulse-ink-soft); transition: transform 0.15s ease; margin-left: auto;
}
.pulse-select:open::picker-icon { transform: rotate(180deg); }

.pulse-select::picker(select) {
  border: 1px solid var(--pulse-hair-strong); border-radius: 12px;
  background: #FFFFFF; padding: 5px; margin-top: 6px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.14);
  max-height: 320px; overflow-y: auto;
  /* The picker is in the top layer, so it needs its own opening transition. */
  opacity: 0; translate: 0 -4px;
  transition: opacity 0.14s ease, translate 0.14s ease, overlay 0.14s allow-discrete, display 0.14s allow-discrete;
}
.pulse-select:open::picker(select) { opacity: 1; translate: 0 0; }
@starting-style { .pulse-select:open::picker(select) { opacity: 0; translate: 0 -4px; } }

.pulse-select option {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-radius: 8px; font-size: 13px; color: var(--pulse-ink);
  cursor: pointer;
}
.pulse-select option:hover, .pulse-select option:focus { background: var(--pulse-wash); outline: none; }
.pulse-select option:checked { font-weight: 550; }
.pulse-select option::checkmark { order: 1; margin-left: auto; color: var(--pulse-ink); }

@media (prefers-reduced-motion: reduce) {
  .pulse-select::picker(select) { transition: none; }
  .pulse-select::picker-icon { transition: none; }
}

/* A screenshot of one screen of the real flow. */
.pulse-shot {
  display: block; border-radius: 8px; border: 1px solid var(--pulse-hair); background: #FFFFFF;
  /* contain, never cover: a cropped screenshot of a screen is worse than none,
     and the whole point of these is to recognise the screen at a glance. */
  object-fit: contain; object-position: center;
  aspect-ratio: 912 / 1744;
}
.pulse-shot.is-thumb { width: 54px; height: 76px; }
.pulse-shot.is-hero {
  width: 172px; height: auto; flex: 0 0 auto; border-radius: 12px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 8px 24px rgba(0,0,0,0.07);
}
.pulse-shot.is-film {
  width: 100%; height: auto; border-radius: 10px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 4px 14px rgba(0,0,0,0.05);
  transition: transform .18s cubic-bezier(0.2,0.7,0.2,1), box-shadow .18s;
}

.pulse-shot.is-missing {
  display: grid; place-items: center; color: var(--text-tertiary); font-size: 10px;
  border-style: dashed; background: rgba(0,0,0,0.02); text-align: center; line-height: 1.2;
  aspect-ratio: 912 / 1744;
}
.pulse-shot.is-missing span { padding: 0 4px; }

/* ---- The funnel table ---------------------------------------------------
   One row = one screen. The screenshot is large enough to recognise the
   screen without opening anything; the bar narrows down the page so the
   funnel shape is visible at a glance; and the only saturated colour on the
   whole table is the single worst row's number. */

.pulse-steps { table-layout: fixed; }
.pulse-steps th { padding-top: 14px; padding-bottom: 12px; }
.pulse-steps td { vertical-align: middle; padding-top: 14px; padding-bottom: 14px; }
.pulse-steps tbody tr:hover { background: rgba(0, 0, 0, 0.012); }

/* The screenshot: a real device card, not a postage stamp. */

.pulse-shot.is-thumb {
  width: 108px; height: auto; border-radius: 10px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 6px 16px rgba(0, 0, 0, 0.06);
}
.pulse-shot.is-thumb.is-missing { box-shadow: none; }

/* The flag is a label, not an alarm: ink on a wash, like every other chip. */
.pulse-flag {
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-secondary); background: var(--pulse-wash);
  border-radius: 4px; padding: 2px 6px; white-space: nowrap;
}

/* ONE bar per row, split where the people split: solid = carried on, hatched =
   stopped here. No track behind it and no rounded pill, because those are the
   grammar of a progress bar and this is a bar-chart mark. The loss is told by
   TEXTURE as well as tone, so it survives a colour-blind reader, a greyscale
   print and forced-colors mode — WCAG 1.4.1 is not satisfied by hue alone. */
.pulse-fbar {
  position: relative;
  display: flex; align-items: stretch;
  height: 8px; margin-top: 10px; border-radius: 2px;
  outline: none;
}

.pulse-fbar[data-tip] { cursor: default; }

.pulse-fbar[data-tip]:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 3px; border-radius: 3px; }

/* The breakdown that opens on the bar. Hoverable by construction — it is a
   child of its trigger, so moving the pointer into it never leaves the
   trigger, which is what WCAG 1.4.13 asks for and what a five-row panel needs
   if anyone is to read row five. */
.pulse-tip {
  position: absolute; left: 0; bottom: calc(100% + 8px); z-index: 30;
  display: none; min-width: 208px; padding: 10px 12px 9px;
  background: #FFFFFF; color: var(--pulse-ink);
  border: 1px solid var(--pulse-hair-strong);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.13);
  text-align: left; cursor: default;
}
.pulse-fbar.is-open .pulse-tip { display: block; }
.pulse-tip-head {
  display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--pulse-ink-soft); margin-bottom: 7px;
}
.pulse-tip-list { list-style: none; margin: 0; padding: 0; }
.pulse-tip-list li {
  display: flex; justify-content: space-between; gap: 16px;
  font-size: 13px; line-height: 21px; white-space: nowrap;
}
.pulse-tip-k { color: var(--pulse-ink); }
.pulse-tip-v { font-variant-numeric: tabular-nums; color: var(--pulse-ink); font-weight: 500; }
.pulse-tip-foot {
  display: block; margin-top: 7px; padding-top: 7px;
  border-top: 1px solid var(--pulse-hair);
  font-size: 12px; color: var(--pulse-ink-soft);
}

/* A screen not everyone sees, or one people join at. Neither is a loss. */

.pulse-steps tr.is-offpath td { background: rgba(0, 0, 0, 0.018); }

/* The worst row is marked by a rule, not by washing the row in red. */
.pulse-steps tr.is-worst td:first-child { box-shadow: inset 3px 0 0 var(--pulse-bad); }
.pulse-steps tr.is-finish td { background: rgba(27, 110, 48, 0.04); }
.pulse-steps tr.is-finish td:first-child { box-shadow: inset 3px 0 0 var(--pulse-good); }

/* The two callouts: biggest drop, longest screen. */
.pulse-callout { display: flex; gap: 20px; padding: 20px; align-items: flex-start; }
.pulse-callout-body { min-width: 0; }
.pulse-callout-figure { font-size: 38px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.05; }
.pulse-callout-label { font-size: 13px; color: var(--text-secondary); margin-top: 6px; line-height: 1.45; }
.pulse-callout-note { font-size: 12.5px; color: var(--text-tertiary); margin-top: 8px; line-height: 1.45; }
.pulse-mini { list-style: none; margin: 10px 0 0; padding: 0; font-size: 12.5px; }
.pulse-mini li { padding: 3px 0; color: var(--text-secondary); }
.pulse-mini b { color: var(--pulse-ink); font-variant-numeric: tabular-nums; }

/* When they gave up. */
.pulse-hours { display: flex; align-items: flex-end; gap: 3px; height: 120px; }
.pulse-hour { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; height: 100%; }
.pulse-hour-stack {
  width: 100%; background: rgba(0,0,0,0.12); border-radius: 3px 3px 0 0;
  display: flex; flex-direction: column; justify-content: flex-end; min-height: 2px;
}
.pulse-hour-lost { width: 100%; background: var(--pulse-ink); border-radius: 3px 3px 0 0; }
.pulse-hour-tick { font-size: 9.5px; color: var(--text-tertiary); margin-top: 4px; height: 12px; }
.pulse-errbar-fill.is-neutral { background: var(--pulse-ink); opacity: 0.55; }

/* The filmstrip: every screen of the flow, in order. */

@media (max-width: 820px) {
  .pulse-callout { flex-direction: column; }
  .pulse-shot.is-hero { width: 132px; height: 210px; }
  
  
}

/* ---------------------------------------------------------------------------
   Recomputing
   ---------------------------------------------------------------------------
   A filter change dims what is on screen rather than replacing it. The 200ms
   delay on the transition means a slice that answers from cache never flashes:
   the dim starts only once the wait is long enough to be worth admitting to.
   Under a second, a person does not want feedback, they want the answer. */
.pulse-flow-body { transition: opacity 0.2s 0.2s linear; }
/* What the two control rows currently add up to, in a sentence. The cohort
   pills and the situation menu are different axes - who the visitor was, and
   why the partner sent them - and nothing on screen said so. */

.pulse-flow-body.is-stale { opacity: 0.45; pointer-events: none; }

/* Only once the wait is genuinely long does it earn a line of its own. */

@keyframes pulse-spin { to { transform: rotate(360deg); } }

/* First load only: the shape of what is coming, so nothing jumps when it
   lands. Never painted over a chart that already has numbers on it. */
.pulse-flow-loading { font-size: 13px; color: var(--pulse-ink-soft); margin-bottom: 14px; }

@keyframes pulse-sheen { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* Motion is decoration here; the dim and the layout carry the meaning. */
@media (prefers-reduced-motion: reduce) {
  
  
  .pulse-flow-body { transition: none; }
}

/* ---------------------------------------------------------------------------
   Why a mailbox fill failed
   ---------------------------------------------------------------------------
   The status chip opens the reason. A row that says "Fill failed" and stops
   there sends the reader to the database to find out what happened, which is
   the errand this board exists to save. Click, not hover: the reason is a
   sentence to read, not a label to glance at, and it has to survive on touch. */
.pulse-why-wrap { position: relative; display: inline-flex; }
.pulse-chip.is-why {
  font: inherit; cursor: pointer; border: 0;
  display: inline-flex; align-items: center; gap: 5px;
  transition: filter 0.15s linear;
}
.pulse-chip.is-why:hover { filter: brightness(0.94); }
.pulse-chip.is-why:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
.pulse-why-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 13px; height: 13px; border-radius: 50%;
  font-size: 9px; font-weight: 700; line-height: 1;
  background: currentColor; color: #FFFFFF; opacity: 0.55;
}
.pulse-chip.is-why:hover .pulse-why-mark,
.pulse-why-wrap.is-open .pulse-why-mark { opacity: 0.9; }

.pulse-why {
  /* Opens to the LEFT of the chip, not below it. Below, a 320px note lands
     exactly on top of the next row's chip in the same column, so the obvious
     next click — the next failure — hits the note instead and nothing happens.
     Beside it, the whole status column stays reachable while one is open. */
  position: absolute; right: calc(100% + 10px); top: -8px; z-index: 40;
  display: none; width: 320px; max-width: 64vw; padding: 11px 13px 10px;
  background: #FFFFFF; color: var(--pulse-ink);
  border: 1px solid var(--pulse-hair-strong);
  border-radius: 10px; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.15);
  text-align: left; white-space: normal; cursor: text;
}
.pulse-why-wrap.is-open .pulse-why { display: block; }
.pulse-why-head {
  display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--pulse-ink-soft); margin-bottom: 6px;
}
.pulse-why-head .is-muted { text-transform: none; letter-spacing: 0; font-weight: 400; }
.pulse-why-body { display: block; font-size: 13px; line-height: 19px; }
.pulse-why-foot {
  display: block; margin-top: 8px; padding-top: 7px;
  border-top: 1px solid var(--pulse-hair);
  font-size: 12px; color: var(--pulse-ink-soft);
}

/* ---------------------------------------------------------------------------
   A count you can open
   ---------------------------------------------------------------------------
   Every counter in the Synthesis panel used to name a number and nobody. These
   are buttons: the number and the names behind it are one click apart rather
   than one database query apart. They still read as text, because a panel of
   buttons reads as a toolbar rather than as a summary. */
.pulse-stat.is-open-list {
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  cursor: pointer; border-bottom: 1px dashed var(--pulse-hair-strong);
  transition: border-color 0.15s linear, color 0.15s linear;
}
.pulse-stat.is-open-list:hover { border-bottom-color: var(--pulse-ink); }
.pulse-stat.is-open-list:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 3px; border-radius: 3px; }
.pulse-stat.is-open-list.is-on { border-bottom: 1px solid var(--pulse-ink); }

.pulse-stat.is-label { color: var(--text-tertiary); }

.pulse-drawer {
  border-top: 1px solid var(--pulse-hair);
  background: rgba(0, 0, 0, 0.014);
  transition: opacity 0.2s 0.2s linear;
}
.pulse-drawer.is-stale { opacity: 0.5; }
.pulse-drawer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 16px 9px;
}
.pulse-drawer-title { font-size: 13px; font-weight: 550; }
.pulse-drawer-title .is-muted { font-weight: 400; }
.pulse-drawer-title .pulse-num { margin-left: 6px; font-variant-numeric: tabular-nums; color: var(--pulse-ink-soft); }
.pulse-drawer-loading, .pulse-drawer-more {
  padding: 4px 16px 13px; font-size: 12px; color: var(--pulse-ink-soft);
}
.pulse-drawer .pulse-list { background: transparent; }

/* ---------------------------------------------------------------------------
   How long it takes
   ---------------------------------------------------------------------------
   Every other number on the board is a count. These are the only durations,
   so they get room rather than being squeezed into a stat strip. Median and
   p90 sit together on purpose: on the current data they are 95 seconds and
   nine hours, and either one alone tells a lie about the other. */
.pulse-timings { display: grid; grid-template-columns: 1fr 1fr; }
.pulse-timing { padding: 16px 18px 17px; border-right: 1px solid var(--pulse-hair); }
.pulse-timing:last-child { border-right: 0; }
.pulse-timing-label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--pulse-ink-soft); margin-bottom: 8px;
}
.pulse-timing-value {
  font-size: 30px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.pulse-timing-foot { margin-top: 7px; font-size: 12px; line-height: 17px; color: var(--pulse-ink-soft); }
.pulse-timing-foot b { color: var(--pulse-ink); font-weight: 550; font-variant-numeric: tabular-nums; }
.pulse-timing-hint { margin-top: 6px; font-size: 12px; line-height: 17px; color: var(--text-tertiary); }
.pulse-timing-none { font-size: 13px; color: var(--pulse-ink-soft); padding: 6px 0 2px; }

.pulse-months { display: flex; align-items: flex-end; gap: 10px; padding: 14px 18px 16px; }
.pulse-month { display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1; max-width: 76px; }
.pulse-month-bar { width: 100%; background: var(--pulse-ink); opacity: 0.86; border-radius: 2px; }
.pulse-month-n { font-size: 12px; font-variant-numeric: tabular-nums; }
.pulse-month-label { font-size: 11px; color: var(--pulse-ink-soft); }

@media (max-width: 900px) {
  .pulse-timings { grid-template-columns: 1fr; }
  .pulse-timing { border-right: 0; border-bottom: 1px solid var(--pulse-hair); }
}

/* With a platform filter on, the panels that cannot be narrowed say so rather
   than letting the filter chip imply they were. */
.pulse-scope {
  display: inline-block; margin-left: 8px; padding: 1px 7px;
  border: 1px solid var(--pulse-hair-strong); border-radius: 999px;
  font-size: 11px; color: var(--pulse-ink-soft); vertical-align: 1px;
}

/* Switching platform asks the table a different question, so the previous
   platform's people leave and this stands in until the new ones arrive. */

/* ---------------------------------------------------------------------------
   Gideon
   ---------------------------------------------------------------------------
   THE MARK is a level meter: five bars in a rounded tile, moving the way a
   signal moves. Not a circle, not a face, not the glowing orb every assistant
   already has. It is the shape of what Gideon does, which is watch numbers
   change.

   Each bar runs on its own period, and the periods are deliberately not
   multiples of one another, so the pattern never visibly repeats. Only
   `transform` animates, which keeps the whole thing on the compositor while it
   sits in the corner of the page all day. */
.pulse-gid-mark { display: inline-block; flex: none; line-height: 0; }
.gid-meter {
  display: flex; align-items: center; justify-content: center;
  gap: 6.5%; width: 100%; height: 100%; padding: 0 13%;
  border-radius: 31%;
  background: linear-gradient(150deg, #3a3a3d 0%, #1b1b1d 55%, #0f0f10 100%);
  box-sizing: border-box;
}
.gid-bar {
  flex: 1 1 0; border-radius: 999px; background: #FFFFFF;
  height: 62%; transform-origin: 50% 50%;
  animation: gid-lvl 2.6s ease-in-out infinite;
}
/* Prime-ish periods and offsets: the five never line up, so it never loops. */
.gid-bar.b1 { opacity: 0.55; animation-duration: 2.3s;  animation-delay: -0.4s; }
.gid-bar.b2 { opacity: 0.78; animation-duration: 1.7s;  animation-delay: -1.1s; }
.gid-bar.b3 { opacity: 1;    animation-duration: 2.9s;  animation-delay: -0.2s; }
.gid-bar.b4 { opacity: 0.78; animation-duration: 1.9s;  animation-delay: -1.6s; }
.gid-bar.b5 { opacity: 0.55; animation-duration: 2.2s;  animation-delay: -0.8s; }
@keyframes gid-lvl {
  0%, 100% { transform: scaleY(0.30); }
  50%      { transform: scaleY(1); }
}

/* Working: taller, faster, brighter. */
.pulse-gid-mark.is-thinking .gid-bar { animation-duration: 0.62s; opacity: 1; }
.pulse-gid-mark.is-thinking .gid-bar.b1 { animation-duration: 0.54s; }
.pulse-gid-mark.is-thinking .gid-bar.b3 { animation-duration: 0.71s; }
.pulse-gid-mark.is-thinking .gid-bar.b5 { animation-duration: 0.58s; }
.pulse-gid-mark.is-streaming .gid-bar { animation-duration: 1.15s; }

/* The corner dock. Present on every view, out of the way until wanted. */
.pulse-gid-fab {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 7px 16px 7px 7px; border: 0; border-radius: 999px;
  background: #FFFFFF; color: var(--pulse-ink); font: inherit; font-size: 13.5px; font-weight: 500;
  box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 8px 26px rgba(0, 0, 0, 0.14); cursor: pointer;
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.pulse-gid-fab:hover { box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 12px 34px rgba(0, 0, 0, 0.18); transform: translateY(-1px); }
.pulse-gid-fab:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 3px; }

/* Soft, not boxy. One rounded panel, a hairline instead of a border, and the
   weight carried by shadow rather than by outline. */
.pulse-gid-dock {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  width: 420px; max-width: calc(100vw - 32px);
  max-height: min(660px, calc(100vh - 110px));
  display: flex; flex-direction: column;
  background: #FFFFFF; border-radius: 20px;
  box-shadow: 0 0 0 1px rgba(0,0,0,.05), 0 24px 60px rgba(0, 0, 0, 0.18);
  overflow: hidden;
  animation: gid-rise 0.2s cubic-bezier(0.2, 0, 0, 1);
}
@keyframes gid-rise { from { opacity: 0; transform: translateY(12px) scale(0.985); } }
.pulse-gid-dock-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 14px 12px 16px; flex: none;
}
.pulse-gid-dock-acts { display: flex; align-items: center; gap: 12px; }
.pulse-gid-x {
  border: 0; background: none; font: inherit; font-size: 19px; line-height: 1;
  color: var(--pulse-ink-soft); cursor: pointer; padding: 0 2px;
}
.pulse-gid-x:hover { color: var(--pulse-ink); }
.pulse-gid-dock-body { flex: 1 1 auto; overflow-y: auto; }
.pulse-gid-who { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 550; }

/* The tab version: the same thread, given room.

   Height is measured rather than guessed. A fixed min-height pushed the
   composer below the fold on shorter windows, so the first thing you had to do
   on opening the tab was scroll to find the place to type. `--gid-top` is set
   from the panel's own distance from the top of the viewport, so it always
   ends exactly at the bottom edge whatever sits above it. */
.pulse-gid-page {
  display: flex; flex-direction: column;
  height: calc(100dvh - var(--gid-top, 320px));
  min-height: 380px;
}
.pulse-gid-page-body { flex: 1 1 auto; overflow-y: auto; padding: 10px 0 0; }
.pulse-gid-page .pulse-gid-thread { max-width: 720px; margin: 0 auto; }
.pulse-gid-page .pulse-gid-form { max-width: 720px; margin: 0 auto; width: 100%; }

/* Empty state. */
.pulse-gid-empty { padding: 48px 26px 40px; text-align: center; }
.pulse-gid-empty .pulse-gid-mark { margin: 0 auto 18px; }
.pulse-gid-hi { font-size: 17px; font-weight: 550; letter-spacing: -0.01em; margin-bottom: 7px; }
.pulse-gid-sub { font-size: 13.5px; line-height: 20px; color: var(--pulse-ink-soft); max-width: 420px; margin: 0 auto 20px; }
/* A 2x2 grid, not a centred wrap. Four chips of unequal width wrapped so the
   fourth sat alone and off-centre under the other three. */
.pulse-gid-chips {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px; max-width: 560px; margin: 0 auto;
}
@media (max-width: 460px) { .pulse-gid-chips { grid-template-columns: 1fr; } }
.pulse-gid-chip {
  font: inherit; font-size: 12.5px; color: var(--pulse-ink); background: #FFFFFF;
  border: 1px solid var(--pulse-hair); border-radius: 12px; padding: 7px 13px; cursor: pointer;
  text-align: left; transition: background 0.15s linear, border-color 0.15s linear;
}
.pulse-gid-chip:hover { background: var(--pulse-wash); border-color: var(--pulse-hair-strong); }

/* THE THREAD. Modelled on a conversation rather than a form: Gideon's words
   sit on the page with nothing drawn around them, because a box around every
   reply makes a transcript feel like a receipt. Only the person's own lines
   get a container, and a soft one. */
.pulse-gid-thread { padding: 8px 20px 10px; }
.pulse-gid-turn { margin-bottom: 26px; }
.pulse-gid-turn:last-child { margin-bottom: 14px; }
.pulse-gid-turn.is-you { display: flex; justify-content: flex-end; }
.pulse-gid-bubble {
  background: var(--pulse-wash); color: var(--pulse-ink);
  border-radius: 18px; padding: 10px 15px;
  font-size: 14px; line-height: 21px; max-width: 84%;
  white-space: pre-wrap; word-break: break-word;
}
.pulse-gid-turn.is-gid .pulse-gid-who { margin-bottom: 10px; color: var(--pulse-ink-soft); font-weight: 500; }
.pulse-gid-say { font-size: 14.5px; line-height: 24px; letter-spacing: -0.003em; }
.pulse-gid-say p { margin: 0 0 14px; }
.pulse-gid-say p:last-child { margin-bottom: 0; }
.pulse-gid-say ul { margin: 0 0 14px; padding-left: 20px; }
.pulse-gid-say li { margin-bottom: 6px; }
.pulse-gid-say code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px;
  background: var(--pulse-wash); padding: 1px 5px; border-radius: 5px;
}
.pulse-gid-say b { font-weight: 600; }

/* A tool call while it runs. */
.pulse-gid-tools { margin-bottom: 12px; display: flex; flex-direction: column; gap: 6px; }
.pulse-gid-tool {
  display: flex; align-items: center; gap: 9px; font-size: 12.5px;
  color: var(--pulse-ink-soft);
}
/* Only a row being seen for the FIRST time animates in. These rows are
   re-created by every paint, so animating the bare class replayed the
   entrance on every rebuild — the tool name visibly flashing. */
.pulse-gid-tool.is-new {
  animation: gid-tool-in 0.24s cubic-bezier(0.2, 0, 0, 1);
}
@keyframes gid-tool-in { from { opacity: 0; transform: translateY(3px); } }
.pulse-gid-tool-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--pulse-ink); flex: none;
  animation: gid-pulse 1.1s ease-in-out infinite;
}
.pulse-gid-tool.is-done .pulse-gid-tool-dot { animation: none; opacity: 0.28; }
@keyframes gid-pulse { 0%, 100% { opacity: 0.22; transform: scale(0.75); } 50% { opacity: 1; transform: scale(1.15); } }
.pulse-gid-tool-detail { color: var(--text-tertiary); }

.pulse-gid-caret {
  display: inline-block; width: 7px; height: 15px; margin-left: 3px;
  background: var(--pulse-ink); vertical-align: -3px; border-radius: 1px;
  animation: gid-blink 1s steps(2, start) infinite;
}
@keyframes gid-blink { 50% { opacity: 0; } }

/* THE COMPOSER grows with what you type, the way a message box does, up to
   about six lines before it scrolls. The send button sits inside the field
   rather than beside it, so the whole thing reads as one control. */
.pulse-gid-form { flex: none; padding: 8px 14px 14px; background: #FFFFFF; }
.pulse-gid-form.is-big { padding: 12px 16px 18px; }
.pulse-gid-field {
  display: flex; align-items: flex-end; gap: 8px;
  border: 1px solid var(--pulse-hair-strong); border-radius: 22px;
  padding: 7px 7px 7px 16px; background: #FFFFFF;
  transition: border-color 0.15s linear, box-shadow 0.15s linear;
}
.pulse-gid-field:focus-within {
  border-color: rgba(54, 54, 54, 0.45);
  box-shadow: 0 0 0 3px rgba(54, 54, 54, 0.06);
}
.pulse-gid-input {
  flex: 1 1 auto; font: inherit; font-size: 14px; line-height: 21px; color: var(--pulse-ink);
  border: 0; outline: none; background: none; resize: none; overflow-y: auto;
  padding: 5px 0; max-height: 168px;
}
/* The console gives every textarea a blue focus ring. Here the ring belongs on
   the pill around the field, not on the field inside it, or you get a
   rectangle drawn inside a rounded control. The indicator is not removed, it
   moves: `.pulse-gid-field:focus-within` above carries it. */
.pulse-gid-input:focus,
.pulse-gid-input:focus-visible { outline: none; box-shadow: none; }
.pulse-gid-input::placeholder { color: var(--pulse-ink-soft); }
.pulse-gid-input:disabled { color: var(--pulse-ink-soft); }
.pulse-gid-send {
  flex: none; width: 32px; height: 32px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--pulse-ink); color: #FFFFFF; display: inline-flex; align-items: center; justify-content: center;
  transition: opacity 0.15s linear, transform 0.15s ease;
}
.pulse-gid-send svg { width: 16px; height: 16px; }
.pulse-gid-send:hover:not(:disabled) { transform: scale(1.06); }
.pulse-gid-send:disabled { opacity: 0.25; cursor: default; }

@media (prefers-reduced-motion: reduce) {
  .gid-bar, .pulse-gid-tool-dot,
  .pulse-gid-caret, .pulse-gid-dock, .pulse-gid-tool { animation: none; }
  /* Parked at a readable level rather than collapsed to a line. */
  .gid-bar { transform: scaleY(0.62); }
  .pulse-gid-send:hover:not(:disabled) { transform: none; }
}

/* Elapsed time on a tool row, only once there is something worth saying. */
.pulse-gid-tool-took { margin-left: auto; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* What an answer can contain. A heading in a reply is emphasis, not a document
   heading: an <h2> inside a chat panel outranks the page it sits on. */
.pulse-gid-h { font-weight: 600; font-size: 14.5px; margin: 16px 0 8px; letter-spacing: -0.01em; }
.pulse-gid-say > .pulse-gid-h:first-child { margin-top: 0; }
.pulse-gid-rule { border: 0; border-top: 1px solid var(--pulse-hair); margin: 16px 0; }
.pulse-gid-say ol { margin: 0 0 14px; padding-left: 22px; }
.pulse-gid-tablewrap { overflow-x: auto; margin: 0 0 14px; border-radius: 6px; }
.pulse-gid-tablewrap:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
.pulse-gid-table { border-collapse: collapse; width: 100%; font-size: 13px; }
.pulse-gid-table th {
  text-align: left; font-weight: 600; font-size: 11px; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--pulse-ink-soft);
  padding: 0 14px 7px 0; white-space: nowrap;
}
.pulse-gid-table td {
  padding: 7px 14px 7px 0; border-top: 1px solid var(--pulse-hair);
  font-variant-numeric: tabular-nums; vertical-align: top;
}
.pulse-gid-table tr td:first-child { color: var(--pulse-ink); }

/* Stop, and what is waiting behind it. */
.pulse-gid-send.is-stop { background: var(--pulse-ink); }
.pulse-gid-send.is-stop:hover { transform: scale(1.06); }
.pulse-gid-queued {
  display: flex; align-items: center; gap: 7px;
  margin: 0 4px 8px; padding: 6px 12px; border-radius: 10px;
  background: var(--pulse-wash); color: var(--pulse-ink-soft);
  font-size: 12.5px; line-height: 17px;
}
.pulse-gid-queued::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: var(--pulse-ink-soft); flex: none; opacity: 0.6;
}
.pulse-gid-stopped {
  margin-top: 10px; font-size: 12.5px; color: var(--pulse-ink-soft);
}

/* HIS WORKING — folded by default. It is context for when you want it, never
   something you must read to get the answer, so it is quieter than the answer
   and never expands on its own. */
.pulse-gid-think { margin: 2px 0 6px; }
.pulse-gid-think-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--pulse-ink-soft);
  transition: color 0.15s ease;
}
.pulse-gid-think-toggle:hover { color: var(--pulse-ink); }
.pulse-gid-think-caret {
  width: 0; height: 0; display: inline-block;
  border-left: 4px solid currentColor;
  border-top: 3.5px solid transparent; border-bottom: 3.5px solid transparent;
  transition: transform 0.15s ease;
}
.pulse-gid-think.is-open .pulse-gid-think-caret { transform: rotate(90deg); }
.pulse-gid-think-body {
  margin-top: 6px; padding: 8px 10px;
  border-left: 2px solid var(--pulse-line);
  font-size: 12.5px; line-height: 1.55; color: var(--pulse-ink-soft);
  white-space: pre-wrap; max-height: 320px; overflow-y: auto;
}
@media (prefers-reduced-motion: reduce) {
  .pulse-gid-think-toggle, .pulse-gid-think-caret { transition: none; }
}

/* CHARTS IN AN ANSWER — drawn from a ```chart fence with the board's own
   primitives: same ink, same hairlines, same axis type. */
.pulse-gid-chart { margin: 6px 0 16px; padding: 12px 14px 10px; border: 1px solid var(--pulse-hair); border-radius: var(--pulse-radius); background: #FFFFFF; }
.pulse-gid-chart figcaption { font-size: 12.5px; font-weight: 550; color: var(--pulse-ink); margin: 0 0 8px; }
.pulse-gid-chart svg { display: block; width: 100%; height: auto; max-height: 440px; }
.pulse-gid-chart.is-donut svg { width: 160px; height: 160px; }
.pulse-gid-chart.is-drawing { border-style: dashed; color: var(--pulse-ink-soft); font-size: 12.5px; padding: 14px; }
.pulse-gid-chart-line { fill: none; stroke: var(--pulse-ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.pulse-gid-chart-dot { fill: #FFFFFF; stroke: var(--pulse-ink); stroke-width: 2; }
.pulse-gid-chart-dot:hover { fill: var(--pulse-ink); }
.pulse-gid-slice { fill: var(--pulse-ink); }
.pulse-gid-chart-total { fill: var(--pulse-ink); font-size: 20px; font-weight: 600; font-family: var(--font-family); font-variant-numeric: tabular-nums; }
.pulse-gid-glyph.is-on { fill: var(--pulse-ink); }
.pulse-gid-glyph.is-off { fill: var(--pulse-wash-strong); }
.pulse-gid-legend { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12.5px; color: var(--pulse-ink-soft); }
.pulse-gid-legend li { display: inline-flex; align-items: center; gap: 7px; }
.pulse-gid-legend b { color: var(--pulse-ink); font-weight: 550; font-variant-numeric: tabular-nums; }
.pulse-gid-swatch { width: 10px; height: 10px; border-radius: 3px; background: var(--pulse-ink); display: inline-block; flex: none; }
.pulse-gid-pre { margin: 0 0 14px; padding: 10px 12px; background: var(--pulse-wash); border-radius: 8px; overflow-x: auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.5; white-space: pre; }
.pulse-gid-pre code { background: none; padding: 0; font-size: inherit; }

/* A side door in the funnel table: reported, but visibly not a step. */

/* ---------------------------------------------------------------------------
 * The design split (renderDesignSplit): one group per step, new design first,
 * classic right under it. The pill carries identity with a word, never colour alone.
 * ------------------------------------------------------------------------- */

/* The platforms table fits the page instead of scrolling sideways (Manuel, Sep 28 2026: "I hate horizontal scroll"):
   headers wrap, names are narrower, and the three least-used columns step aside on narrower screens. */
.pulse-table th { white-space: normal; }
.pulse-plat-name { max-width: 180px; }
@media (max-width: 1280px) { .pulse-table .is-opt { display: none; } }

/* One person (renderPersonPanel): a side panel over either page, closed with Close or Escape. */
.pulse-person-link { all: unset; cursor: pointer; color: inherit; font: inherit; text-decoration: underline; text-decoration-color: var(--pulse-hair-strong); text-underline-offset: 2px; }
.pulse-person-link:hover, .pulse-person-link:focus-visible { text-decoration-color: currentColor; }
.pulse-table tbody tr.pulse-person-row { cursor: pointer; }
.pulse-table tbody tr.pulse-person-row:hover { background: rgba(0,0,0,0.035); }
.pulse-person-row:hover .pulse-person-link { text-decoration-color: currentColor; }
.pulse-pp-host { padding: 0; position: fixed; inset: 0; z-index: 60; pointer-events: none; }
.pulse-pp-host.is-open { pointer-events: auto; }
html.pulse-pp-lock, html.pulse-pp-lock body { overflow: hidden; }
.pulse-pp-backdrop { position: absolute; inset: 0; background: rgba(17, 19, 24, 0.22); opacity: 0;
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); transition: opacity 0.28s ease; }
.pulse-pp-host.is-open .pulse-pp-backdrop { opacity: 1; }
.pulse-person-panel { position: absolute; top: 0; right: 0; bottom: 0; width: min(560px, 100vw); overflow-y: auto; overscroll-behavior: contain;
  background: #FFFFFF; box-shadow: -24px 0 60px rgba(17, 19, 24, 0.14), -1px 0 0 var(--pulse-hair);
  transform: translateX(104%); transition: transform 0.34s cubic-bezier(0.22, 1, 0.36, 1); outline: none; }
.pulse-pp-host.is-open .pulse-person-panel, .pulse-person-panel.is-open { transform: none; }
@media (prefers-reduced-motion: reduce) { .pulse-person-panel, .pulse-pp-backdrop { transition: none; } }
/* The drawer takes focus on open (keyboard, Escape); it is a surface, not a control, so no ring around it. */
#pulse-person-host .pulse-person-panel:focus, #pulse-person-host .pulse-person-panel:focus-visible { outline: none; box-shadow: -24px 0 60px rgba(17, 19, 24, 0.14), -1px 0 0 var(--pulse-hair); }

.pulse-pp-head { position: sticky; top: 0; z-index: 1; display: flex; gap: 14px; align-items: flex-start; padding: 22px 24px 16px;
  background: rgba(255, 255, 255, 0.92); backdrop-filter: saturate(1.4) blur(10px); -webkit-backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--pulse-hair); }
.pulse-pp-avatar { flex: none; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; font-size: 15px; font-weight: 600;
  letter-spacing: 0.02em; color: var(--pulse-ink); background: linear-gradient(145deg, #F2F2F4, #E6E6EA); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05); }
.pulse-pp-ident { flex: 1; min-width: 0; }
.pulse-pp-name { font-size: 17px; font-weight: 600; line-height: 1.3; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.pulse-pp-who { margin-top: 3px; font-size: 13px; color: var(--pulse-ink-soft); overflow-wrap: anywhere; }
.pulse-pp-plats { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.pulse-pp-plat { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 4px; border-radius: 999px; background: var(--pulse-wash);
  font-size: 12.5px; font-weight: 500; }
.pulse-pp-plat .pulse-plat-mark { width: 20px; height: 20px; }
.pulse-pp-plat-when { color: var(--pulse-ink-soft); font-weight: 400; }
.pulse-pp-close { flex: none; width: 32px; height: 32px; border-radius: 50%; border: 0; display: grid; place-items: center; cursor: pointer;
  background: var(--pulse-wash); color: var(--pulse-ink); transition: background 0.15s ease, transform 0.15s ease; }
.pulse-pp-close:hover { background: var(--pulse-wash-strong); }
.pulse-pp-close:active { transform: scale(0.94); }
.pulse-pp-close:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }

.pulse-pp-body { padding: 18px 24px 40px; display: grid; gap: 14px; }
.pulse-pp-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.pulse-pp-stat { padding: 10px 12px; border-radius: 12px; background: var(--pulse-wash); }
.pulse-pp-stat b { display: block; font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.pulse-pp-stat span { font-size: 12px; color: var(--pulse-ink-soft); }
.pulse-pp-sec { border: 1px solid var(--pulse-hair); border-radius: 14px; padding: 14px 16px; background: #FFFFFF; }
.pulse-pp-sec h3 { display: flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--pulse-ink-soft); margin: 0 0 10px; }
.pulse-pp-count { font-variant-numeric: tabular-nums; color: var(--pulse-ink); }
.pulse-pp-none { font-size: 13px; color: var(--pulse-ink-soft); }
.pulse-pp-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.pulse-pp-row { display: flex; gap: 12px; align-items: center; justify-content: space-between; padding: 10px 0; border-top: 1px solid var(--pulse-hair); font-size: 13.5px; }
.pulse-pp-row:first-child { border-top: 0; padding-top: 2px; }
.pulse-pp-row-main { min-width: 0; display: grid; gap: 4px; justify-items: start; }
.pulse-pp-row-side { flex: none; }
.pulse-pp-meta { font-size: 12.5px; color: var(--pulse-ink-soft); overflow-wrap: anywhere; }
.pulse-pp-when { color: var(--pulse-ink-soft); }
.pulse-pp-replay { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; background: var(--pulse-ink); color: #FFFFFF !important;
  font-size: 12.5px; font-weight: 500; text-decoration: none; white-space: nowrap; transition: transform 0.15s ease, opacity 0.15s ease; }
.pulse-pp-replay + .pulse-pp-replay { margin-left: 6px; }
.pulse-pp-replay:hover { opacity: 0.88; }
.pulse-pp-replay:active { transform: scale(0.97); }
.pulse-pp-replay span { opacity: 0.7; font-variant-numeric: tabular-nums; }
.pulse-pp-lead { font-size: 13.5px; margin-bottom: 8px; }
.pulse-pp-mems { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.pulse-pp-mem { padding: 8px 10px; border-radius: 10px; font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere; }
.pulse-pp-mem:hover { background: var(--pulse-wash); }
.pulse-pp-mem .pulse-pp-meta { margin-top: 2px; }
.pulse-pp-more summary { cursor: pointer; font-size: 12.5px; font-weight: 500; padding: 6px 10px; color: var(--pulse-ink); list-style: none; }
.pulse-pp-more summary::-webkit-details-marker { display: none; }
.pulse-pp-more summary::before { content: "+ "; color: var(--pulse-ink-soft); }
.pulse-pp-more[open] summary::before { content: "− "; }

.pulse-pp-doc { border-top: 1px solid var(--pulse-hair); }
.pulse-pp-doc:first-child { border-top: 0; }
.pulse-pp-doc summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
  padding: 10px 0; font-size: 14px; font-weight: 600; }
.pulse-pp-doc summary::-webkit-details-marker { display: none; }
.pulse-pp-doc summary .pulse-pp-when { font-size: 12px; font-weight: 400; }
.pulse-pp-prose { font-size: 14px; line-height: 1.6; color: var(--pulse-ink); padding-bottom: 12px; overflow-wrap: anywhere; }
.pulse-pp-prose h4 { font-size: 13px; font-weight: 600; margin: 16px 0 6px; letter-spacing: -0.005em; }
.pulse-pp-prose h4:first-child { margin-top: 2px; }
.pulse-pp-prose p { margin: 0 0 10px; }
.pulse-pp-prose ul, .pulse-pp-prose ol { margin: 0 0 10px; padding-left: 20px; }
.pulse-pp-prose li { margin: 3px 0; }
.pulse-pp-prose li::marker { color: var(--pulse-ink-soft); }
.pulse-pp-prose strong { font-weight: 600; }
.pulse-pp-prose em { color: var(--pulse-ink-soft); }
.pulse-pp-prose hr { border: 0; border-top: 1px solid var(--pulse-hair); margin: 14px 0; }
.pulse-pp-prose code { font-size: 12.5px; padding: 1px 5px; border-radius: 5px; background: var(--pulse-wash); }

.pulse-pp-tech summary { cursor: pointer; list-style: none; }
.pulse-pp-tech summary::-webkit-details-marker { display: none; }
.pulse-pp-tech summary h3 { margin: 0; }
.pulse-pp-tech summary h3::after { content: "Show"; margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 500; }
.pulse-pp-tech[open] summary h3::after { content: "Hide"; }
.pulse-pp-tech[open] summary h3 { margin-bottom: 10px; }
.pulse-pp-dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; font-size: 13px; margin: 0; }
.pulse-pp-dl dt { color: var(--pulse-ink-soft); }
.pulse-pp-dl dd { margin: 0; overflow-wrap: anywhere; }
.pulse-pp-skel { display: grid; gap: 10px; }
.pulse-pp-skel span { display: block; height: 58px; border-radius: 14px; background: linear-gradient(90deg, var(--pulse-wash) 0%, var(--pulse-wash-strong) 50%, var(--pulse-wash) 100%);
  background-size: 200% 100%; animation: pulse-pp-shimmer 1.2s ease-in-out infinite; }
@keyframes pulse-pp-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (max-width: 640px) {
  .pulse-person-panel { width: 100vw; }
  .pulse-pp-head { padding: 16px; }
  .pulse-pp-body { padding: 14px 16px 32px; }
  .pulse-pp-stats { grid-template-columns: repeat(2, 1fr); }
}
/* The arrivals chart, stacked: linked since (ink) inside the day's arrivals (soft). */
.pulse-chart-bar.is-linked { fill: var(--pulse-ink); }
.pulse-chart-legend { display: flex; gap: 16px; font-size: 12px; color: var(--pulse-ink-soft); margin: 0 0 8px; }
.pulse-chart-legend span { display: inline-flex; align-items: center; gap: 6px; }
.pulse-chart-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.pulse-chart-legend i.is-linked { background: var(--pulse-ink); }
.pulse-chart-legend i.is-soft { background: rgba(54, 54, 54, 0.28); }
.pulse-src-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.pulse-src-row { display: grid; grid-template-columns: minmax(120px, 180px) 1fr auto; gap: 14px; align-items: center; font-size: 13px; }
.pulse-src-name { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pulse-row-open { appearance: none; border: 0; background: none; padding: 0; margin: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; border-radius: 4px;
  /* Truncates (desktop) or wraps (phone cards) exactly as the name around it does. */
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: inherit; vertical-align: top; }
.pulse-row-open:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
button.pulse-src-name { appearance: none; border: 0; background: none; padding: 0; margin: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; border-radius: 6px; }
button.pulse-src-name:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
.pulse-src-name span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pulse-src-bar { position: relative; height: 10px; border-radius: 5px; background: transparent; }
.pulse-src-all, .pulse-src-linked { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 5px; }
.pulse-src-all { background: rgba(54, 54, 54, 0.28); }
.pulse-src-linked { background: var(--pulse-ink); }
.pulse-src-n { font-size: 12.5px; white-space: nowrap; text-align: right; }

/* The Unlinked tab's "Not counted" line: what the smaller number leaves out. */
.pulse-people-note { padding: 10px 16px; font-size: 12.5px; color: var(--text-tertiary); border-bottom: 1px solid var(--pulse-hair); }

/* Assistant marks in the person drawer (Imports, Memories): each source's own logo on a soft tile tinted
   toward its brand, so "Claude 17" reads at a glance instead of "imported from Claude" on every line. */
.pulse-src-mark { flex: none; display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 10px;
  background: #fff; box-shadow: inset 0 0 0 1px var(--pulse-hair), 0 1px 2px rgba(0, 0, 0, 0.04); }
.pulse-src-mark svg { width: 20px; height: 20px; display: block; }
.pulse-src-mark[data-src="claude"] { background: #FAF3EE; box-shadow: inset 0 0 0 1px rgba(217, 119, 87, 0.22); }
.pulse-src-mark[data-src="chatgpt"] { background: #F4F4F4; }
.pulse-src-mark[data-src="gemini"] { background: #F1F5FF; box-shadow: inset 0 0 0 1px rgba(49, 134, 255, 0.18); }
.pulse-src-mark[data-src="perplexity"] { background: #EEF9FA; box-shadow: inset 0 0 0 1px rgba(34, 184, 205, 0.2); }
.pulse-src-mark.is-letter { font-size: 14px; font-weight: 600; color: var(--pulse-ink-soft); background: var(--pulse-wash); }
.pulse-src-mark.is-sm { width: 18px; height: 18px; border-radius: 5px; box-shadow: none; background: transparent; }
.pulse-src-mark.is-sm svg { width: 14px; height: 14px; }
.pulse-src-mark.is-sm.is-letter { font-size: 10px; background: var(--pulse-wash); }
.pulse-pp-row.pulse-pp-import { justify-content: flex-start; }
.pulse-pp-pills { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.pulse-pp-pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 4px; border-radius: 999px;
  background: var(--pulse-wash); font-size: 12.5px; }
.pulse-pp-pill b { font-weight: 600; }
.pulse-pp-pill .pulse-plat-mark { width: 18px; height: 18px; }
.pulse-pp-from { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; }
.pulse-pp-from .pulse-plat-mark { width: 14px; height: 14px; }
.pulse-pp-from .pulse-src-mark.is-sm { width: 14px; height: 14px; }
.pulse-pp-from .pulse-src-mark.is-sm svg { width: 12px; height: 12px; }
/* The summary card: the one document shown open, in full, at reading size. */
.pulse-pp-summary { font-size: 14px; line-height: 1.6; margin-bottom: 8px; }

/* ---- Profile building / Errors and sign-in, rebuilt (Manuel, Sep 29: "this stuff is messy").
   Headline numbers are tiles; sections have a quiet label and space between them; causes and apps are
   drawn, not listed as dotted-underlined text. Spacing on the 4/8/12/16/24 scale. ---- */
.pulse-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; padding: 16px; }
.pulse-tiles.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pulse-tile { display: grid; align-content: start; gap: 4px; padding: 12px; border-radius: 10px; background: var(--pulse-wash);
  text-align: left; font: inherit; color: inherit; border: 0; min-width: 0; }
.pulse-tile.is-button { cursor: pointer; transition: background .15s ease, box-shadow .15s ease; }
.pulse-tile.is-button:hover { background: var(--pulse-wash-strong); }
.pulse-tile.is-button:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
.pulse-tile.is-on { box-shadow: inset 0 0 0 1.5px var(--pulse-ink); }
.pulse-tile-n { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pulse-tile[data-tone="bad"] .pulse-tile-n { color: var(--pulse-bad); }
.pulse-tile[data-tone="warn"] .pulse-tile-n { color: var(--pulse-warn); }
.pulse-tile[data-tone="good"] .pulse-tile-n { color: var(--pulse-good); }
.pulse-tile-label { font-size: 12.5px; color: var(--text-secondary); }
.pulse-tile-sub { font-size: 12px; color: var(--text-tertiary); }
.pulse-tile-n .pulse-delta, .pulse-tile-n .pulse-chip { font-size: 12px; font-weight: 500; letter-spacing: 0; }
.pulse-sec { padding: 12px 16px 16px; border-top: 1px solid var(--pulse-hair); }
.pulse-sec-title { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-tertiary); margin-bottom: 12px; }
.pulse-sec-title.is-list { margin: 0; padding: 16px 16px 4px; border-top: 1px solid var(--pulse-hair); }
.pulse-sec-note { display: flex; flex-wrap: wrap; gap: 4px 16px; padding: 0 16px 12px; margin-top: -4px; }

.pulse-legend { display: flex; flex-wrap: wrap; gap: 4px 8px; margin-top: 12px; }
.pulse-legend-item { display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; border-radius: 8px; border: 0; background: transparent;
  font: inherit; font-size: 13px; color: var(--text-secondary); cursor: pointer; }
.pulse-legend-item:hover, .pulse-legend-item.is-on { background: var(--pulse-wash); color: var(--pulse-ink); }
.pulse-legend-item i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.pulse-legend-item b { font-weight: 600; color: var(--pulse-ink); }
.pulse-app-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pulse-app-pill { display: inline-flex; align-items: center; gap: 8px; padding: 4px 12px 4px 4px; border-radius: 999px; border: 1px solid var(--pulse-hair);
  background: #fff; font: inherit; font-size: 13px; color: var(--pulse-ink); cursor: pointer; transition: border-color .15s ease, background .15s ease; }
.pulse-app-pill:hover { border-color: var(--pulse-hair-strong); }
.pulse-app-pill.is-on { border-color: var(--pulse-ink); }
.pulse-app-pill b { font-weight: 600; }
.pulse-app-mark { flex: none; display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 9px; background: #fff;
  box-shadow: inset 0 0 0 1px var(--pulse-hair); }
.pulse-app-mark svg { width: 18px; height: 18px; display: block; }
.pulse-app-mark.is-sm { width: 24px; height: 24px; border-radius: 999px; box-shadow: none; background: var(--pulse-wash); }
.pulse-app-mark.is-sm svg { width: 14px; height: 14px; }
.pulse-app-mark.is-letter { font-size: 13px; font-weight: 600; color: var(--text-secondary); background: var(--pulse-wash); }
.pulse-fail-list li { align-items: center; gap: 12px; padding: 12px 16px; }
.pulse-fail-who { font-size: 13.5px; font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pulse-fail-who .pulse-person-link { font-weight: 500; text-decoration: none; }
.pulse-fail-who .pulse-person-link:hover { text-decoration: underline; }
.pulse-fail-why { font-size: 13px; color: var(--pulse-bad); margin-top: 2px; }
.pulse-fail-meta { font-size: 12px; color: var(--text-tertiary); margin-top: 2px; }

.pulse-err-list li { padding: 10px 16px; }
.pulse-err-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pulse-err-name { font-size: 13.5px; font-weight: 500; color: var(--pulse-ink); }
.pulse-err-key { font-size: 11px; color: var(--text-tertiary); background: none; padding: 0; }
.pulse-err-n { margin-left: auto; font-weight: 600; }
.pulse-err-list .pulse-errbar { margin-top: 6px; }
.pulse-pp-import .pulse-pp-row-side { margin-left: auto; }
@media (max-width: 640px) {
  .pulse-tiles, .pulse-tiles.is-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  
  
}

/* The people behind a number: who, where they came from, and the app, each readable at a glance. */
.pulse-people-list li { align-items: center; }
.pulse-people-who .pulse-person-link { font-weight: 500; text-decoration: none; }
.pulse-people-who .pulse-person-link:hover { text-decoration: underline; }
.pulse-came-from { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.pulse-came-plat { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px 1px 2px; border-radius: 999px; background: var(--pulse-wash); font-size: 12px; color: var(--text-secondary); }
.pulse-came-plat .pulse-plat-mark { width: 16px; height: 16px; }
.pulse-came-from.is-direct { font-size: 12px; color: var(--text-tertiary); }

/* ---- The hosted flow, by platform (rebuilt Sep 29). Step counts are the story: big tabular numbers, the funnel read
   left to right with the share that made it between steps, the largest loss marked. Near-monochrome; red only for the
   step that loses the most. ---- */
.pulse-jbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin: 16px 0 16px; }
.pulse-pchips { display: flex; flex-wrap: wrap; gap: 8px; }
.pulse-pchip { display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 4px 14px 4px 6px; border-radius: 999px; border: 1px solid var(--pulse-hair);
  background: #fff; font: inherit; font-size: 13.5px; color: var(--pulse-ink); cursor: pointer; transition: border-color .15s ease, background .15s ease; }
.pulse-pchip:first-child { padding-left: 14px; }
.pulse-pchip:hover { border-color: var(--pulse-hair-strong); }
.pulse-pchip.is-on { background: var(--pulse-ink); border-color: var(--pulse-ink); color: #fff; }
.pulse-pchip .pulse-plat-mark { width: 24px; height: 24px; }
.pulse-pchip:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }
.pulse-jtable td, .pulse-jtable th { white-space: nowrap; }
.pulse-jrow-name { display: flex; align-items: center; gap: 10px; font-weight: 500; }
.pulse-jrow-name .pulse-plat-mark { width: 28px; height: 28px; }

.pulse-jhead { display: flex; align-items: center; gap: 16px; padding: 20px 24px; border-bottom: 1px solid var(--pulse-hair); }
.pulse-jhead .pulse-plat-mark { width: 48px; height: 48px; border-radius: 12px; }
.pulse-jhead h3 { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }
.pulse-jhead p { margin: 2px 0 0; font-size: 13px; color: var(--text-secondary); }
.pulse-jhead-actions { margin-left: auto; }
.pulse-jstats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-bottom: 1px solid var(--pulse-hair); }
.pulse-jstats > div { display: grid; gap: 2px; padding: 16px 24px; border-left: 1px solid var(--pulse-hair); }
.pulse-jstats > div:first-child { border-left: 0; }
.pulse-jstats b { font-size: 20px; font-weight: 600; }
.pulse-jstats span { font-size: 12.5px; color: var(--text-secondary); }
.pulse-jfunnel { padding: 24px; }
.pulse-jtakeaway { margin: 0 0 20px; font-size: 16px; line-height: 1.5; color: var(--pulse-ink); max-width: 72ch; }

.pulse-visits li { align-items: center; padding: 10px 24px; }
.pulse-visit-left { font-size: 13.5px; }
.pulse-visit-left b { font-weight: 600; }
.pulse-visit-norec { font-size: 12px; min-width: 88px; text-align: right; }
.pulse-visits .pulse-pp-replay { margin-left: 8px; }
.pulse-yes { color: var(--pulse-good); font-weight: 600; }
.pulse-jsub { font-size: 12px; margin-top: 2px; }
@media (max-width: 760px) {
  .pulse-jstats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  
  
  
  
  
  
  
}

/* Sentences and one-line summaries in place of split bars and progress bars (research audit, Sep 29). */
.pulse-sentence { margin: 0; font-size: 14px; line-height: 1.7; color: var(--text-secondary); }
.pulse-inline-link { border: 0; background: none; padding: 0; font: inherit; color: inherit; cursor: pointer; border-bottom: 1px dotted var(--pulse-hair-strong); }
.pulse-inline-link b { color: var(--pulse-ink); font-weight: 600; }
.pulse-inline-link:hover, .pulse-inline-link.is-on { color: var(--pulse-ink); border-bottom-color: var(--pulse-ink); }
.pulse-sec-line { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; font-size: 13.5px; color: var(--text-secondary); }
.pulse-err-table th, .pulse-err-table td { padding-left: 16px; padding-right: 16px; }
.pulse-times { font-size: 12px; font-weight: 600; color: var(--text-secondary); background: var(--pulse-wash); padding: 1px 6px; border-radius: 999px; }

.pulse-mline-wrap { padding: 8px 16px 16px; }
.pulse-mline { width: 100%; height: auto; display: block; }
.pulse-mline-path { fill: none; stroke: var(--pulse-ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.pulse-mline-dot { fill: #fff; stroke: var(--pulse-ink); stroke-width: 2; }
.pulse-mline-dot.is-last { fill: var(--pulse-ink); }
.pulse-mline-foot { font-size: 12.5px; color: var(--text-tertiary); margin-top: 4px; }

.pulse-defs-wrap { margin-top: 16px; }
.pulse-defs-wrap summary { cursor: pointer; font-size: 13px; color: var(--text-tertiary); list-style: none; }
.pulse-defs-wrap summary::before { content: "+ "; }
.pulse-defs-wrap[open] summary::before { content: "\2212  "; }

/* Real charts (Sep 29): a guide at the point under the pointer, the point highlighted, the months line at its own width. */
.pulse-chart { position: relative; }
.pulse-chart-guide { stroke: var(--pulse-ink); stroke-width: 1; stroke-dasharray: 2 3; opacity: 0; pointer-events: none; }
.pulse-chart-guide.is-on { opacity: 0.35; }
.pulse-chart-tip { line-height: 1.45; }
.pulse-mline { display: block; width: 100%; height: auto; overflow: visible; }
.pulse-mline-area { fill: var(--pulse-ink); opacity: 0.05; }
.pulse-mline-dot.is-hover { r: 6; fill: var(--pulse-ink); }
.pulse-mline .pulse-chart-val { font-size: 12px; }
.pulse-mline .pulse-chart-axis { font-size: 12px; }
.pulse-src-list { max-width: 820px; }
.pulse-src-row { grid-template-columns: minmax(140px, 200px) minmax(80px, 420px) auto; padding: 6px 8px; margin: 0 -8px; border-radius: 8px; cursor: pointer; }
.pulse-src-row.is-hover, .pulse-src-row:hover { background: var(--pulse-wash); }
.pulse-src-bar { height: 12px; background: var(--pulse-wash); border-radius: 6px; overflow: hidden; }
.pulse-src-name .pulse-plat-mark { width: 22px; height: 22px; }

/* Screen pictures in the rebuilt hosted-flow tab (Sep 29). */
.pulse-jshot { display: block; width: 100%; max-width: 132px; aspect-ratio: 456 / 872; object-fit: contain; object-position: top; border-radius: 10px;
  box-shadow: 0 0 0 1px var(--pulse-hair), 0 4px 14px rgba(0,0,0,0.06); background: #fff; }
.pulse-jshot.is-missing { display: grid; place-items: center; background: var(--pulse-wash); box-shadow: inset 0 0 0 1px var(--pulse-hair); }
.pulse-jshot.is-missing span { font-size: 11px; color: var(--text-tertiary); text-align: center; padding: 8px; }
.pulse-jshot.is-mini { width: 36px; max-width: 36px; border-radius: 6px; flex: none; box-shadow: 0 0 0 1px var(--pulse-hair); }

/* the whole screen, bottom button included: the captures are 456x872 cards, and a 9:16 crop cut off every CTA */

/* The flow in its order: one row per place a visit started (journeyBoard.journeyPathsFrom). */

.pulse-visits li { gap: 12px; }

/* Replay session ids, copyable (so an agent can be sent to watch them). */
.pulse-sec-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pulse-copy { border: 1px solid var(--pulse-hair); background: #fff; border-radius: 999px; padding: 4px 12px; font: inherit; font-size: 12px;
  letter-spacing: 0; text-transform: none; color: var(--pulse-ink); cursor: pointer; }
.pulse-copy:hover { border-color: var(--pulse-hair-strong); }
.pulse-copy.is-small { padding: 1px 8px; font-size: 11px; }
.pulse-sid { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.pulse-sid code { font-size: 11.5px; color: var(--text-secondary); user-select: all; }
.pulse-sid-kind { font-size: 10.5px; font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text-tertiary, var(--text-secondary)); }

/* The trust screen A/B card (pulse.js renderTrustPanel): its picture beside its numbers; stacked on a phone. */

/* ===========================================================================
   Phones and touch
   ---------------------------------------------------------------------------
   The board is read between meetings as often as at a desk. Three rules hold
   everywhere below: nothing scrolls sideways (WCAG 1.4.10 Reflow, down to a
   320px screen); on a touch screen no control is under 24px (2.5.8) and the
   ones used most (segments, tabs, pills, close buttons) are 44px, what a thumb
   needs; and nothing is hidden to make it fit — tables become cards, they do
   not lose columns.
   =========================================================================== */

/* Read by a screen reader, not drawn. */
.pulse-sr {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* The drawer's name is its dialog title (aria-labelledby): a heading, styled as before. */
h2.pulse-pp-name { margin: 0; }
/* Page headings take focus when a page switch removes the control that had it (landFocus); a ring on a heading
   would read as a control, so they show the focus as nothing more than they already are. */
.pulse .pulse-title[tabindex="-1"]:focus, .pulse .pulse-jhead h3[tabindex="-1"]:focus { outline: none; }

/* ---- Touch: targets sized for a finger, whatever the width ---------------- */
@media (pointer: coarse) {
  .pulse-seg button, .pulse-tab, .pulse-live, .pulse-toggle, .pulse-select, .pulse-pchip,
  .pulse-copy, .pulse-gid-chip, .pulse-app-pill, .pulse-legend-item { min-height: 44px; }
  .pulse-seg button, .pulse-tab { display: inline-flex; align-items: center; justify-content: center; }
  .pulse-copy.is-small { min-height: 32px; padding: 4px 12px; }
  .pulse-toggle input { width: 18px; height: 18px; }
  /* Text-styled buttons keep their look; the hit area grows invisibly around them. */
  .pulse-link, .pulse-inline-link { position: relative; }
  .pulse-link::after, .pulse-inline-link::after { content: ""; position: absolute; inset: -12px -6px; }
  .pulse-pp-close, .pulse-gid-x { width: 44px; height: 44px; min-width: 44px; }
  .pulse-gid-x { display: inline-grid; place-items: center; margin-right: -8px; }
  .pulse-gid-send { width: 40px; height: 40px; }
  .pulse-filter button { width: 28px; height: 28px; line-height: 28px; position: relative; }
  .pulse-filter button::after { content: ""; position: absolute; inset: -8px; }
  .pulse-defs-wrap summary { padding: 12px 0; }
  .pulse-chip.is-why { min-height: 32px; padding-inline: 10px; }
  .pulse-stat.is-open-list, .pulse-gid-think-toggle { position: relative; }
  .pulse-stat.is-open-list::after, .pulse-gid-think-toggle::after { content: ""; position: absolute; inset: -12px -4px; }
  .pulse-src-row { padding-block: 10px; }
  button.pulse-src-name { min-height: 32px; }
  /* Names inside a table row: the padding grows the hit area, the negative margin keeps the row's height. */
  .pulse-row-open { padding-block: 6px; margin-block: -6px; }
  .pulse-person-link { padding-block: 6px; }
  .pulse-table-wrap[role="region"]:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: -2px; }
  .pulse-pp-tech summary { min-height: 44px; display: flex; align-items: center; }
  .pulse-pp-tech summary h3 { flex: 1; }
  .pulse-pp-more summary, .pulse-pp-doc summary { min-height: 44px; display: flex; align-items: center; }
  /* Hover affordances that a tap would leave stuck on. */
  
}

/* ---- Up to a large phone ---------------------------------------------------- */
@media (max-width: 640px) {
  .pulse { padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }

  /* Head: title, then the controls as full-width rows a thumb can reach. */
  .pulse-head { gap: 14px; margin-bottom: 16px; }
  .pulse-title { font-size: 20px; }
  .pulse-controls { width: 100%; gap: 8px; }
  .pulse-controls > .pulse-seg { display: flex; flex: 1 1 100%; }
  .pulse-controls > .pulse-seg button { flex: 1 1 0; min-width: 0; padding-inline: 6px; white-space: nowrap; }
  .pulse-controls > .pulse-live { margin-left: auto; }

  /* KPIs two by two: the four numbers on one screen. The scope drops under the label to make the room. */
  .pulse-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .pulse-kpi { padding: 12px; }
  .pulse-kpi-label { flex-direction: column; gap: 2px; margin-bottom: 6px; font-size: 12.5px; }
  .pulse-kpi-scope { font-size: 10px; }
  .pulse-kpi-value { font-size: 26px; }
  .pulse-kpi-row { gap: 4px 6px; }
  .pulse-kpi-row .pulse-delta-vs { flex-basis: 100%; }
  .pulse-kpi-foot { font-size: 11.5px; line-height: 1.4; }

  /* Cards: tighter gutters so the numbers get the width. */
  .pulse-card-head { flex-wrap: wrap; padding: 12px 14px; row-gap: 8px; }
  .pulse-card-head > .pulse-card-meta { flex: 1 1 auto; }
  .pulse-card-body { padding: 14px; }
  .pulse-health-tile { padding: 12px 14px; }
  .pulse-kpi { padding: 14px 14px 12px; }
  /* A card's tabs take the card's width and share it, so every tab and its count is on screen. */
  .pulse-card-head > .pulse-tabs { flex: 1 1 100%; }
  .pulse-tabs { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
  .pulse-tabs::-webkit-scrollbar { display: none; }
  .pulse-tab { flex: 1 0 auto; justify-content: center; white-space: nowrap; padding-inline: 8px; gap: 4px; }
  .pulse-tab-count { padding: 1px 5px; }
  .pulse-cohorts { display: flex; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
  
  
  

  /* TABLES BECOME CARDS. One row, one card: the first cell is its title, every
     other cell a label over its value, two to a line. The labels come from the
     table's own header (labelTables in pulse.js); the header row stays in the
     accessibility tree, only out of sight. The funnel tables keep their grid. */
  .pulse-table-wrap { overflow: visible; }
  .pulse-table:not(.pulse-steps) { display: block; }
  .pulse-table:not(.pulse-steps) thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .pulse-table:not(.pulse-steps) tbody { display: block; }
  .pulse-table:not(.pulse-steps) tbody tr {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px;
    padding: 14px; border-bottom: 1px solid var(--pulse-hair);
  }
  .pulse-table:not(.pulse-steps) tbody tr:last-child { border-bottom: 0; }
  .pulse-table:not(.pulse-steps) td,
  .pulse-table:not(.pulse-steps) th:first-child,
  .pulse-table:not(.pulse-steps) td:first-child,
  .pulse-table:not(.pulse-steps) td:last-child {
    display: block; padding: 0; border: 0; min-width: 0; text-align: left;
  }
  .pulse-table:not(.pulse-steps) td:first-child,
  .pulse-table:not(.pulse-steps) td[colspan] { grid-column: 1 / -1; }
  .pulse-table:not(.pulse-steps) td.pulse-empty { padding: 20px 0; text-align: center; }
  .pulse-table:not(.pulse-steps) td:not(:first-child)[data-label]::before {
    content: attr(data-label); display: block; margin-bottom: 3px;
    font-size: 10.5px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-tertiary); font-variant-numeric: normal;
  }
  /* Room to show what the desktop table steps aside on: a card has no column to spare, it has lines. */
  .pulse-table:not(.pulse-steps) .is-opt { display: block; }
  
  
  .pulse-table tbody tr.is-selected { box-shadow: inset 3px 0 0 var(--pulse-ink); }
  .pulse-plat-name, .pulse-person-name, .pulse-person-sub { max-width: none; }
  /* In a card a name has a line of its own to wrap onto; an ellipsis would only hide it. */
  .pulse-table .pulse-plat-name, .pulse-table .pulse-plat-dev, .pulse-table .pulse-person-sub { white-space: normal; overflow-wrap: anywhere; }
  .pulse-person-name { font-size: 14.5px; }
  .pulse-person-link { display: inline-block; padding: 4px 0; margin: -4px 0; }
  .pulse-jtable td, .pulse-jtable th { white-space: normal; }
  /* The funnel tables that keep their grid scroll inside their card, never the page. */
  .pulse-steps { min-width: 560px; }
  .pulse-table-wrap:has(.pulse-steps) { overflow-x: auto; }

  /* Where people come from: the name and its count on a line, the bar under them. */
  .pulse-src-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 6px; }
  .pulse-src-row .pulse-src-bar { grid-column: 1 / -1; grid-row: 2; }

  /* The rebuilt hosted-flow tab. */
  .pulse-jbar { flex-direction: column; align-items: stretch; }
  .pulse-jbar > .pulse-seg { display: flex; }
  .pulse-jbar > .pulse-seg button { flex: 1 1 0; min-width: 0; padding-inline: 6px; white-space: nowrap; }
  .pulse-jhead { flex-wrap: wrap; gap: 12px; padding: 16px; }
  .pulse-jhead .pulse-plat-mark { width: 40px; height: 40px; }
  .pulse-jhead h3 { font-size: 18px; }
  .pulse-jhead-actions { margin-left: 0; flex: 1 1 100%; }
  .pulse-jstats > div { padding: 12px 16px; }
  .pulse-jstats > div:nth-child(odd) { border-left: 0; }
  .pulse-jstats > div:nth-child(n + 3) { border-top: 1px solid var(--pulse-hair); }
  .pulse-jfunnel { padding: 16px; }
  .pulse-jtakeaway { font-size: 15px; }
  
  
   .pulse-visits li { padding-inline: 16px; }
  /* A screen in a path, or a step of the funnel, is a row: its picture small at the left, its numbers beside it.
     Two phone-sized pictures per row of a phone made the flow eight screens long. */
  
  
  
  
  
  
  
  
  
  
  .pulse-visits li { flex-wrap: wrap; }
  .pulse-sid { flex-wrap: wrap; }
  .pulse-sid code { overflow-wrap: anywhere; }
  .pulse-sec-row { flex-wrap: wrap; }

  /* Lists: the time drops under the line instead of squeezing it. */
  .pulse-list li { flex-wrap: wrap; padding-inline: 14px; }
  .pulse-list-when { flex-basis: 100%; }
  .pulse-tiles { padding: 14px; }
  .pulse-timing { padding: 14px; }
  .pulse-timing-value, .pulse-kpi-value { font-size: 28px; }
  .pulse-months { padding: 12px 14px 14px; gap: 6px; }

  /* "Why it failed" opened sideways off the chip; on a phone there is no side. It rises from the bottom instead. */
  .pulse-why {
    position: fixed; left: 12px; right: 12px; top: auto; bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    width: auto; max-width: none; z-index: 70;
  }

  /* The person drawer covers the screen; its foot clears the home indicator. */
  .pulse-pp-body { padding-bottom: calc(32px + env(safe-area-inset-bottom, 0px)); }
  .pulse-pp-row { flex-wrap: wrap; }
  .pulse-pp-dl { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .pulse-pp-dl dd { margin-bottom: 8px; }

  /* Gideon: the corner button keeps clear of the home indicator, and the dock
     becomes a sheet from the bottom edge — a 420px panel in a corner is a
     desktop idea. */
  /* The corner button is its mark alone on a phone (still named "Ask Gideon"): a labelled pill sat on top of the text being read. */
  .pulse-gid-fab { right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); width: 48px; height: 48px; padding: 0; justify-content: center; }
  .pulse-gid-fab > span:not(.pulse-gid-mark) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .pulse-gid-dock {
    left: 0; right: 0; bottom: 0; width: 100%; max-width: none;
    max-height: calc(100dvh - 56px); border-radius: 20px 20px 0 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    animation-name: gid-sheet;
  }
  .pulse-gid-thread { padding-inline: 16px; }
  .pulse-gid-bubble { max-width: 92%; }
  .pulse-gid-page { min-height: 320px; }
  .pulse-gid-form.is-big { padding: 10px 12px calc(12px + env(safe-area-inset-bottom, 0px)); }
  /* 16px keeps iOS from zooming the page when the composer takes focus. */
  .pulse-gid-input { font-size: 16px; }
  .pulse-gid-input::placeholder { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
@keyframes gid-sheet { from { transform: translateY(24px); opacity: 0; } }

/* ---- The smallest phones -------------------------------------------------- */
@media (max-width: 340px) {
  .pulse-table:not(.pulse-steps) tbody tr { gap: 10px 12px; }
  .pulse-controls > .pulse-seg button, .pulse-jbar > .pulse-seg button { font-size: 12px; padding-inline: 4px; }
}

@media (prefers-reduced-motion: reduce) {
  .pulse-gid-dock { animation: none; }
}

/* ---- The Data story (renderStory in pulse.js) ------------------------------------------------------------------
   One accent, as everywhere on the board: ink. Red only for the one biggest drop-off, always with its words beside it.
   The funnel's bars share one scale (everyone who opened the page): solid for who continued, pale for who left there. */
.pulse-story-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 10px; }
.pulse-story-head .pulse-title { font-size: 20px; }
.pulse-story-head .pulse-sub { max-width: 70ch; }
.pulse-story-n { color: var(--text-tertiary); font-size: 12.5px; line-height: 18px; }
p.pulse-story-n { margin: 8px 0 0; max-width: 90ch; }
.pulse-story-section { overflow-wrap: anywhere; }
.pulse-story-section .pulse-card-title { font-size: 15px; margin: 0; }
.pulse-story-answer { font-size: 14.5px; line-height: 22px; margin: 0 0 14px; max-width: 80ch; }
.pulse-story-list { margin: 0; padding-left: 18px; font-size: 13.5px; line-height: 21px; max-width: 90ch; }
.pulse-story-list li { margin-bottom: 6px; }
.pulse-story-para { font-size: 14px; line-height: 22px; margin: 0 0 12px; max-width: 75ch; }
p.pulse-q-asked { margin: -6px 0 14px; font-style: italic; }
.pulse-story-sub { font-size: 13.5px; font-weight: 600; margin: 18px 0 8px; }
/* Who stays: went quiet is drawn below the line in the board's "bad" colour, named in the legend, never colour alone. */
.pulse-chart-bar.is-quiet { fill: var(--pulse-bad); }
.pulse-chart-val.is-quiet { fill: var(--pulse-bad); }
.pulse-chart-legend i.is-quiet { background: var(--pulse-bad); }
.pulse-stay-heat { min-width: 660px; }
.pulse-stay-heat thead th { white-space: nowrap; }
.pulse-stay-heat th:first-child { width: 110px; white-space: normal; }
.pulse-stay-heat td.is-heat { background: color-mix(in srgb, var(--pulse-good) calc(var(--heat, 0) * 60%), transparent); }
.pulse-stay-table { margin-top: 8px; font-size: 12.5px; }
.pulse-stay-table summary { cursor: pointer; color: var(--pulse-ink-soft); }
.pulse-story-plan-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.pulse-story-btn { min-height: 36px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--pulse-hair-strong); background: #FFFFFF; color: var(--pulse-ink); font: inherit; font-size: 13.5px; font-weight: 500; cursor: pointer; }
.pulse-story-btn:hover { background: var(--pulse-wash); }
.pulse-story-btn.is-primary { background: var(--pulse-ink); border-color: var(--pulse-ink); color: #FFFFFF; }
.pulse-story-btn.is-primary:hover { background: var(--pulse-ink-deep); }
.pulse-story-btn:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; }

/* The one sentence the page leads with. */
.pulse-headline { font-size: 17px; line-height: 26px; font-weight: 500; letter-spacing: -0.005em; margin: 0 0 16px; max-width: 72ch; color: var(--pulse-ink-deep); }

/* Which page, which arm. */
.pulse-sf-pick { margin: 0 0 12px; flex-wrap: wrap; }
.pulse-sf-armrow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; }
.pulse-sf-armlabel { font-size: 12.5px; font-weight: 500; color: var(--pulse-ink-soft); }
.pulse-sf-arms { flex-wrap: wrap; }
.pulse-sf-hint { margin: 0 0 6px; }
.pulse-sf-pick-k { color: var(--text-tertiary); font-weight: 400; }
/* On a phone the chip is a flex box, which drops the space before its span: the gap stands in for it. */
.pulse-sf-pick button { column-gap: .3em; }
.pulse-sf-armline { font-size: 13.5px; line-height: 21px; margin: 14px 0 0; padding: 10px 12px; background: var(--pulse-wash); border-radius: var(--radius-sm, 6px); max-width: 90ch; }
.pulse-sf-foot { margin-top: 12px; }

/* The funnel: a name, a bar on the one scale, the numbers. */
.pulse-sf { list-style: none; margin: 0; padding: 0; font-size: 13.5px; }
.pulse-sf-row {
  display: grid; grid-template-columns: minmax(170px, 230px) minmax(0, 1fr) minmax(250px, auto); column-gap: 16px; align-items: center;
  padding: 9px 0; border-bottom: 1px solid var(--pulse-hair);
}
.pulse-sf-row:last-child { border-bottom: 0; }
.pulse-sf-name {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; text-align: left; font: inherit; font-weight: 500; color: var(--pulse-ink);
  background: none; border: 0; padding: 4px 0; margin: 0;
}
button.pulse-sf-name { cursor: pointer; }
button.pulse-sf-name:hover > span:not(.pulse-chip) { text-decoration: underline; text-underline-offset: 3px; }
button.pulse-sf-name:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; border-radius: 4px; }
.pulse-sf-chev { width: 7px; height: 7px; flex: none; border-right: 1.6px solid var(--pulse-ink-soft); border-bottom: 1.6px solid var(--pulse-ink-soft); transform: rotate(-45deg); margin: 0 4px 0 1px; transition: transform 0.15s ease; }
.pulse-sf-row.is-open .pulse-sf-chev { transform: rotate(45deg); }
.pulse-sf-row.is-start .pulse-sf-name, .pulse-sf-row.is-done .pulse-sf-name { padding-left: 18px; color: var(--pulse-ink-soft); }
.pulse-sf-row.is-done .pulse-sf-name { color: var(--pulse-ink); font-weight: 600; }
.pulse-sf-bar { display: flex; gap: 2px; height: 16px; min-width: 0; }
.pulse-sf-kept, .pulse-sf-lost { display: block; height: 100%; border-radius: 0 4px 4px 0; }
.pulse-sf-kept { background: var(--pulse-ink); }
.pulse-sf-row.is-start .pulse-sf-kept { background: var(--pulse-ink-soft); }
.pulse-sf-lost { background: var(--pulse-wash-strong); }
.pulse-sf-lost.is-worst { background: rgba(179, 38, 30, 0.28); }
.pulse-sf-nums { color: var(--pulse-ink-soft); text-align: right; white-space: nowrap; }
.pulse-sf-nums b { color: var(--pulse-ink); font-weight: 600; }
.pulse-sf-pct { color: var(--text-tertiary); }
.pulse-sf-left { color: var(--pulse-ink); }
.pulse-sf-row.is-worst .pulse-sf-left { color: var(--pulse-bad); font-weight: 600; }
.pulse-sf-row .pulse-chip { font-weight: 500; }

/* A screen opened: what people did on it. */
.pulse-fd { grid-column: 1 / -1; margin: 10px 0 4px 18px; padding: 12px 14px; border-left: 2px solid var(--pulse-hair-strong); background: #FAFAFA; border-radius: 0 var(--radius-sm, 6px) var(--radius-sm, 6px) 0; }
.pulse-fd-lead { margin: 0 0 10px; font-size: 14px; line-height: 21px; font-weight: 500; }
.pulse-fd-grid { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 16px; align-items: start; }
.pulse-fd-shot .pulse-jshot.is-detail { width: 132px; height: auto; max-height: 260px; object-fit: cover; object-position: top; border: 1px solid var(--pulse-hair); border-radius: 8px; display: block; }
.pulse-fd-shot .pulse-jshot.is-detail.is-missing { height: 120px; }
.pulse-fd-main { min-width: 0; }
.pulse-fd-lines { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 2px; max-width: 640px; }
.pulse-fd-lines li { display: flex; align-items: baseline; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--pulse-hair); }
.pulse-fd-lines li:last-child { border-bottom: 0; }
.pulse-fd-lines li > span:first-child { flex: 1; min-width: 0; }
.pulse-fd-lines b { font-weight: 600; }
.pulse-fd-table td .pulse-sf-pct { font-size: 11.5px; margin-left: 2px; }
.pulse-fd .pulse-table-wrap { background: #FFFFFF; }

/* The analysis. */
.pulse-sv-analysis { border-top: 3px solid var(--pulse-ink); }
.pulse-sv-running { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; }
.pulse-sv-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pulse-ink); animation: pulse-sv-blink 1.2s ease-in-out infinite; }
@keyframes pulse-sv-blink { 50% { opacity: 0.25; } }
.pulse-sv-summary { font-size: 16px; line-height: 25px; font-weight: 500; margin: 0 0 16px; max-width: 75ch; }
.pulse-sv-findings { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.pulse-sv-finding { border: 1px solid var(--pulse-hair); border-radius: var(--radius-md, 8px); padding: 14px 16px; }
.pulse-sv-finding-head { display: flex; align-items: flex-start; gap: 10px; }
.pulse-sv-finding-head h4 { margin: 1px 0 0; font-size: 15px; line-height: 21px; font-weight: 600; }
.pulse-sv-rank { flex: none; width: 24px; height: 24px; border-radius: 50%; background: var(--pulse-ink); color: #FFFFFF; display: grid; place-items: center; font-size: 12.5px; font-weight: 600; }
.pulse-sv-finding-body { margin: 8px 0 0 34px; font-size: 14px; line-height: 22px; max-width: 78ch; }
.pulse-sv-do { margin: 10px 0 0 34px; padding: 10px 12px; background: var(--pulse-wash); border-radius: var(--radius-sm, 6px); font-size: 14px; line-height: 21px; }
.pulse-sv-do .pulse-story-n { margin-top: 4px; }
.pulse-sv-do-label { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; margin-right: 6px; }
.pulse-sv-details { margin: 8px 0 0; }
.pulse-sv-finding .pulse-sv-details { margin-left: 34px; }
.pulse-sv-details > summary { cursor: pointer; font-size: 13px; font-weight: 500; color: var(--pulse-ink-soft); padding: 4px 0; width: fit-content; }
.pulse-sv-details > summary:hover { color: var(--pulse-ink); }
.pulse-sv-details > summary:focus-visible { outline: 2px solid var(--pulse-ink); outline-offset: 2px; border-radius: 4px; }
.pulse-sv-details[open] > summary { margin-bottom: 6px; }
.pulse-sv-evidence-on { margin: 0 0 4px; font-size: 13px; line-height: 19px; font-weight: 600; color: var(--pulse-ink); }
.pulse-sv-evidence { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: 13px; line-height: 19px; }
.pulse-sv-evidence li { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; border-bottom: 1px solid var(--pulse-hair); }
.pulse-sv-evidence li:last-child { border-bottom: 0; }
.pulse-sv-evidence span { color: var(--pulse-ink-soft); }
.pulse-sv-evidence b { font-weight: 600; text-align: right; white-space: nowrap; }
.pulse-defs p { margin: 0 0 8px; }

/* A row's own name in a story table reads as text, not as a column heading. */
.pulse-story-section .pulse-table tbody th { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 500; color: var(--pulse-ink); text-align: left; padding: 10px 12px 10px 16px; border-bottom: 1px solid var(--pulse-hair); white-space: normal; }
.pulse-story-section .pulse-table tbody tr:last-child th { border-bottom: 0; }

@media (pointer: coarse) {
  .pulse-story-btn { min-height: 44px; }
  .pulse-sv-details > summary { padding: 10px 0; }
  button.pulse-sf-name { min-height: 44px; }
}
@media (max-width: 900px) {
  /* The name and the numbers on one line, the bar under them at full width. */
  .pulse-sf-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 6px; }
  .pulse-sf-bar { grid-column: 1 / -1; grid-row: 2; }
  .pulse-sf-nums { grid-row: 1; grid-column: 2; }
  .pulse-fd { margin-left: 0; }
  .pulse-fd-grid { grid-template-columns: 88px minmax(0, 1fr); gap: 12px; }
  .pulse-fd-shot .pulse-jshot.is-detail { width: 88px; }
}
@media (max-width: 640px) {
  .pulse-headline { font-size: 16px; line-height: 24px; }
  .pulse-sf-row { grid-template-columns: minmax(0, 1fr); }
  .pulse-sf-nums { grid-row: auto; grid-column: 1; text-align: left; white-space: normal; }
  .pulse-fd-grid { grid-template-columns: minmax(0, 1fr); }
  .pulse-fd-shot { display: none; }
  .pulse-sf-bar { grid-row: auto; }
  .pulse-sf-pick button, .pulse-sf-arms button { flex: 1 1 auto; }
  .pulse-sv-summary { font-size: 15px; line-height: 23px; }
  .pulse-sv-finding { padding: 12px; }
  .pulse-sv-finding-body, .pulse-sv-do, .pulse-sv-finding .pulse-sv-details { margin-left: 0; }
  .pulse-sv-evidence li { flex-direction: column; gap: 0; }
  .pulse-sv-evidence b { text-align: left; white-space: normal; }
  .pulse-story-section .pulse-table:not(.pulse-steps) tbody th:first-child { grid-column: 1 / -1; display: block; padding: 0; border: 0; font-size: 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .pulse-sv-dot { animation: none; }
  .pulse-sf-chev { transition: none; }
}
