// femme-app.jsx — Lissé laser landing, Femme-style layout
// All sections in one file (kept ≤500 lines).

const F_PALETTES = {
  cream: { label: 'Cream & Cocoa', swatch: ['#F5EFE6', '#3D2817', '#8B6B4F'],
    vars: { '--bg': '#F5EFE6', '--bg-2': '#ECE3D4', '--ink': '#3D2817', '--ink-soft': '#6B5440',
      '--accent': '#8B6B4F', '--line': 'rgba(61,40,23,0.14)', '--line-strong': 'rgba(61,40,23,0.28)',
      '--paper': '#FBF7EF', '--shadow': '0 30px 60px -30px rgba(61,40,23,0.25)' } },
  sand: { label: 'Sand & Olive', swatch: ['#F0EAE0', '#3F4429', '#7A7256'],
    vars: { '--bg': '#F0EAE0', '--bg-2': '#E3DBCC', '--ink': '#3F4429', '--ink-soft': '#6B6849',
      '--accent': '#7A7256', '--line': 'rgba(63,68,41,0.14)', '--line-strong': 'rgba(63,68,41,0.28)',
      '--paper': '#F7F2E9', '--shadow': '0 30px 60px -30px rgba(63,68,41,0.22)' } },
  blush: { label: 'Blush & Plum', swatch: ['#F4E8E5', '#3A1F2B', '#9A6B73'],
    vars: { '--bg': '#F4E8E5', '--bg-2': '#EAD8D2', '--ink': '#3A1F2B', '--ink-soft': '#6E5158',
      '--accent': '#9A6B73', '--line': 'rgba(58,31,43,0.14)', '--line-strong': 'rgba(58,31,43,0.26)',
      '--paper': '#FAF1EE', '--shadow': '0 30px 60px -30px rgba(58,31,43,0.22)' } },
  ivory: { label: 'Ivory & Ink', swatch: ['#F0EFEB', '#1B1B1A', '#5C5C58'],
    vars: { '--bg': '#F0EFEB', '--bg-2': '#E1DFD9', '--ink': '#1B1B1A', '--ink-soft': '#56564F',
      '--accent': '#5C5C58', '--line': 'rgba(27,27,26,0.12)', '--line-strong': 'rgba(27,27,26,0.25)',
      '--paper': '#F8F7F3', '--shadow': '0 30px 60px -30px rgba(27,27,26,0.2)' } }
};

const F_FONTS = {
  cormorant: { label: 'Cormorant + Manrope',
    display: "'Cormorant Garamond', Georgia, serif", body: "'Manrope', ui-sans-serif, system-ui, sans-serif" },
  bodoni: { label: 'Bodoni + Outfit',
    display: "'Bodoni Moda', Georgia, serif", body: "'Outfit', ui-sans-serif, system-ui, sans-serif" },
  italiana: { label: 'Italiana + Jakarta',
    display: "'Italiana', Georgia, serif", body: "'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif" }
};

const F_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "cream",
  "fonts": "cormorant"
} /*EDITMODE-END*/;

// ─────── Nav ───────
function FNav() {
  React.useEffect(() => {
    const onScroll = () => document.querySelector('.nav')?.classList.toggle('scrolled', window.scrollY > 24);
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const [menuOpen, setMenuOpen] = React.useState(false);
  React.useEffect(() => {
    document.body.style.overflow = menuOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [menuOpen]);
  const links = [
    ['#services', 'Services'], ['#calculator', 'Pricing'], ['#why', 'About'],
    ['#results', 'Results'], ['#testimonials', 'Reviews'], ['#contact', 'Contact'],
  ];
  return (
    <nav className="nav">
      <a href="#" className="logo"><IconLumiere size={24} sw={1.3} /> <span>Lissé</span></a>
      <ul className="nav-menu">
        <li className="nav-item"><a href="#services">Services</a></li>
        <li className="nav-item"><a href="#calculator">Pricing</a></li>
        <li className="nav-item"><a href="#why">About</a></li>
        <li className="nav-item"><a href="#results">Results</a></li>
        <li className="nav-item"><a href="#testimonials">Reviews</a></li>
      </ul>
      <div className="nav-right">
        <a href="#book" className="nav-cta">Book &amp; Glow</a>
        <button
          type="button"
          className={`nav-burger ${menuOpen ? 'on' : ''}`}
          aria-label="Menu"
          aria-expanded={menuOpen}
          onClick={() => setMenuOpen(o => !o)}
        >
          <span></span><span></span>
        </button>
      </div>
      <div className={`nav-drawer ${menuOpen ? 'on' : ''}`} onClick={() => setMenuOpen(false)}>
        <div className="nav-drawer-panel" onClick={(e) => e.stopPropagation()}>
          <button type="button" className="nav-drawer-close" aria-label="Close menu" onClick={() => setMenuOpen(false)}>×</button>
          <ul>
            {links.map((lnk) => (
              <li key={lnk[0]}><a href={lnk[0]} onClick={() => setMenuOpen(false)}>{lnk[1]}</a></li>
            ))}
          </ul>
          <a href="#book" className="btn nav-drawer-cta" onClick={() => setMenuOpen(false)}>Book &amp; Glow</a>
        </div>
      </div>
    </nav>);

}

// ─────── Rotating circle button (Femme signature) ───────
function RotateButton({ children, label = 'Book · Today · Now · ', href = '#contact' }) {
  const ref = useMagnet(0.15);
  return (
    <a href={href} className="btn-rotate">
      <span ref={ref} className="ring">
        <IconArrowUpRight size={20} sw={1.5} />
        <svg className="rotating-text" viewBox="0 0 60 60">
          <defs>
            <path id="rt-circle" d="M 30,30 m -22,0 a 22,22 0 1,1 44,0 a 22,22 0 1,1 -44,0" />
          </defs>
          <text>
            <textPath href="#rt-circle">{label.repeat(3)}</textPath>
          </text>
        </svg>
      </span>
      {children}
    </a>);

}

// ─────── HERO (Femme-style with marquee top, welcome bottom-left, pill grid bottom-right) ───────
function FHero() {
  return (
    <section className="hero">
      <div className="hero-marquee" aria-hidden="true">
        <div className="hero-marquee-track">
          {Array.from({ length: 8 }).map((_, i) =>
          <span key={i} className="hero-marquee-item">
              {['Laser hair removal', 'Smoother skin', 'Now booking', 'Free consultation'][i % 4]} <span className="dot">✦</span>{" "}
            </span>
          )}
        </div>
      </div>
      <div className="hero-bg">
        <HeroSlider />
      </div>
      <div className="hero-bottom">
        <div className="hero-welcome">
          <span className="hero-welcome-eyebrow">— Welcome to Lissé:</span>
          <p className="hero-welcome-body">
            We are more than a laser studio — a quiet haven for those who seek smoother skin, careful hands, and a treatment unhurried by anyone but you.
          </p>
        </div>
        <div className="hero-pills">
          <a href="#why" className="hero-pill">Expert advice</a>
          <a href="#results" className="hero-pill">Gallery</a>
          <a href="#services" className="hero-pill">Pricing</a>
          <a href="#testimonials" className="hero-pill">Reviews</a>
          <a href="#services" className="hero-pill">Services</a>
          <a href="#contact" className="hero-pill">Support</a>
        </div>
      </div>
    </section>);

}

// ─────── Hero auto-cross-fade slider ───────
function HeroSlider() {
  const slides = [
    'images/o/new-face.jpg',
    'images/o/fan-pose.jpg',
  ];
  const [active, setActive] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setActive(a => (a + 1) % slides.length), 8000);
    return () => clearInterval(id);
  }, []);
  return (
    <div className="hero-slider">
      {slides.map((src, i) => (
        <img
          key={src}
          src={src}
          alt=""
          className={"hero-slide" + (i === active ? " on" : "")}
          aria-hidden={i === active ? "false" : "true"}
        />
      ))}
    </div>
  );
}

// ─────── Statement (centered sticky heading + chaotic floating cards) ───────
function FStatement() {
  const benefits = [
  { n: '01', t: 'Lasting smoothness', body: '80–95% reduction after a six-session course.',
    meta: 'Up to 95%', icon: IconSparkle,
    pos: { top: '3%', left: '0%' }, parallax: 0.06, rotate: -5, fromX: -40, fromY: 80 },
  { n: '02', t: 'Kinder to your skin', body: 'No ingrown hairs, no nicks, no razor rash.',
    meta: 'Zero ingrowns', icon: IconLeaf,
    pos: { top: '12%', right: '10%' }, parallax: -0.08, rotate: 6, fromX: 40, fromY: 80 },
  { n: '03', t: 'Calibrated to you', body: 'Skin tone and hair cycle assessed at every visit.',
    meta: 'Tuned each visit', icon: IconCompass,
    pos: { top: '36%', left: '12%' }, parallax: 0.09, rotate: 4, fromX: -30, fromY: 100 },
  { n: '04', t: 'Sapphire cooling', body: 'Continuous cooling keeps sensitive zones quietly comfortable.',
    meta: 'Numbing included', icon: IconDrop,
    pos: { top: '50%', right: '0%' }, parallax: -0.07, rotate: -3, fromX: 50, fromY: 90 },
  { n: '05', t: 'A quiet hour', body: 'Eight-minute sessions in unhurried rooms.',
    meta: 'No rush, ever', icon: IconClock,
    pos: { top: '72%', left: '1%' }, parallax: 0.05, rotate: -4, fromX: -20, fromY: 110 },
  { n: '06', t: 'Considered safety', body: 'BTEC-Level-4 practitioners, calibrated monthly.',
    meta: 'BTEC-Level-4', icon: IconShield,
    pos: { top: '84%', right: '11%' }, parallax: -0.06, rotate: 5, fromX: 30, fromY: 80 }];

  return (
    <section id="statement" className="statement">
      <div className="statement-cards-fall">
        {benefits.map((b, i) => <BenefitCard key={b.n} {...b} index={i} />)}
      </div>
      <div className="statement-middle">
        <div className="statement-sticky">
          <span className="eyebrow">— Considered care</span>
          <h2 className="h-display">
            Laser care, quietly <span className="ny">calibrated</span> to your unique skin and the rhythm of life you'd rather be living.
          </h2>
          <div className="statement-thumbs">
            <div className="statement-thumb-fan">
              <div className="statement-thumb"><img src="images/o/new-face.jpg" alt="" /></div>
              <div className="statement-thumb"><img src="images/o/new-legs.jpg" alt="" /></div>
              <div className="statement-thumb"><img src="images/o/new-armpit.jpg" alt="" /></div>
            </div>
            <span className="statement-thumb-count">Trusted by <strong>2,000+</strong> devoted clients</span>
          </div>
        </div>
      </div>
    </section>);

}

function BenefitCard({ n, t, body, meta, icon: Icon, index, parallax, rotate, fromX, fromY, pos }) {
  const [inRef, inView] = useInView({ threshold: 0.15 });
  const parRef = useParallax(parallax);
  const setRef = (el) => {inRef.current = el;parRef.current = el;};
  return (
    <div ref={setRef} className="benefit-wrap" style={pos}>
      <article
        className={`benefit ${inView ? 'in' : ''}`}
        style={{
          '--enter-rot': `${rotate}deg`,
          '--enter-x': `${fromX}px`,
          '--enter-y': `${fromY}px`
        }}>
        
        <div className="benefit-inner">
          <span className="benefit-icon" aria-hidden="true"><Icon size={20} sw={1.4} /></span>
          <h3 className="benefit-t h-display">{t}</h3>
          <p className="benefit-body">{body}</p>
          <span className="benefit-meta">{meta}</span>
        </div>
      </article>
    </div>);

}

// ─────── Tabbed services ───────
const F_SERVICES = [
{ n: '01', t: 'Face Laser', body: "Upper lip, chin, jawline, full face. Quiet sessions on a 4–6 week rhythm, calibrated to your skin tone each visit.",
  img: 'images/laser-face.jpeg', price: 35 },
{ n: '02', t: 'Body Smooth', body: "Underarms, arms, legs — our most-requested course. Six sessions delivers 80–95% permanent reduction.",
  img: 'images/treatment-session.jpeg', price: 65 },
{ n: '03', t: 'Bikini & Brazilian', body: "Discreet, considered care. Numbing cream and sapphire cooling included. The most popular zone we treat.",
  img: 'images/o/new-legs.jpg', price: 85 },
{ n: '04', t: 'Concierge Full-Body', body: "Whole-body course across the year, with concierge scheduling, dedicated practitioner, and complimentary aftercare.",
  img: 'images/laser-device.jpeg', price: 380 }];


function FServices() {
  const [tab, setTab] = React.useState(0);
  return (
    <section id="services" className="services">
      <div className="container">
        <div className="services-head">
          <div>
            <span className="eyebrow">Laser services</span>
            <h2 className="h-display">
              Four <span className="i">considered</span> ways to begin a course.
            </h2>
          </div>
          <a href="#book" className="btn">Book a service</a>
        </div>
        <div className="services-row">
          <div className="services-tabs">
            {F_SERVICES.map((s, i) =>
            <div key={i} className={`tab ${tab === i ? 'on' : ''}`} onClick={() => setTab(i)}>
                <div className="tab-n">{s.n}</div>
                <div className="tab-main">
                  <div className="tab-title h-display">{s.t}</div>
                  <div className="tab-body">{s.body}</div>
                </div>
                <div className="tab-arrow"><IconArrowUpRight size={16} sw={1.5} /></div>
              </div>
            )}
          </div>
          <div className="services-img">
            {F_SERVICES.map((s, i) =>
            <div key={i} className={`services-img-card ${tab === i ? 'on' : ''}`}>
                <img src={s.img} alt="" />
                <span className="price-tag"><small>from</small>${s.price}</span>
              </div>
            )}
          </div>
        </div>
      </div>
    </section>);

}

// ─────── Word marquee (Femme signature) ───────
function FWordMarquee() {
  const words = ['Quietly', 'Smooth', 'Confident', 'Refined', 'Magnetic', 'Effortless'];
  const dup = [...words, ...words];
  return (
    <div className="word-marquee">
      <div className="word-marquee-track">
        {dup.map((w, i) =>
        <span key={i} className="word-marquee-item">{w}</span>
        )}
      </div>
    </div>);

}

// ─────── Service cards ───────
// ─────── Build your course (calculator) ───────
const F_AREAS = [
  { id: 'lip',     name: 'Upper lip',     price: 35,  zone: 'Face' },
  { id: 'chin',    name: 'Chin',          price: 45,  zone: 'Face' },
  { id: 'neck',    name: 'Neck',          price: 55,  zone: 'Face' },
  { id: 'side',    name: 'Sideburns',     price: 40,  zone: 'Face' },
  { id: 'face',    name: 'Full face',     price: 95,  zone: 'Face' },
  { id: 'pits',    name: 'Underarms',     price: 75,  zone: 'Body' },
  { id: 'hand',    name: 'Hands & fingers', price: 45, zone: 'Body' },
  { id: 'harm',    name: 'Half arm',      price: 110, zone: 'Body' },
  { id: 'farm',    name: 'Full arm',      price: 160, zone: 'Body' },
  { id: 'shoul',   name: 'Shoulders',     price: 110, zone: 'Body' },
  { id: 'chest',   name: 'Chest',         price: 180, zone: 'Body' },
  { id: 'tummy',   name: 'Stomach',       price: 90,  zone: 'Body' },
  { id: 'back',    name: 'Back',          price: 220, zone: 'Body' },
  { id: 'hleg',    name: 'Half leg',      price: 145, zone: 'Body' },
  { id: 'fleg',    name: 'Full leg',      price: 240, zone: 'Body' },
  { id: 'feet',    name: 'Feet & toes',   price: 45,  zone: 'Body' },
  { id: 'bikini',  name: 'Bikini line',   price: 95,  zone: 'Intimate' },
  { id: 'brazil',  name: 'Brazilian',     price: 140, zone: 'Intimate' },
  { id: 'butt',    name: 'Buttocks',      price: 120, zone: 'Intimate' },
];
const F_SESSIONS = [
  { count: 4, label: 'Touch-up', discount: 0,    note: 'For maintenance' },
  { count: 6, label: 'Full course', discount: 0.15, note: 'Recommended', recommended: true },
  { count: 8, label: 'Concierge', discount: 0.20, note: 'For dense growth' },
];

function FBookingModal({ onClose, items, sessions, total }) {
  const [sent, setSent] = React.useState(false);
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, []);
  const submit = (e) => { e.preventDefault(); setSent(true); };
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" role="dialog" aria-modal="true" onClick={(e) => e.stopPropagation()}>
        <button type="button" className="modal-close" onClick={onClose} aria-label="Close">×</button>
        {sent ? (
          <div className="modal-done">
            <span className="eyebrow">— Reservation received</span>
            <h3 className="modal-h">We'll be in touch <span className="i">within the hour.</span></h3>
            <p className="modal-done-p">A Lissé practitioner will confirm your consultation and course, and answer anything you'd like to know first.</p>
            <button type="button" className="btn" onClick={onClose}>Close</button>
          </div>
        ) : (
          <>
            <span className="eyebrow">— Reserve your course</span>
            <h3 className="modal-h">Book my <span className="i">course.</span></h3>
            <div className="modal-summary">
              <div className="modal-summary-row"><span>Areas</span><span>{items.map(a => a.name).join(', ') || '—'}</span></div>
              <div className="modal-summary-row"><span>Sessions</span><span>{sessions}</span></div>
              <div className="modal-summary-row modal-summary-total"><span>Estimated course</span><span>${total.toLocaleString()}</span></div>
            </div>
            <form className="modal-form" onSubmit={submit}>
              <label className="modal-field"><span>Full name</span><input type="text" required placeholder="Your name" /></label>
              <label className="modal-field"><span>Email</span><input type="email" required placeholder="your@email.com" /></label>
              <label className="modal-field"><span>Phone</span><input type="tel" placeholder="+44 …" /></label>
              <label className="modal-field"><span>Preferred date</span><input type="date" className="date-input" min={new Date().toISOString().split('T')[0]} /></label>
              <label className="modal-field modal-field--full"><span>Anything we should know?</span><textarea rows="2" placeholder="Optional — sensitivities, questions, timing"></textarea></label>
              <button type="submit" className="btn modal-submit">Confirm reservation</button>
            </form>
          </>
        )}
      </div>
    </div>
  );
}

function FCalculator() {
  const [selected, setSelected] = React.useState(['pits', 'bikini']);
  const [sessions, setSessions] = React.useState(6);
  const [activeZone, setActiveZone] = React.useState('Body');
  const [booking, setBooking] = React.useState(false);

  const toggle = (id) => setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);

  const session = sessions >= 8
    ? { label: 'Concierge', discount: 0.20, note: 'For dense or stubborn growth.' }
    : sessions >= 6
    ? { label: 'Full course', discount: 0.15, note: 'Recommended for most clients.' }
    : { label: 'Touch-up', discount: 0, note: 'For maintenance between courses.' };
  const sessMin = 1, sessMax = 10;
  const sessPct = ((sessions - sessMin) / (sessMax - sessMin)) * 100;
  const items = F_AREAS.filter(a => selected.includes(a.id));
  const perSession = items.reduce((sum, a) => sum + a.price, 0);
  const subtotal = perSession * sessions;
  const discount = subtotal * session.discount;
  const total = subtotal - discount;
  const animatedTotal = useSmoothNumber(total, 450);

  return (
    <section id="calculator" className="calc">
      <div className="container">
        <div className="calc-head">
          <div>
            <span className="eyebrow">— Build your course</span>
            <h2 className="h-display">
              Calculate your <span className="i">quietly trusted</span> course.
            </h2>
          </div>
          <p className="calc-blurb">
            Pick the areas you'd like to treat and choose your session count. We'll cost out a clear course up front — no upsell, no surprises.
          </p>
        </div>

        <div className="calc-panel">
          <div className="calc-section-head">
            <div className="calc-section-l">— Treatment areas</div>
            {selected.length > 0 && (
              <button type="button" className="calc-clear" onClick={() => setSelected([])}>
                Clear all
              </button>
            )}
          </div>
          <div className="calc-zonetabs">
            {['Face', 'Body', 'Intimate'].map(z => {
              const cnt = F_AREAS.filter(a => a.zone === z && selected.includes(a.id)).length;
              return (
                <button
                  key={z}
                  type="button"
                  className={`calc-zonetab ${activeZone === z ? 'on' : ''}`}
                  onClick={() => setActiveZone(z)}
                >
                  {z}
                  {cnt > 0 && <span className="calc-zonetab-count">{cnt}</span>}
                </button>
              );
            })}
          </div>
          <div className="calc-pills">
            {F_AREAS.filter(a => a.zone === activeZone).map(a => {
              const on = selected.includes(a.id);
              return (
                <button
                  key={a.id}
                  type="button"
                  className={`calc-pill ${on ? 'on' : ''}`}
                  onClick={() => toggle(a.id)}
                  aria-pressed={on}
                >
                  <span className="calc-pill-name">{a.name}</span>
                  <span className="calc-pill-price">${a.price}</span>
                </button>
              );
            })}
          </div>

          <div className="calc-sessions">
            <div className="calc-range-head">
              <div className="calc-section-sub">Sessions</div>
              <div className="calc-range-meta">
                <span className="calc-range-n">{sessions}</span>
                <span className="calc-range-tier">{session.label} · {Math.round(session.discount * 100)}% off</span>
              </div>
            </div>
            <div className="calc-range-wrap">
              <input
                type="range"
                className="calc-range"
                min={sessMin}
                max={sessMax}
                step="1"
                value={sessions}
                onChange={(e) => setSessions(Number(e.target.value))}
                style={{ '--pct': sessPct + '%' }}
                aria-label="Number of sessions"
              />
            </div>
            <div className="calc-range-scale">
              <span>{sessMin}</span>
              <span>6</span>
              <span>{sessMax}</span>
            </div>
            <p className="calc-session-note">{session.note}</p>
          </div>

          <div className="calc-footer">
            <div className="calc-breakdown">
              {items.length === 0 ? (
                <p className="calc-empty">Pick at least one treatment area to see your course price.</p>
              ) : (
                <>
                  <ul className="calc-items">
                    {items.map(a => (
                      <li key={a.id}>
                        <span>{a.name}</span>
                        <span>${a.price} × {sessions}</span>
                      </li>
                    ))}
                  </ul>
                  <div className="calc-row">
                    <span>Subtotal</span>
                    <span>${subtotal.toLocaleString()}</span>
                  </div>
                  {session.discount > 0 && (
                    <div className="calc-row calc-row--discount">
                      <span>Course discount</span>
                      <span>−${Math.round(discount).toLocaleString()}</span>
                    </div>
                  )}
                </>
              )}
            </div>

            <div className="calc-checkout">
              <div className="calc-total">
                <div>
                  <span className="calc-total-l">Total course</span>
                  <span className="calc-total-sub">{items.length} {items.length === 1 ? 'area' : 'areas'} · {sessions} sessions</span>
                </div>
                <div className="calc-total-n">${animatedTotal.toLocaleString()}</div>
              </div>
              <button
                type="button"
                className={`btn calc-cta ${items.length === 0 ? 'disabled' : ''}`}
                onClick={() => items.length > 0 && setBooking(true)}
              >
                {items.length === 0 ? 'Pick an area to begin' : 'Book my course'}
              </button>
              <p className="calc-fineprint">
                Final price confirmed at your free consultation. Sessions on a 4-6 week rhythm. Numbing cream included.
              </p>
            </div>
          </div>
        </div>
      </div>
      {booking && (
        <FBookingModal
          onClose={() => setBooking(false)}
          items={items}
          sessions={sessions}
          total={total}
        />
      )}
    </section>);

}

// ─────── Why us with stats ───────
function FWhy() {
  return (
    <section id="why" className="why">
      <div className="container">
        <div className="why-head">
          <span className="eyebrow">— Trusted artistry</span>
          <h2 className="why-h h-display">
            Why choose <span className="i">Lissé?</span> Because your skin deserves quiet care.
          </h2>
        </div>

        <div className="why-bottom">
          <div className="why-mission">
            <p>To inspire confidence, enhance natural smoothness, and provide an unhurried, considered experience for every client who walks through our doors.</p>
            <p>Eight years of consistent operating record, four BTEC-Level-4 practitioners, and not a single rushed session.</p>
            <a href="#book" className="btn">Meet the practitioners</a>
          </div>
          <div className="why-images">
            <div className="img"><img src="images/o/new-armpit.jpg" alt="" /></div>
            <div className="img"><img src="images/safety-glasses.jpeg" alt="" /></div>
          </div>
        </div>

        <div className="why-stats">
          <CountStatF target={12000} suffix="+" label="Treatments delivered" />
          <CountStatF target={98} suffix="%" label="Happy clients" />
          <CountStatF target={4} suffix="" label="Studio locations" />
          <CountStatF target={8} suffix="+" label="Years of expertise" />
        </div>
      </div>
    </section>);

}

function CountStatF({ target, suffix, label }) {
  const [ref, inView] = useInView({ threshold: 0.3 });
  const v = useCountUp(target, { trigger: inView, duration: 1600 });
  return (
    <div className="why-stat" ref={ref}>
      <div className="why-stat-n">{v.toLocaleString()}{suffix}</div>
      <div className="why-stat-l">{label}</div>
    </div>);

}

// ─────── Video promo banner ───────
function FVideoBanner() {
  const [email, setEmail] = React.useState('');
  const [sent, setSent] = React.useState(false);
  const submit = (e) => { e.preventDefault(); if (email) setSent(true); };
  return (
    <section className="video-banner">
      <div className="video-card">
        <img src="images/laser-device.jpeg" alt="" />
        <div className="video-card-content">
          <div className="video-card-top">
            <span className="eyebrow">A studio note</span>
          </div>
          <div className="video-card-bottom">
            <h3 className="video-card-h">
              Subscribe and enjoy <span style={{ fontStyle: 'normal' }}>−20%</span> on your first laser visit.
            </h3>
            {sent ? (
              <p className="video-card-sent">Thank you — your −20% code is on its way to {email}.</p>
            ) : (
              <form className="video-card-form" onSubmit={submit}>
                <input
                  type="email"
                  required
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  placeholder="your@email.com"
                  aria-label="Email address"
                />
                <button type="submit" className="btn">Claim −20%</button>
              </form>
            )}
          </div>
        </div>
      </div>
    </section>);

}

// ─────── Journal ───────
function FJournal() {
  const posts = [
  { cat: 'Skin science', title: 'How laser actually targets the follicle — and why it takes six sessions.',
    author: 'Camille Reyes', year: 2026,
    img: 'images/face-treatment.jpeg' },
  { cat: 'Treatment guide', title: 'A quiet primer on preparing your skin for a course of laser care.',
    author: 'Inès Laurent', year: 2026,
    img: 'images/treatment-care.jpeg' }];

  return (
    <section id="journal" className="journal">
      <div className="container">
        <div className="journal-head">
          <div>
            <span className="eyebrow">From the journal</span>
            <h2 className="h-display">
              Unlock the secrets to <span className="i">timeless</span> smooth skin.
            </h2>
          </div>
          <a href="#" className="btn">Read all journal</a>
        </div>
        <div className="journal-grid">
          {posts.map((p, i) =>
          <a className="journal-card" key={i} href="#">
              <div className="journal-img"><img src={p.img} alt="" /></div>
              <div className="journal-body">
                <div>
                  <span className="journal-cat"><IconAsterisk size={9} sw={1.4} /> {p.cat}</span>
                  <h3 className="journal-title" style={{ marginTop: 12 }}>{p.title}</h3>
                </div>
                <div className="journal-meta">
                  <span>By <em style={{ fontStyle: 'italic' }}>{p.author}</em></span>
                  <span>{p.year}</span>
                </div>
              </div>
            </a>
          )}
        </div>
      </div>
    </section>);

}

// ─────── Testimonials slider (3-up) ───────
function FTestimonials() {
  const tests = [
  { q: "Lissé always delivers exceptional care. I came in for an underarm course and left with smoother skin and a calmer hour than I'd had all month.",
    name: "Jessica Green", role: "Underarms & arms",
    img: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&q=80&auto=format" },
  { q: "Truly exceeded my expectations. The team made me feel pampered, not processed — every visit feels like a small ritual. I'll definitely be back.",
    name: "Sarah Mail", role: "Brazilian course",
    img: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200&q=80&auto=format" },
  { q: "From the moment I walked in I felt looked after. The staff was friendly, the room was quiet, and I'm thrilled with the results.",
    name: "Sophia Bennett", role: "Full-leg course",
    img: "https://images.unsplash.com/photo-1573497019418-b400bb3ab074?w=200&q=80&auto=format" },
  { q: "I tried two other studios before finding Lissé and the difference is night and day. Zero upsell pressure, current technology, considered care.",
    name: "Amélie Rousseau", role: "Face & jawline",
    img: "https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200&q=80&auto=format" },
  { q: "The concierge full-body course is worth every penny. Same practitioner every time, scheduling that fits my life, useful aftercare guidance.",
    name: "Margaux Dupont", role: "Concierge full-body",
    img: "https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?w=200&q=80&auto=format" },
  { q: "I'd been on the fence about laser for years. Six sessions in and my underarms haven't seen a razor in five months. Worth every visit.",
    name: "Eleanor Whitfield", role: "Underarms",
    img: "https://images.unsplash.com/photo-1517841905240-472988babdf9?w=200&q=80&auto=format" },
  { q: "Their consultation alone is more thorough than three other studios combined. Honest about what laser can and can't do — that's rare.",
    name: "Priya Nair", role: "Face course",
    img: "https://images.unsplash.com/photo-1488426862026-3ee34a7d66df?w=200&q=80&auto=format" }];

  const trackRef = React.useRef(null);
  const [page, setPage] = React.useState(0);
  const [pageCount, setPageCount] = React.useState(1);

  const recompute = React.useCallback(() => {
    const el = trackRef.current;
    if (!el) return;
    const card = el.querySelector('.test-card');
    if (!card) return;
    const styles = getComputedStyle(el);
    const gap = parseFloat(styles.columnGap || styles.gap || 0);
    const padL = parseFloat(styles.paddingLeft) || 0;
    const padR = parseFloat(styles.paddingRight) || 0;
    const cardW = card.getBoundingClientRect().width;
    const step = cardW + gap;
    const visibleArea = Math.max(0, el.clientWidth - padL - padR);
    const visible = Math.max(1, Math.round(visibleArea / step));
    const pages = Math.max(1, tests.length - visible + 1);
    setPageCount(pages);
    const current = Math.min(pages - 1, Math.round(el.scrollLeft / step));
    setPage(current);
  }, [tests.length]);

  React.useEffect(() => {
    recompute();
    const el = trackRef.current;
    if (!el) return;
    const onScroll = () => recompute();
    el.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', recompute);
    return () => {
      el.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', recompute);
    };
  }, [recompute]);

  const goBy = (dir) => {
    const el = trackRef.current;
    if (!el) return;
    const card = el.querySelector('.test-card');
    if (!card) return;
    const gap = parseFloat(getComputedStyle(el).columnGap || 0);
    const step = card.getBoundingClientRect().width + gap;
    el.scrollBy({ left: dir * step, behavior: 'smooth' });
  };
  const goTo = (p) => {
    const el = trackRef.current;
    if (!el) return;
    const card = el.querySelector('.test-card');
    if (!card) return;
    const gap = parseFloat(getComputedStyle(el).columnGap || 0);
    const step = card.getBoundingClientRect().width + gap;
    el.scrollTo({ left: p * step, behavior: 'smooth' });
  };

  return (
    <section id="testimonials" className="testimonials">
      <div className="container">
        <div className="test-head">
          <div className="test-head-left">
            <span className="eyebrow">— Quietly devoted clients</span>
            <h2 className="h-display">What our <span className="i">clients</span> say.</h2>
          </div>
          <div className="test-head-right">
            <div className="test-counter">
              <span className="test-counter-now">{String(page + 1).padStart(2, '0')}</span>
              <span className="test-counter-sep">/</span>
              <span className="test-counter-total">{String(pageCount).padStart(2, '0')}</span>
            </div>
            <div className="test-nav">
              <button className="test-arrow" aria-label="Previous" onClick={() => goBy(-1)} disabled={page === 0}>
                <IconArrowUpRight size={18} sw={1.4} style={{ transform: 'rotate(-135deg)' }} />
              </button>
              <button className="test-arrow" aria-label="Next" onClick={() => goBy(1)} disabled={page >= pageCount - 1}>
                <IconArrowUpRight size={18} sw={1.4} style={{ transform: 'rotate(45deg)' }} />
              </button>
            </div>
          </div>
        </div>

        <div className="test-track" ref={trackRef}>
          {tests.map((t, k) =>
          <article key={k} className="test-card">
              <div className="test-cardtop">
                <span className="test-mark" aria-hidden="true">"</span>
                <div className="test-stars" aria-label="5 out of 5 stars">
                  {[0, 1, 2, 3, 4].map((s) => <IconStar key={s} size={17} sw={0} style={{ fill: 'currentColor' }} />)}
                </div>
              </div>
              <p className="test-q">{t.q}</p>
              <div className="test-foot">
                <div className="test-avatar"><img src={t.img} alt="" /></div>
                <div className="test-who">
                  <div className="test-name">{t.name}</div>
                  <div className="test-role">{t.role}</div>
                </div>
              </div>
            </article>
          )}
        </div>

        <div className="test-dots" role="tablist">
          {Array.from({ length: pageCount }).map((_, k) =>
          <button key={k} className={`test-dot ${k === page ? 'on' : ''}`}
          onClick={() => goTo(k)} aria-label={`Go to slide ${k + 1}`} />
          )}
        </div>
      </div>
    </section>);

}

// ─────── Social / Follow us ───────
function FSocial() {
  const tiles = [
  { src: 'images/o/new-legs.jpg', shape: 'rounded' },
  { src: 'images/treatment-session.jpeg', shape: 'arch' },
  { src: 'images/o/new-armpit.jpg', shape: 'rounded' },
  { src: 'images/o/fan-pose.jpg', shape: 'arch' },
  { src: 'images/o/new-face.jpg', shape: 'rounded' }];

  return (
    <section className="social">
      <div className="social-top">
        <div className="social-top-inner">
          <span className="social-eyebrow">— Follow us</span>
          <ul className="social-links">
            <li><a href="#" aria-label="Instagram">Instagram</a></li>
            <li><a href="#" aria-label="Facebook">Facebook</a></li>
          </ul>
        </div>
      </div>
      <div className="social-strip" aria-hidden="true">
        <div className="social-tiles">
          {tiles.map((t, i) =>
          <div key={i} className={`social-tile social-tile--${t.shape}`}>
              <img src={t.src} alt="" loading="lazy" />
            </div>
          )}
        </div>
      </div>
      <div className="social-bottom">
        <div className="social-bottom-inner">
          <h2 className="social-headline h-display">
            Smoother, hair-free skin starts here — with <span className="i">calibrated lasers</span> and unhurried care.
          </h2>
          <div className="social-foot">
            <p className="social-blurb">
              Book a free consultation and begin your course. Fewer hairs every session — no razors, no waxing, no ingrowns.
            </p>
            <div className="social-phones">
              <a className="social-phone" href="tel:+15551234567">+1 (555) 123-4567</a>
              <span className="social-phone-sep" aria-hidden="true"></span>
              <a className="social-phone" href="tel:+15557654321">+1 (555) 765-4321</a>
            </div>
          </div>
        </div>
      </div>
    </section>);

}

// ─────── Before / After comparison slider ───────
function FBeforeAfter() {
  const [pos, setPos] = React.useState(50);
  const ref = React.useRef(null);
  const dragRef = React.useRef(false);

  const setFromX = (clientX) => {
    const r = ref.current.getBoundingClientRect();
    const next = Math.max(0, Math.min(100, ((clientX - r.left) / r.width) * 100));
    setPos(next);
  };
  const onDown = (e) => {
    dragRef.current = true;
    setFromX(e.touches ? e.touches[0].clientX : e.clientX);
    e.preventDefault();
  };
  const onMove = (e) => {
    if (!dragRef.current) return;
    setFromX(e.touches ? e.touches[0].clientX : e.clientX);
  };
  const onUp = () => { dragRef.current = false; };

  React.useEffect(() => {
    window.addEventListener('mousemove', onMove);
    window.addEventListener('touchmove', onMove, { passive: false });
    window.addEventListener('mouseup', onUp);
    window.addEventListener('touchend', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('touchmove', onMove);
      window.removeEventListener('mouseup', onUp);
      window.removeEventListener('touchend', onUp);
    };
  }, []);

  return (
    <section id="results" className="results">
      <div className="container">
        <div className="results-head">
          <div>
            <span className="eyebrow">— Real client results</span>
            <h2 className="h-display">
              Smoother skin, <span className="i">session by session.</span>
            </h2>
          </div>
          <p className="results-blurb">
            Drag the divider to compare. These photos show a typical underarm course at week 0 and week 24 — six sessions on a five-week rhythm.
          </p>
        </div>

        <div className="ba" ref={ref} onMouseDown={onDown} onTouchStart={onDown}>
          <img className="ba-img ba-img--before"
            src="images/o/ba-before.jpg" alt="Before treatment" />
          <div className="ba-after-wrap" style={{ clipPath: `inset(0 0 0 ${pos}%)` }}>
            <img className="ba-img ba-img--after"
              src="images/o/ba-after.jpg" alt="After 6 sessions" />
          </div>
          <span className="ba-label ba-label--before">Before · Week 0</span>
          <span className="ba-label ba-label--after">After · Week 24</span>
          <div className="ba-divider" style={{ left: `${pos}%` }}>
            <button className="ba-handle" aria-label="Drag to compare">
              <IconArrowUpRight size={14} sw={1.5} style={{transform:'rotate(-135deg)'}} />
              <IconArrowUpRight size={14} sw={1.5} style={{transform:'rotate(45deg)'}} />
            </button>
          </div>
        </div>

        <div className="results-stats">
          <div className="results-stat">
            <span className="results-stat-n">6</span>
            <span className="results-stat-l">Sessions on average</span>
          </div>
          <div className="results-stat">
            <span className="results-stat-n">24<sup>w</sup></span>
            <span className="results-stat-l">From first to final visit</span>
          </div>
          <div className="results-stat">
            <span className="results-stat-n">93<sup>%</sup></span>
            <span className="results-stat-l">Average reduction</span>
          </div>
          <div className="results-stat">
            <span className="results-stat-n">1<sup>×</sup></span>
            <span className="results-stat-l">Yearly touch-up</span>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────── FAQ (accordion) ───────
function FFAQ() {
  const faqs = [
    { q: 'How many sessions will I need?',
      a: 'Most clients see 80–95% reduction after six sessions on a 4–6 week rhythm. Areas with denser, darker hair often need eight to ten visits — we map your course at the first consultation.' },
    { q: 'Does laser hair removal hurt?',
      a: 'Modern diode lasers with sapphire cooling feel like the gentle snap of a warm rubber band — and most clients report nothing at all by the third session. Numbing cream is included for sensitive zones.' },
    { q: 'Is laser safe for my skin tone?',
      a: 'Yes — our dual-wavelength devices are safe for Fitzpatrick types I through VI. Settings are calibrated to your specific tone at every visit, with a 24-hour patch test before your first session.' },
    { q: 'How should I prepare for a session?',
      a: 'Shave the area 24 hours before. Avoid sun, retinol and self-tanners for two weeks prior. Arrive freshly cleansed — no oils, lotions, deodorant or makeup on the treatment area.' },
    { q: 'What does aftercare look like?',
      a: 'Aloe gel and avoiding hot showers or workouts for 48 hours. SPF 50 on the area for two weeks. We send you a tailored aftercare guide by email within an hour of every session.' },
    { q: 'How soon will I notice results?',
      a: 'Most clients see slower, finer regrowth after session two and visibly thinner hair by session four. Final permanent results show two to three weeks after your last session.' },
    { q: 'Can I shave between sessions?',
      a: 'Yes — shaving is encouraged and required. Avoid waxing, threading, or plucking between visits, since those remove the follicle the laser needs to target.' },
    { q: "What's your cancellation policy?",
      a: 'We ask for 24 hours notice to reschedule. Life happens — your first reschedule is always free. After that, missed sessions are charged at half rate.' },
  ];
  const [open, setOpen] = React.useState(-1);
  return (
    <section id="faq" className="faq">
      <div className="container">
        <div className="faq-head">
          <div>
            <span className="eyebrow">— Frequently asked</span>
            <h2 className="h-display">
              The <span className="i">quiet answers</span> to the questions clients ask most.
            </h2>
          </div>
          <a href="#book" className="btn">Ask us anything</a>
        </div>
        <ul className="faq-list">
          {faqs.map((f, i) => (
            <li key={i} className={`faq-item ${open === i ? 'on' : ''}`}>
              <button className="faq-q" aria-expanded={open === i} onClick={() => setOpen(open === i ? -1 : i)}>
                <span className="faq-n">{String(i + 1).padStart(2, '0')}</span>
                <span className="faq-qt">{f.q}</span>
                <span className="faq-toggle" aria-hidden="true">
                  <IconArrowUpRight size={14} sw={1.6} />
                </span>
              </button>
              <div className="faq-a-wrap">
                <div className="faq-a-inner">
                  <p className="faq-a">{f.a}</p>
                </div>
              </div>
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}

// ─────── Booking form (before footer) ───────
function FCTA() {
  const [form, setForm] = React.useState({ name: '', email: '', phone: '', service: '', date: '', notes: '' });
  const upd = (k) => (e) => setForm({ ...form, [k]: e.target.value });
  const onSubmit = (e) => {e.preventDefault();};
  return (
    <section className="cta" id="book">
      <div className="cta-inner">
        <div className="cta-img">
          <img src="images/studio-interior.jpeg" alt="" />
          <div className="cta-img-overlay">
            <span className="eyebrow" style={{ color: 'rgba(255,255,255,0.8)' }}>— Begin your course</span>
            <h3 className="cta-img-h h-display">
              A quiet hour, <span className="i">considered</span> care, smoother skin.
            </h3>
            <div className="cta-img-meta">
              <div>
                <span className="cta-img-meta-l">Reply within</span>
                <span className="cta-img-meta-v">2 hours</span>
              </div>
              <div>
                <span className="cta-img-meta-l">Consultation</span>
                <span className="cta-img-meta-v">Free of charge</span>
              </div>
            </div>
          </div>
        </div>
        <form className="cta-form" onSubmit={onSubmit}>
          <div className="cta-form-head">
            <span className="eyebrow">— Book a consultation</span>
            <h2 className="h-display">
              Reserve your <span className="i">first visit.</span>
            </h2>
            <p className="cta-form-blurb">
              Tell us a little about yourself and the area you'd like to treat. We'll be in touch within two hours to suggest a quiet slot.
            </p>
          </div>

          <div className="cta-form-grid">
            <label className="field">
              <span>Full name</span>
              <input type="text" value={form.name} onChange={upd('name')} placeholder="Inès Laurent" required />
            </label>
            <label className="field">
              <span>Email</span>
              <input type="email" value={form.email} onChange={upd('email')} placeholder="ines@example.com" required />
            </label>
            <label className="field">
              <span>Phone</span>
              <input type="tel" value={form.phone} onChange={upd('phone')} placeholder="+1 (555) 123-4567" />
            </label>
            <label className="field">
              <span>Service</span>
              <div className="field-select">
                <select value={form.service} onChange={upd('service')} required>
                  <option value="">Choose a service…</option>
                  <option value="face">Face Laser</option>
                  <option value="body">Body Smooth</option>
                  <option value="bikini">Bikini & Brazilian</option>
                  <option value="concierge">Concierge Full-Body</option>
                  <option value="unsure">I'd like to be advised</option>
                </select>
                <IconArrowUpRight size={14} sw={1.5} style={{ transform: 'rotate(135deg)' }} />
              </div>
            </label>
            <label className="field field--full">
              <span>Preferred date</span>
              <input type="date" className="date-input" value={form.date} min={new Date().toISOString().split('T')[0]} onChange={upd('date')} />
            </label>
            <label className="field field--full">
              <span>A note for your practitioner <em>(optional)</em></span>
              <textarea rows={3} value={form.notes} onChange={upd('notes')} placeholder="Anything you'd like us to know in advance — skin sensitivities, previous treatments, time-of-day preference." />
            </label>
          </div>

          <div className="cta-form-foot">
            <label className="cta-form-consent">
              <input type="checkbox" defaultChecked />
              <span>I agree to receive a reply by email or phone.</span>
            </label>
            <button type="submit" className="btn cta-form-submit">Send &amp; book</button>
          </div>
        </form>
      </div>
    </section>);

}

// ─────── Footer ───────
function FFooter() {
  const [email, setEmail] = React.useState('');
  const onSubmit = (e) => {e.preventDefault();setEmail('');};
  const year = new Date().getFullYear();
  return (
    <footer id="contact">
      <div className="footer-cta">
        <div className="container">
          <div className="footer-cta-row">
            <div>
              <span className="footer-eyebrow">— Let's begin</span>
              <h2 className="footer-h h-display">
                Ready for a quieter, smoother <span className="i">you?</span>
              </h2>
            </div>
            <a href="#book" className="btn footer-cta-btn">Book a consultation</a>
          </div>
        </div>
      </div>

      <div className="container">
        <div className="footer-mid">
          <div className="footer-col footer-col--brand">
            <span className="footer-logo"><IconLumiere size={30} sw={1.3} /> Lissé</span>
            <p className="footer-brand-blurb">
              A laser hair removal studio. Quietly serious about smoother skin since 2018. Four certified practitioners, four studios, one unhurried hour at a time.
            </p>
            <form className="footer-news" onSubmit={onSubmit}>
              <label className="footer-news-l">Newsletter — quiet notes, twice a season</label>
              <div className="footer-news-row">
                <input type="email" value={email} onChange={(e) => setEmail(e.target.value)}
                placeholder="your@email.com" required aria-label="Email" />
                <button type="submit" aria-label="Subscribe">
                  <IconArrowUpRight size={16} sw={1.6} />
                </button>
              </div>
            </form>
          </div>

          <div className="footer-col">
            <h5>Studios</h5>
            <div className="footer-loc">
              <div className="footer-loc-item">
                <span className="footer-loc-name">Downtown</span>
                <span className="footer-loc-addr">225 East 57th Street, Suite 8C<br />New York, NY 10022</span>
                <a className="footer-loc-link" href="#">Get directions <IconArrowUpRight size={11} sw={1.6} /></a>
              </div>
              <div className="footer-loc-item">
                <span className="footer-loc-name">Uptown</span>
                <span className="footer-loc-addr">1380 North Clark Street, 2F<br />Chicago, IL 60610</span>
                <a className="footer-loc-link" href="#">Get directions <IconArrowUpRight size={11} sw={1.6} /></a>
              </div>
            </div>
          </div>

          <div className="footer-col">
            <h5>Sitemap</h5>
            <ul>
              <li><a href="#why">About</a></li>
              <li><a href="#services">Services</a></li>
              <li><a href="#calculator">Pricing</a></li>
              <li><a href="#testimonials">Reviews</a></li>
              <li><a href="#contact">Contact</a></li>
            </ul>
          </div>

          <div className="footer-col">
            <h5>Get in touch</h5>
            <ul className="footer-contact">
              <li><a href="mailto:hello@lisse.studio"><span>Email</span><em>hello@lisse.studio</em></a></li>
              <li><a href="tel:+15551234567"><span>Phone</span><em>+1 (555) 123-4567</em></a></li>
            </ul>
            <div className="footer-social">
              <a href="#" aria-label="Instagram">Instagram</a>
              <a href="#" aria-label="Facebook">Facebook</a>
            </div>
          </div>
        </div>

        <div className="footer-bottom">
          <span>© {year} Lissé Studio · All rights reserved.</span>
          <span className="footer-legal">
            <a href="#">Privacy</a>
            <a href="#">Terms</a>
            <a href="#">Cookies</a>
            <a href="#">Accessibility</a>
          </span>
          <span className="footer-made">Site quietly crafted in NYC</span>
        </div>
      </div>
    </footer>);

}

// ─────── Immersive cinematic interlude (signature moment) ───────
function FImmersive() {
  const secRef = React.useRef(null);
  const mediaRef = React.useRef(null);
  const [entered, setEntered] = React.useState(false);

  React.useEffect(() => {
    const sec = secRef.current;
    const media = mediaRef.current;
    if (!sec || !media) return;
    let raf;
    let done = false;
    const apply = () => {
      const r = sec.getBoundingClientRect();
      const vh = window.innerHeight;
      const prog = (vh - r.top) / (vh + r.height); // 0..1 as it crosses the viewport
      const y = (Math.min(1, Math.max(0, prog)) - 0.5) * 20; // -10% … +10% drift
      media.style.transform = "translate3d(0, " + y + "%, 0)";
      if (!done && r.top < vh * 0.8) { done = true; setEntered(true); }
    };
    const onScroll = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(apply); };
    window.addEventListener("scroll", onScroll, { passive: true });
    apply();

    return () => {
      window.removeEventListener("scroll", onScroll);
      cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <section ref={secRef} className={"immersive" + (entered ? " in" : "")} aria-label="Considered light">
      <div ref={mediaRef} className="immersive-media">
        <img src="images/o/laser-leg.jpg" alt="" />
      </div>
      <div className="immersive-scrim" aria-hidden="true"></div>
      <div className="immersive-content">
        <span className="immersive-eyebrow"><span>— The Lissé hour</span></span>
        <h2 className="immersive-h">
          <span className="immersive-line"><span>Where precision</span></span>
          <span className="immersive-line"><span>becomes <em className="i">calm.</em></span></span>
        </h2>
        <p className="immersive-caption">An unhurried hour, considered light, and skin that quietly remembers the difference.</p>
        <a href="#calculator" className="immersive-cta">Build your course</a>
      </div>
    </section>
  );
}

function useScrollReveal() {
  React.useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    const sel = ".services-head, .calc-head, .why-head, .faq-head, .reviews-head, .results-head, .cta-form-head, .section-head";
    const els = Array.prototype.slice.call(document.querySelectorAll(sel));
    document.documentElement.classList.add("reveal-on");
    els.forEach(function (el) { el.classList.add("rv"); });
    const io = new IntersectionObserver(function (entries) {
      entries.forEach(function (e) {
        if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); }
      });
    }, { threshold: 0.18, rootMargin: "0px 0px -8% 0px" });
    els.forEach(function (el) { io.observe(el); });

    return () => { io.disconnect(); };
  }, []);
}

// ─────── App root ───────
function FApp() {
  const [t, setTweak] = useTweaks(F_TWEAK_DEFAULTS);
  useScrollReveal();
  React.useEffect(() => {
    const root = document.documentElement;
    const p = F_PALETTES[t.palette] || F_PALETTES.cream;
    Object.entries(p.vars).forEach(([k, v]) => root.style.setProperty(k, v));
    const f = F_FONTS[t.fonts] || F_FONTS.cormorant;
    root.style.setProperty('--font-display', f.display);
    root.style.setProperty('--font-body', f.body);
  }, [t.palette, t.fonts]);

  return (
    <>
      <ScrollProgress />
      <FNav />
      <FHero />
      <FStatement />
      <FServices />
      <FWordMarquee />
      <FImmersive />
      <FCalculator />
      <FWhy />
      <FBeforeAfter />
      <FFAQ />
      <FVideoBanner />
      <FTestimonials />
      <FSocial />
      <FCTA />
      <FFooter />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Color palette" />
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          {Object.entries(F_PALETTES).map(([k, p]) =>
          <button key={k} onClick={() => setTweak('palette', k)}
          style={{ display: 'flex', flexDirection: 'column', gap: 6, padding: 8,
            border: '1px solid ' + (t.palette === k ? 'rgba(41,38,27,0.7)' : 'rgba(0,0,0,0.1)'),
            borderRadius: 8, background: t.palette === k ? 'rgba(0,0,0,0.04)' : 'transparent',
            cursor: 'pointer', textAlign: 'left', font: 'inherit', color: 'inherit' }}>
              <div style={{ display: 'flex', gap: 3, height: 22 }}>
                {p.swatch.map((c, i) =>
              <div key={i} style={{ flex: 1, background: c, borderRadius: 3, border: '0.5px solid rgba(0,0,0,0.08)' }}></div>
              )}
              </div>
              <span style={{ fontSize: 10, color: 'rgba(41,38,27,0.7)' }}>{p.label}</span>
            </button>
          )}
        </div>
        <TweakSection label="Type pair" />
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          {Object.entries(F_FONTS).map(([k, f]) =>
          <button key={k} onClick={() => setTweak('fonts', k)}
          style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', padding: '10px 12px',
            borderRadius: 8, border: '1px solid ' + (t.fonts === k ? 'rgba(41,38,27,0.7)' : 'rgba(0,0,0,0.1)'),
            background: t.fonts === k ? 'rgba(0,0,0,0.04)' : 'transparent', cursor: 'pointer',
            textAlign: 'left', font: 'inherit', color: 'inherit', width: '100%' }}>
              <span style={{ fontFamily: f.display, fontSize: 24, lineHeight: 1, fontStyle: 'italic' }}>Smooth.</span>
              <span style={{ fontFamily: f.body, fontSize: 10, color: 'rgba(41,38,27,0.6)', marginTop: 4, letterSpacing: '0.04em' }}>{f.label}</span>
            </button>
          )}
        </div>
      </TweaksPanel>
    </>);

}

ReactDOM.createRoot(document.getElementById('root')).render(<FApp />);