// site/page-platform.jsx, Platform overview + 5 feature deep dives

// ═══════════════════════════════════════════════════════════
// Platform overview (the "What we do" hub)
// ═══════════════════════════════════════════════════════════
function PagePlatform({ onNav }) {
  return (
    <div>
      <PageHero
        eyebrow="The platform"
        title="One unified system"
        titleAccent="to manage your fair."
        lead="Your fair runs on dozens of moving parts. Fairs.com brings them together in one integrated platform, websites, ticketing, social, marketing, vendors, and sponsors."
      />

      <section style={{ background: S.cream2, padding: '96px 64px', position: 'relative' }}>
        <div className="has-grain" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1320, margin: '0 auto' }}>
          {[
            { heading: 'Grow your fair', ids: ['websites', 'tickets', 'reach', 'grow'] },
            { heading: 'Run your fair', ids: ['vendors', 'sponsors'] },
          ].map((group, gi) => (
            <div key={group.heading} style={{ marginTop: gi === 0 ? 0 : 56 }}>
              <div style={{ marginBottom: 24 }}><SectionEyebrow>{group.heading}</SectionEyebrow></div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 28 }}>
                {REAL_MODULES.filter(m => group.ids.includes(m.id)).map((m) => {
                  const i = REAL_MODULES.indexOf(m);
                  const route = { websites: 'websites', tickets: 'ticketing', reach: 'social', grow: 'marketing', vendors: 'vendors', sponsors: 'sponsors' }[m.id];
                  const tilt = [-0.6, 0.4, -0.4, 0.5, -0.5, 0.45, -0.5][i];
                  return (
                    <div key={m.id} style={{
                      background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 16, padding: 32,
                      boxShadow: `5px 5px 0 0 ${i % 2 === 0 ? S.ink : S.red}`,
                      transform: `rotate(${tilt}deg)`,
                      display: 'grid', gridTemplateColumns: 'auto 1fr', gap: 24, alignItems: 'flex-start',
                    }}>
                      <div style={{
                        width: 64, height: 64, borderRadius: 14, background: S.red100,
                        display: 'flex', alignItems: 'center', justifyContent: 'center', color: S.red,
                      }}>
                        <Ico name={m.icon} size={28} strokeWidth={1.6} />
                      </div>
                      <div>
                        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, color: S.red, letterSpacing: '0.18em', textTransform: 'uppercase' }}>
                          {m.kicker} · Module №{String(i + 1).padStart(2, '0')}
                        </div>
                        <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, color: S.ink, margin: '6px 0 10px', letterSpacing: '-0.025em' }}>{m.label}</h3>
                        <p style={{ fontSize: 16, lineHeight: 1.5, color: S.ink, opacity: 0.75, margin: '0 0 16px' }}>{m.detail}</p>
                        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px 16px', marginBottom: 20 }}>
                          {m.bullets.map((b, j) => (
                            <div key={j} style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12, color: S.ink, opacity: 0.85 }}>
                              <Ico name="check" size={14} color={S.red} strokeWidth={2.6} style={{ marginTop: 2 }} />
                              <span>{b}</span>
                            </div>
                          ))}
                        </div>
                        <StubBtn size="sm" variant="outline" onClick={() => onNav(route)}>Learn about {m.label}</StubBtn>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </div>
      </section>

      <CTAStrip onNav={onNav} />
    </div>
  );
}

// ═══════════════════════════════════════════════════════════
// Feature page shell (used by all 5 sub-pages)
// ═══════════════════════════════════════════════════════════
function FeaturePage({ moduleId, mascotLine, heroTitle, heroAccent, sections = [], gallery, onNav }) {
  const m = REAL_MODULES.find(x => x.id === moduleId);
  const others = REAL_MODULES.filter(x => x.id !== moduleId);
  const ROUTE = { websites: 'websites', tickets: 'ticketing', reach: 'social', grow: 'marketing', vendors: 'vendors', sponsors: 'sponsors' };

  return (
    <div>
      {/* Hero with cow mascot speech */}
      <section style={{ padding: '64px 64px 80px', position: 'relative', overflow: 'hidden' }}>
        <div className="has-grain light" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1320, margin: '0 auto', display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 64, alignItems: 'center' }}>
          <div>
            <SectionEyebrow>{m.kicker} · Module №{String(REAL_MODULES.findIndex(x => x.id === moduleId) + 1).padStart(2, '0')} of {REAL_MODULES.length}</SectionEyebrow>
            <h1 style={{
              fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 56, lineHeight: 0.95,
              letterSpacing: '-0.035em', color: S.ink, margin: '20px 0 16px',
            }}>{heroTitle || m.label.split(' ')[0]} <em style={{ fontStyle: 'italic', color: S.red, fontWeight: 500 }}>{heroAccent || 'that just works.'}</em></h1>
            <p style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontSize: 22, color: S.ink, opacity: 0.85, margin: '0 0 12px', maxWidth: 560 }}>{m.blurb}</p>
            <p style={{ fontSize: 16, lineHeight: 1.55, color: S.ink, opacity: 0.72, maxWidth: 560, margin: 0 }}>{m.detail}</p>
            <div style={{ display: 'flex', gap: 12, marginTop: 36 }}>
              <StubBtn size="lg" onClick={() => onNav('contact')}>Book a demo</StubBtn>
              <StubBtn size="lg" variant="outline" icon={false} onClick={() => onNav('platform')}>See all modules →</StubBtn>
            </div>
          </div>
          <div style={{ position: 'relative', justifySelf: 'start' }}>
            <Cow size={260} rotate={-3} flip />
            <div style={{ position: 'absolute', top: 16, left: 'calc(100% + 16px)', width: 'max-content', maxWidth: 280 }}>
              <SpeechBubble tail="left" tilt={3} style={{ maxWidth: 'none', display: 'block' }}>{mascotLine}</SpeechBubble>
            </div>
          </div>
        </div>
      </section>

      {/* Optional gallery (product UI mosaic) */}
      {gallery && (
        <section style={{ background: S.cream2, padding: '96px 64px', position: 'relative' }}>
          <div className="has-grain" style={{ position: 'absolute', inset: 0 }} />
          <div style={{ position: 'relative', maxWidth: 1320, margin: '0 auto' }}>
            {gallery}
          </div>
        </section>
      )}

      {/* Feature detail sections */}
      {sections.map((sec, i) => (
        <section key={i} style={{ background: i % 2 === 0 ? S.cream : S.cream2, padding: '88px 64px', position: 'relative' }}>
          <div className="has-grain light" style={{ position: 'absolute', inset: 0 }} />
          <div style={{ position: 'relative', maxWidth: 1280, margin: '0 auto', display: 'grid', gridTemplateColumns: i % 2 === 0 ? '1fr 1fr' : '1fr 1fr', gap: 64, alignItems: 'center' }}>
            <div style={{ order: i % 2 === 0 ? 0 : 1 }}>
              <SectionEyebrow>{sec.tag}</SectionEyebrow>
              <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, lineHeight: 1.05, letterSpacing: '-0.025em', color: S.ink, margin: '16px 0 16px' }}>
                {sec.title} {sec.titleAccent && <em style={{ fontStyle: 'italic', color: S.red }}>{sec.titleAccent}</em>}
              </h2>
              <p style={{ fontSize: 16, lineHeight: 1.55, color: S.ink, opacity: 0.72, margin: '0 0 24px' }}>{sec.body}</p>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {sec.bullets.map((b, j) => (
                  <div key={j} style={{ display: 'flex', gap: 12, alignItems: 'flex-start', fontSize: 16, color: S.ink }}>
                    <div style={{ marginTop: 2, width: 20, height: 20, borderRadius: 999, background: S.red100, display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
                      <Ico name="check" size={12} color={S.red} strokeWidth={2.6} />
                    </div>
                    <span><b style={{ fontWeight: 700 }}>{b.title}</b> {b.body}</span>
                  </div>
                ))}
              </div>
            </div>
            <div style={{ order: i % 2 === 0 ? 1 : 0 }}>{sec.visual}</div>
          </div>
        </section>
      ))}

      {/* Cross-module strip */}
      <section style={{ background: S.cream3, padding: '88px 64px', position: 'relative' }}>
        <div className="has-grain" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1280, margin: '0 auto' }}>
          <div style={{ textAlign: 'center', marginBottom: 40 }}>
            <SectionEyebrow>Pairs well with</SectionEyebrow>
            <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, marginTop: 12, letterSpacing: '-0.025em', color: S.ink }}>
              All your modules <em style={{ fontStyle: 'italic', color: S.red }}>talk to each other.</em>
            </h3>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
            {others.map((o, j) => (
              <button key={o.id} onClick={() => onNav(ROUTE[o.id])} style={{
                background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 14, padding: 24,
                cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit',
                boxShadow: `4px 4px 0 0 ${S.ink}`,
                display: 'flex', flexDirection: 'column', gap: 10,
              }}>
                <Ico name={o.icon} size={22} color={S.red} strokeWidth={1.6} />
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.red, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase' }}>{o.kicker}</div>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 22, color: S.ink, letterSpacing: '-0.02em' }}>{o.label}</div>
                <div style={{ fontSize: 12, color: S.ink, opacity: 0.72, lineHeight: 1.5 }}>{o.blurb}</div>
                <div style={{ marginTop: 6, fontSize: 12, fontWeight: 700, color: S.red }}>Learn more →</div>
              </button>
            ))}
          </div>
        </div>
      </section>

      <CTAStrip onNav={onNav} />
    </div>
  );
}

// ═══════════════════════════════════════════════════════════
// Websites
// ═══════════════════════════════════════════════════════════
function PageWebsites({ onNav }) {
  const sections = [
    {
      tag: 'Built for fairs',
      title: 'Purpose-built for fairs,',
      titleAccent: 'down to the code.',
      body: 'Not a generic template with a fair theme painted on. Every site is built around how your fair actually runs — and backed by custom code written for your specific needs.',
      bullets: [
        { title: 'Highlighted events', body: 'Put your marquee events and lineup front and center.' },
        { title: 'Daily schedule', body: 'Multi-stage, day-by-day, easy to keep current all season.' },
        { title: 'Form submissions', body: 'Capture vendor apps, sponsor interest, and contact requests on-site.' },
        { title: 'Custom code', body: 'Written for your fair\'s specific use case, not one-size-fits-all.' },
      ],
      visual: <ProductShot src="assets/product/website-example.webp" alt="A fair website built on Fairs.com, shown on a tablet and phone" tilt={-0.4} />,
    },
    {
      tag: 'You edit it yourself',
      title: 'Your team. Your team\'s pace.',
      titleAccent: 'No agency in the loop.',
      body: 'Edit any page yourself with built-in rollback — mobile-first, ADA-minded, SEO-optimized, all the technical work done for you.',
      bullets: [
        { title: 'Drag-and-drop editor', body: 'Move, add, and restyle anything — no code required.' },
        { title: 'Edit without fear', body: 'Undo any change, anytime.' },
        { title: 'Point-and-click comments', body: 'Flag anything on the page and it goes straight to our developer to make the change.' },
        { title: 'Dynamic landing pages', body: 'Auto-built pages that help you show up in more searches.' },
        { title: 'Built for accessibility', body: 'Made with ADA standards in mind.' },
      ],
      visual: <ProductShot src="assets/product/website-editor.avif" alt="The Fairs.com drag-and-drop editor showing the Smithville County Fair website on a tablet and phone" tilt={0.4} />,
    },
  ];
  return <FeaturePage moduleId="websites" onNav={onNav}
    mascotLine={<><em style={{ fontStyle: 'italic', color: S.red }}>Your site. Your way.</em><br />Fair-budget-friendly pricing.</>}
    sections={sections} />;
}

// ═══════════════════════════════════════════════════════════
// Ticketing
// ═══════════════════════════════════════════════════════════
function PageTicketing({ onNav }) {
  const sections = [
    {
      tag: 'Every ticket type',
      title: 'Day passes, season tickets, flex, bundles',
      titleAccent: 'all in one cart.',
      body: 'Sell the way your fair actually operates. Reserved seats for the grandstand. Bundled carnival packs. Multi-day flex passes. All from one ticket stack.',
      bullets: [
        { title: 'Reserved + GA', body: 'Grandstand seating with stadium-style seat maps.' },
        { title: 'Multi-day passes', body: '2-day, 4-day, and full-week passes.' },
        { title: 'Bundles & packs', body: 'Combine GA + carnival + parking in one.' },
        { title: 'Apple/Google Wallet', body: 'Tickets land in your guests\' phones automatically.' },
      ],
      visual: (
        <div style={{
          transform: 'rotate(-0.4deg)', borderRadius: 16, border: `1.5px solid ${S.ink}`,
          boxShadow: `8px 8px 0 0 ${S.red}`, background: S.cream,
          padding: 56, display: 'flex', justifyContent: 'center', alignItems: 'center',
        }}>
          <img
            src="assets/product/ticketing-wallet-pass.png"
            alt="A Fairs.com admission pass in a phone wallet, showing the ticket holder's name, section, row, seat, price, and a scannable QR code"
            style={{ display: 'block', width: '100%', maxWidth: 250, height: 'auto' }}
          />
        </div>
      ),
    },
    {
      tag: 'Gate app',
      title: 'The gate app,',
      titleAccent: 'made simple.',
      body: 'A gate interface built for minimal clicks — learned and mastered in minutes by volunteers, staffing agencies, and seasonal gate workers. No training day required.',
      bullets: [
        { title: 'Built for volunteers', body: 'Minimal clicks, mastered in minutes by anyone you put on the gate.' },
        { title: 'Cash calculator', body: 'Keeps every till accurate through close-out.' },
        { title: 'Quick QR scan', body: 'Secure scanning that keeps your lines moving.' },
        { title: 'Buyer lookup', body: 'Find any purchase, so a lost ticket is never a lost guest.' },
      ],
      visual: <ProductShot src="assets/product/ticketing-sell-scan.webp" alt="The Fairs.com app on two phones: scanning a ticket QR code and selling tickets at the gate with card or cash" tilt={-0.4} />,
    },
    {
      tag: 'More than event ticketing',
      title: 'Reserved seating,',
      titleAccent: 'mapped to your grandstand and grounds.',
      body: 'Stadium-style reserved seating with seat-level pricing and accessible locations, plus an interactive grounds map your guests can open right on their phone.',
      bullets: [
        { title: 'Stadium-style seat maps', body: 'Sections, rows, and seats, priced per seat.' },
        { title: 'Buy on any device', body: 'Optimized for mobile and desktop purchases.' },
        { title: 'Accessible locations', body: 'Handicap seating built into the map.' },
        { title: 'Interactive grounds map', body: 'Camping, vendors, and anything else you need to sell a spot to.' },
      ],
      visual: <ProductShot src="assets/product/ticketing-seatmap.png" alt="A reserved-seating seat map with a selected seat, next to a phone showing an interactive fairgrounds map on app.fairs.com" tilt={0.4} />,
    },
    {
      tag: 'Built for treasurers',
      title: 'Reports built for fair treasurers,',
      titleAccent: 'by fair treasurers.',
      body: 'Every report is shaped around how fairs actually close the books — so the numbers reconcile the way your treasurer expects, not the way generic software guesses.',
      bullets: [
        { title: 'Sales, every way you slice it', body: 'By channel, ticket level, date & time, gate, payment method, and more.' },
        { title: 'Custom reporting', body: 'Need a cut we don\'t ship? We build the report around your books.' },
        { title: 'Payout report', body: 'See exactly which transactions roll up to each deposit in your account.' },
      ],
      visual: <ProductShot src="assets/product/ticketing-report.webp" alt="A Fairs.com event summary report showing sales by product and sales by channel" tilt={-0.3} />,
    },
  ];
  return <FeaturePage moduleId="tickets" onNav={onNav}
    mascotLine={<><em style={{ fontStyle: 'italic', color: S.red }}>Fast-moving gates.</em><br />Happy staff. Happy customers.</>}
    sections={sections} />;
}

// ═══════════════════════════════════════════════════════════
// Social
// ═══════════════════════════════════════════════════════════
function PageSocial({ onNav }) {
  const sections = [
    {
      tag: 'One inbox · every channel',
      title: 'Instagram, Facebook, TikTok,',
      titleAccent: 'one queue.',
      body: 'Manage every message from every channel without bouncing between five tabs. Replies sync to the right account; you never have to remember which login you used.',
      bullets: [
        { title: 'Unified inbox', body: 'DMs, comments, mentions, all in one place.' },
        { title: 'Approval queues', body: 'Approve every post from your team before it goes out.' },
        { title: 'Performance metrics', body: 'See which posts resonate with your community.' },
        { title: 'Evergreen content scheduling', body: 'Queue evergreen posts once and let them run all season.' },
      ],
      visual: <SocialInboxMock />,
    },
    {
      tag: 'Schedule weeks ahead',
      title: 'Plan the lead-up,',
      titleAccent: 'live the event.',
      body: 'Schedule your entire pre-fair social calendar in one sitting. We post; you walk the midway.',
      bullets: [
        { title: 'Content library', body: 'Pull from Canva, Drive, and your archive.' },
        { title: 'Post everywhere', body: 'Facebook, Instagram, X, and more in one click.' },
        { title: 'AI captions', body: 'On-brand posts drafted in two taps.' },
        { title: 'One-screen replies', body: 'Respond to every connected social in one place.' },
      ],
      visual: <SocialCalendarMock />,
    },
  ];
  return <FeaturePage moduleId="reach" onNav={onNav}
    mascotLine={<>One scheduler.<br /><em style={{ fontStyle: 'italic', color: S.red }}>Five channels.</em><br />Zero "what did I post?"</>}
    sections={sections} />;
}

function SocialInboxMock() {
  const items = [
    ['Instagram DM', 'Liz from @bouquetbbq', 'Hey, can we get a power outlet near our booth?', '12m'],
    ['Facebook comment', 'Mark Whitley', 'Are dogs allowed Saturday?', '24m'],
    ['Email', 'Sarah K., vendor', 'Insurance attached for booth A-14', '1h'],
    ['TikTok comment', '@fairgoer22', 'will derby tickets sell out??', '2h'],
  ];
  return (
    <div style={{ background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 14, padding: 8, boxShadow: '0 18px 36px rgba(40,30,20,0.12)' }}>
      <div style={{ padding: '12px 14px', fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 16, color: S.ink, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <span>Inbox · all channels</span>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.red, fontWeight: 700, letterSpacing: '0.16em' }}>6 UNREAD</span>
      </div>
      {items.map(([ch, who, msg, t], i) => (
        <div key={i} style={{ padding: '14px', borderTop: `1px dashed ${S.border}`, display: 'grid', gridTemplateColumns: 'auto 1fr auto', gap: 12, alignItems: 'flex-start' }}>
          <div style={{ width: 36, height: 36, borderRadius: 999, background: S.kraft, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 12, color: S.ink }}>
            {who.match(/[A-Z]/g)?.slice(0,2).join('') || '@'}
          </div>
          <div>
            <div style={{ display: 'flex', gap: 8, alignItems: 'baseline' }}>
              <span style={{ fontSize: 16, fontWeight: 600, color: S.ink }}>{who}</span>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.red, fontWeight: 700, letterSpacing: '0.16em' }}>{ch}</span>
            </div>
            <div style={{ fontSize: 12, color: S.ink, opacity: 0.78, marginTop: 2 }}>{msg}</div>
          </div>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute }}>{t}</span>
        </div>
      ))}
    </div>
  );
}

function SocialCalendarMock() {
  const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
  const dots = [
    [0,1,2], [1,3], [0,1,2,3], [2], [0,1,3], [0,1,2,3], [],
  ];
  const chColors = [S.red, '#3357BB', '#000', '#1F8A5B']; // IG, FB, TikTok, Email
  return (
    <div style={{ background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 14, padding: 22, boxShadow: '0 18px 36px rgba(40,30,20,0.12)' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
        <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 16, color: S.ink }}>Week of Sep 8 · 18 posts scheduled</div>
        <div style={{ display: 'flex', gap: 10, fontSize: 12, color: S.mute }}>
          {['IG', 'FB', 'TT', 'Email'].map((c, i) => (
            <div key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
              <span style={{ width: 8, height: 8, borderRadius: 999, background: chColors[i] }} />{c}
            </div>
          ))}
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 8 }}>
        {days.map((d, i) => (
          <div key={i} style={{ padding: 12, background: S.cream2, borderRadius: 8, minHeight: 120, border: `1px solid ${S.border}` }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute, fontWeight: 700, letterSpacing: '0.14em' }}>{d}</div>
            <div style={{ marginTop: 8, display: 'flex', flexDirection: 'column', gap: 6 }}>
              {dots[i].map(j => (
                <div key={j} style={{ display: 'flex', gap: 6, alignItems: 'center', fontSize: 12, color: S.ink }}>
                  <span style={{ width: 6, height: 6, borderRadius: 999, background: chColors[j] }} />
                  <span style={{ opacity: 0.75 }}>{['Derby promo', 'Vendor spotlight', '4-H winners', 'Carnival pack'][j]}</span>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════
// Marketing
// ═══════════════════════════════════════════════════════════
function PageMarketing({ onNav }) {
  const sections = [
    {
      tag: 'Email + SMS marketing',
      title: 'Email marketing made',
      titleAccent: 'for event organizers.',
      body: 'Our email and SMS marketing is made for event organizers — wired straight to your ticket sales to take your revenue to the next level and tie every dollar back to the send.',
      bullets: [
        { title: 'Sales attribution', body: 'Track sales back to each email campaign, dollar for dollar.' },
        { title: 'Email + SMS', body: 'One composer, two channels, deduped sending.' },
        { title: 'Revenue per send', body: 'See exactly how much each blast made you.' },
        { title: 'Drip automations', body: 'Welcome flows for new buyers, reminder flows for old.' },
      ],
      visual: <CampaignMock />,
    },
    {
      tag: 'Know what sold the ticket',
      title: 'See the exact ad that',
      titleAccent: 'sold the ticket.',
      body: 'Tag a link on any ad, post, email, or text, and we tie the ticket sales right back to it. You see which ad actually filled the gate, not just which one got clicks.',
      bullets: [
        { title: 'Tagged links', body: 'Drop a tracked link on any ad, post, email, or text.' },
        { title: 'Ad-to-ticket', body: 'See the exact ad that drove each purchase.' },
        { title: 'Email + text too', body: 'The same tracking works on every campaign you send.' },
        { title: 'No spreadsheets', body: 'Sales tie back on their own, nothing to reconcile by hand.' },
      ],
      visual: <AdToTicketMock />,
    },
  ];
  return <FeaturePage moduleId="grow" onNav={onNav}
    mascotLine={<>Stop sending the same email<br />to everyone, try a <em style={{ fontStyle: 'italic', color: S.red }}>segment.</em></>}
    sections={sections} />;
}

function CampaignMock() {
  return (
    <div style={{ background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 14, padding: 22, boxShadow: '0 18px 36px rgba(40,30,20,0.12)' }}>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute, fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase' }}>Campaign · Early bird carnival pack</div>
      <div style={{ display: 'flex', gap: 24, alignItems: 'flex-end', marginTop: 10 }}>
        <div>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 36, fontWeight: 500, color: S.ink, letterSpacing: '-0.02em', lineHeight: 1 }}>$84,210</div>
          <div style={{ fontSize: 12, color: S.mute }}>Revenue · 1 send · SMS + email</div>
        </div>
        <div style={{ flex: 1 }}>
          <svg viewBox="0 0 240 70" style={{ width: '100%' }}>
            <path d="M0,60 L20,55 L40,52 L60,46 L80,44 L100,36 L120,32 L140,28 L160,22 L180,18 L200,14 L220,10 L240,6" stroke={S.red} strokeWidth="2.5" fill="none" />
          </svg>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute, letterSpacing: '0.1em' }}>OPEN 48% · CTR 12% · CONV 4.2%</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginTop: 18 }}>
        {[['Segment', "Last year's buyers"], ['Sent', '18,402'], ['Revenue/send', '$4.57']].map(([k, v], i) => (
          <div key={i} style={{ padding: 12, background: S.cream2, borderRadius: 8 }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase' }}>{k}</div>
            <div style={{ fontSize: 16, color: S.ink, fontWeight: 600, marginTop: 4 }}>{v}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

function AdToTicketMock() {
  const rows = [
    ['Facebook ad',    'Derby Night promo',        '214 tickets', '$6,420'],
    ['Instagram post', '4-H winners reel',         '96 tickets',  '$2,880'],
    ['Text blast',     'Early-bird carnival pack', '173 tickets', '$5,190'],
    ['Email',          'Opening weekend reminder', '142 tickets', '$4,260'],
  ];
  return (
    <div style={{ background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 14, padding: 22, boxShadow: '0 18px 36px rgba(40,30,20,0.12)' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 16 }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute, fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase' }}>Where the tickets came from</div>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.red, fontWeight: 700, letterSpacing: '0.12em' }}>BY AD</div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {rows.map(([ch, name, tix, rev], i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'center', padding: '12px 14px', background: S.cream2, borderRadius: 10, border: `1px solid ${S.border}` }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.red, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase' }}>{ch}</div>
              <div style={{ fontSize: 16, color: S.ink, fontWeight: 600, marginTop: 2 }}>{name}</div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 600, color: S.ink, letterSpacing: '-0.01em' }}>{rev}</div>
              <div style={{ fontSize: 12, color: S.mute }}>{tix}</div>
            </div>
          </div>
        ))}
      </div>
      <div style={{ marginTop: 14, paddingTop: 12, borderTop: `1px dashed ${S.border}`, display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: S.mute }}>
        <Ico name="check" size={14} color={S.red} strokeWidth={2.6} /> Every sale traced to the exact ad that drove it.
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════
// Kiosks + Access Control (OPTIONAL hardware — never required)
// Standalone page (not FeaturePage): the 5-module shell auto-numbers
// "Module №X of 5" and renders a cross-module strip, neither of which
// fits an optional add-on. Built from the shared atoms instead.
// ═══════════════════════════════════════════════════════════
function PageKiosks({ onNav }) {
  const offerings = [
    {
      img: 'assets/hardware/kiosk.jpg', lift: true,
      icon: 'store',
      kicker: 'Self-serve',
      name: 'Kiosks',
      blurb: 'Let guests buy, upgrade, and pick up tickets themselves, right at the gate.',
      bullets: [
        'Buy day passes, upgrades, and add-ons on the spot',
        'Will-call and reprint pickup without a staffed booth',
        'Takes card, contactless, and cash where you want it',
        'Branded to your fair, running your live ticket catalog',
      ],
    },
    {
      img: 'assets/hardware/ultraq-pedestal.jpg',
      icon: 'shield',
      kicker: 'Access control',
      name: 'Gated entry',
      blurb: 'Decide who gets in, where they can go, and when, down to the lane.',
      bullets: [
        'Zoned access for grandstand, VIP, backstage, and camping',
        'Wristband, credential, and season-pass support',
        'Staff and vendor passes with their own rules',
        'Open, close, or re-route any lane from the office',
      ],
    },
    {
      img: 'assets/hardware/ultraq-amt.png',
      icon: 'gate',
      kicker: 'Validated entry',
      name: 'Turnstiles',
      blurb: 'Scan-to-spin entry that counts every head and keeps the line honest.',
      bullets: [
        'The same ticket scan you use on phones, wired to the gate',
        'Accurate, real-time headcount by gate and lane',
        'Anti-passback stops one ticket from working twice',
        'Pairs with the turnstiles you already have where we can',
      ],
    },
  ];

  return (
    <div>
      {/* ── Hero ─────────────────────────────────────────── */}
      <section style={{ padding: '64px 64px 72px', position: 'relative', overflow: 'hidden' }}>
        <div className="has-grain light" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1320, margin: '0 auto', display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 64, alignItems: 'center' }}>
          <div>
            <SectionEyebrow>Platform · Optional hardware</SectionEyebrow>
            <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 56, lineHeight: 0.98, letterSpacing: '-0.035em', color: S.ink, margin: '20px 0 16px' }}>
              Kiosks &amp; access control, <em style={{ fontStyle: 'italic', color: S.red, fontWeight: 500 }}>when you want them.</em>
            </h1>
            <p style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontSize: 22, color: S.ink, opacity: 0.85, margin: '0 0 12px', maxWidth: 580 }}>
              Your fairgrounds, your call.
            </p>
            <p style={{ fontSize: 16, lineHeight: 1.55, color: S.ink, opacity: 0.72, maxWidth: 580, margin: 0 }}>
              Fairs.com runs end-to-end on the phones your gate staff already carry. Self-serve kiosks, turnstiles, and gated entry are here for the day you want them, never a box you have to buy to get started.
            </p>
            <div style={{ display: 'flex', gap: 12, marginTop: 36, flexWrap: 'wrap' }}>
              <StubBtn size="lg" onClick={() => onNav('contact')}>Book a demo</StubBtn>
            </div>
          </div>
          <div style={{ position: 'relative', justifySelf: 'center' }}>
            <KioskPhoto />
          </div>
        </div>
      </section>

      {/* ── "You don't need any of this" reassurance band ── */}
      <section style={{ background: S.ink, padding: '72px 64px', position: 'relative', overflow: 'hidden' }}>
        <div style={{ position: 'absolute', bottom: -120, left: -80, width: 360, height: 360, borderRadius: '50%', background: S.red, opacity: 0.16, filter: 'blur(60px)' }} />
        <div style={{ position: 'relative', maxWidth: 1100, margin: '0 auto', textAlign: 'center' }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, color: S.red, letterSpacing: '0.2em', textTransform: 'uppercase' }}>★ First, the important part ★</div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, lineHeight: 1.12, letterSpacing: '-0.03em', color: S.cream, margin: '16px auto 14px', maxWidth: 760 }}>
            You don't need a single piece of hardware <em style={{ fontStyle: 'italic', color: S.red }}>to run your fair.</em>
          </h2>
          <p style={{ fontSize: 16, lineHeight: 1.6, color: 'rgba(253,249,240,0.72)', maxWidth: 640, margin: '0 auto 36px' }}>
            Every gate can run on an iPhone or iPad your team already owns. Kiosks and turnstiles are an upgrade for busier gates and longer lines, not the cost of getting started.
          </p>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, maxWidth: 880, margin: '0 auto' }}>
            {[
              ['Start on phones', 'Zero hardware, $0 up front. Hand a staffer a phone and scan.'],
              ['Add it per gate', 'Bring in a kiosk or turnstile gate by gate, season by season.'],
              ['Mix and match', 'Phones at the side gate, turnstiles at the main, all one system.'],
            ].map(([t, b], i) => (
              <div key={i} style={{ background: S.ink2, border: `1px solid ${S.borderD}`, borderRadius: 14, padding: 22, textAlign: 'left' }}>
                <div style={{ display: 'inline-flex', width: 34, height: 34, borderRadius: 8, background: 'rgba(255,54,54,0.16)', color: S.red, alignItems: 'center', justifyContent: 'center', marginBottom: 12 }}>
                  <Ico name="check" size={18} strokeWidth={2.6} />
                </div>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 22, color: S.cream, letterSpacing: '-0.015em' }}>{t}</div>
                <div style={{ fontSize: 12, color: 'rgba(253,249,240,0.66)', marginTop: 6, lineHeight: 1.5 }}>{b}</div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ── The 3 hardware offerings ──────────────────────── */}
      <section style={{ background: S.cream2, padding: '96px 64px', position: 'relative' }}>
        <div className="has-grain" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1320, margin: '0 auto' }}>
          <div style={{ textAlign: 'center', marginBottom: 44 }}>
            <SectionEyebrow>On-site hardware</SectionEyebrow>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, marginTop: 12, letterSpacing: '-0.025em', color: S.ink }}>
              Three ways to <em style={{ fontStyle: 'italic', color: S.red }}>level up the gate.</em>
            </h2>
            <p style={{ fontSize: 16, color: S.ink, opacity: 0.72, maxWidth: 600, margin: '12px auto 0' }}>
              Add any one, any two, or all three. Each runs on the same tickets and the same reporting you already use.
            </p>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 24 }}>
            {offerings.map((o, i) => (
              <div key={o.name} style={{
                background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 16, overflow: 'hidden',
                boxShadow: `5px 5px 0 0 ${i === 1 ? S.red : S.ink}`,
                display: 'flex', flexDirection: 'column',
              }}>
                {/* Hardware photo header — renders multiply onto the cream so it sits in the brand world */}
                <div style={{ position: 'relative', height: 210, background: S.cream, borderBottom: `1.5px solid ${S.ink}`, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
                  <img src={o.img} alt={o.name} style={{ maxHeight: '90%', maxWidth: '76%', objectFit: 'contain', mixBlendMode: 'multiply', filter: o.lift ? 'brightness(1.07)' : 'none', display: 'block' }} />
                  <span style={{ position: 'absolute', top: 12, right: 12, fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, color: S.ink, opacity: 0.65, letterSpacing: '0.14em', textTransform: 'uppercase', background: 'rgba(253,249,240,0.9)', border: `1px solid ${S.border}`, borderRadius: 999, padding: '4px 10px' }}>Optional</span>
                </div>
                {/* Body */}
                <div style={{ padding: 28, display: 'flex', flexDirection: 'column', flex: 1 }}>
                  <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, color: S.red, letterSpacing: '0.16em', textTransform: 'uppercase' }}>{o.kicker}</div>
                  <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, color: S.ink, margin: '4px 0 10px', letterSpacing: '-0.025em' }}>{o.name}</h3>
                  <p style={{ fontSize: 16, lineHeight: 1.5, color: S.ink, opacity: 0.75, margin: '0 0 18px' }}>{o.blurb}</p>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 'auto' }}>
                    {o.bullets.map((b, j) => (
                      <div key={j} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', fontSize: 12, color: S.ink, opacity: 0.85 }}>
                        <Ico name="check" size={14} color={S.red} strokeWidth={2.6} style={{ marginTop: 2, flex: '0 0 auto' }} />
                        <span>{b}</span>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ── Access-control hardware (Fairs.com × Alvarado) ── */}
      <section style={{ background: S.cream, padding: '96px 64px', position: 'relative' }}>
        <div className="has-grain light" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1280, margin: '0 auto' }}>
          <div style={{ textAlign: 'center', marginBottom: 44 }}>
            <SectionEyebrow>Fairs.com hardware · in partnership with Alvarado</SectionEyebrow>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, marginTop: 12, letterSpacing: '-0.025em', color: S.ink }}>
              Turnstiles to pedestals, <em style={{ fontStyle: 'italic', color: S.red }}>built on the gold standard.</em>
            </h2>
            <p style={{ fontSize: 16, color: S.ink, opacity: 0.72, maxWidth: 700, margin: '12px auto 0', lineHeight: 1.6 }}>
              Our turnstiles, pedestals, and validators are engineered in partnership with Alvarado, the gold standard in security and access control. From barrier-free pedestals to motorized turnstiles, every device connects to the Fairs.com platform natively over DirectConnect. Add our own self-serve kiosk, and every one runs the same tickets, the same scan, and the same live reporting, with no middleware in between.
            </p>
          </div>
          {[
            {
              img: 'assets/hardware/kiosk.jpg', lift: true,
              kicker: 'Automated kiosk',
              name: 'iPad-powered kiosk',
              tagline: 'Self-serve ticket sales, right at the gate.',
              specs: [
                ['Function', 'Self-serve ticket sales'],
                ['Ticket types', 'General admission + reserved seating'],
                ['Payments', 'Credit, debit, and Apple Pay'],
                ['Platform', 'iPad-powered, custom-branded'],
              ],
            },
            {
              img: 'assets/hardware/ultraq-pedestal.jpg', alvarado: true,
              kicker: 'Barrier-free pedestal',
              name: 'UltraQ Pedestal',
              tagline: 'Portable validation, no barrier.',
              specs: [
                ['Form factor', 'Barrier-free, fully portable'],
                ['Credentials', 'Printed, digital, and NFC'],
                ['Display', 'Bright color, custom-branded'],
                ['Battery', '~12 hours, fully wireless'],
                ['Mobility', 'Rolling dolly + hand grip'],
                ['Finish', 'Powder-coat color options'],
              ],
            },
            {
              img: 'assets/hardware/ultraq-amt.png', alvarado: true,
              kicker: 'Motorized turnstile',
              name: 'UltraQ AMT',
              tagline: 'Validated scan-to-spin entry.',
              specs: [
                ['Throughput', 'Up to 30 guests / lane / min'],
                ['Display', '7-inch guest touchscreen'],
                ['Credentials', '1D/2D barcode · RFID · NFC wallets'],
                ['Egress', 'Drop-arm, switchable entry / exit'],
                ['Power', 'Fixed install or battery + Wi-Fi'],
              ],
            },
          ].map((p, i) => (
            <div key={p.name} className="alv-spec-row" style={{
              display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 56, alignItems: 'center',
              padding: '44px 0', borderTop: i > 0 ? `1px dashed ${S.border}` : 'none',
            }}>
              {/* Product render */}
              <div style={{ order: i % 2 === 0 ? 0 : 1, display: 'flex', alignItems: 'center', justifyContent: 'center', background: S.cream2, borderRadius: 20, padding: 28, minHeight: 320 }}>
                <img src={p.img} alt={p.name} style={{ maxHeight: 290, maxWidth: '64%', objectFit: 'contain', mixBlendMode: 'multiply', filter: p.lift ? 'brightness(1.07)' : 'none', display: 'block' }} />
              </div>
              {/* Spec sheet */}
              <div style={{ order: i % 2 === 0 ? 1 : 0 }}>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, color: S.red, letterSpacing: '0.16em', textTransform: 'uppercase' }}>{p.kicker}</div>
                <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, color: S.ink, margin: '4px 0 4px', letterSpacing: '-0.025em' }}>{p.name}</h3>
                <p style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontSize: 18, color: S.ink, opacity: 0.7, margin: '0 0 20px' }}>{p.tagline}</p>
                <div style={{ borderTop: `1.5px solid ${S.ink}` }}>
                  {p.specs.map(([label, value], j) => (
                    <div key={j} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 24, padding: '12px 2px', borderBottom: `1px dashed ${S.border}` }}>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, color: S.mute, letterSpacing: '0.1em', textTransform: 'uppercase', flex: '0 0 auto' }}>{label}</span>
                      <span style={{ fontSize: 16, color: S.ink, fontWeight: 600, textAlign: 'right' }}>{value}</span>
                    </div>
                  ))}
                </div>
                {p.alvarado && (
                  <p style={{ margin: '18px 0 0', fontSize: 13, lineHeight: 1.55, color: S.mute }}>
                    <span style={{ color: S.red, fontWeight: 700 }}>★ </span>
                    Manufactured by <b style={{ color: S.ink, fontWeight: 700 }}>Alvarado</b>, the leading provider of entry control to large events across the globe.
                  </p>
                )}
              </div>
            </div>
          ))}
        </div>
      </section>

      {/* ── Same-platform tie-in ──────────────────────────── */}
      <section style={{ background: S.cream2, padding: '88px 64px', position: 'relative' }}>
        <div className="has-grain light" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1280, margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 64, alignItems: 'center' }}>
          <div>
            <SectionEyebrow>One system, not a bolt-on</SectionEyebrow>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, lineHeight: 1.05, letterSpacing: '-0.025em', color: S.ink, margin: '16px 0 16px' }}>
              The same tickets. The same scan. <em style={{ fontStyle: 'italic', color: S.red }}>The same reports.</em>
            </h2>
            <p style={{ fontSize: 16, lineHeight: 1.55, color: S.ink, opacity: 0.72, margin: '0 0 24px' }}>
              Hardware isn't a separate world to manage. A turnstile reads the exact ticket your gate staff scan by phone, and every entry lands in the same live dashboard, so your numbers stay in one place.
            </p>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              {[
                ['Nothing new to learn', 'Your catalog, scans, and reports work exactly as they do today.'],
                ['Live headcount everywhere', 'Phone gates and turnstiles feed one real-time count.'],
                ['Reconciles itself', 'Every entry and sale ties back to the same payout report.'],
              ].map(([t, b], i) => (
                <div key={i} style={{ display: 'flex', gap: 12, alignItems: 'flex-start', fontSize: 16, color: S.ink }}>
                  <div style={{ marginTop: 2, width: 20, height: 20, borderRadius: 999, background: S.red100, display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
                    <Ico name="check" size={12} color={S.red} strokeWidth={2.6} />
                  </div>
                  <span><b style={{ fontWeight: 700 }}>{t}</b> {b}</span>
                </div>
              ))}
            </div>
          </div>
          <div><KioskFlowMock /></div>
        </div>
      </section>

      {/* ── Rollout progression (reinforces optional / grow-at-your-pace) ── */}
      <section style={{ background: S.cream3, padding: '88px 64px', position: 'relative' }}>
        <div className="has-grain" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'relative', maxWidth: 1100, margin: '0 auto' }}>
          <div style={{ textAlign: 'center', marginBottom: 40 }}>
            <SectionEyebrow>Grow at your pace</SectionEyebrow>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 36, marginTop: 12, letterSpacing: '-0.025em', color: S.ink }}>
              Most fairs <em style={{ fontStyle: 'italic', color: S.red }}>start with nothing extra.</em>
            </h2>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
            {[
              ['01', 'Start on phones', 'Run your whole gate on iPhones and iPads. No purchase, no install.'],
              ['02', 'Add a kiosk', 'Cut the box-office line at your busiest entrance with self-serve.'],
              ['03', 'Scale to turnstiles', 'Lock in validated entry and exact headcount when the crowds grow.'],
            ].map(([n, t, b], i) => (
              <div key={i} style={{ background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 14, padding: 26, boxShadow: `4px 4px 0 0 ${S.ink}` }}>
                <div style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontSize: 36, color: S.red, lineHeight: 1 }}>{n}</div>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 22, color: S.ink, margin: '10px 0 6px', letterSpacing: '-0.015em' }}>{t}</div>
                <div style={{ fontSize: 12, color: S.ink, opacity: 0.72, lineHeight: 1.55 }}>{b}</div>
              </div>
            ))}
          </div>
          <p style={{ textAlign: 'center', fontFamily: 'var(--font-display)', fontStyle: 'italic', fontSize: 22, color: S.ink, opacity: 0.8, margin: '36px auto 0', maxWidth: 640 }}>
            Stop at step one for as long as you like. The platform doesn't change, it just gets more gates.
          </p>
        </div>
      </section>

      <CTAStrip onNav={onNav} />
    </div>
  );
}

// Hero visual: a self-serve kiosk custom-branded for the demo "Smithville Fair",
// framed as a product card. The render is already fully branded, so it needs no overlay.
function KioskPhoto() {
  return (
    <div style={{ position: 'relative', width: 360, maxWidth: '100%' }}>
      <div style={{ borderRadius: 18, overflow: 'hidden', border: `1.5px solid ${S.ink}`, boxShadow: `8px 8px 0 0 ${S.red}` }}>
        <img src="assets/hardware/kiosk.jpg" alt="A self-serve ticketing kiosk custom-branded for the Smithville Fair"
          style={{ display: 'block', width: '100%', height: 'auto' }} />
      </div>

      {/* OPTIONAL stamp — keep the page's optional theme */}
      <div style={{ position: 'absolute', top: -4, left: -12, transform: 'rotate(-10deg)', border: `2px dashed ${S.red}`, color: S.red, background: 'rgba(253,249,240,0.92)', borderRadius: 999, padding: '6px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase' }}>Optional</div>

      {/* Custom-branding caption */}
      <div style={{ position: 'absolute', bottom: 14, right: -18, transform: 'rotate(3deg)', background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 12, padding: '9px 13px', boxShadow: `4px 4px 0 0 ${S.ink}`, maxWidth: 168 }}>
        <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 15, color: S.ink, lineHeight: 1.2 }}>Custom-branded <em style={{ fontStyle: 'italic', color: S.red }}>for your fair.</em></div>
      </div>
    </div>
  );
}

// Tie-in visual: one ticket feeds phone / kiosk / turnstile into one dashboard.
function KioskFlowMock() {
  const nodes = [['qr', 'Phone scan'], ['store', 'Kiosk'], ['gate', 'Turnstile']];
  return (
    <div style={{ background: S.cream, border: `1.5px solid ${S.ink}`, borderRadius: 16, padding: 24, boxShadow: '0 18px 36px rgba(40,30,20,0.12)' }}>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.mute, fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase' }}>One ticket · every gate</div>
      <div style={{ marginTop: 14, display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', background: S.ink, color: S.cream, borderRadius: 10 }}>
        <Ico name="qr" size={28} color={S.cream} strokeWidth={1.4} />
        <div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 16 }}>Vega, Lila · 2-day pass</div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, opacity: 0.6 }}>#FAIR-2026-018342</div>
        </div>
      </div>
      <div style={{ textAlign: 'center', margin: '6px 0', color: S.mute }}><Ico name="arrowDown" size={18} /></div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
        {nodes.map(([ic, label], i) => (
          <div key={i} style={{ background: S.cream2, border: `1px solid ${S.border}`, borderRadius: 10, padding: '14px 8px', textAlign: 'center' }}>
            <Ico name={ic} size={22} color={S.red} strokeWidth={1.6} />
            <div style={{ fontSize: 12, fontWeight: 700, color: S.ink, marginTop: 6 }}>{label}</div>
          </div>
        ))}
      </div>
      <div style={{ textAlign: 'center', margin: '6px 0', color: S.mute }}><Ico name="arrowDown" size={18} /></div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 14px', background: S.red100, border: `1px solid rgba(255,54,54,0.3)`, borderRadius: 10 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <Ico name="chart" size={20} color={S.red} strokeWidth={1.8} />
          <span style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 16, color: S.ink }}>One live dashboard</span>
        </div>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: S.red, fontWeight: 700 }}>14,209</span>
      </div>
    </div>
  );
}

Object.assign(window, {
  PagePlatform, PageWebsites, PageTicketing, PageSocial, PageMarketing,
  PageKiosks,
});
