/* ============================================================================
   wivo.my — data visualisation layer
   Thin marks, hairline recessive grid, generous air. The data is the only
   thing allowed to be loud. Palette and mark specs follow the validated
   token sheet; see tokens.css for the validator results.
   ========================================================================= */

/* ══ Chart card ══════════════════════════════════════════════════════════ */
.viz-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-3);
  border: 1px solid var(--color-divider);
  background: var(--color-bg);
  min-width: 0;
}
.viz-head { display: flex; align-items: baseline; gap: var(--space-3); min-height: 20px; }
.viz-head h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: .01em;
  margin: 0;
  color: var(--ink-1);
}
.viz-head .sub { font-size: 11.5px; color: var(--ink-3); line-height: 1.35; }
.viz-head .push .ib { width: 24px; height: 22px; min-width: 24px; color: var(--ink-4); }
.viz-head .push .ib:hover { color: var(--ink-1); }
.viz-note { font-size: 11.5px; color: var(--ink-3); line-height: 1.45; }

.viz-plot { position: relative; width: 100%; min-width: 0; }
.viz-fit { width: 100%; min-width: 0; }
/* The viewBox is authored at the container's real pixel width, so the SVG
   renders 1:1 — marks stay at their spec thickness and type stays on the
   app's type scale instead of being scaled up with the box. */
.viz-plot svg { display: block; width: 100%; height: auto; overflow: visible; }

/* Recessive chrome */
.viz-grid-line { stroke: var(--viz-grid); stroke-width: 1; shape-rendering: crispEdges; }
.viz-axis-line { stroke: var(--viz-axis); stroke-width: 1; shape-rendering: crispEdges; }
.viz-tick {
  font-family: var(--font-semi);
  font-size: 10px;
  letter-spacing: .04em;
  fill: var(--ink-4);
  font-variant-numeric: tabular-nums;
}
.viz-cat {
  font-family: var(--font-body);
  font-size: 11.5px;
  fill: var(--ink-2);
}
.viz-value {
  font-family: var(--font-semi);
  font-size: 11px;
  font-weight: 600;
  fill: var(--ink-1);
  font-variant-numeric: tabular-nums;
}
.viz-value-muted { fill: var(--ink-3); font-weight: 400; }

/* Marks */
.viz-bar { transition: opacity .12s ease; }
.viz-hit { fill: transparent; cursor: pointer; }
.viz-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.viz-area { stroke: none; opacity: .1; }
.viz-dot { stroke: var(--color-bg); stroke-width: 2; }
.viz-crosshair { stroke: var(--viz-axis); stroke-width: 1; shape-rendering: crispEdges; }
.viz-band { fill: var(--wash-1); }

.viz-plot.is-dim .viz-bar,
.viz-plot.is-dim .viz-line,
.viz-plot.is-dim .viz-dot { opacity: .35; }
.viz-plot.is-dim .is-hot { opacity: 1; }

/* ══ Legend ══════════════════════════════════════════════════════════════ */
.viz-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: center;
}
.viz-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--ink-2);
  cursor: default;
}
.viz-legend-item .key { width: 10px; height: 10px; flex: none; }
.viz-legend-item .key.line { height: 2px; width: 14px; }
.viz-legend-item .n { color: var(--ink-4); font-variant-numeric: tabular-nums; }
button.viz-legend-item { cursor: pointer; }
button.viz-legend-item:hover { color: var(--ink-1); }
button.viz-legend-item[aria-pressed="false"] { opacity: .4; }

/* ══ Tooltip ═════════════════════════════════════════════════════════════ */
.viz-tip {
  position: fixed;
  z-index: 320;
  pointer-events: none;
  background: var(--color-neutral-900);
  color: var(--color-bg);
  border: 1px solid color-mix(in srgb, var(--color-text) 26%, transparent);
  box-shadow: var(--shadow-md);
  padding: 6px 9px;
  font-size: 12px;
  line-height: 1.45;
  min-width: 96px;
  opacity: 0;
  transition: opacity .1s ease;
}
.viz-tip.is-open { opacity: 1; }
.viz-tip .t {
  font-family: var(--font-semi);
  font-size: 9.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  opacity: .7;
  display: block;
  margin-bottom: 2px;
}
.viz-tip .r { display: flex; align-items: center; gap: 7px; }
.viz-tip .r .key { width: 8px; height: 8px; flex: none; }
.viz-tip .r .v { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 600; }
:root[data-theme="dark"] .viz-tip { background: var(--color-neutral-200); color: var(--color-text); }

/* ══ Table-view twin ═════════════════════════════════════════════════════ */
.viz-table { display: none; max-height: 260px; overflow: auto; border-top: 1px solid var(--color-divider); margin-top: var(--space-2); }
.viz-card.show-table .viz-table { display: block; }
.viz-card.show-table .viz-plot { display: none; }

/* ══ Stat tiles ══════════════════════════════════════════════════════════ */
.tiles { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(146px, 1fr)); }

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: var(--space-3) var(--space-4) var(--space-3);
  border: 1px solid var(--color-divider);
  background: var(--color-bg);
  min-width: 0;
}
.tile .label {
  font-family: var(--font-semi);
  font-size: 10px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.tile .value {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 27px;
  line-height: 1.05;
  letter-spacing: -.015em;
  color: var(--ink-1);
}
.tile .value small { font-size: .5em; font-weight: 500; color: var(--ink-3); margin-left: 3px; letter-spacing: .04em; }
.tile .foot { font-size: 11.5px; color: var(--ink-3); line-height: 1.35; }
.tile .spark { margin-top: 2px; }
.tile .spark svg { display: block; width: 100%; height: 22px; overflow: visible; }

/* The single number a view leads with — one per view */
.hero-figure {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.hero-figure .value {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 58px;
  line-height: .96;
  letter-spacing: -.028em;
  color: var(--ink-1);
}
.hero-figure .value small { font-size: .33em; font-weight: 500; letter-spacing: .02em; color: var(--ink-3); margin-left: 5px; }
.hero-figure .label {
  font-family: var(--font-semi);
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.hero-figure .foot { font-size: 12.5px; color: var(--ink-2); max-width: 46ch; line-height: 1.45; }

/* ══ Meter — fill carries severity, track is a lighter step of one ramp ══ */
.meter { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.meter-head { display: flex; align-items: baseline; gap: var(--space-2); font-size: 12px; color: var(--ink-2); }
.meter-head .v { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink-1); }
.meter-track { height: 6px; background: var(--seq-100); position: relative; overflow: hidden; }
.meter-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--seq-450); transition: width .3s ease; }
/* "Good" is the neutral steel of the sequential ramp, not a green bar. A wall
   of green says "look at me" about the state that needs no looking at; the
   status hues are reserved for the rows that actually want attention. */
.meter[data-sev="good"] .meter-fill { background: var(--seq-450); }
.meter[data-sev="warning"] .meter-fill { background: var(--status-warning); }
.meter[data-sev="serious"] .meter-fill { background: var(--status-serious); }
.meter[data-sev="critical"] .meter-fill { background: var(--status-critical); }
.meter-scale { display: flex; justify-content: space-between; font-size: 9.5px; color: var(--ink-4); font-variant-numeric: tabular-nums; }

/* ══ Heat strip — the document read as a column of paragraphs ════════════ */
.heatstrip { display: flex; flex-direction: column; gap: 2px; }
.heat-row { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; }
.heat-row .idx {
  width: 22px; flex: none;
  font-family: var(--font-semi); font-size: 9.5px; color: var(--ink-4);
  text-align: right; font-variant-numeric: tabular-nums;
}
.heat-row .cells { display: flex; gap: 2px; flex: 1 1 auto; min-width: 0; }
.heat-row .cell { height: 13px; flex: 1 1 0; min-width: 2px; }
.heat-row:hover .cell { outline: 1px solid var(--color-accent); outline-offset: -1px; }
.heat-row .tail { width: 42px; flex: none; font-size: 10px; color: var(--ink-4); font-variant-numeric: tabular-nums; }

.scale-legend { display: flex; align-items: center; gap: 7px; font-size: 10px; color: var(--ink-4); }
.scale-legend .ramp { display: flex; height: 8px; flex: 0 0 96px; }
.scale-legend .ramp i { flex: 1; }

/* ══ Texture — the backup channel, opt-in only ═══════════════════════════ */
:root[data-texture="on"] .viz-bar[data-slot],
:root[data-texture="on"] .viz-area[data-slot] { mask: url(#wivo-hatch-mask); }

@media (forced-colors: active) {
  .viz-bar, .viz-line, .viz-dot { forced-color-adjust: none; }
}
