// shared.jsx — Raseed onboarding · shared primitives
// Exports to window: RaseedMark, Icon, PhoneShell, PrimaryButton, GhostButton,
// ProgressBar, StepDots, StepRail, useTyper, STEPS, fontStack

const fontDisplay = "'Outfit', system-ui, sans-serif";
const fontBody = "'DM Sans', system-ui, sans-serif";

// ─────────────────────────────────────────────────────────────
// Brand mark (receipt logo) — parameterised by color
// ─────────────────────────────────────────────────────────────
function RaseedMark({ size = 20, color = '#fff', faded = true }) {
  const w = size, h = size * 1.26;
  return (
    <svg viewBox="0 0 100 126" width={w} height={h} fill="none" style={{ display: 'block' }}>
      <path d="M 12,0 L 88,0 Q 100,0 100,12 L 100,118 L 95,126 L 90,118 L 85,126 L 80,118 L 75,126 L 70,118 L 65,126 L 60,118 L 55,126 L 50,118 L 45,126 L 40,118 L 35,126 L 30,118 L 25,126 L 20,118 L 15,126 L 10,118 L 5,126 L 0,118 L 0,12 Q 0,0 12,0 Z" fill={faded ? 'rgba(255,255,255,0.22)' : color} fillOpacity={faded ? 1 : 0.22} />
      <path d="M 22,65 L 50,36 L 78,65" stroke={color} strokeWidth="7" strokeLinecap="round" strokeLinejoin="round" />
      <line x1="50" y1="38" x2="50" y2="84" stroke={color} strokeWidth="6" strokeLinecap="round" />
      <line x1="22" y1="95" x2="78" y2="95" stroke={color} strokeWidth="4" strokeOpacity="0.5" strokeLinecap="round" />
      <line x1="28" y1="106" x2="72" y2="106" stroke={color} strokeWidth="4" strokeOpacity="0.28" strokeLinecap="round" />
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────
// Heroicons (outline) — single source, pick by name
// ─────────────────────────────────────────────────────────────
const ICON_PATHS = {
  arrowRight: 'M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3',
  arrowLeft: 'M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18',
  check: 'm4.5 12.75 6 6 9-13.5',
  checkCircle: 'M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z',
  wifi: 'M8.288 15.038a5.25 5.25 0 0 1 7.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565 14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 0 1 1.06 0z',
  power: 'M5.636 5.636a9 9 0 1 0 12.728 0M12 3v9',
  plug: 'M14.121 7.629A3 3 0 0 0 9.017 9.43c-.023.212-.002.425.028.636l.506 3.541a4.5 4.5 0 0 1-.43 2.65L9 17.25l-.547 1.534M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z',
  mapPin: 'M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0z M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1 1 15 0z',
  building: 'M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21',
  tag: 'M9.568 3H5.25A2.25 2.25 0 0 0 3 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.1 18.1 0 0 0 5.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 0 0 9.568 3z M6 6h.008v.008H6z',
  receipt: 'M3 8.689c0-.864.933-1.406 1.683-.977a2.32 2.32 0 0 0 2.282 0 2.32 2.32 0 0 1 2.282 0 2.32 2.32 0 0 0 2.282 0 2.32 2.32 0 0 1 2.282 0 2.32 2.32 0 0 0 2.282 0 2.32 2.32 0 0 1 2.282 0 2.32 2.32 0 0 0 2.282 0c.75-.43 1.683.113 1.683.977V19.5A2.25 2.25 0 0 1 18.75 21.75H5.25A2.25 2.25 0 0 1 3 19.5V8.689zM7.5 11.25h9M7.5 14.25h6',
  device: 'M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3',
  printer: 'M6.72 13.829c-.24.03-.48.062-.72.096m.72-.096a42.4 42.4 0 0 1 10.56 0m-10.56 0L6.34 18m10.94-4.171c.24.03.48.062.72.096m-.72-.096L17.66 18m0 0 .229 2.523a1.125 1.125 0 0 1-1.12 1.227H7.231c-.662 0-1.18-.568-1.12-1.227L6.34 18m11.318 0h1.091A2.25 2.25 0 0 0 21 15.75V9.456c0-1.081-.768-2.015-1.837-2.175a48 48 0 0 0-1.913-.247M6.34 18H5.25A2.25 2.25 0 0 1 3 15.75V9.456c0-1.081.768-2.015 1.837-2.175a48 48 0 0 1 1.913-.247m10.5 0a48.7 48.7 0 0 0-10.5 0m10.5 0V3.375c0-.621-.504-1.125-1.125-1.125h-8.25c-.621 0-1.125.504-1.125 1.125v3.659M18 10.5h.008v.008H18V10.5z',
  bolt: 'm3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z',
  sparkles: 'M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09zM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456zM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423z',
  phone: 'M8.25 18.75a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 0 1-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m3 0h1.125c.621 0 1.129-.504 1.09-1.124a17.9 17.9 0 0 0-3.213-9.193 2.06 2.06 0 0 0-1.66-.838H9.75',
  lock: 'M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25z',
  chevronRight: 'm8.25 4.5 7.5 7.5-7.5 7.5',
  chevronDown: 'm19.5 8.25-7.5 7.5-7.5-7.5',
  clock: 'M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0z',
  shield: 'M9 12.75 11.25 15 15 9.75m-3-7.036A11.96 11.96 0 0 1 3.598 6 12 12 0 0 0 3 9.75c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.623 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.249-8.25-3.286z',
  box: 'm21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9',
};

function Icon({ name, size = 22, color = 'currentColor', stroke = 1.75, style }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={style}>
      <path d={ICON_PATHS[name]} />
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────
// Phone shell — themeable bezel, status bar, home indicator
// ─────────────────────────────────────────────────────────────
const PHONE_W = 374, PHONE_H = 770;
function PhoneShell({ children, statusDark = false, screenBg = '#fafaf7', barTint }) {
  const glyph = statusDark ? '#fff' : '#0f0f0b';
  return (
    <div style={{
      width: PHONE_W, height: PHONE_H, borderRadius: 46, position: 'relative',
      background: '#0f0f0b', padding: 5, boxSizing: 'border-box',
      boxShadow: '0 50px 90px -20px rgba(15,15,11,0.45), 0 0 0 1px rgba(15,15,11,0.15)',
    }}>
      <div style={{
        width: '100%', height: '100%', borderRadius: 41, overflow: 'hidden',
        position: 'relative', background: screenBg,
        fontFamily: fontBody, WebkitFontSmoothing: 'antialiased',
      }}>
        {/* status bar */}
        <div style={{
          position: 'absolute', top: 0, left: 0, right: 0, height: 50, zIndex: 40,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          padding: '0 26px', background: barTint || 'transparent', pointerEvents: 'none',
        }}>
          <span style={{ fontFamily: fontBody, fontWeight: 700, fontSize: 15, color: glyph, letterSpacing: '-0.01em', marginTop: 6 }}>9:41</span>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 6 }}>
            <svg width="18" height="11" viewBox="0 0 18 11"><rect x="0" y="6.5" width="3" height="4.5" rx="0.6" fill={glyph}/><rect x="4.5" y="4" width="3" height="7" rx="0.6" fill={glyph}/><rect x="9" y="2" width="3" height="9" rx="0.6" fill={glyph}/><rect x="13.5" y="0" width="3" height="11" rx="0.6" fill={glyph}/></svg>
            <svg width="25" height="12" viewBox="0 0 25 12"><rect x="0.5" y="0.5" width="21" height="11" rx="3" stroke={glyph} strokeOpacity="0.4" fill="none"/><rect x="2" y="2" width="18" height="8" rx="1.8" fill={glyph}/><rect x="23" y="4" width="1.5" height="4" rx="0.7" fill={glyph} fillOpacity="0.5"/></svg>
          </div>
        </div>
        {/* dynamic island */}
        <div style={{ position: 'absolute', top: 13, left: '50%', transform: 'translateX(-50%)', width: 110, height: 32, borderRadius: 20, background: '#0f0f0b', zIndex: 45 }} />
        {/* content */}
        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column' }}>
          {children}
        </div>
        {/* home indicator */}
        <div style={{ position: 'absolute', bottom: 8, left: '50%', transform: 'translateX(-50%)', width: 130, height: 5, borderRadius: 100, background: statusDark ? 'rgba(255,255,255,0.55)' : 'rgba(15,15,11,0.32)', zIndex: 50, pointerEvents: 'none' }} />
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Buttons
// ─────────────────────────────────────────────────────────────
function PrimaryButton({ children, onClick, disabled, accent = '#15803d', accentHover = '#166534', icon = 'arrowRight', full = true, style }) {
  const [h, setH] = React.useState(false);
  return (
    <button onClick={disabled ? undefined : onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        width: full ? '100%' : undefined, border: 'none', cursor: disabled ? 'default' : 'pointer',
        background: disabled ? '#d1d1c8' : (h ? accentHover : accent), color: disabled ? '#fafaf7' : '#fff',
        fontFamily: fontBody, fontWeight: 600, fontSize: 16, padding: '15px 22px', borderRadius: 14,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9,
        boxShadow: disabled ? 'none' : (h ? '0 8px 24px rgba(21,128,61,0.28)' : '0 4px 14px rgba(21,128,61,0.18)'),
        transform: h && !disabled ? 'translateY(-1px)' : 'none', transition: 'all 200ms cubic-bezier(0.4,0,0.2,1)', ...style,
      }}>
      {children}
      {icon && <Icon name={icon} size={18} stroke={2.2} />}
    </button>
  );
}

function GhostButton({ children, onClick, dark = false, style }) {
  const [h, setH] = React.useState(false);
  const base = dark ? 'rgba(255,255,255,0.0)' : 'transparent';
  const hoverBg = dark ? 'rgba(255,255,255,0.06)' : '#f4f4ef';
  const border = dark ? 'rgba(255,255,255,0.18)' : '#d1d1c8';
  const col = dark ? 'rgba(255,255,255,0.82)' : '#3d3d38';
  return (
    <button onClick={onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        width: '100%', border: `1.5px solid ${border}`, cursor: 'pointer', background: h ? hoverBg : base, color: col,
        fontFamily: fontBody, fontWeight: 600, fontSize: 15, padding: '13px 20px', borderRadius: 14,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, transition: 'all 180ms', ...style,
      }}>
      {children}
    </button>
  );
}

// ─────────────────────────────────────────────────────────────
// Progress indicators
// ─────────────────────────────────────────────────────────────
function ProgressBar({ step, total, accent = '#15803d', track = '#e8e8e1' }) {
  return (
    <div style={{ height: 5, background: track, borderRadius: 999, overflow: 'hidden', width: '100%' }}>
      <div style={{ height: '100%', width: `${(step / total) * 100}%`, background: accent, borderRadius: 999, transition: 'width 450ms cubic-bezier(0.4,0,0.2,1)' }} />
    </div>
  );
}

function StepDots({ step, total, accent = '#4ade80', track = 'rgba(255,255,255,0.18)' }) {
  return (
    <div style={{ display: 'flex', gap: 7, alignItems: 'center' }}>
      {Array.from({ length: total }).map((_, i) => {
        const active = i + 1 === step, done = i + 1 < step;
        return <div key={i} style={{
          height: 5, borderRadius: 999, transition: 'all 350ms cubic-bezier(0.4,0,0.2,1)',
          width: active ? 26 : 5, background: (active || done) ? accent : track,
        }} />;
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Typing simulation hook — tap to "type" a value
// ─────────────────────────────────────────────────────────────
function useTyper() {
  const [vals, setVals] = React.useState({});
  const typing = React.useRef({});
  const type = React.useCallback((key, full, speed = 38) => {
    if (typing.current[key]) return;
    typing.current[key] = true;
    let i = 0;
    const tick = () => {
      i++;
      setVals(v => ({ ...v, [key]: full.slice(0, i) }));
      if (i < full.length) setTimeout(tick, speed);
      else typing.current[key] = false;
    };
    tick();
  }, []);
  return [vals, type, setVals];
}

// ─────────────────────────────────────────────────────────────
// Shared step content (single source of truth across directions)
// ─────────────────────────────────────────────────────────────
const STEPS = [
  { n: 1, key: 'bridge', title: 'Plug in the Print Bridge', short: 'Print Bridge', blurb: 'Sits between your POS and printer. The cashier sees nothing different.', icon: 'plug' },
  { n: 2, key: 'wifi', title: 'Connect to store WiFi', short: 'Store WiFi', blurb: 'We detect the Bridge on your network and connect it. One time only.', icon: 'wifi' },
  { n: 3, key: 'details', title: 'Enter merchant details', short: 'Merchant details', blurb: 'Store name, address and sector. Takes about 30 seconds.', icon: 'building' },
  { n: 4, key: 'tile', title: 'Place the Raseed Tile', short: 'The Tile', blurb: 'Set it on the counter by the terminal and plug in power. It self-connects.', icon: 'receipt' },
  { n: 5, key: 'test', title: 'Run a test receipt', short: 'Test receipt', blurb: 'Ring up one item, hit print, then tap the Tile with your phone.', icon: 'bolt' },
];

Object.assign(window, {
  RaseedMark, Icon, ICON_PATHS, PhoneShell, PHONE_W, PHONE_H,
  PrimaryButton, GhostButton, ProgressBar, StepDots, useTyper, STEPS,
  fontDisplay, fontBody,
});
