// Otto — Design tokens + shared primitives
// Warm, calm, large-type aesthetic for 50+ users.

const OttoTokens = {
  // Colors (light)
  bg: '#F4F0E8',          // warm cream background
  surface: '#FFFFFF',
  surfaceAlt: '#FAF7F1',
  ink: '#1C1A17',         // deep warm charcoal
  inkMuted: '#5C564D',
  inkSubtle: '#8A847A',
  hairline: 'rgba(28,26,23,0.08)',

  // Accents
  sage: '#4F7A6F',        // primary accent
  sageDeep: '#365C53',
  sageSoft: '#E3EDE9',

  amber: '#B8884B',       // attention
  amberSoft: '#F2E6D0',
  clay: '#A65A3D',        // alert (used sparingly)
  claySoft: '#F1DCD2',

  // Typography
  serif: '"Newsreader", "Iowan Old Style", Georgia, serif',
  sans: '-apple-system, "SF Pro Text", "SF Pro", system-ui, sans-serif',
  mono: '"SF Mono", "JetBrains Mono", ui-monospace, monospace',

  // Radii
  rSm: 14,
  rMd: 22,
  rLg: 28,
  rXL: 36,
};

// ─────────────────────────────────────────────────────────────
// Atoms
// ─────────────────────────────────────────────────────────────

function Card({ children, style = {}, padded = true, onClick }) {
  return (
    <div
      onClick={onClick}
      style={{
        background: OttoTokens.surface,
        borderRadius: OttoTokens.rLg,
        padding: padded ? 22 : 0,
        boxShadow: '0 1px 0 rgba(28,26,23,0.04), 0 8px 24px -12px rgba(28,26,23,0.08)',
        cursor: onClick ? 'pointer' : 'default',
        ...style,
      }}
    >
      {children}
    </div>
  );
}

function SectionLabel({ children, style = {} }) {
  return (
    <div style={{
      fontFamily: OttoTokens.sans,
      fontSize: 12, fontWeight: 600,
      letterSpacing: 1.4, textTransform: 'uppercase',
      color: OttoTokens.inkSubtle,
      marginBottom: 10,
      ...style,
    }}>{children}</div>
  );
}

function Pill({ children, tone = 'sage', style = {} }) {
  const tones = {
    sage: { bg: OttoTokens.sageSoft, fg: OttoTokens.sageDeep },
    amber: { bg: OttoTokens.amberSoft, fg: '#7A5524' },
    clay: { bg: OttoTokens.claySoft, fg: '#7A3A22' },
    neutral: { bg: 'rgba(28,26,23,0.06)', fg: OttoTokens.inkMuted },
  };
  const t = tones[tone] || tones.sage;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '5px 11px', borderRadius: 999,
      background: t.bg, color: t.fg,
      fontFamily: OttoTokens.sans, fontSize: 13, fontWeight: 600,
      letterSpacing: -0.1,
      ...style,
    }}>{children}</span>
  );
}

function Dot({ tone = 'sage', size = 8 }) {
  const c = {
    sage: OttoTokens.sage, amber: OttoTokens.amber,
    clay: OttoTokens.clay, neutral: OttoTokens.inkSubtle,
  }[tone];
  return <span style={{
    width: size, height: size, borderRadius: '50%',
    background: c, display: 'inline-block', flexShrink: 0,
  }} />;
}

// big primary CTA
function OttoButton({ children, onClick, kind = 'primary', style = {} }) {
  const styles = {
    primary: { bg: OttoTokens.ink, fg: '#FAF7F1' },
    secondary: { bg: 'rgba(28,26,23,0.06)', fg: OttoTokens.ink },
    sage: { bg: OttoTokens.sage, fg: '#fff' },
  };
  const s = styles[kind];
  return (
    <button onClick={onClick} style={{
      width: '100%', minHeight: 56,
      borderRadius: 999, border: 'none',
      background: s.bg, color: s.fg,
      fontFamily: OttoTokens.sans, fontSize: 18, fontWeight: 600,
      letterSpacing: -0.2, cursor: 'pointer',
      transition: 'transform 120ms ease, opacity 120ms ease',
      ...style,
    }}
    onMouseDown={e => e.currentTarget.style.transform = 'scale(0.98)'}
    onMouseUp={e => e.currentTarget.style.transform = 'scale(1)'}
    onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}
    >{children}</button>
  );
}

// Otto's mark — a soft mono "O" with a small dot, used as logo
function OttoMark({ size = 32, color }) {
  const c = color || OttoTokens.ink;
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" style={{ display: 'block' }}>
      <circle cx="16" cy="16" r="13" stroke={c} strokeWidth="2" fill="none"/>
      <circle cx="22.5" cy="9.5" r="2.4" fill={c}/>
    </svg>
  );
}

// Animated count-up for big numbers
function CountUp({ to, duration = 900, style = {}, suffix = '' }) {
  const [n, setN] = React.useState(0);
  React.useEffect(() => {
    let raf, start;
    const step = (t) => {
      if (!start) start = t;
      const p = Math.min((t - start) / duration, 1);
      const eased = 1 - Math.pow(1 - p, 3);
      setN(Math.round(to * eased));
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [to, duration]);
  return <span style={style}>{n}{suffix}</span>;
}

// Sparkline (tiny svg trend)
function Spark({ values, w = 80, h = 28, color, fill = false }) {
  const c = color || OttoTokens.sage;
  const min = Math.min(...values), max = Math.max(...values);
  const range = max - min || 1;
  const pts = values.map((v, i) => {
    const x = (i / (values.length - 1)) * w;
    const y = h - ((v - min) / range) * h;
    return [x, y];
  });
  const d = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`).join(' ');
  const fillD = fill ? `${d} L${w},${h} L0,${h} Z` : '';
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} style={{ maxWidth: '100%', display: 'block' }}>
      {fill && <path d={fillD} fill={c} fillOpacity="0.12"/>}
      <path d={d} stroke={c} strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
      <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r="2.5" fill={c}/>
    </svg>
  );
}

// Subtle pulsing live dot
function LiveDot() {
  return (
    <span style={{ position: 'relative', width: 8, height: 8, display: 'inline-block' }}>
      <span style={{
        position: 'absolute', inset: 0, borderRadius: '50%',
        background: OttoTokens.sage, animation: 'ottoPulse 2s ease-in-out infinite',
      }}/>
      <span style={{
        position: 'absolute', inset: 0, borderRadius: '50%',
        background: OttoTokens.sage,
      }}/>
    </span>
  );
}

// Ring chart (used for health score)
function ScoreRing({ value, max = 100, size = 180, stroke = 14, label, color }) {
  const c = color || OttoTokens.sage;
  const r = (size - stroke) / 2;
  const circ = 2 * Math.PI * r;
  const [progress, setProgress] = React.useState(0);
  React.useEffect(() => {
    const t = setTimeout(() => setProgress(value / max), 120);
    return () => clearTimeout(t);
  }, [value, max]);
  const offset = circ * (1 - progress);
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} stroke="rgba(28,26,23,0.06)" strokeWidth={stroke} fill="none"/>
        <circle cx={size/2} cy={size/2} r={r} stroke={c} strokeWidth={stroke} fill="none"
          strokeDasharray={circ} strokeDashoffset={offset} strokeLinecap="round"
          style={{ transition: 'stroke-dashoffset 1200ms cubic-bezier(.2,.8,.2,1)' }}/>
      </svg>
      <div style={{
        position: 'absolute', inset: 0, display: 'flex',
        flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      }}>
        <div style={{
          fontFamily: OttoTokens.serif, fontSize: 64, fontWeight: 400,
          color: OttoTokens.ink, lineHeight: 1, letterSpacing: -1,
        }}>
          <CountUp to={value} duration={1200}/>
        </div>
        {label && <div style={{
          fontFamily: OttoTokens.sans, fontSize: 13, fontWeight: 600,
          letterSpacing: 1.2, textTransform: 'uppercase',
          color: OttoTokens.inkSubtle, marginTop: 6,
        }}>{label}</div>}
      </div>
    </div>
  );
}

Object.assign(window, {
  OttoTokens, Card, SectionLabel, Pill, Dot, OttoButton, OttoMark,
  CountUp, Spark, LiveDot, ScoreRing,
});
