/* ==========================================================================
   K10 Data Visualization — page styles
   KPI tiles, SVG charts, forest plot, ring gauge, device status, data table
   and rules. Charts start undrawn; `.is-drawn` on <main> (set by
   assets/js/pages/k10-data-visualization.js) draws them in.
   ========================================================================== */

.replay-btn {
  align-self: flex-start;
  height: 44px;
  padding: 0 18px;
  border: 1px solid var(--ink-a24);
  border-radius: var(--radius-pill);
  background: var(--graphite-0);
  color: var(--graphite-900);
  font: 500 15px/1 'Geist', sans-serif;
  cursor: pointer;
}

/* ── Shared card + draw-in transitions ─────────────────────────────────── */

.kpi,
.chart-card,
.gauge-card {
  margin: 0;
}

/* Animated line: pathLength="1" + stroke-dasharray="1", offset 1 → 0 */
.sparkline__line,
.chart__line--draw {
  stroke-dashoffset: 1;
}
.is-drawn .sparkline__line,
.is-drawn .chart__line--draw {
  stroke-dashoffset: 0;
}

/* ── 10.1 KPI tiles & sparklines ────────────────────────────────────────── */

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: 16px;
}

.kpi {
  padding: 20px;
  border-radius: var(--radius-l);
  border: 1px solid var(--color-hairline);
  background: var(--graphite-0);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.kpi__value-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.kpi__value {
  font: 500 40px/1 'Geist', sans-serif;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.kpi__unit {
  font: 500 14px/1 'Geist Mono', monospace;
  color: var(--graphite-500);
}

.sparkline__area {
  fill: rgba(10, 122, 95, .08);
  opacity: 0;
  transition: opacity var(--dur-5) 400ms;
}
.is-drawn .sparkline__area { opacity: 1; }

.sparkline__line {
  fill: none;
  stroke: var(--graphite-900);
  stroke-width: 1.5;
  transition: stroke-dashoffset 1400ms var(--ease-diastole);
}

.kpi__foot {
  display: flex;
  justify-content: space-between;
  font: 400 12px/1 'Geist Mono', monospace;
}

.kpi__delta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.kpi__delta--good  { color: var(--status-success-fg); }
.kpi__delta--watch { color: var(--status-medium-fg); }

.kpi__period { color: var(--graphite-500); }

/* ── Chart cards ────────────────────────────────────────────────────────── */

.chart-grid {
  max-width: 1120px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr));
  gap: 20px;
}
.chart-grid--narrow {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}

.chart-card {
  padding: 24px;
  border-radius: var(--radius-l);
  border: 1px solid var(--color-hairline);
  background: var(--graphite-0);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.chart-card__head {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.chart-card__title { font: 500 17px/1.2 'Geist', sans-serif; }

.chart-card__meta {
  font: 400 12px/1 'Geist Mono', monospace;
  color: var(--graphite-500);
}

/* Text alternative under every chart */
.chart-card__caption {
  font: 400 12px/1.5 'Geist Mono', monospace;
  color: var(--graphite-500);
}

/* Legend */
.chart-legend {
  display: flex;
  gap: 14px;
  font: 400 12px/1 'Geist Mono', monospace;
  color: var(--graphite-600);
}

.chart-legend__item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.chart-legend__line {
  width: 14px;
  height: 2px;
  background: var(--graphite-900);
}
.chart-legend__line--arc { background: var(--viz-1); }
.chart-legend__line--conventional,
.chart-legend__line--manual {
  height: 0;
  background: none;
  border-top: 2px dashed var(--graphite-400);
}
.chart-legend__line--manual { border-top-color: var(--viz-2); }

.chart-legend__box {
  width: 10px;
  height: 10px;
  background: var(--graphite-300);
}
.chart-legend__box--after { background: var(--scrub-600); }

/* ── SVG chart marks ────────────────────────────────────────────────────── */

.chart__tick,
.chart__annotation,
.chart__bar-value {
  font-family: 'Geist Mono';
  font-size: 11px;
}
.chart__tick { fill: var(--graphite-500); }
.chart__annotation,
.chart__bar-value { fill: var(--graphite-900); }

.chart__grid-line { stroke: var(--ink-a08); }
.chart__baseline  { stroke: var(--ink-a30); }

.chart__annotation-rule {
  stroke: var(--graphite-900);
  stroke-dasharray: 2 3;
}

.chart__area {
  fill: rgba(10, 122, 95, .1);
  opacity: 0;
  transition: opacity var(--dur-5) 600ms;
}
.is-drawn .chart__area { opacity: 1; }

.chart__line {
  fill: none;
  stroke-width: 2;
}
.chart__line--draw { transition: stroke-dashoffset 1600ms var(--ease-diastole); }

.chart__line--arc-cases { stroke: var(--graphite-900); }

.chart__line--conventional {
  stroke: var(--graphite-400);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
}

.chart__line--arc { stroke: var(--viz-1); }

.chart__line--manual {
  stroke: var(--viz-2);
  stroke-dasharray: 6 4;
}

/* Kaplan–Meier censoring ticks */
.chart__censor { stroke-width: 1.5; }
.chart__censor--arc    { stroke: var(--viz-1); }
.chart__censor--manual { stroke: var(--viz-2); }

/* Grouped bars grow from the baseline; --delay staggers each site */
.chart__bar {
  transform-box: fill-box;
  transform-origin: bottom;
  transform: scaleY(0);
  transition: transform var(--dur-5) var(--ease-diastole) var(--delay, 0ms);
}
.is-drawn .chart__bar { transform: scaleY(1); }
.chart__bar--before { fill: var(--graphite-300); }
.chart__bar--after  { fill: var(--scrub-600); }

.chart__bar-value {
  opacity: 0;
  transition: opacity var(--dur-3) 900ms;
}
.is-drawn .chart__bar-value { opacity: 1; }

/* Kaplan–Meier numbers at risk */
.at-risk {
  display: grid;
  grid-template-columns: 90px repeat(3, 1fr);
  padding-top: 6px;
  border-top: 1px solid var(--ink-a10);
  font: 400 11px/1.8 'Geist Mono', monospace;
  color: var(--graphite-600);
}
.at-risk__label { color: var(--graphite-500); }

/* ── Forest plot ────────────────────────────────────────────────────────── */

.forest {
  display: flex;
  flex-direction: column;
}

.forest__row,
.forest__axis {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 2fr) 110px;
  gap: 12px;
}

.forest__row {
  align-items: center;
  min-height: 36px;
  border-bottom: 1px solid rgba(10, 18, 22, .06);
}

.forest__study { font: 400 13px/1.2 'Geist', sans-serif; }

.forest__n {
  display: block;
  font: 400 11px/1.2 'Geist Mono', monospace;
  color: var(--graphite-500);
}

.forest__track {
  position: relative;
  height: 20px;
}

/* Line of no effect at 0 (25% of the −5 … +15 axis) */
.forest__zero {
  position: absolute;
  left: 25%;
  top: -8px;
  bottom: -8px;
  width: 1px;
  background: rgba(10, 18, 22, .4);
}

.forest__ci {
  position: absolute;
  left: var(--lo);
  top: 50%;
  width: var(--ci);
  height: 1px;
  background: var(--graphite-900);
  transform-origin: 25%;
  transform: scaleX(0);
  transition: transform var(--dur-5) var(--ease-diastole) var(--delay, 0ms);
}
.is-drawn .forest__ci { transform: scaleX(1); }

.forest__point {
  position: absolute;
  left: var(--pt);
  top: 50%;
  width: var(--size);
  height: var(--size);
  background: var(--graphite-900);
  transform: translate(-50%, -50%) rotate(0deg);
  opacity: 0;
  transition: opacity var(--dur-3) var(--delay, 0ms);
}
.is-drawn .forest__point { opacity: 1; }

.forest__estimate {
  font: 400 12px/1 'Geist Mono', monospace;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Pooled estimate: scrub diamond, medium weight */
.forest__row--pooled .forest__study,
.forest__row--pooled .forest__estimate { font-weight: 500; }
.forest__row--pooled .forest__point {
  background: var(--scrub-600);
  transform: translate(-50%, -50%) rotate(45deg);
}

.forest__axis {
  padding-top: 8px;
  font: 400 11px/1 'Geist Mono', monospace;
  color: var(--graphite-500);
}

.forest__axis-scale {
  display: flex;
  justify-content: space-between;
}

/* ── Ring gauge (OR Dark card) ──────────────────────────────────────────── */

.gauge-card {
  padding: 24px;
  border-radius: var(--radius-l);
  background: var(--graphite-950);
  color: var(--graphite-mist);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.gauge-card__label {
  align-self: flex-start;
  font: 500 11px/1 'Geist Mono', monospace;
  letter-spacing: .08em;
  color: var(--mist-400);
}

.gauge {
  position: relative;
  width: 200px;
  height: 200px;
}

/* Calibration ticks around the ring */
.gauge__ticks {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: repeating-conic-gradient(var(--mist-a30) 0 .6deg, transparent .6deg 7.5deg);
  -webkit-mask: radial-gradient(circle, transparent 90%, #000 91%);
  mask: radial-gradient(circle, transparent 90%, #000 91%);
}

.gauge__svg {
  position: absolute;
  inset: 0;
  transform: rotate(-90deg);
}

.gauge__track {
  fill: none;
  stroke: var(--mist-a10);
  stroke-width: 10;
}

/* Circumference 2πr = 502.65; --value (0…1) sets the filled share */
.gauge__value {
  fill: none;
  stroke: var(--scrub-300);
  stroke-width: 10;
  stroke-linecap: round;
  stroke-dashoffset: 502.65;
  transition: stroke-dashoffset 1600ms var(--ease-diastole);
}
.is-drawn .gauge__value { stroke-dashoffset: calc(502.65 * (1 - var(--value))); }

.gauge__inner {
  fill: none;
  stroke: var(--mist-a12);
}

.gauge__readout {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

.gauge__number {
  font: 500 48px/1 'Geist', sans-serif;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}

.gauge__unit {
  font: 500 16px 'Geist Mono', monospace;
  color: var(--mist-400);
}

.gauge__target {
  font: 400 11px/1 'Geist Mono', monospace;
  color: var(--mist-400);
}

.gauge-card__caption {
  align-self: stretch;
  font: 400 12px/1.5 'Geist Mono', monospace;
  color: var(--mist-400);
}

/* ── Device status indicators ───────────────────────────────────────────── */

.device-panel {
  grid-column: span 2;
  min-width: 0;
  padding: 24px;
  border-radius: var(--radius-l);
  border: 1px solid var(--color-hairline);
  background: var(--graphite-0);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

.device {
  padding: 14px;
  border-radius: 12px;
  border: 1px solid var(--color-hairline);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.device--fault { border-color: var(--status-high-fg); }

.device__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.device__name { font: 500 15px/1.2 'Geist', sans-serif; }

.device__id {
  font: 400 11px/1 'Geist Mono', monospace;
  color: var(--graphite-500);
}

.device__meta {
  font: 400 12px/1.3 'Geist Mono', monospace;
  color: var(--graphite-500);
}

/* Status pill: glyph + label + colour */
.status-pill {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  font: 500 12px/1 'Geist', sans-serif;
}
.status-pill__glyph { font: 600 11px/1 'Geist Mono', monospace; }

.status-pill--sm { height: 24px; padding: 0 9px; }
.status-pill--sm .status-pill__glyph { font-size: 10px; }

.status-pill--ok   { background: var(--status-success-bg); color: var(--status-success-fg); }
.status-pill--warn { background: var(--status-medium-bg);  color: var(--status-medium-fg); }
.status-pill--err  { background: var(--status-high-bg);    color: var(--status-high-fg); }
.status-pill--info { background: var(--status-low-bg);     color: var(--status-low-fg); }

/* ── 10.2 Data table ────────────────────────────────────────────────────── */

.table-section { gap: 16px; }

.table-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
}

.table-filter {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 240px;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--ink-a20);
  border-radius: var(--radius-m);
  background: var(--graphite-0);
}

.table-filter__icon {
  width: 10px;
  height: 10px;
  border: 1.5px solid var(--graphite-500);
  border-radius: 50%;
}

.table-filter__input {
  flex: 1;
  border: 0;
  outline: 0;
  background: transparent;
  font: 400 15px/1 'Geist', sans-serif;
}

/* Bulk actions — shown while rows are selected */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 6px 0 14px;
  border-radius: var(--radius-pill);
  background: var(--graphite-900);
  color: var(--graphite-50);
  font: 500 14px/1 'Geist', sans-serif;
}

.bulk-bar__btn {
  height: 34px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--graphite-800);
  color: var(--graphite-50);
  font: 500 13px/1 'Geist', sans-serif;
  cursor: pointer;
}

.bulk-bar__clear {
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--mist-300);
  cursor: pointer;
}

.data-table-wrap {
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-l);
  background: var(--graphite-0);
  overflow-x: auto;
}

.data-table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font: 400 14px/1.3 'Geist', sans-serif;
}

.data-table th {
  padding: 0;
  border-bottom: 1px solid var(--color-hairline);
}

.data-table td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--ink-a07);
}

.data-table tr.is-selected { background: var(--graphite-50); }

.data-table .data-table__check { padding: 0 0 0 16px; }
.data-table th.data-table__check { width: 48px; }

.data-table__check input {
  width: 18px;
  height: 18px;
  accent-color: var(--graphite-900);
}

.data-table__head { text-align: left; }
.data-table__head--right { text-align: right; }

.data-table__sort {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 6px;
  width: 100%;
  height: 48px;
  padding: 0 16px;
  border: 0;
  background: none;
  color: var(--graphite-500);
  font: 500 11px/1 'Geist Mono', monospace;
  letter-spacing: .08em;
  cursor: pointer;
}
.data-table__head--right .data-table__sort { justify-content: flex-end; }
[aria-sort="ascending"] > .data-table__sort,
[aria-sort="descending"] > .data-table__sort { color: var(--graphite-900); }

.data-table__site { font-weight: 500; }

.data-table .data-table__serial { font: 400 13px/1 'Geist Mono', monospace; }

.data-table .data-table__num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.data-table .data-table__empty td {
  padding: 32px 16px;
  border-bottom: 0;
  text-align: center;
  color: var(--graphite-600);
}

.data-table__clear {
  border: 0;
  background: none;
  color: var(--scrub-600);
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
}

/* ── 10.3 Rules ─────────────────────────────────────────────────────────── */

.rule-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 16px;
}

.rule-card {
  padding: 20px;
  border-radius: 12px;
  border: 1px solid var(--color-hairline);
  background: var(--graphite-0);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rule-card__text {
  font: 400 15px/1.5 'Geist', sans-serif;
  color: var(--graphite-750);
}

.rule-card__example {
  padding: 8px 10px;
  border-radius: 6px;
  background: var(--graphite-50);
  color: var(--graphite-900);
  font: 400 12px/1.4 'Geist Mono', monospace;
}

/* ── Without JavaScript ─────────────────────────────────────────────────────
   The chart draw-in is started by k10-data-visualization.js. When scripting is off, show the final
   state right away (same declarations as the rules above). */

@media (scripting: none) {
  .sparkline__line,
  .chart__line--draw { stroke-dashoffset: 0; }
  .sparkline__area { opacity: 1; }
  .chart__area { opacity: 1; }
  .chart__bar { transform: scaleY(1); }
  .chart__bar-value { opacity: 1; }
  .forest__ci { transform: scaleX(1); }
  .forest__point { opacity: 1; }
  .gauge__value { stroke-dashoffset: calc(502.65 * (1 - var(--value))); }
}
