// Edgesense main app

const D = window.EDGE_DATA;

// Status color helpers
const aqiTier = (v) => {
  if (v <= 50)  return { label: 'Good',                   color: 'var(--good)',  hue: 'oklch(86% 0.10 160)' };
  if (v <= 100) return { label: 'Moderate',               color: 'oklch(70% 0.16 92)', hue: 'oklch(86% 0.13 110)' };
  if (v <= 150) return { label: 'Unhealthy for sensitive',color: 'var(--warn)', hue: 'oklch(82% 0.16 70)' };
  return { label: 'Unhealthy',                            color: 'var(--bad)',  hue: 'oklch(70% 0.16 30)' };
};

// ---- Hero AQI panel ----
const HeroAQI = () => {
  const tier = aqiTier(D.current.aqi);
  return (
    <Card style={{ padding: 24, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24, alignItems: 'stretch' }}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>
          <span className="pulse-dot" style={{ width: 6, height: 6, borderRadius: '50%', background: tier.color }} />
          Composite Air Quality Index
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-end', gap: 18, flexWrap: 'wrap' }}>
          <span className="serif" style={{ fontSize: 110, lineHeight: 0.85, letterSpacing: '-0.04em', display: 'block' }}>{D.current.aqi}</span>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, paddingBottom: 8 }}>
            <span style={{ fontSize: 20, fontWeight: 500, letterSpacing: '-0.01em' }}>{tier.label}</span>
            <span style={{ fontSize: 12, color: 'var(--ink-3)', fontFamily: 'Geist Mono' }}>0–50 range · best in 30d</span>
          </div>
        </div>
        <p style={{ margin: 0, fontSize: 13.5, color: 'var(--ink-2)', lineHeight: 1.55, maxWidth: 380 }}>
          Air is fresh and well-ventilated. PM2.5 is trending down. Suitable for prolonged
          activity, including those with respiratory sensitivities.
        </p>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 4 }}>
          {[
            { k: 'Comfort',       v: D.indices.comfort,       hint: 'thermal & humidity' },
            { k: 'Productivity',  v: D.indices.productivity,  hint: 'CO₂ + noise model' },
            { k: 'Breathability', v: D.indices.breathability, hint: 'PM / VOC / O₃' },
          ].map(p => (
            <div key={p.k} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '8px 12px',
              border: '1px solid var(--line)', borderRadius: 12,
              background: 'var(--bg)',
            }}>
              <PercentRing value={p.v} size={42} stroke={4} />
              <div style={{ lineHeight: 1.2 }}>
                <div style={{ fontSize: 12.5, fontWeight: 500 }}>{p.k}</div>
                <div style={{ fontSize: 10.5, color: 'var(--ink-4)', fontFamily: 'Geist Mono' }}>{p.hint}</div>
              </div>
            </div>
          ))}
        </div>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'stretch' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <div>
            <div style={{ fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>
              24h Forecast
            </div>
            <div style={{ fontSize: 13.5, color: 'var(--ink-2)', marginTop: 4, maxWidth: 280 }}>
              Mild increase expected after sunset as outside winds shift westward.
            </div>
          </div>
          <span style={{
            fontSize: 11, fontFamily: 'Geist Mono', padding: '4px 8px',
            borderRadius: 999, border: '1px solid var(--line)',
            color: 'var(--ink-3)', display: 'inline-flex', alignItems: 'center', gap: 6,
          }}>
            <Icon name="sparkles" size={11} />
            ML model · v3.2
          </span>
        </div>
        <div style={{ position: 'relative', alignSelf: 'center', marginTop: 4 }}>
          <AQIGauge value={D.current.aqi} max={200} size={210} />
        </div>
        <div>
          <ForecastBars data={D.forecast.aqi} height={88} />
          <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 4, fontSize: 10.5, color: 'var(--ink-4)', fontFamily: 'Geist Mono' }}>
            <span>now · 41</span>
            <span>peak · 68 (+18h)</span>
            <span>avg · 51</span>
          </div>
        </div>
      </div>
    </Card>
  );
};

// ---- Metrics grid ----
const MetricsGrid = () => {
  const c = D.current, d = D.deltas, s = D.series;
  // hue = lighter chip background, line = deeper stroke for the sparkline
  const items = [
    { label: 'Temperature', icon: 'thermo',  value: c.temperature, unit: '°C',    delta: d.temperature, series: s.temperature, hue: 'oklch(88% 0.10 30)',  line: 'oklch(60% 0.16 30)',  dp: 1, status: 'optimal' },
    { label: 'Humidity',    icon: 'drop',    value: c.humidity,    unit: '%',     delta: d.humidity,    series: s.humidity,    hue: 'oklch(88% 0.09 220)', line: 'oklch(58% 0.13 230)', dp: 1, status: 'normal' },
    { label: 'CO₂',         icon: 'wind',    value: c.co2,         unit: 'ppm',   delta: d.co2,         series: s.co2,         hue: 'oklch(88% 0.09 290)', line: 'oklch(58% 0.14 290)', dp: 0, status: 'normal' },
    { label: 'PM2.5',       icon: 'cloud',   value: c.pm25,        unit: 'µg/m³', delta: d.pm25,        series: s.pm25,        hue: 'oklch(88% 0.10 140)', line: 'oklch(58% 0.14 140)', dp: 1, status: 'low' },
    { label: 'PM10',        icon: 'cloud',   value: c.pm10,        unit: 'µg/m³', delta: d.pm10,        series: s.pm10,        hue: 'oklch(88% 0.09 120)', line: 'oklch(58% 0.14 120)', dp: 1, status: 'low' },
    { label: 'VOC',         icon: 'leaf',    value: c.voc,         unit: 'ppm',   delta: d.voc,         series: s.voc,         hue: 'oklch(88% 0.09 95)',  line: 'oklch(60% 0.14 95)',  dp: 2, status: 'low' },
    { label: 'Pressure',    icon: 'gauge',   value: c.pressure,    unit: 'hPa',   delta: d.pressure,    series: s.pressure,    hue: 'oklch(88% 0.07 260)', line: 'oklch(55% 0.12 260)', dp: 1, status: 'steady' },
    { label: 'NO₂',         icon: 'cloud',   value: c.no2,         unit: 'ppb',   delta: d.no2,         series: s.no2,         hue: 'oklch(88% 0.10 60)',  line: 'oklch(60% 0.15 60)',  dp: 0, status: 'normal' },
    { label: 'Noise',       icon: 'activity',value: c.noise,       unit: 'dBA',   delta: d.noise,       series: s.noise,       hue: 'oklch(88% 0.07 320)', line: 'oklch(58% 0.13 320)', dp: 0, status: 'quiet' },
  ];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14 }}>
      {items.map(it => (
        <MetricCard key={it.label} metric={it.label} {...it} />
      ))}
    </div>
  );
};

// ---- Weekly Trends ----
const TrendsPanel = () => {
  const [on, setOn] = React.useState({
    temperature: true, humidity: true, pressure: false, co2: false, pm25: true,
  });
  const palette = {
    temperature: 'oklch(64% 0.18 30)',
    humidity:    'oklch(60% 0.15 240)',
    pressure:    'oklch(60% 0.12 290)',
    co2:         'oklch(70% 0.16 65)',
    pm25:        'oklch(58% 0.14 140)',
  };
  const series = [
    { key: 'temperature', label: 'Temperature', data: D.weekly.temperature, unit: '°C',   color: palette.temperature, on: on.temperature },
    { key: 'humidity',    label: 'Humidity',    data: D.weekly.humidity,    unit: '%',    color: palette.humidity,    on: on.humidity },
    { key: 'pressure',    label: 'Pressure',    data: D.weekly.pressure,    unit: 'hPa',  color: palette.pressure,    on: on.pressure },
    { key: 'co2',         label: 'CO₂',         data: D.weekly.co2,         unit: 'ppm',  color: palette.co2,         on: on.co2, dp: 0 },
    { key: 'pm25',        label: 'PM2.5',       data: D.weekly.pm25,        unit: 'µg/m³',color: palette.pm25,        on: on.pm25 },
  ];

  const days = ['Sun 14', 'Mon 15', 'Tue 16', 'Wed 17', 'Thu 18', 'Fri 19', 'Sat 20'];

  return (
    <Card style={{ padding: 20 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, marginBottom: 16 }}>
        <div>
          <div style={{ fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>Weekly</div>
          <h2 style={{ margin: '4px 0 0', fontWeight: 500, fontSize: 22, letterSpacing: '-0.01em' }}>Trend correlations</h2>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {series.map(s => (
            <button key={s.key} onClick={() => setOn(p => ({ ...p, [s.key]: !p[s.key] }))} style={{
              display: 'inline-flex', alignItems: 'center', gap: 8,
              padding: '6px 11px', borderRadius: 999,
              border: `1px solid ${s.on ? 'var(--line-strong)' : 'var(--line)'}`,
              background: s.on ? 'var(--bg)' : 'transparent',
              cursor: 'pointer', fontSize: 12, color: s.on ? 'var(--ink)' : 'var(--ink-4)',
              transition: 'all 0.15s',
            }}>
              <span style={{
                width: 8, height: 8, borderRadius: 2,
                background: s.on ? s.color : 'transparent',
                border: `1px solid ${s.color}`,
              }} />
              {s.label}
            </button>
          ))}
        </div>
      </div>
      <MultiSeriesChart series={series} labels={days} height={280} hours={168} />
    </Card>
  );
};

// ---- Zones panel ----
const ZonesPanel = () => {
  return (
    <Card style={{ padding: 20 }}>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 16 }}>
        <div>
          <div style={{ fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>Campus</div>
          <h2 style={{ margin: '4px 0 0', fontWeight: 500, fontSize: 22, letterSpacing: '-0.01em' }}>Zones at a glance</h2>
        </div>
        <button style={{ marginLeft: 'auto', ...iconBtn, width: 'auto', padding: '6px 12px', gap: 6, fontSize: 12, display: 'inline-flex', alignItems: 'center' }}>
          <Icon name="plus" size={12} /> Add zone
        </button>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10 }}>
        {D.zones.map(z => {
          const tier = aqiTier(z.aqi);
          return (
            <div key={z.id} style={{
              padding: 14,
              borderRadius: 12,
              border: `1px solid ${z.active ? 'var(--ink)' : 'var(--line)'}`,
              background: z.active ? 'var(--bg)' : 'transparent',
              display: 'flex', flexDirection: 'column', gap: 8,
              cursor: 'pointer', position: 'relative',
            }}>
              {z.active && (
                <div style={{ position: 'absolute', top: 8, right: 10, fontSize: 9, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.1em', color: 'var(--ink-3)' }}>
                  · viewing
                </div>
              )}
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <span style={{ width: 8, height: 8, borderRadius: '50%', background: tier.color }} />
                <span style={{ fontSize: 13, fontWeight: 500 }}>{z.name}</span>
              </div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                <span className="mono" style={{ fontSize: 26, letterSpacing: '-0.02em', fontVariantNumeric: 'tabular-nums', fontWeight: 500 }}>{z.aqi}</span>
                <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>AQI · {tier.label}</span>
              </div>
              <div style={{ display: 'flex', gap: 12, fontSize: 11, color: 'var(--ink-3)', fontFamily: 'Geist Mono' }}>
                <span>{z.temp}°C</span>
                <span>{z.hum}% RH</span>
                <span style={{ marginLeft: 'auto', color: 'var(--ink-4)' }}>{z.devices} nodes</span>
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
};

// ---- Alerts & activity feed ----
const AlertsFeed = () => {
  const levelStyle = {
    warn: { bg: 'oklch(94% 0.06 70)', dot: 'var(--warn)' },
    bad:  { bg: 'oklch(94% 0.06 30)', dot: 'var(--bad)'  },
    info: { bg: 'oklch(94% 0.04 240)', dot: 'var(--info)' },
    good: { bg: 'oklch(94% 0.06 160)', dot: 'var(--good)' },
  };
  return (
    <Card style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{ display: 'flex', alignItems: 'center' }}>
        <div>
          <div style={{ fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>Live feed</div>
          <h2 style={{ margin: '4px 0 0', fontWeight: 500, fontSize: 22, letterSpacing: '-0.01em' }}>Alerts & events</h2>
        </div>
        <div style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--ink-3)', fontFamily: 'Geist Mono' }}>· today</div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {D.alerts.map(a => {
          const st = levelStyle[a.level] || levelStyle.info;
          return (
            <div key={a.id} style={{
              display: 'grid', gridTemplateColumns: '8px 1fr auto',
              gap: 12, alignItems: 'flex-start',
              padding: '10px 12px',
              border: '1px solid var(--line)', borderRadius: 12,
              background: 'var(--bg)',
            }}>
              <span style={{ width: 8, height: 8, borderRadius: '50%', background: st.dot, marginTop: 6 }} />
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 500, display: 'flex', alignItems: 'center', gap: 8 }}>
                  {a.metric} · <span style={{ color: 'var(--ink-3)', fontWeight: 400 }}>{a.zone}</span>
                </div>
                <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{a.detail}</div>
              </div>
              <div style={{ fontSize: 11, color: 'var(--ink-4)', fontFamily: 'Geist Mono', whiteSpace: 'nowrap' }}>{a.time}</div>
            </div>
          );
        })}
      </div>
    </Card>
  );
};

// ---- Heatmap panel ----
const HeatmapPanel = () => {
  return (
    <Card style={{ padding: 20 }}>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 16 }}>
        <div>
          <div style={{ fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>Last 24 hours</div>
          <h2 style={{ margin: '4px 0 0', fontWeight: 500, fontSize: 22, letterSpacing: '-0.01em' }}>AQI by zone × hour</h2>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8, fontSize: 11, color: 'var(--ink-3)', fontFamily: 'Geist Mono' }}>
          <span style={{ width: 12, height: 8, background: 'oklch(86% 0.10 160)', borderRadius: 2 }} />0–30
          <span style={{ width: 12, height: 8, background: 'oklch(86% 0.13 110)', borderRadius: 2 }} />30–55
          <span style={{ width: 12, height: 8, background: 'oklch(82% 0.16 70)', borderRadius: 2 }} />55–80
          <span style={{ width: 12, height: 8, background: 'oklch(70% 0.16 30)', borderRadius: 2 }} />80+
        </div>
      </div>
      <Heatmap rows={D.zones.map(z => z.name)} cols={24} seed={3} />
    </Card>
  );
};

// ---- Devices table ----
const DevicesPanel = () => {
  return (
    <Card style={{ padding: 20 }}>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 12 }}>
        <div>
          <div style={{ fontSize: 11, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>Fleet</div>
          <h2 style={{ margin: '4px 0 0', fontWeight: 500, fontSize: 22, letterSpacing: '-0.01em' }}>Edge devices</h2>
        </div>
        <div style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--ink-3)', fontFamily: 'Geist Mono' }}>19 online · 0 offline</div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 90px 80px 90px 80px', columnGap: 12, rowGap: 8, fontSize: 12.5, alignItems: 'center' }}>
        <div style={hdr}>Node</div>
        <div style={hdr}>Zone</div>
        <div style={hdr}>Battery</div>
        <div style={hdr}>RSSI</div>
        <div style={hdr}>Firmware</div>
        <div style={hdr}>Status</div>
        {D.devices.map(d => {
          const batColor = d.battery < 30 ? 'var(--bad)' : d.battery < 60 ? 'var(--warn)' : 'var(--good)';
          const statusColor = d.status === 'online' ? 'var(--good)' : d.status === 'updating' ? 'var(--info)' : 'var(--warn)';
          return (
            <React.Fragment key={d.id}>
              <div style={{ display: 'flex', flexDirection: 'column' }}>
                <span style={{ fontWeight: 500 }}>{d.name}</span>
                <span style={{ fontSize: 10.5, color: 'var(--ink-4)', fontFamily: 'Geist Mono' }}>{d.id}</span>
              </div>
              <div style={{ color: 'var(--ink-2)' }}>{d.zone}</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <div style={{ flex: 1, height: 5, background: 'var(--line)', borderRadius: 3, overflow: 'hidden' }}>
                  <div style={{ width: `${d.battery}%`, height: '100%', background: batColor }} />
                </div>
                <span style={{ fontFamily: 'Geist Mono', fontSize: 11, color: 'var(--ink-3)' }}>{d.battery}%</span>
              </div>
              <div style={{ fontFamily: 'Geist Mono', fontSize: 11, color: 'var(--ink-3)' }}>{d.rssi} dBm</div>
              <div style={{ fontFamily: 'Geist Mono', fontSize: 11, color: 'var(--ink-3)' }}>{d.fw}</div>
              <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 6, height: 6, borderRadius: '50%', background: statusColor }} />
                <span style={{ fontSize: 11.5, color: 'var(--ink-2)' }}>{d.status}</span>
              </div>
            </React.Fragment>
          );
        })}
      </div>
    </Card>
  );
};

const hdr = {
  fontSize: 10, fontFamily: 'Geist Mono', textTransform: 'uppercase', letterSpacing: '0.08em',
  color: 'var(--ink-4)', paddingBottom: 6, borderBottom: '1px solid var(--line)',
};

// ---- Tweaks integration ----
const TWEAK_DEFAULTS = JSON.parse(document.getElementById('tweak-defaults').textContent.replace('/*EDITMODE-BEGIN*/','').replace('/*EDITMODE-END*/',''));

const ACCENT_OPTIONS = [
  { key: 'lime',  swatch: '#C8E66B' },
  { key: 'sky',   swatch: '#7FB8E6' },
  { key: 'amber', swatch: '#F1B658' },
  { key: 'rose',  swatch: '#E68799' },
];
const accentMap = {
  lime:  { '--accent': 'oklch(82% 0.17 132)', '--accent-deep': 'oklch(58% 0.14 132)', '--accent-soft': 'oklch(94% 0.06 132)' },
  sky:   { '--accent': 'oklch(82% 0.13 230)', '--accent-deep': 'oklch(54% 0.13 230)', '--accent-soft': 'oklch(94% 0.04 230)' },
  amber: { '--accent': 'oklch(84% 0.15 80)',  '--accent-deep': 'oklch(58% 0.13 60)',  '--accent-soft': 'oklch(94% 0.07 80)' },
  rose:  { '--accent': 'oklch(80% 0.13 10)',  '--accent-deep': 'oklch(56% 0.16 15)',  '--accent-soft': 'oklch(94% 0.05 10)' },
};

const App = () => {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [page, setPage] = React.useState('overview');

  // Apply theme + accent
  React.useEffect(() => {
    document.documentElement.dataset.theme = tweaks.theme;
    const a = accentMap[tweaks.accent] || accentMap.lime;
    Object.entries(a).forEach(([k, v]) => document.documentElement.style.setProperty(k, v));
  }, [tweaks.theme, tweaks.accent]);

  // Live "now" clock for that lived-in feel
  const [now, setNow] = React.useState(new Date());
  React.useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(t);
  }, []);

  const { TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakToggle, TweakSelect } = window;

  const META = {
    overview: { crumb: 'Main Atrium',   title: 'Live air',    accent: 'quality intelligence' },
    zones:    { crumb: 'All zones',     title: 'Six zones,',  accent: 'one atmosphere' },
    history:  { crumb: 'Archive',       title: 'Seven days',  accent: 'of readings' },
    forecast: { crumb: 'Model v3.2',    title: 'The next',    accent: 'twenty-four hours' },
    alerts:   { crumb: 'Notifications', title: 'What needs',  accent: 'your attention' },
    devices:  { crumb: 'Fleet',         title: 'Nineteen',    accent: 'edge nodes' },
  }[page];

  const BODY = {
    overview: (
      <>
        <HeroAQI />
        <MetricsGrid />
        <TrendsPanel />
        <div className="split-2" style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.4fr) minmax(0, 1fr)', gap: 16 }}>
          <HeatmapPanel />
          <AlertsFeed />
        </div>
        <ZonesPanel />
        <DevicesPanel />
      </>
    ),
    zones:    <ZonesPage />,
    history:  <HistoryPage />,
    forecast: <ForecastPage />,
    alerts:   <AlertsPage />,
    devices:  <DevicesPage />,
  }[page];

  return (
    <div style={{ display: 'flex', minHeight: '100vh', background: 'var(--bg)' }}>
      <Sidebar current={page} onSelect={setPage} />
      <main style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
        <TopBar now={now} crumb={META.crumb} title={META.title} accent={META.accent} />
        <div key={page} className="fade-up" style={{ padding: '20px 32px 48px', display: 'flex', flexDirection: 'column', gap: 16 }}>
          {BODY}
          <footer style={{ display: 'flex', justifyContent: 'space-between', color: 'var(--ink-4)', fontSize: 11, fontFamily: 'Geist Mono', padding: '12px 4px', borderTop: '1px solid var(--line)' }}>
            <span>Edgesense IAQ · Independent University Bangladesh · {now.toLocaleTimeString()}</span>
            <span>data plane synced · 19/19 · v2.4.1</span>
          </footer>
        </div>
      </main>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Theme">
          <TweakRadio
            label="Mode"
            value={tweaks.theme}
            options={[{ value: 'light', label: 'Light' }, { value: 'dark', label: 'Dark' }]}
            onChange={v => setTweak('theme', v)}
          />
          <TweakColor
            label="Accent"
            value={ACCENT_OPTIONS.find(a => a.key === tweaks.accent)?.swatch || ACCENT_OPTIONS[0].swatch}
            options={ACCENT_OPTIONS.map(a => a.swatch)}
            onChange={hex => {
              const found = ACCENT_OPTIONS.find(a => a.swatch.toLowerCase() === String(hex).toLowerCase());
              setTweak('accent', found ? found.key : 'lime');
            }}
          />
        </TweakSection>
        <TweakSection label="Display">
          <TweakSelect
            label="Units"
            value={tweaks.unit}
            options={[{ value: 'metric', label: 'Metric' }, { value: 'imperial', label: 'Imperial' }]}
            onChange={v => setTweak('unit', v)}
          />
          <TweakToggle
            label="24h forecast"
            value={tweaks.showForecast}
            onChange={v => setTweak('showForecast', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
};

// Panels defined here are referenced by pages.jsx at render time via window.
Object.assign(window, { HeroAQI, MetricsGrid, TrendsPanel, ZonesPanel, AlertsFeed, HeatmapPanel, DevicesPanel, aqiTier });

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