/* Timeless Totes — shared components */
const { useState, useEffect, useRef } = React;

/* ---------- Icons (simple line set) ---------- */
function Icon({ name, size = 20, stroke = 1.7, style }) {
  const p = {
    arrow:   <path d="M5 12h14M13 6l6 6-6 6" />,
    arrowR:  <path d="M5 12h14M13 6l6 6-6 6" />,
    check:   <path d="M5 12.5l4.5 4.5L19 6.5" />,
    cart:    <><circle cx="9" cy="20" r="1.4"/><circle cx="18" cy="20" r="1.4"/><path d="M2 3h3l2.4 12.5a1 1 0 0 0 1 .8h8.6a1 1 0 0 0 1-.8L21 7H6"/></>,
    upload:  <><path d="M12 16V4M7 9l5-5 5 5"/><path d="M4 16v3a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-3"/></>,
    palette: <><circle cx="12" cy="12" r="9"/><circle cx="8" cy="9" r="1.1"/><circle cx="15.5" cy="9" r="1.1"/><circle cx="16.5" cy="13.5" r="1.1"/></>,
    ruler:   <><rect x="3" y="8" width="18" height="8" rx="1.5"/><path d="M7 8v3M11 8v4M15 8v3M19 8v4"/></>,
    pencil:  <path d="M4 20h4L19 9a2 2 0 0 0-3-3L5 17v3z"/>,
    truck:   <><rect x="1" y="6" width="13" height="10" rx="1"/><path d="M14 9h4l3 3v4h-7M5.5 20a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM17.5 20a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/></>,
    flag:    <><path d="M5 21V4M5 4h11l-2 4 2 4H5"/></>,
    phone:   <path d="M5 4h3l2 5-2 1.5a11 11 0 0 0 5 5L16 13l5 2v3a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z"/>,
    mail:    <><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></>,
    pin:     <><path d="M12 21s7-6.5 7-12a7 7 0 0 0-14 0c0 5.5 7 12 7 12z"/><circle cx="12" cy="9" r="2.4"/></>,
    star:    <path d="M12 3l2.6 5.6L20.5 9.4l-4.3 4 1.1 6L12 16.8 6.7 19.4l1.1-6-4.3-4 5.9-.8z"/>,
    shield:  <path d="M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3z"/>,
    spark:   <path d="M12 3v6M12 15v6M3 12h6M15 12h6"/>,
    menu:    <path d="M3 6h18M3 12h18M3 18h18"/>,
    x:       <path d="M6 6l12 12M18 6L6 18"/>,
    plus:    <path d="M12 5v14M5 12h14"/>,
    layers:  <><path d="M12 3l9 5-9 5-9-5 9-5z"/><path d="M3 13l9 5 9-5"/></>,
    heart:   <path d="M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.5A4 4 0 0 1 19 10c0 5.5-7 10-7 10z"/>,
    chevron: <path d="M9 6l6 6-6 6"/>,
    chevronD:<path d="M6 9l6 6 6-6"/>,
    image:   <><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="8.5" cy="9.5" r="1.7"/><path d="M21 15l-5-5L5 21"/></>,
    camera:  <><path d="M4 8h3l1.6-2.2h6.8L17 8h3a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z"/><circle cx="12" cy="13" r="3.3"/></>,
    swatch:  <><rect x="3" y="3" width="8" height="8" rx="1.5"/><rect x="13" y="3" width="8" height="8" rx="1.5"/><rect x="3" y="13" width="8" height="8" rx="1.5"/><rect x="13" y="13" width="8" height="8" rx="1.5"/></>,
    zip:     <><path d="M12 3v18"/><path d="M9 6h6M9 10h6M9 14h6M9 18h6"/></>,
  }[name] || null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={style}>
      {p}
    </svg>
  );
}

/* ---------- Brand flower mark (rebuilt clean from the logo) ---------- */
function Flower({ size = 34, color = 'var(--pink)', hole = 'var(--bone)' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" fill="none" aria-hidden="true" style={{ flexShrink: 0, display: 'block' }}>
      <g fill={color}>
        <circle cx="16" cy="9.2" r="6.6" />
        <circle cx="22.8" cy="16" r="6.6" />
        <circle cx="16" cy="22.8" r="6.6" />
        <circle cx="9.2" cy="16" r="6.6" />
      </g>
      <circle cx="16" cy="16" r="3.3" fill={hole} />
    </svg>
  );
}

/* ---------- Logo wordmark ---------- */
function Logo({ light = false, onClick }) {
  const ink = light ? '#fff' : 'var(--navy)';
  return (
    <a href="#/" onClick={onClick} aria-label="Timeless Totes home"
      style={{ display: 'flex', alignItems: 'center', gap: 11, lineHeight: 1 }}>
      <Flower size={34} color="var(--pink)" hole={light ? 'var(--navy)' : 'var(--bone)'} />
      <span style={{ display: 'flex', flexDirection: 'column' }}>
        <span style={{ fontFamily: 'var(--serif)', fontSize: 21, fontWeight: 600, color: ink, letterSpacing: '-0.015em', whiteSpace: 'nowrap' }}>Timeless Totes</span>
        <span style={{ fontFamily: 'var(--sans)', fontSize: 10.5, fontWeight: 600, letterSpacing: '.12em', textTransform: 'uppercase', color: light ? 'rgba(255,255,255,.6)' : 'var(--pink-600)', marginTop: 3, whiteSpace: 'nowrap' }}>Custom Clear Vinyl</span>
      </span>
    </a>
  );
}

/* ---------- Header ---------- */
/* Primary nav — labels specific to a custom-product business */
const NAV = [
  { label: 'Products', path: '#/products', mega: true },
  { label: 'How It Works', path: '#/how-it-works' },
  { label: 'Artwork & Proofs', path: '#/artwork' },
  { label: 'Quality & Partners', path: '#/quality' },
  { label: 'Contact', path: '#/contact' },
];

/* Products mega-menu categories — small ecommerce cards, not a text dropdown */
const MEGA = [
  { name: 'Kit Keepers', use: 'Clear project bags for needlepoint & stitch kits', path: '#/product/kit-keepers', icon: 'layers', badge: 'Most Popular' },
  { name: 'Craft Cases', use: 'Structured cases that stand up on the shelf', path: '#/product/craft-case', icon: 'swatch' },
  { name: 'Yarn Caddies', use: 'Keep skeins clean and feeding tangle-free', path: '#/product/yarn-caddy', icon: 'spark' },
  { name: 'Clear Vinyl Bags', use: 'Snap totes & pouches for events and everyday carry', path: '#/product/snapped-accessory-tote', icon: 'cart' },
  { name: 'Custom Sizes', use: 'Built to your exact dimensions — just ask', path: '#/quote', icon: 'ruler' },
];

function ProductsMega({ ctx, onNavigate }) {
  const kkImg = (typeof PRODUCTS !== 'undefined' && PRODUCTS.find(p => p.slug === 'kit-keepers')?.cardImg) || null;
  return (
    <div className="mega-panel" style={{ left: 0, right: 'auto' }}>
      <div className="mega-cards">
        {MEGA.map(item => (
          <a key={item.name} href={item.path} className="mega-card"
            onClick={(e) => { e.preventDefault(); onNavigate(item.path); }}>
            <span className="mega-thumb">
              <ProductImage src={item.name === 'Kit Keepers' ? kkImg : null} label={item.name}
                icon={item.icon} accent="pink" compact style={{ width: '100%', height: '100%' }} />
            </span>
            <span className="mega-body">
              <span className="mega-name">
                {item.name}
                {item.badge && <em className="mega-badge">{item.badge}</em>}
              </span>
              <span className="mega-use">{item.use}</span>
            </span>
          </a>
        ))}
        <a href="#/products" className="mega-card mega-all"
          onClick={(e) => { e.preventDefault(); onNavigate('#/products'); }}>
          <span className="mega-body">
            <span className="mega-name">View All Products</span>
            <span className="mega-use">Browse the full clear-vinyl range</span>
          </span>
          <Icon name="arrow" size={18} className="arr" />
        </a>
      </div>
      <aside className="mega-help">
        <h4>Not sure where to start?</h4>
        <p>Send us your project, quantity, and artwork — we'll recommend the right bag and send a custom quote. No payment up front.</p>
        <button className="btn btn-primary btn-block" onClick={() => onNavigate('#/quote')}>Start a Quote</button>
        <button className="btn btn-ghost btn-block" style={{ marginTop: 10 }} onClick={() => onNavigate('#/design-lab')}>
          <Icon name="pencil" size={17} /> Try the Design Lab
        </button>
      </aside>
    </div>
  );
}

function Header({ ctx }) {
  const [scrolled, setScrolled] = useState(false);
  const [menu, setMenu] = useState(false);
  const [mega, setMega] = useState(false);
  const closeT = useRef(null);
  useEffect(() => {
    const f = () => setScrolled(window.scrollY > 8);
    f(); window.addEventListener('scroll', f); return () => window.removeEventListener('scroll', f);
  }, []);
  useEffect(() => { setMenu(false); setMega(false); }, [ctx.route]);
  const count = ctx.cart.reduce((n, i) => n + 1, 0);
  const active = (p) => ctx.route === p || (p !== '#/' && ctx.route.startsWith(p));
  const go = (p) => { setMega(false); setMenu(false); ctx.navigate(p); };
  const openMega = () => { clearTimeout(closeT.current); setMega(true); };
  const closeMega = () => { closeT.current = setTimeout(() => setMega(false), 120); };

  return (
    <>
      <div className="microbar">
        <div className="wrap">
          <div className="microbar-inner">
            <span><Icon name="flag" size={13} /> Made in USA</span>
            <span className="microbar-dot">·</span>
            <span><Icon name="heart" size={13} /> Family-owned · 30+ years</span>
            <span className="microbar-dot">·</span>
            <span className="microbar-extra"><Icon name="palette" size={13} /> Free digital proof with every order</span>
            <span className="microbar-dot microbar-extra">·</span>
            <span><Icon name="shield" size={13} /> No payment until you approve</span>
          </div>
        </div>
      </div>
      <header style={{ position: 'sticky', top: 0, zIndex: 50 }}>
      {/* Main navigation */}
      <div className="navbar" style={{
        background: 'var(--bone)',
        borderBottom: '1px solid var(--line)',
        boxShadow: scrolled ? '0 6px 22px -16px rgba(21,35,59,.4)' : 'none',
        transition: 'box-shadow .25s',
      }}>
        <div className="wrap" style={{ display: 'flex', alignItems: 'center', gap: 22, height: 74 }}>
          <Logo onClick={(e) => { e.preventDefault(); go('#/'); }} />
          <nav className="nav-desktop" style={{ display: 'flex', alignItems: 'center', gap: 2, marginLeft: 'auto' }}>
            {NAV.map(n => n.mega ? (
              <div key={n.path} className="nav-mega-wrap" onMouseEnter={openMega} onMouseLeave={closeMega}
                style={{ position: 'relative' }}>
                <button className="nav-link" aria-expanded={mega} onClick={() => setMega(m => !m)}
                  style={{
                    color: (active(n.path) || mega) ? 'var(--navy)' : 'var(--ink-soft)',
                    background: (active(n.path) || mega) ? 'var(--white)' : 'transparent',
                  }}>
                  {n.label}
                  <Icon name="chevronD" size={15} style={{ transform: mega ? 'rotate(180deg)' : 'none', transition: 'transform .2s', opacity: .7 }} />
                </button>
                {mega && <ProductsMega ctx={ctx} onNavigate={go} />}
              </div>
            ) : (
              <a key={n.path} href={n.path} className="nav-link"
                onClick={(e) => { e.preventDefault(); go(n.path); }}
                style={{
                  color: active(n.path) ? 'var(--navy)' : 'var(--ink-soft)',
                  background: active(n.path) ? 'var(--white)' : 'transparent',
                }}>{n.label}</a>
            ))}
          </nav>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginLeft: 'auto' }} className="header-cta">
            <button className="btn btn-ghost btn-sm cart-btn" onClick={ctx.openDrawer}
              style={{ position: 'relative', gap: 8 }}>
              <Icon name="cart" size={18} /> <span className="cart-label">My Quote</span>
              {count > 0 && <span style={{
                background: 'var(--pink)', color: '#fff', borderRadius: 100, fontSize: 12, fontWeight: 700,
                minWidth: 20, height: 20, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: '0 5px',
              }}>{count}</span>}
            </button>
            <button className="btn btn-primary btn-sm quote-cta" onClick={() => go('#/quote')}>
              Start a Quote
            </button>
            <button className="menu-toggle" aria-label="Menu" onClick={() => setMenu(m => !m)}
              style={{ display: 'none', background: 'none', border: 'none', color: 'var(--ink)', padding: 6 }}>
              <Icon name={menu ? 'x' : 'menu'} size={26} />
            </button>
          </div>
        </div>
      </div>

      {menu && (
        <div className="mobile-menu" style={{ background: 'var(--white)', borderTop: '1px solid var(--line)', padding: '16px var(--gutter) 24px' }}>
          {/* Conversion actions kept at the top, never buried */}
          <button className="btn btn-primary btn-block btn-lg" onClick={() => go('#/quote')}>Start a Quote</button>
          <button className="btn btn-ghost btn-block" style={{ marginTop: 10 }} onClick={() => { setMenu(false); ctx.openDrawer(); }}>
            <Icon name="cart" size={18} /> My Quote {count > 0 && <span style={{ background: 'var(--pink)', color: '#fff', borderRadius: 100, fontSize: 12, fontWeight: 700, minWidth: 20, height: 20, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: '0 5px', marginLeft: 4 }}>{count}</span>}
          </button>
          <div style={{ height: 1, background: 'var(--line)', margin: '18px 0 4px' }} />
          {NAV.map(n => (
            <a key={n.path} href={n.path} onClick={(e) => { e.preventDefault(); go(n.path); }}
              style={{ display: 'block', padding: '15px 4px', fontSize: '1.15rem', fontWeight: 600, color: 'var(--navy)', borderBottom: '1px solid var(--line-soft)' }}>{n.label}</a>
          ))}
          <a href="#/artwork" onClick={(e) => { e.preventDefault(); go('#/artwork'); }}
            style={{ display: 'inline-flex', alignItems: 'center', gap: 8, padding: '16px 4px 4px', fontSize: '1rem', fontWeight: 600, color: 'var(--pink-600)' }}>
            <Icon name="upload" size={17} /> Upload Artwork & Proofs
          </a>
        </div>
      )}
    </header>
    </>
  );
}

/* ---------- Footer ---------- */
function Footer({ ctx }) {
  return (
    <footer style={{ background: 'var(--navy)', color: 'rgba(255,255,255,.82)', paddingTop: 72 }}>
      <div className="wrap">
        <div className="footer-grid" style={{ display: 'grid', gridTemplateColumns: '1.6fr 1fr 1fr 1.2fr', gap: 40, paddingBottom: 56 }}>
          <div>
            <Logo light onClick={(e) => { e.preventDefault(); ctx.navigate('#/'); }} />
            <p style={{ marginTop: 18, maxWidth: 300, fontSize: '.97rem', lineHeight: 1.65 }}>
              Family-owned, American-made custom clear-vinyl totes and bags — silkscreened with your logo for shops, brands, and wholesale orders.
            </p>
            <div style={{ display: 'flex', gap: 8, marginTop: 18 }}>
              <span className="chip" style={{ background: 'rgba(255,255,255,.08)', color: '#fff', borderColor: 'rgba(255,255,255,.15)' }}><Icon name="flag" size={14} /> Made in USA</span>
              <span className="chip" style={{ background: 'rgba(255,255,255,.08)', color: '#fff', borderColor: 'rgba(255,255,255,.15)' }}><Icon name="heart" size={14} /> Family-Owned</span>
            </div>
          </div>
          <div>
            <h4 style={{ color: '#fff', fontFamily: 'var(--sans)', fontSize: '.8rem', letterSpacing: '.14em', textTransform: 'uppercase', marginBottom: 16, fontWeight: 700 }}>Shop</h4>
            {PRODUCTS.slice(0, 5).map(p => (
              <a key={p.slug} href="#" onClick={(e) => { e.preventDefault(); ctx.navigate('#/product/' + p.slug); }}
                style={{ display: 'block', padding: '6px 0', fontSize: '.96rem' }}>{p.name}</a>
            ))}
          </div>
          <div>
            <h4 style={{ color: '#fff', fontFamily: 'var(--sans)', fontSize: '.8rem', letterSpacing: '.14em', textTransform: 'uppercase', marginBottom: 16, fontWeight: 700 }}>Company</h4>
            {[['How It Works', '#/how-it-works'], ['Wholesale / B2B', '#/wholesale'], ['Artwork & Proofs', '#/artwork'], ['Quality & Partners', '#/quality'], ['FAQ', '#/faq'], ['Contact', '#/contact']].map(([l, p]) => (
              <a key={p} href={p} onClick={(e) => { e.preventDefault(); ctx.navigate(p); }}
                style={{ display: 'block', padding: '6px 0', fontSize: '.96rem' }}>{l}</a>
            ))}
          </div>
          <div>
            <h4 style={{ color: '#fff', fontFamily: 'var(--sans)', fontSize: '.8rem', letterSpacing: '.14em', textTransform: 'uppercase', marginBottom: 16, fontWeight: 700 }}>Get in touch</h4>
            <a href="tel:7149736353" style={{ display: 'flex', gap: 9, padding: '6px 0', fontSize: '.96rem' }}><Icon name="phone" size={16} /> (714) 973-6353</a>
            <a href="mailto:timelesstotes@yahoo.com" style={{ display: 'flex', gap: 9, padding: '6px 0', fontSize: '.96rem' }}><Icon name="mail" size={16} /> timelesstotes@yahoo.com</a>
            <div style={{ display: 'flex', gap: 9, padding: '6px 0', fontSize: '.96rem' }}><Icon name="pin" size={16} style={{ flexShrink: 0, marginTop: 3 }} /> 4005 W Segerstrom Ave,<br />Santa Ana, CA 92704</div>
            <button className="btn btn-accent btn-sm" style={{ marginTop: 14 }} onClick={() => ctx.navigate('#/quote')}>Start a Quote <Icon name="arrow" size={15} className="arr" /></button>
          </div>
        </div>
        <div style={{ borderTop: '1px solid rgba(255,255,255,.12)', padding: '22px 0 30px', display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 12, fontSize: '.85rem', opacity: .78 }}>
          <span>© 2026 Timeless Totes · Simply Sew LLC</span>
          <div style={{ display: 'flex', gap: 18, flexWrap: 'wrap' }}>
            {[['Privacy Policy','#/privacy'],['Terms of Service','#/terms'],['Shipping Policy','#/shipping-policy'],['Quote & Production Policy','#/quote-policy']].map(([l,p]) => (
              <a key={p} href={p} onClick={(e) => { e.preventDefault(); ctx.navigate(p); }}
                style={{ color: 'rgba(255,255,255,.78)', textDecoration: 'underline', textUnderlineOffset: 3, textDecorationColor: 'rgba(255,255,255,.3)' }}>{l}</a>
            ))}
          </div>
        </div>
      </div>
    </footer>
  );
}

/* ---------- Mock photo frame (intentional "photo coming" slot, not striped noise) ---------- */
function Mock({ label, sub, icon = 'camera', accent = 'pink', compact = false, tone = 'tint', className = '', style }) {
  const bg = tone === 'neutral' ? 'var(--bone-deep)' : 'var(--' + accent + '-tint)';
  const mark = 'rgba(21,35,59,.16)';
  return (
    <div className={'mock ' + className} style={{
      position: 'relative', overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: bg, ...style,
    }}>
      <div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(115% 82% at 50% 6%, rgba(255,255,255,.6), transparent 64%)' }} />
      {!compact && [['top', 'left'], ['top', 'right'], ['bottom', 'left'], ['bottom', 'right']].map(([v, h]) => (
        <span key={v + h} style={{
          position: 'absolute', [v]: 16, [h]: 16, width: 13, height: 13,
          borderTop: v === 'top' ? '2px solid ' + mark : 'none',
          borderBottom: v === 'bottom' ? '2px solid ' + mark : 'none',
          borderLeft: h === 'left' ? '2px solid ' + mark : 'none',
          borderRight: h === 'right' ? '2px solid ' + mark : 'none',
        }} />
      ))}
      <div style={{ position: 'relative', textAlign: 'center', padding: compact ? 0 : '18px', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: compact ? 0 : 11 }}>
        <span style={{
          width: compact ? 34 : 52, height: compact ? 34 : 52, borderRadius: '50%',
          background: 'rgba(255,255,255,.85)', color: 'var(--pink-600)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: '0 2px 8px rgba(27,26,22,.06)', flexShrink: 0,
        }}><Icon name={icon} size={compact ? 17 : 24} /></span>
        {!compact && label && (
          <div>
            <div style={{ fontWeight: 700, fontSize: '.95rem', color: 'var(--ink)', lineHeight: 1.3 }}>{label}</div>
            <div style={{ fontSize: '.78rem', color: 'var(--ink-soft)', marginTop: 3 }}>{sub || 'Product photo'}</div>
          </div>
        )}
      </div>
    </div>
  );
}

/* ---------- Product image with photo-frame fallback ---------- */
function ProductImage({ src, label, sub, icon = 'camera', accent = 'pink', compact = false, className = '', style }) {
  const [err, setErr] = useState(false);
  if (!src || err) {
    return <Mock label={label} sub={sub} icon={icon} accent={accent} compact={compact} className={className} style={style} />;
  }
  return (
    <div className={className} style={{ ...style, position: 'relative', overflow: 'hidden', background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <img src={src} alt={label} loading="lazy" onError={() => setErr(true)}
        style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }} />
    </div>
  );
}

/* ---------- Product card ---------- */
function ProductCard({ p, ctx, featured = false }) {
  const [hover, setHover] = useState(false);
  const [open, setOpen] = useState(false);
  const variants = p.variants;
  const addVariant = (e, v) => {
    e.stopPropagation();
    ctx.addToQuote({ ...p, slug: p.slug + '-' + v.code, name: p.name + ' · ' + v.code, code: v.code, variantDims: v.dims });
  };
  return (
    <article className="card" onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      onClick={() => ctx.navigate('#/product/' + p.slug)}
      style={{ overflow: 'hidden', cursor: 'pointer', display: 'flex', flexDirection: 'column',
        transform: hover ? 'translateY(-4px)' : 'none', boxShadow: hover ? 'var(--shadow-md)' : 'var(--shadow-sm)',
        transition: 'transform .2s, box-shadow .2s' }}>
      <div style={{ position: 'relative', aspectRatio: featured ? '16/11' : '4/3', borderBottom: '1px solid var(--line)' }}>
        <ProductImage src={p.cardImg} label={p.name} sub="Clear vinyl · logo silkscreen" accent={p.accent} icon="camera"
          style={{ width: '100%', height: '100%' }} />
        {p.tag && <span className="chip" style={{ position: 'absolute', top: 14, left: 14, background: '#fff', fontWeight: 700, boxShadow: 'var(--shadow-sm)', zIndex: 2 }}><span className="dot" style={{ color: 'var(--' + p.accent + ')' }} />{p.tag}</span>}
      </div>
      <div style={{ padding: '20px 22px 22px', display: 'flex', flexDirection: 'column', flex: 1 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 10 }}>
          <h3 style={{ fontSize: featured ? '1.55rem' : '1.3rem' }}>{p.name}</h3>
        </div>
        <p style={{ color: 'var(--ink-soft)', fontSize: '.97rem', margin: '12px 0 16px', flex: 1 }}>{p.blurb}</p>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '12px 0', borderTop: '1px solid var(--line-soft)', borderBottom: open ? 'none' : '1px solid var(--line-soft)', marginBottom: open ? 0 : 16, fontSize: '.84rem', color: 'var(--ink-soft)' }}>
          {p.sizeNote && <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><Icon name="ruler" size={15} style={{ color: 'var(--navy-300)' }} /> {p.sizeNote}</span>}
          {p.moq && <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><Icon name="layers" size={15} style={{ color: 'var(--navy-300)' }} /> Min {p.moq}</span>}
        </div>

        {/* Expandable size list (variant products like Kit Keepers) */}
        {variants && (
          <div style={{ marginBottom: 16 }}>
            <button onClick={(e) => { e.stopPropagation(); setOpen(o => !o); }}
              aria-expanded={open}
              style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, padding: '11px 0', background: 'none', border: 'none', borderBottom: '1px solid var(--line-soft)', color: 'var(--navy)', fontWeight: 600, fontSize: '.9rem', fontFamily: 'var(--sans)' }}>
              {open ? 'Hide sizes' : 'View all ' + variants.length + ' sizes'}
              <Icon name="chevronD" size={18} style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .2s', color: 'var(--pink-600)' }} />
            </button>
            {open && (
              <div style={{ display: 'flex', flexDirection: 'column', marginTop: 4 }}>
                {variants.map(v => (
                  <div key={v.code} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 2px', borderBottom: '1px solid var(--line-soft)' }}>
                    <strong style={{ fontSize: '.88rem', minWidth: 52 }}>{v.code}</strong>
                    <span style={{ flex: 1, fontSize: '.86rem', color: 'var(--ink-soft)' }}>{v.dims}</span>
                    {v.est && <span className="mono" style={{ fontSize: '.66rem', color: 'var(--ink-faint)' }}>est.</span>}
                    <button className="btn btn-ghost btn-sm" style={{ padding: '6px 11px' }} onClick={(e) => addVariant(e, v)}><Icon name="plus" size={13} /> Add</button>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
          <span className="link-arrow" style={{ fontSize: '.93rem' }}>View details <Icon name="arrow" size={15} /></span>
          <button className="btn btn-ghost btn-sm" onClick={(e) => { e.stopPropagation(); ctx.addToQuote(p); }}>
            <Icon name="plus" size={15} /> Add to Quote
          </button>
        </div>
      </div>
    </article>
  );
}

/* ---------- Quote Drawer ---------- */
function QuoteDrawer({ ctx }) {
  const open = ctx.drawerOpen;
  return (
    <>
      <div onClick={ctx.closeDrawer} style={{
        position: 'fixed', inset: 0, background: 'rgba(27,26,22,.4)', zIndex: 90,
        opacity: open ? 1 : 0, pointerEvents: open ? 'auto' : 'none', transition: 'opacity .25s',
        backdropFilter: 'blur(2px)',
      }} />
      <aside style={{
        position: 'fixed', top: 0, right: 0, bottom: 0, width: 'min(420px, 92vw)', zIndex: 91,
        background: 'var(--cream)', boxShadow: 'var(--shadow-lg)', transform: open ? 'none' : 'translateX(100%)',
        transition: 'transform .3s cubic-bezier(.3,.7,.3,1)', display: 'flex', flexDirection: 'column',
      }}>
        <div style={{ padding: '22px 24px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <h3 style={{ fontSize: '1.35rem' }}>Quote Builder</h3>
            <span style={{ fontSize: '.9rem', color: 'var(--ink-soft)' }}>{ctx.cart.length} {ctx.cart.length === 1 ? 'product added' : 'products added'}</span>
          </div>
          <button onClick={ctx.closeDrawer} aria-label="Close" style={{ background: 'none', border: 'none', padding: 6, color: 'var(--ink-soft)' }}><Icon name="x" size={22} /></button>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: '18px 24px' }}>
          {ctx.cart.length === 0 ? (
            <div style={{ textAlign: 'center', padding: '50px 10px', color: 'var(--ink-soft)' }}>
              <div style={{ color: 'var(--navy-300)', display: 'flex', justifyContent: 'center', marginBottom: 14 }}><Icon name="cart" size={42} stroke={1.3} /></div>
              <p style={{ fontWeight: 600, color: 'var(--ink)' }}>Your quote builder is empty</p>
              <p style={{ fontSize: '.95rem' }}>Add products and sizes to request one combined quote — no payment, no checkout.</p>
              <button className="btn btn-ghost btn-sm" style={{ marginTop: 8 }} onClick={() => { ctx.closeDrawer(); ctx.navigate('#/products'); }}>Browse products</button>
            </div>
          ) : ctx.cart.map((item, i) => (
            <div key={i} style={{ display: 'flex', gap: 14, padding: '14px 0', borderBottom: '1px solid var(--line-soft)' }}>
              <ProductImage src={item.cardImg} label="" accent={item.accent} compact style={{ width: 64, height: 64, borderRadius: 10, flexShrink: 0 }} />
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
                  <strong style={{ fontSize: '1rem' }}>{item.name}</strong>
                  <button onClick={() => ctx.removeFromQuote(i)} style={{ background: 'none', border: 'none', color: 'var(--ink-faint)', padding: 2 }}><Icon name="x" size={16} /></button>
                </div>
                <div style={{ fontSize: '.85rem', color: 'var(--ink-soft)', marginTop: 4 }}>Sizes, qty & ink set in the next step</div>
              </div>
            </div>
          ))}
        </div>
        <div style={{ padding: '18px 24px 24px', borderTop: '1px solid var(--line)', background: 'var(--white)' }}>
          <p style={{ fontSize: '.86rem', color: 'var(--ink-soft)', margin: '0 0 12px', display: 'flex', gap: 8 }}>
            <Icon name="shield" size={16} style={{ color: 'var(--pink-600)', flexShrink: 0 }} />
            No payment now. We confirm pricing after artwork &amp; production review.
          </p>
          <button className="btn btn-primary btn-block btn-lg" disabled={ctx.cart.length === 0}
            style={{ opacity: ctx.cart.length === 0 ? .45 : 1 }}
            onClick={() => { ctx.closeDrawer(); ctx.navigate('#/quote'); }}>
            Request Quote <Icon name="arrow" size={17} className="arr" />
          </button>
        </div>
      </aside>
    </>
  );
}

/* ---------- Reusable section header ---------- */
function SectionHead({ eyebrow, title, lede, center, light }) {
  return (
    <div style={{ maxWidth: center ? 720 : 760, margin: center ? '0 auto' : 0, textAlign: center ? 'center' : 'left', marginBottom: 44 }}>
      {eyebrow && <p className={'eyebrow' + (center ? ' center' : '')} style={light ? { color: '#F6A8C9' } : {}}>{eyebrow}</p>}
      <h2 style={light ? { color: '#fff' } : {}}>{title}</h2>
      {lede && <p className="lede" style={{ marginTop: 16, marginBottom: 0, ...(light ? { color: 'rgba(255,255,255,.8)' } : {}) }}>{lede}</p>}
    </div>
  );
}

Object.assign(window, { Icon, Logo, Flower, Mock, ProductImage, Header, Footer, ProductCard, QuoteDrawer, SectionHead });
