// bracelet.jsx - crystal alchemy bracelet builder for Azoth AI

const BRACELET_STONES = {
  black_tourmaline: {
    name: "Чорний турмалін",
    colors: ["#171313", "#32281d"],
    element: "Земля",
    planets: "Сатурн / Марс",
    tags: ["protection", "grounding", "boundary", "shadow"],
    power: "захисний контур, заземлення, відсікання шуму",
    caution: "не замінює реальний захист і тверезі рішення",
  },
  obsidian: {
    name: "Обсидіан",
    colors: ["#0a0909", "#2a211e"],
    element: "Вогонь землі",
    planets: "Плутон / Сатурн",
    tags: ["truth", "shadow", "cut", "protection"],
    power: "жорстка правда, тіньова робота, зріз ілюзій",
    caution: "для чутливих клієнтів вводити м'яко, не як фатальний камінь",
  },
  smoky_quartz: {
    name: "Димчастий кварц",
    colors: ["#4a3b32", "#8a735c"],
    element: "Земля / Повітря",
    planets: "Сатурн",
    tags: ["grounding", "calm", "shadow", "release"],
    power: "зняття надлишкового напруження, тверезість, стабілізація",
    caution: "уникати медичних обіцянок",
  },
  hematite: {
    name: "Гематит",
    colors: ["#272523", "#7f776d"],
    element: "Земля / Залізо",
    planets: "Марс / Сатурн",
    tags: ["will", "body", "grounding", "discipline"],
    power: "тілесна опора, воля, дисципліна, межа",
    caution: "важкий металевий акцент; не для легкого романтичного браслета",
  },
  amethyst: {
    name: "Аметист",
    colors: ["#4a2f63", "#9a73bd"],
    element: "Повітря / Дух",
    planets: "Юпітер / Нептун",
    tags: ["intuition", "clarity", "dream", "spiritual"],
    power: "інтуїтивна чистота, сон, спостереження, духовна тверезість",
    caution: "тривале сонце може бліднити колір",
  },
  clear_quartz: {
    name: "Гірський кришталь",
    colors: ["#d9d2c3", "#fff8e2"],
    element: "Дух",
    planets: "Сонце / Меркурій",
    tags: ["amplifier", "clarity", "focus", "programming"],
    power: "підсилювач формули, ясність наміру, провідник",
    caution: "підсилює хаос так само, як ясність; потребує чіткої програми",
  },
  rose_quartz: {
    name: "Рожевий кварц",
    colors: ["#c78b91", "#f0c2c0"],
    element: "Вода",
    planets: "Венера",
    tags: ["love", "heart", "softness", "repair"],
    power: "серцеве пом'якшення, довіра, ніжність, відновлення контакту",
    caution: "не використовувати для прив'язки іншої людини",
  },
  citrine: {
    name: "Цитрин",
    colors: ["#b67818", "#f0c25a"],
    element: "Вогонь",
    planets: "Сонце / Юпітер",
    tags: ["money", "confidence", "visibility", "joy"],
    power: "сонячна впевненість, гроші, видимість, радісна дія",
    caution: "на ринку багато термообробленого аметисту; це не скасовує символ, але важливо для якості",
  },
  tiger_eye: {
    name: "Тигрове око",
    colors: ["#5a3516", "#d3a12f"],
    element: "Вогонь / Земля",
    planets: "Сонце / Марс",
    tags: ["confidence", "money", "courage", "focus"],
    power: "сміливість, фокус, ділова хватка, тепла оборона",
    caution: "не робити надто агресивним для вже різких клієнтів",
  },
  labradorite: {
    name: "Лабрадорит",
    colors: ["#263a3d", "#4f877e"],
    element: "Вода / Ефір",
    planets: "Місяць / Уран",
    tags: ["intuition", "magic", "protection", "liminal"],
    power: "окультний щит, бачення межі, робота з переходами",
    caution: "берегти від ударів; перелив залежить від якості намистин",
  },
  moonstone: {
    name: "Місячний камінь",
    colors: ["#d8d4c6", "#8ca2b0"],
    element: "Вода",
    planets: "Місяць",
    tags: ["cycles", "intuition", "feminine", "calm"],
    power: "цикли, рецептивність, сон, м'яке інтуїтивне поле",
    caution: "м'який камінь; не перевантажувати жорсткою щоденною носкою",
  },
  garnet: {
    name: "Гранат",
    colors: ["#4b1018", "#9b2234"],
    element: "Вогонь / Кров",
    planets: "Марс / Плутон",
    tags: ["vitality", "passion", "will", "body"],
    power: "життєва сила, пристрасть, витривалість, повернення в тіло",
    caution: "не подавати як лікування крові або тіла",
  },
  carnelian: {
    name: "Сердолік",
    colors: ["#a33d1f", "#e68a3a"],
    element: "Вогонь",
    planets: "Марс / Сонце",
    tags: ["action", "creativity", "sexuality", "confidence"],
    power: "запуск дії, творчість, голос тіла, сміливість",
    caution: "може бути занадто гарячим для нервового запиту",
  },
  lapis: {
    name: "Лазурит",
    colors: ["#142b6f", "#c8a85a"],
    element: "Повітря / Небо",
    planets: "Юпітер / Сатурн",
    tags: ["wisdom", "authority", "truth", "voice"],
    power: "мудрість, авторитет, правдива мова, вчительська позиція",
    caution: "часто фарбований або реконструйований; перевіряти якість",
  },
  sodalite: {
    name: "Содаліт",
    colors: ["#243f7b", "#eef0df"],
    element: "Повітря",
    planets: "Меркурій",
    tags: ["logic", "speech", "calm", "study"],
    power: "логіка, холодна мова, навчання, порядок думки",
    caution: "не робити головним у серцевих запитах",
  },
  amazonite: {
    name: "Амазоніт",
    colors: ["#4c9f93", "#8ed1bf"],
    element: "Вода / Повітря",
    planets: "Меркурій / Венера",
    tags: ["speech", "boundary", "calm", "heart"],
    power: "спокійна комунікація, м'яка межа, голос без конфлікту",
    caution: "берегти від агресивної хімії",
  },
  malachite: {
    name: "Малахіт",
    colors: ["#143d24", "#27a45f"],
    element: "Земля / Венера",
    planets: "Венера / Плутон",
    tags: ["transformation", "heart", "money", "shadow"],
    power: "серцева трансформація, сильне поле змін, ресурс",
    caution: "не класти у воду/сіль, пил малахіту токсичний; тільки готові поліровані намистини",
  },
  aventurine: {
    name: "Зелений авантюрин",
    colors: ["#3f7b48", "#9bc783"],
    element: "Земля / Серце",
    planets: "Венера / Юпітер",
    tags: ["luck", "money", "heart", "growth"],
    power: "м'яка удача, ріст, серцева підприємливість",
    caution: "не замінює дії та фінансовий розрахунок",
  },
  pyrite: {
    name: "Пірит",
    colors: ["#6d5626", "#d4aa3c"],
    element: "Вогонь / Метал",
    planets: "Сонце / Марс",
    tags: ["money", "protection", "will", "status"],
    power: "грошовий щит, статус, сонячна самоповага, дія",
    caution: "не мочити; може тьмяніти і окиснюватися",
  },
  sapphire: {
    name: "Сапфір",
    colors: ["#061639", "#1f5ab5"],
    element: "Небо / Закон",
    planets: "Сатурн / Юпітер",
    tags: ["authority", "wealth", "strategy", "status"],
    power: "імператорська стратегія, статус, холодна влада, фінансова дисципліна",
    caution: "для дорогого браслета перевіряти походження, огранку, сертифікат і сумісність з металом",
  },
  ruby: {
    name: "Рубін",
    colors: ["#4d0614", "#d7283d"],
    element: "Вогонь / Кров",
    planets: "Сонце / Марс",
    tags: ["will", "wealth", "command", "vitality"],
    power: "воля переможця, наказова сила, сміливий матеріальний рух",
    caution: "сильний гарячий камінь; у формулі має бути заземлення і межа",
  },
  emerald: {
    name: "Смарагд",
    colors: ["#06381e", "#34a95a"],
    element: "Земля / Венера",
    planets: "Венера / Меркурій",
    tags: ["wealth", "growth", "networks", "value"],
    power: "ріст капіталу, угоди, цінність, притягання правильних союзів",
    caution: "крихкий у ювелірній роботі; краще брати захищену посадку або вставки-акценти",
  },
  diamond: {
    name: "Діамант",
    colors: ["#d7d2c5", "#ffffff"],
    element: "Дух / Сонце",
    planets: "Сонце / Венера",
    tags: ["amplifier", "clarity", "status", "seal"],
    power: "незламна печать наміру, ясність, преміальний статус, фіксація формули",
    caution: "не є обов'язковим для сили формули; якщо бюджет менший, замінити чистим гірським кришталем",
  },
  onyx: {
    name: "Онікс",
    colors: ["#070707", "#1d1a17"],
    element: "Земля",
    planets: "Сатурн",
    tags: ["discipline", "protection", "boundary", "focus"],
    power: "сухий захист, самоконтроль, межа, витримка",
    caution: "у слабкому емоційному стані може здаватися холодним",
  },
  jasper: {
    name: "Яшма",
    colors: ["#7b2d22", "#c1844a"],
    element: "Земля",
    planets: "Земля / Марс",
    tags: ["endurance", "body", "grounding", "support"],
    power: "витривалість, щоденна опора, стабільна земля",
    caution: "добре як база, слабше як єдиний магічний акцент",
  },
  aquamarine: {
    name: "Аквамарин",
    colors: ["#7fb7bd", "#c5e7df"],
    element: "Вода / Повітря",
    planets: "Місяць / Меркурій",
    tags: ["speech", "calm", "travel", "clarity"],
    power: "чиста мова, спокій, переговори, легкість дихання символічно",
    caution: "не подавати як лікування горла або дихання",
  },
};

const BRACELET_PROFILES = [
  { id: "imperial_money", name: "Імператорський матеріальний шлях і фінансова влада", rx: /(імператор|император|влада|власть|фінансов[а-яіїєґё\s-]{0,28}(систем|імпер|импер|влад)|финансов[а-яіїєґё\s-]{0,28}(систем|импер|влад)|систем[а-яіїєґё\s-]{0,28}(фінансов|финансов|влад)|статус[а-яіїєґё\s-]{0,28}(влад|систем|імпер|импер))/i, stones: ["sapphire", "diamond", "ruby", "emerald", "pyrite", "citrine", "lapis", "tiger_eye"] },
  { id: "breakthrough", name: "Прорив блоків і прискорення шляху", rx: /(злам|слом|ч[іи]ткод|швидш|ускор|пришвид|прорив|прорыв|бар'єр|барьер|блок|перешкод|препятств|відкрити шлях|открыть путь|шлях|путь)/i, stones: ["obsidian", "black_tourmaline", "hematite", "garnet", "tiger_eye", "clear_quartz", "pyrite", "ruby"] },
  { id: "protection", name: "Захист і межа", rx: /(захист|защит|оберіг|оберег|негатив|сглаз|пристр|порч|атака|ворог|страх|тінь|тень)/i, stones: ["black_tourmaline", "obsidian", "smoky_quartz", "hematite", "labradorite", "onyx"] },
  { id: "money", name: "Удача, багатство і проявленість", rx: /(грош|деньг|money|бізнес|бизнес|кар'єр|карьер|успіх|успех|статус|продаж|клієнт|клиент|матеріальн|материальн|капітал|капитал|багат|богат|wealth|abundance|удач|тал[іи]сман|дорог|преміум|премиум|ювелір|ювелир|справжн|настоящ)/i, stones: ["citrine", "pyrite", "tiger_eye", "aventurine", "emerald", "lapis", "hematite"] },
  { id: "love", name: "Серце і стосунки", rx: /(любов|отнош|стосунк|серц|пара|шлюб|брак|примир|довіра|довер|самоцін|самоцен)/i, stones: ["rose_quartz", "moonstone", "amazonite", "aventurine", "malachite", "amethyst"] },
  { id: "intuition", name: "Інтуїція і окультний зір", rx: /(інтуїц|интуиц|бач|видін|сновид|сон|таро|магі|магич|канал|медіум|медиум|практик|езотер)/i, stones: ["amethyst", "labradorite", "moonstone", "clear_quartz", "lapis", "black_tourmaline"] },
  { id: "confidence", name: "Воля і впевненість", rx: /(уверенн|впевнен|воля|смілив|смел|харизм|страх сцени|голос|дія|действ)/i, stones: ["tiger_eye", "carnelian", "citrine", "garnet", "hematite", "clear_quartz"] },
  { id: "calm", name: "Спокій і збирання нервової сили", rx: /(спок|спокой|тривог|тревог|стрес|сон|нерв|гармон|баланс|панік|паник)/i, stones: ["smoky_quartz", "amethyst", "amazonite", "sodalite", "moonstone", "aquamarine"] },
  { id: "truth", name: "Правда і рішення", rx: /(правд|рішення|решени|ясн|вибір|выбор|обман|иллюз|ілюз|розібратись|разобрат)/i, stones: ["obsidian", "lapis", "sodalite", "clear_quartz", "smoky_quartz", "hematite"] },
  { id: "vitality", name: "Життєва сила", rx: /(енергі|энерг|сила|ресурс|витривал|устал|втом|апат|сексуальн|тіло|тело)/i, stones: ["garnet", "carnelian", "jasper", "citrine", "hematite", "tiger_eye"] },
];

const BRACELET_ZODIAC = [
  ["Козоріг", 120, ["onyx", "hematite", "smoky_quartz"]],
  ["Водолій", 219, ["amethyst", "labradorite", "aquamarine"]],
  ["Риби", 320, ["amethyst", "moonstone", "aquamarine"]],
  ["Овен", 421, ["carnelian", "garnet", "hematite"]],
  ["Телець", 521, ["rose_quartz", "aventurine", "malachite"]],
  ["Близнюки", 621, ["sodalite", "amazonite", "clear_quartz"]],
  ["Рак", 722, ["moonstone", "rose_quartz", "aquamarine"]],
  ["Лев", 823, ["citrine", "tiger_eye", "pyrite"]],
  ["Діва", 923, ["sodalite", "jasper", "clear_quartz"]],
  ["Терези", 1023, ["rose_quartz", "lapis", "amazonite"]],
  ["Скорпіон", 1122, ["obsidian", "garnet", "malachite"]],
  ["Стрілець", 1222, ["lapis", "amethyst", "citrine"]],
  ["Козоріг", 1231, ["onyx", "hematite", "smoky_quartz"]],
];

const BRACELET_LIFE_PATH = {
  1: ["carnelian", "citrine"],
  2: ["moonstone", "rose_quartz"],
  3: ["citrine", "amazonite"],
  4: ["hematite", "jasper"],
  5: ["tiger_eye", "aquamarine"],
  6: ["rose_quartz", "aventurine"],
  7: ["amethyst", "labradorite"],
  8: ["pyrite", "onyx"],
  9: ["lapis", "smoky_quartz"],
  11: ["clear_quartz", "amethyst"],
  22: ["hematite", "clear_quartz"],
};

const BRACELET_ARCANA_STONES = {
  1: ["clear_quartz", "carnelian"],
  2: ["moonstone", "amethyst"],
  3: ["rose_quartz", "malachite"],
  4: ["hematite", "onyx"],
  5: ["lapis", "sodalite"],
  6: ["rose_quartz", "amazonite"],
  7: ["tiger_eye", "hematite"],
  8: ["onyx", "clear_quartz"],
  9: ["amethyst", "smoky_quartz"],
  10: ["citrine", "aventurine"],
  11: ["garnet", "tiger_eye"],
  12: ["amethyst", "moonstone"],
  13: ["obsidian", "smoky_quartz"],
  14: ["aquamarine", "clear_quartz"],
  15: ["black_tourmaline", "obsidian"],
  16: ["hematite", "black_tourmaline"],
  17: ["labradorite", "amethyst"],
  18: ["moonstone", "labradorite"],
  19: ["citrine", "pyrite"],
  20: ["lapis", "clear_quartz"],
  21: ["aventurine", "clear_quartz"],
  22: ["aquamarine", "labradorite"],
};

function braceletBirthDate(text) {
  if (window.extractBirthDate) return window.extractBirthDate(text);
  const match = String(text || "").match(/\b(\d{1,2})[.\-/](\d{1,2})[.\-/](\d{4})\b/);
  if (!match) return null;
  return { day: Number(match[1]), month: Number(match[2]), year: Number(match[3]) };
}

function braceletDateString(date) {
  if (!date) return "без дати";
  return `${String(date.day).padStart(2, "0")}.${String(date.month).padStart(2, "0")}.${date.year}`;
}

function braceletDigitSum(value) {
  return String(Math.abs(Number(value) || 0)).split("").reduce((sum, ch) => sum + Number(ch), 0);
}

function braceletLifePath(date) {
  if (!date) return null;
  let n = braceletDigitSum(`${date.day}${date.month}${date.year}`);
  while (![11, 22].includes(n) && n > 9) n = braceletDigitSum(n);
  return n || null;
}

function braceletSunSign(date) {
  if (!date) return null;
  const md = date.month * 100 + date.day;
  const row = BRACELET_ZODIAC.find(item => md <= item[1]);
  return row ? { name: row[0], stones: row[2] } : null;
}

function braceletAddScore(scores, id, points, reason) {
  if (!BRACELET_STONES[id]) return;
  const current = scores[id] || { id, score: 0, reasons: [] };
  current.score += points;
  if (reason && !current.reasons.includes(reason)) current.reasons.push(reason);
  scores[id] = current;
}

function braceletIntent(text) {
  const q = String(text || "");
  const matches = BRACELET_PROFILES.filter(profile => profile.rx.test(q));
  if (matches.length) return matches.slice(0, 3);
  return [
    {
      id: "integrative",
      name: "Підсвітити сильні сторони і прикрити слабкі місця",
      stones: ["clear_quartz", "amethyst", "tiger_eye", "black_tourmaline", "rose_quartz", "hematite"],
    },
  ];
}

function braceletTitleForProfiles(profiles = []) {
  const ids = profiles.map(profile => (typeof profile === "string" ? profile : profile.id)).filter(Boolean);
  if (ids.includes("imperial_money")) return "Імператорський алхімічний браслет";
  if (ids.includes("money") && ids.includes("breakthrough")) return "Алхімічний браслет достатку і прориву";
  if (ids.includes("money")) return "Алхімічний браслет удачі та багатства";
  if (ids.includes("breakthrough")) return "Алхімічний браслет прориву";
  if (ids.includes("protection")) return "Алхімічний браслет захисту";
  if (ids.includes("love")) return "Алхімічний браслет серця";
  if (ids.includes("intuition")) return "Алхімічний браслет окультного зору";
  return "Алхімічний браслет";
}

function braceletHardwareConfig(profiles = [], primaryProfile = "", options = {}) {
  const ids = profiles.map(profile => (typeof profile === "string" ? profile : profile.id)).filter(Boolean);
  const isImperial = options.isImperial || ids.includes("imperial_money");
  const isBreakthrough = options.isBreakthrough || ids.includes("breakthrough");
  const isLove = primaryProfile === "love" || ids.includes("love");
  const isMoney = primaryProfile === "money" || ids.includes("money");

  if (isImperial) {
    return {
      threadMaterial: "чорний шовковий шнур поверх ювелірного тросика",
      threadColor: "#19120a",
      metalTone: "жовте золото",
      metalColor: "#d8ae38",
      metalShadow: "#6f4e14",
      clasp: "золотий карабін 585/750 зі страховим ланцюжком",
      connectors: "золоті кільця 2 мм між сильними акцентами; чорні стопери біля печаті",
      spacers: [
        { name: "золотий розділювач", role: "сонячний міст між владою і дією", color: "#d8ae38" },
        { name: "чорний стопер", role: "сатурніанська межа біля печаті", color: "#171313" },
        { name: "мікро-кільце", role: "фіксує дорогі вставки без тертя каменів", color: "#f1d36b" },
      ],
      assembly: [
        "почати від карабіна: золоте кільце, стопер, головний камінь",
        "між сапфіром, рубіном і діамантом ставити металевий міст",
        "біля захисної печаті ставити чорний стопер з двох боків",
        "закрити формулу страховим ланцюжком і вузлом під металевою кришкою",
      ],
    };
  }

  if (isMoney && isBreakthrough) {
    return {
      threadMaterial: "чорний ювелірний тросик або шнур із золотим вузлом-печаттю",
      threadColor: "#16110b",
      metalTone: "позолота + темна сталь",
      metalColor: "#c49a31",
      metalShadow: "#2f2a23",
      clasp: "позолочений карабін із темним страховим кільцем",
      connectors: "позолочені містки між грошовими акцентами; темні стопери біля захисту",
      spacers: [
        { name: "позолочений міст", role: "веде удачу в матеріальний результат", color: "#c49a31" },
        { name: "темний стопер", role: "не дає прориву розсипатися в хаос", color: "#1b1814" },
        { name: "сонячне кільце", role: "підсилює цитрин і пірит", color: "#e3b743" },
      ],
      assembly: [
        "почати з головного грошового каменя і позолоченого містка",
        "між гарячим проривом і холодним захистом ставити розділювач",
        "захисний камінь закрити темним стопером з двох боків",
        "вузол або замок фіксувати на внутрішньому боці як печать наміру",
      ],
    };
  }

  if (isBreakthrough) {
    return {
      threadMaterial: "чорний еластомер 0.8 мм у два проходи або ювелірний тросик",
      threadColor: "#130f0d",
      metalTone: "темна сталь + латунь",
      metalColor: "#a9822a",
      metalShadow: "#34302a",
      clasp: "магнітний замок із темної сталі або міцний прихований вузол",
      connectors: "латунні розділювачі біля вогняних каменів; темні кільця біля захисту",
      spacers: [
        { name: "латунний міст", role: "проштовхує дію між гарячими каменями", color: "#b98a2a" },
        { name: "темне кільце", role: "відтинає зайвий шум після печаті", color: "#282522" },
        { name: "вузол-фіксатор", role: "тримає контур під напругою", color: "#0f0d0b" },
      ],
      assembly: [
        "першим ставити головний камінь, далі металевий міст",
        "гарячі камені не зіштовхувати напряму з холодними: між ними розділювач",
        "печать замикати темним кільцем до і після каменя",
        "вузол закривати кришкою або ховати під найбільш темною намистиною",
      ],
    };
  }

  if (isLove) {
    return {
      threadMaterial: "м'який прозорий еластомер 0.7-0.8 мм",
      threadColor: "#d8b5ad",
      metalTone: "рожеве золото або мідь",
      metalColor: "#c58a64",
      metalShadow: "#6b3d2c",
      clasp: "невеликий магнітний замок у рожевому металі",
      connectors: "тонкі мідні або rose-gold розділювачі між серцевими каменями",
      spacers: [
        { name: "рожевий міст", role: "пом'якшує контакт каменів", color: "#d49a7b" },
        { name: "мідне кільце", role: "венеріанський провідник", color: "#b66f45" },
      ],
      assembly: [
        "не перевантажувати металом, залишити каменям м'який контакт",
        "центральний камінь ставити без гострих сусідів",
        "вузол сховати на внутрішньому боці браслета",
      ],
    };
  }

  return {
    threadMaterial: "еластомер 0.8 мм у два проходи або ювелірний тросик",
    threadColor: "#171411",
    metalTone: isMoney ? "латунь / позолота" : "срібло або темна сталь",
    metalColor: isMoney ? "#c49a31" : "#a9a39a",
    metalShadow: isMoney ? "#735314" : "#423f3a",
    clasp: isMoney ? "позолочений карабін або магнітний замок" : "малий карабін, магнітний замок або прихований вузол",
    connectors: isMoney ? "позолочені розділювачі біля грошових акцентів" : "тонкі розділювачі тільки між великими або крихкими намистинами",
    spacers: [
      { name: isMoney ? "позолочений міст" : "металевий міст", role: "розділяє акценти і береже камені", color: isMoney ? "#c49a31" : "#a9a39a" },
      { name: "стопер", role: "фіксує печать і вузол", color: "#201b16" },
    ],
    assembly: [
      "почати з замка або вузла, далі головний камінь формули",
      "між великими акцентами ставити тонкий розділювач",
      "захисну печать закрити стопером",
      "після примірки підтягнути нитку і сховати вузол",
    ],
  };
}

function buildBraceletBlueprint(text, matrix) {
  const date = braceletBirthDate(text);
  const lifePath = braceletLifePath(date);
  const sun = braceletSunSign(date);
  const profiles = braceletIntent(text);
  const scores = {};

  profiles.forEach((profile, profileIndex) => {
    profile.stones.forEach((id, index) => {
      braceletAddScore(scores, id, 8 - profileIndex * 2 - Math.min(index, 4), `запит: ${profile.name}`);
    });
  });

  if (sun) {
    sun.stones.forEach((id, index) => braceletAddScore(scores, id, 4 - index, `сонячний знак: ${sun.name}`));
  }
  if (lifePath && BRACELET_LIFE_PATH[lifePath]) {
    BRACELET_LIFE_PATH[lifePath].forEach((id, index) => braceletAddScore(scores, id, 4 - index, `шлях життя: ${lifePath}`));
  }
  if (matrix && matrix.centerNode && BRACELET_ARCANA_STONES[matrix.centerNode.value]) {
    BRACELET_ARCANA_STONES[matrix.centerNode.value].forEach((id, index) => {
      braceletAddScore(scores, id, 4 - index, `центр Матриці XXII: ${matrix.centerNode.value}`);
    });
  }
  if (matrix && matrix.channels) {
    matrix.channels.slice(0, 4).forEach(node => {
      (BRACELET_ARCANA_STONES[node.value] || []).slice(0, 1).forEach(id => {
        braceletAddScore(scores, id, 1, `${node.short}: ${node.value}`);
      });
    });
  }
  if (profiles.some(profile => profile.id === "imperial_money")) {
    [
      ["sapphire", 6],
      ["diamond", 6],
      ["ruby", 5],
      ["emerald", 5],
      ["pyrite", 4],
      ["citrine", 3],
    ].forEach(([id, points]) => braceletAddScore(scores, id, points, "пріоритет поточного імператорського запиту"));
  }
  if (profiles.some(profile => profile.id === "breakthrough")) {
    [
      ["obsidian", 4],
      ["black_tourmaline", 4],
      ["hematite", 3],
      ["garnet", 2],
    ].forEach(([id, points]) => braceletAddScore(scores, id, points, "пріоритет поточного запиту на прорив"));
  }
  if (!profiles.some(profile => profile.id === "imperial_money") && profiles.some(profile => profile.id === "money")) {
    [
      ["citrine", 6],
      ["pyrite", 5],
      ["tiger_eye", 4],
      ["emerald", 4],
      ["aventurine", 3],
      ["lapis", 2],
    ].forEach(([id, points]) => braceletAddScore(scores, id, points, "пріоритет поточного запиту на удачу і багатство"));
  }

  braceletAddScore(scores, "clear_quartz", 1, "провідник формули");
  braceletAddScore(scores, "black_tourmaline", 1, "базовий захисний замок");

  const ranked = Object.values(scores).sort((a, b) => b.score - a.score || a.id.localeCompare(b.id));
  const selected = ranked.slice(0, 6).map(item => ({
    ...BRACELET_STONES[item.id],
    id: item.id,
    score: item.score,
    reasons: item.reasons,
  }));
  const primaryProfile = profiles[0]?.id || "";
  const isImperial = profiles.some(profile => profile.id === "imperial_money");
  const isBreakthrough = profiles.some(profile => profile.id === "breakthrough");
  const isMoney = profiles.some(profile => profile.id === "money");
  let anchor = selected[0];
  if (!isImperial && isMoney) {
    anchor = selected.find(stone => ["citrine", "pyrite", "emerald", "tiger_eye"].includes(stone.id)) || anchor;
  }
  const amplifier = selected.find(stone => stone.id === "diamond")
    || selected.find(stone => stone.id === "clear_quartz")
    || (!isImperial && isMoney ? selected.find(stone => ["pyrite", "tiger_eye", "citrine"].includes(stone.id) && stone.id !== anchor.id) : null)
    || selected[selected.length - 1];
  const seal = selected.find(stone => ["black_tourmaline", "onyx", "hematite", "obsidian"].includes(stone.id) && stone.id !== anchor.id)
    || selected.find(stone => ["black_tourmaline", "onyx", "hematite", "obsidian"].includes(stone.id))
    || selected[1]
    || anchor;
  const beadCount = lifePath === 11 || lifePath === 22 || isImperial ? 22 : (primaryProfile === "protection" ? 21 : 19);
  const hardware = braceletHardwareConfig(profiles, primaryProfile, { isImperial, isBreakthrough });
  const metal = isImperial ? "жовте золото 585/750 або важка позолочена латунь; чорні розділювачі тільки як сатурніанська межа" : (primaryProfile === "money" ? "латунь або позолочені розділювачі" : (primaryProfile === "love" ? "мідь або рожеве золото як венеріанський акцент" : "темна сталь, срібло або без металу"));
  const thread = isImperial ? "ювелірний тросик або шовковий шнур з металевим замком; еластомер тільки для тестової версії" : "еластомер 0.8 мм у два проходи або ювелірний тросик, якщо камені важкі";
  const sequence = [];
  for (let i = 0; i < beadCount; i += 1) {
    let stone = selected[(i + 1) % selected.length] || anchor;
    let role = "ритмічна намистина";
    if (i === 0 || i === Math.floor(beadCount / 2)) {
      stone = anchor;
      role = i === 0 ? "головний замок наміру" : "дзеркальний замок";
    } else if (i % 6 === 0) {
      stone = amplifier;
      role = "підсилювач";
    } else if (i === beadCount - 1 || i === Math.floor(beadCount / 3)) {
      stone = seal;
      role = "захисна печать";
    }
    sequence.push({ index: i + 1, id: stone.id, name: stone.name, colors: stone.colors, role });
  }

  return {
    type: "crystal_bracelet",
    title: braceletTitleForProfiles(profiles),
    date: braceletDateString(date),
    lifePath,
    sunSign: sun ? sun.name : null,
    intent: profiles.map(profile => profile.name).join(" + "),
    stones: selected,
    anchor,
    amplifier,
    seal,
    beadCount,
    beadSize: isImperial ? "8 мм база; 10 мм центральні замки; діамант/сапфір/рубін можна ставити як ювелірні вставки 3-5 мм" : "8 мм як універсальна база; 6 мм для м'якого щоденного носіння; 10 мм для ритуального акценту",
    metal,
    thread,
    ...hardware,
    sequence,
    profiles: profiles.map(profile => profile.id),
    createdAt: new Date().toISOString(),
  };
}

function shouldBuildBracelet(active, text) {
  const raw = String(text || "");
  const q = raw.toLowerCase();
  const explicitBracelet = /(браслет|браслед|намист|бусин|bead|bracelet)/i.test(q);
  const shoppingIntent = /(випиши|выпиши|список|перелік|перечень|що\s+купити|что\s+купить|купити|купить|куплю|купиш|закуп|покуп|замов|заказ|магазин|шопінг|shopping|матеріал|материал|фурнітур|фурнитур)/i.test(q)
    && /(браслет|камн|камін|камен|кристал|кристалл|мінерал|минерал|намист|бусин|нитк|замок|розділювач|разделител|сапфір|сапфир|цитрин|пірит|пирит|гематит|турмалін|турмалин|обсидіан|обсидиан)/i.test(q);
  const assembly = /(збери|собери|підібрати|подобрать|підбери|подбери|формул[ау]|схем[ау]|зроби|сделай|створи|создай).{0,60}(?:браслет|камн|камін|камен|кристал|кристалл|мінерал|минерал|crystal|gemstone|stone)/i.test(q);
  const stoneBracelet = /(камн|камін|камен|кристал|кристалл|мінерал|минерал|crystal|gemstone|stone).{0,80}(?:браслет|намист|бусин|носити|носить|зап'яст|запяст|wrist|оберіг|оберег|амулет|талісман|талисман)/i.test(q);
  const altarContext = /(вівтар|вивтар|алтар|altar|столик|скатерт|свічк|свеч|вогонь|огонь|вода|герб|рожа|роза|пелюст|лепест|дар(?:и|ы)?\s+роду|родов)/i.test(q);
  const hasBirthDate = !!braceletBirthDate(raw);
  const hasSpecificIntent = braceletIntent(raw).some(profile => profile.id !== "integrative");
  const designVerb = /(розроб|разработ|збери|собери|зроб|сдел|створ|созд|підбер|подбер|підібрат|подобрат|формул|схем|спроєкт|спроект)/i.test(q);
  const visualVerb = /(намал|нарис|покаж|зобраз|изобраз|візуал|визуал|картин)/i.test(q);
  if (!explicitBracelet && altarContext) return false;
  if (shoppingIntent) return false;
  if (!explicitBracelet && !assembly && !stoneBracelet) return false;
  return assembly || stoneBracelet || (explicitBracelet && (designVerb || hasBirthDate || hasSpecificIntent || (visualVerb && (hasBirthDate || hasSpecificIntent))));
}

function buildBraceletContext(bracelet) {
  if (!bracelet) return "";
  const hardware = braceletHardwareConfig(bracelet.profiles || [], bracelet.profiles?.[0] || "", {
    isImperial: (bracelet.profiles || []).includes("imperial_money"),
    isBreakthrough: (bracelet.profiles || []).includes("breakthrough"),
  });
  const clasp = bracelet.clasp || hardware.clasp;
  const connectors = bracelet.connectors || hardware.connectors;
  const threadMaterial = bracelet.threadMaterial || hardware.threadMaterial || bracelet.thread;
  const assembly = (bracelet.assembly || hardware.assembly || []).join("; ");
  const stoneText = bracelet.stones.map(stone => (
    `${stone.name}: ${stone.power}; стихія ${stone.element}; планети ${stone.planets}; причини підбору: ${stone.reasons.join(", ")}`
  )).join("; ");
  const sequenceText = bracelet.sequence.map(item => `${item.index}. ${item.name} (${item.role})`).join("; ");
  const cautionText = bracelet.stones.map(stone => `${stone.name}: ${stone.caution}`).join("; ");
  return `\n\n[Алхімічний браслет уже зібраний інтерфейсом Azoth AI для ПОТОЧНОГО запиту. Не замінюй цю формулу старими браслетами з історії або пам'яті. Намір: ${bracelet.intent}. Дата: ${bracelet.date}; сонячний знак: ${bracelet.sunSign || "не визначено"}; шлях життя: ${bracelet.lifePath || "не визначено"}. Формула каменів: ${stoneText}. Головний камінь: ${bracelet.anchor.name}. Підсилювач: ${bracelet.amplifier.name}. Захисна печать: ${bracelet.seal.name}. Кількість намистин: ${bracelet.beadCount}; розмір: ${bracelet.beadSize}; метал/розділювачі: ${bracelet.metal}; нитка/основа: ${threadMaterial}; замок: ${clasp}; конектори: ${connectors}; схема фурнітури: ${assembly}. Порядок намистин по колу: ${sequenceText}. Правила безпеки і догляду: ${cautionText}. Якщо є прикріплене фото клієнта або руки, зв'яжи формулу браслета з видимими людськими ознаками, але не вигадуй те, чого не видно. Дай практику докладний звіт українською: чому саме така формула, що вона підсилює, що захищає, як зібрати, як очистити, як зарядити, як носити, які питання поставити клієнту і як перевірити результат. Окремо опиши нитку, замок, конектори, розділювачі, метал і порядок збірки. Познач камені як традиційні езотеричні відповідності, а не медичну гарантію.]`;
}

function BraceletView({ bracelet }) {
  if (!bracelet || !bracelet.sequence) return null;
  const size = 420;
  const center = size / 2;
  const radiusX = 154;
  const radiusY = 124;
  const profileIds = bracelet.profiles || [];
  const hardware = braceletHardwareConfig(profileIds, profileIds[0] || "", {
    isImperial: profileIds.includes("imperial_money"),
    isBreakthrough: profileIds.includes("breakthrough"),
  });
  const threadMaterial = bracelet.threadMaterial || hardware.threadMaterial || bracelet.thread || "ювелірний тросик";
  const metalTone = bracelet.metalTone || hardware.metalTone || bracelet.metal || "метал";
  const metalColor = bracelet.metalColor || hardware.metalColor || "#c49a31";
  const metalShadow = bracelet.metalShadow || hardware.metalShadow || "#6f4e14";
  const clasp = bracelet.clasp || hardware.clasp;
  const connectors = bracelet.connectors || hardware.connectors;
  const spacers = bracelet.spacers || hardware.spacers || [];
  const assembly = bracelet.assembly || hardware.assembly || [];
  const beads = bracelet.sequence.map((item, i) => {
    const angle = -Math.PI / 2 + (Math.PI * 2 * i) / bracelet.sequence.length;
    const x = center + Math.cos(angle) * radiusX;
    const y = center + Math.sin(angle) * radiusY;
    const r = item.role.includes("замок") ? 18 : item.role.includes("печать") ? 15 : 13;
    return { ...item, x, y, r, angle };
  });
  const links = beads.map((bead, i) => {
    const next = beads[(i + 1) % beads.length];
    const x = (bead.x + next.x) / 2;
    const y = (bead.y + next.y) / 2;
    const angle = Math.atan2(next.y - bead.y, next.x - bead.x) * 180 / Math.PI;
    const major = bead.role.includes("замок") || next.role.includes("замок") || bead.role.includes("печать") || i % 6 === 2;
    return { x, y, angle, major };
  });
  const stoneCounts = bracelet.stones.map(stone => ({
    ...stone,
    count: bracelet.sequence.filter(item => item.id === stone.id).length,
  }));
  return (
    <div className="bracelet" aria-label={`Браслет: ${bracelet.intent}`}>
      <div className="bracelet__top">
        <div>
          <div className="bracelet__eyebrow">Crystal Alchemy · формула</div>
          <div className="bracelet__title">{bracelet.title}</div>
        </div>
        <div className="bracelet__meta">
          <span>{bracelet.date}</span>
          <small>{bracelet.sunSign || "без знаку"}{bracelet.lifePath ? ` · шлях ${bracelet.lifePath}` : ""}</small>
        </div>
      </div>
      <div className="bracelet__grid">
        <svg className="bracelet__svg" viewBox={`0 0 ${size} ${size}`} role="img">
          <defs>
            <radialGradient id="braceletGlow" cx="50%" cy="50%" r="50%">
              <stop offset="0%" stopColor="#e8d28a" stopOpacity="0.36" />
              <stop offset="62%" stopColor="#9f7d21" stopOpacity="0.08" />
              <stop offset="100%" stopColor="#000000" stopOpacity="0" />
            </radialGradient>
            <linearGradient id="braceletMetal" x1="0%" x2="100%">
              <stop offset="0%" stopColor={metalShadow} />
              <stop offset="44%" stopColor={metalColor} />
              <stop offset="72%" stopColor="#f5df86" />
              <stop offset="100%" stopColor={metalShadow} />
            </linearGradient>
            {bracelet.stones.map(stone => (
              <radialGradient id={`stone-${stone.id}`} key={stone.id} cx="35%" cy="30%" r="72%">
                <stop offset="0%" stopColor="#fff7d2" stopOpacity="0.72" />
                <stop offset="34%" stopColor={stone.colors[1]} />
                <stop offset="100%" stopColor={stone.colors[0]} />
              </radialGradient>
            ))}
          </defs>
          <ellipse cx={center} cy={center} rx={radiusX + 16} ry={radiusY + 16} fill="url(#braceletGlow)" />
          <ellipse className="bracelet__cord bracelet__cord--shadow" cx={center} cy={center} rx={radiusX + 1} ry={radiusY + 1} fill="none" stroke={threadColorOrDefault(bracelet, hardware)} strokeWidth="10" />
          <ellipse className="bracelet__cord" cx={center} cy={center} rx={radiusX} ry={radiusY} fill="none" stroke={threadColorOrDefault(bracelet, hardware)} strokeWidth="4" strokeDasharray="9 5" />
          <ellipse cx={center} cy={center} rx={radiusX} ry={radiusY} fill="none" stroke="rgba(220, 183, 72, 0.28)" strokeWidth="1.5" strokeDasharray="5 8" />
          <ellipse cx={center} cy={center} rx={radiusX - 46} ry={radiusY - 36} fill="none" stroke="rgba(220, 183, 72, 0.12)" strokeWidth="1" />
          <g className="bracelet__clasp">
            <text x={center} y="32" textAnchor="middle">замок</text>
            <path d={`M${center - 42} 54 C${center - 28} 31 ${center + 28} 31 ${center + 42} 54`} fill="none" stroke="url(#braceletMetal)" strokeWidth="7" strokeLinecap="round" />
            <rect x={center - 20} y="45" width="40" height="14" rx="7" fill="rgba(12,9,6,0.88)" stroke="url(#braceletMetal)" strokeWidth="2" />
            <circle cx={center - 29} cy="61" r="7" fill="none" stroke="url(#braceletMetal)" strokeWidth="3" />
            <circle cx={center + 29} cy="61" r="7" fill="none" stroke="url(#braceletMetal)" strokeWidth="3" />
          </g>
          {links.map((link, i) => (
            <g key={`link-${i}`} className={`bracelet__connector${link.major ? " bracelet__connector--major" : ""}`} transform={`translate(${link.x} ${link.y}) rotate(${link.angle})`}>
              <rect x={link.major ? -11 : -7} y={link.major ? -4 : -2.8} width={link.major ? 22 : 14} height={link.major ? 8 : 5.6} rx={link.major ? 4 : 2.8} fill="url(#braceletMetal)" />
              {link.major && <circle cx="0" cy="0" r="3" fill="rgba(12,9,6,0.72)" stroke="rgba(255,239,173,0.55)" strokeWidth="0.8" />}
            </g>
          ))}
          <g className="bracelet__svg-labels">
            <path d={`M${center - radiusX - 8} ${center - 4} L68 142`} />
            <text x="42" y="136">нитка</text>
            <path d={`M${center + radiusX - 8} ${center + 10} L360 156`} />
            <text x="322" y="150">метал</text>
            <path d={`M${center + 76} ${center + radiusY - 24} L344 346`} />
            <text x="288" y="363">стопери</text>
          </g>
          {beads.map((bead, i) => (
            <g key={`${bead.index}-${bead.id}`} className="bracelet__bead" style={{ animationDelay: `${120 + i * 28}ms` }}>
              <circle cx={bead.x} cy={bead.y} r={bead.r + 3} fill="rgba(0,0,0,0.34)" />
              <circle cx={bead.x} cy={bead.y} r={bead.r} fill={`url(#stone-${bead.id})`} stroke={bead.role.includes("замок") ? "#e4c65d" : "rgba(238, 210, 128, 0.5)"} strokeWidth={bead.role.includes("замок") ? 2 : 1.1} />
              <circle cx={bead.x - bead.r * 0.25} cy={bead.y - bead.r * 0.28} r={Math.max(2.2, bead.r * 0.18)} fill="rgba(255,255,255,0.42)" />
            </g>
          ))}
          <g className="bracelet__center">
            <circle cx={center} cy={center} r="54" fill="rgba(14, 11, 8, 0.82)" stroke="rgba(220, 183, 72, 0.48)" />
            <text x={center} y={center - 8} textAnchor="middle">AZOTH</text>
            <text x={center} y={center + 16} textAnchor="middle">{bracelet.beadCount} намистин</text>
          </g>
        </svg>
        <div className="bracelet__side">
          <div className="bracelet__intent">{bracelet.intent}</div>
          <div className="bracelet__formula">
            <div><span>Замок</span><b>{bracelet.anchor.name}</b></div>
            <div><span>Підсилювач</span><b>{bracelet.amplifier.name}</b></div>
            <div><span>Печать</span><b>{bracelet.seal.name}</b></div>
          </div>
          <div className="bracelet__hardware">
            <div><span>Нитка</span><b>{threadMaterial}</b></div>
            <div><span>Метал</span><b>{metalTone}</b></div>
            <div><span>Фурнітура</span><b>{clasp}</b></div>
            <div><span>Конектори</span><b>{connectors}</b></div>
            <div><span>Розмір</span><b>{bracelet.beadSize}</b></div>
          </div>
          <div className="bracelet__spacers">
            {spacers.map((spacer, i) => (
              <div className="bracelet__spacer" key={`${spacer.name}-${i}`}>
                <i style={{ background: spacer.color }} />
                <span>{spacer.name}</span>
                <b>{spacer.role}</b>
              </div>
            ))}
          </div>
          <div className="bracelet__assembly">
            {assembly.slice(0, 4).map((step, i) => (
              <div className="bracelet__assembly-row" key={`${i}-${step}`}>
                <span>{String(i + 1).padStart(2, "0")}</span>
                <b>{step}</b>
              </div>
            ))}
          </div>
          <div className="bracelet__legend">
            {stoneCounts.map(stone => (
              <div className="bracelet__stone" key={stone.id}>
                <i style={{ background: `linear-gradient(135deg, ${stone.colors[0]}, ${stone.colors[1]})` }} />
                <span>{stone.name}</span>
                <b>{stone.count}</b>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function threadColorOrDefault(bracelet, hardware) {
  return bracelet.threadColor || hardware.threadColor || "#171411";
}

Object.assign(window, {
  BRACELET_STONES,
  buildBraceletBlueprint,
  shouldBuildBracelet,
  buildBraceletContext,
  BraceletView,
});
