// Static info pages — Shipping & Returns, FAQ, Size Guide

const { useState: useStateI, useEffect: useEffectI, useRef: useRefI } = React;

// ─── shared ─────────────────────────────────────────────
function InfoSection({ title, children }) {
  return (
    <div style={{ borderBottom: '1px solid var(--line)', paddingBottom: 36, marginBottom: 36 }}>
      <div className="eyebrow" style={{ marginBottom: 20 }}>{title}</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14, color: 'var(--fg-mute)', lineHeight: 1.75 }}>
        {children}
      </div>
    </div>
  );
}

function FaqRow({ q, a }) {
  const [open, setOpen] = useStateI(false);
  return (
    <div style={{ borderBottom: '1px solid var(--line)' }}>
      <button className="faq-head-btn" onClick={() => setOpen(o => !o)}
              onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
              style={{ width: 'calc(100% + 20px)', padding: '18px 10px', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 24, textAlign: 'left' }}>
        <span style={{ fontFamily: 'var(--sans)', fontSize: 15, color: 'var(--fg)', fontWeight: 500, lineHeight: 1.4 }}>{q}</span>
        <span className="num" style={{ color: 'var(--fg-mute)', flexShrink: 0, marginTop: 2, transition: 'transform 300ms', transform: open ? 'rotate(45deg)' : 'none' }}>+</span>
      </button>
      <div style={{ display: 'grid', gridTemplateRows: open ? '1fr' : '0fr', transition: 'grid-template-rows 380ms cubic-bezier(.2,.6,.2,1)' }}>
        <div style={{ overflow: 'hidden', minHeight: 0 }}>
          <p style={{ paddingBottom: 20, color: 'var(--fg-mute)', lineHeight: 1.75, maxWidth: 580 }}>{a}</p>
        </div>
      </div>
    </div>
  );
}

const DELIVERY_REGIONS = [
  { label: 'EU / UK',          est: '3–7 business days'  },
  { label: 'United States',    est: '5–10 business days' },
  { label: 'Australia',        est: '7–14 business days' },
  { label: 'Rest of world',    est: '7–21 business days' },
];

const FAQ_ITEMS = [
  {
    q: 'Where are products made?',
    a: 'Everything is made to order by our production partner in Portugal, via Fourthwall. Each piece is cut, printed or embroidered, and finished after your order is placed — nothing sits in a warehouse.'
  },
  {
    q: 'How long will my order take?',
    a: 'Production takes 3–5 business days. After dispatch, EU and UK orders typically arrive in 3–7 days; US orders in 5–10 days; international in 7–21 days depending on destination and customs. You\'ll receive tracking when your order ships.'
  },
  {
    q: 'How does sizing work?',
    a: 'Everything is cut oversized with a dropped shoulder — think boxy, relaxed fit. If you want something closer to a standard fit, size down one. Detailed flat measurements are on every product page.'
  },
  {
    q: "What's the difference between Print and Embroidered?",
    a: "Print pieces carry the main Peripheral design large across the back of the garment, with a clean front. Embroidered pieces have a small embroidered Peripheral mark on the chest, with nothing on the back. Same garment, two very different ways to wear it."
  },
  {
    q: 'Can I return or exchange my order?',
    a: 'Because everything is printed or embroidered to order specifically for you, we can\'t accept returns for sizing preference or change of mind. If your order arrives with a quality issue — wrong size, damaged, or misprinted — contact us within 30 days and we\'ll sort it.'
  },
  {
    q: 'What if my item has a defect?',
    a: 'Contact us at music.peripheral@gmail.com within 30 days of delivery with your order number and clear photos of the issue. We\'ll send a replacement at no cost to you.'
  },
  {
    q: 'Do you ship internationally?',
    a: 'Yes, we ship worldwide. International orders may be subject to import duties and customs fees on arrival — these are set by your country and are the buyer\'s responsibility. We don\'t collect them at checkout.'
  },
  {
    q: 'Can I cancel my order?',
    a: 'Orders are sent to production quickly, so cancellation isn\'t always possible. Email us as soon as possible after placing your order and we\'ll do our best. Once production has started, we can\'t halt the order.'
  },
  {
    q: 'Where does the money go?',
    a: 'Everything goes back into the channel — studio time, mastering, equipment, and buying the music I play. Every order keeps the platter spinning. Thank you.'
  },
];

// ─── sub-pages ──────────────────────────────────────────
function ShippingPage() {
  return (
    <>
      <InfoSection title="Production">
        <p>All products are made to order in Portugal. Once you place your order, production takes <strong style={{color:'var(--fg)',fontWeight:500}}>3–5 business days</strong> before your order is dispatched. Production times do not include weekends or public holidays.</p>
      </InfoSection>

      <InfoSection title="Estimated delivery">
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1px', background: 'var(--line)', border: '1px solid var(--line)', borderRadius: 2, overflow: 'hidden' }}>
          <div style={{ background: 'var(--bg-elev)', padding: '10px 16px', fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--fg-mute)' }}>Destination</div>
          <div style={{ background: 'var(--bg-elev)', padding: '10px 16px', fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--fg-mute)' }}>After dispatch</div>
          {DELIVERY_REGIONS.map(r => (
            <React.Fragment key={r.label}>
              <div style={{ background: 'var(--bg)', padding: '14px 16px', fontFamily: 'var(--mono)', fontSize: 12, borderTop: '1px solid var(--line)' }}>{r.label}</div>
              <div style={{ background: 'var(--bg)', padding: '14px 16px', fontFamily: 'var(--mono)', fontSize: 12, borderTop: '1px solid var(--line)', color: 'var(--fg)' }}>{r.est}</div>
            </React.Fragment>
          ))}
        </div>
        <p>Delivery estimates run from dispatch date and exclude customs processing time. We ship via DHL, with handoff to your local carrier for final delivery — tracking may pause briefly during this handoff, which is normal.</p>
        <p>International orders may incur import duties or customs fees on arrival. These are set by your country's customs authority and are the buyer's responsibility. We do not collect them at checkout.</p>
      </InfoSection>

      <InfoSection title="Returns & refunds">
        <p>Because everything is made to order specifically for you, we can't accept returns for sizing preference or change of mind.</p>
        <p>If your order arrives damaged, misprinted, or with a production defect, <strong style={{color:'var(--fg)',fontWeight:500}}>contact us within 30 days of delivery</strong> with your order number and clear photos of the issue. We'll arrange a replacement at no cost to you — the replacement is covered by the production partner.</p>
        <p>Size exchanges are only possible when the production partner shipped the wrong size. Preference-based size changes don't qualify as items are made to your specification.</p>
        <p>Reach us at <a href="mailto:music.peripheral@gmail.com" style={{color:'var(--accent)', textDecoration:'underline', textUnderlineOffset:3}}>music.peripheral@gmail.com</a></p>
      </InfoSection>

      <InfoSection title="Lost or delayed packages">
        <p>If your tracking hasn't updated for several days, give it a little more time — packages sometimes pause during carrier handoffs. If your order appears genuinely lost, contact us with your order number and we'll investigate and arrange a replacement.</p>
        <p>Please allow at least 2 weeks from the dispatch date for domestic orders and 3 weeks for international orders before reporting a lost package.</p>
      </InfoSection>
    </>
  );
}

function FAQPage() {
  return (
    <>
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        {FAQ_ITEMS.map(item => (
          <FaqRow key={item.q} q={item.q} a={item.a}/>
        ))}
      </div>
    </>
  );
}

function SizeTable({ label, rows, hideSleeve = false, fmtVal }) {
  const fmt = fmtVal || (cm => `${cm} cm`);
  return (
    <div style={{ marginBottom: label ? 36 : 0 }}>
      {label && <div style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--fg)', marginBottom: 12 }}>{label}</div>}
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--fg-mute)' }}>
            <th style={{ textAlign: 'left', paddingBottom: 10, fontWeight: 400 }}>Size</th>
            <th style={{ textAlign: 'right', paddingBottom: 10, fontWeight: 400 }}>Chest</th>
            <th style={{ textAlign: 'right', paddingBottom: 10, fontWeight: 400 }}>Length</th>
            {!hideSleeve && <th style={{ textAlign: 'right', paddingBottom: 10, fontWeight: 400 }}>Sleeve</th>}
          </tr>
        </thead>
        <tbody>
          {rows.map(r => (
            <tr key={r.size} style={{ borderTop: '1px solid var(--line)' }}>
              <td style={{ padding: '10px 0', fontFamily: 'var(--mono)', fontSize: 12 }}>{r.size}</td>
              <td style={{ padding: '10px 0', fontFamily: 'var(--mono)', fontSize: 12, textAlign: 'right' }}>{fmt(r.chest)}</td>
              <td style={{ padding: '10px 0', fontFamily: 'var(--mono)', fontSize: 12, textAlign: 'right' }}>{fmt(r.length)}</td>
              {!hideSleeve && <td style={{ padding: '10px 0', fontFamily: 'var(--mono)', fontSize: 12, textAlign: 'right' }}>{fmt(r.sleeve)}</td>}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function GarmentAccordion({ label, rows, hideSleeve = false, garmentKey, initialOpen = false, measureNotes }) {
  const [open, setOpen] = useStateI(initialOpen);
  const [unit, setUnit] = useStateI('cm');
  const fmtVal = (cm) => unit === 'cm' ? `${cm} cm` : `${(cm / 2.54).toFixed(1)}"`;
  const divRef = useRefI(null);
  useEffectI(() => {
    if (initialOpen && divRef.current) {
      const t = setTimeout(() => {
        const y = divRef.current.getBoundingClientRect().top + window.scrollY - 100;
        window.scrollTo({ top: y, behavior: 'smooth' });
      }, 150);
      return () => clearTimeout(t);
    }
  }, []);
  return (
    <div id={garmentKey} ref={divRef} style={{ borderBottom: '1px solid var(--line)' }}>
      <button className="faq-head-btn" onClick={() => setOpen(o => !o)}
              onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
              style={{ width: 'calc(100% + 20px)', padding: '18px 10px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', textAlign: 'left' }}>
        <span style={{ fontFamily: 'var(--sans)', fontSize: 15, color: 'var(--fg)', fontWeight: 500 }}>{label}</span>
        <span className="num" style={{ color: 'var(--fg-mute)', transform: open ? 'rotate(45deg)' : 'none', transition: 'transform 300ms' }}>+</span>
      </button>
      <div style={{ display: 'grid', gridTemplateRows: open ? '1fr' : '0fr', transition: 'grid-template-rows 380ms cubic-bezier(.2,.6,.2,1)' }}>
        <div style={{ overflow: 'hidden', minHeight: 0 }}>
          <div style={{ paddingBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'flex-start', gap: 4, marginBottom: 14 }}>
              {['cm', 'in'].map(u => (
                <button key={u} className={`btn-unit${unit === u ? ' active' : ''}`}
                        onClick={(e) => { e.stopPropagation(); setUnit(u); }}
                        onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
                  {u}
                </button>
              ))}
            </div>
            <SizeTable rows={rows} hideSleeve={hideSleeve} fmtVal={fmtVal}/>
            {measureNotes && (
              <div style={{ marginTop: 20, display: 'flex', flexDirection: 'column', gap: 10, borderTop: '1px solid var(--line)', paddingTop: 16 }}>
                {measureNotes.map((n, i) => (
                  <div key={i} style={{ fontSize: 13, lineHeight: 1.65, color: 'var(--fg-mute)' }}>
                    {n.label && <span style={{ fontWeight: 500, color: 'var(--fg)', fontFamily: 'var(--sans)' }}>{n.label} — </span>}
                    {n.text}
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

const SHARED_DISCLAIMER = { text: 'Measurements are provided by our suppliers and may vary by up to 5 cm. Pro tip: measure a similar item you own at home and compare it with the sizes listed here.' };

const TEE_NOTES = [
  SHARED_DISCLAIMER,
  { text: 'US customers: the EU sizes for this supplier run smaller than US sizes — order a size up.' },
  { label: 'Length', text: 'Place the end of the tape beside the collar at the top of the tee (Highest Point Shoulder). Pull the tape measure to the bottom of the shirt.' },
  { label: 'Width', text: 'Place the end of the tape at the seam under the sleeve and pull the tape measure across the shirt to the seam under the opposite sleeve.' },
  { label: 'Sleeve', text: 'Place one end of the tape at the top of the set-in sleeve, then pull the tape down to the hem of the sleeve.' },
];

const CROP_TOP_NOTES = [
  SHARED_DISCLAIMER,
  { label: 'Length', text: 'Start at the collar\'s edge at the top of the tee (Highest Point Shoulder) and extend the measuring tape to the bottom of the tee.' },
  { label: 'Width', text: 'From the seam beneath one sleeve, stretching the tape across to the seam beneath the opposite sleeve.' },
];

const TANK_NOTES = [
  SHARED_DISCLAIMER,
  { label: 'Length', text: 'Place the end of the tape beside the collar at the top of the tee (Highest Point Shoulder). Pull the tape measure to the bottom of the shirt.' },
  { label: 'Width', text: 'Place the end of the tape at the seam under the sleeve and pull the tape measure across the shirt to the seam under the opposite sleeve.' },
];

const HOODIE_NOTES = [
  SHARED_DISCLAIMER,
  { label: 'Length', text: 'Place the end of a measuring tape beside the collar at the top of the garment (high point shoulder). Pull the tape to the bottom of the item.' },
  { label: 'Width', text: 'Place the end of the tape at the seam under the sleeve and pull the tape measure across to the seam under the opposite sleeve.' },
];

const PULLOVER_NOTES = [
  { text: 'This product runs small — for the best fit, order one size larger than you usually would.' },
  SHARED_DISCLAIMER,
  { label: 'Length', text: 'Place the end of a measuring tape beside the collar at the top of the garment (high point shoulder). Pull the tape to the bottom of the item.' },
  { label: 'Width', text: 'Place the end of the tape at the seam under the sleeve and pull the tape measure across to the seam under the opposite sleeve.' },
  { label: 'Sleeve', text: 'Place one end of the tape at the top of the set-in sleeve, then pull the tape down to the hem of the sleeve.' },
];

function SizeGuidePage() {
  const openKey = window.location.hash.slice(1);
  return (
    <>
      <InfoSection title="How to measure">
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 4 }}>
          {[
            { k: 'Length', v: 'From the collar\'s edge at the top of the garment (Highest Point Shoulder) to the bottom hem.' },
            { k: 'Chest / Width', v: 'From the seam beneath one sleeve, across to the seam beneath the opposite sleeve. This is a flat (half-chest) measurement.' },
            { k: 'Sleeve', v: 'From the shoulder seam to the end of the cuff.' },
          ].map(({ k, v }) => (
            <div key={k} style={{ padding: '16px', background: 'var(--bg-elev)', borderRadius: 2 }}>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 8 }}>{k}</div>
              <p style={{ fontSize: 13, lineHeight: 1.6, color: 'var(--fg-mute)', margin: 0 }}>{v}</p>
            </div>
          ))}
        </div>
      </InfoSection>

      <InfoSection title="Fit">
        <p>All garments are cut with an oversized, boxy silhouette and a dropped shoulder. If you prefer a closer fit, size down one. When in doubt, size up. The relaxed look is intentional.</p>
      </InfoSection>

      <div>
        <GarmentAccordion garmentKey="tee"      label="Baggy Tee"  rows={SIZES.tee}                initialOpen={openKey === 'tee'}      measureNotes={TEE_NOTES}/>
        <GarmentAccordion garmentKey="cropTop"  label="Crop Top"   rows={SIZES.cropTop} hideSleeve initialOpen={openKey === 'cropTop'}  measureNotes={CROP_TOP_NOTES}/>
        <GarmentAccordion garmentKey="tank"     label="Tank Top"   rows={SIZES.tank}    hideSleeve initialOpen={openKey === 'tank'}     measureNotes={TANK_NOTES}/>
        <GarmentAccordion garmentKey="hoodie"   label="Hoodie"     rows={SIZES.hoodie}  hideSleeve initialOpen={openKey === 'hoodie'}   measureNotes={HOODIE_NOTES}/>
        <GarmentAccordion garmentKey="pullover" label="Pull-over"  rows={SIZES.pullover}           initialOpen={openKey === 'pullover'} measureNotes={PULLOVER_NOTES}/>
      </div>
    </>
  );
}

// ─── main export ────────────────────────────────────────
function InfoPage({ id, navigate }) {
  const defaultLabels = {
    'shipping':   'Shipping & Returns',
    'faq':        'FAQ',
    'size-guide': 'Size Guide',
    'contact':    'Contact',
    'privacy':    'Privacy Policy',
    'terms':      'Terms',
  };
  const params = new URLSearchParams(window.location.search);
  const urlSent  = id === 'contact' && params.get('sent')  === '1';
  const urlError = id === 'contact' && params.get('error') === '1';
  const [contactSuccess, setContactSuccess] = useStateI(urlSent);
  const [contactError,   setContactError]   = useStateI(urlError);
  useEffectI(() => {
    if (urlSent || urlError) {
      history.replaceState(null, '', '/merch/contact');
      window.scrollTo(0, 0);
    }
  }, []);
  const label = defaultLabels[id] || 'Info';

  if (id === 'contact' && contactSuccess) {
    return (
      <main style={{ paddingTop: 120, paddingBottom: 80, minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ maxWidth: 520, width: '100%', padding: '0 24px', textAlign: 'center' }}>
          <div className="eyebrow" style={{ marginBottom: 20 }}>Message sent</div>
          <h1 className="h-1" style={{ marginBottom: 24, fontSize: 'clamp(32px, 4.5vw, 54px)' }}>Thanks for<br/>reaching out.</h1>
          <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 40 }}>
            We'll get back to you within 1–2 business days.
          </p>
          <div style={{ maxWidth: 280, margin: '0 auto' }}>
            <button className="btn-primary" onClick={() => navigate({ name: 'home' }, '/merch')}
              onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
              Back to shop
            </button>
          </div>
        </div>
      </main>
    );
  }

  return (
    <main style={{ paddingTop: 80, minHeight: '70vh' }}>
      <div style={{ maxWidth: 740, margin: '0 auto', padding: '32px var(--pad) 80px' }}>
        <div className="pdp-crumb" style={{ marginBottom: 40 }}>
          <a onClick={() => navigate({ name: 'home' }, '/merch')}
             onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>Shop</a>
          <span className="sep">/</span>
          <span>{label}</span>
        </div>
        <h1 className="h-1" style={{ marginBottom: 48 }}>{label}</h1>

        {id === 'shipping'   && <ShippingPage/>}
        {id === 'faq'        && <FAQPage/>}
        {id === 'size-guide' && <SizeGuidePage/>}
        {id === 'contact'    && <ContactPage showError={contactError}/>}
        {id === 'privacy'    && <PrivacyPage/>}
        {id === 'terms'      && <TermsPage/>}
      </div>
    </main>
  );
}

function ContactPage({ showError }) {
  const [files, setFiles] = useStateI([]);
  const [fileError, setFileError] = useStateI('');
  const [uploadHover, setUploadHover] = useStateI(false);
  const [removeHover, setRemoveHover] = useStateI(null);
  const [faqHover, setFaqHover] = useStateI(false);
  const fileInputRef = useRefI(null);
  const fileErrTimer = useRefI(null);
  const MAX_FILES = 3;

  const textOn  = () => document.body.classList.add('cursor-text-mode');
  const textOff = () => { document.body.classList.remove('cursor-text-mode'); onCursor('default'); };

  const showFileError = msg => {
    setFileError(msg);
    clearTimeout(fileErrTimer.current);
    fileErrTimer.current = setTimeout(() => setFileError(''), 3000);
  };

  const handleFileChange = e => {
    const existing = new Set(files.map(f => f.name));
    const all = Array.from(e.target.files);
    const dupes = all.filter(f => existing.has(f.name));
    const incoming = all.filter(f => !existing.has(f.name));
    const merged = [...files, ...incoming].slice(0, MAX_FILES);
    if (dupes.length > 0) showFileError(`Already added: ${dupes.map(f => f.name).join(', ')}`);
    setFiles(merged);
    const dt = new DataTransfer();
    merged.forEach(f => dt.items.add(f));
    fileInputRef.current.files = dt.files;
  };

  const removeFile = idx => {
    const updated = files.filter((_, i) => i !== idx);
    setFiles(updated);
    const dt = new DataTransfer();
    updated.forEach(f => dt.items.add(f));
    if (fileInputRef.current) fileInputRef.current.files = dt.files;
  };

  const lbl = {
    display: 'block',
    fontFamily: 'var(--mono)',
    fontSize: 10,
    letterSpacing: '0.14em',
    textTransform: 'uppercase',
    color: 'var(--fg-mute)',
    marginBottom: 8,
  };

  const inp = {
    width: '100%',
    fontFamily: 'var(--sans)',
    fontSize: 14,
    color: 'var(--fg)',
    background: 'var(--bg-elev)',
    border: '1px solid var(--line)',
    borderRadius: 6,
    padding: '12px 14px',
    outline: 'none',
    boxSizing: 'border-box',
  };

  return (
    <form action="/api/contact" method="POST" encType="multipart/form-data"
      style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
      {showError && (
        <div style={{ background: 'color-mix(in oklab, #c0392b 12%, var(--bg))', border: '1px solid color-mix(in oklab, #c0392b 30%, transparent)', borderRadius: 6, padding: '12px 16px', color: 'var(--fg)', fontSize: 14, lineHeight: 1.6 }}>
          Something went wrong sending your message. Please try again or email <a href="mailto:music.peripheral@gmail.com" style={{ color: 'var(--accent)' }}>music.peripheral@gmail.com</a> directly.
        </div>
      )}
      <div style={{ color: 'var(--fg-mute)', lineHeight: 1.75 }}>
        <p style={{ margin: '0 0 8px' }}>Fill in the form below and we'll get back to you within 1–2 business days.</p>
        <p style={{ margin: 0 }}>
          For common questions, check the{' '}
          <a href="/merch/faq" style={{ color: faqHover ? 'color-mix(in oklab, var(--accent) 65%, transparent)' : 'var(--accent)', textDecoration: 'underline', transition: 'color 0.15s' }}
            onMouseEnter={() => { setFaqHover(true); onCursor('hover'); }} onMouseLeave={() => { setFaqHover(false); onCursor('default'); }}>FAQ</a>
          {' '}first. You might find an instant answer.
        </p>
      </div>

      <div>
        <label style={lbl}>Name <span style={{ color: 'var(--accent)' }}>*</span></label>
        <input name="name" type="text" required data-form-inp style={inp}
          onMouseEnter={textOn} onMouseLeave={textOff} onFocus={textOn} onBlur={textOff} />
      </div>

      <div>
        <label style={lbl}>Email <span style={{ color: 'var(--accent)' }}>*</span></label>
        <input name="email" type="email" required data-form-inp style={inp}
          onMouseEnter={textOn} onMouseLeave={textOff} onFocus={textOn} onBlur={textOff} />
      </div>

      <div>
        <label style={lbl}>Order number</label>
        <input name="order_number" type="text" data-form-inp style={inp}
          onMouseEnter={textOn} onMouseLeave={textOff} onFocus={textOn} onBlur={textOff} />
      </div>

      <div>
        <label style={lbl}>Message <span style={{ color: 'var(--accent)' }}>*</span></label>
        <textarea name="message" required minLength={20} rows={5} data-form-inp
          style={{ ...inp, resize: 'vertical', lineHeight: 1.6 }}
          onMouseEnter={textOn} onMouseLeave={textOff} onFocus={textOn} onBlur={textOff} />
      </div>

      <div>
        <label style={lbl}>
          Photos
          {files.length > 0 && <span style={{ marginLeft: 6, fontWeight: 400 }}>{files.length}/{MAX_FILES}</span>}
        </label>
        <input ref={fileInputRef} type="file" name="attachment" multiple accept="image/jpeg,image/png,.jpg,.jpeg,.png"
          style={{ display: 'none' }} id="contact-file-input" onChange={handleFileChange} />
        {files.length < MAX_FILES && (
          <label htmlFor="contact-file-input"
            style={{ ...inp, display: 'flex', alignItems: 'center', gap: 10, cursor: 'none', color: 'var(--fg-mute)', background: uploadHover ? 'var(--bg-elev-2)' : 'var(--bg-elev)', transition: 'background 0.15s' }}
            onMouseEnter={() => { setUploadHover(true); onCursor('hover'); }}
            onMouseLeave={() => { setUploadHover(false); onCursor('default'); }}>
            <svg width="15" height="15" viewBox="0 0 15 15" fill="none" style={{ flexShrink: 0 }}>
              <path d="M7.5 1v9M7.5 1L4 4.5M7.5 1L11 4.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
              <path d="M1 11.5v1.5a1 1 0 001 1h11a1 1 0 001-1v-1.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/>
            </svg>
            {files.length === 0 ? 'Choose photos' : 'Add another'}
          </label>
        )}
        {files.length > 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: files.length < MAX_FILES ? 8 : 0 }}>
            {files.map((f, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, background: 'var(--bg-elev-2)', borderRadius: 6, padding: '8px 12px', fontSize: 13 }}>
                <svg width="13" height="13" viewBox="0 0 15 15" fill="none" style={{ flexShrink: 0, color: 'var(--fg-mute)' }}>
                  <path d="M3 2h6.5L12 4.5V13H3V2z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/>
                  <path d="M9 2v3h3" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/>
                </svg>
                <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--fg)' }}>{f.name}</span>
                <button type="button" onClick={() => removeFile(i)}
                  onMouseEnter={() => { setRemoveHover(i); onCursor('hover'); }}
                  onMouseLeave={() => { setRemoveHover(null); onCursor('default'); }}
                  style={{ flexShrink: 0, background: removeHover === i ? 'color-mix(in oklab, var(--fg) 12%, transparent)' : 'none', border: 'none', color: removeHover === i ? 'var(--fg)' : 'var(--fg-mute)', cursor: 'none', width: 22, height: 22, borderRadius: '50%', lineHeight: 1, fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'background 0.15s, color 0.15s' }}>
                  ×
                </button>
              </div>
            ))}
          </div>
        )}
        {fileError && (
          <p style={{ margin: '8px 0 0', fontSize: 12, color: 'var(--accent)', fontFamily: 'var(--mono)' }}>{fileError}</p>
        )}
      </div>

      <div>
        <button type="submit" className="btn-primary"
          style={{ width: 'auto', display: 'inline-flex' }}
          onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
          Send message
        </button>
      </div>
    </form>
  );
}

function PrivacyPage() {
  return (
    <div>
      <InfoSection title="What I collect">
        <p>When you contact me through this site, I collect your name, email address, and the contents of your message. If you connect via Patreon, I receive your Patreon email address and membership tier. No other personal data is collected.</p>
      </InfoSection>
      <InfoSection title="Why I collect it">
        <p>Contact form submissions are used solely to reply to your message. Patreon data is used to verify your membership tier and apply the corresponding discount code. Neither is used for marketing without your consent.</p>
      </InfoSection>
      <InfoSection title="Analytics">
        <p>This site uses Cloudflare Web Analytics, which is cookieless and collects no personal data. I receive only anonymous, aggregated statistics such as page views and approximate geography.</p>
      </InfoSection>
      <InfoSection title="Cookies">
        <p>No tracking or marketing cookies are set. A temporary session cookie (<code>patreon_state</code>) is used during Patreon login for security purposes only and is cleared immediately after login completes.</p>
      </InfoSection>
      <InfoSection title="Who processes your data">
        <p><strong>Fourthwall</strong> — handles all order and payment data. Their privacy policy applies to purchases made through this store.</p>
        <p style={{marginTop:12}}><strong>Resend</strong> — used to deliver contact form emails. Messages are not retained beyond delivery.</p>
        <p style={{marginTop:12}}><strong>Patreon</strong> — their privacy policy applies to your Patreon account and the OAuth connection.</p>
        <p style={{marginTop:12}}><strong>Cloudflare</strong> — hosts this site and processes anonymous analytics.</p>
      </InfoSection>
      <InfoSection title="Data retention">
        <p>Contact form messages are kept until the conversation is resolved. Patreon tier data is stored only in your browser's local storage and can be cleared at any time by clearing your browser data.</p>
      </InfoSection>
      <InfoSection title="Your rights">
        <p>Under GDPR, you have the right to access, correct, or delete any personal data I hold about you. To make a request, email <a href="mailto:music.peripheral@gmail.com" style={{color:'var(--accent)'}}>music.peripheral@gmail.com</a>.</p>
      </InfoSection>
      <InfoSection title="Last updated">
        <p>June 2026</p>
      </InfoSection>
    </div>
  );
}

function TermsPage() {
  return (
    <div>
      <InfoSection title="Products">
        <p>All products are made to order through Fourthwall. By placing an order, you agree to Fourthwall's terms of service, fulfilment policies, and returns procedures.</p>
      </InfoSection>
      <InfoSection title="Returns & refunds">
        <p>Products can be returned within 30 days of delivery in original, unused condition. To initiate a return, email <a href="mailto:music.peripheral@gmail.com" style={{color:'var(--accent)'}}>music.peripheral@gmail.com</a> with your order number.</p>
      </InfoSection>
      <InfoSection title="Intellectual property">
        <p>All designs, artwork, and brand identity on this site are original works owned by Peripheral. Reproduction or commercial use without permission is not permitted.</p>
      </InfoSection>
      <InfoSection title="Limitations">
        <p>Peripheral is an independent personal brand. Products are sold as-is, consistent with Fourthwall's quality standards. I am not liable for delays or issues caused by Fourthwall's fulfilment or carrier services.</p>
      </InfoSection>
      <InfoSection title="Governing law">
        <p>These terms are governed by Dutch law. For disputes, the courts of the Netherlands have jurisdiction.</p>
      </InfoSection>
      <InfoSection title="Contact">
        <p><a href="mailto:music.peripheral@gmail.com" style={{color:'var(--accent)'}}>music.peripheral@gmail.com</a></p>
      </InfoSection>
      <InfoSection title="Last updated">
        <p>June 2026</p>
      </InfoSection>
    </div>
  );
}

function AboutComingSoon({ navigate }) {
  return (
    <main style={{ paddingTop: 80, minHeight: '80vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div style={{ textAlign: 'center', padding: '0 var(--pad)' }}>
        <h1 className="h-1" style={{ marginBottom: 16 }}>Coming Soon</h1>
        <p style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--fg-mute)', marginBottom: 40 }}>
          Turns out writing about yourself is harder than you'd think.
        </p>
        <a onClick={() => navigate({ name: 'home' }, '/merch')}
           onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
           style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', textDecoration: 'underline', textUnderlineOffset: 4 }}>
          Back to shop
        </a>
      </div>
    </main>
  );
}

Object.assign(window, { InfoPage, AboutComingSoon });
