// ====================================================================
// MOCK DATA — fase 1 (vibe coding).  SHAPE CONGELADO desde el día 1:
// cada mención = { id, source, platform, author, reach, excerpt{es,zh},
//                  topic, sentiment, severity, actionable, sourceType, link }
// En fase 2 la API (Exa/Apify/Tavily + Claude) devuelve EXACTAMENTE esto.
// → conectar datos reales = cambiar `MOCK` por `await fetch('/api/...')`.
// ====================================================================

// ---- Plataformas: color + iniciales del ícono ----
const PLATFORMS = {
  reddit:   { label: "Reddit",      color: "#FF4500", abbr: "Re" },
  x:        { label: "X",           color: "#1A1A1A", abbr: "X" },
  facebook: { label: "Facebook",    color: "#1877F2", abbr: "Fb" },
  playstore:{ label: "Play Store",  color: "#0F9D58", abbr: "Pl", glyph: "gplay" },
  appstore: { label: "App Store",   color: "#0A84FF", abbr: "As", glyph: "apple" },
  press:    { label: "Prensa",      color: "#8A5BD6", abbr: "Pr" },
  tiktok:   { label: "TikTok",      color: "#25F4EE", abbr: "Tk" },
};

// ---- Capas de ingesta (no se exponen las herramientas, solo la función) ----
// Las menciones no siempre tienen datos de cada red, pero sí de cada capa.
const SOURCE_LAYERS = {
  reddit: 'comunidades', x: 'comunidades', facebook: 'comunidades', tiktok: 'comunidades',
  playstore: 'resenas', appstore: 'resenas',
  press: 'prensa', news: 'prensa', regulator: 'prensa',
};
// Para el heatmap: columnas por capa (no por red individual)
const HEAT_COLS = {
  comunidades: { label: "Foros & Redes",    glyph: null },
  playstore:   { label: "Play Store",       glyph: "gplay" },
  appstore:    { label: "App Store",        glyph: "apple" },
  prensa:      { label: "Prensa & Reg.",    glyph: null },
};

const TOPIC_KEYS = {
  cobranza: "topic_cobranza", tasas: "topic_tasas", china: "topic_china",
  ia: "topic_ia", fraude: "topic_fraude", servicio: "topic_servicio",
};

// ---- Menciones (stream) ----
const MENTIONS = [
  { id:"m1", platform:"reddit", author:"u/finanzas_mx_real", handle:"r/MexicoFinanciero",
    reach:48200, topic:"cobranza", sentiment:"neg", severity:91, actionable:false, sourceType:"social",
    link:"reddit.com/r/MexicoFinanciero/…",
    excerpt:{ es:"Otra app de préstamos china que <hl>accede a tus contactos</hl> y los amenaza si te atrasas un día. ¿Crece es de las mismas?",
              zh:"又一款中国贷款 App，<hl>读取你的通讯录</hl>，逾期一天就威胁亲友。Crece 是不是也这样？" } },
  { id:"m2", platform:"playstore", author:"María G.", handle:"★ 1.0",
    reach:12400, topic:"cobranza", sentiment:"neg", severity:78, actionable:true, sourceType:"own_channel",
    link:"play.google.com/store/apps/details?id=crece…",
    excerpt:{ es:"Me llamaron <hl>17 veces en un día</hl> por un retraso de 48 h. Bajen el tono o cancelo.",
              zh:"仅逾期 48 小时，一天内给我打了 <hl>17 通电话</hl>。请收敛，否则我注销。" } },
  { id:"m3", platform:"x", author:"@CondusefMX", handle:"Oficial",
    reach:310000, topic:"servicio", sentiment:"neu", severity:40, actionable:false, sourceType:"press",
    link:"x.com/CondusefMX/status/…",
    excerpt:{ es:"Recuerda: una SOFOM regulada nunca te pedirá acceso a tu lista de contactos. Verifica en el SIPRES.",
              zh:"提醒：受监管的 SOFOM 绝不会索取你的通讯录权限。请在 SIPRES 核实。" } },
  { id:"m4", platform:"press", author:"Reforma", handle:"Negocios",
    reach:520000, topic:"china", sentiment:"neu", severity:55, actionable:false, sourceType:"press",
    link:"reforma.com/fintech-asiaticas-mexico…",
    excerpt:{ es:"Fintechs de capital asiático crecen en México; reguladores observan prácticas de <hl>cobranza y datos</hl>.",
              zh:"亚洲资本金融科技在墨西哥扩张；监管机构正关注其<hl>催收与数据</hl>做法。" } },
  { id:"m5", platform:"reddit", author:"u/prestamo_victima", handle:"r/Mexico",
    reach:67000, topic:"cobranza", sentiment:"neg", severity:88, actionable:false, sourceType:"social",
    link:"reddit.com/r/Mexico/…",
    excerpt:{ es:"iPeso y MaxCrédito te <hl>difaman con tu familia</hl>. Cuidado con todas las apps chinas, incluida Crece.",
              zh:"iPeso 和 MaxCrédito 会<hl>向你家人散布污蔑</hl>。所有中国 App 都要当心，包括 Crece。" } },
  { id:"m6", platform:"facebook", author:"Víctimas de Apps Gota a Gota", handle:"Grupo · 42k",
    reach:42000, topic:"cobranza", sentiment:"neg", severity:84, actionable:false, sourceType:"social",
    link:"facebook.com/groups/victimasapps…",
    excerpt:{ es:"Lista negra de apps que <hl>amenazan</hl>: aporten capturas. Empecemos por las de cobranza extorsiva.",
              zh:"威胁催收 App 黑名单：请大家上传截图，从暴力催收的开始整理。" } },
  { id:"m7", platform:"playstore", author:"Carlos R.", handle:"★ 5.0",
    reach:8900, topic:"servicio", sentiment:"pos", severity:18, actionable:true, sourceType:"own_channel",
    link:"play.google.com/store/apps/details?id=crece…",
    excerpt:{ es:"Crece me dio crédito en minutos y el trato fue claro. La mejor de las que he probado.",
              zh:"Crece 几分钟就放款，条款清晰。是我用过最好的一款。" } },
  { id:"m8", platform:"x", author:"@montadeudas_no", handle:"Activista",
    reach:94000, topic:"china", sentiment:"neg", severity:72, actionable:false, sourceType:"social",
    link:"x.com/montadeudas_no/status/…",
    excerpt:{ es:"Hilo: cómo identificar una app de <hl>'montadeudas'</hl> de origen chino antes de pedir un peso.",
              zh:"长帖：在借第一分钱之前，如何识别中国背景的<hl>「高利贷」</hl> App。" } },
  { id:"m9", platform:"press", author:"El Universal", handle:"Cartera",
    reach:410000, topic:"tasas", sentiment:"neu", severity:46, actionable:false, sourceType:"press",
    link:"eluniversal.com.mx/cartera/cat-fintech…",
    excerpt:{ es:"CAT de apps de crédito rápido supera el 300%; expertos piden transparencia a las fintech.",
              zh:"快贷 App 年化成本(CAT)超 300%；专家呼吁金融科技提高透明度。" } },
  { id:"m10", platform:"tiktok", author:"@tipsdedinero", handle:"230k seguidores",
    reach:180000, topic:"ia", sentiment:"neu", severity:38, actionable:false, sourceType:"social",
    link:"tiktok.com/@tipsdedinero/video/…",
    excerpt:{ es:"¿La IA decide tu préstamo? Cómo funcionan los <hl>agentes de crédito</hl> de estas apps.",
              zh:"AI 决定你的贷款额度？解析这些 App 的<hl>信贷智能体</hl>如何运作。" } },
  { id:"m11", platform:"reddit", author:"u/dev_anon", handle:"r/programacion",
    reach:21000, topic:"ia", sentiment:"pos", severity:22, actionable:false, sourceType:"social",
    link:"reddit.com/r/programacion/…",
    excerpt:{ es:"El credit AI agent de QFIN es técnicamente sólido; el problema es la cobranza, no el modelo.",
              zh:"QFIN 的信贷 AI 智能体技术上很扎实；问题在催收，不在模型。" } },
  { id:"m12", platform:"facebook", author:"Milenio", handle:"Página oficial",
    reach:280000, topic:"servicio", sentiment:"pos", severity:20, actionable:false, sourceType:"press",
    link:"facebook.com/Milenio/posts…",
    excerpt:{ es:"Crece anuncia programa de educación financiera con la CONDUSEF para usuarios primerizos.",
              zh:"Crece 宣布与 CONDUSEF 合作，面向首次借款人推出金融教育计划。" } },
  { id:"m13", platform:"x", author:"@usuaria_cdmx", handle:"",
    reach:5400, topic:"fraude", sentiment:"neg", severity:64, actionable:false, sourceType:"social",
    link:"x.com/usuaria_cdmx/status/…",
    excerpt:{ es:"Me llegó un SMS de 'Crece' pidiendo datos. ¿Es <hl>phishing</hl>? Ojo con los clones.",
              zh:"我收到一条自称「Crece」的短信索要资料。是<hl>钓鱼</hl>吗？小心仿冒。" } },
  { id:"m14", platform:"playstore", author:"Jorge M.", handle:"★ 2.0",
    reach:7600, topic:"tasas", sentiment:"neg", severity:52, actionable:true, sourceType:"own_channel",
    link:"play.google.com/store/apps/details?id=crece…",
    excerpt:{ es:"Las comisiones no estaban claras al contratar. Mejoren la transparencia del CAT.",
              zh:"签约时手续费不清楚。请提高 CAT 的透明度。" } },
];

// Programmatic generation of 50 Qcrece reviews in May 2026 for consistency with the backend seed
(function() {
  const QCRECE_TEMPLATES = [
    { score: 5, text: "Excelente aplicación, me autorizaron el crédito de inmediato y el depósito tardó menos de 5 minutos. Muy recomendable.", text_zh: "优秀的应用程序，立即批准了我的贷款，到账时间不到 5 分钟。非常推荐。" },
    { score: 5, text: "Muy fácil de usar, los términos son claros y no hay cargos ocultos. Es la mejor app de préstamos en México.", text_zh: "非常容易使用，条款清晰，没有隐藏费用。是墨西哥最好的贷款应用。" },
    { score: 5, text: "Es mi tercer préstamo con Qcrece y siempre cumplen. Si pagas a tiempo te van subiendo el límite.", text_zh: "这是我在 Qcrece 的第三次贷款，他们总是很讲信用。如果你按时还款，额度会不断提高。" },
    { score: 5, text: "Me salvó de una emergencia médica. El trámite es 100% digital y sin papeleo. Excelente servicio.", text_zh: "它在医疗紧急情况下救了我。流程 100% 数字化，无需繁琐手续。优质服务。" },
    { score: 4, text: "Buen servicio y rapidez, lo único malo es que la tasa de interés es un poco alta. Pero vale la pena por la velocidad.", text_zh: "服务好，速度快，唯一不好的是利率有点高。但为了速度是值得的。" },
    { score: 4, text: "La interfaz es muy intuitiva. Me gustaría que dieran más días para el primer pago, pero en general todo bien.", text_zh: "界面非常直观。希望首期还款能多给几天时间，但总体来说很不错。" },
    { score: 3, text: "Es aceptable, los intereses son elevados comparado con un banco, pero te saca del apuro si no tienes historial.", text_zh: "还可以，与银行相比利率较高，但如果你没有信用历史，它可以帮你解决燃眉之急。" },
    { score: 3, text: "La app funciona bien, pero tardó varias horas en reflejarse mi pago de OXXO. Tuve que mandar comprobante a soporte.", text_zh: "应用运行良好，但我的 OXXO 还款花了几个小时才在系统里显示。我不得不向客服发送付款凭证。" },
    { score: 2, text: "Tengo problemas para iniciar sesión desde la última actualización, se queda la pantalla en blanco. Solucionen por favor.", text_zh: "自上次更新以来，我登录时遇到问题，屏幕一直是白色的。请解决。" },
    { score: 1, text: "Me están llamando asesores cobrándome dos días antes de mi fecha límite. Es muy molesto el acoso telefónico.", text_zh: "催收员在截止日期前两天就给我打电话催收。电话骚扰太烦人了。" },
    { score: 1, text: "El interés que cobran es excesivo y cuando intentas comunicarte con soporte nadie te responde. Pésima experiencia.", text_zh: "收取的利息过高，尝试联系客服时没人回复。体验极差。" },
  ];

  const SPANISH_NAMES = [
    "Alejandro Gómez", "Sofía Rodríguez", "Mateo Fernández", "Valentina López", "Santiago Martínez",
    "Isabella González", "Sebastian Pérez", "Camila Sanchez", "Leonardo Romero", "Mariana Torres",
    "Diego Ruiz", "Lucía Díaz", "Daniel Morales", "Valeria Ortiz", "Nicolás Castro",
    "Gabriela Silva", "Samuel Flores", "Andrea Mendoza", "Ángel Castillo", "Jimena Morales",
    "Javier Reyes", "Paola Gutiérrez", "Felipe Ruiz", "Daniela Vega", "Andrés Delgado"
  ];

  for (let i = 1; i <= 50; i++) {
    const templateIndex = (i * 7) % QCRECE_TEMPLATES.length;
    const template = QCRECE_TEMPLATES[templateIndex];
    const authorIndex = (i * 3) % SPANISH_NAMES.length;
    const author = SPANISH_NAMES[authorIndex] + " " + String.fromCharCode(65 + (i % 26)) + ".";
    
    const day = 1 + ((i * 13) % 28);
    const dayStr = String(day).padStart(2, '0');
    
    const hasReply = i % 5 !== 0; // 80% reply rate
    let replyTextEs = "";
    let replyTextZh = "";
    if (template.score >= 4) {
      replyTextEs = `¡Hola ${SPANISH_NAMES[authorIndex]}! Muchas gracias por tu confianza. Nos alegra saber que te ayudamos en tu financiamiento. Seguimos trabajando para darte el mejor servicio.`;
      replyTextZh = `您好 ${SPANISH_NAMES[authorIndex]}！非常感谢您的信任。我们很高兴能为您提供资金支持。我们将继续努力为您提供最优质的服务。`;
    } else if (template.score === 3) {
      replyTextEs = `Hola ${SPANISH_NAMES[authorIndex]}. Agradecemos tus comentarios. Tomamos en cuenta tu sugerencia sobre los plazos y comisiones para nuestras futuras actualizaciones de producto.`;
      replyTextZh = `您好 ${SPANISH_NAMES[authorIndex]}。感谢您的反馈。在未来的产品更新中，我们会考虑您关于期限和手续费的建议。`;
    } else {
      replyTextEs = `Lamentamos los inconvenientes con el servicio, ${SPANISH_NAMES[authorIndex]}. Por favor comunícate a nuestro canal oficial soporte@qcrece.com para revisar tu cuenta de inmediato y darte una solución.`;
      replyTextZh = `非常抱歉给您带来不便，${SPANISH_NAMES[authorIndex]}。请通过我们的官方渠道 soporte@qcrece.com 与我们联系，以便我们立即核查您的账户并为您提供解决方案。`;
    }

    const sentiment = template.score >= 4 ? 'pos' : template.score === 3 ? 'neu' : 'neg';
    const severity = template.score === 1 ? 75 : template.score === 2 ? 40 : 10;
    
    MENTIONS.push({
      id: `qcr-${1000 + i}`,
      platform: "playstore",
      author,
      handle: `★ ${template.score.toFixed(1)}`,
      reach: 0,
      topic: template.score <= 2 ? 'cobranza' : 'servicio',
      sentiment,
      severity,
      actionable: template.score <= 2,
      sourceType: template.score <= 2 ? 'own_channel' : 'social',
      link: `https://play.google.com/store/apps/details?id=com.quieroya.prestamo.loan.cash.credit.mx`,
      excerpt: { es: template.text, zh: template.text_zh },
      entity: "crece",
      publishedAt: `2026-05-${dayStr}T12:00:00.000Z`,
      replyText: hasReply ? { es: replyTextEs, zh: replyTextZh } : null,
      replyDate: hasReply ? `2026-05-${dayStr}T16:30:00.000Z` : null
    });
  }
})();

// ---- Serie de sentimiento 30 días (apilado pos/neu/neg, suman ~menciones/día) ----
const SENTIMENT_SERIES = (() => {
  const arr = [];
  for (let i = 29; i >= 0; i--) {
    const base = 60 + Math.round(Math.sin(i / 4) * 14);
    // brote negativo en los últimos 6 días
    const spike = i < 6 ? (6 - i) * 7 : 0;
    const neg = 18 + Math.round(Math.abs(Math.sin(i / 3)) * 10) + spike;
    const pos = Math.max(14, base - neg + Math.round(Math.cos(i / 5) * 8));
    const neu = Math.max(10, Math.round(base * 0.5));
    arr.push({ d: i, pos, neu, neg });
  }
  return arr;
})();

// ---- KPIs (home) ----
const KPIS = {
  risk:    { value: 68, unit: "/100", trend: +9, dir: "up", level: "high", spark: [42,45,44,49,53,58,61,64,68] },
  contam:  { value: 54, unit: "%", trend: +12, dir: "up", level: "medium", spark: [30,33,35,38,41,46,49,52,54] },
  mentions:{ value: 1284, unit: "", trend: +31, dir: "up", level: "", spark: [620,680,710,790,840,910,1010,1150,1284] },
  alerts:  { value: 3, unit: "", trend: +2, dir: "up", level: "high", spark: [0,1,1,1,2,2,2,3,3] },
};

// ---- Competidores ----
const COMP_KOSHER = [
  { name:"Kueski",   sov:21, sentiment:"pos", note:"benchmark", color:"#7B2FF7", downloads: { playstore: 10000000, appstore: 605880 } },
  { name:"Crece",    sov:14, sentiment:"neu", note:"you",       color:"#14C46A", downloads: { playstore: 450000, appstore: 50000 } },
  { name:"Klar",     sov:13, sentiment:"pos", note:"",          color:"#2A6FDB", downloads: { playstore: 10000000, appstore: 3589920 } },
  { name:"Stori",    sov:11, sentiment:"pos", note:"",          color:"#E0533D", downloads: { playstore: 10000000, appstore: 23081760 } },
  { name:"Tala",     sov:8,  sentiment:"pos", note:"",          color:"#1F9D77", downloads: { playstore: 10000000, appstore: 800000 } },
  { name:"Kubo",     sov:6,  sentiment:"pos", note:"",          color:"#F2A30F", downloads: { playstore: 1000000, appstore: 221040 } },
  { name:"MoneyMan", sov:5,  sentiment:"neu", note:"",          color:"#2BB0A6", downloads: { playstore: 1000000, appstore: 1538160 } },
  { name:"Creditea", sov:4,  sentiment:"neu", note:"",          color:"#3FB6C9", downloads: { playstore: 1000000, appstore: 733080 } },
  { name:"AvaFin",   sov:3,  sentiment:"neu", note:"",          color:"#5EABD6", downloads: { playstore: 1000000, appstore: 50000 } },
];
const COMP_AZTLAN = [
  { name:"iPeso",             sov:9, complaints:1240, color:"#C8412F", downloads: { playstore: 1000000, appstore: 100000 } },
  { name:"DiDi Préstamos",    sov:7, complaints:890,  color:"#E85D00", downloads: { playstore: 10000000, appstore: 1000000 } },
  { name:"MaxCrédito",        sov:6, complaints:980,  color:"#A8331F", downloads: { playstore: 500000, appstore: 50000 } },
  { name:"MexaCash/XFectivo", sov:4, complaints:760,  color:"#D45A2A", downloads: { playstore: 250000, appstore: 25000 } },
  { name:"Fintopia",          sov:3, complaints:610,  color:"#8A2417", downloads: { playstore: 10000000, appstore: 1000000 } },
  { name:"MexDin",            sov:3, complaints:480,  color:"#B84A2A", downloads: { playstore: 5000000, appstore: 3228720 } },
];

// ---- Heatmap cobranza: cols = capas (no redes individuales — la info no siempre existe por red) ----
// Columnas: Foros & Redes (reddit/x/fb agregados) | Play Store | App Store | Prensa & Reg.
// -1 = sin datos para esa capa/plataforma (celda atenuada con "—")
// Todas las 15 entidades monitoreadas: crece + 8 kosher + 6 controvertidas
// App Store -1: Tala, AvaFin, Fintopia, iPeso, DiDi, MexaCash no tienen App Store MX confirmada
const HEAT_PLATFORMS = ["comunidades", "playstore", "appstore", "prensa"];
const HEAT_ROWS = [
  // ── Crece (self) ────────────────────────────────────────────────────────
  { name:"Crece",              v:[ 38,  44,  -1,  25] },
  // ── Club Kosher (regulados, benchmark) ──────────────────────────────────
  { name:"Kueski",             v:[ 18,  26,  20,  15] },
  { name:"Klar",               v:[  8,  14,  12,   8] },
  { name:"Stori",              v:[ 12,  20,  18,  10] },
  { name:"Tala",               v:[ 15,  22,  -1,  12] },
  { name:"Kubo",               v:[ 10,  18,  14,   6] },
  { name:"MoneyMan",           v:[ 20,  24,  22,  16] },
  { name:"Creditea",           v:[ 14,  16,  12,   8] },
  { name:"AvaFin",             v:[  8,  10,  -1,   6] },
  // ── Clúster Controvertido (montadeudas/SpyLoan) ──────────────────────────
  { name:"iPeso",              v:[ 88,  92,  -1,  40] },
  { name:"DiDi Préstamos",     v:[ 65,  78,  -1,  55] },
  { name:"MaxCrédito",         v:[ 82,  86,  78,  32] },
  { name:"MexaCash/XFectivo",  v:[ 74,  81,  -1,  22] },
  { name:"Fintopia",           v:[ 69,  72,  -1,  48] },
  { name:"MexDin",             v:[ 55,  68,  48,  18] },
];

// ---- Quejas crudas (cobranza) ----
const RAW_COMPLAINTS = [
  { id:"c1", platform:"reddit", reach:48200, severity:91, aiClass:{es:"Acceso a contactos + amenaza",zh:"读取通讯录 + 威胁"},
    text:{es:"«Tienen los números de toda mi familia y los amenazan.»", zh:"「他们有我全家的电话，并以此威胁。」"} },
  { id:"c2", platform:"playstore", reach:12400, severity:78, aiClass:{es:"Acoso telefónico",zh:"电话骚扰"},
    text:{es:"«Me llaman 17 veces al día, hasta a las 6am.»", zh:"「一天打 17 通电话，早上 6 点都打。」"} },
  { id:"c3", platform:"facebook", reach:42000, severity:84, aiClass:{es:"Difamación a terceros",zh:"向第三方诽谤"},
    text:{es:"«Le escribieron a mi jefe diciendo que soy un fraude.»", zh:"「他们给我老板发消息说我是骗子。」"} },
  { id:"c4", platform:"x", reach:94000, severity:72, aiClass:{es:"Lenguaje intimidatorio",zh:"恐吓性言语"},
    text:{es:"«Mensajes con 'vamos por ti' y fotos de mi casa.»", zh:"「收到『我们会找上你』的消息和我家照片。」"} },
];

// ---- Narrativas (timeline temas, vol + tono) ----
const NARRATIVES = [
  { topic:"cobranza", vol:[20,24,30,38,52,71,88], tone:"neg" },
  { topic:"china",    vol:[12,18,22,29,41,55,62], tone:"neg" },
  { topic:"tasas",    vol:[30,28,32,35,40,44,47], tone:"neu" },
  { topic:"ia",       vol:[8,11,14,20,26,30,38],  tone:"neu" },
  { topic:"servicio", vol:[18,22,20,24,28,31,34], tone:"pos" },
  { topic:"fraude",   vol:[5,6,9,11,14,18,24],    tone:"neg" },
];
const NARR_MONTHS = ["Feb","Mar","Abr","May","Ene","Abr","Hoy"];

// ---- Alertas ----
const ALERTS = [
  { id:"a1", level:"crisis", topic:"cobranza", velocity:96, since:"38 min", spark:[2,3,3,5,8,13,21,34,52],
    title:{es:"Hilo viral en Reddit asocia a Crece con 'montadeudas chinos'",
           zh:"Reddit 热帖将 Crece 与「中国高利贷」关联"},
    desc:{es:"Un post con 48k de alcance acusa acceso a contactos. Sin respuesta oficial aún.",
          zh:"一条覆盖 4.8 万的帖子指控读取通讯录，目前尚无官方回应。"},
    threshold:{es:"> 50 menc/h sobre 'cobranza'", zh:"「催收」话题 > 50 提及/小时"} },
  { id:"a2", level:"crisis", topic:"china", velocity:71, since:"2 h", spark:[4,5,6,8,11,15,19,24,29],
    title:{es:"Activista lanza hilo 'cómo identificar montadeudas chinos'",
           zh:"活动人士发起「如何识别中国高利贷」长帖"},
    desc:{es:"94k de alcance. Menciona apps chinas en bloque; Crece aparece por asociación.",
          zh:"覆盖 9.4 万。整体点名中国 App，Crece 因关联被波及。"},
    threshold:{es:"Pico de contaminación de categoría", zh:"品类污染度峰值"} },
  { id:"a3", level:"warn", topic:"fraude", velocity:44, since:"5 h", spark:[1,1,2,2,3,4,6,8,11],
    title:{es:"Reportes de SMS de phishing suplantando a 'Crece'",
           zh:"出现冒充「Crece」的钓鱼短信报告"},
    desc:{es:"Varios usuarios reportan clones. Oportunidad de comunicado de seguridad.",
          zh:"多名用户报告仿冒。可发布安全提示公告。"},
    threshold:{es:"Nuevo patrón detectado", zh:"检测到新模式"} },
];

window.PLATFORMS = PLATFORMS;
window.SOURCE_LAYERS = SOURCE_LAYERS;
window.HEAT_COLS = HEAT_COLS;
window.TOPIC_KEYS = TOPIC_KEYS;
window.MOCK = {
  MENTIONS, SENTIMENT_SERIES, KPIS, COMP_KOSHER, COMP_AZTLAN,
  HEAT_PLATFORMS, HEAT_ROWS, RAW_COMPLAINTS, NARRATIVES, NARR_MONTHS, ALERTS,
  // Periodo del snapshot (fallback mock); en vivo lo sobreescribe api.jsx desde los datos.
  PERIOD: { month: '2026-05', labelEs: 'Mayo 2026', labelZh: '2026年5月', days: 31 },
};
