<!DOCTYPE html>
<html lang="fr" data-theme="dark">
<head>
  <meta charset="UTF-8">
  <title>Exemple complet — mon design system</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">

  <link rel="stylesheet" href="../tokens/tokens.css">

  <style>
    body {
      background:
        radial-gradient(ellipse at top, var(--bg-2) 0%, var(--bg-1) 60%);
      min-height: 100vh;
    }

    /* Topbar */
    .topbar {
      position: sticky; top: 0; z-index: 50;
      padding: 14px 24px;
      background: var(--surf-glass-strong);
      backdrop-filter: blur(14px) saturate(150%);
      border-bottom: 1px solid var(--border-2);
      display: flex; align-items: center; gap: 14px;
      box-shadow: var(--shadow-2);
    }
    .topbar .logo {
      width: 32px; height: 32px; border-radius: 8px;
      background: var(--accent);
      color: var(--bg-1);
      display: flex; align-items: center; justify-content: center;
      box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 2px 6px var(--accent-glow);
    }
    .topbar h1 {
      margin: 0; font-size: 17px; font-weight: 700;
    }
    .topbar h1 small {
      font-family: var(--font-mono);
      font-size: 10px; letter-spacing: 0.1em;
      color: var(--ink-3); font-weight: 400;
      margin-left: 8px; text-transform: uppercase;
    }

    /* Layout : sidebar + content */
    .shell { display: flex; min-height: calc(100vh - 60px); }

    .side-nav {
      width: 220px; flex: 0 0 auto;
      padding: 20px 8px;
      border-right: 1px solid var(--border-2);
      background: var(--bg-2);
      position: sticky; top: 60px; align-self: flex-start;
      max-height: calc(100vh - 60px);
      overflow-y: auto;
    }
    .side-nav h3 {
      margin: 14px 12px 4px;
      font-family: var(--font-mono);
      font-size: 10px; letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--ink-3);
    }
    .side-nav a {
      display: block;
      padding: 6px 12px;
      color: var(--ink-2);
      text-decoration: none;
      border-radius: 6px;
      font-size: 13px;
      border-left: 3px solid transparent;
      margin-bottom: 1px;
    }
    .side-nav a:hover {
      background: var(--bg-3);
      color: var(--ink-1);
    }

    main { flex: 1; min-width: 0; padding: 32px 40px 80px; }
    section { margin-bottom: 56px; max-width: 1100px; scroll-margin-top: 80px; }
    section > h2 {
      font-size: 24px; margin: 0 0 4px;
      display: flex; align-items: center; gap: 12px;
    }
    section > .desc {
      color: var(--ink-3); font-size: 14px; margin: 0 0 20px;
      max-width: 720px; line-height: 1.5;
    }

    /* Cards demo */
    .demo {
      padding: 22px;
      background: var(--bg-2);
      border: 1px solid var(--border-2);
      border-radius: 10px;
      box-shadow: var(--tile-3d);
      margin-bottom: 14px;
    }
    .demo h3 {
      font-family: var(--font-mono); font-size: 10px;
      letter-spacing: 0.08em; text-transform: uppercase;
      color: var(--ink-3); margin: 0 0 14px;
    }
    .demo .row {
      display: flex; flex-wrap: wrap; gap: 12px; align-items: center;
    }
    .demo .col {
      display: flex; flex-direction: column; gap: 12px;
    }
    .demo .grid-3 {
      display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
    }
    .demo .grid-4 {
      display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px;
    }

    /* Color swatches */
    .swatch-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
      gap: 8px;
    }
    .swatch {
      border-radius: 8px;
      overflow: hidden;
      border: 1px solid var(--border-2);
      box-shadow: var(--shadow-1);
    }
    .swatch .sw-color { height: 50px; }
    .swatch .sw-meta {
      padding: 6px 9px;
      background: var(--bg-3);
    }
    .swatch .sw-var {
      font-family: var(--font-mono); font-size: 10px; color: var(--ink-1);
    }
    .swatch .sw-hex {
      font-family: var(--font-mono); font-size: 9.5px; color: var(--ink-3);
    }

    /* Typography sample */
    .typo-sample {
      display: grid;
      grid-template-columns: 120px 1fr;
      gap: 18px;
      align-items: center;
      padding: 12px 0;
      border-bottom: 1px dashed var(--border-1);
    }
    .typo-sample:last-child { border-bottom: 0; }
    .typo-sample .name {
      font-family: var(--font-mono);
      font-size: 10px; letter-spacing: 0.08em;
      text-transform: uppercase; color: var(--ink-3);
    }

    /* Icon grid */
    .icon-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
      gap: 8px;
    }
    .icon-cell {
      display: flex; flex-direction: column; align-items: center;
      gap: 6px; padding: 12px 6px;
      background: var(--bg-3);
      border: 1px solid var(--border-2);
      border-radius: 6px;
    }
    .icon-cell .name {
      font-family: var(--font-mono);
      font-size: 9.5px;
      color: var(--ink-3);
    }

    /* Native HTML form elements stylés avec tokens */
    .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
    .field-label {
      font-family: var(--font-mono); font-size: 10px;
      letter-spacing: 0.08em; text-transform: uppercase;
      color: var(--ink-3);
    }
    input[type="text"], input[type="email"], input[type="password"],
    input[type="time"], input[type="number"], textarea, select {
      padding: 9px 12px;
      background: var(--bg-1);
      border: 1px solid var(--border-2);
      border-radius: 8px;
      color: var(--ink-1);
      font-family: var(--font-ui); font-size: 13px;
      box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);
      outline: none;
    }
    input:focus, textarea:focus, select:focus {
      border-color: var(--accent);
      box-shadow: inset 0 1px 2px rgba(0,0,0,0.3), 0 0 0 2px var(--accent-tint);
    }
    textarea { resize: vertical; font-family: var(--font-mono); font-size: 12px; }
    input[type="range"] { accent-color: var(--accent); }

    /* Status pill (utilisable en HTML pur) */
    .pill {
      display: inline-flex; align-items: center; gap: 6px;
      padding: 3px 10px;
      border-radius: 999px;
      font-family: var(--font-mono);
      font-size: 10px; font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
    }
    .pill-ok    { background: rgba(77,187,38,0.18);  color: var(--ok);   border: 1px solid var(--ok); }
    .pill-warn  { background: rgba(250,189,47,0.18); color: var(--warn); border: 1px solid var(--warn); }
    .pill-err   { background: rgba(251,73,52,0.18);  color: var(--err);  border: 1px solid var(--err); }
    .pill-info  { background: rgba(131,165,152,0.2); color: var(--info); border: 1px solid var(--info); }

    /* Logs / terminal block */
    .term-block {
      background: #15110c;
      border: 1px solid var(--border-2);
      border-radius: 8px;
      padding: 14px 16px;
      font-family: var(--font-terminal);
      font-size: 13px; line-height: 1.55;
      letter-spacing: 0.02em;
      color: var(--ink-2);
      position: relative;
      overflow: hidden;
    }
    .term-block::before {
      content: '';
      position: absolute; inset: 0;
      background: repeating-linear-gradient(0deg, transparent 0 2px, rgba(0,0,0,0.18) 2px 3px);
      pointer-events: none;
    }
    .term-block .prompt { color: var(--accent); font-weight: 700; }
    .term-block .ok    { color: var(--ok); }
    .term-block .warn  { color: var(--warn); }
    .term-block .err   { color: var(--err); }
    .term-block .info  { color: var(--info); }
    .term-block .dim   { color: var(--ink-4); }
  </style>

  <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>
</head>
<body>

<div id="root"></div>

<script type="text/babel" src="../components/ui-kit.jsx"></script>

<script type="text/babel">
const { useState, useEffect } = React;

/* ============================================================
   TOPBAR + thème switcher
   ============================================================ */
function Topbar({ theme, setTheme }) {
  return (
    <header className="topbar">
      <div className="logo"><Icon name="grid" size={16} /></div>
      <h1>Exemple complet <small>tous les composants · v1.0</small></h1>
      <span style={{ flex: 1 }}></span>
      <a href="exemple-minimal.html" style={{
        fontFamily: 'var(--font-mono)', fontSize: 12,
        color: 'var(--ink-3)', textDecoration: 'none',
        display: 'inline-flex', alignItems: 'center', gap: 6,
      }}>
        <Icon name="chevL" size={12} /> exemple minimal
      </a>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8,
        padding: '5px 10px',
        background: 'var(--bg-3)',
        border: '1px solid var(--border-2)',
        borderRadius: 8,
      }}>
        <Icon name={theme === 'dark' ? 'moon' : 'sun'} size={12} />
        <span className="label" style={{ fontSize: 10 }}>{theme}</span>
        <Toggle on={theme === 'light'} onChange={(v) => setTheme(v ? 'light' : 'dark')} />
      </div>
    </header>
  );
}

/* ============================================================
   SIDE NAV
   ============================================================ */
const SECTIONS = [
  { id: 'colors',     label: 'Couleurs' },
  { id: 'typo',       label: 'Typographie' },
  { id: 'shadows',    label: 'Ombres & relief' },
  { id: 'icons',      label: 'Icônes' },
  { id: 'buttons',    label: 'Boutons' },
  { id: 'iconbtns',   label: 'Boutons icônes' },
  { id: 'toggles',    label: 'Toggles' },
  { id: 'leds',       label: 'StatusLed' },
  { id: 'tooltips',   label: 'Tooltips' },
  { id: 'gauges',     label: 'Jauges' },
  { id: 'charts',     label: 'Graphes' },
  { id: 'tree',       label: 'TreeNav' },
  { id: 'popup',      label: 'Popup' },
  { id: 'forms',      label: 'Formulaires' },
  { id: 'pills',      label: 'Badges / Pills' },
  { id: 'terminal',   label: 'Logs & Terminal' },
];

function Nav() {
  return (
    <nav className="side-nav">
      <h3>Tokens</h3>
      {SECTIONS.slice(0, 3).map((s) => <a key={s.id} href={'#' + s.id}>{s.label}</a>)}
      <h3>Atomes</h3>
      {SECTIONS.slice(3, 9).map((s) => <a key={s.id} href={'#' + s.id}>{s.label}</a>)}
      <h3>Datavis</h3>
      {SECTIONS.slice(9, 11).map((s) => <a key={s.id} href={'#' + s.id}>{s.label}</a>)}
      <h3>Molécules</h3>
      {SECTIONS.slice(11).map((s) => <a key={s.id} href={'#' + s.id}>{s.label}</a>)}
    </nav>
  );
}

/* ============================================================
   COULEURS
   ============================================================ */
function Swatches({ list }) {
  return (
    <div className="swatch-grid">
      {list.map(([k, v]) => (
        <div key={k} className="swatch">
          <div className="sw-color" style={{ background: v }}></div>
          <div className="sw-meta">
            <div className="sw-var">{k}</div>
            <div className="sw-hex">{v}</div>
          </div>
        </div>
      ))}
    </div>
  );
}
const SW_BG_DARK = [['--bg-0','#221c17'],['--bg-1','#2a231d'],['--bg-2','#322a23'],['--bg-3','#3c332a'],['--bg-4','#4a4035'],['--bg-5','#5a4f43']];
const SW_INK_DARK = [['--ink-1','#f2e5c7'],['--ink-2','#d5c4a1'],['--ink-3','#a89984'],['--ink-4','#7c6f64']];
const SW_BG_LIGHT = [['--bg-0','#b8b2a3'],['--bg-1','#d5d0c5'],['--bg-2','#dcd7cc'],['--bg-3','#e3ded3'],['--bg-4','#ccc6b8'],['--bg-5','#bdb6a7']];
const SW_INK_LIGHT = [['--ink-1','#28241f'],['--ink-2','#3c3836'],['--ink-3','#5a544c'],['--ink-4','#8a8278']];
const SW_ACCENT_DARK = [['--accent','#fe8019'],['--accent-soft','#d65d0e']];
const SW_ACCENT_LIGHT = [['--accent','#af3a03'],['--accent-soft','#d65d0e']];
const SW_STATUS_DARK = [['--ok','#4dbb26'],['--warn','#fabd2f'],['--err','#fb4934'],['--info','#83a598']];
const SW_STATUS_LIGHT = [['--ok','#3c911c'],['--warn','#b57614'],['--err','#9d0006'],['--info','#427b58']];
const SW_EXTRA_DARK = [['--blue','#3db0d1'],['--purple','#c882c8']];
const SW_EXTRA_LIGHT = [['--blue','#2d82a3'],['--purple','#8c468c']];

function ColorsSection({ theme }) {
  const sets = theme === 'dark'
    ? { bg: SW_BG_DARK, ink: SW_INK_DARK, accent: SW_ACCENT_DARK, status: SW_STATUS_DARK, extra: SW_EXTRA_DARK }
    : { bg: SW_BG_LIGHT, ink: SW_INK_LIGHT, accent: SW_ACCENT_LIGHT, status: SW_STATUS_LIGHT, extra: SW_EXTRA_LIGHT };
  return (
    <section id="colors">
      <h2><Icon name="grid" size={22} style={{ color: 'var(--accent)' }} /> Couleurs</h2>
      <p className="desc">19 tokens couleur par thème. Bascule le thème en haut à droite pour comparer dark / light.</p>
      <div className="demo">
        <h3>Fonds (du plus profond au plus haut)</h3>
        <Swatches list={sets.bg} />
      </div>
      <div className="demo">
        <h3>Encres / texte</h3>
        <Swatches list={sets.ink} />
      </div>
      <div className="demo">
        <h3>Accent</h3>
        <Swatches list={sets.accent} />
      </div>
      <div className="demo">
        <h3>Statuts</h3>
        <Swatches list={sets.status} />
      </div>
      <div className="demo">
        <h3>Datavis additionnel</h3>
        <Swatches list={sets.extra} />
      </div>
    </section>
  );
}

/* ============================================================
   TYPO
   ============================================================ */
function TypoSection() {
  return (
    <section id="typo">
      <h2><Icon name="list" size={22} style={{ color: 'var(--accent)' }} /> Typographie</h2>
      <p className="desc">3 polices. Une seule règle : Inter pour l'UI, JetBrains Mono pour les données, Share Tech Mono pour les logs/terminal.</p>
      <div className="demo">
        <h3>Inter — UI</h3>
        <div className="typo-sample"><span className="name">display</span><div style={{ fontSize: 44, fontWeight: 700, lineHeight: 1 }}>Santé système</div></div>
        <div className="typo-sample"><span className="name">h1 / 28px</span><div style={{ fontSize: 28, fontWeight: 700 }}>Tableau de bord</div></div>
        <div className="typo-sample"><span className="name">h2 / 22px</span><div style={{ fontSize: 22, fontWeight: 700 }}>Sous-titre</div></div>
        <div className="typo-sample"><span className="name">title / 18px</span><div style={{ fontSize: 18, fontWeight: 700 }}>Titre de carte</div></div>
        <div className="typo-sample"><span className="name">body / 14px</span><div style={{ fontSize: 14 }}>Paragraphe corps de texte, lisible 14px, line-height 1.5</div></div>
        <div className="typo-sample"><span className="name">caption / 12px</span><div style={{ fontSize: 12, color: 'var(--ink-3)' }}>Texte secondaire, hints, métadonnées</div></div>
      </div>
      <div className="demo">
        <h3>JetBrains Mono — données</h3>
        <div className="typo-sample"><span className="name">kpi / 32px</span><div className="mono" style={{ fontSize: 32, fontWeight: 700 }}>87<span style={{ color: 'var(--ink-3)', fontSize: 18 }}>%</span></div></div>
        <div className="typo-sample"><span className="name">value / 18px</span><div className="mono" style={{ fontSize: 18, fontWeight: 600 }}>10.0.1.236</div></div>
        <div className="typo-sample"><span className="name">data / 13px</span><div className="mono" style={{ fontSize: 13 }}>14:02:11 · node-03 · 0.4ms</div></div>
        <div className="typo-sample"><span className="name">label / 11px</span><div className="label">label uppercase</div></div>
      </div>
      <div className="demo">
        <h3>Share Tech Mono — logs / terminal</h3>
        <div className="typo-sample"><span className="name">prompt</span><div className="terminal" style={{ fontSize: 16 }}><span style={{ color: 'var(--accent)', fontWeight: 700 }}>root@srv</span>:~$ <span style={{ color: 'var(--ink-3)' }}>tail -f /var/log/ops.log</span></div></div>
        <div className="typo-sample"><span className="name">log line</span><div className="terminal" style={{ fontSize: 14 }}><span style={{ color: 'var(--ink-4)' }}>14:02:11</span> <span style={{ color: 'var(--ok)' }}>INFO</span> scan terminé · 1022 IPs</div></div>
      </div>
    </section>
  );
}

/* ============================================================
   OMBRES
   ============================================================ */
function ShadowsSection() {
  const items = [
    { name: '--shadow-1',     style: { boxShadow: 'var(--shadow-1)' },     desc: 'Élévation discrète' },
    { name: '--shadow-2',     style: { boxShadow: 'var(--shadow-2)' },     desc: 'Élévation standard' },
    { name: '--shadow-3',     style: { boxShadow: 'var(--shadow-3)' },     desc: 'Élévation modale' },
    { name: '--shadow-press', style: { boxShadow: 'var(--shadow-press)', background: 'var(--bg-1)' }, desc: 'État pressé (inset)' },
    { name: '--tile-3d',      style: { boxShadow: 'var(--tile-3d)' },      desc: 'Relief 3D marqué' },
    { name: '--tile-3d-strong', style: { boxShadow: 'var(--tile-3d-strong)' }, desc: 'Relief 3D fort' },
  ];
  return (
    <section id="shadows">
      <h2><Icon name="bars" size={22} style={{ color: 'var(--accent)' }} /> Ombres & relief</h2>
      <p className="desc">6 niveaux d'élévation pour hiérarchiser les surfaces.</p>
      <div className="demo">
        <div className="grid-3">
          {items.map((s) => (
            <div key={s.name} style={{
              padding: 18,
              background: 'var(--bg-3)',
              borderRadius: 10,
              border: '1px solid var(--border-2)',
              minHeight: 90,
              display: 'flex', flexDirection: 'column', justifyContent: 'center',
              ...s.style,
            }}>
              <div className="mono" style={{ fontSize: 11, color: 'var(--accent)', fontWeight: 600 }}>{s.name}</div>
              <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4 }}>{s.desc}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   ICÔNES
   ============================================================ */
const ALL_ICONS = ['cpu','memory','disk','network','clock','grid','list','cog','alert','bell','server','chart','bars','terminal','refresh','play','pause','power','sun','moon','search','close','plus','filter','download','folder','node','user','chevR','chevL','chevD','chevU'];

function IconsSection() {
  return (
    <section id="icons">
      <h2><Icon name="grid" size={22} style={{ color: 'var(--accent)' }} /> Icônes</h2>
      <p className="desc">32 icônes Font Awesome 6 mappées sous des noms logiques. Toujours via &lt;Icon name="…" /&gt;.</p>
      <div className="demo">
        <div className="icon-grid">
          {ALL_ICONS.map((n) => (
            <div key={n} className="icon-cell">
              <Icon name={n} size={20} style={{ color: 'var(--ink-1)' }} />
              <span className="name">{n}</span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   BOUTONS
   ============================================================ */
function ButtonsSection() {
  return (
    <section id="buttons">
      <h2><Icon name="play" size={22} style={{ color: 'var(--accent)' }} /> Boutons</h2>
      <p className="desc">4 variantes (default, primary, ghost, danger) · 3 tailles (sm, md, lg) · icône optionnelle.</p>
      <div className="demo">
        <h3>Variantes</h3>
        <div className="row">
          <Button>défaut</Button>
          <Button variant="primary" icon="play">primaire</Button>
          <Button variant="ghost" icon="filter">ghost</Button>
          <Button variant="danger" icon="power">danger</Button>
        </div>
      </div>
      <div className="demo">
        <h3>Tailles</h3>
        <div className="row">
          <Button size="sm" variant="primary" icon="play">petit (sm)</Button>
          <Button size="md" variant="primary" icon="play">moyen (md)</Button>
          <Button size="lg" variant="primary" icon="play">grand (lg)</Button>
        </div>
      </div>
      <div className="demo">
        <h3>Avec / sans icône</h3>
        <div className="row">
          <Button variant="primary">sans icône</Button>
          <Button variant="primary" icon="cog">avec icône à gauche</Button>
          <Button variant="ghost" icon="download">exporter</Button>
          <Button variant="ghost" icon="refresh">rafraîchir</Button>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   ICONBUTTONS
   ============================================================ */
function IconBtnsSection() {
  return (
    <section id="iconbtns">
      <h2><Icon name="cog" size={22} style={{ color: 'var(--accent)' }} /> Boutons icônes</h2>
      <p className="desc">Bouton icône seul, tooltip obligatoire (apparaît au survol après ~280 ms). Variantes : default, primary, active, danger.</p>
      <div className="demo">
        <h3>Variantes (survoler pour voir les tooltips)</h3>
        <div className="row">
          <IconButton icon="refresh" label="Rafraîchir" />
          <IconButton icon="cog" label="Configurer" primary />
          <IconButton icon="play" label="Démarrer" active />
          <IconButton icon="power" label="Arrêter le service" danger />
          <IconButton icon="bell" label="3 notifications" />
          <IconButton icon="search" label="Rechercher" />
          <IconButton icon="filter" label="Filtrer" />
          <IconButton icon="download" label="Exporter" />
        </div>
      </div>
      <div className="demo">
        <h3>Tailles</h3>
        <div className="row">
          <IconButton icon="cog" label="petit (26)" size={26} />
          <IconButton icon="cog" label="moyen (34, défaut)" />
          <IconButton icon="cog" label="grand (44)" size={44} />
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   TOGGLES
   ============================================================ */
function TogglesSection() {
  const [a, setA] = useState(true);
  const [b, setB] = useState(false);
  const [c, setC] = useState(true);
  return (
    <section id="toggles">
      <h2><Icon name="power" size={22} style={{ color: 'var(--accent)' }} /> Toggles</h2>
      <p className="desc">Switch on/off avec glow accent quand actif. Label et icône optionnels.</p>
      <div className="demo">
        <div className="col">
          <Toggle on={a} onChange={setA} label="auto-refresh" icon="refresh" />
          <Toggle on={b} onChange={setB} label="mode debug" icon="terminal" />
          <Toggle on={c} onChange={setC} label="notifications" icon="bell" />
          <Toggle on={true} onChange={() => {}} />
          <Toggle on={false} onChange={() => {}} />
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   STATUS LEDs
   ============================================================ */
function LedsSection() {
  return (
    <section id="leds">
      <h2><Icon name="alert" size={22} style={{ color: 'var(--accent)' }} /> Status LEDs</h2>
      <p className="desc">Pastille colorée + halo. 5 statuts × option pulse.</p>
      <div className="demo">
        <h3>Statuts standard</h3>
        <div className="row" style={{ gap: 22 }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="ok" size={14} /> ok</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="warn" size={14} /> warn</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="err" size={14} /> err</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="info" size={14} /> info</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="off" size={14} /> off</span>
        </div>
      </div>
      <div className="demo">
        <h3>Avec pulse (pour signaler un changement / état critique)</h3>
        <div className="row" style={{ gap: 22 }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="ok" pulse size={14} /> ok pulse</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="warn" pulse size={14} /> warn pulse</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><StatusLed status="err" pulse size={14} /> err pulse</span>
        </div>
      </div>
      <div className="demo">
        <h3>Tailles</h3>
        <div className="row" style={{ gap: 16, alignItems: 'center' }}>
          <StatusLed status="ok" size={6} />
          <StatusLed status="ok" size={9} />
          <StatusLed status="ok" size={14} />
          <StatusLed status="ok" size={20} />
          <StatusLed status="ok" size={28} />
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   TOOLTIPS
   ============================================================ */
function TooltipsSection() {
  return (
    <section id="tooltips">
      <h2><Icon name="alert" size={22} style={{ color: 'var(--accent)' }} /> Tooltips</h2>
      <p className="desc">Bulle d'info au survol, 4 positions disponibles.</p>
      <div className="demo">
        <div className="row">
          <Tooltip label="top (défaut)"><Button>haut</Button></Tooltip>
          <Tooltip label="position bottom" side="bottom"><Button>bas</Button></Tooltip>
          <Tooltip label="position left" side="left"><Button>gauche</Button></Tooltip>
          <Tooltip label="position right" side="right"><Button>droite</Button></Tooltip>
          <Tooltip label="bulle plus longue avec quelques mots"><Button variant="ghost">label long</Button></Tooltip>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   JAUGES
   ============================================================ */
function GaugesSection() {
  return (
    <section id="gauges">
      <h2><Icon name="disk" size={22} style={{ color: 'var(--accent)' }} /> Jauges</h2>
      <p className="desc">Radiales (rondes) ou Batterie (horizontales). Glow lumineux au survol. Couleur auto selon seuils warnAt/errAt, ou couleur fixe.</p>

      <div className="demo">
        <h3>Radiales — 3 tailles, 3 niveaux</h3>
        <div className="row" style={{ alignItems: 'flex-end', justifyContent: 'space-around' }}>
          <RadialGauge value={28} label="OK" size={100} />
          <RadialGauge value={72} label="WARN" size={120} />
          <RadialGauge value={93} label="ERR" size={140} />
        </div>
      </div>

      <div className="demo">
        <h3>BigRadialGauge — métrique héro cockpit</h3>
        <div style={{ display: 'flex', justifyContent: 'center' }}>
          <BigRadialGauge value={87} label="score santé · stable" />
        </div>
      </div>

      <div className="demo">
        <h3>Battery — stack vertical (standard)</h3>
        <div className="col">
          <BatteryGauge value={28} label="DISQUE" />
          <BatteryGauge value={64} label="CPU" warnAt={70} errAt={85} />
          <BatteryGauge value={88} label="RÉSEAU" warnAt={70} errAt={85} />
          <BatteryGauge value={42} label="MÉMOIRE" height={14} />
        </div>
      </div>

      <div className="demo">
        <h3>Battery compact — inline 1 ligne (idéal listes denses)</h3>
        <div className="col" style={{ gap: 8 }}>
          <BatteryGauge compact value={88} label="mémoire" icon="memory" />
          <BatteryGauge compact value={64} label="cpu" icon="cpu" warnAt={70} errAt={85} />
          <BatteryGauge compact value={28} label="disque" icon="disk" />
          <BatteryGauge compact value={92} label="réseau" icon="network" warnAt={70} errAt={85} />
          <BatteryGauge compact value={1.4} max={4} unit="Go" label="ram libre" icon="memory" color="var(--blue)" />
          <BatteryGauge compact value={68} label="charge" icon="cpu" color="var(--purple)" />
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   GRAPHES
   ============================================================ */
function ChartsSection() {
  return (
    <section id="charts">
      <h2><Icon name="chart" size={22} style={{ color: 'var(--accent)' }} /> Graphes</h2>
      <p className="desc">Sparkline pour KPI compacts. LineChart pour évolution multi-séries.</p>
      <div className="demo">
        <h3>Sparkline (dans des KPI tiles)</h3>
        <div className="grid-4">
          {[
            { label: 'CPU',     val: 64, unit: '%',    color: 'var(--accent)', pts: [40,45,38,50,55,60,58,62,65,64,66,64], icon: 'cpu' },
            { label: 'Mémoire', val: 42, unit: '%',    color: 'var(--info)',   pts: [30,32,35,38,40,41,42,42,42,42,42,42], icon: 'memory' },
            { label: 'Réseau',  val: 8.4, unit: 'Mb',  color: 'var(--ok)',     pts: [2,4,3,6,5,8,7,9,8,8.4,7.8,8.4], icon: 'network' },
            { label: 'Latence', val: 12, unit: 'ms',   color: 'var(--purple)', pts: [10,11,9,12,11,13,12,14,12,11,12,12], icon: 'clock' },
          ].map((k, i) => (
            <div key={i} style={{
              padding: 12, borderRadius: 10,
              background: 'var(--bg-3)',
              border: '1px solid var(--border-2)',
              boxShadow: 'var(--tile-3d)',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <Icon name={k.icon} size={12} style={{ color: k.color }} />
                <span className="label">{k.label}</span>
              </div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 4 }}>
                <span className="mono" style={{ fontSize: 24, fontWeight: 700, color: 'var(--ink-1)' }}>{k.val}</span>
                <span className="label">{k.unit}</span>
              </div>
              <Sparkline points={k.pts} color={k.color} h={26} />
            </div>
          ))}
        </div>
      </div>
      <div className="demo">
        <h3>LineChart multi-séries</h3>
        <LineChart h={200} labels={Array.from({length:24},(_,i)=>String(i).padStart(2,'0')+'h')} series={[
          { color: 'var(--accent)', points: [12,18,14,22,28,35,30,42,38,45,52,48,55,60,52,58,45,50,38,44,36,40,32,38] },
          { color: 'var(--info)',   points: [8,10,12,14,16,20,18,24,22,28,30,32,30,28,26,24,22,20,18,16,14,12,10,12] },
          { color: 'var(--blue)',   points: [4,5,6,8,10,12,13,15,14,16,18,20,18,15,14,13,12,10,9,8,7,6,5,4] },
        ]} />
        <div className="row" style={{ marginTop: 8 }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12 }}><StatusLed status="ok" size={8} style={{ background: 'var(--accent)' }} /> entrant</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12 }}><StatusLed status="ok" size={8} style={{ background: 'var(--info)' }} /> sortant</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12 }}><StatusLed status="ok" size={8} style={{ background: 'var(--blue)' }} /> erreurs</span>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   TREENAV
   ============================================================ */
function TreeNavSection() {
  const [active, setActive] = useState('a2');
  return (
    <section id="tree">
      <h2><Icon name="folder" size={22} style={{ color: 'var(--accent)' }} /> TreeNav</h2>
      <p className="desc">Navigation arborescente dépliable avec icône en tête, statut LED par enfant.</p>
      <div className="demo" style={{ maxWidth: 380 }}>
        <TreeNav activeId={active} onSelect={setActive} groups={[
          { id: 'a', icon: 'server', label: 'cluster-prod', count: 3, open: true, children: [
            { id: 'a1', label: 'node-01', status: 'ok', meta: '0.4ms' },
            { id: 'a2', label: 'node-02', status: 'warn', meta: '14ms' },
            { id: 'a3', label: 'node-03', status: 'err', meta: 'down' },
          ]},
          { id: 'b', icon: 'node', label: 'cluster-edge', count: 2, open: true, children: [
            { id: 'b1', label: 'edge-fr', status: 'ok' },
            { id: 'b2', label: 'edge-de', status: 'err', meta: 'down' },
          ]},
          { id: 'c', icon: 'disk', label: 'storage', count: 4, open: false, children: [
            { id: 'c1', label: 'sda', status: 'ok' },
          ]},
        ]} />
        <p style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 12 }}>
          Sélection : <span className="mono" style={{ color: 'var(--accent)' }}>{active}</span>
        </p>
      </div>
    </section>
  );
}

/* ============================================================
   POPUP
   ============================================================ */
function PopupSection() {
  const [open1, setOpen1] = useState(false);
  const [open2, setOpen2] = useState(false);
  const [open3, setOpen3] = useState(false);
  return (
    <section id="popup">
      <h2><Icon name="close" size={22} style={{ color: 'var(--accent)' }} /> Popup</h2>
      <p className="desc">Modale glassmorphism centrée, header avec ✕, footer optionnel. Clic à l'extérieur ou Échap pour fermer.</p>
      <div className="demo">
        <div className="row">
          <Button variant="primary" icon="cog" onClick={() => setOpen1(true)}>Popup simple</Button>
          <Button variant="primary" icon="alert" onClick={() => setOpen2(true)}>Confirmation</Button>
          <Button variant="ghost" icon="filter" onClick={() => setOpen3(true)}>Avec formulaire</Button>
        </div>
      </div>

      <Popup open={open1} onClose={() => setOpen1(false)} title="Popup simple"
        footer={<Button variant="primary" onClick={() => setOpen1(false)}>OK</Button>}>
        <div style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.5 }}>
          Une popup glassmorphism centrée avec un titre et un bouton OK.
        </div>
      </Popup>

      <Popup open={open2} onClose={() => setOpen2(false)} title="Confirmer le redémarrage"
        footer={<>
          <Button variant="ghost" onClick={() => setOpen2(false)}>Annuler</Button>
          <Button variant="danger" icon="power" onClick={() => setOpen2(false)}>Redémarrer</Button>
        </>}>
        <div style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.5 }}>
          Redémarrer <span className="mono" style={{ color: 'var(--accent)' }}>worker_01</span> ?
          Le service sera indisponible 8s environ.
        </div>
      </Popup>

      <Popup open={open3} onClose={() => setOpen3(false)} title="Filtres"
        footer={<>
          <Button variant="ghost" onClick={() => setOpen3(false)}>Annuler</Button>
          <Button variant="primary" icon="filter" onClick={() => setOpen3(false)}>Appliquer</Button>
        </>}>
        <PopupFormDemo />
      </Popup>
    </section>
  );
}

function PopupFormDemo() {
  const [thr, setThr] = useState(60);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div className="field">
        <span className="field-label">recherche</span>
        <input type="text" placeholder="filtrer par nom…" />
      </div>
      <Toggle on={true} onChange={() => {}} label="activé uniquement" icon="play" />
      <div className="field">
        <span className="field-label">seuil ({thr}%)</span>
        <input type="range" min="0" max="100" value={thr} onChange={(e) => setThr(+e.target.value)} />
      </div>
    </div>
  );
}

/* ============================================================
   FORMULAIRES (HTML natif + tokens)
   ============================================================ */
function FormsSection() {
  const [v, setV] = useState(50);
  return (
    <section id="forms">
      <h2><Icon name="list" size={22} style={{ color: 'var(--accent)' }} /> Formulaires</h2>
      <p className="desc">Champs HTML natifs habillés par les tokens. Focus accent, fond inset profond.</p>
      <div className="demo">
        <h3>Champs texte</h3>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          <div className="field">
            <span className="field-label">nom utilisateur</span>
            <input type="text" defaultValue="root" />
          </div>
          <div className="field">
            <span className="field-label">email</span>
            <input type="email" placeholder="admin@exemple.local" />
          </div>
          <div className="field">
            <span className="field-label">mot de passe</span>
            <input type="password" defaultValue="••••••••" />
          </div>
          <div className="field">
            <span className="field-label">heure de début</span>
            <input type="time" defaultValue="22:00" />
          </div>
        </div>
      </div>
      <div className="demo">
        <h3>Select</h3>
        <div className="field">
          <span className="field-label">source de données</span>
          <select defaultValue="prom">
            <option value="prom">prometheus.local:9090</option>
            <option value="node">node-exporter:9100</option>
            <option value="file">fichier local /var/log/…</option>
          </select>
        </div>
      </div>
      <div className="demo">
        <h3>Range (slider)</h3>
        <div className="field">
          <span className="field-label">intervalle de rafraîchissement ({v}s)</span>
          <input type="range" min="5" max="120" value={v} onChange={(e) => setV(+e.target.value)} />
        </div>
      </div>
      <div className="demo">
        <h3>Textarea (avec police monospace)</h3>
        <div className="field">
          <span className="field-label">CSS personnalisé</span>
          <textarea rows={4} defaultValue=":root { --accent: #fe8019; }"></textarea>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   PILLS / BADGES
   ============================================================ */
function PillsSection() {
  return (
    <section id="pills">
      <h2><Icon name="bell" size={22} style={{ color: 'var(--accent)' }} /> Badges / Pills</h2>
      <p className="desc">Pastilles arrondies pour étiqueter un statut. Disponibles en HTML pur via les classes <code className="mono" style={{ color: 'var(--accent)' }}>.pill .pill-ok / -warn / -err / -info</code>.</p>
      <div className="demo">
        <div className="row">
          <span className="pill pill-ok">ok</span>
          <span className="pill pill-warn">warn</span>
          <span className="pill pill-err">err</span>
          <span className="pill pill-info">info</span>
        </div>
      </div>
      <div className="demo">
        <h3>Combinaisons usuelles</h3>
        <div className="row">
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
            <span className="mono">nginx</span>
            <span className="pill pill-ok">actif</span>
          </span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
            <span className="mono">redis</span>
            <span className="pill pill-warn">latent</span>
          </span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
            <span className="mono">worker_01</span>
            <span className="pill pill-err">arrêté</span>
          </span>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   TERMINAL / LOGS
   ============================================================ */
function TerminalSection() {
  return (
    <section id="terminal">
      <h2><Icon name="terminal" size={22} style={{ color: 'var(--accent)' }} /> Logs & Terminal</h2>
      <p className="desc">Bloc terminal avec police Share Tech Mono, effet CRT, couleurs par niveau de sévérité.</p>
      <div className="demo">
        <h3>Stream de logs typé</h3>
        <div className="term-block">
          <div><span className="dim">14:02:04</span> <span className="info">INFO </span> nouveau hôte 10.0.1.236</div>
          <div><span className="dim">14:02:09</span> <span className="warn">WARN </span> latence élevée sur 10.0.1.42</div>
          <div><span className="dim">14:02:11</span> <span className="info">INFO </span> scan terminé · 1022 IPs</div>
          <div><span className="dim">14:01:58</span> <span className="err">ERROR</span> worker_01 arrêté inopinément</div>
          <div><span className="dim">14:01:42</span> <span className="ok">OK   </span> backup horaire OK (812 Mo)</div>
        </div>
      </div>
      <div className="demo">
        <h3>Prompt terminal</h3>
        <div className="term-block">
          <div><span className="prompt">root@pve-edge-01</span><span className="dim">:~$</span> ps aux</div>
          <div className="dim">PID    USER     CPU%  MEM%  COMMAND</div>
          <div>2341   postgres 14.8  22.1  postgres</div>
          <div><span className="warn">3120   node     28.5  18.7  node app.js</span></div>
          <div><span className="err">4012   worker    0.0   0.0  worker_01 [Z]</span></div>
          <div><span className="prompt">root@pve-edge-01</span><span className="dim">:~$</span> <span style={{
            display: 'inline-block', width: 8, height: 14,
            background: 'var(--accent)', verticalAlign: 'middle',
            animation: 'blink 1s steps(2) infinite',
          }}></span></div>
          <style>{`@keyframes blink { 50% { opacity: 0 } }`}</style>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   APP COMPLÈTE
   ============================================================ */
function App() {
  const [theme, setTheme] = useState('dark');
  useEffect(() => { document.documentElement.dataset.theme = theme; }, [theme]);

  return (
    <>
      <Topbar theme={theme} setTheme={setTheme} />
      <div className="shell">
        <Nav />
        <main>
          <ColorsSection theme={theme} />
          <TypoSection />
          <ShadowsSection />
          <IconsSection />
          <ButtonsSection />
          <IconBtnsSection />
          <TogglesSection />
          <LedsSection />
          <TooltipsSection />
          <GaugesSection />
          <ChartsSection />
          <TreeNavSection />
          <PopupSection />
          <FormsSection />
          <PillsSection />
          <TerminalSection />
        </main>
      </div>
    </>
  );
}

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

</body>
</html>
