/* AIWine v2 — shared UI primitives. Exports to window at end of file. */
const { useState, useEffect, useRef } = React;

const S = {
  serif: { fontFamily: 'var(--font-serif)', fontWeight: 400, letterSpacing: '-0.01em' },
  sans: { fontFamily: 'var(--font-sans)' },
  mono: { fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase' }
};

function Eyebrow({ children, color = 'var(--muted)', style }) {
  return <div style={{ ...S.mono, color, ...style }}>{children}</div>;
}

/* ---------- device ---------- */
function Device({ children }) {
  const [scale, setScale] = useState(1);
  const full = typeof window !== 'undefined' && window.AW_FULL;
  useEffect(() => {
    if (full) return;
    const fit = () => {
      const h = window.innerHeight - 48, w = window.innerWidth - 32;
      setScale(Math.min(1, h / 874, w / 402));
    };
    fit(); window.addEventListener('resize', fit);
    return () => window.removeEventListener('resize', fit);
  }, [full]);
  if (full) return <div style={{ position: 'fixed', inset: 0, background: 'var(--bg-alt)', display: 'flex', justifyContent: 'center' }}><div style={{ position: 'relative', width: 'min(100%, 560px)', height: '100%', overflow: 'hidden', background: 'var(--bg)', boxShadow: '0 0 60px rgba(27,20,16,.10)' }}>{children}</div></div>;
  return (
    <div style={{ width: 402 * scale, height: 874 * scale }}>
      <div style={{ width: 402, height: 874, transform: `scale(${scale})`, transformOrigin: 'top left', position: 'relative', borderRadius: 54, background: '#0B0907', padding: 5, boxShadow: '0 40px 90px rgba(30,18,10,.42), 0 2px 0 rgba(255,255,255,.14) inset' }}>
        <div style={{ position: 'relative', width: '100%', height: '100%', borderRadius: 49, overflow: 'hidden', background: 'var(--bg)' }}>{children}</div>
      </div>
    </div>
  );
}

function StatusBar({ dark }) {
  if (typeof window !== 'undefined' && window.AW_FULL) return null;
  const c = dark ? '#F4EFE5' : 'var(--ink)';
  return (
    <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 52, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 30px', zIndex: 60, pointerEvents: 'none' }}>
      <div style={{ ...S.sans, fontSize: 14, fontWeight: 600, color: c, letterSpacing: '.01em' }}>7:42</div>
      <div style={{ position: 'absolute', left: '50%', transform: 'translateX(-50%)', top: 8, width: 108, height: 30, borderRadius: 20, background: '#0B0907' }} />
      <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}>
        {[7, 10, 13, 16].map((h, i) => <div key={i} style={{ width: 3, height: h, borderRadius: 1, background: c, opacity: i === 3 ? .4 : 1 }} />)}
        <div style={{ marginLeft: 4, width: 22, height: 11, borderRadius: 3, border: '1px solid ' + c, opacity: .9, padding: 1.5 }}><div style={{ width: '72%', height: '100%', borderRadius: 1, background: c }} /></div>
      </div>
    </div>
  );
}

/* ---------- scrolling screen ---------- */
function Screen({ children, pad = 22, top = 58, bottom = 108, bg }) {
  const ref = useRef(null);
  return (
    <div ref={ref} className="aw-scroll" style={{ position: 'absolute', inset: 0, overflowY: 'auto', overflowX: 'hidden', background: bg || 'var(--bg)', paddingTop: top, paddingBottom: bottom, paddingLeft: pad, paddingRight: pad, WebkitOverflowScrolling: 'touch' }}>{children}</div>
  );
}

/* ---------- bottle ---------- */
function Bottle({ wine, h = 150, glow = true }) {
  return (
    <div style={{ position: 'relative', height: h, display: 'flex', alignItems: 'flex-end', justifyContent: 'center' }}>
      {glow && <div style={{ position: 'absolute', bottom: 2, left: '50%', transform: 'translateX(-50%)', width: h * .42, height: 10, borderRadius: '50%', background: 'rgba(27,20,16,.20)', filter: 'blur(6px)' }} />}
      <img src={wine.bottle} alt="" style={{ height: h, width: 'auto', objectFit: 'contain', filter: 'drop-shadow(0 6px 10px rgba(27,20,16,.18))' }} />
      <div style={{ position: 'absolute', bottom: h * .30, left: '50%', transform: 'translateX(-50%)', width: h * .27, height: h * .175, background: '#F7F2E7', border: '0.5px solid rgba(27,20,16,.16)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 2, padding: 3 }}>
        <div style={{ width: 5, height: 5, borderRadius: '50%', background: wine.tint }} />
        <div style={{ ...S.serif, fontSize: Math.max(5, h * .043), lineHeight: 1, textAlign: 'center', color: 'var(--ink)' }}>{wine.winery.split(' ')[0]}</div>
      </div>
    </div>
  );
}

/* ---------- match ---------- */
function Match({ v, size = 46, dark, delay = 0 }) {
  const [p, setP] = useState(0);
  useEffect(() => { const t = setTimeout(() => setP(v), 60 + delay); return () => clearTimeout(t); }, [v, delay]);
  const r = size / 2 - 2.5, c = 2 * Math.PI * r;
  return (
    <div style={{ position: 'relative', width: size, height: size, flex: 'none' }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={dark ? 'rgba(244,239,229,.20)' : 'var(--line)'} strokeWidth="2" />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={dark ? 'var(--brass-soft)' : 'var(--claret)'} strokeWidth="2" strokeLinecap="round" strokeDasharray={c} strokeDashoffset={c - c * p / 100} style={{ transition: 'stroke-dashoffset 1.1s cubic-bezier(.22,.9,.28,1)' }} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', ...S.sans, fontSize: size * .28, fontWeight: 700, color: dark ? 'var(--bone)' : 'var(--ink)' }}>{v}<span style={{ fontSize: size * .18, opacity: .55 }}>%</span></div>
    </div>
  );
}

/* ---------- controls ---------- */
function Btn({ children, onClick, kind = 'primary', full, style, small }) {
  const base = { ...S.sans, fontSize: small ? 12.5 : 14, fontWeight: 600, letterSpacing: '.02em', padding: small ? '9px 15px' : '15px 22px', borderRadius: 100, border: '1px solid transparent', cursor: 'pointer', width: full ? '100%' : undefined, transition: 'transform .12s ease, opacity .12s', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8 };
  const kinds = {
    primary: { background: 'var(--claret)', color: 'var(--bone)' },
    dark: { background: 'var(--ink)', color: 'var(--bone)' },
    ghost: { background: 'transparent', color: 'var(--ink)', borderColor: 'var(--line)' },
    gilt: { background: 'var(--brass)', color: '#20160F' },
    onDark: { background: 'rgba(244,239,229,.12)', color: 'var(--bone)', borderColor: 'rgba(244,239,229,.28)' }
  };
  return <button onClick={onClick} style={{ ...base, ...kinds[kind], ...style }} onMouseDown={e => e.currentTarget.style.transform = 'scale(.97)'} onMouseUp={e => e.currentTarget.style.transform = 'scale(1)'} onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}>{children}</button>;
}

function Chip({ children, active, onClick, dark, style }) {
  return (
    <button onClick={onClick} style={{ ...S.sans, fontSize: 13, fontWeight: 500, padding: '9px 15px', borderRadius: 100, cursor: 'pointer', whiteSpace: 'nowrap',
      background: active ? (dark ? 'var(--bone)' : 'var(--ink)') : (dark ? 'rgba(244,239,229,.10)' : 'transparent'),
      color: active ? (dark ? 'var(--ink)' : 'var(--bone)') : (dark ? 'var(--bone)' : 'var(--ink-soft)'),
      border: '1px solid ' + (active ? 'transparent' : (dark ? 'rgba(244,239,229,.25)' : 'var(--line)')), ...style }}>{children}</button>
  );
}

function Rail({ children, gap = 14, pad = 22 }) {
  return <div className="aw-rail" style={{ display: 'flex', gap, overflowX: 'auto', margin: `0 -${pad}px`, padding: `0 ${pad}px`, scrollSnapType: 'x mandatory' }}>{children}</div>;
}

function Divider({ style }) { return <div style={{ height: 1, background: 'var(--line)', ...style }} />; }

function SectionHead({ eyebrow, title, action, onAction }) {
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 12, marginBottom: 14 }}>
      <div>
        {eyebrow && <Eyebrow style={{ marginBottom: 7 }}>{eyebrow}</Eyebrow>}
        <div style={{ ...S.serif, fontSize: 26, lineHeight: 1.1, color: 'var(--ink)' }}>{title}</div>
      </div>
      {action && <button onClick={onAction} style={{ ...S.sans, fontSize: 12.5, fontWeight: 600, color: 'var(--claret)', background: 'none', border: 'none', cursor: 'pointer', padding: 0, whiteSpace: 'nowrap' }}>{action}</button>}
    </div>
  );
}

/* ---------- taste axis ---------- */
function Axis({ left, right, v, delay = 0, dark }) {
  const [x, setX] = useState(50);
  useEffect(() => { const t = setTimeout(() => setX(v), 80 + delay); return () => clearTimeout(t); }, [v, delay]);
  const line = dark ? 'rgba(244,239,229,.22)' : 'var(--line)';
  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 9 }}>
        <div style={{ ...S.mono, fontSize: 9.5, color: dark ? 'rgba(244,239,229,.6)' : 'var(--muted)' }}>{left}</div>
        <div style={{ ...S.mono, fontSize: 9.5, color: dark ? 'rgba(244,239,229,.6)' : 'var(--muted)' }}>{right}</div>
      </div>
      <div style={{ position: 'relative', height: 2, background: line }}>
        {[0, 25, 50, 75, 100].map(t => <div key={t} style={{ position: 'absolute', left: t + '%', top: -3, width: 1, height: 8, background: line }} />)}
        <div style={{ position: 'absolute', left: `calc(${x}% - 7px)`, top: -6, width: 14, height: 14, borderRadius: '50%', background: dark ? 'var(--brass)' : 'var(--claret)', boxShadow: '0 2px 6px rgba(27,20,16,.28)', transition: 'left .9s cubic-bezier(.22,.9,.28,1)' }} />
      </div>
    </div>
  );
}

function Stars({ n, size = 12, color = 'var(--brass)' }) {
  return <div style={{ display: 'flex', gap: 2 }}>{[1, 2, 3, 4, 5].map(i => <span key={i} style={{ fontSize: size, color: i <= n ? color : 'var(--line)', lineHeight: 1 }}>★</span>)}</div>;
}

/* ---------- sheet ---------- */
function Sheet({ open, onClose, children, height = '78%', dark }) {
  const [mounted, setMounted] = useState(open);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    if (open) { setMounted(true); requestAnimationFrame(() => setTimeout(() => setShown(true), 10)); }
    else { setShown(false); const t = setTimeout(() => setMounted(false), 280); return () => clearTimeout(t); }
  }, [open]);
  if (!mounted) return null;
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 80 }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(27,20,16,.44)', opacity: shown ? 1 : 0, transition: 'opacity .28s', backdropFilter: 'blur(2px)' }} />
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height, background: dark ? 'var(--ink)' : 'var(--card-2)', borderRadius: '26px 26px 0 0', transform: shown ? 'translateY(0)' : 'translateY(100%)', transition: 'transform .32s cubic-bezier(.22,.9,.28,1)', overflow: 'hidden', boxShadow: '0 -20px 50px rgba(27,20,16,.22)' }}>
        <div style={{ position: 'absolute', top: 10, left: '50%', transform: 'translateX(-50%)', width: 38, height: 4, borderRadius: 3, background: dark ? 'rgba(244,239,229,.3)' : 'var(--line)', zIndex: 5 }} />
        {children}
      </div>
    </div>
  );
}

/* ---------- toast ---------- */
function Toast({ msg }) {
  if (!msg) return null;
  return (
    <div style={{ position: 'absolute', left: 20, right: 20, bottom: 118, zIndex: 90, background: 'var(--ink)', color: 'var(--bone)', borderRadius: 14, padding: '13px 16px', display: 'flex', gap: 10, alignItems: 'center', boxShadow: '0 14px 30px rgba(27,20,16,.3)', animation: 'aw-rise .34s cubic-bezier(.22,.9,.28,1)' }}>
      <div style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--brass)', flex: 'none' }} />
      <div style={{ ...S.sans, fontSize: 13, lineHeight: 1.4 }}>{msg}</div>
    </div>
  );
}

/* ---------- icons — the house line set (components/core/Icon.jsx): 24px grid, 1.7 stroke, rounded caps ---------- */
const ICON = {
  home: '<path d="M3 10.5 12 4l9 6.5"/><path d="M5 9.5V20h14V9.5"/>',
  map: '<path d="M9 4 4 6v14l5-2 6 2 5-2V4l-5 2-6-2z"/><path d="M9 4v14"/><path d="M15 6v14"/>',
  cellar: '<rect x="4" y="4" width="16" height="16" rx="2"/><circle cx="9" cy="9" r="1.4"/><circle cx="15" cy="9" r="1.4"/><circle cx="9" cy="15" r="1.4"/><circle cx="15" cy="15" r="1.4"/>',
  passport: '<rect x="5" y="3" width="14" height="18" rx="2"/><circle cx="12" cy="10" r="2.6"/><path d="M9 16h6"/>',
  back: '<path d="M15 5l-7 7 7 7"/>',
  send: '<path d="M5 12l14-7-5 16-3-6-6-3z"/>',
  image: '<rect x="4" y="5" width="16" height="14" rx="2"/><circle cx="9" cy="10" r="1.6"/><path d="M5 17l5-4 4 3 3-2 2 2"/>',
  voice: '<path d="M5 10v4"/><path d="M9 7v10"/><path d="M12 4v16"/><path d="M15 7v10"/><path d="M19 10v4"/>',
  scan: '<path d="M4 8V6a2 2 0 0 1 2-2h2"/><path d="M16 4h2a2 2 0 0 1 2 2v2"/><path d="M20 16v2a2 2 0 0 1-2 2h-2"/><path d="M8 20H6a2 2 0 0 1-2-2v-2"/><path d="M4 12h16"/>',
  sparkle: '<path d="M12 4l1.6 4.4L18 10l-4.4 1.6L12 16l-1.6-4.4L6 10l4.4-1.6z"/>',
  check: '<path d="M5 12.5l4.5 4.5L19 6.5"/>',
  plus: '<path d="M12 5v14M5 12h14"/>',
  chevron: '<path d="M9 5l7 7-7 7"/>',
  cart: '<path d="M4 5h2l2.2 10.2a1.5 1.5 0 0 0 1.5 1.2h7.6a1.5 1.5 0 0 0 1.5-1.2L20.5 8H6.4"/><circle cx="10" cy="20" r="1.2"/><circle cx="17" cy="20" r="1.2"/>'
};

function Ic({ name, size = 22, color = 'currentColor', strokeWidth = 1.7, style }) {
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" style={{ display: 'block', flex: 'none', ...style }} dangerouslySetInnerHTML={{ __html: ICON[name] || '' }} />;
}

/* ---------- tab bar ---------- */
const TAB_ICON = { home: 'home', explore: 'map', cellar: 'cellar', profile: 'passport' };

function TabBar({ tab, go }) {
  const item = (k, label) => {
    const on = tab === k;
    return (
      <button key={k} onClick={() => go(k)} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '4px 2px', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5, flex: 1 }}>
        <Ic name={TAB_ICON[k]} size={21} color={on ? 'var(--claret)' : 'var(--muted)'} />
        <span style={{ ...S.mono, fontSize: 8.5, color: on ? 'var(--claret)' : 'var(--muted)' }}>{label}</span>
      </button>
    );
  };
  return (
    <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 96, zIndex: 70, background: 'rgba(250,246,238,.90)', backdropFilter: 'blur(18px)', borderTop: '1px solid var(--line)', display: 'flex', alignItems: 'flex-start', paddingTop: 12 }}>
      {item('home', 'Home')}
      {item('explore', 'Explore')}
      <div style={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
        <button onClick={() => go('ask')} style={{ position: 'relative', top: -22, width: 62, height: 62, borderRadius: '50%', border: '3px solid var(--bg)', cursor: 'pointer', background: 'radial-gradient(120% 120% at 30% 20%, #7A2634 0%, var(--claret) 45%, var(--claret-deep) 100%)', color: 'var(--bone)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 2, boxShadow: tab === 'ask' ? '0 0 0 4px rgba(92,27,39,.16), 0 10px 24px rgba(92,27,39,.4)' : '0 8px 20px rgba(92,27,39,.34)' }}>
          <span style={{ ...S.serif, fontSize: 20, lineHeight: 1 }}>Ask</span>
          <span style={{ width: 14, height: 1, background: 'var(--brass-soft)' }} />
        </button>
      </div>
      {item('cellar', 'Cellar')}
      {item('profile', 'You')}
    </div>
  );
}

/* ---------- cart button ----------
   Sits above the tab bar on every screen whenever the basket has something in
   it. Deliberately not shown when empty: an empty cart is noise, and the app
   already opens the cart the moment you add a bottle. */
function CartFab({ count, onClick }) {
  if (!count) return null;
  return (
    <button onClick={onClick} aria-label={count + ' bottles in your cart'}
      style={{ position: 'absolute', right: 18, bottom: 108, zIndex: 74, display: 'flex', alignItems: 'center', gap: 9,
        background: 'var(--ink)', color: 'var(--bone)', border: 'none', borderRadius: 100, padding: '12px 17px',
        cursor: 'pointer', boxShadow: '0 10px 26px rgba(27,20,16,.32)', animation: 'aw-rise .3s cubic-bezier(.22,.9,.28,1)' }}>
      <Ic name="cart" size={17} color="var(--bone)" />
      <span style={{ ...S.sans, fontSize: 13.5, fontWeight: 700 }}>{count}</span>
      <span style={{ ...S.sans, fontSize: 13, opacity: .8 }}>{count === 1 ? 'bottle' : 'bottles'}</span>
    </button>
  );
}

/* ---------- misc ---------- */
function Price({ v, size = 15, color = 'var(--ink)' }) {
  return <span style={{ ...S.sans, fontSize: size, fontWeight: 600, color }}>{AIW.money(v)}</span>;
}

function BackBar({ onBack, title, dark, right }) {
  return (
    <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 100, zIndex: 65, display: 'flex', alignItems: 'flex-end', gap: 12, padding: '0 20px 8px' }}>
      <button onClick={onBack} style={{ width: 36, height: 36, borderRadius: '50%', border: '1px solid ' + (dark ? 'rgba(244,239,229,.3)' : 'var(--line)'), background: dark ? 'rgba(27,20,16,.35)' : 'rgba(250,246,238,.85)', backdropFilter: 'blur(10px)', cursor: 'pointer', color: dark ? 'var(--bone)' : 'var(--ink)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Ic name="back" size={17} /></button>
      {title && <div style={{ ...S.mono, fontSize: 10, color: dark ? 'rgba(244,239,229,.75)' : 'var(--muted)', paddingBottom: 11 }}>{title}</div>}
      <div style={{ flex: 1 }} />
      {right}
    </div>
  );
}

Object.assign(window, { S, Ic, ICON, CartFab, Eyebrow, Device, StatusBar, Screen, Bottle, Match, Btn, Chip, Rail, Divider, SectionHead, Axis, Stars, Sheet, Toast, TabBar, Price, BackBar });
