/* global React, ReactDOM, Cat, Icon, GAME, EventsBar, EventPopup, DebugPanel, GachaCard, GachaModal, GACHA, CollectionTab */
const { useState, useEffect, useRef, useMemo, useCallback } = React;
const { HELPERS, SKILLS, PERMA, OUTFITS, QUESTS, EVENTS, fmt, fmt1, helperCost, xpForLevel, helperMilestoneMult, NAP_UNLOCK, napGainFn } = GAME;

const HELPER_ICON = { paw: Icon.paw, music: Icon.music, star: Icon.star, trophy: Icon.trophy, sparkle: Icon.sparkle, moon: Icon.moon, leaf: Icon.leaf, cloud: Icon.cloud, heart: Icon.heart };
const NAV_ICON = { play: Icon.paw, upgrades: Icon.star, outfits: Icon.heart, collection: Icon.music, stats: Icon.trophy };

/* ============== Initial state ============== */
const initialState = () => ({
  pp: 0,
  totalEarned: 0,
  pets: 0,
  level: 1,
  xp: 0,
  helpers: Object.fromEntries(HELPERS.map((h) => [h.id, 0])),
  skills: Object.fromEntries(
    Object.entries(SKILLS).flatMap(([branch, list]) => list.map((s) => [s.id, 0]))
  ),
  skillPoints: 0,
  outfit: "none",
  ownedOutfits: ["none"],
  napCount: 0,
  napBonus: 1, // multiplier
  perma: {},
  questDone: {},
  dailyPull: { lastDate: null, streak: 0, lastTier: null },
  pulls: [],
});

function isYesterdayKey(key) {
  if (!key) return false;
  const y = new Date();
  y.setDate(y.getDate() - 1);
  const k = `${y.getFullYear()}-${String(y.getMonth() + 1).padStart(2, "0")}-${String(y.getDate()).padStart(2, "0")}`;
  return key === k;
}

/* ============== App ============== */
function App() {
  const [tab, setTab] = useState("play");
  const [state, setState] = useState(initialState);
  const [authUser, setAuthUser] = useState(null);

  useEffect(() => {
    fetch("/api/me", { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : null))
      .then((u) => setAuthUser(u))
      .catch(() => {});
  }, []);

  const [stateReady, setStateReady] = useState(false);

  const applyServerState = useCallback((serverState) => {
    setState((s) => ({ ...s, ...serverState }));
    if (Array.isArray(serverState.events)) setEvents(serverState.events);
  }, []);

  useEffect(() => {
    if (!authUser) { setStateReady(true); return; }
    setStateReady(false);
    fetch("/api/state", { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : null))
      .then((payload) => {
        if (payload && payload.state) applyServerState(payload.state);
      })
      .catch(() => {})
      .finally(() => setStateReady(true));
  }, [authUser, applyServerState]);

  // Periodic state refresh to pull newly spawned events
  useEffect(() => {
    if (!authUser) return;
    const t = setInterval(() => {
      fetch("/api/state", { credentials: "same-origin" })
        .then((r) => (r.ok ? r.json() : null))
        .then((payload) => { if (payload?.state) applyServerState(payload.state); })
        .catch(() => {});
    }, 15000);
    return () => clearInterval(t);
  }, [authUser, applyServerState]);

  // ===== Action dispatcher (server-authoritative) =====
  const dispatch = useCallback(async (kind, payload) => {
    const action_id = crypto.randomUUID();
    try {
      const r = await fetch("/api/action", {
        method: "POST",
        credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action_id, kind, payload }),
      });
      if (!r.ok) {
        const err = await r.json().catch(() => ({}));
        return { error: err.error || `http ${r.status}` };
      }
      const data = await r.json();
      if (data.state) {
        setState((s) => ({ ...s, ...data.state }));
        if (Array.isArray(data.state.events)) setEvents(data.state.events);
      }
      return data;
    } catch (e) {
      return { error: e.message };
    }
  }, []);

  // ===== Pet batching =====
  const petBuf = useRef(0);
  const petFlush = useRef(null);
  const flushPets = useCallback(() => {
    const count = petBuf.current;
    petBuf.current = 0;
    if (count <= 0) return;
    dispatch("pet", { count });
  }, [dispatch]);
  const queuePet = useCallback(() => {
    petBuf.current += 1;
    clearTimeout(petFlush.current);
    petFlush.current = setTimeout(flushPets, 250);
    if (petBuf.current >= 20) flushPets();
  }, [flushPets]);

  const logout = useCallback(() => {
    fetch("/auth/logout", { method: "POST", credentials: "same-origin" })
      .then(() => {
        setAuthUser(null);
        setState(initialState());
      });
  }, []);
  const [floats, setFloats] = useState([]);
  const [toasts, setToasts] = useState([]);
  const [napOpen, setNapOpen] = useState(false);
  const [purring, setPurring] = useState(false);
  const [theme, setTheme] = useState("light");
  const purrTimer = useRef(null);
  const lastPet = useRef(0);
  const [combo, setCombo] = useState(0);

  // Events (session-only — not persisted)
  const [events, setEvents] = useState([]);
  const [pending, setPending] = useState(null);
  const [now, setNow] = useState(() => Date.now());
  const [debugOpen, setDebugOpen] = useState(false);
  const [gachaOpen, setGachaOpen] = useState(false);
  const [gachaForcedTier, setGachaForcedTier] = useState(null);
  const [justBoughtPerma, setJustBoughtPerma] = useState(null);
  const stageRef = useRef(null);
  const onPetRef = useRef(null);
  const justBoughtTimer = useRef(null);

  // Resolve active event multipliers
  const evMul = useMemo(() => {
    let allMul = 1, helperMul = 1, xpMul = 1;
    let critForce = false, critMult = 1, autoPet = 0, comboLock = false;
    for (const ev of events) {
      const e = ev.def.effect || {};
      if (e.allMul) allMul *= e.allMul;
      if (e.helperMul) helperMul *= e.helperMul;
      if (e.xpMul) xpMul *= e.xpMul;
      if (e.critForce) critForce = true;
      if (e.critMult) critMult = Math.max(critMult, e.critMult);
      if (e.autoPet) autoPet = Math.max(autoPet, e.autoPet);
      if (e.comboLock) comboLock = true;
    }
    return { allMul, helperMul, xpMul, critForce, critMult, autoPet, comboLock };
  }, [events]);

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
  }, [theme]);

  // Derived: skill levels
  const sl = (id) => state.skills[id] || 0;

  // v2: raw helper PPS without global multipliers, used to scale pet power
  const ppsRaw = useMemo(() => {
    let total = 0;
    for (const h of HELPERS) {
      const owned = state.helpers[h.id] || 0;
      total += owned * h.pps * helperMilestoneMult(owned);
    }
    return total;
  }, [state.helpers]);

  const petPower = useMemo(() => {
    let base = 1;
    base *= 1 + sl("tempo") * 0.15;
    base *= state.napBonus;
    if (state.outfit === "ribbon") base *= 1.05;
    if (state.outfit === "crown") base *= 1.25;
    if (state.perma.tablet) base *= 1.25;
    if (state.perma.skin) base *= 1.15;
    if (state.perma.supporter) base *= 1.50;
    if (state.perma.legendary) base *= 3.0;
    base *= 1 + Math.min(combo, 10 + sl("combo") * 4) * 0.04;
    base *= evMul.allMul;
    // v2: a tap is worth ~0.5s of idle income so manual play stays meaningful
    base += ppsRaw * 0.5;
    return base;
  }, [state.skills, state.napBonus, state.outfit, state.perma, combo, evMul, ppsRaw]);

  // pps with v2 milestone bonuses (every 25 of a helper doubles its pps)
  const pps = useMemo(() => {
    let mult = 1 + sl("encore") * 0.10;
    if (state.outfit === "flower") mult *= 1.10;
    if (state.outfit === "crown") mult *= 1.25;
    if (state.perma.headphones) mult *= 1.20;
    if (state.perma.skin) mult *= 1.15;
    if (state.perma.supporter) mult *= 1.50;
    if (state.perma.legendary) mult *= 3.0;
    mult *= state.napBonus;
    mult *= evMul.allMul * evMul.helperMul;
    return ppsRaw * mult;
  }, [ppsRaw, state.skills, state.outfit, state.napBonus, state.perma, evMul]);

  // Tick PPS + clock
  useEffect(() => {
    const t = setInterval(() => {
      setState((s) => {
        const gain = pps / 10;
        return { ...s, pp: s.pp + gain, totalEarned: s.totalEarned + gain };
      });
      const t2 = Date.now();
      setNow(t2);
      // expire events
      setEvents((evs) => {
        const next = evs.filter((e) => e.expiresAt > t2);
        return next.length === evs.length ? evs : next;
      });
      setPending((p) => (p && p.expiresAt > t2 ? p : null));
    }, 100);
    return () => clearInterval(t);
  }, [pps]);

  // Combo decay (locked during Encore)
  useEffect(() => {
    if (combo === 0 || evMul.comboLock) return;
    const t = setTimeout(() => setCombo(0), 1500 + (state.perma.energy ? 1000 : 0));
    return () => clearTimeout(t);
  }, [combo, evMul.comboLock, state.perma.energy]);

  // Level up logic
  useEffect(() => {
    setState((s) => {
      let { level, xp } = s;
      let need = xpForLevel(level);
      let leveled = false;
      while (xp >= need) {
        xp -= need;
        level += 1;
        leveled = true;
        need = xpForLevel(level);
      }
      if (leveled) {
        const gainedSp = level - s.level;
        toast({ title: `Level ${level}!`, sub: `+${gainedSp} skill point${gainedSp>1?'s':''}`, ico: "star" });
        return { ...s, level, xp, skillPoints: s.skillPoints + gainedSp };
      }
      return s;
    });
  }, [state.xp]);

  // v2: quest targets scale with nap count
  const activeQuests = useMemo(() => QUESTS(state.napCount), [state.napCount]);

  // Quest completion now server-side; show toasts based on prior questDone diff
  const prevQuestDone = useRef(state.questDone);
  useEffect(() => {
    const before = prevQuestDone.current || {};
    const after = state.questDone || {};
    for (const q of activeQuests) {
      if (!before[q.id] && after[q.id]) {
        toast({ title: "Quest complete!", sub: q.name, ico: "trophy" });
      }
    }
    prevQuestDone.current = after;
  }, [state.questDone, activeQuests]);

  function questValue(q, s) {
    if (q.metric === "pets") return s.pets;
    if (q.metric === "earned") return s.totalEarned;
    if (q.metric === "helpers") return Object.values(s.helpers).reduce((a, b) => a + b, 0);
    if (q.metric === "level") return s.level;
    return 0;
  }

  // Pet handler
  const onPet = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    const t = Date.now();
    const fast = t - lastPet.current < 800;
    lastPet.current = t;
    setCombo((c) => fast ? c + 1 : 1);

    // Crit (forced during Critical Hour)
    let mult = 1;
    const critChance = sl("perfect") * 0.05;
    const isCrit = evMul.critForce || Math.random() < critChance;
    if (isCrit) {
      const skillCrit = 1 + sl("perfect") * 0.5;
      mult *= Math.max(skillCrit, evMul.critMult);
    }

    const gain = petPower * mult;
    setState((s) => ({
      ...s,
      pp: s.pp + gain,
      totalEarned: s.totalEarned + gain,
      pets: s.pets + 1,
      xp: s.xp + (1 + sl("fluff") * 0.08) * evMul.xpMul,
    }));
    queuePet();

    // Float text
    const id = Math.random();
    const usedCrit = isCrit || evMul.critForce;
    setFloats((f) => [...f, { id, x, y, txt: `+${fmt1(gain)}`, crit: usedCrit, heart: Math.random() < 0.2 }]);
    setTimeout(() => setFloats((f) => f.filter((fl) => fl.id !== id)), 1300);

    // Purr
    setPurring(true);
    clearTimeout(purrTimer.current);
    purrTimer.current = setTimeout(() => setPurring(false), 600);
  };

  // Helpers actions (server-authoritative)
  const buyHelper = async (h) => {
    const owned = state.helpers[h.id] || 0;
    const cost = helperCost(h, owned, sl("smile"));
    if (state.pp < cost) return;
    const r = await dispatch("buyHelper", { id: h.id });
    if (r.error) { toast({ title: "Can't hire", sub: r.error, ico: h.icon }); return; }
    toast({ title: `Hired ${h.name}!`, sub: `+${h.pps} PP/s`, ico: h.icon });
  };

  // Skill actions
  const buySkill = async (skill) => {
    const lvl = state.skills[skill.id] || 0;
    if (lvl >= skill.max) return;
    if (state.skillPoints < skill.cost) return;
    const r = await dispatch("buySkill", { id: skill.id });
    if (r.error) { toast({ title: "Can't learn", sub: r.error, ico: "sparkle" }); return; }
    toast({ title: skill.name, sub: `Lv ${lvl+1}`, ico: "sparkle" });
  };

  // Outfit actions
  const buyOutfit = async (o) => {
    const r = await dispatch("buyOutfit", { id: o.id });
    if (r.error) { toast({ title: "Can't equip", sub: r.error, ico: "heart" }); return; }
    if (!state.ownedOutfits.includes(o.id)) toast({ title: "New outfit!", sub: o.name, ico: "heart" });
  };

  // Permanent upgrade
  const buyPerma = async (p) => {
    if (state.perma[p.id]) return;
    if (state.pp < p.cost) return;
    const r = await dispatch("buyPerma", { id: p.id });
    if (r.error) { toast({ title: "Can't unlock", sub: r.error, ico: p.icon }); return; }
    setJustBoughtPerma(p.id);
    clearTimeout(justBoughtTimer.current);
    justBoughtTimer.current = setTimeout(() => setJustBoughtPerma(null), 4200);
    setTab("play");
    toast({ title: "Unlocked!", sub: p.name, ico: p.icon });
  };

  // v2 Nap: unlock 25K (was 5K), gentler exponent 0.6 (was 0.5)
  const canNap = state.totalEarned >= NAP_UNLOCK;
  const napGain = useMemo(
    () => napGainFn(state.totalEarned, sl("stardust")),
    [state.totalEarned, state.skills.stardust]
  );

  const doNap = async () => {
    const r = await dispatch("nap");
    if (r.error) { toast({ title: "Can't nap", sub: r.error, ico: "moon" }); return; }
    setNapOpen(false);
    toast({ title: "WhiteCat napped!", sub: `+${(napGain*10).toFixed(0)}% all PP`, ico: "moon" });
  };

  // Keep latest onPet in a ref so timers / auto-pet can call it
  useEffect(() => { onPetRef.current = onPet; });

  // Auto-pet during Frenzy
  useEffect(() => {
    if (!evMul.autoPet) return;
    const period = 1000 / evMul.autoPet;
    const t = setInterval(() => {
      const el = stageRef.current;
      if (!el || !onPetRef.current) return;
      const r = el.getBoundingClientRect();
      onPetRef.current({
        currentTarget: el,
        clientX: r.left + r.width * (0.3 + Math.random() * 0.4),
        clientY: r.top + r.height * (0.3 + Math.random() * 0.4),
      });
    }, period);
    return () => clearInterval(t);
  }, [evMul.autoPet]);

  /* ============== Event spawning ============== */
  const spawnEvent = useCallback((id) => {
    const def = EVENTS.find((e) => e.id === id);
    if (!def) return;
    const uid = Math.random().toString(36).slice(2);
    const t = Date.now();
    if (def.type === "instant") {
      const reward = (def.reward?.ppsSeconds || 60) * Math.max(pps, 1);
      setState((s) => ({ ...s, pp: s.pp + reward, totalEarned: s.totalEarned + reward }));
      toast({ title: def.name, sub: `+${fmt1(reward)} PP burst`, ico: def.icon });
      return;
    }
    if (def.type === "click") {
      setPending({ uid, def, expiresAt: t + def.duration * 1000 });
      toast({ title: def.name, sub: def.desc, ico: def.icon });
      return;
    }
    // buff: replace existing of same id, refresh duration
    setEvents((evs) => {
      const filtered = evs.filter((e) => e.def.id !== def.id);
      return [...filtered, { uid, def, expiresAt: t + def.duration * 1000 }];
    });
    toast({ title: def.name, sub: def.desc, ico: def.icon });
  }, [pps]);

  const claimPending = () => {
    if (!pending) return;
    const r = pending.def.reward || {};
    const ppGain = (r.ppsSeconds || 30) * Math.max(pps, 1);
    setState((s) => ({
      ...s,
      pp: s.pp + ppGain,
      totalEarned: s.totalEarned + ppGain,
      skillPoints: s.skillPoints + (r.sp || 0),
    }));
    toast({ title: "Claimed!", sub: `+${fmt1(ppGain)} PP${r.sp ? ` · +${r.sp} SP` : ""}`, ico: pending.def.icon });
    setPending(null);
  };
  const dismissPending = () => setPending(null);

  // Events are now server-spawned via /api/state polling (Phase 8)
  // refs to avoid restarting the spawn timer when deps change
  const pendingRef = useRef(null);
  const spawnEventRef = useRef(spawnEvent);
  useEffect(() => { pendingRef.current = pending; }, [pending]);
  useEffect(() => { spawnEventRef.current = spawnEvent; }, [spawnEvent]);

  /* ============== Debug actions (server-side) ============== */
  const dbgGivePP = (n) => dispatch("debugGivePP", { n });
  const dbgGiveSP = (n) => dispatch("debugGiveSP", { n });
  const dbgLevelUp = () => dispatch("debugGivePP", { n: 0 }); // no-op stub; level-up via xp gain
  const dbgMaxAll = () => dispatch("debugGivePP", { n: 0 }); // not yet wired server-side
  const dbgReset = async () => {
    setEvents([]); setPending(null); setCombo(0);
    const r = await dispatch("debugReset");
    if (r.error) toast({ title: "Reset failed", sub: r.error, ico: "trophy" });
    else toast({ title: "State reset", sub: "Fresh start", ico: "sparkle" });
  };
  const dbgResetDaily = async () => {
    const r = await dispatch("debugResetDaily");
    if (r.error) toast({ title: "Reset failed", sub: r.error, ico: "sparkle" });
    else toast({ title: "Daily pull reset", sub: "Roulette ready again", ico: "sparkle" });
  };

  /* Daily gacha (server-authoritative) */
  const dailyAvailable = state.dailyPull.lastDate !== GACHA.todayKey();
  const gachaPullRequest = useCallback(() => dispatch("gachaDaily"), [dispatch]);
  const onGachaClaim = (result) => {
    if (result.tier.stars === 10) { spawnEvent("tournament"); spawnEvent("encore"); }
    else if (result.tier.stars === 9) spawnEvent("encore");
    else if (result.tier.stars === 8) spawnEvent("lucky");
    toast({
      title: `${"★".repeat(result.tier.stars)} ${result.tier.name}!`,
      sub: `${result.tier.flair}`,
      ico: "music",
    });
    setGachaOpen(false);
  };

  function toast({ title, sub, ico }) {
    const id = Math.random();
    setToasts((t) => [...t, { id, title, sub, ico }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 3200);
  }

  const xpNeed = xpForLevel(state.level);
  const xpPct = (state.xp / xpNeed) * 100;
  const totalHelpers = Object.values(state.helpers).reduce((a, b) => a + b, 0);
  const cuteMood = combo > 4 ? "excited" : "happy";

  return (
    <div className="app">
      <Sidebar
        tab={tab}
        setTab={setTab}
        pp={state.pp}
        pps={pps}
        sp={state.skillPoints}
        napBonus={state.napBonus}
        canNap={canNap}
        napUnlock={NAP_UNLOCK}
        openNap={() => setNapOpen(true)}
        theme={theme}
        setTheme={setTheme}
        openDebug={() => setDebugOpen(true)}
        dailyAvailable={dailyAvailable}
        dailyStreak={state.dailyPull.streak}
        dailyLastTier={state.dailyPull.lastTier}
        openGacha={() => dailyAvailable && setGachaOpen(true)}
        now={now}
        authUser={authUser}
        onLogout={logout}
      />
      <main className="main">
        {tab === "play" && (
          <PlayTab
            state={state}
            pps={pps}
            xpPct={xpPct}
            xpNeed={xpNeed}
            mood={cuteMood}
            purring={purring}
            floats={floats}
            onPet={onPet}
            buyHelper={buyHelper}
            sl={sl}
            stageRef={stageRef}
            events={events}
            pending={pending}
            now={now}
            onClaim={claimPending}
            onDismiss={dismissPending}
            activeQuests={activeQuests}
            justBoughtPerma={justBoughtPerma}
          />
        )}
        {tab === "upgrades" && (
          <UpgradesTab state={state} buySkill={buySkill} buyPerma={buyPerma} />
        )}
        {tab === "outfits" && (
          <OutfitsTab state={state} buyOutfit={buyOutfit} sl={sl} />
        )}
        {tab === "collection" && (
          <CollectionTab pulls={state.pulls || []} tiers={GACHA.TIERS} />
        )}
        {tab === "stats" && (
          <StatsTab state={state} pps={pps} petPower={petPower} totalHelpers={totalHelpers} />
        )}
      </main>

      <DebugPanel
        open={debugOpen}
        onClose={() => setDebugOpen(false)}
        onSpawn={spawnEvent}
        eventsDefs={EVENTS}
        onGivePP={dbgGivePP}
        onGiveSP={dbgGiveSP}
        onLevelUp={dbgLevelUp}
        onMaxAll={dbgMaxAll}
        onReset={dbgReset}
        onResetDaily={dbgResetDaily}
        gachaTiers={GACHA.TIERS}
        gachaForcedTier={gachaForcedTier}
        onForceGacha={setGachaForcedTier}
      />

      <GachaModal
        open={gachaOpen}
        onClose={() => setGachaOpen(false)}
        onClaim={onGachaClaim}
        streak={state.dailyPull.streak}
        forcedTier={gachaForcedTier}
        onConsumeForced={() => setGachaForcedTier(null)}
        pullRequest={gachaPullRequest}
      />

      {napOpen && (
        <NapModal
          gain={napGain}
          totalEarned={state.totalEarned}
          onConfirm={doNap}
          onClose={() => setNapOpen(false)}
        />
      )}

      <div className="toast-stack" role="status" aria-live="polite" aria-atomic="false">
        {toasts.map((t) => (
          <div className="toast" key={t.id}>
            <div className="toast-ico" style={{ color: "var(--pink-deep)" }}>
              {Icon[t.ico] ? Icon[t.ico](16) : Icon.heart(16)}
            </div>
            <div>
              <div className="toast-title">{t.title}</div>
              <div className="toast-sub">{t.sub}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ============== Sidebar ============== */
// Sidebar — expose debug toggle on the App via portal-ish prop drilling
function Sidebar({ tab, setTab, pp, pps, sp, napBonus, canNap, napUnlock, openNap, theme, setTheme, openDebug, dailyAvailable, dailyStreak, dailyLastTier, openGacha, now, authUser, onLogout }) {
  const items = [
    { id: "play", label: "Play", ico: "paw" },
    { id: "upgrades", label: "Skill Tree", ico: "star", badge: sp > 0 ? sp : null },
    { id: "outfits", label: "Outfits", ico: "heart" },
    { id: "collection", label: "Collection", ico: "music" },
    { id: "stats", label: "Stats", ico: "trophy" },
  ];
  return (
    <aside className="sidebar">
      <div className="brand">
        <div className="brand-mark">
          <Cat size={32} mood="happy" blink={false} />
        </div>
        <div>
          <div className="brand-name">WhiteCat</div>
          <div className="brand-sub">Idle · v2 Balanced</div>
        </div>
      </div>

      <div className="auth-block">
        {authUser ? (
          <div className="auth-user">
            {authUser.avatar_url && <img src={authUser.avatar_url} alt="" className="auth-avatar" />}
            <div className="auth-info">
              <div className="auth-name">{authUser.username}</div>
              <button className="auth-logout" onClick={onLogout}>Logout</button>
            </div>
          </div>
        ) : (
          <a className="auth-login" href="/auth/osu">
            Login with osu!
          </a>
        )}
      </div>

      <div className="resources">
        <div className="res-card">
          <div className="res-icon pp">{Icon.paw(20)}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="res-label">Performance Pts</div>
            <div className="res-value">{fmt(pp)}</div>
            <div className="res-rate">+{fmt1(pps)} / sec</div>
          </div>
        </div>
        {sp > 0 && (
          <div className="res-card">
            <div className="res-icon fish">{Icon.sparkle(20)}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="res-label">Skill Points</div>
              <div className="res-value">{sp}</div>
              <div className="res-rate">spend in skill tree</div>
            </div>
          </div>
        )}
        {napBonus > 1.001 && (
          <div className="res-card">
            <div className="res-icon cb">{Icon.moon(20)}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="res-label">Nap Bonus</div>
              <div className="res-value">×{napBonus.toFixed(2)}</div>
              <div className="res-rate">all PP gain</div>
            </div>
          </div>
        )}
      </div>

      <GachaCard
        available={dailyAvailable}
        streak={dailyStreak}
        lastTier={dailyLastTier}
        onOpen={openGacha}
        now={now}
      />

      <nav className="nav">
        {items.map((it) => (
          <button
            key={it.id}
            className={`nav-item ${tab === it.id ? "active" : ""}`}
            onClick={() => setTab(it.id)}
          >
            <span className="nav-ico">{Icon[it.ico](18)}</span>
            <span>{it.label}</span>
            {it.badge && <span className="nav-badge">{it.badge}</span>}
          </button>
        ))}
      </nav>

      <div className="sidebar-footer">
        <button className="nap-btn" onClick={openNap} disabled={!canNap}>
          {Icon.moon(16)}
          <span>Take a Nap</span>
        </button>
        <div className="nap-hint">
          {canNap ? "Reset for permanent boost" : `Earn ${fmt(napUnlock)} PP to unlock`}
        </div>
        <div className="theme-toggle">
          <button className={`theme-btn ${theme === "light" ? "active" : ""}`} onClick={() => setTheme("light")}>
            {Icon.sun(13)} Light
          </button>
          <button className={`theme-btn ${theme === "dark" ? "active" : ""}`} onClick={() => setTheme("dark")}>
            {Icon.moon(13)} Dark
          </button>
        </div>
        <button className="debug-trigger" onClick={openDebug} title="Debug menu">
          {Icon.gear(13)} Debug menu
        </button>
      </div>
    </aside>
  );
}

/* ============== Play tab ============== */
function PlayTab({ state, pps, xpPct, xpNeed, mood, purring, floats, onPet, buyHelper, sl, stageRef, events, pending, now, onClaim, onDismiss, activeQuests, justBoughtPerma }) {
  return (
    <>
      <div className="page-head">
        <div>
          <h1 className="page-title">Pet WhiteCat</h1>
          <div className="page-sub">Tap the cat. Hire friends. Earn Performance Points.</div>
        </div>
      </div>
      <EventsBar events={events} now={now} />
      <div className="play-grid">
        <CatStage
          state={state}
          mood={mood}
          purring={purring}
          floats={floats}
          xpPct={xpPct}
          xpNeed={xpNeed}
          pps={pps}
          onPet={onPet}
          stageRef={stageRef}
          pending={pending}
          now={now}
          onClaim={onClaim}
          onDismiss={onDismiss}
          justBoughtPerma={justBoughtPerma}
        />
        <div className="side-panel">
          <HelpersPanel state={state} buyHelper={buyHelper} sl={sl} />
          <QuestsPanel state={state} activeQuests={activeQuests} />
        </div>
      </div>
    </>
  );
}

function CatStage({ state, mood, purring, floats, xpPct, xpNeed, pps, onPet, stageRef, pending, now, onClaim, onDismiss, justBoughtPerma }) {
  return (
    <div className="cat-stage" ref={stageRef}>
      <div className="stage-bg" />
      <div className="stage-floor" />
      <StageDecor perma={state.perma} justBoughtPerma={justBoughtPerma} />

      {/* Decorative sparkles */}
      <div className="sparkle" style={{ top: 60, left: 80, color: "#ffafcc" }}>
        {Icon.sparkle(14)}
      </div>
      <div className="sparkle" style={{ top: 140, right: 90, color: "#cdb4db", animationDelay: "1s" }}>
        {Icon.sparkle(18)}
      </div>
      <div className="sparkle" style={{ bottom: 200, left: 60, color: "#ffc8dd", animationDelay: "2s" }}>
        {Icon.sparkle(12)}
      </div>
      <div className="sparkle" style={{ bottom: 160, right: 70, color: "#e2d2ec", animationDelay: "3s" }}>
        {Icon.sparkle(16)}
      </div>

      <div className="stage-info">
        <div className="cat-name">WhiteCat</div>
        <div className="cat-mood"><span className="mood-dot" />{mood === "excited" ? "Excited!" : "Content"}</div>
      </div>

      <div className="stage-level">
        <div className="level-pill">{Icon.star(12)} Lv {state.level}</div>
        <div className="xp-bar" role="progressbar" aria-valuenow={Math.round(xpPct)} aria-valuemin={0} aria-valuemax={100} aria-label={`XP: ${Math.floor(state.xp)} of ${xpNeed}`}><div className="xp-fill" style={{ width: `${xpPct}%` }} /></div>
        <div className="xp-text">{Math.floor(state.xp)} / {xpNeed} XP</div>
      </div>

      <div
        className={`cat-wrap ${purring ? "purring" : ""}`}
        onClick={onPet}
        onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && onPet(e)}
        role="button"
        tabIndex={0}
        aria-label="Pet WhiteCat"
        style={{ position: "relative" }}
      >
        <Cat size={300} mood={mood} outfit={state.outfit} purring={purring} />
        {floats.map((f) => (
          f.heart ? (
            <div key={f.id} className="cat-heart" style={{ left: f.x, top: f.y }}>
              {Icon.heart(22)}
            </div>
          ) : (
            <div
              key={f.id}
              className="cat-floater"
              style={{
                left: f.x, top: f.y,
                color: f.crit ? "#c79b22" : "var(--pink-deep)",
                fontSize: f.crit ? 24 : 18,
              }}
            >
              {f.crit ? "✦ " : ""}{f.txt}
            </div>
          )
        ))}
      </div>

      <div className="stage-hint">
        Click anywhere on the cat to pet · {fmt1(pps)} PP/s passive
      </div>

      <EventPopup pending={pending} now={now} onClaim={onClaim} onDismiss={onDismiss} />
    </div>
  );
}

/* ============== Stage decorations — appear when a perma upgrade is bought ============== */
const PERMA_LABELS = {
  tablet:     "Pro Tablet",
  skin:       "Custom Skin",
  headphones: "Studio Headphones",
  energy:     "Energy Drink",
  pp_save:    "Cloud Saves",
  supporter:  "Supporter Tag",
  legendary:  "Legendary Tablet",
};

function StageDecor({ perma, justBoughtPerma }) {
  const items = [
    perma.headphones && (
      <div key="headphones" className={`decor decor-headphones ${justBoughtPerma === "headphones" ? "decor-pop" : ""}`}>
        <div className="d-hp-hook" />
        <div className="d-hp-cord" />
        <div className="d-hp-band" />
        <div className="d-hp-cup d-hp-cup-l" />
        <div className="d-hp-cup d-hp-cup-r" />
      </div>
    ),
    perma.pp_save && (
      <div key="pp_save" className={`decor decor-cloud ${justBoughtPerma === "pp_save" ? "decor-pop" : ""}`}>
        <div className="d-cloud">
          <div className="d-cloud-puff p1" />
          <div className="d-cloud-puff p2" />
          <div className="d-cloud-puff p3" />
          <div className="d-cloud-puff p4" />
        </div>
      </div>
    ),
    perma.skin && (
      <div key="skin" className={`decor decor-skin ${justBoughtPerma === "skin" ? "decor-pop" : ""}`}>
        <div className="d-skin-tape" />
        <div className="d-skin-name">skin.pp</div>
      </div>
    ),
    perma.supporter && (
      <div key="supporter" className={`decor decor-supporter ${justBoughtPerma === "supporter" ? "decor-pop" : ""}`}>
        <div className="d-pin">
          {Icon.heart(18, "#ffffff")}
        </div>
        <div className="d-pin-label">SUPPORTER</div>
      </div>
    ),
    perma.tablet && (
      <div key="tablet" className={`decor decor-tablet ${justBoughtPerma === "tablet" ? "decor-pop" : ""}`}>
        <div className="d-tablet-pad">
          <div className="d-tablet-active" />
          <div className="d-tablet-led" />
        </div>
        <div className="d-tablet-pen" />
      </div>
    ),
    perma.energy && (
      <div key="energy" className={`decor decor-energy ${justBoughtPerma === "energy" ? "decor-pop" : ""}`}>
        <div className="d-can">
          <div className="d-can-top" />
          <div className="d-can-stripe" />
          <div className="d-can-bolt" />
        </div>
      </div>
    ),
    perma.legendary && (
      <div key="legendary" className={`decor decor-legendary ${justBoughtPerma === "legendary" ? "decor-pop" : ""}`}>
        <div className="d-legend-glow" />
        <div className="d-legend-ring" />
        <div className="d-legend-trophy">{Icon.trophy(34)}</div>
        <div className="d-legend-spark s1">{Icon.sparkle(10)}</div>
        <div className="d-legend-spark s2">{Icon.sparkle(8)}</div>
        <div className="d-legend-spark s3">{Icon.sparkle(12)}</div>
      </div>
    ),
  ].filter(Boolean);

  return (
    <div className="stage-decor">
      {items}
      {justBoughtPerma && PERMA_LABELS[justBoughtPerma] && (
        <div className={`decor-unlock-banner decor-unlock-${justBoughtPerma}`}>
          <span className="dub-spark">✦</span>
          <span>New on stage</span>
          <span className="dub-name">{PERMA_LABELS[justBoughtPerma]}</span>
        </div>
      )}
    </div>
  );
}

function HelpersPanel({ state, buyHelper, sl }) {
  return (
    <div className="panel">
      <div className="panel-head">
        <div>
          <div className="panel-title">Helpers</div>
          <div className="panel-sub">Auto-earn PP per second</div>
        </div>
      </div>
      <div className="helpers">
        {HELPERS.map((h) => {
          const owned = state.helpers[h.id] || 0;
          const cost = helperCost(h, owned, sl("smile"));
          const locked = state.totalEarned < h.unlock;
          const can = !locked && state.pp >= cost;
          const ariaLabel = locked
            ? `${h.name} — locked, unlock at ${fmt(h.unlock)} PP`
            : `Hire ${h.name} for ${fmt(cost)} PP, adds ${fmt1(h.pps * helperMilestoneMult(owned))} PP/s`;
          return (
            <div
              key={h.id}
              className={`helper ${locked ? "locked" : ""}`}
              onClick={() => !locked && can && buyHelper(h)}
              onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && !locked && can && buyHelper(h)}
              role="button"
              tabIndex={locked || !can ? -1 : 0}
              aria-label={ariaLabel}
              aria-disabled={locked || !can}
            >
              <div className="helper-ico" style={{ color: "var(--pink-deep)" }} aria-hidden="true">
                {HELPER_ICON[h.icon] ? HELPER_ICON[h.icon](18) : Icon.paw(18)}
              </div>
              <div className="helper-mid">
                <div className="helper-name">
                  {locked ? "???" : h.name}
                  {owned > 0 && <span className="helper-count" style={{ marginLeft: 8 }}>×{owned}</span>}
                </div>
                <div className="helper-meta">
                  {locked
                    ? `Unlock at ${fmt(h.unlock)} PP`
                    : `+${fmt1(h.pps * helperMilestoneMult(owned))} PP/s · ${owned >= 25 ? `×${helperMilestoneMult(owned)} bonus` : `next ×2 at ${25 - (owned % 25)}`}`}
                </div>
              </div>
              <div className={`helper-cost ${!can ? "cant" : ""}`} aria-hidden="true">
                {locked ? <><span aria-hidden="true">🔒</span><span className="sr-only">Locked</span></> : `${fmt(cost)} PP`}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function QuestsPanel({ state, activeQuests }) {
  return (
    <div className="panel">
      <div className="panel-head">
        <div>
          <div className="panel-title">Daily Quests</div>
          <div className="panel-sub">Scales each nap</div>
        </div>
      </div>
      {activeQuests.map((q) => {
        const done = state.questDone[q.id];
        let v = 0;
        if (q.metric === "pets") v = state.pets;
        if (q.metric === "earned") v = state.totalEarned;
        if (q.metric === "helpers") v = Object.values(state.helpers).reduce((a, b) => a + b, 0);
        if (q.metric === "level") v = state.level;
        const pct = Math.min(100, (v / q.target) * 100);
        return (
          <div key={q.id} className={`quest ${done ? "done" : ""}`}>
            <div className="quest-row">
              <div className="quest-name">{q.name}</div>
              <div className="quest-reward">
                {q.rewardType === "pp" ? `+${q.reward} PP` : `+${q.reward} SP`}
              </div>
            </div>
            <div className="quest-prog" role="progressbar" aria-valuenow={Math.round(pct)} aria-valuemin={0} aria-valuemax={100} aria-label={`${q.name}: ${Math.round(pct)}% complete`}><div className="quest-prog-fill" style={{ width: `${pct}%` }} /></div>
            <div className="quest-meta">
              {done ? "✓ Complete" : `${fmt(Math.min(v, q.target))} / ${fmt(q.target)}`}
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ============== Upgrades / Skill Tree ============== */
function UpgradesTab({ state, buySkill, buyPerma }) {
  return (
    <>
      <div className="page-head">
        <div>
          <h1 className="page-title">Skill Tree</h1>
          <div className="page-sub">Spend skill points to make WhiteCat shine.</div>
        </div>
      </div>
      <div className="skill-points-banner">
        <div className="sp-num">{state.skillPoints}</div>
        <div className="sp-meta">
          <div className="sp-meta-title">Skill Points available</div>
          <div className="sp-meta-sub">Earn 1 SP per level up. Skills are permanent across naps.</div>
        </div>
      </div>
      <div className="skill-grid">
        <Branch
          name="Aim"
          desc="Pet power & crits"
          icon="star"
          klass="rhythm"
          skills={SKILLS.aim}
          state={state}
          buySkill={buySkill}
        />
        <Branch
          name="Streams"
          desc="XP, helpers & outfits"
          icon="music"
          klass="cute"
          skills={SKILLS.streams}
          state={state}
          buySkill={buySkill}
        />
        <Branch
          name="Stamina"
          desc="Drops & nap power"
          icon="sparkle"
          klass="luck"
          skills={SKILLS.stamina}
          state={state}
          buySkill={buySkill}
        />
      </div>

      <div className="page-head" style={{ marginTop: 36 }}>
        <div>
          <h1 className="page-title">Permanent Upgrades</h1>
          <div className="page-sub">Bought with PP. Kept forever — even after a nap.</div>
        </div>
      </div>
      <div className="perma-grid">
        {PERMA.map((p) => {
          const owned = !!state.perma[p.id];
          const can = !owned && state.pp >= p.cost;
          const permaLabel = owned
            ? `${p.name} — already owned. ${p.desc}`
            : `${p.name}: ${p.desc}. Cost: ${fmt(p.cost)} PP`;
          return (
            <div
              key={p.id}
              className={`perma ${owned ? "owned" : ""} ${can ? "affordable" : ""}`}
              onClick={() => !owned && can && buyPerma(p)}
              onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && !owned && can && buyPerma(p)}
              role="button"
              tabIndex={owned || !can ? -1 : 0}
              aria-label={permaLabel}
              aria-disabled={owned || !can}
            >
              <div className="perma-ico">{HELPER_ICON[p.icon] ? HELPER_ICON[p.icon](22) : Icon.star(22)}</div>
              <div className="perma-mid">
                <div className="perma-name">{p.name}</div>
                <div className="perma-desc">{p.desc}</div>
                <div className="perma-effect">{p.effect}</div>
              </div>
              <div className={`perma-cost ${owned ? "owned" : !can ? "cant" : ""}`}>
                {owned ? "OWNED" : `${fmt(p.cost)} PP`}
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
}

function Branch({ name, desc, icon, klass, skills, state, buySkill }) {
  return (
    <div className="skill-branch">
      <div className="branch-head">
        <div className={`branch-ico ${klass}`}>{Icon[icon](22)}</div>
        <div>
          <div className="branch-name">{name}</div>
          <div className="branch-desc">{desc}</div>
        </div>
      </div>
      {skills.map((sk, i) => {
        const lvl = state.skills[sk.id] || 0;
        const maxed = lvl >= sk.max;
        // Lock if previous skill not started
        const locked = i > 0 && (state.skills[skills[i-1].id] || 0) === 0;
        const affordable = !maxed && !locked && state.skillPoints >= sk.cost;
        const skLabel = maxed
          ? `${sk.name} — maxed out`
          : locked
          ? `${sk.name} — locked, upgrade previous skill first`
          : `${sk.name}: ${sk.desc}. Cost: ${sk.cost} SP. Level ${lvl} of ${sk.max}`;
        return (
          <div
            key={sk.id}
            className={`skill-node ${maxed ? "maxed" : ""} ${locked ? "locked" : ""} ${affordable ? "affordable" : ""}`}
            onClick={() => !maxed && !locked && affordable && buySkill(sk)}
            onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && !maxed && !locked && affordable && buySkill(sk)}
            role="button"
            tabIndex={maxed || locked || !affordable ? -1 : 0}
            aria-label={skLabel}
            aria-disabled={maxed || locked || !affordable}
          >
            <div className="skill-icon">
              {klass === "rhythm" && Icon.star(18)}
              {klass === "cute" && Icon.music(18)}
              {klass === "luck" && Icon.sparkle(18)}
            </div>
            <div>
              <div className="skill-name">{sk.name}</div>
              <div className="skill-desc">{sk.desc} · {sk.effect(Math.max(1, lvl))}</div>
              <div className="skill-pips">
                {Array.from({ length: sk.max }).map((_, j) => (
                  <span key={j} className={`skill-pip ${j < lvl ? "on" : ""}`} />
                ))}
              </div>
            </div>
            <div className={`skill-cost ${maxed ? "maxed" : locked ? "locked" : ""}`}>
              {maxed ? "MAX" : locked ? "🔒" : `${sk.cost} SP`}
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ============== Outfits ============== */
function OutfitsTab({ state, buyOutfit, sl }) {
  return (
    <>
      <div className="page-head">
        <div>
          <h1 className="page-title">Outfits</h1>
          <div className="page-sub">Dress up WhiteCat. Each outfit grants a bonus.</div>
        </div>
      </div>
      <div className="outfit-grid">
        {OUTFITS.map((o) => {
          const owned = state.ownedOutfits.includes(o.id);
          const equipped = state.outfit === o.id;
          const locked = !owned && state.totalEarned < o.req;
          const outfitLabel = locked
            ? `Outfit locked — unlock at ${fmt(o.req)} PP earned`
            : equipped
            ? `${o.name} — currently equipped. ${o.bonus}`
            : owned
            ? `${o.name} — owned, click to equip. ${o.bonus}`
            : `${o.name} — buy for ${fmt(o.req)} PP. ${o.bonus}`;
          return (
            <div
              key={o.id}
              className={`outfit ${equipped ? "equipped" : ""} ${locked ? "locked" : ""}`}
              onClick={() => !locked && buyOutfit(o)}
              onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && !locked && buyOutfit(o)}
              role="button"
              tabIndex={locked ? -1 : 0}
              aria-label={outfitLabel}
              aria-pressed={equipped}
            >
              <div className="outfit-thumb">
                <Cat size={140} mood="happy" outfit={o.id} blink={false} />
              </div>
              <div className="outfit-name">{locked ? "???" : o.name}</div>
              <div className="outfit-bonus">
                {locked ? `Unlock at ${fmt(o.req)} PP earned` : o.bonus}
              </div>
              {equipped && <span className="outfit-tag tag-equipped">Equipped</span>}
              {!equipped && owned && o.id !== "none" && <span className="outfit-tag tag-new">Owned</span>}
              {!owned && !locked && <span className="outfit-tag tag-new" style={{ background: "var(--butter)", color: "#8a6a14" }}>{fmt(o.req)} PP</span>}
              {locked && <span className="outfit-tag tag-locked">Locked</span>}
            </div>
          );
        })}
      </div>
    </>
  );
}

/* ============== Stats ============== */
function StatsTab({ state, pps, petPower, totalHelpers }) {
  return (
    <>
      <div className="page-head">
        <div>
          <h1 className="page-title">Stats</h1>
          <div className="page-sub">Your career as WhiteCat&rsquo;s human.</div>
        </div>
      </div>
      <div className="stats-grid">
        <StatCard label="Total PP earned" value={fmt(state.totalEarned)} trend={`+${fmt1(pps)}/s now`} />
        <StatCard label="Times petted" value={fmt(state.pets)} trend={`${fmt1(petPower)} PP per pet`} />
        <StatCard label="Helpers hired" value={totalHelpers} trend={`${HELPERS.filter(h => state.helpers[h.id]).length} types`} />
        <StatCard label="Naps taken" value={state.napCount} trend={`×${state.napBonus.toFixed(2)} bonus`} />
      </div>
      <div className="stat-section">
        <div className="panel-title" style={{ marginBottom: 14 }}>Helpers Roster</div>
        {HELPERS.map((h) => {
          const owned = state.helpers[h.id] || 0;
          if (owned === 0) return null;
          return (
            <div className="stat-row" key={h.id}>
              <span className="lbl">{h.name} ×{owned}</span>
              <span className="val">{fmt1(owned * h.pps)} PP/s</span>
            </div>
          );
        })}
        {totalHelpers === 0 && <div className="stat-row"><span className="lbl">No helpers hired yet</span></div>}
      </div>
      <div className="stat-section">
        <div className="panel-title" style={{ marginBottom: 14 }}>Skills Trained</div>
        {Object.entries(SKILLS).flatMap(([branch, list]) => list).map((sk) => {
          const lvl = state.skills[sk.id] || 0;
          if (lvl === 0) return null;
          return (
            <div className="stat-row" key={sk.id}>
              <span className="lbl">{sk.name}</span>
              <span className="val">Lv {lvl} / {sk.max}</span>
            </div>
          );
        })}
        {Object.values(state.skills).every((v) => v === 0) && (
          <div className="stat-row"><span className="lbl">No skills trained yet</span></div>
        )}
      </div>
    </>
  );
}

function StatCard({ label, value, trend }) {
  return (
    <div className="stat-card">
      <div className="stat-label">{label}</div>
      <div className="stat-value">{value}</div>
      <div className="stat-trend">{trend}</div>
    </div>
  );
}

/* ============== Nap Modal ============== */
function NapModal({ gain, totalEarned, onConfirm, onClose }) {
  useEffect(() => {
    const fn = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", fn);
    return () => document.removeEventListener("keydown", fn);
  }, [onClose]);

  return (
    <div className="modal-veil" onClick={onClose} aria-hidden="true">
      <div
        className="modal"
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="nap-modal-title"
      >
        <div className="modal-cat">
          <Cat size={140} mood="sleepy" blink={false} />
        </div>
        <div className="modal-title" id="nap-modal-title">Take a nap?</div>
        <div className="modal-body">
          WhiteCat will reset progress, but earn a permanent <strong>nap bonus</strong> based
          on how much PP you&rsquo;ve gathered. Skills, outfits, and naps are kept.
        </div>
        <div className="modal-stat">
          <div className="modal-stat-item">
            <div className="lbl">Bonus gained</div>
            <div className="val">+{(gain * 10).toFixed(0)}%</div>
          </div>
          <div className="modal-stat-item">
            <div className="lbl">Free skill pts</div>
            <div className="val">+{Math.floor(gain / 2)}</div>
          </div>
          <div className="modal-stat-item">
            <div className="lbl">Resets at</div>
            <div className="val">{fmt(totalEarned)}</div>
          </div>
        </div>
        <div className="modal-actions">
          <button className="btn" onClick={onClose}>Not yet</button>
          <button className="btn primary" onClick={onConfirm}>Sweet dreams</button>
        </div>
      </div>
    </div>
  );
}

/* ============== Mount ============== */
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
