// Shared UI primitives — Ciao Bella (Staplelab restyle)

const { useState, useEffect, useRef, useCallback, useMemo } = React;

// ── Helper: navigate to /phone configurator ("Make one that's theirs") ──
// Optional `qty` pre-fills the configurator quantity (used by BFF/Trio bundle CTAs).
function goToConfigurator(navigate, currentRoute, qty) {
  if (qty && qty >= 1 && qty <= 5) {
    try { sessionStorage.setItem('cb_initial_qty', String(qty)); } catch (e) {}
    // If already on /phone, the PhonePage is mounted — fire an event so it can
    // update its quantity state live without a remount.
    if (currentRoute === '/phone') {
      window.dispatchEvent(new CustomEvent('ciao:configurator-qty', { detail: { qty } }));
    }
  }
  if (currentRoute === '/phone') {
    document.getElementById('configurator')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  } else {
    navigate('/phone');
    setTimeout(() => {
      document.getElementById('configurator')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }, 120);
  }
}

// ── Signature CTA: blue pill + cream circle + arrow ──
function CTA({ children, onClick, href, className = '', sm = false, ...rest }) {
  const cls = (sm ? 'cta-sm ' : 'cta ') + className;
  const inner = (
    <>
      <span>{children}</span>
      <span className="cta-circle">
        <svg fill="none" stroke="#1a1a1a" strokeWidth={2.5} viewBox="0 0 12 20">
          <path strokeLinecap="round" strokeLinejoin="round" d="M2 18L10 10L2 2" />
        </svg>
      </span>
    </>
  );
  if (href) return <a href={href} className={cls} onClick={onClick} {...rest}>{inner}</a>;
  return <button type="button" className={cls} onClick={onClick} {...rest}>{inner}</button>;
}

function CTAGhost({ children, onClick, href, ...rest }) {
  const Tag = href ? 'a' : 'button';
  return (
    <Tag href={href} onClick={onClick} className="cta-ghost" {...rest}>
      {children}
    </Tag>
  );
}

// ── Pill badge ──
function Pill({ children }) {
  return <span className="pill">{children}</span>;
}

// ── Brand mark: shape-letter Ciao Bella logo ──
function Logo({ height = 32, mark = false, style }) {
  if (mark) {
    return <img src="assets/brand/mark.svg" alt="Ciao Bella" style={{ height, display: 'block', ...style }} />;
  }
  return <img src="assets/brand/logo.png" alt="Ciao Bella" style={{ height, display: 'block', ...style }} />;
}

// ── Retro sticker (decorative) ──
function Sticker({ kind = 'good-vibe', size = 110, rotate = 0, style, className = '' }) {
  const map = {
    'good-vibe':   'assets/brand/sticker-good-vibe.svg',
    'ciao-heart':  'assets/brand/sticker-ciao-heart.svg',
    'good-job':    'assets/brand/sticker-good-job.svg',
    'time-travel': 'assets/sticker-time-travel.svg',
    'ciao-tile':   'assets/brand/sticker-ciao-tile.svg',
    'daisy':       'assets/sticker-daisy.svg',
    'mascot':      'assets/mascot-character.svg',
    'sardine':     'assets/sardine-tin.svg',
    'pizza':       'assets/jeffs-pizza.svg',
    'lasagne':     'assets/lasagne-1300.svg',
  };
  return (
    <img
      src={map[kind] || map['good-vibe']}
      alt=""
      aria-hidden="true"
      className={'sticker ' + className}
      style={{
        width: size,
        height: 'auto',
        transform: `rotate(${rotate}deg)`,
        filter: 'drop-shadow(0 4px 0 rgba(46,44,41,0.12))',
        ...style,
      }}
    />
  );
}

// ── Gutter stickers (decorative, scattered down the page) ──
// Each item can opt out of routes via `hideOn`, or override its vertical
// position per route via `topByRoute` — so we can tune each page without
// re-shuffling the rest.
function GutterStickers({ currentRoute = '/' }) {
  const items = [
    // ============================================================
    // Stickers re-tuned for compressed section padding (200 → 112).
    // All content shifted up ~25%, so top values reduced accordingly.
    // Hidden under 1080px via CSS — these are desktop-only decorative.
    // Layout: alternating L/R rhythm down the page.
    // ============================================================

    // 1. Top-left — hidden on home/phone/about (those have their own hero stickers)
    { src: 'assets/stickers/pack-c-04.png', top: 200,  side: 'left',  offset: 48, size: 110, rotate: -10, hideOn: ['/', '/phone', '/about'] },

    // 2. Right — flower; hidden on home (replaced by in-photo flower); top of /phone, mid /about, above-divider on /for-parents
    { src: 'assets/stickers/pack-c-02.png', top: 600,  side: 'right', offset: 44, size: 110, rotate: -6, hideOn: ['/'], topByRoute: { '/about': 420, '/phone': 220, '/for-parents': 380, '/subscriptions': 380 } },

    // 6. Right — bottom of long pages; hidden on /phone (overlaps the pricing summary CTA)
    { src: 'assets/stickers/pack-c-06.png', top: 3200, side: 'right', offset: 52, size: 110, rotate: -12, hideOn: ['/phone'] },
  ];

  // Measure footer-top so stickers below the real content don't extend the page.
  const [maxTop, setMaxTop] = useState(Infinity);
  useEffect(() => {
    let raf;
    const measure = () => {
      const footer = document.querySelector('footer');
      if (!footer) return;
      const rect = footer.getBoundingClientRect();
      const top = rect.top + window.scrollY;
      setMaxTop(Math.max(0, top - 80));
    };
    measure();
    const ro = new ResizeObserver(() => { cancelAnimationFrame(raf); raf = requestAnimationFrame(measure); });
    ro.observe(document.body);
    window.addEventListener('load', measure);
    return () => { ro.disconnect(); window.removeEventListener('load', measure); cancelAnimationFrame(raf); };
  }, [currentRoute]);

  const visible = items.filter(s => {
    const effectiveTop = (s.topByRoute && s.topByRoute[currentRoute] != null) ? s.topByRoute[currentRoute] : s.top;
    // Always hide every gutter sticker on /preorder — it's a transactional
    // page (checkout form + order summary) and stickers crowd the form.
    if (currentRoute === '/preorder') return false;
    return effectiveTop <= maxTop && !(s.hideOn && s.hideOn.includes(currentRoute));
  });
  return (
    <div className="gutter-stickers" aria-hidden="true">
      {visible.map((s, i) => {
        const top = (s.topByRoute && s.topByRoute[currentRoute] != null) ? s.topByRoute[currentRoute] : s.top;
        return (
          <img
            key={i}
            src={s.src}
            alt=""
            className="gutter-sticker"
            style={{
              top: top + 'px',
              [s.side]: s.offset + 'px',
              width: s.size + 'px',
              transform: `rotate(${s.rotate}deg)`,
            }}
          />
        );
      })}
    </div>
  );
}

// ── Cord frame (curly squiggle border around an image) ──
function CordFrame({ color = 'yellow', children, className = '', style }) {
  const upper = color.toUpperCase();
  const h = `assets/brand/CB_PATTERN_CORD_${upper}.svg`;
  const v = `assets/brand/CB_PATTERN_CORD_${upper}_VERT.svg`;
  return (
    <div className={'cord-frame ' + className} style={style}>
      {children}
      <img src={h} alt="" aria-hidden="true" className="cord cord-top" />
      <img src={h} alt="" aria-hidden="true" className="cord cord-bottom" />
      <img src={v} alt="" aria-hidden="true" className="cord cord-left" />
      <img src={v} alt="" aria-hidden="true" className="cord cord-right" />
    </div>
  );
}

// ── Section divider (curly cord pattern band between sections) ──
function SectionDivider({ color = 'blue', height = 56, style }) {
  const map = {
    blue:   'assets/brand/CB_PATTERN_CORD_BLUE.svg',
    yellow: 'assets/brand/CB_PATTERN_CORD_YELLOW.svg',
    orange: 'assets/brand/CB_PATTERN_CORD_ORANGE.svg',
    red:    'assets/brand/CB_PATTERN_CORD_RED.svg',
    green:  'assets/brand/CB_PATTERN_CORD_GREEN.svg',
  };
  const src = map[color] || map.blue;
  return (
    <div
      className="section-divider"
      aria-hidden="true"
      style={{
        backgroundImage: `url(${src})`,
        backgroundRepeat: 'repeat-x',
        backgroundSize: 'auto 100%',
        backgroundPosition: 'left center',
        height: height + 'px',
        width: '100%',
        position: 'relative',
        zIndex: 2,
        ...style,
      }}
    ></div>
  );
}

// ── Loopy squiggle border strip (top/bottom of cards & sections) ──
function CheckerStrip({ color = 'green', height = 36, style, className = '' }) {
  const colorMap = {
    green: 'assets/brand/loop-green.svg',
    red:   'assets/brand/loop-red.svg',
    blue:  'assets/brand/loop-blue.svg',
    yellow: 'assets/brand/loop-yellow.svg',
  };
  const src = colorMap[color] || colorMap.green;
  return (
    <div
      className={'checker-strip ' + className}
      style={{
        backgroundImage: `url(${src})`,
        backgroundRepeat: 'repeat-x',
        backgroundSize: 'auto 100%',
        backgroundPosition: 'left center',
        height: height + 'px',
        width: '100%',
        ...style,
      }}
    ></div>
  );
}
// ── Squiggle line (multi-coloured loops) ──
function Squiggle({ color = 'red', height = 22, style, className = '' }) {
  return (
    <img
      src={`assets/brand/squiggle-${color}.svg`}
      alt=""
      aria-hidden="true"
      className={'squiggle ' + className}
      style={{ width: '100%', height, display: 'block', ...style }}
    />
  );
}

// ── Section heading with arrow underline on a key word ──
function SectionHeading({ children, underlineWord }) {
  // Extract a flat string from children (which may be a string, an element
  // wrapper from the text-editor, or an array of those).
  const flatten = (node) => {
    if (node == null || node === false) return '';
    if (typeof node === 'string' || typeof node === 'number') return String(node);
    if (Array.isArray(node)) return node.map(flatten).join('');
    if (node.props && node.props.children !== undefined) return flatten(node.props.children);
    return '';
  };
  const text = flatten(children);

  if (underlineWord && text.includes(underlineWord)) {
    const idx = text.indexOf(underlineWord);
    const before = text.slice(0, idx);
    const after = text.slice(idx + underlineWord.length);
    return (
      <h2 className="h-section">
        {before}
        <span className="underlined">
          {underlineWord}
          <img src="assets/brand/squiggle-red.svg" alt="" className="arrow" aria-hidden="true" />
        </span>
        {after}
      </h2>
    );
  }
  return <h2 className="h-section">{children}</h2>;
}

// ── Eyebrow row (dot + label) ──
function EyebrowRow({ children }) {
  return (
    <span className="eyebrow-row">
      <span className="dot"></span>
      <span>{children}</span>
    </span>
  );
}

// ── Announcement bar — pre-order pricing teaser ──
function AnnouncementBar({ navigate }) {
  const [dismissed, setDismissed] = useState(false);

  useEffect(() => {
    try {
      if (sessionStorage.getItem('cb_announcement_dismissed') === '1') {
        setDismissed(true);
      }
    } catch (e) { /* no-op */ }
  }, []);

  const dismiss = () => {
    try { sessionStorage.setItem('cb_announcement_dismissed', '1'); } catch (e) {}
    setDismissed(true);
  };

  if (dismissed) return null;

  return (
    <div className="announce-bar" role="region" aria-label="Pre-order announcement">
      <div className="announce-bar-inner">
        <span className="announce-bar-dot" aria-hidden="true"></span>
        <a
          href="#"
          className="announce-bar-text"
          onClick={(e) => { e.preventDefault(); navigate('/phone'); }}
        >
          <strong>Limited Pre-Order Offer</strong>
          <span className="announce-bar-divider" aria-hidden="true">·</span>
          Grab yours today to join the Ciao Bella crew!
        </a>
        <button
          type="button"
          className="announce-bar-close"
          onClick={dismiss}
          aria-label="Dismiss announcement"
        >×</button>
      </div>
    </div>
  );
}

// ── Navbar ──
function Navbar({ currentRoute, navigate }) {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    window.addEventListener('scroll', onScroll);
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  // Lock body scroll while menu open
  useEffect(() => {
    if (menuOpen) {
      const prev = document.body.style.overflow;
      document.body.style.overflow = 'hidden';
      return () => { document.body.style.overflow = prev; };
    }
  }, [menuOpen]);

  // Close on route change
  useEffect(() => { setMenuOpen(false); }, [currentRoute]);

  const go = (path) => { setMenuOpen(false); navigate(path); };
  const goFaq = () => {
    setMenuOpen(false);
    if (currentRoute !== '/') navigate('/');
    setTimeout(() => document.getElementById('faq')?.scrollIntoView({ behavior: 'smooth' }), 100);
  };

  const link = (path, label) => (
    <a
      href={'#' + path}
      onClick={(e) => { e.preventDefault(); go(path); }}
      className={currentRoute === path ? 'active' : ''}
    >{label}</a>
  );

  return (
    <nav className={'nav' + (scrolled ? ' scrolled' : '')}>
      <div className="nav-inner">
        <a href="#/" onClick={(e) => { e.preventDefault(); go('/'); }} className="nav-logo" aria-label="Ciao Bella — home">
          <Logo height={28} />
        </a>
        <div className="nav-links">
          {link('/phone', 'The Phone')}
          {link('/for-parents', 'For Parents')}
          {link('/subscriptions', 'Subscriptions')}
          {link('/about', 'About Us')}
        </div>
        <div className="nav-actions">
          <CTA sm className="nav-cta" onClick={() => { setMenuOpen(false); goToConfigurator(navigate, currentRoute); }}>Reserve for $25</CTA>
          <button
            type="button"
            className={'nav-burger' + (menuOpen ? ' open' : '')}
            aria-label={menuOpen ? 'Close menu' : 'Open menu'}
            aria-expanded={menuOpen}
            onClick={() => setMenuOpen(o => !o)}
          >
            <span></span>
            <span></span>
            <span></span>
          </button>
        </div>
      </div>

      {/* Mobile drawer */}
      <div className={'nav-drawer' + (menuOpen ? ' open' : '')} role="dialog" aria-hidden={!menuOpen}>
        <div className="nav-drawer-inner">
          <a href="#/" onClick={(e) => { e.preventDefault(); go('/'); }} className={'nav-drawer-link' + (currentRoute === '/' ? ' active' : '')}>Home</a>
          <a href="#/phone" onClick={(e) => { e.preventDefault(); go('/phone'); }} className={'nav-drawer-link' + (currentRoute === '/phone' ? ' active' : '')}>The Phone</a>
          <a href="#/for-parents" onClick={(e) => { e.preventDefault(); go('/for-parents'); }} className={'nav-drawer-link' + (currentRoute === '/for-parents' ? ' active' : '')}>For Parents</a>
          <a href="#/subscriptions" onClick={(e) => { e.preventDefault(); go('/subscriptions'); }} className={'nav-drawer-link' + (currentRoute === '/subscriptions' ? ' active' : '')}>Subscriptions</a>
          <a href="#/about" onClick={(e) => { e.preventDefault(); go('/about'); }} className={'nav-drawer-link' + (currentRoute === '/about' ? ' active' : '')}>About Us</a>
          <div className="nav-drawer-cta">
            <CTA onClick={() => { setMenuOpen(false); goToConfigurator(navigate, currentRoute); }}>Reserve for $25</CTA>
          </div>
        </div>
      </div>
      {menuOpen && <div className="nav-scrim" onClick={() => setMenuOpen(false)} aria-hidden="true"></div>}
    </nav>
  );
}

// ── EmailSignup — appears above footer on every page ──
function EmailSignup() {
  const [emailVal, setEmailVal] = React.useState('');
  const [status, setStatus] = React.useState('idle');
  const [errMsg, setErrMsg] = React.useState('');

  const submit = async () => {
    const v = emailVal.trim();
    if (!v || v.indexOf('@') < 1 || v.indexOf('.') < 0) {
      setErrMsg('Please enter a valid email address.');
      return;
    }
    setStatus('loading');
    setErrMsg('');
    try {
      const res = await fetch('/api/subscribe', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: v }),
      });
      const data = await res.json();
      if (data.success) {
        setStatus('success');
      } else {
        setStatus('error');
        setErrMsg('Something went wrong. Please try again.');
      }
    } catch (e) {
      setStatus('error');
      setErrMsg('Something went wrong. Please try again.');
    }
  };

  if (status === 'success') {
    return (
      <div className="email-signup-section">
        <div className="container">
          <div className="email-signup-inner email-signup-success">
            <p className="email-signup-success-msg">Welcome to the Ciao Bella family.</p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="email-signup-section">
      <div className="container">
        <div className="email-signup-inner">
          <div className="email-signup-copy">
            <p className="email-signup-eyebrow">Ciao, friend.</p>
            <p className="email-signup-heading">Join our list for launch updates and early access to what's new.</p>
          </div>
          <div className="email-signup-form">
            <div className="email-signup-row">
              <input
                type="email"
                className="email-signup-input"
                placeholder="your@email.com"
                value={emailVal}
                onChange={function(e) { setEmailVal(e.target.value); setErrMsg(''); }}
                onKeyDown={function(e) { if (e.key === 'Enter') submit(); }}
                disabled={status === 'loading'}
              />
              <button className="email-signup-btn" onClick={submit} disabled={status === 'loading'}>
                {status === 'loading' ? '...' : 'Join the list'}
              </button>
            </div>
            {errMsg ? <p className="email-signup-error">{errMsg}</p> : null}
            <p className="email-signup-fine">No spam. Unsubscribe any time.</p>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Footer ──
function Footer({ navigate, currentRoute }) {
  return (
    <footer className="footer" style={{ position: 'relative' }}>
      <img
        src="assets/footer-heart.svg"
        alt=""
        aria-hidden="true"
        className="footer-sticker"
      />
      <div className="container">
        <div className="footer-grid">
          <div className="footer-col">
            <Logo height={32} />
            <p className="footer-tagline" style={{ marginTop: 16 }}>A beautiful home phone made just for kids. Australian-owned.</p>
          </div>
          <div className="footer-col">
            <h4>Product</h4>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/phone'); }}>The phone</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/subscriptions'); }}>Subscriptions</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/preorder'); }}>Pre-order</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/parent-app'); }}>Parent app</a>
          </div>
          <div className="footer-col">
            <h4>Company</h4>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/about'); }}>About</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/for-parents'); }}>For parents</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/contact'); }}>Contact</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/for-parents'); setTimeout(() => document.getElementById('faq')?.scrollIntoView({ behavior: 'smooth' }), 100); }}>Support &amp; FAQs</a>
          </div>
          <div className="footer-col">
            <h4>Legal</h4>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/privacy'); }}>Privacy</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/terms'); }}>Terms</a>
            <a href="#" onClick={(e) => { e.preventDefault(); navigate('/refunds'); }}>Returns &amp; refunds</a>
          </div>
        </div>

        <div className="footer-bottom">
          <span>© 2026 Ciao Bella. Australian-owned.</span>
          <a
            href="https://www.instagram.com/ciaobellaphone/"
            target="_blank"
            rel="noopener noreferrer"
            className="footer-social"
            aria-label="Follow Ciao Bella on Instagram"
          >
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <rect x="3" y="3" width="18" height="18" rx="5" ry="5"/>
              <path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/>
              <line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/>
            </svg>
            <span>@ciaobellaphone</span>
          </a>
          <span>30-day money-back · 12-month warranty</span>
        </div>
      </div>
    </footer>
  );
}

// ── FAQ accordion ──
function FaqItem({ q, a, defaultOpen = false }) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className={'faq-item' + (open ? ' open' : '')}>
      <button className="faq-q" onClick={() => setOpen(o => !o)} aria-expanded={open}>
        <span>{q}</span>
        <span className="faq-chev">+</span>
      </button>
      <div className="faq-a">
        <div className="faq-a-inner">{a}</div>
      </div>
    </div>
  );
}

// ── Doodle helper ──
function Doodle({ src, style, className = '' }) {
  return (
    <img
      src={src}
      alt=""
      aria-hidden="true"
      className={'section-doodle ' + className}
      style={style}
    />
  );
}

// ── Phone colour catalog ──
// Three solid shells. Each phone is built from a top half + bottom half.
const PHONE_SHELLS = [
  { id: 'flamingo', name: 'Flamingo', hex: '#F0A8A5' },
  { id: 'buttercream', name: 'Buttercream', hex: '#F4EFE6' },
  { id: 'afterdark', name: 'After Dark', hex: '#1a1a1a' },
];

// Preset colourways — solid top + bottom in the same shell
const PHONE_PRESETS = [
  { id: 'flamingo', name: 'Flamingo', top: 'flamingo', bot: 'flamingo' },
  { id: 'buttercream', name: 'Buttercream', top: 'buttercream', bot: 'buttercream' },
  { id: 'afterdark', name: 'After Dark', top: 'afterdark', bot: 'afterdark' },
];

// All 9 top/bottom combinations and their flavour names.
// slotId is the key used by the product-photo lookup in configurator.jsx
const PHONE_COMBOS = [
  { top: 'flamingo',    bot: 'flamingo',    name: 'Flamingo',      slotId: 'combo-flamingo-flamingo' },
  { top: 'flamingo',    bot: 'buttercream', name: 'Nigiri',        slotId: 'combo-flamingo-buttercream' },
  { top: 'flamingo',    bot: 'afterdark',   name: 'Volcano',       slotId: 'combo-flamingo-afterdark' },
  { top: 'buttercream', bot: 'flamingo',    name: 'Marshmallow',   slotId: 'combo-buttercream-flamingo' },
  { top: 'buttercream', bot: 'buttercream', name: 'Buttercream',   slotId: 'combo-buttercream-buttercream' },
  { top: 'buttercream', bot: 'afterdark',   name: 'Day and Night', slotId: 'combo-buttercream-afterdark' },
  { top: 'afterdark',   bot: 'flamingo',    name: 'Lollipop',      slotId: 'combo-afterdark-flamingo' },
  { top: 'afterdark',   bot: 'buttercream', name: 'Tuxedo',        slotId: 'combo-afterdark-buttercream' },
  { top: 'afterdark',   bot: 'afterdark',   name: 'After Dark',    slotId: 'combo-afterdark-afterdark' },
];

function getCombo(top, bot) {
  return PHONE_COMBOS.find(c => c.top === top && c.bot === bot) || PHONE_COMBOS[0];
}

function getShell(id) { return PHONE_SHELLS.find(s => s.id === id) || PHONE_SHELLS[0]; }

// Backwards-compatible export for any legacy refs
const PHONE_COLOURS = PHONE_PRESETS.map(p => ({
  id: p.id, name: p.name,
  top: getShell(p.top).hex, bot: getShell(p.bot).hex,
}));

// Pricing rules
// `deposit` is the amount charged today to reserve a pre-order;
// the bundle's full `price` is charged when the phone ships.
const PRICING = {
  rrp: 139,
  preorder: 109,
  deposit: 25,
  bundles: {
    1: { price: 109, save: 30 },
    2: { price: 199, save: 79 },
    3: { price: 279, save: 138 },
    4: { price: 371, save: 185 },
    5: { price: 464, save: 231 },
  },
};

// ── ImageSlot — drag-and-drop image placeholder wrapper ──
// Wraps <image-slot> and lets a user drop their own photo onto any spot in the site.
// `id` must be unique across the page so the drop persists.
function ImageSlot({ id, src, alt = '', shape = 'rounded', radius = 12, fit = 'cover', position = '50% 50%', placeholder = 'Drop a photo', style, className }) {
  return (
    <image-slot
      id={id}
      src={src}
      shape={shape}
      radius={radius}
      fit={fit}
      position={position}
      placeholder={placeholder}
      class={className}
      style={{ display: 'block', width: '100%', height: '100%', ...style }}
      aria-label={alt}
    ></image-slot>
  );
}

Object.assign(window, {
  CTA, CTAGhost, Pill, SectionHeading, EyebrowRow,
  AnnouncementBar, Navbar, EmailSignup, Footer, FaqItem, Doodle,
  Logo, Sticker, GutterStickers, CheckerStrip, SectionDivider, CordFrame, Squiggle,
  ImageSlot, goToConfigurator,
  PHONE_SHELLS, PHONE_PRESETS, PHONE_COMBOS, PHONE_COLOURS, PRICING, getShell, getCombo,
});
