// Kafana — landing page sections. Composed by App.jsx into mobile + desktop frames.

const { useState, useRef, useEffect, Fragment } = React;

// Email capture — used in dedicated section
function EmailForm({ id, dark = false, stacked = false, buttonLabel = 'Notify me.' }) {
  const [email, setEmail] = useState('');
  const [state, setState] = useState('idle'); // idle | submitting | done | error
  const submit = (e) => {
    e.preventDefault();
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      setState('error');
      return;
    }
    setState('submitting');
    setTimeout(() => setState('done'), 700);
  };

  if (state === 'done') {
    return (
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12,
        padding: '14px 20px',
        border: `0.5px solid ${dark ? 'var(--d-whisper)' : 'var(--whisper)'}`,
        borderRadius: 10,
        fontFamily: 'var(--sans)', fontSize: 15,
        color: dark ? 'var(--d-text)' : 'var(--ink)',
        background: dark ? 'var(--d-card)' : 'var(--honey-light)',
      }}>
        <Icon name="check" size={18} color={dark ? 'var(--copper)' : 'var(--copper-deep)'} />
        <span>You're on the list. Živeli.</span>
      </div>
    );
  }

  const inputStyle = {
    background: 'var(--cream)',
    border: `0.5px solid ${state === 'error' ? 'var(--copper-deep)' : 'var(--whisper)'}`,
    borderRadius: 10,
    padding: '14px 18px',
    fontFamily: 'var(--sans)', fontSize: 16,
    color: 'var(--ink)', outline: 'none',
    flex: stacked ? 'none' : 1,
    width: stacked ? '100%' : 'auto',
    minWidth: 0,
    boxSizing: 'border-box',
    transition: 'border-color 220ms cubic-bezier(.2,.7,.3,1)',
  };

  const btnStyle = {
    width: stacked ? '100%' : 'auto',
    borderRadius: 10,
    padding: '14px 24px',
  };

  return (
    <form id={id} onSubmit={submit} style={{
      display: 'flex', gap: 8,
      flexDirection: stacked ? 'column' : 'row',
      width: '100%',
    }}>
      <input
        type="email"
        placeholder="your@email.com"
        value={email}
        onChange={e => { setEmail(e.target.value); if (state === 'error') setState('idle'); }}
        aria-invalid={state === 'error'}
        style={inputStyle}
        onFocus={e => { if (state !== 'error') e.target.style.borderColor = 'var(--copper)'; }}
        onBlur={e => { if (state !== 'error') e.target.style.borderColor = 'var(--whisper)'; }}
      />
      <button type="submit" className="kf-cta" disabled={state === 'submitting'} style={btnStyle}>
        {state === 'submitting' ? 'Pouring…' : buttonLabel}
      </button>
    </form>
  );
}

// Layout-tier helper. Inline-style page; centralizing the side-padding
// + max-content-width tokens here keeps every section consistent without
// pulling in a CSS-tokens layer.
const SIDE_PAD = { mobile: 24, tablet: 40, desktop: 80 };
const CONTENT_MAX = 1200;

function innerMax(layout) {
  // Wraps each section's content so it caps at CONTENT_MAX on ultra-wide
  // viewports. Side padding lives on the <section> so background fills
  // still bleed full-width.
  return { maxWidth: CONTENT_MAX, marginInline: 'auto' };
}

// Nav — minimal. Wordmark left.
function Nav({ width = 'mobile', dark = false }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  return (
    <nav style={{
      padding: `${isMobile ? 20 : isTablet ? 24 : 28}px ${padX}px`,
      borderBottom: `0.5px solid ${dark ? 'var(--d-whisper)' : 'var(--whisper)'}`,
    }}>
      <div style={{
        ...innerMax(width),
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <Wordmark size={isMobile ? 22 : 26} />
      </div>
    </nav>
  );
}

// Hero
//
// Stacked single-column on mobile + tablet (the 320pt phone bezel
// alongside text only fits comfortably at 1024+). Desktop is the
// 2-column "text left, phone right" treatment.
function Hero({ width = 'mobile', dark = false }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const isDesktop = width === 'desktop';

  // CTA → opens the vanilla-JS modal defined in waitlist-modal.js.
  // Falls through to the in-page #signup anchor if for any reason the
  // script didn't load (no-JS scenario, ad-blocker stripping the script).
  const onHeroCtaClick = (e) => {
    if (typeof window !== 'undefined' && typeof window.openWaitlistModal === 'function') {
      e.preventDefault();
      window.openWaitlistModal('hero');
    }
  };

  if (!isDesktop) {
    return (
      <section style={{
        padding: isMobile ? '40px 24px 56px' : '56px 40px 64px',
      }}>
        <div style={innerMax(width)}>
          <h1 className="t-display" style={{
            fontSize: isMobile ? 44 : 64,
            lineHeight: 1.05, marginBottom: isMobile ? 18 : 22, marginTop: 0,
            letterSpacing: isMobile ? undefined : '-1px',
            color: dark ? 'var(--d-text)' : 'var(--ink)',
          }}>
            A passport for <span style={{ fontStyle: 'italic', color: dark ? 'var(--cream)' : 'var(--plum)' }}>every glass.</span>
          </h1>
          <p className="t-body" style={{
            fontSize: isMobile ? 17 : 18,
            color: dark ? 'var(--d-smoke)' : 'var(--smoke)',
            marginBottom: isMobile ? 28 : 32, marginTop: 0,
            maxWidth: isMobile ? 320 : 480,
          }}>
            Log every pour of rakija — fruit, place, producer, photo.
            A personal record across the Balkans.
          </p>
          <div style={{ marginBottom: isMobile ? 40 : 48 }}>
            <a href="#signup" className="kf-cta" onClick={onHeroCtaClick}>Notify me when it launches</a>
          </div>

          {/* Phone mockup — wrapped in .kf-phone-glow for the honey
              radial halo behind the bezel. */}
          <div style={{ display: 'flex', justifyContent: 'center', marginTop: 8 }}>
            <div className="kf-phone-glow">
              <div className="kf-phone" style={{ width: isMobile ? 280 : 300 }}>
                <div className="kf-phone-screen" style={{ height: isMobile ? 580 : 620 }}>
                  <div className="kf-phone-notch" />
                  <CaptureSheet dark={dark} />
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
    );
  }
  // Desktop
  return (
    <section style={{ padding: '72px 80px 80px' }}>
      <div style={{
        ...innerMax(width),
        display: 'grid', gridTemplateColumns: '1.1fr 0.9fr',
        gap: 72, alignItems: 'center',
      }}>
        <div>
          <h1 className="t-display" style={{
            fontSize: 84, lineHeight: 0.98, marginBottom: 28, marginTop: 0,
            letterSpacing: '-1.5px',
            color: dark ? 'var(--d-text)' : 'var(--ink)',
          }}>
            A passport for<br/>
            <span style={{ fontStyle: 'italic', color: dark ? 'var(--cream)' : 'var(--plum)' }}>every glass.</span>
          </h1>
          <p className="t-body" style={{
            fontSize: 19, lineHeight: 1.5,
            color: dark ? 'var(--d-smoke)' : 'var(--smoke)',
            marginBottom: 36, marginTop: 0, maxWidth: 460,
          }}>
            Log every pour of rakija — fruit, place, producer, photo.
            A personal record across the Balkans, free forever.
          </p>
          <div>
            <a href="#signup" className="kf-cta" onClick={onHeroCtaClick} style={{ fontSize: 17, padding: '16px 28px' }}>
              Notify me when it launches
            </a>
          </div>
        </div>
        {/* Layered phone mockups (desktop only). Two screenshot phones
            (Discover + Šljiva fruit-detail) sit behind the foreground
            capture-sheet, tilted in opposite directions so the
            composition reads as a stack rather than three separate
            phones. The foreground stays the React-rendered CaptureSheet
            (so it animates / inherits brand tokens); the two behind
            are static <img> screens inside the same .kf-phone bezel,
            keeping the bezel-color/radius consistent across all three.
            relative+overflow:visible on the wrapper lets the right-
            side bg phone bleed past the column edge into the section's
            cream margin without clipping. */}
        <div style={{
          position: 'relative',
          minHeight: 720,
          display: 'flex', justifyContent: 'flex-end', alignItems: 'center',
        }}>
          {/* Background phone — Discover screen, peeks upper-left.
              Right offset (320 + bezel width) puts the bg phone clearly
              past the foreground's left edge, with the rotation
              tipping its upper-left corner away from the foreground. */}
          <div style={{
            position: 'absolute',
            right: 320,
            top: 30,
            transform: 'rotate(-9deg)',
            transformOrigin: 'center',
            zIndex: 0,
          }}>
            <div className="kf-phone" style={{ width: 240 }}>
              <div className="kf-phone-screen" style={{ height: 500 }}>
                <div className="kf-phone-notch" />
                <img
                  src="assets/screens/discover.png"
                  alt=""
                  aria-hidden="true"
                  style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                />
              </div>
            </div>
          </div>

          {/* Background phone — Šljiva fruit detail, peeks lower-right.
              Negative right pushes it past the column's right edge into
              the section's cream margin. */}
          <div style={{
            position: 'absolute',
            right: -150,
            top: 130,
            transform: 'rotate(9deg)',
            transformOrigin: 'center',
            zIndex: 0,
          }}>
            <div className="kf-phone" style={{ width: 240 }}>
              <div className="kf-phone-screen" style={{ height: 500 }}>
                <div className="kf-phone-notch" />
                <img
                  src="assets/screens/sljiva.png"
                  alt=""
                  aria-hidden="true"
                  style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                />
              </div>
            </div>
          </div>

          {/* Foreground phone — interactive CaptureSheet, halo behind */}
          <div className="kf-phone-glow" style={{ position: 'relative', zIndex: 2 }}>
            <div className="kf-phone" style={{ width: 320 }}>
              <div className="kf-phone-screen" style={{ height: 660 }}>
                <div className="kf-phone-notch" />
                <CaptureSheet dark={dark} />
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// Three-up value props — Capture, Library, Passport
//
// Pattern matches ThirtySecondLog: overline → serif H2 thesis →
// per-item grid. Per-item icon now sits inline (left) of the serif
// title rather than stacked above it in a 44pt rounded box — pulls
// the eye horizontally with the heading, denser visual rhythm.
function Trio({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const items = [
    { icon: 'camera', title: 'Capture',
      body: 'Tap +. A photo, a fruit, a place. The first sip is logged before the second.' },
    { icon: 'book', title: 'Library',
      body: 'Twelve fruits. Eight regions. Producers who deserve to be remembered.' },
    { icon: 'passport', title: 'Passport',
      body: 'A shareable record of where rakija has taken you. No leaderboards.' },
  ];
  const padY = isMobile ? 56 : isTablet ? 64 : 80;
  const titleSize = isMobile ? 28 : isTablet ? 28 : 32;
  // Icon scales with the title so the row reads as one composed unit
  // rather than icon-first / title-second. Roughly cap-height of the
  // serif h3.
  const iconSize = isMobile ? 22 : isTablet ? 22 : 24;
  return (
    <section style={{
      padding: `${padY}px ${padX}px`,
      borderTop: '0.5px solid var(--whisper)',
      borderBottom: '0.5px solid var(--whisper)',
    }}>
      <div style={innerMax(width)}>
        <div className="t-overline" style={{ marginBottom: 16 }}>What it is</div>
        <h2 style={{
          fontFamily: 'var(--serif)',
          fontSize: isMobile ? 36 : isTablet ? 44 : 56,
          fontWeight: 600, letterSpacing: '-0.03em',
          margin: isMobile ? '0 0 36px' : '0 0 48px',
          color: 'var(--ink)',
          maxWidth: 760,
          lineHeight: 1.05,
        }}>
          Three pieces, plainly told.
        </h2>
        <div style={{
          display: 'grid',
          gridTemplateColumns: isMobile ? '1fr' : 'repeat(3, 1fr)',
          gap: isMobile ? 40 : isTablet ? 40 : 56,
        }}>
          {items.map(it => (
            <div key={it.title}>
              <div style={{
                display: 'flex', alignItems: 'center', gap: 14,
                margin: '0 0 12px',
              }}>
                <Icon name={it.icon} size={iconSize} color="var(--plum)" />
                <h3 style={{
                  fontFamily: 'var(--serif)',
                  fontSize: titleSize,
                  fontWeight: 600, letterSpacing: '-0.02em',
                  margin: 0,
                  color: 'var(--ink)',
                  lineHeight: 1.1,
                }}>
                  {it.title}
                </h3>
              </div>
              <p className="t-body" style={{
                margin: 0, color: 'var(--smoke)',
                maxWidth: 360,
                fontSize: isMobile ? 16 : 17,
              }}>
                {it.body}
              </p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// 30-second log walkthrough — annotated 5 frames
function ThirtySecondLog({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 56 : isTablet ? 64 : 80;
  const steps = [
    { n: '01', label: 'Photo', body: 'Snap the bottle, the glass, the label. Or skip — words are fine too.' },
    { n: '02', label: 'Fruit', body: 'Šljiva, kajsija, dunja… twelve to start. Or write your own.' },
    { n: '03', label: 'Place', body: 'Where you are. The kafana, the home, the mountain.' },
    { n: '04', label: 'Stars', body: 'Five marks. No vocabulary tests, no flavor wheels.' },
    { n: '05', label: 'Save', body: 'Tap. Pour. Repeat.' },
  ];
  return (
    <section style={{ padding: `${padY}px ${padX}px` }}>
      <div style={innerMax(width)}>
        <div className="t-overline" style={{ marginBottom: 16 }}>The log</div>
        <h2 style={{
          fontFamily: 'var(--serif)',
          fontSize: isMobile ? 36 : isTablet ? 44 : 56,
          fontWeight: 600, letterSpacing: '-0.03em',
          margin: isMobile ? '0 0 36px' : '0 0 40px',
          color: 'var(--ink)',
          maxWidth: 760,
          lineHeight: 1.05,
        }}>
          Thirty seconds, start to finish.
        </h2>

        <div style={{
          display: 'grid',
          gridTemplateColumns: isMobile ? '1fr' : 'repeat(5, 1fr)',
          gap: isMobile ? 24 : isTablet ? 20 : 24,
          position: 'relative',
        }}>
          {steps.map((s, i) => (
            <div key={s.n} style={{ position: 'relative' }}>
              <div style={{
                display: 'flex', alignItems: 'baseline', gap: 12,
                paddingBottom: 12,
                borderBottom: '0.5px solid var(--whisper)',
                marginBottom: 14,
              }}>
                <span className="t-mono" style={{
                  fontSize: 12, fontWeight: 600,
                  color: 'var(--copper-deep)',
                  letterSpacing: '0.05em',
                }}>{s.n}</span>
                <span style={{
                  fontFamily: 'var(--sans)', fontSize: 11, fontWeight: 600,
                  letterSpacing: '0.12em', textTransform: 'uppercase',
                  color: 'var(--smoke)',
                }}>{s.label}</span>
              </div>
              <p className="t-body" style={{ margin: 0, color: 'var(--ink)', fontSize: 15, lineHeight: 1.5 }}>
                {s.body}
              </p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// Passport showcase
//
// Tablet stacks like mobile — the PassportCard is ~320pt wide and a
// 768pt viewport doesn't have room for it side-by-side with copy.
function PassportShowcase({ width = 'mobile', dark = false }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const isDesktop = width === 'desktop';
  const stacked = !isDesktop;
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 64 : isTablet ? 72 : 96;
  return (
    <section style={{
      padding: `${padY}px ${padX}px`,
      background: dark ? 'var(--d-bg)' : 'var(--honey-light)',
      borderTop: `0.5px solid ${dark ? 'var(--d-whisper)' : 'var(--whisper)'}`,
      borderBottom: `0.5px solid ${dark ? 'var(--d-whisper)' : 'var(--whisper)'}`,
    }}>
      <div style={{
        ...innerMax(width),
        display: 'grid',
        gridTemplateColumns: stacked ? '1fr' : '1fr 1fr',
        gap: stacked ? (isMobile ? 40 : 48) : 80,
        alignItems: 'center',
      }}>
        <div>
          <div className="t-overline" style={{
            marginBottom: 16,
            color: dark ? 'var(--d-smoke)' : 'var(--smoke)',
          }}>The passport</div>
          <h2 style={{
            fontFamily: 'var(--serif)',
            fontSize: isMobile ? 38 : isTablet ? 48 : 60,
            fontWeight: 600, letterSpacing: '-0.03em',
            margin: '0 0 20px',
            color: dark ? 'var(--d-text)' : 'var(--ink)',
            lineHeight: 1.05,
          }}>
            Where rakija has taken you.
          </h2>
          <p className="t-body" style={{
            margin: '0 0 24px',
            fontSize: isMobile ? 16 : 18,
            maxWidth: 460, lineHeight: 1.55,
            color: dark ? 'var(--d-smoke)' : 'var(--smoke)',
          }}>
            Cities walked, fruits tasted, countries crossed. A single card you can keep,
            share, or print. Updated quietly as you go.
          </p>
          <ul style={{
            margin: 0, padding: 0, listStyle: 'none',
            display: 'grid', gap: 10, maxWidth: 460,
          }}>
            {[
              'Map of every Balkan country',
              'Stats: glasses, cities, countries, fruits',
              'Yours alone unless you choose to share',
            ].map(li => (
              <li key={li} style={{
                display: 'flex', alignItems: 'flex-start', gap: 12,
                fontFamily: 'var(--sans)', fontSize: 15,
                color: dark ? 'var(--d-text)' : 'var(--ink)',
              }}>
                <span style={{
                  width: 6, height: 6, marginTop: 8,
                  background: dark ? 'var(--copper)' : 'var(--copper-deep)',
                  borderRadius: 999, flexShrink: 0,
                }} />
                {li}
              </li>
            ))}
          </ul>
        </div>
        <div style={{ display: 'flex', justifyContent: stacked ? 'center' : 'flex-end' }}>
          <PassportCard dark={dark} />
        </div>
      </div>
    </section>
  );
}

// Library — 12 fruits.
//   mobile  → 2 cols (cards expand to share half the viewport)
//   tablet  → 4 cols (3 rows of 4 = clean Pannonian-grid feel)
//   desktop → 6 cols, each card capped at 160px so they don't grow on
//             ultra-wide. Grid is centered when capped.
function LibrarySection({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const isDesktop = width === 'desktop';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 56 : isTablet ? 64 : 80;
  return (
    <section style={{ padding: `${padY}px ${padX}px` }}>
      <div style={innerMax(width)}>
        <div style={{ maxWidth: 760, marginBottom: isMobile ? 28 : 36 }}>
          <div className="t-overline" style={{ marginBottom: 16 }}>The library</div>
          <h2 style={{
            fontFamily: 'var(--serif)',
            fontSize: isMobile ? 32 : isTablet ? 40 : 48,
            fontWeight: 600, letterSpacing: '-0.03em',
            margin: '0 0 12px', color: 'var(--ink)',
            lineHeight: 1.05,
          }}>
            <span className="t-mono" style={{ fontSize: '0.7em', color: 'var(--copper-deep)', marginRight: 16 }}>12</span>
            fruits.
            <span className="t-mono" style={{ fontSize: '0.7em', color: 'var(--copper-deep)', margin: '0 16px 0 24px' }}>8</span>
            regions.
          </h2>
          <p className="t-body" style={{ margin: 0, color: 'var(--smoke)', fontSize: isMobile ? 16 : 18 }}>
            Curated, not exhaustive. Add what we miss; we'll learn from it.
          </p>
        </div>
        <div style={{
          display: 'grid',
          gridTemplateColumns:
            isMobile ? 'repeat(2, 1fr)' :
            isTablet ? 'repeat(4, 1fr)' :
            'repeat(6, minmax(0, 160px))',
          justifyContent: isDesktop ? 'center' : 'stretch',
          gap: isMobile ? 12 : isTablet ? 16 : 20,
        }}>
          {FRUITS.map((f) => (
            <FruitCard key={f.latin} fruit={f} />
          ))}
        </div>
      </div>
    </section>
  );
}

// Library feature — text-left, three layered phone mockups right.
//
// Mirrors the hero composition (text col + layered-phone col on
// desktop; stacked single-phone on mobile/tablet). Foreground is
// library1.png (Library tab with illustrated fruit cards); the two
// background phones (library.png + library2.png) tilt away from the
// foreground at -9° / +9°. All three are static <img> screens inside
// the same .kf-phone bezel — no interactive surface here, just the
// hero-style stack.
//
// Slots into the page after LibrarySection (the at-a-glance fruit
// grid) so the at-a-glance + the deep-dive sit as a pair, mirroring
// how Capture pairs with ThirtySecondLog and Passport pairs with
// PassportShowcase.
function LibraryFeature({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const isDesktop = width === 'desktop';
  const stacked = !isDesktop;
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 64 : isTablet ? 72 : 96;

  return (
    <section style={{
      padding: `${padY}px ${padX}px`,
      borderTop: '0.5px solid var(--whisper)',
    }}>
      <div style={{
        ...innerMax(width),
        display: 'grid',
        gridTemplateColumns: stacked ? '1fr' : '1.1fr 0.9fr',
        gap: stacked ? (isMobile ? 40 : 48) : 72,
        alignItems: 'center',
      }}>
        <div>
          <div className="t-overline" style={{ marginBottom: 16 }}>Inside the library</div>
          <h2 style={{
            fontFamily: 'var(--serif)',
            fontSize: isMobile ? 36 : isTablet ? 48 : 60,
            fontWeight: 600, letterSpacing: '-0.03em',
            margin: '0 0 20px',
            color: 'var(--ink)',
            lineHeight: 1.05,
          }}>
            Each fruit, a small essay.
          </h2>
          <p className="t-body" style={{
            margin: 0,
            fontSize: isMobile ? 16 : 18,
            maxWidth: 460, lineHeight: 1.55,
            color: 'var(--smoke)',
          }}>
            Each fruit gets its own page — story, regional variations,
            typical ABV, food pairings, the rituals. Cross-linked to
            places that pour them.
          </p>
        </div>

        {stacked ? (
          // Mobile / tablet: foreground phone only, centered, with halo.
          <div style={{ display: 'flex', justifyContent: 'center' }}>
            <div className="kf-phone-glow">
              <div className="kf-phone" style={{ width: isMobile ? 280 : 300 }}>
                <div className="kf-phone-screen" style={{ height: isMobile ? 580 : 620 }}>
                  <div className="kf-phone-notch" />
                  <img
                    src="assets/screens/library1.png"
                    alt=""
                    aria-hidden="true"
                    style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                  />
                </div>
              </div>
            </div>
          </div>
        ) : (
          // Desktop: layered three-phone composition. Same offsets the
          // hero uses (right: 320 / -150) so the two columns of the page
          // read as a coherent visual pair — both with the foreground
          // bezel right-aligned and bg phones peeking on either side.
          <div style={{
            position: 'relative',
            minHeight: 720,
            display: 'flex', justifyContent: 'flex-end', alignItems: 'center',
          }}>
            {/* Background phone — Library list, peeks upper-left */}
            <div style={{
              position: 'absolute',
              right: 320,
              top: 30,
              transform: 'rotate(-9deg)',
              transformOrigin: 'center',
              zIndex: 0,
            }}>
              <div className="kf-phone" style={{ width: 240 }}>
                <div className="kf-phone-screen" style={{ height: 500 }}>
                  <div className="kf-phone-notch" />
                  <img
                    src="assets/screens/library.png"
                    alt=""
                    aria-hidden="true"
                    style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                  />
                </div>
              </div>
            </div>

            {/* Background phone — secondary library view, peeks lower-right */}
            <div style={{
              position: 'absolute',
              right: -150,
              top: 130,
              transform: 'rotate(9deg)',
              transformOrigin: 'center',
              zIndex: 0,
            }}>
              <div className="kf-phone" style={{ width: 240 }}>
                <div className="kf-phone-screen" style={{ height: 500 }}>
                  <div className="kf-phone-notch" />
                  <img
                    src="assets/screens/library2.png"
                    alt=""
                    aria-hidden="true"
                    style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                  />
                </div>
              </div>
            </div>

            {/* Foreground phone — library1 (the Library tab), halo behind */}
            <div className="kf-phone-glow" style={{ position: 'relative', zIndex: 2 }}>
              <div className="kf-phone" style={{ width: 320 }}>
                <div className="kf-phone-screen" style={{ height: 660 }}>
                  <div className="kf-phone-notch" />
                  <img
                    src="assets/screens/library1.png"
                    alt=""
                    aria-hidden="true"
                    style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                  />
                </div>
              </div>
            </div>
          </div>
        )}
      </div>
    </section>
  );
}

// Pan-Balkan strip — Latin / Cyrillic
//   mobile  → 2 cols (5 rows × 2)
//   tablet  → 3 cols (4 rows × 3 = 12 with 1 trailing slot, 10 fit cleanly)
//   desktop → 5 cols (2 rows × 5)
function CountryStrip({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 48 : isTablet ? 56 : 72;
  const markSize = isMobile ? 84 : isTablet ? 92 : 100;
  return (
    <section style={{
      padding: `${padY}px ${padX}px`,
      borderTop: '0.5px solid var(--whisper)',
      borderBottom: '0.5px solid var(--whisper)',
      background: 'var(--cream)',
    }}>
      <div style={innerMax(width)}>
        <div className="t-overline" style={{ marginBottom: isMobile ? 32 : 40, textAlign: 'center' }}>
          Equal weight, every country
        </div>
        <div style={{
          display: 'grid',
          gridTemplateColumns:
            isMobile ? 'repeat(2, 1fr)' :
            isTablet ? 'repeat(3, 1fr)' :
            'repeat(5, 1fr)',
          gap: isMobile ? '36px 16px' : isTablet ? '40px 20px' : '56px 24px',
        }}>
          {COUNTRIES.map(c => (
            <div key={c.latin} style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center',
              textAlign: 'center', gap: 12,
            }}>
              <div style={{
                width: markSize,
                height: Math.round(markSize * 82 / 100),
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                <CountryMarkPlum id={c.id} size={markSize} />
              </div>
              <div>
                <div style={{
                  fontFamily: 'var(--serif)',
                  fontSize: isMobile ? 16 : isTablet ? 18 : 20,
                  fontWeight: 600, letterSpacing: '-0.01em',
                  color: 'var(--ink)',
                  lineHeight: 1.2,
                }}>{c.latin}</div>
                <div style={{
                  fontFamily: 'var(--serif)',
                  fontSize: isMobile ? 14 : isTablet ? 15 : 17,
                  fontWeight: 400,
                  color: 'var(--smoke)',
                  fontStyle: 'italic',
                  marginTop: 4,
                  lineHeight: 1.2,
                }}>{c.cyr}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// Plum-fill variant of CountryMark — used in the country strip so we don't
// blow the "one copper per viewport" budget on this section.
function CountryMarkPlum({ id, size = 100 }) {
  const muted = 'rgba(74,27,12,0.10)';
  const filled = 'var(--plum)';
  const stroke = 'var(--whisper)';
  const vb = window.BALKAN_VB || '0 0 320 260';
  return (
    <svg width={size} viewBox={vb} style={{ display: 'block' }}>
      {window.BALKAN_PATHS.map(c => (
        <path key={c.id} d={c.d}
          fill={c.id === id ? filled : muted}
          stroke={stroke} strokeWidth="0.5"
          strokeLinejoin="round" />
      ))}
    </svg>
  );
}

// Free forever
function FreeForever({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 72 : isTablet ? 80 : 96;
  return (
    <section style={{
      padding: `${padY}px ${padX}px`,
      textAlign: 'center',
    }}>
      <div style={innerMax(width)}>
        <h2 style={{
          fontFamily: 'var(--serif)',
          fontSize: isMobile ? 36 : isTablet ? 48 : 64,
          fontWeight: 600,
          letterSpacing: '-0.03em',
          lineHeight: 1.1,
          margin: 0,
          color: 'var(--ink)',
          maxWidth: 920, marginInline: 'auto',
        }}>
          Free.<br/>
          <span style={{ color: 'var(--smoke)' }}>No subscriptions. No ads.</span><br/>
          <span style={{ fontStyle: 'italic', color: 'var(--plum)' }}>Forever.</span>
        </h2>
      </div>
    </section>
  );
}

// Email capture section — single CTA that opens the same modal the
// hero CTA opens. The disclaimer / no-spam line lives inside the modal
// now, so the section reads as one clean confident button.
function EmailCapture({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const isTablet = width === 'tablet';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const padY = isMobile ? 56 : isTablet ? 64 : 80;
  const onFooterCtaClick = (e) => {
    if (typeof window !== 'undefined' && typeof window.openWaitlistModal === 'function') {
      e.preventDefault();
      window.openWaitlistModal('footer');
    }
  };
  return (
    <section id="signup" style={{
      padding: `${padY}px ${padX}px`,
      background: 'var(--cream)',
    }}>
      <div style={{ maxWidth: 480, marginInline: 'auto', textAlign: 'center' }}>
        <div className="t-overline" style={{ marginBottom: 16 }}>Be the first to pour</div>
        <h2 style={{
          fontFamily: 'var(--serif)',
          fontSize: isMobile ? 32 : isTablet ? 38 : 44,
          fontWeight: 600, letterSpacing: '-0.02em',
          margin: '0 0 28px', color: 'var(--ink)', lineHeight: 1.1,
        }}>
          iOS first. We'll let you know.
        </h2>
        <a
          href="#signup"
          className="kf-cta"
          onClick={onFooterCtaClick}
          style={{ fontSize: 16, padding: '14px 28px' }}
        >
          Notify me when it launches
        </a>
      </div>
    </section>
  );
}

// Footer — cream bg, 48px vertical padding, two rows w/ whisper divider above.
function Footer({ width = 'mobile' }) {
  const isMobile = width === 'mobile';
  const padX = SIDE_PAD[width] ?? SIDE_PAD.mobile;
  const links = [
    { label: 'Privacy', href: 'privacy.html' },
    { label: 'Terms', href: 'terms.html' },
    { label: 'support@kafana.app', href: 'mailto:support@kafana.app' },
  ];
  return (
    <footer style={{
      padding: `48px ${padX}px`,
      background: 'var(--cream)',
      borderTop: '0.5px solid var(--whisper)',
    }}>
      <div style={innerMax(width)}>
        {/* Row 1 */}
        <div style={{
          display: 'flex',
          flexDirection: isMobile ? 'column' : 'row',
          gap: 16,
          alignItems: isMobile ? 'flex-start' : 'center',
          justifyContent: 'space-between',
        }}>
          <Wordmark size={18} />
          <div style={{
            display: 'flex', alignItems: 'center', gap: 8,
            flexWrap: 'wrap',
          }}>
            {links.map((l, i) => (
              <Fragment key={l.label}>
                <a href={l.href} style={{
                  fontFamily: 'var(--sans)', fontSize: 14,
                  color: 'var(--ink)', textDecoration: 'none',
                }}>{l.label}</a>
                {i < links.length - 1 && (
                  <span style={{ color: 'var(--smoke)', fontSize: 14 }}>·</span>
                )}
              </Fragment>
            ))}
          </div>
        </div>
        {/* Row 2 */}
        <div style={{
          marginTop: 28,
          textAlign: 'center',
          fontFamily: 'var(--sans)', fontSize: 12,
          color: 'var(--smoke)',
        }}>
          English · Bosanski · Hrvatski · Srpski (latinica)
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, {
  Nav, Hero, Trio, ThirtySecondLog, PassportShowcase,
  LibrarySection, LibraryFeature, CountryStrip, FreeForever, EmailCapture, Footer,
  EmailForm,
});
