/**
 * Chart Factory - Shared Base Styles
 *
 * Common styles used across all D3 visualization components.
 * Import after tokens.css:
 *
 *   @import 'chart-factory/core/tokens.css';
 *   @import 'chart-factory/core/base.css';
 */

/* ===========================
   CONTAINER
   =========================== */

.d3-container {
  display: block;
  width: 100%;
  max-width: var(--container-max-width, 660px);
  box-sizing: border-box;
  background: var(--color-bg-container);
  padding: var(--container-padding, var(--space-8));
  box-shadow: var(--shadow-container);
  text-align: left;
}

/* Charts fill their container; svg viewBox scaling is applied by the factory */
.d3-container svg,
.chart-container svg {
  display: block;
}

/* ===========================
   CHART ELEMENT DEFAULTS
   ===========================
   The canonical look for factory-generated SVG elements. Historically these
   rules were copy-pasted into every example page's <style> block, which meant
   package consumers loading only tokens.css + base.css got browser-default
   black axes and gridlines. They belong here. Scoped under `svg` so generic
   class names (.line, .dot) don't leak onto host-page HTML. */

svg .line {
  fill: none;
  stroke-width: var(--line-stroke-width);
}

svg .axis-x,
svg .axis-y {
  font-family: var(--font-family);
  font-size: var(--font-size-sm);
  color: var(--axis-color);
}

svg .axis-x path,
svg .axis-y path,
svg .axis-x line,
svg .axis-y line {
  stroke: var(--color-border-light, #e5e5e5);
}

svg .axis-y .domain {
  display: none;
}

svg .grid line {
  stroke: var(--color-border-light, #e5e5e5);
  stroke-opacity: var(--grid-stroke-opacity);
}

svg .grid path {
  stroke-width: 0;
}

/* Fallback fill only — dots that set their own fill attribute (per-category
   coloring in the Dot family) keep it. */
svg .dot:not([fill]) {
  fill: var(--chart-primary);
}

/* Legend swatches must never be squished by a tight flex row (would turn a
   circular dot into an oval) — pin their box regardless of available space. */
.legend-dot,
.legend-swatch {
  flex: none;
}

/* ===========================
   TITLE / SUBTITLE / FOOTER
   =========================== */

.d3-title {
  font-family: var(--font-family);
  font-size: var(--font-size-title);
  font-weight: var(--font-weight-bold);
  margin: 0 0 var(--space-2) 0;
  color: var(--color-black);
  letter-spacing: var(--letter-spacing-tight);
}

.d3-subtitle {
  font-family: var(--font-family);
  font-size: var(--font-size-subtitle);
  color: var(--color-text-subtle);
  margin: 0 0 var(--space-6) 0;
  line-height: var(--line-height-normal);
  font-weight: var(--font-weight-normal);
}

.d3-footer {
  margin-top: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-footer);
  font-family: var(--font-family);
  font-size: var(--font-size-xs);
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wider);
  font-weight: var(--font-weight-semibold);
}

/* ===========================
   TOOLTIPS (Shared)
   =========================== */

/* Chart hover tooltip — the node TooltipManager creates ('.d3-tooltip').
   Positioning (fixed/left/top/opacity/z-index) is managed by JS; this class
   owns the appearance. */
.d3-tooltip {
  position: fixed;
  background: var(--color-bg-container);
  border: 1px solid var(--color-border-tooltip);
  border-radius: 6px;
  padding: var(--tooltip-padding, 10px 13px);
  box-shadow: var(--shadow-tooltip);
  z-index: var(--tooltip-z-index, 9999);
  pointer-events: none;
  font-family: var(--font-family);
  font-size: var(--tooltip-font-size, 12px);
  line-height: 1.45;
  min-width: var(--tooltip-min-width, 130px);
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: var(--tooltip-row-gap, 4px);
}

/* Standard tooltip shell rows (TooltipManager.rows).
   Hierarchy: title > values > labels > notes.
   Alignment discipline: text labels flush LEFT, numeric values flush RIGHT. */
.d3-tooltip .d3-tooltip-title {
  font-size: var(--tooltip-title-font-size, 15px);
  font-weight: var(--font-weight-semibold);
  color: var(--color-black);
  letter-spacing: var(--letter-spacing-tight);
}

.d3-tooltip .d3-tooltip-label {
  color: var(--color-text-subtle);
}

.d3-tooltip .d3-tooltip-value {
  font-weight: var(--font-weight-semibold);
  color: var(--color-black);
  font-variant-numeric: tabular-nums;
}

.d3-tooltip .d3-tooltip-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

/* In swatched rows the label is the middle of three flex children —
   grow it so it hugs the swatch on the left instead of centering.
   (No flex gap: the swatch's own margin spaces it from the label; the
   value's margin guarantees the minimum label-to-value separation.) */
.d3-tooltip .d3-tooltip-row .d3-tooltip-label {
  flex: 1 1 auto;
  text-align: left;
}

.d3-tooltip .d3-tooltip-row .d3-tooltip-value {
  text-align: right;
  margin-left: var(--space-4);
}

.d3-tooltip .d3-tooltip-note {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.d3-tooltip .d3-tooltip-footer {
  border-top: 1px solid var(--color-border-row);
  padding-top: var(--tooltip-row-gap, 3px);
  margin-top: 1px;
}

.d3-tooltip .d3-tooltip-bar {
  height: 3px;
  border-radius: 2px;
  margin-top: 2px;
}

.d3-tooltip .d3-tooltip-swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: var(--space-1);
  flex: none;
}

.d3-tooltip-chart {
  display: flex;
  align-items: flex-end;
  gap: var(--tooltip-bar-gap);
  height: var(--tooltip-chart-height);
  position: relative;
  box-sizing: border-box;
}

.d3-tooltip-bar {
  flex: 1;
  background-color: var(--color-text-muted);
  border-radius: var(--tooltip-bar-border-radius);
  min-width: var(--tooltip-bar-min-width);
  position: relative;
  max-height: var(--tooltip-chart-height);
}

.d3-tooltip-bar-label {
  position: absolute;
  bottom: calc(-1 * var(--tooltip-label-offset-y));
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  white-space: nowrap;
}

.d3-tooltip-bar-value {
  position: absolute;
  top: calc(-1 * var(--tooltip-value-offset-y));
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-black);
  white-space: nowrap;
}

/* ===========================
   RESPONSIVE
   =========================== */

@media (max-width: 768px) {
  .d3-container {
    padding: var(--container-padding-mobile);
  }

  .d3-title {
    font-size: var(--title-font-size-mobile);
  }
}

/* ===========================
   CHART SHELL (universal config: title / subtitle / legend / footer)
   Rendered by the responsive wrapper around the chart svg — one
   implementation for every builder, token-driven, dark-mode-live.
   =========================== */
.d3-shell-title {
  font-family: var(--font-family);
  font-size: var(--shell-title-size, 15px);
  font-weight: var(--font-weight-bold);
  color: var(--color-black);
  letter-spacing: var(--letter-spacing-tight);
  margin: 0 0 2px 0;
}

.d3-shell-subtitle {
  font-family: var(--font-family);
  font-size: var(--shell-subtitle-size, 11px);
  color: var(--color-text-subtle);
  margin: 0 0 var(--space-3) 0;
}

.d3-shell--featured.d3-shell-title {
  font-size: var(--shell-featured-title-size, 20px);
  margin-bottom: var(--space-1);
}

.d3-shell--featured.d3-shell-subtitle {
  font-size: var(--shell-featured-subtitle-size, 14px);
  margin-bottom: var(--space-4);
}

.d3-shell-legend {
  margin-bottom: var(--space-3);
}

.d3-shell-footer {
  font-family: var(--font-family);
  font-size: var(--font-size-xs);
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-row);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* Chart story (story: config): narrative summary module rendered by the
   wrapper below the svg, above the footer. Variants replicate the picked
   story-module mockups: panel (accent-tinted takeaway), bubble (card with
   an up-pointing tail — the chart is speaking), band (full-width dark
   stat lede). All colors flow through the --story-* tokens; the `accent`
   option overrides --story-accent inline on the module. */
.chart-story {
  font-family: var(--font-family);
  font-size: var(--story-font-size);
  line-height: var(--story-line-height);
  color: var(--color-text-primary);
  margin-top: var(--space-3);
}

.chart-story-body { margin: 0; }

/* Optional uppercase lead-in (bubble and band variants) */
.chart-story-overline {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-wider);
  text-transform: uppercase;
  color: var(--color-text-subtle);
  margin-bottom: 3px;
}

.chart-story-icon { display: inline-flex; flex: none; }
.chart-story-icon svg { display: block; }

/* panel — soft accent wash + accent hairline; icon and bold accent label
   lead the prose inline */
.chart-story--panel {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  background: color-mix(in srgb, var(--story-accent) var(--story-panel-bg-alpha), transparent);
  border: 1px solid color-mix(in srgb, var(--story-accent) var(--story-panel-border-alpha), transparent);
  border-radius: 8px;
  padding: 11px 14px;
}
.chart-story--panel .chart-story-icon { margin-top: 2px; }
.chart-story-label {
  color: var(--story-accent);
  font-weight: var(--font-weight-bold);
}

/* bubble — container-background card whose rotated-square tail points up
   at the chart */
.chart-story--bubble {
  position: relative;
  margin-top: calc(var(--space-3) + 7px);   /* room for the tail */
  background: var(--color-bg-container);
  border: 1px solid var(--color-border-light);
  border-radius: 10px;
  padding: 11px 15px;
  box-shadow: var(--shadow-tooltip);
}
.chart-story--bubble::before {
  content: "";
  position: absolute;
  top: -7px;
  left: 34px;
  width: 12px;
  height: 12px;
  background: var(--color-bg-container);
  border-left: 1px solid var(--color-border-light);
  border-top: 1px solid var(--color-border-light);
  transform: rotate(45deg);
}

/* band — full-width dark lede strip; spans the CHART CONTAINER (not any
   outer card the page may have); <b>/<strong> pick up the accent */
.chart-story--band {
  background: var(--story-band-bg);
  color: var(--story-band-text);
  border-radius: 6px;
  padding: 13px 16px 14px;
}
.chart-story--band .chart-story-overline { color: var(--story-band-label); }
.chart-story--band .chart-story-body b,
.chart-story--band .chart-story-body strong { color: var(--story-accent); }

/* ===========================
   CHART STATES (state: 'loading' | 'empty' | 'error')
   ===========================
   The state box takes the chart's exact footprint (height set inline by
   the wrapper), so the real chart swaps in with zero layout jump. Loading
   skeletons breathe on a constant 5s cadence with one straight shimmer
   band (9s cycle: ~3.3s crossing + ~5.7s rest) clipped to the shapes. */

.d3-state {
  position: relative;
  width: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  text-align: center;
}

.d3-state-msg {
  font-family: var(--font-family);
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
}

.d3-state-glyph {
  font-size: 22px;
  line-height: 1;
  color: var(--color-text-faint);
}

.d3-state--error .d3-state-glyph { color: var(--chart-red); opacity: 0.7; }
.d3-state--error .d3-state-msg   { color: var(--color-text-primary); }

/* Loading fallback: three pulsing dots */
.d3-state-dots { display: flex; gap: 5px; }
.d3-state-dots span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-text-faint);
  animation: d3-state-pulse 1.2s ease-in-out infinite;
}
.d3-state-dots span:nth-child(2) { animation-delay: 0.2s; }
.d3-state-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes d3-state-pulse {
  0%, 80%, 100% { opacity: 0.25; transform: scale(0.85); }
  40%           { opacity: 1;    transform: scale(1); }
}

/* Loading skeleton: breathing columns. The shimmer is ONE band swept
   across the whole set — each column's ::after is sized/offset in
   container coordinates (via the --sw-* custom properties the wrapper
   sets) so the gradient lines up seamlessly across all columns. */
.d3-state--columns { display: block; }
.d3-skel-col {
  position: absolute;
  bottom: 8%;
  border-radius: 3px 3px 0 0;
  background: var(--color-bg-highlight);
  overflow: hidden;
  transition: height 5s ease-in-out;
}
.d3-skel-col::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--sw-left);
  width: var(--sw-width);
  background: linear-gradient(90deg, transparent 42%,
      color-mix(in srgb, var(--color-text-faint) 16%, transparent) 50%,
      transparent 58%);
  animation: d3-skel-sweep 9s linear infinite;
  transform: translateX(-100%);
}
@keyframes d3-skel-sweep {
  0%   { transform: translateX(-100%); }
  37%  { transform: translateX(100%); }
  100% { transform: translateX(100%); }
}

/* Rows/trend skeletons are SVG (shimmer clipped to the shapes via SMIL);
   the svg just needs to fill the state box. */
.d3-state--rows svg, .d3-state--trend svg { display: block; width: 100%; height: 100%; }

/* ============================================
   Facet helper (ChartFactory.facet) — minimal small-multiples chrome.
   The grid itself is inline (display:grid on the caller's container);
   these style the panels the helper creates inside it.
   ============================================ */
.d3-facet-panel { min-width: 0; }
.d3-facet-chart { display: block; width: 100%; }
