// Variant 02 — HEX DUMP / MEMORY INSPECTOR (v2 — with fishki)
// Boot overlay, scramble-on-scroll decoding, hex byte tooltips,
// vertical mini-map navigator, project decompile view, glitch-on-hover headlines.

const { useEffect: hxUseEffect, useRef: hxUseRef, useState: hxUseState,
        useCallback: hxUseCallback, useMemo: hxUseMemo } = React;

// ── one-time CSS ─────────────────────────────────────────────────────────
if (typeof document !== 'undefined' && !document.getElementById('hx-styles')) {
  const s = document.createElement('style');
  s.id = 'hx-styles';
  s.textContent = `
    .hx { --bg:#08080a; --bg2:#0d0d10; --ink:#e8d6a8; --hi:#ffb86c;
          --cy:#7fe3e1; --gn:#8ef58e; --dim:#5a5247; --vdim:#2c2922;
          --red:#ff6e6e; --hair:#1a1814; --hair2:#2a2620;
          font-family: 'IBM Plex Mono','JetBrains Mono', ui-monospace, monospace;
          font-size: 13px; line-height: 1.55;
          background: var(--bg); color: var(--ink);
          position: relative; width: 100%; height: 100%; overflow: hidden;
          letter-spacing: 0; }

    .hx::before {
      content:''; position:absolute; inset:0; pointer-events:none;
      background-image:
        repeating-linear-gradient(180deg, rgba(255,184,108,0.025) 0 1px, transparent 1px 3px);
      mix-blend-mode: lighten;
    }
    .hx-scan {
      position:absolute; left:0; right:0; height: 60px; top: -60px;
      background: linear-gradient(180deg, transparent, rgba(127,227,225,0.06) 50%, transparent);
      pointer-events: none; animation: hx-scan 6s linear infinite; z-index: 1;
    }
    @keyframes hx-scan { 0% { top: -60px; } 100% { top: 100%; } }

    .hx-statusbar {
      position: relative; z-index: 5;
      display: grid; grid-template-columns: auto 1fr auto auto;
      gap: 28px; align-items: center;
      padding: 12px 32px;
      border-bottom: 1px solid var(--hair2);
      background: var(--bg2);
      font-size: 10.5px; letter-spacing: 0.04em; color: var(--dim);
    }
    .hx-statusbar .o { color: var(--hi); }
    .hx-statusbar .c { color: var(--cy); }
    .hx-statusbar .g { color: var(--gn); }
    .hx-statusbar .blip {
      display:inline-block; width:6px; height:6px; background: var(--gn);
      margin-right: 8px; animation: hx-pulse 1.2s infinite;
      vertical-align: 1px;
    }
    @keyframes hx-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }

    .hx-tabs {
      position: relative; z-index: 5;
      display: flex; gap: 0;
      padding: 0 32px; border-bottom: 1px solid var(--hair2);
      background: var(--bg2); font-size: 10.5px;
    }
    .hx-tabs .tab {
      padding: 8px 14px; color: var(--dim);
      border-right: 1px solid var(--hair2);
      letter-spacing: 0.04em;
    }
    .hx-tabs .tab.on { color: var(--hi); background: var(--bg); position:relative; }
    .hx-tabs .tab.on::before {
      content:''; position:absolute; top:0; left:0; right:0; height:1px;
      background: var(--hi);
    }
    .hx-tabs .tab .x { color: var(--dim); margin-left: 8px; }

    .hx-main { position: relative; z-index: 2; padding: 0; padding-right: 28px; }

    /* ── Section anchor ─────────── */
    .hx-anchor {
      display: grid; grid-template-columns: 100px 1fr auto;
      gap: 24px; align-items: baseline;
      padding: 28px 32px 10px;
      margin-top: 36px;
      border-bottom: 1px dashed var(--hair2);
      font-size: 11px; color: var(--cy);
    }
    .hx-anchor .ad { color: var(--hi); letter-spacing: 0.04em; }
    .hx-anchor .lb {
      font-size: 20px; color: var(--ink); letter-spacing: 0.04em;
      font-weight: 500;
    }
    .hx-anchor .lb .dot { color: var(--gn); }
    .hx-anchor .lb .sec { color: var(--cy); }
    .hx-anchor .rt { font-size: 10px; color: var(--dim); letter-spacing: 0.06em; }

    /* ── Hex rows ─────────────────────────── */
    .hx-dump { padding: 8px 32px; }
    .hx-row {
      display: grid; grid-template-columns: 100px 1fr 22ch;
      gap: 24px; padding: 2px 0;
      font-size: 12px; line-height: 1.55;
      white-space: nowrap;
    }
    .hx-row .ad { color: var(--dim); }
    .hx-row .by { color: var(--ink); }
    .hx-row .as { color: var(--cy); letter-spacing: 0.03em; }

    .hx-byte {
      display: inline-block; padding: 0 1px; margin: 0 1px 0 0;
      cursor: crosshair; transition: background 0.1s, color 0.1s;
    }
    .hx-byte.h { color: var(--hi); }
    .hx-byte.c { color: var(--cy); }
    .hx-byte.g { color: var(--gn); }
    .hx-byte.d { color: var(--vdim); }
    .hx-byte:hover { background: var(--hi); color: var(--bg) !important; }
    .hx-ascii { display: inline-block; padding: 0 1px; cursor: crosshair; }
    .hx-ascii.h { color: var(--hi); }
    .hx-ascii.g { color: var(--gn); }
    .hx-ascii.d { color: var(--vdim); }
    .hx-ascii:hover { background: var(--hi); color: var(--bg) !important; }

    /* hex byte tooltip */
    .hx-tooltip {
      position: fixed; z-index: 9999;
      background: var(--bg); border: 1px solid var(--hi);
      padding: 8px 12px; font-size: 10.5px; line-height: 1.7;
      color: var(--ink); pointer-events: none;
      white-space: nowrap; letter-spacing: 0.04em;
      box-shadow: 0 4px 24px rgba(0,0,0,0.5);
      opacity: 0; transition: opacity 0.08s;
    }
    .hx-tooltip.on { opacity: 1; }
    .hx-tooltip .k { color: var(--dim); display: inline-block; min-width: 38px; }
    .hx-tooltip .v { color: var(--ink); }
    .hx-tooltip .v.o { color: var(--hi); }
    .hx-tooltip .v.c { color: var(--cy); }
    .hx-tooltip .v.g { color: var(--gn); }
    .hx-tooltip::before {
      content:''; position:absolute; bottom:-5px; left: 12px;
      width: 8px; height: 8px; background: var(--bg);
      border-right: 1px solid var(--hi); border-bottom: 1px solid var(--hi);
      transform: rotate(45deg);
    }

    /* ── Hero ────────────── */
    .hx-hero { padding: 56px 32px 0; position: relative; }
    .hx-hero .deck {
      font-size: 10.5px; color: var(--dim); letter-spacing: 0.14em;
      text-transform: uppercase;
      display: grid; grid-template-columns: auto 1fr auto;
      gap: 20px; align-items: center;
      border-top: 1px solid var(--hair2); border-bottom: 1px solid var(--hair2);
      padding: 10px 0;
    }
    .hx-hero .deck .o { color: var(--hi); }
    .hx-hero .deck .g { color: var(--gn); }
    .hx-hero .deck .rule { flex:1; height:1px;
      background: repeating-linear-gradient(90deg, var(--hair2) 0 4px, transparent 4px 8px); }

    .hx-bigwrap {
      position: relative; padding: 44px 0 24px;
      display: grid; grid-template-columns: 1fr auto;
      gap: 56px; align-items: end;
    }
    .hx-big {
      font-family: 'Major Mono Display', monospace;
      font-size: 198px; line-height: 0.84;
      letter-spacing: -0.05em; color: var(--ink); text-transform: uppercase;
      position: relative;
    }
    .hx-big .a {
      background: linear-gradient(180deg, var(--hi), #d97f3a);
      -webkit-background-clip: text; background-clip: text;
      color: transparent;
    }
    .hx-big .cur {
      display: inline-block; width: 0.36em; height: 0.78em;
      vertical-align: -2px; background: var(--hi); margin-left: 0.04em;
      animation: hx-blink 0.9s steps(2,end) infinite;
    }
    @keyframes hx-blink { 50% { opacity: 0; } }

    .hx-bigaside {
      width: 320px;
      border-left: 1px solid var(--hair2); padding-left: 24px;
      font-size: 10.5px; line-height: 1.85; letter-spacing: 0.04em;
    }
    .hx-bigaside .k { color: var(--dim); letter-spacing: 0.16em; text-transform: uppercase;
                      font-size: 9.5px; display:block; margin-top: 12px; }
    .hx-bigaside .k:first-child { margin-top: 0; }
    .hx-bigaside .v { color: var(--ink); }
    .hx-bigaside .v.o { color: var(--hi); }
    .hx-bigaside .v.g { color: var(--gn); }
    .hx-bigaside .v.c { color: var(--cy); }

    .hx-prompt {
      margin-top: 20px; padding: 0;
      font-size: 13px; color: var(--ink);
      border-top: 1px solid var(--hair2);
      padding-top: 18px;
    }
    .hx-prompt .ps { color: var(--gn); }
    .hx-prompt .cmd { color: var(--hi); }
    .hx-prompt .arg { color: var(--cy); }
    .hx-prompt .ln { padding: 1px 0; }
    .hx-prompt .ln.out { color: var(--ink); padding-left: 0; }
    .hx-prompt .ln.dim { color: var(--dim); }

    /* ── Region ────────────────────── */
    .hx-region {
      border: 1px solid var(--hair2);
      margin: 24px 32px;
      background: linear-gradient(180deg, rgba(255,184,108,0.015), transparent);
    }
    .hx-region-h {
      display: grid; grid-template-columns: auto 1fr auto auto;
      gap: 16px; align-items: center;
      padding: 8px 14px;
      background: var(--bg2);
      border-bottom: 1px solid var(--hair2);
      font-size: 10.5px; letter-spacing: 0.06em;
    }
    .hx-region-h .ad { color: var(--hi); }
    .hx-region-h .tt { color: var(--ink); font-size: 11px; letter-spacing: 0.14em;
                       text-transform: uppercase; }
    .hx-region-h .rt { color: var(--dim); }
    .hx-region-h .pr { color: var(--gn); font-size: 9.5px; letter-spacing: 0.14em;
                       text-transform: uppercase; }
    .hx-region-b { padding: 16px 24px; }

    /* ── Bio ───────────────────────── */
    .hx-bio {
      display: grid; grid-template-columns: 32px 1fr;
      gap: 12px; font-size: 13.5px; line-height: 1.72;
    }
    .hx-bio .gut { color: var(--dim); text-align: right; line-height: 1.72;
                   font-size: 11px; padding-top: 1px; }
    .hx-bio .p { color: var(--ink); }
    .hx-bio .p strong { color: var(--hi); font-weight: 500; }
    .hx-bio .p .c { color: var(--cy); }
    .hx-bio .com { color: var(--dim); font-size: 12px; }

    /* ── Skills ────────────────────── */
    .hx-skill-grid {
      display: grid; grid-template-columns: 1fr 1fr; gap: 0 56px;
    }
    .hx-skill-row {
      display: grid; grid-template-columns: 130px 1fr 50px;
      gap: 14px; align-items: center;
      padding: 8px 0; border-bottom: 1px dashed var(--hair2);
      font-size: 12px;
    }
    .hx-skill-row .k { color: var(--ink); }
    .hx-skill-row .bar { color: var(--hi); letter-spacing: -1px;
      font-family: 'IBM Plex Mono', monospace; overflow: hidden; white-space: nowrap; }
    .hx-skill-row .bar .e { color: var(--vdim); }
    .hx-skill-row .v { color: var(--cy); text-align: right;
      font-family: 'IBM Plex Mono', monospace; }
    .hx-skill-row .v::after { content: ' %'; color: var(--dim); }
    .hx-skill-row .v::before { content: '0x'; color: var(--dim); }

    .hx-stack {
      display: grid; grid-template-columns: 90px 1fr 80px;
      gap: 14px; font-size: 12px; padding: 6px 0;
      border-bottom: 1px dashed var(--hair2);
    }
    .hx-stack .ad { color: var(--dim); }
    .hx-stack .k { color: var(--ink); }
    .hx-stack .v { color: var(--cy); text-align: right; }
    .hx-stack.hot .k { color: var(--hi); }
    .hx-stack.hot .v { color: var(--gn); }
    .hx-stack.hot .v::before { content: '★ '; color: var(--gn); }

    /* ── Work ───────────────────────── */
    .hx-strct { margin: 14px 0; font-size: 13px; line-height: 1.7; }
    .hx-strct .opn, .hx-strct .clo { color: var(--cy); }
    .hx-strct .row { display: grid; grid-template-columns: 130px 1fr; gap: 14px; }
    .hx-strct .row .k { color: var(--dim); padding-left: 24px;
      font-size: 11.5px; padding-top: 2px; }
    .hx-strct .row .v { color: var(--ink); }
    .hx-strct .val.str { color: var(--gn); }
    .hx-strct .val.str::before, .hx-strct .val.str::after { content: '"'; color: var(--gn); }
    .hx-strct .val.num { color: var(--cy); }
    .hx-strct .val.flag { color: var(--hi); }
    .hx-strct .nm {
      font-family: 'Major Mono Display', monospace; font-size: 38px;
      color: var(--ink); letter-spacing: -0.03em; text-transform: uppercase;
      line-height: 1; margin: 4px 0;
    }
    .hx-strct .nm .dot { color: var(--hi); }
    .hx-strct .tag {
      color: var(--cy); font-size: 10.5px; letter-spacing: 0.14em;
      text-transform: uppercase; margin-bottom: 14px;
    }
    .hx-strct .desc {
      color: var(--ink); font-size: 13px; line-height: 1.6;
      max-width: 60ch; margin: 0 0 18px;
    }

    /* decompile toggle */
    .hx-tools {
      display: flex; gap: 4px; padding: 4px 0 14px;
      border-bottom: 1px dashed var(--hair2); margin-bottom: 14px;
    }
    .hx-tools button {
      font-family: 'IBM Plex Mono', monospace;
      background: transparent; border: 1px solid var(--hair2);
      color: var(--dim); padding: 4px 10px; cursor: pointer;
      font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
      transition: border-color 0.15s, color 0.15s, background 0.15s;
    }
    .hx-tools button:hover { border-color: var(--hi); color: var(--hi); }
    .hx-tools button.on { background: var(--hi); color: var(--bg); border-color: var(--hi); }
    .hx-tools .sp { flex: 1; }

    /* disassembly view */
    .hx-asm {
      font-family: 'IBM Plex Mono', monospace; font-size: 12px;
      line-height: 1.75; padding: 6px 0;
    }
    .hx-asm .ln {
      display: grid;
      grid-template-columns: 130px 24px 90px 1fr;
      gap: 8px; padding: 1px 0;
    }
    .hx-asm .ln:hover { background: rgba(255,184,108,0.04); }
    .hx-asm .ad { color: var(--dim); }
    .hx-asm .by { color: var(--cy); font-size: 11px; opacity: 0.7; }
    .hx-asm .op { color: var(--hi); }
    .hx-asm .ar { color: var(--ink); }
    .hx-asm .ar .reg { color: var(--cy); }
    .hx-asm .ar .imm { color: var(--gn); }
    .hx-asm .ar .lbl { color: var(--hi); }
    .hx-asm .ar .com { color: var(--dim); }
    .hx-asm .lbl-line { color: var(--gn); padding: 8px 0 2px; }
    .hx-asm .lbl-line::before { content:''; }

    /* ── Timeline ─────────────────── */
    .hx-tl {
      font-size: 13px;
      display: grid; grid-template-columns: 140px 18px 1fr;
      gap: 28px;
      padding: 24px 0; border-bottom: 1px dashed var(--hair2);
      position: relative;
    }
    .hx-tl .date { color: var(--hi); font-size: 11px; line-height: 1.7;
      letter-spacing: 0.04em; }
    .hx-tl .date .to { color: var(--dim); }
    .hx-tl .date .now {
      display: inline-block; margin-top: 6px; padding: 2px 6px;
      background: var(--gn); color: var(--bg);
      font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase;
      font-weight: 700;
    }
    .hx-tl .marker { position: relative; }
    .hx-tl .marker::before {
      content:'■'; position:absolute; left: 0; top: 0;
      color: var(--hi); font-size: 12px;
    }
    .hx-tl .body .rl {
      font-family: 'Major Mono Display', monospace;
      font-size: 22px; color: var(--ink); letter-spacing: -0.02em;
      text-transform: uppercase; line-height: 1;
    }
    .hx-tl .body .rl .it { color: var(--hi); }
    .hx-tl .body .co {
      color: var(--cy); font-size: 10.5px; letter-spacing: 0.14em;
      text-transform: uppercase; margin: 8px 0 12px;
    }
    .hx-tl .body .ds { color: var(--ink); font-size: 13px; line-height: 1.65;
      max-width: 60ch; }
    .hx-tl .body .ds strong { color: var(--hi); font-weight: 500; }

    /* ── Contact ─────────────────── */
    .hx-ct-big {
      font-family: 'Major Mono Display', monospace;
      font-size: 132px; letter-spacing: -0.04em; text-transform: uppercase;
      line-height: 0.88; color: var(--ink);
      padding: 20px 0 18px;
    }
    .hx-ct-big .a { color: var(--hi); }

    .hx-ct-lns { border-top: 1px solid var(--hair2); margin-top: 18px; }
    .hx-ct-ln {
      display: grid; grid-template-columns: 80px 1fr auto auto 24px;
      gap: 18px; align-items: center;
      padding: 18px 8px;
      border-bottom: 1px solid var(--hair2);
      text-decoration: none; color: inherit;
      transition: background 0.15s, padding-left 0.18s;
    }
    .hx-ct-ln:hover { background: rgba(255,184,108,0.05); padding-left: 18px; }
    .hx-ct-ln:hover .arr { color: var(--hi); transform: translate(2px,-2px); }
    .hx-ct-ln .ad { color: var(--dim); font-size: 11px; }
    .hx-ct-ln .nm {
      color: var(--ink); font-size: 18px; line-height: 1;
      font-family: 'Major Mono Display', monospace; letter-spacing: -0.02em;
      text-transform: uppercase;
    }
    .hx-ct-ln .nm .dot { color: var(--hi); }
    .hx-ct-ln .vl { color: var(--cy); font-size: 11px; margin-top: 6px; }
    .hx-ct-ln .ic { color: var(--hi); font-size: 12px; font-weight: 500;
      letter-spacing: 0.04em; }
    .hx-ct-ln .tg { color: var(--dim); font-size: 9.5px; letter-spacing: 0.16em;
      text-transform: uppercase; }
    .hx-ct-ln .arr {
      color: var(--dim); font-family: 'Major Mono Display', monospace;
      font-size: 16px; transition: color 0.15s, transform 0.15s; text-align: right;
    }

    /* footer */
    .hx-foot {
      display: grid; grid-template-columns: 1fr auto 1fr;
      padding: 16px 32px;
      border-top: 1px solid var(--hair2);
      background: var(--bg2);
      font-size: 10px; letter-spacing: 0.04em; color: var(--dim);
      margin-top: 40px;
    }
    .hx-foot .c { text-align: center; }
    .hx-foot .r { text-align: right; }
    .hx-foot .o { color: var(--hi); }
    .hx-foot .g { color: var(--gn); }

    /* ── FISHKA 1: boot overlay ───────────────────── */
    .hx-boot {
      position: absolute; inset: 0; z-index: 1000;
      background: var(--bg);
      padding: 56px 64px;
      font-family: 'IBM Plex Mono', monospace; font-size: 14px;
      line-height: 1.7; color: var(--ink);
      overflow: hidden; cursor: pointer;
      transition: opacity 0.35s ease-out;
    }
    .hx-boot.fade { opacity: 0; pointer-events: none; }
    .hx-boot .hd {
      display: flex; justify-content: space-between; align-items: baseline;
      font-size: 11px; color: var(--dim); letter-spacing: 0.14em;
      text-transform: uppercase;
      border-bottom: 1px solid var(--hair2);
      padding-bottom: 16px; margin-bottom: 28px;
    }
    .hx-boot .hd .o { color: var(--hi); }
    .hx-boot .ln {
      display: grid; grid-template-columns: 90px 1fr auto;
      gap: 18px; align-items: baseline;
      padding: 2px 0; opacity: 0;
    }
    .hx-boot .ln.in { opacity: 1; }
    .hx-boot .ln .tg { color: var(--gn); }
    .hx-boot .ln .tg.warn { color: var(--hi); }
    .hx-boot .ln .tg.boot { color: var(--cy); }
    .hx-boot .ln .ms { color: var(--ink); }
    .hx-boot .ln .rs { color: var(--gn); font-weight: 500; }
    .hx-boot .ln .rs.warn { color: var(--hi); }
    .hx-boot .skip {
      position: absolute; bottom: 32px; left: 64px;
      font-size: 11px; color: var(--dim); letter-spacing: 0.14em;
      text-transform: uppercase;
    }
    .hx-boot .skip kbd {
      display: inline-block; padding: 2px 8px; margin: 0 2px;
      border: 1px solid var(--dim); color: var(--ink);
      font-family: inherit; font-size: 10px;
    }
    .hx-boot .cur {
      display: inline-block; width: 9px; height: 14px; vertical-align: -2px;
      background: var(--hi); margin-left: 6px;
      animation: hx-blink 0.9s steps(2,end) infinite;
    }
    .hx-boot .ascii {
      margin-top: 28px; color: var(--hi);
      font-size: 12px; line-height: 1.1; opacity: 0;
      transition: opacity 0.4s ease-in;
    }
    .hx-boot .ascii.in { opacity: 1; }

    /* ── FISHKA 7: mini-map ──────────────────────── */
    .hx-mini {
      position: absolute; right: 0; top: 0; bottom: 0; width: 28px;
      background: var(--bg2); border-left: 1px solid var(--hair2);
      z-index: 4; padding: 16px 4px;
      display: flex; flex-direction: column; gap: 0;
    }
    .hx-mini .lbl {
      writing-mode: vertical-rl; transform: rotate(180deg);
      font-size: 8.5px; letter-spacing: 0.2em; color: var(--dim);
      text-transform: uppercase; padding: 8px 0;
    }
    .hx-mini .scl {
      flex: 1; position: relative;
      display: flex; flex-direction: column;
      border: 1px solid var(--hair2); background: var(--bg);
    }
    .hx-mini .seg {
      flex: var(--w, 1);
      border-bottom: 1px solid var(--hair2);
      position: relative; cursor: pointer;
      transition: background 0.15s;
    }
    .hx-mini .seg:last-child { border-bottom: none; }
    .hx-mini .seg::after {
      content: attr(data-tt);
      position: absolute; right: 100%; top: 50%; transform: translateY(-50%);
      margin-right: 12px;
      background: var(--bg); border: 1px solid var(--hi);
      color: var(--ink); padding: 5px 10px;
      font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
      white-space: nowrap; opacity: 0; pointer-events: none;
      transition: opacity 0.12s;
    }
    .hx-mini .seg:hover { background: rgba(255,184,108,0.18); }
    .hx-mini .seg:hover::after { opacity: 1; }
    .hx-mini .seg .col {
      position: absolute; inset: 2px;
      background: var(--col, var(--dim)); opacity: 0.4;
    }
    .hx-mini .seg.on .col { opacity: 1; }
    .hx-mini .seg.on { background: rgba(255,184,108,0.08); }
    .hx-mini .pos {
      position: absolute; left: 0; right: 0;
      height: 18px; background: rgba(255,184,108,0.18);
      border-top: 1px solid var(--hi); border-bottom: 1px solid var(--hi);
      pointer-events: none; transition: top 0.18s ease-out;
      mix-blend-mode: screen;
    }

    /* ── FISHKA 3: scramble shimmer ──────────────── */
    .hx-scramble { color: var(--vdim) !important; transition: color 0.05s; }
    .hx-scramble.done { color: inherit !important; }
    .hx-scramble-row.scrambling .hx-byte,
    .hx-scramble-row.scrambling .hx-ascii {
      color: var(--dim) !important;
    }

    /* ── FISHKA 10: glitch on hover ──────────────── */
    .hx-glitch { display: inline-block; position: relative; }
    .hx-glitch:hover {
      animation: hx-glitch 0.4s steps(6, end);
    }
    @keyframes hx-glitch {
      0%   { text-shadow: 2px 0 var(--red), -2px 0 var(--cy); transform: translate(0, 0); }
      14%  { text-shadow: -2px 0 var(--red), 2px 0 var(--cy); transform: translate(1px, -1px); clip-path: polygon(0 8%, 100% 8%, 100% 32%, 0 32%); }
      28%  { text-shadow: 2px 0 var(--red), -2px 0 var(--cy); transform: translate(-1px, 1px); clip-path: polygon(0 38%, 100% 38%, 100% 56%, 0 56%); }
      42%  { text-shadow: -1px 0 var(--red), 1px 0 var(--cy); transform: translate(0, 0); clip-path: none; }
      57%  { text-shadow: 1px 0 var(--cy), -1px 0 var(--hi); transform: translate(-1px, 0); }
      72%  { text-shadow: -1px 0 var(--cy), 1px 0 var(--hi); transform: translate(1px, 0); }
      100% { text-shadow: none; transform: none; clip-path: none; }
    }
    .hx-glitch::after {
      content: attr(data-text);
      position: absolute; top: 0; left: 0; right: 0; bottom: 0;
      color: var(--cy); opacity: 0; pointer-events: none;
      clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);
    }
    .hx-glitch:hover::after {
      opacity: 0.6;
      animation: hx-glitch-after 0.4s steps(6, end);
    }
    @keyframes hx-glitch-after {
      0% { clip-path: polygon(0 12%, 100% 12%, 100% 28%, 0 28%); transform: translate(-2px, 0); }
      50% { clip-path: polygon(0 50%, 100% 50%, 100% 64%, 0 64%); transform: translate(2px, 0); }
      100% { opacity: 0; clip-path: polygon(0 0, 100% 0, 100% 0, 0 0); transform: translate(0, 0); }
    }

    /* mark element as scramble target — initial dim color before reveal */
    [data-scramble-region] .hx-byte,
    [data-scramble-region] .hx-ascii {
      transition: color 0.12s;
    }

    /* ── EXTRA 8: Hex backdrop with cursor parallax ─────────── */
    .hx-hero { position: relative; overflow: hidden; isolation: isolate; }
    .hx-hexbg {
      position: absolute; inset: -80px;
      pointer-events: none; z-index: 0;
      font-family: 'IBM Plex Mono', monospace;
      font-size: 15px; line-height: 1.55;
      letter-spacing: 0.04em;
      color: var(--vdim);
      overflow: hidden; user-select: none;
      transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
      transition: transform 0.5s cubic-bezier(.2,.7,.3,1);
      mask-image: radial-gradient(ellipse 80% 100% at 30% 50%, #000 25%, transparent 90%);
      -webkit-mask-image: radial-gradient(ellipse 80% 100% at 30% 50%, #000 25%, transparent 90%);
    }
    .hx-hexbg .row { white-space: nowrap; padding-right: 80px; }
    .hx-hexbg .b { display: inline-block; padding-right: 6px;
      transition: color 0.4s, opacity 0.4s; }
    .hx-hexbg .b.dim { color: var(--vdim); opacity: 0.6; }
    .hx-hexbg .b.hi  { color: var(--hi); opacity: 0.85; }
    .hx-hexbg .b.cy  { color: var(--cy); opacity: 0.7; }
    .hx-hexbg .b.gn  { color: var(--gn); opacity: 0.7; }
    .hx-hero .hx-bigwrap,
    .hx-hero > .deck,
    .hx-hero > .hx-prompt,
    .hx-hero > .hx-dump { position: relative; z-index: 1; }

    /* ── EXTRA 7: Selection → hex inspector chip ────────────── */
    .hx-sel-chip {
      position: fixed; z-index: 9998;
      background: var(--bg); border: 1px solid var(--hi);
      padding: 10px 14px;
      font-family: 'IBM Plex Mono', monospace;
      font-size: 11px; line-height: 1.6;
      color: var(--ink); pointer-events: none;
      white-space: pre-wrap; word-break: break-all;
      letter-spacing: 0.04em;
      box-shadow: 0 8px 32px rgba(0,0,0,0.6);
      max-width: 480px; min-width: 220px;
      opacity: 0; transform: translateY(4px) scale(0.98);
      transition: opacity 0.12s, transform 0.12s;
    }
    .hx-sel-chip.on { opacity: 1; transform: translateY(0) scale(1); }
    .hx-sel-chip .hdr {
      display: flex; justify-content: space-between; gap: 14px;
      color: var(--dim); font-size: 9.5px; letter-spacing: 0.16em;
      text-transform: uppercase; margin-bottom: 8px;
      padding-bottom: 6px; border-bottom: 1px dashed var(--hair2);
    }
    .hx-sel-chip .hdr .o { color: var(--hi); }
    .hx-sel-chip .bytes { color: var(--hi); }
    .hx-sel-chip .bytes .ws { color: var(--vdim); }
    .hx-sel-chip .ft {
      color: var(--dim); margin-top: 8px; padding-top: 6px;
      border-top: 1px dashed var(--hair2);
      font-size: 9.5px; letter-spacing: 0.14em;
      text-transform: uppercase;
      display: flex; gap: 14px; flex-wrap: wrap;
    }
    .hx-sel-chip .ft .v   { color: var(--cy); }
    .hx-sel-chip .ft .v.o { color: var(--hi); }
    .hx-sel-chip .ft .v.g { color: var(--gn); }
    .hx-sel-chip::before {
      content:''; position: absolute; top: -5px; left: 12px;
      width: 8px; height: 8px; background: var(--bg);
      border-left: 1px solid var(--hi); border-top: 1px solid var(--hi);
      transform: rotate(45deg);
    }

    /* ── EXTRA 11: Screensaver after 60s idle ───────────────── */
    .hx-screensaver {
      position: fixed; inset: 0; z-index: 9999;
      background: var(--bg);
      opacity: 0; pointer-events: none;
      transition: opacity 0.5s ease;
      overflow: hidden; user-select: none;
      font-family: 'IBM Plex Mono', monospace;
      font-size: 13px; line-height: 1.6;
      color: var(--vdim);
    }
    .hx-screensaver.on { opacity: 1; pointer-events: auto; cursor: pointer; }
    .hx-screensaver .scroller {
      position: absolute; top: 0; left: 0; right: 0;
      padding: 64px 56px;
      white-space: pre;
      animation: hx-ss-scroll 80s linear infinite;
    }
    @keyframes hx-ss-scroll {
      from { transform: translateY(0); }
      to   { transform: translateY(-50%); }
    }
    .hx-screensaver .head {
      position: absolute; top: 16px; left: 56px; right: 56px;
      display: flex; justify-content: space-between; align-items: baseline;
      font-size: 10.5px; letter-spacing: 0.14em; color: var(--dim);
      text-transform: uppercase; z-index: 2;
      padding-bottom: 12px; border-bottom: 1px solid var(--hair2);
      background: var(--bg);
    }
    .hx-screensaver .head .o   { color: var(--hi); }
    .hx-screensaver .head .blip {
      display: inline-block; width: 6px; height: 6px; background: var(--hi);
      border-radius: 50%; margin-right: 8px; vertical-align: 1px;
      animation: hx-pulse 1.4s infinite;
    }
    .hx-screensaver .pill {
      position: absolute; bottom: 32px; left: 50%; transform: translateX(-50%);
      font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
      color: var(--hi); border: 1px solid var(--hi); padding: 12px 22px;
      background: var(--bg); z-index: 2;
    }
    .hx-screensaver .pill kbd {
      display: inline-block; padding: 1px 7px; margin: 0 2px;
      border: 1px solid var(--hi); color: var(--ink);
      font-family: inherit; font-size: 9.5px;
    }
    .hx-screensaver .ad   { color: var(--dim); }
    .hx-screensaver .hi   { color: var(--hi); }
    .hx-screensaver .cy   { color: var(--cy); }
    .hx-screensaver .gn   { color: var(--gn); }
    .hx-screensaver .as   { color: var(--cy); }
    .hx-screensaver .ovr {
      position: absolute; inset: 0; pointer-events: none; z-index: 1;
      background:
        linear-gradient(180deg, var(--bg) 0%, transparent 12%, transparent 88%, var(--bg) 100%);
    }
  `;
  document.head.appendChild(s);
}

// ─────────────────────────────────────────────────────────────────────────
// HELPER: Glitch-wrapped text
// ─────────────────────────────────────────────────────────────────────────
function Glitch({ children, className = '', as: As = 'span' }) {
  const txt = typeof children === 'string' ? children
            : Array.isArray(children) ? children.filter(c => typeof c === 'string').join('')
            : '';
  return (
    <As className={`hx-glitch ${className}`} data-text={txt}>{children}</As>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// HELPER: Single hex byte cell, hoverable + tooltip data
// ─────────────────────────────────────────────────────────────────────────
const ASCII_REPLACEMENT = '·';
function asciiSafe(code) {
  if (code === 0) return '.';
  if (code < 32 || code === 127) return ASCII_REPLACEMENT;
  if (code > 126) return ASCII_REPLACEMENT;
  return String.fromCharCode(code);
}

function HxByte({ code, addr, cls = '' }) {
  const hex = code.toString(16).padStart(2, '0').toUpperCase();
  const bin = code.toString(2).padStart(8, '0');
  const dec = code.toString();
  const ch  = asciiSafe(code);
  const addrHex = '0x' + addr.toString(16).padStart(8, '0').toUpperCase();
  return (
    <span
      className={`hx-byte ${cls}`}
      data-addr={addrHex}
      data-hex={hex}
      data-dec={dec}
      data-bin={bin}
      data-char={ch}
    >{hex}</span>
  );
}

function HxAscii({ code, addr, cls = '' }) {
  const hex = code.toString(16).padStart(2, '0').toUpperCase();
  const bin = code.toString(2).padStart(8, '0');
  const dec = code.toString();
  const ch  = asciiSafe(code);
  const addrHex = '0x' + addr.toString(16).padStart(8, '0').toUpperCase();
  return (
    <span
      className={`hx-ascii ${cls}`}
      data-addr={addrHex}
      data-hex={hex}
      data-dec={dec}
      data-bin={bin}
      data-char={ch}
    >{ch === ' ' ? '\u00A0' : ch}</span>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// HELPER: Single hex row using new byte cells
// ─────────────────────────────────────────────────────────────────────────
function HxRow({ offset, codes, classes = [] }) {
  // codes is array of byte codes (0-255 or null for padding)
  const ad = offset.toString(16).padStart(8, '0').toUpperCase();
  return (
    <div className="hx-row">
      <span className="ad">{ad}</span>
      <span className="by">
        {codes.map((c, i) => (
          <React.Fragment key={i}>
            {c === null
              ? <span className="hx-byte d" data-addr={'0x' + (offset+i).toString(16).padStart(8,'0').toUpperCase()}
                  data-hex="00" data-dec="0" data-bin="00000000" data-char=".">00</span>
              : <HxByte code={c} addr={offset + i} cls={classes[i] || ''} />}
            {(i+1) % 8 === 0 && i !== codes.length - 1 ? <span>&nbsp;</span> : null}
          </React.Fragment>
        ))}
      </span>
      <span className="as">
        {codes.map((c, i) => (
          c === null
            ? <span className="hx-ascii d" data-addr={'0x' + (offset+i).toString(16).padStart(8,'0').toUpperCase()}
                data-hex="00" data-dec="0" data-bin="00000000" data-char=".">.</span>
            : <HxAscii key={i} code={c} addr={offset + i} cls={classes[i] || ''} />
        ))}
      </span>
    </div>
  );
}

// Convert a string into rows of bytes. Returns list of {offset, codes, classes}
function strToRowsV2(str, baseOffset, hiCls = 'h') {
  const codes = [];
  const classes = [];
  for (let i = 0; i < str.length; i++) {
    codes.push(str.charCodeAt(i));
    classes.push(hiCls);
  }
  while (codes.length % 16 !== 0) {
    codes.push(0);
    classes.push('d');
  }
  const rows = [];
  for (let i = 0; i < codes.length; i += 16) {
    rows.push({
      offset: baseOffset + i,
      codes: codes.slice(i, i + 16),
      classes: classes.slice(i, i + 16),
    });
  }
  return rows;
}

// ─────────────────────────────────────────────────────────────────────────
// FISHKA 6: Global byte tooltip — single instance, tracks mouse
// ─────────────────────────────────────────────────────────────────────────
function ByteTooltip({ rootRef }) {
  const tipRef = hxUseRef(null);

  hxUseEffect(() => {
    const root = rootRef.current;
    const tip = tipRef.current;
    if (!root || !tip) return;

    let hovered = null;

    const move = (e) => {
      const target = e.target.closest('[data-addr]');
      if (target) {
        if (target !== hovered) {
          hovered = target;
          const addr = target.getAttribute('data-addr');
          const hex  = target.getAttribute('data-hex');
          const dec  = target.getAttribute('data-dec');
          const bin  = target.getAttribute('data-bin');
          const ch   = target.getAttribute('data-char');
          tip.innerHTML = `
            <div><span class="k">addr</span> <span class="v o">${addr}</span></div>
            <div><span class="k">hex</span> <span class="v o">0x${hex}</span></div>
            <div><span class="k">dec</span> <span class="v c">${dec}</span></div>
            <div><span class="k">bin</span> <span class="v">0b${bin}</span></div>
            <div><span class="k">char</span> <span class="v g">'${ch === "'" ? "\\'" : ch}'</span></div>
          `;
          tip.classList.add('on');
        }
        // position
        const rect = tip.getBoundingClientRect();
        const x = Math.min(e.clientX + 14, window.innerWidth - rect.width - 8);
        const y = Math.max(e.clientY - rect.height - 18, 8);
        tip.style.left = x + 'px';
        tip.style.top  = y + 'px';
      } else if (hovered) {
        hovered = null;
        tip.classList.remove('on');
      }
    };
    const leave = () => {
      hovered = null;
      tip.classList.remove('on');
    };

    root.addEventListener('mousemove', move);
    root.addEventListener('mouseleave', leave);
    return () => {
      root.removeEventListener('mousemove', move);
      root.removeEventListener('mouseleave', leave);
    };
  }, [rootRef]);

  return <div className="hx-tooltip" ref={tipRef}></div>;
}

// ─────────────────────────────────────────────────────────────────────────
// FISHKA 3: Scramble — when region first intersects viewport, scramble its
// byte cells (hex AND ASCII) for ~350ms then settle.
// ─────────────────────────────────────────────────────────────────────────
const HEX_CHARS = '0123456789ABCDEF';
const ASCII_NOISE = '@#$%&*+=-<>/?!.';

function startScramble(root) {
  // collect targets: hex bytes (data-addr) + plain-text markers (data-scramble-text)
  const bytes = root.querySelectorAll('[data-addr], [data-scramble-text]');
  if (!bytes.length) return;

  const finals = [];
  bytes.forEach((b) => {
    finals.push({
      el: b,
      text: b.textContent,
      isHex: b.classList.contains('hx-byte'),
      isText: b.hasAttribute('data-scramble-text'),
    });
  });

  // mark scrambling
  finals.forEach(f => f.el.classList.add('hx-scramble'));

  const start = performance.now();
  const dur = 480;
  const TEXT_NOISE = '!@#$%^&*+=-<>/?_|\\~';

  function tick(now) {
    const t = Math.min(1, (now - start) / dur);
    finals.forEach((f, i) => {
      const order = i / finals.length;
      const reveal = t > order * 0.85;
      if (reveal) {
        if (f.el.textContent !== f.text) f.el.textContent = f.text;
        f.el.classList.remove('hx-scramble');
        f.el.classList.add('hx-scramble', 'done');
      } else {
        const len = f.text.length;
        let r = '';
        if (f.isText) {
          // for plain text, preserve spaces; jumble chars
          for (let k = 0; k < len; k++) {
            const ch = f.text[k];
            if (ch === ' ' || ch === '\n' || ch === '\t' || ch === '.') {
              r += ch;
            } else {
              const src = (Math.random() < 0.5 ? HEX_CHARS : TEXT_NOISE);
              r += src[(Math.random() * src.length) | 0];
            }
          }
        } else {
          const src = f.isHex ? HEX_CHARS : ASCII_NOISE;
          for (let k = 0; k < len; k++) r += src[(Math.random() * src.length) | 0];
        }
        f.el.textContent = r;
      }
    });
    if (t < 1) requestAnimationFrame(tick);
    else {
      finals.forEach(f => {
        f.el.textContent = f.text;
        f.el.classList.remove('hx-scramble');
      });
    }
  }
  requestAnimationFrame(tick);
}

function useScrambleOnEnter(rootRef, enabled) {
  hxUseEffect(() => {
    if (!enabled) return;
    const root = rootRef.current;
    if (!root) return;

    const targets = root.querySelectorAll('[data-scramble-region]');
    if (!targets.length) return;

    const seen = new WeakSet();
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !seen.has(e.target)) {
          seen.add(e.target);
          startScramble(e.target);
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, root: null, rootMargin: '0px 0px -10% 0px' });

    targets.forEach((t) => io.observe(t));
    return () => io.disconnect();
  }, [rootRef, enabled]);
}

// ─────────────────────────────────────────────────────────────────────────
// FISHKA 1: Boot sequence overlay
// ─────────────────────────────────────────────────────────────────────────
const BOOT_LINES = [
  { tg: 'BIOS', tc: 'boot', ms: 'Power-on self-test', rs: 'OK', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Mounting /dev/kamen — ext4', rs: '1.4 GB', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Reading PE header @ 0x00400000', rs: 'OK', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Verifying signature 0xDEADBEEF', rs: 'valid', rt: 'g' },
  { tg: 'WARN', tc: 'warn', ms: 'Anti-debug heuristics tripped — bypassed', rs: 'skipped', rt: 'warn' },
  { tg: ' ok ', tc: '',     ms: 'Decoding .header @ 0x00000000', rs: '17 B', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Loading .text.profile @ 0x00000100', rs: '1.4 KB', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Indexing .data.work @ 0x00001000', rs: '4 entries', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Mapping .log.career @ 0x00002000', rs: '3 records', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Opening .bss.contact @ 0x0000FF00', rs: '4 channels', rt: 'g' },
  { tg: ' ok ', tc: '',     ms: 'Stack inventory sized', rs: '16 parts', rt: 'g' },
  { tg: 'BIOS', tc: 'boot', ms: 'CRC kamen.dmp', rs: '0xC0DE OK', rt: 'g' },
  { tg: 'BIOS', tc: 'boot', ms: 'Handing off to inspector…', rs: '>>>', rt: 'g' },
];

const ASCII_LOGO = [
'  ┌─────────────────────────────────────────┐',
'  │  K A M E N  —  L O W   L E V E L   E   │',
'  │  C++ · RE · WINDOWS INTERNALS · 7 YRS  │',
'  └─────────────────────────────────────────┘',
];

function Boot({ onDone }) {
  const [shown, setShown] = hxUseState(0);
  const [fade, setFade]   = hxUseState(false);
  const [logo, setLogo]   = hxUseState(false);
  const doneRef = hxUseRef(false);

  hxUseEffect(() => {
    let i = 0;
    const tick = () => {
      i++;
      setShown(i);
      if (i < BOOT_LINES.length) {
        // accelerating — early lines slower, later faster
        const delay = i < 3 ? 220 : i < 7 ? 140 : 90;
        timer = setTimeout(tick, delay);
      } else {
        timer = setTimeout(() => setLogo(true), 200);
        timer2 = setTimeout(() => finish(), 1200);
      }
    };
    let timer = setTimeout(tick, 180);
    let timer2;
    const finish = () => {
      if (doneRef.current) return;
      doneRef.current = true;
      setFade(true);
      setTimeout(() => onDone && onDone(), 380);
    };
    const onKey = (e) => {
      if (e.code === 'Space' || e.code === 'Enter' || e.code === 'Escape') {
        e.preventDefault();
        finish();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => {
      clearTimeout(timer);
      clearTimeout(timer2);
      window.removeEventListener('keydown', onKey);
    };
  }, [onDone]);

  const skip = () => {
    if (doneRef.current) return;
    doneRef.current = true;
    setFade(true);
    setTimeout(() => onDone && onDone(), 380);
  };

  return (
    <div className={`hx-boot ${fade ? 'fade' : ''}`} onClick={skip}>
      <div className="hd">
        <span>kamen.dmp <span className="o">v3.7</span> · mem-inspector</span>
        <span>{new Date().toISOString().split('T')[0]} · vlv · utc+10</span>
      </div>

      {BOOT_LINES.map((l, i) => (
        <div className={`ln ${i < shown ? 'in' : ''}`} key={i}>
          <span className={`tg ${l.tc}`}>[{l.tg}]</span>
          <span className="ms">{l.ms}{i === shown - 1 ? <span className="cur"></span> : null}</span>
          <span className={`rs ${l.rt === 'warn' ? 'warn' : ''}`}>{l.rs}</span>
        </div>
      ))}

      <div className={`ascii ${logo ? 'in' : ''}`}>
        {ASCII_LOGO.map((l, i) => <div key={i}>{l}</div>)}
      </div>

      <div className="skip">
        press <kbd>SPACE</kbd> / <kbd>ESC</kbd> / click — skip
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// FISHKA 7: Mini-map (vertical region navigator)
// ─────────────────────────────────────────────────────────────────────────
const MINI_SEGS = [
  { id: 'header',  ad: '0x0000', lbl: '.header',   col: '#ffb86c' },
  { id: 'profile', ad: '0x0100', lbl: '.text.profile', col: '#7fe3e1' },
  { id: 'skills',  ad: '0x0300', lbl: '.rodata.skills', col: '#8ef58e' },
  { id: 'work',    ad: '0x1000', lbl: '.data.work', col: '#ffb86c' },
  { id: 'career',  ad: '0x2000', lbl: '.log.career', col: '#7fe3e1' },
  { id: 'contact', ad: '0xFF00', lbl: '.bss.contact', col: '#ff6e6e' },
];

function MiniMap({ rootRef }) {
  const [active, setActive] = hxUseState('header');
  const [progress, setProgress] = hxUseState(0); // 0..1 position in artboard
  const wrapRef = hxUseRef(null);

  // find scroll parent of artboard
  hxUseEffect(() => {
    const root = rootRef.current;
    if (!root) return;

    function findScrollParent(el) {
      let p = el.parentElement;
      while (p) {
        const s = getComputedStyle(p);
        if (/(auto|scroll)/.test(s.overflowY) && p.scrollHeight > p.clientHeight + 4) {
          return p;
        }
        p = p.parentElement;
      }
      return null;
    }

    const sp = findScrollParent(root);
    const scroller = sp || window;
    const getScroll = () => sp ? sp.scrollTop : window.scrollY;
    const getH = () => sp ? sp.clientHeight : window.innerHeight;

    const anchors = root.querySelectorAll('[data-section]');

    const onScroll = () => {
      const rRect = root.getBoundingClientRect();
      const vh = getH();
      // progress: how far into the artboard we are
      const top = rRect.top;
      const h = root.scrollHeight || root.offsetHeight;
      const visTop = -top; // pixels of artboard above viewport top
      const center = visTop + vh / 2;
      setProgress(Math.max(0, Math.min(1, center / h)));

      // find which anchor is closest to top-third
      let best = anchors[0];
      let bestDist = Infinity;
      anchors.forEach((a) => {
        const r = a.getBoundingClientRect();
        const d = Math.abs(r.top - vh * 0.25);
        if (d < bestDist) { bestDist = d; best = a; }
      });
      if (best) setActive(best.getAttribute('data-section'));
    };

    scroller.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => {
      scroller.removeEventListener('scroll', onScroll);
      window.removeEventListener('scroll', onScroll);
    };
  }, [rootRef]);

  const jump = (id) => {
    const root = rootRef.current;
    if (!root) return;
    const target = root.querySelector(`[data-section="${id}"]`);
    if (!target) return;
    function findScrollParent(el) {
      let p = el.parentElement;
      while (p) {
        const s = getComputedStyle(p);
        if (/(auto|scroll)/.test(s.overflowY) && p.scrollHeight > p.clientHeight + 4) {
          return p;
        }
        p = p.parentElement;
      }
      return null;
    }
    const sp = findScrollParent(root);
    const r = target.getBoundingClientRect();
    if (sp) {
      const sr = sp.getBoundingClientRect();
      sp.scrollTo({ top: sp.scrollTop + (r.top - sr.top) - 20, behavior: 'smooth' });
    } else {
      window.scrollTo({ top: window.scrollY + r.top - 40, behavior: 'smooth' });
    }
  };

  return (
    <div className="hx-mini" ref={wrapRef}>
      <div className="lbl">mem map / regions</div>
      <div className="scl">
        {MINI_SEGS.map((s) => (
          <div
            key={s.id}
            className={`seg ${active === s.id ? 'on' : ''}`}
            data-tt={`${s.ad}  ${s.lbl}`}
            onClick={() => jump(s.id)}
            style={{ '--col': s.col, '--w': s.id === 'work' ? 1.8 : s.id === 'profile' ? 1.2 : 1 }}
          >
            <div className="col"></div>
          </div>
        ))}
        <div className="pos" style={{ top: `calc(${progress * 100}% - 9px)` }}></div>
      </div>
      <div className="lbl">cursor / 0x{(progress * 0xFFFF | 0).toString(16).padStart(4,'0').toUpperCase()}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// FISHKA 8: Project decompile lines
// ─────────────────────────────────────────────────────────────────────────
const ASM_PER_PROJECT = {
  '01': [
    { lbl: 'kernelguard_init:' },
    { ad: '0x10401000', by: '55',           op: 'push',  ar: <><span className="reg">rbp</span></> },
    { ad: '0x10401001', by: '48 89 E5',     op: 'mov',   ar: <><span className="reg">rbp</span>, <span className="reg">rsp</span></> },
    { ad: '0x10401004', by: '48 83 EC 30',  op: 'sub',   ar: <><span className="reg">rsp</span>, <span className="imm">0x30</span></> },
    { ad: '0x10401008', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">ZwOpenSection</span></> },
    { ad: '0x1040100D', by: '85 C0',        op: 'test',  ar: <><span className="reg">eax</span>, <span className="reg">eax</span></> },
    { ad: '0x1040100F', by: '75 12',        op: 'jnz',   ar: <><span className="lbl">.bypass</span> <span className="com">; on driver fail</span></> },
    { ad: '0x10401011', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">decrypt_payload</span></> },
    { lbl: '.bypass:' },
    { ad: '0x10401023', by: 'BA 45 41 43',  op: 'mov',   ar: <><span className="reg">edx</span>, <span className="imm">'EAC '</span></> },
    { ad: '0x10401028', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">hook_anticheat</span> <span className="com">; bypass live</span></> },
    { ad: '0x1040102D', by: 'C9',           op: 'leave', ar: <></> },
    { ad: '0x1040102E', by: 'C3',           op: 'ret',   ar: <></> },
  ],
  '02': [
    { lbl: 'cheat_frame:' },
    { ad: '0x00428100', by: '48 89 5C 24',  op: 'mov',   ar: <>[<span className="reg">rsp</span>+<span className="imm">0x8</span>], <span className="reg">rbx</span></> },
    { ad: '0x00428105', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">entity_list</span></> },
    { ad: '0x0042810A', by: '48 85 C0',     op: 'test',  ar: <><span className="reg">rax</span>, <span className="reg">rax</span></> },
    { ad: '0x0042810D', by: '74 1A',        op: 'jz',    ar: <><span className="lbl">.next_frame</span></> },
    { ad: '0x0042810F', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">draw_esp</span> <span className="com">; players, loot, nodes</span></> },
    { ad: '0x00428114', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">aimbot_solve</span> <span className="com">; bezier curve</span></> },
    { ad: '0x00428119', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">kread_pid</span> <span className="com">; via driver</span></> },
    { lbl: '.next_frame:' },
    { ad: '0x00428127', by: 'C3',           op: 'ret',   ar: <></> },
  ],
  '03': [
    { lbl: 'iocp_worker:' },
    { ad: '0x00501000', by: '53',           op: 'push',  ar: <><span className="reg">rbx</span></> },
    { ad: '0x00501001', by: '48 89 CB',     op: 'mov',   ar: <><span className="reg">rbx</span>, <span className="reg">rcx</span> <span className="com">; ctx</span></> },
    { ad: '0x00501004', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">GetQueuedCompletionStatus</span></> },
    { ad: '0x00501009', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">verify_hwid_rsa</span></> },
    { ad: '0x0050100E', by: '85 C0',        op: 'test',  ar: <><span className="reg">eax</span>, <span className="reg">eax</span></> },
    { ad: '0x00501010', by: '78 0C',        op: 'js',    ar: <><span className="lbl">.deny</span></> },
    { ad: '0x00501012', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">issue_session</span> <span className="com">; 10k+ active</span></> },
    { ad: '0x00501017', by: 'EB 06',        op: 'jmp',   ar: <><span className="lbl">.ack</span></> },
    { lbl: '.deny:' },
    { ad: '0x00501022', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">log_revoke</span></> },
  ],
  '04': [
    { lbl: 'vm_dispatch:' },
    { ad: '0x00601000', by: '0F B6 06',     op: 'movzx', ar: <><span className="reg">eax</span>, byte ptr [<span className="reg">rsi</span>]</> },
    { ad: '0x00601003', by: '48 FF C6',     op: 'inc',   ar: <><span className="reg">rsi</span> <span className="com">; advance vip</span></> },
    { ad: '0x00601006', by: 'FF 24 C5',     op: 'jmp',   ar: <>[<span className="lbl">vm_handlers</span>+<span className="reg">rax</span>*8]</> },
    { lbl: 'handler_07:' },
    { ad: '0x00601020', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">vmprotect_unwrap</span></> },
    { ad: '0x00601025', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">recover_iat</span> <span className="com">; restore imports</span></> },
    { ad: '0x0060102A', by: 'E8 ?? ?? ??',  op: 'call',  ar: <><span className="lbl">devirt_opcode</span> <span className="com">; → pseudo-C</span></> },
    { ad: '0x0060102F', by: 'EB CF',        op: 'jmp',   ar: <><span className="lbl">vm_dispatch</span></> },
  ],
};

function WorkCard({ w, i, D }) {
  const [view, setView] = hxUseState('struct'); // 'struct' | 'asm'
  const asm = ASM_PER_PROJECT[w.n] || [];

  return (
    <div className="hx-region" data-scramble-region>
      <div className="hx-region-h">
        <span className="ad">0x0000{(0x1000 + i*0x100).toString(16).toUpperCase().padStart(4,'0')}</span>
        <span className="tt">project_t · entry {w.n}</span>
        <span className="pr">{w.status}</span>
        <span className="rt">YR {w.year}</span>
      </div>
      <div className="hx-region-b">
        <div className="hx-tools">
          <button
            className={view === 'struct' ? 'on' : ''}
            onClick={() => setView('struct')}
          >struct</button>
          <button
            className={view === 'asm' ? 'on' : ''}
            onClick={() => setView('asm')}
          >► decompile / disasm</button>
          <span className="sp"></span>
          <span style={{ color: 'var(--dim)', fontSize: 10, letterSpacing: '0.14em',
            textTransform: 'uppercase', alignSelf: 'center' }}>
            view: {view === 'struct' ? 'data structure' : 'pseudo-asm x86_64'}
          </span>
        </div>

        {view === 'struct' ? (
          <div className="hx-strct">
            <div><span className="opn">struct project_t</span>{' '}
              <span style={{ color:'var(--hi)' }}>
                {w.name.toLowerCase().replace(/[^a-z0-9]/g,'_')}
              </span>{' '}
              <span className="opn">{'{'}</span></div>
            <Glitch className="nm" as="div">{w.name}<span className="dot">.</span></Glitch>
            <div className="tag">{w.tag}</div>
            <div className="desc">{w.desc}</div>
            <div className="row"><span className="k">.stack</span>
              <span className="v"><span className="val str">{w.stack}</span></span></div>
            <div className="row"><span className="k">.target</span>
              <span className="v"><span className="val flag">{w.bypass}</span></span></div>
            <div className="row"><span className="k">.year</span>
              <span className="v"><span className="val num">{w.year}</span></span></div>
            <div className="row"><span className="k">.status</span>
              <span className="v"><span className="val flag">{w.status.toUpperCase()}</span></span></div>
            <div><span className="clo">{'};'}</span></div>
          </div>
        ) : (
          <div className="hx-asm">
            <div style={{ marginBottom: 10 }}>
              <Glitch className="nm" as="div" style={{
                fontFamily:'"Major Mono Display", monospace', fontSize: 32,
                color:'var(--ink)', letterSpacing:'-0.03em', textTransform:'uppercase',
                lineHeight: 1, marginBottom: 4 }}>
                {w.name}<span style={{ color:'var(--hi)' }}>.</span>
              </Glitch>
              <div style={{ color:'var(--cy)', fontSize: 10.5,
                letterSpacing:'0.14em', textTransform:'uppercase', marginBottom: 14 }}>
                {w.tag} · decompiled view · {asm.length} instructions
              </div>
            </div>
            {asm.map((l, k) => l.lbl ? (
              <div className="lbl-line" key={k}>{l.lbl}</div>
            ) : (
              <div className="ln" key={k}>
                <span className="ad">{l.ad}</span>
                <span className="by"></span>
                <span className="op">{l.op}</span>
                <span className="ar">{l.ar}</span>
              </div>
            ))}
            <div style={{ marginTop: 14, color:'var(--dim)', fontSize: 11,
              borderTop: '1px dashed var(--hair2)', paddingTop: 12 }}>
              // {w.desc}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// MAIN COMPONENT
// ─────────────────────────────────────────────────────────────────────────
function HexDump() {
  const D = window.KAMEN_DATA;
  const rootRef = hxUseRef(null);
  const [typed, setTyped] = hxUseState('');
  const [booted, setBooted] = hxUseState(false);
  const target = 'kamen';

  hxUseEffect(() => {
    if (!booted) return;
    let i = 0;
    const t = setInterval(() => {
      i++;
      setTyped(target.slice(0, i));
      if (i >= target.length) clearInterval(t);
    }, 90);
    return () => clearInterval(t);
  }, [booted]);

  // wire up scramble-on-enter (after boot to avoid running prematurely)
  useScrambleOnEnter(rootRef, booted);

  // Hero hex rows
  const heroRows  = strToRowsV2('MAXIM KAMEN / VLV', 0x00000000, 'h');
  const heroRows2 = strToRowsV2('kamen@dev.local', 0x00000010, 'g');
  const heroRows3 = strToRowsV2('C++ reverse eng.', 0x00000020, 'c');

  return (
    <div className="hx" ref={rootRef}>
      <div className="hx-scan"></div>

      {!booted && <Boot onDone={() => setBooted(true)} />}

      <ByteTooltip rootRef={rootRef} />
      <MiniMap rootRef={rootRef} />
      <SelectionHex active={booted} />
      <Screensaver enabled={booted} />

      {/* status bar */}
      <div className="hx-statusbar">
        <span><span className="o">[mem-inspector]</span> v3.7</span>
        <span>kamen.exe — base=<span className="o">0x00400000</span> · region=<span className="c">.kamen</span> · {D.yrs} yrs</span>
        <span className="g"><span className="blip"></span>accepting work</span>
        <span>{D.loc} · UTC+10 · 22:00</span>
      </div>

      <div className="hx-tabs">
        <span className="tab on">█ kamen.dmp <span className="x">×</span></span>
        <span className="tab">profile.cpp</span>
        <span className="tab">work/</span>
        <span className="tab">career.log</span>
        <span className="tab">contact.h</span>
        <span style={{ marginLeft:'auto', alignSelf:'center', color:'var(--dim)' }}>+</span>
      </div>

      <div className="hx-main">

        {/* ── HERO ─────────────────────────────────── */}
        <section className="hx-hero" data-section="header">
          <div className="deck">
            <span className="o">0x00000000</span>
            <span className="rule"></span>
            <span>SECTION .HEADER</span>
            <span className="rule"></span>
            <span className="g">decoded ok / 17 bytes</span>
          </div>

          <div className="hx-bigwrap">
            <h1 className="hx-big">
              <Glitch as="span" className="">
                {typed.split('').map((ch, i) => (
                  <span key={i} className={ch === 'a' ? 'a' : ''}>{ch}</span>
                ))}
              </Glitch>
              <span className="cur"></span>
            </h1>

            <aside className="hx-bigaside">
              <span className="k">subject</span>
              <span className="v">{D.name}</span>

              <span className="k">handle</span>
              <span className="v o">@{D.handle}</span>

              <span className="k">discipline</span>
              <span className="v c">{D.role}</span>

              <span className="k">based</span>
              <span className="v">{D.loc} · {D.tz}</span>

              <span className="k">since</span>
              <span className="v">{D.since} — {D.yrs} yrs cumulative</span>

              <span className="k">availability</span>
              <span className="v g">● {D.slots} slots open / Q3</span>

              <span className="k">response time</span>
              <span className="v o">{D.response} (max)</span>
            </aside>
          </div>

          <div className="hx-prompt">
            <div className="ln dim">// preview: decoded header strings @ base + 0x0</div>
            <div className="ln"><span className="ps">$</span> <span className="cmd">strings</span> <span className="arg">--region=.header kamen.dmp | head</span></div>
          </div>

          <div className="hx-dump" data-scramble-region style={{ marginTop: 18, paddingLeft: 0, paddingRight: 0 }}>
            {heroRows.map((r, i) => <HxRow key={i} {...r} />)}
            {heroRows2.map((r, i) => <HxRow key={'b'+i} {...r} />)}
            {heroRows3.map((r, i) => <HxRow key={'c'+i} {...r} />)}
          </div>

          <div className="hx-prompt" style={{ marginTop: 20 }}>
            <div className="ln"><span className="ps">$</span> <span className="cmd">cat</span> <span className="arg">./about.txt</span></div>
            <div className="ln out">
              Семь лет в кишках Windows. <span style={{ color:'var(--hi)' }}>Реверс защит</span>,
              ядерные драйверы, читы, <span style={{ color:'var(--cy)' }}>PE-лоадеры
              с собственной обфускацией</span>.
            </div>
          </div>
        </section>

        {/* ── PROFILE ─────────────────────────────── */}
        <div className="hx-anchor" data-section="profile" data-scramble-region>
          <span className="ad" data-scramble-text>0x00000100</span>
          <Glitch as="span" className="lb"><span className="sec" data-scramble-text>.text</span><span className="dot">.</span><span data-scramble-text>profile</span> <span style={{ color:'var(--dim)', fontSize:11 }}>// readable text segment</span></Glitch>
          <span className="rt" data-scramble-text>size: 1.4 KB · perms: r--</span>
        </div>

        <div className="hx-region" data-scramble-region>
          <div className="hx-region-h">
            <span className="ad">0x00000100 → 0x00000280</span>
            <span className="tt">bio paragraphs · UTF-8</span>
            <span className="pr">decoded</span>
            <span className="rt">3 segments</span>
          </div>
          <div className="hx-region-b">
            <div className="hx-bio">
              <span className="gut">001<br/>002<br/>003<br/>004</span>
              <div>
                <div className="com">// part 1 — origin</div>
                <p className="p">
                  Пишу низкоуровневый код на <strong>C++</strong> с 2018 года. От ядерных драйверов
                  до юзермодных читов. Глубоко знаю Windows internals,
                  <span className="c"> PE-формат</span> и поведение античит-систем:
                  <strong> EAC, BattlEye, VAC</strong>.
                </p>
              </div>
            </div>
            <div className="hx-bio" style={{ marginTop: 18 }}>
              <span className="gut">005<br/>006<br/>007<br/>008</span>
              <div>
                <div className="com">// part 2 — service catalogue</div>
                <p className="p">
                  Делаю <strong>читы</strong> (ESP, aimbot, wallhack),
                  <strong> PE-лоадеры</strong> с шифрованием и антиотладкой,
                  <strong> байпасы</strong> EAC, BattlEye и VAC. Параллельно пишу
                  <span className="c"> backend на C++</span>: сетевые сервисы, лицензионные сервера,
                  протоколы поверх raw-sockets с IOCP.
                </p>
              </div>
            </div>
            <div className="hx-bio" style={{ marginTop: 18 }}>
              <span className="gut">009<br/>010<br/>011</span>
              <div>
                <div className="com">// part 3 — manifesto</div>
                <p className="p" style={{ fontFamily:'"Space Grotesk", sans-serif',
                  fontSize: 22, lineHeight: 1.25, color:'var(--hi)', fontStyle:'italic' }}>
                  Знаю, как работают защиты. Изнутри.
                </p>
                <div className="com" style={{ marginTop: 8 }}>// kamen, 7 yrs in</div>
              </div>
            </div>
          </div>
        </div>

        {/* ── SKILLS ──────────────────────────────── */}
        <div className="hx-anchor" data-section="skills" data-scramble-region>
          <span className="ad" data-scramble-text>0x00000300</span>
          <Glitch as="span" className="lb"><span className="sec" data-scramble-text>.rodata</span><span className="dot">.</span><span data-scramble-text>skills</span> <span style={{ color:'var(--dim)', fontSize:11 }}>// skill matrix + stack inventory</span></Glitch>
          <span className="rt" data-scramble-text>size: 7+16 entries</span>
        </div>

        <div className="hx-region" data-scramble-region>
          <div className="hx-region-h">
            <span className="ad" data-scramble-text>0x00000300 → 0x00000340</span>
            <span className="tt" data-scramble-text>skill_matrix[7] · uint8_t</span>
            <span className="pr">live</span>
            <span className="rt" data-scramble-text>0..100 ranged</span>
          </div>
          <div className="hx-region-b">
            <div className="hx-skill-grid">
              <div>
                {D.skills.slice(0, 4).map((s) => (
                  <div className="hx-skill-row" key={s.k}>
                    <span className="k">{s.k}</span>
                    <span className="bar">
                      {'█'.repeat(Math.floor(s.v / 5))}
                      <span className="e">{'░'.repeat(20 - Math.floor(s.v / 5))}</span>
                    </span>
                    <span className="v" data-scramble-text>{s.v.toString(16).padStart(2,'0').toUpperCase()}</span>
                  </div>
                ))}
              </div>
              <div>
                {D.skills.slice(4).map((s) => (
                  <div className="hx-skill-row" key={s.k}>
                    <span className="k">{s.k}</span>
                    <span className="bar">
                      {'█'.repeat(Math.floor(s.v / 5))}
                      <span className="e">{'░'.repeat(20 - Math.floor(s.v / 5))}</span>
                    </span>
                    <span className="v" data-scramble-text>{s.v.toString(16).padStart(2,'0').toUpperCase()}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>

        <div className="hx-region" data-scramble-region>
          <div className="hx-region-h">
            <span className="ad" data-scramble-text>0x00000340 → 0x00000440</span>
            <span className="tt" data-scramble-text>stack[] · const char*</span>
            <span className="pr">parts inventory</span>
            <span className="rt" data-scramble-text>16 entries</span>
          </div>
          <div className="hx-region-b">
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'0 56px' }}>
              {D.stack.map((s, i) => (
                <div className={`hx-stack ${s.hot ? 'hot' : ''}`} key={i}>
                  <span className="ad" data-scramble-text>[0x{(0x40 + i*8).toString(16).padStart(4,'0').toUpperCase()}]</span>
                  <span className="k">{s.k}</span>
                  <span className="v">{s.hot ? 'primary' : 'std'}</span>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* ── WORK ────────────────────────────────── */}
        <div className="hx-anchor" data-section="work" data-scramble-region>
          <span className="ad" data-scramble-text>0x00001000</span>
          <Glitch as="span" className="lb"><span className="sec" data-scramble-text>.data</span><span className="dot">.</span><span data-scramble-text>work</span> <span style={{ color:'var(--dim)', fontSize:11 }}>// project_t work[4] · click ► to decompile</span></Glitch>
          <span className="rt" data-scramble-text>size: 4 × 256 B</span>
        </div>

        {D.work.map((w, i) => (
          <WorkCard key={w.n} w={w} i={i} D={D} />
        ))}

        {/* ── CAREER ──────────────────────────────── */}
        <div className="hx-anchor" data-section="career" data-scramble-region>
          <span className="ad" data-scramble-text>0x00002000</span>
          <Glitch as="span" className="lb"><span className="sec" data-scramble-text>.log</span><span className="dot">.</span><span data-scramble-text>career</span> <span style={{ color:'var(--dim)', fontSize:11 }}>// reverse-chronological journal</span></Glitch>
          <span className="rt" data-scramble-text>3 entries · 7 yrs span</span>
        </div>

        <div className="hx-region" data-scramble-region>
          <div className="hx-region-h">
            <span className="ad" data-scramble-text>tail -n 3 career.log</span>
            <span className="tt" data-scramble-text>positions journal</span>
            <span className="pr">live</span>
            <span className="rt" data-scramble-text>since {D.since}</span>
          </div>
          <div className="hx-region-b">
            {D.career.map((c, i) => (
              <div className="hx-tl" key={i}>
                <div className="date">
                  {c.from}<br/><span className="to">↓</span><br/>{c.to}
                  {c.live && <span className="now">live</span>}
                </div>
                <div className="marker"></div>
                <div className="body">
                  <Glitch as="div" className="rl">{c.role.split(' ').map((w, j, arr) => (
                    j === arr.length - 1
                      ? <span className="it" key={j}>{w}</span>
                      : <span key={j}>{w} </span>
                  ))}</Glitch>
                  <div className="co">{c.where}</div>
                  <div className="ds">{c.desc}</div>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* ── CONTACT ─────────────────────────────── */}
        <div className="hx-anchor" data-section="contact" data-scramble-region>
          <span className="ad" data-scramble-text>0x0000FF00</span>
          <Glitch as="span" className="lb"><span className="sec" data-scramble-text>.bss</span><span className="dot">.</span><span data-scramble-text>contact</span> <span style={{ color:'var(--dim)', fontSize:11 }}>// 4 channels available</span></Glitch>
          <span className="rt" data-scramble-text>writable / awaiting input</span>
        </div>

        <div style={{ padding: '0 32px' }}>
          <Glitch as="h2" className="hx-ct-big">
            есть<br/><span className="a">проект?</span>
          </Glitch>
          <p style={{ fontSize: 13, color:'var(--cy)', lineHeight: 1.85,
            margin: '8px 0 28px', maxWidth: '56ch' }}>
            <span style={{ color:'var(--dim)' }}>//</span> читы, лоадеры, байпасы · <span style={{ color:'var(--hi)' }}>OK</span><br/>
            <span style={{ color:'var(--dim)' }}>//</span> C++ backend, RE-задачи · <span style={{ color:'var(--hi)' }}>OK</span><br/>
            <span style={{ color:'var(--dim)' }}>//</span> отвечаю в пределах двух часов · NDA подписываю без вопросов
          </p>

          <div className="hx-ct-lns">
            {D.contact.map((c, i) => (
              <a className="hx-ct-ln" href={c.href} key={i}>
                <span className="ad">[0x{(0xFF00 + i*0x20).toString(16).toUpperCase()}]</span>
                <span>
                  <div><span className="ic">{c.ico}</span> &nbsp;
                    <Glitch as="span" className="nm">{c.name}<span className="dot">.</span></Glitch></div>
                  <div className="vl">{c.val}</div>
                </span>
                <span className="tg">{c.tag}</span>
                <span></span>
                <span className="arr">↗</span>
              </a>
            ))}
          </div>
        </div>
      </div>

      {/* footer */}
      <div className="hx-foot">
        <span>(c) 2026 / <span className="o">kamen</span></span>
        <span className="c">EOF · 0xDEADBEEF · <span className="g">crc OK</span></span>
        <span className="r">/dev/kamen — written solo</span>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// EXTRA 8: HexBackdrop — running bytes behind hero, parallaxes with cursor
// ─────────────────────────────────────────────────────────────────────────
function HexBackdrop({ rootRef }) {
  const wrapRef = hxUseRef(null);

  // generate initial byte grid once, then mutate small batches per tick
  hxUseEffect(() => {
    const wrap = wrapRef.current;
    if (!wrap) return;

    const ROWS = 36, COLS = 28;
    const palette = ['dim','dim','dim','dim','dim','hi','cy','gn']; // weighted to dim
    const hexChars = '0123456789ABCDEF';
    const randHex = () => hexChars[(Math.random()*16)|0] + hexChars[(Math.random()*16)|0];
    const randCls = () => palette[(Math.random() * palette.length) | 0];

    // build initial dom
    wrap.innerHTML = '';
    const cells = [];
    for (let r = 0; r < ROWS; r++) {
      const row = document.createElement('div');
      row.className = 'row';
      for (let c = 0; c < COLS; c++) {
        const span = document.createElement('span');
        span.className = 'b ' + randCls();
        span.textContent = randHex();
        row.appendChild(span);
        cells.push(span);
      }
      wrap.appendChild(row);
    }

    // mutate ~8 cells every 110ms
    const id = setInterval(() => {
      for (let i = 0; i < 10; i++) {
        const c = cells[(Math.random() * cells.length) | 0];
        c.textContent = randHex();
        c.className = 'b ' + randCls();
      }
    }, 110);

    return () => clearInterval(id);
  }, []);

  // cursor parallax — listen on whole document
  hxUseEffect(() => {
    const wrap = wrapRef.current;
    if (!wrap) return;
    let raf = 0;
    let tx = 0, ty = 0;
    const onMove = (e) => {
      const w = window.innerWidth, h = window.innerHeight;
      const nx = (e.clientX / w - 0.5) * 2;  // -1..1
      const ny = (e.clientY / h - 0.5) * 2;
      tx = -nx * 22; // invert + soften
      ty = -ny * 16;
      if (!raf) raf = requestAnimationFrame(apply);
    };
    const apply = () => {
      raf = 0;
      wrap.style.setProperty('--px', tx + 'px');
      wrap.style.setProperty('--py', ty + 'px');
    };
    document.addEventListener('mousemove', onMove);
    return () => {
      document.removeEventListener('mousemove', onMove);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);

  return <div className="hx-hexbg" ref={wrapRef} aria-hidden="true"></div>;
}

// ─────────────────────────────────────────────────────────────────────────
// EXTRA 7: SelectionHex — when user selects text, show floating chip with
// the selection rendered as hex bytes, plus length/decimal stats.
// ─────────────────────────────────────────────────────────────────────────
function SelectionHex({ active }) {
  const chipRef = hxUseRef(null);

  hxUseEffect(() => {
    if (!active) return;
    const chip = chipRef.current;
    if (!chip) return;

    let raf = 0;
    const update = () => {
      raf = 0;
      const sel = window.getSelection();
      if (!sel || sel.rangeCount === 0 || sel.isCollapsed) {
        chip.classList.remove('on'); return;
      }
      const text = sel.toString();
      if (!text || !text.trim()) {
        chip.classList.remove('on'); return;
      }
      // ignore selections inside the chip itself, mini-map, tooltip, screensaver
      let node = sel.anchorNode;
      if (node && node.nodeType === 3) node = node.parentElement;
      if (node && node.closest && (
        node.closest('.hx-sel-chip') ||
        node.closest('.hx-mini') ||
        node.closest('.hx-tooltip') ||
        node.closest('.hx-screensaver') ||
        node.closest('.hx-boot')
      )) {
        chip.classList.remove('on'); return;
      }

      const range = sel.getRangeAt(0);
      const rect = range.getBoundingClientRect();

      // build hex view — show up to 64 chars, truncate with ellipsis
      const MAX = 64;
      const sliced = text.length > MAX ? text.slice(0, MAX) : text;
      const bytes = [];
      for (let i = 0; i < sliced.length; i++) {
        const code = sliced.charCodeAt(i);
        const isWS = sliced[i] === ' ' || sliced[i] === '\n' || sliced[i] === '\t';
        bytes.push(`<span class="${isWS ? 'ws' : ''}">${code.toString(16).padStart(2,'0').toUpperCase()}</span>`);
      }
      const more = text.length > MAX ? `<span class="ws"> … +${text.length - MAX}B</span>` : '';

      // stats
      const charCount = text.length;
      const byteCount = new Blob([text]).size;
      const sum = [...text].reduce((s, c) => s + c.charCodeAt(0), 0);
      const crc = (sum * 0xCAFE & 0xFFFF).toString(16).toUpperCase().padStart(4, '0');

      chip.innerHTML = `
        <div class="hdr">
          <span>selection · <span class="o">UTF-8</span></span>
          <span>len=<span class="o">${charCount}</span></span>
        </div>
        <div class="bytes">${bytes.join(' ')}${more}</div>
        <div class="ft">
          <span>bytes <span class="v o">${byteCount}</span></span>
          <span>sum <span class="v">0x${sum.toString(16).toUpperCase()}</span></span>
          <span>crc16 <span class="v g">0x${crc}</span></span>
        </div>
      `;

      // position above the selection
      const chipW = Math.min(480, Math.max(220, chip.offsetWidth));
      let x = rect.left;
      let y = rect.top - chip.offsetHeight - 12;
      if (y < 8) y = rect.bottom + 12; // flip below if no room
      if (x + chipW > window.innerWidth - 16) x = window.innerWidth - chipW - 16;
      if (x < 8) x = 8;
      chip.style.left = x + 'px';
      chip.style.top = y + 'px';
      chip.classList.add('on');
    };

    const onSel = () => {
      if (raf) cancelAnimationFrame(raf);
      raf = requestAnimationFrame(update);
    };
    document.addEventListener('selectionchange', onSel);
    document.addEventListener('mouseup', onSel);
    document.addEventListener('keyup', onSel);
    return () => {
      document.removeEventListener('selectionchange', onSel);
      document.removeEventListener('mouseup', onSel);
      document.removeEventListener('keyup', onSel);
      if (raf) cancelAnimationFrame(raf);
    };
  }, [active]);

  return <div className="hx-sel-chip" ref={chipRef} aria-hidden="true"></div>;
}

// ─────────────────────────────────────────────────────────────────────────
// EXTRA 11: Screensaver — kicks in after 60s of no input.
// Renders a long flowing hex dump that loops.
// Any keypress / mousemove / click dismisses.
// ─────────────────────────────────────────────────────────────────────────
const IDLE_MS = 60 * 1000;

function buildScreensaverHex() {
  const hexCh = '0123456789ABCDEF';
  const greens = ['windows internals', 'eac bypass', 'kernel driver loaded',
                  'PE header valid', 'IAT restored', 'antidebug ok',
                  'session open', 'BattlEye skipped', 'VAC negotiated',
                  'kamen@dev.local'];
  const lines = [];
  for (let r = 0; r < 220; r++) {
    const addr = (0x00400000 + r * 16).toString(16).toUpperCase().padStart(8, '0');
    // hex columns
    const codes = [];
    let plant = null;
    // randomly seed a "decoded" string in some rows
    if (Math.random() < 0.07) {
      plant = greens[(Math.random() * greens.length) | 0];
    }
    let asciiBuf = '';
    for (let c = 0; c < 16; c++) {
      let code;
      if (plant && c < plant.length) {
        code = plant.charCodeAt(c);
      } else {
        code = (Math.random() * 256) | 0;
      }
      codes.push(code);
      const ch = (code >= 32 && code <= 126) ? String.fromCharCode(code) : '·';
      asciiBuf += ch;
    }
    const hexStr = codes.map((c, i) => {
      const cls = plant && i < plant.length
        ? 'gn'
        : (Math.random() < 0.04 ? 'hi'
        : Math.random() < 0.06 ? 'cy' : 'ad');
      return `<span class="${cls}">${c.toString(16).toUpperCase().padStart(2,'0')}</span>`;
    }).join(' ');

    let asciiHTML = '';
    for (let i = 0; i < asciiBuf.length; i++) {
      const ch = asciiBuf[i];
      const isPlant = plant && i < plant.length;
      asciiHTML += `<span class="${isPlant ? 'gn' : 'as'}">${ch === ' ' ? '\u00A0' : ch}</span>`;
    }

    lines.push(
      `<div><span class="ad">${addr}</span>  ${hexStr}  ${asciiHTML}</div>`
    );
  }
  // double the lines for seamless loop
  return lines.concat(lines).join('');
}

function Screensaver({ enabled }) {
  const [on, setOn] = hxUseState(false);
  const lastRef = hxUseRef(Date.now());
  const html = hxUseMemo(() => buildScreensaverHex(), []);

  hxUseEffect(() => {
    if (!enabled) return;
    let timer = 0;
    const reset = () => {
      lastRef.current = Date.now();
      if (on) setOn(false);
    };
    const tick = () => {
      if (Date.now() - lastRef.current >= IDLE_MS) {
        setOn(true);
      }
    };
    const onActivity = () => reset();

    document.addEventListener('mousemove', onActivity);
    document.addEventListener('keydown', onActivity);
    document.addEventListener('click', onActivity);
    document.addEventListener('scroll', onActivity, true);
    document.addEventListener('touchstart', onActivity);

    timer = setInterval(tick, 2000);
    return () => {
      clearInterval(timer);
      document.removeEventListener('mousemove', onActivity);
      document.removeEventListener('keydown', onActivity);
      document.removeEventListener('click', onActivity);
      document.removeEventListener('scroll', onActivity, true);
      document.removeEventListener('touchstart', onActivity);
    };
  }, [enabled, on]);

  return (
    <div className={`hx-screensaver ${on ? 'on' : ''}`} aria-hidden={!on}>
      <div className="head">
        <span><span className="blip"></span>kamen.dmp <span className="o">idle / sleep</span> — auto-suspend after 60s</span>
        <span>continuous read — region <span className="o">0x00400000</span>+</span>
      </div>
      <div className="scroller" dangerouslySetInnerHTML={{ __html: html }}></div>
      <div className="ovr"></div>
      <div className="pill">
        move mouse · press <kbd>any key</kbd> to resume
      </div>
    </div>
  );
}

window.HexDump = HexDump;