/* ==========================================================================
   Voca Design System — Data-viz components
   The graphic language of the product dashboard, reused on the marketing page.

   Method (per the dataviz skill): coral is the primary data hue, navy the
   comparison hue (CVD-safe pair), neutral tracks behind. Marks are thin, ends
   are rounded (4px), fills sit on a 2px surface gap, and EVERY mark is
   direct-labeled — colour never carries meaning alone. Grid/axes are recessive.

   Values are passed in from app.js as inline custom properties (e.g. --pct:74);
   the `.is-drawn` class (toggled when the chart scrolls into view) animates
   marks from zero. All motion is disabled under prefers-reduced-motion.
   ========================================================================== */

/* ---------- Horizontal bar chart ---------- */
.chart {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.chart-caption {
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--data-axis-text);
  margin: 0;
}

.bar-row {
  display: grid;
  gap: var(--space-2);
}
.bar-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}
.bar-row-label {
  font-size: var(--text-sm);
  color: var(--text-primary);
}
.bar-row-value {
  font-weight: 700;
  font-size: var(--text-base);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bar-track {
  position: relative;
  height: 12px;
  border-radius: 6px;
  background: var(--data-track);
  overflow: hidden;
}
.bar-fill {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 0;
  border-radius: 6px;
  background: var(--data-primary);
  transition: width 1s cubic-bezier(0.22, 1, 0.36, 1);
}
.bar-fill--secondary { background: var(--data-secondary); }
.is-drawn .bar-fill { width: calc(var(--pct) * 1%); }

.bar-row-source {
  font-size: var(--text-xs);
  color: var(--data-axis-text);
}

/* ---------- Gap comparison (two large paired bars) ---------- */
.gap {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.gap-pair { display: flex; flex-direction: column; gap: var(--space-3); }
.gap-bar { display: grid; gap: var(--space-2); }
.gap-bar-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
}
.gap-bar-value {
  font-family: var(--font-family-base);
  font-weight: 700;
  font-size: var(--text-2xl);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.gap-bar--high .gap-bar-value { color: var(--data-primary); }
.gap-bar--low  .gap-bar-value { color: var(--text-secondary); }
.gap-bar-label { font-size: var(--text-sm); color: var(--text-secondary); text-align: end; }
.gap-track { height: 16px; border-radius: 8px; background: var(--data-track); overflow: hidden; }
.gap-track-fill {
  height: 100%; width: 0; border-radius: 8px;
  transition: width 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.gap-bar--high .gap-track-fill { background: var(--data-primary); }
.gap-bar--low  .gap-track-fill { background: var(--data-secondary); }
.is-drawn .gap-track-fill { width: calc(var(--pct) * 1%); }

/* ---------- Radial gauge / ring ----------
   The ring holds the number ONLY. Its label always sits below the ring
   (.gauge-figure > .gauge-caption) so the mark stays uncluttered at any size. */
.gauge-figure {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
}
.gauge-caption {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  text-align: center;
  max-width: 16ch;
}
.on-inverse .gauge-caption { color: color-mix(in srgb, var(--text-on-brand) 70%, transparent); }

.gauge { position: relative; display: inline-grid; place-items: center; }
.gauge svg { display: block; transform: rotate(-90deg); }
.gauge .gauge-track { fill: none; stroke: var(--data-track); }
.gauge .gauge-value {
  fill: none;
  stroke: var(--data-primary);
  stroke-linecap: round;
  /* --c (circumference) and --off (target) are set inline by app.js.
     Start fully hidden; .is-drawn animates the offset down to --off. */
  stroke-dashoffset: var(--c);
  transition: stroke-dashoffset 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.is-drawn .gauge .gauge-value,
.gauge.is-drawn .gauge-value { stroke-dashoffset: var(--off); }
.gauge-center {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
}
.gauge-num {
  font-family: var(--font-family-base);
  font-weight: 700;
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* On inverse (dark) surfaces */
.on-inverse .gauge .gauge-track { stroke: var(--data-track-on-inverse); }
.on-inverse .gauge-num { color: var(--text-on-brand); }

/* ---------- Sparkline / area ---------- */
.spark { position: relative; width: 100%; }
.spark svg { display: block; width: 100%; height: auto; }
.spark-area { fill: url(#sparkFill); opacity: 0.9; }
.spark-line {
  fill: none;
  stroke: var(--data-primary);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* draw-on animation */
  stroke-dasharray: var(--len);
  stroke-dashoffset: var(--len);
  transition: stroke-dashoffset 1.3s ease-out;
}
.is-drawn .spark-line { stroke-dashoffset: 0; }
.spark-dot { fill: var(--data-primary); stroke: var(--bg-surface); stroke-width: 2; }
.on-inverse .spark-dot { stroke: var(--bg-inverse); }

/* ---------- Split bar (stacked, e.g. auto vs human) ---------- */
.split-bar {
  display: flex;
  height: 16px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--data-track);
  gap: 2px; /* 2px surface gap between segments, per mark specs */
}
.split-seg { height: 100%; width: 0; transition: width 1s cubic-bezier(0.22, 1, 0.36, 1); }
.split-seg--primary { background: var(--data-primary); }
.split-seg--secondary { background: var(--data-secondary); }
.is-drawn .split-seg { width: var(--seg); }
.split-legend { display: flex; gap: var(--space-4); flex-wrap: wrap; margin-top: var(--space-3); }
.split-key { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--text-secondary); }
.split-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.split-swatch--primary { background: var(--data-primary); }
.split-swatch--secondary { background: var(--data-secondary); }

/* ---------- Stat tile with radial ring ---------- */
.stat-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.stat-tile-num {
  font-family: var(--font-family-base);
  font-weight: 700;
  font-size: clamp(var(--text-3xl), 5vw, var(--text-4xl));
  line-height: 1;
  color: var(--data-primary);
  font-variant-numeric: tabular-nums;
}
.stat-tile-track {
  height: 6px;
  border-radius: 3px;
  background: var(--data-track);
  overflow: hidden;
}
.stat-tile-fill {
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: var(--data-primary);
  transition: width 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.is-drawn .stat-tile-fill { width: calc(var(--pct) * 1%); }
.stat-tile-label { font-size: var(--text-sm); color: var(--text-secondary); line-height: var(--leading-normal); }
.stat-tile-source { font-size: var(--text-xs); color: var(--data-axis-text); }

/* ---------- Node graph — platforms + business data wired into the Voca brain ----------
   Says the core thing visually: Voca is not a bolt-on tool, it's the layer the
   business's channels and data both plug into. Coral = channels customers speak
   on, navy = the business's own data. Rendered as SVG by app.js. */
.nodegraph {
  background: var(--bg-inverse);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  color: var(--text-on-brand);
}
.nodegraph svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  /* Anchors must stay geometric: under dir=rtl, text-anchor start/end swap sides
     and labels would render back over their nodes. Hebrew runs still shape RTL
     correctly via bidi — only the anchor semantics are pinned here. */
  direction: ltr;
}

.ng-link {
  fill: none;
  stroke: var(--data-track-on-inverse);
  stroke-width: 1.5;
}
.ng-link--platform { stroke: color-mix(in srgb, var(--coral-500) 45%, transparent); }
.ng-link--data { stroke: color-mix(in srgb, var(--navy-300) 55%, transparent); }

/* pulse travelling along each link toward the hub (motion via SVG animateMotion,
   which app.js omits entirely under prefers-reduced-motion) */
.ng-pulse { opacity: 0.9; }
.ng-pulse--platform { fill: var(--coral-300); }
.ng-pulse--data { fill: var(--navy-100); }

.ng-node { fill: color-mix(in srgb, var(--neutral-0) 8%, transparent); stroke-width: 1.5; }
.ng-node--platform { stroke: color-mix(in srgb, var(--coral-500) 70%, transparent); }
.ng-node--data { stroke: color-mix(in srgb, var(--navy-300) 80%, transparent); }
.ng-label {
  fill: color-mix(in srgb, var(--neutral-0) 88%, transparent);
  font-family: var(--font-family-base);
  font-size: 11px;
}
.ng-icon { font-family: 'Material Symbols Outlined'; font-size: 16px; }
.ng-icon--platform { fill: var(--coral-300); }
.ng-icon--data { fill: var(--navy-100); }

.ng-hub { fill: var(--coral-500); }
.ng-hub-ring {
  fill: none;
  stroke: color-mix(in srgb, var(--coral-500) 40%, transparent);
  stroke-width: 1.5;
  transform-box: fill-box;
  transform-origin: center;
}
.is-drawn .ng-hub-ring { animation: ngHalo 3s ease-out infinite; }
@keyframes ngHalo {
  0%   { transform: scale(1); opacity: 0.9; }
  100% { transform: scale(1.5); opacity: 0; }
}
/* Full logo lockup, top-centre of the graph. */
.ng-lockup { fill: color-mix(in srgb, var(--neutral-0) 92%, transparent); }

/* The brand mark sits in the hub, knocked out white on the coral disc. */
.ng-hub-mark { fill: var(--neutral-0); }
.ng-hub-label {
  fill: color-mix(in srgb, var(--neutral-0) 88%, transparent);
  font-family: var(--font-family-base);
  font-weight: 700;
  font-size: 13px;
}
.ng-col-title {
  fill: color-mix(in srgb, var(--neutral-0) 55%, transparent);
  font-family: var(--font-family-base);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
  .is-drawn .ng-hub-ring { animation: none; }
}

/* ---------- Cost ratio bars (dramatic magnitude) ---------- */
.cost-chart { display: flex; flex-direction: column; gap: var(--space-6); }
.cost-bar { display: grid; gap: var(--space-3); }
.cost-bar-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.cost-bar-name { font-size: var(--text-sm); color: var(--text-secondary); }
.cost-bar-amount {
  font-family: var(--font-family-base);
  font-weight: 700;
  font-size: var(--text-xl);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cost-bar-unit { font-weight: 400; font-size: var(--text-xs); color: var(--text-secondary); }
.cost-bar--human .cost-bar-amount { color: var(--text-secondary); }
.cost-bar--voca  .cost-bar-amount { color: var(--data-primary); }
.cost-track { height: 16px; border-radius: 8px; background: var(--data-track); overflow: hidden; }
.cost-fill { height: 100%; width: 0; border-radius: 8px; min-width: 6px; transition: width 1.2s cubic-bezier(0.22, 1, 0.36, 1); }
.cost-bar--human .cost-fill { background: var(--data-secondary); }
.cost-bar--voca  .cost-fill { background: var(--data-primary); }
.is-drawn .cost-fill { width: calc(var(--pct) * 1%); }

@media (prefers-reduced-motion: reduce) {
  .bar-fill, .gap-track-fill, .gauge .gauge-value, .spark-line,
  .split-seg, .stat-tile-fill, .cost-fill {
    transition: none !important;
  }
}
