/* Wellpaged Builder — components.jsx (chrome). Exports to window.
   A landing-page intake flow (not a links list): Theme → Brand → Story →
   Socials → Review. Navigation is driven by Back / Next buttons.
   Adapted from the design handoff: wired to the real publish flow (Turnstile in
   the dialog) and the full TypeUI template library in the theme picker. */
const { useState, useRef, useEffect } = React;

// Wellpaged house themes get a live, accurate preview (themes.css scopes).
const HOUSE_THEMES = [
  { id: "soft", name: "Soft Asymmetry", concept: "Cream studio zine", bg: "#FAF7F2", fg: "#0B0B12", accent: "#2A55D6" },
  { id: "pastel", name: "Pastel Dream", concept: "Soft daylight", bg: "#fdf5f3", fg: "#2d2a44", accent: "#e89ab5" },
  { id: "velvet", name: "Velvet Dark", concept: "Velvet midnight", bg: "#0a0712", fg: "#f2e9db", accent: "#d4b77a" },
  { id: "neon", name: "Neon Night", concept: "Club flyer", bg: "#0a0a0f", fg: "#f5f5f7", accent: "#C6FF3D" },
  { id: "press", name: "Press", concept: "Editorial broadsheet", bg: "#f6f4ef", fg: "#15110d", accent: "#d32f2f" },
];
// TypeUI design systems (design-skills/<id>.md). These build a full bespoke site;
// the live preview is indicative (shows the generic themed page).
const TYPEUI_THEMES = [
  { id: "agentic", name: "Agentic", concept: "Conversational AI-first interface with m…", bg: "#FFFFFF", fg: "#111827", accent: "#FF5701" },
  { id: "ant", name: "Ant", concept: "Structured, enterprise-focused design sy…", bg: "#FFFFFF", fg: "#111827", accent: "#1677ff" },
  { id: "application", name: "Application", concept: "App dashboard with purple-themed aesthet…", bg: "#FFFFFF", fg: "#09090b", accent: "#9333ea" },
  { id: "artistic", name: "Artistic", concept: "High-contrast, expressive style with cre…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "bento", name: "Bento", concept: "Modular grid layout with card-like block…", bg: "#FFF5E6", fg: "#111827", accent: "#FAD4C0" },
  { id: "bold", name: "Bold", concept: "Strong visual presence with heavyweight …", bg: "#111111", fg: "#111827", accent: "#0077BC" },
  { id: "brutalism", name: "Brutalism", concept: "Raw, anti-design aesthetic inspired by c…", bg: "#FFFFFF", fg: "#111827", accent: "#DD614C" },
  { id: "cafe", name: "Cafe", concept: "Cozy cafe-inspired interface with warm t…", bg: "#F9F7F5", fg: "#3E2B1E", accent: "#5D4432" },
  { id: "claude", name: "Claude", concept: "Research-journal aesthetic on warm stone…", bg: "#FFFFFF", fg: "#111827", accent: "#141413" },
  { id: "claymorphism", name: "Claymorphism", concept: "Soft, rounded 3D-like shapes mimicking m…", bg: "#FFFFFF", fg: "#1C398E", accent: "#3B82F6" },
  { id: "clean", name: "Clean", concept: "Simplicity-focused design with ample whi…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "codex", name: "Codex", concept: "Radically minimal blank-canvas interface…", bg: "#FFFFFF", fg: "#111827", accent: "#000000" },
  { id: "colorful", name: "Colorful", concept: "Vibrant, high-contrast palettes and grad…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "contemporary", name: "Contemporary", concept: "Current-era minimalist design with bento…", bg: "#FFFFFF", fg: "#111827", accent: "#C800DF" },
  { id: "corporate", name: "Corporate", concept: "Professional, brand-aligned design with …", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "cosmic", name: "Cosmic", concept: "Futuristic sci-fi aesthetic with dark th…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "creative", name: "Creative", concept: "Playful, character-driven design with ex…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "dashboard", name: "Dashboard", concept: "Dark-themed cloud-platform aesthetic wit…", bg: "#09090b", fg: "#fafafa", accent: "#0C5CAB" },
  { id: "dithered", name: "Dithered", concept: "Dot-pattern rendering technique that sim…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "doodle", name: "Doodle", concept: "Hand-drawn, sketch-like style with doodl…", bg: "#FFFFFF", fg: "#111827", accent: "#49B6E5" },
  { id: "dramatic", name: "Dramatic", concept: "High-contrast, theatrical design with bo…", bg: "#09090B", fg: "#FAFAFA", accent: "#8B5CF6" },
  { id: "editorial", name: "Editorial", concept: "Magazine-inspired editorial layout with …", bg: "#FFFFFF", fg: "#111827", accent: "#111111" },
  { id: "elegant", name: "Elegant", concept: "Graceful, refined aesthetic with delicat…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "energetic", name: "Energetic", concept: "Dynamic, vibrant style with thick border…", bg: "#FDBA74", fg: "#EA580C", accent: "#EA580B" },
  { id: "enterprise", name: "Enterprise", concept: "Clean, high-contrast enterprise design f…", bg: "#EDEADE", fg: "#111827", accent: "#072C2C" },
  { id: "expressive", name: "Expressive", concept: "Vibrant, personality-driven design with …", bg: "#FFFFFF", fg: "#111827", accent: "#db2777" },
  { id: "fantasy", name: "Fantasy", concept: "Game-inspired fantasy aesthetic with bol…", bg: "#FFFFFF", fg: "#111827", accent: "#0250CC" },
  { id: "fiction", name: "Fiction", concept: "Playful, storybook-inspired interface wi…", bg: "#FFFFFF", fg: "#111827", accent: "#222222" },
  { id: "flat", name: "Flat", concept: "Two-dimensional minimalist style with vi…", bg: "#FFFFFF", fg: "#111827", accent: "#F2673C" },
  { id: "friendly", name: "Friendly", concept: "Approachable, intuitive design with roun…", bg: "#FFFFFF", fg: "#111827", accent: "#F2D9DC" },
  { id: "futuristic", name: "Futuristic", concept: "Forward-looking design with tech-inspire…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "glassmorphism", name: "Glassmorphism", concept: "Frosted glass effect with translucent la…", bg: "#FFFFFF", fg: "#141414", accent: "#1856FF" },
  { id: "gradient", name: "Gradient", concept: "Smooth color transitions and gradient-ri…", bg: "#FFFFFF", fg: "#111827", accent: "#990FFA" },
  { id: "immersive", name: "Immersive", concept: "Exhibit-style interface that blends stor…", bg: "#FFFFFF", fg: "#111827", accent: "#00592B" },
  { id: "impeccable", name: "Impeccable", concept: "Graphic editorial-poster aesthetic with …", bg: "#FFFFFF", fg: "#111827", accent: "#CC8800" },
  { id: "levels", name: "Levels", concept: "Conversion-focused design that removes f…", bg: "#FFFFFF", fg: "#111827", accent: "#27272A" },
  { id: "lingo", name: "Lingo", concept: "Playful, minimal design with bright colo…", bg: "#FFFFFF", fg: "#3c3c3c", accent: "#58cc02" },
  { id: "luxury", name: "Luxury", concept: "High-end dark aesthetic with bold headin…", bg: "#000000", fg: "#ffffff", accent: "#FAFAFA" },
  { id: "material", name: "Material", concept: "Google's Material Design with layered su…", bg: "#FFFFFF", fg: "#111827", accent: "#6442D6" },
  { id: "matrix", name: "Matrix", concept: "Dark cyber-terminal visual language with…", bg: "#FFFFFF", fg: "#111827", accent: "#2DB58A" },
  { id: "minimal", name: "Minimal", concept: "Stripped-back design emphasizing whitesp…", bg: "#F4F4F1", fg: "#0C0C09", accent: "#0C0C09" },
  { id: "modern", name: "Modern", concept: "Contemporary editorial style with serif …", bg: "#553F83", fg: "#ffffff", accent: "#553F83" },
  { id: "mono", name: "Mono", concept: "Monospace-driven, matrix-inspired design…", bg: "#E7E5E4", fg: "#78716B", accent: "#37F712" },
  { id: "neobrutalism", name: "Neobrutalism", concept: "Modern take on brutalism with bold borde…", bg: "#FBFBF9", fg: "#1C293C", accent: "#FDC800" },
  { id: "neumorphism", name: "Neumorphism", concept: "Soft, extruded UI elements with inner an…", bg: "#E7E5E4", fg: "#1E2938", accent: "#006666" },
  { id: "pacman", name: "Pacman", concept: "Retro arcade-inspired design with pixel …", bg: "#000000", fg: "#111827", accent: "#2A3FE5" },
  { id: "paper", name: "Paper", concept: "Paper-textured, print-inspired design wi…", bg: "#FFFFFF", fg: "#111827", accent: "#111111" },
  { id: "perspective", name: "Perspective", concept: "Spatial depth design with isometric view…", bg: "#FFFFFF", fg: "#111827", accent: "#00BD7D" },
  { id: "premium", name: "Premium", concept: "Apple-inspired premium aesthetic with pr…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "professional", name: "Professional", concept: "Polished, business-ready design with mod…", bg: "#FFFFFF", fg: "#111827", accent: "#FECE14" },
  { id: "publication", name: "Publication", concept: "Print-inspired visual language for books…", bg: "#FFFFFF", fg: "#0A1829", accent: "#A855F7" },
  { id: "refined", name: "Refined", concept: "Carefully curated, modern minimal style …", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "retro", name: "Retro", concept: "Throwback design with vintage-inspired t…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "riso", name: "Riso", concept: "Playful two-color risograph-inspired sys…", bg: "#FFFFFF", fg: "#111827", accent: "#F237A1" },
  { id: "sega", name: "Sega", concept: "Arcade-inspired game interface with pixe…", bg: "#FFFFFF", fg: "#111827", accent: "#4502FF" },
  { id: "shadcn", name: "Shadcn", concept: "Shadcn/ui-inspired design with minimal, …", bg: "#FFFFFF", fg: "#111827", accent: "#000000" },
  { id: "simple", name: "Simple", concept: "Straightforward, no-frills design with c…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "sketch", name: "Sketch", concept: "Hand-drawn sketch aesthetic on warm pape…", bg: "#FFFFFF", fg: "#111827", accent: "#1DAD97" },
  { id: "skeumorphism", name: "Skeumorphism", concept: "Real-world mimicry with textured surface…", bg: "#FFFFFF", fg: "#111827", accent: "#FA3C00" },
  { id: "sleek", name: "Sleek", concept: "Modern minimalist aesthetic with clean l…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "spacious", name: "Spacious", concept: "Generous whitespace, consistent padding,…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "storytelling", name: "Storytelling", concept: "Narrative-driven design using visuals, c…", bg: "#FFFFFF", fg: "#111827", accent: "#3B82F6" },
  { id: "tetris", name: "Tetris", concept: "Classic block-game inspired design with …", bg: "#DFE7FF", fg: "#1C398E", accent: "#1C202B" },
  { id: "vibrant", name: "Vibrant", concept: "Lively, colorful design with bold playfu…", bg: "#FFFFFF", fg: "#2F281D", accent: "#7C61D4" },
  { id: "vintage", name: "Vintage", concept: "1950s-1990s nostalgia with skeuomorphic …", bg: "#C0C0C0", fg: "#000000", accent: "#008080" },
];
const THEMES = HOUSE_THEMES.concat(TYPEUI_THEMES);
const HOUSE_IDS = new Set(HOUSE_THEMES.map((t) => t.id));
// Real per-template screenshots from the TypeUI registry (used for non-house cards
// and the device preview so every template shows its actual look).
const REGISTRY_PREVIEW = "https://www.typeui.sh/registry-examples/";
const previewImg = (id) => (HOUSE_IDS.has(id) ? null : REGISTRY_PREVIEW + id + ".png");

const STEPS = [
  { id: "theme", label: "Theme" },
  { id: "brand", label: "Brand" },
  { id: "story", label: "Story" },
  { id: "socials", label: "Socials" },
  { id: "review", label: "Review" },
];

const CATEGORIES = ["Creator", "ASMR & Sleep", "Beauty", "Music / DJ", "Small business", "Coach", "Writer", "Photographer"];
const PLATFORMS = [
  { id: "tiktok", name: "TikTok", ph: "@yourhandle" },
  { id: "instagram", name: "Instagram", ph: "@yourhandle" },
  { id: "youtube", name: "YouTube", ph: "@yourchannel" },
  { id: "x", name: "X", ph: "@yourhandle" },
];

// Mirror of RESERVED in functions/api/publish.js — slugs are subdomains.
const RESERVED_SLUGS = ["assets", "partials", "scripts", "_template", "404", "500",
  "about", "contact", "pricing", "work", "blog", "privacy", "terms", "admin", "builder",
  "www", "staging", "api", "app", "mail", "email", "status", "docs", "help", "support",
  "cdn", "static", "ns1", "ns2"];

function StatusSticker({ s }) {
  const label = { draft: "Draft", staged: "Staged", building: "Building", live: "Live" }[s] || s;
  return <span className={"st " + s}><span className="dot"></span>{label}</span>;
}

function TopBar({ status }) {
  return (
    <header className="topbar">
      <span className="wm">wellpaged</span>
      <span className="topbar-kicker">Builder</span>
      <span className="spacer"></span>
      <StatusSticker s={status} />
    </header>
  );
}

/* Progress rail — indicative; click a completed step to jump back, not ahead. */
function Stepper({ current, maxReached, onGo }) {
  const ci = STEPS.findIndex((s) => s.id === current);
  const mi = STEPS.findIndex((s) => s.id === maxReached);
  return (
    <nav className="stepper" aria-label="Progress">
      {STEPS.map((s, i) => {
        const done = i < ci, active = s.id === current, reachable = i <= mi;
        return (
          <div key={s.id} className={"step" + (active ? " active" : (done ? " done" : "")) + (reachable ? " reachable" : "")}
               onClick={() => reachable && onGo(s.id)} aria-current={active ? "step" : undefined}>
            <span className="n">{done ? "✓" : i + 1}</span>{s.label}
          </div>
        );
      })}
    </nav>
  );
}

/* Persistent footer nav — the primary way to move through the flow. */
function StepNav({ stepIndex, total, canNext, nextLabel, onBack, onNext }) {
  return (
    <div className="step-nav">
      {stepIndex > 0
        ? <button className="btn ghost" onClick={onBack}>← Back</button>
        : <span style={{ width: 1 }}></span>}
      <span className="spacer"></span>
      <span className="progress">Step {stepIndex + 1} of {total}</span>
      <button className="btn primary" onClick={onNext} disabled={!canNext}>{nextLabel}</button>
    </div>
  );
}

function StepHead({ kicker, children }) {
  return <div className="step-head"><span className="eyebrow">{kicker}</span><h2>{children}</h2></div>;
}

/* ---- Step 1: Theme ---- */
function ThemeCard({ t, value, onChange }) {
  const sel = value === t.id;
  return (
    <div className={"theme-card" + (sel ? " sel" : "")} onClick={() => onChange(t.id)}
         role="button" tabIndex={0} aria-pressed={sel}
         onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onChange(t.id); } }}>
      <span className="pick-badge">✦ Picked</span>
      <ThemeThumb id={t.id} bg={t.bg} fg={t.fg} accent={t.accent} name={t.name.split(" ")[0]} img={previewImg(t.id)} />
      <div className="theme-meta"><div className="tn">{t.name}</div><div className="tc">{t.concept}</div></div>
    </div>
  );
}
function ThemePicker({ value, onChange }) {
  const [q, setQ] = useState("");
  const ql = q.trim().toLowerCase();
  const match = (t) => !ql || t.name.toLowerCase().includes(ql) || (t.concept || "").toLowerCase().includes(ql) || t.id.includes(ql);
  const house = HOUSE_THEMES.filter(match);
  const typeui = TYPEUI_THEMES.filter(match);
  return (
    <React.Fragment>
      <StepHead kicker="Theme">Pick a <em>concept.</em></StepHead>
      <p className="step-intro">This sets the whole feeling of your landing page — {THEMES.length} designs. House themes preview live; TypeUI designs build a full custom site.</p>
      <input className="inp theme-search" placeholder="Search designs…" value={q} onChange={(e) => setQ(e.target.value)} aria-label="Search designs" />
      {house.length > 0 && <React.Fragment>
        <div className="theme-group">Wellpaged house</div>
        <div className="theme-grid">{house.map((t) => <ThemeCard key={t.id} t={t} value={value} onChange={onChange} />)}</div>
      </React.Fragment>}
      {typeui.length > 0 && <React.Fragment>
        <div className="theme-group">TypeUI designs <span className="theme-group-n">{typeui.length}</span></div>
        <div className="theme-grid">{typeui.map((t) => <ThemeCard key={t.id} t={t} value={value} onChange={onChange} />)}</div>
      </React.Fragment>}
      {house.length + typeui.length === 0 && <p className="step-intro">No designs match “{q}”.</p>}
    </React.Fragment>
  );
}

/* ---- Step 2: Brand basics ---- */
function BrandForm({ profile, onChange }) {
  const h = (profile.handle || "").toLowerCase();
  const taken = RESERVED_SLUGS.includes(h);
  const tooShort = !!h && (h.length < 3 || h.length > 40 || h.startsWith("-") || h.endsWith("-"));
  const set = (patch) => onChange({ ...profile, ...patch });
  return (
    <React.Fragment>
      <StepHead kicker="Your brand">The <em>basics.</em></StepHead>
      <div className="field"><label>Display name</label>
        <input className="inp" value={profile.name} placeholder="e.g. Rissa"
          onChange={(e) => set({ name: e.target.value, initial: (e.target.value.trim()[0] || "?").toUpperCase() })} /></div>
      <div className="field"><label>Your address</label>
        <div className="handle-row"><span className="pre">wellpaged.com/</span>
          <input value={profile.handle} placeholder="yourname"
            onChange={(e) => set({ handle: e.target.value.replace(/[^a-z0-9-]/gi, "").toLowerCase() })} /></div>
        {taken ? <div className="avail taken">✕ That address is taken — try another.</div>
         : tooShort ? <div className="avail taken">✕ Use 3–40 letters/numbers; no leading or trailing hyphen.</div>
         : <div className="avail ok">✓ {profile.handle || "yourname"}.wellpaged.com is available</div>}
      </div>
      <div className="field"><label>What do you do?</label>
        <div className="cat-chips">
          {CATEGORIES.map((c) => (
            <button key={c} className={"cat-chip" + (profile.category === c ? " on" : "")} onClick={() => set({ category: c })}>{c}</button>
          ))}
        </div>
      </div>
      <div className="field"><label>One-line tagline</label>
        <input className="inp" value={profile.tagline} placeholder="The hook under your name"
          onChange={(e) => set({ tagline: e.target.value })} /></div>
    </React.Fragment>
  );
}

/* ---- Step 3: Story + highlights (the landing-page content) ---- */
function StoryForm({ profile, links, onProfile, onLinks }) {
  const dragIdx = useRef(null);
  const [dragOver, setDragOver] = useState(null);
  const set = (i, patch) => onLinks(links.map((l, j) => (j === i ? { ...l, ...patch } : l)));
  const onDel = (i) => onLinks(links.filter((_, j) => j !== i));
  const onAdd = () => onLinks([...links, { label: "", url: "", feat: false }]);
  const toggleFeat = (i) => set(i, { feat: !links[i].feat });
  const normalizeUrl = (i) => {
    const u = (links[i].url || "").trim();
    if (u && !/^(https?:|mailto:|tel:)/i.test(u) && /\./.test(u) && !/\s/.test(u)) set(i, { url: "https://" + u });
  };
  const handleDrop = (i) => {
    const from = dragIdx.current; if (from == null || from === i) return;
    const arr = [...links]; const [m] = arr.splice(from, 1); arr.splice(i, 0, m); onLinks(arr);
    dragIdx.current = null; setDragOver(null);
  };
  return (
    <React.Fragment>
      <StepHead kicker="Your story">Tell visitors <em>who you are.</em></StepHead>
      <div className="field"><label>About you</label>
        <textarea value={profile.about} placeholder="A few sentences in your own voice — what you make, who it's for, why people should care."
          onChange={(e) => onProfile({ ...profile, about: e.target.value })}></textarea>
        <div className="field-hint">This becomes the intro paragraph on your landing page.</div>
      </div>
      <div className="field"><label>Highlights &amp; calls-to-action</label>
        <div className="link-edit-list">
          {links.map((l, i) => {
            const ic = l.icon || (window.inferIcon && window.inferIcon(l.url));
            return (
              <div className={"link-edit" + (dragOver === i ? " drag" : "")} key={i}
                   onDragOver={(e) => { e.preventDefault(); setDragOver(i); }}
                   onDrop={() => handleDrop(i)} onDragEnd={() => setDragOver(null)}>
                <span className="grip" draggable onDragStart={() => (dragIdx.current = i)} title="Drag to reorder" aria-label="Drag to reorder">⋮⋮</span>
                {ic ? <span className="le-ic"><SocialIcon name={ic} /></span> : null}
                <div className="le-fields">
                  <input className="le-in" placeholder="Label (e.g. Watch my latest live)" value={l.label || ""}
                         onChange={(e) => set(i, { label: e.target.value })} aria-label="Highlight label" />
                  <input className="le-in mono" placeholder="https://…" value={l.url || ""} inputMode="url"
                         onChange={(e) => set(i, { url: e.target.value })} onBlur={() => normalizeUrl(i)} aria-label="Highlight URL" />
                </div>
                <button className={"le-feat" + (l.feat ? " on" : "")} onClick={() => toggleFeat(i)} title="Feature this" aria-label="Feature this">✦</button>
                <button className="le-del" onClick={() => onDel(i)} aria-label="Delete">✕</button>
              </div>
            );
          })}
          <button className="add-link" onClick={onAdd}>+ Add a highlight</button>
        </div>
        <div className="field-hint">Featured (✦) highlights get the accent treatment. Drag the handle to reorder.</div>
      </div>
    </React.Fragment>
  );
}

/* ---- Step 4: Socials (the core intake) ---- */
function SocialsForm({ socials, onChange }) {
  const set = (id, patch) => onChange(socials.map((s) => s.platform === id ? { ...s, ...patch } : s));
  const onCount = socials.filter((s) => s.on && s.handle).length;
  return (
    <React.Fragment>
      <StepHead kicker="Your socials">Where can people <em>find you?</em></StepHead>
      <p className="step-intro">Add the platforms you're on. Only the ones you fill in show on your page — {onCount} active.</p>
      <div className="social-edit-list">
        {PLATFORMS.map((p) => {
          const s = socials.find((x) => x.platform === p.id) || { on: false, handle: "" };
          return (
            <div className={"social-edit" + (s.on ? "" : " off")} key={p.id}>
              <span className="si"><SocialIcon name={p.id} /></span>
              <span className="sname">{p.name}</span>
              <input value={s.handle} placeholder={p.ph}
                onChange={(e) => set(p.id, { handle: e.target.value, on: e.target.value ? true : s.on })} />
              <button className={"s-toggle" + (s.on ? " on" : "")} onClick={() => set(p.id, { on: !s.on })} aria-pressed={s.on}>
                {s.on ? "On" : "Add"}
              </button>
            </div>
          );
        })}
      </div>
    </React.Fragment>
  );
}

/* ---- Step 5: Review ---- */
function ReviewStep({ profile, theme, socials }) {
  const handle = profile.handle || "yourname";
  const onSocials = socials.filter((s) => s.on && s.handle);
  const t = THEMES.find((x) => x.id === theme);
  const rows = [
    ["Address", handle + ".wellpaged.com"],
    ["Name", profile.name],
    ["Template", t ? t.name : theme],
    ["Category", profile.category || "—"],
    ["Socials", onSocials.length ? onSocials.map((s) => s.platform).join(" · ") : "none yet"],
  ];
  return (
    <React.Fragment>
      <StepHead kicker="Review">Looks good? <em>Ship it.</em></StepHead>
      <p className="step-intro">We'll build your landing page and put it live. Usually under a minute — you can keep editing and rebuild anytime.</p>
      <div className="review-card">
        {rows.map(([k, v]) => (
          <div className="review-row" key={k}><span className="rk">{k}</span><span className="rv">{v}</span></div>
        ))}
      </div>
    </React.Fragment>
  );
}

// Cloudflare Turnstile site key (PUBLIC — safe to ship in client JS). Production
// widget for wellpaged.com; pairs with the TURNSTILE_SECRET_KEY secret set on the
// Worker (Settings → Variables and Secrets).
const TURNSTILE_SITE_KEY = "0x4AAAAAADeD5ucTFpg4bGBQ";

function PublishDialog({ handle, token, onToken, onConfirm, onClose }) {
  const boxRef = useRef(null);
  const widgetId = useRef(null);
  useEffect(() => {
    let stop = false;
    const mount = () => {
      if (stop || !boxRef.current || !window.turnstile) return;
      try {
        widgetId.current = window.turnstile.render(boxRef.current, {
          sitekey: TURNSTILE_SITE_KEY,
          callback: (t) => onToken(t),
          "expired-callback": () => onToken(null),
          "error-callback": () => onToken(null),
        });
      } catch (e) {}
    };
    if (window.turnstile) { mount(); }
    else {
      const iv = setInterval(() => { if (window.turnstile) { clearInterval(iv); mount(); } }, 150);
      return () => { stop = true; clearInterval(iv); };
    }
    return () => {
      stop = true;
      try { if (widgetId.current != null && window.turnstile) window.turnstile.remove(widgetId.current); } catch (e) {}
    };
  }, []);
  return (
    <div className="scrim" onClick={onClose}>
      <div className="dialog" onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true">
        <span className="eyebrow">Publish</span>
        <h3>Put it live?</h3>
        <p>We'll build your landing page and put it live at:</p>
        <p className="url-line">{handle}.wellpaged.com</p>
        <p style={{ marginTop: 8 }}>Usually under a minute. You can keep editing and rebuild anytime.</p>
        <div ref={boxRef} className="cf-turnstile-box" style={{ marginTop: 14, minHeight: 65 }}></div>
        <div className="dialog-actions">
          <button className="btn ghost" onClick={onClose}>Not yet</button>
          <button className="btn primary" onClick={onConfirm} disabled={!token}>Build &amp; publish →</button>
        </div>
        {!token && <p className="ts-hint" style={{ marginTop: 8, fontSize: 12, color: "var(--text-dim)" }}>Complete the check above to enable publishing.</p>}
      </div>
    </div>
  );
}

function DevicePreview({ theme, profile, links, socials, status }) {
  const handle = profile.handle || "yourname";
  const url = status === "staged" ? "staging--" + handle + ".wellpaged.com"
            : status === "live" ? handle + ".wellpaged.com"
            : "live preview";
  const isHouse = HOUSE_IDS.has(theme);
  const t = THEMES.find((x) => x.id === theme) || {};
  return (
    <aside className="preview-pane">
      <div className="preview-tag"><StatusSticker s={status} /> <span className="url">{url}</span></div>
      {isHouse ? (
        <div className="phone">
          <div className="phone-screen"><div className="phone-scroll">
            <BioPage theme={theme} profile={profile} links={links} socials={socials} />
          </div></div>
        </div>
      ) : (
        <div className="tpl-preview">
          <img src={previewImg(theme)} alt={(t.name || theme) + " template preview"} loading="lazy" />
        </div>
      )}
      {!isHouse && <div className="preview-note">Reference design for <strong>{t.name || theme}</strong>. Your published page is a full custom site built from this template with your name, story, links and socials.</div>}
    </aside>
  );
}

Object.assign(window, {
  TopBar, Stepper, StepNav, ThemePicker, BrandForm, StoryForm, SocialsForm, ReviewStep,
  PublishDialog, DevicePreview, StatusSticker, THEMES, STEPS,
});
