
  :root{
    --void:#070810; --panel:#0c0e1a; --ink:#f3f6fc; --muted:#8890a6;
    --hair:rgba(255,255,255,.07); --hair-2:rgba(255,255,255,.13);
    --violet:#b58cff;  /* LEARNING   */
    --cyan:#63e6ff;    /* OPERATIONS */
    --fuchsia:#d98cf0; /* WRITING    */
    --sand:#c9ad7d;    /* SUBSTRATE  */
    --ghost:#5f6d86;   /* outside    */
    --core:#dff2ff;
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html,body{height:100%;margin:0;overflow:hidden}
  body{
    background:var(--void); color:var(--ink);
    font-family:'IBM Plex Sans Condensed',ui-sans-serif,system-ui,sans-serif;
    -webkit-font-smoothing:antialiased; overflow:hidden;
  }
  .wrap{display:grid;grid-template-rows:auto 1fr auto;height:100%;min-height:0}

  /* ---------- masthead ---------- */
  .top{display:flex;align-items:baseline;gap:14px;padding:16px 22px 10px;flex-wrap:wrap}
  .brand{font-family:'Unbounded',sans-serif;font-weight:700;font-size:16px;letter-spacing:.02em}
  .sub{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.14em;
       text-transform:uppercase;color:var(--muted)}
  .live{margin-left:auto;font-family:'JetBrains Mono',monospace;font-size:9.5px;
        letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
        border:1px solid var(--hair);border-radius:100px;padding:4px 10px;white-space:nowrap}

  /* ---------- stage ---------- */
  .stage{position:relative;min-height:0;padding:0 18px 6px}
  .map{position:absolute;inset:0 18px 6px;min-width:0;min-height:0}
  canvas{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}

  /* ---------- layer chrome ---------- */
  .band,.rail,.slab{position:absolute;border:1px solid var(--hair-2);border-radius:10px;
        background:rgba(255,255,255,.012);pointer-events:none}
  .bandlab,.raillab{position:absolute;font-family:'JetBrains Mono',monospace;font-size:9px;
        letter-spacing:.22em;text-transform:uppercase;color:var(--muted);pointer-events:none}
  .raillab{writing-mode:vertical-rl;transform:rotate(180deg)}

  /* ---------- nodes ---------- */
  .node{position:absolute;transform:translate(-50%,-50%);display:flex;flex-direction:column;
        align-items:center;gap:5px;cursor:pointer;text-align:center;width:auto;white-space:nowrap;
        opacity:0;animation:rise .5s ease forwards}
  @keyframes rise{to{opacity:1}}
  .chip{display:flex;align-items:center;gap:6px;padding:5px 9px;border-radius:8px;
        border:1px solid var(--c);background:var(--panel);
        transition:box-shadow .18s ease,transform .18s ease}
  .node:hover .chip,.node.sel .chip{box-shadow:0 0 0 1px var(--c),0 0 22px -6px var(--c);transform:translateY(-1px)}
  .chip svg{width:14px;height:14px;color:var(--c);flex:none;overflow:visible}
  .chip .t{font-size:11px;font-weight:600;letter-spacing:.01em;white-space:nowrap}
  .cap{display:none;white-space:normal;font-family:'JetBrains Mono',monospace;font-size:8.5px;line-height:1.5;
       letter-spacing:.07em;text-transform:uppercase;color:var(--muted);max-width:150px}
  .node.layer .cap,.node.core .cap,.node.substrate .cap,.node:hover .cap,.node.sel .cap{display:block}
  .node.layer .chip{padding:8px 15px}
  .node.layer .chip .t{font-size:13.5px;font-family:'Unbounded',sans-serif;font-weight:600}
  .node.core .chip{padding:11px 19px;border-width:1.5px}
  .node.core .chip .t{font-size:16px;font-family:'Unbounded',sans-serif;font-weight:700}
  .node.ghosted .chip{border-style:dashed;opacity:.62}
  .node.ghosted .cap,.node.ghosted .chip .t{opacity:.62}
  .node.pending .chip{border-style:dashed}

  /* ---------- side panels ---------- */
  /* Panels float over the map. The map is the content; these are support and
     must not take width from it. */
  .side{position:absolute;top:0;bottom:46px;width:172px;display:flex;flex-direction:column;
        gap:10px;overflow:auto;z-index:4;transition:opacity .22s ease,transform .22s ease}
  .side.left{left:18px}
  .side.right{right:18px;width:252px;top:0;bottom:46px;max-height:calc(100% - 46px)}
  .side.hidden{opacity:0;transform:translateX(-14px);pointer-events:none}
  .side.right.hidden{transform:translateX(14px)}
  .card{border:1px solid var(--hair);border-radius:10px;
        background:color-mix(in srgb, var(--panel) 88%, transparent);
        backdrop-filter:blur(7px);padding:12px 13px}
  /* These were 9px muted grey with a 7%-opacity border on near-black: present
     in the DOM, invisible to a person. They are the only way to reopen a panel,
     so they have to be findable. Solid ground, real contrast, and a slow glow
     that runs a few times on arrival and then settles.
     The pulse is deliberately SLOW (2.4s) and finite. Rapid flashing is a
     photosensitive seizure risk and is ruled out everywhere else in this file;
     do not speed it up or make it loop forever. */
  .toggle{position:absolute;z-index:6;bottom:8px;font-family:'JetBrains Mono',monospace;
          font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink);
          background:#141827;border:1px solid rgba(181,140,255,.55);border-radius:100px;
          padding:7px 15px;cursor:pointer;
          box-shadow:0 2px 10px -2px rgba(0,0,0,.6);
          animation:noticeMe 2.4s ease-in-out 3}
  .toggle::after{content:' \25B4';opacity:.65}
  .toggle.off::after{content:' \25BE'}
  .toggle:hover{border-color:var(--violet);background:#1b2036;
                box-shadow:0 0 16px -3px rgba(181,140,255,.55)}
  .toggle:focus-visible{outline:2px solid var(--violet);outline-offset:2px}
  @keyframes noticeMe{
    0%,100%{box-shadow:0 2px 10px -2px rgba(0,0,0,.6)}
    50%    {box-shadow:0 0 18px -1px rgba(181,140,255,.75)}
  }
  @media (prefers-reduced-motion: reduce){ .toggle{animation:none} }
  #tKey{left:18px} #tDetail{right:18px}
  .hint{font-size:11.5px;line-height:1.55;color:#7c869c}
  .card h3{font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.2em;
           text-transform:uppercase;color:var(--muted);font-weight:500;margin-bottom:9px}
  .dtitle{font-size:15px;font-weight:600;margin-bottom:2px}
  .dtag{display:inline-block;font-family:'JetBrains Mono',monospace;font-size:8.5px;
        letter-spacing:.14em;text-transform:uppercase;padding:2px 7px;border-radius:100px;margin-bottom:9px}
  .dbody{font-size:12.5px;line-height:1.62;color:#cfd6e6}
  .dconn{margin-top:11px;padding-top:10px;border-top:1px solid var(--hair)}
  .dconn div{font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.06em;
             color:var(--muted);padding:2.5px 0}
  .kv{display:flex;align-items:center;gap:8px;padding:3.5px 0;
      font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.07em;
      text-transform:uppercase;color:var(--muted)}
  .sw{width:15px;height:0;border-top-width:2px;border-top-style:solid;flex:none}
  .dot{width:8px;height:8px;border-radius:50%;flex:none}
  .ring{width:9px;height:9px;border-radius:50%;border:2px solid;flex:none}

  /* ---------- footer ---------- */
  .foot{display:flex;gap:16px;align-items:center;flex-wrap:wrap;
        padding:8px 22px 14px;font-family:'JetBrains Mono',monospace;font-size:9px;
        letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
  .foot b{color:#aab3c8;font-weight:500}


  /* ---------- narrow screens ----------
     Below 860px the diagram cannot carry the architecture: one band is wider
     than the whole viewport. So the bands become SECTIONS. Same nodes, same
     descriptions, same structure — read top to bottom instead of centre out.
     Nothing is dropped; the spatial metaphor is, because it stops working. */
  .stack{display:none}
  @media (max-width:860px){
    /* The iframe-fit rule above pins html AND body to 100% with overflow
       hidden. That is right for the map and wrong for the stacked list,
       which is taller than the frame — it was being clipped at 568px with
       20 cards inside. Release both for narrow screens. */
    html{height:auto;overflow:visible}
    body{height:auto;overflow:auto}
    .wrap{display:block;height:auto;min-height:100vh}
    .stage,.toggle{display:none}
    .stack{display:block;padding:0 14px 26px}
    .sect{margin:16px 0 0}
    /* Sections collapse. Inside the site's iframe the frame is ~568px tall and
       the open list is ~1880px, so an all-open default means scroll-inside-
       scroll on a phone. Collapsed, the whole map fits the frame at rest. */
    .sect h4{display:flex;align-items:center;gap:7px;cursor:pointer;
             font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.22em;
             text-transform:uppercase;color:var(--muted);font-weight:500;
             padding:9px 0;border-bottom:1px solid var(--hair);margin-bottom:0}
    .sect h4::before{content:'+';font-size:12px;line-height:1;color:var(--muted)}
    .sect.open h4::before{content:'\2212'}
    .sect h4 .n{margin-left:auto;opacity:.6}
    .sect .row{display:none;padding:10px 0 2px}
    .sect.open .row{display:flex}
    .row{flex-direction:column;gap:8px}
    .mchip{border:1px solid var(--c);border-radius:9px;background:var(--panel);
           padding:10px 12px;cursor:pointer}
    .mhead{display:flex;align-items:center;gap:9px}
    .mhead svg{width:15px;height:15px;color:var(--c);flex:none;overflow:visible}
    .mhead .t{font-size:14px;font-weight:600}
    .mcap{font-family:'JetBrains Mono',monospace;font-size:8.5px;letter-spacing:.07em;
          text-transform:uppercase;color:var(--muted);margin-top:5px;line-height:1.5}
    .mdesc{display:none;font-size:13px;line-height:1.62;color:#cfd6e6;margin-top:9px;
           padding-top:9px;border-top:1px solid var(--hair)}
    .mchip.open .mdesc{display:block}
    .mchip.pending{border-style:dashed}
    .mchip.ghost{border-style:dashed;opacity:.7}
    /* Inside the site page the wrapper already carries the brand, the title and
       a "How to read the map" section, so the embed repeating them wastes the
       frame. The NOT A LIVE FEED pill stays — it is a locked claim and the
       wrapper does not say it. */
    .foot{display:none}
    .brand,.sub{display:none}
    .top{padding:12px 14px 0}
    .live{margin-left:0}
    .sect{margin:10px 0 0}
  }
  @media (max-width:1400px){ .stage{grid-template-columns:162px 1fr 232px} }
  @media (prefers-reduced-motion: reduce){ .node{animation:none;opacity:1} }
