/* ═══════════════════════════════════════════════════════════════
   HOLO.PET — app shell, state, tooltip behavior, tweaks
   ═══════════════════════════════════════════════════════════════ */

const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* ── ACTIONS / DESCRIPTIONS ─────────────────────────────────── */

const ACTIONS = [
  {
    id: 'feed',
    label: 'ごはん',
    icon: '⏣',
    hotkey: '1',
    title: 'ごはん // NUTRIENT.EXE',
    desc: '栄養カプセルを合成して与える。空腹ゲージを大きく回復するが、与えすぎるとわずかに清潔度が下がる。ほどほどに。',
    effects: { hunger: +28, clean: -4, happy: +4 },
    activity: 'eating',
    cooldown: 1800,
    logMsg: 'カプセル射出 → /dev/くち'
  },
  {
    id: 'play',
    label: 'あそぶ',
    icon: '◈',
    hotkey: '2',
    title: 'あそぶ // PROTO.MINIGAME',
    desc: 'ミニゲームを起動して幸福度を上昇させる。体力と空腹を消費。就寝中や重病時は使用不可。',
    effects: { happy: +32, energy: -12, hunger: -6 },
    activity: 'playing',
    cooldown: 2200,
    logMsg: 'ゲーム.EXE 起動 ▸ わらい=true'
  },
  {
    id: 'clean',
    label: 'そうじ',
    icon: '✦',
    hotkey: '3',
    title: 'そうじ // SANITIZE.SH',
    desc: 'フォトン洗浄サイクルを実行。清潔度を100に戻し、健康値も少し回復する。',
    effects: { clean: 100, health: +6 },
    activity: 'clean',
    cooldown: 1200,
    logMsg: 'フォトン洗浄 完了'
  },
  {
    id: 'sleep',
    label: 'ねむる',
    icon: '☾',
    hotkey: '4',
    title: 'ねむる // REST.MODE',
    desc: '省電力モードのON/OFF。睡眠中は体力と健康が回復する。再度押すと起こす。途中で起こすと幸福度が下がる。',
    effects: {},
    activity: 'sleep',
    cooldown: 400,
    toggles: 'sleeping',
    logMsg: 'スタンバイへ移行…'
  },
  {
    id: 'med',
    label: 'くすり',
    icon: '✚',
    hotkey: '5',
    title: 'くすり // PATCH.BIN',
    desc: 'ナノマシンパッチを投与。健康値を回復し病気状態を解除する。味は最悪なので幸福度が一時的に下がる。',
    effects: { health: +40, happy: -6 },
    activity: 'med',
    cooldown: 3000,
    heals: true,
    logMsg: 'ナノマシン投与 完了'
  },
  {
    id: 'stats',
    label: 'しんだん',
    icon: '▢',
    hotkey: '6',
    title: 'しんだん // SYS.READOUT',
    desc: '診断パネルを展開する。種族、世代、起動時間、気分、直近12件のログを表示。読み取り専用。',
    effects: {},
    activity: 'stats',
    cooldown: 300,
    toggles: 'statsOverlay',
    logMsg: '診断パネル 展開'
  }
];

/* idle / ambient descriptions for the CRT when nothing hovered */
const IDLE_MESSAGES = {
  happy:    'エンティティ正常。信号良好。入力を待機中…',
  hungry:   '空腹アラート。バイタル低下前に /ごはん を投与せよ。',
  tired:    '体力低下。/ねむる で再生を推奨。',
  dirty:    '衛生値 危険域。/そうじ サイクルを実行。',
  sad:      '気分ベクトル マイナス。/あそぶ ルーチンを起動せよ。',
  sick:     '⚠ 病原体を検出。直ちに /くすり を投与せよ。',
  sleeping: 'スタンバイ中 // 自動再生 // 起こさないで',
  dead:     '✕ 信号喪失。再起動が必要。'
};

const IDLE_STATE_LABELS = {
  happy: 'せいじょう',
  hungry: 'くうふく',
  tired: 'たいりょくていか',
  dirty: 'よごれ',
  sad: 'ふきげん',
  sick: 'びょうき',
  sleeping: 'すいみん中',
  dead: 'しんごうそうしつ'
};

/* ── PERSISTENCE ────────────────────────────────────────────── */

const STORAGE_KEY = 'holopet:v2';
const loadState = () => {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    return JSON.parse(raw);
  } catch { return null; }
};
const saveState = (s) => {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch {}
};

/* ── APP ─────────────────────────────────────────────────────── */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "matrix",
  "layout": "radial",
  "shape": "default",
  "character": "blobby",
  "fx": 2
}/*EDITMODE-END*/;

const PALETTES = [
  { id: 'matrix', label: 'マトリクス', hex: '#39ff88' },
  { id: 'cyan',   label: 'サイバー',   hex: '#5affe8' },
  { id: 'amber',  label: 'アンバー',   hex: '#ffb347' },
  { id: 'purple', label: 'ヴェイパー', hex: '#c78aff' },
  { id: 'ghost',  label: 'ゴースト',   hex: '#e6fff4' }
];

const LAYOUTS   = [
  { id: 'radial', label: 'ラジアル' },
  { id: 'arc',    label: 'アーク' },
  { id: 'grid',   label: 'ライン' }
];
const SHAPES    = [
  { id: 'default', label: 'ホロ' },
  { id: 'hex',     label: 'ヘックス' },
  { id: 'pod',     label: 'ポッド' },
  { id: 'ring',    label: 'リング' }
];
const CHARACTERS = [
  { id: 'blobby', label: 'ブロブ-77' },
  { id: 'cubo',   label: 'キュボ-01' },
  { id: 'byte',   label: 'バイト-9' },
  { id: 'spook',  label: 'スプーク-X' }
];

function App() {
  // ── tweaks state ─────────────────────────────────────────
  const [tweaks, setTweaks] = useState(TWEAK_DEFAULTS);
  const [tweaksOpen, setTweaksOpen] = useState(false);

  // ── pet state ────────────────────────────────────────────
  const saved = loadState();
  const [vitals, setVitals] = useState(saved?.vitals ?? {
    hunger: 72, happy: 82, energy: 70, clean: 80, health: 92
  });
  const [flags, setFlags] = useState(saved?.flags ?? {
    sleeping: false, sick: false, dirty: false
  });
  const [birth]     = useState(saved?.birth ?? Date.now());
  const [activity, setActivity] = useState(null);    // transient
  const [toast, setToast]       = useState(null);
  const [log, setLog]           = useState(saved?.log ?? [
    { t: Date.now(), msg: '起動 // holopet.os v0.7 読込完了' },
    { t: Date.now(), msg: 'エンティティ生成 // ハロー・ワールド' }
  ]);
  const [statsOverlay, setStatsOverlay] = useState(false);

  // hovered button id for CRT tooltip
  const [hovered, setHovered] = useState(null);
  const [typed, setTyped] = useState('');
  const typingRef = useRef({ target: '', i: 0, raf: 0, started: 0 });

  // ── persist ──────────────────────────────────────────────
  useEffect(() => {
    saveState({ vitals, flags, birth, log: log.slice(-30) });
  }, [vitals, flags, log, birth]);

  // ── apply tweaks -> body classes ─────────────────────────
  useEffect(() => {
    const body = document.body;
    body.className = '';
    body.classList.add(`palette-${tweaks.palette}`);
    body.classList.add(`fx-${tweaks.fx}`);
    if (flags.sleeping) body.classList.add('pet-sleeping');
    if (flags.sick)     body.classList.add('pet-sick');
  }, [tweaks, flags]);

  // ── vitals tick (decay) ─────────────────────────────────
  useEffect(() => {
    const id = setInterval(() => {
      setVitals(v => {
        const asleep = flags.sleeping;
        const nv = { ...v };
        // decay rates per 3s tick
        nv.hunger = clamp(nv.hunger - (asleep ? 0.3 : 1.2));
        nv.happy  = clamp(nv.happy  - (asleep ? 0.2 : 0.9));
        nv.clean  = clamp(nv.clean  - (asleep ? 0.3 : 0.7));
        if (asleep) {
          nv.energy = clamp(nv.energy + 2.5);
          nv.health = clamp(nv.health + 0.6);
        } else {
          nv.energy = clamp(nv.energy - 0.6);
        }
        // low stats hurt health
        if (nv.hunger < 15 || nv.clean < 15 || nv.energy < 10) {
          nv.health = clamp(nv.health - 0.8);
        }
        return nv;
      });
    }, 3000);
    return () => clearInterval(id);
  }, [flags.sleeping]);

  // ── derived flags from vitals ──────────────────────────
  useEffect(() => {
    setFlags(f => {
      const sick  = vitals.health < 35;
      const dirty = vitals.clean  < 30;
      if (sick === f.sick && dirty === f.dirty) return f;
      return { ...f, sick, dirty };
    });
  }, [vitals.health, vitals.clean]);

  // ── state-based idle tooltip when nothing hovered ─────
  const idleState = useMemo(() => {
    if (flags.sleeping)         return 'sleeping';
    if (vitals.health < 35)     return 'sick';
    if (vitals.clean  < 30)     return 'dirty';
    if (vitals.hunger < 30)     return 'hungry';
    if (vitals.energy < 20)     return 'tired';
    if (vitals.happy  < 35)     return 'sad';
    return 'happy';
  }, [vitals, flags.sleeping]);

  // ── tooltip typing animation ─────────────────────────
  useEffect(() => {
    cancelAnimationFrame(typingRef.current.raf);
    const action = ACTIONS.find(a => a.id === hovered);
    const target = action ? action.desc : IDLE_MESSAGES[idleState];
    typingRef.current.target = target;
    typingRef.current.i = 0;
    typingRef.current.started = performance.now();
    const tick = (now) => {
      const elapsed = now - typingRef.current.started;
      const cps = 90; // chars per second
      const want = Math.floor(elapsed * cps / 1000);
      const str = typingRef.current.target.slice(0, Math.min(want, typingRef.current.target.length));
      setTyped(str);
      if (want < typingRef.current.target.length) {
        typingRef.current.raf = requestAnimationFrame(tick);
      }
    };
    typingRef.current.raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(typingRef.current.raf);
  }, [hovered, idleState]);

  // ── action dispatcher ───────────────────────────────
  const dispatch = useCallback((id) => {
    const action = ACTIONS.find(a => a.id === id);
    if (!action) return;

    // toggles
    if (action.toggles === 'sleeping') {
      setFlags(f => {
        const next = !f.sleeping;
        pushLog(next ? 'スタンバイ開始 ⏸' : '再稼働 ▶');
        if (!next) setVitals(v => ({ ...v, happy: clamp(v.happy - 4) }));
        void next;
        return { ...f, sleeping: next };
      });
      setToast(null);
      return;
    }
    if (action.toggles === 'statsOverlay') {
      setStatsOverlay(s => !s);
      return;
    }

    // gate: sleeping blocks most actions
    if (flags.sleeping) {
      pushLog('⚠ ねむっています — ねむるボタンで起こす');
      setToast('ZZzz…');
      setTimeout(() => setToast(null), 1000);
      return;
    }
    // gate: sick blocks play/feed eating
    if (flags.sick && (id === 'play' || id === 'feed')) {
      pushLog('✕ 病気のため実行不可 — くすりを投与');
      setToast('✕ びょうき');
      setTimeout(() => setToast(null), 1000);
      return;
    }

    // apply effects
    setVitals(v => {
      const nv = { ...v };
      for (const k in action.effects) {
        nv[k] = clamp((nv[k] ?? 0) + action.effects[k]);
      }
      return nv;
    });

    // activity animation
    setActivity(action.activity);
    setTimeout(() => setActivity(null), 1500);

    // toast
    const toastMap = { feed: '♦ もぐもぐ', play: '♥ たのしい', clean: '✦ きれい', med: '+ かいふく' };
    if (toastMap[id]) {
      setToast(toastMap[id]);
      setTimeout(() => setToast(null), 1100);
    }

    pushLog(action.logMsg);
  }, [flags.sleeping, flags.sick]);

  const pushLog = (msg) => {
    setLog(l => [...l, { t: Date.now(), msg }].slice(-30));
  };

  // ── keyboard shortcuts ──────────────────────────────
  useEffect(() => {
    const onKey = (e) => {
      const action = ACTIONS.find(a => a.hotkey === e.key);
      if (action) dispatch(action.id);
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [dispatch]);

  // ── tweaks host protocol ────────────────────────────
  useEffect(() => {
    const onMsg = (e) => {
      const d = e.data || {};
      if (d.type === '__activate_edit_mode')   setTweaksOpen(true);
      if (d.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);

  const updateTweak = (k, v) => {
    const next = { ...tweaks, [k]: v };
    setTweaks(next);
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [k]: v } }, '*');
  };

  // ── derived stats ──────────────────────────────────
  const ageSec = Math.floor((Date.now() - birth) / 1000);
  const ageDisplay = formatAge(ageSec);
  const mood = getMood(vitals, flags);

  // action for current hover
  const hoveredAction = ACTIONS.find(a => a.id === hovered);

  return (
    <>
      {/* environment layers handled in HTML */}

      {/* TOP BAR */}
      <div className="topbar">
        <div className="left">
          <span className="brand">HOLO.PET</span>
          <span className="cell">ノード 0xA7F4</span>
          <span><span className="blink"/> 接続中</span>
        </div>
        <div className="right">
          <span className="cell">稼働 {ageDisplay}</span>
          <span className="cell">気分 {mood}</span>
          <span className="cell">v0.7.2</span>
        </div>
      </div>

      {/* SIDE PANEL — species / info */}
      <div className="panel left">
        <h3>エンティティ情報</h3>
        <div className="row"><span className="k">種族</span><span className="v">{CHARACTERS.find(c=>c.id===tweaks.character)?.label}</span></div>
        <div className="row"><span className="k">世代</span><span className="v">第三</span></div>
        <div className="row"><span className="k">誕生</span><span className="v">{new Date(birth).toISOString().slice(0,10)}</span></div>
        <div className="row"><span className="k">稼働</span><span className="v">{ageDisplay}</span></div>
        <div className="row"><span className="k">気分</span><span className="v">{mood}</span></div>
        <div className="row"><span className="k">状態</span><span className="v">{flags.sleeping ? '就寝中' : flags.sick ? '病気' : flags.dirty ? 'よごれ' : '良好'}</span></div>
      </div>

      {/* SIDE PANEL — controls help */}
      <div className="panel right">
        <h3>キー操作</h3>
        {ACTIONS.map(a => (
          <div className="row" key={a.id}>
            <span className="k">[{a.hotkey}]</span>
            <span className="v">{a.label}</span>
          </div>
        ))}
      </div>

      {/* LOG */}
      <div className="panel log">
        <h3>シグナルログ</h3>
        {log.slice(-6).reverse().map((l, i) => (
          <div className={`line ${i === 0 ? 'new' : ''}`} key={l.t + '-' + i}>
            <span className="t">{new Date(l.t).toTimeString().slice(0,8)}</span>
            {l.msg}
          </div>
        ))}
      </div>

      {/* HELP */}
      <div className="panel help">
        <h3>// ボタンにカーソルを合わせて</h3>
        <div className="row"><span className="k">マウス</span><span className="v">ホバー + クリック</span></div>
        <div className="row"><span className="k">キー</span><span className="v">1〜6</span></div>
        <div className="row"><span className="k">調整</span><span className="v">TWEAKSパネル</span></div>
      </div>

      {/* STAGE */}
      <div className={`stage shape-${tweaks.shape} layout-${tweaks.layout}`}>
        <div className="device">

          <div className="ring r1"/>
          <div className="ring r2"/>
          <div className="ring r3"/>

          <div className="brackets">
            <span className="tl"/><span className="tr"/><span className="bl"/><span className="br"/>
          </div>

          <div className="beam"/>
          <div className="base"/>

          {/* CRT */}
          <div className="crt">
            <div className="crt-inner">
              <div className="crt-header">
                <span className="pet-name">
                  // {CHARACTERS.find(c=>c.id===tweaks.character)?.label}
                </span>
                <span className="age">{ageDisplay}</span>
              </div>
              <div className="pet-stage">
                <div className="floor-grid"/>
                <PetCanvas
                  character={tweaks.character}
                  state={flags.sleeping ? 'sleeping' : flags.sick ? 'sick' : flags.dirty ? 'dirty' : 'ok'}
                  activity={activity}
                />
                <div className="pet-shadow"/>
                <div className="pet-floor"/>
                {toast && <div className="toast" key={toast + Date.now()}>{toast}</div>}
              </div>
              <div className="crt-tooltip">
                <div className="title">
                  <span className="prompt">&gt;</span>
                  <span>{hoveredAction ? hoveredAction.title : `環境 // ${IDLE_STATE_LABELS[idleState] || idleState}`}</span>
                </div>
                <div className="body">
                  {typed}<span className="cursor"/>
                </div>
              </div>
            </div>
            <div className="chroma"/>
          </div>

          {/* GAUGES */}
          <div className="gauges">
            <Gauge label="くうふく" value={vitals.hunger} />
            <Gauge label="しあわせ" value={vitals.happy}  />
            <Gauge label="たいりょく" value={vitals.energy} />
            <Gauge label="せいけつ" value={vitals.clean}  />
          </div>

          {/* BUTTONS */}
          <div className="buttons">
            {ACTIONS.map((a, i) => (
              <button
                key={a.id}
                className={`btn b${i}`}
                onMouseEnter={() => setHovered(a.id)}
                onMouseLeave={() => setHovered(null)}
                onFocus={() => setHovered(a.id)}
                onBlur={() => setHovered(null)}
                onClick={() => dispatch(a.id)}
              >
                <span className="icon">{a.icon}</span>
                <span className="hotkey">{a.hotkey}</span>
                <span className="label">{a.label}</span>
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* STATS OVERLAY */}
      {statsOverlay && (
        <StatsOverlay
          vitals={vitals}
          flags={flags}
          ageDisplay={ageDisplay}
          character={CHARACTERS.find(c=>c.id===tweaks.character)?.label}
          log={log}
          onClose={() => setStatsOverlay(false)}
        />
      )}

      {/* TWEAKS */}
      <div className={`tweaks ${tweaksOpen ? 'on' : ''}`}>
        <h4>// カスタマイズ</h4>
        <div className="row">
          <span className="lbl">パレット</span>
          <div className="opts">
            {PALETTES.map(p => (
              <button key={p.id}
                className={`opt ${tweaks.palette===p.id?'active':''}`}
                onClick={() => updateTweak('palette', p.id)}>
                <span className="swatch" style={{background: p.hex}}/>{p.label}
              </button>
            ))}
          </div>
        </div>
        <div className="row">
          <span className="lbl">レイアウト</span>
          <div className="opts">
            {LAYOUTS.map(o => (
              <button key={o.id}
                className={`opt ${tweaks.layout===o.id?'active':''}`}
                onClick={() => updateTweak('layout', o.id)}>{o.label}</button>
            ))}
          </div>
        </div>
        <div className="row">
          <span className="lbl">かたち</span>
          <div className="opts">
            {SHAPES.map(o => (
              <button key={o.id}
                className={`opt ${tweaks.shape===o.id?'active':''}`}
                onClick={() => updateTweak('shape', o.id)}>{o.label}</button>
            ))}
          </div>
        </div>
        <div className="row">
          <span className="lbl">キャラクター</span>
          <div className="opts">
            {CHARACTERS.map(o => (
              <button key={o.id}
                className={`opt ${tweaks.character===o.id?'active':''}`}
                onClick={() => updateTweak('character', o.id)}>{o.label}</button>
            ))}
          </div>
        </div>
        <div className="row">
          <span className="lbl">エフェクト</span>
          <div className="opts">
            {[0,1,2,3].map(n => (
              <button key={n}
                className={`opt ${tweaks.fx===n?'active':''}`}
                onClick={() => updateTweak('fx', n)}>{n}</button>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

/* ── Gauge ─────────────────────────────────────────── */
function Gauge({ label, value }) {
  const cls = value < 25 ? 'danger' : value < 45 ? 'warn' : '';
  return (
    <div className={`gauge ${cls}`}>
      <div className="label"><span>{label}</span><span className="val">{Math.round(value)}</span></div>
      <div className="bar"><div className="fill" style={{width: `${value}%`}}/></div>
    </div>
  );
}

/* ── Stats overlay ────────────────────────────────── */
function StatsOverlay({ vitals, flags, ageDisplay, character, log, onClose }) {
  return (
    <div className="stats-overlay" onClick={onClose} style={{
      position:'fixed', inset:0, background:'rgba(2,6,4,0.82)', backdropFilter:'blur(4px)',
      zIndex: 120, display:'grid', placeItems:'center', cursor:'pointer'
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width:'min(560px, 92vw)', padding:24, cursor:'default',
        background:'linear-gradient(135deg, rgba(7,32,15,0.9), rgba(4,17,10,0.6))',
        border:'1px solid var(--fg)', fontFamily:'var(--font-crt)',
        color:'var(--fg)', position:'relative',
        clipPath:'polygon(16px 0, 100% 0, 100% calc(100% - 16px), calc(100% - 16px) 100%, 0 100%, 0 16px)',
        boxShadow:'0 0 40px rgba(57,255,136,0.35)'
      }}>
        <div style={{fontFamily:'var(--font-hud)', fontSize:14, letterSpacing:'0.3em',
          textShadow:'var(--phosphor-blur)', marginBottom:12, display:'flex', justifyContent:'space-between'}}>
          <span>// 診断レポート</span>
          <span style={{cursor:'pointer', color:'var(--fg-dim)'}} onClick={onClose}>閉じる [ESC]</span>
        </div>
        <div style={{fontSize:18, lineHeight:1.4, color:'var(--fg-dim)', fontFamily:'var(--font-mono)', fontSize:11}}>
          <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:'4px 20px'}}>
            <Line k="ID" v={character}/>
            <Line k="稼働時間" v={ageDisplay}/>
            <Line k="くうふく" v={`${Math.round(vitals.hunger)} / 100`}/>
            <Line k="しあわせ" v={`${Math.round(vitals.happy)} / 100`}/>
            <Line k="たいりょく" v={`${Math.round(vitals.energy)} / 100`}/>
            <Line k="せいけつ" v={`${Math.round(vitals.clean)} / 100`}/>
            <Line k="けんこう" v={`${Math.round(vitals.health)} / 100`}/>
            <Line k="じょうたい" v={flags.sleeping?'就寝中':flags.sick?'病気':flags.dirty?'よごれ':'良好'}/>
          </div>
          <div style={{marginTop:16, fontSize:11, letterSpacing:'0.15em'}}>// 直近12件のイベント</div>
          <div style={{marginTop:6, maxHeight:180, overflow:'auto', fontSize:10}}>
            {log.slice(-12).reverse().map((l,i) => (
              <div key={i} style={{padding:'2px 0', color: i===0?'var(--fg)':'var(--fg-dim)'}}>
                <span style={{color:'var(--fg-faint)', marginRight:8}}>
                  {new Date(l.t).toTimeString().slice(0,8)}
                </span>
                {l.msg}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}
function Line({k,v}) {
  return (
    <div style={{display:'flex', justifyContent:'space-between', borderBottom:'1px dashed var(--fg-faint)', padding:'4px 0'}}>
      <span>{k}</span><span style={{color:'var(--fg)', textShadow:'var(--phosphor-blur)'}}>{v}</span>
    </div>
  );
}

/* ── utils ─────────────────────────────────────────── */
function clamp(n, lo = 0, hi = 100) { return Math.max(lo, Math.min(hi, n)); }
function formatAge(sec) {
  const h = Math.floor(sec / 3600);
  const m = Math.floor((sec % 3600) / 60);
  const s = sec % 60;
  return `${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`;
}
function getMood(v, f) {
  if (f.sleeping) return 'やすみ中';
  if (v.health < 35) return 'びょうき';
  if (v.hunger < 25) return 'ぺこぺこ';
  if (v.clean  < 30) return 'よごれ';
  if (v.energy < 20) return 'くたくた';
  if (v.happy  < 35) return 'ゆううつ';
  if (v.happy  > 80) return 'ごきげん';
  return 'ふつう';
}

// Escape to close stats overlay
window.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    // handled in component via click-out, but keep a hook just in case
  }
});

const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<App />);
