/* global window */
// Mock data for Atria Radar → Image Gen redesign.

const PERSONAS = [
  ["Coffee enthusiasts", "Productivity-minded", "Urban professionals 25-40"],
  ["Eco-conscious shoppers", "Sustainability advocates", "Millennials"],
  ["Time-strapped parents", "Convenience seekers"],
  ["Outdoor / travel", "Adventure seekers", "Gen-Z"],
  ["Health-curious", "Wellness", "30-45"],
];

const REC_TEMPLATES = [
  {
    id: "rec-cta",
    title: "Strengthen Call-to-Action",
    titleZh: "强化行动按钮文案",
    short: "CTA verbs are passive — swap to direct, value-led commands.",
    shortZh: "按钮文案太被动 —— 换成直接、点出好处的命令式动词。",
    why: "Three of the top-performing creatives in this brand's cohort lead with imperative verbs (\"Brew\", \"Save\", \"Try free\"). Yours leans on \"Learn more\".",
    whyZh: "你这个品牌的同类账户里,跑得最好的 3 条创意都用命令式动词开头(「冲一杯」「省钱」「免费试用」)。你这条还在用「了解更多」这种被动文案。",
    example: "Replace \"Learn more\" with \"Brew in 3 sec → Save 10 hrs/week\" overlay on the bottom third.",
    exampleZh: "把「了解更多」换成「3 秒冲一杯 → 一周省 10 小时」,叠在图片底部三分之一处。",
    metrics: ["CTR", "ROAS"],
    primaryMetric: { name: "CTR", baseline: 1.4, projected: 1.93, delta: 38, confidence: "med", basis: 18 },
    priority: 1,
    action_kind: "copy_overlay",
    cta_label: "Generate 4 copy variants",
    cta_labelZh: "生成 4 个文案变体",
    output_label: "4 copy variants ready",
    output_labelZh: "4 个文案变体已就绪",
  },
  {
    id: "rec-audience",
    title: "Optimize Audience Targeting",
    titleZh: "优化投放受众",
    short: "Drop 18-24, double down on 28-40 urban professionals.",
    shortZh: "砍掉 18-24 岁人群,集中投 28-40 岁城市白领。",
    why: "Spend on 18-24 is 23% of budget but converts at 0.4× — cohort fatigue, not creative.",
    whyZh: "18-24 岁人群占了 23% 预算,转化率只有大盘的 0.4 倍 —— 不是创意问题,是这群人疲劳了。",
    example: "Reallocate to lookalikes seeded from last-30-day purchasers; exclude existing customers.",
    exampleZh: "把预算挪到「近 30 天购买者」的相似人群;同时排除已经买过的老客户。",
    metrics: ["ROAS", "CPA"],
    primaryMetric: { name: "ROAS", baseline: 1.4, projected: 1.74, delta: 24, confidence: "high", basis: 32 },
    priority: 2,
    action_kind: "targeting_change",
    cta_label: "Apply targeting change",
    cta_labelZh: "应用受众调整",
    output_label: "Targeting updated on Meta",
    output_labelZh: "Meta 受众已更新",
  },
  {
    id: "rec-reorder",
    title: "Reorder to Show Benefits First",
    titleZh: "重新排序,把卖点放前面",
    short: "Lead frame is product shot — should be the time-saving benefit.",
    shortZh: "开头给的是产品图 —— 应该先给「省时间」这个卖点。",
    why: "Hold rate drops 38% before the 3-second mark; benefit reveal happens at 4.2s.",
    whyZh: "前 3 秒留存率掉了 38%,而卖点要到 4.2 秒才出现 —— 大部分观众没看到关键信息就走了。",
    example: "Cut the opening 2 sec; start with the \"$2,000/month → $19\" frame.",
    exampleZh: "砍掉开头 2 秒,从「每月 2000 → 19」这一帧开场。",
    metrics: ["Hold Rate", "Watch Time"],
    primaryMetric: { name: "Hold rate", baseline: 28, projected: 41, delta: 46, confidence: "med", basis: 14 },
    priority: 3,
    action_kind: "image_gen",
    cta_label: "Generate 4 images",
    cta_labelZh: "生成 4 张图",
    output_label: "4 image variants ready",
    output_labelZh: "4 张图变体已就绪",
  },
  {
    id: "rec-format",
    title: "Test Split-Screen Format",
    titleZh: "测试分屏对比格式",
    short: "Comparison frames out-perform single-product in this niche.",
    shortZh: "在这个品类里,「对比画面」比「纯产品图」表现更好。",
    why: "Split-screen variants in your cohort show 1.6× thumbstop and 1.3× CTR vs single-product.",
    whyZh: "你同类账户里,分屏格式的变体钩住率(thumbstop)是纯产品图的 1.6 倍,CTR 是 1.3 倍。",
    example: "Left: traditional drip brew (60 sec wait). Right: your product (3 sec).",
    exampleZh: "左屏:传统手冲(等 60 秒)。右屏:你的产品(3 秒搞定)。",
    metrics: ["Thumbstop", "View Time"],
    primaryMetric: { name: "Thumbstop", baseline: 19, projected: 31, delta: 63, confidence: "high", basis: 27 },
    priority: 4,
    action_kind: "image_gen",
    cta_label: "Generate 4 images",
    cta_labelZh: "生成 4 张图",
    output_label: "4 image variants ready",
    output_labelZh: "4 张图变体已就绪",
  },
  {
    id: "rec-visual",
    title: "Refresh Visual Style",
    titleZh: "换一套视觉风格",
    short: "Creative is 11 weeks old — visual fatigue is measurable.",
    shortZh: "这条创意已经投了 11 周 —— 视觉疲劳已经能从数据上看出来。",
    why: "Frequency is 4.8 on your top audience; CTR has decayed 22% week-over-week.",
    whyZh: "核心受众接触频次已经到 4.8;CTR 周环比衰减 22%。",
    example: "Same copy, swap to warm kitchen lifestyle palette (vs current studio white).",
    exampleZh: "文案保持不动,把背景从「纯白棚拍」换成「温暖家居场景」配色。",
    metrics: ["Hook Rate", "CTR"],
    primaryMetric: { name: "Hook rate", baseline: 31, projected: 44, delta: 42, confidence: "med", basis: 21 },
    priority: 5,
    action_kind: "image_gen",
    cta_label: "Generate 4 images",
    cta_labelZh: "生成 4 张图",
    output_label: "4 image variants ready",
    output_labelZh: "4 张图变体已就绪",
  },
];

const VARIANT_NAMES = [
  { name: "Explore Now", desc: "Direct CTA, neutral palette, product hero centered.", tags: ["Promotion", "Hero"] },
  { name: "Limited Time Offer", desc: "Urgency-led, red price tag overlay, ribbon banner.", tags: ["Urgency", "Discount"] },
  { name: "Save 10 Hours / Week", desc: "Benefit-first headline, lifestyle background, soft sun.", tags: ["Lifestyle", "Benefit"] },
  { name: "Get Started", desc: "Onboarding-style framing, two-step illustration.", tags: ["Onboarding", "Educational"] },
];

// 15 ads — 10 image + 5 video.
const AD_HEADLINES = [
  // 10 images
  { type: "image", headline: "$2,000/month ad tools are robbing marketers", headlineZh: "每月 2000 美金的广告工具正在掏空营销预算", sub: "switch in 3 sec", subZh: "3 秒切换", code: "WARN-2K" },
  { type: "image", headline: "Brew in 3 seconds. Anywhere.", headlineZh: "3 秒一杯,随时随地。", sub: "saturnbird · freeze-dried", subZh: "三顿半 · 冻干咖啡", code: "BREW-3S" },
  { type: "image", headline: "Specialty coffee. Without the wait.", headlineZh: "精品咖啡,不用等。", sub: "shelf-stable for 18 months", subZh: "保质期 18 个月", code: "SPEC-NW" },
  { type: "image", headline: "From farm to cup in one packet", headlineZh: "一包,从产地直达你的杯子", sub: "Yunnan single-origin", subZh: "云南单一产区", code: "FARM-1P" },
  { type: "image", headline: "Your camping kit is missing this", headlineZh: "你的露营装备里少了这个", sub: "lightweight · no equipment", subZh: "轻便 · 无需器具", code: "CAMP-KIT" },
  { type: "image", headline: "Office coffee, fixed.", headlineZh: "办公室咖啡,这次搞定了。", sub: "no machine, no mess", subZh: "不要机器,不会脏", code: "OFFICE-FX" },
  { type: "image", headline: "Real beans. Real fast.", headlineZh: "真豆子,真快。", sub: "freeze-dried, not instant", subZh: "冻干,不是速溶", code: "REAL-FAST" },
  { type: "image", headline: "12 origins. One pack.", headlineZh: "12 个产区,一盒搞定。", sub: "tasting flight at home", subZh: "在家品鉴", code: "12-OR" },
  { type: "image", headline: "Cold brew without the 12-hour wait", headlineZh: "冷萃咖啡,不用等 12 小时", sub: "drop in cold water", subZh: "丢进冷水即可", code: "COLD-BR" },
  { type: "image", headline: "Why pour-over takes 4 minutes you don't have", headlineZh: "手冲要 4 分钟,你没那么多时间", sub: "ours takes 3 seconds", subZh: "我们只要 3 秒", code: "POUR-4M" },
  // 5 videos
  { type: "video", headline: "60 seconds of drip vs 3 seconds of us", headlineZh: "60 秒手冲 vs 我们的 3 秒", sub: "split-screen demo", subZh: "分屏对比", code: "VID-60V3" },
  { type: "video", headline: "Behind the freeze-drying lab", headlineZh: "走进冻干工厂", sub: "60s factory tour", subZh: "60 秒厂区一览", code: "VID-LAB" },
  { type: "video", headline: "Barista reacts to instant coffee", headlineZh: "咖啡师试喝速溶咖啡", sub: "blind taste test", subZh: "盲测", code: "VID-REACT" },
  { type: "video", headline: "Morning routine, 3 seconds in", headlineZh: "3 秒搞定的晨间例行", sub: "POV ASMR", subZh: "第一视角 · ASMR", code: "VID-MORN" },
  { type: "video", headline: "Camping trip · day 2 coffee", headlineZh: "露营第 2 天 · 今天的咖啡", sub: "outdoor lifestyle", subZh: "户外生活", code: "VID-CAMP" },
];

function pick(arr, i) { return arr[i % arr.length]; }
function rnd(seed) {
  // deterministic-ish
  let x = Math.sin(seed) * 10000;
  return x - Math.floor(x);
}

const GRADES = ["A", "B", "C", "D"];
// Force grade distribution: A=2, B=5, C=5, D=3
const GRADE_DIST = ["A","A","B","B","B","B","B","C","C","C","C","C","D","D","D"];
// Recommendation type per row — distributed so Pause/Scale/Refresh all land on image rows
// (video rows get overridden to "Video · advisory" in the UI regardless of recType).
const REC_TYPE = ["Scale","Scale","Iterate","Iterate","Refresh","Iterate","Refresh","Pause","Pause","Iterate","Iterate","Iterate","Iterate","Iterate","Iterate"];

function subGrade(r) {
  if (r > 0.78) return "A";
  if (r > 0.52) return "B";
  if (r > 0.28) return "C";
  return "D";
}

const ADS = AD_HEADLINES.map((h, i) => {
  const grade = GRADE_DIST[i];
  const recType = REC_TYPE[i];
  const spend = Math.round((100 + rnd(i + 1) * 1900) * 100) / 100;
  const roas = Math.round((0.5 + rnd(i + 7) * 3.5) * 100) / 100;
  return {
    id: `ad-${String(i + 1).padStart(2, "0")}`,
    code: h.code,
    type: h.type,
    headline: h.headline,
    headlineZh: h.headlineZh,
    sub: h.sub,
    subZh: h.subZh,
    name: `${h.code} · ${h.headline.slice(0, 32)}${h.headline.length > 32 ? "…" : ""}`,
    grade,
    subGrades: {
      roas: subGrade(rnd(i + 11)),
      hook: subGrade(rnd(i + 13)),
      retention: subGrade(rnd(i + 17)),
      ctr: subGrade(rnd(i + 19)),
    },
    spend,
    roas,
    impressions: Math.round(spend * (180 + rnd(i + 23) * 800)),
    recType,
    persona: PERSONAS[i % PERSONAS.length],
    age: `${Math.round(2 + rnd(i + 29) * 16)} weeks`,
    perfText: i % 3 === 0
      ? "Spend is concentrated in the first 7 days; ROAS plateaued at 1.4 after a strong open. Frequency on the top audience has crossed 4.8 — fatigue is the most likely cause of decay rather than creative quality."
      : i % 3 === 1
      ? "Mid-funnel performance is strong (CTR 1.8%, hook 32%) but conversion is leaking late — landing page bounce on mobile is 71%. Creative is working harder than the post-click."
      : "This ad is over-performing on retention (top decile) but under-spending. CTR is below cohort median; the headline is doing most of the work — the visual is weak.",
    topIssues: [
      "Frequency saturation on primary audience (4.8×)",
      "Mobile landing page bounce (71%) leaking late-funnel conversion",
      "CTA below the fold on 9:16 placements",
    ],
    recs: REC_TEMPLATES,
  };
});

// Mark which ads already had iterations done (for TC-11 demo + table badges)
const INITIAL_ITERATIONS = {
  "ad-04": 3,  // already 3 iterations
  "ad-07": 1,
};

// Initial tasks for the global Tasks panel
function nowOffset(min) { return Date.now() - min * 60 * 1000; }
const INITIAL_TASKS = [
  {
    id: "task-r1", status: "running",
    adId: "ad-09", adCode: "COLD-BR",
    recId: "rec-cta", recTitle: "Strengthen Call-to-Action",
    action_kind: "copy_overlay",
    startedAt: nowOffset(0), eta: 35, progress: 30,
  },
  {
    id: "task-r2", status: "running",
    adId: "ad-06", adCode: "OFFICE-FX",
    recId: "rec-format", recTitle: "Test Split-Screen Format",
    action_kind: "image_gen",
    startedAt: nowOffset(0), eta: 12, progress: 70,
  },
  {
    id: "task-c1", status: "completed",
    adId: "ad-04", adCode: "FARM-1P",
    recId: "rec-cta", recTitle: "Strengthen Call-to-Action",
    action_kind: "copy_overlay",
    completedAt: nowOffset(38),
  },
  {
    id: "task-c2", status: "completed",
    adId: "ad-04", adCode: "FARM-1P",
    recId: "rec-visual", recTitle: "Refresh Visual Style",
    action_kind: "image_gen",
    completedAt: nowOffset(54),
  },
  {
    id: "task-c3", status: "completed",
    adId: "ad-04", adCode: "FARM-1P",
    recId: "rec-reorder", recTitle: "Reorder to Show Benefits First",
    action_kind: "image_gen",
    completedAt: nowOffset(75),
  },
  {
    id: "task-c4", status: "completed",
    adId: "ad-07", adCode: "REAL-FAST",
    recId: "rec-audience", recTitle: "Optimize Audience Targeting",
    action_kind: "targeting_change",
    completedAt: nowOffset(102),
  },
  {
    id: "task-c5", status: "completed",
    adId: "ad-02", adCode: "BREW-3S",
    recId: "rec-cta", recTitle: "Strengthen Call-to-Action",
    action_kind: "copy_overlay",
    completedAt: nowOffset(118),
  },
  {
    id: "task-f1", status: "failed",
    adId: "ad-03", adCode: "SPEC-NW",
    recId: "rec-visual", recTitle: "Refresh Visual Style",
    action_kind: "image_gen",
    failedAt: nowOffset(22),
    reason: "Content policy: prompt referenced a competitor brand name.",
  },
];

// Brand
const BRAND = {
  name: "Lipsum Brand",
  alias: "SATURNBIRD freeze-dried specialty coffee",
  primary: "#D14A1F",
  logo: "LB",
  url: "https://lipsum-brand.com/products/freeze-dried-coffee",
  description: "Premium freeze-dried specialty coffee. 3-second brew. Shelf-stable 18 months. Single-origin Yunnan beans, 12 flavor profiles.",
  productImages: ["PROD-A", "PROD-B", "PROD-C", "PROD-D"],
  styles: ["Editorial photography", "Warm lifestyle", "Studio minimal", "Bold typographic"],
  fonts: ["Söhne Display", "Editorial Old"],
};

// Tabs on the Radar screen (counts derived)
function radarTabs(ads) {
  return [
    { id: "winners", label: "Winners", labelZh: "赢家", glyph: "★", filter: a => a.grade === "A" },
    { id: "high", label: "High iteration potential", labelZh: "迭代潜力大", glyph: "▴", filter: a => a.grade === "B" },
    { id: "candidates", label: "Iteration candidates", labelZh: "待迭代", glyph: "·", filter: a => a.grade === "C" || a.grade === "D" },
    { id: "all", label: "All ads", labelZh: "全部广告", glyph: "", filter: () => true },
  ];
}

// === Pulse alerts — live signal stream tied to Radar ads ===
// severity: "critical" | "warn" | "info"
const PULSE_ALERTS = [
  {
    id: "alrt-1", severity: "critical", adId: "ad-09", adCode: "COLD-BR",
    title: "CTR collapsed 38% in the last 4 hours",
    titleZh: "过去 4 小时 CTR 暴跌 38%",
    body: "From 1.6% to 0.99%. Audience overlap with paused ad COFFEE-X spiked at 14:00.",
    bodyZh: "从 1.6% 掉到 0.99%。14:00 起跟已暂停的 COFFEE-X 广告受众重叠飙升。",
    metric: "CTR", from: 1.6, to: 0.99, delta: -38,
    actionLabel: "Open in Radar", actionLabelZh: "在 Radar 中打开",
    minutesAgo: 22,
  },
  {
    id: "alrt-2", severity: "critical", adId: "ad-06", adCode: "OFFICE-FX",
    title: "Budget pacing 2.3× over plan",
    titleZh: "预算消耗比计划快 2.3 倍",
    body: "Spent $4,210 in last 6h. Daily cap of $1,800 will be hit by 17:00. Likely auction bug.",
    bodyZh: "过去 6 小时花了 4210 美金。17:00 之前就会撞到 1800 美金的日预算上限。大概率是竞价系统出问题。",
    metric: "Spend", from: 1800, to: 4210, delta: 134,
    actionLabel: "Pause in Radar", actionLabelZh: "在 Radar 中暂停",
    minutesAgo: 41,
  },
  {
    id: "alrt-3", severity: "critical", adId: "ad-12", adCode: "VID-60V3",
    title: "Meta flagged the headline copy",
    titleZh: "Meta 标记了广告标题文案",
    body: "Policy violation — \"robbed\" triggered the misleading claims filter. Ad disabled pending review.",
    bodyZh: "政策违规 —— 「robbed」(抢钱)一词触发了「误导性宣称」过滤器。广告已停投,等待复审。",
    metric: "Status", from: "Active", to: "Under review", delta: 0,
    actionLabel: "Review copy in Radar", actionLabelZh: "在 Radar 中复查文案",
    minutesAgo: 78,
  },
  {
    id: "alrt-4", severity: "warn", adId: "ad-02", adCode: "BREW-3S",
    title: "Frequency reached 5.2 on top audience",
    titleZh: "核心受众接触频次达到 5.2",
    body: "Eco-conscious 28-40 cluster has seen this ad 5.2× this week. Creative fatigue is measurable.",
    bodyZh: "「环保人群 28-40 岁」这群人本周已经看到这条广告 5.2 次。创意疲劳已经能从数据上看出来了。",
    metric: "Frequency", from: 4.1, to: 5.2, delta: 27,
    actionLabel: "Refresh in Radar", actionLabelZh: "在 Radar 中换素材",
    minutesAgo: 105,
  },
  {
    id: "alrt-5", severity: "warn", adId: "ad-04", adCode: "FARM-1P",
    title: "CPM rising — 26% above 14d avg",
    titleZh: "CPM 持续上升,比 14 天均值高 26%",
    body: "Cost per mille climbed from $9.20 to $11.55 over the last 48h. Likely audience saturation.",
    bodyZh: "千次曝光成本(CPM)过去 48 小时从 9.2 美金涨到 11.55 美金。大概率是受众饱和了。",
    metric: "CPM", from: 9.20, to: 11.55, delta: 26,
    actionLabel: "Diagnose in Radar", actionLabelZh: "在 Radar 中诊断",
    minutesAgo: 142,
  },
  {
    id: "alrt-6", severity: "warn", adId: "ad-07", adCode: "SPEC-NW",
    title: "Hold-rate dropping below median",
    titleZh: "留存率掉到同类中位数以下",
    body: "3-sec hold-rate at 52% vs cohort median of 64%. Hook is losing grip.",
    bodyZh: "3 秒留存率 52%,同类账户中位数是 64%。开头钩子开始抓不住人了。",
    metric: "Hold rate", from: 64, to: 52, delta: -19,
    actionLabel: "Iterate in Radar", actionLabelZh: "在 Radar 中迭代",
    minutesAgo: 188,
  },
  {
    id: "alrt-7", severity: "info", adId: "ad-00", adCode: "WARN-2K",
    title: "A/B test reached significance",
    titleZh: "A/B 测试已达到统计显著性",
    body: "Variant B (Limited Time Offer) beating control at p<0.01. Safe to roll out.",
    bodyZh: "变体 B(限时优惠)以 p<0.01 跑赢对照组。可以放心全量上线。",
    metric: "Conversion", from: 2.1, to: 2.9, delta: 38,
    actionLabel: "Promote in Radar", actionLabelZh: "在 Radar 中推广",
    minutesAgo: 240,
  },
  {
    id: "alrt-8", severity: "info", adId: "ad-01", adCode: "BREW-1S",
    title: "Cohort drift — new persona matching",
    titleZh: "受众漂移 —— 新画像匹配上了",
    body: "12% of last-week conversions came from \"Outdoor / travel\" — a persona not in your seed set.",
    bodyZh: "上周 12% 的转化来自「户外 / 旅行」人群 —— 这个画像不在你最初设的种子人群里。",
    metric: "Persona", from: "Seed only", to: "Expanded", delta: 0,
    actionLabel: "Explore in Radar", actionLabelZh: "在 Radar 中探索",
    minutesAgo: 320,
  },
  {
    id: "alrt-9", severity: "info", adId: "ad-04", adCode: "FARM-1P",
    title: "Lookalike refresh complete",
    titleZh: "相似人群已刷新",
    body: "Meta refreshed your 1% lookalike from last-30-day purchasers. 4.2M reach available.",
    bodyZh: "Meta 基于近 30 天的购买者刷新了你的 1% 相似人群。可触达 420 万人。",
    metric: "Audience size", from: 3.8, to: 4.2, delta: 11,
    actionLabel: "View in Radar", actionLabelZh: "在 Radar 中查看",
    minutesAgo: 410,
  },
  {
    id: "alrt-10", severity: "warn", adId: "ad-11", adCode: "VID-30V2",
    title: "Watch-time falling on mobile",
    titleZh: "移动端观看时长在下降",
    body: "Mobile completion rate down 22% week-over-week. Desktop stable. Mobile-first cut recommended.",
    bodyZh: "移动端完播率周环比下降 22%。桌面端稳定。建议出一个「移动端优先」的剪辑版本。",
    metric: "Completion", from: 41, to: 32, delta: -22,
    actionLabel: "Brief a re-cut", actionLabelZh: "出一份重剪 brief",
    minutesAgo: 500,
  },
  {
    id: "alrt-11", severity: "info", adId: "ad-02", adCode: "BREW-3S",
    title: "Iteration BREW-3S/v2 outperforming control",
    titleZh: "迭代版本 BREW-3S/v2 跑赢原版",
    body: "Pushed 2 days ago. +42% CTR observed in first 48h. Confidence: high.",
    bodyZh: "2 天前推回投放。前 48 小时 CTR +42%。置信度:高。",
    metric: "CTR", from: 1.4, to: 2.0, delta: 42,
    actionLabel: "View iteration history", actionLabelZh: "查看迭代历史",
    minutesAgo: 720,
  },
  {
    id: "alrt-12", severity: "warn", adId: "ad-08", adCode: "ECOM-DR",
    title: "ROAS slipped below 1.0 — losing money",
    titleZh: "ROAS 跌破 1.0 —— 在亏钱",
    body: "ROAS at 0.84 over last 24h. Auction efficiency dropped after a competitor entered the same audience.",
    bodyZh: "过去 24 小时 ROAS 只有 0.84。一个竞品也开始投同一波受众之后,竞价效率掉下来了。",
    metric: "ROAS", from: 1.32, to: 0.84, delta: -36,
    actionLabel: "Pause in Radar", actionLabelZh: "在 Radar 中暂停",
    minutesAgo: 60,
  },
];

// === AI Playground — multi-demo presets ===
const PLAYGROUND_DEMOS = [
  {
    id: "demo-coffee", title: "Cold-brew · Gen-Z · summer",
    titleZh: "冷萃咖啡 · Gen-Z · 夏季",
    promptEn: "Lifestyle ad for a freeze-dried coffee subscription. Target Gen-Z urban professionals 22-30. Tone: confident, slightly ironic, sustainability-aware.",
    promptZh: "冻干咖啡订阅服务的生活方式广告。目标用户:22-30 岁 Gen-Z 都市白领。基调:自信、略带反讽、有环保意识。",
    style: "Warm orange palette · editorial photography",
    styleZh: "暖橙色调 · 编辑感摄影",
    variants: [
      { name: "Morning shortcut", desc: "Hand grinder vs. our packet, 3sec brew comparison", delta: 28 },
      { name: "Climate proof", desc: "Coffee in a backpack — outdoor lifestyle pivot", delta: 41 },
      { name: "Subscription math", desc: "$2/cup vs $6 cafe — typographic explainer", delta: 19 },
      { name: "Studio still", desc: "Product hero on warm beige — minimal copy", delta: 12 },
    ],
  },
  {
    id: "demo-classic", title: "True Classic · 30-45 men · premium",
    titleZh: "True Classic · 30-45 岁男性 · 轻奢",
    promptEn: "Tee-shirt ad for True Classic. Target professional men 30-45 who want fitted basics. Tone: understated, confident, no irony.",
    promptZh: "True Classic 修身基础款 T 恤广告。目标用户:30-45 岁追求剪裁基础款的职业男性。基调:克制、自信、不带反讽。",
    style: "Slate gray palette · documentary photography",
    styleZh: "石板灰色调 · 纪实风格摄影",
    variants: [
      { name: "Fit shot", desc: "Side-by-side fit comparison with H&M / Uniqlo", delta: 34 },
      { name: "Wardrobe set", desc: "5-pack flat-lay, monochrome", delta: 22 },
      { name: "Real customer", desc: "User-generated style — Aaron from Boston", delta: 17 },
      { name: "Material macro", desc: "Cotton-modal close-up, texture-led", delta: 9 },
    ],
  },
  {
    id: "demo-vestigial", title: "Vestigial Foods · eco-conscious · plant",
    titleZh: "Vestigial Foods · 环保人群 · 植物基",
    promptEn: "Plant-based dinner kit ad. Target millennial families who care about sustainability but want fast weeknight dinners. Tone: warm, honest, no greenwashing.",
    promptZh: "植物基晚餐套餐广告。目标用户:关心可持续但工作日想快速做饭的千禧一代家庭。基调:温暖、诚实、不绑架环保。",
    style: "Sage + cream palette · soft daylight",
    styleZh: "鼠尾草绿 + 奶白调 · 柔和自然光",
    variants: [
      { name: "Tuesday after work", desc: "Mom + kid plating in 8 minutes — story moment", delta: 36 },
      { name: "Carbon math", desc: "1 kit = 4 trees worth — typographic infographic", delta: 24 },
      { name: "Behind the farm", desc: "Supplier portrait — 3 farmers, name + crop", delta: 18 },
      { name: "Box on table", desc: "Studio still — minimal, focused on contents", delta: 11 },
    ],
  },
  {
    id: "demo-holm", title: "Holm Bros · DIY · weekend",
    titleZh: "Holm Bros 工具 · DIY · 周末项目",
    promptEn: "Cordless drill ad for Holm Bros. Target homeowners 35-55 who do weekend DIY but aren't pros. Tone: capable, no condescension, project-led.",
    promptZh: "Holm Bros 无线电钻广告。目标用户:35-55 岁周末 DIY 但非专业的房主。基调:能干、不居高临下、以项目为导向。",
    style: "Workshop tones · raw wood + steel",
    styleZh: "工坊感色调 · 原木 + 钢铁",
    variants: [
      { name: "Saturday shelves", desc: "Mid-project hands shot — sawdust + drill in use", delta: 38 },
      { name: "Spec comparison", desc: "Torque + battery vs Ryobi / DeWalt, table format", delta: 21 },
      { name: "Father / kid", desc: "First project — generational angle, warm narrative", delta: 26 },
      { name: "Tool in hand", desc: "Studio macro — texture, scale, grip detail", delta: 14 },
    ],
  },
  {
    id: "demo-athletic", title: "FastFoot Apparel · runners 30-45",
    titleZh: "FastFoot 跑步装备 · 30-45 岁跑者",
    promptEn: "Running shorts ad for FastFoot. Target serious recreational runners 30-45 — half-marathon distance, 3-4x weekly. Tone: practical, performance-led, no hype.",
    promptZh: "FastFoot 跑步短裤广告。目标用户:30-45 岁、半马水平、每周跑 3-4 次的资深业余跑者。基调:实用、性能导向、不浮夸。",
    style: "Cool slate palette · golden-hour outdoor",
    styleZh: "冷石板调 · 黄金时刻户外光",
    variants: [
      { name: "5am road", desc: "Solo runner at sunrise — quiet committed energy", delta: 31 },
      { name: "Fabric tech", desc: "Sweat-wicking macro with thread-count callouts", delta: 18 },
      { name: "Race day kit", desc: "Flat-lay of full kit, bib + watch + shorts", delta: 23 },
      { name: "Athlete portrait", desc: "Real masters runner mid-stride, hero-shot", delta: 15 },
    ],
  },
  {
    id: "demo-serum", title: "Lumen · skincare-curious millennials",
    titleZh: "Lumen 护肤精华 · 入门级千禧一代",
    promptEn: "Vitamin C serum ad for Lumen. Target millennials 28-40 entering more serious skincare, post-acne era. Tone: knowledgeable but not clinical, beauty without intimidation.",
    promptZh: "Lumen 维 C 精华广告。目标用户:28-40 岁刚开始认真护肤、痘痘期已过的千禧一代。基调:专业但不冷感、美感不带压迫。",
    style: "Champagne + glass palette · backlit product",
    styleZh: "香槟金 + 玻璃质感 · 背光产品摄影",
    variants: [
      { name: "Bottle on linen", desc: "Editorial still — soft fabric, golden light", delta: 27 },
      { name: "Routine sequence", desc: "Step 1 → 2 → 3, typographic timeline", delta: 19 },
      { name: "Before / 4 weeks", desc: "Honest comparison with explicit timeline", delta: 33 },
      { name: "Hand application", desc: "Macro of drop landing on skin, sensory cue", delta: 16 },
    ],
  },
];

// === Image Ads — standalone gen projects (post-Move 10, Radar iterations live elsewhere) ===
// source: "clone-s" | "it-rid" | "playground"
const IMAGE_AD_PROJECTS = [
  {
    id: "proj-1", source: "clone-s", title: "True Classic · summer mailers",
    titleZh: "True Classic · 夏季 mailer",
    brand: "True Classic",
    description: "Catalog reshoot — 8 SKUs, lifestyle + flat-lay sets for July promo.",
    descriptionZh: "目录重拍 —— 8 个 SKU,生活方式 + 平铺组合,用于 7 月活动。",
    createdAt: "2 hours ago", createdAtZh: "2 小时前",
    variants: 12,
  },
  {
    id: "proj-2", source: "it-rid", title: "Vestigial Foods · packaging refresh",
    titleZh: "Vestigial Foods · 包装焕新",
    brand: "Vestigial Foods",
    description: "Image-to-Image refinement on 3 hero shots — softer light, less saturation.",
    descriptionZh: "对 3 张主图做图生图微调 —— 更柔和的光、降低饱和度。",
    createdAt: "Yesterday", createdAtZh: "昨天",
    variants: 9,
  },
  {
    id: "proj-3", source: "playground", title: "Cold-brew · summer wave 02",
    titleZh: "冷萃咖啡 · 夏季 wave 02",
    brand: "Lipsum Brand",
    description: "Free-form prompt experiments — testing climate-conscious angles.",
    descriptionZh: "自由 prompt 实验 —— 测试环保叙事的角度。",
    createdAt: "2 days ago", createdAtZh: "2 天前",
    variants: 6,
  },
  {
    id: "proj-4", source: "clone-s", title: "Holm Bros · holiday lookbook",
    titleZh: "Holm Bros · 节日 lookbook",
    brand: "Holm Bros",
    description: "Father's-Day-adjacent angle, indoor workshop scenes, 6 SKUs.",
    descriptionZh: "父亲节相关角度,室内工坊场景,6 个 SKU。",
    createdAt: "4 days ago", createdAtZh: "4 天前",
    variants: 8,
  },
  {
    id: "proj-5", source: "playground", title: "FastFoot · fall trail capsule",
    titleZh: "FastFoot · 秋季越野系列",
    brand: "FastFoot Apparel",
    description: "Mood-board exploration — terrain × time-of-day × fabric.",
    descriptionZh: "情绪板探索 —— 地形 × 时间 × 面料组合。",
    createdAt: "1 week ago", createdAtZh: "1 周前",
    variants: 10,
  },
];

// === Brands list ===
const BRANDS = [
  {
    id: "lipsum", name: "Lipsum Brand", subline: "SATURNBIRD freeze-dried coffee",
    sublineZh: "SATURNBIRD 冻干咖啡",
    logo: "L", primary: "#D14A1F",
    activeAds: 15, iterations: 4, spend: "$18,362",
    active: true,
  },
  {
    id: "trueclassic", name: "True Classic", subline: "Modern fitted basics for men",
    sublineZh: "现代修身基础款男装",
    logo: "T", primary: "#2A5FD1",
    activeAds: 22, iterations: 7, spend: "$31,840",
  },
  {
    id: "vestigial", name: "Vestigial Foods", subline: "Plant-based weeknight dinners",
    sublineZh: "植物基工作日晚餐",
    logo: "V", primary: "#3D7A4F",
    activeAds: 9, iterations: 3, spend: "$11,205",
  },
  {
    id: "holm", name: "Holm Bros", subline: "Cordless tools for weekend DIY",
    sublineZh: "面向周末 DIY 的无线电动工具",
    logo: "H", primary: "#8B5A2B",
    activeAds: 14, iterations: 2, spend: "$22,710",
  },
];

function relTimeFromMinutes(min) {
  if (min < 60) return min + "m ago";
  if (min < 60 * 24) return Math.floor(min / 60) + "h ago";
  return Math.floor(min / (60 * 24)) + "d ago";
}

Object.assign(window, {
  ADS, BRAND, INITIAL_TASKS, INITIAL_ITERATIONS,
  REC_TEMPLATES, VARIANT_NAMES, PERSONAS, radarTabs,
  PULSE_ALERTS, PLAYGROUND_DEMOS, IMAGE_AD_PROJECTS, BRANDS,
  relTimeFromMinutes,
});
