/* ═══════════════════════════════════════════════════════════════════
   PerfCharts.jsx — net-new viz primitives for Performance / CWV. v1.0.0
   Ported verbatim from the Claude Design v2 package
   (_CLAUDE-DESIGN/_2026-06-12-v2-SaaS-Redesign/perf-charts.jsx) — port,
   not redesign. Verdict reads by ICON + LABEL + color (never color
   alone, per WCAG 2.1 AA). All colors via --viz-* and --v-* tokens
   (landed in Increment 1). No inline hex.
   Load order: FIRST of the four Perf modules (charts → data → page →
   surface), after the Seo block.
   Registers: window.WPSB.PerfCharts = { VERDICT, VerdictChip,
   MetricCell, ThresholdMeter, UptimeStrip, EndpointBar }.
   Deliberately NOT exported as bare globals (VERDICT is too generic —
   collision risk with other modules).
   ═══════════════════════════════════════════════════════════════════ */
(function () {

/* verdict → token + icon + label. shape/text carry meaning, color reinforces */
const VERDICT = {
  good:  { c: 'var(--v-good)', cf: 'var(--v-good-fill)', icon: 'check-circle', label: 'Good' },
  ni:    { c: 'var(--v-warn)', cf: 'var(--v-warn-fill)', icon: 'alert-triangle', label: 'Needs work' },
  poor:  { c: 'var(--v-poor)', cf: 'var(--v-poor-fill)', icon: 'x-circle', label: 'Poor' },
};

function VerdictChip({ verdict, size = 'md' }) {
  const v = VERDICT[verdict];
  const sm = size === 'sm';
  return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: sm ? 4 : 6,
    padding: sm ? '2px 7px' : '3px 9px', borderRadius: 999, whiteSpace: 'nowrap',
    background: 'color-mix(in oklch, ' + v.cf + ' 22%, transparent)', color: v.c,
    border: '1px solid color-mix(in oklch, ' + v.cf + ' 55%, transparent)',
    fontFamily: 'var(--font-mono)', fontWeight: 'var(--fw-tag)', fontSize: sm ? '.58rem' : '.64rem', letterSpacing: '.04em' } },
    React.createElement(WIcon, { name: v.icon, size: sm ? 11 : 13 }), v.label);
}

/* small verdict dot + value (table cells) — dot shape + text value, color reinforces */
function MetricCell({ value, unit, verdict }) {
  const v = VERDICT[verdict];
  return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 7 },
    title: v.label },
    React.createElement('span', { style: { width: 8, height: 8, borderRadius: '50%', background: v.cf, flex: 'none' } }),
    React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.84rem', color: 'var(--text)', fontVariantNumeric: 'tabular-nums' } }, value,
      unit && React.createElement('span', { style: { color: 'var(--muted)', fontSize: '.72rem', marginLeft: 1 } }, unit)),
    React.createElement('span', { className: 'sr-only' }, v.label));
}

/* threshold meter: track split into good/ni/poor zones + a marker at the value.
   zones in fractions of the track [0..goodFrac..niFrac..1]; thresholds labeled. */
function ThresholdMeter({ value, display, goodMax, niMax, scaleMax, verdict, labelGood, labelNi }) {
  const pct = (x) => Math.min(100, Math.max(0, (x / scaleMax) * 100));
  const v = VERDICT[verdict];
  return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 5 },
    role: 'img', 'aria-label': display + ' — ' + v.label },
    React.createElement('div', { style: { position: 'relative', height: 8, borderRadius: 999, overflow: 'hidden', display: 'flex' } },
      React.createElement('span', { style: { width: pct(goodMax) + '%', background: 'var(--v-good-fill)' } }),
      React.createElement('span', { style: { width: (pct(niMax) - pct(goodMax)) + '%', background: 'var(--v-warn-band)' } }),
      React.createElement('span', { style: { flex: 1, background: 'var(--v-poor-fill)' } }),
      // marker
      React.createElement('span', { style: { position: 'absolute', top: -2, left: 'calc(' + pct(value) + '% - 1.5px)', width: 3, height: 12, borderRadius: 2, background: 'var(--text)', boxShadow: '0 0 0 1.5px var(--surface)' } })),
    React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', fontFamily: 'var(--font-mono)', fontSize: '.58rem', color: 'var(--dim)' } },
      React.createElement('span', null, labelGood), React.createElement('span', null, labelNi)));
}

/* 30-day uptime strip — per-day cells (up/degraded/down). color + the legend
   + per-cell title carry state; AA: legend labels states textually. */
function UptimeStrip({ days, label, pct }) {
  const tone = { up: 'var(--v-good-fill)', degraded: 'var(--v-warn-fill)', down: 'var(--v-poor-fill)' };
  const txt = { up: 'operational', degraded: 'degraded', down: 'outage' };
  return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 8 } },
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 } },
      React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.8rem', color: 'var(--text)' } }, label),
      React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.78rem', fontWeight: 'var(--fw-bold)',
        color: pct >= 99.9 ? 'var(--v-good)' : pct >= 99 ? 'var(--v-warn)' : 'var(--v-poor)' } }, pct + '%')),
    React.createElement('div', { style: { display: 'flex', gap: 2, alignItems: 'stretch', flexWrap: 'wrap' }, role: 'img', 'aria-label': label + ' uptime ' + pct + ' percent over 30 days' },
      days.map((d, i) => React.createElement('span', { key: i, title: 'Day ' + (i + 1) + ': ' + txt[d],
        style: { flex: '1 1 auto', height: 13, minWidth: 3, borderRadius: 1, background: tone[d] } }))));
}

/* slowest-endpoint bar row: path + ms bar + reason chip. Flex-wraps so the
   reason chip drops to its own line on narrow widths instead of overflowing. */
function EndpointBar({ path, ms, max, reason, verdict }) {
  const v = VERDICT[verdict];
  return React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', flexWrap: 'wrap' } },
    React.createElement('span', { style: { flex: '1 1 120px', minWidth: 0, fontFamily: 'var(--font-mono)', fontSize: '.76rem', color: 'var(--beam)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, path),
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flex: '1 1 120px', minWidth: 100 } },
      React.createElement('div', { style: { flex: 1, height: 6, borderRadius: 999, background: 'var(--viz-track)', overflow: 'hidden' } },
        React.createElement('div', { style: { width: Math.min(100, (ms / max) * 100) + '%', height: '100%', background: v.cf, borderRadius: 999 } })),
      React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.74rem', color: 'var(--text-2)', minWidth: 44, textAlign: 'right' } }, (ms / 1000).toFixed(1) + 's')),
    React.createElement('span', { className: 'wiz-tag wiz-tag-locked', style: { flex: '0 0 auto', maxWidth: '100%' } }, reason));
}

window.WPSB = window.WPSB || {};
window.WPSB.PerfCharts = { VERDICT, VerdictChip, MetricCell, ThresholdMeter, UptimeStrip, EndpointBar };
console.log('[WPSB] PerfCharts v1.0.0 loaded');
})();
