// =====================================================================
// CAMPAIGN CADDIE — REAL APP
// Backend-ready functional dashboard.
// All data flows through `api` — wire those calls to your backend.
// =====================================================================

const { useState: useS, useEffect: useE, useRef: useR, useMemo: useM, useCallback: useC } = React;

// ---------- API CLIENT (swap fetches with real endpoints) ----------
const API_BASE = window.CC_API_BASE || ''; // e.g. 'https://api.campaigncaddie.com'

async function jsonFetch(path, init = {}) {
  // Demo mode: when no base URL is set, hit localStorage instead of the network.
  if (!API_BASE) return localBackend(path, init);
  const res = await fetch(API_BASE + path, {
    ...init,
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + (sessionStorage.getItem('cc:token') || ''),
      ...(init.headers || {}),
    },
  });
  if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
  return res.status === 204 ? null : res.json();
}

// localStorage-backed demo backend so the app is fully functional offline.
function localBackend(path, init) {
  const method = (init.method || 'GET').toUpperCase();
  const body = init.body ? JSON.parse(init.body) : null;
  const seg = path.replace(/^\/+/, '').split('/');
  const key = (k) => 'cc:db:' + k;
  const read = (k) => { try { return JSON.parse(localStorage.getItem(key(k)) || 'null'); } catch (_) { return null; } };
  const write = (k, v) => localStorage.setItem(key(k), JSON.stringify(v));

  // resource [id]
  const [resource, id] = seg;
  const collection = read(resource) || [];

  if (method === 'GET' && !id) return Promise.resolve(collection);
  if (method === 'GET' && id) return Promise.resolve(collection.find(r => r.id === id) || null);
  if (method === 'POST') {
    const newItem = { id: 'r_' + Math.random().toString(36).slice(2, 9), createdAt: Date.now(), ...body };
    write(resource, [...collection, newItem]);
    return Promise.resolve(newItem);
  }
  if (method === 'PATCH' && id) {
    const next = collection.map(r => r.id === id ? { ...r, ...body, updatedAt: Date.now() } : r);
    write(resource, next);
    return Promise.resolve(next.find(r => r.id === id));
  }
  if (method === 'DELETE' && id) {
    write(resource, collection.filter(r => r.id !== id));
    return Promise.resolve(null);
  }
  return Promise.reject(new Error('Unsupported demo route: ' + method + ' ' + path));
}

const api = {
  // wire each of these to a backend endpoint when ready
  list:   (resource)         => jsonFetch(`/${resource}`),
  get:    (resource, id)     => jsonFetch(`/${resource}/${id}`),
  create: (resource, body)   => jsonFetch(`/${resource}`,        { method: 'POST',   body: JSON.stringify(body) }),
  update: (resource, id, b)  => jsonFetch(`/${resource}/${id}`,  { method: 'PATCH',  body: JSON.stringify(b) }),
  remove: (resource, id)     => jsonFetch(`/${resource}/${id}`,  { method: 'DELETE' }),
  ai:     (prompt, ctx)      => Promise.resolve({ // swap for /v1/coach
    text: aiStub(prompt, ctx),
  }),
};

function aiStub(q, ctx) {
  const Q = (q || '').toLowerCase();
  if (Q.includes('caption') || Q.includes('write') || Q.includes('post')) return "Here's a draft: \"Quietly excited to share what we've been working on. Small drop, big love. ✨\" Want a different tone?";
  if (Q.includes('time') || Q.includes('when')) return "For a small audience like yours, Tue–Thu 7:30–9 PM tends to drive the most saves. Want me to schedule there by default?";
  if (Q.includes('budget') || Q.includes('cost') || Q.includes('reach')) return "I can't size that without spend data yet. Once you connect Meta or run your first paid post, I'll give you real estimates.";
  if (Q.includes('campaign') || Q.includes('plan')) return "Tell me what you're launching (product, offer, audience) and I'll draft a 7-day campaign with channels, copy, and a calendar.";
  return "Got it. Once you connect a channel or add a product, I can give you specific next steps. For now, try asking me to draft a caption or plan a campaign.";
}

// ---------- HOOKS ----------
function useResource(name) {
  const [items, setItems] = useS([]);
  const [loading, setLoading] = useS(true);
  const refresh = useC(async () => {
    setLoading(true);
    try { setItems(await api.list(name) || []); } finally { setLoading(false); }
  }, [name]);
  useE(() => { refresh(); }, [refresh]);
  const create = async (body) => { const r = await api.create(name, body); setItems(s => [...s, r]); return r; };
  const update = async (id, body) => { const r = await api.update(name, id, body); setItems(s => s.map(x => x.id === id ? r : x)); return r; };
  const remove = async (id) => { await api.remove(name, id); setItems(s => s.filter(x => x.id !== id)); };
  return { items, loading, refresh, create, update, remove };
}

function useToast() {
  const [t, setT] = useS(null);
  const show = (msg) => {
    setT({ msg, id: Math.random() });
    setTimeout(() => setT(null), 2400);
  };
  return [t, show];
}

// ---------- ICONS (re-defined so app.jsx is self-contained) ----------
function I({ name, size = 16, stroke = 1.5 }) {
  const s = { width: size, height: size, fill: 'none', stroke: 'currentColor', strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'home':    return <svg {...s} viewBox="0 0 24 24"><path d="M3 11l9-8 9 8"/><path d="M5 9v12h14V9"/></svg>;
    case 'flag':    return <svg {...s} viewBox="0 0 24 24"><path d="M4 21V4"/><path d="M4 4h13l-2 4 2 4H4"/></svg>;
    case 'cal':     return <svg {...s} viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/></svg>;
    case 'check':   return <svg {...s} viewBox="0 0 24 24"><path d="M5 12l5 5L20 7"/></svg>;
    case 'video':   return <svg {...s} viewBox="0 0 24 24"><rect x="3" y="6" width="13" height="12" rx="2"/><path d="M16 10l5-3v10l-5-3z"/></svg>;
    case 'cost':    return <svg {...s} viewBox="0 0 24 24"><path d="M12 2v20M17 7H10a3 3 0 100 6h4a3 3 0 110 6H7"/></svg>;
    case 'plus':    return <svg {...s} viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg>;
    case 'plug':    return <svg {...s} viewBox="0 0 24 24"><path d="M9 2v6M15 2v6M6 8h12v4a6 6 0 11-12 0z"/><path d="M12 18v4"/></svg>;
    case 'bell':    return <svg {...s} viewBox="0 0 24 24"><path d="M6 8a6 6 0 0112 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 003.4 0"/></svg>;
    case 'list':    return <svg {...s} viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h10"/></svg>;
    case 'send':    return <svg {...s} viewBox="0 0 24 24"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4z"/></svg>;
    case 'arrow':   return <svg {...s} viewBox="0 0 24 24"><path d="M5 12h14M13 6l6 6-6 6"/></svg>;
    case 'spark':   return <svg {...s} viewBox="0 0 24 24"><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M18.4 5.6l-2.8 2.8M8.4 15.6l-2.8 2.8"/></svg>;
    case 'x':       return <svg {...s} viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18"/></svg>;
    case 'edit':    return <svg {...s} viewBox="0 0 24 24"><path d="M14 4l6 6L8 22H2v-6z"/></svg>;
    case 'trash':   return <svg {...s} viewBox="0 0 24 24"><path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M5 6l1 14a2 2 0 002 2h8a2 2 0 002-2l1-14"/></svg>;
    case 'search':  return <svg {...s} viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5-5"/></svg>;
    case 'cog':     return <svg {...s} viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19 12a7 7 0 00-.1-1.2l2-1.6-2-3.4-2.4.9a7 7 0 00-2.1-1.2L14 3h-4l-.4 2.5a7 7 0 00-2.1 1.2l-2.4-.9-2 3.4 2 1.6A7 7 0 005 12a7 7 0 00.1 1.2l-2 1.6 2 3.4 2.4-.9a7 7 0 002.1 1.2L10 21h4l.4-2.5a7 7 0 002.1-1.2l2.4.9 2-3.4-2-1.6c.07-.4.1-.8.1-1.2z"/></svg>;
    case 'chevron': return <svg {...s} viewBox="0 0 24 24"><path d="M9 6l6 6-6 6"/></svg>;
    case 'chev-d':  return <svg {...s} viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg>;
    case 'logout':  return <svg {...s} viewBox="0 0 24 24"><path d="M16 17l5-5-5-5M21 12H9M9 21H4V3h5"/></svg>;
    case 'menu':    return <svg {...s} viewBox="0 0 24 24"><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></svg>;
    default:        return null;
  }
}

// ---------- TOKENS ----------
const APP_NAV = [
  { id: 'home',         label: 'Home',          icon: 'home' },
  { id: 'campaigns',    label: 'Campaigns',     icon: 'flag' },
  { id: 'calendar',     label: 'Calendar',      icon: 'cal' },
  { id: 'todos',        label: 'To-do',         icon: 'check' },
  { id: 'video',        label: 'Video tracker', icon: 'video' },
  { id: 'cost',         label: 'Cost estimator',icon: 'cost' },
  { id: 'products',     label: 'Products',      icon: 'plus' },
  { id: 'integrations', label: 'Integrations',  icon: 'plug' },
];

// ---------- ROOT ----------
function RealApp({ go }) {
  const [view, setView] = useS(() => sessionStorage.getItem('cc:view') || 'home');
  const [coachOpen, setCoachOpen] = useS(false); // narrower & off by default
  const [navOpen, setNavOpen] = useS(true);
  const [paletteOpen, setPaletteOpen] = useS(false);
  const [accountOpen, setAccountOpen] = useS(false);
  const [logoMenuOpen, setLogoMenuOpen] = useS(false);
  const [toast, showToast] = useToast();
  const [user] = useS(() => ({
    name: sessionStorage.getItem('cc:userName') || 'Beta User',
    email: sessionStorage.getItem('cc:userEmail') || 'you@business.com',
    org: sessionStorage.getItem('cc:userOrg') || 'My Workspace',
  }));

  useE(() => { sessionStorage.setItem('cc:view', view); }, [view]);

  // Cmd-K / Ctrl-K
  useE(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); setPaletteOpen(o => !o); }
      if (e.key === 'Escape') { setPaletteOpen(false); setLogoMenuOpen(false); setAccountOpen(false); }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  const signOut = () => {
    try {
      sessionStorage.removeItem('cc:authed');
      sessionStorage.removeItem('cc:token');
      sessionStorage.removeItem('cc:view');
    } catch (_) {}
    go('home');
  };

  const ctx = { showToast, view, setView, user };

  return (
    <div className="cc-app">
      <CCStyles/>

      {/* Top bar */}
      <header className="cc-topbar">
        <div className="cc-topbar-left">
          <button className="cc-icon-btn" onClick={() => setNavOpen(o => !o)} aria-label="Toggle nav">
            <I name="list"/>
          </button>
          <div style={{ position: 'relative' }}>
            <button className="cc-logo-btn" onClick={() => setLogoMenuOpen(o => !o)}>
              <svg width="20" height="20" viewBox="0 0 64 64" fill="none">
                <g stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><line x1="32" y1="32" x2="32" y2="14"/><line x1="32" y1="32" x2="49.12" y2="26.44"/><line x1="32" y1="32" x2="42.58" y2="46.56"/><line x1="32" y1="32" x2="21.42" y2="46.56"/><line x1="32" y1="32" x2="14.88" y2="26.44"/></g><circle cx="32" cy="32" r="5" fill="currentColor"/><circle cx="32" cy="14" r="3.3" fill="currentColor"/><circle cx="49.12" cy="26.44" r="3.3" fill="currentColor"/><circle cx="42.58" cy="46.56" r="3.3" fill="currentColor"/><circle cx="21.42" cy="46.56" r="3.3" fill="currentColor"/><circle cx="14.88" cy="26.44" r="3.3" fill="currentColor"/>
              </svg>
              <span style={{ fontFamily: 'var(--serif)', fontSize: 17 }}>Campaign Caddie</span>
              <I name="chev-d" size={12}/>
            </button>
            {logoMenuOpen && (
              <LogoMenu close={() => setLogoMenuOpen(false)} setView={setView} go={go}/>
            )}
          </div>
          <span className="cc-tag">BETA · COHORT 03</span>
        </div>

        <button className="cc-search" onClick={() => setPaletteOpen(true)}>
          <I name="search" size={13}/>
          <span style={{ flex: 1, color: 'var(--mute-2)' }}>Search or jump to…</span>
          <span className="cc-kbd">⌘K</span>
        </button>

        <div className="cc-topbar-right">
          <button className="cc-icon-btn" onClick={() => setCoachOpen(o => !o)} aria-label="Toggle Caddie">
            <I name="spark" size={14}/>
            {coachOpen && <span className="cc-dot"/>}
          </button>
          <button className="cc-icon-btn" aria-label="Notifications">
            <I name="bell" size={14}/>
          </button>
          <div style={{ position: 'relative' }}>
            <button className="cc-account-chip" onClick={() => setAccountOpen(o => !o)}>
              <span className="cc-avatar">{initials(user.name)}</span>
              <span style={{ fontSize: 12, fontWeight: 500 }}>{user.name.split(' ')[0]}</span>
              <I name="chev-d" size={11}/>
            </button>
            {accountOpen && (
              <div className="cc-menu" style={{ right: 0 }}>
                <div className="cc-menu-head">
                  <div style={{ fontWeight: 500, fontSize: 13 }}>{user.name}</div>
                  <div className="mono" style={{ color: 'var(--mute)', fontSize: 10 }}>{user.email}</div>
                </div>
                <button className="cc-menu-item" onClick={() => { setView('home'); setAccountOpen(false); }}><I name="home" size={13}/> Home</button>
                <button className="cc-menu-item" onClick={() => { setView('integrations'); setAccountOpen(false); }}><I name="plug" size={13}/> Integrations</button>
                <button className="cc-menu-item" onClick={() => { setAccountOpen(false); showToast('Settings coming soon'); }}><I name="cog" size={13}/> Settings</button>
                <div className="cc-menu-sep"/>
                <button className="cc-menu-item" onClick={signOut}><I name="logout" size={13}/> Sign out</button>
              </div>
            )}
          </div>
        </div>
      </header>

      {/* Body */}
      <div className="cc-body" style={{
        gridTemplateColumns: `${navOpen ? '220px' : '0px'} 1fr ${coachOpen ? '300px' : '0px'}`,
      }}>
        <SideNav view={view} setView={setView} open={navOpen}/>
        <main className="cc-main">
          <ViewRouter view={view} setView={setView} ctx={ctx}/>
        </main>
        {coachOpen && <Coach view={view} onClose={() => setCoachOpen(false)}/>}
      </div>

      {/* Palette */}
      {paletteOpen && (
        <CommandPalette
          close={() => setPaletteOpen(false)}
          setView={(v) => { setView(v); setPaletteOpen(false); }}
        />
      )}

      {/* Toast */}
      {toast && <div className="cc-toast">{toast.msg}</div>}
    </div>
  );
}

function initials(name) {
  return (name || '').split(/\s+/).map(s => s[0]).filter(Boolean).slice(0,2).join('').toUpperCase() || '?';
}

// ---------- LOGO MENU (replaces "back to marketing") ----------
function LogoMenu({ close, setView, go }) {
  useE(() => {
    const onClick = (e) => { if (!e.target.closest('.cc-menu')) close(); };
    setTimeout(() => document.addEventListener('click', onClick), 0);
    return () => document.removeEventListener('click', onClick);
  }, []);
  return (
    <div className="cc-menu" style={{ left: 0 }}>
      <div className="cc-menu-head">
        <div className="mono" style={{ color: 'var(--mute)', fontSize: 10 }}>WORKSPACE</div>
        <div style={{ fontSize: 13, fontWeight: 500, marginTop: 2 }}>My Workspace</div>
      </div>
      <button className="cc-menu-item" onClick={() => { setView('home'); close(); }}><I name="home" size={13}/> Go to Home</button>
      <button className="cc-menu-item" onClick={() => { setView('integrations'); close(); }}><I name="plug" size={13}/> Manage integrations</button>
      <div className="cc-menu-sep"/>
      <button className="cc-menu-item" onClick={() => { go('home'); close(); }}>
        <I name="arrow" size={13}/> View marketing site
      </button>
    </div>
  );
}

// ---------- SIDE NAV ----------
function SideNav({ view, setView, open }) {
  const { items: todos } = useResource('todos');
  const todosCount = todos.filter(t => !t.done).length;
  return (
    <aside className="cc-sidenav" style={{ display: open ? 'flex' : 'none' }}>
      <div className="mono cc-section-label">WORKSPACE</div>
      {APP_NAV.map(n => {
        const active = view === n.id;
        const badge = n.id === 'todos' && todosCount > 0 ? todosCount : null;
        return (
          <button key={n.id} className={'cc-navitem' + (active ? ' active' : '')} onClick={() => setView(n.id)}>
            <I name={n.icon} size={14}/>
            <span>{n.label}</span>
            {badge != null && <span className="cc-badge">{badge}</span>}
          </button>
        );
      })}
      <div className="cc-spacer"/>
      <div className="mono cc-section-label">SHORTCUTS</div>
      <button className="cc-navitem" onClick={() => setView('campaigns')}>
        <I name="plus" size={13}/><span>New campaign</span>
      </button>
      <button className="cc-navitem" onClick={() => setView('calendar')}>
        <I name="cal" size={13}/><span>Schedule</span>
      </button>
    </aside>
  );
}

// ---------- VIEW ROUTER ----------
function ViewRouter({ view, setView, ctx }) {
  switch (view) {
    case 'home':         return <HomeView setView={setView} ctx={ctx}/>;
    case 'campaigns':    return <CampaignsView ctx={ctx}/>;
    case 'calendar':     return <CalendarView ctx={ctx}/>;
    case 'todos':        return <TodosView ctx={ctx}/>;
    case 'video':        return <VideoView ctx={ctx}/>;
    case 'cost':         return <CostView ctx={ctx}/>;
    case 'products':     return <ProductsView ctx={ctx}/>;
    case 'integrations': return <IntegrationsView ctx={ctx}/>;
    default:             return <HomeView setView={setView} ctx={ctx}/>;
  }
}

// =====================================================================
// HOME
// =====================================================================
function HomeView({ setView, ctx }) {
  const { items: campaigns } = useResource('campaigns');
  const { items: todos } = useResource('todos');
  const { items: products } = useResource('products');
  const { items: integrations } = useResource('integrations');

  const live = campaigns.filter(c => c.status === 'Live').length;
  const open = todos.filter(t => !t.done).length;
  const today = new Date();
  const greeting = today.getHours() < 12 ? 'Good morning' : today.getHours() < 18 ? 'Good afternoon' : 'Good evening';

  const noData = campaigns.length === 0 && todos.length === 0 && products.length === 0;

  return (
    <PageShell>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
        <div>
          <div className="mono" style={{ color: 'var(--mute)' }}>{today.toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' }).toUpperCase()}</div>
          <h1 className="cc-h1">{greeting}, {ctx.user.name.split(' ')[0]}.</h1>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="cc-btn" onClick={() => setView('products')}><I name="plus" size={13}/> Add product</button>
          <button className="cc-btn primary" onClick={() => setView('campaigns')}><I name="spark" size={13}/> New campaign</button>
        </div>
      </div>

      {noData ? (
        <FirstRunChecklist setView={setView} ctx={ctx}/>
      ) : (
        <>
          <div className="cc-kpi-row">
            <KPI label="ACTIVE CAMPAIGNS" v={live} sub={`${campaigns.length} total`}/>
            <KPI label="TASKS OPEN" v={open} sub={`${todos.length - open} done`}/>
            <KPI label="PRODUCTS" v={products.length} sub="In catalog"/>
            <KPI label="INTEGRATIONS" v={integrations.filter(i => i.status === 'Connected').length} sub={`${integrations.length} configured`} last/>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 16 }} className="cc-stack-on-mobile">
            <Card title="Active campaigns" action={<button className="cc-link" onClick={() => setView('campaigns')}>View all →</button>}>
              {campaigns.length === 0 ? (
                <Empty
                  title="No campaigns yet"
                  desc="Create your first campaign to start scheduling, drafting copy, and tracking results."
                  cta="New campaign"
                  onClick={() => setView('campaigns')}
                />
              ) : (
                <div>
                  {campaigns.slice(0, 4).map(c => (
                    <div key={c.id} className="cc-row">
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13, fontWeight: 500 }}>{c.name}</div>
                        <div className="mono cc-row-sub">{(c.channels || []).join(' · ') || '—'} &nbsp;·&nbsp; ${c.spent || 0}/{c.budget || 0}</div>
                      </div>
                      <Chip status={c.status}/>
                    </div>
                  ))}
                </div>
              )}
            </Card>

            <Card title="To-do" action={<button className="cc-link" onClick={() => setView('todos')}>View all →</button>}>
              {todos.length === 0 ? (
                <Empty
                  title="No tasks yet"
                  desc="Tasks Caddie generates from your campaigns will appear here."
                  cta="Add a task"
                  onClick={() => setView('todos')}
                />
              ) : (
                <div>
                  {todos.slice(0, 5).map(t => <TodoRow key={t.id} todo={t}/>)}
                </div>
              )}
            </Card>
          </div>
        </>
      )}
    </PageShell>
  );
}

function FirstRunChecklist({ setView, ctx }) {
  const steps = [
    { id: 'integrations', t: 'Connect a channel', d: 'Link Instagram, Meta, Klaviyo or Shopify so Caddie knows where to post.' },
    { id: 'products',     t: 'Add a product or offer', d: "What you're selling. Caddie tunes its copy and audience to it." },
    { id: 'campaigns',    t: 'Plan your first campaign', d: 'Tell Caddie what you want to launch — it drafts the calendar.' },
  ];
  return (
    <Card>
      <div style={{ padding: '32px 8px 24px' }}>
        <div className="mono" style={{ color: 'var(--mute)' }}>GETTING STARTED</div>
        <h3 className="cc-h3" style={{ margin: '6px 0 4px' }}>Three steps to your first campaign.</h3>
        <p className="cc-p">Welcome to Campaign Caddie. The app is empty until you connect something — let's fix that.</p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 1, marginTop: 22, border: '1px solid var(--hair)', borderRadius: 10, overflow: 'hidden' }}>
          {steps.map((s, i) => (
            <button key={s.id} onClick={() => setView(s.id)} className="cc-step">
              <div className="cc-step-num">0{i + 1}</div>
              <div style={{ flex: 1, textAlign: 'left' }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{s.t}</div>
                <div style={{ fontSize: 13, color: 'var(--mute-2)', marginTop: 2 }}>{s.d}</div>
              </div>
              <I name="arrow" size={14}/>
            </button>
          ))}
        </div>
      </div>
    </Card>
  );
}

// =====================================================================
// CAMPAIGNS
// =====================================================================
function CampaignsView({ ctx }) {
  const { items, create, update, remove } = useResource('campaigns');
  const [filter, setFilter] = useS('All');
  const [editing, setEditing] = useS(null);
  const [creating, setCreating] = useS(false);

  const filtered = filter === 'All' ? items : items.filter(i => i.status === filter);
  const counts = items.reduce((acc, i) => ({ ...acc, [i.status]: (acc[i.status] || 0) + 1 }), {});

  return (
    <PageShell>
      <PageHead
        kicker={`ALL CAMPAIGNS · ${items.length}`}
        title="Campaigns"
        action={<button className="cc-btn primary" onClick={() => setCreating(true)}><I name="plus" size={13}/> New campaign</button>}
      />

      <div className="cc-tabs">
        {['All', 'Live', 'Drafting', 'Scheduled', 'Ended'].map(t => (
          <button key={t} onClick={() => setFilter(t)} className={'cc-tab' + (filter === t ? ' active' : '')}>
            {t} {t !== 'All' && counts[t] != null && <span className="cc-tab-count">{counts[t]}</span>}
          </button>
        ))}
      </div>

      {filtered.length === 0 ? (
        <Empty
          title={items.length === 0 ? 'No campaigns yet' : `No ${filter.toLowerCase()} campaigns`}
          desc={items.length === 0 ? 'A campaign is a batch of posts, emails, or ads tied to a single goal. Caddie will draft the schedule and copy for you.' : ''}
          cta={items.length === 0 ? 'New campaign' : null}
          onClick={() => setCreating(true)}
        />
      ) : (
        <div className="cc-table">
          <div className="cc-table-head">
            <span>Name</span>
            <span>Channels</span>
            <span>Budget</span>
            <span>Status</span>
            <span></span>
          </div>
          {filtered.map(c => (
            <div key={c.id} className="cc-table-row">
              <div>
                <div style={{ fontSize: 13, fontWeight: 500 }}>{c.name}</div>
                <div className="mono cc-row-sub">{c.goal || '—'}</div>
              </div>
              <div className="mono cc-row-sub">{(c.channels || []).join(' · ') || '—'}</div>
              <div className="mono cc-row-sub">${c.spent || 0}/{c.budget || 0}</div>
              <div><Chip status={c.status}/></div>
              <div style={{ display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
                <button className="cc-icon-btn sm" onClick={() => setEditing(c)}><I name="edit" size={13}/></button>
                <button className="cc-icon-btn sm" onClick={async () => {
                  if (confirm(`Delete "${c.name}"?`)) { await remove(c.id); ctx.showToast('Campaign deleted'); }
                }}><I name="trash" size={13}/></button>
              </div>
            </div>
          ))}
        </div>
      )}

      {creating && (
        <CampaignDialog
          onClose={() => setCreating(false)}
          onSave={async (data) => { await create(data); setCreating(false); ctx.showToast('Campaign created'); }}
        />
      )}
      {editing && (
        <CampaignDialog
          campaign={editing}
          onClose={() => setEditing(null)}
          onSave={async (data) => { await update(editing.id, data); setEditing(null); ctx.showToast('Campaign saved'); }}
        />
      )}
    </PageShell>
  );
}

function CampaignDialog({ campaign, onClose, onSave }) {
  const [name, setName] = useS(campaign?.name || '');
  const [goal, setGoal] = useS(campaign?.goal || '');
  const [budget, setBudget] = useS(campaign?.budget || 0);
  const [status, setStatus] = useS(campaign?.status || 'Drafting');
  const [channels, setChannels] = useS(campaign?.channels || []);
  const allChannels = ['Instagram', 'TikTok', 'Meta Ads', 'Email', 'Pinterest', 'Google Ads'];
  const toggle = (c) => setChannels(s => s.includes(c) ? s.filter(x => x !== c) : [...s, c]);
  return (
    <Modal title={campaign ? 'Edit campaign' : 'New campaign'} onClose={onClose}>
      <Field label="Name">
        <input value={name} onChange={e => setName(e.target.value)} className="cc-input" placeholder="Spring launch" autoFocus/>
      </Field>
      <Field label="Goal" hint="One sentence">
        <input value={goal} onChange={e => setGoal(e.target.value)} className="cc-input" placeholder="Sell out the new tote in 10 days"/>
      </Field>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Field label="Budget (USD)">
          <input type="number" value={budget} onChange={e => setBudget(Number(e.target.value) || 0)} className="cc-input"/>
        </Field>
        <Field label="Status">
          <select value={status} onChange={e => setStatus(e.target.value)} className="cc-input">
            <option>Drafting</option><option>Scheduled</option><option>Live</option><option>Ended</option>
          </select>
        </Field>
      </div>
      <Field label="Channels">
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {allChannels.map(c => (
            <button key={c} type="button" onClick={() => toggle(c)} className={'cc-pill' + (channels.includes(c) ? ' active' : '')}>{c}</button>
          ))}
        </div>
      </Field>
      <ModalActions
        onClose={onClose}
        onSave={() => name.trim() && onSave({ name, goal, budget, status, channels, spent: campaign?.spent || 0 })}
        canSave={!!name.trim()}
      />
    </Modal>
  );
}

// =====================================================================
// CALENDAR
// =====================================================================
function CalendarView({ ctx }) {
  const { items, create, remove } = useResource('events');
  const [cursor, setCursor] = useS(() => { const d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 1); });
  const [adding, setAdding] = useS(null); // { date }

  const monthLabel = cursor.toLocaleDateString(undefined, { month: 'long', year: 'numeric' });
  const startDay = (cursor.getDay() + 6) % 7; // Mon = 0
  const daysInMonth = new Date(cursor.getFullYear(), cursor.getMonth() + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < startDay; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);
  while (cells.length % 7) cells.push(null);

  const dateKey = (d) => `${cursor.getFullYear()}-${String(cursor.getMonth() + 1).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
  const eventsByDay = items.reduce((acc, e) => {
    if (!e.date) return acc;
    (acc[e.date] = acc[e.date] || []).push(e);
    return acc;
  }, {});
  const todayKey = new Date().toISOString().slice(0, 10);

  return (
    <PageShell>
      <PageHead
        kicker={`MARKETING CALENDAR · ${items.length} EVENTS`}
        title={monthLabel}
        action={
          <div style={{ display: 'flex', gap: 6 }}>
            <button className="cc-btn" onClick={() => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1))}>‹</button>
            <button className="cc-btn" onClick={() => { const d = new Date(); setCursor(new Date(d.getFullYear(), d.getMonth(), 1)); }}>Today</button>
            <button className="cc-btn" onClick={() => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1))}>›</button>
          </div>
        }
      />

      <div className="cc-cal">
        <div className="cc-cal-head">
          {['MON','TUE','WED','THU','FRI','SAT','SUN'].map(d => <div key={d}>{d}</div>)}
        </div>
        <div className="cc-cal-grid">
          {cells.map((d, i) => {
            if (d === null) return <div key={i} className="cc-cal-cell empty"/>;
            const k = dateKey(d);
            const isToday = k === todayKey;
            const events = eventsByDay[k] || [];
            return (
              <button key={i} className={'cc-cal-cell' + (isToday ? ' today' : '')} onClick={() => setAdding({ date: k })}>
                <div className="mono" style={{ fontSize: 10, opacity: isToday ? 1 : 0.7 }}>{String(d).padStart(2, '0')}</div>
                {events.slice(0, 3).map(e => (
                  <span key={e.id} className="cc-cal-evt" onClick={(ev) => { ev.stopPropagation(); if (confirm('Delete event?')) { remove(e.id); ctx.showToast('Event removed'); } }}>
                    {e.kind === 'launch' ? '◆' : e.kind === 'email' ? '✉' : e.kind === 'ad' ? '$' : '●'} {e.title}
                  </span>
                ))}
                {events.length > 3 && <span className="mono" style={{ fontSize: 9, opacity: 0.6 }}>+{events.length - 3} more</span>}
              </button>
            );
          })}
        </div>
      </div>

      {adding && (
        <Modal title="Add event" subtitle={new Date(adding.date + 'T00:00').toDateString()} onClose={() => setAdding(null)}>
          <NewEventForm
            date={adding.date}
            onClose={() => setAdding(null)}
            onSave={async (e) => { await create(e); setAdding(null); ctx.showToast('Event added'); }}
          />
        </Modal>
      )}
    </PageShell>
  );
}

function NewEventForm({ date, onClose, onSave }) {
  const [title, setTitle] = useS('');
  const [kind, setKind] = useS('post');
  return (
    <>
      <Field label="Title">
        <input value={title} onChange={e => setTitle(e.target.value)} className="cc-input" placeholder="IG Reel: behind the scenes" autoFocus/>
      </Field>
      <Field label="Type">
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {[
            ['post', 'Post'], ['email', 'Email'], ['ad', 'Ad'], ['launch', 'Launch'],
          ].map(([k, l]) => (
            <button key={k} type="button" onClick={() => setKind(k)} className={'cc-pill' + (kind === k ? ' active' : '')}>{l}</button>
          ))}
        </div>
      </Field>
      <ModalActions onClose={onClose} onSave={() => title.trim() && onSave({ title, kind, date })} canSave={!!title.trim()}/>
    </>
  );
}

// =====================================================================
// TODOS
// =====================================================================
function TodosView({ ctx }) {
  const { items, create, update, remove } = useResource('todos');
  const [text, setText] = useS('');
  const open = items.filter(t => !t.done);
  const done = items.filter(t => t.done);

  const add = async (e) => {
    e?.preventDefault();
    if (!text.trim()) return;
    await create({ text: text.trim(), done: false });
    setText('');
    ctx.showToast('Task added');
  };

  return (
    <PageShell>
      <PageHead kicker={`${open.length} OPEN · ${done.length} DONE`} title="To-do"/>
      <form onSubmit={add} className="cc-newtask">
        <I name="plus" size={14}/>
        <input value={text} onChange={e => setText(e.target.value)} placeholder="Add a task… (e.g. Schedule Friday Reel)" className="cc-input bare"/>
        <button type="submit" className="cc-btn primary sm">Add</button>
      </form>

      {items.length === 0 ? (
        <Empty title="No tasks yet" desc="Add one above. Caddie will also create tasks automatically when you launch a campaign."/>
      ) : (
        <div className="cc-list">
          {open.map(t => (
            <TodoRow key={t.id} todo={t}
              onToggle={() => update(t.id, { done: true })}
              onRemove={() => remove(t.id)}
            />
          ))}
          {done.length > 0 && (
            <div className="cc-section-label" style={{ padding: '20px 0 8px' }}>DONE</div>
          )}
          {done.map(t => (
            <TodoRow key={t.id} todo={t}
              onToggle={() => update(t.id, { done: false })}
              onRemove={() => remove(t.id)}
            />
          ))}
        </div>
      )}
    </PageShell>
  );
}

function TodoRow({ todo, onToggle, onRemove }) {
  return (
    <div className="cc-todo">
      <button className={'cc-check' + (todo.done ? ' on' : '')} onClick={onToggle}>
        {todo.done && <I name="check" size={11} stroke={2.6}/>}
      </button>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 500, textDecoration: todo.done ? 'line-through' : 'none', opacity: todo.done ? 0.45 : 1 }}>{todo.text}</div>
        {todo.meta && <div className="mono cc-row-sub">{todo.meta}</div>}
      </div>
      {onRemove && <button className="cc-icon-btn sm" onClick={onRemove}><I name="trash" size={12}/></button>}
    </div>
  );
}

// =====================================================================
// VIDEO TRACKER
// =====================================================================
function VideoView({ ctx }) {
  const { items, create, remove } = useResource('videos');
  const [url, setUrl] = useS('');
  const [title, setTitle] = useS('');

  const add = async (e) => {
    e.preventDefault();
    if (!title.trim()) return;
    await create({ title, url, views: 0, saves: 0, postedAt: Date.now() });
    setTitle(''); setUrl('');
    ctx.showToast('Video tracked');
  };

  return (
    <PageShell>
      <PageHead kicker={`${items.length} TRACKED`} title="Video Reach Tracker"/>
      <Card title="Add a video">
        <form onSubmit={add} style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <input value={title} onChange={e => setTitle(e.target.value)} placeholder="e.g. IG Reel — 5 things I keep restocking" className="cc-input"/>
          <input value={url} onChange={e => setUrl(e.target.value)} placeholder="https://… (optional)" className="cc-input"/>
          <button className="cc-btn primary" type="submit" style={{ alignSelf: 'flex-end' }}><I name="plus" size={13}/> Track video</button>
        </form>
      </Card>

      {items.length === 0 ? (
        <Empty title="No videos tracked yet" desc="Add a video above. Caddie will pull view + save data once your channel is connected."/>
      ) : (
        <div className="cc-list">
          {items.map(v => (
            <div key={v.id} className="cc-row">
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 500 }}>{v.title}</div>
                {v.url && <div className="mono cc-row-sub">{v.url}</div>}
              </div>
              <div className="mono cc-row-sub" style={{ marginRight: 16 }}>{v.views} views · {v.saves} saves</div>
              <button className="cc-icon-btn sm" onClick={() => { remove(v.id); ctx.showToast('Removed'); }}><I name="trash" size={12}/></button>
            </div>
          ))}
        </div>
      )}
    </PageShell>
  );
}

// =====================================================================
// COST ESTIMATOR (live calculator)
// =====================================================================
function CostView() {
  const [budget, setBudget] = useS(400);
  const [days, setDays] = useS(7);
  const [channel, setChannel] = useS('Meta Ads');
  // Rough demo CPMs — backend should return real estimates per channel.
  const cpms = { 'Meta Ads': 12, 'Instagram': 9, 'TikTok': 7, 'Google Ads': 18 };
  const cpm = cpms[channel];
  const reach = Math.round((budget / cpm) * 1000);
  const perDay = (budget / days).toFixed(2);

  return (
    <PageShell>
      <PageHead kicker="ESTIMATE A SPEND PLAN" title="Cost Estimator"/>
      <Card>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18, padding: 4 }} className="cc-stack-on-mobile">
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
            <Field label="Channel">
              <select value={channel} onChange={e => setChannel(e.target.value)} className="cc-input">
                {Object.keys(cpms).map(k => <option key={k}>{k}</option>)}
              </select>
            </Field>
            <Field label={`Budget — $${budget}`}>
              <input type="range" min="50" max="5000" step="10" value={budget} onChange={e => setBudget(Number(e.target.value))} style={{ width: '100%' }}/>
            </Field>
            <Field label={`Duration — ${days} days`}>
              <input type="range" min="1" max="30" value={days} onChange={e => setDays(Number(e.target.value))} style={{ width: '100%' }}/>
            </Field>
          </div>
          <div style={{ background: 'var(--paper-warm)', border: '1px solid var(--hair)', borderRadius: 10, padding: 24 }}>
            <div className="mono" style={{ color: 'var(--mute)' }}>ESTIMATED REACH</div>
            <div style={{ fontFamily: 'var(--serif)', fontSize: 56, lineHeight: 1, margin: '8px 0' }}>{reach.toLocaleString()}</div>
            <div className="mono" style={{ color: 'var(--mute)', fontSize: 11 }}>${perDay}/DAY · ${cpm} CPM</div>
            <hr style={{ border: 0, borderTop: '1px solid var(--hair)', margin: '20px 0' }}/>
            <p style={{ fontSize: 13, lineHeight: 1.55, margin: 0, color: 'var(--mute-2)' }}>
              Estimates use industry-average CPMs for {channel}. Connect the channel to get personalized estimates from your real account history.
            </p>
          </div>
        </div>
      </Card>
    </PageShell>
  );
}

// =====================================================================
// PRODUCTS
// =====================================================================
function ProductsView({ ctx }) {
  const { items, create, update, remove } = useResource('products');
  const [editing, setEditing] = useS(null);
  const [creating, setCreating] = useS(false);

  return (
    <PageShell>
      <PageHead
        kicker={`${items.length} IN CATALOG`}
        title="Products"
        action={<button className="cc-btn primary" onClick={() => setCreating(true)}><I name="plus" size={13}/> Add product</button>}
      />

      {items.length === 0 ? (
        <Empty
          title="No products yet"
          desc="Add what you sell. Caddie tunes copy, audience, and pricing to your real catalog."
          cta="Add product"
          onClick={() => setCreating(true)}
        />
      ) : (
        <div className="cc-grid-cards">
          {items.map(p => (
            <div key={p.id} className="cc-product-card">
              <div className="cc-product-thumb">{(p.name || '?')[0]}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{p.name}</div>
                <div className="mono cc-row-sub">{p.sku || '—'} · ${p.price || 0}</div>
                {p.stock != null && <div className="mono cc-row-sub" style={{ marginTop: 4 }}>{p.stock} in stock</div>}
              </div>
              <div style={{ display: 'flex', gap: 6 }}>
                <button className="cc-icon-btn sm" onClick={() => setEditing(p)}><I name="edit" size={12}/></button>
                <button className="cc-icon-btn sm" onClick={() => { if (confirm('Delete?')) { remove(p.id); ctx.showToast('Product removed'); } }}><I name="trash" size={12}/></button>
              </div>
            </div>
          ))}
        </div>
      )}

      {creating && (
        <ProductDialog onClose={() => setCreating(false)} onSave={async (d) => { await create(d); setCreating(false); ctx.showToast('Product added'); }}/>
      )}
      {editing && (
        <ProductDialog product={editing} onClose={() => setEditing(null)} onSave={async (d) => { await update(editing.id, d); setEditing(null); ctx.showToast('Product saved'); }}/>
      )}
    </PageShell>
  );
}

function ProductDialog({ product, onClose, onSave }) {
  const [name, setName] = useS(product?.name || '');
  const [sku, setSku] = useS(product?.sku || '');
  const [price, setPrice] = useS(product?.price || 0);
  const [stock, setStock] = useS(product?.stock || 0);
  return (
    <Modal title={product ? 'Edit product' : 'New product'} onClose={onClose}>
      <Field label="Name">
        <input value={name} onChange={e => setName(e.target.value)} className="cc-input" autoFocus/>
      </Field>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Field label="SKU">
          <input value={sku} onChange={e => setSku(e.target.value)} className="cc-input"/>
        </Field>
        <Field label="Price (USD)">
          <input type="number" value={price} onChange={e => setPrice(Number(e.target.value) || 0)} className="cc-input"/>
        </Field>
      </div>
      <Field label="Stock">
        <input type="number" value={stock} onChange={e => setStock(Number(e.target.value) || 0)} className="cc-input"/>
      </Field>
      <ModalActions onClose={onClose} onSave={() => name.trim() && onSave({ name, sku, price, stock })} canSave={!!name.trim()}/>
    </Modal>
  );
}

// =====================================================================
// INTEGRATIONS
// =====================================================================
function IntegrationsView({ ctx }) {
  const { items, create, update, remove } = useResource('integrations');
  const available = ['Instagram', 'Meta Ads', 'TikTok', 'Klaviyo', 'Mailchimp', 'Shopify', 'Google Ads', 'Pinterest'];
  const connectedNames = new Set(items.filter(i => i.status === 'Connected').map(i => i.name));
  const [connecting, setConnecting] = useS(null);

  return (
    <PageShell>
      <PageHead kicker="CONNECT YOUR CHANNELS" title="Integrations"/>

      {items.filter(i => i.status === 'Connected').length === 0 ? (
        <Card>
          <div style={{ padding: '8px 4px' }}>
            <div className="mono" style={{ color: 'var(--mute)' }}>NOT CONNECTED YET</div>
            <h3 className="cc-h3" style={{ margin: '6px 0 4px' }}>Connect a channel to get started.</h3>
            <p className="cc-p">Caddie can plan campaigns without integrations, but it gets dramatically smarter once it can see your audience and post for you.</p>
          </div>
        </Card>
      ) : (
        <Card title={`${items.filter(i => i.status === 'Connected').length} connected`}>
          <div className="cc-list">
            {items.filter(i => i.status === 'Connected').map(i => (
              <div key={i.id} className="cc-row">
                <div className="cc-int-icon">{i.name[0]}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13, fontWeight: 500 }}>{i.name}</div>
                  <div className="mono cc-row-sub">{i.account || 'Account'}</div>
                </div>
                <Chip status="Connected"/>
                <button className="cc-icon-btn sm" style={{ marginLeft: 8 }} onClick={async () => { if (confirm('Disconnect?')) { await remove(i.id); ctx.showToast('Disconnected'); } }}>
                  <I name="x" size={13}/>
                </button>
              </div>
            ))}
          </div>
        </Card>
      )}

      <Card title="Available">
        <div className="cc-grid-cards">
          {available.filter(n => !connectedNames.has(n)).map(name => (
            <div key={name} className="cc-product-card">
              <div className="cc-int-icon">{name[0]}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{name}</div>
                <div className="mono cc-row-sub">Not connected</div>
              </div>
              <button className="cc-btn sm" onClick={() => setConnecting(name)}>Connect →</button>
            </div>
          ))}
        </div>
      </Card>

      {connecting && (
        <Modal title={`Connect ${connecting}`} onClose={() => setConnecting(null)}>
          <p className="cc-p" style={{ marginTop: 0 }}>
            In production, this opens an OAuth flow. For demo, enter the account handle to connect.
          </p>
          <ConnectForm
            name={connecting}
            onClose={() => setConnecting(null)}
            onSave={async (acct) => {
              await create({ name: connecting, status: 'Connected', account: acct });
              setConnecting(null);
              ctx.showToast(`${connecting} connected`);
            }}
          />
        </Modal>
      )}
    </PageShell>
  );
}

function ConnectForm({ name, onClose, onSave }) {
  const [acct, setAcct] = useS('');
  return (
    <>
      <Field label="Account handle / ID">
        <input value={acct} onChange={e => setAcct(e.target.value)} className="cc-input" placeholder={`@yourhandle`} autoFocus/>
      </Field>
      <ModalActions onClose={onClose} onSave={() => acct.trim() && onSave(acct.trim())} canSave={!!acct.trim()} saveLabel="Connect"/>
    </>
  );
}

// =====================================================================
// AI COACH (narrower drawer)
// =====================================================================
function Coach({ view, onClose }) {
  const [msgs, setMsgs] = useS([]);
  const [draft, setDraft] = useS('');
  const [busy, setBusy] = useS(false);
  const endRef = useR(null);
  useE(() => { endRef.current?.scrollTo({ top: 99999, behavior: 'smooth' }); }, [msgs, busy]);

  const send = async (text) => {
    const q = (text || draft).trim();
    if (!q) return;
    setMsgs(m => [...m, { who: 'me', t: q }]);
    setDraft('');
    setBusy(true);
    try {
      const res = await api.ai(q, { view });
      setMsgs(m => [...m, { who: 'caddie', t: res.text }]);
    } finally { setBusy(false); }
  };

  return (
    <aside className="cc-coach">
      <div className="cc-coach-head">
        <div>
          <div className="mono" style={{ color: 'var(--mute)', fontSize: 10 }}>AI COACH</div>
          <div style={{ fontFamily: 'var(--serif)', fontSize: 16, marginTop: 1 }}>Caddie</div>
        </div>
        <button className="cc-icon-btn sm" onClick={onClose}><I name="x" size={13}/></button>
      </div>

      <div ref={endRef} className="cc-coach-msgs">
        {msgs.length === 0 && (
          <div className="cc-coach-empty">
            <div style={{ fontSize: 13, color: 'var(--mute-2)', marginBottom: 14 }}>
              Ask Caddie about your campaigns, copy, or strategy.
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {['Plan my next campaign', 'Draft a caption', 'Best time to post?'].map(s => (
                <button key={s} onClick={() => send(s)} className="cc-suggest">{s}</button>
              ))}
            </div>
          </div>
        )}
        {msgs.map((m, i) => (
          <div key={i} className={'cc-bubble ' + m.who}>{m.t}</div>
        ))}
        {busy && <div className="cc-bubble caddie typing"><span/><span/><span/></div>}
      </div>

      <form className="cc-coach-input" onSubmit={(e) => { e.preventDefault(); send(); }}>
        <input value={draft} onChange={e => setDraft(e.target.value)} placeholder="Ask Caddie…" className="cc-input bare"/>
        <button type="submit" className="cc-icon-btn sm filled"><I name="send" size={13}/></button>
      </form>
    </aside>
  );
}

// =====================================================================
// COMMAND PALETTE
// =====================================================================
function CommandPalette({ close, setView }) {
  const [q, setQ] = useS('');
  const navItems = APP_NAV.map(n => ({ kind: 'view', id: n.id, label: 'Go to ' + n.label, icon: n.icon }));
  const actions = [
    { kind: 'action', id: 'new-campaign', label: 'New campaign', icon: 'plus', go: () => setView('campaigns') },
    { kind: 'action', id: 'new-product',  label: 'Add product',  icon: 'plus', go: () => setView('products') },
    { kind: 'action', id: 'new-event',    label: 'Schedule event', icon: 'cal', go: () => setView('calendar') },
  ];
  const all = [...navItems, ...actions];
  const filtered = q.trim() ? all.filter(i => i.label.toLowerCase().includes(q.toLowerCase())) : all;
  const [sel, setSel] = useS(0);
  useE(() => { setSel(0); }, [q]);
  const onKey = (e) => {
    if (e.key === 'ArrowDown') { e.preventDefault(); setSel(s => Math.min(filtered.length - 1, s + 1)); }
    if (e.key === 'ArrowUp')   { e.preventDefault(); setSel(s => Math.max(0, s - 1)); }
    if (e.key === 'Enter')     { e.preventDefault(); pick(filtered[sel]); }
  };
  const pick = (item) => {
    if (!item) return;
    if (item.kind === 'view') setView(item.id);
    else if (item.kind === 'action') { item.go(); close(); }
  };

  return (
    <div className="cc-palette-bg" onClick={close}>
      <div className="cc-palette" onClick={e => e.stopPropagation()}>
        <div className="cc-palette-input">
          <I name="search" size={14}/>
          <input autoFocus value={q} onChange={e => setQ(e.target.value)} onKeyDown={onKey} placeholder="Search or jump to…" className="cc-input bare"/>
          <span className="cc-kbd">ESC</span>
        </div>
        <div className="cc-palette-list">
          {filtered.length === 0 && <div style={{ padding: 18, fontSize: 13, color: 'var(--mute-2)' }}>No matches.</div>}
          {filtered.map((it, i) => (
            <button key={it.id} className={'cc-palette-item' + (i === sel ? ' active' : '')} onMouseEnter={() => setSel(i)} onClick={() => pick(it)}>
              <I name={it.icon} size={13}/>
              <span style={{ flex: 1, textAlign: 'left' }}>{it.label}</span>
              <span className="mono" style={{ fontSize: 9, opacity: 0.5 }}>{it.kind === 'view' ? 'GO' : 'DO'}</span>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

// =====================================================================
// SHARED PRIMITIVES
// =====================================================================
function PageShell({ children }) {
  return <div className="cc-page">{children}</div>;
}
function PageHead({ kicker, title, action }) {
  return (
    <div className="cc-page-head">
      <div>
        <div className="mono" style={{ color: 'var(--mute)' }}>{kicker}</div>
        <h2 className="cc-h2">{title}</h2>
      </div>
      {action}
    </div>
  );
}
function Card({ title, action, children }) {
  return (
    <div className="cc-card">
      {(title || action) && (
        <div className="cc-card-head">
          {title && <div className="mono" style={{ color: 'var(--mute)' }}>{title.toUpperCase()}</div>}
          {action}
        </div>
      )}
      <div className="cc-card-body">{children}</div>
    </div>
  );
}
function KPI({ label, v, sub, last }) {
  return (
    <div className="cc-kpi" style={{ borderRight: last ? 'none' : '1px solid var(--hair)' }}>
      <div className="mono" style={{ color: 'var(--mute)' }}>{label}</div>
      <div style={{ fontFamily: 'var(--serif)', fontSize: 36, lineHeight: 1, margin: '6px 0 4px' }}>{v}</div>
      <div className="mono" style={{ color: 'var(--mute)', fontSize: 10 }}>{sub}</div>
    </div>
  );
}
function Chip({ status }) {
  const live = status === 'Live' || status === 'Connected';
  return (
    <span className={'cc-chip' + (live ? ' live' : '')}>
      {live && <span className="cc-chip-dot"/>} {(status || '').toUpperCase()}
    </span>
  );
}
function Empty({ title, desc, cta, onClick }) {
  return (
    <div className="cc-empty">
      <div className="cc-empty-frame">
        <I name="spark" size={20}/>
      </div>
      <div className="cc-h3" style={{ margin: '0 0 6px' }}>{title}</div>
      {desc && <p className="cc-p" style={{ maxWidth: 420, margin: '0 auto 16px' }}>{desc}</p>}
      {cta && <button className="cc-btn primary" onClick={onClick}>{cta}</button>}
    </div>
  );
}
function Modal({ title, subtitle, onClose, children }) {
  useE(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [onClose]);
  return (
    <div className="cc-modal-bg" onClick={onClose}>
      <div className="cc-modal" onClick={e => e.stopPropagation()}>
        <div className="cc-modal-head">
          <div>
            <div style={{ fontFamily: 'var(--serif)', fontSize: 22 }}>{title}</div>
            {subtitle && <div className="mono" style={{ color: 'var(--mute)', marginTop: 2 }}>{subtitle.toUpperCase()}</div>}
          </div>
          <button className="cc-icon-btn sm" onClick={onClose}><I name="x" size={14}/></button>
        </div>
        <div className="cc-modal-body">{children}</div>
      </div>
    </div>
  );
}
function ModalActions({ onClose, onSave, canSave, saveLabel = 'Save' }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 18, paddingTop: 18, borderTop: '1px solid var(--hair)' }}>
      <button className="cc-btn" onClick={onClose}>Cancel</button>
      <button className="cc-btn primary" onClick={onSave} disabled={!canSave} style={{ opacity: canSave ? 1 : 0.4, cursor: canSave ? 'pointer' : 'not-allowed' }}>{saveLabel}</button>
    </div>
  );
}
function Field({ label, hint, children }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 12 }}>
      <span style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
        <span className="mono" style={{ fontSize: 11 }}>{label.toUpperCase()}</span>
        {hint && <span className="mono" style={{ color: 'var(--mute)', fontSize: 10 }}>{hint}</span>}
      </span>
      {children}
    </label>
  );
}

// =====================================================================
// STYLES
// =====================================================================
function CCStyles() {
  return <style>{`
.cc-app { min-height: 100vh; display: flex; flex-direction: column; background: var(--paper); color: var(--ink); }
.cc-topbar { display: flex; align-items: center; gap: 12px; padding: 8px 16px; border-bottom: 1px solid var(--hair); background: var(--paper-warm); position: sticky; top: 0; z-index: 30; }
.cc-topbar-left { display: flex; align-items: center; gap: 10px; }
.cc-topbar-right { display: flex; align-items: center; gap: 6px; }
.cc-tag { font-family: var(--mono); font-size: 10px; padding: 3px 7px; border: 1px solid var(--ink); border-radius: 3px; }
.cc-logo-btn { display: flex; align-items: center; gap: 8px; background: transparent; border: none; padding: 4px 8px; border-radius: 6px; cursor: pointer; color: var(--ink); font-family: inherit; }
.cc-logo-btn:hover { background: rgba(10,10,10,0.05); }
.cc-search { flex: 1; max-width: 460px; margin: 0 auto; display: flex; align-items: center; gap: 10px; padding: 7px 14px; border: 1px solid var(--hair-strong); border-radius: 999px; background: var(--paper); cursor: text; font-size: 13px; font-family: inherit; color: var(--ink); }
.cc-search:hover { border-color: var(--ink); }
.cc-kbd { font-family: var(--mono); font-size: 9px; color: var(--mute); padding: 2px 5px; border: 1px solid var(--hair-strong); border-radius: 3px; }
.cc-icon-btn { width: 32px; height: 32px; border-radius: 999px; border: 1px solid var(--hair-strong); background: var(--paper); display: grid; place-items: center; cursor: pointer; color: var(--ink); padding: 0; font-family: inherit; position: relative; }
.cc-icon-btn:hover { border-color: var(--ink); }
.cc-icon-btn.sm { width: 26px; height: 26px; }
.cc-icon-btn.filled { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.cc-dot { position: absolute; top: 6px; right: 6px; width: 5px; height: 5px; border-radius: 999px; background: var(--ink); }
.cc-account-chip { display: flex; align-items: center; gap: 8px; padding: 4px 10px 4px 4px; border: 1px solid var(--hair-strong); border-radius: 999px; background: var(--paper); cursor: pointer; font-family: inherit; color: var(--ink); }
.cc-account-chip:hover { border-color: var(--ink); }
.cc-avatar { width: 24px; height: 24px; border-radius: 999px; background: var(--ink); color: var(--paper); display: grid; place-items: center; font-size: 9px; font-family: var(--mono); }

.cc-menu { position: absolute; top: calc(100% + 6px); min-width: 220px; background: var(--paper); border: 1px solid var(--ink); border-radius: 10px; box-shadow: 0 12px 30px -10px rgba(0,0,0,0.18); padding: 6px; z-index: 50; }
.cc-menu-head { padding: 10px 12px 8px; border-bottom: 1px solid var(--hair); margin-bottom: 4px; }
.cc-menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px; border: none; background: transparent; cursor: pointer; border-radius: 6px; font-family: inherit; font-size: 13px; color: var(--ink); text-align: left; }
.cc-menu-item:hover { background: rgba(10,10,10,0.05); }
.cc-menu-sep { height: 1px; background: var(--hair); margin: 4px 0; }

.cc-body { display: grid; flex: 1; min-height: 0; transition: grid-template-columns 0.2s ease; }
.cc-sidenav { border-right: 1px solid var(--hair); padding: 16px 12px; flex-direction: column; gap: 1px; overflow-y: auto; background: var(--paper); }
.cc-section-label { color: var(--mute); padding: 6px 10px; font-size: 10px; }
.cc-navitem { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; font-size: 13px; background: transparent; color: var(--ink); border: none; cursor: pointer; text-align: left; font-family: inherit; }
.cc-navitem:hover { background: rgba(10,10,10,0.05); }
.cc-navitem.active { background: var(--ink); color: var(--paper); font-weight: 500; }
.cc-navitem.active:hover { background: var(--ink); }
.cc-navitem .cc-badge { margin-left: auto; }
.cc-badge { font-family: var(--mono); font-size: 9px; padding: 2px 6px; border-radius: 3px; background: var(--ink); color: var(--paper); }
.cc-navitem.active .cc-badge { background: rgba(255,255,255,0.18); }
.cc-spacer { flex: 1; min-height: 16px; }

.cc-main { overflow-y: auto; min-width: 0; }
.cc-page { padding: 28px 32px; display: flex; flex-direction: column; gap: 20px; max-width: 1280px; }
.cc-page-head { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 12px; }
.cc-h1 { font-family: var(--serif); font-size: 34px; font-weight: 400; letter-spacing: -0.015em; margin: 4px 0 0; }
.cc-h2 { font-family: var(--serif); font-size: 30px; font-weight: 400; letter-spacing: -0.015em; margin: 4px 0 0; }
.cc-h3 { font-family: var(--serif); font-size: 22px; font-weight: 400; letter-spacing: -0.01em; margin: 0; }
.cc-p { font-size: 14px; line-height: 1.6; color: var(--mute-2); margin: 8px 0 0; }
.cc-link { background: none; border: none; cursor: pointer; color: var(--ink); font-family: var(--mono); font-size: 11px; padding: 0; }

.cc-btn { display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px; border: 1px solid var(--ink); background: transparent; color: var(--ink); border-radius: 999px; font-size: 12px; font-family: inherit; cursor: pointer; }
.cc-btn:hover { background: rgba(10,10,10,0.05); }
.cc-btn.primary { background: var(--ink); color: var(--paper); }
.cc-btn.primary:hover { background: rgba(10,10,10,0.85); }
.cc-btn.sm { padding: 6px 11px; font-size: 11px; }
.cc-btn[disabled] { opacity: 0.5; cursor: not-allowed; }

.cc-kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); border: 1px solid var(--hair); border-radius: 10px; overflow: hidden; }
.cc-kpi { padding: 16px 18px; }

.cc-card { border: 1px solid var(--hair); border-radius: 10px; overflow: hidden; background: var(--paper); }
.cc-card-head { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--hair); }
.cc-card-body { padding: 4px 0; }
.cc-row { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--hair); }
.cc-row:first-child { border-top: none; }
.cc-row-sub { font-size: 11px; color: var(--mute); margin-top: 3px; }

.cc-table { display: grid; border: 1px solid var(--hair); border-radius: 10px; overflow: hidden; }
.cc-table-head, .cc-table-row { display: grid; grid-template-columns: 2fr 1.5fr 1fr 0.8fr 0.6fr; align-items: center; gap: 12px; padding: 10px 16px; }
.cc-table-head { background: var(--paper-warm); border-bottom: 1px solid var(--hair); font-family: var(--mono); font-size: 10px; color: var(--mute); }
.cc-table-row { border-top: 1px solid var(--hair); font-size: 13px; }
.cc-table-row:first-of-type { border-top: none; }

.cc-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--hair); margin-bottom: 4px; }
.cc-tab { background: transparent; border: none; padding: 8px 14px; font-size: 12px; font-family: var(--mono); color: var(--mute); cursor: pointer; border-radius: 6px 6px 0 0; }
.cc-tab.active { color: var(--ink); border-bottom: 2px solid var(--ink); margin-bottom: -1px; }
.cc-tab-count { font-size: 9px; padding: 1px 5px; background: var(--hair); color: var(--ink); border-radius: 3px; margin-left: 4px; }

.cc-input { width: 100%; padding: 10px 14px; border: 1px solid var(--hair-strong); border-radius: 8px; background: var(--paper); font-size: 13px; font-family: inherit; outline: none; color: var(--ink); }
.cc-input:focus { border-color: var(--ink); }
.cc-input.bare { border: none; background: transparent; padding: 8px 0; }
.cc-pill { padding: 6px 12px; border-radius: 999px; border: 1px solid var(--hair-strong); background: transparent; font-family: var(--mono); font-size: 10px; cursor: pointer; color: var(--ink); }
.cc-pill.active { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.cc-cal { border: 1px solid var(--hair); border-radius: 10px; overflow: hidden; }
.cc-cal-head { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--hair); font-family: var(--mono); font-size: 10px; color: var(--mute); }
.cc-cal-head > div { padding: 10px 12px; border-right: 1px solid var(--hair); }
.cc-cal-head > div:last-child { border-right: none; }
.cc-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.cc-cal-cell { min-height: 92px; border-right: 1px solid var(--hair); border-top: 1px solid var(--hair); padding: 6px 8px; background: var(--paper); cursor: pointer; display: flex; flex-direction: column; gap: 4px; align-items: stretch; text-align: left; font-family: inherit; color: var(--ink); }
.cc-cal-cell:nth-child(7n) { border-right: none; }
.cc-cal-cell.empty { background: rgba(0,0,0,0.02); cursor: default; }
.cc-cal-cell.today { background: var(--ink); color: var(--paper); }
.cc-cal-cell:hover:not(.empty) { background: rgba(10,10,10,0.04); }
.cc-cal-cell.today:hover { background: var(--ink); }
.cc-cal-evt { font-family: var(--mono); font-size: 9px; padding: 2px 5px; border: 1px solid currentColor; border-radius: 3px; cursor: pointer; }
.cc-cal-cell.today .cc-cal-evt { color: var(--paper); }

.cc-newtask { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border: 1px solid var(--hair-strong); border-radius: 10px; background: var(--paper); }
.cc-list { display: flex; flex-direction: column; }
.cc-todo { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--hair); }
.cc-todo:last-child { border-bottom: none; }
.cc-check { width: 18px; height: 18px; border-radius: 4px; border: 1px solid var(--hair-strong); background: transparent; cursor: pointer; display: grid; place-items: center; padding: 0; flex-shrink: 0; color: var(--paper); }
.cc-check.on { background: var(--ink); border-color: var(--ink); }

.cc-step { display: flex; align-items: center; gap: 16px; padding: 18px 20px; border: none; background: var(--paper); cursor: pointer; border-bottom: 1px solid var(--hair); font-family: inherit; color: var(--ink); }
.cc-step:hover { background: rgba(10,10,10,0.03); }
.cc-step:last-child { border-bottom: none; }
.cc-step-num { width: 32px; height: 32px; border: 1px solid var(--ink); border-radius: 999px; display: grid; place-items: center; font-family: var(--mono); font-size: 11px; flex-shrink: 0; }

.cc-grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.cc-product-card { display: flex; gap: 12px; align-items: center; padding: 14px; border: 1px solid var(--hair); border-radius: 10px; background: var(--paper); }
.cc-product-thumb { width: 44px; height: 44px; border-radius: 8px; background: var(--paper-warm); border: 1px solid var(--hair); display: grid; place-items: center; font-family: var(--serif); font-size: 18px; color: var(--mute-2); flex-shrink: 0; }
.cc-int-icon { width: 32px; height: 32px; border-radius: 6px; background: var(--ink); color: var(--paper); display: grid; place-items: center; font-family: var(--mono); font-size: 13px; flex-shrink: 0; }

.cc-chip { display: inline-flex; align-items: center; gap: 5px; font-family: var(--mono); font-size: 9px; padding: 3px 7px; border: 1px solid var(--ink); border-radius: 3px; }
.cc-chip.live { background: var(--ink); color: var(--paper); }
.cc-chip-dot { width: 5px; height: 5px; border-radius: 999px; background: var(--paper); }

.cc-empty { padding: 60px 20px; text-align: center; border: 1px dashed var(--hair-strong); border-radius: 12px; background: var(--paper-warm); }
.cc-empty-frame { width: 48px; height: 48px; border-radius: 999px; background: var(--paper); border: 1px solid var(--hair); display: grid; place-items: center; margin: 0 auto 14px; color: var(--mute-2); }

.cc-modal-bg { position: fixed; inset: 0; background: rgba(10,10,10,0.32); z-index: 60; display: grid; place-items: center; padding: 16px; backdrop-filter: blur(2px); }
.cc-modal { background: var(--paper); border: 1px solid var(--ink); border-radius: 14px; width: 100%; max-width: 480px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column; }
.cc-modal-head { display: flex; justify-content: space-between; align-items: flex-start; padding: 20px 22px; border-bottom: 1px solid var(--hair); }
.cc-modal-body { padding: 20px 22px; overflow-y: auto; }

.cc-coach { display: flex; flex-direction: column; border-left: 1px solid var(--hair); background: var(--paper-warm); min-width: 0; }
.cc-coach-head { display: flex; justify-content: space-between; align-items: flex-start; padding: 14px 16px; border-bottom: 1px solid var(--hair); background: var(--paper); }
.cc-coach-msgs { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.cc-coach-empty { padding: 24px 8px; }
.cc-suggest { background: var(--paper); border: 1px solid var(--hair-strong); border-radius: 8px; padding: 9px 12px; font-size: 12px; cursor: pointer; text-align: left; font-family: inherit; color: var(--ink); }
.cc-suggest:hover { border-color: var(--ink); }
.cc-bubble { max-width: 90%; padding: 9px 12px; border-radius: 12px; font-size: 13px; line-height: 1.45; }
.cc-bubble.me { align-self: flex-end; background: var(--ink); color: var(--paper); }
.cc-bubble.caddie { align-self: flex-start; background: var(--paper); color: var(--ink); border: 1px solid var(--hair); }
.cc-bubble.typing { display: inline-flex; gap: 4px; align-items: center; padding: 12px; }
.cc-bubble.typing span { width: 5px; height: 5px; border-radius: 999px; background: var(--ink); opacity: 0.4; animation: ccPulse 1.2s infinite ease-in-out; }
.cc-bubble.typing span:nth-child(2) { animation-delay: 0.15s; }
.cc-bubble.typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes ccPulse { 0%, 100% { opacity: 0.25; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-2px); } }
.cc-coach-input { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--hair); background: var(--paper); }

.cc-palette-bg { position: fixed; inset: 0; background: rgba(10,10,10,0.32); z-index: 70; padding-top: 14vh; display: flex; justify-content: center; backdrop-filter: blur(2px); }
.cc-palette { width: 100%; max-width: 540px; height: fit-content; max-height: 60vh; background: var(--paper); border: 1px solid var(--ink); border-radius: 14px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 30px 60px -20px rgba(0,0,0,0.35); }
.cc-palette-input { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--hair); }
.cc-palette-list { overflow-y: auto; padding: 6px; }
.cc-palette-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px; border: none; background: transparent; cursor: pointer; border-radius: 6px; font-family: inherit; font-size: 13px; color: var(--ink); }
.cc-palette-item.active { background: var(--ink); color: var(--paper); }

.cc-toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); background: var(--ink); color: var(--paper); padding: 10px 18px; border-radius: 999px; font-size: 13px; z-index: 80; box-shadow: 0 8px 24px -6px rgba(0,0,0,0.3); animation: ccFadeUp 0.2s ease both; }
@keyframes ccFadeUp { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }

@media (max-width: 900px) {
  .cc-body { grid-template-columns: 1fr !important; }
  .cc-sidenav, .cc-coach { display: none !important; }
  .cc-stack-on-mobile { grid-template-columns: 1fr !important; }
  .cc-kpi-row { grid-template-columns: repeat(2, 1fr); }
  .cc-kpi-row .cc-kpi { border-right: none; border-bottom: 1px solid var(--hair); }
  .cc-table-head, .cc-table-row { grid-template-columns: 1.5fr 0.8fr 0.6fr; }
  .cc-table-head > :nth-child(2), .cc-table-row > :nth-child(2),
  .cc-table-head > :nth-child(3), .cc-table-row > :nth-child(3) { display: none; }
  .cc-search { display: none; }
  .cc-page { padding: 20px 16px; }
}
  `}</style>;
}

window.RealApp = RealApp;
