// app.jsx — Get Call Home webapp shell (live-API)
const { useState: useS, useEffect: useE, useCallback: useCb, useRef: useR } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "lang": "en",
  "topbar": "chip",
  "demoBalance": "full",
  "demoCallState": "in-progress",
  "demoPillState": "queued",
  "typePair": "ios",
  "demoMode": false,
  "apiBase": "http://localhost:3000"
} /*EDITMODE-END*/;

const TYPE_PAIRS = {
  ios: { display: '-apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", "Manrope", system-ui, sans-serif', ui: '-apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Manrope", system-ui, sans-serif' },
  inter: { display: '"Inter", -apple-system, system-ui, sans-serif', ui: '"Inter", -apple-system, system-ui, sans-serif' },
  newsreader_manrope: { display: '"Newsreader", "Cormorant Garamond", Georgia, serif', ui: '"Manrope", ui-sans-serif, system-ui, sans-serif' },
  fraunces_inter: { display: '"Fraunces", "Playfair Display", Georgia, serif', ui: '"Inter", ui-sans-serif, system-ui, sans-serif' },
  cormorant_dmsans: { display: '"Cormorant Garamond", Georgia, serif', ui: '"DM Sans", ui-sans-serif, system-ui, sans-serif' },
  ibm_ibm: { display: '"IBM Plex Serif", Georgia, serif', ui: '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif' }
};

// ── Demo seed data (used when demoMode = true) ───────────────────────
const DEMO_CONTACTS = [
{ id: "d1", name: "Mom", phone: "+989123456789", created_at: "2025-01-01" },
{ id: "d2", name: "Baba", phone: "+989132224419", created_at: "2025-01-02" },
{ id: "d3", name: "Sara Khaleh", phone: "+989358871102", created_at: "2025-01-03" },
{ id: "d4", name: "Reza Dadash", phone: "+989215046671", created_at: "2025-01-04" },
{ id: "d5", name: "Mamani", phone: "+982188392210", created_at: "2025-01-05" }];

const DEMO_RECENTS = [
{ id: "r1", target_name: "Mom", target_phone: "+989123456789", status: "completed", duration_seconds: 452, created_at: dateAgoIso(0, 2.5), completed_at: dateAgoIso(0, 2) },
{ id: "r2", target_name: "Mamani", target_phone: "+982188392210", status: "completed", duration_seconds: 768, created_at: dateAgoIso(0, 5.5), completed_at: dateAgoIso(0, 5) },
{ id: "r3", target_name: "Baba", target_phone: "+989132224419", status: "queued", duration_seconds: null, created_at: dateAgoIso(0, 0.05) },
{ id: "r4", target_name: "Sara", target_phone: "+989358871102", status: "completed", duration_seconds: 241, created_at: dateAgoIso(1, 0), completed_at: dateAgoIso(1, 0) },
{ id: "r5", target_name: null, target_phone: "+989185523300", status: "cancelled", duration_seconds: null, created_at: dateAgoIso(3, 0) },
{ id: "r6", target_name: "Reza", target_phone: "+989215046671", status: "completed", duration_seconds: 1269, created_at: dateAgoIso(3, 0), completed_at: dateAgoIso(3, 0) }];

function dateAgoIso(daysAgo, hoursAgo) {
  const d = new Date();
  d.setDate(d.getDate() - daysAgo);
  d.setHours(d.getHours() - hoursAgo);
  return d.toISOString();
}

const DEMO_PLANS = [
{ id: "starter",  name: "Quick Call",  minutes: 5,  price: 3.99, expiry_days: 3,  currency: "usd" },
{ id: "standard", name: "Family Call", minutes: 10, price: 6.99, expiry_days: 7,  currency: "usd" },
{ id: "premium",  name: "Best Value",  minutes: 30, price: 9.99, expiry_days: 14, currency: "usd" }];


const PACK_CFG_DEFAULT = { minutes: 5, price: 3.99, expiryDays: 3 };

// ── helpers ─────────────────────────────────────────────────────────
function fmtPhoneDisplay(p, fa) {
  // +989128858465 → +98 912 885 8465
  // 09128858465   → 0912 885 8465
  if (!p) return "";
  const s = p.replace(/[^\d+]/g, "");
  let out = s;
  if (s.startsWith("+98") && s.length === 13) {
    out = `+98 ${s.slice(3,6)} ${s.slice(6,9)} ${s.slice(9)}`;
  } else if (s.startsWith("0") && s.length === 11) {
    out = `0${s.slice(1,4)} ${s.slice(4,7)} ${s.slice(7)}`;
  }
  return fa ? toFa(out) : out;
}
function relTime(iso, fa) {
  if (!iso) return "";
  const d = new Date(iso);
  const now = new Date();
  const sameDay = d.toDateString() === now.toDateString();
  const yest = new Date(now);yest.setDate(now.getDate() - 1);
  const yesterday = d.toDateString() === yest.toDateString();
  const hh = d.getHours(),mm = d.getMinutes();
  const hmm = `${hh % 12 || 12}:${String(mm).padStart(2, "0")} ${hh >= 12 ? "PM" : "AM"}`;
  if (sameDay) return fa ? toFa(`${String(hh).padStart(2, "0")}:${String(mm).padStart(2, "0")}`) : hmm;
  if (yesterday) return fa ? "دیروز" : "Yesterday";
  const days = Math.round((now - d) / 86400000);
  if (days < 7) return fa ? `${toFa(days)} روز پیش` : `${days}d ago`;
  return fa ? toFa(d.toLocaleDateString("fa-IR")) : d.toLocaleDateString();
}
function whenBucket(iso, fa) {
  if (!iso) return fa ? "اخیر" : "Recent";
  const d = new Date(iso);const now = new Date();
  if (d.toDateString() === now.toDateString()) return fa ? "امروز" : "Today";
  const yest = new Date(now);yest.setDate(now.getDate() - 1);
  if (d.toDateString() === yest.toDateString()) return fa ? "دیروز" : "Yesterday";
  const days = (now - d) / 86400000;
  if (days < 7) return fa ? "اوایل این هفته" : "Earlier this week";
  return fa ? "قبل‌تر" : "Earlier";
}
function durStr(sec, fa) {
  if (sec == null || sec === 0) return "";
  const m = Math.floor(sec / 60),s = Math.floor(sec % 60);
  const out = `${m}:${String(s).padStart(2, "0")}`;
  return fa ? toFa(out) : out;
}
function initialOf(name) {
  if (!name) return "?";
  return name.trim()[0].toUpperCase();
}
const TINTS = ["rose", "saffron", "green", "turq"];
function tintFor(id) {
  let h = 0;for (const c of String(id || "")) h = h * 31 + c.charCodeAt(0) | 0;
  return TINTS[Math.abs(h) % TINTS.length];
}

// ── StatusBar ───────────────────────────────────────────────────────
function StatusBar({ fa }) {
  return (
    <div className="statusbar" dir="ltr">
      <span>{fa ? "۹:۴۱" : "9:41"}</span>
      <div className="right">
        <Ico name="signal" size={14} />
        <Ico name="wifi" size={14} />
        <Ico name="battery" size={18} />
      </div>
    </div>);

}

// ── App ─────────────────────────────────────────────────────────────
function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  // In design mode (GetCallHome-design.html), force demo mode permanently
  // — no backend calls, no errors, no auth state to worry about.
  const designMode = !!window.__C2I_DESIGN_MODE;
  if (designMode && !t.demoMode) {setTweak("demoMode", true);}
  const fa = t.lang === "fa";
  const S = STRINGS[t.lang];
  const liveMode = !t.demoMode && !designMode;

  // Update API base
  useE(() => {window.C2I_API_BASE = t.apiBase;}, [t.apiBase]);

  // Typography injection
  React.useLayoutEffect(() => {
    const pair = TYPE_PAIRS[t.typePair];
    document.documentElement.style.setProperty("--font-display", pair.display);
    document.documentElement.style.setProperty("--font-ui", pair.ui);
  }, [t.typePair]);

  // Routes: landing → signup/signin → home
  const [route, setRoute] = useS(() => {
    if (t.demoMode) return { kind: "landing" };
    return C2I.isAuthed() ? { kind: "home" } : { kind: "landing" };
  });
  const [tab, setTab] = useS("keypad");

  // Handle Paddle redirect back: /payment-success
  // Paddle doesn't append the transaction id to the redirect, so fall
  // back to the id stashed in localStorage when checkout started.
  useE(() => {
    if (t.demoMode || !C2I.isAuthed()) return;
    const url = new URL(window.location.href);
    const txnId = url.searchParams.get("session_id") || localStorage.getItem("c2i_pending_txn");
    if (url.pathname === "/payment-success" && txnId) {
      localStorage.removeItem("c2i_pending_txn");
      C2I.paySuccess(txnId)
        .then(() => { window.history.replaceState({}, "", "/"); setRoute({ kind: "home" }); })
        .catch(() => { window.history.replaceState({}, "", "/"); setRoute({ kind: "home" }); });
    }
    if (url.pathname === "/payment-cancel") {
      window.history.replaceState({}, "", "/");
      setRoute({ kind: "home" });
    }
  }, []);

  // Live data
  const [contacts, setContacts] = useS([]);
  const [recents, setRecents] = useS([]);
  const [balance, setBalance] = useS({ minutes_remaining: 0, days_until_expiry: 0, has_minutes: false });
  const [plans, setPlans] = useS(DEMO_PLANS);
  const [serverErr, setServerErr] = useS(null);

  // Active call (drives the call-screen overlay)
  // shape: { call_id, contact, status: 'queued'|'in-progress'|'completed'|'cancelled', durationSeconds }
  const [activeCall, setActiveCall] = useS(null);

  // ── Demo pill (for previewing notification states without making a call)
  function makeDemoPill(state, fa) {
    if (state === "none") return null;
    const demoContact = { id: "demo-mom", name: fa ? "مامان" : "Mom", numDisplay: fa ? toFa("+98 912 345 6789") : "+98 912 345 6789", phone: "+989123456789", initial: fa ? "م" : "M", tint: "rose" };
    if (state === "queued") return { id: "demo-q", kind: "queued", contact: demoContact, retry: "once" };
    if (state === "completed") return { id: "demo-c", kind: "completed", contact: demoContact, durationLabel: fa ? toFa("7:32") : "7:32" };
    if (state === "missed") return { id: "demo-m", kind: "missed", contact: demoContact };
    return null;
  }

  // overlays
  const [editingContact, setEditingContact] = useS(null);
  const [showBuy, setShowBuy] = useS(false);
  const [statusPill, setStatusPill] = useS(null); // active notification pill

  // ── Live mode bootstrap ─────────────────────────────────────────
  const reload = useCb(async () => {
    if (t.demoMode) return;
    if (!C2I.isAuthed()) return;
    try {
      const [cts, hist, bal] = await Promise.all([
      C2I.listContacts(), C2I.callHistory(50), C2I.getBalance()]
      );
      setContacts(cts);
      setRecents(hist);
      setBalance(bal);
      setServerErr(null);
    } catch (e) {
      if (e.status === 401) {C2I.logout();setRoute({ kind: "landing" });} else
      setServerErr(e.offline ? S.network_err : e.message);
    }
  }, [t.demoMode]);

  // Clear stale error when entering demo mode
  useE(() => {
    if (t.demoMode) setServerErr(null);
  }, [t.demoMode]);

  // Plans don't require auth — fetch once when leaving demo mode
  useE(() => {
    if (t.demoMode) {setPlans(DEMO_PLANS);return;}
    C2I.listPlans().
    then((r) => {if (r && r.plans) setPlans(r.plans);}).
    catch(() => {/* keep demo plans as fallback */});
  }, [t.demoMode]);

  useE(() => {
    if (t.demoMode) return;
    reload();
    // light polling: refresh balance + recents every 10s while authed
    const id = setInterval(() => {if (C2I.isAuthed()) reload();}, 10000);
    return () => clearInterval(id);
  }, [reload, t.demoMode]);

  // Poll the one call the pill is tied to (by call_id). "failed" is final too.
  const pillCallId = statusPill?.callId;
  const pillKind = statusPill?.kind;
  useE(() => {
    if (t.demoMode || !pillCallId) return;
    if (pillKind !== "queued" && pillKind !== "in-progress") return;
    const id = setInterval(async () => {
      try {
        const s = await C2I.callStatus(pillCallId);
        setStatusPill((p) => {
          if (!p || p.callId !== pillCallId) return p;
          const expireMinutes = s.config?.queue_expire_minutes ?? p.expireMinutes;
          if (s.status === "failed") return { ...p, kind: "failed", reason: s.fail_reason, retrying: false, cancellable: false };
          if (s.status === "completed") return { ...p, kind: "completed", durationLabel: durStr(s.duration_seconds, fa) };
          if (s.status === "cancelled") return null;
          if (s.status === "in-progress") return { ...p, kind: "in-progress", retrying: false, cancellable: false, expireMinutes };
          return { ...p, kind: "queued", retrying: !!s.retrying, expireMinutes };
        });
        if (["failed", "completed", "cancelled"].includes(s.status)) reload();
      } catch {}
    }, 3000);
    return () => clearInterval(id);
  }, [pillCallId, pillKind, t.demoMode, reload, fa]);

  // While "in-progress", count up locally so UI feels live
  const liveTimerRef = useR(null);
  useE(() => {
    clearInterval(liveTimerRef.current);
    if (activeCall?.status === "in-progress") {
      liveTimerRef.current = setInterval(() => {
        setActiveCall((ac) => ac ? { ...ac, durationSeconds: (ac.durationSeconds || 0) + 1 } : ac);
      }, 1000);
    }
    return () => clearInterval(liveTimerRef.current);
  }, [activeCall?.status]);

  // ── Computed UI state ──────────────────────────────────────────
  // Low threshold:
  //  • 20% or less of last purchased pack, OR
  //  • 2 days or fewer until expiry.
  // Either triggers red.
  const lastPackMinutes = (() => {
    if (!liveMode) return 10; // demo
    const v = parseInt(localStorage.getItem("c2i_last_pack_minutes") || "10", 10);
    return Number.isFinite(v) && v > 0 ? v : 10;
  })();

  const liveSeconds = t.demoMode ?
  t.demoBalance === "empty" ? 0 : t.demoBalance === "low" ? 80 : 510 :
  Math.floor(balance.minutes_remaining * 60);
  const liveDays = t.demoMode ?
  t.demoBalance === "empty" ? 0 : t.demoBalance === "low" ? 1 : 5 :
  balance.days_until_expiry;

  const liveBalanceState = (() => {
    if (t.demoMode) return t.demoBalance;
    if (!balance.has_minutes) return "empty";
    const timeLow = liveSeconds <= 120;
    const daysLow = liveDays <= 2;
    if (timeLow || daysLow) return "low";
    return "full";
  })();

  const liveBannerMsg = (() => {
    if (liveBalanceState === "empty") return S.empty_banner;
    if (liveBalanceState !== "low") return null;
    const timeLow = liveSeconds <= 120;
    const daysLow = liveDays <= 2;
    const mm = Math.floor(liveSeconds / 60);
    const ss = String(liveSeconds % 60).padStart(2, "0");
    const timeStr = fa ? toFa(`${mm}:${ss}`) : `${mm}:${ss}`;
    if (timeLow && daysLow && liveDays === 0) return S.expiry_today_banner;
    if (timeLow) return S.low_time_banner(timeStr);
    if (liveDays === 0) return S.expiry_today_banner;
    if (liveDays === 1) return S.expiry_1day_banner;
    return S.expiry_2days_banner;
  })();

  // Contact list to render (with localization)
  const contactsRender = (t.demoMode ? DEMO_CONTACTS : contacts).map((c) => ({
    id: c.id,
    name: fa ? faName(c.name) : c.name || c.phone,
    phone: c.phone,
    numDisplay: fmtPhoneDisplay(c.phone, fa),
    initial: initialOf(c.name || c.phone),
    tint: tintFor(c.id),
    lastCalled: null
  }));

  // Recents to render — group by bucket
  const sourceRecents = t.demoMode ? DEMO_RECENTS : recents;
  const recentsRender = sourceRecents.map((r) => {
    const name = r.target_name ? fa ? faName(r.target_name) : r.target_name : null;
    return {
      id: r.id,
      name,
      numDisplay: fmtPhoneDisplay(r.target_phone, fa),
      initial: name ? initialOf(name) : "?",
      tint: tintFor(r.id),
      dir: "out",
      status: r.status,
      failReason: r.fail_reason,
      time: relTime(r.created_at, fa),
      duration: durStr(r.duration_seconds, fa),
      when: whenBucket(r.created_at, fa),
      unknown: !r.target_name
    };
  });

  // ── Actions ────────────────────────────────────────────────────
  // Honest flow: tap a contact → call goes out → status pill shows
  // "your phone will ring in a minute". User keeps using the app.
  // We know the call completed when Android polls back.

  const errText = (e) => {
    if (e.offline || e.code === "offline") return S.err_offline;
    if (e.status === 409 || e.code === "active_call") return S.err_active_call;
    if (e.status === 402 || e.code === "no_minutes") return S.err_no_minutes;
    return S.err_generic;
  };

  const callNow = (contact) => {
    if (liveBalanceState === "empty") { setShowBuy(true); return; }

    // Show the pill in queued state; callId is attached once the server answers
    const pillId = "queued-" + Date.now();
    setStatusPill({ id: pillId, kind: "queued", contact, retry: "once", callId: null });

    if (liveMode) {
      C2I.requestCall(contact.phone, contact.name && !fa ? contact.name : null)
        .then((r) => {
          setStatusPill((p) => p && p.id === pillId ? { ...p, callId: r.call_id } : p);
          reload();
        })
        .catch((e) => {
          if (e.status === 402) { setShowBuy(true); setStatusPill(null); }
          else if (e.status === 409 && e.payload?.active_call?.call_id) {
            // Show (and poll) the call that is already active; never cancel it silently.
            const ac = e.payload.active_call;
            setStatusPill({
              id: pillId, kind: ac.status === "in-progress" ? "in-progress" : "queued",
              contact, callId: ac.call_id, cancellable: ac.status === "queued"
            });
          }
          else { setStatusPill(null); alert(errText(e)); }
        });
    }
  };

  const cancelPillCall = () => {
    const id = statusPill?.callId;
    if (!id) { setStatusPill(null); return; }
    C2I.cancelCall(id).catch(() => {}).then(() => { setStatusPill(null); reload(); });
  };

  const placeCall = callNow; // entry point used by Contacts/Recents

  const placeCallFromNumber = (e164) => {
    if (!e164) return;
    // e164 already validated by the keypad — the home country-format check happened there
    const display = fmtPhoneDisplay(e164, fa);
    // Keypad is direct dial (no contact card): straight to callNow
    callNow({ name: display, phone: e164, numDisplay: display, initial: "#", tint: "saffron" });
  };

  const endActiveCall = () => {
    setActiveCall(null);
    if (!t.demoMode) reload();
  };

  const onSaveContact = (saved) => {
    setEditingContact(null);
    if (!t.demoMode) reload();
  };
  const onDeleteContact = () => {
    setEditingContact(null);
    if (!t.demoMode) reload();
  };

  // ── Render: marketing screens ──────────────────────────────────
  if (route.kind === "landing") {
    return (
      <div className="device" dir={fa ? "rtl" : "ltr"}>
        <Landing t={S} fa={fa}
        setLang={(l) => setTweak("lang", l)}
        onSignup={() => setRoute({ kind: "signup" })}
        onSignin={() => setRoute({ kind: "signin" })} />
      </div>);

  }
  if (route.kind === "signup") {
    return (
      <div className="device" dir={fa ? "rtl" : "ltr"}>
        <Signup t={S} fa={fa}
        onDone={() => {setRoute({ kind: "home" });reload();}}
        onBack={() => setRoute({ kind: "landing" })}
        onSwitchToSignin={() => setRoute({ kind: "signin" })} />
      </div>);

  }
  if (route.kind === "signin") {
    return (
      <div className="device" dir={fa ? "rtl" : "ltr"}>
        <Signin t={S} fa={fa}
        onDone={() => {setRoute({ kind: "home" });reload();}}
        onBack={() => setRoute({ kind: "landing" })}
        onSwitchToSignup={() => setRoute({ kind: "signup" })} />
      </div>);

  }

  // ── Home ───────────────────────────────────────────────────────
  return (
    <div className="device" dir={fa ? "rtl" : "ltr"}>
      <div className="screen">
        <div className="topbar">
          <div className="brand"><span className="glyph">{fa ? "ت" : "C"}</span>{fa ? "تماس" : "Get Call Home"}</div>
          <TopBar variant={t.topbar} state={liveBalanceState} seconds={liveSeconds} days={liveDays}
          onBuy={() => setShowBuy(true)} t={S} fa={fa} />
        </div>

        {serverErr &&
        <div style={{ margin: "10px 18px 0" }}>
            <ErrBox msg={serverErr} />
          </div>
        }

        <StatusPill
          pill={statusPill || (t.demoMode ? makeDemoPill(t.demoPillState, fa) : null)}
          t={S} fa={fa}
          onCancel={cancelPillCall}
          onDismiss={() => {setStatusPill(null);if (t.demoMode) setTweak("demoPillState", "none");}}
          onRetry={() => {
            const c = statusPill?.contact || makeDemoPill(t.demoPillState, fa)?.contact;
            if (c) callNow(c);
          }} />
        

        <div className="scrollarea" style={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
          {tab === "keypad" &&
          <Keypad t={S} fa={fa}
          balanceState={liveBalanceState}
          bannerMsg={liveBannerMsg}
          onTopUp={() => setShowBuy(true)}
          onCall={placeCallFromNumber}
          onSchedule={(e164) => {
            if (!e164) return;
            const display = fmtPhoneDisplay(e164, fa);
            setScheduleSeed({
              id: "kp-" + Date.now(),
              name: display,
              phone: e164,
              numDisplay: display,
              initial: "#",
              tint: "saffron"
            });
            setShowSchedule(true);
          }}
          onAddContact={(num) => setEditingContact({ phone: fromFa(num).replace(/[^\d+]/g, ""), numDisplay: fa ? toFa(num) : num })} />

          }
          {tab === "contacts" &&
          <Contacts t={S} fa={fa}
          contacts={contactsRender}
          balanceState={liveBalanceState}
          bannerMsg={liveBannerMsg}
          onCall={(c) => placeCall(c)}
          onEdit={(c) => setEditingContact(contactsRender.find((x) => x.id === c.id) || c)}
          onAdd={() => setEditingContact({})}
          onTopUp={() => setShowBuy(true)} />

          }
          {tab === "recents" &&
          <Recents t={S} fa={fa}
          recents={recentsRender}
          balanceState={liveBalanceState}
          bannerMsg={liveBannerMsg}
          onCall={(r) => placeCall({ name: r.name || r.numDisplay, phone: r.numDisplay.replace(/[^\d+]/g, ""), numDisplay: r.numDisplay, initial: r.initial })}
          onTopUp={() => setShowBuy(true)} />

          }
        </div>

        <div className="tabbar">
          <button className={`tab ${tab === "keypad" ? "active" : ""}`} onClick={() => setTab("keypad")}>
            <Ico name="keypad" size={22} />{S.tab_keypad}
          </button>
          <button className={`tab ${tab === "contacts" ? "active" : ""}`} onClick={() => setTab("contacts")}>
            <Ico name="contacts" size={22} />{S.tab_contacts}
          </button>
          <button className={`tab ${tab === "recents" ? "active" : ""}`} onClick={() => setTab("recents")}>
            <Ico name="recents" size={22} />{S.tab_recents}
          </button>
        </div>
      </div>

      {editingContact &&
      <Overlay>
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', paddingTop: 44 }}>
            <ContactForm t={S} fa={fa} draft={editingContact}
          liveMode={liveMode}
          onSave={onSaveContact}
          onDelete={onDeleteContact}
          onCancel={() => setEditingContact(null)} />
          </div>
        </Overlay>
      }

      {showBuy &&
      <Overlay>
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', paddingTop: 44 }}>
            <BuyTime t={S} fa={fa} balanceState={liveBalanceState}
          plans={plans}
          liveMode={liveMode}
          liveSeconds={liveSeconds}
          liveDays={liveDays}
          hasEverPurchased={balance.has_ever_purchased || false}
          onClose={() => setShowBuy(false)}
          onPaid={(picked) => {
            setShowBuy(false);
            if (picked?.minutes) { try { localStorage.setItem("c2i_last_pack_minutes", String(picked.minutes)); } catch {} }
            if (t.demoMode) setTweak("demoBalance", "full"); else reload();
          }} />
          </div>
        </Overlay>
      }

      {activeCall &&
      <CallScreen
        t={S} fa={fa}
        contact={activeCall.contact}
        callId={activeCall.call_id}
        status={t.demoMode ? t.demoCallState : activeCall.status}
        durationSeconds={activeCall.durationSeconds || 0}
        liveMode={liveMode}
        onEnd={endActiveCall} />
      }

    </div>);

}

function Overlay({ children }) {
  return (
    <div style={{ position: 'absolute', inset: 0, background: 'var(--paper)', display: 'flex', flexDirection: 'column', zIndex: 50, animation: 'slideUp .25s ease' }}>
      {children}
    </div>);

}
function faName(n) {
  const map = { "Mom": "مامان", "Baba": "بابا", "Sara": "سارا", "Sara Khaleh": "سارا خاله", "Reza Dadash": "رضا داداش", "Reza": "رضا", "Mamani": "مامانی", "Unknown": "ناشناس" };
  return map[n] || n;
}

window.App = App;