// Admin screen — privileged controls (rename, OTA, WiFi, reboot) plus diagnostics.
// Regular users never see this tab; access is gated client-side in index.html.
function AdminScreen({ device, log, broker, topicCounts, onPublish, wifiAttempt, onDismissWifiAttempt, otaAttempt, onDismissOtaAttempt, renameAttempt, onDismissRenameAttempt, onLogout, fwManifest, knownDevices, onRefreshDevices, selectedDevice }) {
  const [ssid, setSsid] = React.useState('');
  const [wifiPass, setWifiPass] = React.useState('');
  const [showPass, setShowPass] = React.useState(false);
  const [renameInput, setRenameInput] = React.useState('');
  const [status, setStatus] = React.useState(null);

  const lvlColor = { info: 'var(--ink-3)', ok: 'oklch(0.55 0.15 145)', warn: 'oklch(0.6 0.17 60)', err: 'oklch(0.55 0.2 25)' };

  const show = (kind, msg) => { setStatus({ kind, msg }); setTimeout(() => setStatus(null), 3000); };
  const send = (payload, label) => {
    const ok = onPublish(payload);
    show(ok ? 'ok' : 'err', ok ? `${label} sent` : 'Not connected');
  };

  const boardId = device.boardId || '—';
  const espFW = device.espFW ? `v${device.espFW}` : '—';
  const radarFW = device.radarFW ? `v${device.radarFW}` : '—';
  const uptimeStr = device.uptimeH != null ? `${device.uptimeH.toFixed(1)} h` : '—';
  const vitalsIntStr = device.vitalsInterval != null ? `${device.vitalsInterval} s` : '—';
  const brokerLabel = { connected: 'Connected', connecting: 'Connecting', closed: 'Disconnected', error: 'Error', disconnected: 'Disconnected' }[broker] || broker;
  const brokerColor = broker === 'connected' ? 'oklch(0.55 0.15 145)' : broker === 'error' ? 'oklch(0.55 0.2 25)' : 'oklch(0.6 0.1 80)';

  const deviceOnlineSub = device.lastMsgSec == null
    ? 'No messages yet'
    : device.lastMsgSec < 10 ? `Last msg ${device.lastMsgSec}s ago` : `Stale · ${device.lastMsgSec}s ago`;
  const isOnline = device.lastMsgSec != null && device.lastMsgSec < 15;

  // Available firmware version vs running. Null fwManifest = manifest not loaded.
  const availableFw = fwManifest && fwManifest.version;
  const fwOutOfDate = availableFw && device.espFW && availableFw !== device.espFW;

  const topicRows = [
    ['vitals', '→', 'Device vitals', topicCounts.vitals || 0],
    ['target', '→', 'Radar target', topicCounts.target || 0],
    ['status', '→', 'Heartbeat', topicCounts.status || 0],
    ['lwt', '→', 'Last will', topicCounts.lwt || 0],
    ...Object.keys(topicCounts).filter(t => t.startsWith('sleep/')).map(t => [t, '←', t.endsWith('/summary') ? 'Session summary' : 'Sleep epoch', topicCounts[t]]),
  ];

  return (
    <>
      <div className="page-header">
        <div>
          <div className="page-eyebrow">Admin · device console</div>
          <h1 className="page-title">{boardId}</h1>
          <div className="page-subtitle row items-center gap-12" style={{ display: 'inline-flex', flexWrap: 'wrap' }}>
            <span className="row items-center gap-4">
              <span className="live-dot" style={{
                background: isOnline ? 'oklch(0.65 0.17 145)' : 'oklch(0.6 0.02 260)',
                boxShadow: isOnline ? '0 0 0 3px oklch(0.65 0.17 145 / 0.2)' : 'none',
              }}/>
              {isOnline ? 'Online' : 'Offline'}
            </span>
            <span>·</span>
            <span>{deviceOnlineSub}</span>
            <span>·</span>
            <span className="mono">{(device.msgCount || 0).toLocaleString()} msgs</span>
          </div>
        </div>
        <div className="row gap-8">
          <button className="btn" onClick={() => send('ping', 'Ping')}>Ping</button>
          <button className="btn btn-ghost" onClick={onLogout}>Sign out</button>
        </div>
      </div>

      {status && (
        <div className="card-flat" style={{ marginBottom: 16, color: status.kind === 'ok' ? 'oklch(0.4 0.15 145)' : 'oklch(0.5 0.2 25)' }}>
          {status.msg}
        </div>
      )}

      {wifiAttempt && <WifiAttemptBanner attempt={wifiAttempt} onDismiss={onDismissWifiAttempt} />}
      {renameAttempt && <RenameAttemptBanner attempt={renameAttempt} onDismiss={onDismissRenameAttempt} />}
      {otaAttempt && <OtaAttemptBanner attempt={otaAttempt} onDismiss={onDismissOtaAttempt} />}

      {/* ---------------- Read-only diagnostics ---------------- */}
      <div className="text-xs text-ink-3" style={{ textTransform: 'uppercase', letterSpacing: '0.12em', fontWeight: 600, margin: '8px 0 12px' }}>
        Diagnostics
      </div>

      <div className="grid-2" style={{ marginBottom: 16 }}>
        <div className="card">
          <div className="card-title">Hardware &amp; firmware</div>
          <div className="col gap-8">
            {[
              ['Board ID', boardId],
              ['ESP firmware', espFW],
              ['Radar firmware', radarFW],
              ['MAC', device.mac || '—'],
              ['IP', device.ip || '—'],
              ['Uptime', uptimeStr],
              ['Vitals interval', vitalsIntStr],
            ].map(([k, v]) => (
              <div key={k} className="row justify-between" style={{ padding: '8px 0', borderBottom: '1px solid var(--line)' }}>
                <span className="text-sm text-ink-3">{k}</span>
                <span className="text-sm mono">{v}</span>
              </div>
            ))}
          </div>
        </div>

        <div className="card">
          <div className="card-title">Network</div>
          <div className="row items-center gap-12" style={{ padding: 14, background: 'var(--bg-sunken)', borderRadius: 10 }}>
            <Icon name="wifi" size={20}/>
            <div className="flex-1">
              <div className="text-sm" style={{ fontWeight: 500 }}>{device.ssid || '—'}</div>
              <div className="text-xs text-ink-3 mono">
                {device.rssi != null ? `RSSI ${device.rssi} dBm · ${device.rssi > -60 ? 'strong' : device.rssi > -75 ? 'ok' : 'weak'}` : 'unknown'}
              </div>
            </div>
            <span className="stage-chip" style={{
              background: isOnline ? 'oklch(0.94 0.06 145)' : 'oklch(0.92 0.01 260)',
              color: isOnline ? 'oklch(0.4 0.12 145)' : 'oklch(0.45 0.02 260)',
            }}>
              {!device.ssid ? '—' : isOnline ? 'Connected' : 'Last seen'}
            </span>
          </div>
        </div>
      </div>

      {/* MQTT bridge */}
      <div className="card" style={{ marginBottom: 16 }}>
        <div className="row justify-between items-center" style={{ marginBottom: 16 }}>
          <div className="card-title" style={{ margin: 0 }}>MQTT bridge</div>
          <span className="stage-chip" style={{ background: 'oklch(0.94 0.06 145)', color: brokerColor }}>
            <span className="stage-dot" style={{ background: brokerColor }}/> {brokerLabel} · HiveMQ
          </span>
        </div>
        <div className="grid-4">
          {topicRows.map(([t, dir, desc, count]) => (
            <div key={t} className="col gap-4" style={{ padding: 12, background: 'var(--bg-sunken)', borderRadius: 8 }}>
              <span className="mono text-xs text-ink-3">{dir} {t}</span>
              <span className="text-sm" style={{ fontWeight: 500 }}>{desc}</span>
              <span className="num text-xs text-ink-3">{count.toLocaleString()} msgs</span>
            </div>
          ))}
        </div>
      </div>

      {/* Device health — every board ever seen by the backend */}
      <DeviceHealthCard
        knownDevices={knownDevices}
        onRefresh={onRefreshDevices}
        selectedDevice={selectedDevice}
        currentlyOnlineSec={device.lastMsgSec}
      />

      {/* ---------------- Controls ---------------- */}
      <div className="text-xs text-ink-3" style={{ textTransform: 'uppercase', letterSpacing: '0.12em', fontWeight: 600, margin: '24px 0 12px' }}>
        Controls
      </div>

      <div className="grid-2" style={{ marginBottom: 16 }}>
        {/* Rename device */}
        <div className="card">
          <div className="card-title">Rename device</div>
          <div className="text-xs text-ink-3" style={{ marginBottom: 12, lineHeight: 1.5 }}>
            Sets a new <code>board_id</code> in NVS and reboots. Use the canonical format <code>KC2507V0XX</code> for production units.
          </div>
          <div className="col gap-8">
            <input className="btn" style={{ width: '100%', padding: '10px 14px', textAlign: 'left', fontFamily: 'inherit' }}
              value={renameInput} onChange={e => setRenameInput(e.target.value)} placeholder={boardId !== '—' ? `e.g. ${boardId}` : 'KC2507V005'} />
            <div className="row gap-8">
              <button className="btn btn-primary" onClick={() => {
                const id = renameInput.trim();
                if (!id) { show('err', 'New ID required'); return; }
                if (id.length > 32) { show('err', 'ID too long (max 32 chars)'); return; }
                if (id === boardId) { show('err', 'Same as current ID'); return; }
                if (!confirm(`Rename ${boardId} → ${id}? Device will reboot.`)) return;
                send({ set_device_id: id }, 'Rename');
                setRenameInput('');
              }}>Push to device</button>
              <button className="btn btn-ghost" onClick={() => setRenameInput('')}>Clear</button>
            </div>
          </div>
        </div>

        {/* OTA firmware */}
        <div className="card">
          <div className="card-title">Update firmware (OTA)</div>
          <div className="col gap-8">
            <div className="row justify-between" style={{ padding: '8px 0', borderBottom: '1px solid var(--line)' }}>
              <span className="text-sm text-ink-3">Running</span>
              <span className="text-sm mono">{espFW}</span>
            </div>
            <div className="row justify-between" style={{ padding: '8px 0', borderBottom: '1px solid var(--line)' }}>
              <span className="text-sm text-ink-3">Available</span>
              <span className="text-sm mono">
                {availableFw ? `v${availableFw}` : 'no manifest'}
                {fwOutOfDate && <span style={{ color: 'oklch(0.55 0.18 60)', marginLeft: 6 }}>· update</span>}
              </span>
            </div>
            <div className="text-xs text-ink-3" style={{ marginTop: 4, lineHeight: 1.5 }}>
              Device downloads the binary from <code>{(fwManifest && fwManifest.url) || '/firmware/HRBR_V4.0.bin'}</code>, verifies the flash, and reboots into the new image. WiFi and device ID survive.
            </div>
            <button className="btn btn-primary" disabled={!availableFw}
              onClick={() => {
                if (!fwManifest || !fwManifest.url) { show('err', 'No firmware manifest'); return; }
                if (!confirm(`Push firmware v${availableFw} to ${boardId}? Device will be unavailable for ~30 s.`)) return;
                const url = new URL(fwManifest.url, location.origin).toString();
                send({ ota: { url } }, 'OTA update');
              }}>
              {fwOutOfDate ? `Update to v${availableFw}` : (availableFw ? 'Reflash current version' : 'No manifest')}
            </button>
          </div>
        </div>
      </div>

      {/* WiFi + Reboot row */}
      <div className="grid-2" style={{ marginBottom: 16 }}>
        <div className="card">
          <div className="card-title">Update WiFi</div>
          <div className="col gap-8">
            <input className="btn" style={{ width: '100%', padding: '10px 14px', textAlign: 'left', fontFamily: 'inherit' }}
              value={ssid} onChange={e => setSsid(e.target.value)} placeholder="SSID" />
            <div style={{ position: 'relative' }}>
              <input type={showPass ? 'text' : 'password'} className="btn"
                style={{ width: '100%', padding: '10px 42px 10px 14px', textAlign: 'left', fontFamily: 'inherit' }}
                value={wifiPass} onChange={e => setWifiPass(e.target.value)} placeholder="Password" autoComplete="off" />
              <button type="button" onClick={() => setShowPass(v => !v)} aria-label={showPass ? 'Hide password' : 'Show password'}
                style={{
                  position: 'absolute', right: 6, top: '50%', transform: 'translateY(-50%)',
                  background: 'transparent', border: 'none', padding: 6, cursor: 'pointer',
                  color: 'var(--ink-3)', display: 'grid', placeItems: 'center',
                }}>
                <EyeIcon open={showPass} size={16}/>
              </button>
            </div>
            <div className="row gap-8" style={{ flexWrap: 'wrap' }}>
              <button className="btn btn-primary" onClick={() => {
                if (!ssid) { show('err', 'SSID required'); return; }
                send({ set_wifi: { ssid, password: wifiPass } }, 'WiFi credentials');
                setSsid(''); setWifiPass('');
              }}>Push to device</button>
              <button className="btn btn-ghost" onClick={() => { setSsid(''); setWifiPass(''); }}>Clear form</button>
              <button className="btn btn-ghost btn-danger" onClick={() => {
                if (confirm('Clear stored WiFi on device and reboot?')) send({ clear_wifi: true }, 'WiFi clear');
              }}>Clear stored</button>
            </div>
          </div>
        </div>

        <div className="card">
          <div className="card-title">Power</div>
          <div className="text-xs text-ink-3" style={{ marginBottom: 12, lineHeight: 1.5 }}>
            Reboot cycles the device. WiFi credentials and device ID stored in NVS survive.
          </div>
          <button className="btn btn-danger" onClick={() => {
            if (confirm('Reboot the device? It will be unavailable for ~15s.')) send('reboot', 'Reboot');
          }}>Reboot device</button>
        </div>
      </div>

      {/* Activity log */}
      <div className="card">
        <div className="row justify-between items-center" style={{ marginBottom: 16 }}>
          <div className="card-title" style={{ margin: 0 }}>Activity log</div>
          <span className="text-xs text-ink-3">{log.length} entries</span>
        </div>
        <div className="mono" style={{
          background: 'var(--bg-sunken)', borderRadius: 8, padding: 16,
          fontSize: 12, lineHeight: 1.8, maxHeight: 280, overflow: 'auto',
        }}>
          {log.length === 0 && <div className="text-ink-3">No activity yet.</div>}
          {log.map((l, i) => (
            <div key={i} className="row gap-12" style={{ alignItems: 'flex-start' }}>
              <span className="text-ink-3" style={{ flexShrink: 0 }}>{l.t}</span>
              <span style={{ color: lvlColor[l.lvl], textTransform: 'uppercase', fontSize: 10, width: 40, flexShrink: 0 }}>{l.lvl}</span>
              <span style={{ flex: 1, minWidth: 0, overflowWrap: 'anywhere', wordBreak: 'break-word' }}>{l.msg}</span>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}

function DeviceHealthCard({ knownDevices, onRefresh, selectedDevice, currentlyOnlineSec }) {
  React.useEffect(() => {
    if (knownDevices && knownDevices.status === 'idle' && onRefresh) onRefresh();
  }, []);

  const items = (knownDevices && knownDevices.items) || [];
  const status = knownDevices && knownDevices.status;
  const errorMsg = knownDevices && knownDevices.error;

  const fmtAge = (ts) => {
    if (!ts) return '—';
    const sec = Math.max(0, Math.floor(Date.now() / 1000 - ts));
    if (sec < 60) return `${sec}s ago`;
    if (sec < 3600) return `${Math.round(sec / 60)} min ago`;
    if (sec < 86400) return `${Math.round(sec / 3600)} h ago`;
    return `${Math.round(sec / 86400)} d ago`;
  };

  return (
    <div className="card" style={{ marginBottom: 16 }}>
      <div className="row justify-between items-center" style={{ marginBottom: 12, flexWrap: 'wrap', gap: 8 }}>
        <div className="card-title" style={{ margin: 0 }}>Device health · all boards</div>
        <button className="btn btn-sm btn-ghost" onClick={onRefresh} disabled={status === 'loading'}>
          {status === 'loading' ? 'Refreshing…' : 'Refresh'}
        </button>
      </div>
      {status === 'error' && (
        <div className="text-sm" style={{ color: 'oklch(0.55 0.2 25)', marginBottom: 12 }}>
          Could not load device list: {errorMsg}
        </div>
      )}
      {status === 'ready' && items.length === 0 && (
        <div className="text-sm text-ink-3">No devices have published vitals yet.</div>
      )}
      {items.length > 0 && (
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr style={{ textAlign: 'left', color: 'var(--ink-3)', fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.08em' }}>
                <th style={{ padding: '8px 4px', borderBottom: '1px solid var(--line)' }}>Board ID</th>
                <th style={{ padding: '8px 4px', borderBottom: '1px solid var(--line)' }}>Last seen</th>
                <th style={{ padding: '8px 4px', borderBottom: '1px solid var(--line)' }}>First seen</th>
                <th style={{ padding: '8px 4px', borderBottom: '1px solid var(--line)', textAlign: 'right' }}>Messages</th>
                <th style={{ padding: '8px 4px', borderBottom: '1px solid var(--line)' }}>Status</th>
              </tr>
            </thead>
            <tbody>
              {items.map((d) => {
                const isCurrent = d.board_id === selectedDevice;
                const liveOnline = isCurrent && currentlyOnlineSec != null && currentlyOnlineSec < 15;
                // Backend gives last_seen as unix epoch seconds. If less than 60s old, treat as live.
                const recentSec = d.last_seen ? Math.floor(Date.now() / 1000 - d.last_seen) : Infinity;
                const inferredOnline = recentSec < 60;
                const online = liveOnline || inferredOnline;
                return (
                  <tr key={d.board_id} style={{ background: isCurrent ? 'var(--bg-sunken)' : 'transparent' }}>
                    <td className="mono" style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)' }}>
                      {d.board_id}{isCurrent && <span className="text-xs text-ink-3" style={{ marginLeft: 6 }}>(selected)</span>}
                    </td>
                    <td className="text-ink-2" style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)' }}>{fmtAge(d.last_seen)}</td>
                    <td className="text-ink-3" style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)' }}>{fmtAge(d.first_seen)}</td>
                    <td className="num text-ink-2" style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)', textAlign: 'right' }}>
                      {(d.message_count || 0).toLocaleString()}
                    </td>
                    <td style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)' }}>
                      <span className="stage-chip" style={{
                        background: online ? 'oklch(0.94 0.06 145)' : 'oklch(0.94 0.01 260)',
                        color: online ? 'oklch(0.4 0.12 145)' : 'oklch(0.5 0.02 260)',
                        fontSize: 11,
                      }}>
                        <span className="stage-dot" style={{ background: online ? 'oklch(0.55 0.16 145)' : 'oklch(0.6 0.02 260)' }}/>
                        {online ? 'Online' : 'Offline'}
                      </span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function RenameAttemptBanner({ attempt, onDismiss }) {
  const tone = attempt.status === 'ok' ? 'ok' : attempt.status === 'failed' ? 'err' : 'pending';
  const palette = {
    ok:      { bg: 'oklch(0.96 0.04 145)', accent: 'oklch(0.5 0.16 145)' },
    err:     { bg: 'oklch(0.96 0.04 25)',  accent: 'oklch(0.55 0.2 25)' },
    pending: { bg: 'oklch(0.96 0.02 260)', accent: 'oklch(0.45 0.05 260)' },
  }[tone];
  const heading = attempt.status === 'ok'
    ? `Renamed to ${attempt.newId}`
    : attempt.status === 'failed'
      ? `Rename failed`
      : `Renaming → ${attempt.newId} (waiting for reboot)`;
  return (
    <div className="card-flat" style={{ marginBottom: 16, borderLeft: `3px solid ${palette.accent}`, background: palette.bg }}>
      <div className="row justify-between items-start gap-12">
        <div>
          <div className="text-sm" style={{ fontWeight: 600, color: palette.accent }}>{heading}</div>
          {attempt.error && <div className="text-xs text-ink-3" style={{ marginTop: 4 }}>{attempt.error}</div>}
        </div>
        {onDismiss && <button className="btn btn-ghost btn-sm" onClick={onDismiss}>Dismiss</button>}
      </div>
    </div>
  );
}

function OtaAttemptBanner({ attempt, onDismiss }) {
  const tone = attempt.status === 'ok' ? 'ok' : attempt.status === 'failed' ? 'err' : 'pending';
  const palette = {
    ok:      { bg: 'oklch(0.96 0.04 145)', accent: 'oklch(0.5 0.16 145)' },
    err:     { bg: 'oklch(0.96 0.04 25)',  accent: 'oklch(0.55 0.2 25)' },
    pending: { bg: 'oklch(0.96 0.02 260)', accent: 'oklch(0.45 0.05 260)' },
  }[tone];
  const heading = attempt.status === 'ok'
    ? `OTA succeeded · running v${attempt.newVersion}`
    : attempt.status === 'failed'
      ? `OTA failed`
      : `OTA in progress · downloading from ${attempt.url}`;
  return (
    <div className="card-flat" style={{ marginBottom: 16, borderLeft: `3px solid ${palette.accent}`, background: palette.bg }}>
      <div className="row justify-between items-start gap-12">
        <div>
          <div className="text-sm" style={{ fontWeight: 600, color: palette.accent }}>{heading}</div>
          {attempt.error && <div className="text-xs text-ink-3" style={{ marginTop: 4 }}>{attempt.error}</div>}
        </div>
        {onDismiss && <button className="btn btn-ghost btn-sm" onClick={onDismiss}>Dismiss</button>}
      </div>
    </div>
  );
}

function WifiAttemptBanner({ attempt, onDismiss }) {
  const { status, requestedSsid, actualSsid, requestedAt } = attempt;
  const since = Math.max(0, Math.round((Date.now() - requestedAt) / 1000));

  if (status === 'pending') {
    return (
      <div className="card" style={{
        marginBottom: 16, padding: '14px 18px',
        borderLeft: '3px solid var(--accent)', background: 'var(--accent-soft)',
        display: 'flex', alignItems: 'center', gap: 16,
      }}>
        <div className="flex-1">
          <div style={{ fontWeight: 600, color: 'var(--accent-ink)', fontSize: 14 }}>Verifying WiFi change…</div>
          <div className="text-xs text-ink-3" style={{ marginTop: 2 }}>
            Waiting for device to reboot and reconnect to <span className="mono">{requestedSsid}</span> ({since}s elapsed).
          </div>
        </div>
      </div>
    );
  }

  if (status === 'ok') {
    return (
      <div className="card" style={{
        marginBottom: 16, padding: '14px 18px',
        borderLeft: '3px solid oklch(0.6 0.16 145)', background: 'oklch(0.95 0.05 145)',
        display: 'flex', alignItems: 'center', gap: 16,
      }}>
        <div className="flex-1">
          <div style={{ fontWeight: 600, color: 'oklch(0.35 0.15 145)', fontSize: 14 }}>WiFi change confirmed</div>
          <div className="text-xs" style={{ marginTop: 2, color: 'oklch(0.4 0.1 145)' }}>
            Device is now on <span className="mono">{actualSsid}</span>.
          </div>
        </div>
        <button className="btn btn-sm btn-ghost" onClick={onDismiss}>Dismiss</button>
      </div>
    );
  }

  if (status === 'failed') {
    return (
      <div className="card" style={{
        marginBottom: 16, padding: '14px 18px',
        borderLeft: '3px solid oklch(0.55 0.2 25)', background: 'oklch(0.96 0.04 25)',
        display: 'flex', alignItems: 'flex-start', gap: 16,
      }}>
        <div className="flex-1">
          <div style={{ fontWeight: 600, color: 'oklch(0.4 0.18 25)', fontSize: 14 }}>WiFi change failed</div>
          <div className="text-sm" style={{ marginTop: 4, color: 'oklch(0.35 0.1 25)', lineHeight: 1.5 }}>
            You requested <span className="mono" style={{ fontWeight: 600 }}>{requestedSsid}</span>, but the device fell back and is now on <span className="mono" style={{ fontWeight: 600 }}>{actualSsid}</span>. Check the SSID and password for typos.
          </div>
        </div>
        <button className="btn btn-sm btn-ghost" onClick={onDismiss}>Dismiss</button>
      </div>
    );
  }

  if (status === 'timeout') {
    return (
      <div className="card" style={{
        marginBottom: 16, padding: '14px 18px',
        borderLeft: '3px solid oklch(0.6 0.17 60)', background: 'oklch(0.96 0.05 60)',
        display: 'flex', alignItems: 'center', gap: 16,
      }}>
        <div className="flex-1">
          <div style={{ fontWeight: 600, color: 'oklch(0.4 0.14 60)', fontSize: 14 }}>WiFi verification timed out</div>
          <div className="text-xs" style={{ marginTop: 2, color: 'oklch(0.4 0.1 60)' }}>
            No status heartbeat received after {since}s. Device may still be rebooting or unreachable. Try Ping once it reappears.
          </div>
        </div>
        <button className="btn btn-sm btn-ghost" onClick={onDismiss}>Dismiss</button>
      </div>
    );
  }

  return null;
}

function EyeIcon({ open, size = 16 }) {
  const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' };
  if (open) {
    return <svg {...p}><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></svg>;
  }
  return <svg {...p}><path d="M17.94 17.94A10.94 10.94 0 0 1 12 19c-7 0-11-7-11-7a19.78 19.78 0 0 1 4.06-4.88"/><path d="M9.9 4.24A10.94 10.94 0 0 1 12 4c7 0 11 7 11 7a19.69 19.69 0 0 1-3.08 4.06"/><path d="M9.88 9.88a3 3 0 0 0 4.24 4.24"/><path d="M1 1l22 22"/></svg>;
}

window.AdminScreen = AdminScreen;
