<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>adom-schematic</title>
<style>
  /* Canonical Adom design tokens (adom-ui-design). Legacy names kept as aliases so
     the rest of this stylesheet is untouched. Primary accent is #00b8b0; #00e6dc is
     the bright hover variant. */
  :root { color-scheme: dark;
    --bg:#0d1117; --panel:#161b22; --elevated:#1c2128; --overlay:#21262d; --edge:#30363d;
    --ink:#e6edf3; --mut:#8b949e; --acc:#00b8b0; --acc2:#00e6dc;
    --green:#3fb950; --red:#f85149; --yellow:#d29922;
    --line:var(--edge); --txt:var(--ink); --muted:var(--mut); --accent:var(--acc); }
  * { box-sizing: border-box; }
  /* Three fonts by role (declared by name w/ system fallbacks, matching APM): body
     Satoshi, headers Familjen Grotesk, data/meta JetBrains Mono. */
  html, body { margin: 0; height: 100%; background: var(--bg); color: var(--txt); font: 13px/1.45 'Satoshi', -apple-system, 'Segoe UI', Roboto, sans-serif; overflow: hidden; }
  /* dragging to pan shouldn't select the sheet's text/labels */
  #svgbox, #svgbox * { user-select: none; -webkit-user-select: none; }
  /* match the sheet colour so the drawing reads as one infinite sheet, not a
     white page floating on a dark viewport */
  #svgbox { position: absolute; inset: 0; cursor: grab; background: #fbfbf6; }
  #svgbox:active { cursor: grabbing; }
  #svgbox svg { display: block; }
  .empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); }

  /* component hotspots: transparent hit targets (no visual). */
  #svgbox svg .adom-comp { pointer-events: fill; cursor: pointer; }
  /* hierarchical-sheet links: highlight the box on hover, click to descend */
  #svgbox svg .adom-sheet-link { pointer-events: fill; cursor: pointer; }
  #svgbox svg .adom-sheet-link:hover { fill: var(--accent); fill-opacity: .12; stroke: var(--accent); stroke-width: .4; }
  /* sheet breadcrumb, top-left */
  #crumb { position: fixed; right: 12px; top: 12px; z-index: 40; display: none; align-items: center; gap: 6px;
           background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 5px 10px; font-size: 12px; }
  #crumb a { color: var(--accent); cursor: pointer; text-decoration: none; }
  #crumb a:hover { text-decoration: underline; }
  #crumb .sep { color: var(--muted); }
  #crumb .cur { color: var(--txt); }
  #crumb .sheetlbl { color: var(--muted); font-size: 10px; letter-spacing: .06em; text-transform: uppercase; }
  #crumb select { background: var(--elevated, #1c2128); color: var(--txt); border: 1px solid var(--line); border-radius: 6px; padding: 3px 6px; font: inherit; font-size: 12px; cursor: pointer; }
  #crumb select:focus { outline: none; border-color: var(--accent); }
  /* Hover highlight: recolour the hovered symbol's real KiCad strokes to the
     accent teal. This is a plain paint (a `stroke` swap), NOT an SVG `filter` —
     per-element drop-shadow filters forced an offscreen render for EACH of a
     symbol's strokes (a connector like J3 has ~1500), which made hovering crawl.
     A stroke recolour reads just as clearly and repaints almost for free.
     `paint-order:stroke` + a hairline widen makes it pop without a filter. */
  #svgbox svg .adom-sheet .symhl {
    stroke: #00b3a6 !important;
    stroke-width: .28 !important;
    paint-order: stroke;
  }
  /* keep the body fill readable: recolour its outline but don't fatten the fill */
  #svgbox svg .adom-sheet rect.symhl { stroke-width: .2 !important; }

  .panel { position: absolute; background: rgba(22,27,34,.82); backdrop-filter: blur(8px); border: 1px solid var(--line); border-radius: 10px; }
  #side { top: 12px; right: 12px; width: 220px; max-height: 94vh; padding: 10px 12px; display: flex; flex-direction: column; }
  #side h1 { margin: 0 0 8px; font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
  .sec-h { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600; margin: 2px 0 5px; border-bottom: 1px solid var(--line); padding-bottom: 3px; }
  #complist { overflow-y: auto; max-height: 74vh; }
  .crow { padding: 3px 7px; border-radius: 5px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .crow b { color: var(--accent); }
  .crow:hover { background: #1c2a2a; }
  .crow.sel { background: var(--accent); color: #06232a; }
  .crow.sel b { color: #06232a; }
  #fitbtn { margin-top: 8px; width: 100%; background: #17231c; color: var(--txt); border: 1px solid var(--line); border-radius: 7px; padding: 5px; cursor: pointer; }
  #fitbtn:hover { border-color: var(--accent); }
  #stat { bottom: 12px; left: 12px; padding: 6px 11px; color: var(--muted); }
  .muted { color: var(--muted); }

  /* follows the cursor and flips away from the viewport edges (same as the
     layout viewer); a click pins it where it currently sits, and only then does
     it accept pointer events so the JLC/wiki/datasheet links are clickable. */
  #card { position: fixed; z-index: 9999; display: none; min-width: 210px; max-width: 300px; padding: 10px 12px; pointer-events: none; }
  /* abridged hover card (small/embedded screens): ref · MPN · stock only */
  #card.brief { min-width: 0; max-width: 230px; padding: 7px 9px; }
  #card.brief .ci-h { margin-bottom: 4px; padding-bottom: 4px; }
  #card.brief .ci-ref { font-size: 13px; }
  #card.pinned { pointer-events: auto; box-shadow: 0 0 0 1px var(--accent); }
  .ci-h { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 5px; padding-bottom: 5px; border-bottom: 1px solid var(--line); }
  .ci-ref { font-weight: 700; color: var(--accent); font-size: 15px; }
  .ci-val { color: var(--txt); }
  .ci-desc { color: var(--muted); font-size: 12px; margin-bottom: 6px; }
  .ci-row { display: flex; justify-content: space-between; gap: 10px; padding: 1px 0; }
  .ci-k { color: var(--muted); }
  .ci-v { text-align: right; word-break: break-word; }
  .ci-enrich { margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--line); }
  .pills { display: flex; flex-wrap: wrap; gap: 5px; }
  .pill { background: #17231c; border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; font-size: 11px; }
  .pill.ok { color: #57d97e; border-color: #2c5a3a; }
  .pill.no { color: #e08a8a; border-color: #5a2c2c; }
  .pill.tier { color: #f2d060; }
  .pill.pop { color: #cba6ff; }
  .ci-mfr { color: var(--txt); font-size: 12px; margin-bottom: 5px; }
  .ci-links { margin-top: 6px; display: flex; gap: 12px; }
  .ci-lnk, .ci-ds { color: #6bb3ff; text-decoration: none; font-size: 12px; }
  .ci-ds { display: inline-block; margin-top: 6px; }
  #side h1, .sec-h { font-family: 'Familjen Grotesk', -apple-system, sans-serif; }

  /* ── canonical Adom 44px three-zone header (brand · subject · actions) ──
     Shown standalone / fullscreened; hidden in APM's small embedded panes
     (body.chrome gate, same as the side panels). */
  header.app { display: none; position: fixed; top: 0; left: 0; right: 0; height: 44px; z-index: 50;
    grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px; padding: 0 14px;
    background: var(--panel); border-bottom: 1px solid var(--edge); }
  body.chrome header.app { display: grid; }
  body.chrome #svgbox { top: 44px; }
  body.chrome #side { top: 56px; }
  body.chrome #crumb { top: 56px; }
  header.app .brand { display: flex; align-items: center; gap: 8px; min-width: 0; position: relative; cursor: default; padding-right: 14px; border-right: 1px solid var(--edge); }
  header.app .brand svg { width: 16px; height: 16px; color: var(--ink); flex: 0 0 16px; }
  header.app .app-name { font-family: 'Familjen Grotesk', -apple-system, sans-serif; font-weight: 600; font-size: 13px; color: var(--acc); white-space: nowrap; }
  header.app .app-sub { color: var(--mut); font-size: 12px; white-space: nowrap; }
  header.app .app-sub::before { content: "·"; margin: 0 6px; color: var(--mut); }
  header.app .subject { justify-self: center; display: flex; align-items: baseline; gap: 10px; min-width: 0; }
  header.app .subject-name { font-weight: 600; font-size: 13px; max-width: 44vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  header.app .subject-meta { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px; color: var(--mut); white-space: nowrap; }
  header.app .actions { justify-self: end; display: flex; align-items: center; gap: 8px; }
  header.app .actions button { background: var(--elevated); color: var(--ink); border: 1px solid var(--edge); border-radius: 7px; width: 30px; height: 26px; cursor: pointer; display: grid; place-items: center; }
  header.app .actions button:hover { border-color: var(--acc); }
  header.app .actions button svg { width: 15px; height: 15px; }
  header.app .appinfo { position: absolute; top: calc(100% + 6px); left: 0; min-width: 220px; background: var(--overlay); border: 1px solid var(--edge);
    border-radius: 10px; box-shadow: 0 12px 34px #000a; padding: 12px 14px; font-size: 12px; opacity: 0; visibility: hidden; transition: opacity .18s ease; pointer-events: none; z-index: 60; }
  header.app .brand:hover .appinfo { opacity: 1; visibility: visible; pointer-events: auto; transition-delay: .6s; }
  header.app .appinfo .ai-row { display: flex; justify-content: space-between; gap: 16px; padding: 2px 0; }
  header.app .appinfo .ai-k { color: var(--mut); }
  header.app .appinfo .ai-v { font-family: 'JetBrains Mono', ui-monospace, monospace; }
  header.app .appinfo a { color: var(--acc); text-decoration: none; }
  header.app .appinfo a:hover { text-decoration: underline; }

  /* ── toasts: transient feedback, bottom-center; also the AI's live channel ── */
  #toasts { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 3000; display: flex; flex-direction: column-reverse; gap: 8px; align-items: center; pointer-events: none; }
  .toast { pointer-events: auto; min-width: 200px; max-width: min(420px,90vw); display: flex; align-items: center; gap: 10px; padding: 10px 13px; border-radius: 10px;
    background: var(--overlay); border: 1px solid var(--edge); color: var(--ink); font-size: 13px; box-shadow: 0 10px 30px #000a; cursor: pointer; animation: toastin .18s ease; }
  @keyframes toastin { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
  .toast.out { opacity: 0; transform: translateY(8px); transition: opacity .2s ease, transform .2s ease; }
  .toast .ti { flex: 0 0 16px; width: 16px; height: 16px; }
  .toast.success .ti { color: var(--green); } .toast.success { border-color: #2c5a3a; }
  .toast.error .ti { color: var(--red); } .toast.error { border-color: #5a2c2c; }
  .toast.info .ti { color: var(--acc); }
  .toast .tmsg { flex: 1; min-width: 0; }

  /* ── tooltips: body-appended fixed div, 600ms reveal, viewport-clamped both axes.
     Never a ::after (clipped by panel overflow/backdrop-filter). ── */
  #tt { position: fixed; z-index: 99999; max-width: 260px; background: var(--overlay); color: var(--ink); border: 1px solid var(--edge);
    border-radius: 7px; padding: 6px 9px; font-size: 12px; line-height: 1.4; box-shadow: 0 8px 22px #000b; pointer-events: none;
    opacity: 0; transform: translateY(3px); transition: opacity .18s ease, transform .18s ease; text-transform: none; }
  #tt.show { opacity: 1; transform: none; }
  @media (hover: none), (pointer: coarse) { #tt { display: none; } }
</style>
</head>
<body>
  <header class="app">
    <div class="brand">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h4l2-5 3 10 2-5h7"/><circle cx="19" cy="12" r="1.4"/></svg>
      <span class="app-name">Schematic Viewer</span><span class="app-sub">interactive sheet</span>
      <div class="appinfo">
        <div class="ai-row"><span class="ai-k">version</span><span class="ai-v" id="ai-ver">-</span></div>
        <div class="ai-row"><span class="ai-k">engine</span><span class="ai-v">KiCad · Altium · Fusion</span></div>
        <div class="ai-row"><span class="ai-k">source</span><a href="https://wiki.adom.inc/adom/adom-schematic" target="_blank" rel="noopener">wiki page ↗</a></div>
      </div>
    </div>
    <div class="subject"><span class="subject-name" id="hdr-name"></span><span class="subject-meta" id="hdr-meta"></span></div>
    <div class="actions">
      <button id="hdr-fit" data-tip="Fit the whole sheet to the view (also: the Fit button, or press F)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"/></svg></button>
    </div>
  </header>
  <div id="svgbox"><div class="empty">loading…</div></div>
  <div id="crumb"></div>
  <div id="side" class="panel">
    <div class="sec-h">Components</div>
    <div id="complist"></div>
    <button id="fitbtn" data-tip="Zoom to fit the entire sheet">Fit</button>
  </div>
  <div id="stat" class="panel"></div>
  <div id="card" class="panel"></div>
  <div id="toasts"></div>
  <script src="viewer.js"></script>
</body>
</html>