// admin-app.jsx — Top-level back-office shell: browser window > sidebar
// (role switcher) > active role view. Plus the employee + timecard drawers
// and access-code gate.

const A_PALETTE = ['#E55B13', '#1D6FB8', '#137C50', '#5B3FB8', '#0F172A'];

function adminApplyTheme(accent) {
  const root = document.documentElement;
  root.style.setProperty('--accent', accent);
  const h = accent.replace('#', '');
  const r = parseInt(h.slice(0,2),16), g = parseInt(h.slice(2,4),16), b = parseInt(h.slice(4,6),16);
  root.style.setProperty('--accent-deep', `#${Math.round(r*0.78).toString(16).padStart(2,'0')}${Math.round(g*0.78).toString(16).padStart(2,'0')}${Math.round(b*0.78).toString(16).padStart(2,'0')}`);
  root.style.setProperty('--accent-soft', `#${Math.round(r+(255-r)*0.86).toString(16).padStart(2,'0')}${Math.round(g+(255-g)*0.86).toString(16).padStart(2,'0')}${Math.round(b+(255-b)*0.86).toString(16).padStart(2,'0')}`);
}

function AdminApp() {
  const [tweaks, setTweak] = useTweaks(window.__TWEAK_DEFAULTS);
  useEffect(() => {
    window.__currentTweaks = tweaks;
    window.dispatchEvent(new Event('tweaks-changed'));
    adminApplyTheme(tweaks.accent);
    document.title = `${tweaks.companyName} — Operations Console`;
  }, [tweaks]);
  useEffect(() => { adminApplyTheme(tweaks.accent); }, []);

  return (
    <AdminProvider>
      <div style={{
        minHeight: '100vh', width: '100%',
        background: 'radial-gradient(circle at 30% 10%, #20262e 0%, #0a0d11 60%, #06080b 100%)',
        display: 'grid', placeItems: 'center', padding: 16,
      }}>
        <BrowserWindow url="console.railflagspro.com/operations">
          <ConsoleGate />
        </BrowserWindow>
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="White-label">
          <TweakText label="Company name" value={tweaks.companyName} onChange={v => setTweak('companyName', v)} />
          <TweakText label="Tagline" value={tweaks.tagline} onChange={v => setTweak('tagline', v)} />
        </TweakSection>
        <TweakSection label="Theme">
          <TweakColor label="Accent" value={tweaks.accent} options={A_PALETTE} onChange={v => setTweak('accent', v)} />
        </TweakSection>
      </TweaksPanel>
    </AdminProvider>
  );
}

// ── Auth gate ────────────────────────────────────────────────
function ConsoleGate() {
  const [session, setSession] = useState(() => RFP.session());
  const [sub, setSub] = useState(null);
  const [subLoaded, setSubLoaded] = useState(false);
  const [paywalled, setPaywalled] = useState(false);

  const handleAuthed = async (newSession) => {
    setSession(newSession);
    try {
      // Load subscription via RFP_ENTITLEMENTS (new spec helper) with RFP.subscription fallback
      let s = null;
      if (typeof RFP_ENTITLEMENTS !== 'undefined') {
        RFP_ENTITLEMENTS.clearCache();
        s = await RFP_ENTITLEMENTS.getSubscription();
      }
      // Fallback to old helper
      if (!s) s = await RFP.subscription.load();
      setSub(s);

      // Gate check: if Supabase is live and explicitly returned null, show paywall
      // If Supabase is unavailable (null due to network), fall through (don't lock demo)
      const hasActive = s
        ? (s.status === 'active' || s.status === 'trialing')
        : null; // null = unknown (offline/demo mode)

      if (hasActive === false) {
        setPaywalled(true);
      }
    } catch (e) {
      console.warn('ConsoleGate: subscription load failed', e);
    } finally {
      setSubLoaded(true);
    }
  };

  // Load subscription on mount if already logged in
  useEffect(() => {
    if (session && session.app === 'console' && !subLoaded) {
      const loadSub = async () => {
        try {
          let s = null;
          if (typeof RFP_ENTITLEMENTS !== 'undefined') {
            s = await RFP_ENTITLEMENTS.getSubscription();
          }
          if (!s) s = await RFP.subscription.load();
          setSub(s);
          if (s && !(s.status === 'active' || s.status === 'trialing')) {
            setPaywalled(true);
          }
        } catch (e) {
          console.warn('ConsoleGate mount: subscription load failed', e);
        } finally {
          setSubLoaded(true);
        }
      };
      loadSub();
    }
  }, []);

  const handleLogout = () => {
    RFP.logout();
    RFP.subscription.clear();
    if (typeof RFP_ENTITLEMENTS !== 'undefined') RFP_ENTITLEMENTS.clearCache();
    setSession(null);
    setSub(null);
    setSubLoaded(false);
    setPaywalled(false);
  };

  if (!session || session.app !== 'console') return <ConsoleLogin onAuthed={handleAuthed} />;

  // Full-screen paywall when subscription is explicitly inactive
  if (paywalled) return <SubscriptionPaywall onSignOut={handleLogout} />;

  return <Console session={session} sub={sub} onLogout={handleLogout} />;
}

// ── Full-screen subscription paywall ─────────────────────────
function SubscriptionPaywall({ onSignOut }) {
  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 9999,
      background: '#0f1117',
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      fontFamily: 'system-ui, -apple-system, sans-serif',
      color: '#f1f5f9',
    }}>
      <div style={{ maxWidth: 480, textAlign: 'center', padding: 40 }}>
        <div style={{ fontSize: 48, marginBottom: 24 }}>🚂</div>
        <h1 style={{ fontSize: 28, fontWeight: 700, margin: '0 0 12px' }}>Subscription Required</h1>
        <p style={{ color: '#94a3b8', fontSize: 16, lineHeight: 1.6, margin: '0 0 32px' }}>
          Your company does not have an active Railflagging Pro subscription.
          Subscribe to access the Operations Console.
        </p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <a href="https://madethis.com/checkout/railflagging-pro/md7a7cvecnzkkrzhqzd224s2xx88cpp2"
            target="_blank" rel="noopener noreferrer"
            style={{ display: 'block', background: '#dc2626', color: '#fff', textDecoration: 'none', padding: '14px 28px', borderRadius: 8, fontWeight: 600, fontSize: 16 }}>
            Small Crew — $598/mo (≤15 crew)
          </a>
          <a href="https://madethis.com/checkout/railflagging-pro/md77z5xjr71tgyvv96krmr9ba188c1sf"
            target="_blank" rel="noopener noreferrer"
            style={{ display: 'block', background: '#1d4ed8', color: '#fff', textDecoration: 'none', padding: '14px 28px', borderRadius: 8, fontWeight: 600, fontSize: 16 }}>
            Large Crew — $1,198/mo (16–200 crew)
          </a>
          <button onClick={onSignOut}
            style={{ background: 'transparent', border: '1px solid #334155', color: '#94a3b8', padding: '10px 24px', borderRadius: 8, cursor: 'pointer', fontSize: 14 }}>
            Sign Out
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Plan badge ───────────────────────────────────────────────
function PlanBadge({ sub }) {
  if (!sub) return null;
  const isActive = sub && (sub.status === 'active' || sub.status === 'trialing');
  if (!isActive) {
    return (
      <a href="https://railflagging-pro.madethis.app/#pricing" target="_blank" rel="noopener noreferrer"
        style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 6, background: 'rgba(180,35,24,0.2)', border: '1px solid rgba(180,35,24,0.4)', color: '#f87171', fontSize: 10, fontWeight: 700, textDecoration: 'none', whiteSpace: 'nowrap' }}>
        Inactive — Renew
      </a>
    );
  }
  const planLabel = sub.plan === 'large_crew' ? 'Large Crew' : sub.plan === 'trial' ? 'Trial' : 'Small Crew';
  const isTrial = sub.plan === 'trial' || sub.status === 'trialing';
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 6, background: isTrial ? 'rgba(180,83,9,0.2)' : 'rgba(19,124,80,0.2)', border: isTrial ? '1px solid rgba(180,83,9,0.4)' : '1px solid rgba(19,124,80,0.4)', color: isTrial ? '#fbbf24' : '#34d399', fontSize: 10, fontWeight: 700, whiteSpace: 'nowrap' }}>
      {planLabel}
    </span>
  );
}

// ── Subscription banner (shown when inactive) ─────────────────
function SubBanner({ sub }) {
  const [dismissed, setDismissed] = useState(false);
  if (!sub || dismissed) return null;
  const isActive = sub.status === 'active' || sub.status === 'trialing';
  if (isActive) return null;
  return (
    <div style={{ background: '#7f1d1d', borderBottom: '1px solid #991b1b', padding: '8px 20px', display: 'flex', alignItems: 'center', gap: 12, fontSize: 12.5, color: '#fecaca', flexShrink: 0 }}>
      <span style={{ flex: 1 }}>
        ⚠️ Your subscription is inactive. Subscribe at{' '}
        <a href="https://railflagging-pro.madethis.app/#pricing" target="_blank" rel="noopener noreferrer" style={{ color: '#fca5a5', fontWeight: 700 }}>
          railflagging-pro.madethis.app/#pricing
        </a>
      </span>
      <button onClick={() => setDismissed(true)} style={{ background: 'transparent', border: '1px solid rgba(252,165,165,0.4)', borderRadius: 6, padding: '3px 8px', color: '#fca5a5', fontSize: 11, cursor: 'pointer' }}>Dismiss</button>
    </div>
  );
}

// ── Console — sidebar + role view ────────────────────────────
function Console({ session, sub, onLogout }) {
  const allRoleIds = ROLES.map(r => r.id);
  const visible = RFP.visibleRoles(allRoleIds);
  const isOfficer = session.role === 'officer';
  const [role, setRole] = useState(isOfficer ? 'officer' : (visible[0] || session.role));
  const { tweaks } = useTweakValues();
  const { exceptions, timecards, employeeDrawer, setEmployeeDrawer, timecardDrawer, setTimecardDrawer, toasts } = useAdmin();

  const visibleRolesList = ROLES.filter(r => visible.includes(r.id));

  const pendingTotal = timecards.filter(t => t.status === 'pending-ops' || t.status === 'pending-acct').length;

  const roleBadges = {
    safety: exceptions.length,
    accounting: timecards.filter(t => t.status === 'pending-acct').length,
  };

  return (
    <>
      {/* Sidebar */}
      <aside style={{
        width: 248, flexShrink: 0, background: '#0E1622', color: 'rgba(255,255,255,0.85)',
        display: 'flex', flexDirection: 'column', padding: 14, overflow: 'hidden',
      }}>
        {/* Brand */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '6px 6px 16px' }}>
          <div style={{
            width: 36, height: 36, borderRadius: 9, background: '#0F172A', color: '#fff',
            display: 'grid', placeItems: 'center', fontWeight: 700, fontSize: 13,
            position: 'relative', overflow: 'hidden', border: '1px solid rgba(255,255,255,0.1)',
          }}>
            <div style={{ position: 'absolute', inset: 0, background: 'var(--accent)', clipPath: 'polygon(0 100%, 100% 100%, 100% 58%, 0 90%)' }} />
            <span style={{ position: 'relative', zIndex: 1 }}>{(tweaks.companyName || 'RF').split(/\s+/).map(w => w[0]).join('').slice(0, 2).toUpperCase()}</span>
          </div>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 14, color: '#fff', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{tweaks.companyName}</div>
            <div style={{ fontSize: 10.5, color: 'rgba(255,255,255,0.5)', display: 'flex', alignItems: 'center', gap: 6 }}>
              {tweaks.tagline}
              {sub && <PlanBadge sub={sub} />}
            </div>
          </div>
        </div>

        {/* Role nav */}
        <div className="eyebrow" style={{ color: 'rgba(255,255,255,0.4)', padding: '8px 8px 6px' }}>{isOfficer ? 'ROLE VIEW' : 'YOUR WORKSPACE'}</div>
        <nav style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
          {visibleRolesList.map(r => {
            const on = role === r.id;
            const badge = roleBadges[r.id];
            const icon = { officer: <IconBuilding size={17} />, ops: <IconKanban size={17} />, safety: <IconShield size={17} />, dispatch: <IconMap size={17} />, accounting: <IconDollar size={17} /> }[r.id];
            return (
              <button key={r.id} onClick={() => setRole(r.id)} style={{
                display: 'flex', alignItems: 'center', gap: 11, padding: '10px 12px',
                background: on ? 'rgba(255,255,255,0.08)' : 'transparent',
                border: 'none',
                borderLeft: on ? '3px solid var(--accent)' : '3px solid transparent',
                borderRadius: 8, cursor: 'pointer', textAlign: 'left',
                color: on ? '#fff' : 'rgba(255,255,255,0.65)',
              }}>
                <span style={{ color: on ? 'var(--accent)' : 'rgba(255,255,255,0.5)' }}>{icon}</span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13.5, fontWeight: on ? 600 : 500 }}>{r.label}</div>
                  <div style={{ fontSize: 10.5, color: 'rgba(255,255,255,0.4)' }}>{r.short}</div>
                </div>
                {badge > 0 && (
                  <span style={{
                    background: r.id === 'safety' ? 'var(--bad)' : 'var(--accent)',
                    color: '#fff', fontSize: 10.5, fontWeight: 700, fontFamily: 'var(--font-mono)',
                    padding: '1px 6px', borderRadius: 8,
                  }}>{badge}</span>
                )}
              </button>
            );
          })}
        </nav>

        {/* System / backend admin entry */}
        {isOfficer && (
        <button onClick={() => setRole('system')} style={{
          display: 'flex', alignItems: 'center', gap: 11, padding: '10px 12px', marginTop: 8,
          background: role === 'system' ? 'rgba(255,255,255,0.08)' : 'transparent',
          borderLeft: role === 'system' ? '3px solid var(--accent)' : '3px solid transparent',
          border: 'none', borderRadius: 8, cursor: 'pointer', textAlign: 'left',
          color: role === 'system' ? '#fff' : 'rgba(255,255,255,0.65)',
        }}>
          <span style={{ color: role === 'system' ? 'var(--accent)' : 'rgba(255,255,255,0.5)' }}><IconSettings size={17} /></span>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13.5, fontWeight: role === 'system' ? 600 : 500 }}>System</div>
            <div style={{ fontSize: 10.5, color: 'rgba(255,255,255,0.4)' }}>BACKEND</div>
          </div>
        </button>
        )}

        {/* Developer / API entry (officer-only) */}
        {isOfficer && (
        <button onClick={() => setRole('developer')} style={{
          display: 'flex', alignItems: 'center', gap: 11, padding: '10px 12px', marginTop: 4,
          background: role === 'developer' ? 'rgba(255,255,255,0.08)' : 'transparent',
          borderLeft: role === 'developer' ? '3px solid var(--accent)' : '3px solid transparent',
          border: 'none', borderRadius: 8, cursor: 'pointer', textAlign: 'left',
          color: role === 'developer' ? '#fff' : 'rgba(255,255,255,0.65)',
        }}>
          <span style={{ color: role === 'developer' ? 'var(--accent)' : 'rgba(255,255,255,0.5)' }}><IconPlug size={17} /></span>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13.5, fontWeight: role === 'developer' ? 600 : 500 }}>API &amp; Webhooks</div>
            <div style={{ fontSize: 10.5, color: 'rgba(255,255,255,0.4)' }}>DEVELOPER</div>
          </div>
          {!RFP.addon('api-webhooks') && <span style={{ fontSize: 9, fontWeight: 700, color: 'var(--accent)', background: 'rgba(229,91,19,0.15)', padding: '2px 6px', borderRadius: 4 }}>ADD-ON</span>}
        </button>
        )}

        <div style={{ flex: 1 }} />

        {/* Pending approvals mini */}
        <div style={{
          background: 'rgba(229,91,19,0.1)', border: '1px solid rgba(229,91,19,0.25)',
          borderRadius: 10, padding: '12px 14px', marginBottom: 12,
        }}>
          <div className="eyebrow" style={{ color: 'rgba(255,255,255,0.55)', fontSize: 9.5 }}>PENDING APPROVAL</div>
          <div className="mono" style={{ fontSize: 22, fontWeight: 700, color: '#fff', marginTop: 2 }}>{pendingTotal} cards</div>
          <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.55)', marginTop: 1 }}>two-step workflow</div>
        </div>

        {/* Officer access chip + link to tablet */}
        <div style={{
          background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.08)',
          borderRadius: 10, padding: '10px 12px', marginBottom: 10,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <div style={{ width: 30, height: 30, borderRadius: 15, background: 'var(--accent-soft)', color: 'var(--accent-deep)', display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 700 }}>{A_initials(session.name)}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12.5, fontWeight: 600, color: '#fff', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{session.name}</div>
              <div className="mono" style={{ fontSize: 10, color: 'rgba(255,255,255,0.5)', textTransform: 'capitalize' }}>{session.role}{session.viaCode ? ' · code' : ''}</div>
            </div>
            <button onClick={onLogout} title="Sign out" style={{ background: 'transparent', border: '1px solid rgba(255,255,255,0.12)', borderRadius: 8, padding: '5px 8px', color: 'rgba(255,255,255,0.6)', cursor: 'pointer', fontSize: 11 }}>Sign out</button>
          </div>
        </div>

        <a href="../index.html" style={{
          display: 'flex', alignItems: 'center', gap: 8, padding: '9px 12px',
          background: 'transparent', border: '1px solid rgba(255,255,255,0.1)',
          borderRadius: 9, color: 'rgba(255,255,255,0.7)', textDecoration: 'none',
          fontSize: 12.5, fontWeight: 500,
        }}>
          <IconArrowRight size={14} style={{ transform: 'rotate(180deg)' }} /> Open field tablet
        </a>
        <a href="../portal/index.html" style={{
          display: 'flex', alignItems: 'center', gap: 8, padding: '9px 12px', marginTop: 8,
          background: 'transparent', border: '1px solid rgba(255,255,255,0.1)',
          borderRadius: 9, color: 'rgba(255,255,255,0.7)', textDecoration: 'none',
          fontSize: 12.5, fontWeight: 500,
        }}>
          <IconUser size={14} /> Open employee portal
        </a>
      </aside>

      {/* Main */}
      <main style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', background: 'var(--bg)', position: 'relative' }}>
        <SubBanner sub={sub} />
        {role === 'officer'    && <RoleOfficer />}
        {role === 'ops'        && <RoleOps />}
        {role === 'safety'     && <RoleSafety />}
        {role === 'dispatch'   && <RoleDispatch />}
        {role === 'accounting' && <RoleAccounting />}
        {role === 'system'     && <RoleSystem />}
        {role === 'developer'  && <DeveloperView />}

        {/* Drawers live over main */}
        <EmployeeDrawer />
        <TimecardDrawer />
        <PayrollRunWizard />
        <DocHost />

        {/* Toasts */}
        <div style={{ position: 'absolute', bottom: 20, right: 20, display: 'flex', flexDirection: 'column', gap: 8, zIndex: 400 }}>
          {toasts.map(t => (
            <div key={t.id} className="anim-up" style={{
              background: t.kind === 'success' ? 'var(--good)' : t.kind === 'warn' ? 'var(--warn)' : t.kind === 'bad' ? 'var(--bad)' : '#0F172A',
              color: '#fff', padding: '11px 16px', borderRadius: 10,
              fontSize: 13, fontWeight: 500, boxShadow: 'var(--shadow-lg)',
              display: 'flex', alignItems: 'center', gap: 8, maxWidth: 360,
            }}>
              <IconCheckCircle size={16} /> {t.text}
            </div>
          ))}
        </div>
      </main>
    </>
  );
}

// ── Employee drawer ──────────────────────────────────────────
function EmployeeDrawer() {
  const { employeeDrawer, setEmployeeDrawer, timecards, jobs, taxPolicy, ytdGross, launchDoc } = useAdmin();
  const e = employeeDrawer;
  if (!e) return null;
  const myCards = timecards.filter(t => t.employeeId === e.id);
  const hrs = myCards.reduce((s, t) => s + t.total, 0);
  const ot = myCards.reduce((s, t) => s + t.overtime, 0);
  const gross = hrs * e.baseRate;
  const expDays = Math.round((new Date(e.certExpires) - new Date()) / 86400000);

  return (
    <Drawer open={!!e} onClose={() => setEmployeeDrawer(null)} eyebrow={`${e.role} · ${e.badge}`} title={e.name} width={560}
      footer={<>
        <Button variant="secondary" onClick={() => setEmployeeDrawer(null)}>Close</Button>
        <Button variant="secondary" icon={<IconRRB size={14} />} onClick={() => launchDoc(buildW2({ company: 'RailFlagsPro LLC', employee: e, ytdGross: ytdGross[e.id] }))}>W-2</Button>
        <Button variant="primary" icon={<IconClipboard size={14} />} onClick={() => launchDoc(buildPayStub({ company: 'RailFlagsPro LLC', employee: e, cards: myCards, taxPolicy, ytdGross: ytdGross[e.id] }))}>Pay stub</Button>
      </>}>
      {/* Header card */}
      <div style={{ display: 'flex', gap: 16, marginBottom: 20 }}>
        <div style={{ width: 64, height: 64, borderRadius: 16, background: 'var(--accent-soft)', color: 'var(--accent-deep)', display: 'grid', placeItems: 'center', fontSize: 22, fontWeight: 700 }}>{e.avatar}</div>
        <div style={{ flex: 1 }}>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 6 }}>
            {e.status === 'on-duty' ? <Pill tone="good"><StatusDot tone="good" size={6} pulse /> On duty</Pill> : <Pill tone="neutral">Off duty</Pill>}
            {e.rrbContributor ? <Pill tone="info">Railroad Retirement</Pill> : <Pill tone="neutral">FICA only</Pill>}
          </div>
          <div style={{ fontSize: 13, color: 'var(--muted)', lineHeight: 1.6 }}>
            {e.cert}<br />
            <span className="mono">{e.phone}</span> · {e.homeBase}
          </div>
        </div>
      </div>

      {/* Period stats */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginBottom: 20 }}>
        <DrawerStat label="Period hours" value={A_fmtNum(hrs, 1)} />
        <DrawerStat label="OT hours" value={A_fmtNum(ot, 1)} tone="warn" />
        <DrawerStat label="Gross" value={A_fmtCurrency(gross)} tone="accent" />
      </div>

      {/* Payroll profile */}
      <div className="eyebrow" style={{ marginBottom: 8 }}>PAYROLL PROFILE</div>
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10, marginBottom: 20 }}>
        {[
          ['Base rate', `${A_fmtCurrency(e.baseRate)}/hr`],
          ['Resident state', e.resident],
          ['Pay frequency', e.payrollFreq],
          ['Retirement', e.rrbContributor ? 'Railroad Retirement (Tier I + II)' : 'FICA (Social Security + Medicare)'],
          ['Cert expires', `${e.certExpires} · ${expDays} days`],
          ['Hire date', e.hireDate],
        ].map(([k, v], i) => (
          <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '10px 14px', borderTop: i === 0 ? 'none' : '1px solid var(--line)', fontSize: 13 }}>
            <span style={{ color: 'var(--muted)' }}>{k}</span>
            <span style={{ fontWeight: 600 }} className={k === 'Resident state' || k === 'Cert expires' || k === 'Base rate' ? 'mono' : ''}>{v}</span>
          </div>
        ))}
      </div>

      {/* Recent timecards */}
      <div className="eyebrow" style={{ marginBottom: 8 }}>TIMECARDS THIS PERIOD</div>
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10 }}>
        {myCards.map((t, i) => {
          const job = jobs.find(j => j.id === t.jobId);
          return (
            <div key={t.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderTop: i === 0 ? 'none' : '1px solid var(--line)' }}>
              <span className="mono" style={{ fontSize: 12, color: 'var(--muted)', minWidth: 48 }}>{A_fmtDateShort(t.date)}</span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 12.5, fontWeight: 500 }}>
                  {t.blocks.map(b => b.code).join(' · ')} <span style={{ color: 'var(--muted)' }}>· {job?.id}</span>
                </div>
              </div>
              <span className="mono" style={{ fontSize: 12.5, fontWeight: 600 }}>{t.total.toFixed(1)}h</span>
              <TimecardStatusPill status={t.status} />
            </div>
          );
        })}
      </div>
    </Drawer>
  );
}

function DrawerStat({ label, value, tone }) {
  return (
    <div style={{ background: 'var(--panel-2)', border: '1px solid var(--line)', borderRadius: 10, padding: '12px 14px' }}>
      <div className="eyebrow" style={{ fontSize: 10 }}>{label}</div>
      <div className="mono" style={{ fontSize: 19, fontWeight: 700, marginTop: 3, color: tone === 'accent' ? 'var(--accent)' : tone === 'warn' ? 'var(--warn)' : 'var(--text)' }}>{value}</div>
    </div>
  );
}

// ── Timecard drawer ──────────────────────────────────────────
function TimecardDrawer() {
  const { timecardDrawer, setTimecardDrawer, employees, jobs, updateTimecard, toast } = useAdmin();
  const t = timecardDrawer;
  if (!t) return null;
  const e = employees.find(x => x.id === t.employeeId);
  const job = jobs.find(j => j.id === t.jobId);
  const gross = t.total * (e?.baseRate || 0);

  const act = (action) => {
    const next = action === 'approve'
      ? (t.status === 'pending-ops' ? 'pending-acct' : 'approved')
      : 'rejected';
    updateTimecard(t.id, { status: next });
    toast(action === 'approve' ? 'Timecard advanced' : 'Timecard returned to employee', action === 'approve' ? 'success' : 'warn');
    setTimecardDrawer(null);
  };

  return (
    <Drawer open={!!t} onClose={() => setTimecardDrawer(null)} eyebrow={`${e?.name} · ${A_fmtDateMed(t.date)}`} title={`Timecard ${t.id.slice(-8)}`} width={580}
      footer={(t.status === 'pending-ops' || t.status === 'pending-acct') && (
        <>
          <Button variant="secondary" icon={<IconClose size={14} />} onClick={() => act('reject')}>Return</Button>
          <Button variant="primary" icon={<IconCheck size={14} />} onClick={() => act('approve')}>
            {t.status === 'pending-ops' ? 'Approve → Accounting' : 'Approve for payroll'}
          </Button>
        </>
      )}>
      <div style={{ display: 'flex', gap: 8, marginBottom: 18 }}>
        <TimecardStatusPill status={t.status} />
        {t.gpsVerified && <Pill tone="good"><IconLocation size={10} /> GPS verified</Pill>}
        {t.flags.includes('extreme-ot') && <Pill tone="warn">High OT</Pill>}
        {t.flags.includes('missing-photo') && <Pill tone="bad">Missing photo</Pill>}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginBottom: 20 }}>
        <DrawerStat label="Total" value={`${t.total.toFixed(1)}h`} />
        <DrawerStat label="Regular / OT" value={`${t.regular.toFixed(1)} / ${t.overtime.toFixed(1)}`} />
        <DrawerStat label="Gross" value={A_fmtCurrency(gross)} tone="accent" />
      </div>

      <div className="eyebrow" style={{ marginBottom: 8 }}>JOB</div>
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10, padding: '12px 14px', marginBottom: 20 }}>
        <div style={{ fontWeight: 600, fontSize: 14 }}>{job?.name}</div>
        <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 2 }}>
          <span className="mono">{job?.id}</span> · {job?.railroad} · {job?.subdivision} · MP {job?.mp} · {job?.state}
        </div>
      </div>

      <div className="eyebrow" style={{ marginBottom: 8 }}>ACTIVITY BLOCKS</div>
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10 }}>
        {t.blocks.map((b, i) => {
          const ac = codeByValue ? codeByValue(b.code) : null;
          return (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '11px 14px', borderTop: i === 0 ? 'none' : '1px solid var(--line)' }}>
              <span className="mono" style={{ fontSize: 12, fontWeight: 700, padding: '3px 8px', borderRadius: 5, background: 'var(--accent-soft)', color: 'var(--accent-deep)', minWidth: 44, textAlign: 'center' }}>{b.code}</span>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 500 }}>{ac?.label || b.code}</div>
                <div style={{ fontSize: 11, color: 'var(--muted)' }}>worked in <span className="mono" style={{ fontWeight: 600 }}>{b.state}</span></div>
              </div>
              <span className="mono" style={{ fontSize: 13.5, fontWeight: 600 }}>{b.hrs.toFixed(2)}h</span>
            </div>
          );
        })}
      </div>
    </Drawer>
  );
}

// codeByValue may not exist in this bundle — provide a minimal fallback map
const RFL_LABELS = {
  F10: 'RWIC — Railroad Flagger', F20: 'RWIC — Supervisor / Manager', F30: 'Track Inspector',
  F40: 'Observer / Construction Inspector', F50: 'Field Supervision', F60: 'CSX FCI',
  V10: 'Travel Time', L30: 'Sick', L20: 'Holiday',
};
function codeByValue(c) { return { code: c, label: RFL_LABELS[c] || c }; }

ReactDOM.createRoot(document.getElementById('root')).render(<AdminApp />);
