function Playbook() {
  const { IconArrowRight, IconArrowLeft, IconClock, IconCheck, IconDownload, IconWheel, IconUsers, IconCard, IconCamera, IconTrophy, IconBolt, IconBadge } = window.Icons;

  const sections = [
    { id: 'ibv',        n: '01', t: 'The Ideal Booth Visitor (IBV)' },
    { id: 'loop',       n: '02', t: 'The loop: Engage → Exchange → Reward' },
    { id: 'engage',     n: '03', t: 'Stage 1: Engage — the game pulls people in' },
    { id: 'staff',      n: '04', t: 'Stage 2: Track the staff (the hidden engine)' },
    { id: 'exchange',   n: '05', t: 'Stage 3: Exchange — contact as a bonus round' },
    { id: 'reward',     n: '06', t: 'Stage 4: Reward — make the merch tiered and visible' },
    { id: 'mascot',     n: '07', t: 'The mascot multiplier' },
    { id: 'walkaway',   n: '08', t: 'What you walk away with' },
    { id: 'closing',    n: '09', t: 'Closing' },
  ];

  return (
    <React.Fragment>
      {/* Article hero */}
      <section style={{ padding: '0 8px 8px' }}>
        <div className="wp wp-indigo grain" style={{ borderRadius: 16, overflow: 'hidden' }}>
          <div className="container" style={{ padding: '88px 24px 80px', display: 'flex', flexDirection: 'column', gap: 20, maxWidth: 880 }}>
            <a href="index.html" style={{ display: 'inline-flex', alignSelf: 'flex-start', alignItems: 'center', gap: 8, padding: '4px 12px', borderRadius: 9999, background: 'rgba(0,0,0,.18)', color: 'white', fontSize: 13, fontWeight: 500, textDecoration: 'none' }}>
              <IconArrowLeft /> Back to Booth Blueprint
            </a>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'rgba(255,255,255,.75)', textTransform: 'uppercase', letterSpacing: '.06em' }}>The Playbook · For your next booth</div>
            <h1 className="h-display" style={{ fontSize: 'clamp(40px, 5.2vw, 68px)' }}>
              The Booth Gamification <em style={{ fontStyle: 'italic' }}>Playbook.</em>
            </h1>
            <p style={{ fontSize: 19, lineHeight: 1.55, color: 'rgba(255,255,255,.8)', maxWidth: '60ch' }}>
              How to engineer an Ideal Booth Visitor — the staff leaderboard that drives them, the tiered reward shelf that closes them, and the booth your visitors keep posting from after they've left.
            </p>
            <div style={{ display: 'flex', gap: 20, marginTop: 12, flexWrap: 'wrap', fontSize: 13, color: 'rgba(255,255,255,.7)' }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconClock /> ~10 min read</span>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconCheck /> Available as Web · PDF · Markdown</span>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconCheck /> No signup required</span>
            </div>
          </div>
        </div>
      </section>

      {/* Article body */}
      <section className="section" style={{ paddingTop: 64 }}>
        <div className="container" style={{ display: 'grid', gridTemplateColumns: '220px 1fr', gap: 64, alignItems: 'flex-start' }}>
          {/* TOC */}
          <aside style={{ position: 'sticky', top: 96, fontSize: 13 }}>
            <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--olive-500)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 16 }}>Contents</div>
            <ol style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 10 }}>
              {sections.map(s => (
                <li key={s.id}>
                  <a href={`#${s.id}`} style={{ display: 'flex', gap: 10, color: 'var(--olive-700)', lineHeight: 1.4 }}>
                    <span style={{ color: 'var(--olive-400)', fontVariantNumeric: 'tabular-nums', minWidth: 22 }}>{s.n}</span>
                    <span>{s.t.replace(/^Stage \d:\s/, '').replace(/^The /, 'The ')}</span>
                  </a>
                </li>
              ))}
            </ol>
            <div style={{ marginTop: 32, padding: 16, background: 'rgba(0,0,0,.03)', borderRadius: 12, display: 'flex', flexDirection: 'column', gap: 8 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--olive-700)' }}>Pair with the calculator</div>
              <p style={{ fontSize: 12, color: 'var(--olive-700)', lineHeight: 1.55 }}>Map the loop to your booth's actual numbers.</p>
              <a href="roi-calculator.html" className="link" style={{ fontSize: 12 }}>Open ROI calculator <IconArrowRight /></a>
            </div>
          </aside>

          {/* Body */}
          <article style={{ maxWidth: 720, fontSize: 17, lineHeight: 1.8, color: 'var(--olive-800)' }}>
            <Lead>
              Most conference booths look the same. A backdrop, a counter, two laptops, a bowl of branded mints, three staff who alternate between scrolling their phones and ambushing anyone who slows down. Visitors collect a sticker, scan a QR code, and disappear into the crowd. The post-event "leads" CSV is a list of strangers your team has no memory of.
            </Lead>

            <p>The booths people <em>talk about</em> — the ones with a queue all weekend — work differently. They run a <strong>loop</strong>: a tiny game pulls people in, a contact exchange happens during the high, and a tiered reward pushes the visitor to do the next thing.</p>
            <p>This blueprint shows you how to build that loop yourself, in the time it takes to ship a small product feature. The game is the surface — what matters is the data layer underneath that turns a visitor into a tracked, attributed lead.</p>

            <H2 id="ibv" n="01">The Ideal Booth Visitor (IBV)</H2>
            <p>The IBV is not a persona at the top of your funnel. It's a behaviour pattern at the booth. An IBV does six things, in order:</p>
            <Steps items={[
              ['Stops at the booth and ', <strong>plays the game</strong>],
              [<strong>Talks</strong>, ' to a specific staff member during the play'],
              [<strong>Exchanges contact</strong>, ' information — card, LinkedIn, follow'],
              [<strong>Earns merch</strong>, ' through a tiered quest'],
              [<strong>Leaves with a memory</strong>, ' — a selfie, a photo, a story'],
              [<strong>Becomes a lead</strong>, ' in your CRM with the staff member attributed'],
            ]} />
            <p>If you only count step six you get a CSV. If you engineer steps one through five you get a customer.</p>

            <H2 id="loop" n="02">The loop: Engage → Exchange → Reward</H2>
            <p>Three stages, no detours. Each stage is short — under two minutes. Each stage hands the visitor smoothly into the next.</p>
            <Table
              head={['Stage', 'Visitor action', 'What you capture', 'What they get']}
              rows={[
                ['Engage',   'Plays a 30-second game with a staff member', 'Staff attribution', 'Endorphins, score'],
                ['Exchange', 'Saves contact card, follows social, optionally connects on LinkedIn', 'Email, social handles, LinkedIn', 'Bonus points'],
                ['Reward',   'Picks merch from a tiered shelf', 'Tier-locked extra quests done', 'Branded item, story'],
              ]}
            />
            <p>Notice: there's no form. No "scan this QR to join the mailing list." The contact exchange is a <em>bonus round</em> of the game.</p>

            <H2 id="engage" n="03">Stage 1: Engage — the game pulls people in</H2>
            <p>The game has one job: lower the cost of stopping. A passing visitor needs to feel that a 30-second commitment will be fun, not a sales trap.</p>
            <p><strong>What works:</strong></p>
            <ul>
              <li><strong>Spin the wheel.</strong> Classic. Every spin wins something — even the consolation tier is a sticker. No empty slots. The wheel is loud enough to draw the next visitor.</li>
              <li><strong>1-v-1 with a staff member.</strong> A 30-second mini-game on a tablet — trivia about the visitor's industry, a reflex challenge, a guess-the-stat about your product. The staff member loses on purpose 60% of the time. The visitor laughs.</li>
              <li><strong>Daily prize draw.</strong> Every play enters a daily prize. A high-value item — an iPad, a flight upgrade, a year of your product — keeps people coming back to check the leaderboard.</li>
            </ul>
            <p><strong>What doesn't:</strong></p>
            <ul>
              <li>Anything that takes more than 30 seconds before it's clear they've won something.</li>
              <li>Anything that requires reading a paragraph.</li>
              <li>Anything that makes the visitor stand alone — pair them with a staff member from second one.</li>
            </ul>

            <Callout icon={IconWheel} wp="green" title="The 30-second test">
              If a passer-by can't go from "stopped at the booth" to "won something" in under 30 seconds, the game is too long. Cut something.
            </Callout>

            <H2 id="staff" n="04">Stage 2: Track the staff (the hidden engine)</H2>
            <p>Here's the part most booths skip. <strong>The app tags every play with the staff member who hosted it.</strong> This single piece of data changes the booth.</p>
            <ul>
              <li>When a visitor opens the app, they pick the staff member they're playing with from a list of who's on shift — photo and name. From that moment, every quest they complete is attributed to that staff member.</li>
              <li>Staff have their own dashboard inside the app — their rank, their plays, their attributed leads. They check it between visitors. It runs the booth on competitive instinct alone.</li>
              <li>A booth-wide leaderboard runs on a screen behind the booth — staff rankings, plays per hour, conversions earned. Same data, public view.</li>
            </ul>
            <p>What this produces:</p>
            <ul>
              <li><strong>Competition.</strong> Staff stop scrolling. They engage. The booth feels alive because the people running it have skin in the game.</li>
              <li><strong>Coaching data.</strong> Day-two morning standup, you can see which staff member's plays converted highest into LinkedIn follows, who claimed the most tier-3 merch, who turned plays into pipeline two weeks later.</li>
              <li><strong>Reward fairness.</strong> Bonuses, dinners, and bragging rights go to the staff who earned them — not to whoever happened to scan the most badges.</li>
            </ul>
            <p>A booth where staff are competing is a booth visitors want to walk past again.</p>

            <H2 id="exchange" n="05">Stage 3: Exchange — contact as a bonus round</H2>
            <p>The transition from game to contact is the most important sentence anyone says all weekend:</p>
            <Pull>"Nice — tier 1 score. Want tier 2? Save my contact card and follow us on Instagram — that's 200 points, gets you the t-shirt. Snap a booth selfie and post it to your story tagging us, you're locked into tier 3 — fifteen minutes with our founder before close."</Pull>
            <p>That's the whole script. The visitor is in a "yes" mood from the win, and you're not asking for anything they don't already do daily.</p>
            <p>The unlocks, in order of friction:</p>
            <PointsList items={[
              [50,    'Save staff contact card (vCard from the app)'],
              [100,   'Follow company on Instagram, LinkedIn, or X'],
              [200,   'Take a booth selfie with the staff member'],
              [400,   'Post the selfie as an Instagram Story, tagging the company'],
              [600,   'Post the selfie to your LinkedIn / IG feed, tagging the company'],
              [1000,  'Find the roaming mascot, post a selfie with them to your Instagram Story'],
            ]} />
            <p>Each tier unlocks the merch tier above it. Staff don't have to upsell — the points and the reward shelf do the selling. Notice how front-loaded the public-posting actions are: the cheapest, highest-leverage UGC (an Instagram Story selfie) sits in the middle of the journey, not at the top.</p>

            <H2 id="reward" n="06">Stage 4: Reward — make the rewards tiered and visible</H2>
            <p>Most booths give the same lanyard to everyone. The IBV loop only works if the reward shelf is visible, tiered, and cumulatively desirable. The trap: making Tier 3 a piece of consumer electronics. AirPods and mechanical keyboards are expensive, generic, and forgettable. The right Tier 3 is <em>access</em> — the things your company already has that nobody can buy at retail.</p>
            <Tiers tiers={[
              { wp: 'blue',   tag: 'Tier 1', name: 'Sticker · Pen · Custom branded notebook', need: 'Earned by playing the game. Everyone gets these.' },
              { wp: 'brown',  tag: 'Tier 2', name: 'T-shirt · Tote bag · Branded socks', need: 'Earned at 200 points — vCard saved, social follow.' },
              { wp: 'orange', tag: 'Tier 3', name: '15-min founder Zoom · A year of the product · VIP after-party pass', need: 'Earned at 1,000 points — Instagram Story posted, mascot selfie.' },
            ]} />
            <p><strong>Why this works.</strong> A 15-minute founder Zoom costs you nothing and is more memorable than any consumer-electronic giveaway. A year of the product is high-LTV, zero marginal cost, and exactly what your real customers want. A VIP wristband is a status symbol your competitors can't replicate. The visitor walks away with a story, not a charger they'll lose.</p>
            <p><strong>Two design rules:</strong></p>
            <ul>
              <li><strong>Tier 3 must be teased clearly.</strong> A printed sign on the booth wall: <em>"1,000 points = 15 minutes with the founder."</em> Or a polaroid wall of past Tier-3 winners. The point isn't that the prize is on a glass shelf — it's that visitors can see exactly what they're playing for.</li>
              <li><strong>Tier 3 must require a <em>public</em> action</strong> — a posted Instagram Story, a tagged feed post, a mascot selfie. UGC is the cost; access is the reward. Every Tier 3 claim produces a piece of branded content that other conference-goers see, attribute, and walk to the booth from.</li>
            </ul>

            <H2 id="mascot" n="07">The mascot multiplier</H2>
            <p>The mascot quest deserves its own callout. A team member in a costume — or a partner with a recognisable mascot — roams the conference floor. Visitors who find them, take a selfie, and post it with the booth tag earn the top tier.</p>
            <p><strong>Cost:</strong> one suit, one extra body on the team. <strong>Effect:</strong> dozens of organic posts that other attendees see, follow, and walk to the booth from. The mascot is the highest-leverage hire of the week.</p>
            <Callout icon={IconBolt} wp="orange" title="Why this works">
              The mascot is doing two jobs at once — generating UGC across the venue, and creating a treasure-hunt mechanic that gives visitors a reason to come back to the booth a second and third time.
            </Callout>

            <H2 id="walkaway" n="08">What you walk away with</H2>
            <p>A booth running this loop produces, by the end of three days:</p>
            <Walkaway items={[
              { i: IconUsers,   t: 'Attributed leads',          d: 'Every contact in your CRM has a staff member tag and a quest progression.' },
              { i: IconTrophy,  t: 'Staff performance data',    d: 'Who turned plays into pipeline, who needs more coaching, who you should send to the next event.' },
              { i: IconCamera,  t: 'Social reach',              d: 'Hundreds of tagged posts and stories — far higher reach than your paid social would buy in the same week.' },
              { i: IconBadge,   t: 'Brand recall',              d: 'Visitors remember a story — the spin, the mascot, the founder Zoom they unlocked — not a logo.' },
              { i: IconBolt,    t: 'Foot traffic',              d: 'A booth with a leaderboard, a mascot, and a teased Tier 3 reward becomes the booth people direct their friends to.' },
            ]} />
            <p>The "lead magnet" of a great booth is the booth itself.</p>

            <H2 id="closing" n="09">Closing</H2>
            <p>A booth is a software product with a three-day deployment window. Run it like one. The loop is simple — Engage → Exchange → Reward — but the data layer underneath, attributing every action to a staff member and a quest, is what turns the foot traffic into a forecast.</p>
            <p>You can ship the whole thing yourself. The <strong>Copy for agent</strong> button at the top right has the full build brief — paste it into Claude Code, Cursor, or any agent that scaffolds a project, and iterate from there. Or run it on Domino's quest engine and skip straight to the booth design. Either way, the playbook is the same: design the loop, tier the rewards, and turn your staff into a leaderboard.</p>
            <p>Visitors won't remember your demo. They'll remember the founder Zoom they unlocked, the mascot selfie that ended up on their Instagram Story, and the staff member who beat them at the trivia game. That's the booth they'll tell their colleagues about. That's the IBV.</p>

            {/* Inline CTAs */}
            <div style={{ marginTop: 56, padding: '32px 28px', background: 'rgba(0,0,0,.025)', borderRadius: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>
              <div className="eyebrow">Next step</div>
              <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 28, letterSpacing: '-0.02em', lineHeight: 1.1 }}>Run the numbers, then ship it.</h3>
              <p style={{ fontSize: 15, color: 'var(--olive-700)', lineHeight: 1.7 }}>Plug your booth size and conference length into the calculator to size the opportunity. Then copy the build prompt and hand it to Claude Code or Cursor — the loop is small enough to ship in a week.</p>
              <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 8 }}>
                <a href="roi-calculator.html" className="btn btn-primary lg">Open the calculator <IconArrowRight /></a>
                {window.CopyPromptButton && <window.CopyPromptButton className="btn btn-soft lg" label="Copy for agent" />}
              </div>
            </div>

            {/* Continue reading */}
            <div style={{ marginTop: 56, paddingTop: 32, borderTop: '1px solid rgba(0,0,0,.08)' }}>
              <div className="eyebrow" style={{ marginBottom: 16 }}>Continue reading</div>
              <a href="https://domino.run/campaigns/breakpoint" className="card" style={{ display: 'flex', textDecoration: 'none', alignItems: 'stretch' }}>
                <div className="wp wp-green grain" style={{ width: 200, borderRadius: 10, padding: 20, display: 'flex', alignItems: 'flex-end' }}>
                  <div style={{ position: 'relative', fontFamily: 'var(--font-display)', fontSize: 22, color: 'white', letterSpacing: '-0.02em', lineHeight: 1.05 }}>Gamifying Breakpoint</div>
                </div>
                <div style={{ padding: '16px 20px', display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 6, flex: 1 }}>
                  <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--olive-500)', textTransform: 'uppercase', letterSpacing: '.06em' }}>Case study</div>
                  <div style={{ fontSize: 15, fontWeight: 500, color: 'var(--olive-950)' }}>How 19 partner booths shared one quest system at Solana Breakpoint 2025.</div>
                  <div className="link" style={{ fontSize: 13, marginTop: 4 }}>Read the case study <IconArrowRight /></div>
                </div>
              </a>
            </div>
          </article>
        </div>
      </section>
    </React.Fragment>
  );
}

// ----- Article primitives -----

function Lead({ children }) {
  return <p style={{ fontFamily: 'var(--font-display)', fontSize: 26, lineHeight: 1.4, color: 'var(--olive-950)', letterSpacing: '-0.01em', marginBottom: 28 }}>{children}</p>;
}

function H2({ id, n, children }) {
  return (
    <h2 id={id} style={{ fontFamily: 'var(--font-display)', fontSize: 36, letterSpacing: '-0.02em', lineHeight: 1.1, color: 'var(--olive-950)', marginTop: 64, marginBottom: 16, scrollMarginTop: 96 }}>
      <span style={{ display: 'block', fontSize: 13, fontWeight: 600, fontFamily: 'var(--font-sans)', color: 'var(--olive-500)', letterSpacing: '.04em', textTransform: 'uppercase', marginBottom: 8 }}>{n}</span>
      {children}
    </h2>
  );
}

function H3({ children }) {
  return <h3 style={{ fontSize: 18, fontWeight: 600, color: 'var(--olive-950)', marginTop: 32, marginBottom: 8 }}>{children}</h3>;
}

function Steps({ items }) {
  return (
    <ol style={{ listStyle: 'none', counterReset: 'step', display: 'flex', flexDirection: 'column', gap: 8, margin: '8px 0 16px' }}>
      {items.map((parts, i) => (
        <li key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: 14 }}>
          <span style={{ minWidth: 28, height: 28, borderRadius: 9999, background: 'var(--olive-950)', color: 'white', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 600 }}>{i + 1}</span>
          <span style={{ paddingTop: 2 }}>{parts}</span>
        </li>
      ))}
    </ol>
  );
}

function Table({ head, rows }) {
  return (
    <div style={{ overflowX: 'auto', margin: '16px 0 24px', border: '1px solid rgba(0,0,0,.08)', borderRadius: 12 }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
        <thead>
          <tr style={{ background: 'rgba(0,0,0,.03)' }}>
            {head.map(h => <th key={h} style={{ textAlign: 'left', padding: '12px 16px', fontWeight: 600, color: 'var(--olive-950)', borderBottom: '1px solid rgba(0,0,0,.08)' }}>{h}</th>)}
          </tr>
        </thead>
        <tbody>
          {rows.map((r, i) => (
            <tr key={i}>
              {r.map((c, j) => <td key={j} style={{ padding: '14px 16px', verticalAlign: 'top', color: j === 0 ? 'var(--olive-950)' : 'var(--olive-700)', fontWeight: j === 0 ? 600 : 400, borderTop: i > 0 ? '1px solid rgba(0,0,0,.06)' : 'none' }}>{c}</td>)}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function PointsList({ items }) {
  return (
    <ol style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 6, margin: '12px 0 16px' }}>
      {items.map(([pts, label], i) => (
        <li key={i} style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '12px 16px', background: 'rgba(0,0,0,.025)', borderRadius: 10 }}>
          <span style={{ fontFamily: 'var(--font-display)', fontSize: 22, letterSpacing: '-0.02em', color: 'var(--olive-950)', minWidth: 56, fontVariantNumeric: 'tabular-nums' }}>+{pts}</span>
          <span style={{ fontSize: 15, color: 'var(--olive-800)' }}>{label}</span>
        </li>
      ))}
    </ol>
  );
}

function Tiers({ tiers }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, margin: '12px 0 16px' }}>
      {tiers.map(t => (
        <div key={t.tag} className="card" style={{ display: 'flex', flexDirection: 'column' }}>
          <div className={`wp wp-${t.wp} grain`} style={{ borderRadius: 10, padding: 20, minHeight: 120, display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
            <div style={{ display: 'inline-flex', alignSelf: 'flex-start', alignItems: 'center', padding: '2px 10px', borderRadius: 9999, background: 'rgba(0,0,0,.22)', fontSize: 12, fontWeight: 600, position: 'relative', color: 'white' }}>{t.tag}</div>
            <div style={{ position: 'relative', fontFamily: 'var(--font-display)', fontSize: 18, letterSpacing: '-0.01em', lineHeight: 1.2, color: 'white' }}>{t.name}</div>
          </div>
          <div style={{ padding: '14px 12px 8px', fontSize: 13, color: 'var(--olive-700)', lineHeight: 1.6 }}>{t.need}</div>
        </div>
      ))}
    </div>
  );
}

function Walkaway({ items }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, margin: '12px 0 16px' }}>
      {items.map(({ i: Icon, t, d }) => (
        <div key={t} style={{ background: 'rgba(0,0,0,.025)', borderRadius: 12, padding: 18, display: 'flex', flexDirection: 'column', gap: 10 }}>
          <div style={{ width: 36, height: 36, borderRadius: 9999, background: 'var(--olive-950)', color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon /></div>
          <div style={{ fontSize: 15, fontWeight: 600, color: 'var(--olive-950)' }}>{t}</div>
          <div style={{ fontSize: 13, color: 'var(--olive-700)', lineHeight: 1.6 }}>{d}</div>
        </div>
      ))}
    </div>
  );
}

function Plan({ days }) {
  return (
    <div style={{ margin: '12px 0 16px', border: '1px solid rgba(0,0,0,.08)', borderRadius: 12, overflow: 'hidden' }}>
      {days.map((d, i) => (
        <div key={d.d} style={{ display: 'grid', gridTemplateColumns: '120px 200px 1fr', padding: '16px 20px', borderTop: i > 0 ? '1px solid rgba(0,0,0,.06)' : 'none', alignItems: 'center', gap: 12 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--olive-950)' }}>{d.d}</div>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, letterSpacing: '-0.01em', color: 'var(--olive-950)' }}>{d.t}</div>
          <div style={{ fontSize: 14, color: 'var(--olive-700)', lineHeight: 1.6 }}>{d.b}</div>
        </div>
      ))}
    </div>
  );
}

function Callout({ icon: Icon, wp, title, children }) {
  return (
    <div className={`wp wp-${wp} grain`} style={{ borderRadius: 14, padding: 24, margin: '20px 0 16px', display: 'flex', gap: 16, color: 'white', overflow: 'hidden' }}>
      <div style={{ position: 'relative', width: 40, height: 40, borderRadius: 9999, background: 'rgba(0,0,0,.25)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon /></div>
      <div style={{ position: 'relative' }}>
        <div style={{ fontFamily: 'var(--font-display)', fontSize: 20, letterSpacing: '-0.01em', marginBottom: 6 }}>{title}</div>
        <div style={{ fontSize: 15, color: 'rgba(255,255,255,.85)', lineHeight: 1.6 }}>{children}</div>
      </div>
    </div>
  );
}

function Pull({ children }) {
  return (
    <blockquote style={{ margin: '20px 0', padding: '4px 0 4px 24px', borderLeft: '3px solid var(--olive-950)', fontFamily: 'var(--font-display)', fontSize: 22, lineHeight: 1.4, color: 'var(--olive-950)', letterSpacing: '-0.01em' }}>
      {children}
    </blockquote>
  );
}

function Quote({ children }) {
  return (
    <blockquote style={{ margin: '12px 0 16px', padding: '20px 24px', background: 'rgba(0,0,0,.04)', borderRadius: 12, fontSize: 15, lineHeight: 1.7, color: 'var(--olive-800)', fontStyle: 'italic' }}>
      {children}
    </blockquote>
  );
}

function Code({ children }) {
  return (
    <pre style={{ background: 'var(--olive-950)', color: '#d6e0d6', padding: '20px 24px', borderRadius: 12, overflowX: 'auto', fontSize: 13, lineHeight: 1.6, margin: '12px 0 16px', fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace' }}>
      <code>{children}</code>
    </pre>
  );
}

window.Playbook = Playbook;
