// ═════════════════════════════════════════════════════════════════════════════
// MindForge · Layer 1 · core/data.jsx
// ─────────────────────────────────────────────────────────────────────────────
// Role     : Bootstrap layer — design tokens, base CSS, default dataset, tiny
//            shared helpers (rand, shuffle, norm, save/load), placeholder bg.
// Loaded   : #1 (first script). Nothing depends on later modules.
// Reads    : nothing from window (no upstream MindForge module).
// Exposes  : window.{ MF, DECK_TKD, rand, shuffle, pickN, pickOtherN, norm,
//            answerMatches, comboMult, loadSave, writeSave, cardPlaceholderBg }
// See also : docs/ARCHITECTURE.md §"Layered module map"
//            docs/DATA-MODEL.md §"Built-in Taekwondo dataset"
// ═════════════════════════════════════════════════════════════════════════════
//
// This file does three things on purpose, in this order:
//   1. Injects the global stylesheet + Google Fonts link (idempotent: checks
//      for #mf-styles before re-injecting).
//   2. Defines the `MF` design-token object (colors, fonts, animations).
//   3. Ships the canonical demo dataset (`DECK_TKD`) + math helpers used by
//      every other layer (XP combo curve, fuzzy answer match, persistence).
//
// MindForge — data, theme & helpers (legacy header preserved below)

// ─── Theme tokens (dark, calm SaaS w/ subtle gamification) ───
const MF = {
  bg:        '#0e0d12',
  bg2:       '#15131c',
  card:      '#1a1824',
  card2:     '#221f2e',
  line:      '#2a2735',
  line2:     '#363345',
  text:      '#ece9f5',
  textDim:   '#a39fb5',
  textMute:  '#6c6880',
  purple:    '#a78bfa',
  purpleDim: '#7c5cf5',
  blue:      '#7fb4ff',
  blueDim:   '#4d8eff',
  good:      '#74d8a1',
  goodDim:   '#3fae74',
  bad:       '#f48a8a',
  badDim:    '#d65a5a',
  amber:     '#f4c674',
  font: '-apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", system-ui, sans-serif',
  display: '"SF Pro Display", -apple-system, "Inter", system-ui, sans-serif',
  mono: 'ui-monospace,"SF Mono",Menlo,Consolas,monospace',
};

// Inject base styles once
if (typeof document !== 'undefined' && !document.getElementById('mf-styles')) {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Sans+KR:wght@400;500;700&display=swap';
  document.head.appendChild(link);
  const s = document.createElement('style');
  s.id = 'mf-styles';
  s.textContent = `
    .mf{font-family:${MF.font};color:${MF.text};-webkit-font-smoothing:antialiased}
    .mf *{box-sizing:border-box}
    .mf-kr{font-family:"Noto Sans KR",${MF.font};font-feature-settings:"ss01"}
    .mf-mono{font-family:${MF.mono}}
    .mf-tap{cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent;transition:transform .12s ease, opacity .12s ease, background .15s ease, border-color .15s ease, box-shadow .2s ease}
    .mf-tap:active{transform:scale(.97)}
    .mf-press{transition:transform .14s cubic-bezier(.34,1.4,.5,1)}
    @keyframes mf-pop{0%{transform:scale(.85);opacity:0}60%{transform:scale(1.06);opacity:1}100%{transform:scale(1);opacity:1}}
    @keyframes mf-shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-6px)}40%{transform:translateX(6px)}60%{transform:translateX(-4px)}80%{transform:translateX(4px)}}
    @keyframes mf-float-up{0%{transform:translateY(0);opacity:0}15%{opacity:1}100%{transform:translateY(-50px);opacity:0}}
    @keyframes mf-glow-pulse{0%,100%{box-shadow:0 0 0 0 rgba(167,139,250,0)}50%{box-shadow:0 0 0 8px rgba(167,139,250,.15)}}
    @keyframes mf-fade-up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
    @keyframes mf-fade-in{from{opacity:0}to{opacity:1}}
    @keyframes mf-spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
    @keyframes mf-blink{50%{opacity:.3}}
    .mf-fade-up{animation:mf-fade-up .32s cubic-bezier(.2,.7,.3,1) both}
    .mf-pop{animation:mf-pop .35s cubic-bezier(.34,1.4,.5,1) both}
    .mf-shake{animation:mf-shake .42s ease both}
    .mf-glow{animation:mf-glow-pulse 1.4s ease-in-out infinite}
    .mf-btn-ghost{background:${MF.card};border:1px solid ${MF.line};color:${MF.text}}
    .mf-btn-ghost:active{background:${MF.card2}}
    .mf-btn-primary{background:${MF.purple};color:#1a0f2e;border:1px solid ${MF.purple};box-shadow:0 4px 14px rgba(167,139,250,.32),inset 0 1px 0 rgba(255,255,255,.2)}
    .mf-btn-primary:active{background:${MF.purpleDim}}
    input.mf-input{background:transparent;border:none;outline:none;color:${MF.text};font-family:${MF.font};width:100%;font-size:24px;font-weight:600;caret-color:${MF.purple}}
    input.mf-input::placeholder{color:${MF.textMute}}
    .mf-scroll::-webkit-scrollbar{display:none}
    .mf-scroll{scrollbar-width:none}
  `;
  document.head.appendChild(s);
}

// ─── Dataset: Enchaînements Module A — 1er dan ───
//
// 24 enchaînements (combo sequences) with embedded YouTube demos. Each card
// carries the canonical sequence in `ro`; Korean (`kr`) is blank — these
// are technique sequences, not single vocabulary entries.
//
// The card `custom` object references the two built-in fields by their fixed
// ids (`cf-builtin-video-url`, `cf-builtin-carte`). Those ids are defined by
// `BUILTIN_FIELDS` in stores/decks-store.jsx, so a fresh install boots with a
// library where every default card already displays its video demo (and
// exposes an empty "Carte" pdf_region slot ready for the user to fill).
//
// Why a static seed instead of CSV import?
//   We own the default content and know its exact shape, so we ship it
//   directly rather than routing it through the importer.
const DECK_TKD = {
  id: 'tkd',
  name: 'Enchaînements Module A — 1er dan',
  sub: '24 enchaînements · démos YouTube embarquées',
  cards: [
    {
      id: 1,
      fr: "1er dan · Sup+Pos · n°1",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - HAN SONNAL MOMTONG BAKKAT MAKI ? AP KOUBI SEUGUI - JEBIPOUM MOK TCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "a",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=14s&end=19"},
    },
    {
      id: 2,
      fr: "1er dan · Sup+Pos · n°2",
      kr: "",
      ro: "TCHOUMBI : AP KOUBI SEUGUI - HAN SONNAL EULGOUL BITEURO MAKI ? EULGOUL BANDE JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "b",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=29s&end=39"},
    },
    {
      id: 3,
      fr: "1er dan · Sup+Pos · n°3",
      kr: "",
      ro: "TCHOUMBI : JOUTCHOUM SEUGUI - HAN SONNAL MOMTONG YOP MAKI ? MOMTOMG YOP JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "c",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=50s&end=56"},
    },
    {
      id: 4,
      fr: "1er dan · Sup+Pos · n°4",
      kr: "",
      ro: "TCHOUMBI : AP KOUBI SEUGUI - JEBIPOUM MOK TCHIGUI ? DEUNG JOUMOK EULGOUL AP TCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "d",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=66s&end=73"},
    },
    {
      id: 5,
      fr: "1er dan · Sup+Pos · n°5",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - KEUDEURO MOMTONG BAKKAT MAKI ? AP KOUBI SEUGUI - PALKOUP DOLYEU TCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "a",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=84s&end=91"},
    },
    {
      id: 6,
      fr: "1er dan · Sup+Pos · n°6",
      kr: "",
      ro: "TCHOUMBI : AP KOUBI SEUGUI – MOMTONG HETCHEU MAKI ? DWITT KOA SEUGUI - DOU JOUMOK JETCHEU JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "b",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=102s&end=110"},
    },
    {
      id: 7,
      fr: "1er dan · Sup+Pos · n°7",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - SONAL ARE MAKI - BEUM SEUGUI ? BATANG SON MOMTONG MAKI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "c",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=120s&end=129"},
    },
    {
      id: 8,
      fr: "1er dan · Sup+Pos · n°8",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - MOMTONG BAKKAT MAKI ? AP KOUBI SEUGUI - ME JOUMOK NERYOCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","positions"],
      tone: "d",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=WDqUNVOgYJo&t=138s&end=149"},
    },
    {
      id: 9,
      fr: "1er dan · Sup+Inf+Pos · n°1",
      kr: "",
      ro: "TCHOUMBI : AP SEUGUI - HAN SONNAL JEBIPOUM MOK TCHIGUI ? AP TCHAGUI - AP KOUBI SEUGUI - PALKOUP DOLYEU TCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "a",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=GmDWt-NNWJA&t=11s&end=23"},
    },
    {
      id: 10,
      fr: "1er dan · Sup+Inf+Pos · n°2",
      kr: "",
      ro: "TCHOUMBI : AP SEUGUI - DEUNG JOUMOK EULGOUL BAKKAT TCHIGUI ? AP TCHAGUI - AP KOUBI SEUGUI - MOMTONG BARO JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "b",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=33s&end=43"},
    },
    {
      id: 11,
      fr: "1er dan · Sup+Inf+Pos · n°3",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - HAN SONNAL MOMTONG BAKKAT MAKI ? YOP TCHAGUI - AP KOUBI SEUGUI - PALKOUP MOMTONG PYOJOK TCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "c",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=53s&end=63"},
    },
    {
      id: 12,
      fr: "1er dan · Sup+Inf+Pos · n°4",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - SONNAL MOMTONG MAKI ? DOLYEU TCHAGUI - AP KOUBI SEUGUI - EULGOUL BAKKAT MAKI ? MOMTONG BARO JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "d",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=72s&end=85"},
    },
    {
      id: 13,
      fr: "1er dan · Sup+Inf+Pos · n°5",
      kr: "",
      ro: "TCHOUMBI : AP KOUBI SEUGUI - HAN SONNAL EULGOUL BITEURO MAKI ? DOLYEU TCHAGUI - MOMTONG BARO JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "a",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=94s&end=105"},
    },
    {
      id: 14,
      fr: "1er dan · Sup+Inf+Pos · n°6",
      kr: "",
      ro: "TCHOUMBI : AP KOUBI SEUGUI - OWE SAN TEUL MAKI - AP BAL YOP TCHAGUI ? AP KOUBI SEUGUI - JEBIPOUM MOK TCHIGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "b",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=114s&end=125"},
    },
    {
      id: 15,
      fr: "1er dan · Sup+Inf+Pos · n°7",
      kr: "",
      ro: "TCHOUMBI : BEUM SEUGUI - SONNAL MOMTONG MAKI - AP BAL AP TCHAGUI ? AP KOUBI SEUGUI - MOMTONG BARO JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "c",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=136s&end=146"},
    },
    {
      id: 16,
      fr: "1er dan · Sup+Inf+Pos · n°8",
      kr: "",
      ro: "TCHOUMBI : DWITT KOUBI SEUGUI - KEUDEURO ARE MAKI - AP TCHAGUI ? AP KOUBI SEUGUI - MOMTONG DOUBONN JILEUGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_supérieurs","membres_inférieurs","positions"],
      tone: "d",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=oc4FUvyo3gM&t=153s&end=165"},
    },
    {
      id: 17,
      fr: "1er dan · Inf · n°1",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : NELYEU TCHAGUI - BANDAL TCHAGUI ? DWITT TCHAGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat"],
      tone: "a",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=12s&end=22"},
    },
    {
      id: 18,
      fr: "1er dan · Inf · n°2",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : YOP TCHAGUI - AP BAL FOURYEU TCHAGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat"],
      tone: "b",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=32s&end=45"},
    },
    {
      id: 19,
      fr: "1er dan · Inf · n°3",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : TUYEU DOLYEU TCHAGUI (Cible : raquette)",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat","cible_raquette"],
      tone: "c",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=52s&end=59"},
    },
    {
      id: 20,
      fr: "1er dan · Inf · n°4",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : Y OH DOLYEU TCHAGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat"],
      tone: "d",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=68s&end=75"},
    },
    {
      id: 21,
      fr: "1er dan · Inf · n°5",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : SOKKOT TCHAGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat"],
      tone: "a",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=84s&end=90"},
    },
    {
      id: 22,
      fr: "1er dan · Inf · n°6",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : AP BAL TUYEU AP TCHAGUI (Cible : raquette)",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat","cible_raquette"],
      tone: "b",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=100s&end=105"},
    },
    {
      id: 23,
      fr: "1er dan · Inf · n°7",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : DOU BAL DANG SANG AP TCHAGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat"],
      tone: "c",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=115s&end=124"},
    },
    {
      id: 24,
      fr: "1er dan · Inf · n°8",
      kr: "",
      ro: "KYORUGUI TCHOUMBI SEUGUI : BANDAL TCHAGUI ? MOM DOLYEU FOULYEU TCHAGUI",
      cat: "Enchaînement",
      tags: ["enchaînement","module_a","1er_dan","membres_inférieurs","combat"],
      tone: "d",
      custom: {"cf-builtin-video-url":"https://www.youtube.com/watch?v=xqiMFaH92QY&t=134s&end=144"},
    }
  ],
};

// ─── Helpers ───
const rand = (n) => Math.floor(Math.random() * n);
const shuffle = (arr) => {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) { const j = rand(i + 1); [a[i], a[j]] = [a[j], a[i]]; }
  return a;
};
const pickN = (arr, n) => shuffle(arr).slice(0, n);
const pickOtherN = (arr, exclude, n) => pickN(arr.filter(x => x.id !== exclude.id), n);

// Loose answer match (normalize accents/case/spaces)
const norm = (s) => (s || '')
  .toLowerCase()
  .normalize('NFD').replace(/[\u0300-\u036f]/g, '')
  .replace(/[^a-z0-9가-힣]+/g, '');

const answerMatches = (input, card, accept = ['ro', 'kr']) => {
  const n = norm(input);
  if (!n) return false;
  return accept.some(k => norm(card[k]) === n);
};

// Combo multiplier curve
const comboMult = (combo) => {
  if (combo >= 8) return 3;
  if (combo >= 5) return 2.5;
  if (combo >= 3) return 2;
  if (combo >= 1) return 1.5;
  return 1;
};

// Persistent state (XP, streak, last play)
const SAVE_KEY = 'mindforge.state.v1';
const LEGACY_SAVE_KEY = 'mindforge.playable.v1';
const loadSave = () => {
  try {
    const cur = localStorage.getItem(SAVE_KEY);
    if (cur) return JSON.parse(cur) || {};
    // One-shot migration from the legacy key.
    const legacy = localStorage.getItem(LEGACY_SAVE_KEY);
    if (legacy) {
      localStorage.setItem(SAVE_KEY, legacy);
      localStorage.removeItem(LEGACY_SAVE_KEY);
      return JSON.parse(legacy) || {};
    }
    return {};
  } catch { return {}; }
};
const writeSave = (s) => { try { localStorage.setItem(SAVE_KEY, JSON.stringify(s)); } catch {} };

// Card visual placeholder — tone-based colored panel with Hangul big
const cardPlaceholderBg = (tone) => ({
  a: 'linear-gradient(135deg, #2b1f4d 0%, #6a4cc7 100%)',
  b: 'linear-gradient(135deg, #1f2d4d 0%, #4d8eff 100%)',
  c: 'linear-gradient(135deg, #1f3d33 0%, #3fae74 100%)',
  d: 'linear-gradient(135deg, #3d1f2d 0%, #c75c7a 100%)',
}[tone] || '#2a2735');

Object.assign(window, {
  MF, DECK_TKD, rand, shuffle, pickN, pickOtherN, norm, answerMatches, comboMult,
  loadSave, writeSave, cardPlaceholderBg,
});
