// fa-shared.jsx — Icons, primitives, i18n, API helpers, routing
// Production-ready shared module for Freedom Agent frontend.

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

/* ───────── API helpers ───────── */
const CSRF = (typeof __CSRF__ !== 'undefined') ? __CSRF__ : '';

async function api(url, opts = {}) {
  const o = { credentials: 'same-origin', headers: { ...opts.headers }, ...opts };
  if (o.method && o.method !== 'GET') {
    o.headers['x-csrf-token'] = CSRF;
    if (o.body && typeof o.body === 'object' && !(o.body instanceof FormData)) {
      o.headers['content-type'] = 'application/json';
      o.body = JSON.stringify(o.body);
    }
  }
  const r = await fetch(url, o);
  if (!r.ok) {
    const text = await r.text().catch(() => '');
    let msg = text;
    try { msg = JSON.parse(text).error || text; } catch {}
    throw new Error(msg || `HTTP ${r.status}`);
  }
  const ct = r.headers.get('content-type') || '';
  if (ct.includes('json')) return r.json();
  return r.text();
}

function useApi(url, deps = []) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const refresh = useCallback(() => {
    setLoading(true);
    setError(null);
    api(url).then(setData).catch(e => setError(e.message)).finally(() => setLoading(false));
  }, [url, ...deps]);
  useEffect(() => { refresh(); }, [refresh]);
  return { data, loading, error, refresh, setData };
}

/* ───────── Polling ───────── */
function usePoll(fn, interval = 3000, enabled = true) {
  const savedFn = useRef(fn);
  savedFn.current = fn;
  useEffect(() => {
    if (!enabled) return;
    let alive = true;
    const tick = async () => {
      if (!alive) return;
      try { await savedFn.current(); } catch {}
      if (alive) timer = setTimeout(tick, interval);
    };
    let timer = setTimeout(tick, interval);
    return () => { alive = false; clearTimeout(timer); };
  }, [interval, enabled]);
}

/* ───────── Toast ───────── */
const ToastCtx = createContext(() => {});
function useToast() { return useContext(ToastCtx); }
function ToastProvider({ children }) {
  const [msg, setMsg] = useState(null);
  const show = useCallback((text, ms = 3000) => {
    setMsg(text);
    setTimeout(() => setMsg(null), ms);
  }, []);
  return React.createElement(ToastCtx.Provider, { value: show },
    children,
    msg && React.createElement('div', { className: 'fa-toast' }, msg)
  );
}

/* ───────── i18n ───────── */
const I18N = {
  en: {
    continue: "Continue", back: "Back", next: "Next", skip: "Skip",
    submit: "Submit", cancel: "Cancel", learn_more: "Learn more",
    sign_in: "Sign in", get_started: "Get the invite", or: "or",
    advanced: "Advanced options", troubleshoot: "Troubleshooting",
    copied: "Copied", copy: "Copy", save: "Save", saving: "Saving…",
    loading: "Loading…", error: "Error", retry: "Retry",

    // landing
    nav_features: "Features", nav_how: "How it works", nav_pricing: "Pricing", nav_proof: "Proof",
    eyebrow: "Your AI agent · hosted and ready",
    hero_title_a: "Your own", hero_title_b: "AI agent. Hosted.",
    hero_sub: "A branded AI assistant trained on your knowledge base, delivered as a Telegram bot you own. Your customers chat with it on the app they already use every day. No code required.",
    cta_join: "Start free", cta_demo: "See a live demo",
    hero_caption: "Trusted by consultants, coaches, and businesses automating their customer support on Telegram.",
    feat_title: "Everything you need to launch your Telegram agent.", feat_sub: "Upload your docs, configure personality, connect your bot. Your agent handles the rest.",
    feat_1_t: "Custom branding", feat_1_b: "Name, tone, personality: the agent talks like you. Your brand's voice applied everywhere.",
    feat_2_t: "Knowledge base", feat_2_b: "Upload PDFs, docs, or FAQs. Your agent learns from them and answers accurately — no hallucinations.",
    feat_3_t: "Lives on Telegram", feat_3_b: "Your agent lives in Telegram, always with you. Push notifications, mobile-first, no app to install.",
    feat_4_t: "Analytics dashboard", feat_4_b: "See how many conversations happen, what topics come up, and how your agent performs. All in one place.",
    proof_title: "What people are building.",
    proof_1_quote: "I uploaded my coaching materials and had a working assistant in 15 minutes. Clients love it.",
    proof_1_name: "Marta R.", proof_1_role: "Business coach, Bologna",
    proof_2_quote: "My support agent answers 80% of questions before they reach me. Best ROI I've ever seen.",
    proof_2_name: "Davide P.", proof_2_role: "SaaS founder",
    proof_3_quote: "Set it up for my restaurant — menu, hours, reservations. Customers message it on Telegram instead of calling.",
    proof_3_name: "Alex K.", proof_3_role: "Restaurant owner, Berlin",
    how_title: "Live in four steps.",
    how_1: "Sign up and pick a name for your agent.", how_2: "Upload your knowledge base — PDFs, docs, FAQs.",
    how_3: "Connect your Telegram bot in 5 minutes via BotFather.", how_4: "Share your bot handle. Done.",
    cmp_title: "Why not just use ChatGPT?", cmp_left: "Generic chatbots", cmp_right: "Freedom Agent",
    cmp_l1: "Generic, no brand", cmp_l2: "Hallucinate freely", cmp_l3: "No knowledge base", cmp_l4: "You pay per conversation",
    cmp_r1: "Your brand, your personality", cmp_r2: "Grounded in your documents", cmp_r3: "Trained on your knowledge", cmp_r4: "Simple monthly plans",
    price_title: "Simple pricing.", price_sub: "Start free. Upgrade when you grow.",
    price_free: "Free", price_free_p: "€0/mo", price_free_f1: "50 messages/day", price_free_f2: "1 document", price_free_f3: "Basic branding",
    price_starter: "Starter", price_starter_p: "€29/mo", price_starter_f1: "500 messages/day", price_starter_f2: "25 documents", price_starter_f3: "Full branding",
    price_pro: "Pro", price_pro_p: "€79/mo", price_pro_f1: "Unlimited messages", price_pro_f2: "Unlimited documents", price_pro_f3: "Priority support",
    final_t: "Your agent. Ready in minutes.",
    final_b: "Sign up free. Upload your docs. Connect your Telegram bot. It's that simple.",
    email_ph: "you@yourdomain.com", why_ph: "What will your agent do? (optional)",
    lead_send: "Get started free", lead_tos: "No credit card required. Free plan included.",
    lead_sent: "You're in — here's your access link.",
    footer_made: "Built with care, in Italy.",

    // onboarding
    invite_eyebrow: "You're invited", step: "Step", of: "of",
    s1_title: "Pick a username.", s1_sub: "This is how your agent is named on the network. Lowercase letters, numbers, underscore.",
    s1_label: "Username", s1_ph: "marta_r", s1_resume: "Already have one? Resume your setup",
    s1_rules: "3–30 chars · starts with a letter · a–z, 0–9, _",
    s2_title: "Create your Telegram bot.", s2_sub: "Your agent speaks through a bot you own. We'll walk you through BotFather.",
    s2_step_1: "Open @BotFather on Telegram", s2_step_1d: "Tap the link or search BotFather inside the app.",
    s2_step_2: "Send /newbot and follow the prompts", s2_step_2d: "Pick a name (e.g. \"My Agent\") and a unique username ending in _bot.",
    s2_step_3: "Copy the HTTP API token", s2_step_3d: "BotFather sends a long token. Keep it private — it's your bot's password.",
    s2_step_4: "Come back here and paste it in step 3", s2_step_4d: "We verify it talks to Telegram. Nothing is stored until then.",
    s2_what: "What is a Telegram bot?", s2_what_b: "A free chat account run by code instead of a person. You'll talk to your agent the same way you'd talk to any contact.",
    s2_verified: "Already verified? Skip to step 4",
    s3_title: "Paste your bot token.", s3_sub: "We'll ping Telegram to make sure it's alive. Takes a second.",
    s3_label: "Bot token", s3_verify: "Verify token", s3_ok: "Token verified. Bot:",
    s4_title: "Connect your AI provider.",
    s4_sub: "Sign in to OpenAI/Codex once. We open a secure device login — no password leaves your browser.",
    s4_start: "Start authentication", s4_code_label: "Your one-time code",
    s4_code_help: "Open the link, sign in, then enter this code. We'll detect it automatically.",
    s4_status_idle: "Ready", s4_status_running: "Waiting for sign-in…",
    s4_status_success: "Connected", s4_status_failed: "Auth failed",
    s4_manual: "Paste redirect URL manually", s4_manual_help: "Stuck? Copy the URL from your browser after sign-in and paste it here.",
    s5_title: "Setting things up.", s5_sub: "We're spinning up your workspace. This usually takes about a minute.",
    s5_phase_1: "Workspace created", s5_phase_2: "Configuration written", s5_phase_3: "Provider auth verified",
    s5_phase_4: "Services starting", s5_phase_5: "Finalizing",
    s5_reassure: "Still working — first-time setup can take up to two minutes. You can leave this tab open.",
    s6_title: "Almost there.", s6_sub: "Three small actions. Then your agent says hello.",
    s6_a1: "Start your service", s6_a1d: "We turn the engine on. Takes a few seconds.", s6_a1_btn: "Start service",
    s6_a2: "Pair on Telegram", s6_a2d: "Open your bot and send /start. We auto-approve the pairing.",
    s6_a2_open: "Open bot in Telegram", s6_a2_listening: "Listening for /start…",
    s6_a3: "Finish setup", s6_a3d: "All set. Head to your dashboard.", s6_a3_btn: "Go to dashboard",

    // dashboard
    dash_hi: "Good to see you,", dash_sub: "Your agent is here. What are we doing today?",
    dash_health: "Status", dash_service: "Service", dash_gateway: "Gateway", dash_telegram: "Telegram",
    dash_last: "Last active", dash_actions: "Quick actions", dash_quota: "Today's usage",
    dash_quota_help: "Resets at midnight Europe/Rome.", dash_messages: "Messages", dash_tokens: "Tokens",
    dash_cost: "Est. cost", dash_skills: "Active skills", dash_apps: "Your apps",
    dash_no_apps: "Nothing deployed yet.", dash_new_app: "New app", dash_open_mission: "Open mission",
    dash_restart: "Restart", dash_stop: "Stop", dash_start: "Start", dash_running: "Running", dash_open: "Open",

    // mission
    mis_title: "Give your agent a mission.",
    mis_sub: "Describe an outcome. Not a prompt. The agent will ask the right questions and report back.",
    mis_ph: "e.g. \"Find me three apartments in Lisbon under €1800, viewable next week, and book the viewings.\"",
    mis_files: "Drop reference files here", mis_files_help: "PDF, TXT, CSV, MD, JSON — up to 15 MB each, 6 max.",
    mis_count: "characters", mis_next: "Next",
    mis_clar_title: "A few quick questions.", mis_clar_sub: "These help your agent get it right the first time.",
    mis_launch: "Launch mission", mis_active_title: "Mission active.",
    mis_active_sub: "Your agent is on it. You'll get a Telegram message when there's an update.",
    mis_sent: "Sent", mis_status: "Status", mis_status_running: "Working", mis_back_dash: "Back to dashboard",

    // settings
    set_title: "Settings", set_sub: "How your agent shows up — and what to call it.",
    set_section_agent: "Your agent", set_displayname: "How it calls you", set_displayname_ph: "Marta",
    set_agentname: "Agent name", set_agentname_ph: "Olive", set_emoji: "Emoji",
    set_nature: "Nature", set_nature_ph: "Personal assistant",
    set_vibe: "Vibe", set_vibe_ph: "Concise, dry-witted, never apologizes for being late.",
    set_section_account: "Account", set_lang: "Interface language",
    set_save: "Save changes", set_saved: "Changes saved.",

    // agent config
    agent_title: "Your Agent", agent_sub: "Configure personality, branding and chat deployment.",
    agent_identity: "Identity", agent_personality: "Personality", agent_chat_branding: "Chat branding",
    agent_chat_status: "Chat deployment", agent_welcome: "Welcome message",
    agent_welcome_ph: "Hi! How can I help you?",
    agent_color: "Primary color", agent_avatar: "Avatar URL", agent_avatar_ph: "https://...",
    agent_personality_label: "System instructions",
    agent_personality_ph: "Describe how your agent should behave...",
    agent_deploy_chat: "Deploy chat", agent_chat_live: "Chat is live",
    agent_chat_pending: "Chat pending deployment", agent_open_chat: "Open chat",

    // knowledge
    kb_title: "Knowledge Base", kb_sub: "Upload documents your agent uses to answer questions.",
    kb_upload: "Upload files", kb_upload_help: "PDF, TXT, CSV, MD — max 6 files, 15 MB each.",
    kb_empty: "No documents yet.", kb_name: "Name", kb_size: "Size", kb_status: "Status",
    kb_date: "Uploaded", kb_reindex: "Re-index", kb_delete: "Delete",
    kb_indexed: "Indexed", kb_processing: "Processing", kb_error: "Error",

    // analytics
    an_title: "Conversations", an_sub: "How people are using your agent.",
    an_total: "Total conversations", an_today: "Today", an_week: "This week",
    an_avg: "Avg messages/conversation", an_topics: "Top topics",
    an_empty: "No conversation data yet.",

    // billing
    bill_title: "Subscription", bill_sub: "Manage your plan and billing.",
    bill_plan: "Current plan", bill_usage: "Usage this period",
    bill_upgrade: "Upgrade", bill_manage: "Manage subscription",
    bill_free: "Free", bill_starter: "Starter", bill_pro: "Pro",
    bill_msgs_day: "messages/day", bill_next: "Next billing date",
    bill_free_desc: "50 messages/day, basic branding",
    bill_starter_desc: "500 messages/day, custom branding, analytics",
    bill_pro_desc: "Unlimited messages, priority support, API access",
  },
  it: {
    continue: "Continua", back: "Indietro", next: "Avanti", skip: "Salta",
    submit: "Invia", cancel: "Annulla", learn_more: "Scopri di più",
    sign_in: "Accedi", get_started: "Richiedi l'invito", or: "oppure",
    advanced: "Opzioni avanzate", troubleshoot: "Risoluzione problemi",
    copied: "Copiato", copy: "Copia", save: "Salva", saving: "Salvataggio…",
    loading: "Caricamento…", error: "Errore", retry: "Riprova",

    nav_features: "Funzionalità", nav_how: "Come funziona", nav_pricing: "Prezzi", nav_proof: "Testimonianze",
    eyebrow: "Il tuo agente IA · ospitato e pronto",
    hero_title_a: "Il tuo", hero_title_b: "agente IA. Ospitato.",
    hero_sub: "Un assistente IA personalizzato, addestrato sulla tua knowledge base, consegnato come bot Telegram che è tuo. I tuoi clienti gli scrivono sull'app che già usano ogni giorno. Zero codice.",
    cta_join: "Inizia gratis", cta_demo: "Vedi una demo live",
    hero_caption: "Scelto da consulenti, coach e aziende che automatizzano il supporto clienti su Telegram.",
    feat_title: "Tutto quello che serve per lanciare il tuo agente Telegram.", feat_sub: "Carica i documenti, configura la personalità, collega il tuo bot. Il tuo agente fa il resto.",
    feat_1_t: "Branding personalizzato", feat_1_b: "Nome, tono, personalità: l'agente parla come te. La voce del tuo brand applicata ovunque.",
    feat_2_t: "Knowledge base", feat_2_b: "Carica PDF, documenti o FAQ. Il tuo agente impara da loro e risponde con precisione — niente allucinazioni.",
    feat_3_t: "Vive su Telegram", feat_3_b: "Il tuo agente vive in Telegram, sempre con te. Notifiche push, mobile-first, niente da installare.",
    feat_4_t: "Dashboard analytics", feat_4_b: "Vedi quante conversazioni avvengono, quali temi emergono, e come performa il tuo agente. Tutto in un posto.",
    proof_title: "Cosa stanno costruendo.",
    proof_1_quote: "Ho caricato i miei materiali di coaching e in 15 minuti avevo un assistente funzionante. I clienti lo adorano.",
    proof_1_name: "Marta R.", proof_1_role: "Business coach, Bologna",
    proof_2_quote: "Il mio agente di supporto risponde all'80% delle domande prima che arrivino a me. Miglior ROI di sempre.",
    proof_2_name: "Davide P.", proof_2_role: "Founder SaaS",
    proof_3_quote: "L'ho configurato per il mio ristorante — menu, orari, prenotazioni. I clienti gli scrivono su Telegram invece di chiamare.",
    proof_3_name: "Alex K.", proof_3_role: "Ristoratore, Berlino",
    how_title: "Online in quattro passi.",
    how_1: "Registrati e scegli un nome per il tuo agente.", how_2: "Carica la knowledge base — PDF, documenti, FAQ.",
    how_3: "Collega il tuo bot Telegram in 5 minuti via BotFather.", how_4: "Condividi l'handle del bot. Fatto.",
    cmp_title: "Perché non usare ChatGPT?", cmp_left: "Chatbot generici", cmp_right: "Freedom Agent",
    cmp_l1: "Generici, senza brand", cmp_l2: "Allucinano liberamente", cmp_l3: "Nessuna knowledge base", cmp_l4: "Paghi per conversazione",
    cmp_r1: "Il tuo brand, la tua personalità", cmp_r2: "Basato sui tuoi documenti", cmp_r3: "Addestrato sulla tua conoscenza", cmp_r4: "Piani mensili semplici",
    price_title: "Prezzi semplici.", price_sub: "Inizia gratis. Scala quando cresci.",
    price_free: "Free", price_free_p: "€0/mese", price_free_f1: "50 messaggi/giorno", price_free_f2: "1 documento", price_free_f3: "Branding base",
    price_starter: "Starter", price_starter_p: "€29/mese", price_starter_f1: "500 messaggi/giorno", price_starter_f2: "25 documenti", price_starter_f3: "Branding completo",
    price_pro: "Pro", price_pro_p: "€79/mese", price_pro_f1: "Messaggi illimitati", price_pro_f2: "Documenti illimitati", price_pro_f3: "Supporto prioritario",
    final_t: "Il tuo agente. Pronto in minuti.",
    final_b: "Registrati gratis. Carica i documenti. Collega il tuo bot Telegram. È così semplice.",
    email_ph: "tu@tuo-dominio.com", why_ph: "Cosa farà il tuo agente? (facoltativo)",
    lead_send: "Inizia gratis", lead_tos: "Nessuna carta di credito. Piano free incluso.",
    lead_sent: "Ci sei — ecco il tuo link di accesso.",
    footer_made: "Costruito con cura, in Italia.",

    invite_eyebrow: "Sei stato invitato", step: "Passo", of: "di",
    s1_title: "Scegli uno username.", s1_sub: "È così che il tuo agente è identificato sulla rete. Minuscolo, numeri, underscore.",
    s1_label: "Username", s1_ph: "marta_r", s1_resume: "Già registrato? Riprendi il setup",
    s1_rules: "3–30 caratteri · inizia con una lettera · a–z, 0–9, _",
    s2_title: "Crea il tuo bot Telegram.", s2_sub: "Il tuo agente parla attraverso un bot che è tuo. Ti accompagniamo da BotFather.",
    s2_step_1: "Apri @BotFather su Telegram", s2_step_1d: "Tocca il link o cerca BotFather nell'app.",
    s2_step_2: "Manda /newbot e segui le indicazioni", s2_step_2d: "Scegli un nome (es. \"Il Mio Agente\") e uno username unico che termina con _bot.",
    s2_step_3: "Copia il token HTTP API", s2_step_3d: "BotFather ti manda un token lungo. Tienilo privato — è la password del bot.",
    s2_step_4: "Torna qui e incollalo nel passo 3", s2_step_4d: "Verifichiamo che parli con Telegram. Niente viene salvato prima.",
    s2_what: "Cos'è un bot Telegram?", s2_what_b: "Un account chat gratuito gestito da codice invece che da una persona.",
    s2_verified: "Già verificato? Salta al passo 4",
    s3_title: "Incolla il token del bot.", s3_sub: "Pinghiamo Telegram per essere sicuri che sia vivo. Un secondo.",
    s3_label: "Token del bot", s3_verify: "Verifica token", s3_ok: "Token verificato. Bot:",
    s4_title: "Collega il tuo provider IA.",
    s4_sub: "Accedi a OpenAI/Codex una volta sola. Apriamo un login sicuro — nessuna password lascia il browser.",
    s4_start: "Avvia autenticazione", s4_code_label: "Codice usa-e-getta",
    s4_code_help: "Apri il link, accedi, inserisci questo codice. Lo rileviamo in automatico.",
    s4_status_idle: "Pronto", s4_status_running: "In attesa del login…",
    s4_status_success: "Collegato", s4_status_failed: "Auth fallita",
    s4_manual: "Incolla manualmente l'URL di redirect", s4_manual_help: "Bloccato? Copia l'URL dal browser dopo il login e incollalo qui.",
    s5_title: "Stiamo preparando tutto.", s5_sub: "Stiamo creando il tuo workspace. Di solito serve circa un minuto.",
    s5_phase_1: "Workspace creato", s5_phase_2: "Configurazione scritta", s5_phase_3: "Auth provider verificata",
    s5_phase_4: "Servizi in avvio", s5_phase_5: "Finalizzazione",
    s5_reassure: "Sto ancora lavorando — il primo setup può richiedere fino a due minuti.",
    s6_title: "Quasi fatto.", s6_sub: "Tre piccoli passi. Poi il tuo agente ti saluta.",
    s6_a1: "Avvia il servizio", s6_a1d: "Accendiamo il motore. Pochi secondi.", s6_a1_btn: "Avvia servizio",
    s6_a2: "Abbinamento su Telegram", s6_a2d: "Apri il bot e manda /start. Approviamo l'abbinamento in automatico.",
    s6_a2_open: "Apri bot in Telegram", s6_a2_listening: "In ascolto di /start…",
    s6_a3: "Completa il setup", s6_a3d: "Tutto pronto. Vai alla dashboard.", s6_a3_btn: "Vai alla dashboard",

    dash_hi: "Bentornata,", dash_sub: "Il tuo agente è qui. Cosa facciamo oggi?",
    dash_health: "Stato", dash_service: "Servizio", dash_gateway: "Gateway", dash_telegram: "Telegram",
    dash_last: "Ultima attività", dash_actions: "Azioni rapide", dash_quota: "Utilizzo oggi",
    dash_quota_help: "Si resetta a mezzanotte (Europe/Rome).", dash_messages: "Messaggi", dash_tokens: "Token",
    dash_cost: "Costo stimato", dash_skills: "Skill attive", dash_apps: "Le tue app",
    dash_no_apps: "Niente deployato.", dash_new_app: "Nuova app", dash_open_mission: "Apri mission",
    dash_restart: "Riavvia", dash_stop: "Ferma", dash_start: "Avvia", dash_running: "In esecuzione", dash_open: "Apri",

    mis_title: "Dai al tuo agente una mission.",
    mis_sub: "Descrivi un risultato. Non un prompt. L'agente ti farà le domande giuste e ti risponderà.",
    mis_ph: "es. \"Trovami tre appartamenti a Lisbona sotto €1800, visitabili la prossima settimana, e prenota i sopralluoghi.\"",
    mis_files: "Trascina qui i file di riferimento", mis_files_help: "PDF, TXT, CSV, MD, JSON — fino a 15 MB l'uno, max 6.",
    mis_count: "caratteri", mis_next: "Avanti",
    mis_clar_title: "Due domande veloci.", mis_clar_sub: "Aiutano il tuo agente a centrarla al primo colpo.",
    mis_launch: "Lancia mission", mis_active_title: "Mission attiva.",
    mis_active_sub: "Il tuo agente ci sta lavorando. Ti scrive su Telegram quando ha novità.",
    mis_sent: "Inviata", mis_status: "Stato", mis_status_running: "In lavorazione", mis_back_dash: "Torna alla dashboard",

    set_title: "Impostazioni", set_sub: "Come si presenta il tuo agente — e come si chiama.",
    set_section_agent: "Il tuo agente", set_displayname: "Come ti chiama", set_displayname_ph: "Marta",
    set_agentname: "Nome agente", set_agentname_ph: "Olivia", set_emoji: "Emoji",
    set_nature: "Natura", set_nature_ph: "Assistente personale",
    set_vibe: "Vibe", set_vibe_ph: "Conciso, ironico, non si scusa mai se è in ritardo.",
    set_section_account: "Account", set_lang: "Lingua interfaccia",
    set_save: "Salva modifiche", set_saved: "Modifiche salvate.",

    // agent config
    agent_title: "Il tuo agente", agent_sub: "Configura personalità, branding e chat.",
    agent_identity: "Identità", agent_personality: "Personalità", agent_chat_branding: "Branding chat",
    agent_chat_status: "Stato chat", agent_welcome: "Messaggio di benvenuto",
    agent_welcome_ph: "Ciao! Come posso aiutarti?",
    agent_color: "Colore primario", agent_avatar: "URL avatar", agent_avatar_ph: "https://...",
    agent_personality_label: "Istruzioni di sistema",
    agent_personality_ph: "Descrivi come deve comportarsi il tuo agente...",
    agent_deploy_chat: "Pubblica chat", agent_chat_live: "Chat attiva",
    agent_chat_pending: "Chat in attesa di pubblicazione", agent_open_chat: "Apri chat",

    // knowledge
    kb_title: "Knowledge Base", kb_sub: "Carica documenti che il tuo agente usa per rispondere.",
    kb_upload: "Carica file", kb_upload_help: "PDF, TXT, CSV, MD — max 6 file, 15 MB ciascuno.",
    kb_empty: "Nessun documento.", kb_name: "Nome", kb_size: "Dimensione", kb_status: "Stato",
    kb_date: "Caricato", kb_reindex: "Re-indicizza", kb_delete: "Elimina",
    kb_indexed: "Indicizzato", kb_processing: "In elaborazione", kb_error: "Errore",

    // analytics
    an_title: "Conversazioni", an_sub: "Come le persone usano il tuo agente.",
    an_total: "Conversazioni totali", an_today: "Oggi", an_week: "Questa settimana",
    an_avg: "Media messaggi/conversazione", an_topics: "Argomenti principali",
    an_empty: "Nessun dato sulle conversazioni.",

    // billing
    bill_title: "Abbonamento", bill_sub: "Gestisci il tuo piano e la fatturazione.",
    bill_plan: "Piano attuale", bill_usage: "Utilizzo nel periodo",
    bill_upgrade: "Aggiorna", bill_manage: "Gestisci abbonamento",
    bill_free: "Gratuito", bill_starter: "Starter", bill_pro: "Pro",
    bill_msgs_day: "messaggi/giorno", bill_next: "Prossima fatturazione",
    bill_free_desc: "50 messaggi/giorno, branding base",
    bill_starter_desc: "500 messaggi/giorno, branding personalizzato, analytics",
    bill_pro_desc: "Messaggi illimitati, supporto prioritario, accesso API",
  },
};

const LangCtx = createContext({ lang: "en", t: (k) => I18N.en[k] || k, setLang: () => {} });
function useT() { return useContext(LangCtx); }

function LangProvider({ initial, children }) {
  const [lang, setLangState] = useState(initial || 'en');
  const setLang = useCallback((l) => {
    setLangState(l);
    api('/api/locale', { method: 'POST', body: { locale: l } }).catch(() => {});
  }, []);
  const t = useCallback((k) => (I18N[lang] && I18N[lang][k]) || I18N.en[k] || k, [lang]);
  const ctx = useMemo(() => ({ lang, t, setLang }), [lang, t, setLang]);
  return React.createElement(LangCtx.Provider, { value: ctx }, children);
}

/* ───────── Icons (24px stroke, currentColor) ───────── */
const Icon = ({ name, size = 18, stroke = 1.6, style, className }) => {
  const s = stroke;
  const props = {
    width: size, height: size, viewBox: "0 0 24 24", fill: "none",
    stroke: "currentColor", strokeWidth: s, strokeLinecap: "round", strokeLinejoin: "round",
    style: { flex: "0 0 auto", ...style }, className
  };
  switch (name) {
    case "arrow-right": return <svg {...props}><path d="M5 12h14M13 6l6 6-6 6"/></svg>;
    case "arrow-left": return <svg {...props}><path d="M19 12H5M11 6l-6 6 6 6"/></svg>;
    case "check": return <svg {...props}><path d="M5 12.5l4 4L19 7"/></svg>;
    case "check-circle": return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M8 12.5l3 3 5-6"/></svg>;
    case "x": return <svg {...props}><path d="M6 6l12 12M18 6L6 18"/></svg>;
    case "play": return <svg {...props}><path d="M7 5l12 7-12 7V5z"/></svg>;
    case "pause": return <svg {...props}><path d="M7 5v14M17 5v14"/></svg>;
    case "stop": return <svg {...props}><rect x="6" y="6" width="12" height="12" rx="2"/></svg>;
    case "refresh": return <svg {...props}><path d="M3 12a9 9 0 0 1 15.5-6.3L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15.5 6.3L3 16"/><path d="M3 21v-5h5"/></svg>;
    case "send": return <svg {...props}><path d="M21 3L10 14"/><path d="M21 3l-7 18-4-8-8-4 19-6z"/></svg>;
    case "user": return <svg {...props}><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 4-7 8-7s8 3 8 7"/></svg>;
    case "shield": return <svg {...props}><path d="M12 3l8 3v6c0 5-3.5 8.5-8 9-4.5-.5-8-4-8-9V6l8-3z"/></svg>;
    case "lock": return <svg {...props}><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>;
    case "server": return <svg {...props}><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r=".7" fill="currentColor"/><circle cx="7" cy="16.5" r=".7" fill="currentColor"/></svg>;
    case "send-tg": return <svg {...props}><path d="M21 4L3 11l6 2 2 6 4-4 5 4z"/></svg>;
    case "target": return <svg {...props}><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5" fill="currentColor"/></svg>;
    case "code": return <svg {...props}><path d="M8 6l-6 6 6 6M16 6l6 6-6 6"/></svg>;
    case "spark": return <svg {...props}><path d="M12 3l1.7 5.3L19 10l-5.3 1.7L12 17l-1.7-5.3L5 10l5.3-1.7L12 3z"/></svg>;
    case "globe": return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 4 3 14 0 18M12 3c-3 4-3 14 0 18"/></svg>;
    case "settings": return <svg {...props}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06A2 2 0 1 1 4.27 16.96l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>;
    case "menu": return <svg {...props}><path d="M4 7h16M4 12h16M4 17h16"/></svg>;
    case "chevron-down": return <svg {...props}><path d="M6 9l6 6 6-6"/></svg>;
    case "chevron-right": return <svg {...props}><path d="M9 6l6 6-6 6"/></svg>;
    case "plus": return <svg {...props}><path d="M12 5v14M5 12h14"/></svg>;
    case "minus": return <svg {...props}><path d="M5 12h14"/></svg>;
    case "copy": return <svg {...props}><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>;
    case "upload": return <svg {...props}><path d="M12 3v12M7 8l5-5 5 5"/><path d="M4 21h16"/></svg>;
    case "file": return <svg {...props}><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/></svg>;
    case "bot": return <svg {...props}><rect x="4" y="7" width="16" height="12" rx="3"/><circle cx="9" cy="13" r="1.2" fill="currentColor"/><circle cx="15" cy="13" r="1.2" fill="currentColor"/><path d="M12 3v4M8 19v2M16 19v2"/></svg>;
    case "flag": return <svg {...props}><path d="M4 22V4a1 1 0 0 1 1-1h12l-2 4 2 4H5"/></svg>;
    case "compass": return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M15.5 8.5L13 14l-5.5 2.5L10 11l5.5-2.5z"/></svg>;
    case "key": return <svg {...props}><circle cx="8" cy="15" r="4"/><path d="M11 12l9-9M16 7l3 3M14 9l3 3"/></svg>;
    case "heart": return <svg {...props}><path d="M12 21s-7-4.5-9-9a5 5 0 0 1 9-3 5 5 0 0 1 9 3c-2 4.5-9 9-9 9z"/></svg>;
    case "moon": return <svg {...props}><path d="M21 13A9 9 0 1 1 11 3a7 7 0 0 0 10 10z"/></svg>;
    case "zap": return <svg {...props}><path d="M13 2L4 14h7l-2 8 9-12h-7l2-8z"/></svg>;
    case "download": return <svg {...props}><path d="M12 3v12M7 11l5 5 5-5"/><path d="M4 21h16"/></svg>;
    case "trash": return <svg {...props}><path d="M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/></svg>;
    case "external": return <svg {...props}><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><path d="M15 3h6v6"/><path d="M10 14L21 3"/></svg>;
    case "book": return <svg {...props}><path d="M4 19V5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v14"/><path d="M4 19a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2"/><path d="M4 19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2"/></svg>;
    case "chart": return <svg {...props}><path d="M4 20h16"/><path d="M4 20V10l4-4 4 6 4-8 4 6v10"/></svg>;
    case "credit-card": return <svg {...props}><rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20"/></svg>;
    case "message": return <svg {...props}><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>;
    case "logo": return (
      <svg width={size} height={size} viewBox="0 0 32 32" fill="none" style={style}>
        <rect x="2" y="2" width="28" height="28" rx="9" fill="var(--fa-ink)"/>
        <path d="M10 21V10h11" stroke="var(--fa-accent)" strokeWidth="2.4" strokeLinecap="round"/>
        <path d="M10 15.5h7" stroke="var(--fa-bg)" strokeWidth="2.4" strokeLinecap="round"/>
        <circle cx="22.5" cy="20.5" r="2.5" fill="var(--fa-accent)"/>
      </svg>
    );
    default: return null;
  }
};

/* ───────── Primitives ───────── */
const Btn = ({ children, kind = "primary", size, icon, iconRight, disabled, full, onClick, type = "button", style, className }) => {
  const cls = ["fa-btn", `fa-btn-${kind}`, size && `fa-btn-${size}`, full && "fa-btn-full", className].filter(Boolean).join(" ");
  return (
    <button type={type} className={cls} disabled={disabled} onClick={onClick} style={style}>
      {icon && <Icon name={icon} size={size === "lg" ? 18 : 16} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size === "lg" ? 18 : 16} />}
    </button>
  );
};

const Badge = ({ kind = "default", icon, dot, children, style }) => {
  const cls = ["fa-badge", kind !== "default" && `fa-badge-${kind}`].filter(Boolean).join(" ");
  return (
    <span className={cls} style={style}>
      {dot && <span className="dot"/>}
      {icon && <Icon name={icon} size={11}/>}
      {children}
    </span>
  );
};

const Field = ({ label, hint, children, error, htmlFor }) => (
  <div className="fa-field">
    {label && <label className="fa-label" htmlFor={htmlFor}>{label}</label>}
    {children}
    {hint && !error && <div style={{ font: "500 12px var(--fa-font-sans)", color: "var(--fa-ink-3)" }}>{hint}</div>}
    {error && <div style={{ font: "500 12px var(--fa-font-sans)", color: "var(--fa-danger)" }}>{error}</div>}
  </div>
);

const Stepper = ({ total, current }) => (
  <div className="fa-stepper" role="progressbar" aria-valuenow={current} aria-valuemax={total}>
    {Array.from({ length: total }).map((_, i) => (
      <span key={i} className={`step ${i < current - 1 ? "done" : i === current - 1 ? "cur" : ""}`}/>
    ))}
  </div>
);

const TopBar = ({ current }) => {
  const { t, lang, setLang } = useT();
  const isLanding = current === 'landing';
  const isAuth = current === 'auth' || current === 'login';
  return (
    <div style={{
      display: "flex", alignItems: "center", justifyContent: "space-between",
      padding: "18px 32px", borderBottom: "1px solid var(--fa-border)",
      background: "var(--fa-bg)", position: "sticky", top: 0, zIndex: 10,
    }}>
      <a href="/" className="fa-row" style={{ gap: 10, textDecoration: "none", color: "inherit" }}>
        <Icon name="logo" size={28}/>
        <span style={{ font: "700 16px/1 var(--fa-font-sans)", letterSpacing: "-0.01em" }}>Freedom Agent</span>
      </a>
      {isLanding && (
        <div className="fa-row fa-hide-mobile" style={{ gap: 24, font: "500 13.5px var(--fa-font-sans)", color: "var(--fa-ink-2)" }}>
          <a href="#features">{t("nav_features")}</a>
          <a href="#how">{t("nav_how")}</a>
          <a href="#pricing">{t("nav_pricing")}</a>
          <a href="#proof">{t("nav_proof")}</a>
        </div>
      )}
      <div className="fa-row" style={{ gap: 8 }}>
        <LangToggle />
        {isAuth ? (
          <a href="/" className="fa-btn fa-btn-ghost fa-btn-sm">
            {lang === "it" ? "Home" : "Home"}
          </a>
        ) : (
          <>
            <a href="/login" className="fa-btn fa-btn-ghost fa-btn-sm">{t("sign_in")}</a>
            <a href="/signup" className="fa-btn fa-btn-primary fa-btn-sm">
              {lang === "it" ? "Registrati" : "Sign up"}
            </a>
          </>
        )}
      </div>
    </div>
  );
};

const LangToggle = ({ compact }) => {
  const { lang, setLang } = useT();
  return (
    <div className="fa-row" style={{
      gap: 0, padding: 3, background: "var(--fa-surface)", border: "1px solid var(--fa-border)",
      borderRadius: 999, font: "600 11.5px var(--fa-font-sans)"
    }}>
      {["en", "it"].map(l => (
        <button key={l} onClick={() => setLang(l)} style={{
          padding: compact ? "4px 8px" : "5px 10px", borderRadius: 999, border: "none",
          background: lang === l ? "var(--fa-ink)" : "transparent",
          color: lang === l ? "var(--fa-bg)" : "var(--fa-ink-2)",
          cursor: "pointer", textTransform: "uppercase", letterSpacing: "0.04em"
        }}>{l}</button>
      ))}
    </div>
  );
};

const StatusDot = ({ kind = "success" }) => (
  <span style={{
    display: "inline-block", width: 8, height: 8, borderRadius: 999,
    background: kind === "success" ? "var(--fa-success)" : kind === "warn" ? "var(--fa-warn)" : kind === "danger" ? "var(--fa-danger)" : "var(--fa-ink-3)",
    boxShadow: `0 0 0 4px ${kind === "success" ? "var(--fa-success-soft)" : kind === "warn" ? "var(--fa-warn-soft)" : kind === "danger" ? "var(--fa-danger-soft)" : "var(--fa-bg-2)"}`
  }}/>
);

const Avatar = ({ children = "M", color, style: extraStyle }) => (
  <span className="fa-avatar" style={{ ...(color ? { background: color } : {}), ...extraStyle }}>{children}</span>
);

const Sidebar = ({ active }) => {
  const { lang, t, setLang } = useT();
  const D = typeof __PAGE_DATA__ !== 'undefined' ? __PAGE_DATA__ : {};
  const user = D.username || 'user';
  const agent = D.agentName || 'Agent';
  const items = [
    { key: "dashboard", label: "Dashboard", icon: "compass", href: "/dashboard" },
    { key: "agent", label: lang === "it" ? "Agente" : "Agent", icon: "spark", href: "/agent" },
    { key: "knowledge", label: lang === "it" ? "Conoscenze" : "Knowledge", icon: "book", href: "/knowledge" },
    { key: "analytics", label: lang === "it" ? "Conversazioni" : "Conversations", icon: "chart", href: "/analytics" },
    { key: "billing", label: lang === "it" ? "Abbonamento" : "Billing", icon: "credit-card", href: "/billing" },
    { key: "settings", label: lang === "it" ? "Impostazioni" : "Settings", icon: "settings", href: "/settings" },
  ];
  return (
    <aside style={{
      width: 248, flex: "0 0 248px", borderRight: "1px solid var(--fa-border)",
      background: "var(--fa-bg-2)", padding: "20px 14px", display: "flex", flexDirection: "column", gap: 6,
      minHeight: "100vh", position: "sticky", top: 0, alignSelf: "flex-start",
    }}>
      <div className="fa-row" style={{ gap: 10, padding: "6px 8px 16px" }}>
        <Icon name="logo" size={26}/>
        <div style={{ display: "flex", flexDirection: "column", lineHeight: 1.15 }}>
          <span style={{ font: "700 14px var(--fa-font-sans)" }}>Freedom Agent</span>
          <span style={{ font: "500 11.5px var(--fa-font-sans)", color: "var(--fa-ink-3)" }}>{agent} · @{user}</span>
        </div>
      </div>
      {items.map(it => (
        <a key={it.key} href={it.href} style={{
          display: "flex", alignItems: "center", gap: 10, padding: "10px 12px",
          borderRadius: 12, font: "600 13.5px var(--fa-font-sans)",
          color: active === it.key ? "var(--fa-ink)" : "var(--fa-ink-2)",
          background: active === it.key ? "var(--fa-surface)" : "transparent",
          border: active === it.key ? "1px solid var(--fa-border)" : "1px solid transparent",
          boxShadow: active === it.key ? "var(--fa-sh-1)" : "none",
          cursor: "pointer", textDecoration: "none",
        }}>
          <Icon name={it.icon} size={17} stroke={1.7}/>
          {it.label}
        </a>
      ))}
      <div style={{ flex: 1 }}/>
      <div className="fa-row" style={{ gap: 8, padding: "12px 8px" }}>
        <LangToggle compact />
        <a href="/logout" className="fa-btn fa-btn-ghost fa-btn-sm" style={{ marginLeft: "auto" }}>
          {lang === "it" ? "Esci" : "Sign out"}
        </a>
      </div>
    </aside>
  );
};

const ProductShell = ({ active, children }) => (
  <div className="fa-root" style={{ display: "flex", minHeight: "100vh" }}>
    <Sidebar active={active} />
    <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }}>
      {children}
    </div>
  </div>
);

const WizardShell = ({ step, children, side, narrow }) => {
  const { t, lang, setLang } = useT();
  return (
    <div className="fa-root" style={{ minHeight: "100vh", display: "flex", flexDirection: "column" }}>
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "20px 32px", borderBottom: "1px solid var(--fa-border)", background: "var(--fa-bg)",
      }}>
        <div className="fa-row" style={{ gap: 12 }}>
          <Icon name="logo" size={28}/>
          <span style={{ font: "700 16px var(--fa-font-sans)" }}>Freedom Agent</span>
          <Badge kind="accent" style={{ marginLeft: 4 }}>{t("invite_eyebrow")}</Badge>
        </div>
        <div className="fa-row" style={{ gap: 12 }}>
          <span className="fa-hide-mobile" style={{ font: "500 12px var(--fa-font-sans)", color: "var(--fa-ink-3)", letterSpacing: ".06em", textTransform: "uppercase" }}>
            {t("step")} {step} {t("of")} 6
          </span>
          <Stepper total={6} current={step}/>
          <LangToggle />
        </div>
      </div>
      <div style={{
        flex: 1, display: "grid",
        gridTemplateColumns: side ? "1.05fr 0.95fr" : "1fr",
        gap: 0,
      }}>
        <div style={{ padding: "56px 80px 80px", display: "flex", flexDirection: "column", justifyContent: "center", maxWidth: narrow ? 720 : "none" }}>
          {children}
        </div>
        {side && (
          <div className="fa-hide-mobile" style={{
            background: "var(--fa-bg-2)", borderLeft: "1px solid var(--fa-border)",
            padding: "56px 64px", display: "flex", flexDirection: "column", justifyContent: "center", gap: 20,
          }}>
            {side}
          </div>
        )}
      </div>
    </div>
  );
};

const Bubble = ({ side, children, plain, working }) => (
  <div style={{ display: "flex", justifyContent: side === "right" ? "flex-end" : "flex-start" }}>
    <div style={{
      maxWidth: "78%",
      background: working ? "var(--fa-accent-soft)" : side === "right" ? "var(--fa-accent)" : "var(--fa-surface)",
      color: working ? "var(--fa-accent-ink)" : side === "right" ? "#fff" : "var(--fa-ink)",
      padding: plain ? "10px 14px" : "8px 12px",
      borderRadius: side === "right" ? "16px 16px 4px 16px" : "16px 16px 16px 4px",
      font: "500 13.5px var(--fa-font-sans)", lineHeight: 1.45,
      border: side === "left" && !working ? "1px solid var(--fa-border)" : "none",
      boxShadow: side === "left" && !working ? "var(--fa-sh-1)" : "none",
    }}>{children}</div>
  </div>
);

const DataTable = ({ cols, rows }) => (
  <div>
    <div className="fa-row" style={{
      padding: "8px 14px", borderBottom: "1px solid var(--fa-border)", background: "var(--fa-surface)",
      font: "500 10.5px var(--fa-font-sans)", color: "var(--fa-ink-3)", textTransform: "uppercase", letterSpacing: ".06em"
    }}>
      {cols.map((c, i) => (
        <div key={i} style={{ flex: c.w, textAlign: c.center ? "center" : c.num ? "right" : "left", paddingRight: 8 }}>{c.l}</div>
      ))}
    </div>
    {rows.map((r, i) => (
      <div key={i} className="fa-row" style={{
        padding: "9px 14px", gap: 0, borderBottom: i < rows.length - 1 ? "1px solid var(--fa-border)" : "none",
        font: "500 13px var(--fa-font-sans)",
      }}>
        {r.map((cell, j) => (
          <div key={j} style={{
            flex: cols[j].w, paddingRight: 8,
            textAlign: cols[j].center ? "center" : cols[j].num ? "right" : "left",
            minWidth: 0, overflow: "hidden",
          }}>{cell}</div>
        ))}
      </div>
    ))}
  </div>
);

const SectionHeader = ({ title }) => (
  <div style={{ font: "700 13px var(--fa-font-sans)", color: "var(--fa-ink-3)", letterSpacing: ".08em", textTransform: "uppercase" }}>
    {title}
  </div>
);

const DetailMiniCard = ({ title, badge, rows }) => (
  <div className="fa-card" style={{ padding: 16, display: "flex", flexDirection: "column", gap: 12 }}>
    <div className="fa-row" style={{ justifyContent: "space-between" }}>
      <span style={{ font: "600 12.5px var(--fa-font-sans)", color: "var(--fa-ink-2)" }}>{title}</span>
      {badge}
    </div>
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      {rows.map((r, i) => (
        <div key={i} className="fa-row" style={{ justifyContent: "space-between", fontSize: 12.5 }}>
          <span style={{ color: "var(--fa-ink-3)" }}>{r[0]}</span>
          <span className="fa-mono" style={{ font: "600 12.5px var(--fa-font-mono)", color: "var(--fa-ink)" }}>{r[1]}</span>
        </div>
      ))}
    </div>
  </div>
);

/* ───────── Auth page shell ───────── */
const AuthShell = ({ children }) => {
  const isMobile = window.innerWidth < 769;
  return (
    <div className="fa-root fa-page" style={{ minHeight: "100vh", display: "flex", flexDirection: "column" }}>
      <TopBar current="auth"/>
      <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", padding: isMobile ? "32px 20px" : "64px 40px" }}>
        <div style={{ width: "100%", maxWidth: 420 }}>
          {children}
        </div>
      </div>
    </div>
  );
};

/* ───────── Login Page ───────── */
const LoginPage = () => {
  const { lang } = useT();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const error = __PAGE_DATA__?.error;

  const submit = (e) => {
    if (!username.trim() || !password) { e.preventDefault(); return; }
    setSubmitting(true);
  };

  return (
    <AuthShell>
      <div style={{ textAlign: "center", marginBottom: 32 }}>
        <Icon name="logo" size={40} style={{ marginBottom: 16 }}/>
        <h1 className="fa-display" style={{ fontSize: 32, letterSpacing: "-0.02em", fontWeight: 700 }}>
          {lang === "it" ? "Accedi" : "Sign in"}
        </h1>
        <p style={{ fontSize: 15, color: "var(--fa-ink-2)", marginTop: 8 }}>
          {lang === "it" ? "Accedi al pannello del tuo agente" : "Sign in to your agent dashboard"}
        </p>
      </div>

      {error && (
        <div className="fa-alert fa-alert-danger" style={{ marginBottom: 16 }}>
          <Icon name="x" size={16}/> {error}
        </div>
      )}

      <form method="POST" action="/login" onSubmit={submit}>
        <input type="hidden" name="_csrf" value={CSRF} />
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Field label="Username">
            <input className="fa-input fa-input-lg" type="text" name="username" required autoComplete="username"
              placeholder={lang === "it" ? "il_tuo_username" : "your_username"}
              value={username} onChange={e => setUsername(e.target.value)} autoFocus/>
          </Field>
          <Field label="Password">
            <input className="fa-input fa-input-lg" type="password" name="password" required autoComplete="current-password"
              placeholder="••••••••"
              value={password} onChange={e => setPassword(e.target.value)}/>
          </Field>
          <div style={{ textAlign: "right", marginTop: -6 }}>
            <a href="/forgot-password" style={{ fontSize: 13, color: "var(--fa-accent)", textDecoration: "none" }}>
              {lang === "it" ? "Password dimenticata?" : "Forgot password?"}
            </a>
          </div>
          <Btn kind="primary" size="lg" full type="submit" disabled={submitting}>
            {submitting
              ? (lang === "it" ? "Accesso…" : "Signing in…")
              : (lang === "it" ? "Accedi" : "Sign in")}
          </Btn>
        </div>
      </form>

      <div style={{ textAlign: "center", marginTop: 24 }}>
        <span style={{ fontSize: 13, color: "var(--fa-ink-3)" }}>
          {lang === "it" ? "Non hai un account? " : "Don't have an account? "}
        </span>
        <a href="/signup" style={{ fontSize: 13, color: "var(--fa-accent)", textDecoration: "none", fontWeight: 600 }}>
          {lang === "it" ? "Registrati gratis" : "Sign up free"}
        </a>
      </div>
    </AuthShell>
  );
};

/* ───────── Signup Page ───────── */
const SignupPage = () => {
  const { lang } = useT();
  const [username, setUsername] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [confirm, setConfirm] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const errors = __PAGE_DATA__?.errors || {};

  const submit = (e) => {
    if (!username.trim() || !password || password.length < 8) { e.preventDefault(); return; }
    if (password !== confirm) { e.preventDefault(); return; }
    setSubmitting(true);
  };

  const pwMatch = !confirm || password === confirm;

  return (
    <AuthShell>
      <div style={{ textAlign: "center", marginBottom: 32 }}>
        <Icon name="logo" size={40} style={{ marginBottom: 16 }}/>
        <h1 className="fa-display" style={{ fontSize: 32, letterSpacing: "-0.02em", fontWeight: 700 }}>
          {lang === "it" ? "Crea il tuo account" : "Create your account"}
        </h1>
        <p style={{ fontSize: 15, color: "var(--fa-ink-2)", marginTop: 8 }}>
          {lang === "it" ? "Inizia gratis — il tuo agente IA in pochi minuti" : "Start free — your AI agent in minutes"}
        </p>
      </div>

      {errors.generic && (
        <div className="fa-alert fa-alert-danger" style={{ marginBottom: 16 }}>
          <Icon name="x" size={16}/> {errors.generic}
        </div>
      )}

      <form method="POST" action="/signup" onSubmit={submit}>
        <input type="hidden" name="_csrf" value={CSRF} />
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Field label="Username" hint={lang === "it" ? "Minuscolo, numeri, underscore (3-30 caratteri)" : "Lowercase, numbers, underscore (3-30 chars)"}>
            <input className={"fa-input fa-input-lg" + (errors.username ? " fa-input-error" : "")} type="text" name="username" required autoComplete="username"
              placeholder={lang === "it" ? "il_tuo_username" : "your_username"}
              value={username} onChange={e => setUsername(e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, ''))} autoFocus/>
            {errors.username && <div style={{ fontSize: 12, color: "var(--fa-danger)", marginTop: 4 }}>{errors.username}</div>}
          </Field>
          <Field label="Email" hint={lang === "it" ? "Per recupero password" : "For password recovery"}>
            <input className={"fa-input fa-input-lg" + (errors.email ? " fa-input-error" : "")} type="email" name="email"
              placeholder="you@example.com" autoComplete="email"
              value={email} onChange={e => setEmail(e.target.value)}/>
            {errors.email && <div style={{ fontSize: 12, color: "var(--fa-danger)", marginTop: 4 }}>{errors.email}</div>}
          </Field>
          <Field label="Password" hint={lang === "it" ? "Almeno 8 caratteri" : "At least 8 characters"}>
            <input className={"fa-input fa-input-lg" + (errors.password ? " fa-input-error" : "")} type="password" name="password" required autoComplete="new-password"
              placeholder="••••••••" minLength={8}
              value={password} onChange={e => setPassword(e.target.value)}/>
            {errors.password && <div style={{ fontSize: 12, color: "var(--fa-danger)", marginTop: 4 }}>{errors.password}</div>}
          </Field>
          <Field label={lang === "it" ? "Conferma password" : "Confirm password"}>
            <input className={"fa-input fa-input-lg" + (!pwMatch ? " fa-input-error" : "")} type="password" required autoComplete="new-password"
              placeholder="••••••••"
              value={confirm} onChange={e => setConfirm(e.target.value)}/>
            {!pwMatch && <div style={{ fontSize: 12, color: "var(--fa-danger)", marginTop: 4 }}>
              {lang === "it" ? "Le password non corrispondono" : "Passwords don't match"}
            </div>}
          </Field>
          <Btn kind="primary" size="lg" full type="submit" disabled={submitting || !pwMatch || password.length < 8}>
            {submitting
              ? (lang === "it" ? "Creazione…" : "Creating…")
              : (lang === "it" ? "Crea account" : "Create account")}
          </Btn>
        </div>
      </form>

      <div style={{ textAlign: "center", marginTop: 20 }}>
        <span style={{ fontSize: 12, color: "var(--fa-ink-3)" }}>
          {lang === "it" ? "Nessuna carta di credito richiesta. Piano Free incluso." : "No credit card required. Free plan included."}
        </span>
      </div>
      <div style={{ textAlign: "center", marginTop: 10 }}>
        <span style={{ fontSize: 12, color: "var(--fa-ink-3)", lineHeight: 1.5 }}>
          {lang === "it" ? "Creando un account accetti i nostri " : "By creating an account you agree to our "}
          <a href="/terms" style={{ color: "var(--fa-ink-2)", textDecoration: "underline" }}>{lang === "it" ? "Termini" : "Terms"}</a>
          {lang === "it" ? " e la " : " and "}
          <a href="/privacy" style={{ color: "var(--fa-ink-2)", textDecoration: "underline" }}>{lang === "it" ? "Privacy" : "Privacy Policy"}</a>.
        </span>
      </div>
      <div style={{ textAlign: "center", marginTop: 12 }}>
        <span style={{ fontSize: 13, color: "var(--fa-ink-3)" }}>
          {lang === "it" ? "Hai già un account? " : "Already have an account? "}
        </span>
        <a href="/login" style={{ fontSize: 13, color: "var(--fa-accent)", textDecoration: "none", fontWeight: 600 }}>
          {lang === "it" ? "Accedi" : "Sign in"}
        </a>
      </div>
    </AuthShell>
  );
};

/* ───────── Forgot Password Page ───────── */
const ForgotPasswordPage = () => {
  const { lang } = useT();
  const [identifier, setIdentifier] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const pd = __PAGE_DATA__ || {};

  if (pd.sent) {
    return (
      <AuthShell>
        <div style={{ textAlign: "center" }}>
          <div style={{ width: 56, height: 56, borderRadius: 16, background: "var(--fa-success-soft)", color: "var(--fa-success)", display: "inline-flex", alignItems: "center", justifyContent: "center", marginBottom: 20 }}>
            <Icon name="check" size={28}/>
          </div>
          <h1 className="fa-display" style={{ fontSize: 28, letterSpacing: "-0.02em", fontWeight: 700 }}>
            {lang === "it" ? "Controlla Telegram" : "Check Telegram"}
          </h1>
          <p style={{ fontSize: 15, color: "var(--fa-ink-2)", marginTop: 12, lineHeight: 1.5 }}>
            {lang === "it"
              ? "Se il tuo account ha un bot Telegram collegato, ti abbiamo inviato un link per reimpostare la password. Controlla i messaggi del bot."
              : "If your account has a linked Telegram bot, we sent you a password reset link. Check your bot messages."}
          </p>
          <p style={{ fontSize: 13, color: "var(--fa-ink-3)", marginTop: 16 }}>
            {lang === "it"
              ? "Nessun bot Telegram collegato o non hai ricevuto nulla? Scrivi a support@freedom-agent.com e reimpostiamo noi la password."
              : "No Telegram bot linked, or didn't receive anything? Email support@freedom-agent.com and we'll reset your password for you."}
          </p>
          <div style={{ marginTop: 24 }}>
            <a href="/login" style={{ fontSize: 14, color: "var(--fa-accent)", textDecoration: "none", fontWeight: 600 }}>
              {lang === "it" ? "Torna al login" : "Back to sign in"}
            </a>
          </div>
        </div>
      </AuthShell>
    );
  }

  return (
    <AuthShell>
      <div style={{ textAlign: "center", marginBottom: 32 }}>
        <Icon name="logo" size={40} style={{ marginBottom: 16 }}/>
        <h1 className="fa-display" style={{ fontSize: 28, letterSpacing: "-0.02em", fontWeight: 700 }}>
          {lang === "it" ? "Password dimenticata?" : "Forgot your password?"}
        </h1>
        <p style={{ fontSize: 15, color: "var(--fa-ink-2)", marginTop: 8, lineHeight: 1.5 }}>
          {lang === "it"
            ? "Inserisci username o email. Se hai un bot Telegram collegato, ti invieremo lì il link di reset. Altrimenti scrivi a support@freedom-agent.com e reimpostiamo noi la password."
            : "Enter your username or email. If you have a linked Telegram bot, we'll send the reset link there. Otherwise email support@freedom-agent.com and we'll reset it for you."}
        </p>
      </div>

      {pd.error && (
        <div className="fa-alert fa-alert-danger" style={{ marginBottom: 16 }}>
          <Icon name="x" size={16}/> {pd.error}
        </div>
      )}

      <form method="POST" action="/forgot-password" onSubmit={() => setSubmitting(true)}>
        <input type="hidden" name="_csrf" value={CSRF} />
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Field label={lang === "it" ? "Username o email" : "Username or email"}>
            <input className="fa-input fa-input-lg" type="text" name="identifier" required autoComplete="username"
              placeholder={lang === "it" ? "il_tuo_username o email" : "your_username or email"}
              value={identifier} onChange={e => setIdentifier(e.target.value)} autoFocus/>
          </Field>
          <Btn kind="primary" size="lg" full type="submit" disabled={submitting || !identifier.trim()}>
            {submitting
              ? (lang === "it" ? "Invio…" : "Sending…")
              : (lang === "it" ? "Invia link di reset" : "Send reset link")}
          </Btn>
        </div>
      </form>

      <div style={{ textAlign: "center", marginTop: 24 }}>
        <a href="/login" style={{ fontSize: 13, color: "var(--fa-accent)", textDecoration: "none", fontWeight: 600 }}>
          {lang === "it" ? "Torna al login" : "Back to sign in"}
        </a>
      </div>
    </AuthShell>
  );
};

/* ───────── Reset Password Page ───────── */
const ResetPasswordPage = () => {
  const { lang } = useT();
  const [password, setPassword] = useState('');
  const [confirm, setConfirm] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const pd = __PAGE_DATA__ || {};

  if (pd.expired) {
    return (
      <AuthShell>
        <div style={{ textAlign: "center" }}>
          <div style={{ width: 56, height: 56, borderRadius: 16, background: "var(--fa-danger-soft, #fef2f2)", color: "var(--fa-danger, #ef4444)", display: "inline-flex", alignItems: "center", justifyContent: "center", marginBottom: 20 }}>
            <Icon name="x" size={28}/>
          </div>
          <h1 className="fa-display" style={{ fontSize: 28, letterSpacing: "-0.02em", fontWeight: 700 }}>
            {lang === "it" ? "Link scaduto" : "Link expired"}
          </h1>
          <p style={{ fontSize: 15, color: "var(--fa-ink-2)", marginTop: 12, lineHeight: 1.5 }}>
            {lang === "it"
              ? "Questo link di reset è scaduto o è già stato usato. Richiedi un nuovo link."
              : "This reset link has expired or was already used. Request a new one."}
          </p>
          <div style={{ marginTop: 24, display: "flex", gap: 12, justifyContent: "center" }}>
            <Btn kind="primary" onClick={() => location.href = '/forgot-password'}>
              {lang === "it" ? "Richiedi nuovo link" : "Request new link"}
            </Btn>
            <Btn kind="ghost" onClick={() => location.href = '/login'}>
              {lang === "it" ? "Torna al login" : "Back to sign in"}
            </Btn>
          </div>
        </div>
      </AuthShell>
    );
  }

  const pwMatch = !confirm || password === confirm;

  const submit = (e) => {
    if (password.length < 8 || password !== confirm) { e.preventDefault(); return; }
    setSubmitting(true);
  };

  return (
    <AuthShell>
      <div style={{ textAlign: "center", marginBottom: 32 }}>
        <Icon name="logo" size={40} style={{ marginBottom: 16 }}/>
        <h1 className="fa-display" style={{ fontSize: 28, letterSpacing: "-0.02em", fontWeight: 700 }}>
          {lang === "it" ? "Reimposta password" : "Reset your password"}
        </h1>
        {pd.username && (
          <p style={{ fontSize: 15, color: "var(--fa-ink-2)", marginTop: 8 }}>
            {lang === "it" ? `Account: @${pd.username}` : `Account: @${pd.username}`}
          </p>
        )}
      </div>

      {(pd.error || pd.error2) && (
        <div className="fa-alert fa-alert-danger" style={{ marginBottom: 16 }}>
          <Icon name="x" size={16}/> {pd.error || pd.error2}
        </div>
      )}

      <form method="POST" onSubmit={submit}>
        <input type="hidden" name="_csrf" value={CSRF} />
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Field label={lang === "it" ? "Nuova password" : "New password"} hint={lang === "it" ? "Almeno 8 caratteri" : "At least 8 characters"}>
            <input className="fa-input fa-input-lg" type="password" name="password" required autoComplete="new-password"
              placeholder="••••••••" minLength={8}
              value={password} onChange={e => setPassword(e.target.value)} autoFocus/>
          </Field>
          <Field label={lang === "it" ? "Conferma password" : "Confirm password"}>
            <input className={"fa-input fa-input-lg" + (!pwMatch ? " fa-input-error" : "")} type="password" name="password_confirm" required autoComplete="new-password"
              placeholder="••••••••"
              value={confirm} onChange={e => setConfirm(e.target.value)}/>
            {!pwMatch && <div style={{ fontSize: 12, color: "var(--fa-danger)", marginTop: 4 }}>
              {lang === "it" ? "Le password non corrispondono" : "Passwords don't match"}
            </div>}
          </Field>
          <Btn kind="primary" size="lg" full type="submit" disabled={submitting || !pwMatch || password.length < 8}>
            {submitting
              ? (lang === "it" ? "Salvataggio…" : "Saving…")
              : (lang === "it" ? "Reimposta password" : "Reset password")}
          </Btn>
        </div>
      </form>
    </AuthShell>
  );
};

/* ───────── Export to window for cross-file use ───────── */
Object.assign(window, {
  // API
  api, useApi, usePoll, CSRF,
  // Context
  I18N, LangCtx, useT, LangProvider, ToastProvider, useToast,
  // Components
  Icon, Btn, Badge, Field, Stepper, TopBar, LangToggle, StatusDot, Avatar,
  Sidebar, ProductShell, WizardShell, Bubble, DataTable, SectionHeader, DetailMiniCard,
  LoginPage, SignupPage, ForgotPasswordPage, ResetPasswordPage,
});
