/**
 * Keystone — Charts (optional module) — Style
 * ============================================================
 * Chart tokens + chart chrome for the Keystone charting toolset.
 *
 *   <link rel="stylesheet" href="keystone-charts.css">
 *   <script type="module" src="keystone-charts.js"></script>
 *
 * Works standalone: every token that borrows from keystone.css carries a
 * literal fallback, so charts render correctly without the core stylesheet
 * (and keystone-charts.js self-boots without keystone.js). Without the JS,
 * a chart's source <table> simply renders as a readable table — nothing in
 * this file hides content on its own.
 *
 * Sections:
 *   1. Chart tokens (light / dark / system-dark)
 *   2. Figure & plot chrome
 *   3. Marks (SVG)
 *   4. Legend
 *   5. Tooltip & crosshair
 *   6. Data table (the "View data" disclosure)
 *   7. Donut center label
 *   8. Sparklines
 *   9. Entrance animation & motion preferences
 */

/* ============================================================
   1. CHART TOKENS
   ------------------------------------------------------------
   The categorical slots are a colorblind-safe palette validated
   against Keystone's light (#FFFFFF) and dark (#191A1E) surfaces
   (adjacent-pair CVD dE >= 8, normal-vision dE >= 15, both modes).
   Slot 1 is Keystone steel blue re-stepped to clear the chroma
   floor. THE SLOT ORDER IS THE SAFETY MECHANISM — never reorder
   or re-hue without re-running the palette validator. Series are
   assigned by fixed slot index, never cycled or ranked.
   Dark values are re-stepped for the dark surface, not a flip.
   State tokens (--ks-success-* etc.) are NEVER series colors.
   ============================================================ */

:root {
  --ks-chart-1: #386AAA;  /* steel blue (brand-anchored) */
  --ks-chart-2: #EB6834;  /* orange  */
  --ks-chart-3: #1BAF7A;  /* aqua    */
  --ks-chart-4: #EDA100;  /* yellow  */
  --ks-chart-5: #E87BA4;  /* magenta */
  --ks-chart-6: #008300;  /* green   */
  --ks-chart-7: #4A3AA7;  /* violet  */
  --ks-chart-8: #E34948;  /* red     */

  /* Chart chrome — recessive by design; the data is the loud part. */
  --ks-chart-grid:    var(--ks-slate-100, #ECECEE);
  --ks-chart-axis:    var(--ks-slate-300, #C6C6CB);
  --ks-chart-label:   var(--ks-text-muted, #6A6A72);
  /* The color of the 2px gaps between touching marks and the rings around
     dots. Defaults to the raised surface; when a chart sits directly on the
     canvas, override per instance: style="--ks-chart-surface: var(--ks-canvas)" */
  --ks-chart-surface: var(--ks-surface-default, #FFFFFF);
}

/* ---- Dark theme ---- */
[data-theme="dark"] {
  --ks-chart-1: #588BCD;
  --ks-chart-2: #D95926;
  --ks-chart-3: #199E70;
  --ks-chart-4: #C98500;
  --ks-chart-5: #D55181;
  --ks-chart-6: #008300;
  --ks-chart-7: #9085E9;
  --ks-chart-8: #E66767;

  --ks-chart-grid:    var(--ks-surface-emphasis, #2B2C32);
  --ks-chart-axis:    var(--ks-slate-700, #3D3D43);
  --ks-chart-label:   var(--ks-text-muted, #95959C);
  --ks-chart-surface: var(--ks-surface-default, #191A1E);
}

/* ---- System mode: honor the OS when no explicit theme is set ----
   KEEP THESE TOKENS IN SYNC with the [data-theme="dark"] block above. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --ks-chart-1: #588BCD;
    --ks-chart-2: #D95926;
    --ks-chart-3: #199E70;
    --ks-chart-4: #C98500;
    --ks-chart-5: #D55181;
    --ks-chart-6: #008300;
    --ks-chart-7: #9085E9;
    --ks-chart-8: #E66767;

    --ks-chart-grid:    var(--ks-surface-emphasis, #2B2C32);
    --ks-chart-axis:    var(--ks-slate-700, #3D3D43);
    --ks-chart-label:   var(--ks-text-muted, #95959C);
    --ks-chart-surface: var(--ks-surface-default, #191A1E);
  }
}

/* ============================================================
   2. FIGURE & PLOT CHROME — .ks-chart
   ============================================================ */

.ks-chart {
  margin: 0;  /* <figure> reset */
  font-family: var(--ks-font-sans, system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif);
  color: var(--ks-text-default, #191A1E);
}
.ks-chart-title {
  margin: 0 0 var(--ks-space-3, 0.75rem);
  font-size: var(--ks-text-sm, 0.875rem);
  font-weight: var(--ks-weight-semibold, 600);
  color: var(--ks-text-default, #191A1E);
}
/* The plot region wraps the SVG (and the donut center overlay). */
.ks-chart-plot { position: relative; }
.ks-chart-svg { display: block; width: 100%; }
.ks-chart-svg text {
  font-family: var(--ks-font-sans, system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif);
}

/* ============================================================
   3. MARKS (SVG)
   ------------------------------------------------------------
   Marks carry the series color via currentColor: each series
   group gets style="color: var(--ks-chart-N)", so a theme flip
   recolors every chart with zero JS. Text NEVER wears the series
   color — labels/ticks use text tokens.
   ============================================================ */

/* Recessive chrome: hairline solid gridlines, baseline-only axis. */
.ks-chart-gridline { stroke: var(--ks-chart-grid, #ECECEE); stroke-width: 1; shape-rendering: crispEdges; }
.ks-chart-axisline { stroke: var(--ks-chart-axis, #C6C6CB); stroke-width: 1; shape-rendering: crispEdges; }
.ks-chart-tick {
  fill: var(--ks-chart-label, #6A6A72);
  font-size: var(--ks-text-xs, 0.75rem);
  font-variant-numeric: tabular-nums;  /* axis ticks align vertically */
}

/* Series marks */
.ks-chart-bar  { fill: currentColor; }
.ks-chart-line {
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
}
.ks-chart-area { fill: currentColor; fill-opacity: 0.1; stroke: none; }
/* Dots/end-markers wear a 2px surface ring so they stay legible where
   they cross a line or another dot. */
.ks-chart-dot  { fill: currentColor; stroke: var(--ks-chart-surface, #FFFFFF); stroke-width: 2; }
.ks-chart-arc  { fill: none; stroke: currentColor; }

/* Direct labels (selective — endpoint/cap only, never every point).
   Text tokens, never the series color. */
.ks-chart-mark-label {
  fill: var(--ks-text-default, #191A1E);
  font-size: var(--ks-text-xs, 0.75rem);
  font-weight: var(--ks-weight-semibold, 600);
  font-variant-numeric: tabular-nums;
}
.ks-chart-end-label {
  fill: var(--ks-chart-label, #6A6A72);
  font-size: var(--ks-text-xs, 0.75rem);
  font-weight: var(--ks-weight-medium, 500);
}

/* Invisible enlarged hit targets (>= mark + gap; min 24px). Focusable:
   keyboard users get the same tooltip as hover. */
.ks-chart-hit { fill: transparent; stroke: none; outline: none; }
.ks-chart-hit:focus-visible { stroke: var(--ks-border-focus, #3D5A82); stroke-width: 2; }

/* Hovered mark responds tonally: siblings recede, nothing moves or glows. */
.ks-chart-svg.is-hovering .ks-chart-bar:not(.is-hover),
.ks-chart-svg.is-hovering .ks-chart-arc:not(.is-hover) {
  opacity: 0.55;
}
.ks-chart-bar, .ks-chart-arc {
  transition: opacity var(--ks-duration-fast, 100ms) var(--ks-ease-default, cubic-bezier(0.4, 0, 0.2, 1));
}

/* ============================================================
   4. LEGEND — always present for >= 2 series (JS omits it for one)
   ============================================================ */

.ks-chart-legend {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--ks-space-1\.5, 0.375rem) var(--ks-space-4, 1rem);
  margin-top: var(--ks-space-3, 0.75rem);
  font-size: var(--ks-text-sm, 0.875rem);
  color: var(--ks-text-muted, #6A6A72);
}
.ks-chart-legend-item { display: inline-flex; align-items: center; gap: var(--ks-space-2, 0.5rem); }
/* The key mirrors the mark: rect for bars/areas/segments, stroke for lines.
   The key element itself carries style="color: var(--ks-chart-N)". */
.ks-chart-key {
  flex: none; width: 12px; height: 12px;
  border-radius: var(--ks-radius-sm, 2px);
  background: currentColor;
}
.ks-chart-key--line { width: 16px; height: 3px; border-radius: 1.5px; }

/* ============================================================
   5. TOOLTIP & CROSSHAIR
   ------------------------------------------------------------
   One fixed-position tooltip chip shared by every chart on the
   page. Same dark-chip treatment as .ks-tooltip: stays a dark,
   elevated chip in dark mode rather than flipping to white.
   ============================================================ */

.ks-chart-tip {
  position: fixed; z-index: var(--ks-z-tooltip, 1060);
  max-width: 280px;
  padding: var(--ks-space-2, 0.5rem) var(--ks-space-2\.5, 0.625rem);
  font-family: var(--ks-font-sans, system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif);
  font-size: var(--ks-text-xs, 0.75rem);
  line-height: var(--ks-leading-snug, 1.375);
  color: var(--ks-slate-0, #FFFFFF);
  background: var(--ks-slate-900, #191A1E);
  border-radius: var(--ks-radius-sm, 2px);
  box-shadow: var(--ks-shadow-lg, 0 2px 4px rgb(24 24 28 / 0.06), 0 12px 30px -4px rgb(24 24 28 / 0.14));
  opacity: 0;
  transition: opacity var(--ks-duration-fast, 100ms) var(--ks-ease-default, cubic-bezier(0.4, 0, 0.2, 1));
  pointer-events: none;
}
.ks-chart-tip.is-visible { opacity: 1; }
[data-theme="dark"] .ks-chart-tip {
  background: var(--ks-surface-emphasis, #2B2C32);
  color: var(--ks-text-default, #F6F6F7);
  box-shadow: var(--ks-shadow-lg, none), var(--ks-edge, inset 0 0 0 1px rgb(255 255 255 / 0.10));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .ks-chart-tip {
    background: var(--ks-surface-emphasis, #2B2C32);
    color: var(--ks-text-default, #F6F6F7);
    box-shadow: var(--ks-shadow-lg, none), var(--ks-edge, inset 0 0 0 1px rgb(255 255 255 / 0.10));
  }
}

.ks-chart-tip-title {
  margin-bottom: var(--ks-space-1, 0.25rem);
  font-weight: var(--ks-weight-semibold, 600);
}
/* Values lead, labels follow: the value is the strong element, the series
   name secondary. Rows key their series with a short stroke, not a box. */
.ks-chart-tip-row { display: flex; align-items: center; gap: var(--ks-space-2, 0.5rem); }
.ks-chart-tip-row + .ks-chart-tip-row { margin-top: var(--ks-space-0\.5, 0.125rem); }
.ks-chart-tip-key { flex: none; width: 10px; height: 2px; border-radius: 1px; background: currentColor; }
.ks-chart-tip-name { opacity: 0.75; }
.ks-chart-tip-val {
  margin-left: auto; padding-left: var(--ks-space-3, 0.75rem);
  font-weight: var(--ks-weight-semibold, 600);
  font-variant-numeric: tabular-nums;
}

/* Crosshair — a vertical hairline that snaps to the nearest X on
   line/area charts. Readers aim at a date, never at a 2px line. */
.ks-chart-crosshair { stroke: var(--ks-chart-axis, #C6C6CB); stroke-width: 1; visibility: hidden; }
.ks-chart-svg.is-hovering .ks-chart-crosshair { visibility: visible; }
/* Cursor dots ride the crosshair, one per series, at the snapped X. */
.ks-chart-cursor-dot { visibility: hidden; }
.ks-chart-svg.is-hovering .ks-chart-cursor-dot { visibility: visible; }

/* ============================================================
   6. DATA TABLE — the disclosure that keeps the source table
   ------------------------------------------------------------
   The table is the chart's non-visual representation; the JS
   moves it here but NEVER removes it. Without JS this container
   never exists and the table just renders in place.
   ============================================================ */

.ks-chart-data { margin-top: var(--ks-space-2, 0.5rem); }
.ks-chart-data-toggle {
  display: inline-flex; align-items: center; gap: var(--ks-space-1\.5, 0.375rem);
  padding: var(--ks-space-1\.5, 0.375rem) var(--ks-space-2\.5, 0.625rem);
  font: inherit;
  font-size: var(--ks-text-sm, 0.875rem);
  font-weight: var(--ks-weight-medium, 500);
  color: var(--ks-text-muted, #6A6A72);
  background: transparent; border: 0;
  border-radius: var(--ks-radius-md, 3px);
  cursor: pointer;
  transition: var(--ks-transition-colors, color 100ms, background-color 100ms);
}
.ks-chart-data-toggle:hover {
  color: var(--ks-text-default, #191A1E);
  background: rgb(var(--ks-shadow-color, 24 24 28) / 0.05);
}
.ks-chart-data-toggle:focus-visible {
  outline: none;
  box-shadow: var(--ks-glow-focus, 0 0 0 2px #FFFFFF, 0 0 0 4px #466A99);
}
.ks-chart-data-toggle svg {
  transition: transform var(--ks-duration-normal, 200ms) var(--ks-ease-default, cubic-bezier(0.4, 0, 0.2, 1));
}
.ks-chart-data.is-open .ks-chart-data-toggle svg { transform: rotate(180deg); }
.ks-chart-data-body { margin-top: var(--ks-space-2, 0.5rem); overflow-x: auto; }

/* Screen-reader-only mode (data-ks-table="sr-only"): the table stays in the
   accessibility tree but off-screen. Self-contained (no core dependency). */
.ks-chart-data--sr {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
}

/* ============================================================
   7. DONUT CENTER LABEL — HTML overlay, never SVG text
   ============================================================ */

.ks-chart-donut-center {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  pointer-events: none;
}
.ks-chart-donut-value {
  font-size: var(--ks-text-2xl, 1.5rem);
  font-weight: var(--ks-weight-bold, 700);
  line-height: var(--ks-leading-tight, 1.25);
  color: var(--ks-text-default, #191A1E);
  /* Proportional figures: a big standalone number, not a column. */
}
.ks-chart-donut-caption {
  font-size: var(--ks-text-xs, 0.75rem);
  color: var(--ks-text-muted, #6A6A72);
}

/* ============================================================
   8. SPARKLINES — .ks-sparkline
   ------------------------------------------------------------
   An inline mini-trend. Colored via currentColor (default slot 1);
   override per instance with style="color: ...". `.ks-stat-spark`
   seats one inside a .ks-stat tile (core CSS untouched).
   ============================================================ */

.ks-sparkline {
  display: inline-block;
  width: 120px; height: 32px;
  vertical-align: middle;
  color: var(--ks-chart-1, #386AAA);
}
.ks-sparkline svg { display: block; width: 100%; height: 100%; }
.ks-sparkline-line {
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
}
.ks-sparkline-area { fill: currentColor; fill-opacity: 0.1; stroke: none; }
.ks-sparkline-bar  { fill: currentColor; }
.ks-sparkline-dot  { fill: currentColor; stroke: var(--ks-chart-surface, #FFFFFF); stroke-width: 2; }

.ks-stat-spark {
  display: block;
  width: 100%; height: 36px;
  margin-top: var(--ks-space-2\.5, 0.625rem);
}

/* ============================================================
   9. ENTRANCE ANIMATION & MOTION PREFERENCES
   ------------------------------------------------------------
   The JS renders FINAL geometry immediately and (when motion is
   allowed) adds .ks-anim at build, then .is-in on first
   intersection — so the transition runs from the CSS-declared
   start state to the true values. Reduced motion is honored
   twice: the JS never adds .ks-anim (braces), and the block at
   the bottom zeroes everything anyway (belt).
   ============================================================ */

/* Bars grow from the baseline. fill-box + origin keeps the scale local
   to each rect; horizontal variants scale from the value axis instead. */
.ks-chart-bar { transform-box: fill-box; }
.ks-chart-svg.ks-anim .ks-chart-bar { transform: scaleY(0); transform-origin: 50% 100%; }
.ks-chart-svg.ks-anim.ks-anim--h .ks-chart-bar { transform: scaleX(0); transform-origin: 0% 50%; }
.ks-chart-svg.ks-anim.is-in .ks-chart-bar {
  transform: none;
  transition: transform var(--ks-duration-slow, 350ms) var(--ks-ease-out, cubic-bezier(0, 0, 0.2, 1));
}

/* Lines draw in left-to-right. pathLength="1" normalizes every path,
   so a unit dash is a full draw — no measurement needed. */
.ks-chart-svg.ks-anim .ks-chart-line { stroke-dasharray: 1; stroke-dashoffset: 1; }
.ks-chart-svg.ks-anim.is-in .ks-chart-line {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 600ms var(--ks-ease-out, cubic-bezier(0, 0, 0.2, 1));
}

/* Areas, dots, labels and donut arcs fade in behind the draw. */
.ks-chart-svg.ks-anim .ks-chart-area,
.ks-chart-svg.ks-anim .ks-chart-dot,
.ks-chart-svg.ks-anim .ks-chart-arc,
.ks-chart-svg.ks-anim .ks-chart-mark-label,
.ks-chart-svg.ks-anim .ks-chart-end-label { opacity: 0; }
.ks-chart-svg.ks-anim.is-in .ks-chart-area,
.ks-chart-svg.ks-anim.is-in .ks-chart-dot,
.ks-chart-svg.ks-anim.is-in .ks-chart-arc,
.ks-chart-svg.ks-anim.is-in .ks-chart-mark-label,
.ks-chart-svg.ks-anim.is-in .ks-chart-end-label {
  opacity: 1;
  transition: opacity var(--ks-duration-slow, 350ms) var(--ks-ease-default, cubic-bezier(0.4, 0, 0.2, 1)) 150ms;
}
/* The area/dot/arc rules above end at their class-declared opacity; the
   arc/dot base opacity is 1, the area's fill-opacity is its own wash. */

/* Reduced motion zeroes the entrance (the JS also never adds .ks-anim then —
   belt AND braces); print forces the final state so a chart that hasn't been
   scrolled into view yet never prints collapsed. */
@media (prefers-reduced-motion: reduce), print {
  .ks-chart-svg.ks-anim .ks-chart-bar { transform: none; }
  .ks-chart-svg.ks-anim .ks-chart-line { stroke-dasharray: none; stroke-dashoffset: 0; }
  .ks-chart-svg.ks-anim .ks-chart-area,
  .ks-chart-svg.ks-anim .ks-chart-dot,
  .ks-chart-svg.ks-anim .ks-chart-arc,
  .ks-chart-svg.ks-anim .ks-chart-mark-label,
  .ks-chart-svg.ks-anim .ks-chart-end-label { opacity: 1; }
  .ks-chart-svg .ks-chart-bar,
  .ks-chart-svg .ks-chart-arc,
  .ks-chart-tip,
  .ks-chart-data-toggle svg { transition: none; }
}
