/* =========================================================
   AllComponents.jsx — じぶん湯 全Reactコンポーネント統合
   FluidHero / Diagnosis / RecipeBuilder /
   MoodSlider / SeasonRecipes / PlanTable
   ========================================================= */
'use strict';

/* =========================================================
   FLUID HERO — Hero背景 Canvasアニメーション
   ========================================================= */
function hexAlpha(hex, alpha) {
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return `rgba(${r},${g},${b},${alpha})`;
}

function FluidHero() {
  const canvasRef = React.useRef(null);
  const animRef   = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const colors = ['#b4563a', '#34486e', '#c4aa6c', '#5c7a4e'];

    const resize = () => {
      canvas.width  = canvas.offsetWidth;
      canvas.height = canvas.offsetHeight;
    };
    resize();
    window.addEventListener('resize', resize);

    const blobs = colors.map((color, i) => ({
      x: (canvas.width / 5) * (i + 1),
      y: canvas.height * 0.5 + (Math.random() - 0.5) * 80,
      vx: (Math.random() - 0.5) * 0.4,
      vy: (Math.random() - 0.5) * 0.3,
      r: 80 + Math.random() * 60,
      color,
      phase: i * Math.PI * 0.5,
    }));

    let t = 0;
    const draw = () => {
      const w = canvas.width, h = canvas.height;
      ctx.clearRect(0, 0, w, h);
      t += 0.005;
      blobs.forEach((b, i) => {
        b.x += b.vx + Math.sin(t * 0.7 + b.phase) * 0.25;
        b.y += b.vy + Math.cos(t * 0.5 + b.phase) * 0.18;
        if (b.x < b.r)             { b.x = b.r;             b.vx *= -0.6; }
        if (b.x > w - b.r)         { b.x = w - b.r;         b.vx *= -0.6; }
        if (b.y < b.r * 0.5)       { b.y = b.r * 0.5;       b.vy *= -0.6; }
        if (b.y > h - b.r * 0.5)   { b.y = h - b.r * 0.5;   b.vy *= -0.6; }
        const pulsedR = b.r * (1 + 0.08 * Math.sin(t * 1.2 + i));
        const grad = ctx.createRadialGradient(b.x, b.y, 0, b.x, b.y, pulsedR * 1.8);
        grad.addColorStop(0,   hexAlpha(b.color, 0.18));
        grad.addColorStop(0.5, hexAlpha(b.color, 0.09));
        grad.addColorStop(1,   hexAlpha(b.color, 0));
        ctx.beginPath();
        ctx.arc(b.x, b.y, pulsedR * 1.8, 0, Math.PI * 2);
        ctx.fillStyle = grad;
        ctx.fill();
      });
      animRef.current = requestAnimationFrame(draw);
    };
    draw();
    return () => {
      cancelAnimationFrame(animRef.current);
      window.removeEventListener('resize', resize);
    };
  }, []);

  return React.createElement('canvas', {
    ref: canvasRef,
    style: { position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none' }
  });
}
window.FluidHero = FluidHero;

/* =========================================================
   DIAGNOSIS — 3問体調診断 → パーソナル処方レシピ
   ========================================================= */
const DX_QUESTIONS = [
  {
    id: 'energy', q: '今日の気力は？', en: 'Energy Level',
    options: [
      { value: 'low',    label: '低い',   icon: '○', hint: 'くたびれぎみ' },
      { value: 'medium', label: 'ふつう', icon: '◎', hint: 'まあまあ' },
      { value: 'high',   label: '高い',   icon: '●', hint: 'エネルギッシュ' },
    ],
  },
  {
    id: 'body', q: '体のどこが気になりますか？', en: 'Body Focus',
    options: [
      { value: 'cold',    label: '冷え',    icon: '❄', hint: '末端冷え性気味' },
      { value: 'stiff',   label: 'こわばり', icon: '⊞', hint: '肩・首まわり' },
      { value: 'skin',    label: '肌荒れ',  icon: '◇', hint: 'かさつき・乾燥' },
      { value: 'fatigue', label: '疲れ',    icon: '◈', hint: '全身だるさ' },
    ],
  },
  {
    id: 'mood', q: '今夜求めるのは？', en: "Tonight's Wish",
    options: [
      { value: 'relax',   label: 'ほぐれたい',    icon: '~', hint: '頭も体も' },
      { value: 'refresh', label: 'すっきりしたい', icon: '↑', hint: '気分転換' },
      { value: 'sleep',   label: '眠りたい',      icon: '◐', hint: 'ぐっすり眠る' },
    ],
  },
];

const RECIPES = {
  'low_cold_relax':      { name: 'ぬく湯・よもぎ処方',    solid: '温浴固形',       liquid: 'ローズマリー',   flower: '多め', herb: 'よもぎ',        temp: 40, min: 20 },
  'low_cold_refresh':    { name: '炭酸+柚子処方',          solid: '炭酸タブレット', liquid: '柚子液',         flower: '少量', herb: 'ヒノキ',        temp: 39, min: 15 },
  'low_cold_sleep':      { name: '深夜の温め処方',          solid: '温浴固形',       liquid: 'ラベンダー',     flower: '多め', herb: 'よもぎ',        temp: 40, min: 25 },
  'low_stiff_relax':     { name: '肩こり解消処方',          solid: '薬用固形',       liquid: 'ユーカリ',       flower: '中量', herb: 'よもぎ+クロモジ', temp: 41, min: 20 },
  'low_stiff_refresh':   { name: '清涼ハーブ処方',          solid: '炭酸タブレット', liquid: 'ペパーミント',   flower: '少量', herb: 'クロモジ',      temp: 38, min: 15 },
  'low_stiff_sleep':     { name: 'まどろみ処方',            solid: '温浴固形',       liquid: 'ラベンダー',     flower: '多め', herb: 'スギナ',        temp: 40, min: 20 },
  'low_skin_relax':      { name: '保湿・巡り処方',          solid: 'シアバター固形', liquid: '桃の葉',         flower: '中量', herb: 'ドクダミ',      temp: 39, min: 20 },
  'low_skin_refresh':    { name: '柑橘保湿処方',            solid: 'シアバター固形', liquid: '柚子液',         flower: '少量', herb: 'ヒノキ',        temp: 38, min: 15 },
  'low_skin_sleep':      { name: '夜の保湿処方',            solid: 'シアバター固形', liquid: '桃の葉',         flower: '多め', herb: 'ドクダミ',      temp: 39, min: 20 },
  'low_fatigue_relax':   { name: '全身回復処方',            solid: '薬用固形',       liquid: 'ローズマリー',   flower: '多め', herb: 'よもぎ',        temp: 40, min: 25 },
  'low_fatigue_refresh': { name: '活力回復処方',            solid: '炭酸タブレット', liquid: 'ユーカリ',       flower: '少量', herb: 'ヒノキ',        temp: 39, min: 15 },
  'low_fatigue_sleep':   { name: '疲労解消・睡眠処方',      solid: '温浴固形',       liquid: 'ラベンダー',     flower: '多め', herb: 'スギナ',        temp: 40, min: 20 },

  'medium_cold_relax':      { name: 'やわらか温め処方',   solid: '温浴固形',       liquid: '柚子液',       flower: '中量', herb: 'よもぎ',   temp: 40, min: 15 },
  'medium_cold_refresh':    { name: '柑橘目覚め処方',     solid: '炭酸タブレット', liquid: '柚子液',       flower: '少量', herb: 'ヒノキ',   temp: 38, min: 12 },
  'medium_cold_sleep':      { name: 'ほんのり処方',       solid: '温浴固形',       liquid: 'ラベンダー',   flower: '中量', herb: 'スギナ',   temp: 39, min: 18 },
  'medium_stiff_relax':     { name: 'ふわりほぐし処方',   solid: '薬用固形',       liquid: 'ユーカリ',     flower: '中量', herb: 'クロモジ', temp: 40, min: 18 },
  'medium_stiff_refresh':   { name: 'クールダウン処方',   solid: '炭酸タブレット', liquid: 'ペパーミント', flower: '少量', herb: 'クロモジ', temp: 38, min: 12 },
  'medium_stiff_sleep':     { name: '夜のほぐし処方',     solid: '温浴固形',       liquid: 'ラベンダー',   flower: '中量', herb: 'よもぎ',   temp: 39, min: 18 },
  'medium_skin_relax':      { name: '肌うるおい処方',     solid: 'シアバター固形', liquid: '桃の葉',       flower: '中量', herb: 'ドクダミ', temp: 38, min: 18 },
  'medium_skin_refresh':    { name: '透明感処方',         solid: 'シアバター固形', liquid: '柚子液',       flower: '少量', herb: 'ヒノキ',   temp: 38, min: 12 },
  'medium_skin_sleep':      { name: '夜の肌リセット処方', solid: 'シアバター固形', liquid: '桃の葉',       flower: '多め', herb: 'ドクダミ', temp: 39, min: 20 },
  'medium_fatigue_relax':   { name: 'ゆるり回復処方',     solid: '薬用固形',       liquid: 'ローズマリー', flower: '中量', herb: 'よもぎ',   temp: 40, min: 18 },
  'medium_fatigue_refresh': { name: 'リフレッシュ処方',   solid: '炭酸タブレット', liquid: 'ユーカリ',     flower: '少量', herb: 'ヒノキ',   temp: 38, min: 12 },
  'medium_fatigue_sleep':   { name: 'ゆっくり眠り処方',   solid: '温浴固形',       liquid: 'ラベンダー',   flower: '中量', herb: 'スギナ',   temp: 39, min: 18 },

  'high_cold_relax':      { name: '活動後の温め処方',       solid: '温浴固形',       liquid: '柚子液',       flower: '少量', herb: 'よもぎ',   temp: 39, min: 12 },
  'high_cold_refresh':    { name: '爽快リフレッシュ処方',   solid: '炭酸タブレット', liquid: '柚子液',       flower: '少量', herb: 'ヒノキ',   temp: 38, min: 10 },
  'high_cold_sleep':      { name: 'ゆるやか切り替え処方',   solid: '温浴固形',       liquid: 'ラベンダー',   flower: '中量', herb: 'スギナ',   temp: 39, min: 15 },
  'high_stiff_relax':     { name: '運動後ほぐし処方',       solid: '薬用固形',       liquid: 'ユーカリ',     flower: '少量', herb: 'クロモジ', temp: 39, min: 15 },
  'high_stiff_refresh':   { name: '清涼リカバリー処方',     solid: '炭酸タブレット', liquid: 'ペパーミント', flower: '少量', herb: 'クロモジ', temp: 37, min: 10 },
  'high_stiff_sleep':     { name: 'アクティブ後の鎮静処方', solid: '薬用固形',       liquid: 'ラベンダー',   flower: '中量', herb: 'よもぎ',   temp: 39, min: 15 },
  'high_skin_relax':      { name: '艶肌処方',               solid: 'シアバター固形', liquid: '桃の葉',       flower: '少量', herb: 'ドクダミ', temp: 38, min: 15 },
  'high_skin_refresh':    { name: '光沢肌処方',             solid: 'シアバター固形', liquid: '柚子液',       flower: '少量', herb: 'ヒノキ',   temp: 37, min: 10 },
  'high_skin_sleep':      { name: '美肌おやすみ処方',       solid: 'シアバター固形', liquid: '桃の葉',       flower: '中量', herb: 'ドクダミ', temp: 38, min: 15 },
  'high_fatigue_relax':   { name: 'ピーク後の回復処方',     solid: '薬用固形',       liquid: 'ローズマリー', flower: '少量', herb: 'よもぎ',   temp: 39, min: 15 },
  'high_fatigue_refresh': { name: '体リセット処方',         solid: '炭酸タブレット', liquid: 'ユーカリ',     flower: '少量', herb: 'ヒノキ',   temp: 38, min: 10 },
  'high_fatigue_sleep':   { name: '完全回復処方',           solid: '薬用固形',       liquid: 'ラベンダー',   flower: '多め', herb: 'スギナ',   temp: 39, min: 20 },
};

const EC = { solid: '#b4563a', liquid: '#34486e', flower: '#c4aa6c', herb: '#5c7a4e' };

function Diagnosis() {
  const [step, setStep]       = React.useState(0);
  const [answers, setAnswers] = React.useState({});
  const [result, setResult]   = React.useState(null);
  const q = DX_QUESTIONS[step];

  const handleSelect = (value) => {
    const na = { ...answers, [q.id]: value };
    setAnswers(na);
    if (step < DX_QUESTIONS.length - 1) {
      setTimeout(() => setStep(step + 1), 260);
    } else {
      const key = `${na.energy}_${na.body}_${na.mood}`;
      setTimeout(() => setResult(RECIPES[key] || RECIPES['medium_fatigue_relax']), 260);
    }
  };
  const reset = () => { setStep(0); setAnswers({}); setResult(null); };

  const st = {
    wrap:       { maxWidth: 680, margin: '0 auto', padding: '0 0 40px' },
    progress:   { display: 'flex', gap: 6, marginBottom: 40 },
    bar: (a,d) => ({ flex: 1, height: 2, background: d ? '#1a1a1a' : a ? '#1a1a1a' : 'rgba(26,26,26,0.15)', transition: 'background 0.3s' }),
    qLabel:     { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#8a857b', marginBottom: 12 },
    question:   { fontFamily: '"Shippori Mincho",serif', fontSize: 'clamp(20px,3vw,28px)', fontWeight: 500, color: '#1a1a1a', marginBottom: 36, lineHeight: 1.5 },
    optGrid:    { display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(140px,1fr))', gap: 12 },
    opt: (sel) => ({ padding: '24px 16px', border: `1px solid ${sel ? '#1a1a1a' : 'rgba(26,26,26,0.15)'}`, background: sel ? 'rgba(26,26,26,0.04)' : 'rgba(255,255,255,0.5)', cursor: 'pointer', transition: 'all 0.2s', textAlign: 'center' }),
    optIcon:    { fontFamily: '"JetBrains Mono",monospace', fontSize: 20, marginBottom: 10, color: '#1a1a1a' },
    optLabel:   { fontFamily: '"Shippori Mincho",serif', fontSize: 14, fontWeight: 500, color: '#1a1a1a', marginBottom: 4 },
    optHint:    { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 10, color: '#8a857b', letterSpacing: '0.06em' },
    resultCard: { border: '1px solid rgba(26,26,26,0.2)', padding: '48px 40px', background: 'rgba(255,255,255,0.5)' },
    resLabel:   { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#8a857b', marginBottom: 20 },
    resName:    { fontFamily: '"Shippori Mincho",serif', fontSize: 'clamp(22px,3vw,32px)', fontWeight: 500, color: '#1a1a1a', marginBottom: 32, lineHeight: 1.4 },
    ingRow:     { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 32 },
    ingItem: (c) => ({ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 16px', borderLeft: `3px solid ${c}`, background: 'rgba(255,255,255,0.6)' }),
    ingDot:  (c) => ({ width: 8, height: 8, borderRadius: '50%', background: c, flexShrink: 0 }),
    ingKind:    { fontFamily: '"JetBrains Mono",monospace', fontSize: 9, color: '#8a857b', letterSpacing: '0.12em', display: 'block', marginBottom: 2 },
    ingVal:     { fontFamily: '"Shippori Mincho",serif', fontSize: 13, color: '#1a1a1a' },
    paramRow:   { display: 'flex', gap: 24, borderTop: '1px solid rgba(26,26,26,0.12)', paddingTop: 24, flexWrap: 'wrap' },
    paramItem:  { fontFamily: '"JetBrains Mono",monospace', fontSize: 11, color: '#5c584d', letterSpacing: '0.1em' },
    resetBtn:   { marginTop: 32, display: 'inline-flex', alignItems: 'center', gap: 8, fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#5c584d', border: '1px solid rgba(26,26,26,0.2)', padding: '10px 20px', cursor: 'pointer', background: 'transparent' },
  };

  const ce = React.createElement;
  if (result) {
    return ce('div', { style: st.wrap },
      ce('div', { style: st.resultCard },
        ce('div', { style: st.resLabel }, "— TODAY'S PRESCRIPTION · 本日の処方"),
        ce('div', { style: st.resName }, result.name),
        ce('div', { style: st.ingRow },
          [['solid','SOLID · 固形',result.solid],['liquid','LIQUID · 液体',result.liquid],['flower','FLOWER · 湯の花',result.flower],['herb','HERB · 和ハーブ',result.herb]]
          .map(([k,label,val]) =>
            ce('div', { key: k, style: st.ingItem(EC[k]) },
              ce('div', { style: st.ingDot(EC[k]) }),
              ce('div', null, ce('span', { style: st.ingKind }, label), ce('span', { style: st.ingVal }, val))
            )
          )
        ),
        ce('div', { style: st.paramRow },
          ce('span', { style: st.paramItem }, `TEMP · ${result.temp}.0°C`),
          ce('span', { style: st.paramItem }, `DURATION · ${result.min} MIN`)
        ),
        ce('button', { style: st.resetBtn, onClick: reset }, '← もう一度診断する')
      )
    );
  }

  return ce('div', { style: st.wrap },
    ce('div', { style: st.progress }, DX_QUESTIONS.map((_,i) => ce('div', { key: i, style: st.bar(i===step, i<step) }))),
    ce('div', { style: st.qLabel }, `Q.0${step+1} · ${q.en}`),
    ce('div', { style: st.question }, q.q),
    ce('div', { style: st.optGrid },
      q.options.map(opt =>
        ce('button', { key: opt.value, style: st.opt(answers[q.id]===opt.value), onClick: () => handleSelect(opt.value) },
          ce('div', { style: st.optIcon }, opt.icon),
          ce('div', { style: st.optLabel }, opt.label),
          ce('div', { style: st.optHint }, opt.hint)
        )
      )
    )
  );
}
window.Diagnosis = Diagnosis;

/* =========================================================
   RECIPE BUILDER — タブで4要素を最大4種選択
   ========================================================= */
const ELEMENTS = {
  solid:  { label: '固形',   en: 'SOLID',  color: '#b4563a', bg: 'rgba(180,86,58,0.08)',   items: [{ id:'solid_relax', name:'ぬくもり固形',   sub:'温浴・保温',    icon:'●' },{ id:'solid_spa',  name:'温泉固形',        sub:'硫酸塩系',      icon:'◎' },{ id:'solid_carb', name:'炭酸タブレット', sub:'血行促進',      icon:'○' },{ id:'solid_med',  name:'薬用固形',        sub:'肩こり・冷え',  icon:'◉' },{ id:'solid_shea', name:'シアバター固形', sub:'保湿・美肌',    icon:'◌' }] },
  liquid: { label: '液体',   en: 'LIQUID', color: '#34486e', bg: 'rgba(52,72,110,0.08)',    items: [{ id:'liq_rose',  name:'ローズマリー液', sub:'血行・覚醒',    icon:'▲' },{ id:'liq_lav',   name:'ラベンダー液',   sub:'鎮静・睡眠',    icon:'▽' },{ id:'liq_yuzu',  name:'柚子液',         sub:'温め・清潔感',  icon:'◁' },{ id:'liq_euca',  name:'ユーカリ液',      sub:'呼吸・清涼',    icon:'▷' },{ id:'liq_peach', name:'桃の葉液',       sub:'肌あれ・乾燥',  icon:'△' },{ id:'liq_mint',  name:'ペパーミント液', sub:'清涼・頭皽',    icon:'▼' }] },
  flower: { label: '湯の花', en: 'FLOWER', color: '#c4aa6c', bg: 'rgba(196,170,108,0.08)', items: [{ id:'flower_s', name:'湯の花 少量', sub:'やさしい濃さ', icon:'·' },{ id:'flower_m', name:'湯の花 中量', sub:'標準的な濃度', icon:':' },{ id:'flower_l', name:'湯の花 多め', sub:'濃厚な湯質',   icon:'⁝' }] },
  herb:   { label: '和ハーブ', en: 'HERB', color: '#5c7a4e', bg: 'rgba(92,122,78,0.08)',   items: [{ id:'herb_yomogi',   name:'よもぎ',   sub:'血行・抗炎症',      icon:'⌇' },{ id:'herb_hinoki',   name:'ヒノキ',   sub:'浄化・リラックス',  icon:'⌆' },{ id:'herb_kuromoji', name:'クロモジ', sub:'鎮静・高貴な香り',  icon:'⌅' },{ id:'herb_sugina',   name:'スギナ',   sub:'ミネラル・保湿',    icon:'⌈' },{ id:'herb_dokudami', name:'ドクダミ', sub:'肌あれ・デトックス', icon:'⌋' }] },
};
const MAX_SELECT = 4;

function RecipeBuilder() {
  const [selected, setSelected] = React.useState([]);
  const [activeTab, setActiveTab] = React.useState('solid');

  const toggle = (itemId, catKey) => {
    const exists = selected.find(s => s.id === itemId);
    if (exists) { setSelected(selected.filter(s => s.id !== itemId)); return; }
    if (selected.length >= MAX_SELECT) return;
    const filtered = catKey === 'flower' ? selected.filter(s => !s.id.startsWith('flower_')) : selected;
    const item = ELEMENTS[catKey].items.find(i => i.id === itemId);
    setSelected([...filtered, { ...item, catKey }]);
  };
  const isSel = (id) => selected.some(s => s.id === id);

  const ce = React.createElement;
  const s = {
    wrap:  { maxWidth: 900, margin: '0 auto' },
    tabs:  { display: 'flex', borderBottom: '1px solid rgba(26,26,26,0.15)', marginBottom: 32 },
    tab: (a,k) => ({ fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.18em', padding: '12px 20px', cursor: 'pointer', background: 'transparent', border: 'none', borderBottom: a ? `2px solid ${ELEMENTS[k].color}` : '2px solid transparent', color: a ? ELEMENTS[k].color : '#8a857b', transition: 'all 0.2s', marginBottom: -1 }),
    counter: { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: selected.length >= MAX_SELECT ? '#b4563a' : '#8a857b', marginBottom: 24 },
    grid:  { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(160px,1fr))', gap: 10, marginBottom: 40 },
    item: (sel,k) => ({ padding: '16px', border: `1px solid ${sel ? ELEMENTS[k].color : 'rgba(26,26,26,0.12)'}`, background: sel ? ELEMENTS[k].bg : 'rgba(255,255,255,0.5)', cursor: selected.length >= MAX_SELECT && !sel ? 'not-allowed' : 'pointer', opacity: selected.length >= MAX_SELECT && !sel ? 0.4 : 1, transition: 'all 0.18s', display: 'flex', flexDirection: 'column', gap: 6 }),
    itemIcon: (k) => ({ fontFamily: '"JetBrains Mono",monospace', fontSize: 18, color: ELEMENTS[k].color }),
    itemName: { fontFamily: '"Shippori Mincho",serif', fontSize: 13, fontWeight: 500, color: '#1a1a1a' },
    itemSub:  { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 10, color: '#8a857b' },
    blend:    { border: '1px solid rgba(26,26,26,0.15)', padding: '32px 28px', background: 'rgba(255,255,255,0.5)' },
    blendTitle: { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#8a857b', marginBottom: 20 },
    blendItems: { display: 'flex', flexWrap: 'wrap', gap: 10, minHeight: 52 },
    tag: (k) => ({ display: 'inline-flex', alignItems: 'center', gap: 8, padding: '8px 14px', background: ELEMENTS[k].bg, borderLeft: `3px solid ${ELEMENTS[k].color}`, fontFamily: '"Shippori Mincho",serif', fontSize: 13, color: '#1a1a1a' }),
    tagX: { fontFamily: '"JetBrains Mono",monospace', fontSize: 12, color: '#8a857b', cursor: 'pointer', lineHeight: 1, marginLeft: 4 },
    empty: { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 12, color: '#8a857b', padding: '12px 0' },
    clear: { marginTop: 20, display: 'inline-flex', gap: 6, fontFamily: '"JetBrains Mono",monospace', fontSize: 9, letterSpacing: '0.18em', color: '#8a857b', background: 'transparent', border: '1px solid rgba(26,26,26,0.12)', padding: '8px 14px', cursor: 'pointer' },
  };

  return ce('div', { style: s.wrap },
    ce('div', { style: s.tabs }, Object.keys(ELEMENTS).map(k => ce('button', { key: k, style: s.tab(activeTab===k, k), onClick: () => setActiveTab(k) }, `${ELEMENTS[k].en} · ${ELEMENTS[k].label}`))),
    ce('div', { style: s.counter }, `SELECTED ${selected.length} / ${MAX_SELECT}${selected.length >= MAX_SELECT ? ' — MAX REACHED' : ''}`),
    ce('div', { style: s.grid },
      ELEMENTS[activeTab].items.map(item =>
        ce('button', { key: item.id, style: s.item(isSel(item.id), activeTab), onClick: () => toggle(item.id, activeTab), disabled: selected.length >= MAX_SELECT && !isSel(item.id) },
          ce('div', { style: s.itemIcon(activeTab) }, item.icon),
          ce('div', { style: s.itemName }, item.name),
          ce('div', { style: s.itemSub }, item.sub)
        )
      )
    ),
    ce('div', { style: s.blend },
      ce('div', { style: s.blendTitle }, '— YOUR BLEND · 今日の処方箋'),
      ce('div', { style: s.blendItems },
        selected.length === 0
          ? ce('div', { style: s.empty }, '上から素材を選んでください。最大4種まで。')
          : selected.map(item => ce('div', { key: item.id, style: s.tag(item.catKey) },
              ce('span', null, item.name),
              ce('span', { style: s.tagX, onClick: () => setSelected(selected.filter(s => s.id !== item.id)) }, '×')
            ))
      ),
      selected.length > 0 && ce('button', { style: s.clear, onClick: () => setSelected([]) }, '× CLEAR ALL')
    )
  );
}
window.RecipeBuilder = RecipeBuilder;

/* =========================================================
   MOOD SLIDER — 気力×温め度ダイヤル
   ========================================================= */
function MoodSlider() {
  const [energy, setEnergy] = React.useState(50);
  const [warmth, setWarmth] = React.useState(60);

  const temp     = Math.round(37 + (warmth / 100) * 4);
  const duration = Math.round(10 + (energy > 50 ? (100 - energy) / 100 : 1) * 15 + (warmth / 100) * 5);
  const herb     = energy < 30 ? 'よもぎ（深い回復）' : energy < 60 ? 'クロモジ（ほどよい鎮静）' : 'ヒノキ（爽快なリフレッシュ）';
  const tempNote = warmth < 30 ? 'ぬるめ — ゆっくり長めに' : warmth < 70 ? '標準 — 心地よい温さ' : '熱め — 短めで芯まで温める';
  const energyLabel = energy < 30 ? 'LOW · 低め' : energy < 70 ? 'MEDIUM · ふつう' : 'HIGH · 高め';
  const warmthLabel = warmth < 30 ? 'MILD · ぬるめ' : warmth < 70 ? 'WARM · 標準' : 'HOT · 熱め';
  const accent = warmth < 30 ? '#34486e' : warmth < 70 ? '#c4aa6c' : '#b4563a';

  const ce = React.createElement;
  const s = {
    wrap:      { maxWidth: 720, margin: '0 auto' },
    dialGrid:  { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 32, marginBottom: 48 },
    dialBlock: { display: 'flex', flexDirection: 'column', gap: 16 },
    dialLabel: { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#8a857b' },
    dialValue: (c) => ({ fontFamily: '"Shippori Mincho",serif', fontSize: 22, fontWeight: 500, color: c || '#1a1a1a', lineHeight: 1.2 }),
    sliderWrap:  { position: 'relative', padding: '8px 0' },
    sliderTrack: { position: 'relative', height: 2, background: 'rgba(26,26,26,0.12)', borderRadius: 1 },
    fill: (v,c) => ({ position: 'absolute', left: 0, top: 0, height: '100%', width: `${v}%`, background: c||'#1a1a1a', borderRadius: 1, transition: 'width 0.1s' }),
    thumb: (v,c) => ({ position: 'absolute', top: -5, left: `calc(${v}% - 6px)`, width: 12, height: 12, borderRadius: '50%', background: c||'#1a1a1a', border: '2px solid #f4efe4', boxShadow: '0 1px 4px rgba(0,0,0,0.2)', pointerEvents: 'none', transition: 'left 0.1s' }),
    input: { position: 'absolute', top: -8, left: 0, width: '100%', height: 18, opacity: 0, cursor: 'pointer', margin: 0 },
    tickRow: { display: 'flex', justifyContent: 'space-between', marginTop: 6 },
    tick:    { fontFamily: '"JetBrains Mono",monospace', fontSize: 8, color: 'rgba(26,26,26,0.3)', letterSpacing: '0.1em' },
    card:    { border: '1px solid rgba(26,26,26,0.15)', padding: '36px 32px', background: 'rgba(255,255,255,0.5)' },
    cardHead: { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#8a857b', marginBottom: 24, display: 'flex', justifyContent: 'space-between', alignItems: 'center' },
    paramRow: { display: 'flex', borderTop: '1px solid rgba(26,26,26,0.1)', borderBottom: '1px solid rgba(26,26,26,0.1)', marginBottom: 24 },
    paramItem: { flex: 1, padding: '16px 0', textAlign: 'center', borderRight: '1px solid rgba(26,26,26,0.1)' },
    paramLast: { flex: 1, padding: '16px 0', textAlign: 'center' },
    paramNum: (c) => ({ fontFamily: '"Cormorant Garamond","Times New Roman",serif', fontSize: 36, fontWeight: 400, color: c, lineHeight: 1, display: 'block' }),
    paramUnit: { fontFamily: '"JetBrains Mono",monospace', fontSize: 9, color: '#8a857b', letterSpacing: '0.15em' },
    herbRow:  { display: 'flex', alignItems: 'center', gap: 12 },
    herbDot:  { width: 8, height: 8, borderRadius: '50%', background: '#5c7a4e', flexShrink: 0 },
    herbLbl:  { fontFamily: '"JetBrains Mono",monospace', fontSize: 9, color: '#8a857b', letterSpacing: '0.12em', marginRight: 8 },
    herbText: { fontFamily: '"Shippori Mincho",serif', fontSize: 14, color: '#1a1a1a' },
    noteText: { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 11, color: '#8a857b', lineHeight: 1.7, marginTop: 12 },
  };

  const mkSlider = (value, setter, color, min, max) =>
    ce('div', { style: s.sliderWrap },
      ce('div', { style: s.sliderTrack },
        ce('div', { style: s.fill(value, color) }),
        ce('div', { style: s.thumb(value, color) }),
        ce('input', { type:'range', min, max, value, style: s.input, onChange: e => setter(Number(e.target.value)) })
      )
    );

  return ce('div', { style: s.wrap },
    ce('div', { style: s.dialGrid },
      ce('div', { style: s.dialBlock },
        ce('div', { style: s.dialLabel }, 'ENERGY · 今日の気力'),
        ce('div', { style: s.dialValue('#5c7a4e') }, energyLabel),
        mkSlider(energy, setEnergy, '#5c7a4e', 0, 100),
        ce('div', { style: s.tickRow }, ce('span', { style: s.tick }, 'LOW'), ce('span', { style: s.tick }, 'HIGH'))
      ),
      ce('div', { style: s.dialBlock },
        ce('div', { style: s.dialLabel }, 'WARMTH · 温めたい度'),
        ce('div', { style: s.dialValue(accent) }, warmthLabel),
        mkSlider(warmth, setWarmth, accent, 0, 100),
        ce('div', { style: s.tickRow }, ce('span', { style: s.tick }, 'MILD'), ce('span', { style: s.tick }, 'HOT'))
      )
    ),
    ce('div', { style: s.card },
      ce('div', { style: s.cardHead },
        ce('span', null, '— GUIDED PRESCRIPTION · 導かれた処方'),
        ce('span', { style: { color: accent } }, `${energy < 30 ? '●' : energy < 70 ? '◎' : '○'} ${energy} / 100`)
      ),
      ce('div', { style: s.paramRow },
        ce('div', { style: s.paramItem }, ce('span', { style: s.paramNum(accent) }, temp), ce('span', { style: s.paramUnit }, '°C · TEMP')),
        ce('div', { style: s.paramItem }, ce('span', { style: s.paramNum('#1a1a1a') }, duration), ce('span', { style: s.paramUnit }, 'MIN · DURATION')),
        ce('div', { style: s.paramLast }, ce('span', { style: s.paramNum('#c4aa6c') }, warmth < 30 ? 'S' : warmth < 70 ? 'M' : 'L'), ce('span', { style: s.paramUnit }, 'FLOWER AMOUNT'))
      ),
      ce('div', { style: s.herbRow }, ce('span', { style: s.herbLbl }, 'HERB ·'), ce('div', { style: s.herbDot }), ce('span', { style: s.herbText }, herb)),
      ce('div', { style: s.noteText }, tempNote)
    )
  );
}
window.MoodSlider = MoodSlider;

/* =========================================================
   SEASON RECIPES — 春夏秋冬 処方カード
   ========================================================= */
const SEASONS = [
  { id:'spring', label:'SPRING · 春', jp:'春の処方', month:'3–5月', theme:'疲労回復・花粉対策', color:'#5c7a4e', bg:'rgba(92,122,78,0.06)',   desc:'冬の疲れを解きほぐし、春の体のリセットに。よもぎの力で血行を整え、揺らぎやすい季節の変わり目を乗り越える処方です。', blend:[{cat:'SOLID',name:'炭酸タブレット',color:'#b4563a'},{cat:'LIQUID',name:'ローズマリー液',color:'#34486e'},{cat:'FLOWER',name:'湯の花 中量',color:'#c4aa6c'},{cat:'HERB',name:'よもぎ（山間採取）',color:'#5c7a4e'}], temp:40, min:20, note:'代謝が上がりはじめる春に、やや高めの温度で深部から温める。' },
  { id:'summer', label:'SUMMER · 夏', jp:'夏の処方', month:'6–8月', theme:'冷え補正・熱疲労回復', color:'#b4563a', bg:'rgba(180,86,58,0.06)', desc:'冷房による冷えと夏の熱疲労を同時に解消。ヒノキの清涼感と炭酸の血行促進で、夏の体をリセットします。', blend:[{cat:'SOLID',name:'薬用固形',color:'#b4563a'},{cat:'LIQUID',name:'ユーカリ液',color:'#34486e'},{cat:'FLOWER',name:'湯の花 少量',color:'#c4aa6c'},{cat:'HERB',name:'ヒノキ（高知県産）',color:'#5c7a4e'}], temp:38, min:15, note:'ぬるめの設定で長めに浸かることで、深部体温を均一に整える。' },
  { id:'autumn', label:'AUTUMN · 秋', jp:'秋の処方', month:'9–11月', theme:'乾燥対策・気持ち落ち着ける', color:'#c4aa6c', bg:'rgba(196,170,108,0.06)', desc:'乾燥が進む秋に、肌と心を潤す処方。ドクダミとシアバターで保湿を内側から支え、クロモジの香りで気持ちを整えます。', blend:[{cat:'SOLID',name:'シアバター固形',color:'#b4563a'},{cat:'LIQUID',name:'桃の葉液',color:'#34486e'},{cat:'FLOWER',name:'湯の花 中量',color:'#c4aa6c'},{cat:'HERB',name:'クロモジ（熊野産）',color:'#5c7a4e'}], temp:39, min:18, note:'入浴後すぐに保湿ケアを行うことで、湯上がりの水分を逃さない。' },
  { id:'winter', label:'WINTER · 冬', jp:'冬の処方', month:'12–2月', theme:'深部保温・冷え性解消', color:'#34486e', bg:'rgba(52,72,110,0.06)',   desc:'芯まで冷えた冬の体を、時間をかけて温める処方。よもぎとスギナの組み合わせが、循環を深いところから整えます。', blend:[{cat:'SOLID',name:'ぬくもり固形',color:'#b4563a'},{cat:'LIQUID',name:'ラベンダー液',color:'#34486e'},{cat:'FLOWER',name:'湯の花 多め',color:'#c4aa6c'},{cat:'HERB',name:'スギナ（別府近郊）',color:'#5c7a4e'}], temp:41, min:25, note:'熱めの湯に短く、ではなく、やや熱めに長めが冬の鉄則。' },
];

function SeasonRecipes() {
  const [active, setActive] = React.useState('spring');
  const [isMobile, setIsMobile] = React.useState(window.innerWidth < 680);
  React.useEffect(() => {
    const h = () => setIsMobile(window.innerWidth < 680);
    window.addEventListener('resize', h);
    return () => window.removeEventListener('resize', h);
  }, []);

  const ss = SEASONS.find(s => s.id === active);
  const ce = React.createElement;
  const s = {
    wrap:  { maxWidth: 900, margin: '0 auto' },
    tabs:  { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', marginBottom: 40, border: '1px solid rgba(26,26,26,0.12)' },
    tab: (a,c,last) => ({ padding: '16px 8px', fontFamily: '"JetBrains Mono",monospace', fontSize: 9, letterSpacing: '0.18em', textAlign: 'center', cursor: 'pointer', background: a ? c : 'transparent', color: a ? '#fff' : '#8a857b', border: 'none', borderRight: last ? 'none' : '1px solid rgba(26,26,26,0.12)', transition: 'all 0.2s', lineHeight: 1.6 }),
    card:  { display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', border: '1px solid rgba(26,26,26,0.12)', background: ss.bg },
    cardL: { padding: '40px 36px', borderRight: isMobile ? 'none' : '1px solid rgba(26,26,26,0.12)' },
    cardR: { padding: '40px 36px' },
    sLabel:  { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: ss.color, marginBottom: 8 },
    sJp:     { fontFamily: '"Shippori Mincho",serif', fontSize: 'clamp(20px,3vw,28px)', fontWeight: 500, color: '#1a1a1a', marginBottom: 8 },
    sTheme:  { fontFamily: '"JetBrains Mono",monospace', fontSize: 9, letterSpacing: '0.18em', color: '#8a857b', marginBottom: 24 },
    sDesc:   { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 13, color: '#5c584d', lineHeight: 1.9 },
    bLabel:  { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.22em', color: '#8a857b', marginBottom: 20 },
    bList:   { display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 28 },
    bItem: (c) => ({ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 14px', borderLeft: `3px solid ${c}`, background: 'rgba(255,255,255,0.5)' }),
    bDot:  (c) => ({ width: 7, height: 7, borderRadius: '50%', background: c, flexShrink: 0 }),
    bCat:    { fontFamily: '"JetBrains Mono",monospace', fontSize: 8, letterSpacing: '0.12em', color: '#8a857b', minWidth: 52 },
    bName:   { fontFamily: '"Shippori Mincho",serif', fontSize: 13, color: '#1a1a1a' },
    params:  { display: 'flex', gap: 24, padding: '16px 0', borderTop: '1px solid rgba(26,26,26,0.1)' },
    pItem:   { fontFamily: '"JetBrains Mono",monospace', fontSize: 10, color: '#5c584d', letterSpacing: '0.1em' },
    note:    { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 10, color: '#8a857b', lineHeight: 1.7, marginTop: 12 },
  };

  return ce('div', { style: s.wrap },
    ce('div', { style: s.tabs },
      SEASONS.map((season,i) => ce('button', { key: season.id, style: s.tab(active===season.id, season.color, i===3), onClick: () => setActive(season.id) }, season.label))
    ),
    ce('div', { style: s.card },
      ce('div', { style: s.cardL },
        ce('div', { style: s.sLabel }, `${ss.month} · ${ss.theme}`),
        ce('div', { style: s.sJp }, ss.jp),
        ce('div', { style: s.sTheme }, ss.label),
        ce('p',   { style: s.sDesc }, ss.desc)
      ),
      ce('div', { style: s.cardR },
        ce('div', { style: s.bLabel }, '— BLEND · 素材'),
        ce('div', { style: s.bList },
          ss.blend.map(b => ce('div', { key: b.cat, style: s.bItem(b.color) },
            ce('div', { style: s.bDot(b.color) }),
            ce('span', { style: s.bCat }, b.cat),
            ce('span', { style: s.bName }, b.name)
          ))
        ),
        ce('div', { style: s.params },
          ce('span', { style: s.pItem }, `TEMP · ${ss.temp}°C`),
          ce('span', { style: s.pItem }, `DURATION · ${ss.min} MIN`)
        ),
        ce('div', { style: s.note }, ss.note)
      )
    )
  );
}
window.SeasonRecipes = SeasonRecipes;

/* =========================================================
   PLAN TABLE — 料金プラン 3カラム
   ========================================================= */
const PLANS = [
  { id:'trial',    code:'PLAN · 01', name:'お試しセット', en:'Trial',        price:2480, unit:'1回限り',    badge:null,       color:'#8a857b', bg:'transparent',            features:[{t:'4要素 各1種 × ミニサイズ',on:true},{t:'診断カード付き',on:true},{t:'処方箋レシピ 1回分',on:true},{t:'定期割引',on:false},{t:'優先配送',on:false},{t:'カスタム処方最適化',on:false}], cta:'まず試してみる', note:'送料 660円（税込）' },
  { id:'seasonal', code:'PLAN · 02', name:'季節のセット', en:'Seasonal',     price:4980, unit:'月1回・定期', badge:'POPULAR',  color:'#5c7a4e', bg:'rgba(92,122,78,0.04)',   features:[{t:'季節に合わせたフルセット',on:true},{t:'診断カード付き',on:true},{t:'処方箋レシピ 月2レシピ',on:true},{t:'定期割引 10%OFF',on:true},{t:'5,500円以上 送料無料',on:true},{t:'カスタム処方最適化',on:false}], cta:'定期便を始める', note:'解約はいつでも可能' },
  { id:'custom',   code:'PLAN · 03', name:'診断カスタム', en:'Prescription', price:7980, unit:'月1回・定期', badge:'ADVANCED', color:'#34486e', bg:'rgba(52,72,110,0.04)',  features:[{t:'体調診断に基づく完全カスタム',on:true},{t:'詳細診断レポート',on:true},{t:'処方箋レシピ 無制限',on:true},{t:'定期割引 15%OFF',on:true},{t:'優先配送',on:true},{t:'カスタム処方最適化',on:true}], cta:'処方を受け取る', note:'スキップ・一時停止も可' },
];

function PlanTable() {
  const [hovered, setHovered] = React.useState(null);
  const [isMobile, setIsMobile] = React.useState(window.innerWidth < 720);
  React.useEffect(() => {
    const h = () => setIsMobile(window.innerWidth < 720);
    window.addEventListener('resize', h);
    return () => window.removeEventListener('resize', h);
  }, []);

  const ce = React.createElement;
  const s = {
    wrap: { maxWidth: 960, margin: '0 auto' },
    grid: { display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(3,1fr)', border: '1px solid rgba(26,26,26,0.12)' },
    card: (p,hov,last) => ({ padding: '40px 28px', background: hov ? (p.bg||'rgba(255,255,255,0.3)') : (p.bg||'transparent'), borderRight: (!last&&!isMobile) ? '1px solid rgba(26,26,26,0.12)' : 'none', borderTop: `3px solid ${hov ? p.color : 'transparent'}`, display: 'flex', flexDirection: 'column', transition: 'all 0.22s', cursor: 'default' }),
    badge: (c) => ({ display: 'inline-block', fontFamily: '"JetBrains Mono",monospace', fontSize: 8, letterSpacing: '0.2em', color: '#fff', background: c, padding: '3px 8px', marginBottom: 12 }),
    code:  (c) => ({ fontFamily: '"JetBrains Mono",monospace', fontSize: 9, letterSpacing: '0.22em', color: c, marginBottom: 12 }),
    name:  { fontFamily: '"Shippori Mincho",serif', fontSize: 20, fontWeight: 500, color: '#1a1a1a', marginBottom: 6, lineHeight: 1.3 },
    en:    { fontFamily: '"Cormorant Garamond","Times New Roman",serif', fontStyle: 'italic', fontSize: 14, color: '#8a857b', marginBottom: 28 },
    priceRow: { display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 6 },
    price: (c) => ({ fontFamily: '"Cormorant Garamond","Times New Roman",serif', fontSize: 42, fontWeight: 400, color: c, lineHeight: 1 }),
    pUnit: { fontFamily: '"JetBrains Mono",monospace', fontSize: 9, color: '#8a857b', letterSpacing: '0.1em' },
    freq:  { fontFamily: '"Noto Sans JP",sans-serif', fontSize: 11, color: '#8a857b', marginBottom: 32 },
    hr:    { height: 1, background: 'rgba(26,26,26,0.1)', margin: '0 0 24px' },
    ul:    { listStyle: 'none', padding: 0, margin: '0 0 32px', flex: 1 },
    li: (on) => ({ display: 'flex', alignItems: 'flex-start', gap: 10, padding: '7px 0', fontFamily: '"Noto Sans JP",sans-serif', fontSize: 12, color: on ? '#1a1a1a' : 'rgba(26,26,26,0.3)', borderBottom: '1px solid rgba(26,26,26,0.06)' }),
    mark: (on,c) => ({ fontFamily: '"JetBrains Mono",monospace', fontSize: 10, color: on ? c : 'rgba(26,26,26,0.2)', flexShrink: 0, marginTop: 2 }),
    cta: (c) => ({ display: 'block', width: '100%', padding: '14px 0', fontFamily: '"JetBrains Mono",monospace', fontSize: 10, letterSpacing: '0.18em', textAlign: 'center', color: '#fff', background: c, border: 'none', cursor: 'pointer', marginBottom: 12 }),
    note: { fontFamily: '"JetBrains Mono",monospace', fontSize: 9, color: '#8a857b', letterSpacing: '0.1em', textAlign: 'center' },
  };

  return ce('div', { style: s.wrap },
    ce('div', { style: s.grid },
      PLANS.map((plan, i) =>
        ce('div', {
          key: plan.id,
          style: s.card(plan, hovered===plan.id, i===PLANS.length-1),
          onMouseEnter: () => setHovered(plan.id),
          onMouseLeave: () => setHovered(null),
        },
          plan.badge && ce('div', { style: s.badge(plan.color) }, plan.badge),
          ce('div', { style: s.code(plan.color) }, plan.code),
          ce('div', { style: s.name }, plan.name),
          ce('div', { style: s.en }, plan.en),
          ce('div', { style: s.priceRow },
            ce('span', { style: s.price(plan.color) }, `¥${plan.price.toLocaleString()}`),
            ce('span', { style: s.pUnit }, '税込')
          ),
          ce('div', { style: s.freq }, plan.unit),
          ce('div', { style: s.hr }),
          ce('ul', { style: s.ul },
            plan.features.map((f,fi) =>
              ce('li', { key: fi, style: s.li(f.on) },
                ce('span', { style: s.mark(f.on, plan.color) }, f.on ? '✓' : '—'),
                f.t
              )
            )
          ),
          ce('button', { style: s.cta(plan.color) }, plan.cta),
          ce('div', { style: s.note }, plan.note)
        )
      )
    )
  );
}
window.PlanTable = PlanTable;
