/* ===== Mi Urbania · App root: context, shell, nav, onboarding, demo control ===== */
window.MU = window.MU || {};
(function (MU) {
  const { useState, useEffect, useRef, useMemo } = React;
  const e = React.createElement;
  const DAY = 86400000;

  MU.Ctx = MU.Ctx || React.createContext(null);
  MU.useApp = () => React.useContext(MU.Ctx);

  const NAV = [
    { id: "home", icon: "home", key: "nav_home" },
    { id: "unit", icon: "building", key: "nav_unit" },
    { id: "report", icon: "report", key: "nav_report", center: true },
    { id: "warranties", icon: "shield", key: "nav_warranties" },
    { id: "help", icon: "help", key: "nav_help" },
  ];
  const SCREENS = { home: () => MU.Home, unit: () => MU.Unit, report: () => MU.Report, warranties: () => MU.Warranties, help: () => MU.Help };

  /* ---------- Language toggle ---------- */
  function LangToggle({ lang, setLang }) {
    return e("div", { className: "mu-seg", style: { padding: 2 } },
      ["es", "en"].map((l) => { const active = lang === l; return e("button", { key: l, onClick: () => setLang(l), className: "mu-seg-btn", style: { padding: "5px 10px", fontSize: 12, fontWeight: 700, textTransform: "uppercase", background: active ? "#fff" : "transparent", color: active ? "var(--ink)" : "var(--ink-3)", boxShadow: active ? "var(--sh-1)" : "none" } }, l); }));
  }

  /* ---------- Top bar ---------- */
  function TopBar({ app, onUnits, onNotif, onDemo }) {
    const { lang, unit } = app;
    return e("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "12px 14px", borderBottom: "1px solid var(--line)", background: "rgba(247,245,241,.86)", backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)", position: "sticky", top: 0, zIndex: 20 } },
      e("button", { onClick: onUnits, style: { display: "flex", alignItems: "center", gap: 8, padding: "5px 9px 5px 6px", borderRadius: 11, background: "rgba(14,17,22,.04)" } },
        e("img", { src: "app/logo-green.png", alt: "Urbania", style: { height: 17, display: "block" } }),
        e("div", { style: { width: 1, height: 18, background: "var(--line-2)" } }),
        e("div", { style: { textAlign: "left", lineHeight: 1.05 } },
          e("div", { style: { fontSize: 12.5, fontWeight: 800, letterSpacing: "-.01em" } }, unit.unitNumber),
          e("div", { style: { fontSize: 9.5, color: "var(--ink-4)", fontWeight: 600 } }, unit.projectName)),
        e(MU.Icon, { name: "chevD", size: 14, color: "var(--ink-4)" })),
      e("div", { style: { flex: 1 } }),
      e(LangToggle, { lang, setLang: app.setLang }),
      e("button", { className: "mu-iconbtn", onClick: onNotif, style: { position: "relative" } },
        e(MU.Icon, { name: "bell", size: 20 }),
        app.unreadCount > 0 && e("span", { style: { position: "absolute", top: 5, right: 5, minWidth: 15, height: 15, padding: "0 3px", borderRadius: 9, background: "var(--urgent)", color: "#fff", fontSize: 9.5, fontWeight: 800, display: "flex", alignItems: "center", justifyContent: "center", border: "2px solid var(--paper)" } }, app.unreadCount)),
      e("button", { className: "mu-iconbtn", onClick: onDemo, "aria-label": "demo" }, e(MU.Icon, { name: "sliders", size: 19 })));
  }

  /* ---------- Bottom nav ---------- */
  function BottomNav({ app }) {
    const { lang, tab } = app;
    return e("div", { style: { position: "absolute", left: 0, right: 0, bottom: 0, display: "flex", alignItems: "flex-end", justifyContent: "space-around", padding: "8px 8px calc(8px + env(safe-area-inset-bottom))", background: "rgba(247,245,241,.92)", backdropFilter: "blur(14px)", WebkitBackdropFilter: "blur(14px)", borderTop: "1px solid var(--line)", zIndex: 30 } },
      NAV.map((n) => {
        if (n.center) return e("button", { key: n.id, onClick: () => app.openReport(null), style: { transform: "translateY(-12px)", display: "flex", flexDirection: "column", alignItems: "center", gap: 4 } },
          e("div", { style: { width: 54, height: 54, borderRadius: 99, background: "var(--brand)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", boxShadow: "0 8px 22px rgba(31,111,92,.4)", border: "3px solid var(--paper)" } }, e(MU.Icon, { name: "report", size: 25, stroke: 2.4 })),
          e("div", { style: { fontSize: 10, fontWeight: 700, color: "var(--brand)" } }, MU.t(lang, n.key)));
        const active = tab === n.id;
        return e("button", { key: n.id, onClick: () => app.setTab(n.id), style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 4, padding: "4px 0", color: active ? "var(--brand)" : "var(--ink-4)" } },
          e(MU.Icon, { name: n.icon, size: 22, stroke: active ? 2.1 : 1.8 }),
          e("div", { style: { fontSize: 10, fontWeight: active ? 800 : 600 } }, MU.t(lang, n.key)));
      }));
  }

  /* ---------- Desktop rail ---------- */
  function Rail({ app }) {
    const { lang, tab } = app;
    return e("div", { style: { width: 230, flex: "0 0 auto", borderRight: "1px solid var(--line)", padding: "22px 16px", display: "flex", flexDirection: "column", gap: 4, background: "var(--card-warm)" } },
      e("img", { src: "app/logo-green.png", alt: "Urbania", style: { height: 22, alignSelf: "flex-start", margin: "0 6px 22px" } }),
      NAV.map((n) => {
        const active = tab === n.id;
        const onClick = n.center ? () => app.openReport(null) : () => app.setTab(n.id);
        return e("button", { key: n.id, onClick, style: { display: "flex", alignItems: "center", gap: 12, padding: "11px 13px", borderRadius: 13, textAlign: "left", background: active ? "var(--brand-soft)" : n.center ? "var(--brand)" : "transparent", color: n.center ? "#fff" : active ? "var(--brand-deep)" : "var(--ink-2)", fontWeight: active || n.center ? 700 : 600, fontSize: 14, marginBottom: n.center ? 4 : 0 } },
          e(MU.Icon, { name: n.icon, size: 20, stroke: active || n.center ? 2.1 : 1.8 }), MU.t(lang, n.key));
      }));
  }

  /* ---------- Unit switcher sheet ---------- */
  function UnitSheet({ open, onClose, app }) {
    const { lang, unit } = app;
    const tt = (k) => MU.t(lang, k);
    return e(MU.Sheet, { open, onClose, title: tt("switch_unit") },
      e("div", { style: { display: "flex", flexDirection: "column", gap: 10 } },
        MU.UNITS.map((u) => {
          const active = u.id === unit.id;
          const pre = u.status !== "delivered";
          return e("button", { key: u.id, onClick: () => { app.setUnitId(u.id); onClose(); }, className: "mu-card", style: { padding: 13, display: "flex", gap: 12, alignItems: "center", textAlign: "left", border: active ? "2px solid var(--brand)" : "1px solid var(--line)" } },
            e(MU.Placeholder, { label: u.unitNumber, h: 52, radius: 11, style: { width: 52, flex: "0 0 auto", fontSize: 10 } }),
            e("div", { style: { flex: 1 } },
              e("div", { style: { fontWeight: 700, fontSize: 14.5 } }, u.projectName + " · " + u.unitNumber),
              e("div", { style: { fontSize: 12, color: "var(--ink-4)", marginTop: 2 } }, u.model + " · " + u.areaM2 + " m²"),
              e("div", { style: { marginTop: 6 } }, e(MU.StatusPill, { status: pre ? "soon" : "active", small: true, label: pre ? MU.t(lang, "ms_" + u.status) : MU.t(lang, "ms_delivered") }))),
            active && e(MU.Icon, { name: "check", size: 20, color: "var(--brand)" }));
        })));
  }

  /* ---------- Notifications sheet ---------- */
  function NotifSheet({ open, onClose, app }) {
    const { lang } = app;
    const tt = (k) => MU.t(lang, k);
    const ICON = { crack: "crack", claim: "report", expiry: "clock", maintenance: "spark", handover: "home" };
    return e(MU.Sheet, { open, onClose, title: tt("notifications"),
      headerRight: app.unreadCount > 0 && e("button", { onClick: app.markAllRead, style: { fontSize: 12, fontWeight: 700, color: "var(--brand)", padding: "0 8px" } }, tt("mark_all_read")) },
      app.notifications.length === 0
        ? e("p", { className: "mu-sub", style: { textAlign: "center", padding: 30 } }, tt("no_notifications"))
        : e("div", { style: { display: "flex", flexDirection: "column", gap: 9 } },
          app.notifications.map((n) => e("button", { key: n.id, onClick: () => { app.markRead(n.id); onClose(); if (n.link) setTimeout(() => app.navigate(n.link), 60); }, className: "mu-card", style: { padding: 13, display: "flex", gap: 12, textAlign: "left", alignItems: "flex-start", background: n.read ? "var(--card)" : "var(--brand-soft)" } },
            e("div", { style: { width: 36, height: 36, borderRadius: 11, flex: "0 0 auto", background: n.read ? "rgba(14,17,22,.05)" : "#fff", color: "var(--brand)", display: "flex", alignItems: "center", justifyContent: "center" } }, e(MU.Icon, { name: ICON[n.type] || "bell", size: 18 })),
            e("div", { style: { flex: 1 } },
              e("div", { style: { fontWeight: 700, fontSize: 13.5, lineHeight: 1.3 } }, n["title_" + lang]),
              e("div", { style: { fontSize: 12.5, color: "var(--ink-3)", marginTop: 3, lineHeight: 1.4 } }, n["body_" + lang]),
              e("div", { style: { fontSize: 11, color: "var(--ink-4)", marginTop: 6 } }, MU.formatDate(n.date, lang))),
            !n.read && e("span", { style: { width: 8, height: 8, borderRadius: 9, background: "var(--brand)", flex: "0 0 auto", marginTop: 5 } }))))
    );
  }

  /* ---------- Demo control sheet ---------- */
  function DemoPanel({ open, onClose, app }) {
    const { lang } = app;
    const tt = (k) => MU.t(lang, k);
    const u = app.unit;
    const handover = MU.D(u.handoverDate);
    const ageNow = MU.daysBetween(handover, app.now);
    const presets = [
      { label: tt("demo_reset"), off: 0 },
      { label: lang === "es" ? "Cierre fisuras" : "Crack close", target: 241 },
      { label: lang === "es" ? "Vence pintura" : "Paint expires", target: 181 },
      { label: lang === "es" ? "1 año" : "1 year", target: 366 },
      { label: lang === "es" ? "2 años" : "2 years", target: 731 },
    ];
    const baseAge = MU.daysBetween(handover, app.baseNow);
    return e(MU.Sheet, { open, onClose, title: tt("demo_title") },
      e("p", { className: "mu-sub", style: { marginBottom: 16 } }, tt("demo_sub")),
      e("div", { style: { display: "flex", alignItems: "baseline", gap: 8, marginBottom: 6 } },
        e("div", { className: "tnum", style: { fontFamily: "var(--display)", fontSize: 32, fontWeight: 800, color: "var(--brand)" } }, Math.max(0, ageNow)),
        e("div", { style: { fontSize: 13, color: "var(--ink-3)", fontWeight: 600 } }, lang === "es" ? "días desde la entrega" : "days since handover")),
      e("div", { style: { fontSize: 12, color: "var(--ink-4)", marginBottom: 14 } }, lang === "es" ? "Fecha simulada: " : "Simulated date: ", MU.formatDate(app.now, lang)),
      e("input", { type: "range", min: 0, max: 760, value: app.offset, onChange: (ev) => app.setOffset(+ev.target.value), style: { width: "100%", accentColor: "var(--brand)" } }),
      e("div", { style: { display: "flex", gap: 7, flexWrap: "wrap", marginTop: 16 } },
        presets.map((p, i) => e("button", { key: i, className: "mu-chip", onClick: () => app.setOffset(p.off != null ? p.off : Math.max(0, (p.target - baseAge))) }, p.label))),
      e("div", { className: "mu-divider", style: { margin: "20px 0" } }),
      e("div", { style: { fontSize: 12, color: "var(--ink-4)", fontWeight: 700, textTransform: "uppercase", letterSpacing: ".1em", marginBottom: 10 } }, tt("demo_mode")),
      e("p", { className: "mu-sub", style: { fontSize: 12.5, marginBottom: 12 } }, lang === "es" ? "Cambia de unidad (arriba) para ver el modo pre-entrega de Casa 14, y desliza el tiempo para verla transformarse en el reloj." : "Switch units (top) to see Casa 14 in pre-delivery mode, then slide time forward to watch it transform into the clock."),
      e(MU.Btn, { variant: "outline", block: true, icon: "refresh", onClick: () => { app.replayOnboarding(); onClose(); } }, lang === "es" ? "Ver onboarding otra vez" : "Replay onboarding"),
      e(MU.Btn, { variant: "ghost", block: true, icon: "x", style: { marginTop: 9 }, onClick: () => { if (window.confirm(lang === "es" ? "¿Borrar reportes, notificaciones y tareas guardados y restablecer los datos de demo?" : "Clear saved claims, notifications and tasks, and reset the demo data?")) app.resetData(); } }, lang === "es" ? "Restablecer datos guardados" : "Reset saved data"));
  }

  /* ---------- Onboarding ---------- */
  function Onboarding({ app, onDone }) {
    const [step, setStep] = useState(0);
    const [lang, setLang] = useState(app.lang);
    const [unitId, setUnitId] = useState(app.unit.id);
    const tt = (k) => MU.t(lang, k);
    const tours = [["ob_tour_1_t", "ob_tour_1_b", "shield"], ["ob_tour_2_t", "ob_tour_2_b", "camera"], ["ob_tour_3_t", "ob_tour_3_b", "home"]];

    const wrap = (children) => e("div", { style: { position: "absolute", inset: 0, zIndex: 80, background: "radial-gradient(120% 90% at 80% 0%, #2a8a72 0%, var(--brand) 45%, var(--brand-deep) 100%)", color: "#fff", display: "flex", flexDirection: "column", padding: 24 } },
      e("div", { style: { position: "absolute", inset: 0, opacity: .1, background: "repeating-linear-gradient(115deg,#fff 0 1px,transparent 1px 26px)" } }),
      e("div", { style: { position: "relative", flex: 1, display: "flex", flexDirection: "column" } }, children));

    if (step === 0) return wrap(e(React.Fragment, null,
      e("img", { src: "app/logo-white.png", style: { height: 34, alignSelf: "flex-start", marginTop: 8 } }),
      e("div", { style: { flex: 1, display: "flex", flexDirection: "column", justifyContent: "center" } },
        e("h1", { style: { fontSize: 28, fontWeight: 800, letterSpacing: "-.03em" } }, tt("ob_lang_title")),
        e("p", { style: { opacity: .8, marginTop: 8, fontSize: 14.5 } }, tt("ob_lang_sub")),
        e("div", { style: { display: "flex", flexDirection: "column", gap: 10, marginTop: 26 } },
          [["es", "Español"], ["en", "English"]].map(([l, name]) => e("button", { key: l, onClick: () => setLang(l), style: { padding: "16px 18px", borderRadius: 16, textAlign: "left", fontWeight: 700, fontSize: 16, background: lang === l ? "#fff" : "rgba(255,255,255,.12)", color: lang === l ? "var(--brand-deep)" : "#fff", display: "flex", alignItems: "center", justifyContent: "space-between" } }, name, lang === l && e(MU.Icon, { name: "check", size: 20 }))))),
      e("button", { className: "mu-btn", style: { background: "#fff", color: "var(--brand-deep)", width: "100%" }, onClick: () => { app.setLang(lang); setStep(1); } }, MU.t(lang, "continue"))));

    if (step === 1) return wrap(e(React.Fragment, null,
      e("button", { onClick: () => setStep(0), style: { color: "#fff", alignSelf: "flex-start", marginTop: 8 } }, e(MU.Icon, { name: "chevL", size: 24 })),
      e("div", { style: { flex: 1, display: "flex", flexDirection: "column", justifyContent: "center" } },
        e("h1", { style: { fontSize: 26, fontWeight: 800, letterSpacing: "-.03em" } }, tt("ob_confirm_title")),
        e("p", { style: { opacity: .8, marginTop: 8, fontSize: 14 } }, tt("ob_confirm_sub")),
        e("div", { style: { display: "flex", flexDirection: "column", gap: 10, marginTop: 24 } },
          MU.UNITS.map((u) => e("button", { key: u.id, onClick: () => setUnitId(u.id), style: { padding: 14, borderRadius: 16, textAlign: "left", background: unitId === u.id ? "#fff" : "rgba(255,255,255,.12)", color: unitId === u.id ? "var(--ink)" : "#fff", display: "flex", gap: 12, alignItems: "center" } },
            e("div", { style: { width: 44, height: 44, borderRadius: 12, background: unitId === u.id ? "var(--brand-soft)" : "rgba(255,255,255,.18)", display: "flex", alignItems: "center", justifyContent: "center", flex: "0 0 auto" } }, e(MU.Icon, { name: "building", size: 22, color: unitId === u.id ? "var(--brand)" : "#fff" })),
            e("div", { style: { flex: 1 } }, e("div", { style: { fontWeight: 700, fontSize: 15 } }, u.projectName + " · " + u.unitNumber), e("div", { style: { fontSize: 12.5, opacity: .7 } }, u.model)),
            unitId === u.id && e(MU.Icon, { name: "check", size: 20, color: "var(--brand)" }))))),
      e("button", { className: "mu-btn", style: { background: "#fff", color: "var(--brand-deep)", width: "100%" }, onClick: () => { app.setUnitId(unitId); setStep(2); } }, MU.t(lang, "continue"))));

    const ti = step - 2;
    return wrap(e(React.Fragment, null,
      e("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 8 } },
        e("div", { style: { display: "flex", gap: 6 } }, tours.map((_, i) => e("div", { key: i, style: { width: i === ti ? 22 : 7, height: 7, borderRadius: 9, background: i <= ti ? "#fff" : "rgba(255,255,255,.35)", transition: ".3s" } }))),
        e("button", { onClick: onDone, style: { color: "rgba(255,255,255,.8)", fontSize: 13, fontWeight: 700 } }, tt("ob_skip"))),
      e("div", { style: { flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "flex-start" } },
        e("div", { style: { width: 76, height: 76, borderRadius: 22, background: "rgba(255,255,255,.16)", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: 24 } }, e(MU.Icon, { name: tours[ti][2], size: 38, color: "#fff" })),
        e("h1", { style: { fontSize: 28, fontWeight: 800, letterSpacing: "-.03em", textWrap: "pretty" } }, tt(tours[ti][0])),
        e("p", { style: { opacity: .82, marginTop: 12, fontSize: 15.5, lineHeight: 1.5, textWrap: "pretty" } }, tt(tours[ti][1]))),
      e("button", { className: "mu-btn", style: { background: "#fff", color: "var(--brand-deep)", width: "100%" }, onClick: () => { ti < tours.length - 1 ? setStep(step + 1) : onDone(); } }, ti < tours.length - 1 ? MU.t(lang, "next") : tt("ob_start"))));
  }

  /* ---------- App UI (chrome + screen) ---------- */
  function AppUI({ app, rail }) {
    const [sheet, setSheet] = useState(null); // units | notif | demo
    const Screen = SCREENS[app.tab]();
    // Top bar + screen share one centered column so they stay aligned. On desktop the
    // column is capped (cards don't stretch across a wide window); on mobile it's full-bleed.
    const column = e("div", { style: { width: "100%", maxWidth: rail ? 920 : "none", height: "100%", margin: "0 auto", display: "flex", flexDirection: "column", minWidth: 0, position: "relative", overflow: "hidden" } },
      e(TopBar, { app, onUnits: () => setSheet("units"), onNotif: () => setSheet("notif"), onDemo: () => setSheet("demo") }),
      e("div", { style: { flex: 1, position: "relative", overflow: "hidden" } }, e(Screen, { key: app.tab })),
      // Hide the bottom nav during the claim wizard so it can't cover the wizard's own
      // action bar (the wizard has its own ✕/back to exit).
      !rail && !app.reportSession && e(BottomNav, { app })
    );
    const main = e("div", { style: { flex: 1, height: "100%", display: "flex", justifyContent: "center", minWidth: 0, position: "relative", overflow: "hidden" } },
      column,
      e(UnitSheet, { open: sheet === "units", onClose: () => setSheet(null), app }),
      e(NotifSheet, { open: sheet === "notif", onClose: () => setSheet(null), app }),
      e(DemoPanel, { open: sheet === "demo", onClose: () => setSheet(null), app })
    );
    const shell = rail ? e("div", { style: { display: "flex", height: "100%" } }, e(Rail, { app }), main) : main;
    // Onboarding overlays the whole app (over the rail too on desktop), not just the content column.
    return e(React.Fragment, null, shell, app.showOnboarding && e(Onboarding, { app, onDone: app.finishOnboarding }));
  }

  /* ---------- Root ---------- */
  function App() {
    const S = MU.store;
    const baseNow = useRef(new Date(2026, 5, 8, 12, 0, 0)); // fixed demo "today": 8 Jun 2026
    const [lang, setLangState] = useState(() => localStorage.getItem("mu_lang") || "es");
    const [unitId, setUnitId] = useState(() => S.get("unitId", "25b"));
    const [tab, setTab] = useState("home");
    const [offset, setOffset] = useState(0);
    const [claims, setClaims] = useState(() => S.get("claims", MU.CLAIMS || []));
    const [notifs, setNotifs] = useState(() => S.get("notifs", MU.NOTIFICATIONS || []));
    const [care, setCare] = useState(() => {
      const base = {}; (MU.CARE_ITEMS || []).forEach((c) => (base[c.id] = c.done));
      return Object.assign(base, S.get("care", {})); // defaults + persisted overrides
    });
    const [pending, setPending] = useState(null);
    const [reportSession, setReportSession] = useState(null);
    const [showOnboarding, setShowOnboarding] = useState(() => !localStorage.getItem("mu_onboarded"));
    const [vw, setVw] = useState(window.innerWidth);
    const [handoverVideos, setHandoverVideos] = useState({});

    // Mirror persistable state into localStorage on change (no backend).
    useEffect(() => { S.setClaims(claims); }, [claims]);
    useEffect(() => { S.set("notifs", notifs); }, [notifs]);
    useEffect(() => { S.set("care", care); }, [care]);
    useEffect(() => { S.set("unitId", unitId); }, [unitId]);

    useEffect(() => { const onR = () => setVw(window.innerWidth); window.addEventListener("resize", onR); return () => window.removeEventListener("resize", onR); }, []);
    useEffect(() => { const s = document.getElementById("splash"); if (s) { s.style.opacity = 0; setTimeout(() => s.remove(), 450); } document.documentElement.lang = lang; }, [lang]);

    const now = useMemo(() => new Date(baseNow.current.getTime() + offset * DAY), [offset]);
    const unit = MU.UNITS.find((u) => u.id === unitId) || MU.UNITS[0];

    const setLang = (l) => { setLangState(l); localStorage.setItem("mu_lang", l); };
    const app = {
      lang, setLang, unit, setUnitId: (id) => { setUnitId(id); setTab("home"); setReportSession(null); },
      now, baseNow: baseNow.current, offset, setOffset,
      tab, setTab: (t) => { setReportSession(null); setTab(t); },
      claims, getUnitClaims: () => claims.filter((c) => c.unitId === unitId),
      addClaim: (c) => setClaims((prev) => [c, ...prev]),
      updateClaim: (id, fn) => setClaims((prev) => prev.map((c) => (c.id === id ? fn(c) : c))),
      notifications: notifs, unreadCount: notifs.filter((n) => !n.read).length,
      markRead: (id) => setNotifs((p) => p.map((n) => n.id === id ? Object.assign({}, n, { read: true }) : n)),
      markAllRead: () => setNotifs((p) => p.map((n) => Object.assign({}, n, { read: true }))),
      care, toggleCare: (id) => setCare((p) => Object.assign({}, p, { [id]: !p[id] })),
      handoverVideo: handoverVideos[unitId] || null,
      setHandoverVideo: (item) => setHandoverVideos((p) => Object.assign({}, p, { [unitId]: item })),
      pending, clearPending: () => setPending(null),
      navigate: (link) => { if (!link) return; if (link.tab) setTab(link.tab); if (link.cat || link.gaas || link.care || link.crack || link.claim) setPending(link); if (link.crack) { setTab("report"); openReport({ issueId: "crack-hairline", crack: true }); } },
      reportSession,
      openReport: (prefill) => { setReportSession({ prefill, key: Date.now() }); setTab("report"); },
      closeReport: () => setReportSession(null),
      showOnboarding, finishOnboarding: () => { setShowOnboarding(false); localStorage.setItem("mu_onboarded", "1"); },
      replayOnboarding: () => setShowOnboarding(true),
      resetData: () => { S.reset(); window.location.reload(); }, // wipe persisted demo data, keep lang/onboarding
    };
    function openReport(p) { app.openReport(p); }

    // Auto-detect form factor: phones/small windows get the bottom-nav layout,
    // wider viewports get the desktop left-rail layout. No manual toggle, no phone frame.
    const rail = vw >= 768;
    // Fluid sizing: the whole UI scales smoothly with the viewport so it never feels
    // cramped on a small phone or undersized on a large monitor. We size the inner box
    // to 1/scale and scale it back up, so it always fills the viewport exactly (no overflow).
    //   phones  : track a ~390px design, 0.86×–1.18×
    //   desktop : native up to 1240px, then up to 1.3× on big monitors
    const clamp = (lo, v, hi) => Math.max(lo, Math.min(hi, v));
    const scale = Math.round((rail ? clamp(1, vw / 1240, 1.3) : clamp(0.86, vw / 390, 1.18)) * 1e4) / 1e4;

    return e(MU.Ctx.Provider, { value: app },
      e("div", { style: { height: "100%", width: "100%", background: "var(--paper)", position: "relative", overflow: "hidden" } },
        e("div", { style: { width: "calc(100% / " + scale + ")", height: "calc(100% / " + scale + ")", transform: "scale(" + scale + ")", transformOrigin: "top left", position: "relative", overflow: "hidden" } },
          e(AppUI, { app, rail }))));
  }

  ReactDOM.createRoot(document.getElementById("root")).render(e(App));
})(window.MU);
