/* innerbloom — Rainbow Number tool — full version matching main branch */
const { useState: useStateR, useEffect: useEffectR, useRef: useRefR } = React;

/* ── Main-number descriptions ───────────────────────────────────────────── */
const MND_DATA = {
  1: { yuan: "由无到有，纯粹能量", high: "意志专一、独立自信、原创力强", low: "主观自我、顽固、无自信、猜忌、霸道", life: "独立自主，建立自信，开发原创力，学谦虚", love: "较自我，需被崇拜，专情" },
  2: { yuan: "两点间连成直线，探索相对性", high: "为别人设想、体贴、察言观色、宽恕", low: "缺乏主见、犹豫不决、说谎", life: "从委曲求全到真诚接受，学习平衡", love: "喜恋爱亲密感，浪漫互补型" },
  3: { yuan: "跳出直线外成三角形，拥有1的创造力与2的洞见能力", high: "新思维和创意、从旧中革新、乐观转念、数3是美和艺术", low: "任性爱讲话多嘴、容易喜新厌旧滥情、沟通弱不知所云", life: "丰富生命经验，创意完整沟通，接受梦想积极进取，要知足", love: "眼光很高完美要求对方，极度投入与执着，太任性" },
  4: { yuan: "三角形内包含新点，受保护与巩固", high: "理智务实勤劳、安全感定心定性、逻辑有主见组织力强", low: "功利主义物欲强、无安全感无责任感、自私自利宅男(女)", life: "倾全力建构安全感，深入内心探索自我，谨慎做抉择不推卸责任", love: "家庭缘深，初冷后热，恋爱对象等于结婚对象" },
  5: { yuan: "五芒星，代表人类自身的圆满和神秘的秘意", high: "少年早成、积极热情勇敢主动、心通灵感、内观正气", low: "醉生梦死易迷失、五分钟热度没耐心半途而废、放纵任性", life: "学习担当责任，寻找真自由，自我营销，学习专心集中精力", love: "期待各自拥有自由空间，一见钟情五分钟热度，初热后冷" },
  6: { yuan: "六角形，象征护持、疗愈、自我牺牲、慈悲为怀", high: "照顾关怀体贴服务奉献、大爱疗愈者慈爱", low: "不是天使就是恶魔、太自我占有欲忌妒心、极度要求对方完美", life: '学着用健康平衡关系与别人相处，追求的是"真爱"', love: "绝对爱情观，喜欢浪漫氛围有情调，容易陷在不开心的感情关系里" },
  7: { yuan: "两个交迭三角形中心出现第7点，代表灵性、灵光乍现", high: "相信内在感应瞬间直觉、贵人福报感恩、好学认真研究", low: "个性急冲动意气用事、质疑猜忌疑心病、好大喜功", life: "管理懒散拖延个性，正视恐惧面对现实，相信内在直觉力", love: "戏剧化浪漫一见钟情，婚后运势好，当关系有压力会开始抗拒" },
  8: { yuan: "八角形意喻八卦图，全方位强力能量的互动", high: "心想事成洞悉先机、成熟内敛冷静判断、诚实做真人真事", low: "好胜爱面子骄傲、欲望无底洞赌博投机、独断独裁不择手段", life: "真诚的爱钱，经营人脉，培养预知未来能力，对自己和他人诚实", love: "爱憎分明情绪多变，婚后情绪较温和有趣，追求感情火力大" },
  9: { yuan: "身心灵三个三角形能量重迭，代表释放、牺牲、割舍", high: "灵修宗教、服务人类救难家、无我大我智慧、美梦成真舍得", low: "醉生梦死逃避现实、爱幻想好逸恶劳、自私自利自欺欺人", life: "专注于实现梦想，虚心接受批评，超越逻辑思维，修智慧与慈悲", love: "异性缘好，对象选择条件较高，爱情的奴隶" },
};

/* ── Helpers ─────────────────────────────────────────────────────────────── */
function buildDateStr(d) {
  const y = d.y.trim();
  const m = d.m.trim().padStart(2, "0");
  const dd = d.d.trim().padStart(2, "0");
  if (y.length !== 4 || !m || !dd) return null;
  const yn = +y, mn = +m, dn = +dd;
  if (yn < 1900 || yn > 2100 || mn < 1 || mn > 12 || dn < 1 || dn > 31) return null;
  const test = new Date(yn, mn - 1, dn);
  if (test.getMonth() !== mn - 1 || test.getDate() !== dn) return null;
  return `${y}-${m}-${dd}`;
}

function getLunarDateStr(solarDateStr) {
  if (!solarDateStr || typeof RainbowCalculator === "undefined") return null;
  try {
    const ld = new RainbowCalculator().solarToLunar(solarDateStr);
    if (!ld) return null;
    return `${ld.year}-${String(ld.month).padStart(2, "0")}-${String(ld.day).padStart(2, "0")}`;
  } catch (e) { return null; }
}

function getLunarDisplayStr(solarDateStr, lang) {
  if (!solarDateStr) return "—";
  try {
    const [y, m, d] = solarDateStr.split("-").map(Number);
    if (typeof Solar !== "undefined") {
      const lunar = Solar.fromYmd(y, m, d).getLunar();
      if (lang === "zh") return `${lunar.getYearInChinese()}年 ${lunar.getMonthInChinese()}月${lunar.getDayInChinese()}`;
      return `${lunar.getYear()}/${String(lunar.getMonth()).padStart(2,"0")}/${String(lunar.getDay()).padStart(2,"0")}`;
    }
    const lds = getLunarDateStr(solarDateStr);
    if (lds) { const [ly, lm, ld2] = lds.split("-"); return lang === "zh" ? `${ly}年 ${lm}月${ld2}日` : lds; }
    return "—";
  } catch (e) { return "—"; }
}

function fullReduce(n) { while (n > 9) n = String(n).split("").reduce((a, c) => a + +c, 0); return n || 1; }

/* ── DateGroup ────────────────────────────────────────────────────────────── */
function DateGroup({ d, set, nextRef }) {
  const mRef = useRefR(null), dRef = useRefR(null);

  function handleYear(raw) {
    const v = raw.replace(/\D/g, "").slice(0, 4);
    set({ ...d, y: v });
    if (v.length === 4 && mRef.current) mRef.current.focus();
  }

  function handleMonth(raw) {
    const v = raw.replace(/\D/g, "").slice(0, 2);
    if (v === "") { set({ ...d, m: "" }); return; }
    const num = +v;
    if (v.length === 2 && (num < 1 || num > 12)) return;
    if (v.length === 1 && num >= 2) {
      set({ ...d, m: "0" + v });
      if (dRef.current) dRef.current.focus();
      return;
    }
    set({ ...d, m: v });
    if (v.length === 2 && dRef.current) dRef.current.focus();
  }

  function handleDay(raw) {
    const v = raw.replace(/\D/g, "").slice(0, 2);
    if (v === "") { set({ ...d, d: "" }); return; }
    const num = +v;
    if (v.length === 2 && (num < 1 || num > 31)) return;
    if (v.length === 1 && num >= 4) {
      set({ ...d, d: "0" + v });
      if (nextRef && nextRef.current) nextRef.current.focus();
      return;
    }
    set({ ...d, d: v });
    if (v.length === 2 && nextRef && nextRef.current) nextRef.current.focus();
  }

  return (
    <div className="date-parts-group">
      <input className="date-part-input year-input" inputMode="numeric" placeholder="YYYY" maxLength="4"
        value={d.y} onChange={(e) => handleYear(e.target.value)} />
      <span className="date-part-sep">/</span>
      <input className="date-part-input month-input" inputMode="numeric" placeholder="MM" maxLength="2"
        ref={mRef} value={d.m} onChange={(e) => handleMonth(e.target.value)} />
      <span className="date-part-sep">/</span>
      <input className="date-part-input day-input" inputMode="numeric" placeholder="DD" maxLength="2"
        ref={dRef} value={d.d} onChange={(e) => handleDay(e.target.value)} />
    </div>
  );
}

/* ── PersonCard ───────────────────────────────────────────────────────────── */
function PersonCard({ n, label, d, setD, t, setT, lunarDisplay, onDateChange, lang }) {
  const hRef = useRefR(null), minRef = useRefR(null);

  function handleHour(raw) {
    const v = raw.replace(/\D/g, "").slice(0, 2);
    if (v === "") { setT({ ...t, h: "" }); return; }
    const num = +v;
    if (v.length === 2 && num > 23) return;
    if (v.length === 1 && num >= 3) {
      setT({ ...t, h: "0" + v });
      if (minRef.current) minRef.current.focus();
      return;
    }
    setT({ ...t, h: v });
    if (v.length === 2 && minRef.current) minRef.current.focus();
  }

  function handleMinute(raw) {
    const v = raw.replace(/\D/g, "").slice(0, 2);
    if (v === "") { setT({ ...t, min: "" }); return; }
    const num = +v;
    if (v.length === 2 && num > 59) return;
    if (v.length === 1 && num >= 6) {
      setT({ ...t, min: "0" + v });
      return;
    }
    setT({ ...t, min: v });
  }

  return (
    <section className="person-card">
      <div className="card-label">
        <span className={"card-label-dot " + (n === 1 ? "dot-gold" : "dot-blue")}></span>
        <span>{label}</span>
      </div>
      <div className="picker-group">
        <div className="picker-row-label">{tt(lang, "rt_solar_bday")}</div>
        <div className="date-time-row">
          <DateGroup d={d} set={onDateChange} nextRef={hRef} />
          <div className="time-parts-group">
            <input className="time-part-input hour-input" inputMode="numeric" placeholder="HH" maxLength="2"
              ref={hRef} value={t.h} onChange={(e) => handleHour(e.target.value)} />
            <span className="time-part-sep">:</span>
            <input className="time-part-input min-input" inputMode="numeric" placeholder="MM" maxLength="2"
              ref={minRef} value={t.min} onChange={(e) => handleMinute(e.target.value)} />
            <div className="cal-btn-wrap"><button className="cal-btn" tabIndex="-1"><IbIcon.Clock width="16" height="16" /></button></div>
          </div>
        </div>
      </div>
      {lunarDisplay && lunarDisplay !== "—" && (
        <div className="lunar-display-row">
          <span className="lunar-row-label">{tt(lang, "rt_lunar_bday")} <span className="auto-badge">{tt(lang, "rt_auto")}</span></span>
          <span className="lunar-row-value">{lunarDisplay}</span>
        </div>
      )}
    </section>
  );
}

/* ── RainbowRow ───────────────────────────────────────────────────────────── */
function RainbowRow({ solarDate, lunarDate, lunarDisplay, lang, calc }) {
  const solarSum = calc.calculateSum(solarDate.replace(/-/g, ""));
  const solarFmt = calc.formatRainbowNumber(solarSum);
  let lunarFmt = "—";
  if (lunarDate) {
    const lunarSum = calc.calculateSum(lunarDate.replace(/-/g, ""));
    lunarFmt = calc.formatRainbowNumber(lunarSum);
  }
  return (
    <div className="rainbow-results">
      <div className="rr-row">
        <div className="rr-item rr-solar">
          <span className="rr-sign">+</span>
          <span className="rr-num">{solarFmt}</span>
          <div className="rr-info">
            <span className="rr-type">{lang === "zh" ? "阳历" : "Solar"}</span>
            <span className="rr-date">{solarDate}</span>
          </div>
        </div>
        <div className="rr-sep"></div>
        <div className="rr-item rr-lunar">
          <span className="rr-sign">−</span>
          <span className="rr-num">{lunarFmt}</span>
          <div className="rr-info">
            <span className="rr-type">{lang === "zh" ? "阴历" : "Lunar"}</span>
            <span className="rr-date">{lunarDate ? lunarDisplay : "—"}</span>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── BirthInfoTable ───────────────────────────────────────────────────────── */
function BirthInfoTable({ date, hasHour, hasMinute, h, min, label, lang, calc }) {
  if (!date) return null;
  const [year, month, day] = date.split("-").map(Number);
  const mm = String(month).padStart(2, "0");
  const dd = String(day).padStart(2, "0");
  const hh = hasHour ? String(+h || 0).padStart(2, "0") : "00";
  const mi = hasMinute ? String(+min || 0).padStart(2, "0") : "00";
  const DASH = "–";

  const yearPH   = calc.calculateSum(String(year));
  const monthPH  = calc.calculateSum(String(year) + mm);
  const dayPH    = calc.calculateSum(String(year) + mm + dd);
  const hourPH   = hasHour   ? calc.calculateSum(String(year) + mm + dd + hh) : null;
  const minPH    = hasMinute ? calc.calculateSum(String(year) + mm + dd + hh + mi) : null;
  const birthDig = String(year) + mm + dd;

  function getSoul(ph) {
    if (ph == null) return DASH;
    try { const s = calc.computeSoulLevel(birthDig, ph, calc.reduceToTwoDigits(ph)); return s ? (s.soulLevel ?? DASH) : DASH; } catch (e) { return DASH; }
  }

  const cols = [
    { d: String(year), ph: calc.formatPostHeavenNumber(yearPH),  life: calc.reduceToSingleDigit(yearPH),  sl: getSoul(yearPH) },
    { d: mm,           ph: calc.formatPostHeavenNumber(monthPH), life: calc.reduceToSingleDigit(monthPH), sl: getSoul(monthPH) },
    { d: dd,           ph: calc.formatPostHeavenNumber(dayPH),   life: calc.reduceToSingleDigit(dayPH),   sl: getSoul(dayPH) },
    { d: hasHour   ? hh : DASH, ph: hasHour   ? calc.formatPostHeavenNumber(hourPH) : DASH, life: hasHour   ? calc.reduceToSingleDigit(hourPH) : DASH, sl: getSoul(hourPH) },
    { d: hasMinute ? mi : DASH, ph: hasMinute ? calc.formatPostHeavenNumber(minPH)  : DASH, life: hasMinute ? calc.reduceToSingleDigit(minPH)  : DASH, sl: getSoul(minPH) },
  ];
  const colH = lang === "zh" ? ["年","月","日","时","分"] : ["Year","Mo","Day","Hr","Min"];
  const rowH = lang === "zh" ? ["日期","后天数","主命数","灵魂层次"] : ["Date","Post-Heaven","Life Path","Soul Level"];

  return (
    <div className="birth-table">
      <div className="table-header"><h4>{label} — {date}</h4></div>
      <div style={{ overflowX: "auto" }}>
        <table className="birth-calculation-table">
          <thead>
            <tr>
              <th style={{ fontSize: 11, padding: "6px 4px" }}>{lang === "zh" ? "项目" : "Item"}</th>
              {colH.map((c, i) => <th key={i} style={{ fontSize: 11, padding: "6px 4px" }}>{c}</th>)}
            </tr>
          </thead>
          <tbody>
            <tr>
              <td className="label-cell">{rowH[0]}</td>
              {cols.map((c, i) => <td key={i} className="date-cell">{c.d}</td>)}
            </tr>
            <tr>
              <td className="label-cell">{rowH[1]}</td>
              {cols.map((c, i) => <td key={i} className="post-heaven-cell">{c.ph}</td>)}
            </tr>
            <tr>
              <td className="label-cell">{rowH[2]}</td>
              {cols.map((c, i) => <td key={i} className="master-cell">{c.life}</td>)}
            </tr>
            <tr>
              <td className="label-cell">{rowH[3]}</td>
              {cols.map((c, i) => {
                const sl = c.sl;
                const hasLevel = sl !== DASH && sl != null;
                return (
                  <td key={i} className={"soul-cell" + (hasLevel ? ` soul-level-${sl}` : "")}>
                    <span className={"soul-circle" + (!hasLevel ? " soul-circle-empty" : "")}>{sl}</span>
                  </td>
                );
              })}
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ── MainNumDesc ──────────────────────────────────────────────────────────── */
function MainNumDesc({ solarNum, lunarNum, solarLabel, lunarLabel, lang }) {
  const TAGS = lang === "zh"
    ? { yuan: "源由", high: "高阶", low: "低阶", life: "功课", love: "爱情" }
    : { yuan: "Origin", high: "High", low: "Low", life: "Lesson", love: "Love" };
  const TAG_CLS = { yuan: "mnd-tag-yuan", high: "mnd-tag-high", low: "mnd-tag-low", life: "mnd-tag-life", love: "mnd-tag-love" };

  const renderBlock = (num, label) => {
    const d = MND_DATA[num];
    if (!d) return null;
    return (
      <div key={num + label} className={"mnd-block mnd-num-" + num}>
        <div className="mnd-header">
          <span className="mnd-num-badge">{num}</span>
          <span className="mnd-label">{label} · {lang === "zh" ? "主命数" : "Main #"} {num}</span>
        </div>
        <div className="mnd-body">
          {["yuan","high","low","life","love"].map(k => (
            <div key={k} className="mnd-row">
              <span className={"mnd-tag " + TAG_CLS[k]}>{TAGS[k]}</span>
              <span className="mnd-text">{d[k]}</span>
            </div>
          ))}
        </div>
      </div>
    );
  };

  return (
    <div className="main-number-desc-panel">
      <div className="mnd-title">{lang === "zh" ? "主命数解析" : "Main Number"} <span className="mnd-subtitle">{lang === "zh" ? "（日柱）" : "(Day pillar)"}</span></div>
      {renderBlock(solarNum, solarLabel)}
      {lunarNum !== null && lunarNum !== solarNum && renderBlock(lunarNum, lunarLabel)}
    </div>
  );
}

/* ── TreeDiagram ─────────────────────────────────────────────────────────── */
function TreeDiagram({ solarDate, lunarDate, name, lang, calc }) {
  if (!solarDate) return null;
  const NODE_R = 22;
  const W = 260;
  const triangleTop = NODE_R + 4;
  const triangleH = Math.round(W * 0.72);
  const halfW = Math.round(W / 2);

  const topX  = halfW,   topY  = triangleTop;
  const leftX = NODE_R,  leftY = triangleTop + triangleH;
  const rightX = W - NODE_R, rightY = triangleTop + triangleH;
  const containerH = triangleTop + triangleH + 30;

  const [by, bm, bd] = solarDate.split("-").map(Number);
  const bmm = String(bm).padStart(2, "0"), bdd = String(bd).padStart(2, "0");

  let lby = by, lmm = bmm, ldd = bdd;
  if (lunarDate) { const [a, b, c] = lunarDate.split("-"); lby = +a; lmm = b; ldd = c; }
  const lunarOffset = lby - by;

  const now = new Date();
  const ny = now.getFullYear(), nm = now.getMonth() + 1, nd = now.getDate();
  let flowYear = ny;
  if (nm < bm || (nm === bm && nd < bd)) flowYear = ny - 1;

  const curSolarFlow = fullReduce(calc.calculateSum(String(flowYear) + bmm + bdd));
  const curLunarFlow = fullReduce(calc.calculateSum(String(flowYear + lunarOffset) + lmm + ldd));

  const cycles = [];
  for (let i = 0; i < 9; i++) {
    const sy = by + i, ly2 = lby + i;
    cycles.push({
      solar: fullReduce(calc.calculateSum(String(sy) + bmm + bdd)),
      lunar: fullReduce(calc.calculateSum(String(ly2) + lmm + ldd)),
      year: sy,
      isCurrent: sy === ny,
    });
  }

  const lerp = (a, b, t) => a + (b - a) * t;
  const pts = [
    { x: leftX, y: leftY },
    { x: lerp(leftX, topX, 0.33), y: lerp(leftY, topY, 0.33) },
    { x: lerp(leftX, topX, 0.67), y: lerp(leftY, topY, 0.67) },
    { x: topX, y: topY },
    { x: lerp(rightX, topX, 0.67), y: lerp(rightY, topY, 0.67) },
    { x: lerp(rightX, topX, 0.33), y: lerp(rightY, topY, 0.33) },
    { x: rightX, y: rightY },
    { x: lerp(rightX, leftX, 0.33), y: rightY },
    { x: lerp(rightX, leftX, 0.67), y: rightY },
  ];

  let markerX = null, markerY = null;
  const ci = cycles.findIndex(c => c.solar === curSolarFlow && c.lunar === curLunarFlow);
  if (ci !== -1 && ci < 8) {
    markerX = (pts[ci].x + pts[ci + 1].x) / 2;
    markerY = (pts[ci].y + pts[ci + 1].y) / 2;
  } else {
    let best = 0, minD = Infinity;
    cycles.forEach((c, i) => {
      const dist = Math.abs(c.solar - curSolarFlow) + Math.abs(c.lunar - curLunarFlow);
      if (dist < minD) { minD = dist; best = i; }
    });
    markerX = pts[best].x; markerY = pts[best].y;
  }

  return (
    <div className="tree-diagram">
      <h3>{lang === "zh" ? "九年周期" : "9-Year Cycle"}</h3>
      {name && <div className="section-person-label">{name}</div>}
      <div className="triangle-container" style={{ width: W, height: containerH, position: "relative", margin: "0 auto", overflow: "visible" }}>
        <svg className="triangle-svg" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", overflow: "visible", pointerEvents: "none" }}>
          <polyline points={`${leftX},${leftY} ${topX},${topY} ${rightX},${rightY} ${leftX},${leftY}`}
            fill="none" stroke="rgba(150,110,130,0.20)" strokeWidth="1.5" />
        </svg>
        {pts.map((pt, i) => {
          const c = cycles[i];
          return (
            <div key={i} className="triangle-point" style={{ position: "absolute", left: pt.x, top: pt.y, transform: "translate(-50%,-50%)" }}>
              <div className={"number-display" + (c.isCurrent ? " current-year" : "")}>
                <div className="positive">+{c.solar}</div>
                <div className="negative">−{c.lunar}</div>
                {c.isCurrent && <div className="current-indicator">{lang === "zh" ? "今年" : "NOW"}</div>}
              </div>
            </div>
          );
        })}
        {markerX !== null && (
          <div className="flow-marker-dot" style={{ position: "absolute", left: markerX, top: markerY, transform: "translate(-50%,-50%)" }} />
        )}
      </div>
    </div>
  );
}

/* ── AnnualTables ─────────────────────────────────────────────────────────── */
function AnnualTables({ solarDate, lunarDate, name, lang, calc }) {
  const [open, setOpen] = useStateR(false);
  if (!solarDate) return null;
  const [by, bm, bd] = solarDate.split("-").map(Number);
  const bmm = String(bm).padStart(2, "0"), bdd = String(bd).padStart(2, "0");
  let lby = by, lmm = bmm, ldd = bdd;
  if (lunarDate) { const [a, b, c] = lunarDate.split("-"); lby = +a; lmm = b; ldd = c; }
  const now = new Date(), ny = now.getFullYear(), nm = now.getMonth() + 1, nd = now.getDate();

  const fmtFlow = (n) => {
    if (n < 10) return `0${n}/${n}`;
    const r1 = calc.calculateSum(String(n));
    if (r1 >= 10) return `${n}/${r1}/${calc.calculateSum(String(r1))}`;
    return `${n}/${r1}`;
  };

  const sections = [];
  for (let sec = 0; sec < 11; sec++) {
    const rows = { age: [], year: [], solar: [], lunar: [] };
    for (let i = 0; i < 9; i++) {
      const age = sec * 9 + i + 1;
      const sy = by + age - 1, ly = lby + age - 1;
      const isCur = nm > bm || (nm === bm && nd >= bd) ? sy === ny : sy === ny - 1;
      const sf = calc.calculateSum(String(sy) + bmm + bdd);
      const lf = calc.calculateSum(String(ly) + lmm + ldd);
      const cls = isCur ? " current-year-cell" : "";
      rows.age.push({ v: age, cls });
      rows.year.push({ v: sy, cls });
      rows.solar.push({ v: fmtFlow(sf), cls });
      rows.lunar.push({ v: fmtFlow(lf), cls });
    }
    sections.push(rows);
  }

  const aH = lang === "zh" ? "岁" : "Age";
  const yH = lang === "zh" ? "年份" : "Year";
  const sH = lang === "zh" ? "阳" : "Solar";
  const lH = lang === "zh" ? "阴" : "Lunar";

  return (
    <div className="annual-tables">
      <button className="annual-tables-toggle" onClick={() => setOpen(!open)}>
        <span className="toggle-label">{open ? (lang === "zh" ? "隐藏流年表" : "Hide Flow Year") : (lang === "zh" ? "查看流年表" : "Show Flow Year")}</span>
        <span className="toggle-meta">{by}–{by + 98}</span>
        <span className="toggle-chevron">{open ? "▾" : "▸"}</span>
        {name && <span className="toggle-person">{name}</span>}
      </button>
      {open && (
        <div className="annual-tables-content">
          {sections.map((rows, si) => (
            <div key={si} className="annual-table-section">
              <div className="annual-table-container">
                <table className="annual-table">
                  <colgroup>
                    <col style={{ width: "22%" }} />
                    <col span="9" style={{ width: "8.67%" }} />
                  </colgroup>
                  <tbody>
                    <tr><th>{aH}</th>{rows.age.map((c,i)=><td key={i} className={c.cls}><strong>{c.v}</strong></td>)}</tr>
                    <tr><th>{yH}</th>{rows.year.map((c,i)=><td key={i} className={c.cls}><strong>{c.v}</strong></td>)}</tr>
                    <tr><th>{sH}</th>{rows.solar.map((c,i)=><td key={i} className={c.cls}>{c.v}</td>)}</tr>
                    <tr><th>{lH}</th>{rows.lunar.map((c,i)=><td key={i} className={c.cls}>{c.v}</td>)}</tr>
                  </tbody>
                </table>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ── RelChart (2-person relationship square) ─────────────────────────────── */
function RelChart({ p1Solar, p1Lunar, p2Solar, p2Lunar, name1, name2, lang, calc }) {
  const top    = calc.reduceToRelationshipRange(p1Solar + p2Solar);
  const bottom = calc.reduceToRelationshipRange(p1Lunar + p2Lunar);
  const left   = calc.reduceToRelationshipRange(p1Solar + p2Lunar);
  const right  = calc.reduceToRelationshipRange(p2Solar + p1Lunar);
  const sL = lang === "zh" ? "阳" : "Solar";
  const lL = lang === "zh" ? "阴" : "Lunar";
  return (
    <div className="relationship-chart">
      <h3>{lang === "zh" ? "主命数关系" : "Relationship"}</h3>
      <div className="relationship-analysis">
        <div className="relationship-grid">
          <div className="main-life-relationship-square">
            <div className="relationship-square-container">
              <div className="square-with-edges">
                <div className="edge-number top-edge">{top}</div>
                <div className="edge-number bottom-edge">{bottom}</div>
                <div className="edge-number left-edge">{left}</div>
                <div className="edge-number right-edge">{right}</div>
                <div className="square-grid">
                  <div className="square-cell top-left">
                    <div className="number-display"><span className="positive">+{p1Solar}</span></div>
                    <div className="person-label">{name1} {sL}</div>
                  </div>
                  <div className="square-cell top-right">
                    <div className="number-display"><span className="positive">+{p2Solar}</span></div>
                    <div className="person-label">{name2} {sL}</div>
                  </div>
                  <div className="square-cell bottom-left">
                    <div className="number-display"><span className="negative">−{p1Lunar}</span></div>
                    <div className="person-label">{name1} {lL}</div>
                  </div>
                  <div className="square-cell bottom-right">
                    <div className="number-display"><span className="negative">−{p2Lunar}</span></div>
                    <div className="person-label">{name2} {lL}</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── MiniRelSquare ───────────────────────────────────────────────────────── */
function MiniRelSquare({ p1Solar, p1Lunar, p2Solar, p2Lunar, name1, name2, lang, calc }) {
  const top    = calc.reduceToRelationshipRange(p1Solar + p2Solar);
  const bottom = calc.reduceToRelationshipRange(p1Lunar + p2Lunar);
  const left   = calc.reduceToRelationshipRange(p1Solar + p2Lunar);
  const right  = calc.reduceToRelationshipRange(p2Solar + p1Lunar);
  const sL = lang === "zh" ? "阳" : "Solar";
  const lL = lang === "zh" ? "阴" : "Lunar";
  return (
    <div className="rel-period-square">
      <div className="main-life-relationship-square">
        <div className="relationship-square-container">
          <div className="square-with-edges">
            <div className="edge-number top-edge">{top}</div>
            <div className="edge-number bottom-edge">{bottom}</div>
            <div className="edge-number left-edge">{left}</div>
            <div className="edge-number right-edge">{right}</div>
            <div className="rel-col-header">
              <span>{name1}</span><span>{name2}</span>
            </div>
            <div className="square-grid">
              <div className="square-cell top-left">
                <div className="number-display"><span className="positive">+{p1Solar}</span></div>
                <div className="person-label">{sL}</div>
              </div>
              <div className="square-cell top-right">
                <div className="number-display"><span className="positive">+{p2Solar}</span></div>
                <div className="person-label">{sL}</div>
              </div>
              <div className="square-cell bottom-left">
                <div className="number-display"><span className="negative">−{p1Lunar}</span></div>
                <div className="person-label">{lL}</div>
              </div>
              <div className="square-cell bottom-right">
                <div className="number-display"><span className="negative">−{p2Lunar}</span></div>
                <div className="person-label">{lL}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── RelTimeline ──────────────────────────────────────────────────────────── */
function RelTimeline({ p1Solar, p1Lunar, p2Solar, p2Lunar, name1, name2, lang, calc }) {
  const pad = (n) => String(n).padStart(2, "0");
  const [p1by, p1bm, p1bd] = p1Solar.split("-").map(Number);
  const [p2by, p2bm, p2bd] = p2Solar.split("-").map(Number);
  const p1bmm = pad(p1bm), p1bdd = pad(p1bd);
  const p2bmm = pad(p2bm), p2bdd = pad(p2bd);

  let p1lby = p1by, p1lmm = p1bmm, p1ldd = p1bdd;
  if (p1Lunar) { const [a, b, c] = p1Lunar.split("-"); p1lby = +a; p1lmm = b; p1ldd = c; }
  let p2lby = p2by, p2lmm = p2bmm, p2ldd = p2bdd;
  if (p2Lunar) { const [a, b, c] = p2Lunar.split("-"); p2lby = +a; p2lmm = b; p2ldd = c; }

  const p1LunarOff = p1lby - p1by;
  const p2LunarOff = p2lby - p2by;
  const now = new Date(), nowY = now.getFullYear();

  const events = [];
  for (let off = -2; off <= 3; off++) {
    const y = nowY + off;
    events.push({ year: y, month: p1bm, day: p1bd, person: 1, name: name1 });
    events.push({ year: y, month: p2bm, day: p2bd, person: 2, name: name2 });
  }
  events.sort((a, b) => new Date(a.year, a.month - 1, a.day) - new Date(b.year, b.month - 1, b.day));

  const periods = [];
  for (let i = 0; i < events.length - 1; i++) {
    const from = events[i], to = events[i + 1];
    const fromD = new Date(from.year, from.month - 1, from.day);
    const toD   = new Date(to.year,   to.month   - 1, to.day);
    const isCur = now >= fromD && now < toD;
    const isPast = now >= toD;

    const p1BDY = new Date(from.year, p1bm - 1, p1bd);
    const p1FY = fromD >= p1BDY ? from.year : from.year - 1;
    const p2BDY = new Date(from.year, p2bm - 1, p2bd);
    const p2FY = fromD >= p2BDY ? from.year : from.year - 1;

    const p1S = fullReduce(calc.calculateSum(String(p1FY) + p1bmm + p1bdd));
    const p1L = fullReduce(calc.calculateSum(String(p1FY + p1LunarOff) + p1lmm + p1ldd));
    const p2S = fullReduce(calc.calculateSum(String(p2FY) + p2bmm + p2bdd));
    const p2L = fullReduce(calc.calculateSum(String(p2FY + p2LunarOff) + p2lmm + p2ldd));

    periods.push({ from, to, fromD, toD, isCur, isPast, p1S, p1L, p2S, p2L });
  }

  let lastYear = null;
  const items = [];
  periods.forEach((p, pi) => {
    const yr = p.from.year;
    if (yr !== lastYear) {
      items.push(<div key={"yr" + yr} className="rel-year-chip">{yr}</div>);
      lastYear = yr;
    }
    const fromMD = `${pad(p.from.month)}/${pad(p.from.day)}`;
    items.push(
      <div key={pi} className={"rel-period-item" + (p.isCur ? " is-current" : "") + (p.isPast ? " is-past" : "")}>
        <div className="rel-point">
          <span className={"rel-point-dot p" + p.from.person}></span>
          <span className="rel-point-date">{fromMD}</span>
        </div>
        <div className={"rel-period-card" + (p.isCur ? " is-current" : "")}>
          {p.isCur && <div className="rel-period-header"><span className="rel-now-badge">{lang === "zh" ? "当前" : "NOW"}</span></div>}
          <MiniRelSquare p1Solar={p.p1S} p1Lunar={p.p1L} p2Solar={p.p2S} p2Lunar={p.p2L} name1={name1} name2={name2} lang={lang} calc={calc} />
        </div>
      </div>
    );
  });

  return (
    <div className="relationship-timeline">
      <h3>{lang === "zh" ? "关系时间轴" : "Relationship Timeline"}</h3>
      <div className="rel-timeline-track">{items}</div>
    </div>
  );
}

/* ── PersonResults ────────────────────────────────────────────────────────── */
function PersonResults({ solarDate, lunarDate, lunarDisplay, hasHour, hasMinute, h, min, name, lang, calc, solarLabel, lunarLabel }) {
  const solarSum = calc.calculateSum(solarDate.replace(/-/g, ""));
  const solarMainNum = calc.reduceToSingleDigit(calc.calculateSum(String(+solarDate.split("-")[0]) + solarDate.split("-")[1] + solarDate.split("-")[2]));
  let lunarMainNum = null;
  if (lunarDate) {
    const [ly, lm, ld] = lunarDate.split("-");
    lunarMainNum = calc.reduceToSingleDigit(calc.calculateSum(ly + lm + ld));
  }
  const lunarNum = lunarDate ? fullReduce(calc.calculateSum(lunarDate.replace(/-/g, ""))) : null;
  const solarNum = fullReduce(solarSum);

  return (
    <div className="person-results">
      <RainbowRow solarDate={solarDate} lunarDate={lunarDate} lunarDisplay={lunarDisplay} lang={lang} calc={calc} />
      <div className="detailed-birth-info">
        <BirthInfoTable date={solarDate} hasHour={hasHour} hasMinute={hasMinute} h={h} min={min}
          label={lang === "zh" ? "阳历" : "Solar"} lang={lang} calc={calc} />
        {lunarDate && (
          <BirthInfoTable date={lunarDate} hasHour={hasHour} hasMinute={hasMinute} h={h} min={min}
            label={lang === "zh" ? "阴历" : "Lunar"} lang={lang} calc={calc} />
        )}
        <MainNumDesc solarNum={solarMainNum} lunarNum={lunarMainNum} solarLabel={solarLabel} lunarLabel={lunarLabel} lang={lang} />
      </div>
      <TreeDiagram solarDate={solarDate} lunarDate={lunarDate} name={name} lang={lang} calc={calc} />
      <AnnualTables solarDate={solarDate} lunarDate={lunarDate} name={name} lang={lang} calc={calc} />
    </div>
  );
}

/* ── RainbowTool ─────────────────────────────────────────────────────────── */
function RainbowTool({ lang, onBack, onResult }) {
  const [d1, setD1] = useStateR({ y: "", m: "", d: "" });
  const [t1, setT1] = useStateR({ h: "", min: "" });
  const [lunar1Str, setLunar1Str] = useStateR(null);
  const [lunar1Disp, setLunar1Disp] = useStateR("—");

  const [showP2, setShowP2] = useStateR(false);
  const [d2, setD2] = useStateR({ y: "", m: "", d: "" });
  const [t2, setT2] = useStateR({ h: "", min: "" });
  const [lunar2Str, setLunar2Str] = useStateR(null);
  const [lunar2Disp, setLunar2Disp] = useStateR("—");

  const [results, setResults] = useStateR(null);
  const [generating, setGenerating] = useStateR(false);
  const [error, setError] = useStateR(null);
  const [ageError, setAgeError] = useStateR(false);

  const handleDateChange1 = (next) => {
    setD1(next);
    const ds = buildDateStr(next);
    setLunar1Str(getLunarDateStr(ds));
    setLunar1Disp(getLunarDisplayStr(ds, lang));
  };
  const handleDateChange2 = (next) => {
    setD2(next);
    const ds = buildDateStr(next);
    setLunar2Str(getLunarDateStr(ds));
    setLunar2Disp(getLunarDisplayStr(ds, lang));
  };

  const swap = () => {
    setD1(d2); setT1(t2); setLunar1Str(lunar2Str); setLunar1Disp(lunar2Disp);
    setD2(d1); setT2(t1); setLunar2Str(lunar1Str); setLunar2Disp(lunar1Disp);
    setAgeError(false);
  };

  const removeP2 = () => {
    setShowP2(false);
    setD2({ y: "", m: "", d: "" }); setT2({ h: "", min: "" });
    setLunar2Str(null); setLunar2Disp("—"); setAgeError(false);
  };

  const generate = () => {
    setError(null); setAgeError(false); setResults(null);
    const ds1 = buildDateStr(d1);
    if (!ds1) { setError(lang === "zh" ? "请检查日期格式" : "Please check date format"); return; }
    if (typeof RainbowCalculator === "undefined") { setError(lang === "zh" ? "计算失败，请刷新页面" : "Calculation failed — refresh"); return; }

    const ds2 = showP2 ? buildDateStr(d2) : null;
    if (showP2 && !ds2) { setError(lang === "zh" ? "请检查第二人日期格式" : "Check Person 2 date"); return; }

    if (ds2) {
      const age1 = new Date(ds1), age2 = new Date(ds2);
      if (age2 < age1) { setAgeError(true); return; }
    }

    setGenerating(true);
    try {
      const calc = new RainbowCalculator();
      const p1 = { solarDate: ds1, lunarDate: lunar1Str, hasHour: t1.h !== "", hasMinute: t1.min !== "", h: t1.h, min: t1.min };
      const p2 = ds2 ? { solarDate: ds2, lunarDate: lunar2Str, hasHour: t2.h !== "", hasMinute: t2.min !== "", h: t2.h, min: t2.min } : null;

      const solarNum = fullReduce(calc.calculateSum(ds1.replace(/-/g, "")));
      const lunarNum = lunar1Str ? fullReduce(calc.calculateSum(lunar1Str.replace(/-/g, ""))) : solarNum;
      if (onResult) onResult({ solar: solarNum, lunar: lunarNum });
      setResults({ p1, p2, calc });
    } catch (e) {
      console.error(e);
      setError(lang === "zh" ? "计算失败，请检查日期" : "Calculation failed — check date");
    } finally {
      setGenerating(false);
    }
  };

  const sL = lang === "zh" ? "阳历" : "Solar";
  const lL = lang === "zh" ? "阴历" : "Lunar";
  const p1Name = lang === "zh" ? "本人" : "Person 1";
  const p2Name = lang === "zh" ? "第二人" : "Person 2";

  return (
    <div className="scr fade">
      <PushHeader title={tt(lang, "tool_rainbow_t")} onBack={onBack} lang={lang} solid />
      <div className="scr-scroll pushed">
        <main className="app-main" style={{ overflow: "visible", paddingTop: "var(--space-sm)" }}>

          <PersonCard n={1} label={`${tt(lang,"rt_person")} · ${p1Name}`}
            d={d1} setD={setD1} t={t1} setT={setT1}
            lunarDisplay={lunar1Disp} onDateChange={handleDateChange1} lang={lang} />

          {showP2 && (
            <div style={{ position: "relative" }}>
              <PersonCard n={2} label={`${tt(lang,"rt_person")} 2 · ${p2Name}`}
                d={d2} setD={setD2} t={t2} setT={setT2}
                lunarDisplay={lunar2Disp} onDateChange={handleDateChange2} lang={lang} />
              <button className="remove-person-btn" onClick={removeP2}>{lang === "zh" ? "移除" : "Remove"}</button>
            </div>
          )}

          {!showP2 && (
            <button className="add-person-btn" onClick={() => setShowP2(true)}>
              <span className="add-person-icon">＋</span>
              <span>{tt(lang, "rt_add")}</span>
            </button>
          )}

          {showP2 && (
            <button className="swap-btn" onClick={swap}>
              <span>⇅ {lang === "zh" ? "交换两人" : "Swap"}</span>
            </button>
          )}

          {ageError && (
            <div className="error-msg">{lang === "zh" ? "请确保第一人年龄大于第二人" : "Person 1 must be older than Person 2"}</div>
          )}

          <button className="generate-btn" onClick={generate} disabled={generating}>
            {generating
              ? <span className="generate-btn-text">{lang === "zh" ? "计算中…" : "Calculating…"}</span>
              : <><span className="generate-btn-text">{tt(lang, "rt_generate")}</span><span className="generate-btn-icon">→</span></>}
          </button>

          {error && <div className="error-msg">{error}</div>}

          {results && (() => {
            const { p1, p2, calc } = results;
            const p1SolarRed = fullReduce(calc.calculateSum(p1.solarDate.replace(/-/g, "")));
            const p1LunarRed = p1.lunarDate ? fullReduce(calc.calculateSum(p1.lunarDate.replace(/-/g, ""))) : p1SolarRed;
            const p2SolarRed = p2 ? fullReduce(calc.calculateSum(p2.solarDate.replace(/-/g, ""))) : null;
            const p2LunarRed = p2 ? (p2.lunarDate ? fullReduce(calc.calculateSum(p2.lunarDate.replace(/-/g, ""))) : p2SolarRed) : null;

            return (
              <div className="results-section">
                {p2 && (
                  <div className="two-person-layout">
                    <div className="birth-info-row">
                      <PersonResults solarDate={p1.solarDate} lunarDate={p1.lunarDate} lunarDisplay={lunar1Disp}
                        hasHour={p1.hasHour} hasMinute={p1.hasMinute} h={p1.h} min={p1.min}
                        name={p1Name} lang={lang} calc={calc} solarLabel={sL} lunarLabel={lL} />
                      <PersonResults solarDate={p2.solarDate} lunarDate={p2.lunarDate} lunarDisplay={lunar2Disp}
                        hasHour={p2.hasHour} hasMinute={p2.hasMinute} h={p2.h} min={p2.min}
                        name={p2Name} lang={lang} calc={calc} solarLabel={sL} lunarLabel={lL} />
                    </div>
                    <div className="relationship-chart-row">
                      <RelChart p1Solar={p1SolarRed} p1Lunar={p1LunarRed}
                        p2Solar={p2SolarRed} p2Lunar={p2LunarRed}
                        name1={p1Name} name2={p2Name} lang={lang} calc={calc} />
                    </div>
                    <div className="relationship-timeline-row">
                      <RelTimeline p1Solar={p1.solarDate} p1Lunar={p1.lunarDate}
                        p2Solar={p2.solarDate} p2Lunar={p2.lunarDate}
                        name1={p1Name} name2={p2Name} lang={lang} calc={calc} />
                    </div>
                  </div>
                )}
                {!p2 && (
                  <PersonResults solarDate={p1.solarDate} lunarDate={p1.lunarDate} lunarDisplay={lunar1Disp}
                    hasHour={p1.hasHour} hasMinute={p1.hasMinute} h={p1.h} min={p1.min}
                    name={p1Name} lang={lang} calc={calc} solarLabel={sL} lunarLabel={lL} />
                )}
                <ConsultStrip lang={lang} />
              </div>
            );
          })()}

          <div className="flowpad"></div>
        </main>
      </div>
    </div>
  );
}
window.RainbowTool = RainbowTool;
