// HACCP TempMon — Admin screen (full HRBR V2.0 parity)
// Features: rename, OTA, WiFi, reboot, device health, MQTT bridge, activity log
function AdminScreen({
  device, live, log, broker, topicCounts,
  onPublish, onLogout,
  wifiAttempt,   onDismissWifiAttempt,
  renameAttempt, onDismissRenameAttempt,
  otaAttempt,    onDismissOtaAttempt,
  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.fwVersion ? `v${device.fwVersion}` : '—';
  const uptimeStr = live.uptimeMs != null ? formatUptime(Math.floor(live.uptimeMs / 1000)) : '—';

  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 isOnline      = device.lastMsgSec != null && device.lastMsgSec < 15;
  const onlineSub     = device.lastMsgSec == null ? 'No messages yet'
                      : device.lastMsgSec < 10    ? `Last msg ${device.lastMsgSec}s ago`
                      :                             `Stale · ${device.lastMsgSec}s ago`;

  const availableFw   = fwManifest && fwManifest.version;
  const fwOutOfDate   = availableFw && device.fwVersion && availableFw !== device.fwVersion;

  const topicRows = [
    ['temp',   '→', 'Temp reading',  topicCounts.temp    || 0],
    ['vitals', '→', 'HRBR bridge',   topicCounts.vitals  || 0],
    ['alert',  '→', 'CCP alert',     topicCounts.alert   || 0],
    ['status', '→', 'Heartbeat',     topicCounts.status  || 0],
    ['lwt',    '→', 'Last will',     topicCounts.lwt     || 0],
  ];

  return (
    <>
      {/* Header */}
      <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>{onlineSub}</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>

      {/* Toast */}
      {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>
      )}

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

      {/* ── 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 }}>
        {/* Hardware card */}
        <div className="card">
          <div className="card-title">Hardware &amp; Firmware</div>
          <div className="col gap-8">
            {[
              ['Board ID',  boardId],
              ['Firmware',  espFW],
              ['MAC',       device.mac || '—'],
              ['IP',        device.ip  || '—'],
              ['Uptime',    uptimeStr],
              ['CCP type',  live.ccpType || '—'],
              ['Battery',   live.batteryMv != null ? `${(live.batteryMv / 1000).toFixed(2)} V` : '—'],
            ].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>

        {/* Network card */}
        <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, marginBottom: 12 }}>
            <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 style={{
              display: 'inline-flex', alignItems: 'center', gap: 5,
              padding: '4px 10px', borderRadius: 100, fontSize: 12, fontWeight: 500,
              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)',
            }}>
              <span style={{ width: 7, height: 7, borderRadius: '50%', background: isOnline ? 'oklch(0.55 0.16 145)' : 'oklch(0.6 0.02 260)' }}/>
              {!device.ssid ? '—' : isOnline ? 'Connected' : 'Last seen'}
            </span>
          </div>

          {/* Current temps summary */}
          <div className="grid-2" style={{ gap: 8 }}>
            {[
              { label: 'Probe',   val: live.probeTempC },
              { label: 'Ambient', val: live.ambientTempC },
              { label: 'Cooking', val: live.cookingTempC },
              { label: 'RH',      val: live.ambientRh != null ? live.ambientRh.toFixed(1) + '%' : null, raw: true },
            ].map(({ label, val, raw }) => (
              <div key={label} style={{ padding: '10px 12px', background: 'var(--bg-sunken)', borderRadius: 8 }}>
                <div className="text-xs text-ink-4" style={{ textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 2 }}>{label}</div>
                <div className="num" style={{ fontSize: 18, fontWeight: 600 }}>
                  {raw ? (val || '—') : (val != null ? val.toFixed(1) + '°C' : '—')}
                </div>
              </div>
            ))}
          </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 style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: '4px 10px', borderRadius: 100, fontSize: 12, fontWeight: 500,
            background: 'var(--bg-sunken)', color: brokerColor,
          }}>
            <span style={{ width: 7, height: 7, borderRadius: '50%', background: brokerColor }}/>
            {brokerLabel} · HiveMQ
          </span>
        </div>
        <div className="grid-4" style={{ gap: 8 }}>
          {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 — all boards 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 */}
        <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 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}` : 'KC2507V001'}
            />
            <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 */}
        <div className="card">
          <div className="card-title">Update Firmware (OTA)</div>
          <div className="col gap-8">
            {[
              ['Running',   espFW],
              ['Available', availableFw ? `v${availableFw}${fwOutOfDate ? ' · update available' : ''}` : 'no manifest'],
            ].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" style={{ color: k === 'Available' && fwOutOfDate ? 'oklch(0.55 0.18 60)' : undefined }}>{v}</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/HACCP_TempMon.bin'}</code>, verifies, and reboots into the new image.
            </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 ~30s.`)) 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>

      <div className="grid-2" style={{ marginBottom: 16 }}>
        {/* WiFi update */}
        <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)}
                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>

        {/* Power */}
        <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 ESP32. WiFi credentials and device ID stored in NVS survive.
          </div>
          <button className="btn btn-danger" onClick={() => {
            if (confirm(`Reboot ${boardId}? 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: 36, flexShrink: 0 }}>{l.lvl}</span>
              <span style={{ flex: 1, minWidth: 0, overflowWrap: 'anywhere', wordBreak: 'break-word' }}>{l.msg}</span>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}

// ── Device health table (all boards from backend) ──
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 errMsg  = knownDevices && knownDevices.error;

  function 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)}m 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: 'var(--status-breach)', marginBottom: 12 }}>
          Could not load device list: {errMsg}
        </div>
      )}
      {status !== 'error' && items.length === 0 && (
        <div className="text-sm text-ink-3">
          {status === 'idle' || status === 'loading' ? 'Loading…' : 'No devices have published readings 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' }}>
                {['Board ID', 'Last seen', 'First seen', 'Messages', 'Status'].map(h => (
                  <th key={h} style={{ padding: '8px 4px', borderBottom: '1px solid var(--line)', fontWeight: 600, textAlign: h === 'Messages' ? 'right' : 'left' }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {items.map((d, i) => {
                const id         = d.device_id || d.board_id;
                const isCurrent  = id === selectedDevice;
                const liveOnline = isCurrent && currentlyOnlineSec != null && currentlyOnlineSec < 15;
                const recentSec  = d.last_seen ? Math.floor(Date.now() / 1000 - d.last_seen) : Infinity;
                const online     = liveOnline || recentSec < 60;
                return (
                  <tr key={id || i} style={{ background: isCurrent ? 'var(--bg-sunken)' : 'transparent' }}>
                    <td className="mono" style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)' }}>
                      {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.reading_count || d.message_count || 0).toLocaleString()}
                    </td>
                    <td style={{ padding: '10px 4px', borderBottom: '1px solid var(--line)' }}>
                      <span style={{
                        display: 'inline-flex', alignItems: 'center', gap: 5,
                        padding: '3px 9px', borderRadius: 100, fontSize: 11, fontWeight: 500,
                        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)',
                      }}>
                        <span style={{ width: 6, height: 6, borderRadius: '50%', background: online ? 'oklch(0.55 0.16 145)' : 'oklch(0.6 0.02 260)' }}/>
                        {online ? 'Online' : 'Offline'}
                      </span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ── Attempt banners ──
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 firmware`;
  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 }}>
          Requested <span className="mono" style={{ fontWeight: 600 }}>{requestedSsid}</span> but device fell back to <span className="mono" style={{ fontWeight: 600 }}>{actualSsid}</span>. Check SSID and password.
        </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 after {since}s. Device may still be rebooting or unreachable.
        </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>;
}
