/* public/css/fk-viz.css — styles for window.fkViz (public/js/fk-viz.js).
   Tokens only: --font-* / --fs-* / --space-* / --radius-* and the text ramp
   (--text / --muted / --muted2) come from :root in public/index.html. Marks
   take their colour from --fkv-c, set per datum by fk-viz.js from
   window.fkChartTheme.palette; text never wears it. Geometry rides
   --fkv-x / --fkv-w so layout stays here, where a media query can reach it. */

/* The type tokens are px, so a reader's larger default font size (125%,
   150%) never reached a chart. Each fkViz size is the token OR the same size
   in rem, whichever is larger: identical at the default 16px root, and it
   grows with the reader's setting. Axis fitting is in ch, so it still holds. */
:root {
  --fkv-fs-micro: max(var(--fs-micro, 11px), .6875rem);
  --fkv-fs-meta:  max(var(--fs-meta, 12px), .75rem);
  --fkv-fs-desc:  max(var(--fs-desc, 13.5px), .84375rem);
  --fkv-fs-lede:  max(var(--fs-lede, 15px), .9375rem);
}

/* ── frame ──────────────────────────────────────────────────────────────── */
.fkv-frame {
  margin: 0; background: var(--bg2); border: 1px solid var(--border2);
  border-radius: var(--radius-lg); padding: var(--space-lg) var(--space-xl) var(--space-lg);
  min-width: 0;
}
.fkv-frame__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-md); flex-wrap: wrap; margin-bottom: var(--space-md); }
.fkv-frame__titles { min-width: 0; flex: 1 1 240px; }
.fkv-frame__title {
  margin: 0; font-family: var(--font-display); font-weight: 700; font-size: var(--fkv-fs-lede);
  color: var(--text); letter-spacing: .2px; line-height: 1.3;
}
.fkv-frame__sub { margin: var(--space-xs) 0 0; font-family: var(--font-body); font-size: var(--fkv-fs-desc); color: var(--muted); line-height: 1.5; }
.fkv-frame__actions { display: flex; gap: var(--space-sm); flex-wrap: wrap; align-items: center; }
.fkv-frame__body { min-width: 0; }
.fkv-frame__meta {
  margin: var(--space-md) 0 0; font-family: var(--font-mono); font-size: var(--fkv-fs-micro);
  letter-spacing: .6px; color: var(--muted2);
}
.fkv-frame__table { margin-top: var(--space-md); border-top: 1px solid var(--border2); padding-top: var(--space-sm); }
.fkv-frame__table > summary {
  cursor: pointer; font-family: var(--font-mono); font-size: var(--fkv-fs-meta); letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--muted); padding: var(--space-xs) 0; width: max-content; max-width: 100%;
}
.fkv-frame__table > summary:hover { color: var(--text); }
.fkv-frame__table[open] > summary { margin-bottom: var(--space-sm); }
.fkv-table caption { text-align: left; font-size: var(--fkv-fs-meta); color: var(--muted); padding-bottom: var(--space-xs); }

.fkv-caption { margin: var(--space-sm) 0 0; font-family: var(--font-body); font-size: var(--fkv-fs-meta); color: var(--muted); line-height: 1.5; }
.fkv-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ── shared axis + gridlines (solid 1px hairlines, never dashed) ─────────── */
.fkv-grid { position: absolute; top: 0; bottom: 0; left: var(--fkv-x); width: 1px; background: var(--cg-hair, rgba(240,237,230,.07)); pointer-events: none; }
/* The axis is a size container in the tick font. Tick text is DM Mono, where
   every glyph is 1ch, so fk-viz.js knows each label's width (--fkv-lw, in ch)
   and the narrowest axis at which it clears its neighbours: .fkv-tick--h<N>
   hides it below N ch. The queries below resolve ch against THIS container's
   font, so they hold at any root font size and re-apply on every resize. */
.fkv-axis {
  position: relative; height: 18px; container: fkv-axis / inline-size;
  font-family: var(--font-mono); font-size: var(--fkv-fs-micro);
}
/* Centred on its value, clamped inside the axis: the first and last label
   never leave the plot, whatever the width. */
.fkv-tick {
  position: absolute; top: 2px;
  left: clamp(0px, calc(var(--fkv-x) - var(--fkv-lw, 0ch) / 2), calc(100% - var(--fkv-lw, 0ch)));
  font-family: var(--font-mono); font-size: var(--fkv-fs-micro); color: var(--muted2);
  white-space: nowrap; font-variant-numeric: tabular-nums; letter-spacing: 0;
}
/* Month labels start just right of their gridline (the label names the month
   that follows it), clamped so the last one ends inside the right edge. */
.fkv-tick--start { left: min(var(--fkv-x), calc(100% - var(--fkv-lw, 0ch))); }
.fkv-tick--month { padding-left: var(--space-xs); line-height: 1.25; }
.fkv-tick__sub { display: block; }
@container fkv-axis (max-width: 5.99ch) { .fkv-tick--h6 { display: none; } }
@container fkv-axis (max-width: 11.99ch) { .fkv-tick--h12 { display: none; } }
@container fkv-axis (max-width: 17.99ch) { .fkv-tick--h18 { display: none; } }
@container fkv-axis (max-width: 23.99ch) { .fkv-tick--h24 { display: none; } }
@container fkv-axis (max-width: 29.99ch) { .fkv-tick--h30 { display: none; } }
@container fkv-axis (max-width: 35.99ch) { .fkv-tick--h36 { display: none; } }
@container fkv-axis (max-width: 41.99ch) { .fkv-tick--h42 { display: none; } }
@container fkv-axis (max-width: 47.99ch) { .fkv-tick--h48 { display: none; } }
@container fkv-axis (max-width: 53.99ch) { .fkv-tick--h54 { display: none; } }
@container fkv-axis (max-width: 59.99ch) { .fkv-tick--h60 { display: none; } }
@container fkv-axis (max-width: 65.99ch) { .fkv-tick--h66 { display: none; } }
@container fkv-axis (max-width: 71.99ch) { .fkv-tick--h72 { display: none; } }
@container fkv-axis (max-width: 77.99ch) { .fkv-tick--h78 { display: none; } }
@container fkv-axis (max-width: 83.99ch) { .fkv-tick--h84 { display: none; } }
@container fkv-axis (max-width: 89.99ch) { .fkv-tick--h90 { display: none; } }
@container fkv-axis (max-width: 95.99ch) { .fkv-tick--h96 { display: none; } }
@container fkv-axis (max-width: 101.99ch) { .fkv-tick--h102 { display: none; } }
@container fkv-axis (max-width: 107.99ch) { .fkv-tick--h108 { display: none; } }
@container fkv-axis (max-width: 113.99ch) { .fkv-tick--h114 { display: none; } }
@container fkv-axis (max-width: 119.99ch) { .fkv-tick--h120 { display: none; } }
@container fkv-axis (max-width: 125.99ch) { .fkv-tick--h126 { display: none; } }
@container fkv-axis (max-width: 131.99ch) { .fkv-tick--h132 { display: none; } }
@container fkv-axis (max-width: 137.99ch) { .fkv-tick--h138 { display: none; } }
@container fkv-axis (max-width: 143.99ch) { .fkv-tick--h144 { display: none; } }
@container fkv-axis (max-width: 149.99ch) { .fkv-tick--h150 { display: none; } }
@container fkv-axis (max-width: 155.99ch) { .fkv-tick--h156 { display: none; } }
@container fkv-axis (max-width: 161.99ch) { .fkv-tick--h162 { display: none; } }
@container fkv-axis (max-width: 167.99ch) { .fkv-tick--h168 { display: none; } }
@container fkv-axis (max-width: 173.99ch) { .fkv-tick--h174 { display: none; } }
@container fkv-axis (max-width: 179.99ch) { .fkv-tick--h180 { display: none; } }
@container fkv-axis (max-width: 185.99ch) { .fkv-tick--h186 { display: none; } }
@container fkv-axis (max-width: 191.99ch) { .fkv-tick--h192 { display: none; } }
@container fkv-axis (max-width: 197.99ch) { .fkv-tick--h198 { display: none; } }
@container fkv-axis (max-width: 203.99ch) { .fkv-tick--h204 { display: none; } }
@container fkv-axis (max-width: 209.99ch) { .fkv-tick--h210 { display: none; } }
@container fkv-axis (max-width: 215.99ch) { .fkv-tick--h216 { display: none; } }
@container fkv-axis (max-width: 221.99ch) { .fkv-tick--h222 { display: none; } }
@container fkv-axis (max-width: 227.99ch) { .fkv-tick--h228 { display: none; } }
@container fkv-axis (max-width: 233.99ch) { .fkv-tick--h234 { display: none; } }
@container fkv-axis (max-width: 239.99ch) { .fkv-tick--h240 { display: none; } }
@container fkv-axis (max-width: 245.99ch) { .fkv-tick--h246 { display: none; } }
@container fkv-axis (max-width: 251.99ch) { .fkv-tick--h252 { display: none; } }
@container fkv-axis (max-width: 257.99ch) { .fkv-tick--h258 { display: none; } }
@container fkv-axis (max-width: 263.99ch) { .fkv-tick--h264 { display: none; } }
@container fkv-axis (max-width: 269.99ch) { .fkv-tick--h270 { display: none; } }
@container fkv-axis (max-width: 275.99ch) { .fkv-tick--h276 { display: none; } }
@container fkv-axis (max-width: 281.99ch) { .fkv-tick--h282 { display: none; } }
@container fkv-axis (max-width: 287.99ch) { .fkv-tick--h288 { display: none; } }
@container fkv-axis (max-width: 293.99ch) { .fkv-tick--h294 { display: none; } }
@container fkv-axis (max-width: 299.99ch) { .fkv-tick--h300 { display: none; } }
@container fkv-axis (max-width: 305.99ch) { .fkv-tick--h306 { display: none; } }
@container fkv-axis (max-width: 311.99ch) { .fkv-tick--h312 { display: none; } }
@container fkv-axis (max-width: 317.99ch) { .fkv-tick--h318 { display: none; } }
@container fkv-axis (max-width: 323.99ch) { .fkv-tick--h324 { display: none; } }
@container fkv-axis (max-width: 329.99ch) { .fkv-tick--h330 { display: none; } }
@container fkv-axis (max-width: 335.99ch) { .fkv-tick--h336 { display: none; } }
@container fkv-axis (max-width: 341.99ch) { .fkv-tick--h342 { display: none; } }
@container fkv-axis (max-width: 347.99ch) { .fkv-tick--h348 { display: none; } }
@container fkv-axis (max-width: 353.99ch) { .fkv-tick--h354 { display: none; } }
@container fkv-axis (max-width: 359.99ch) { .fkv-tick--h360 { display: none; } }

/* ── compareBars ────────────────────────────────────────────────────────── */
.fkv-cb { display: flex; flex-direction: column; gap: var(--space-sm); min-width: 0; }
.fkv-cb__row {
  display: grid; grid-template-columns: minmax(84px, 26%) minmax(0, 1fr) var(--fkv-vw, 9ch);
  align-items: center; gap: var(--space-md);
}
.fkv-cb__label {
  font-family: var(--font-body); font-size: var(--fkv-fs-desc); color: var(--text); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
}
.fkv-cb__row--hi .fkv-cb__label { font-weight: 700; }
.fkv-cb__track { position: relative; height: 20px; min-width: 0; }
.fkv-cb__bar {
  position: absolute; top: 2px; height: 16px; left: var(--fkv-x); width: var(--fkv-w);
  min-width: 2px; background: var(--fkv-c); border-radius: 0 4px 4px 0; transform-origin: left center;
}
.fkv-cb__bar--neg { border-radius: 4px 0 0 4px; transform-origin: right center; }
.fkv-cb__ns, .fkv-tl__none {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  font-family: var(--font-mono); font-size: var(--fkv-fs-micro); letter-spacing: .8px; color: var(--muted2);
  font-style: italic; white-space: nowrap;
}
.fkv-cb__value {
  font-family: var(--font-body); font-size: var(--fkv-fs-desc); font-weight: 600; color: var(--text);
  text-align: right; font-variant-numeric: tabular-nums; line-height: 1.3; display: flex; flex-direction: column; align-items: flex-end;
}
.fkv-cb__value--ns { font-weight: 400; font-style: italic; color: var(--muted2); font-size: var(--fkv-fs-meta); }
.fkv-cb__diff, .fkv-cb__note { font-family: var(--font-mono); font-size: var(--fkv-fs-micro); font-weight: 400; color: var(--muted2); letter-spacing: .3px; white-space: nowrap; }
.fkv-cb__note { white-space: normal; }
.fkv-cb__row--axis { align-items: start; }
.fkv-cb--gap .fkv-caption { color: var(--muted); }
.fkv-anim .fkv-cb__bar { animation: fkv-grow var(--dur-slow, .2s) var(--ease-out, ease-out) both; animation-duration: 240ms; }
@keyframes fkv-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ── ring ───────────────────────────────────────────────────────────────── */
.fkv-ring { display: inline-grid; grid-template-rows: auto auto auto; justify-items: center; gap: var(--space-xs); position: relative; }
.fkv-ring svg { width: var(--fkv-size, 96px); height: var(--fkv-size, 96px); display: block; grid-row: 1; grid-column: 1; }
.fkv-ring__track { fill: none; stroke: var(--border); stroke-width: 9; }
.fkv-ring--ns .fkv-ring__track { stroke: var(--muted2); stroke-width: 1.5; opacity: .6; }
.fkv-ring__arc { fill: none; stroke: var(--fkv-c); stroke-width: 9; stroke-linecap: round; }
.fkv-ring__centre {
  grid-row: 1; grid-column: 1; align-self: center; justify-self: center; max-width: calc(var(--fkv-size, 96px) - 24px);
  font-family: var(--font-display); font-weight: 700; font-size: var(--fkv-fs-lede); color: var(--text);
  text-align: center; line-height: 1.15; font-variant-numeric: tabular-nums;
}
.fkv-ring--ns .fkv-ring__centre { font-family: var(--font-mono); font-weight: 400; font-style: italic; font-size: var(--fkv-fs-micro); color: var(--muted2); }
.fkv-ring__label { font-family: var(--font-mono); font-size: var(--fkv-fs-micro); letter-spacing: 1.3px; text-transform: uppercase; color: var(--muted); text-align: center; max-width: 18ch; }
.fkv-ring__sub { font-family: var(--font-body); font-size: var(--fkv-fs-meta); color: var(--muted2); text-align: center; max-width: 22ch; }
.fkv-anim .fkv-ring__arc { animation: fkv-ring 600ms var(--ease-out, ease-out) both; }
@keyframes fkv-ring { from { stroke-dashoffset: var(--fkv-len); } to { stroke-dashoffset: var(--fkv-off); } }

/* ── waffle ─────────────────────────────────────────────────────────────── */
.fkv-waffle { display: flex; flex-wrap: wrap; gap: var(--space-lg); align-items: flex-start; }
.fkv-waffle__grid { width: 178px; max-width: 100%; height: auto; flex: 0 0 auto; }

/* ── legend ─────────────────────────────────────────────────────────────── */
.fkv-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg); min-width: 0; }
.fkv-waffle .fkv-legend { flex-direction: column; flex: 1 1 200px; }
.fkv-legend__item {
  display: grid; grid-template-columns: 10px minmax(0, max-content) minmax(0, 1fr); column-gap: var(--space-sm); align-items: baseline;
  font-family: var(--font-body); font-size: var(--fkv-fs-desc); color: var(--text); min-width: 0;
}
.fkv-swatch { width: 10px; height: 10px; border-radius: 2px; background: var(--fkv-c); align-self: center; }
.fkv-swatch--hollow { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fkv-c); }
.fkv-legend__label { overflow-wrap: anywhere; }
.fkv-legend__value { font-weight: 600; font-variant-numeric: tabular-nums; }
.fkv-legend__note { grid-column: 2 / -1; font-size: var(--fkv-fs-meta); color: var(--muted); }

/* ── stackedBar ─────────────────────────────────────────────────────────── */
.fkv-sb { display: flex; flex-direction: column; gap: var(--space-md); }
/* The 2px gap between segments is surface, not a stroke around each mark. */
.fkv-sb__bar { display: flex; gap: 2px; height: 20px; width: 100%; }
.fkv-sb__seg { min-width: 2px; background: var(--fkv-c); }
.fkv-sb__seg:first-child { border-radius: 4px 0 0 4px; }
.fkv-sb__seg:last-child { border-radius: 0 4px 4px 0; }
.fkv-sb__seg:only-child { border-radius: 4px; }
/* The flex gap eats width: each share is a basis and they shrink together,
   so the bar never spills past its container. */
.fkv-sb__seg { flex: 1 1 var(--fkv-w); }
.fkv-sb__single { margin: 0; display: flex; align-items: center; gap: var(--space-sm); font-family: var(--font-body); font-size: var(--fkv-fs-desc); color: var(--text); }
.fkv-anim .fkv-sb__bar { animation: fkv-grow 260ms var(--ease-out, ease-out) both; transform-origin: left center; }

/* ── timeline ───────────────────────────────────────────────────────────── */
.fkv-tl { display: flex; flex-direction: column; gap: var(--space-md); min-width: 0; }
.fkv-tl__nav { display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm); flex-wrap: wrap; }
.fkv-tl__range-label { font-family: var(--font-mono); font-size: var(--fkv-fs-meta); letter-spacing: .6px; color: var(--muted); text-align: center; flex: 1 1 auto; }
.fkv-tl__chart { display: flex; flex-direction: column; gap: var(--space-xs); }
.fkv-tl__lane { display: grid; grid-template-columns: minmax(84px, 22%) minmax(0, 1fr); gap: var(--space-md); align-items: center; }
.fkv-tl__label {
  font-family: var(--font-body); font-size: var(--fkv-fs-desc); color: var(--text); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
}
.fkv-tl__track { position: relative; height: 24px; background: var(--bg3); border-radius: var(--radius-sm); min-width: 0; }
.fkv-tl__range { position: absolute; top: 4px; height: 16px; left: var(--fkv-x); width: var(--fkv-w); min-width: 3px; background: var(--fkv-c); border-radius: 3px; box-shadow: 0 0 0 1px var(--bg3); }
.fkv-tl__point { position: absolute; top: 50%; left: var(--fkv-x); width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: var(--fkv-c); box-shadow: 0 0 0 2px var(--bg2); }
.fkv-tl__none { left: var(--space-sm); }
.fkv-axis--months { display: block; height: 32px; }
.fkv-tl__lane--axis .fkv-grid { top: -6px; height: 6px; }

/* ── states ─────────────────────────────────────────────────────────────── */
/* empty / error reuse .empty-state (index.html); this only sizes the drawing. */
.fkv-state__ill { color: var(--gold); line-height: 0; }
.fkv-state__ill .fkv-ill { display: block; }
.fkv-state--error .empty-state__title { color: var(--text); }
.fkv-ill { color: var(--gold); overflow: visible; }
.fkv-ill__dim { stroke: var(--muted2); }
.fkv-ill__fill { fill: currentColor; stroke: none; }

/* loading: a skeleton in the shape of the content (ported from
   .claude/skills/command-grid-ui/reference/components.css .skb) */
.fkv-loading { position: relative; padding: var(--space-sm) 0; }
.fkv-loading__skel { display: flex; flex-direction: column; gap: var(--space-md); }
.fkv-skel-row { display: grid; grid-template-columns: minmax(84px, 26%) minmax(0, 1fr); gap: var(--space-md); align-items: center; }
.fkv-skel {
  display: block; height: 12px; border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--bg3), var(--bg4), var(--bg3)); background-size: 200% 100%;
}
.fkv-skel--label { width: 80%; }
.fkv-skel--bar { height: 16px; width: var(--fkv-w); }
.fkv-skel--line { width: var(--fkv-w); }
.fkv-anim .fkv-skel { animation: fkv-shimmer 1.4s linear infinite; }
@keyframes fkv-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* Narrow: labels go above their bar so the plot keeps its width. */
@media (max-width: 560px) {
  .fkv-frame { padding: var(--space-md); }
  .fkv-cb__row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "label value" "track track"; row-gap: var(--space-xs); }
  .fkv-cb__label { grid-area: label; }
  .fkv-cb__value { grid-area: value; }
  .fkv-cb__track { grid-area: track; }
  .fkv-cb__row--axis { grid-template-areas: "track track"; }
  .fkv-cb__row--axis > span:first-child, .fkv-cb__row--axis > span:last-child { display: none; }
  .fkv-cb__row--axis > .fkv-axis { grid-area: track; }
  .fkv-tl__lane { grid-template-columns: minmax(0, 1fr); gap: var(--space-xs); }
  .fkv-tl__lane--axis > span:first-child { display: none; }
}

/* The one motion gate is fkAnimateAllowed() (fk-viz.js writes .fkv-anim only
   when it says yes); this is the belt to that brace. Final state is the markup. */
@media (prefers-reduced-motion: reduce) {
  .fkv-anim .fkv-cb__bar, .fkv-anim .fkv-sb__bar, .fkv-anim .fkv-ring__arc, .fkv-anim .fkv-skel { animation: none !important; }
}
