// More sections: Personas (made for the way you talk), WhisperMode,
// HeroRibbon (raw speech ticker), PlatformBadge
const { useState: useStateM, useEffect: useEffectM, useRef: useRefM } = React;

// ————————————————————————————————————————————————————————————
// Platform badge — repeated wherever a download decision happens
// ————————————————————————————————————————————————————————————
function AppleGlyph() {
  return (
    <svg width="11" height="13" viewBox="0 0 15 18" aria-hidden>
      <path d="M12.6 9.6c0-2.1 1.7-3.1 1.8-3.2-1-1.4-2.5-1.6-3-1.6-1.3-.1-2.5.7-3.1.7-.6 0-1.6-.7-2.7-.7C4.2 4.8 2.9 5.6 2.2 6.9c-1.4 2.4-.4 6 1 8 .7 1 1.5 2.1 2.5 2 1 0 1.4-.6 2.6-.6s1.6.6 2.7.6 1.8-1 2.5-2c.8-1.1 1.1-2.2 1.1-2.3 0 0-2-.8-2-3zM10.4 3.1c.5-.7.9-1.6.8-2.6-.8 0-1.8.5-2.3 1.2-.5.6-1 1.6-.8 2.5.9.1 1.8-.4 2.3-1.1z" fill="currentColor"/>
    </svg>
  );
}

function PlatformBadge({ light = false }) {
  return (
    <div className={`plat-pills ${light ? "plat-pills-light" : ""}`}>
      <span className="plat-pill"><AppleGlyph /> macOS 14+</span>
      <span className="plat-pill">native app</span>
      <span className="plat-pill">lives in your menu bar</span>
    </div>
  );
}

// ————————————————————————————————————————————————————————————
// Hero ribbon — raw speech crossing the hero, fillers struck mid-flight
// ————————————————————————————————————————————————————————————
const RIBBON_FILLERS = new Set(["um", "uh", "like", "basically", "so", "actually", "kinda", "maybe"]);

function RibbonRaw({ raw }) {
  return raw.split(/\s+/).map((w, i) => {
    const bare = w.toLowerCase().replace(/[^a-z']/g, "");
    return (
      <React.Fragment key={i}>
        {RIBBON_FILLERS.has(bare)
          ? <span className="ribbon-filler">{w}</span>
          : w}
        {" "}
      </React.Fragment>
    );
  });
}

// Distinct from the LiveDemo scripts on purpose — the ribbon is a second
// glance at the trick, not a rerun of the same sentences.
const RIBBON_PAIRS = [
  { raw: "um can we push the uh launch to thursday actually wait no friday", clean: "Can we push the launch to Friday?" },
  { raw: "so basically the api is uh rate limited at like a hundred requests", clean: "The API is rate-limited at 100 requests." },
  { raw: "hey um remind me to like call the dentist uh tomorrow morning", clean: "Remind me to call the dentist tomorrow morning." },
];

function HeroRibbon() {
  const pairs = RIBBON_PAIRS;

  const items = pairs.map((p, i) => (
    <span key={i} className="ribbon-item">
      <span className="ribbon-wave" aria-hidden>
        {Array.from({ length: 9 }).map((_, k) => (
          <span key={k} style={{ height: `${30 + Math.abs(Math.sin(k * 1.4)) * 60}%` }} />
        ))}
      </span>
      <span className="ribbon-raw"><RibbonRaw raw={p.raw} /></span>
      <svg className="ribbon-arrow" width="16" height="10" viewBox="0 0 16 10" aria-hidden>
        <path d="M1 5h12M9 1l4 4-4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
      </svg>
      <span className="ribbon-clean">{p.clean}</span>
      <svg className="ribbon-check" width="12" height="12" viewBox="0 0 14 14" aria-hidden>
        <path d="M2 7.5L5.5 11L12 3.5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
      </svg>
    </span>
  ));

  return (
    <div className="hero-ribbon" aria-hidden>
      <div className="ribbon-track">
        {items}
        {items.map((el, i) => React.cloneElement(el, { key: `dup-${i}` }))}
      </div>
    </div>
  );
}

// ————————————————————————————————————————————————————————————
// Personas — same ninja, different trades
// ————————————————————————————————————————————————————————————
const PERSONAS = [
  {
    id: "dev",
    label: "Developers",
    app: "VS Code",
    appHint: "commit message",
    raw: "um add retry logic to the uh websocket client it keeps like dying on hotel wifi",
    clean: "Add retry logic to the WebSocketClient; it keeps dying on hotel Wi-Fi.",
    perks: ["your identifiers, spelled your way", "casing kept exact", "works in terminals too"],
  },
  {
    id: "writer",
    label: "Writers",
    app: "Notion",
    appHint: "draft · chapter 3",
    raw: "so the uh detective knows the whole time right but like the reader shouldnt find out until the ferry scene",
    clean: "The detective knows the whole time, but the reader shouldn't find out until the ferry scene.",
    perks: ["thoughts at talking speed", "punctuation handled", "your voice, never rewritten"],
  },
  {
    id: "founder",
    label: "Founders",
    app: "Gmail",
    appHint: "to: investors",
    raw: "um q2 update revenue is up like forty percent and uh churn is finally under two",
    clean: "Q2 update: revenue is up 40% and churn is finally under 2%.",
    perks: ["numbers formatted", "reads like you on a good day", "sent before the coffee cools"],
  },
  {
    id: "student",
    label: "Students",
    app: "Notes",
    appHint: "lecture · biology",
    raw: "uh mitochondria make atp um through oxidative phosphorylation remember for the uh midterm",
    clean: "Mitochondria make ATP through oxidative phosphorylation. Remember for the midterm.",
    perks: ["57 languages", "jargon spelled right", "free during early access"],
  },
  {
    id: "support",
    label: "Support",
    app: "Slack",
    appHint: "#customer-help",
    raw: "um hey sorry about that the uh export bug ships in tomorrows release ill follow up personally",
    clean: "Hey, sorry about that! The export bug ships in tomorrow's release. I'll follow up personally.",
    perks: ["app-aware tone", "replies at 200 wpm", "empathy included"],
  },
];

function Personas() {
  const [sel, setSel] = useStateM("dev");
  const [typed, setTyped] = useStateM("");
  const [typing, setTyping] = useStateM(false);
  const p = PERSONAS.find(x => x.id === sel);

  useEffectM(() => {
    setTyping(true);
    setTyped("");
    const target = p.clean;
    let i = 0;
    const id = setInterval(() => {
      i += Math.max(1, Math.round(target.length / 70));
      if (i >= target.length) {
        setTyped(target);
        setTyping(false);
        clearInterval(id);
      } else {
        setTyped(target.slice(0, i));
      }
    }, 18);
    return () => clearInterval(id);
  }, [sel]);

  return (
    <section className="section personas" id="personas">
      <div className="section-head">
        <div className="section-eyebrow">道 · TRADE</div>
        <h2 className="section-title">Made for the way <span className="personas-accent">you talk.</span></h2>
        <p className="section-sub">Commit messages, chapters, investor updates, lecture notes, apologies to customers. Same ninja, different dojo. Pick yours.</p>
      </div>

      <div className="persona-tabs" role="tablist">
        {PERSONAS.map(x => (
          <button
            key={x.id}
            role="tab"
            aria-selected={sel === x.id}
            className={`persona-tab ${sel === x.id ? "persona-tab-active" : ""}`}
            onClick={() => setSel(x.id)}
          >
            {x.label}
          </button>
        ))}
      </div>

      <div className="persona-card">
        <div className="demo-chrome">
          <div className="demo-dots"><span /><span /><span /></div>
          <div className="demo-app">
            <span className="demo-app-name">{p.app}</span>
            <span className="demo-app-hint">{p.appHint}</span>
          </div>
          <div className="demo-shortcut">
            <kbd>fn</kbd>
            <span className="demo-hold">hold</span>
          </div>
        </div>
        <div className="persona-solo">
          <div className="persona-label"><span className="persona-dot persona-dot-green" />ninja typed</div>
          <div className="persona-clean-text">
            {typed}
            {typing && <span className="persona-caret" />}
          </div>
        </div>
        <div className="persona-perks">
          {p.perks.map((perk, i) => <span key={i} className="persona-perk">{perk}</span>)}
        </div>
      </div>
    </section>
  );
}

// ————————————————————————————————————————————————————————————
// Whisper mode — auto gain normalization for whispered dictation
// ————————————————————————————————————————————————————————————
const WM_HEIGHTS = Array.from({ length: 36 }, (_, i) =>
  18 + Math.abs(Math.sin(i * 0.9)) * 58 + Math.abs(Math.cos(i * 1.7)) * 16
);

function WhisperMode() {
  const [whisper, setWhisper] = useStateM(true);

  return (
    <section className="section whisper" id="whisper">
      <div className="section-head">
        <div className="section-eyebrow">囁 · WHISPER</div>
        <h2 className="section-title">Whisper mode. <span className="whisper-title-alt">The mic leans in.</span></h2>
        <p className="section-sub">Ninjas don't shout, and now neither do you. Automatic gain normalization boosts your signal before transcription, so a whisper lands as accurately as your presentation voice. Open office, red-eye flight, sleeping household: dictate without broadcasting.</p>
      </div>

      <div className="wm-stage">
        <div className="wm-toggle">
          <span className="wm-toggle-label">You're speaking…</span>
          <div className="wm-toggle-btns">
            <button className={!whisper ? "active" : ""} onClick={() => setWhisper(false)}>normal voice</button>
            <button className={whisper ? "active" : ""} onClick={() => setWhisper(true)}>a whisper</button>
          </div>
        </div>

        <div className="wm-panels">
          <div className="wm-panel">
            <div className="wm-panel-label">what the mic hears</div>
            <div className="wm-wave" aria-hidden>
              {WM_HEIGHTS.map((h, i) => (
                <span
                  key={i}
                  className="wm-bar"
                  style={{ height: `${whisper ? Math.max(h * 0.16, 4) : h}%`, animationDelay: `${(i * 50) % 1100}ms` }}
                />
              ))}
            </div>
            <div className="wm-meta">{whisper ? "−26 dB · barely a breath" : "0 dB · full voice"}</div>
          </div>

          <div className="wm-gain">
            <div className={`wm-gain-chip ${whisper ? "is-boosting" : ""}`}>
              <svg width="12" height="12" viewBox="0 0 14 14" aria-hidden>
                <path d="M7 12V2M3 6l4-4 4 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
              </svg>
              {whisper ? "auto gain · +26 dB" : "auto gain · idle"}
            </div>
            <div className="wm-gain-label">normalized before transcription</div>
          </div>

          <div className="wm-panel wm-panel-out">
            <div className="wm-panel-label">what the engine gets</div>
            <div className="wm-wave" aria-hidden>
              {WM_HEIGHTS.map((h, i) => (
                <span
                  key={i}
                  className="wm-bar wm-bar-out"
                  style={{ height: `${h}%`, animationDelay: `${(i * 50) % 1100}ms` }}
                />
              ))}
            </div>
            <div className="wm-meta">full signal · same accuracy</div>
          </div>
        </div>

        <div className="wm-transcript">
          <strong>"Remind me to move the car at seven."</strong>
          <span>identical output, either way</span>
        </div>

        <div className="wm-points">
          <div className="wm-point"><strong>Automatic.</strong> No settings, no calibration, no "whisper button". The ninja adjusts gain in real time and gets out of the way.</div>
          <div className="wm-point"><strong>Everywhere.</strong> Works in cloud mode and local mode alike. The normalization happens on your Mac, before anything else touches the audio.</div>
          <div className="wm-point"><strong>Actually quiet.</strong> Pairs nicely with vow number one: no windows, no clicks, and now no volume either. The full stealth kit.</div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { Personas, WhisperMode, HeroRibbon, PlatformBadge });
