<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KOOLD — Dashboard</title>
<style>
  @font-face {
    font-family: 'Cormorant Garamond';
    src: url('../../fonts/CormorantGaramond-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 900; font-style: normal; font-display: swap;
  }
  @font-face {
    font-family: 'Cormorant Garamond';
    src: url('../../fonts/CormorantGaramond-Italic-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 900; font-style: italic; font-display: swap;
  }
</style>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
<script type="text/babel" src="Sidebar.jsx"></script>
<script type="text/babel" src="MetricCard.jsx"></script>
<script type="text/babel" src="AlertBanner.jsx"></script>
<script type="text/babel" src="ChartLine.jsx"></script>
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  html, body { height: 100%; background: #191919; font-family: 'DM Sans', sans-serif; }
  #root { height: 100%; }
  ::-webkit-scrollbar { width: 4px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: #37657B; border-radius: 2px; }
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useCallback } = React;

/* ── Colour tokens ── */
const C = {
  deepVoid:    '#0F384D',
  arcticNight: '#37657B',
  stormLayer:  '#4A7A90',
  signalIce:   '#FEEC7E',
  pulseGreen:  '#B2DE7B',
  compliance:  '#589E84',
  cloudDancer: '#F0EEE9',
  darkest:     '#191919',
};

/* ── Static demo data ── */
const ROUTES = [
  { id:'r1', name:'MUC → AMS', status:'ok',   temp:'+4.2°C', sensors:12, lastEvent:'2 min ago' },
  { id:'r2', name:'FRA → LHR', status:'ok',   temp:'+3.8°C', sensors:8,  lastEvent:'5 min ago' },
  { id:'r3', name:'ZRH → CDG', status:'warn', temp:'+7.1°C', sensors:6,  lastEvent:'Just now' },
  { id:'r4', name:'VIE → BRU', status:'ok',   temp:'+4.9°C', sensors:10, lastEvent:'11 min ago' },
];

const ALERTS = [
  { id:'a1', message:'ZRH → CDG Route: Temperature approaching upper threshold (+7.1°C / limit +8°C). Sensor KLD-0342 flagged.', time:'Just now', severity:'warn' },
  { id:'a2', message:'MUC → AMS Sensor KLD-1029 battery low (12%). Replacement recommended within 48h.', time:'1h ago', severity:'info' },
];

function makeTempData(seed = 0, hasDev = false) {
  return Array.from({ length: 24 }, (_, i) => ({
    t: `${String(i).padStart(2,'0')}:00`,
    v: 4 + Math.sin((i + seed) * 0.6) * 1.1 + (hasDev && i > 20 ? (i - 20) * 0.8 : 0) + (Math.random() * 0.3),
  }));
}

/* ── Section header ── */
function SectionHeader({ label, children }) {
  return (
    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:14 }}>
      <span style={{ fontFamily:"'Outfit',sans-serif", fontSize:10, fontWeight:600, letterSpacing:'0.12em', textTransform:'uppercase', color:'rgba(240,238,233,0.35)' }}>{label}</span>
      {children}
    </div>
  );
}

/* ── Top bar ── */
function TopBar({ screen }) {
  const titles = { dashboard:'Dashboard', routes:'Routes', alerts:'Alert Center', compliance:'Compliance', sensors:'Sensors', reports:'Reports' };
  return (
    <div style={{ height:56, background:'#111111', borderBottom:'1px solid rgba(74,122,144,0.2)', display:'flex', alignItems:'center', justifyContent:'space-between', padding:'0 28px', flexShrink:0 }}>
      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
        <span style={{ fontFamily:"'DM Sans',sans-serif", fontSize:15, fontWeight:600, color:'#F0EEE9' }}>{titles[screen] || screen}</span>
        <span style={{ background:'rgba(178,222,123,0.12)', border:'1px solid rgba(178,222,123,0.25)', borderRadius:2, fontSize:9, fontWeight:600, letterSpacing:'0.08em', textTransform:'uppercase', color:'#B2DE7B', padding:'2px 8px' }}>Live</span>
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:20 }}>
        <span style={{ fontSize:11, color:'rgba(240,238,233,0.35)', letterSpacing:'0.04em' }}>Last sync: just now</span>
        <div style={{ width:30, height:30, borderRadius:'50%', background:'#37657B', display:'flex', alignItems:'center', justifyContent:'center', fontSize:11, fontWeight:600, color:'#F0EEE9' }}>JK</div>
      </div>
    </div>
  );
}

/* ── Route table row ── */
function RouteRow({ route, onSelect, selected }) {
  return (
    <div onClick={() => onSelect(route.id)} style={{ display:'flex', alignItems:'center', gap:0, padding:'14px 20px', borderBottom:'1px solid rgba(74,122,144,0.12)', cursor:'pointer', background: selected ? 'rgba(254,236,126,0.04)' : 'transparent', transition:'background 0.15s ease' }}>
      <div style={{ flex:2, fontSize:13, fontWeight:500, color:'#F0EEE9' }}>{route.name}</div>
      <div style={{ flex:1 }}>
        <span style={{ fontSize:12, fontFamily:"'Courier New',monospace", color: route.status==='warn' ? '#FEEC7E' : '#B2DE7B' }}>{route.temp}</span>
      </div>
      <div style={{ flex:1 }}>
        <span style={{ fontSize:10, fontWeight:600, letterSpacing:'0.06em', padding:'3px 8px', borderRadius:2, background: route.status==='ok' ? 'rgba(178,222,123,0.12)' : 'rgba(254,236,126,0.15)', color: route.status==='ok' ? '#B2DE7B' : '#FEEC7E' }}>{route.status==='ok' ? 'COMPLIANT' : 'WARNING'}</span>
      </div>
      <div style={{ flex:1, fontSize:11, color:'rgba(240,238,233,0.4)' }}>{route.sensors} sensors</div>
      <div style={{ flex:1, fontSize:11, color:'rgba(240,238,233,0.35)' }}>{route.lastEvent}</div>
    </div>
  );
}

/* ── Alert list item ── */
function AlertItem({ alert }) {
  return (
    <div style={{ padding:'16px 20px', borderBottom:'1px solid rgba(74,122,144,0.1)', display:'flex', gap:16, alignItems:'flex-start' }}>
      <div style={{ width:8, height:8, borderRadius:'50%', marginTop:4, flexShrink:0, background: alert.severity==='warn' ? '#FEEC7E' : '#4A7A90', boxShadow: alert.severity==='warn' ? '0 0 8px rgba(254,236,126,0.5)' : 'none' }} />
      <div style={{ flex:1 }}>
        <div style={{ fontSize:13, color:'#F0EEE9', lineHeight:1.5, marginBottom:4 }}>{alert.message}</div>
        <div style={{ fontSize:11, color:'rgba(240,238,233,0.35)', letterSpacing:'0.03em' }}>{alert.time}</div>
      </div>
      <span style={{ fontSize:9, fontWeight:600, letterSpacing:'0.08em', textTransform:'uppercase', padding:'3px 8px', borderRadius:2, background: alert.severity==='warn' ? 'rgba(254,236,126,0.12)' : 'rgba(74,122,144,0.25)', color: alert.severity==='warn' ? '#FEEC7E' : '#F0EEE9', flexShrink:0 }}>{alert.severity==='warn' ? 'Warning' : 'Info'}</span>
    </div>
  );
}

/* ── Compliance row ── */
function ComplianceRow({ label, status, detail, date }) {
  return (
    <div style={{ display:'flex', alignItems:'center', padding:'14px 20px', borderBottom:'1px solid rgba(74,122,144,0.1)', gap:0 }}>
      <div style={{ flex:3, fontSize:13, color:'#F0EEE9' }}>{label}</div>
      <div style={{ flex:2, fontSize:11, color:'rgba(240,238,233,0.5)' }}>{detail}</div>
      <div style={{ flex:1 }}>
        <span style={{ fontSize:10, fontWeight:600, letterSpacing:'0.06em', padding:'3px 8px', borderRadius:2, background: status==='pass' ? 'rgba(178,222,123,0.12)' : 'rgba(88,158,132,0.2)', color: status==='pass' ? '#B2DE7B' : '#589E84' }}>{status==='pass' ? 'PASS' : 'REVIEWED'}</span>
      </div>
      <div style={{ flex:1, fontSize:11, color:'rgba(240,238,233,0.35)', textAlign:'right' }}>{date}</div>
    </div>
  );
}

/* ── Screens ── */
function DashboardScreen() {
  return (
    <div style={{ padding:28, display:'flex', flexDirection:'column', gap:20, overflowY:'auto', flex:1 }}>
      {/* KPI row */}
      <div>
        <SectionHeader label="Live KPIs" />
        <div style={{ display:'flex', gap:12 }}>
          <MetricCard value="47" label="Failures Prevented" trend="12% vs last month" trendUp status="green" highlight />
          <MetricCard value="4" label="Active Routes" trend="All monitored" trendUp status="neutral" />
          <MetricCard value="4.3" unit="s" label="Alert Response" trend="−0.2s vs avg" trendUp status="yellow" highlight />
          <MetricCard value="0" label="GDP Violations" trend="30-day streak" trendUp status="green" highlight />
          <MetricCard value="99.97" unit="%" label="Platform Uptime" trend="12-month avg" trendUp status="neutral" />
        </div>
      </div>

      {/* Charts row */}
      <div>
        <SectionHeader label="Temperature · Last 24h">
          <span style={{ fontSize:10, color:'rgba(240,238,233,0.3)', letterSpacing:'0.06em' }}>Threshold: +8°C GDP</span>
        </SectionHeader>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }}>
          <ChartLine label="MUC → AMS" data={makeTempData(0)} threshold={8} />
          <ChartLine label="ZRH → CDG" data={makeTempData(2, true)} threshold={8} />
        </div>
      </div>

      {/* Route table */}
      <div>
        <SectionHeader label="Route Status" />
        <div style={{ background:'#37657B', border:'1px solid #4A7A90', borderRadius:4, overflow:'hidden' }}>
          <div style={{ display:'flex', padding:'10px 20px', background:'rgba(0,0,0,0.15)', fontSize:9, fontWeight:600, letterSpacing:'0.10em', textTransform:'uppercase', color:'rgba(240,238,233,0.35)', gap:0 }}>
            <div style={{ flex:2 }}>Route</div><div style={{ flex:1 }}>Temp</div><div style={{ flex:1 }}>Status</div><div style={{ flex:1 }}>Sensors</div><div style={{ flex:1 }}>Last Event</div>
          </div>
          {ROUTES.map(r => <RouteRow key={r.id} route={r} onSelect={() => {}} selected={false} />)}
        </div>
      </div>
    </div>
  );
}

function RoutesScreen() {
  const [selected, setSelected] = useState('r1');
  const route = ROUTES.find(r => r.id === selected);
  return (
    <div style={{ display:'flex', flex:1, overflow:'hidden' }}>
      <div style={{ width:280, borderRight:'1px solid rgba(74,122,144,0.2)', overflowY:'auto', background:'rgba(0,0,0,0.1)' }}>
        <div style={{ padding:'16px 20px', fontSize:9, fontWeight:600, letterSpacing:'0.12em', textTransform:'uppercase', color:'rgba(240,238,233,0.35)' }}>Select Route</div>
        {ROUTES.map(r => (
          <div key={r.id} onClick={() => setSelected(r.id)} style={{ padding:'14px 20px', cursor:'pointer', borderBottom:'1px solid rgba(74,122,144,0.12)', background: selected===r.id ? 'rgba(254,236,126,0.06)' : 'transparent', borderLeft: selected===r.id ? '2px solid #FEEC7E' : '2px solid transparent', transition:'all 0.15s ease' }}>
            <div style={{ fontSize:13, fontWeight:500, color:'#F0EEE9', marginBottom:4 }}>{r.name}</div>
            <div style={{ display:'flex', gap:8, alignItems:'center' }}>
              <span style={{ fontSize:11, fontFamily:"'Courier New',monospace", color: r.status==='warn' ? '#FEEC7E' : '#B2DE7B' }}>{r.temp}</span>
              <span style={{ fontSize:9, fontWeight:600, letterSpacing:'0.06em', padding:'2px 6px', borderRadius:2, background: r.status==='ok' ? 'rgba(178,222,123,0.12)' : 'rgba(254,236,126,0.15)', color: r.status==='ok' ? '#B2DE7B' : '#FEEC7E' }}>{r.status==='ok' ? 'OK' : 'WARN'}</span>
            </div>
          </div>
        ))}
      </div>
      <div style={{ flex:1, padding:28, overflowY:'auto', display:'flex', flexDirection:'column', gap:18 }}>
        <div>
          <div style={{ fontFamily:"'Cormorant Garamond',serif", fontSize:32, fontWeight:600, color:'#F0EEE9', marginBottom:4 }}>{route.name}</div>
          <div style={{ fontSize:12, color:'rgba(240,238,233,0.4)', letterSpacing:'0.04em' }}>{route.sensors} sensors active · Last event: {route.lastEvent}</div>
        </div>
        <div style={{ display:'flex', gap:12 }}>
          <MetricCard value={route.temp} label="Current Temp" status={route.status==='warn' ? 'yellow' : 'green'} highlight />
          <MetricCard value={route.sensors.toString()} label="Active Sensors" status="neutral" />
          <MetricCard value={route.status==='ok' ? '100%' : '92%'} label="Compliance Score" status={route.status==='ok' ? 'green' : 'yellow'} highlight />
        </div>
        <ChartLine label={`${route.name} · Temperature 24h`} data={makeTempData(route.id==='r3' ? 2 : 0, route.id==='r3')} threshold={8} height={100} />
        <div style={{ background:'#37657B', border:'1px solid #4A7A90', borderRadius:4, padding:'18px 20px' }}>
          <div style={{ fontSize:10, fontWeight:600, letterSpacing:'0.10em', textTransform:'uppercase', color:'rgba(240,238,233,0.35)', marginBottom:12 }}>Sensor Readings</div>
          {Array.from({ length: route.sensors > 6 ? 6 : route.sensors }, (_, i) => (
            <div key={i} style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'8px 0', borderBottom:'1px solid rgba(255,255,255,0.05)' }}>
              <span style={{ fontFamily:"'Courier New',monospace", fontSize:11, color:'rgba(240,238,233,0.5)' }}>KLD-{String(1000 + i + parseInt(route.id.slice(1)) * 100).padStart(4,'0')}</span>
              <span style={{ fontFamily:"'Courier New',monospace", fontSize:12, color: route.status==='warn' && i===0 ? '#FEEC7E' : '#B2DE7B' }}>
                +{(4 + Math.random() * (route.status==='warn' && i===0 ? 3 : 1)).toFixed(1)}°C
              </span>
              <span style={{ fontSize:9, fontWeight:600, letterSpacing:'0.06em', padding:'2px 6px', borderRadius:2, background:'rgba(178,222,123,0.12)', color:'#B2DE7B' }}>ACTIVE</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function AlertsScreen() {
  const allAlerts = [
    ...ALERTS,
    { id:'a3', message:'FRA → LHR Sensor KLD-0881 reconnected after 3-minute outage. Data gap logged for audit.', time:'3h ago', severity:'info' },
    { id:'a4', message:'MUC → AMS Customs hold at AMS extended by 2h. Temperature stable. No intervention required.', time:'6h ago', severity:'info' },
    { id:'a5', message:'Daily compliance report generated. All routes GDP-compliant. No violations.', time:'8h ago', severity:'info' },
  ];
  return (
    <div style={{ padding:28, flex:1, overflowY:'auto' }}>
      <div style={{ display:'flex', gap:12, marginBottom:20 }}>
        <MetricCard value="1" label="Active Warnings" status="yellow" highlight />
        <MetricCard value="0" label="Critical Alerts" status="green" />
        <MetricCard value="4" label="Info Events Today" status="neutral" />
      </div>
      <SectionHeader label="All Alerts — Today" />
      <div style={{ background:'#37657B', border:'1px solid #4A7A90', borderRadius:4, overflow:'hidden' }}>
        {allAlerts.map(a => <AlertItem key={a.id} alert={a} />)}
      </div>
    </div>
  );
}

function ComplianceScreen() {
  return (
    <div style={{ padding:28, flex:1, overflowY:'auto' }}>
      <div style={{ display:'flex', gap:12, marginBottom:20 }}>
        <MetricCard value="0" label="GDP Violations" status="green" highlight trend="30-day streak" trendUp />
        <MetricCard value="100%" label="Documentation Rate" status="green" />
        <MetricCard value="Apr 12" label="Last Audit" status="neutral" />
      </div>
      <SectionHeader label="GDP Compliance Log · April 2026" />
      <div style={{ background:'#37657B', border:'1px solid #4A7A90', borderRadius:4, overflow:'hidden', marginBottom:16 }}>
        <div style={{ display:'flex', padding:'10px 20px', background:'rgba(0,0,0,0.15)', fontSize:9, fontWeight:600, letterSpacing:'0.10em', textTransform:'uppercase', color:'rgba(240,238,233,0.35)' }}>
          <div style={{ flex:3 }}>Requirement</div><div style={{ flex:2 }}>Detail</div><div style={{ flex:1 }}>Status</div><div style={{ flex:1, textAlign:'right' }}>Date</div>
        </div>
        <ComplianceRow label="Temperature Excursion Documentation" detail="All deviations logged within 4.3s" status="pass" date="Apr 26" />
        <ComplianceRow label="Qualification of Transport Conditions" detail="Routes QT-validated, IQ/OQ complete" status="pass" date="Apr 20" />
        <ComplianceRow label="Sensor Calibration Records" detail="47 sensors · ISO 17025 certified" status="pass" date="Apr 15" />
        <ComplianceRow label="GDP Audit Trail" detail="Full chain of custody documented" status="pass" date="Apr 12" />
        <ComplianceRow label="DSCSA Serialisation Review" detail="DSCSA module active · Nov 2026 ready" status="reviewed" date="Apr 10" />
        <ComplianceRow label="Deviation Investigation Reports" detail="2 minor deviations · CAPA closed" status="pass" date="Apr 7" />
      </div>
      <div style={{ background:'rgba(178,222,123,0.06)', border:'1px solid rgba(178,222,123,0.2)', borderRadius:4, padding:'16px 20px', display:'flex', gap:12, alignItems:'center' }}>
        <div style={{ width:8, height:8, borderRadius:'50%', background:'#B2DE7B', flexShrink:0 }} />
        <span style={{ fontSize:13, color:'#F0EEE9' }}>All active routes are GDP-compliant. Next scheduled audit: May 14, 2026.</span>
      </div>
    </div>
  );
}

/* ── Root App ── */
function App() {
  const [nav, setNav] = useState('dashboard');

  const screenMap = {
    dashboard: <DashboardScreen />,
    routes:    <RoutesScreen />,
    alerts:    <AlertsScreen />,
    compliance:<ComplianceScreen />,
    sensors:   <DashboardScreen />,
    reports:   <ComplianceScreen />,
  };

  return (
    <div style={{ display:'flex', height:'100vh', overflow:'hidden', background:'#191919' }}>
      <Sidebar activeNav={nav} onNav={setNav} />
      <div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden' }}>
        <TopBar screen={nav} />
        <AlertBanner alerts={nav==='dashboard' || nav==='alerts' ? ALERTS : []} />
        <div style={{ flex:1, overflowY:'auto', display:'flex', flexDirection:'column' }}>
          {screenMap[nav]}
        </div>
      </div>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
