// Home, Results, Services, Budget, Listings, Reviews, Campaigns, Invoice, Settings pages
// Plus sidebar, topbar, chat panel, notifications, tweaks, HQ rollup

const { useState, useEffect, useRef } = React;

// ====================================================================
// SCOPE MODEL, single source of truth for location vs. account scope.
// Most pages are LOCATION-scoped: they're filtered to the one location
// selected in the sidebar switcher. A few pages are ACCOUNT-scoped: they
// inherently span every location under the account (e.g. consolidated
// billing across all 4 locations) and ignore the location selection.
// The chrome, sidebar location switcher + breadcrumb, reads from this so
// the path always matches what the page actually shows.
// (Settings stays location-scoped, it configures the selected store.)
// ====================================================================
const ACCOUNT_SCOPED_PAGES = new Set(['invoice']);
function isAccountScoped(page, persona) {
  return persona !== 'hq' && ACCOUNT_SCOPED_PAGES.has(page);
}
window.isAccountScoped = isAccountScoped;

// ====================================================================
// CHROME PICKERS, client (sidebar) + location & date range (topbar)
// ====================================================================
const PinIcon = (
  <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>
  </svg>
);
const CalIcon = (
  <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <rect x="3" y="4" width="18" height="18" rx="3"/><path d="M16 2v4M8 2v4M3 10h18"/>
  </svg>
);

function useClickOutside(open, setOpen) {
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, [open]);
  return ref;
}

const initialsOf = (name) => (name || '').split(/\s+/).filter(Boolean).map(w => w[0]).join('').slice(0, 2).toUpperCase();

// Client picker, sidebar, top-left. FreshNest is the only client in this demo.
function ClientPicker({ account = {}, persona }) {
  const active = 'FreshNest';
  // Single-client demo: static identity, no dropdown.
  return (
    <div className="client-sw-wrap">
      <div className="client-sw" style={{ cursor: 'default' }}>
        <div className="client-sw-av">FN</div>
        <div className="client-sw-txt">
          <div className="client-sw-lbl">Client</div>
          <div className="client-sw-name">{active}</div>
        </div>
      </div>
    </div>
  );
}
window.ClientPicker = ClientPicker;

// ====================================================================
// VIEW-AS PICKER, sidebar, under the client picker. Corporate users can
// step into any local user's view from anywhere; local users never see it.
// Neutral when viewing your own corporate account; gold when viewing as
// someone else (paired with the top banner).
// ====================================================================
const CORP_SELF = { name: 'Maya Chen', initials: 'MC', role: 'VP Marketing', badge: 'Corporate' };

function ViewAsPicker({ persona, mirroredUser, onMirror = () => {}, onExitMirror = () => {}, onNav = () => {} }) {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState('');
  const ref = useClickOutside(open, setOpen);

  // Local users cannot view as anyone, only render for corporate, or while
  // a corporate user is already viewing as a local user (to switch / exit).
  if (persona !== 'hq' && !mirroredUser) return null;

  const users = (window.FRESHNEST_LOCAL_USERS || []).filter(u => u.enabled && u.locationCount > 0);
  const ql = q.trim().toLowerCase();
  const results = ql
    ? users.filter(u => u.name.toLowerCase().includes(ql) || u.email.toLowerCase().includes(ql) || u.locations.toLowerCase().includes(ql))
    : users.slice(0, 6);

  const viewing = !!mirroredUser;
  const cur = viewing ? mirroredUser : CORP_SELF;

  const badgeStyle = (corp) => ({
    display: 'inline-block', padding: '1px 7px', borderRadius: 999,
    fontSize: 9, fontWeight: 800, letterSpacing: '0.07em', textTransform: 'uppercase',
    background: corp ? 'rgba(0,29,85,0.08)' : 'rgba(13,138,138,0.12)',
    color: corp ? 'var(--la-brand-secondary-700,#001e40)' : '#0a6666',
  });

  return (
    <div className="client-sw-wrap" ref={ref} style={{ marginTop: 6 }}>
      <div className={`client-sw ${open ? 'open' : ''}`} onClick={() => setOpen(o => !o)}
           style={viewing ? {
             background: 'var(--la-status-warning-subtle,#fcf6e1)',
             boxShadow: 'inset 0 0 0 1.5px rgba(237,169,26,0.45)',
           } : {}}>
        <div className="client-sw-av" style={viewing ? { background: 'rgba(237,169,26,0.22)', color: '#886805' } : {}}>
          {cur.initials}
        </div>
        <div className="client-sw-txt">
          <div className="client-sw-lbl" style={viewing ? { color: '#917200', fontWeight: 800 } : {}}>Viewing as</div>
          <div className="client-sw-name" style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>
            <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{cur.name}</span>
            <span style={badgeStyle(!viewing)}>{viewing ? 'Local' : 'Corporate'}</span>
          </div>
        </div>
        <span className="client-sw-chev">⌄</span>
      </div>

      {open && (
        <div className="client-sw-menu" style={{ maxHeight: 380, overflowY: 'auto' }}>
          {/* Your own corporate view */}
          <div className={`client-sw-item ${!viewing ? 'on' : ''}`}
               onClick={() => { setOpen(false); setQ(''); if (viewing) onExitMirror(); }}>
            <div className="client-sw-item-av">{CORP_SELF.initials}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="client-sw-item-name">{CORP_SELF.name} <span style={badgeStyle(true)}>Corporate</span></div>
              <div className="client-sw-item-sub">Your corporate view · {CORP_SELF.role}</div>
            </div>
            {!viewing && <span style={{ color: 'var(--terra-2)', fontSize: 13, fontWeight: 700 }}>✓</span>}
          </div>

          <div style={{ padding: '8px 10px 4px' }}>
            <div style={{ fontSize: 9.5, fontWeight: 800, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--la-text-muted)', margin: '0 2px 6px' }}>View as a local user</div>
            <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search local users…"
                   onClick={e => e.stopPropagation()}
                   style={{ width: '100%', boxSizing: 'border-box', padding: '7px 10px', fontSize: 12, fontFamily: 'var(--la-font-ui)', border: '1px solid var(--la-border-default,#e3e3e8)', borderRadius: 9, outline: 'none', background: 'var(--la-surface,#f5f5f7)' }}/>
          </div>

          {results.map(u => (
            <div key={u.id} className={`client-sw-item ${viewing && mirroredUser.id === u.id ? 'on' : ''}`}
                 onClick={() => { setOpen(false); setQ(''); if (!viewing || mirroredUser.id !== u.id) onMirror(u); }}>
              <div className="client-sw-item-av" style={{ background: 'rgba(13,138,138,0.10)', color: '#0a6666' }}>{u.initials}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="client-sw-item-name">{u.name}</div>
                <div className="client-sw-item-sub">{u.locations} · {u.locationCount} location{u.locationCount !== 1 ? 's' : ''}</div>
              </div>
              {viewing && mirroredUser.id === u.id && <span style={{ color: 'var(--terra-2)', fontSize: 13, fontWeight: 700 }}>✓</span>}
            </div>
          ))}
          {results.length === 0 && (
            <div style={{ padding: '10px 14px', fontSize: 12, color: 'var(--la-text-muted)' }}>No local users match “{q}”.</div>
          )}

          <div onClick={() => { setOpen(false); setQ(''); if (viewing) onExitMirror(); onNav('local-users'); }}
               style={{ padding: '9px 14px', fontSize: 12, fontWeight: 700, color: 'var(--la-brand-primary-600,#b35f18)', cursor: 'pointer', borderTop: '1px solid var(--la-border-subtle,#ececf0)' }}>
            Open the full Local users directory →
          </div>
        </div>
      )}
    </div>
  );
}
window.ViewAsPicker = ViewAsPicker;

// Location picker, topbar. Scopes the view to one location or the whole account.
function TopbarLocationPicker({ accountLocations = [], selectedLoc = 'all', onSelectLoc = () => {}, persona, isMulti = false }) {
  const [open, setOpen] = useState(false);
  const ref = useClickOutside(open, setOpen);
  // Single-location accounts: nothing to switch, show the one store, static.
  if (persona !== 'hq' && !isMulti) {
    const only = accountLocations[0];
    return (
      <div className="tb-picker tb-picker--static">
        <span className="tb-picker-ic">{PinIcon}</span>
        <span className="tb-picker-txt">
          <span className="tb-picker-lbl">Location</span>
          <span className="tb-picker-val">{(only && only.name) || 'Your location'}</span>
        </span>
      </div>
    );
  }
  const cur = selectedLoc === 'all' ? null : accountLocations.find(l => String(l.id) === String(selectedLoc));
  return (
    <div className="tb-picker-wrap" ref={ref}>
      <div className={`tb-picker ${open ? 'open' : ''}`} onClick={() => setOpen(o => !o)}>
        <span className="tb-picker-ic">{PinIcon}</span>
        <span className="tb-picker-txt">
          <span className="tb-picker-lbl">Location</span>
          <span className="tb-picker-val">{cur ? cur.name : 'All locations'}</span>
        </span>
        <span className="tb-picker-chev">⌄</span>
      </div>
      {open && (
        <div className="tb-picker-menu">
          <div className={`tb-pick-item ${selectedLoc === 'all' ? 'on' : ''}`} onClick={() => { onSelectLoc('all'); setOpen(false); }}>
            <span className="tb-pick-item-name">All locations</span>
            <span className="tb-pick-item-sub">{persona === 'hq' ? 'Entire portfolio' : `${accountLocations.length} locations · rollup`}</span>
          </div>
          {accountLocations.map(l => (
            <div key={l.id} className={`tb-pick-item ${String(selectedLoc) === String(l.id) ? 'on' : ''}`} onClick={() => { onSelectLoc(l.id); setOpen(false); }}>
              <span className="tb-pick-item-name">{l.name}</span>
              <span className="tb-pick-item-sub">{l.city}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
window.TopbarLocationPicker = TopbarLocationPicker;

// Date range picker, topbar. Sets the reporting window across dashboards.
const TB_DATE_PRESETS = ['Last 7 days', 'Last 30 days', 'Last 90 days', 'This month', 'Last month', 'This quarter', 'Year to date'];
function TopbarDatePicker() {
  const [open, setOpen] = useState(false);
  const [val, setVal] = useState(() => localStorage.getItem('la_tb_range') || 'Last 30 days');
  const ref = useClickOutside(open, setOpen);
  return (
    <div className="tb-picker-wrap" ref={ref}>
      <div className={`tb-picker ${open ? 'open' : ''}`} onClick={() => setOpen(o => !o)}>
        <span className="tb-picker-ic">{CalIcon}</span>
        <span className="tb-picker-txt">
          <span className="tb-picker-lbl">Dates</span>
          <span className="tb-picker-val">{val}</span>
        </span>
        <span className="tb-picker-chev">⌄</span>
      </div>
      {open && (
        <div className="tb-picker-menu">
          {TB_DATE_PRESETS.map(p => (
            <div key={p} className={`tb-pick-item ${val === p ? 'on' : ''}`}
                 onClick={() => { setVal(p); localStorage.setItem('la_tb_range', p); setOpen(false); window.toast && window.toast('Date range updated', `Showing ${p.toLowerCase()} across your dashboards.`, 'info'); }}>
              <span className="tb-pick-item-name">{p}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
window.TopbarDatePicker = TopbarDatePicker;

// ====================================================================
// SIDEBAR
// ====================================================================
function Sidebar({ currentPage, onNav, persona, location, locations, onLocChange, account = {}, accountLocations = [], isMulti = false, selectedLoc = 'all', onSelectLoc = () => {}, mirroredUser = null, onMirror = () => {}, onExitMirror = () => {} }) {
  const [locOpen, setLocOpen] = useState(false);
  const navItems = persona === 'hq' ? [
    { key: 'hq', icon: 'home', label: 'Local Portfolio' },
    { key: 'results', icon: 'results', label: 'Results' },
    { key: 'leads', icon: 'leads', label: 'Leads' },
    { key: 'bench', icon: 'bench', label: 'Playbook' },
  ] : [
    { key: 'home', icon: 'home', label: 'Home' },
    { key: 'results', icon: 'results', label: 'Results' },
    { key: 'leads', icon: 'leads', label: 'Leads' },
    { key: 'bench', icon: 'bench', label: 'Playbook' },
    { key: 'support', icon: 'chat', label: 'Support' },
  ];

  const servicesItems = persona === 'hq' ? [
    { key: 'services', icon: 'services', label: 'Command Center' },
    { key: 'listings', icon: 'listings', label: 'Locations Management' },
    { key: 'local-users', icon: 'users', label: 'Local Users' },
    { key: 'field-team', icon: 'users', label: 'Corporate Field Team' },
    { key: 'support', icon: 'chat', label: 'Franchisee Support' },
  ] : [
    { key: 'services', icon: 'services', label: 'Strategy' },
    { key: 'budget', icon: 'budget', label: 'Budget' },
  ];

  const presenceItems = persona === 'hq' ? [] : [
    { key: 'listings', icon: 'listings', label: 'Listings', badge: '2' },
    { key: 'reviews', icon: 'reviews', label: 'Reviews', badge: '3', badgeSoft: true },
  ];

  // Location-scoped management (the selected store's own config) lives in its
  // own section, distinct from account-wide items below.
  const locationItems = persona === 'hq' ? [] : [
    { key: 'settings', icon: 'settings', label: 'Settings' },
  ];

  const accountItems = persona === 'hq' ? [
    { key: 'invoice', icon: 'invoice', label: 'Billing' },
    { key: 'settings', icon: 'settings', label: 'Settings' },
  ] : [
    { key: 'invoice', icon: 'invoice', label: 'Invoice & Billing' },
  ];

  // Local Users, Corporate Field Team, and Franchisee Support now live under the
  // Marketing Operations group (see servicesItems), so this section is retired for HQ.
  const localUserItems = [];

  return (
    <aside className="sidebar">
      <div className="sb-logo" style={{ cursor: 'pointer' }} title="Back to demo start"
           onClick={() => window.dispatchEvent(new CustomEvent('la-reset-demo'))}>
        <div className="sb-logo-mark">
          <img src="brand/localact-mark.png" alt="LOCALACT" style={{ width: 22, height: 22, objectFit: 'contain', display: 'block' }} />
        </div>
        <div className="sb-logo-text">LOCALACT</div>
      </div>

      <ClientPicker account={account} persona={persona}/>
      <ViewAsPicker persona={persona} mirroredUser={mirroredUser} onMirror={onMirror} onExitMirror={onExitMirror} onNav={onNav}/>

      <nav className="sb-nav">
        <div className="sb-section">{persona === 'hq' ? 'Local Performance' : 'Overview'}</div>
        {navItems.map(n => (
          <div key={n.key} className={`nav-item ${currentPage === n.key ? 'active' : ''}`} onClick={() => onNav(n.key)}>
            <span className="nav-icon">{Icon[n.icon]}</span>
            <span>{n.label}</span>
          </div>
        ))}

        {persona === 'hq' && <>
          <div className="sb-section">National Performance</div>
          <div className={`nav-item nav-item-premium ${currentPage === 'enterprise-reporting' ? 'active' : ''}`}
               onClick={() => onNav('enterprise-reporting')}
               title="Enterprise Reporting · premium analytics">
            <span className="nav-premium-glow"/>
            <span className="nav-icon">
              <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 3v18h18"/><path d="M7 14l4-4 4 4 5-7"/><circle cx="20" cy="7" r="1.6" fill="currentColor"/></svg>
            </span>
            <span style={{ flex: 1 }}>Enterprise Reporting</span>
            <span className="nav-premium-badge">★</span>
          </div>
        </>}

        {servicesItems.length > 0 && <>
          <div className="sb-section">{persona === 'hq' ? 'Marketing Operations' : 'Marketing'}</div>
          {servicesItems.map(n => (
            <div key={n.key} className={`nav-item ${currentPage === n.key ? 'active' : ''}`} onClick={() => onNav(n.key)}>
              <span className="nav-icon">{Icon[n.icon]}</span>
              <span>{n.label}</span>
            </div>
          ))}
        </>}

        {presenceItems.length > 0 && <>
          <div className="sb-section">Presence</div>
          {presenceItems.map(n => (
            <div key={n.key} className={`nav-item ${currentPage === n.key ? 'active' : ''}`} onClick={() => onNav(n.key)}>
              <span className="nav-icon">{Icon[n.icon]}</span>
              <span>{n.label}</span>
              {n.badge && <span className={`nav-badge ${n.badgeSoft ? 'soft' : ''}`}>{n.badge}</span>}
            </div>
          ))}
        </>}

        {locationItems.length > 0 && <>
          <div className="sb-section">Locations</div>
          {locationItems.map(n => (
            <div key={n.key} className={`nav-item ${currentPage === n.key ? 'active' : ''}`} onClick={() => onNav(n.key)}>
              <span className="nav-icon">{Icon[n.icon]}</span>
              <span>{n.label}</span>
            </div>
          ))}
        </>}

        {localUserItems.length > 0 && <>
          <div className="sb-section">Local users</div>
          {localUserItems.map(n => (
            <div key={n.key} className={`nav-item ${currentPage === n.key ? 'active' : ''}`} onClick={() => onNav(n.key)}>
              <span className="nav-icon">{Icon[n.icon]}</span>
              <span>{n.label}</span>
            </div>
          ))}
        </>}

        <div className="sb-section">Account</div>
        {accountItems.map(n => (
          <div key={n.key} className={`nav-item ${currentPage === n.key ? 'active' : ''}`} onClick={() => onNav(n.key)}>
            <span className="nav-icon">{Icon[n.icon]}</span>
            <span>{n.label}</span>
          </div>
        ))}
      </nav>

      <div className="sb-lenny" onClick={() => window.dispatchEvent(new CustomEvent('open-lenny'))}>
        <div className="sb-lenny-row">
          <div className="sb-lenny-avatar">
            <LennyLlama size={36} mood="thinking" bg="circle"/>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="sb-lenny-name">Lenny</div>
            <div className="sb-lenny-role">Your marketing AI</div>
          </div>
        </div>
        <div className="sb-lenny-msg">
          {persona === 'hq'
            ? "Demand Gen isn't in your playbook, yet it's a key channel to show your brand across Google's surfaces and maximize exposure, generating more lead volume at the local level."
            : 'I spotted a quick win — a $200/mo Search bump could add an estimated 3–6 leads, based on FreshNest peer performance. Needs your approval.'}
        </div>
        <div className="sb-lenny-cta">Let's chat →</div>
      </div>

      <div className="sb-bottom">
        <div className="user-row">
          <div className="user-avatar-sm" style={mirroredUser ? { background: 'rgba(242,128,32,0.15)', color: 'var(--la-brand-primary-600,#b35f18)' } : {}}>
            {mirroredUser ? mirroredUser.initials : (persona === 'hq' ? 'MC' : (account.initials || 'AC'))}
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="user-name-sm">
              {mirroredUser ? mirroredUser.name : (persona === 'hq' ? 'Maya Chen' : (account.owner || 'Alicia Chen'))}
            </div>
            <div className="user-role-sm" style={mirroredUser ? { color: 'var(--la-brand-primary-500)', fontWeight: 700 } : {}}>
              {mirroredUser ? '● Viewing as local user' : (persona === 'hq' ? 'Franchise Marketing' : (account.role || 'Owner/Operator'))}
            </div>
          </div>
        </div>
      </div>
    </aside>
  );
}
window.Sidebar = Sidebar;

// ====================================================================
// MIRROR BANNER, persistent bar when a corporate user mirrors a franchise
// ====================================================================
function MirrorBanner({ mirroredUser, onExit, onBackToDirectory }) {
  const chipBase = {
    display: 'inline-flex', alignItems: 'center', gap: 6,
    padding: '4px 11px', fontSize: 12, fontWeight: 600,
    fontFamily: 'var(--la-font-ui)',
    background: 'rgba(255,255,255,0.08)', color: 'rgba(255,255,255,0.92)',
    border: '1px solid rgba(255,255,255,0.18)', borderRadius: 999,
    cursor: 'pointer', flexShrink: 0, whiteSpace: 'nowrap',
    transition: 'background 140ms, border-color 140ms',
  };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '8px 20px',
      background: 'var(--la-brand-secondary-900,#001132)',
      borderBottom: '2px solid var(--la-brand-primary-500,#f28020)',
      fontFamily: 'var(--la-font-ui)',
      flexShrink: 0,
    }}>
      {/* Eye icon + label */}
      <span style={{ color: 'var(--la-brand-primary-400,#f6a663)', display: 'flex', flexShrink: 0 }}>
        <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7z"/>
          <circle cx="12" cy="12" r="3"/>
        </svg>
      </span>
      <span style={{
        fontSize: 10.5, fontWeight: 800, letterSpacing: '0.10em',
        textTransform: 'uppercase', color: 'var(--la-brand-primary-400,#f6a663)',
        flexShrink: 0,
      }}>Viewing as</span>

      {/* Breadcrumb, back to the account/user picker */}
      <button onClick={onBackToDirectory} title="Back to the Local users directory" style={chipBase}
        onMouseEnter={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.16)'; }}
        onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.08)'; }}>
        <svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
        Local users
      </button>
      <span style={{ color: 'rgba(255,255,255,0.30)', fontSize: 13, flexShrink: 0 }}>/</span>

      {/* Mirrored identity, absorbs the squeeze so the controls stay pinned */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, flex: 1, minWidth: 0, overflow: 'hidden' }}>
        <span style={{ fontSize: 13, fontWeight: 700, color: '#fff', whiteSpace: 'nowrap', flexShrink: 0 }}>{mirroredUser.name}</span>
        <span style={{ fontSize: 12, color: 'rgba(255,255,255,0.50)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0 }}>{mirroredUser.email}</span>
        <span style={{ width: 1, height: 13, background: 'rgba(255,255,255,0.16)', flexShrink: 0 }}/>
        <span style={{ fontSize: 12, color: 'rgba(255,255,255,0.50)', whiteSpace: 'nowrap', flexShrink: 0 }}>
          {mirroredUser.locationCount} location{mirroredUser.locationCount !== 1 ? 's' : ''}
        </span>
        <span style={{ fontSize: 12, color: 'rgba(255,255,255,0.40)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0 }}>{mirroredUser.locations}</span>
      </div>

      <span style={{ fontSize: 11.5, color: 'rgba(255,255,255,0.45)', whiteSpace: 'nowrap', flexShrink: 0 }}>Acting on their behalf</span>
      <button onClick={onExit} style={{
        display: 'inline-flex', alignItems: 'center', gap: 5,
        padding: '5px 14px', fontSize: 11.5, fontWeight: 700,
        fontFamily: 'var(--la-font-ui)',
        background: 'var(--la-brand-primary-surface,#d5711c)',
        color: '#fff', border: 'none', borderRadius: 999,
        cursor: 'pointer', flexShrink: 0, letterSpacing: '0.01em', whiteSpace: 'nowrap',
        transition: 'background 140ms, transform 100ms',
      }}
      onMouseEnter={e => { e.currentTarget.style.background = '#b35f18'; e.currentTarget.style.transform = 'translateY(-1px)'; }}
      onMouseLeave={e => { e.currentTarget.style.background = 'var(--la-brand-primary-surface,#d5711c)'; e.currentTarget.style.transform = 'none'; }}
      >
        Back to corporate view
        <svg viewBox="0 0 24 24" width="10" height="10" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <path d="M18 6 6 18M6 6l12 12"/>
        </svg>
      </button>
    </div>
  );
}
window.MirrorBanner = MirrorBanner;

// ====================================================================
// TOPBAR
// ====================================================================
function Topbar({ page, persona, onNotif, onChat, onTweaks, onNav, onCmd, density, setDensity, isMulti = false, accountLocations = [], selectedLoc = 'all', onSelectLoc = () => {} }) {
  const titles = {
    home: ['Home', 'Your location at a glance'],
    results: ['Results', 'Performance across every channel'],
    leads: ['Leads', 'Every lead, end-to-end'],
    services: ['Strategy', 'Your marketing strategy'],
    budget: ['Budget', 'Monthly allocation & pacing'],
    campaigns: ['Campaigns', 'Budget periods and promotions'],
    listings: persona === 'hq' ? ['Location Management', 'Source of truth for every location.'] : ['Listings', 'Directory presence & sync'],
    'location-detail': ['Location detail', 'Listings, reviews & presence for this location'],
    reviews: ['Reviews', 'What your customers are saying'],
    bench: ['Playbook', 'Plan progress & benchmarks'],
    invoice: persona === 'hq' ? ['Corporate Billing', 'National services & franchisee billing health'] : ['Invoice', 'Billing & statements'],
    settings: ['Settings', 'Account & preferences'],
    'enterprise-reporting': ['Enterprise Reporting', 'Premium analytics across every campaign'],
    'field-team': ['Corporate Field Team', 'Coach franchisees across your territory'],
    hq: ['Local Portfolio', 'All 700 locations'],
    support: persona === 'hq'
      ? ['Support', 'Franchisee communications & advisor performance']
      : ['Support', 'Talk to your Local Marketing Team'],
    'local-users': ['Local users', 'Franchise account directory · mirror any view to assist'],
  };
  const [title] = titles[page] || ['Home', ''];
  return (
    <div className="topbar">
      <div className="tb-pickers">
        <TopbarLocationPicker accountLocations={accountLocations} selectedLoc={selectedLoc}
                              onSelectLoc={onSelectLoc} persona={persona} isMulti={isMulti}/>
        <TopbarDatePicker/>
      </div>
      <div className="topbar-spacer"/>
      {persona !== 'hq' && setDensity && (
        <div className="density-toggle" role="group" aria-label="View density">
          {[
            { k: 'simple', label: 'Basic view' },
            { k: 'full', label: 'Advanced view' },
          ].map(o => (
            <button key={o.k}
                    className={`density-seg ${density === o.k ? 'on' : ''}`}
                    title={o.k === 'simple' ? 'A calm, owner-friendly summary' : 'Full detail, every chart and control'}
                    onClick={() => {
                      if (density === o.k) return;
                      setDensity(o.k);
                      window.toast && window.toast(
                        o.k === 'simple' ? 'Basic view' : 'Advanced view',
                        o.k === 'simple' ? 'Simplified, headline numbers and next moves only.' : 'Full detail restored across screens.',
                        'info'
                      );
                    }}>
              <span className="density-dot"/>
              {o.label}
            </button>
          ))}
        </div>
      )}
      <div className="topbar-search" onClick={onCmd} style={{ cursor: 'pointer' }}>
        {Icon.search}
        <span>Search leads, listings, campaigns…</span>
        <kbd>⌘K</kbd>
      </div>
      <button className="tb-icon-btn" title="Tweaks" onClick={onTweaks}>
        {Icon.settings}
      </button>
      <button className="tb-icon-btn" title="Notifications" onClick={onNotif}>
        {Icon.bell}
        <span className="dot"/>
      </button>
      <button className="tb-lenny-btn" onClick={onChat}>
        <span className="avatar"><LennyLlama size={22} mood="happy"/></span>
        Ask Lenny
      </button>
    </div>
  );
}
window.Topbar = Topbar;

// ====================================================================
// NOTIFICATIONS
// ====================================================================
function NotifPanel({ open, onClose, activity }) {
  return (
    <div className={`notif-panel ${open ? 'open' : ''}`}>
      <div className="notif-hdr">
        <div className="notif-hdr-title">Activity</div>
        <button className="btn btn-quiet btn-xs" onClick={onClose}>Close</button>
      </div>
      <div className="notif-body">
        {activity.map((a, i) => {
          const bg = { ok: 'var(--sage-soft)', marigold: 'var(--marigold-soft)', sage: 'var(--sage-soft)', sky: 'var(--sky-soft)', terra: 'var(--terra-soft)' }[a.color];
          const fg = { ok: 'var(--ok)', marigold: 'var(--marigold)', sage: 'var(--sage)', sky: 'var(--sky)', terra: 'var(--terra)' }[a.color];
          return (
            <div key={i} className={`notif-item ${i < 2 ? 'unread' : ''}`}>
              <div className="notif-ic" style={{ background: bg, color: fg }}>{Icon[a.icon]}</div>
              <div className="notif-text">
                <div className="t">{a.title}</div>
                <div className="m">{a.meta}</div>
              </div>
              <div className="notif-time">{a.time}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
window.NotifPanel = NotifPanel;

// ====================================================================
// CHAT PANEL
// ====================================================================
function ChatPanel({ open, onClose }) {
  const [msgs, setMsgs] = useState([
    { role: 'bot', text: "Hi Alicia, I just ran your numbers this morning. Your LocalScore hit 87 ( top 18% of FreshNest system). Want the rundown or should I cover a specific area?" },
  ]);
  const [thinking, setThinking] = useState(false);
  const [input, setInput] = useState('');
  const suggestions = [
    "What's hurting my Yelp?",
    "Why's my CPL down?",
    "Should I raise PPC?",
    "Best next move?",
  ];
  const bodyRef = useRef(null);
  useEffect(() => {
    if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
  }, [msgs, thinking]);

  function send(text) {
    if (!text.trim()) return;
    setMsgs(m => [...m, { role: 'user', text }]);
    setInput('');
    setThinking(true);
    setTimeout(() => {
      setThinking(false);
      const reply = fakeReply(text);
      setMsgs(m => [...m, { role: 'bot', text: reply }]);
    }, 900 + Math.random() * 600);
  }

  function fakeReply(t) {
    const s = t.toLowerCase();
    if (s.includes('yelp')) return "Your Sunday hours are the issue, Yelp's publisher overwrote your 9 PM close to 8 PM. I've queued auto-correction; you'll see it sync in ~4 hrs. Nothing for you to do.";
    if (s.includes('cpl') || s.includes('cost')) return "CPL dropped from $66 to $58 because your Performance Max creative refresh on Mar 14 lifted CTR to 7.8% (from 4.2%). That's compounding nicely, you're getting more leads per dollar every week.";
    if (s.includes('ppc') || s.includes('budget') || s.includes('raise')) return "Here's what I'm seeing: your impression share is 74%, below the 84% top FreshNest peers reach, so you're losing searches when the $1,850 budget caps out. Bumping to ~$2,050 (+$200/mo) projects an estimated 3–6 more qualified leads, based on the last 60 days of peer performance. This affects your spend and needs your approval, want me to line it up for April 1?";
    if (s.includes('review')) return "You've got 2 new 5★ reviews today. Dev R. left a 3★ mentioning online ordering, I drafted a reply acknowledging the bug (your webmaster fixed it Mar 18). Approve?";
    if (s.includes('score') || s.includes('local')) return "LocalScore 87 = top 18% in FreshNest system. You gained +4 this period from: +2 listing accuracy (Yelp fix pending), +1 review velocity, +1 AI visibility (Perplexity now cites you).";
    return "Good question. Let me pull that together, I can tie this into your campaigns, lead data, or listings. Which angle matters most right now?";
  }

  if (!open) return null;
  return (
    <div className={`chat-panel ${open ? 'open' : ''}`}>
      <div className="chat-hdr">
        <div className="avatar"><LennyLlama size={38} mood={thinking ? 'thinking' : 'happy'} bg="circle"/></div>
        <div>
          <div className="name">Lenny</div>
          <div className="status"><span style={{width:6,height:6,borderRadius:'50%',background:'var(--ok)',display:'inline-block'}}/> Online · AI marketing coach</div>
        </div>
        <button className="chat-close" onClick={onClose}>×</button>
      </div>
      <div className="chat-body" ref={bodyRef}>
        {msgs.map((m, i) => (
          <div key={i} className={`chat-msg ${m.role}`}>{m.text}</div>
        ))}
        {thinking && (
          <div className="chat-msg bot"><span className="thinking"><span/><span/><span/></span></div>
        )}
        {!thinking && msgs.length < 3 && (
          <div className="chat-suggestions">
            {suggestions.map(s => <button key={s} className="chat-sug" onClick={() => send(s)}>{s}</button>)}
          </div>
        )}
      </div>
      <div className="chat-footer">
        <input className="chat-input" placeholder="Ask Lenny anything…" value={input}
               onChange={e => setInput(e.target.value)}
               onKeyDown={e => e.key === 'Enter' && send(input)}/>
        <button className="chat-send" onClick={() => send(input)}>{Icon.send}</button>
      </div>
    </div>
  );
}
window.ChatPanel = ChatPanel;

// ====================================================================
// TWEAKS PANEL
// ====================================================================
function TweaksPanel({ open, onClose, persona, setPersona, locationVariant, setLocationVariant }) {
  return (
    <div className={`tweaks ${open ? 'open' : ''}`}>
      <div className="tweaks-hdr">
        Tweaks
        <button className="btn btn-quiet btn-xs" onClick={onClose}>×</button>
      </div>
      <div className="tweaks-body">
        <div>
          <div className="tweak-group-label">Account</div>
          <div className="tweak-options">
            {[
              { k: 'star', t: 'Austin Group · multi-location', s: 'Alicia Chen · 4 locations · full marketing plan', ic: '◆' },
              { k: 'bare', t: 'Plano Legacy · single location', s: 'Danny Ruiz · 1 location · $300 Google Search only', ic: '●' },
            ].map(o => (
              <div key={o.k} className={`tweak-opt ${locationVariant === o.k ? 'on' : ''}`} onClick={() => setLocationVariant(o.k)}>
                <div className="ic" style={{fontSize:15}}>{o.ic}</div>
                <div className="meta">
                  <div className="t">{o.t}</div>
                  <div className="s">{o.s}</div>
                </div>
              </div>
            ))}
          </div>
        </div>
        <div>
          <div className="tweak-group-label">Persona</div>
          <div className="tweak-options">
            {[
              { k: 'franchisee', t: 'Franchisee', s: 'Alicia Chen · Austin Downtown', ic: 'user' },
              { k: 'hq', t: 'Corporate / Franchisor', s: 'FreshNest HQ · 700 locations', ic: 'services' },
            ].map(o => (
              <div key={o.k} className={`tweak-opt ${persona === o.k ? 'on' : ''}`} onClick={() => setPersona(o.k)}>
                <div className="ic" style={{ width: 16, height: 16, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--ink-3)' }}>{Icon[o.ic]}</div>
                <div className="meta">
                  <div className="t">{o.t}</div>
                  <div className="s">{o.s}</div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}
window.TweaksPanel = TweaksPanel;

// ====================================================================
// PLAYBOOK CONVERSION-VALUE CALIBRATOR
// Opens when sidebar Playbook card or "store visit value" tile fires
// `open-playbook-customization`. Lets HQ set the dollar value of every
// conversion type so revenue rolls up correctly across the brand.
// ====================================================================
function PlaybookValueCalibrator() {
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const onOpen = () => setOpen(true);
    window.addEventListener('open-playbook-customization', onOpen);
    return () => window.removeEventListener('open-playbook-customization', onOpen);
  }, []);

  // ---- inputs ----
  const [storeVisit, setStoreVisit]       = useState(39);
  const [leadQuality, setLeadQuality]     = useState(40);   // % of leads that qualify
  const [closeRate, setCloseRate]         = useState(48);   // % of qualified that close
  const [oneTimeValue, setOneTimeValue]   = useState(62);   // $ per first transaction
  const [visitsPerYear, setVisitsPerYear] = useState(4.2);  // avg return frequency

  // Annual customer value = first-purchase + (visits-1)*first-purchase
  const annualValue = oneTimeValue * visitsPerYear;
  // Effective revenue per general lead (call/form) = qual% × close% × annual value
  const revPerLead  = (leadQuality / 100) * (closeRate / 100) * annualValue;

  if (!open) return null;

  return (
    <window.Modal open={true} onClose={() => setOpen(false)} width={760}
      title="Conversion value calibration"
      sub="Tell us what each conversion is worth so revenue numbers across the brand are real, not guessed."
      footer={<>
        <button className="btn btn-ghost btn-sm" onClick={() => setOpen(false)}>Cancel</button>
        <button className="btn btn-primary btn-sm" onClick={() => {
          setOpen(false);
          window.T && window.T('Playbook updated', `Store visit $${storeVisit} · est. $${revPerLead.toFixed(0)}/lead applied brand-wide.`, 'ok');
        }}>Save to playbook</button>
      </>}>
      <div style={{ padding: '12px 14px', background: 'var(--violet-soft)', border: '1px solid rgba(77,105,137,0.20)', borderRadius: 10, marginBottom: 18, fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.5 }}>
        <div style={{ fontSize: 10.5, color: 'var(--violet)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, marginBottom: 4 }}>How this is used</div>
        Without a CRM connection, this is the <strong>primary revenue model</strong> for non-ecommerce locations. We multiply each conversion (calls, form fills, store visits) by these values to estimate revenue across every dashboard, report, and benchmark.
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, marginLeft: 8, padding: '2px 6px', background: 'rgba(77,105,137,0.10)', borderRadius: 3, fontSize: 10.5, fontWeight: 700, color: 'var(--violet)', fontFamily: 'var(--ff-mono)' }}>CRM not connected</span>
      </div>

      {/* ---- Section 1: Store visit ---- */}
      <PVCSection
        title="Store visit value"
        tag="New"
        subtitle="When a customer walks in. Pulled from POS averages or set manually here."
      >
        <PVCInput label="Per-visit value" value={storeVisit} onChange={setStoreVisit} prefix="$" min={1} max={500} step={1}/>
        <div style={{ flex: 1, fontSize: 11.5, color: 'var(--ink-3)', lineHeight: 1.5, paddingTop: 4 }}>
          Brand average across FreshNest locations: <strong style={{ color: 'var(--ink-2)' }}>$39.40</strong>. We'll use this on every store-visit conversion in Results & Reporting.
        </div>
      </PVCSection>

      {/* ---- Section 2: General leads (calls + form fills) ---- */}
      <PVCSection
        title="General leads · calls & form fills"
        subtitle="Not every lead becomes a customer. Tune the funnel and we'll do the math."
      >
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 14, width: '100%' }}>
          <PVCSlider label="Lead quality" sub="% of leads that qualify" value={leadQuality} onChange={setLeadQuality} suffix="%" min={0} max={100} step={1}/>
          <PVCSlider label="Close rate"   sub="% of qualified that book" value={closeRate}   onChange={setCloseRate}   suffix="%" min={0} max={100} step={1}/>
          <PVCInput  label="Customer first-time value" sub="One-time customer worth" value={oneTimeValue} onChange={setOneTimeValue} prefix="$" min={0} max={2000} step={1}/>
          <PVCInput  label="Visits per year" sub="Avg return frequency / customer / yr" value={visitsPerYear} onChange={setVisitsPerYear} suffix=" visits" min={1} max={52} step={0.1}/>
        </div>
      </PVCSection>

      {/* ---- Live calculation summary ---- */}
      <div style={{ marginTop: 8, padding: '16px 18px', background: 'linear-gradient(135deg, var(--terra-softer), var(--paper) 60%, var(--marigold-soft))', border: '1px solid var(--marigold-soft-2, rgba(246,166,99,0.55))', borderRadius: 12 }}>
        <div style={{ fontSize: 10.5, color: '#917200', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, marginBottom: 10 }}>Live calculation</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 24px 1fr 24px 1fr 24px 1fr', gap: 10, alignItems: 'center' }}>
          <PVCStep label="Lead quality" value={`${leadQuality}%`}/>
          <PVCArrow/>
          <PVCStep label="Close rate" value={`${closeRate}%`}/>
          <PVCArrow/>
          <PVCStep label="Annual value" value={`$${annualValue.toFixed(0)}`} sub={`$${oneTimeValue} × ${visitsPerYear.toFixed(1)} visits`}/>
          <PVCArrow/>
          <PVCStep label="Revenue per lead" value={`$${revPerLead.toFixed(0)}`} accent/>
        </div>
        <div style={{ marginTop: 12, fontSize: 11.5, color: 'var(--ink-3)', lineHeight: 1.5 }}>
          With <strong style={{ color: 'var(--ink-2)' }}>1,420 leads/mo brand-wide</strong>, that's an estimated <strong style={{ color: 'var(--ink)' }}>${(revPerLead * 1420 / 1000).toFixed(0)}k/mo</strong> in attributed revenue from calls + forms. Store visits add on top.
        </div>
      </div>

      {/* ---- Per-conversion-type rates table ---- */}
      <div style={{ marginTop: 18 }}>
        <div style={{ fontSize: 10.5, color: 'var(--violet)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, marginBottom: 8 }}>Per-conversion-type values</div>
        <div style={{ border: '1px solid var(--cream-3)', borderRadius: 10, overflow: 'hidden' }}>
          {[
            { name: 'Phone call',           method: 'lead-funnel', formula: `${leadQuality}% × ${closeRate}% × $${annualValue.toFixed(0)}`, val: revPerLead },
            { name: 'Form fill',            method: 'lead-funnel', formula: `${leadQuality}% × ${closeRate}% × $${annualValue.toFixed(0)}`, val: revPerLead },
            { name: 'Store visit',          method: 'flat',        formula: `Per-visit value`, val: storeVisit },
            { name: 'Reservation booked',   method: 'flat',        formula: `Per-visit value`, val: storeVisit },
            { name: 'Online order',         method: 'crm',         formula: `Synced from POS`, val: null, note: 'Connect CRM' },
          ].map((r, i, arr) => (
            <div key={r.name} style={{ display: 'grid', gridTemplateColumns: '1.1fr 1fr 1.6fr 0.9fr', gap: 12, padding: '11px 14px', borderBottom: i === arr.length - 1 ? 'none' : '1px solid var(--cream-2)', alignItems: 'center', background: i % 2 === 0 ? 'transparent' : 'rgba(0,0,0,0.012)' }}>
              <div style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink)' }}>{r.name}</div>
              <div>
                <span style={{
                  display: 'inline-block', padding: '2px 7px', borderRadius: 4, fontSize: 9.5, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase',
                  background: r.method === 'flat' ? 'var(--marigold-soft)' : r.method === 'lead-funnel' ? 'var(--violet-soft)' : 'var(--cream-2)',
                  color:      r.method === 'flat' ? '#917200' : r.method === 'lead-funnel' ? 'var(--violet)' : 'var(--ink-3)',
                }}>{r.method === 'flat' ? 'Flat value' : r.method === 'lead-funnel' ? 'Funnel calc' : 'CRM only'}</span>
              </div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', fontFamily: 'var(--ff-mono)' }}>{r.formula}</div>
              <div style={{ textAlign: 'right', fontFamily: 'var(--ff-mono)', fontWeight: 700, fontSize: 13, color: r.val == null ? 'var(--ink-4)' : 'var(--ink)' }}>
                {r.val == null ? <span style={{ fontSize: 11, fontWeight: 600 }}>{r.note}</span> : `$${r.val.toFixed(0)}`}
              </div>
            </div>
          ))}
        </div>
      </div>
    </window.Modal>
  );
}

function PVCSection({ title, subtitle, tag, children }) {
  return (
    <div style={{ marginBottom: 18 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 6 }}>
        <div style={{ fontFamily: 'var(--ff-display)', fontSize: 16, fontWeight: 600, color: 'var(--ink)', letterSpacing: '-0.01em' }}>{title}</div>
        {tag && <span style={{ padding: '2px 6px', background: 'var(--marigold-soft)', color: '#917200', fontSize: 9.5, fontWeight: 700, borderRadius: 3, letterSpacing: '0.06em', textTransform: 'uppercase' }}>{tag}</span>}
      </div>
      {subtitle && <div style={{ fontSize: 12, color: 'var(--ink-3)', marginBottom: 10, lineHeight: 1.5 }}>{subtitle}</div>}
      <div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>{children}</div>
    </div>
  );
}

function PVCInput({ label, sub, value, onChange, prefix, suffix, min, max, step }) {
  return (
    <div style={{ flex: 1, minWidth: 160 }}>
      <div style={{ fontSize: 10.5, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700, marginBottom: 4 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'center', background: 'var(--paper)', border: '1px solid var(--cream-3)', borderRadius: 8, overflow: 'hidden' }}>
        {prefix && <span style={{ padding: '0 4px 0 10px', color: 'var(--ink-3)', fontFamily: 'var(--ff-mono)', fontWeight: 700 }}>{prefix}</span>}
        <input type="number" value={value} min={min} max={max} step={step}
               onChange={e => onChange(parseFloat(e.target.value) || 0)}
               style={{ flex: 1, border: 'none', outline: 'none', padding: '9px 8px', fontFamily: 'var(--ff-mono)', fontSize: 14, fontWeight: 700, color: 'var(--ink)', background: 'transparent', minWidth: 0 }}/>
        {suffix && <span style={{ padding: '0 10px 0 2px', color: 'var(--ink-3)', fontFamily: 'var(--ff-mono)', fontSize: 11 }}>{suffix}</span>}
      </div>
      {sub && <div style={{ fontSize: 10.5, color: 'var(--ink-4)', marginTop: 4 }}>{sub}</div>}
    </div>
  );
}

function PVCSlider({ label, sub, value, onChange, suffix, min, max, step }) {
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 4 }}>
        <span style={{ fontSize: 10.5, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700 }}>{label}</span>
        <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 14, fontWeight: 700, color: 'var(--ink)' }}>{value}{suffix}</span>
      </div>
      <input type="range" min={min} max={max} step={step} value={value}
             onChange={e => onChange(parseFloat(e.target.value))}
             style={{ width: '100%', accentColor: 'var(--violet)' }}/>
      {sub && <div style={{ fontSize: 10.5, color: 'var(--ink-4)', marginTop: 2 }}>{sub}</div>}
    </div>
  );
}

function PVCStep({ label, value, sub, accent }) {
  return (
    <div style={{ padding: '8px 10px', background: accent ? 'var(--violet)' : 'var(--paper)', border: '1px solid ' + (accent ? 'var(--violet)' : 'rgba(246,166,99,0.55)'), borderRadius: 8, color: accent ? 'var(--cream)' : 'var(--ink)' }}>
      <div style={{ fontSize: 9.5, opacity: 0.78, textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700, marginBottom: 2 }}>{label}</div>
      <div style={{ fontFamily: 'var(--ff-display)', fontSize: 18, fontWeight: 600, letterSpacing: '-0.01em', lineHeight: 1.1 }}>{value}</div>
      {sub && <div style={{ fontSize: 10, opacity: 0.72, marginTop: 2, fontFamily: 'var(--ff-mono)' }}>{sub}</div>}
    </div>
  );
}

function PVCArrow() {
  return <span style={{ textAlign: 'center', color: 'var(--ink-4)', fontSize: 16 }}>→</span>;
}
window.PlaybookValueCalibrator = PlaybookValueCalibrator;
