// The 4 screens of DAEV Arbiter

const { useState: Su, useEffect: Eu, useRef: Ru, useMemo: Mu, useCallback: Cu } = React;

// ─────────────────────────────────────────────────────────────
// Shared chrome — top bar used on all screens
// ─────────────────────────────────────────────────────────────
function TopBar({ t, screen, onNavigate, themeMode, onToggleTheme, onOpenShortcuts }) {
  const tabs = [
    { id: 'dashboard', label: 'Dashboard' },
    { id: 'audit',     label: 'New Audit' },
  ];
  // Detect host site so the "Back" link works on local + on-prod
  const backHref = (typeof window !== 'undefined' && window.DAEV_BACK_HREF) || '/';

  // Sentinel "live sweep" widget — fake counter advances every 15s,
  // wraps to 5 once it crosses 99 so the timer never feels stale.
  const [sweepAge, setSweepAge] = Su(14);
  const [sentinelHover, setSentinelHover] = Su(false);
  Eu(() => {
    const id = setInterval(() => {
      setSweepAge((prev) => {
        const next = prev + 1;
        return next > 99 ? 5 : next;
      });
    }, 15000);
    return () => clearInterval(id);
  }, []);
  return (
    <div style={{
      display:'flex', alignItems:'center',
      padding:'10px 20px',
      borderBottom:`1px solid ${t.line}`,
      background: t.bg0,
      gap: 18,
      flexShrink: 0,
    }}>
      {/* Back to aelethion.com — primary brand return */}
      <a href={backHref} style={{
        display:'inline-flex', alignItems:'center', gap: 6,
        padding:'6px 10px',
        fontFamily: t.font.mono, fontSize: 11, fontWeight: 600,
        color: t.fg2, textDecoration:'none',
        border:`1px solid ${t.line}`, borderRadius: t.radius.lg,
        letterSpacing: 0.4,
        transition:'all 180ms cubic-bezier(0.4,0,0.2,1)',
      }}
      onMouseOver={e => { e.currentTarget.style.color = t.fg0; e.currentTarget.style.borderColor = t.accent.base; }}
      onMouseOut={e => { e.currentTarget.style.color = t.fg2; e.currentTarget.style.borderColor = t.line; }}
      >
        ← Aelethion
      </a>

      <div style={{ width: 1, height: 20, background: t.line }}/>

      {/* Canonical Aelethion · Arbiter wordmark — sized 17/700 so the
          AuditFlowSteps label beneath is the loudest type on the bar. */}
      <a href={backHref} style={{
        textDecoration: 'none',
      }}>
        <Wordmark t={t} size={17} sub="Arbiter"/>
      </a>

      <div style={{
        fontFamily: t.font.mono, fontSize: 10, color: t.fg2,
        letterSpacing: 1, textTransform:'uppercase',
        padding: '2px 6px', border:`1px solid ${t.line}`, borderRadius: t.radius.sm,
      }}>v0.6.4</div>

      <div style={{ flex:1 }}/>

      {/* ⌘K discoverability hint */}
      <button
        onClick={() => {
          // Synthesize a ⌘K keypress so the App's listener picks it up
          try {
            window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true, bubbles: true }));
          } catch (_) {}
        }}
        title="Quick fixture switcher"
        style={{
          display:'inline-flex', alignItems:'center', gap: 6,
          padding: '5px 10px',
          background: t.bg1,
          border: `1px solid ${t.line}`,
          borderRadius: t.radius.lg,
          color: t.fg2,
          fontFamily: t.font.mono, fontSize: 11, fontWeight: 500,
          cursor:'pointer',
          letterSpacing: 0.3,
          transition: 'all 180ms cubic-bezier(0.4,0,0.2,1)',
        }}
        onMouseOver={e => {
          e.currentTarget.style.borderColor = t.accent.base;
          e.currentTarget.style.color = t.fg0;
        }}
        onMouseOut={e => {
          e.currentTarget.style.borderColor = t.line;
          e.currentTarget.style.color = t.fg2;
        }}>
        <Icon name="search" size={12} color="currentColor"/>
        <span>fixtures</span>
        <span style={{
          fontFamily: t.font.mono, fontSize: 10, fontWeight: 600,
          padding: '1px 5px',
          border: `1px solid ${t.line}`,
          borderRadius: 4,
          color: t.fg3,
          marginLeft: 2,
        }}>⌘K</span>
      </button>

      <div style={{ display:'flex', gap: 4 }}>
        {tabs.map(tab => {
          const active = (tab.id==='audit' && (screen==='audit'||screen==='live'||screen==='result')) ||
                         (tab.id==='dashboard' && screen==='dashboard');
          return (
            <button key={tab.id}
              onClick={() => onNavigate(tab.id === 'audit' ? 'audit' : 'dashboard')}
              style={{
                padding:'6px 12px',
                background: active ? t.bg2 : 'transparent',
                color: active ? t.fg0 : t.fg2,
                border: `1px solid ${active ? t.line : 'transparent'}`,
                borderRadius: t.radius.lg,
                fontFamily: t.font.ui, fontSize: 13, fontWeight: 500,
                cursor:'pointer',
              }}>
              {tab.label}
            </button>
          );
        })}
      </div>

      {/* Keyboard-shortcuts modal opener */}
      {onOpenShortcuts && (
        <button
          onClick={onOpenShortcuts}
          aria-label="Keyboard shortcuts"
          title="Keyboard shortcuts (?)"
          style={{
            display:'inline-flex', alignItems:'center', justifyContent:'center',
            width: 32, height: 32,
            background: t.bg1,
            border: `1px solid ${t.line}`,
            borderRadius: t.radius.lg,
            color: t.fg1,
            fontFamily: t.font.mono, fontSize: 14, fontWeight: 700,
            cursor: 'pointer',
            transition: 'all 180ms cubic-bezier(0.4,0,0.2,1)',
          }}
          onMouseOver={e => { e.currentTarget.style.borderColor = t.accent.base; e.currentTarget.style.color = t.accent.base; }}
          onMouseOut={e => { e.currentTarget.style.borderColor = t.line; e.currentTarget.style.color = t.fg1; }}>
          ?
        </button>
      )}

      {/* Sentinel live status widget — fake-but-credible production heartbeat
          so the visitor sees the platform arc (audit → watch) without a roadmap blurb */}
      <div
        className="daev-sentinel-pulse-once"
        onMouseEnter={() => setSentinelHover(true)}
        onMouseLeave={() => setSentinelHover(false)}
        style={{
          display:'inline-flex', alignItems:'center', gap: 8,
          padding:'5px 10px',
          background: t.bg1,
          border: `1px solid ${t.line}`,
          borderRadius: t.radius.lg,
          fontFamily: t.font.mono, fontSize: 11,
          color: t.fg2,
          cursor: 'default',
          position: 'relative',
        }}
      >
        <span style={{
          width: 6, height: 6, borderRadius: '50%',
          background: t.semantic.green,
          boxShadow: `0 0 8px ${t.semantic.green}`,
          animation: 'daev-blip 1.6s infinite',
          display: 'inline-block',
        }}/>
        <span style={{
          color: t.fg1, fontWeight: 700, letterSpacing: 1.2, textTransform:'uppercase',
        }}>SENTINEL</span>
        <span style={{ width: 1, height: 14, background: t.line }}/>
        <span style={{ color: t.fg2 }}>0 drifts</span>
        <span style={{ width: 1, height: 14, background: t.line }}/>
        <span style={{ color: t.fg3 }}>{sweepAge}s ago</span>

        {sentinelHover && (
          <div style={{
            position: 'absolute',
            top: 'calc(100% + 6px)',
            left: 0,
            background: t.bg1,
            border: `1px solid ${t.line2}`,
            borderRadius: t.radius.md,
            padding: '10px 12px',
            boxShadow: `0 8px 24px rgba(0,0,0,${t.mode === 'dark' ? 0.4 : 0.12})`,
            zIndex: 50,
            minWidth: 220,
            pointerEvents: 'none',
            fontFamily: t.font.mono, fontSize: 11, lineHeight: 1.6,
            color: t.fg1,
          }}>
            <div>Sentinel is watching 3 production agents</div>
            <div>No behavioural drift detected in the last 24h</div>
            <div style={{ color: t.fg3, marginTop: 6 }}>→ Coming Q4 2026</div>
          </div>
        )}
      </div>

      {/* Theme toggle (sun ↔ moon) — persists to localStorage via App */}
      {onToggleTheme && (
        <button
          onClick={onToggleTheme}
          aria-label={themeMode === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'}
          title={themeMode === 'dark' ? 'Light mode' : 'Dark mode'}
          style={{
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            width: 32, height: 32,
            background: t.bg1,
            border: `1px solid ${t.line}`,
            borderRadius: t.radius.lg,
            color: t.fg1,
            cursor: 'pointer',
            transition: 'all 180ms cubic-bezier(0.4,0,0.2,1)',
          }}
          onMouseOver={e => {
            e.currentTarget.style.borderColor = t.accent.base;
            e.currentTarget.style.color = t.accent.base;
          }}
          onMouseOut={e => {
            e.currentTarget.style.borderColor = t.line;
            e.currentTarget.style.color = t.fg1;
          }}
        >
          {themeMode === 'dark' ? (
            // Sun icon — switch to light
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="12" cy="12" r="4"/>
              <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
            </svg>
          ) : (
            // Moon icon — switch to dark
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
              <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
            </svg>
          )}
        </button>
      )}

      <div style={{ width: 1, height: 20, background: t.line }}/>

      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
        <div style={{
          fontFamily: t.font.mono, fontSize: 11, color: t.fg2,
          display:'flex', alignItems:'center', gap:6,
        }}>
          <span style={{
            width:6, height:6, borderRadius:'50%',
            background: t.semantic.green,
            boxShadow: `0 0 8px ${t.semantic.green}`,
          }}/>
          demo.aelethion.com
        </div>
        <div style={{
          width: 26, height: 26, borderRadius:'50%',
          background: `color-mix(in oklch, ${t.accent.base} 30%, ${t.bg2})`,
          border:`1px solid ${t.line}`,
          color: t.fg0, fontFamily: t.font.ui, fontSize: 11, fontWeight:600,
          display:'flex', alignItems:'center', justifyContent:'center',
        }}>KV</div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Screen 1 — Audit Input / Home
// ─────────────────────────────────────────────────────────────
function AuditInput({ t, onRunAudit, onRunGithubAudit, fixtureId, setFixtureId, mode, setMode }) {
  const fx = window.DAEV_FIXTURES[fixtureId] || window.DAEV_FIXTURES.sqli;
  // Slice 6.4.5 wiring brief — GitHub URL input state
  const [githubUrl, setGithubUrl] = SA('');
  // Slice 6.4.5.2 Phase 12 (BUG-74): user code state for the _user fixture's
  // textarea. Initialized from FIX_USER.lines so the textarea has placeholder
  // content; on change we mirror lines into window.DAEV_FIXTURES._user.lines
  // so the existing handleRunAudit path picks up the typed code without
  // needing any prop-threading changes upstream.
  const initialUserCode = (window.DAEV_FIXTURES._user && window.DAEV_FIXTURES._user.lines.join('\n')) || '';
  const [userCode, setUserCode] = SA(initialUserCode);
  const langLabel = { python:'Python', javascript:'JavaScript', typescript:'TypeScript' }[fx.lang] || 'Python';
  const fileExt    = { python:'py', javascript:'js', typescript:'tsx' }[fx.lang] || 'py';
  const fileName   = fx.id === '_user'     ? 'custom_input.py'
                   : fx.id === 'xss-js'    ? 'frontend/Profile.tsx'
                   : fx.id === 'cmdi-js'   ? 'ops/diag.js'
                   : fx.id === 'hardcoded' ? 'config/secrets.py'
                   : fx.id === 'pathtrav'  ? 'storage/s3_proxy.py'
                   : fx.id === 'cmdi'      ? 'infra/ssh_executor.py'
                   : fx.id === 'racecond'  ? 'billing/redeem.py'
                   : fx.id === 'sqli'      ? 'payments/checkout.py'
                   : 'handler.' + fileExt;

  // Slice 6.4.5.2 Phase 12 (BUG-74): keep window.DAEV_FIXTURES._user.lines in
  // sync with the textarea so handleRunAudit (which reads fx.lines.join('\n'))
  // sends the typed code unmodified to /switzerland/gate.
  function handleUserCodeChange(e) {
    const val = e.target.value;
    setUserCode(val);
    if (window.DAEV_FIXTURES && window.DAEV_FIXTURES._user) {
      window.DAEV_FIXTURES._user.lines = val.split('\n');
    }
  }

  return (
    <div style={{ flex:1, display:'flex', minHeight:0 }}>
      {/* LEFT: editor */}
      <div style={{ width:'50%', borderRight:`1px solid ${t.line}`, display:'flex', flexDirection:'column' }}>
        {/* Fixture selector row */}
        <div style={{
          padding:'10px 14px',
          display:'flex', alignItems:'center', gap:10,
          borderBottom:`1px solid ${t.line}`,
          background: t.bg0,
        }}>
          <div style={{
            fontFamily: t.font.mono, fontSize: 10,
            color: t.fg2, letterSpacing: 1, textTransform:'uppercase',
          }}>fixture</div>
          <div data-tour="fixture-picker" style={{ display:'flex', flexWrap:'wrap', gap:4, flex:1 }}>
            {[
              { value:'racecond',  label:'TOCTOU race',  causal: true,
                desc: 'Concurrent requests exploit the validate-then-use gap — SAST clean.' },
              { value:'sqli',      label:'SQL inj',
                desc: 'Untrusted path param interpolated into SQL — classic CWE-89.' },
              { value:'cmdi',      label:'Cmd inj',
                desc: 'shell=True turns admin diag into RCE primitive.' },
              { value:'pathtrav',  label:'Path trav',
                desc: 'Filename joined into filesystem path with no canonicalization.' },
              { value:'xss-js',    label:'XSS (JSX)',
                desc: 'Server-rendered bio reaches dangerouslySetInnerHTML.' },
              { value:'cmdi-js',   label:'Node exec',
                desc: 'req.query.host into child_process.exec template literal.' },
              { value:'hardcoded', label:'Secrets',
                desc: 'Production credentials committed to source.' },
              { value:'safe',      label:'Clean',
                desc: 'Parameterized query + sanitizer dominates — no taint reaches sink.' },
              // Slice 6.4.5.2 Phase 12 (BUG-74)
              { value:'_user',     label:'Custom paste',
                desc: 'Paste your own Python code; live audit hits /switzerland/gate.' },
            // HC-69 — _user (Custom Paste) hidden during video recording.
            // Toggle window.DAEV_HIDE_CUSTOM_PASTE in wiring-init.jsx.
            ].filter(opt => opt.value !== '_user' || !window.DAEV_HIDE_CUSTOM_PASTE).map(opt => {
              const active = fixtureId === opt.value;
              return (
                <button key={opt.value} onClick={()=>setFixtureId(opt.value)} style={{
                  background: active ? t.bg2 : 'transparent',
                  color: active ? t.fg0 : t.fg1,
                  border:`1px solid ${active ? (opt.causal ? t.accent.base : t.line2) : (opt.causal ? t.accent.soft : t.line)}`,
                  borderRadius: t.radius.sm,
                  padding:'7px 10px',
                  fontFamily: t.font.ui,
                  cursor:'pointer',
                  letterSpacing: 0.1,
                  textAlign: 'left',
                  flex: '0 0 auto',
                  minWidth: 168,
                  display:'flex', flexDirection:'column', gap: 2,
                }} title={opt.causal ? 'Causal-only: SAST returns clean. DAEV catches via counterfactual reasoning.' : opt.desc}>
                  <span style={{ display:'inline-flex', alignItems:'center', gap: 6, fontSize: 11.5, fontWeight: active ? 600 : 500 }}>
                    {opt.causal && (
                      <span style={{
                        width: 6, height: 6, borderRadius:'50%',
                        background: t.accent.base,
                        boxShadow: `0 0 6px ${t.accent.base}`,
                      }}/>
                    )}
                    {opt.label}
                  </span>
                  <span style={{ fontSize: 10, color: t.fg2, lineHeight: 1.35, fontWeight: 400 }}>
                    {opt.desc.length > 80 ? opt.desc.slice(0,79) + '…' : opt.desc}
                  </span>
                </button>
              );
            })}
          </div>
          <div style={{
            fontFamily: t.font.mono, fontSize: 10,
            color: t.fg2, letterSpacing: 1, textTransform:'uppercase',
          }}>lang</div>
          <div style={{
            fontFamily: t.font.mono, fontSize: 11, color: t.fg1,
            padding:'4px 10px', border:`1px solid ${t.line}`,
            borderRadius: t.radius.sm, background: t.bg1,
          }}>{langLabel}</div>
        </div>

        {/* Editor filename bar */}
        <div style={{
          padding:'6px 14px',
          display:'flex', alignItems:'center', gap:10,
          fontFamily: t.font.mono, fontSize: 11, color: t.fg2,
          borderBottom:`1px solid ${t.line}`,
          background: t.bg0,
        }}>
          <span style={{
            width: 6, height: 6, borderRadius:'50%', background: t.accent.base,
          }}/>
          {fileName}
          <span style={{ color: t.fg3, marginLeft: 6 }}>· {fx.lines.length} lines</span>
          <span style={{
            fontFamily: t.font.mono, fontSize: 9, fontWeight: 700,
            color: t.accent.base, letterSpacing: 1.2, textTransform:'uppercase',
            padding:'1px 6px',
            border: `1px solid ${t.accent.base}`,
            borderRadius: t.radius.sm,
            marginLeft: 8,
          }}>// selected</span>
          <span style={{ flex:1 }}/>
          <span>UTF-8 · LF · {langLabel}</span>
        </div>

        <div data-tour="code-editor" style={{ flex:1, minHeight:0, overflow:'hidden' }}>
          {fixtureId === '_user' ? (
            <textarea
              value={userCode}
              onChange={handleUserCodeChange}
              spellCheck={false}
              placeholder="# Paste your Python code here…"
              style={{
                width: '100%', height: '100%',
                padding: '14px 16px',
                background: t.bg0, color: t.fg0,
                border: 'none', outline: 'none', resize: 'none',
                fontFamily: t.font.mono, fontSize: 12.5, lineHeight: 1.55,
                whiteSpace: 'pre',
              }}
            />
          ) : (
            <CodeEditor t={t} lines={fx.lines} language={fx.lang}
              highlightLine={fx.finding ? fx.finding.line : null}/>
          )}
        </div>

        {/* Slice 6.4.5 wiring brief — GitHub URL input.
            2026-05-11 pre-LOI demo: disabled + COMING SOON badge while the
            F-216 broader graph-density consumer audit lands in slice 6.5.x.
            Wrapper adds `position: relative` so the badge can absolute-
            position over the dimmed inner div without inheriting opacity. */}
        <div style={{ position: 'relative', margin: '10px 16px 0' }}>
          <div data-tour="github-url-input" style={{
            padding: '10px 12px',
            border: `1px solid ${t.line2}`,
            borderRadius: 6,
            background: t.bg2,
            display: 'flex',
            alignItems: 'center',
            gap: 8,
            opacity: 0.5,
            pointerEvents: 'none',
          }}>
            <span style={{
              fontFamily: t.font.mono, fontSize: 11, fontWeight: 600,
              color: t.fg2, letterSpacing: 0.6, textTransform: 'uppercase',
              whiteSpace: 'nowrap',
            }}>OR Repo URL</span>
            <input
              type="text"
              placeholder="https://github.com/owner/repo (Python only)"
              value={githubUrl}
              onChange={e => setGithubUrl(e.target.value)}
              disabled
              readOnly
              style={{
                flex: 1,
                padding: '6px 8px',
                border: `1px solid ${t.line2}`,
                borderRadius: 4,
                background: t.bg0,
                color: t.fg0,
                fontFamily: t.font.mono, fontSize: 12,
                outline: 'none',
              }}
            />
            <button
              onClick={() => onRunGithubAudit && onRunGithubAudit(githubUrl)}
              disabled
              style={{
                padding: '6px 12px',
                border: `1px solid ${t.accent.base}`,
                borderRadius: 4,
                background: 'transparent',
                color: t.fg2,
                fontFamily: t.font.ui, fontSize: 12, fontWeight: 600,
                cursor: 'not-allowed',
              }}
            >
              Audit Repo
            </button>
          </div>
          <span style={{
            position: 'absolute',
            top: -8,
            right: 10,
            padding: '2px 8px',
            background: t.accent.base,
            color: '#fff',
            fontFamily: t.font.mono, fontSize: 9, fontWeight: 700,
            letterSpacing: 1.2, textTransform: 'uppercase',
            borderRadius: 3,
          }}>Coming Soon</span>
        </div>

        {/* Bottom control strip */}
        <div style={{
          padding: '14px 16px',
          borderTop:`1px solid ${t.line}`,
          background: t.bg0,
          display:'flex', alignItems:'center', gap:14,
        }}>
          <div style={{
            fontFamily: t.font.mono, fontSize: 10,
            color: t.fg2, letterSpacing: 1, textTransform:'uppercase',
          }}>mode</div>
          <span data-tour="audit-mode" style={{ display:'inline-flex' }}>
          <Segmented t={t} value={mode} onChange={setMode} options={[
            { value:'fast', label:'Fast', icon:<Icon name="zap" size={12}/>,
              title:'~6s · graph + root cause · single-pass SecurityAgent' },
            { value:'council', label:'Council', icon:<Icon name="brain" size={12}/>,
              title:'~30–90s · 5-agent debate · 4 rounds · sycophancy correction' },
          ]}/>
          </span>
          <div style={{ flex:1 }}/>
          <div style={{ fontFamily: t.font.mono, fontSize: 11, color: t.fg2 }}>
            {mode === 'fast' ? '~3–15s' : '~30–90s'}
          </div>
          <Button t={t} variant="primary" size="lg"
            onClick={onRunAudit}
            icon={<Icon name="play" size={12} color={t.mode==='dark'?'oklch(0.14 0.01 240)':'white'}/>}>
            Audit
          </Button>
        </div>
      </div>

      {/* RIGHT: empty state / ghost graph */}
      <div style={{ width:'50%', display:'flex', flexDirection:'column', background: t.bg0 }}>
        <div style={{
          padding:'10px 14px',
          fontFamily: t.font.mono, fontSize: 10,
          color: t.fg2, letterSpacing: 1, textTransform:'uppercase',
          borderBottom:`1px solid ${t.line}`,
          display:'flex', alignItems:'center', gap: 10,
        }}>
          <span>causal graph</span>
          <span style={{ color: t.fg3 }}>· awaiting audit</span>
        </div>
        <div style={{ flex:1, position:'relative', overflow:'hidden' }}>
          <GhostGraph t={t}/>
          <div style={{
            position:'absolute', inset:0,
            display:'flex', flexDirection:'column',
            alignItems:'center', justifyContent:'center',
            gap: 12,
            pointerEvents:'none',
          }}>
            <div style={{
              fontFamily: t.font.ui, fontSize: 20, fontWeight: 500,
              color: t.fg1, letterSpacing: -0.3,
            }}>Your causal graph will render here</div>
            <div style={{
              fontFamily: t.font.mono, fontSize: 12, color: t.fg2,
              maxWidth: 440, textAlign:'center', lineHeight: 1.6,
            }}>
              Sources, sinks, sanitizers and taint flow appear as nodes arrive
              from the reasoning stream. Run an audit to begin.
            </div>
            <div style={{
              marginTop: 14,
              fontFamily: t.font.mono, fontSize: 10, color: t.fg3,
              letterSpacing: 1, textTransform:'uppercase',
              display:'flex', gap: 18,
            }}>
              <span>pearl ladder · intervention · counterfactual</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function GhostGraph({ t }) {
  // Subtle pre-rendered placeholder of node silhouettes
  const nodes = [
    {x:0.15,y:0.4}, {x:0.35,y:0.4}, {x:0.55,y:0.35},
    {x:0.55,y:0.6}, {x:0.75,y:0.5}, {x:0.9,y:0.35},
  ];
  return (
    <svg width="100%" height="100%" style={{ position:'absolute', inset:0, opacity: 0.35 }}>
      <defs>
        <pattern id="ghostGrid" width="8" height="8" patternUnits="userSpaceOnUse">
          <circle cx="1" cy="1" r="0.6" fill={t.line} fillOpacity="0.5"/>
        </pattern>
      </defs>
      <rect width="100%" height="100%" fill="url(#ghostGrid)"/>
      <g stroke={t.line2} strokeWidth="1" fill="none" strokeDasharray="3 3">
        <line x1="15%" y1="40%" x2="35%" y2="40%"/>
        <line x1="35%" y1="40%" x2="55%" y2="35%"/>
        <line x1="35%" y1="40%" x2="55%" y2="60%"/>
        <line x1="55%" y1="35%" x2="75%" y2="50%"/>
        <line x1="55%" y1="60%" x2="75%" y2="50%"/>
        <line x1="75%" y1="50%" x2="90%" y2="35%"/>
      </g>
      {nodes.map((n,i) => (
        <circle key={i} cx={`${n.x*100}%`} cy={`${n.y*100}%`} r="8"
          fill={t.bg2} stroke={t.line2} strokeWidth="1"/>
      ))}
    </svg>
  );
}

Object.assign(window, { TopBar, AuditInput });
