// Wordra — additional screens & helpers (Pause, Onboarding, Countdown, Settings, Profile, Loading, Empty states, Lang picker, Share card)

const { useState: useStateX, useEffect: useEffectX, useRef: useRefX } = React;

// ============================================================
// PAUSE OVERLAY
// ============================================================
function WordraPause({ lang, onResume, onRestart, onExit, soundOn, onToggleSound, hapticsOn, onToggleHaptics }) {
  const t = (en, th) => (lang === "th" ? th : en);
  return (
    <div className="wp-root">
      <div className="wp-backdrop" onClick={onResume}/>
      <div className="wp-card">
        <div className="wp-tag">{t("PAUSED", "หยุดชั่วคราว")}</div>
        <div className="wp-title">{t("Take a breath", "พักก่อน")}</div>

        <div className="wp-toggles">
          <button className={"wp-toggle " + (soundOn ? "on" : "")} onClick={onToggleSound}>
            <span className="wp-toggle-icon">{soundOn ? "🔊" : "🔇"}</span>
            <span className="wp-toggle-label">{t("Sound", "เสียง")}</span>
            <span className="wp-toggle-state">{soundOn ? t("ON", "เปิด") : t("OFF", "ปิด")}</span>
          </button>
          <button className={"wp-toggle " + (hapticsOn ? "on" : "")} onClick={onToggleHaptics}>
            <span className="wp-toggle-icon">📳</span>
            <span className="wp-toggle-label">{t("Haptics", "สั่น")}</span>
            <span className="wp-toggle-state">{hapticsOn ? t("ON", "เปิด") : t("OFF", "ปิด")}</span>
          </button>
        </div>

        <div className="wp-actions">
          <button className="wp-btn primary" onClick={onResume}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 4 20 12 6 20"/></svg>
            {t("RESUME", "เล่นต่อ")}
          </button>
          <button className="wp-btn secondary" onClick={onRestart}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
            {t("RESTART", "เริ่มใหม่")}
          </button>
          <button className="wp-btn ghost" onClick={onExit}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
            {t("EXIT", "ออก")}
          </button>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// ONBOARDING — ghost-swipe tutorial (3-second)
// ============================================================
function WordraOnboarding({ lang, onDone }) {
  const t = (en, th) => (lang === "th" ? th : en);
  const [step, setStep] = useStateX(0);
  // demo grid letters
  const demoBoard = ["P","L","A","Y","S","E","T","I","M","R","C","O","N","B","U","D","G","H","V","W","K","F","X","Q","Z"];
  // ghost swipe path: P-L-A-Y (indices 0,1,2,3)
  const ghostPath = [0, 1, 2, 3];

  useEffectX(() => {
    if (step >= 3) return;
    const id = setTimeout(() => setStep(step + 1), step === 0 ? 1200 : 1500);
    return () => clearTimeout(id);
  }, [step]);

  return (
    <div className="wo-root">
      <button className="wo-skip" onClick={onDone}>{t("SKIP", "ข้าม")}</button>

      <div className="wo-stage">
        <div className="wo-grid">
          {demoBoard.map((ch, i) => {
            const sel = step >= 1 && ghostPath.indexOf(i) <= step && ghostPath.includes(i);
            const order = ghostPath.indexOf(i);
            return (
              <div key={i} className={"wo-cell " + (sel ? "sel " : "") + (step >= 2 && ghostPath.includes(i) ? "valid " : "")}>
                <span>{ch}</span>
                {sel && order !== -1 && <span className="wo-order">{order + 1}</span>}
              </div>
            );
          })}
          {/* ghost finger */}
          {step >= 1 && step < 3 && (
            <div className="wo-finger" style={{
              "--gx": (ghostPath[Math.min(step, ghostPath.length - 1)] % 5),
              "--gy": Math.floor(ghostPath[Math.min(step, ghostPath.length - 1)] / 5),
            }}/>
          )}
          {step >= 2 && (
            <div className="wo-popup">+80 <small>×1</small></div>
          )}
        </div>
      </div>

      <div className="wo-copy">
        <div className="wo-step">
          <span className="wo-step-num">01</span>
          <span className="wo-step-text">{t("Drag adjacent letters", "ลากตัวอักษรที่ติดกัน")}</span>
        </div>
        <div className="wo-step">
          <span className="wo-step-num">02</span>
          <span className="wo-step-text">{t("Spell ≥ 3 letters", "สะกดอย่างน้อย 3 ตัว")}</span>
        </div>
        <div className="wo-step">
          <span className="wo-step-num">03</span>
          <span className="wo-step-text">{t("Chain for combos · score × 5", "ต่อเนื่องเพื่อคอมโบ × 5")}</span>
        </div>
      </div>

      <button className="wo-cta" onClick={onDone}>{t("GOT IT", "เข้าใจแล้ว")}</button>
    </div>
  );
}

// ============================================================
// COUNTDOWN — 3, 2, 1, GO
// ============================================================
function WordraCountdown({ lang, onDone }) {
  const t = (en, th) => (lang === "th" ? th : en);
  const [n, setN] = useStateX(3);
  useEffectX(() => {
    if (n < 0) {
      onDone && onDone();
      return;
    }
    const id = setTimeout(() => setN(n - 1), 700);
    return () => clearTimeout(id);
  }, [n]);
  return (
    <div className="wc-root">
      <div className="wc-backdrop"/>
      <div key={n} className={"wc-num " + (n === 0 ? "go" : "")}>
        {n === 0 ? "GO!" : n > 0 ? n : ""}
      </div>
      <div className="wc-sub">{t("Get ready", "เตรียมตัว")}</div>
    </div>
  );
}

// ============================================================
// SETTINGS
// ============================================================
function WordraSettings({ lang, onBack, settings, onChange, onLang, onResetProgress }) {
  const t = (en, th) => (lang === "th" ? th : en);
  const [confirming, setConfirming] = useStateX(false);
  const Row = ({ icon, title, sub, value, on, onClick, options, current }) => (
    <button className={"ws-row " + (on ? "on " : "")} onClick={onClick}>
      <span className="ws-row-icon">{icon}</span>
      <span className="ws-row-meta">
        <span className="ws-row-title">{title}</span>
        {sub && <span className="ws-row-sub">{sub}</span>}
      </span>
      {options ? (
        <span className="ws-row-opts">
          {options.map(o => (
            <span key={o.v} className={"ws-row-opt " + (current === o.v ? "sel" : "")}>{o.label}</span>
          ))}
        </span>
      ) : (
        <span className="ws-row-toggle">
          <span className="ws-row-knob"/>
        </span>
      )}
    </button>
  );
  return (
    <div className="ws-root">
      <div className="ws-topbar">
        <button className="ws-back" onClick={onBack}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><polyline points="15 18 9 12 15 6"/></svg>
        </button>
        <span className="ws-title">{t("SETTINGS", "ตั้งค่า")}</span>
        <span className="ws-spacer"/>
      </div>

      <div className="ws-section">
        <div className="ws-section-head">{t("AUDIO & FEEL", "เสียงและสัมผัส")}</div>
        <Row icon="🔊" title={t("Sound effects", "เสียงเอฟเฟกต์")} sub={t("swipe · word · combo · peak", "ลาก · คำ · คอมโบ · พีค")}
          on={settings.sound} onClick={() => onChange({ sound: !settings.sound })}/>
        <Row icon="🎵" title={t("Music", "เพลง")} sub={t("dynamic · flow → peak", "ไดนามิก · ปกติ → พีค")}
          on={settings.music} onClick={() => onChange({ music: !settings.music })}/>
        <Row icon="📳" title={t("Haptics", "สั่นสะเทือน")} sub={t("vibrate on word & combo", "สั่นเมื่อคำถูก & คอมโบ")}
          on={settings.haptics} onClick={() => onChange({ haptics: !settings.haptics })}/>
      </div>

      <div className="ws-section">
        <div className="ws-section-head">{t("DISPLAY", "การแสดงผล")}</div>
        <button className="ws-row" onClick={() => onChange({ theme: settings.theme === "light" ? "dark" : "light" })}>
          <span className="ws-row-icon">{settings.theme === "light" ? "☀️" : "🌙"}</span>
          <span className="ws-row-meta">
            <span className="ws-row-title">{t("Theme", "ธีม")}</span>
            <span className="ws-row-sub">{settings.theme === "light" ? t("Light", "สว่าง") : t("Dark", "มืด")}</span>
          </span>
          <span className="ws-row-opts">
            <span className={"ws-row-opt " + (settings.theme === "light" ? "sel" : "")}>{t("LIGHT", "สว่าง")}</span>
            <span className={"ws-row-opt " + (settings.theme === "dark" ? "sel" : "")}>{t("DARK", "มืด")}</span>
          </span>
        </button>
        <button className="ws-row" onClick={() => onLang(lang === "en" ? "th" : "en")}>
          <span className="ws-row-icon">🌐</span>
          <span className="ws-row-meta">
            <span className="ws-row-title">{t("Language", "ภาษา")}</span>
            <span className="ws-row-sub">{lang === "en" ? "English" : "ไทย"}</span>
          </span>
          <span className="ws-row-opts">
            <span className={"ws-row-opt " + (lang === "en" ? "sel" : "")}>EN</span>
            <span className={"ws-row-opt " + (lang === "th" ? "sel" : "")}>TH</span>
          </span>
        </button>
      </div>

      <div className="ws-section">
        <div className="ws-section-head">{t("ABOUT", "เกี่ยวกับ")}</div>
        <div className="ws-meta-row">
          <span>{t("Version", "เวอร์ชัน")}</span><span>1.0.0 · web prototype</span>
        </div>
        <div className="ws-meta-row">
          <span>{t("Build", "บิวด์")}</span><span>2026.05.07</span>
        </div>
        <div className="ws-meta-row">
          <span>{t("Platform", "แพลตฟอร์ม")}</span><span>PWA · Unity-ready</span>
        </div>
      </div>

      <div className="ws-foot">
        <a className="ws-link" href="/privacy.html" target="_blank" rel="noopener">{t("Privacy", "ความเป็นส่วนตัว")}</a>
        <span>·</span>
        <a className="ws-link" href="/terms.html" target="_blank" rel="noopener">{t("Terms", "ข้อตกลง")}</a>
        <span>·</span>
        <button
          className="ws-link"
          onClick={() => {
            if (!confirming) { setConfirming(true); setTimeout(() => setConfirming(false), 4000); return; }
            setConfirming(false);
            onResetProgress && onResetProgress();
          }}
          style={confirming ? { color: "var(--danger)", fontWeight: 800 } : null}
        >
          {confirming ? t("Tap again to confirm", "แตะอีกครั้งเพื่อยืนยัน") : t("Reset progress", "รีเซ็ต")}
        </button>
      </div>
    </div>
  );
}

// ============================================================
// PROFILE / STATS
// ============================================================
function WordraProfile({ lang, onBack, stats, onOpenVocab }) {
  const t = (en, th) => (lang === "th" ? th : en);
  // Live vocab counts replace the placeholder when WordraVocab is available.
  const vocabUnique = (window.WordraVocab && window.WordraVocab.countUnique()) || 0;
  const vocabTotal  = (window.WordraVocab && window.WordraVocab.countTotal())  || 0;
  const s = stats || { games: 28, best: 1840, totalScore: 24210, avg: 865, longest: "STARTLE", streak: 4, words: vocabUnique || 312, daysPlayed: 11 };

  // sparkline data (last 14 sessions)
  const trend = [620, 480, 920, 540, 1100, 760, 1240, 980, 1060, 1480, 1180, 1520, 1640, 1840];
  const max = Math.max(...trend);
  const min = Math.min(...trend);
  const w = 280, h = 60;
  const points = trend.map((v, i) => {
    const x = (i / (trend.length - 1)) * w;
    const y = h - ((v - min) / (max - min)) * h * 0.85 - 6;
    return `${x},${y}`;
  }).join(" ");

  return (
    <div className="wpr-root">
      <div className="wpr-topbar">
        <button className="wpr-back" onClick={onBack}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><polyline points="15 18 9 12 15 6"/></svg>
        </button>
        <span className="wpr-title">{t("PROFILE", "โปรไฟล์")}</span>
        <span className="wpr-spacer"/>
      </div>

      <div className="wpr-hero">
        <div className="wpr-avatar">W</div>
        <div className="wpr-name">{t("you", "คุณ")}</div>
        <div className="wpr-rank">
          <span className="wpr-rank-tier">SILVER II</span>
          <span className="wpr-rank-progress">
            <span className="wpr-rank-fill" style={{ width: "62%" }}/>
          </span>
          <span className="wpr-rank-meta">620 / 1000</span>
        </div>
      </div>

      <div className="wpr-stats">
        <div className="wpr-stat hero">
          <div className="wpr-stat-num">{s.best.toLocaleString()}</div>
          <div className="wpr-stat-lbl">{t("BEST SCORE", "คะแนนดีที่สุด")}</div>
        </div>
        <div className="wpr-stat">
          <div className="wpr-stat-num">{s.games}</div>
          <div className="wpr-stat-lbl">{t("GAMES", "เกม")}</div>
        </div>
        <div className="wpr-stat">
          <div className="wpr-stat-num">{s.avg}</div>
          <div className="wpr-stat-lbl">{t("AVG", "เฉลี่ย")}</div>
        </div>
        <div className="wpr-stat streak">
          <div className="wpr-stat-num">🔥{s.streak}</div>
          <div className="wpr-stat-lbl">{t("DAY STREAK", "ต่อเนื่อง")}</div>
        </div>
      </div>

      <div className="wpr-trend">
        <div className="wpr-trend-head">
          <span>{t("LAST 14 GAMES", "14 เกมล่าสุด")}</span>
          <span className="wpr-trend-up">+24%</span>
        </div>
        <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width: "100%", height: 60 }}>
          <defs>
            <linearGradient id="wprgrad" x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor="var(--purple)" stopOpacity="0.4"/>
              <stop offset="100%" stopColor="var(--purple)" stopOpacity="0"/>
            </linearGradient>
          </defs>
          <polygon fill="url(#wprgrad)" points={`0,${h} ${points} ${w},${h}`}/>
          <polyline fill="none" stroke="var(--purple)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" points={points}/>
          {trend.map((v, i) => {
            const x = (i / (trend.length - 1)) * w;
            const y = h - ((v - min) / (max - min)) * h * 0.85 - 6;
            return <circle key={i} cx={x} cy={y} r={i === trend.length - 1 ? 4 : 0} fill="var(--gold)"/>;
          })}
        </svg>
      </div>

      {/* Vocab nav — primary action on the Profile screen */}
      <button className="wpr-vocab-cta" onClick={onOpenVocab}>
        <span className="wpr-vocab-icon">📖</span>
        <span className="wpr-vocab-meta">
          <span className="wpr-vocab-title">{t("VOCAB COLLECTION", "คลังคำของฉัน")}</span>
          <span className="wpr-vocab-sub">
            {vocabUnique > 0
              ? t(`${vocabUnique} unique · ${vocabTotal} plays`, `${vocabUnique} คำไม่ซ้ำ · ${vocabTotal} ครั้ง`)
              : t("Start your collection — play a round", "เริ่มสะสม — เล่นสักรอบ")}
          </span>
        </span>
        <span className="wpr-vocab-chev">›</span>
      </button>

      <div className="wpr-row-stats">
        <div className="wpr-row-stat">
          <span className="wpr-row-stat-lbl">{t("Longest word", "คำยาวที่สุด")}</span>
          <span className="wpr-row-stat-val mono">{s.longest}</span>
        </div>
        <div className="wpr-row-stat">
          <span className="wpr-row-stat-lbl">{t("Words found", "คำที่เจอ")}</span>
          <span className="wpr-row-stat-val">{vocabUnique || s.words}</span>
        </div>
        <div className="wpr-row-stat">
          <span className="wpr-row-stat-lbl">{t("Total score", "คะแนนรวม")}</span>
          <span className="wpr-row-stat-val">{s.totalScore.toLocaleString()}</span>
        </div>
        <div className="wpr-row-stat">
          <span className="wpr-row-stat-lbl">{t("Days played", "จำนวนวัน")}</span>
          <span className="wpr-row-stat-val">{s.daysPlayed}</span>
        </div>
      </div>

      <div className="wpr-achievements">
        <div className="wpr-ach-head">{t("ACHIEVEMENTS", "ความสำเร็จ")} <span>3 / 9</span></div>
        <div className="wpr-ach-row">
          {[
            { icon: "🎯", on: true, name: t("First word", "คำแรก") },
            { icon: "🔥", on: true, name: t("×5 combo", "คอมโบ ×5") },
            { icon: "📅", on: true, name: t("Daily 3", "ประจำวัน 3") },
            { icon: "🏆", on: false, name: t("Top 10", "ท็อป 10") },
            { icon: "💎", on: false, name: t("2000 pts", "2000 คะแนน") },
            { icon: "📚", on: false, name: t("8-letter", "8 ตัว") },
          ].map((a, i) => (
            <div key={i} className={"wpr-ach " + (a.on ? "on " : "")}>
              <span className="wpr-ach-icon">{a.icon}</span>
              <span className="wpr-ach-name">{a.name}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ============================================================
// LOADING
// ============================================================
function WordraLoading({ lang, progress }) {
  const t = (en, th) => (lang === "th" ? th : en);
  const p = progress != null ? progress : 0.6;
  const tips = [
    t("Tip · longer words = more points", "เคล็ดลับ · คำยาวยิ่งได้คะแนนมาก"),
    t("Chain words within 2s for combos", "ต่อคำใน 2 วิเพื่อคอมโบ"),
    t("Daily board resets at midnight", "บอร์ดประจำวันรีเซ็ตเที่ยงคืน"),
  ];
  const [tip] = useStateX(() => tips[Math.floor(Math.random() * tips.length)]);
  return (
    <div className="wl-root">
      <div className="wl-logo">
        <div className="wl-logo-tiles">
          {"WORDRA".split("").map((ch, i) => (
            <span key={i} className="wl-tile" style={{ animationDelay: (i * 100) + "ms" }}>{ch}</span>
          ))}
        </div>
      </div>
      <div className="wl-bar">
        <div className="wl-bar-fill" style={{ width: (p * 100) + "%" }}/>
      </div>
      <div className="wl-pct">{Math.round(p * 100)}%</div>
      <div className="wl-tip">{tip}</div>
    </div>
  );
}

// ============================================================
// LANG PICKER (first launch)
// ============================================================
function WordraLangPicker({ onPick }) {
  return (
    <div className="wlp-root">
      <div className="wlp-logo">WORDRA</div>
      <div className="wlp-sub">Choose your language · เลือกภาษา</div>
      <div className="wlp-grid">
        <button className="wlp-card" onClick={() => onPick("en")}>
          <span className="wlp-flag">🇬🇧</span>
          <span className="wlp-name">English</span>
          <span className="wlp-meta">EN</span>
        </button>
        <button className="wlp-card" onClick={() => onPick("th")}>
          <span className="wlp-flag">🇹🇭</span>
          <span className="wlp-name">ภาษาไทย</span>
          <span className="wlp-meta">TH</span>
        </button>
      </div>
      <div className="wlp-foot">You can change this later in Settings</div>
    </div>
  );
}

// ============================================================
// EMPTY STATE
// ============================================================
function WordraEmpty({ lang, kind, onAction }) {
  const t = (en, th) => (lang === "th" ? th : en);
  const variants = {
    leaderboard: {
      icon: "🏆",
      title: t("No scores yet", "ยังไม่มีคะแนน"),
      sub: t("Be the first today", "เป็นคนแรกของวันนี้"),
      cta: t("PLAY DAILY", "เล่นประจำวัน"),
    },
    offline: {
      icon: "📡",
      title: t("You're offline", "คุณออฟไลน์อยู่"),
      sub: t("Daily needs internet · Solo works fine", "ประจำวันต้องใช้เน็ต · เดี่ยวเล่นได้"),
      cta: t("PLAY SOLO", "เล่นเดี่ยว"),
    },
    nostats: {
      icon: "📊",
      title: t("No stats yet", "ยังไม่มีสถิติ"),
      sub: t("Play your first game", "เล่นเกมแรกของคุณ"),
      cta: t("PLAY", "เล่น"),
    },
  };
  const v = variants[kind] || variants.nostats;
  return (
    <div className="we-root">
      <div className="we-icon">{v.icon}</div>
      <div className="we-title">{v.title}</div>
      <div className="we-sub">{v.sub}</div>
      <button className="we-cta" onClick={onAction}>{v.cta}</button>
    </div>
  );
}

// ============================================================
// SHARE CARD (canvas) — for image export
// ============================================================
// Drawing logic factored out so it can be used both by the React component
// (preview) and by the Web Share flow (offscreen canvas → Blob).
function _drawShareCard(canvas, opts) {
  const { score, words, dailyNo, isDaily } = opts;
  const ctx = canvas.getContext("2d");
  const W = 480, H = 600;
  canvas.width = W * 2; canvas.height = H * 2;
  if (canvas.style) { canvas.style.width = W + "px"; canvas.style.height = H + "px"; }
  ctx.setTransform(2, 0, 0, 2, 0, 0);

  const grad = ctx.createLinearGradient(0, 0, 0, H);
  grad.addColorStop(0, "#1A1326");
  grad.addColorStop(1, "#0B0B0F");
  ctx.fillStyle = grad;
  ctx.fillRect(0, 0, W, H);

  const glow = ctx.createRadialGradient(W * 0.7, H * 0.3, 0, W * 0.7, H * 0.3, 280);
  glow.addColorStop(0, "rgba(124,92,255,0.35)");
  glow.addColorStop(1, "rgba(124,92,255,0)");
  ctx.fillStyle = glow;
  ctx.fillRect(0, 0, W, H);

  ctx.fillStyle = "#FFFFFF";
  ctx.font = "800 22px Inter, sans-serif";
  ctx.fillText("WORDRA", 32, 56);
  ctx.fillStyle = "#A1A1AA";
  ctx.font = "600 12px JetBrains Mono, monospace";
  ctx.fillText(isDaily ? `#${dailyNo} · DAILY` : "SOLO ROUND", 32, 76);

  ctx.fillStyle = "#FFFFFF";
  ctx.font = "900 110px Inter, sans-serif";
  ctx.fillText(score.toLocaleString(), 32, 220);
  ctx.fillStyle = "#FFD84D";
  ctx.font = "700 14px JetBrains Mono, monospace";
  ctx.fillText("FINAL SCORE", 32, 248);

  ctx.fillStyle = "#FFFFFF";
  ctx.font = "800 36px Inter, sans-serif";
  ctx.fillText(String(words.length), 32, 320);
  ctx.fillStyle = "#A1A1AA";
  ctx.font = "600 12px JetBrains Mono, monospace";
  ctx.fillText("WORDS", 32, 340);

  const longest = [...words].sort((a, b) => b.length - a.length)[0];
  if (longest) {
    ctx.fillStyle = "#FFFFFF";
    ctx.font = "800 36px Inter, sans-serif";
    ctx.fillText(longest.toUpperCase(), 160, 320);
    ctx.fillStyle = "#A1A1AA";
    ctx.font = "600 12px JetBrains Mono, monospace";
    ctx.fillText("LONGEST", 160, 340);
  }

  let y = 400, x = 32;
  ctx.font = "600 14px Inter, sans-serif";
  for (const w of words.slice(0, 12)) {
    const tw = ctx.measureText(w).width + 20;
    if (x + tw > W - 32) { x = 32; y += 32; }
    if (y > H - 80) break;
    ctx.fillStyle = "rgba(255,255,255,0.08)";
    if (typeof ctx.roundRect === "function") {
      ctx.beginPath();
      ctx.roundRect(x, y - 18, tw, 26, 13);
      ctx.fill();
    } else {
      ctx.fillRect(x, y - 18, tw, 26);
    }
    ctx.fillStyle = "#FFFFFF";
    ctx.fillText(w, x + 10, y);
    x += tw + 8;
  }

  ctx.fillStyle = "#7C5CFF";
  ctx.fillRect(0, H - 56, W, 56);
  ctx.fillStyle = "#FFFFFF";
  ctx.font = "800 16px Inter, sans-serif";
  ctx.fillText("wordra.app", 32, H - 22);
  ctx.font = "600 12px JetBrains Mono, monospace";
  ctx.fillStyle = "rgba(255,255,255,0.7)";
  ctx.textAlign = "right";
  ctx.fillText("PLAY · SWIPE · COMBO", W - 32, H - 22);
  ctx.textAlign = "left";
}

// Promise-returning helper used by the Result-screen Share button. Renders to
// an offscreen canvas at 2× DPR, then exports a PNG Blob.
function getShareCardBlob(opts) {
  return new Promise((resolve, reject) => {
    try {
      const canvas = document.createElement("canvas");
      _drawShareCard(canvas, opts);
      canvas.toBlob((blob) => {
        if (!blob) return reject(new Error("toBlob returned null"));
        resolve(blob);
      }, "image/png");
    } catch (err) {
      reject(err);
    }
  });
}

function WordraShareCard({ score, words, dailyNo, isDaily }) {
  const ref = useRefX(null);
  useEffectX(() => {
    if (ref.current) _drawShareCard(ref.current, { score, words, dailyNo, isDaily });
  }, [score, words, dailyNo, isDaily]);
  return <canvas ref={ref} className="ws-card-canvas"/>;
}

window.getShareCardBlob = getShareCardBlob;

window.WordraPause = WordraPause;
window.WordraOnboarding = WordraOnboarding;
window.WordraCountdown = WordraCountdown;
window.WordraSettings = WordraSettings;
window.WordraProfile = WordraProfile;
window.WordraLoading = WordraLoading;
window.WordraLangPicker = WordraLangPicker;
window.WordraEmpty = WordraEmpty;
window.WordraShareCard = WordraShareCard;
