/* ========================================================================
   screens-generate.jsx — Multi-platform image-first generator
   ====================================================================== */

// ── SHIFT-specific post types ─────────────────────────────────────────────
const POST_TYPES = [
  { id: "training-drop",  label: "Training",    prompt: "High-intensity athlete training session, peak physical focus, performance data overlay" },
  { id: "race-week",      label: "Race Week",   prompt: "Race week atmosphere, circuit details, countdown tension, motorsport energy and speed" },
  { id: "app-feature",    label: "App Feature", prompt: "Mobile performance dashboard, clean UI data, tracking metrics, digital interface aesthetic" },
  { id: "perf-stats",     label: "Stats",       prompt: "Bold performance numbers, personal best metrics, progress data visualisation, large typography" },
  { id: "recovery",       label: "Recovery",    prompt: "Active recovery science, controlled breathing, cool-down ritual, body performance optimisation" },
  { id: "coach-insight",  label: "Coach",       prompt: "Expert coaching wisdom, bold motivational statement, technical training insight, powerful quote" },
  { id: "community",      label: "Community",   prompt: "Athlete community moment, user results, social proof, real achievement celebration" },
  { id: "coming-soon",    label: "Teaser",      prompt: "Mysterious product reveal, anticipation building, cryptic preview, premium dark drama" },
];

const IG_FORMATS = [
  { id: "story",    label: "Reels",  ratio: "9:16", dalle: "story",    aspect: "9/16" },
  { id: "portrait", label: "Post",   ratio: "4:5",  dalle: "portrait", aspect: "4/5"  },
  { id: "square",   label: "Square", ratio: "1:1",  dalle: "square",   aspect: "1/1"  },
];

const FB_FORMATS = [
  { id: "landscape", label: "Landscape", ratio: "1.91:1", dalle: "landscape", aspect: "1.91/1" },
  { id: "square",    label: "Square",    ratio: "1:1",    dalle: "square",    aspect: "1/1"    },
  { id: "portrait",  label: "Portrait",  ratio: "4:5",    dalle: "portrait",  aspect: "4/5"    },
];

const GEN_QUANTITIES = [3, 5, 10, 20];

// ── Reusable toggle switch ────────────────────────────────────────────────
const Toggle = ({ label, value, onChange, accentColor = "#EFFF00" }) => (
  <button
    data-bk-bound="true"
    onClick={() => onChange(!value)}
    style={{ display: "flex", alignItems: "center", gap: 7, background: "none", border: "none", cursor: "pointer", padding: 0, flexShrink: 0 }}
  >
    <div style={{ width: 30, height: 16, borderRadius: 8, background: value ? accentColor : "#3A372F", position: "relative", transition: "background 0.2s", flexShrink: 0 }}>
      <div style={{ position: "absolute", top: 2, left: value ? 16 : 2, width: 12, height: 12, borderRadius: "50%", background: value ? "#1A1813" : "#5C5C5C", transition: "left 0.2s" }} />
    </div>
    <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: value ? "#C8C8C5" : "#5C5C5C", letterSpacing: "0.12em", fontWeight: 700, textTransform: "uppercase", userSelect: "none" }}>{label}</span>
  </button>
);

// ── Segmented control ─────────────────────────────────────────────────────
const SegCtrl = ({ label, options, value, onChange }) => (
  <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
    {label && <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#5C5C5C", letterSpacing: "0.12em", fontWeight: 700, textTransform: "uppercase" }}>{label}</span>}
    <div style={{ display: "flex", gap: 2, background: "#141210", border: "1px solid #3A372F", borderRadius: 5, padding: 2 }}>
      {options.map(([v, l]) => (
        <button key={v} data-bk-bound="true" onClick={() => onChange(v)} style={{
          padding: "3px 9px", borderRadius: 3, fontSize: 9, fontWeight: 700,
          fontFamily: "'JetBrains Mono', monospace", letterSpacing: "0.06em",
          cursor: "pointer", border: "none",
          background: value === v ? "#EFFF00" : "transparent",
          color: value === v ? "#1A1813" : "#5C5C5C",
          transition: "all 0.12s",
        }}>{l}</button>
      ))}
    </div>
  </div>
);

const IGGenerateScreen = ({ forcePlatform } = {}) => {
  const project = (() => { try { return JSON.parse(localStorage.getItem("boltkit.currentProject.v1") || "{}"); } catch { return {}; } })();
  const hasProject = Boolean(project.name || project.url);

  const [postType,    setPostType]    = React.useState(POST_TYPES[0]);
  const [format,      setFormat]      = React.useState(forcePlatform === "facebook" ? FB_FORMATS[0] : IG_FORMATS[1]);
  const [quantity,    setQuantity]    = React.useState(5);
  const [brief,       setBrief]       = React.useState("");
  const [generating,  setGenerating]  = React.useState(false);
  const [genProgress, setGenProgress] = React.useState({ done: 0, total: 0 });
  const [captionIds,  setCaptionIds]  = React.useState({});
  const [copied,      setCopied]      = React.useState(null);
  const [provider,    setProvider]    = React.useState(null); // { provider, model, connected }
  const [videoJobs,   setVideoJobs]   = React.useState({}); // postId → { taskId, status, videoUrl, polling }
  const [posts,       setPosts]       = React.useState(() => {
    const initKey = (forcePlatform || "instagram") === "facebook" ? "boltkit.fbDraftPosts.v1" : "boltkit.igPosts.v2";
    try { return JSON.parse(localStorage.getItem(initKey) || "[]"); } catch { return []; }
  });

  // Settings toggles
  const [styleMode,           setStyleMode]           = React.useState("auto");  // "auto" | "graphic" | "photo"
  const [promptMode,          setPromptMode]          = React.useState("simple");// "simple" | "full"
  const [autoCaptionAfterGen, setAutoCaptionAfterGen] = React.useState(true);

  const [platform,      setPlatform]      = React.useState(forcePlatform || "instagram"); // "instagram" | "facebook"

  // Storage keys per platform
  const storageKey   = platform === "facebook" ? "boltkit.fbDraftPosts.v1" : "boltkit.igPosts.v2";
  const calendarRoute = platform === "facebook" ? "fb-calendar" : "ig-calendar";
  const FORMATS      = platform === "facebook" ? FB_FORMATS : IG_FORMATS;

  const switchPlatform = (p) => {
    setPlatform(p);
    setFormat(p === "facebook" ? FB_FORMATS[0] : IG_FORMATS[1]);
    try {
      const saved = JSON.parse(localStorage.getItem(p === "facebook" ? "boltkit.fbDraftPosts.v1" : "boltkit.igPosts.v2") || "[]");
      setPosts(saved);
    } catch { setPosts([]); }
  };

  const [runwayConnected, setRunwayConnected] = React.useState(null);
  const [tweakTexts,    setTweakTexts]    = React.useState({});
  const [tweakingIds,   setTweakingIds]   = React.useState({});
  const [bulkUploading, setBulkUploading] = React.useState(false);
  const [uploadProgress, setUploadProgress] = React.useState({ done: 0, total: 0 });
  const [showLogoOverlay, setShowLogoOverlay] = React.useState(false);
  const [bulkCaptioning, setBulkCaptioning] = React.useState(false);
  const [bulkCapProgress, setBulkCapProgress] = React.useState({ done: 0, total: 0 });
  const [orderMode, setOrderMode] = React.useState(false);
  const [orderQueue, setOrderQueue] = React.useState([]); // post IDs in desired posting order

  // Auto-schedule state
  const genTimesForCount = (n) => {
    if (n <= 0) return [];
    if (n === 1) return ["09:00"];
    const START = 8 * 60, END = 21 * 60; // 8 am – 9 pm
    return Array.from({ length: n }, (_, i) => {
      const mins = Math.round(START + (END - START) * i / (n - 1));
      return `${String(Math.floor(mins / 60)).padStart(2,"0")}:${String(mins % 60).padStart(2,"0")}`;
    });
  };
  const tomorrowStr = () => { const d = new Date(); d.setDate(d.getDate() + 1); return d.toISOString().slice(0, 10); };
  const [schedStart,  setSchedStart]  = React.useState(tomorrowStr());
  const [schedPerDay, setSchedPerDay] = React.useState(4);
  const [schedTimes,  setSchedTimes]  = React.useState(genTimesForCount(4));
  // In-memory store for object URLs created from uploaded files (lost on page reload, replaced by publicUrl once uploaded)
  const uploadedImageStore = React.useRef(new Map());
  // Brand logo URL — prefers uploaded SVG assets, falls back to the baked-in SHIFT wordmark
  const [brandLogoSvg, setBrandLogoSvg] = React.useState(() => {
    try {
      const assets = JSON.parse(localStorage.getItem("boltkit.brandAssets.v1") || "[]");
      const svgAsset = assets.find(a => a.dataUrl && a.dataUrl.startsWith("data:image/svg"));
      return svgAsset ? svgAsset.dataUrl : "/boltkit-design/shift-wordmark.svg";
    } catch { return "/boltkit-design/shift-wordmark.svg"; }
  });
  // PNG version of the SVG logo — used as Ideogram remix reference (Ideogram rejects SVGs)
  const [brandLogoPng, setBrandLogoPng] = React.useState(null);
  const brandLogoPngRef = React.useRef(null);

  // Convert SVG logo → rich brand card PNG so Ideogram gets a proper style reference
  React.useEffect(() => {
    const bb = loadBrandBrain ? (() => { try { return JSON.parse(localStorage.getItem("boltkit.brandBrain.v1") || "null"); } catch { return null; } })() : null;
    const bg   = bb?.secondary || "#07080A";
    const lime = bb?.primary   || "#B8FF1A";
    const name = ((project?.name || "SHIFT")).toUpperCase();

    const renderCard = (whiteLogoImg, darkLogoImg) => {
      try {
        const W = 900, H = 900;
        const canvas = document.createElement("canvas");
        canvas.width = W; canvas.height = H;
        const ctx = canvas.getContext("2d");

        // ── Dark half (top) ───────────────────────────────────────────
        ctx.fillStyle = bg;
        ctx.fillRect(0, 0, W, H * 0.55);

        // SHIFT 'S' monogram icon — 4 horizontal bars of decreasing width on lime square
        // (accurate reproduction of the actual app icon structure)
        const iconX = 52, iconY = 44, iconSize = 108;
        ctx.fillStyle = lime;
        ctx.beginPath();
        ctx.roundRect(iconX, iconY, iconSize, iconSize, 14);
        ctx.fill();
        // 4 stacked bars: decreasing width from top, last row has short bar + tiny square
        const bars = [
          { x: 14, w: 76 }, // longest
          { x: 14, w: 60 }, // second
          { x: 14, w: 44 }, // third
          { x: 14, w: 26 }, // short bottom bar
        ];
        const barH2 = 13, gap2 = 19, barY0 = iconY + 20;
        ctx.fillStyle = bg;
        bars.forEach((b, i) => {
          ctx.fillRect(iconX + b.x, barY0 + i * gap2, b.w, barH2);
        });
        // small square after the bottom bar (the "dot" accent)
        ctx.fillRect(iconX + 14 + 30, barY0 + 3 * gap2, barH2, barH2);

        // Large brand name — Impact with italic transform (Teko proxy)
        ctx.font = `bold 190px Impact, 'Arial Narrow', Arial, sans-serif`;
        ctx.fillStyle = lime;
        ctx.textBaseline = "top";
        ctx.save();
        ctx.transform(1, 0, -0.32, 1, 0, 0); // -20° italic skew
        ctx.fillText(name, 180, 90);
        ctx.restore();

        // Sub-brand "PRO" tag
        ctx.fillStyle = lime;
        ctx.font = `bold 34px Impact, sans-serif`;
        ctx.save();
        ctx.transform(1, 0, -0.32, 1, 0, 0);
        ctx.fillText("PRO", 182, 290);
        ctx.restore();

        // White wordmark on dark (shows logo at actual color on brand background)
        if (whiteLogoImg) {
          ctx.drawImage(whiteLogoImg, 52, 360, 500, 95);
        }

        // Lime divider rule
        ctx.fillStyle = lime;
        ctx.fillRect(0, H * 0.55 - 5, W, 5);

        // ── Lime half (bottom) — dark wordmark on lime (second lockup) ─
        ctx.fillStyle = lime;
        ctx.fillRect(0, H * 0.55, W, H * 0.45);

        // Colour swatches
        ctx.fillStyle = bg;
        ctx.fillRect(52, H * 0.55 + 28, 90, 90);
        ctx.fillStyle = "#FFFFFF";
        ctx.fillRect(160, H * 0.55 + 28, 90, 90);
        ctx.fillStyle = "#FF5232";
        ctx.fillRect(268, H * 0.55 + 28, 90, 90);

        // Swatch labels
        ctx.font = "bold 11px monospace";
        ctx.fillStyle = bg;
        ctx.fillText(bg.toUpperCase(),   52,  H * 0.55 + 132);
        ctx.fillText("#FFFFFF",          160, H * 0.55 + 132);
        ctx.fillText("#FF5232",          268, H * 0.55 + 132);

        // Dark wordmark on lime (the second canonical lockup)
        if (darkLogoImg) {
          ctx.drawImage(darkLogoImg, 52, H * 0.55 + 155, 500, 95);
        } else if (whiteLogoImg) {
          // Fallback: draw white logo with darken blend mode
          ctx.globalCompositeOperation = "multiply";
          ctx.drawImage(whiteLogoImg, 52, H * 0.55 + 155, 500, 95);
          ctx.globalCompositeOperation = "source-over";
        } else {
          // Text fallback
          ctx.fillStyle = bg;
          ctx.font = `bold 72px Impact, sans-serif`;
          ctx.save();
          ctx.transform(1, 0, -0.32, 1, 0, 0);
          ctx.fillText(name, 52, H * 0.55 + 175);
          ctx.restore();
        }

        // Font label
        ctx.fillStyle = bg;
        ctx.font = "bold 12px monospace";
        ctx.fillText("HEADING: TEKO 700  ·  BODY: SPACE GROTESK  ·  MONO: JETBRAINS MONO", 52, H - 28);

        const png = canvas.toDataURL("image/png");
        brandLogoPngRef.current = png;
        setBrandLogoPng(png);
      } catch {}
    };

    // Load both the white-on-dark SVG and the dark-on-light SVG in parallel
    const loadSvg = (src) => new Promise(resolve => {
      const img = new window.Image();
      img.onload = () => resolve(img);
      img.onerror = () => resolve(null);
      img.crossOrigin = "anonymous";
      img.src = src;
    });

    Promise.all([
      brandLogoSvg ? loadSvg(brandLogoSvg) : Promise.resolve(null),
      loadSvg("/boltkit-design/shift-wordmark-dark.svg"),
    ]).then(([whiteImg, darkImg]) => renderCard(whiteImg, darkImg));
  }, [brandLogoSvg]);

  // Check which image provider is active + Runway status
  React.useEffect(() => {
    fetch("/api/image-provider")
      .then(r => r.json())
      .then(setProvider)
      .catch(() => setProvider({ provider: "none", connected: false }));
    fetch("/api/image-provider") // Runway check via dedicated endpoint when built
      .catch(() => {});
    // Check Runway separately
    fetch("/api/video-status?taskId=ping")
      .then(r => r.json())
      .then(d => setRunwayConnected(d.error !== "RUNWAY_API_KEY not configured"))
      .catch(() => setRunwayConnected(false));
  }, []);

  // Reload posts when the active project switches — switchProject already saved/restored
  // the correct project-scoped draft posts into boltkit.igPosts.v2 / boltkit.fbDraftPosts.v1
  React.useEffect(() => {
    const onSwitch = () => {
      try {
        const key = platform === "facebook" ? "boltkit.fbDraftPosts.v1" : "boltkit.igPosts.v2";
        const saved = JSON.parse(localStorage.getItem(key) || "[]");
        setPosts(saved);
      } catch { setPosts([]); }
    };
    window.addEventListener("boltkit:project-switched", onSwitch);
    return () => window.removeEventListener("boltkit:project-switched", onSwitch);
  }, [platform]);

  const savePosts = (list) => {
    setPosts(list);
    try {
      localStorage.setItem(storageKey, JSON.stringify(list.slice(0, 500)));
      window.dispatchEvent(new Event("boltkit:saved"));
    } catch {}
  };

  const loadBrandBrain = () => {
    try { return JSON.parse(localStorage.getItem("boltkit.brandBrain.v1") || "null"); } catch { return null; }
  };

  const loadBrandAsset = () => {
    try {
      // Priority order:
      // 1. App screenshots — actual brand posts/UI, the best visual reference for Ideogram
      // 2. Uploaded brand assets (non-SVG PNGs/JPGs)
      // 3. Canvas brand card — only used when nothing else is available
      const shots = JSON.parse(localStorage.getItem("boltkit.appScreenshots.v1") || "[]");
      const usableShots = shots.filter(s => s.dataUrl && !s.dataUrl.startsWith("data:image/svg") && !s.dataUrl.startsWith("data:image/gif"));
      if (usableShots.length) return usableShots[Math.floor(Math.random() * usableShots.length)];

      const assets = JSON.parse(localStorage.getItem("boltkit.brandAssets.v1") || "[]");
      const usable = assets.filter(a => a.dataUrl && !a.dataUrl.startsWith("data:image/svg"));
      if (usable.length) return usable[Math.floor(Math.random() * usable.length)];

      // Fallback: canvas brand card (shows logo, colors, and lockups)
      if (brandLogoPngRef.current) return { id: "logo-png", name: "brand-style-card.png", dataUrl: brandLogoPngRef.current };
      return null;
    } catch { return null; }
  };

  const loadBrandInfluence = () => {
    return localStorage.getItem("boltkit.brandInfluence.v1") || "medium";
  };

  const buildPrompt = (index) => {
    const bb = loadBrandBrain();

    // Detect SHIFT brand by name or primary colour
    const brandName = (project.name || "").toUpperCase().trim();
    const isShift   = brandName === "SHIFT" || brandName === "SHIFT PRO"
                   || (bb?.primary || "").toUpperCase() === "#B8FF1A";
    const primary   = bb?.primary   || (isShift ? "#B8FF1A" : null);
    const secondary = bb?.secondary || (isShift ? "#07080A" : null);

    if (isShift) {
      // ── SHIFT-specific Ideogram prompt ────────────────────────────
      const briefLine = brief ? ` ${brief.trim()}.` : "";

      if (promptMode === "simple") {
        // Short prompt — reference image + Ideogram's magic_prompt do the heavy lifting.
        // Just anchor brand colours and hand off creative variation.
        return `SHIFT PRO sports app social post. Black background #07080A, electric lime #B8FF1A accents, bold condensed italic typography. ${postType.prompt}.${briefLine} Variation ${index + 1}.`;
      }

      // Full prompt — detailed SHIFT brand brief with rotating compositional angle
      const angles = [
        "dramatic close-up of an athlete in peak focus, dark studio lighting",
        "bold graphic typography composition, abstract speed lines and circuit shapes",
        "athlete training montage with performance data dashboard overlay",
        "minimalist dark poster with a single bold typographic statement",
        "dynamic split composition: dark photography left, lime graphic right",
        "overhead aerial perspective of a race circuit with performance stats",
        "cinematic wide shot of an athlete silhouette against dramatic lighting",
        "data-driven dashboard aesthetic with large score metrics and lime accents",
        "powerful portrait shot with large condensed text overlay",
        "bold geometric graphic design with race livery-inspired stripe elements",
      ];
      const angle = angles[index % angles.length];

      return [
        `SHIFT PRO motorsport fitness app social media post. Dark near-black background (#07080A). Electric lime (#B8FF1A) dominant accent. White secondary.`,
        `Extreme condensed bold all-caps display typography in electric lime, very large text. Teko Bold or Bebas Neue letterforms, slight italic slant.`,
        `Small lime square badge with horizontal stacked bars in upper corner. Bold italic condensed wordmark "SHIFT" at the bottom edge.`,
        `Content: ${postType.prompt}.${briefLine}`,
        `Composition: ${angle}.`,
        `Style: premium sports brand campaign — Nike x F1, Alpinestars, Puma motorsport. Dark, sharp, electric. ${format.ratio} format.`,
        `Unique variation ${index + 1}.`,
      ].join(" ");
    }

    // ── Generic brand prompt (non-SHIFT) ────────────────────────────
    const parts = [
      bb?.imageBrief ? `${bb.imageBrief}` : null,
      postType.prompt,
      brief || null,
      project.name ? `Brand: ${project.name}` : null,
      project.description ? project.description.slice(0, 80) : null,
      primary   ? `Primary colour ${primary} — use prominently` : null,
      secondary ? `Background ${secondary}` : null,
      bb?.typography ? `${bb.typography} — bold condensed all-caps` : `Bold condensed all-caps display font`,
      project.name ? `Include "${project.name}" wordmark` : null,
      `${format.ratio} ${platform === "facebook" ? "Facebook" : "Instagram"} ${format.label}. Image ${index + 1}.`,
    ].filter(Boolean);
    return parts.join(". ");
  };

  // Map UI styleMode → Ideogram style_type
  const getStyleType = () => ({ graphic: "DESIGN", photo: "REALISTIC", auto: "GENERAL" }[styleMode] || "GENERAL");

  const generateImages = async () => {
    if (generating) return;
    setGenerating(true);
    const total = quantity;
    setGenProgress({ done: 0, total });
    const styleType = getStyleType();

    const placeholders = Array.from({ length: total }, (_, i) => ({
      id: `igpost-${Date.now()}-${i}`,
      postType: postType.id,
      format: format.id,
      status: "generating",
      imageUrl: null,
      caption: null,
      hashtags: [],
      prompt: buildPrompt(i),
    }));

    savePosts([...placeholders, ...posts]);

    const results = [...placeholders];
    for (let i = 0; i < results.length; i++) {
      const post = results[i];
      try {
        const brandAsset     = loadBrandAsset();
        const brandInfluence = loadBrandInfluence();
        const bb2 = loadBrandBrain();
        const bn2 = (project.name || "").toUpperCase();
        const isS = bn2 === "SHIFT" || bn2 === "SHIFT PRO" || (bb2?.primary || "").toUpperCase() === "#B8FF1A";
        const resp = await fetch("/api/generate-image", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            prompt:               post.prompt,
            size:                 format.dalle,
            styleHint:            postType.id,
            styleType,
            referenceImageBase64: brandAsset?.dataUrl || null,
            brandInfluence:       isS && brandAsset ? "strong" : brandInfluence,
          }),
        });
        const data = await resp.json();
        results[i] = data.ok && data.imageUrl
          ? { ...post, status: "ready", imageUrl: data.imageUrl }
          : { ...post, status: "error", error: data.error || "Failed" };
      } catch (e) {
        results[i] = { ...post, status: "error", error: e.message };
      }
      setGenProgress(p => ({ ...p, done: p.done + 1 }));
      const tail = posts.filter(p => !placeholders.find(pl => pl.id === p.id));
      savePosts([...results, ...tail]);
    }

    setGenerating(false);
    const ok = results.filter(p => p.status === "ready").length;
    window.BoltKitToast?.({ msg: `${ok} image${ok !== 1 ? "s" : ""} generated.`, type: ok ? "success" : "error" });

    // Auto-caption mode — immediately generate captions for all new images
    if (autoCaptionAfterGen && ok > 0) {
      const toCaption = results.filter(p => p.status === "ready" && !p.caption);
      if (toCaption.length) await generateAllCaptionsFor(toCaption);
    }
  };

  const generateCaption = async (post) => {
    if (captionIds[post.id]) return 0;
    setCaptionIds(prev => ({ ...prev, [post.id]: true }));
    let cost = 0;
    try {
      const resp = await fetch("/api/generate-instagram-post", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          project,
          post: {
            tone: project.tone_of_voice || "Bold & engaging",
            size: post.format,
            theme: postType.label,
            content_type: post.postType,
            image_prompt: (post.prompt || "").slice(0, 500),
            // Hosted image URL so the AI captions the actual picture (vision).
            imageUrl: post.publicUrl || post.imageUrl,
          },
        }),
      });
      const data = await resp.json();
      if (data.ok && data.post) {
        cost = data.cost?.cost_usd || 0;
        // Functional update — safe for sequential bulk generation
        setPosts(prev => {
          const updated = prev.map(p => p.id === post.id ? { ...p, ...data.post } : p);
          try { localStorage.setItem(storageKey, JSON.stringify(updated.slice(0, 500))); } catch {}
          return updated;
        });
      } else {
        window.BoltKitToast?.({ msg: data.error || "Caption failed.", type: "error" });
      }
    } catch (e) {
      window.BoltKitToast?.({ msg: e.message || "Caption failed.", type: "error" });
    }
    setCaptionIds(prev => { const n = { ...prev }; delete n[post.id]; return n; });
    return cost;
  };

  // Internal: caption a specific list (used by auto-caption after generate, and by the manual button)
  const generateAllCaptionsFor = async (list) => {
    if (bulkCaptioning) return;
    setBulkCaptioning(true);
    setBulkCapProgress({ done: 0, total: list.length });
    let totalCost = 0;
    for (const post of list) {
      totalCost += (await generateCaption(post)) || 0;
      setBulkCapProgress(p => ({ ...p, done: p.done + 1 }));
    }
    setBulkCaptioning(false);
    const costStr = totalCost > 0 ? ` · ~$${totalCost.toFixed(2)} used` : "";
    window.BoltKitToast?.({ msg: `${list.length} caption${list.length !== 1 ? "s" : ""} done.${costStr}`, type: "success" });
  };

  const generateAllCaptions = async () => {
    if (bulkCaptioning) return;
    const needCaption = posts.filter(p => (p.status === "ready" || p.isUploaded) && !p.caption);
    if (!needCaption.length) {
      window.BoltKitToast?.({ msg: "All posts already have captions.", type: "success" }); return;
    }
    // Pre-flight: show the estimated cost before spending anything.
    let estMsg = `Generating ${needCaption.length} captions…`;
    try {
      const er = await fetch("/api/generate-instagram-post", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          estimate: true,
          count: needCaption.length,
          withImage: needCaption.some(p => p.publicUrl || p.imageUrl),
        }),
      });
      const ed = await er.json();
      if (ed.ok && ed.estimate) estMsg = `Generating ${needCaption.length} captions… ~$${ed.estimate.total_cost_usd.toFixed(2)} est.`;
    } catch {}
    window.BoltKitToast?.({ msg: estMsg, type: "loading" });
    await generateAllCaptionsFor(needCaption);
  };

  const schedulePost = (post) => {
    try {
      if (platform === "facebook") {
        const existing = JSON.parse(localStorage.getItem("boltkit.fbPosts.v1") || "[]");
        localStorage.setItem("boltkit.fbPosts.v1", JSON.stringify([{ ...post, status: "Draft", date: "", time: "09:00" }, ...existing]));
      } else {
        const existing = JSON.parse(localStorage.getItem("boltkit.scheduledPosts.v1") || "[]");
        localStorage.setItem("boltkit.scheduledPosts.v1", JSON.stringify([{ ...post, status: "Draft", date: "", time: "09:00" }, ...existing]));
      }
      window.BoltKitToast?.({ msg: "Added to calendar.", type: "success" });
      window.BoltKitGo?.(calendarRoute);
    } catch {}
  };

  const copyCaption = (post) => {
    const text = [post.hook, post.caption, post.hashtags?.length ? post.hashtags.map(h => `#${h}`).join(" ") : ""].filter(Boolean).join("\n\n");
    navigator.clipboard?.writeText(text).catch(() => {});
    setCopied(post.id);
    setTimeout(() => setCopied(null), 2000);
  };

  const deletePost = (id) => savePosts(posts.filter(p => p.id !== id));

  const handleBulkUpload = async (e) => {
    const files = Array.from(e.target.files || []).filter(f => f.type.startsWith("image/"));
    if (!files.length) return;
    e.target.value = "";

    setBulkUploading(true);
    setUploadProgress({ done: 0, total: files.length });

    // Create placeholder posts immediately so the grid shows them at once
    const placeholders = files.map((file, i) => {
      const id = `upload-${Date.now()}-${i}-${Math.random().toString(36).slice(2)}`;
      const objectUrl = URL.createObjectURL(file);
      uploadedImageStore.current.set(id, objectUrl);
      return {
        id,
        status: "uploading",
        imageUrl: objectUrl,
        publicUrl: null,
        format: format.id, // use current selected format
        postType: postType.id,
        prompt: `Uploaded: ${file.name}`,
        caption: null,
        hashtags: [],
        isUploaded: true,
        fileName: file.name,
      };
    });

    // Prepend to grid (no localStorage yet — object URLs can't persist)
    setPosts(prev => [...placeholders, ...prev]);

    // Upload each to Supabase Storage to get a public URL Instagram can use
    // Guard: base64 ≈ 4/3× raw size; Vercel serverless body limit is 4.5 MB.
    // Reject files that would exceed ~3 MB raw to avoid silent 413 failures.
    const MAX_UPLOAD_BYTES = 3 * 1024 * 1024; // 3 MB
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      const postId = placeholders[i].id;
      try {
        if (file.size > MAX_UPLOAD_BYTES) {
          const mb = (file.size / 1024 / 1024).toFixed(1);
          window.BoltKitToast?.({ msg: `"${file.name}" is ${mb} MB — max upload is 3 MB. Compress the image before uploading.`, type: "error" });
          setPosts(prev => prev.map(p => p.id !== postId ? p : { ...p, status: "error", errorMsg: "File too large (max 3 MB)" }));
          continue;
        }
        const base64 = await new Promise((resolve, reject) => {
          const reader = new FileReader();
          reader.onload  = ev => resolve(ev.target.result);
          reader.onerror = reject;
          reader.readAsDataURL(file);
        });
        const resp = await fetch("/api/supabase-upload", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ base64, fileName: file.name, mimeType: file.type, folder: "instagram-posts" }),
        });
        const data = await resp.json();
        const publicUrl = data.ok && data.publicUrl ? data.publicUrl : null;

        setPosts(prev => {
          const updated = prev.map(p => p.id !== postId ? p : {
            ...p,
            status: "ready",
            imageUrl: publicUrl || p.imageUrl,
            publicUrl,
          });
          // Persist once we have a public URL (safe to save — no blob URLs)
          if (publicUrl) {
            try { localStorage.setItem(storageKey, JSON.stringify(updated.slice(0, 500))); } catch {}
          }
          return updated;
        });
      } catch {
        // Keep the object URL — can display but not publish to Instagram
        setPosts(prev => prev.map(p => p.id === postId ? { ...p, status: "ready" } : p));
      }
      setUploadProgress(p => ({ ...p, done: p.done + 1 }));
    }

    setBulkUploading(false);
    window.BoltKitToast?.({ msg: `${files.length} image${files.length !== 1 ? "s" : ""} added to grid.`, type: "success" });
  };

  const autoSchedulePosts = async () => {
    const readyPosts = posts.filter(p => p.status === "ready" || p.isUploaded);
    if (!readyPosts.length) { window.BoltKitToast?.({ msg: "No posts to schedule.", type: "error" }); return; }
    const start = new Date(schedStart + "T12:00:00");
    const times = schedTimes.slice(0, schedPerDay);
    const platformLabel = platform === "facebook" ? "Facebook" : "Instagram";
    const toSchedule = readyPosts.map((post, i) => {
      const d = new Date(start);
      d.setDate(d.getDate() + Math.floor(i / schedPerDay));
      return {
        ...post,
        date: d.toISOString().slice(0, 10),
        time: times[i % schedPerDay] || "09:00",
        status: "Scheduled",
        scheduleStarted: true, // marks as confirmed — no extra "push to server" step needed on calendar
        platforms: [platformLabel],
      };
    });

    // 1. Write to calendar queue in localStorage
    const calKey = platform === "facebook" ? "boltkit.fbPosts.v1" : "boltkit.scheduledPosts.v1";
    let merged = toSchedule;
    try {
      const existing = JSON.parse(localStorage.getItem(calKey) || "[]");
      const ids = new Set(toSchedule.map(p => p.id));
      merged = [...toSchedule, ...existing.filter(p => !ids.has(p.id))];
      localStorage.setItem(calKey, JSON.stringify(merged));
    } catch {}

    // 2. Mark source posts as scheduled so they disappear from the draft tray
    try {
      const srcKey = platform === "facebook" ? "boltkit.fbDraftPosts.v1" : "boltkit.igPosts.v2";
      const scheduledIds = new Set(toSchedule.map(p => p.id));
      const src = JSON.parse(localStorage.getItem(srcKey) || "[]");
      const updated = src.map(p => scheduledIds.has(p.id) ? { ...p, status: "Scheduled", scheduleStarted: true } : p);
      localStorage.setItem(srcKey, JSON.stringify(updated));
    } catch {}

    window.dispatchEvent(new Event("boltkit:saved"));

    const days = Math.ceil(readyPosts.length / schedPerDay);
    window.BoltKitToast?.({ msg: `${toSchedule.length} posts scheduled across ${days} days — saving to server…`, type: "loading" });

    // 3. Push to Supabase so Vercel cron runs posts without the browser open
    try {
      const proj = (() => { try { return JSON.parse(localStorage.getItem("boltkit.currentProject.v1") || "{}"); } catch { return {}; } })();
      const endpoint = platform === "facebook" ? "/api/supabase-facebook-posts" : "/api/supabase-scheduled-posts";
      const resp = await fetch(endpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "save", project: proj, posts: merged }),
      });
      const data = await resp.json();
      if (data.ok) {
        window.BoltKitToast?.({ msg: `${toSchedule.length} posts live — autopilot will post every 15 min ✓`, type: "success" });
      } else {
        throw new Error(data.error || "Server sync failed");
      }
    } catch (e) {
      console.error("[autoSchedule] server sync failed:", e.message);
      window.BoltKitToast?.({ msg: `Scheduled locally — server sync failed. Posts saved in browser; open the Calendar to retry.`, type: "error" });
    }

    window.BoltKitGo?.(calendarRoute);
  };

  const toggleOrderCard = (postId) => {
    setOrderQueue(prev =>
      prev.includes(postId) ? prev.filter(id => id !== postId) : [...prev, postId]
    );
  };

  const applyOrder = () => {
    if (!orderQueue.length) { setOrderMode(false); return; }
    // Ordered picks first, then remaining posts in original sequence
    const ordered = orderQueue.map(id => posts.find(p => p.id === id)).filter(Boolean);
    const rest    = posts.filter(p => !orderQueue.includes(p.id));
    savePosts([...ordered, ...rest]);
    setOrderMode(false);
    setOrderQueue([]);
    window.BoltKitToast?.({ msg: "Order applied.", type: "success" });
  };

  const tweakPost = async (post, tweakText) => {
    if (!tweakText.trim() || tweakingIds[post.id]) return;
    setTweakingIds(prev => ({ ...prev, [post.id]: true }));
    setPosts(prev => prev.map(p => p.id === post.id ? { ...p, status: "generating" } : p));
    try {
      const newPrompt = [post.prompt, `TWEAK: ${tweakText.trim()}`].filter(Boolean).join(". ");
      const brandAsset    = loadBrandAsset();
      const brandInfluence = loadBrandInfluence();
      const resp = await fetch("/api/generate-image", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          prompt: newPrompt,
          size: post.format || "square",
          styleHint: post.postType || postType.id,
          styleType: getStyleType(),
          referenceImageBase64: brandAsset?.dataUrl || null,
          brandInfluence,
        }),
      });
      const data = await resp.json();
      setPosts(prev => {
        const updated = prev.map(p => {
          if (p.id !== post.id) return p;
          return data.ok && data.imageUrl
            ? { ...p, status: "ready", imageUrl: data.imageUrl, prompt: newPrompt }
            : { ...p, status: "error", error: data.error || "Failed" };
        });
        try { localStorage.setItem(storageKey, JSON.stringify(updated.slice(0, 500))); } catch {}
        return updated;
      });
      if (data.ok) {
        setTweakTexts(prev => { const n = { ...prev }; delete n[post.id]; return n; });
        window.BoltKitToast?.({ msg: "Image updated.", type: "success" });
      } else {
        window.BoltKitToast?.({ msg: "Tweak failed — try again.", type: "error" });
      }
    } catch (e) {
      setPosts(prev => {
        const updated = prev.map(p => p.id === post.id ? { ...p, status: "error", error: e.message } : p);
        try { localStorage.setItem(storageKey, JSON.stringify(updated.slice(0, 500))); } catch {}
        return updated;
      });
      window.BoltKitToast?.({ msg: "Tweak failed.", type: "error" });
    }
    setTweakingIds(prev => { const n = { ...prev }; delete n[post.id]; return n; });
  };

  // ── Runway video generation ──────────────────────────────────────────────
  const hasRunway = () => Boolean(provider?.provider); // check via image-provider (Runway is separate)

  const makeReel = async (post) => {
    if (!post.imageUrl || post.imageUrl.startsWith("data:")) {
      window.BoltKitToast?.({ msg: "Image must finish generating before making a Reel.", type: "error" });
      return;
    }
    setVideoJobs(j => ({ ...j, [post.id]: { status: "submitting" } }));
    try {
      const bb = loadBrandBrain();
      const motionPrompt = [
        bb?.imageBrief ? "Cinematic camera move over a " + String(bb.imageBrief).slice(0, 80) : "Dynamic camera move",
        "High energy motorsport atmosphere. Subtle parallax depth. Professional motion graphics.",
      ].join(". ");

      const res = await fetch("/api/generate-video", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          imageUrl: post.imageUrl,
          prompt: motionPrompt,
          size: post.format || "story",
          duration: 5,
        }),
      });
      const data = await res.json();
      if (!data.ok) throw new Error(data.error || "Failed to submit");

      const taskId = data.taskId;
      setVideoJobs(j => ({ ...j, [post.id]: { taskId, status: "processing", progress: 0 } }));
      window.BoltKitToast?.({ msg: "Reel submitted to Runway — takes ~30–60s.", type: "success" });

      // Client-side polling
      const poll = async () => {
        try {
          const sr = await fetch(`/api/video-status?taskId=${taskId}`);
          const sd = await sr.json();
          if (sd.status === "SUCCEEDED" && sd.videoUrl) {
            setVideoJobs(j => ({ ...j, [post.id]: { taskId, status: "done", videoUrl: sd.videoUrl } }));
            savePosts(posts.map(p => p.id === post.id ? { ...p, videoUrl: sd.videoUrl } : p));
            window.BoltKitToast?.({ msg: "Reel ready!", type: "success" });
          } else if (sd.status === "FAILED") {
            setVideoJobs(j => ({ ...j, [post.id]: { taskId, status: "error", error: sd.error || "Runway failed" } }));
          } else {
            setVideoJobs(j => ({ ...j, [post.id]: { taskId, status: "processing", progress: sd.progress || 0 } }));
            setTimeout(poll, 6000);
          }
        } catch (e) {
          setTimeout(poll, 8000);
        }
      };
      setTimeout(poll, 8000);

    } catch (e) {
      setVideoJobs(j => ({ ...j, [post.id]: { status: "error", error: e.message } }));
      window.BoltKitToast?.({ msg: "Reel failed: " + e.message, type: "error" });
    }
  };

  const fmtLabel = (fmtId) => (FORMATS.find(f => f.id === fmtId) || FORMATS[0]);

  const readyPosts = posts.filter(p => p.status === "ready" || p.isUploaded);
  const readyCount = readyPosts.length;

  // ── Status chip helper ────────────────────────────────────────────────
  const StatusChip = ({ bg, dot, text }) => (
    <div style={{ display: "flex", alignItems: "center", gap: 5, background: bg, border: `1px solid ${dot}33`, borderRadius: 5, padding: "4px 9px" }}>
      <span style={{ width: 6, height: 6, borderRadius: "50%", background: dot, display: "inline-block", flexShrink: 0 }} />
      <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8.5, color: dot, letterSpacing: "0.1em", fontWeight: 700, whiteSpace: "nowrap" }}>{text}</span>
    </div>
  );

  return (
    <div style={{ height: "100%", display: "flex", background: "#1A1813" }}>
      <SidebarNav active={forcePlatform === "facebook" ? "fb-generate" : "ig-generate"} />
      <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
        <TopBar />
        <div style={{ flex: 1, overflowY: "auto" }}>

          {/* ═══════════════════════════════════════════════════════════════
              CONFIG PANEL — compact 3-row layout
              ═══════════════════════════════════════════════════════════════ */}
          <div style={{ padding: "18px 28px 16px", borderBottom: "1px solid #2C2A22" }}>

            {/* ── Row 1: header + platform + status ── */}
            <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 14 }}>
              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, letterSpacing: "0.2em", color: "#EFFF00", fontWeight: 800, textTransform: "uppercase" }}>
                {platform === "facebook" ? "FACEBOOK" : "INSTAGRAM"} · IMAGE GENERATOR
              </span>
              {/* Platform toggle — hidden when screen is force-locked to a platform */}
              {!forcePlatform && (
                <div style={{ display: "flex", gap: 2, background: "#141210", border: "1px solid #2C2A22", borderRadius: 5, padding: 2 }}>
                  {[["instagram","IG"],["facebook","FB"]].map(([p, lbl]) => (
                    <button key={p} data-bk-bound="true" onClick={() => switchPlatform(p)} style={{
                      padding: "3px 9px", borderRadius: 3, fontSize: 9, fontWeight: 800,
                      fontFamily: "'JetBrains Mono', monospace", letterSpacing: "0.1em",
                      cursor: "pointer", border: "none",
                      background: platform === p ? "#EFFF00" : "transparent",
                      color: platform === p ? "#1A1813" : "#5C5C5C",
                    }}>{lbl}</button>
                  ))}
                </div>
              )}
              <div style={{ marginLeft: "auto", fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#5C5C5C", letterSpacing: "0.08em" }}>
                {generating
                  ? <span style={{ color: "#EFFF00", fontWeight: 700 }}>⚡ {genProgress.done} / {genProgress.total} generating…</span>
                  : posts.length ? `${posts.length} post${posts.length !== 1 ? "s" : ""} in grid` : "no posts yet"}
              </div>
            </div>

            {/* ── Row 2: post type pills ── */}
            <div style={{ display: "flex", gap: 5, flexWrap: "wrap", marginBottom: 12 }}>
              {POST_TYPES.map(pt => (
                <button key={pt.id} data-bk-bound="true" onClick={() => setPostType(pt)} style={{
                  padding: "6px 14px", borderRadius: 20, fontSize: 11.5, fontWeight: 700, cursor: "pointer",
                  background: postType.id === pt.id ? "#EFFF00" : "#26241E",
                  color: postType.id === pt.id ? "#1A1813" : "#A8A89E",
                  border: `1px solid ${postType.id === pt.id ? "#EFFF00" : "#3A372F"}`,
                  transition: "all 0.12s",
                }}>{pt.label}</button>
              ))}
            </div>

            {/* ── Row 3: format / count / brief ── */}
            <div style={{ display: "grid", gridTemplateColumns: "auto auto 1fr", gap: 14, alignItems: "flex-end", marginBottom: 14 }}>
              {/* Format */}
              <div>
                <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8, letterSpacing: "0.14em", color: "#5C5C5C", fontWeight: 700, marginBottom: 6 }}>FORMAT</div>
                <div style={{ display: "flex", gap: 4 }}>
                  {FORMATS.map(f => (
                    <button key={f.id} data-bk-bound="true" onClick={() => setFormat(f)} style={{
                      padding: "5px 11px", minHeight: 44, borderRadius: 4, fontSize: 10.5, fontWeight: 800, cursor: "pointer", textAlign: "center",
                      background: format.id === f.id ? "#EFFF00" : "#26241E",
                      color: format.id === f.id ? "#1A1813" : "#A8A89E",
                      border: `1px solid ${format.id === f.id ? "#EFFF00" : "#3A372F"}`,
                    }}>
                      <div>{f.label}</div>
                      <div style={{ fontSize: 8, fontFamily: "'JetBrains Mono', monospace", opacity: 0.65 }}>{f.ratio}</div>
                    </button>
                  ))}
                </div>
              </div>
              {/* Count */}
              <div>
                <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8, letterSpacing: "0.14em", color: "#5C5C5C", fontWeight: 700, marginBottom: 6 }}>COUNT</div>
                <div style={{ display: "flex", gap: 3 }}>
                  {GEN_QUANTITIES.map(q => (
                    <button key={q} data-bk-bound="true" onClick={() => setQuantity(q)} style={{
                      width: 44, height: 44, borderRadius: 4, fontSize: 13, fontWeight: 800, cursor: "pointer",
                      background: quantity === q ? "#EFFF00" : "#26241E",
                      color: quantity === q ? "#1A1813" : "#A8A89E",
                      border: `1px solid ${quantity === q ? "#EFFF00" : "#3A372F"}`,
                    }}>{q}</button>
                  ))}
                </div>
              </div>
              {/* Brief */}
              <div>
                <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8, letterSpacing: "0.14em", color: "#5C5C5C", fontWeight: 700, marginBottom: 6 }}>BRIEF (optional)</div>
                <input value={brief} onChange={e => setBrief(e.target.value)}
                  placeholder="Focus on blue colourway · include athlete · dark moody…"
                  style={{ width: "100%", boxSizing: "border-box", background: "#201E18", border: "1px solid #3A372F", color: "#F4F4F0", padding: "8px 11px", fontSize: 12, borderRadius: 4, outline: "none" }}
                  onFocus={e => e.target.style.borderColor = "#EFFF00"}
                  onBlur={e => e.target.style.borderColor = "#3A372F"} />
              </div>
            </div>

            {/* ── Row 4: settings strip ── */}
            <div style={{ display: "flex", gap: 18, alignItems: "center", flexWrap: "wrap", padding: "9px 12px", background: "#141210", borderRadius: 6, marginBottom: 14 }}>
              <Toggle label="Logo overlay" value={showLogoOverlay} onChange={setShowLogoOverlay} />
              <Toggle label="Auto-caption" value={autoCaptionAfterGen} onChange={setAutoCaptionAfterGen} />
              <SegCtrl label="Style" value={styleMode} onChange={setStyleMode}
                options={[["auto","Auto"],["graphic","Graphic"],["photo","Photo"]]} />
              <SegCtrl label="Prompt" value={promptMode} onChange={setPromptMode}
                options={[["simple","Short"],["full","Full"]]} />
            </div>

            {/* ── Row 5: generate button + upload + status chips ── */}
            <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
              <button
                className={"btn btn-primary" + (generating ? " btn-analysing" : "")}
                data-bk-bound="true"
                onClick={generateImages}
                disabled={generating}
                style={{ fontSize: 13, padding: "10px 26px", minWidth: 190 }}
              >
                <span className={generating ? "bolt-thinking" : ""}><BoltMini size={14} color={generating ? "#EFFF00" : "#1A1813"} /></span>
                {generating
                  ? `${genProgress.done} / ${genProgress.total} generating…`
                  : `Generate ${quantity} ${format.label}${quantity !== 1 ? "s" : ""}`}
              </button>

              {/* Upload */}
              <label
                data-bk-bound="true"
                style={{ cursor: "pointer", display: "flex", alignItems: "center", gap: 7, padding: "9px 14px", background: "#201E18", border: "1px dashed #3A372F", borderRadius: 5, transition: "border-color 0.15s" }}
                onMouseEnter={e => e.currentTarget.style.borderColor = "#EFFF00"}
                onMouseLeave={e => e.currentTarget.style.borderColor = "#3A372F"}
              >
                <input type="file" accept="image/png,image/jpeg,image/webp" multiple onChange={handleBulkUpload} disabled={bulkUploading} style={{ display: "none" }} data-bk-bound="true" />
                {bulkUploading
                  ? <><span className="bolt-thinking" style={{ display: "inline-block", lineHeight: 0 }}><BoltMini size={11} color="#EFFF00" /></span>
                    <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#EFFF00", fontWeight: 800, letterSpacing: "0.1em" }}>{uploadProgress.done}/{uploadProgress.total} uploading…</span></>
                  : <><Icon name="upload" size={13} stroke={1.8} color="#5C5C5C" />
                    <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#5C5C5C", fontWeight: 700, letterSpacing: "0.08em" }}>Upload images</span></>}
              </label>

              {/* Status chips */}
              <div style={{ display: "flex", gap: 6, alignItems: "center", flexWrap: "wrap" }}>
                {provider === null
                  ? <StatusChip bg="#1A1813" dot="#5C5C5C" text="CHECKING…" />
                  : provider.provider === "ideogram"
                  ? <StatusChip bg="#0D1F0D" dot="#4ADE80" text={`IDEOGRAM ${provider.model || "V3"}`} />
                  : provider.provider === "openai"
                  ? <StatusChip bg="#1A1A0D" dot="#EFFF00" text={`OPENAI ${provider.model || ""}`} />
                  : <StatusChip bg="#1F0D0D" dot="#FF4D5E" text="NO IMAGE API — ADD KEY IN VERCEL" />}

                {runwayConnected === true && <StatusChip bg="#1A0D1F" dot="#a259ff" text="RUNWAY · REELS ON" />}
                {runwayConnected === false && <StatusChip bg="#1A1813" dot="#5C5C5C" text="RUNWAY · ADD KEY FOR REELS" />}

                {(() => {
                  const assets = (() => { try { return JSON.parse(localStorage.getItem("boltkit.brandAssets.v1") || "[]"); } catch { return []; } })();
                  const shots  = (() => { try { return JSON.parse(localStorage.getItem("boltkit.appScreenshots.v1") || "[]"); } catch { return []; } })();
                  const total  = assets.length + shots.length;
                  if (total > 0) return <StatusChip bg="#0D1F0D" dot="#4ADE80" text={`REMIX · ${total} REF${total !== 1 ? "S" : ""} · STRONG`} />;
                  const bb = loadBrandBrain();
                  if (bb?.imageBrief) return <StatusChip bg="#1A1813" dot="#4ADE80" text="BRAND BRIEF ACTIVE" />;
                  return null;
                })()}

                {!hasProject && (
                  <button data-bk-bound="true" onClick={() => window.BoltKitGo?.("project-about")}
                    style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#FF4D5E", background: "none", border: "1px solid rgba(255,77,94,0.3)", borderRadius: 4, padding: "4px 9px", cursor: "pointer", letterSpacing: "0.08em" }}>
                    SET UP PROJECT FIRST →
                  </button>
                )}
              </div>
            </div>
          </div>

          {/* ═══════════════════════════════════════════════════════════════
              PIPELINE BAR — appears when ready posts exist
              ═══════════════════════════════════════════════════════════════ */}
          {readyCount > 0 && !generating && (
            <div style={{ padding: "10px 28px", background: "#141210", borderBottom: "1px solid #2C2A22", display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <span style={{ width: 7, height: 7, borderRadius: "50%", background: "#4ADE80", display: "inline-block" }} />
                <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, color: "#4ADE80", fontWeight: 800, letterSpacing: "0.1em" }}>
                  {readyCount} READY
                </span>
              </div>
              <span style={{ color: "#3A372F", fontSize: 14, fontWeight: 300 }}>→</span>
              <button
                className={"btn btn-primary btn-sm" + (bulkCaptioning ? " btn-analysing" : "")}
                data-bk-bound="true"
                onClick={generateAllCaptions}
                disabled={bulkCaptioning}
              >
                {bulkCaptioning
                  ? <><span className="bolt-thinking" style={{ display: "inline-block", lineHeight: 0 }}><BoltMini size={11} color="#EFFF00" /></span> {bulkCapProgress.done}/{bulkCapProgress.total} captions…</>
                  : <><BoltMini size={11} color="#1A1813" /> Caption all</>}
              </button>
              <span style={{ color: "#3A372F", fontSize: 14, fontWeight: 300 }}>→</span>
              <button className="btn btn-primary btn-sm" data-bk-bound="true" onClick={autoSchedulePosts}>
                <Icon name="calendar" size={11} stroke={2} color="#1A1813" /> Schedule all →
              </button>

              <div style={{ marginLeft: "auto", display: "flex", gap: 6 }}>
                {!orderMode ? (
                  <>
                    <button className="btn btn-secondary btn-sm" data-bk-bound="true" onClick={() => { setOrderMode(true); setOrderQueue([]); }}>
                      <Icon name="list" size={11} stroke={2} /> Reorder
                    </button>
                    <button className="btn btn-secondary btn-sm" data-bk-bound="true" onClick={() => {
                      const shuffled = [...posts];
                      for (let i = shuffled.length - 1; i > 0; i--) {
                        const j = Math.floor(Math.random() * (i + 1));
                        [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
                      }
                      savePosts(shuffled);
                      window.BoltKitToast?.({ msg: "Posts shuffled into random order.", type: "success" });
                    }}>
                      <Icon name="refresh" size={11} stroke={2} /> Mix up
                    </button>
                  </>
                ) : (
                  <>
                    <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#EFFF00", letterSpacing: "0.08em", alignSelf: "center" }}>
                      {orderQueue.length} selected
                    </span>
                    <button className="btn btn-primary btn-sm" data-bk-bound="true" onClick={applyOrder}>
                      <Icon name="check" size={11} stroke={2.5} color="#1A1813" /> Apply
                    </button>
                    <button className="btn btn-secondary btn-sm" data-bk-bound="true" onClick={() => { setOrderMode(false); setOrderQueue([]); }}>Cancel</button>
                  </>
                )}
                <button className="btn btn-secondary btn-sm" data-bk-bound="true" onClick={() => { if (window.confirm("Clear all posts from grid?")) savePosts([]); }}>
                  <Icon name="trash" size={11} stroke={2} /> Clear
                </button>
              </div>
            </div>
          )}

          {/* ═══════════════════════════════════════════════════════════════
              IMAGE GRID
              ═══════════════════════════════════════════════════════════════ */}
          <div style={{ padding: "20px 28px 60px" }}>

            {/* Empty state */}
            {posts.length === 0 && !generating && (
              <div style={{ textAlign: "center", padding: "64px 0", color: "#5C5C5C" }}>
                <BoltMini size={32} color="#2C2A22" />
                <div style={{ marginTop: 14, fontSize: 13, lineHeight: 1.6 }}>
                  Choose a post type and format above, then hit Generate.<br />
                  <span style={{ fontSize: 11, color: "#3A372F" }}>Images appear here as they finish — caption and schedule without leaving this page.</span>
                </div>
              </div>
            )}

            {posts.length > 0 && (
              <div>
                {/* ── Auto-schedule panel ── */}
                {readyCount > 0 && (() => {
                  const days = Math.ceil(readyCount / schedPerDay);
                  const endDate = new Date(schedStart + "T12:00:00");
                  endDate.setDate(endDate.getDate() + days - 1);
                  const endStr = endDate.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
                  return (
                    <div style={{ background: "#EFFF00", borderRadius: 8, padding: "16px 20px", marginBottom: 16 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 12 }}>
                        <BoltMini size={13} color="#1A1813" />
                        <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, letterSpacing: "0.18em", color: "#1A1813", fontWeight: 900, textTransform: "uppercase" }}>Step 3 — Schedule &amp; activate autopilot</span>
                      </div>
                      <div style={{ display: "flex", gap: 12, alignItems: "center", flexWrap: "wrap" }}>
                        <div style={{ display: "flex", alignItems: "center", gap: 5 }}>
                          <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8, color: "#5C5A20", letterSpacing: "0.1em", fontWeight: 700 }}>START DATE</span>
                          <input type="date" value={schedStart} onChange={e => setSchedStart(e.target.value)}
                            style={{ background: "#D4E600", border: "1px solid #ADC700", color: "#1A1813", padding: "5px 8px", fontSize: 11, borderRadius: 4, outline: "none", fontWeight: 600 }} />
                        </div>

                        <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                          <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8, color: "#5C5A20", letterSpacing: "0.1em", fontWeight: 700 }}>POSTS/DAY</span>
                          <button data-bk-bound="true"
                            onClick={() => { const n = Math.max(1, schedPerDay - 1); setSchedPerDay(n); setSchedTimes(genTimesForCount(n)); }}
                            style={{ width: 32, height: 32, borderRadius: 4, fontSize: 18, fontWeight: 700, cursor: "pointer", background: "#D4E600", color: "#1A1813", border: "1px solid #ADC700", lineHeight: 1 }}>−</button>
                          <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 20, fontWeight: 900, color: "#1A1813", minWidth: 28, textAlign: "center" }}>{schedPerDay}</span>
                          <button data-bk-bound="true"
                            onClick={() => { const n = Math.min(12, schedPerDay + 1); setSchedPerDay(n); setSchedTimes(genTimesForCount(n)); }}
                            style={{ width: 32, height: 32, borderRadius: 4, fontSize: 18, fontWeight: 700, cursor: "pointer", background: "#D4E600", color: "#1A1813", border: "1px solid #ADC700", lineHeight: 1 }}>+</button>
                        </div>

                        <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
                          {schedTimes.map((t, i) => (
                            <input key={i} type="time" value={t}
                              onChange={e => setSchedTimes(prev => prev.map((v, j) => j === i ? e.target.value : v))}
                              style={{ background: "#D4E600", border: "1px solid #ADC700", color: "#1A1813", padding: "4px 6px", fontSize: 10.5, borderRadius: 4, width: 82, fontFamily: "'JetBrains Mono', monospace", outline: "none", fontWeight: 700 }} />
                          ))}
                        </div>

                        <div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 10 }}>
                          <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: "#5C5A20", letterSpacing: "0.06em", fontWeight: 700 }}>
                            {readyCount} posts · {days} day{days !== 1 ? "s" : ""} · ends {endStr}
                          </span>
                          <button className="btn" data-bk-bound="true" onClick={autoSchedulePosts}
                            style={{ background: "#1A1813", color: "#EFFF00", border: "none", fontWeight: 800, fontSize: 13, padding: "10px 20px", whiteSpace: "nowrap", borderRadius: 6 }}>
                            ▶ Schedule &amp; start autopilot
                          </button>
                        </div>
                      </div>
                    </div>
                  );
                })()}

                {/* ── Grid header ── */}
                <div style={{ display: "flex", alignItems: "center", marginBottom: 14 }}>
                  <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, letterSpacing: "0.16em", color: "#5C5C5C", fontWeight: 800 }}>
                    {posts.length} POST{posts.length !== 1 ? "S" : ""}
                    {readyCount < posts.length ? ` · ${posts.length - readyCount} generating` : ""}
                  </span>
                </div>

                {/* ── Post cards grid ── */}
                <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(264px, 1fr))", gap: 14 }}>
                  {posts.map(post => {
                    const fmt = fmtLabel(post.format);
                    const vj  = videoJobs[post.id];
                    const isOrdering = orderMode;
                    const isInOrder  = orderQueue.includes(post.id);

                    return (
                      <div key={post.id} style={{
                        background: "#201E18",
                        border: `1px solid ${isOrdering && isInOrder ? "#EFFF00" : "#2C2A22"}`,
                        borderRadius: 8, overflow: "hidden", position: "relative",
                        transition: "border-color 0.15s",
                      }}>

                        {/* Order mode overlay */}
                        {isOrdering && (
                          <button data-bk-bound="true" onClick={() => toggleOrderCard(post.id)} style={{
                            position: "absolute", inset: 0, zIndex: 10,
                            background: isInOrder ? "rgba(239,255,0,0.06)" : "rgba(0,0,0,0.5)",
                            border: "none", cursor: "pointer",
                            display: "flex", alignItems: "center", justifyContent: "center",
                          }}>
                            {isInOrder
                              ? <div style={{ width: 40, height: 40, borderRadius: "50%", background: "#EFFF00", display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "'Anton', Impact, sans-serif", fontSize: 20, color: "#1A1813", boxShadow: "0 2px 12px rgba(0,0,0,0.5)" }}>{orderQueue.indexOf(post.id) + 1}</div>
                              : <div style={{ width: 36, height: 36, borderRadius: "50%", background: "rgba(255,255,255,0.1)", border: "2px dashed rgba(255,255,255,0.25)", display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.5)", fontSize: 20 }}>+</div>}
                          </button>
                        )}

                        {/* ── Image area ── */}
                        <div style={{ aspectRatio: fmt.aspect, background: "#1A1813", position: "relative", display: "flex", alignItems: "center", justifyContent: "center", minHeight: 80, overflow: "hidden" }}>
                          {(post.status === "generating" || post.status === "uploading") && !post.imageUrl && (
                            <span className="bolt-thinking" style={{ display: "inline-block" }}><BoltMini size={26} color="#EFFF00" /></span>
                          )}
                          {post.status === "uploading" && post.imageUrl && (
                            <div style={{ position: "absolute", top: 8, left: 8, display: "flex", alignItems: "center", gap: 5, background: "rgba(0,0,0,0.75)", borderRadius: 4, padding: "3px 8px", zIndex: 2 }}>
                              <span className="bolt-thinking" style={{ display: "inline-block", lineHeight: 0 }}><BoltMini size={9} color="#EFFF00" /></span>
                              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8, color: "#EFFF00", letterSpacing: "0.08em" }}>SAVING…</span>
                            </div>
                          )}
                          {post.status === "error" && (
                            <div style={{ textAlign: "center", padding: 16 }}>
                              <Icon name="alert" size={18} color="#FF4D5E" />
                              <div style={{ fontSize: 10, color: "#FF4D5E", marginTop: 5 }}>Generation failed</div>
                              {post.error && <div style={{ fontSize: 8.5, color: "#FF4D5E", marginTop: 4, opacity: 0.7, fontFamily: "'JetBrains Mono', monospace", wordBreak: "break-word", padding: "0 8px" }}>{String(post.error).slice(0, 100)}</div>}
                            </div>
                          )}
                          {post.imageUrl && (
                            <img src={post.imageUrl} alt={post.alt_text || "Generated"} style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", position: "absolute", inset: 0 }} />
                          )}

                          {/* Brand logo overlay */}
                          {post.imageUrl && showLogoOverlay && (
                            <div style={{ position: "absolute", inset: 0, pointerEvents: "none" }}>
                              {/* S badge */}
                              <div style={{ position: "absolute", top: 24, left: 9, width: 32, height: 32, background: "#B8FF1A", borderRadius: 5, display: "flex", flexDirection: "column", justifyContent: "center", gap: 2.5, padding: "5px 4px", boxShadow: "0 2px 8px rgba(0,0,0,0.7)" }}>
                                {[76,60,44,26].map((w, i) => (
                                  <div key={i} style={{ height: 2.5, width: `${w}%`, background: "#07080A", borderRadius: 1 }} />
                                ))}
                              </div>
                              {/* Bottom gradient + wordmark */}
                              <div style={{ position: "absolute", bottom: 0, left: 0, right: 0, padding: "36px 11px 10px", background: "linear-gradient(to top, rgba(7,8,10,0.93) 0%, rgba(7,8,10,0.38) 60%, transparent 100%)", display: "flex", alignItems: "flex-end" }}>
                                <img src="/boltkit-design/shift-wordmark.svg" alt="SHIFT" style={{ height: 34, width: "auto", display: "block" }} />
                              </div>
                            </div>
                          )}

                          {/* Corner badges */}
                          <div style={{ position: "absolute", top: 7, left: 7, background: "rgba(0,0,0,0.7)", color: "#EFFF00", fontFamily: "'JetBrains Mono', monospace", fontSize: 8.5, fontWeight: 800, padding: "2px 6px", borderRadius: 3 }}>{fmt.ratio}</div>
                          <button data-bk-bound="true" onClick={() => deletePost(post.id)} style={{ position: "absolute", top: 7, right: 7, width: 24, height: 24, borderRadius: 4, background: "rgba(0,0,0,0.7)", color: "#FF4D5E", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", border: "1px solid rgba(255,77,94,0.25)" }}>
                            <Icon name="trash" size={10} stroke={2} />
                          </button>
                        </div>

                        {/* ── Tweak bar ── */}
                        {(post.status === "ready" || post.status === "error") && (
                          <div style={{ padding: "7px 9px", borderTop: "1px solid #252320", display: "flex", gap: 5, alignItems: "center" }}>
                            <input
                              type="text"
                              value={tweakTexts[post.id] || ""}
                              onChange={e => setTweakTexts(prev => ({ ...prev, [post.id]: e.target.value }))}
                              onKeyDown={e => { if (e.key === "Enter") tweakPost(post, tweakTexts[post.id] || ""); }}
                              placeholder="Tweak: darker, more lime, different pose…"
                              style={{ flex: 1, background: "#1A1813", border: "1px solid #3A372F", color: "#F4F4F0", padding: "5px 8px", fontSize: 10.5, borderRadius: 4, outline: "none" }}
                              onFocus={e => e.target.style.borderColor = "#EFFF00"}
                              onBlur={e => e.target.style.borderColor = "#3A372F"}
                            />
                            <button
                              data-bk-bound="true"
                              onClick={() => tweakPost(post, tweakTexts[post.id] || "")}
                              disabled={!tweakTexts[post.id]?.trim() || tweakingIds[post.id]}
                              style={{
                                flexShrink: 0, padding: "5px 9px", borderRadius: 4, cursor: tweakTexts[post.id]?.trim() ? "pointer" : "default",
                                background: tweakTexts[post.id]?.trim() ? "#EFFF00" : "#26241E",
                                color: tweakTexts[post.id]?.trim() ? "#1A1813" : "#5C5C5C",
                                border: `1px solid ${tweakTexts[post.id]?.trim() ? "#EFFF00" : "#3A372F"}`,
                                fontFamily: "'JetBrains Mono', monospace", fontSize: 8.5, fontWeight: 800,
                                letterSpacing: "0.08em", display: "flex", alignItems: "center", gap: 4,
                              }}
                            >
                              {tweakingIds[post.id]
                                ? <span className="bolt-thinking" style={{ display: "inline-block", lineHeight: 0 }}><BoltMini size={9} color="#EFFF00" /></span>
                                : <Icon name="refresh" size={10} stroke={2.5} />}
                              {tweakingIds[post.id] ? "GOING…" : "REDO"}
                            </button>
                          </div>
                        )}

                        {/* ── Video / Reel ── */}
                        {(() => {
                          if (vj?.status === "done" || post.videoUrl) {
                            const url = vj?.videoUrl || post.videoUrl;
                            return (
                              <div style={{ padding: "0 9px 8px" }}>
                                <video src={url} controls loop muted playsInline style={{ width: "100%", borderRadius: 5, display: "block", background: "#000" }} />
                                <a href={url} download="reel.mp4" data-bk-bound="true" style={{ display: "block", textAlign: "center", marginTop: 4, fontFamily: "'JetBrains Mono', monospace", fontSize: 8.5, color: "#4ADE80", letterSpacing: "0.08em" }}>↓ DOWNLOAD REEL</a>
                              </div>
                            );
                          }
                          if (vj?.status === "processing" || vj?.status === "submitting") {
                            return (
                              <div style={{ padding: "5px 12px 4px", display: "flex", alignItems: "center", gap: 5 }}>
                                <span className="bolt-thinking" style={{ display: "inline-block" }}><BoltMini size={9} color="#EFFF00" /></span>
                                <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 8.5, color: "#EFFF00", letterSpacing: "0.08em" }}>
                                  {vj.status === "submitting" ? "SUBMITTING TO RUNWAY…" : `RUNWAY${vj.progress ? ` ${Math.round(vj.progress * 100)}%` : "…"}`}
                                </span>
                              </div>
                            );
                          }
                          if (vj?.status === "error") {
                            return <div style={{ padding: "4px 12px", fontFamily: "'JetBrains Mono', monospace", fontSize: 8.5, color: "#FF4D5E", letterSpacing: "0.06em" }}>REEL FAILED: {String(vj.error || "").slice(0, 60)}</div>;
                          }
                          return null;
                        })()}

                        {/* ── Caption area ── */}
                        <div style={{ padding: "10px 12px 12px" }}>
                          {post.caption ? (
                            <div style={{ marginBottom: 9 }}>
                              {post.hook && <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, fontWeight: 800, color: "#EFFF00", marginBottom: 4, lineHeight: 1.4 }}>{post.hook}</div>}
                              <div style={{ fontSize: 11.5, color: "#C8C8C5", lineHeight: 1.55, marginBottom: 5, display: "-webkit-box", WebkitLineClamp: 3, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{post.caption}</div>
                              {post.hashtags?.length > 0 && (
                                <div style={{ fontSize: 9, color: "#4DA8FF", fontFamily: "'JetBrains Mono', monospace", lineHeight: 1.7, wordBreak: "break-word" }}>
                                  {post.hashtags.slice(0, 8).map(h => `#${h}`).join(" ")}{post.hashtags.length > 8 ? ` +${post.hashtags.length - 8}` : ""}
                                </div>
                              )}
                            </div>
                          ) : (
                            <div style={{ marginBottom: 9, fontSize: 11, color: post.status === "generating" ? "#EFFF00" : "#5C5C5C", fontStyle: post.status === "generating" ? "normal" : "italic" }}>
                              {post.status === "ready" || post.isUploaded ? "Ready — add a caption" : post.status === "generating" ? "Generating image…" : "Generation failed"}
                            </div>
                          )}

                          {/* Action buttons */}
                          <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
                            {(post.status === "ready" || post.isUploaded) && !post.caption && (
                              <button data-bk-bound="true" className="btn btn-primary btn-sm" onClick={() => generateCaption(post)} disabled={captionIds[post.id]} style={{ flex: 1 }}>
                                {captionIds[post.id]
                                  ? <><span className="bolt-thinking" style={{ display: "inline-block", lineHeight: 0 }}><BoltMini size={10} color="#EFFF00" /></span> Writing…</>
                                  : <><BoltMini size={10} color="#1A1813" /> Caption</>}
                              </button>
                            )}
                            {(post.status === "ready" || post.isUploaded) && !vj?.videoUrl && !post.videoUrl && (
                              <button data-bk-bound="true" className="btn btn-secondary btn-sm" onClick={() => makeReel(post)} disabled={!!vj} style={{ borderColor: "#a259ff", color: "#a259ff" }}>
                                <Icon name="play" size={10} stroke={2} /> Reel
                              </button>
                            )}
                            {(vj?.videoUrl || post.videoUrl) && (
                              <button data-bk-bound="true" className="btn btn-secondary btn-sm" onClick={() => makeReel(post)} style={{ borderColor: "#a259ff", color: "#a259ff" }}>
                                <Icon name="refresh" size={10} stroke={2} /> Reel
                              </button>
                            )}
                            {post.caption && (
                              <>
                                <button data-bk-bound="true" className="btn btn-secondary btn-sm" onClick={() => copyCaption(post)}>
                                  <Icon name={copied === post.id ? "check" : "copy"} size={10} stroke={2} /> {copied === post.id ? "✓" : "Copy"}
                                </button>
                                <button data-bk-bound="true" className="btn btn-secondary btn-sm" onClick={() => generateCaption(post)} disabled={captionIds[post.id]} title="Rewrite caption">
                                  {captionIds[post.id] ? <span className="bolt-thinking" style={{ display: "inline-block", lineHeight: 0 }}><BoltMini size={10} color="#EFFF00" /></span> : <Icon name="refresh" size={10} stroke={2} />}
                                </button>
                                <button data-bk-bound="true" className="btn btn-secondary btn-sm" onClick={() => schedulePost(post)}>
                                  <Icon name="calendar" size={10} stroke={2} /> +Cal
                                </button>
                              </>
                            )}
                          </div>
                        </div>

                      </div>
                    );
                  })}
                </div>
              </div>
            )}
          </div>

        </div>
      </div>
    </div>
  );
};

const TONES = ["Bold & punchy", "Educational", "Professional", "Funny & relatable", "Inspiring", "Conversational"];
const QUANTITIES = [3, 5, 10, 20, 30];
const SIZE_OPTIONS = [
  { id: "square",   label: "Square",   sub: "1:1"  },
  { id: "portrait", label: "Portrait", sub: "4:5"  },
  { id: "story",    label: "Story",    sub: "9:16" },
];

const GenerateHubScreen = () => {
  const project = (() => { try { return JSON.parse(localStorage.getItem("boltkit.currentProject.v1") || "{}"); } catch { return {}; } })();
  const hasProject = Boolean(project.name || project.url);

  const [tone,      setTone]      = React.useState(project.tone_of_voice || "Bold & punchy");
  const [theme,     setTheme]     = React.useState("");
  const [quantity,  setQuantity]  = React.useState(5);
  const [sizes,     setSizes]     = React.useState(["square", "portrait"]);
  const [deepScan,  setDeepScan]  = React.useState(false);
  const [generating, setGenerating] = React.useState(false);
  const [progress,  setProgress]  = React.useState({ done: 0, total: 0 });
  const [results,   setResults]   = React.useState(() => {
    try { return JSON.parse(localStorage.getItem("boltkit.generated.v1") || "[]"); } catch { return []; }
  });
  const [status,    setStatus]    = React.useState("");
  const [copied,    setCopied]    = React.useState(null);
  const [editId,    setEditId]    = React.useState(null);
  const [editField, setEditField] = React.useState({});
  const [imgGenId,  setImgGenId]  = React.useState(null);

  const toggleSize = (id) => setSizes(prev => prev.includes(id) ? prev.filter(s => s !== id) : [...prev, id]);

  const sizeColour = { square: "#4DA8FF", portrait: "#EFFF00", story: "#FF4D5E" };

  const saveResults = (list) => {
    setResults(list);
    try { localStorage.setItem("boltkit.generated.v1", JSON.stringify(list.slice(0, 300))); } catch {}
  };

  const generate = async () => {
    if (!hasProject) { setStatus("Set up your workspace in Setup first."); return; }
    if (!sizes.length) { setStatus("Select at least one post size."); return; }

    setGenerating(true);
    setStatus("");
    const sizesToGen = sizes;
    const posts = [];
    for (let i = 0; i < quantity; i++) for (const size of sizesToGen) posts.push({ index: i + 1, size });
    setProgress({ done: 0, total: posts.length });

    const fresh = [];
    for (const { index, size } of posts) {
      try {
        const resp = await fetch("/api/generate-instagram-post", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ project: { ...project, deepScan }, post: { tone, size, theme: theme || `${project.name || "brand"} content`, index } }),
        });
        const data = await resp.json();
        if (data.ok && data.post) fresh.push({ id: `gen-${Date.now()}-${Math.random().toString(36).slice(2)}`, size, index, status: "Draft", ...data.post });
      } catch {}
      setProgress(p => ({ ...p, done: p.done + 1 }));
    }

    setGenerating(false);
    setStatus(`Generated ${fresh.length} post${fresh.length !== 1 ? "s" : ""}.`);
    saveResults([...fresh, ...results].slice(0, 300));
  };

  const copyPost = (post) => {
    const text = `${post.hook ? post.hook + "\n\n" : ""}${post.caption || ""}${post.hashtags?.length ? "\n\n" + post.hashtags.map(h => `#${h}`).join(" ") : ""}`;
    navigator.clipboard?.writeText(text).catch(() => {});
    setCopied(post.id);
    setTimeout(() => setCopied(null), 2000);
  };

  const schedulePost = (post) => {
    try {
      const existing = JSON.parse(localStorage.getItem("boltkit.scheduledPosts.v1") || "[]");
      localStorage.setItem("boltkit.scheduledPosts.v1", JSON.stringify([{ ...post, status: "Draft", date: "", time: "09:00" }, ...existing]));
      window.BoltKitToast?.("Added to scheduler.");
      window.BoltKitGo?.("instagram");
    } catch {}
  };

  const scheduleAll = () => {
    try {
      const existing = JSON.parse(localStorage.getItem("boltkit.scheduledPosts.v1") || "[]");
      const toAdd = results.map(p => ({ ...p, status: "Draft", date: "", time: "09:00" }));
      localStorage.setItem("boltkit.scheduledPosts.v1", JSON.stringify([...toAdd, ...existing]));
      window.BoltKitGo?.("instagram");
    } catch {}
  };

  const deletePost = (id) => saveResults(results.filter(p => p.id !== id));

  const generateImage = async (post) => {
    if (imgGenId) return;
    setImgGenId(post.id);
    try {
      const prompt = post.alt_text || `${post.hook ? post.hook + ". " : ""}${post.caption?.slice(0, 300) || ""}`.trim() || `Instagram post for ${project.name || "brand"}`;
      const resp = await fetch("/api/generate-image", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ prompt, size: post.size || "square" })
      });
      const data = await resp.json();
      if (data.ok && data.imageUrl) {
        saveResults(results.map(p => p.id === post.id ? { ...p, imageUrl: data.imageUrl } : p));
        window.BoltKitToast?.("Image generated.");
      } else {
        window.BoltKitToast?.(data.error || "Image generation failed.");
      }
    } catch {
      window.BoltKitToast?.("Image generation failed.");
    }
    setImgGenId(null);
  };

  const startEdit = (post) => { setEditId(post.id); setEditField({ caption: post.caption, hashtags: (post.hashtags || []).join(" "), hook: post.hook || "" }); };
  const saveEdit  = (id) => { saveResults(results.map(p => p.id === id ? { ...p, ...editField, hashtags: editField.hashtags.split(/[\s,]+/).map(h => h.replace(/^#/, "")).filter(Boolean) } : p)); setEditId(null); };

  return (
    <div style={{ height: "100%", display: "flex", background: "#1A1813" }}>
      <SidebarNav active="generate" />
      <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
        <TopBar />
        <div style={{ flex: 1, overflowY: "auto" }}>

          {/* ── Config panel ── */}
          <div style={{ padding: "28px 36px 20px", borderBottom: "1px solid #34312A" }}>
            <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.22em", color: "#EFFF00", fontWeight: 800, marginBottom: 6, textTransform: "uppercase" }}>INSTAGRAM CONTENT GENERATOR</div>
            <h1 style={{ fontFamily: "'Anton', Impact, sans-serif", fontSize: 40, lineHeight: 1, margin: "0 0 20px", color: "#FFF", textTransform: "uppercase" }}>
              {generating ? `WRITING ${progress.done}/${progress.total}…` : results.length ? `${results.length} POSTS READY` : "GENERATE POSTS"}
            </h1>

            {/* Tone */}
            <div style={{ marginBottom: 14 }}>
              <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: "0.12em", color: "#5C5C5C", textTransform: "uppercase", marginBottom: 7 }}>Tone</div>
              <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                {TONES.map(t => (
                  <button key={t} onClick={() => setTone(t)} style={{ padding: "6px 12px", borderRadius: 4, fontSize: 12, fontWeight: 700, cursor: "pointer", background: tone === t ? "#EFFF00" : "#26241E", color: tone === t ? "#1A1813" : "#C8C8C5", border: `1px solid ${tone === t ? "#EFFF00" : "#3A372F"}` }}>{t}</button>
                ))}
              </div>
            </div>

            {/* Theme + Quantity + Sizes */}
            <div style={{ display: "grid", gridTemplateColumns: "1fr auto auto", gap: 14, marginBottom: 14, alignItems: "flex-end" }}>
              <div>
                <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: "0.12em", color: "#5C5C5C", textTransform: "uppercase", marginBottom: 6 }}>What's this about? (optional)</div>
                <input value={theme} onChange={e => setTheme(e.target.value)} placeholder={`e.g. "New product launch" · "Behind the scenes" · "Customer results"`}
                  style={{ width: "100%", boxSizing: "border-box", background: "#201E18", border: "1px solid #3A372F", color: "#F4F4F0", padding: "9px 12px", fontSize: 13, borderRadius: 4, outline: "none" }} />
              </div>
              <div>
                <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: "0.12em", color: "#5C5C5C", textTransform: "uppercase", marginBottom: 6 }}>How many</div>
                <div style={{ display: "flex", gap: 4 }}>
                  {QUANTITIES.map(q => (
                    <button key={q} onClick={() => setQuantity(q)} style={{ width: 36, height: 36, borderRadius: 4, fontSize: 12, fontWeight: 800, cursor: "pointer", background: quantity === q ? "#EFFF00" : "#26241E", color: quantity === q ? "#1A1813" : "#C8C8C5", border: `1px solid ${quantity === q ? "#EFFF00" : "#3A372F"}` }}>{q}</button>
                  ))}
                </div>
              </div>
              <div>
                <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: "0.12em", color: "#5C5C5C", textTransform: "uppercase", marginBottom: 6 }}>Sizes</div>
                <div style={{ display: "flex", gap: 4 }}>
                  {SIZE_OPTIONS.map(s => (
                    <button key={s.id} onClick={() => toggleSize(s.id)} title={`${s.label} ${s.sub}`} style={{ height: 36, padding: "0 10px", borderRadius: 4, fontSize: 11, fontWeight: 800, cursor: "pointer", background: sizes.includes(s.id) ? "#EFFF00" : "#26241E", color: sizes.includes(s.id) ? "#1A1813" : "#C8C8C5", border: `1px solid ${sizes.includes(s.id) ? "#EFFF00" : "#3A372F"}` }}>{s.sub}</button>
                  ))}
                </div>
              </div>
            </div>

            {/* Actions row */}
            <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
              <button className={"btn btn-primary" + (generating ? " btn-analysing" : "")} onClick={generate} disabled={generating} style={{ fontSize: 13, padding: "10px 22px" }}>
                <span className={generating ? "bolt-thinking" : ""}><BoltMini size={14} color={generating ? "#EFFF00" : "#1A1813"} /></span>
                {generating ? `Writing ${progress.done} of ${progress.total}…` : `Generate ${quantity * sizes.length} post${quantity * sizes.length !== 1 ? "s" : ""}`}
              </button>
              <label style={{ display: "flex", alignItems: "center", gap: 7, cursor: "pointer", fontSize: 12, color: "#8A8A8A", userSelect: "none" }}>
                <span onClick={() => setDeepScan(d => !d)} style={{ width: 16, height: 16, borderRadius: 3, background: deepScan ? "#EFFF00" : "#201E18", border: deepScan ? "1px solid #EFFF00" : "1px solid #3A372F", display: "grid", placeItems: "center", cursor: "pointer", flex: "none" }}>
                  {deepScan && <Icon name="check" size={10} stroke={3} color="#1A1813" />}
                </span>
                Deep scan (reads all pages on your site — slower, richer content)
              </label>
              {status && <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5, color: "#EFFF00", fontWeight: 700 }}>{status}</span>}
            </div>
          </div>

          {/* ── Results ── */}
          <div style={{ padding: "20px 36px 60px" }}>

            {/* Empty state */}
            {results.length === 0 && !generating && (
              <div style={{ textAlign: "center", padding: "60px 0", color: "#5C5C5C" }}>
                <BoltMini size={32} color="#3A372F" />
                <div style={{ marginTop: 12, fontSize: 13 }}>Pick your tone and theme above, then hit Generate.</div>
                {!hasProject && <div style={{ marginTop: 8, fontSize: 12, color: "#FF4D5E" }}>No workspace set up — go to Setup first.</div>}
              </div>
            )}

            {/* Generating splash */}
            {generating && results.length === 0 && (
              <div style={{ textAlign: "center", padding: "60px 0" }}>
                <span className="bolt-thinking" style={{ display: "inline-block" }}><BoltMini size={36} color="#EFFF00" /></span>
                <div style={{ marginTop: 16, fontFamily: "'JetBrains Mono', monospace", fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", color: "#EFFF00", textTransform: "uppercase" }}>AI IS WRITING YOUR POSTS…</div>
                <div style={{ marginTop: 6, fontSize: 12, color: "#5C5C5C" }}>{progress.done} of {progress.total} done</div>
              </div>
            )}

            {/* Post list */}
            {results.length > 0 && (
              <div>
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
                  <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.18em", color: "#5C5C5C", fontWeight: 800, textTransform: "uppercase" }}>{results.length} POSTS</div>
                  <div style={{ display: "flex", gap: 8 }}>
                    <button className="btn btn-secondary btn-sm" onClick={scheduleAll}><Icon name="calendar" size={12} stroke={2} /> Schedule all</button>
                    <button className="btn btn-secondary btn-sm" onClick={() => { if (window.confirm("Clear all generated posts?")) saveResults([]); }}><Icon name="trash" size={12} stroke={2} /> Clear all</button>
                  </div>
                </div>
                <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                  {results.map(post => (
                    <div key={post.id} style={{ background: "#201E18", border: "1px solid #3A372F", borderRadius: 8, padding: "14px 16px" }}>

                      {/* Post header */}
                      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }}>
                        <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, fontWeight: 800, letterSpacing: "0.14em", padding: "3px 7px", background: sizeColour[post.size] || "#8A8A8A", color: post.size === "portrait" ? "#1A1813" : "#FFF", borderRadius: 3 }}>{({ square: "1:1", portrait: "4:5", story: "9:16" })[post.size] || post.size}</span>
                        {post.viral_score && <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, fontWeight: 800, color: "#EFFF00", letterSpacing: "0.1em" }}>VIRAL {post.viral_score}/10</span>}
                        <span style={{ flex: 1 }} />
                        {editId === post.id ? (
                          <>
                            <button className="btn btn-primary btn-sm" onClick={() => saveEdit(post.id)}>Save</button>
                            <button className="btn btn-secondary btn-sm" onClick={() => setEditId(null)}>Cancel</button>
                          </>
                        ) : (
                          <>
                            <button className="btn btn-secondary btn-sm" onClick={() => startEdit(post)}><Icon name="edit" size={12} stroke={2} /> Edit</button>
                            <button className="btn btn-secondary btn-sm" onClick={() => copyPost(post)}><Icon name={copied === post.id ? "check" : "copy"} size={12} stroke={2} /> {copied === post.id ? "Copied!" : "Copy"}</button>
                            <button className="btn btn-secondary btn-sm" onClick={() => generateImage(post)} disabled={imgGenId === post.id} style={{ color: "#EFFF00", borderColor: "rgba(239,255,0,0.3)" }}>{imgGenId === post.id ? <span className="bolt-thinking" style={{ display: "inline-block" }}><BoltMini size={11} color="#EFFF00" /></span> : <BoltMini size={11} color="#EFFF00" />} {imgGenId === post.id ? "Generating…" : post.imageUrl ? "Regen image" : "Gen image"}</button>
                            <button className="btn btn-secondary btn-sm" onClick={() => schedulePost(post)}><Icon name="calendar" size={12} stroke={2} /> Schedule</button>
                            <button className="btn btn-secondary btn-sm" onClick={() => deletePost(post.id)} style={{ color: "#FF4D5E" }}><Icon name="trash" size={12} stroke={2} /></button>
                          </>
                        )}
                      </div>

                      {/* Editable content */}
                      {editId === post.id ? (
                        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                          <textarea value={editField.hook} onChange={e => setEditField(f => ({ ...f, hook: e.target.value }))} rows={2} placeholder="Hook (first line)" style={{ background: "#1A1813", border: "1px solid #3A372F", color: "#EFFF00", padding: "8px 10px", fontSize: 12, fontFamily: "'JetBrains Mono', monospace", borderRadius: 4, resize: "vertical", outline: "none" }} />
                          <textarea value={editField.caption} onChange={e => setEditField(f => ({ ...f, caption: e.target.value }))} rows={6} placeholder="Caption" style={{ background: "#1A1813", border: "1px solid #3A372F", color: "#C8C8C5", padding: "8px 10px", fontSize: 13, borderRadius: 4, resize: "vertical", outline: "none" }} />
                          <textarea value={editField.hashtags} onChange={e => setEditField(f => ({ ...f, hashtags: e.target.value }))} rows={3} placeholder="Hashtags (space separated)" style={{ background: "#1A1813", border: "1px solid #3A372F", color: "#4DA8FF", padding: "8px 10px", fontSize: 12, fontFamily: "'JetBrains Mono', monospace", borderRadius: 4, resize: "vertical", outline: "none" }} />
                        </div>
                      ) : (
                        <>
                          {post.hook && <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 12, fontWeight: 800, color: "#EFFF00", letterSpacing: "0.04em", marginBottom: 8, lineHeight: 1.4 }}>{post.hook}</div>}
                          <div style={{ fontSize: 13, color: "#C8C8C5", lineHeight: 1.6, marginBottom: 8, whiteSpace: "pre-line" }}>{post.caption}</div>
                          {post.hashtags?.length > 0 && (
                            <div style={{ fontSize: 11, color: "#4DA8FF", lineHeight: 1.9, fontFamily: "'JetBrains Mono', monospace", wordBreak: "break-word" }}>
                              {post.hashtags.map(h => `#${h}`).join(" ")}
                            </div>
                          )}
                          {post.first_comment && (
                            <div style={{ marginTop: 8, padding: "6px 10px", background: "#1A1813", borderRadius: 4, fontSize: 10.5, color: "#8A8A8A", fontFamily: "'JetBrains Mono', monospace" }}>
                              <span style={{ color: "#5C5C5C", fontWeight: 700, marginRight: 6 }}>FIRST COMMENT:</span>{post.first_comment}
                            </div>
                          )}
                          {post.seo_keywords?.length > 0 && (
                            <div style={{ marginTop: 6, display: "flex", gap: 4, flexWrap: "wrap" }}>
                              {post.seo_keywords.map(k => <span key={k} style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, padding: "2px 6px", background: "rgba(77,168,255,0.12)", color: "#4DA8FF", border: "1px solid rgba(77,168,255,0.25)", borderRadius: 3 }}>SEO: {k}</span>)}
                            </div>
                          )}
                          {post.imageUrl && (
                            <div style={{ marginTop: 10 }}>
                              <img src={post.imageUrl} alt={post.alt_text || "Generated"} style={{ width: "100%", maxWidth: post.size === "story" ? 220 : post.size === "portrait" ? 280 : "100%", borderRadius: 6, display: "block" }} />
                            </div>
                          )}
                        </>
                      )}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

const OutputViewerScreen = () => (
  <div style={{ height: "100%", display: "flex", background: "#1A1813" }}>
    <SidebarNav active="packs" />
    <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
      <TopBar project="Renoo · Notes" />

      {/* header strip */}
      <div style={{ padding: "18px 28px 6px" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
          <div>
            <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.22em", color: "#EFFF00", fontWeight: 800, textTransform: "uppercase" }}>PACK · RENOO · v3.2 · BRAND-LOCKED</div>
            <h2 style={{ fontFamily: "'Anton', Impact, sans-serif", fontSize: 44, lineHeight: 1, textTransform: "uppercase", margin: "6px 0 4px", color: "#FFF" }}>Full Launch Pack</h2>
            <div style={{ display: "flex", gap: 10, alignItems: "center", color: "#8A8A8A", fontSize: 12 }}>
              <span>Generated 09:02 · ~22s · 132 assets</span>
              <span>·</span>
              <span style={{ color: "#4ADE80", fontFamily: "'JetBrains Mono', monospace", fontWeight: 800, letterSpacing: "0.14em", textTransform: "uppercase" }}>QS 94</span>
              <span>·</span>
              <span style={{ color: "#EFFF00", fontFamily: "'JetBrains Mono', monospace", fontWeight: 800, letterSpacing: "0.14em", textTransform: "uppercase" }}>BRAND MATCH 92</span>
            </div>
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <button className="btn btn-secondary"><Icon name="copy" size={12} stroke={2} /> Copy all</button>
            <button className="btn btn-secondary"><Icon name="refresh" size={12} stroke={2} /> Regenerate</button>
            <button className="btn btn-primary"><Icon name="download" size={12} stroke={2} /> Export ZIP</button>
          </div>
        </div>
      </div>

      {/* tabs */}
      <div className="out-tab-row" style={{ padding: "0 28px", overflowX: "auto" }}>
        {["Overview","Instagram","Video","Ads","App Store","Landing","SEO","Claude","Codex"].map((t, i) => (
          <div key={t} className={"t" + (i === 0 ? " active" : "")}>{t}</div>
        ))}
      </div>

      {/* body — 2 col layout: list + editor */}
      <div style={{ flex: 1, overflow: "hidden", display: "grid", gridTemplateColumns: "320px 1fr", gap: 0 }}>
        <div style={{ borderRight: "1px solid #3A372F", overflowY: "auto", padding: 12, background: "#1A1813" }}>
          {[
            { g: "Hooks · 8" },
            { g: "Captions · 30" },
            { g: "Hashtag stacks · 6" },
            { g: "First comments · 30" },
          ].map(s => (
            <div key={s.g} style={{ marginBottom: 12 }}>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, letterSpacing: "0.2em", color: "#8A8A8A", fontWeight: 800, textTransform: "uppercase", padding: "4px 6px" }}>{s.g}</div>
              {[0,1,2,3,4].map(i => (
                <div key={i} style={{ display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 8, padding: "8px 8px", background: i === 1 ? "#2C2A23" : "transparent", borderRadius: 4, alignItems: "center", cursor: "pointer", marginBottom: 1 }}>
                  <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, color: "#8A8A8A", fontWeight: 800, letterSpacing: "0.1em" }}>{String(i + 1).padStart(2, "0")}</span>
                  <span style={{ fontSize: 12, color: i === 1 ? "#FFF" : "#C8C8C5", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{["30 ideas from one brand pack.","One folder. Every post.","Captions that sound like you.","Batch now, post calmly.","Stop guessing what to post."][i]}</span>
                  <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, color: "#4ADE80", fontWeight: 800 }}>{[91,94,88,82,78][i]}</span>
                </div>
              ))}
            </div>
          ))}
        </div>

        <div style={{ overflowY: "auto", padding: 22, background: "#201E18" }}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 280px", gap: 16 }}>
            <div>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
                <span className="ai-chip"><Icon name="sparkle" size={11} stroke={2} /> EDIT</span>
                <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#8A8A8A", letterSpacing: "0.14em", textTransform: "uppercase", fontWeight: 800 }}>INSTAGRAM · POST 02 · CAPTION</span>
                <div style={{ marginLeft: "auto", display: "flex", gap: 4 }}>
                  <span className="pill pill-yellow" style={{ fontSize: 9 }}>QS 94</span>
                  <span className="pill pill-yellow-soft" style={{ fontSize: 9 }}>BM 92</span>
                </div>
              </div>
              <div style={{ background: "#1A1813", border: "1px solid #3A372F", padding: 18 }}>
                <div style={{ fontFamily: "'Anton', Impact, sans-serif", fontSize: 24, color: "#FFF", textTransform: "uppercase", lineHeight: 1.05, marginBottom: 12 }}>One folder. Every post.</div>
                <div style={{ color: "#C8C8C5", fontSize: 13.5, lineHeight: 1.65 }}>
                  Your best ideas are already sitting in links, notes, screenshots and camera roll chaos. BoltKit turns them into a clear content plan. <b style={{ color: "#FFF" }}>One folder, every post — ready when you are.</b><br/><br/>
                  → Upload your assets. <br/>→ Pick your goal. <br/>→ Schedule the week calmly.
                </div>
                <div style={{ marginTop: 14, display: "flex", gap: 6, flexWrap: "wrap" }}>
                  {["#contentcreator","#instagramtips","#socialmediatips","#creatorbusiness","#smallbusiness","#reelsideas","#contentcalendar","#brandvoice"].map(h => (
                    <span key={h} style={{ background: "rgba(239,255,0,0.08)", color: "#EFFF00", padding: "3px 8px", fontFamily: "'JetBrains Mono', monospace", fontSize: 11, fontWeight: 700 }}>{h}</span>
                  ))}
                </div>
                <div style={{ marginTop: 14, paddingTop: 12, borderTop: "1px dashed #3A372F", fontSize: 11.5, color: "#8A8A8A" }}>
                  <b style={{ color: "#C8C8C5" }}>First comment:</b> Want the batching checklist? Comment CONTENT.
                </div>
              </div>

              {/* improve toolbar */}
              <div style={{ marginTop: 14, display: "flex", gap: 6, flexWrap: "wrap" }}>
                {["Punchier","Shorter","More premium","More viral","Stronger CTA","Rewrite for X","Rewrite for LinkedIn","A/B 5 hooks"].map(t => (
                  <button key={t} className="chip" style={{ background: "#2C2A23", color: "#C8C8C5", border: "1px solid #333" }}>{t}</button>
                ))}
              </div>
            </div>

            {/* preview phone */}
            <div>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.18em", color: "#EFFF00", fontWeight: 800, textTransform: "uppercase", marginBottom: 8 }}>LIVE PREVIEW</div>
              <div style={{ background: "#2C2A23", border: "1px solid #333", padding: 12, borderRadius: 6 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 11, color: "#FFF", fontWeight: 700 }}>
                  <div style={{ width: 24, height: 24, borderRadius: 99, background: "#FF6B35" }} />
                  <span>boltkit.creator</span>
                  <Icon name="check_circle" size={11} color="#4DA8FF" />
                </div>
                <div style={{ height: 220, marginTop: 8, background: "#FF6B35", display: "grid", placeItems: "center", borderRadius: 4, color: "#FFF", fontFamily: "'Anton', Impact, sans-serif", fontSize: 28, textTransform: "uppercase", letterSpacing: "0.02em" }}>POST · 1</div>
                <div style={{ marginTop: 8, fontSize: 11.5, color: "#C8C8C5", lineHeight: 1.5 }}>
                  <b style={{ color: "#FFF" }}>boltkit.creator</b> One folder. Every post. Your next content batch starts here…
                </div>
              </div>

              <div style={{ marginTop: 14, background: "#26241E", border: "1px solid #3A372F", padding: 12 }}>
                <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.18em", color: "#8A8A8A", fontWeight: 800, textTransform: "uppercase", marginBottom: 6 }}>VERSIONS</div>
                {["v3 · 09:02 · current","v2 · 08:54","v1 · 08:41"].map((v, i) => (
                  <div key={i} style={{ display: "flex", justifyContent: "space-between", padding: "6px 0", fontSize: 12, color: i === 0 ? "#EFFF00" : "#8A8A8A", fontWeight: i === 0 ? 700 : 500, borderTop: i ? "1px dashed #3A372F" : 0 }}>
                    <span>{v}</span>
                    <button style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5, letterSpacing: "0.14em", color: "#8A8A8A", fontWeight: 800, textTransform: "uppercase", background: "transparent" }}>Open</button>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
);

const VideoStudioScreen = () => (
  <div style={{ height: "100%", display: "flex", background: "#1A1813" }}>
    <SidebarNav active="video" />
    <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
      <TopBar />
      <div style={{ flex: 1, overflowY: "auto", padding: "24px 28px 40px" }}>
        <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5, letterSpacing: "0.22em", color: "#EFFF00", fontWeight: 800, textTransform: "uppercase", display: "inline-flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
          <span style={{ width: 18, height: 1, background: "#EFFF00" }} />VIDEO STUDIO · 10s SOCIAL
        </div>
        <h1 style={{ fontFamily: "'Anton', Impact, sans-serif", fontSize: 56, lineHeight: 0.94, textTransform: "uppercase", margin: "0 0 22px", color: "#FFF" }}>Reels · Shorts · TikTok</h1>

        <div style={{ display: "grid", gridTemplateColumns: "1.2fr 1fr", gap: 16 }}>
          <div className="card has-corners" style={{ padding: 20 }}>
            <div style={{ display: "flex", gap: 6, marginBottom: 14 }}>
              {[
                { l: "REELS", on: true,  i: "insta" },
                { l: "TIKTOK", on: false, i: "tiktok" },
                { l: "SHORTS", on: false, i: "youtube" },
              ].map(p => (
                <div key={p.l} style={{ padding: "8px 12px", background: p.on ? "#EFFF00" : "#26241E", color: p.on ? "#1A1813" : "#FFF", border: p.on ? "1px solid #ADC700" : "1px solid #3A372F", display: "flex", alignItems: "center", gap: 7, fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5, fontWeight: 800, letterSpacing: "0.12em", textTransform: "uppercase" }}>
                  <Icon name={p.i} size={13} stroke={2} />{p.l}
                </div>
              ))}
            </div>
            <label className="field-label">Hook (line 1)</label>
            <input className="input" defaultValue="30 ideas from one brand pack." />
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginTop: 14 }}>
              <div>
                <label className="field-label">Style</label>
                <select className="select"><option>Creator POV · jump-cut</option></select>
              </div>
              <div>
                <label className="field-label">Length</label>
                <select className="select"><option>10s · 5 cuts</option></select>
              </div>
            </div>

            {/* shot list */}
            <div style={{ marginTop: 18 }}>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
                <span className="ai-chip"><Icon name="sparkle" size={11} stroke={2} /> AI SHOT LIST</span>
                <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#8A8A8A", letterSpacing: "0.14em", fontWeight: 800, textTransform: "uppercase" }}>5 shots · ~10s</span>
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                {[
                  { t: "0:00", s: "POV: camera roll full of unused posts", v: "30 ideas." },
                  { t: "0:02", s: "Cut: BoltKit calendar filling instantly", v: "One brand pack." },
                  { t: "0:04", s: "Phone preview · caption appears", v: "Ready to post." },
                  { t: "0:07", s: "Weekly schedule locks in", v: "Your week planned." },
                  { t: "0:09", s: "Logo + CTA card", v: "BoltKit. Create calmly." },
                ].map(s => (
                  <div key={s.t} style={{ display: "grid", gridTemplateColumns: "44px 1fr 1fr", gap: 10, alignItems: "center", padding: "10px 12px", background: "#201E18", border: "1px solid #3A372F" }}>
                    <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: "#EFFF00", letterSpacing: "0.08em", fontWeight: 800 }}>{s.t}</span>
                    <span style={{ color: "#C8C8C5", fontSize: 12 }}>{s.s}</span>
                    <span style={{ color: "#FFF", fontSize: 12, fontWeight: 700 }}>"{s.v}"</span>
                  </div>
                ))}
              </div>
            </div>

            <div style={{ display: "flex", gap: 8, marginTop: 18, alignItems: "center" }}>
              <button className="btn btn-secondary"><Icon name="refresh" size={12} stroke={2} /> Regenerate</button>
              <button className="btn btn-secondary"><Icon name="copy" size={12} stroke={2} /> Copy script</button>
              <span style={{ marginLeft: "auto", fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#FFB23F", fontWeight: 800, letterSpacing: "0.14em", textTransform: "uppercase" }}>RENDER · 25 CREDITS</span>
              <button className="btn btn-primary"><BoltMini size={13} color="#1A1813" /> Render with Sora</button>
            </div>
          </div>

          {/* preview phone */}
          <div className="card" style={{ padding: 20, display: "flex", flexDirection: "column", gap: 12 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <span className="ai-chip-soft"><Icon name="video" size={11} stroke={2} /> PREVIEW</span>
              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#8A8A8A", letterSpacing: "0.14em", textTransform: "uppercase", fontWeight: 800 }}>9:19 · MUTED</span>
            </div>
            <div style={{ background: "#2C2A23", border: "1px solid #333", aspectRatio: "9/16", position: "relative", display: "grid", placeItems: "center" }}>
              <div style={{ position: "absolute", top: 12, left: 12, fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#FFF", padding: "4px 8px", background: "rgba(0,0,0,0.6)", fontWeight: 800, letterSpacing: "0.14em" }}>SHOT 02 · 0:02</div>
              <div style={{ position: "absolute", bottom: 16, left: 16, right: 16 }}>
                <div style={{ fontFamily: "'Anton', Impact, sans-serif", fontSize: 38, color: "#FFF", textTransform: "uppercase", letterSpacing: "-0.005em", lineHeight: 0.95 }}>Zero<br />launches.</div>
              </div>
              <button style={{ width: 60, height: 60, borderRadius: 99, background: "rgba(239,255,0,0.95)", color: "#1A1813", display: "grid", placeItems: "center" }}>
                <Icon name="play" size={26} stroke={2} />
              </button>
            </div>
            <div style={{ background: "#201E18", border: "1px solid #3A372F", padding: 12 }}>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: "#8A8A8A", letterSpacing: "0.18em", textTransform: "uppercase", fontWeight: 800, marginBottom: 6 }}>RENDER QUEUE</div>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", fontSize: 12, color: "#FFF" }}>
                <span>3 shots queued</span>
                <span style={{ color: "#EFFF00", fontFamily: "'JetBrains Mono', monospace", fontWeight: 800, letterSpacing: "0.1em" }}>~ 3min</span>
              </div>
              <div style={{ height: 4, background: "#2C2A23", marginTop: 8 }}>
                <div style={{ width: "62%", height: "100%", background: "#EFFF00" }} />
              </div>
            </div>
            <div style={{ fontSize: 11.5, color: "#8A8A8A", lineHeight: 1.5 }}>
              <b style={{ color: "#FFB23F" }}>Heads up:</b> Real-time video rendering is gated behind Pro &amp; available when your Sora / OpenAI key is connected.
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
);

Object.assign(window, { IGGenerateScreen, GenerateHubScreen, OutputViewerScreen, VideoStudioScreen });
