{"id":987,"date":"2026-03-27T20:27:28","date_gmt":"2026-03-27T20:27:28","guid":{"rendered":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/?page_id=987"},"modified":"2026-04-08T12:11:15","modified_gmt":"2026-04-08T12:11:15","slug":"interface","status":"publish","type":"page","link":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/interface\/","title":{"rendered":"Interface"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\"\/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n<title>ENGRAM \u00b7 Quantum Control Interface<\/title>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=IBM+Plex+Mono:wght@300;400;500;600&#038;family=IBM+Plex+Sans:wght@300;400;500;600&#038;display=swap\" rel=\"stylesheet\"\/>\n<style>\n:root {\n  --bg:        #f5f4f0;\n  --white:     #fefefe;\n  --border:    #dddbd5;\n  --border2:   #c8c6be;\n  --text:      #1a1916;\n  --muted:     #7a7872;\n  --light:     #eceae4;\n  --mono:      'IBM Plex Mono', monospace;\n  --sans:      'IBM Plex Sans', sans-serif;\n\n  --blue:      #1a56cc;\n  --blue-lt:   #eef3fc;\n  --blue-bd:   #b3c8f0;\n\n  --green:     #1a7a3e;\n  --green-lt:  #edf7f1;\n  --green-bd:  #9fd4b3;\n\n  --amber:     #a85e00;\n  --amber-lt:  #fdf5e6;\n  --amber-bd:  #e8c47a;\n\n  --red:       #b81c1c;\n  --red-lt:    #fdf0f0;\n  --red-bd:    #e8a3a3;\n\n  --radius:    4px;\n  --radius-lg: 8px;\n}\n\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\nbody {\n  background: var(--bg);\n  color: var(--text);\n  font-family: var(--sans);\n  font-size: 13px;\n  -webkit-font-smoothing: antialiased;\n  min-height: 100vh;\n}\n\n\/* \u2500\u2500 HEADER \u2500\u2500 *\/\nheader {\n  background: var(--white);\n  border-bottom: 1px solid var(--border);\n  padding: 0 28px;\n  height: 56px;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  position: sticky;\n  top: 0;\n  z-index: 100;\n}\n\n.h-brand {\n  display: flex;\n  align-items: baseline;\n  gap: 10px;\n}\n.h-logo {\n  font-family: var(--mono);\n  font-size: 1.1rem;\n  font-weight: 600;\n  letter-spacing: 0.08em;\n  color: var(--text);\n}\n.h-logo span {\n  color: var(--muted);\n  font-weight: 300;\n  margin-left: 2px;\n}\n.h-sub {\n  font-size: .72rem;\n  color: var(--muted);\n  font-weight: 400;\n  border-left: 1px solid var(--border);\n  padding-left: 10px;\n}\n\n.h-chips { display: flex; align-items: center; gap: 6px; }\n\n.chip {\n  font-family: var(--mono);\n  font-size: .63rem;\n  padding: 3px 10px;\n  border-radius: 20px;\n  border: 1px solid;\n  display: flex;\n  align-items: center;\n  gap: 5px;\n  letter-spacing: .03em;\n  font-weight: 500;\n}\n.chip.ok   { color: var(--green); border-color: var(--green-bd); background: var(--green-lt); }\n.chip.err  { color: var(--red);   border-color: var(--red-bd);   background: var(--red-lt);  }\n.chip.warn { color: var(--amber); border-color: var(--amber-bd); background: var(--amber-lt); }\n.chip.unk  { color: var(--muted); border-color: var(--border2);  background: var(--light);   }\n\n.chip-dot { width: 5px; height: 5px; border-radius: 50%; flex-shrink: 0; }\n.chip.ok   .chip-dot { background: var(--green); animation: pulse 2.2s infinite; }\n.chip.err  .chip-dot { background: var(--red); }\n.chip.warn .chip-dot { background: var(--amber); animation: pulse 1.4s infinite; }\n.chip.unk  .chip-dot { background: #aaa; }\n@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.3} }\n\n\/* \u2500\u2500 TOOLBAR \u2500\u2500 *\/\n.toolbar {\n  background: var(--white);\n  border-bottom: 1px solid var(--border);\n  padding: 10px 28px;\n  display: flex;\n  align-items: center;\n  gap: 10px;\n}\n\n.btn {\n  font-family: var(--mono);\n  font-size: .72rem;\n  font-weight: 500;\n  letter-spacing: .04em;\n  border: 1px solid;\n  border-radius: var(--radius);\n  padding: 6px 16px;\n  cursor: pointer;\n  transition: all .15s;\n}\n.btn-run {\n  background: var(--text);\n  color: var(--white);\n  border-color: var(--text);\n}\n.btn-run:hover:not(:disabled) { background: #333; }\n.btn-run:disabled { opacity: .35; cursor: not-allowed; }\n\n.btn-stop {\n  background: var(--white);\n  color: var(--red);\n  border-color: var(--red-bd);\n}\n.btn-stop:hover:not(:disabled) { background: var(--red-lt); }\n.btn-stop:disabled { opacity: .35; cursor: not-allowed; }\n\n.t-status {\n  font-family: var(--mono);\n  font-size: .67rem;\n  padding: 4px 11px;\n  border-radius: var(--radius);\n  border: 1px solid;\n  letter-spacing: .03em;\n}\n.t-status.lock  { color: var(--green); border-color: var(--green-bd); background: var(--green-lt); }\n.t-status.marg  { color: var(--amber); border-color: var(--amber-bd); background: var(--amber-lt); }\n.t-status.drift { color: var(--red);   border-color: var(--red-bd);   background: var(--red-lt);  }\n.t-status.idle  { color: var(--muted); border-color: var(--border2);  background: var(--light);   }\n\n.t-spacer { flex: 1; }\n\n.t-meta {\n  font-family: var(--mono);\n  font-size: .67rem;\n  color: var(--muted);\n  padding: 3px 10px;\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  background: var(--light);\n}\n.t-meta strong { color: var(--text); font-weight: 600; }\n\n\/* \u2500\u2500 LAYOUT \u2500\u2500 *\/\n.wrap { max-width: 1020px; margin: 0 auto; padding: 20px 28px; display: flex; flex-direction: column; gap: 14px; }\n\n\/* \u2500\u2500 CARD \u2500\u2500 *\/\n.card {\n  background: var(--white);\n  border: 1px solid var(--border);\n  border-radius: var(--radius-lg);\n  overflow: hidden;\n}\n.card-head {\n  padding: 10px 18px;\n  border-bottom: 1px solid var(--border);\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  background: var(--light);\n}\n.card-title {\n  font-family: var(--mono);\n  font-size: .72rem;\n  font-weight: 600;\n  letter-spacing: .05em;\n  text-transform: uppercase;\n  color: var(--text);\n}\n.card-hint {\n  font-family: var(--mono);\n  font-size: .62rem;\n  color: var(--muted);\n}\n.card-body { padding: 18px; }\n\n\/* \u2500\u2500 VALS GRID \u2500\u2500 *\/\n.vals-grid {\n  display: grid;\n  grid-template-columns: repeat(5, 1fr);\n  gap: 10px;\n}\n.val-cell {\n  padding: 13px 15px;\n  background: var(--light);\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n}\n.val-label {\n  font-family: var(--mono);\n  font-size: .62rem;\n  color: var(--muted);\n  letter-spacing: .04em;\n  text-transform: uppercase;\n  margin-bottom: 7px;\n}\n.val-num {\n  font-family: var(--mono);\n  font-size: 1.35rem;\n  font-weight: 500;\n  color: var(--text);\n  line-height: 1;\n}\n.val-num.blue  { color: var(--blue); }\n.val-num.green { color: var(--green); }\n.val-num.amber { color: var(--amber); }\n.val-sub {\n  font-family: var(--mono);\n  font-size: .58rem;\n  color: var(--muted);\n  margin-top: 5px;\n}\n\n\/* \u2500\u2500 IPR SECTION \u2500\u2500 *\/\n.ipr-layout { display: flex; gap: 20px; align-items: flex-start; }\n.ipr-gauge { flex: 1; }\n.ipr-big {\n  font-family: var(--mono);\n  font-size: 2.6rem;\n  font-weight: 300;\n  color: var(--text);\n  line-height: 1;\n  margin-bottom: 10px;\n}\n.prog-track {\n  height: 6px;\n  background: var(--light);\n  border: 1px solid var(--border2);\n  border-radius: 3px;\n  overflow: hidden;\n  margin-bottom: 4px;\n}\n.prog-fill {\n  height: 100%;\n  border-radius: 3px;\n  transition: width .5s ease, background .5s ease;\n}\n.prog-labels {\n  display: flex;\n  justify-content: space-between;\n  font-family: var(--mono);\n  font-size: .58rem;\n  color: #aaa;\n}\n.status-pill {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  padding: 5px 13px;\n  border-radius: var(--radius);\n  border: 1px solid;\n  font-family: var(--mono);\n  font-size: .7rem;\n  font-weight: 500;\n  margin-top: 10px;\n  transition: all .3s;\n}\n.status-pill::before { content:''; width:6px; height:6px; border-radius:50%; flex-shrink:0; }\n.status-pill.lock  { color: var(--green); border-color: var(--green-bd); background: var(--green-lt); }\n.status-pill.lock::before  { background: var(--green); animation: pulse 2s infinite; }\n.status-pill.marg  { color: var(--amber); border-color: var(--amber-bd); background: var(--amber-lt); }\n.status-pill.marg::before  { background: var(--amber); animation: pulse 1.3s infinite; }\n.status-pill.drift { color: var(--red);   border-color: var(--red-bd);   background: var(--red-lt); }\n.status-pill.drift::before { background: var(--red); }\n.status-pill.idle  { color: var(--muted); border-color: var(--border2);  background: var(--light); }\n.status-pill.idle::before  { background: #aaa; }\n\n\/* Zeta freq mini-bars *\/\n.zeta-bars {\n  width: 200px;\n  flex-shrink: 0;\n  display: flex;\n  align-items: flex-end;\n  gap: 2px;\n  height: 56px;\n  padding: 4px 0;\n}\n.zeta-bar {\n  flex: 1;\n  border-radius: 2px 2px 0 0;\n  background: var(--blue);\n  opacity: .55;\n  transition: height .4s ease, opacity .4s;\n}\n.zeta-label {\n  font-family: var(--mono);\n  font-size: .58rem;\n  color: var(--muted);\n  margin-top: 4px;\n  text-align: center;\n}\n\n\/* \u2500\u2500 COMPARISON CHART \u2500\u2500 *\/\ncanvas#cmpChart { width: 100%; height: 210px; display: block; }\n.chart-legend { display: flex; gap: 18px; margin-top: 10px; flex-wrap: wrap; }\n.cl { display: flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: .65rem; color: var(--muted); }\n.cl-line { width: 20px; height: 2px; border-radius: 1px; flex-shrink: 0; }\n\n\/* Gain banner *\/\n.gain-banner {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 10px 16px;\n  border-radius: var(--radius);\n  border: 1px solid var(--green-bd);\n  background: var(--green-lt);\n  margin-top: 14px;\n}\n.gain-val {\n  font-family: var(--mono);\n  font-size: 1.8rem;\n  font-weight: 500;\n  color: var(--green);\n}\n.gain-lbl { font-family: var(--mono); font-size: .63rem; color: var(--muted); margin-top: 2px; }\n.gain-right { text-align: right; }\n.gain-target { font-family: var(--mono); font-size: .65rem; color: var(--muted); }\n.gain-target strong { color: var(--green); font-weight: 600; }\n.gain-note { font-family: var(--mono); font-size: .62rem; color: var(--muted); margin-top: 3px; }\n\n\/* \u2500\u2500 TWO COL \u2500\u2500 *\/\n.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }\n\n\/* \u2500\u2500 CONTROLLERS \u2500\u2500 *\/\n.ctrl-row {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 11px 14px;\n  background: var(--light);\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  margin-bottom: 8px;\n  transition: border-color .2s, background .2s;\n}\n.ctrl-row.active-ctrl {\n  background: var(--blue-lt);\n  border-color: var(--blue-bd);\n}\n.ctrl-name { font-family: var(--mono); font-size: .78rem; font-weight: 600; }\n.ctrl-role { font-family: var(--mono); font-size: .62rem; color: var(--muted); margin-top: 2px; }\n.ctrl-badge {\n  font-family: var(--mono);\n  font-size: .6rem;\n  padding: 2px 9px;\n  border-radius: 20px;\n  border: 1px solid;\n  letter-spacing: .04em;\n}\n.ctrl-badge.on  { color: var(--green); border-color: var(--green-bd); background: var(--green-lt); }\n.ctrl-badge.off { color: var(--muted); border-color: var(--border2);  background: var(--white);   }\n\n\/* \u2500\u2500 MEMORY \u2500\u2500 *\/\n.mem-list { display: flex; flex-direction: column; gap: 7px; }\n.mem-item {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 10px 14px;\n  background: var(--light);\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  transition: all .25s;\n}\n.mem-item.ep-on { background: var(--blue-lt);  border-color: var(--blue-bd);  }\n.mem-item.se-on { background: var(--green-lt); border-color: var(--green-bd); }\n.mem-item.pr-on { background: var(--amber-lt); border-color: var(--amber-bd); }\n.mem-tag {\n  font-family: var(--mono);\n  font-size: .6rem;\n  font-weight: 600;\n  letter-spacing: .07em;\n  text-transform: uppercase;\n  padding: 1px 8px;\n  border-radius: 2px;\n}\n.mem-tag.ep { background: var(--blue);  color: #fff; }\n.mem-tag.se { background: var(--green); color: #fff; }\n.mem-tag.pr { background: var(--amber); color: #fff; }\n.mem-name { font-family: var(--mono); font-size: .76rem; font-weight: 500; margin-left: 10px; }\n.mem-desc { font-family: var(--mono); font-size: .62rem; color: var(--muted); margin-left: auto; text-align: right; padding-left: 10px; }\n.mem-left { display: flex; align-items: center; }\n.mem-dot {\n  width: 7px; height: 7px;\n  border-radius: 50%;\n  background: var(--border2);\n  flex-shrink: 0;\n  transition: all .25s;\n}\n.mem-item.ep-on .mem-dot { background: var(--blue);  box-shadow: 0 0 5px rgba(26,86,204,.45); }\n.mem-item.se-on .mem-dot { background: var(--green); box-shadow: 0 0 5px rgba(26,122,62,.45); }\n.mem-item.pr-on .mem-dot { background: var(--amber); box-shadow: 0 0 5px rgba(168,94,0,.45); }\n\n\/* \u2500\u2500 CORRECTION NOTICE \u2500\u2500 *\/\n.corr-notice {\n  display: none;\n  padding: 8px 14px;\n  background: var(--amber-lt);\n  border: 1px solid var(--amber-bd);\n  border-radius: var(--radius);\n  font-family: var(--mono);\n  font-size: .7rem;\n  color: var(--amber);\n  font-weight: 500;\n  margin-top: 10px;\n}\n.corr-notice.show { display: block; }\n\n\/* \u2500\u2500 LOG TABLE \u2500\u2500 *\/\n.log-layout { display: grid; grid-template-columns: 1fr 300px; }\n.log-table-wrap { overflow-x: auto; border-right: 1px solid var(--border); }\n.log-scroll { max-height: 300px; overflow-y: auto; }\n.log-scroll::-webkit-scrollbar { width: 4px; }\n.log-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }\ntable { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: .65rem; }\nthead th {\n  padding: 7px 12px;\n  text-align: left;\n  font-weight: 600;\n  letter-spacing: .04em;\n  text-transform: uppercase;\n  color: var(--muted);\n  background: var(--light);\n  border-bottom: 1px solid var(--border);\n  white-space: nowrap;\n  font-size: .6rem;\n}\ntbody tr { border-bottom: 1px solid var(--border); transition: background .1s; }\ntbody tr:hover { background: var(--light); }\ntbody td { padding: 5px 12px; }\ntd.lock  { color: var(--green); font-weight: 500; }\ntd.marg  { color: var(--amber); }\ntd.drift { color: var(--red);   }\ntd.pos   { color: var(--green); font-weight: 600; }\ntd.neg   { color: var(--red);   font-weight: 600; }\n.log-empty { padding: 28px; text-align: center; font-family: var(--mono); font-size: .72rem; color: var(--muted); }\n\n\/* \u2500\u2500 SUMMARY \u2500\u2500 *\/\n.summary { padding: 16px; display: flex; flex-direction: column; gap: 6px; }\n.sum-title { font-family: var(--mono); font-size: .67rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }\n.sum-row { display: flex; justify-content: space-between; align-items: baseline; padding: 5px 0; border-bottom: 1px solid var(--border); }\n.sum-row:last-child { border-bottom: none; }\n.sum-label { font-family: var(--mono); font-size: .65rem; color: var(--muted); }\n.sum-val { font-family: var(--mono); font-size: .76rem; font-weight: 600; }\n.sum-inference {\n  font-family: var(--mono);\n  font-size: .66rem;\n  line-height: 1.6;\n  padding: 9px 11px;\n  background: var(--light);\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  color: var(--muted);\n  margin-top: 4px;\n}\n.sum-inference strong { color: var(--blue); }\n\n\/* \u2500\u2500 CHAT \u2500\u2500 *\/\n.chat-msgs {\n  height: 220px;\n  overflow-y: auto;\n  padding: 14px;\n  display: flex;\n  flex-direction: column;\n  gap: 9px;\n  background: var(--light);\n  border-bottom: 1px solid var(--border);\n}\n.chat-msgs::-webkit-scrollbar { width: 4px; }\n.chat-msgs::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }\n\n.msg { max-width: 82%; display: flex; flex-direction: column; gap: 2px; }\n.msg.user { align-self: flex-end; }\n.msg.bot  { align-self: flex-start; }\n.msg-who { font-family: var(--mono); font-size: .58rem; color: var(--muted); padding: 0 3px; letter-spacing: .04em; text-transform: uppercase; }\n.msg-b {\n  padding: 8px 13px;\n  border-radius: 6px;\n  font-family: var(--mono);\n  font-size: .72rem;\n  line-height: 1.6;\n}\n.msg.user .msg-b {\n  background: var(--text);\n  color: var(--white);\n  border-radius: 6px 6px 2px 6px;\n}\n.msg.bot.glm .msg-b {\n  background: var(--white);\n  border: 1px solid var(--amber-bd);\n  border-radius: 6px 6px 6px 2px;\n}\n.msg.bot.llm .msg-b {\n  background: var(--white);\n  border: 1px solid var(--blue-bd);\n  border-radius: 6px 6px 6px 2px;\n}\n.msg.bot.sys .msg-b {\n  background: var(--white);\n  border: 1px solid var(--border);\n  color: var(--muted);\n  font-size: .68rem;\n}\n.msg-stores { display: flex; gap: 4px; padding: 0 3px; flex-wrap: wrap; margin-top: 2px; }\n.mtag {\n  font-family: var(--mono);\n  font-size: .56rem;\n  padding: 1px 7px;\n  border-radius: 2px;\n  font-weight: 600;\n  letter-spacing: .04em;\n  text-transform: uppercase;\n}\n.mtag.ep { background: var(--blue);  color: #fff; }\n.mtag.se { background: var(--green); color: #fff; }\n.mtag.pr { background: var(--amber); color: #fff; }\n\n.typing {\n  display: flex;\n  gap: 3px;\n  align-items: center;\n  padding: 7px 16px;\n  background: var(--light);\n  border-bottom: 1px solid var(--border);\n}\n.typing span {\n  width: 5px; height: 5px; border-radius: 50%;\n  background: var(--muted);\n  animation: td 1.2s infinite;\n}\n.typing span:nth-child(2){animation-delay:.18s}\n.typing span:nth-child(3){animation-delay:.36s}\n@keyframes td{0%,60%,100%{transform:translateY(0)}30%{transform:translateY(-5px)}}\n\n.chip-row { display:flex; gap:6px; flex-wrap:wrap; padding:8px 14px; border-bottom:1px solid var(--border); }\n.chip {\n  display:inline-flex; align-items:center;\n  background:var(--blue-lt); border:1px solid var(--blue-bd); color:var(--blue);\n  border-radius:var(--radius); font-family:var(--mono); font-size:.62rem;\n  padding:4px 10px; cursor:pointer; transition:background .1s;\n}\n.chip:hover { background:#dbeafe; }\n.chat-footer { background:var(--white); }\n.chat-input-row { display:flex; gap:8px; padding:10px 14px; }\n.chat-input {\n  flex:1; border:1px solid var(--border); border-radius:var(--radius);\n  padding:8px 10px; font-family:var(--mono); font-size:.72rem;\n  resize:none; outline:none; min-height:38px; max-height:120px;\n}\n.chat-input:focus { border-color:var(--blue); }\n.chat-status { font-family:var(--mono); font-size:.65rem; color:var(--muted); padding:0 14px 6px; min-height:18px; }\n.dot { display:inline-block; width:5px; height:5px; border-radius:50%; background:var(--muted); margin-right:2px; animation:blink 1.2s infinite; }\n.dot:nth-child(2){animation-delay:.2s} .dot:nth-child(3){animation-delay:.4s}\n@keyframes blink{0%,80%,100%{opacity:.15}40%{opacity:1}}\n\n\/* \u2500\u2500 FOOTER \u2500\u2500 *\/\nfooter {\n  max-width: 1020px;\n  margin: 0 auto;\n  padding: 12px 28px;\n  font-family: var(--mono);\n  font-size: .62rem;\n  color: var(--muted);\n  border-top: 1px solid var(--border);\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n}\n\n\/* \u2500\u2500 ZETA COMB PANEL \u2500\u2500 *\/\n\n\/* dimension selector *\/\n.dim-row {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  margin-bottom: 16px;\n  flex-wrap: wrap;\n}\n.dim-label {\n  font-family: var(--mono);\n  font-size: .67rem;\n  color: var(--muted);\n  letter-spacing: .05em;\n  text-transform: uppercase;\n}\n.dim-btns { display: flex; gap: 5px; flex-wrap: wrap; }\n.dim-btn {\n  font-family: var(--mono);\n  font-size: .65rem;\n  font-weight: 600;\n  padding: 4px 11px;\n  border: 1px solid var(--border2);\n  border-radius: var(--radius);\n  background: var(--light);\n  color: var(--muted);\n  cursor: pointer;\n  transition: all .15s;\n  letter-spacing: .04em;\n}\n.dim-btn:hover { background: var(--blue-lt); border-color: var(--blue-bd); color: var(--blue); }\n.dim-btn.active { background: var(--blue); border-color: var(--blue); color: #fff; }\n \n.dim-info {\n  margin-left: auto;\n  font-family: var(--mono);\n  font-size: .65rem;\n  color: var(--muted);\n  padding: 4px 11px;\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  background: var(--light);\n}\n.dim-info strong { color: var(--text); }\n \n\/* main comb canvas *\/\n.comb-wrap {\n  position: relative;\n  margin-bottom: 10px;\n}\ncanvas#zetaComb {\n  width: 100%;\n  height: 220px;\n  display: block;\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  background: var(--white);\n}\n \n\/* hover tooltip *\/\n.comb-tooltip {\n  position: absolute;\n  pointer-events: none;\n  background: var(--text);\n  color: var(--white);\n  font-family: var(--mono);\n  font-size: .62rem;\n  padding: 5px 9px;\n  border-radius: var(--radius);\n  white-space: nowrap;\n  display: none;\n  z-index: 10;\n  line-height: 1.6;\n}\n \n\/* stats row under comb *\/\n.comb-stats {\n  display: grid;\n  grid-template-columns: repeat(5, 1fr);\n  gap: 8px;\n  margin-bottom: 14px;\n}\n.comb-stat {\n  padding: 9px 12px;\n  background: var(--light);\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n}\n.comb-stat-label {\n  font-family: var(--mono);\n  font-size: .58rem;\n  color: var(--muted);\n  text-transform: uppercase;\n  letter-spacing: .04em;\n  margin-bottom: 5px;\n}\n.comb-stat-val {\n  font-family: var(--mono);\n  font-size: 1.05rem;\n  font-weight: 500;\n  color: var(--text);\n}\n.comb-stat-val.blue  { color: var(--blue); }\n.comb-stat-val.green { color: var(--green); }\n.comb-stat-val.amber { color: var(--amber); }\n.comb-stat-sub {\n  font-family: var(--mono);\n  font-size: .57rem;\n  color: var(--muted);\n  margin-top: 3px;\n}\n \n\/* drive amplitude A(t) canvas *\/\ncanvas#driveAmp {\n  width: 100%;\n  height: 110px;\n  display: block;\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  background: var(--white);\n  margin-bottom: 10px;\n}\n \n\/* navigation vector row *\/\n.navvec-row {\n  display: flex;\n  gap: 10px;\n  align-items: stretch;\n  margin-bottom: 14px;\n  flex-wrap: wrap;\n}\n.navvec-cell {\n  flex: 1;\n  min-width: 140px;\n  padding: 11px 14px;\n  border: 1px solid var(--border);\n  border-radius: var(--radius);\n  background: var(--light);\n}\n.navvec-cell.highlight {\n  background: var(--blue-lt);\n  border-color: var(--blue-bd);\n}\n.navvec-title {\n  font-family: var(--mono);\n  font-size: .6rem;\n  font-weight: 600;\n  letter-spacing: .07em;\n  text-transform: uppercase;\n  color: var(--muted);\n  margin-bottom: 6px;\n}\n.navvec-val {\n  font-family: var(--mono);\n  font-size: 1.0rem;\n  font-weight: 500;\n  color: var(--text);\n  line-height: 1.2;\n}\n.navvec-sub {\n  font-family: var(--mono);\n  font-size: .59rem;\n  color: var(--muted);\n  margin-top: 4px;\n}\n \n\/* scaling table *\/\n.scale-table {\n  width: 100%;\n  border-collapse: collapse;\n  font-family: var(--mono);\n  font-size: .67rem;\n}\n.scale-table thead th {\n  padding: 6px 12px;\n  text-align: left;\n  font-weight: 600;\n  letter-spacing: .05em;\n  text-transform: uppercase;\n  color: var(--muted);\n  font-size: .6rem;\n  background: var(--light);\n  border-bottom: 1px solid var(--border);\n}\n.scale-table tbody tr { border-bottom: 1px solid var(--border); transition: background .1s; }\n.scale-table tbody tr:hover { background: var(--light); }\n.scale-table tbody tr.active-dim { background: var(--blue-lt); }\n.scale-table tbody td { padding: 6px 12px; }\n.scale-table .gain { color: var(--green); font-weight: 600; }\n.scale-table .dim-cell { color: var(--blue); font-weight: 600; }\n \n\/* clock sync note *\/\n.clock-note {\n  display: flex;\n  align-items: flex-start;\n  gap: 12px;\n  padding: 11px 14px;\n  background: var(--amber-lt);\n  border: 1px solid var(--amber-bd);\n  border-radius: var(--radius);\n  margin-top: 12px;\n}\n.clock-icon {\n  font-size: 1.1rem;\n  flex-shrink: 0;\n  margin-top: 1px;\n}\n.clock-text {\n  font-family: var(--mono);\n  font-size: .65rem;\n  line-height: 1.6;\n  color: var(--amber);\n}\n.clock-text strong { color: var(--text); }\n\n.hidden { display: none !important; }\n<\/style>\n<\/head>\n<body>\n\n<!-- HEADER -->\n<header>\n  <div class=\"h-brand\">\n    <div class=\"h-logo\">ENGRAM<span>\u00b7v1<\/span><\/div>\n    <div class=\"h-sub\">Quantum Control Interface \u00b7 PP-RAI 2026<\/div>\n  <\/div>\n  <div class=\"h-chips\">\n    <div class=\"chip unk\" id=\"chipQ\"><div class=\"chip-dot\"><\/div>QRNG<\/div>\n    <div class=\"chip unk\" id=\"chipG\"><div class=\"chip-dot\"><\/div>GLM-4<\/div>\n    <div class=\"chip unk\" id=\"chipL\"><div class=\"chip-dot\"><\/div>Llama 3.3<\/div>\n    <div class=\"chip unk\" id=\"chipAer\"><div class=\"chip-dot\"><\/div>Qiskit Aer<\/div>\n  <\/div>\n<\/header>\n\n<!-- TOOLBAR -->\n<div class=\"toolbar\">\n  <button class=\"btn btn-run\"  id=\"btnStart\" onclick=\"startSim()\">\u25b6 RUN<\/button>\n  <button class=\"btn btn-stop\" id=\"btnStop\"  onclick=\"stopSim()\" disabled>\u25a0 HALT<\/button>\n  <span class=\"t-status idle\" id=\"tStatus\">OFFLINE<\/span>\n  <div class=\"t-spacer\"><\/div>\n  <span class=\"t-meta\">CYCLE <strong id=\"tCycle\">\u2014<\/strong><\/span>\n  <span class=\"t-meta\" style=\"margin-left:6px;\">FIDELITY <strong id=\"tFidelity\">\u2014<\/strong><\/span>\n  <span class=\"t-meta\" style=\"margin-left:6px;\">ds\u00b2 <strong id=\"tDsq\">\u2014<\/strong><\/span>\n  <span class=\"t-meta\" style=\"margin-left:6px;\">QRNG BUF <strong id=\"tBuf\">\u2014<\/strong><\/span>\n<\/div>\n\n<div class=\"wrap\">\n\n  <!-- LIVE VALUES -->\n  <div class=\"card\">\n    <div class=\"card-head\">\n      <span class=\"card-title\">Live Metrics<\/span>\n      <span class=\"card-hint\">Updated each Floquet cycle \u00b7 0.6s interval<\/span>\n    <\/div>\n    <div class=\"card-body\">\n      <div class=\"vals-grid\">\n        <div class=\"val-cell\">\n          <div class=\"val-label\">Entropy S<\/div>\n          <div class=\"val-num blue\" id=\"vEntropy\">\u2014<\/div>\n          <div class=\"val-sub\">von Neumann \u00b7 QRNG track<\/div>\n        <\/div>\n        <div class=\"val-cell\">\n          <div class=\"val-label\">Syntropy \u03a3<\/div>\n          <div class=\"val-num green\" id=\"vSyntropy\">\u2014<\/div>\n          <div class=\"val-sub\">1 \u2212 IPR(QRNG)<\/div>\n        <\/div>\n        <div class=\"val-cell\">\n          <div class=\"val-label\">Fidelity<\/div>\n          <div class=\"val-num\" id=\"vFidelity\">\u2014<\/div>\n          <div class=\"val-sub\">1 \u2212 |ds\u00b2|<\/div>\n        <\/div>\n        <div class=\"val-cell\">\n          <div class=\"val-label\">Gain (QRNG\u2212PRNG)<\/div>\n          <div class=\"val-num\" id=\"vGain\" style=\"font-size:1.1rem;padding-top:4px;\">\u2014<\/div>\n          <div class=\"val-sub\">MBL stability \u00b7 paper: +38%<\/div>\n        <\/div>\n        <div class=\"val-cell\">\n          <div class=\"val-label\">Entropy Source<\/div>\n          <div class=\"val-num\" id=\"vSource\" style=\"font-size:.85rem;padding-top:4px;\">\u2014<\/div>\n          <div class=\"val-sub\" id=\"vSourceSub\">\u2014<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- IPR + ZETA COMB -->\n  <div class=\"card\">\n    <div class=\"card-head\">\n      <span class=\"card-title\">Inverse Participation Ratio \u2014 QRNG track<\/span>\n      <span class=\"card-hint\">IPR &lt; 0.3 \u2192 Syntropy lock \u00b7 Riemann Zeta zero frequency comb<\/span>\n    <\/div>\n    <div class=\"card-body\">\n      <div class=\"ipr-layout\">\n        <div class=\"ipr-gauge\">\n          <div class=\"ipr-big\" id=\"iprNum\">\u2014<\/div>\n          <div class=\"prog-track\"><div class=\"prog-fill\" id=\"iprFill\" style=\"width:0%;background:var(--border2);\"><\/div><\/div>\n          <div class=\"prog-labels\">\n            <span>0.0 Localised \u00b7 syntropic<\/span><span>0.3<\/span><span>0.6<\/span><span>1.0 Delocalised \u00b7 thermal<\/span>\n          <\/div>\n          <div class=\"status-pill idle\" id=\"statusPill\">Offline<\/div>\n          <div class=\"corr-notice\" id=\"corrNotice\">\u26a0 Topological correction triggered \u2014 Phase_Reset_v2 dispatched<\/div>\n        <\/div>\n        <div>\n          <div class=\"zeta-bars\" id=\"zetaBars\"><\/div>\n          <div class=\"zeta-label\">\u03b3\u2081\u2026\u03b3\u2082\u2080 Zeta zeros \u00b7 drive comb<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  \n\n\n  <!-- QRNG vs PRNG COMPARISON -->\n  <div class=\"card\">\n    <div class=\"card-head\">\n      <span class=\"card-title\">QRNG vs PRNG \u2014 IPR Comparison<\/span>\n      <span class=\"card-hint\">Identical Floquet circuit \u00b7 entropy source is the only variable<\/span>\n    <\/div>\n    <div class=\"card-body\">\n      <canvas id=\"cmpChart\"><\/canvas>\n      <div class=\"chart-legend\">\n        <div class=\"cl\"><div class=\"cl-line\" style=\"background:var(--green);\"><\/div>QRNG (Aer Hadamard circuit)<\/div>\n        <div class=\"cl\"><div class=\"cl-line\" style=\"background:var(--red);opacity:.65;\"><\/div>PRNG (numpy baseline)<\/div>\n        <div class=\"cl\"><div class=\"cl-line\" style=\"background:var(--border2);border-top:1px dashed #bbb;\"><\/div>Lock threshold 0.3<\/div>\n      <\/div>\n      <div class=\"gain-banner\" id=\"gainBanner\">\n        <div>\n          <div class=\"gain-val\" id=\"gainVal\">\u2014<\/div>\n          <div class=\"gain-lbl\">current stability gain \u00b7 QRNG vs PRNG<\/div>\n        <\/div>\n        <div class=\"gain-right\">\n          <div class=\"gain-target\">Paper target: <strong>+38%<\/strong> MBL stability<\/div>\n          <div class=\"gain-note\" id=\"gainNote\">\u2014<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- CONTROLLERS + MEMORY -->\n  <div class=\"two-col\">\n    <div class=\"card\">\n      <div class=\"card-head\"><span class=\"card-title\">LLM Controllers (Ollama)<\/span><\/div>\n      <div class=\"card-body\">\n        <div class=\"ctrl-row\" id=\"ctrlGLM\">\n          <div>\n            <div class=\"ctrl-name\">GLM-4-9B<\/div>\n            <div class=\"ctrl-role\">Recovery \u00b7 dispatched when IPR \u2265 0.3<\/div>\n          <\/div>\n          <div class=\"ctrl-badge off\" id=\"glmBadge\">STANDBY<\/div>\n        <\/div>\n        <div class=\"ctrl-row\" id=\"ctrlLlama\">\n          <div>\n            <div class=\"ctrl-name\">Llama 3.3<\/div>\n            <div class=\"ctrl-role\">Maintenance \u00b7 active when IPR &lt; 0.3<\/div>\n          <\/div>\n          <div class=\"ctrl-badge off\" id=\"llamaBadge\">STANDBY<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <div class=\"card\">\n      <div class=\"card-head\"><span class=\"card-title\">ENGRAM Memory Architecture<\/span><\/div>\n      <div class=\"card-body\">\n        <div class=\"mem-list\">\n          <div class=\"mem-item\" id=\"memEp\">\n            <div class=\"mem-left\">\n              <span class=\"mem-tag ep\">E<\/span>\n              <span class=\"mem-name\">Episodic<\/span>\n            <\/div>\n            <span class=\"mem-desc\">IPR history \u00b7 state vectors \u00b7 phase noise<\/span>\n            <div class=\"mem-dot\" style=\"margin-left:10px;\"><\/div>\n          <\/div>\n          <div class=\"mem-item\" id=\"memSe\">\n            <div class=\"mem-left\">\n              <span class=\"mem-tag se\">S<\/span>\n              <span class=\"mem-name\">Semantic<\/span>\n            <\/div>\n            <span class=\"mem-desc\">Zeta zeros \u00b7 physics priors \u00b7 specs<\/span>\n            <div class=\"mem-dot\" style=\"margin-left:10px;\"><\/div>\n          <\/div>\n          <div class=\"mem-item\" id=\"memPr\">\n            <div class=\"mem-left\">\n              <span class=\"mem-tag pr\">P<\/span>\n              <span class=\"mem-name\">Procedural<\/span>\n            <\/div>\n            <span class=\"mem-desc\">Phase_Reset_v2 \u00b7 NOT-NOT gate<\/span>\n            <div class=\"mem-dot\" style=\"margin-left:10px;\"><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<div class=\"card\" id=\"zetaPanel\">\n  <div class=\"card-head\">\n    <span class=\"card-title\">Riemann Zeta Frequency Comb \u2014 Drive Spectrum A(t)<\/span>\n    <span class=\"card-hint\">\u03b3\u2081\u2026\u03b3\u2081\u2080\u2080 non-trivial zeros \u00b7 Floquet-Zeta drive with QRNG noise \u03b5(t)<\/span>\n  <\/div>\n  <div class=\"card-body\">\n \n    <!-- Dimension selector -->\n    <div class=\"dim-row\">\n      <span class=\"dim-label\">Hilbert dim<\/span>\n      <div class=\"dim-btns\">\n        <button class=\"dim-btn active\" onclick=\"setDim(11)\"  id=\"dBtn11\" >d-11<\/button>\n        <button class=\"dim-btn\"        onclick=\"setDim(22)\"  id=\"dBtn22\" >d-22<\/button>\n        <button class=\"dim-btn\"        onclick=\"setDim(33)\"  id=\"dBtn33\" >d-33<\/button>\n        <button class=\"dim-btn\"        onclick=\"setDim(55)\"  id=\"dBtn55\" >d-55<\/button>\n        <button class=\"dim-btn\"        onclick=\"setDim(100)\" id=\"dBtn100\">d-100<\/button>\n      <\/div>\n      <div class=\"dim-info\" id=\"dimInfo\">\n        <strong>d-11<\/strong> \u00b7 11 Zeta zeros active \u00b7 Exact method \u00b7 128 KB\n      <\/div>\n    <\/div>\n \n    <!-- Navigation vector info row -->\n    <div class=\"navvec-row\" id=\"navvecRow\">\n      <div class=\"navvec-cell highlight\">\n        <div class=\"navvec-title\">Navigation Vector<\/div>\n        <div class=\"navvec-val\" id=\"nvLabel\">d-11 \/ d-100<\/div>\n        <div class=\"navvec-sub\">Floquet-Zeta drive \u00b7 QRNG \u03b5(t)<\/div>\n      <\/div>\n      <div class=\"navvec-cell\">\n        <div class=\"navvec-title\">Active Zeros<\/div>\n        <div class=\"navvec-val blue\" id=\"nvZeros\">11<\/div>\n        <div class=\"navvec-sub\">of 100 total \u00b7 \u03b3\u2081\u2026\u03b3\u2099<\/div>\n      <\/div>\n      <div class=\"navvec-cell\">\n        <div class=\"navvec-title\">\u03b3\u2081 (fundamental)<\/div>\n        <div class=\"navvec-val\">14.135 Hz<\/div>\n        <div class=\"navvec-sub\">first non-trivial zero<\/div>\n      <\/div>\n      <div class=\"navvec-cell\">\n        <div class=\"navvec-title\">\u03b3\u2099 (highest active)<\/div>\n        <div class=\"navvec-val\" id=\"nvGammaN\">52.970 Hz<\/div>\n        <div class=\"navvec-sub\">current dim cutoff<\/div>\n      <\/div>\n      <div class=\"navvec-cell\">\n        <div class=\"navvec-title\">Syntropy Gain<\/div>\n        <div class=\"navvec-val green\" id=\"nvGain\">baseline<\/div>\n        <div class=\"navvec-sub\">vs d-11 reference<\/div>\n      <\/div>\n      <div class=\"navvec-cell\">\n        <div class=\"navvec-title\">Max Coherence<\/div>\n        <div class=\"navvec-val amber\" id=\"nvCoherence\">1,200 \u00b1 300<\/div>\n        <div class=\"navvec-sub\">cycles \u00b7 paper Table 3<\/div>\n      <\/div>\n    <\/div>\n \n    <!-- Main comb spectrum canvas -->\n    <div class=\"comb-wrap\">\n      <canvas id=\"zetaComb\"><\/canvas>\n      <div class=\"comb-tooltip\" id=\"combTip\"><\/div>\n    <\/div>\n \n    <!-- Stats row -->\n    <div class=\"comb-stats\">\n      <div class=\"comb-stat\">\n        <div class=\"comb-stat-label\">Spectral span<\/div>\n        <div class=\"comb-stat-val blue\" id=\"csSpan\">\u2014<\/div>\n        <div class=\"comb-stat-sub\">\u03b3\u2081 \u2192 \u03b3\u2099 \u00b7 Hz<\/div>\n      <\/div>\n      <div class=\"comb-stat\">\n        <div class=\"comb-stat-label\">Mean spacing<\/div>\n        <div class=\"comb-stat-val\" id=\"csMean\">\u2014<\/div>\n        <div class=\"comb-stat-sub\">avg \u0394\u03b3 \u00b7 Hz<\/div>\n      <\/div>\n      <div class=\"comb-stat\">\n        <div class=\"comb-stat-label\">Min spacing<\/div>\n        <div class=\"comb-stat-val\" id=\"csMin\">\u2014<\/div>\n        <div class=\"comb-stat-sub\">GUE level repulsion<\/div>\n      <\/div>\n      <div class=\"comb-stat\">\n        <div class=\"comb-stat-label\">A(t) amplitude<\/div>\n        <div class=\"comb-stat-val green\" id=\"csAmp\">\u2014<\/div>\n        <div class=\"comb-stat-sub\">current drive \u00b7 normalised<\/div>\n      <\/div>\n      <div class=\"comb-stat\">\n        <div class=\"comb-stat-label\">\u03b5(t) injection<\/div>\n        <div class=\"comb-stat-val amber\" id=\"csEps\">\u2014<\/div>\n        <div class=\"comb-stat-sub\">QRNG entropy \u00b7 cycle<\/div>\n      <\/div>\n    <\/div>\n \n    <!-- Drive amplitude A(t) time series -->\n    <div class=\"card-head\" style=\"margin: 0 -18px; padding: 7px 18px; margin-bottom: 10px;\">\n      <span class=\"card-title\" style=\"font-size:.65rem;\">Drive Amplitude A(t) = \u03a3 sin(\u03b3\u2099t + \u03c6\u2099) + \u03b5(t)<\/span>\n      <span class=\"card-hint\">Live \u00b7 scrolling time window<\/span>\n    <\/div>\n    <canvas id=\"driveAmp\"><\/canvas>\n \n    <!-- Scaling performance table (Paper Table 3) -->\n    <div class=\"card-head\" style=\"margin: 0 -18px; padding: 7px 18px; margin-bottom: 10px;\">\n      <span class=\"card-title\" style=\"font-size:.65rem;\">Scaling Performance \u2014 d-11 \u2192 d-110 (Paper Table 3)<\/span>\n      <span class=\"card-hint\">Active row highlighted<\/span>\n    <\/div>\n    <table class=\"scale-table\">\n      <thead>\n        <tr>\n          <th>Dimension<\/th>\n          <th>Method<\/th>\n          <th>Syntropy Gain<\/th>\n          <th>Memory Footprint<\/th>\n          <th>Max Coherence Time<\/th>\n        <\/tr>\n      <\/thead>\n      <tbody id=\"scaleBody\">\n        <tr id=\"scRow11\"  class=\"active-dim\"><td class=\"dim-cell\">d-11<\/td> <td>Exact<\/td>      <td>Baseline<\/td>          <td>128 KB<\/td>  <td>1,200 \u00b1 300 cycles<\/td><\/tr>\n        <tr id=\"scRow22\" >                   <td class=\"dim-cell\">d-22<\/td> <td>Exact<\/td>      <td class=\"gain\">+18.2%<\/td><td>268 MB<\/td>  <td>2,100 \u00b1 400 cycles<\/td><\/tr>\n        <tr id=\"scRow33\" >                   <td class=\"dim-cell\">d-33<\/td> <td>Hybrid<\/td>     <td class=\"gain\">+29.4%<\/td><td>1.2 GB<\/td>  <td>3,400 \u00b1 500 cycles<\/td><\/tr>\n        <tr id=\"scRow55\" >                   <td class=\"dim-cell\">d-55<\/td> <td>Hybrid<\/td>     <td class=\"gain\">+34.1%<\/td><td>8.7 GB<\/td>  <td>5,800 \u00b1 700 cycles<\/td><\/tr>\n        <tr id=\"scRow100\">                   <td class=\"dim-cell\">d-100<\/td><td>GPU tensor<\/td> <td class=\"gain\">+38.0%<\/td><td>~512 GB<\/td> <td>12,000 \u00b1 1,200 cycles<\/td><\/tr>\n      <\/tbody>\n    <\/table>\n \n    <!-- Clock sync note -->\n    <div class=\"clock-note\">\n      <div class=\"clock-icon\">\u23f1<\/div>\n      <div class=\"clock-text\">\n        <strong>Quantum Clock Synchronisation:<\/strong>\n        Zeta frequency combs derived from Riemann zeros provide ultra-stable timing references for distributed satellite constellations.\n        \u03b3\u2081 = 14.135 Hz serves as the fundamental clock tick; higher zeros encode sub-harmonic corrections.\n        Spectral rigidity of the GUE ensemble ensures phase noise suppression analogous to optical frequency combs in precision metrology.\n      <\/div>\n    <\/div>\n \n  <\/div>\n<\/div>\n  <!-- LOG TABLE -->\n  <div class=\"card\">\n    <div class=\"card-head\">\n      <span class=\"card-title\">Cycle Log<\/span>\n      <span class=\"card-hint\" id=\"logCount\">No cycles recorded<\/span>\n    <\/div>\n    <div class=\"log-layout\">\n      <div class=\"log-table-wrap\">\n        <div class=\"log-scroll\" id=\"logScroll\">\n          <div class=\"log-empty\" id=\"logEmpty\">Start the simulation to record cycles.<\/div>\n          <table id=\"logTable\" style=\"display:none;\">\n            <thead>\n              <tr>\n                <th>#<\/th>\n                <th>Time<\/th>\n                <th>IPR\u00b7QRNG<\/th>\n                <th>IPR\u00b7PRNG<\/th>\n                <th>Gain<\/th>\n                <th>Entropy<\/th>\n                <th>Syntropy<\/th>\n                <th>Fidelity<\/th>\n                <th>Controller<\/th>\n                <th>Correction<\/th>\n              <\/tr>\n            <\/thead>\n            <tbody id=\"logBody\"><\/tbody>\n          <\/table>\n        <\/div>\n      <\/div>\n      <div class=\"summary\" id=\"summaryPanel\">\n        <div class=\"sum-title\">Session Summary<\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Cycles<\/span><span class=\"sum-val\" id=\"sumCycles\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Avg IPR \u00b7 QRNG<\/span><span class=\"sum-val\" id=\"sumIprQ\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Avg IPR \u00b7 PRNG<\/span><span class=\"sum-val\" id=\"sumIprP\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Avg stability gain<\/span><span class=\"sum-val\" id=\"sumGain\" style=\"color:var(--green);\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Lock time \u00b7 QRNG<\/span><span class=\"sum-val\" id=\"sumLockQ\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Lock time \u00b7 PRNG<\/span><span class=\"sum-val\" id=\"sumLockP\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Corrections<\/span><span class=\"sum-val\" id=\"sumCorr\">\u2014<\/span><\/div>\n        <div class=\"sum-row\"><span class=\"sum-label\">Avg fidelity<\/span><span class=\"sum-val\" id=\"sumFid\">\u2014<\/span><\/div>\n        <div class=\"sum-inference\" id=\"sumInf\">Run the simulation to generate an inference.<\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- CHAT -->\n  <div class=\"card\">\n    <div class=\"card-head\">\n      <span class=\"card-title\">ENGRAM Query Interface<\/span>\n      <span class=\"card-hint\">Live state + ENGRAM context injected into each LLM query<\/span>\n    <\/div>\n    <div class=\"chat-msgs\" id=\"chatMsgs\">\n      <div class=\"msg bot sys\">\n        <div class=\"msg-b\">Start the simulation, then query GLM-4 or Llama 3.3 with ENGRAM context. Try: &#8220;Why is QRNG more stable?&#8221; or &#8220;What correction routine should run now?&#8221;<\/div>\n      <\/div>\n    <\/div>\n    <div class=\"typing hidden\" id=\"typingRow\"><span><\/span><span><\/span><span><\/span><\/div>\n    <div class=\"chat-footer\">\n      <div class=\"chip-row\">\n        <span class=\"chip\" onclick=\"chip('What does the current IPR value indicate about MBL stability?')\">IPR analysis<\/span>\n        <span class=\"chip\" onclick=\"chip('Interpret the syntropy trend across these cycles.')\">Syntropy trend<\/span>\n        <span class=\"chip\" onclick=\"chip('Why is QRNG more stable than PRNG in this Floquet system?')\">QRNG vs PRNG<\/span>\n        <span class=\"chip\" onclick=\"chip('Summarise all simulation results from this run.')\">Summarise run<\/span>\n        <span class=\"chip\" onclick=\"chip('What correction should run if IPR exceeds 0.3?')\">Correction advice<\/span>\n        <span class=\"chip\" onclick=\"chip('Explain the Floquet drive with Riemann Zeta phase modulation.')\">Floquet \/ Zeta<\/span>\n        <span class=\"chip\" onclick=\"chip('What is the ENGRAM tri-partite memory architecture?')\">ENGRAM memory<\/span>\n      <\/div>\n      <div class=\"chat-input-row\">\n        <select id=\"modelSel\">\n          <option value=\"auto\">Auto (active controller)<\/option>\n          <option value=\"glm4:9b\" selected>GLM-4-9B (fast)<\/option>\n          <option value=\"llama3.3:latest\">Llama 3.3<\/option>\n        <\/select>\n        <textarea class=\"chat-input\" id=\"chatIn\"\n          placeholder=\"Ask about IPR, syntropy, Floquet physics, MBL, or the current run\u2026\"\n          onkeydown=\"if(event.key==='Enter'&#038;&#038;!event.shiftKey){event.preventDefault();sendChat();}\"\n          rows=\"1\"><\/textarea>\n        <button class=\"btn btn-run\" id=\"btnSend\" onclick=\"sendChat()\">SEND<\/button>\n        <button class=\"btn\" onclick=\"injectContext()\" style=\"font-size:.7rem;\">\ud83d\udcca State<\/button>\n      <\/div>\n      <div class=\"chat-status\" id=\"chatStatus\"><\/div>\n    <\/div>\n  <\/div>\n\n<\/div>\n\n<footer>\n  <span>ENGRAM v1.0 \u00b7 AGH UST Krak\u00f3w \/ KUL Lublin \/ IU Berlin \u00b7 PP-RAI 2026<\/span>\n  <span id=\"connStatus\" style=\"color:var(--muted);\">Connecting to backend\u2026<\/span>\n<\/footer>\n\n<script>\nconst API = 'http:\/\/localhost:8000';\nlet sse = null, running = false, lastState = null;\n\nconst MAX_PTS = 150;\nlet chartQ = [], chartP = [];\nconst logRows = [];\nlet corrections = 0;\n\n\/\/ \u2500\u2500 ZETA MINI BARS (static, first 20 zeros for decoration) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst ZETA20 = [14.13,21.02,25.01,30.42,32.93,37.58,40.91,43.32,48.00,49.77,\n                52.97,56.44,59.34,60.83,65.11,67.07,69.54,72.06,75.70,77.14];\nfunction buildZetaBars() {\n  const c = document.getElementById('zetaBars');\n  const max = Math.max(...ZETA20);\n  ZETA20.forEach(v => {\n    const bar = document.createElement('div');\n    bar.className = 'zeta-bar';\n    bar.style.height = Math.round((v \/ max) * 100) + '%';\n    c.appendChild(bar);\n  });\n}\nbuildZetaBars();\n\n\/\/ \u2500\u2500 CHART \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst cmpCanvas = document.getElementById('cmpChart');\nconst ctx = cmpCanvas.getContext('2d');\n\nfunction resizeChart() {\n  cmpCanvas.width  = cmpCanvas.offsetWidth;\n  cmpCanvas.height = 210;\n}\nwindow.addEventListener('resize', () => { resizeChart(); drawChart(); });\nsetTimeout(resizeChart, 100);\n\nfunction drawChart() {\n  resizeChart();\n  const W = cmpCanvas.width, H = cmpCanvas.height;\n  const P = { t: 12, r: 14, b: 26, l: 42 };\n  const cW = W - P.l - P.r, cH = H - P.t - P.b;\n\n  ctx.clearRect(0, 0, W, H);\n  ctx.fillStyle = '#f5f4f0'; ctx.fillRect(0,0,W,H);\n  ctx.fillStyle = '#fefefe'; ctx.fillRect(P.l, P.t, cW, cH);\n  ctx.strokeStyle = '#dddbd5'; ctx.lineWidth = 1;\n  ctx.strokeRect(P.l, P.t, cW, cH);\n\n  [0, 0.3, 0.6, 1.0].forEach(v => {\n    const y = P.t + cH - v * cH;\n    ctx.strokeStyle = v === 0.3 ? '#9fd4b3' : '#eceae4';\n    ctx.lineWidth   = v === 0.3 ? 1.5 : 1;\n    ctx.setLineDash(v === 0.3 ? [5,4] : []);\n    ctx.beginPath(); ctx.moveTo(P.l, y); ctx.lineTo(P.l+cW, y); ctx.stroke();\n    ctx.setLineDash([]);\n    ctx.fillStyle = '#aaa'; ctx.font = '9px IBM Plex Mono, monospace';\n    ctx.textAlign = 'right';\n    ctx.fillText(v.toFixed(1), P.l - 5, y + 3);\n  });\n\n  ctx.fillStyle = '#bbb'; ctx.font = '9px IBM Plex Mono, monospace';\n  ctx.textAlign = 'center';\n  ctx.fillText('CYCLE \u2192', P.l + cW\/2, H - 3);\n\n  const all = [...chartQ, ...chartP].filter(Number.isFinite);\n  if (all.length < 2) {\n    ctx.fillStyle = '#aaa'; ctx.font = '11px IBM Plex Sans, sans-serif';\n    ctx.textAlign = 'center';\n    ctx.fillText('Waiting for simulation data\u2026', W\/2, H\/2);\n    return;\n  }\n\n  function plotLine(data, color, dashed) {\n    if (data.length < 2) return;\n    ctx.strokeStyle = color; ctx.lineWidth = 2;\n    ctx.setLineDash(dashed ? [5,4] : []);\n    ctx.beginPath();\n    data.forEach((v, i) => {\n      const x = P.l + (i \/ (MAX_PTS - 1)) * cW;\n      const y = P.t + cH - Math.min(v, 1.0) * cH;\n      i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);\n    });\n    ctx.stroke();\n    ctx.setLineDash([]);\n  }\n\n  plotLine(chartP, 'rgba(184,28,28,0.5)', true);\n  plotLine(chartQ, '#1a7a3e', false);\n}\n\n\/\/ \u2500\u2500 HEALTH \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction setChip(id, cls) { document.getElementById(id).className = 'chip ' + cls; }\n\nasync function checkHealth() {\n  try {\n    const r = await fetch(`${API}\/health`, { signal: AbortSignal.timeout(2500) });\n    const d = await r.json();\n\n    setChip('chipQ',   d.qrng   ? 'ok' : 'warn');\n    setChip('chipG',   d.glm    ? 'ok' : 'err');\n    setChip('chipL',   d.llama  ? 'ok' : 'err');\n    setChip('chipAer', d.qiskit ? 'ok' : 'warn');\n\n    const src = d.qrng ? 'QRNG \u00b7 Aer' : 'PRNG fallback';\n    document.getElementById('vSource').textContent    = src;\n    document.getElementById('vSourceSub').textContent = d.qrng\n      ? 'IBM Quantum Aer (Hadamard)' : 'Quantis\/Aer unavailable';\n    document.getElementById('vSource').style.color    = d.qrng\n      ? 'var(--green)' : 'var(--amber)';\n\n    document.getElementById('connStatus').textContent = 'Backend connected \u00b7 port 8000';\n    document.getElementById('connStatus').style.color = 'var(--green)';\n  } catch {\n    ['chipQ','chipG','chipL','chipAer'].forEach(id => setChip(id, 'err'));\n    document.getElementById('connStatus').textContent = 'Backend unreachable \u00b7 uvicorn q_b:app --host 0.0.0.0 --port 8000';\n    document.getElementById('connStatus').style.color = 'var(--red)';\n  }\n}\ncheckHealth();\nsetInterval(checkHealth, 10000);\n\n\/\/ \u2500\u2500 APPLY STATE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction applyState(d) {\n  liveEps = d.ds_squared || 0;\n  driveT  = d.t; \n  lastState = d;\n  addLogRow(d);\n\n  \/\/ Toolbar\n  document.getElementById('tCycle').textContent    = d.cycle;\n  document.getElementById('tFidelity').textContent = d.fidelity.toFixed(5);\n  document.getElementById('tDsq').textContent      = d.ds_squared.toFixed(6);\n  document.getElementById('tBuf').textContent      = d.qrng_buf_depth;\n\n  \/\/ Live values\n  document.getElementById('vEntropy').textContent  = d.entropy.toFixed(4);\n  document.getElementById('vSyntropy').textContent = d.syntropy.toFixed(4);\n  document.getElementById('vFidelity').textContent = d.fidelity.toFixed(5);\n\n  const gain = d.ipr_prng > 0\n    ? (d.ipr_prng - d.ipr_qrng) \/ d.ipr_prng * 100 : 0;\n  const gainEl = document.getElementById('vGain');\n  gainEl.textContent = (gain >= 0 ? '+' : '') + gain.toFixed(1) + '%';\n  gainEl.style.color = gain >= 0 ? 'var(--green)' : 'var(--red)';\n\n  \/\/ IPR gauge\n  const ipr = d.ipr_qrng;\n  document.getElementById('iprNum').textContent = ipr.toFixed(4);\n  const fill = document.getElementById('iprFill');\n  fill.style.width      = Math.round(ipr * 100) + '%';\n  fill.style.background = ipr < .3 ? 'var(--green)' : ipr < .6 ? 'var(--amber)' : 'var(--red)';\n\n  const cls = ipr < .3 ? 'lock' : ipr < .6 ? 'marg' : 'drift';\n  const lbl = ipr < .3 ? 'Syntropy Locked' : ipr < .6 ? 'Marginal \u2014 correction pending' : 'Entropy Drift Detected';\n\n  document.getElementById('statusPill').className   = 'status-pill ' + cls;\n  document.getElementById('statusPill').textContent = lbl;\n  document.getElementById('tStatus').className      = 't-status ' + cls;\n  document.getElementById('tStatus').textContent    = lbl.toUpperCase();\n\n  \/\/ Correction\n  if (d.correction_triggered) {\n    const cn = document.getElementById('corrNotice');\n    cn.textContent = `\u26a0 ${d.correction_routine || 'Correction triggered'}`;\n    cn.classList.add('show');\n    setTimeout(() => cn.classList.remove('show'), 3500);\n  }\n\n  \/\/ Zeta bar animation (subtle pulse on correction)\n  if (d.correction_triggered) {\n    document.querySelectorAll('.zeta-bar').forEach(b => {\n      b.style.opacity = '0.9';\n      setTimeout(() => b.style.opacity = '.55', 400);\n    });\n  }\n\n  \/\/ Chart\n  chartQ.push(d.ipr_qrng);\n  chartP.push(d.ipr_prng);\n  if (chartQ.length > MAX_PTS) { chartQ.shift(); chartP.shift(); }\n  drawChart();\n\n  \/\/ Gain banner\n  document.getElementById('gainVal').textContent = (gain >= 0 ? '+' : '') + gain.toFixed(1) + '%';\n  document.getElementById('gainVal').style.color = gain >= 0 ? 'var(--green)' : 'var(--red)';\n  document.getElementById('gainNote').textContent =\n    gain >= 35 ? '\u2713 Consistent with paper result' :\n    gain >= 0  ? 'Below target \u2014 accumulating cycles' :\n                 'PRNG currently lower \u2014 converging';\n\n  \/\/ Controllers\n  const isGLM = d.controller && d.controller.includes('glm');\n  document.getElementById('ctrlGLM').className    = 'ctrl-row' + (isGLM ? ' active-ctrl' : '');\n  document.getElementById('glmBadge').className   = 'ctrl-badge ' + (isGLM ? 'on' : 'off');\n  document.getElementById('glmBadge').textContent = isGLM ? 'ACTIVE' : 'STANDBY';\n  document.getElementById('ctrlLlama').className  = 'ctrl-row' + (!isGLM ? ' active-ctrl' : '');\n  document.getElementById('llamaBadge').className  = 'ctrl-badge ' + (!isGLM ? 'on' : 'off');\n  document.getElementById('llamaBadge').textContent = !isGLM ? 'ACTIVE' : 'STANDBY';\n\n  \/\/ Memory stores\n  const stores = d.memory_stores || [];\n  document.getElementById('memEp').className = 'mem-item' + (stores.includes('episodic')   ? ' ep-on' : '');\n  document.getElementById('memSe').className = 'mem-item' + (stores.includes('semantic')   ? ' se-on' : '');\n  document.getElementById('memPr').className = 'mem-item' + (stores.includes('procedural') ? ' pr-on' : '');\n\n  const zeros = ZETA_ZEROS.slice(0, DIM_DATA[currentDim].zeros);\nconst amp   = computeAmp(driveT, zeros, liveEps);\ndriveHistory.push(amp);\nif (driveHistory.length > MAX_DRIVE) driveHistory.shift();\ndrawComb();\ndrawDriveAmp();\nupdateCombStats(zeros);\n}\n\n\/\/ \u2500\u2500 LOG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction addLogRow(d) {\n  logRows.push(d);\n  if (d.correction_triggered) corrections++;\n\n  const gain = d.ipr_prng > 0\n    ? (d.ipr_prng - d.ipr_qrng) \/ d.ipr_prng * 100 : 0;\n  const cls = d.ipr_qrng < .3 ? 'lock' : d.ipr_qrng < .6 ? 'marg' : 'drift';\n  const ctrl = d.controller || '\u2014';\n  const ctrlShort = ctrl.includes('glm') ? 'GLM-4' : ctrl.includes('llama') ? 'Llama3.3' : ctrl;\n\n  const tr = document.createElement('tr');\n  tr.innerHTML =\n    `<td>${d.cycle}<\/td>` +\n    `<td>${new Date().toTimeString().slice(0,8)}<\/td>` +\n    `<td class=\"${cls}\">${d.ipr_qrng.toFixed(4)}<\/td>` +\n    `<td>${d.ipr_prng.toFixed(4)}<\/td>` +\n    `<td class=\"${gain>=0?'pos':'neg'}\">${gain>=0?'+':''}${gain.toFixed(1)}%<\/td>` +\n    `<td>${d.entropy.toFixed(4)}<\/td>` +\n    `<td>${d.syntropy.toFixed(4)}<\/td>` +\n    `<td>${d.fidelity.toFixed(5)}<\/td>` +\n    `<td>${ctrlShort}<\/td>` +\n    `<td>${d.correction_triggered ? '<span style=\"color:var(--amber);font-weight:700;\">\u2713<\/span>' : '\u2014'}<\/td>`;\n\n  document.getElementById('logBody').prepend(tr);\n  document.getElementById('logEmpty').style.display = 'none';\n  document.getElementById('logTable').style.display = '';\n  document.getElementById('logCount').textContent   = logRows.length + ' cycles recorded';\n\n  updateSummary();\n}\n\nfunction updateSummary() {\n  const n = logRows.length; if (!n) return;\n  const avg = k => logRows.reduce((s,r) => s + (r[k]||0), 0) \/ n;\n  const avgQ   = avg('ipr_qrng'), avgP = avg('ipr_prng');\n  const avgFid = avg('fidelity');\n  const avgG   = avgP > 0 ? (avgP - avgQ) \/ avgP * 100 : 0;\n  const lockQ  = Math.round(logRows.filter(r => r.ipr_qrng < .3).length \/ n * 100);\n  const lockP  = Math.round(logRows.filter(r => r.ipr_prng < .3).length \/ n * 100);\n\n  document.getElementById('sumCycles').textContent = n;\n  document.getElementById('sumIprQ').textContent   = avgQ.toFixed(4);\n  document.getElementById('sumIprP').textContent   = avgP.toFixed(4);\n  document.getElementById('sumGain').textContent   = (avgG>=0?'+':'') + avgG.toFixed(1) + '%';\n  document.getElementById('sumGain').style.color   = avgG >= 0 ? 'var(--green)' : 'var(--red)';\n  document.getElementById('sumLockQ').textContent  = lockQ + '%';\n  document.getElementById('sumLockP').textContent  = lockP + '%';\n  document.getElementById('sumCorr').textContent   = corrections;\n  document.getElementById('sumFid').textContent    = avgFid.toFixed(5);\n\n  const src = logRows[0]?.qrng_active ? 'Aer QRNG (Hadamard)' : 'PRNG fallback';\n  let inf = '';\n  if (avgG >= 35)\n    inf = `<strong>Paper result reproduced.<\/strong> Avg IPR(QRNG)=${avgQ.toFixed(3)} vs IPR(PRNG)=${avgP.toFixed(3)} \u2014 ${avgG.toFixed(1)}% gain over ${n} cycles. Source: ${src}. QRNG in lock ${lockQ}% vs ${lockP}% PRNG.`;\n  else if (avgG > 0)\n    inf = `<strong>Positive gain, below paper +38%.<\/strong> ${avgG.toFixed(1)}% over ${n} cycles \u2014 continue accumulating. Source: ${src}.`;\n  else if (avgG < 0)\n    inf = `<strong>PRNG lower \u2014 not yet converged.<\/strong> ${n} cycles only. Source: ${src}. Expected to invert with more data.`;\n  else\n    inf = `<strong>Accumulating.<\/strong> ${n} cycles \u00b7 source: ${src}.`;\n\n  document.getElementById('sumInf').innerHTML = inf;\n}\n\n\/\/ \u2500\u2500 SSE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction connectSSE() {\n  if (sse) sse.close();\n  sse = new EventSource(`${API}\/stream`);\n  sse.onmessage = e => { try { applyState(JSON.parse(e.data)); } catch {} };\n  sse.onerror   = () => {\n    document.getElementById('connStatus').textContent = 'Stream interrupted \u2014 retrying\u2026';\n    document.getElementById('connStatus').style.color = 'var(--amber)';\n  };\n}\n\n\/\/ \u2500\u2500 START \/ STOP \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nasync function startSim() {\n  try {\n    await fetch(`${API}\/start`, { method: 'POST' });\n    running = true;\n    document.getElementById('btnStart').disabled = true;\n    document.getElementById('btnStop').disabled  = false;\n    connectSSE();\n  } catch {\n    alert('Cannot reach backend.\\n\\nRun:\\n  uvicorn q_b:app --host 0.0.0.0 --port 8000');\n  }\n}\nasync function stopSim() {\n  try { await fetch(`${API}\/stop`, { method: 'POST' }); } catch {}\n  running = false;\n  document.getElementById('btnStart').disabled = false;\n  document.getElementById('btnStop').disabled  = true;\n  if (sse) { sse.close(); sse = null; }\n  document.getElementById('tStatus').className   = 't-status idle';\n  document.getElementById('tStatus').textContent = 'OFFLINE';\n}\n\n\/\/ \u2500\u2500 CHAT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst STORE_TAGS = {\n  episodic:   '<span class=\"mtag ep\">E<\/span>',\n  semantic:   '<span class=\"mtag se\">S<\/span>',\n  procedural: '<span class=\"mtag pr\">P<\/span>',\n};\n\nfunction addMsg(cls, model, text, stores) {\n  const c = document.getElementById('chatMsgs');\n  const d = document.createElement('div');\n  d.className = 'msg bot ' + cls;\n  const tags = (stores || []).map(s => (typeof STORE_TAGS !== 'undefined' ? STORE_TAGS[s] : '') || '').join('');\n  const modelLabel = model.includes('glm') ? 'GLM-4-9B' : model.includes('llama') ? 'LLAMA 3.3' : model.toUpperCase();\n  d.innerHTML =\n    `<div class=\"msg-who\">${modelLabel}<\/div>` +\n    `<div class=\"msg-b\">${text}<\/div>` +\n    (tags ? `<div class=\"msg-stores\">${tags}<\/div>` : '');\n  c.appendChild(d);\n  c.scrollTop = c.scrollHeight;\n}\nfunction addUser(t) {\n  const c = document.getElementById('chatMsgs');\n  const d = document.createElement('div');\n  d.className = 'msg user';\n  d.innerHTML = `<div class=\"msg-who\">YOU<\/div><div class=\"msg-b\">${t}<\/div>`;\n  c.appendChild(d); c.scrollTop = c.scrollHeight;\n}\n\nconst SYSTEM_PROMPT = `You are the ENGRAM quantum control assistant. You have expertise in:\n- Floquet time crystals, MBL, and DTC signatures\n- IPR (Inverse Participation Ratio) as a syntropy metric\n- The ENGRAM tri-partite memory architecture (episodic, semantic, procedural)\n- Riemann Zeta zero frequency combs for Floquet modulation\n- QRNG vs PRNG entropy sources and their effect on MBL stability\nWhen given live simulation metrics, interpret them concisely and technically. Be direct.`;\n\nlet chatHistory = [];\nlet chatBusy    = false;\nlet includeSnapshotNext = false;\n\nfunction simStateText() {\n  if (!lastState) return null;\n  const d = lastState;\n  return `[ENGRAM Live State \u2014 Cycle ${d.cycle} | IPR_QRNG=${d.ipr_qrng?.toFixed(4)} | IPR_PRNG=${d.ipr_prng?.toFixed(4)} | Gain=${d.gain_pct?.toFixed(1)}% | Entropy=${d.entropy?.toFixed(4)} | Syntropy=${d.syntropy?.toFixed(4)} | Lock=${d.lock} | Controller=${d.controller} | QRNG_active=${d.qrng_active}]`;\n}\n\nfunction injectContext() {\n  includeSnapshotNext = true;\n  const inp = document.getElementById('chatIn');\n  inp.value = '(Sim state will be attached) ';\n  inp.focus();\n  inp.setSelectionRange(inp.value.length, inp.value.length);\n}\n\nfunction chip(text) {\n  const ctx = simStateText();\n  document.getElementById('chatIn').value = ctx ? `${ctx}\\n\\n${text}` : text;\n  sendChat();\n}\n\nfunction setTyping(on) {\n  document.getElementById('chatStatus').innerHTML = on\n    ? '<span class=\"dot\"><\/span><span class=\"dot\"><\/span><span class=\"dot\"><\/span> Thinking\u2026'\n    : '';\n}\n\nfunction addUserMsg(text) {\n  const c = document.getElementById('chatMsgs');\n  const d = document.createElement('div');\n  d.className = 'msg user';\n  d.innerHTML = `<div class=\"msg-who\">YOU<\/div><div class=\"msg-b\">${text}<\/div>`;\n  c.appendChild(d); c.scrollTop = c.scrollHeight;\n}\n\nfunction addAssistantBubble(model) {\n  const c   = document.getElementById('chatMsgs');\n  const wrap = document.createElement('div');\n  wrap.className = 'msg bot ' + (model.includes('glm') ? 'glm' : 'llm');\n  const who = document.createElement('div'); who.className = 'msg-who';\n  who.textContent = model.includes('glm') ? 'GLM-4-9B' : 'LLAMA 3.3';\n  const bub = document.createElement('div'); bub.className = 'msg-b'; bub.textContent = '';\n  const meta = document.createElement('div'); meta.className = 'msg-who'; meta.style.marginTop = '2px';\n  wrap.appendChild(who); wrap.appendChild(bub); wrap.appendChild(meta);\n  c.appendChild(wrap); c.scrollTop = c.scrollHeight;\n  return { bub, meta };\n}\n\nasync function sendChat() {\n  if (chatBusy) return;\n  const inp  = document.getElementById('chatIn');\n  const text = inp.value.trim(); if (!text) return;\n  inp.value  = ''; chatBusy = true;\n  document.getElementById('btnSend').disabled = true;\n\n  addUserMsg(text);\n  chatHistory.push({ role: 'user', content: text });\n  setTyping(true);\n\n  const model    = document.getElementById('modelSel').value === 'auto'\n    ? (lastState?.controller || 'glm4:9b') : document.getElementById('modelSel').value;\n  const messages = [{ role: 'system', content: SYSTEM_PROMPT }, ...chatHistory];\n  const snapshot = includeSnapshotNext ? lastState : null;\n  includeSnapshotNext = false;\n\n  const { bub, meta } = addAssistantBubble(model);\n  let full = '';\n\n  try {\n    const res = await fetch('http:\/\/localhost:8000\/ollama\/chat', {\n      method:  'POST',\n      headers: { 'Content-Type': 'application\/json' },\n      body:    JSON.stringify({ model, messages, stream: true, context_snapshot: snapshot }),\n    });\n    if (!res.ok) throw new Error(`HTTP ${res.status}`);\n\n    const reader = res.body.getReader();\n    const dec    = new TextDecoder();\n    const c      = document.getElementById('chatMsgs');\n\n    while (true) {\n      const { done, value } = await reader.read(); if (done) break;\n      const lines = dec.decode(value, { stream: true }).split('\\n').filter(l => l.trim());\n      for (const line of lines) {\n        try {\n          const obj = JSON.parse(line);\n          if (obj.message?.content) { full += obj.message.content; bub.textContent = full; c.scrollTop = c.scrollHeight; }\n          if (obj.done) { const dur = obj.total_duration ? ` \u00b7 ${(obj.total_duration\/1e9).toFixed(1)}s` : ''; meta.textContent = `done${dur}`; }\n          if (obj.error) throw new Error(obj.error);\n        } catch {}\n      }\n    }\n    chatHistory.push({ role: 'assistant', content: full });\n\n  } catch (err) {\n    bub.textContent = `Error: ${err.message}\\n\\nCheck Ollama is running: ollama serve`;\n    meta.textContent = 'error';\n  } finally {\n    setTyping(false);\n    chatBusy = false;\n    document.getElementById('btnSend').disabled = false;\n  }\n}\n\n\/\/ \u2500\u2500 All 100 Riemann Zeta zeros (imaginary parts \u03b3\u2099, in Hz) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst ZETA_ZEROS = [\n  14.134725, 21.022040, 25.010858, 30.424876, 32.935062,\n  37.586178, 40.918719, 43.327073, 48.005151, 49.773832,\n  52.970321, 56.446248, 59.347044, 60.831779, 65.112544,\n  67.079811, 69.546402, 72.067158, 75.704691, 77.144840,\n  79.337375, 82.910381, 84.735493, 87.425275, 88.809111,\n  92.491899, 94.651344, 95.870634, 98.831194, 101.317851,\n  103.725538, 105.446623, 107.168611, 111.029536, 111.874659,\n  114.320221, 116.226680, 118.790782, 121.370125, 122.946829,\n  124.256819, 127.516683, 129.578704, 131.087688, 133.497737,\n  134.756510, 138.116042, 139.736209, 141.123707, 143.111846,\n  146.000982, 147.422765, 150.053521, 150.925257, 153.024693,\n  156.112909, 157.597591, 158.849988, 161.188964, 163.030710,\n  165.537069, 167.184439, 169.094515, 169.911977, 173.411536,\n  174.754191, 176.441434, 178.377407, 179.916484, 182.207078,\n  184.874467, 185.598783, 187.228922, 189.416158, 192.026656,\n  193.079726, 195.265397, 196.876481, 198.015309, 201.264751,\n  202.493594, 204.189671, 205.394697, 207.906259, 209.576509,\n  211.690862, 213.347919, 214.547044, 216.169538, 219.067596,\n  220.714918, 221.430705, 224.007000, 224.983324, 227.421444,\n  229.337413, 231.250188, 231.987235, 233.693404, 236.524230,\n];\n \n\/\/ Scaling table data keyed by dim\nconst DIM_DATA = {\n  11:  { zeros: 11,  gain: 'Baseline', mem: '128 KB',   coh: '1,200 \u00b1 300',   rowId: 'scRow11'  },\n  22:  { zeros: 22,  gain: '+18.2%',  mem: '268 MB',   coh: '2,100 \u00b1 400',   rowId: 'scRow22'  },\n  33:  { zeros: 33,  gain: '+29.4%',  mem: '1.2 GB',   coh: '3,400 \u00b1 500',   rowId: 'scRow33'  },\n  55:  { zeros: 55,  gain: '+34.1%',  mem: '8.7 GB',   coh: '5,800 \u00b1 700',   rowId: 'scRow55'  },\n  100: { zeros: 100, gain: '+38.0%',  mem: '~512 GB',  coh: '12,000 \u00b1 1,200', rowId: 'scRow100' },\n};\n \nlet currentDim = 11;\nlet driveHistory = [];\nlet zetaAnimFrame = null;\nlet driveT = 0;\n\/\/ Live epsilon from backend (updated by applyState if integrated)\nlet liveEps = 0.0;\n \n\/\/ Phases \u03c6\u2099 (fixed, Zeta-derived mod 2\u03c0)\nconst PHASES = ZETA_ZEROS.map(z => z % (2 * Math.PI));\n \n\/\/ \u2500\u2500 Dimension selector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction setDim(d) {\n  currentDim = d;\n  document.querySelectorAll('.dim-btn').forEach(b => b.classList.remove('active'));\n  document.getElementById('dBtn' + d).classList.add('active');\n \n  const info = DIM_DATA[d];\n  const zeros = ZETA_ZEROS.slice(0, info.zeros);\n  const gammaN = zeros[zeros.length - 1];\n \n  document.getElementById('dimInfo').innerHTML =\n    `<strong>d-${d}<\/strong> \u00b7 ${info.zeros} Zeta zeros active \u00b7 ${info.mem}`;\n  document.getElementById('nvLabel').textContent    = `d-${d} \/ d-100`;\n  document.getElementById('nvZeros').textContent    = info.zeros;\n  document.getElementById('nvGammaN').textContent   = gammaN.toFixed(3) + ' Hz';\n  document.getElementById('nvGain').textContent     = info.gain;\n  document.getElementById('nvCoherence').textContent = info.coh;\n \n  \/\/ Highlight table row\n  document.querySelectorAll('.scale-table tbody tr').forEach(r => r.classList.remove('active-dim'));\n  document.getElementById(info.rowId).classList.add('active-dim');\n \n  \/\/ Recompute stats\n  updateCombStats(zeros);\n  drawComb();\n}\n \n\/\/ \u2500\u2500 Comb stats \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction updateCombStats(zeros) {\n  const span = zeros[zeros.length - 1] - zeros[0];\n  const spacings = zeros.slice(1).map((v, i) => v - zeros[i]);\n  const meanSp = spacings.reduce((a, b) => a + b, 0) \/ spacings.length;\n  const minSp  = Math.min(...spacings);\n  const amp    = computeAmp(driveT, zeros, liveEps);\n \n  document.getElementById('csSpan').textContent = span.toFixed(3) + ' Hz';\n  document.getElementById('csMean').textContent = meanSp.toFixed(3) + ' Hz';\n  document.getElementById('csMin').textContent  = minSp.toFixed(3) + ' Hz';\n  document.getElementById('csAmp').textContent  = amp.toFixed(4);\n  document.getElementById('csEps').textContent  = liveEps.toFixed(4);\n}\n \n\/\/ \u2500\u2500 Drive amplitude A(t) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction computeAmp(t, zeros, eps) {\n  let val = 0;\n  zeros.forEach((gamma, i) => {\n    val += Math.sin(gamma * t + PHASES[i]);\n  });\n  return val \/ zeros.length + eps;\n}\n \n\/\/ \u2500\u2500 Draw comb spectrum \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst combCanvas = document.getElementById('zetaComb');\nconst combCtx    = combCanvas.getContext('2d');\nconst combTip    = document.getElementById('combTip');\n \nfunction resizeComb() {\n  combCanvas.width  = combCanvas.offsetWidth;\n  combCanvas.height = 220;\n}\n \nfunction drawComb() {\n  resizeComb();\n  const W = combCanvas.width, H = combCanvas.height;\n  const PAD = { t: 18, r: 16, b: 32, l: 52 };\n  const cW = W - PAD.l - PAD.r, cH = H - PAD.t - PAD.b;\n \n  combCtx.clearRect(0, 0, W, H);\n  combCtx.fillStyle = '#fefefe';\n  combCtx.fillRect(0, 0, W, H);\n \n  const zeros   = ZETA_ZEROS.slice(0, DIM_DATA[currentDim].zeros);\n  const minGamma = zeros[0], maxGamma = zeros[zeros.length - 1];\n  const range    = maxGamma - minGamma || 1;\n \n  \/\/ Grid lines\n  const gridVals = [0, 50, 100, 150, 200, 250].filter(v => v >= minGamma - 5 && v <= maxGamma + 5);\n  gridVals.forEach(v => {\n    const x = PAD.l + ((v - minGamma) \/ range) * cW;\n    combCtx.strokeStyle = '#eceae4';\n    combCtx.lineWidth   = 1;\n    combCtx.beginPath(); combCtx.moveTo(x, PAD.t); combCtx.lineTo(x, PAD.t + cH); combCtx.stroke();\n    combCtx.fillStyle = '#bbb';\n    combCtx.font = '9px IBM Plex Mono, monospace';\n    combCtx.textAlign = 'center';\n    combCtx.fillText(v + ' Hz', x, H - 4);\n  });\n \n  \/\/ Y axis label\n  combCtx.save();\n  combCtx.translate(12, PAD.t + cH \/ 2);\n  combCtx.rotate(-Math.PI \/ 2);\n  combCtx.fillStyle = '#aaa';\n  combCtx.font = '9px IBM Plex Mono, monospace';\n  combCtx.textAlign = 'center';\n  combCtx.fillText('|sin(\u03b3\u2099t + \u03c6\u2099)|', 0, 0);\n  combCtx.restore();\n \n  \/\/ Border\n  combCtx.strokeStyle = '#dddbd5';\n  combCtx.lineWidth = 1;\n  combCtx.strokeRect(PAD.l, PAD.t, cW, cH);\n \n  \/\/ Draw each zero as a vertical line (comb tooth)\n  zeros.forEach((gamma, i) => {\n    const x       = PAD.l + ((gamma - minGamma) \/ range) * cW;\n    const contrib = Math.abs(Math.sin(gamma * driveT + PHASES[i]));\n    const barH    = contrib * cH * 0.85;\n \n    \/\/ Colour by index group\n    const hue = i < 10 ? 'var(--blue)' :\n                i < 30 ? '#2980b9'     :\n                i < 60 ? '#1a7a3e'     : '#a85e00';\n \n    \/\/ Shadow glow on active zeros\n    combCtx.shadowColor = i < DIM_DATA[currentDim].zeros ? '#1a56cc33' : 'transparent';\n    combCtx.shadowBlur  = 3;\n \n    combCtx.fillStyle = hue;\n    combCtx.globalAlpha = 0.75;\n    combCtx.fillRect(x - 1.5, PAD.t + cH - barH, 3, barH);\n    combCtx.globalAlpha = 1;\n    combCtx.shadowBlur  = 0;\n \n    \/\/ Tip dot\n    combCtx.beginPath();\n    combCtx.arc(x, PAD.t + cH - barH, 2, 0, Math.PI * 2);\n    combCtx.fillStyle = hue;\n    combCtx.fill();\n \n    \/\/ Label first zero \u03b3\u2081\n    if (i === 0) {\n      combCtx.fillStyle = '#1a56cc';\n      combCtx.font = '9px IBM Plex Mono, monospace';\n      combCtx.textAlign = 'center';\n      combCtx.fillText('\u03b3\u2081', x, PAD.t + cH - barH - 6);\n    }\n    \/\/ Label last active zero\n    if (i === zeros.length - 1) {\n      combCtx.fillStyle = '#a85e00';\n      combCtx.font = '9px IBM Plex Mono, monospace';\n      combCtx.textAlign = 'center';\n      combCtx.fillText('\u03b3' + zeros.length, x, PAD.t + cH - barH - 6);\n    }\n  });\n \n  \/\/ Greyed-out remaining zeros (if not d-100)\n  if (currentDim < 100) {\n    ZETA_ZEROS.slice(zeros.length).forEach((gamma, i) => {\n      if (gamma > maxGamma + 80) return; \/\/ skip far ones\n      const x = PAD.l + ((gamma - minGamma) \/ range) * cW;\n      if (x < PAD.l || x > PAD.l + cW) return;\n      combCtx.fillStyle = '#dddbd5';\n      combCtx.globalAlpha = 0.5;\n      combCtx.fillRect(x - 0.5, PAD.t + cH - 8, 1, 8);\n      combCtx.globalAlpha = 1;\n    });\n  }\n}\n \n\/\/ \u2500\u2500 Hover tooltip on comb \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncombCanvas.addEventListener('mousemove', e => {\n  const rect    = combCanvas.getBoundingClientRect();\n  const mx      = e.clientX - rect.left;\n  const scaleX  = combCanvas.width \/ rect.width;\n  const PAD_L   = 52, PAD_R = 16;\n  const cW      = combCanvas.width - PAD_L - PAD_R;\n \n  const zeros   = ZETA_ZEROS.slice(0, DIM_DATA[currentDim].zeros);\n  const minG    = zeros[0], maxG = zeros[zeros.length - 1], range = maxG - minG;\n \n  \/\/ Find nearest zero\n  let best = null, bestDist = Infinity;\n  zeros.forEach((gamma, i) => {\n    const x = PAD_L + ((gamma - minG) \/ range) * cW;\n    const d = Math.abs(mx * scaleX - x);\n    if (d < bestDist) { bestDist = d; best = { gamma, i }; }\n  });\n \n  if (best &#038;&#038; bestDist < 15 * scaleX) {\n    const contrib = Math.sin(best.gamma * driveT + PHASES[best.i]);\n    combTip.style.display = 'block';\n    combTip.style.left    = (e.clientX - rect.left + 12) + 'px';\n    combTip.style.top     = (e.clientY - rect.top  - 40) + 'px';\n    combTip.innerHTML =\n      `\u03b3${best.i + 1} = ${best.gamma.toFixed(6)} Hz\\n` +\n      `sin(\u03b3t + \u03c6) = ${contrib.toFixed(4)}\\n` +\n      `\u03c6${best.i + 1} = ${PHASES[best.i].toFixed(4)} rad`;\n    combTip.style.whiteSpace = 'pre';\n  } else {\n    combTip.style.display = 'none';\n  }\n});\ncombCanvas.addEventListener('mouseleave', () => { combTip.style.display = 'none'; });\n \n\/\/ \u2500\u2500 Drive A(t) scrolling canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst driveCanvas = document.getElementById('driveAmp');\nconst driveCtx    = driveCanvas.getContext('2d');\nconst MAX_DRIVE   = 300;\n \nfunction resizeDrive() {\n  driveCanvas.width  = driveCanvas.offsetWidth;\n  driveCanvas.height = 110;\n}\n \nfunction drawDriveAmp() {\n  resizeDrive();\n  const W = driveCanvas.width, H = driveCanvas.height;\n  const PAD = { t: 10, r: 14, b: 22, l: 44 };\n  const cW = W - PAD.l - PAD.r, cH = H - PAD.t - PAD.b;\n \n  driveCtx.clearRect(0, 0, W, H);\n  driveCtx.fillStyle = '#fefefe'; driveCtx.fillRect(0, 0, W, H);\n  driveCtx.strokeStyle = '#dddbd5'; driveCtx.lineWidth = 1;\n  driveCtx.strokeRect(PAD.l, PAD.t, cW, cH);\n \n  \/\/ Zero line\n  driveCtx.strokeStyle = '#eceae4';\n  driveCtx.beginPath();\n  driveCtx.moveTo(PAD.l, PAD.t + cH \/ 2);\n  driveCtx.lineTo(PAD.l + cW, PAD.t + cH \/ 2);\n  driveCtx.stroke();\n \n  \/\/ Y labels\n  ['\u22121', '0', '+1'].forEach((lbl, i) => {\n    const y = PAD.t + (i === 0 ? 0 : i === 1 ? cH \/ 2 : cH);\n    driveCtx.fillStyle = '#bbb';\n    driveCtx.font = '9px IBM Plex Mono, monospace';\n    driveCtx.textAlign = 'right';\n    driveCtx.fillText(lbl, PAD.l - 5, y + 3);\n  });\n \n  \/\/ X label\n  driveCtx.fillStyle = '#bbb'; driveCtx.font = '9px IBM Plex Mono, monospace';\n  driveCtx.textAlign = 'center';\n  driveCtx.fillText('t \u2192', PAD.l + cW \/ 2, H - 3);\n \n  if (driveHistory.length < 2) return;\n \n  const n = driveHistory.length;\n  const vals = driveHistory;\n  const maxV = Math.max(...vals.map(Math.abs), 0.01);\n \n  driveCtx.strokeStyle = '#1a56cc';\n  driveCtx.lineWidth   = 1.5;\n  driveCtx.beginPath();\n  vals.forEach((v, i) => {\n    const x = PAD.l + (i \/ (MAX_DRIVE - 1)) * cW;\n    const y = PAD.t + cH \/ 2 - (v \/ maxV) * (cH \/ 2) * 0.9;\n    i === 0 ? driveCtx.moveTo(x, y) : driveCtx.lineTo(x, y);\n  });\n  driveCtx.stroke();\n \n  \/\/ Current value dot\n  const lastV = vals[vals.length - 1];\n  const lx = PAD.l + ((n - 1) \/ (MAX_DRIVE - 1)) * cW;\n  const ly = PAD.t + cH \/ 2 - (lastV \/ maxV) * (cH \/ 2) * 0.9;\n  driveCtx.beginPath();\n  driveCtx.arc(lx, ly, 3, 0, Math.PI * 2);\n  driveCtx.fillStyle = '#1a56cc';\n  driveCtx.fill();\n}\n \n\/\/ \u2500\u2500 Animation loop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction zetaAnimLoop() {\n  driveT += 0.004;\n \n  const zeros = ZETA_ZEROS.slice(0, DIM_DATA[currentDim].zeros);\n  const amp   = computeAmp(driveT, zeros, liveEps);\n \n  driveHistory.push(amp);\n  if (driveHistory.length > MAX_DRIVE) driveHistory.shift();\n \n  drawComb();\n  drawDriveAmp();\n  updateCombStats(zeros);\n \n  zetaAnimFrame = requestAnimationFrame(zetaAnimLoop);\n}\n \n\/\/ \u2500\u2500 Hook into existing applyState (if in front.html context) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ Add this line inside your existing applyState(d) function:\n\/\/ liveEps = d.ds_squared || 0;  \/\/ use ds\u00b2 as proxy for \u03b5(t) injection\n \n\/\/ \u2500\u2500 Init \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nwindow.addEventListener('resize', () => { drawComb(); drawDriveAmp(); });\nsetTimeout(() => {\n  resizeComb(); resizeDrive();\n  setDim(11);\n  resizeComb(); resizeDrive();\nsetDim(11);\ndrawComb();       \/\/ static initial draw only\ndrawDriveAmp();   \/\/ no loop \u2014 driven by SSE instead\n}, 150);\n\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>ENGRAM \u00b7 Quantum Control Interface ENGRAM\u00b7v1 Quantum Control Interface \u00b7 PP-RAI 2026 QRNG GLM-4 Llama 3.3 Qiskit Aer \u25b6 RUN \u25a0 HALT OFFLINE CYCLE \u2014 FIDELITY \u2014 ds\u00b2 \u2014 QRNG BUF \u2014 Live Metrics Updated each Floquet cycle \u00b7 0.6s interval Entropy S \u2014 von Neumann \u00b7 QRNG track Syntropy \u03a3 \u2014 1 \u2212 IPR(QRNG) &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/stringtimecrystal.com\/stringtimecrystal\/interface\/\" class=\"more-link\">Read more<span class=\"screen-reader-text\"> &#8220;Interface&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-987","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/pages\/987","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/comments?post=987"}],"version-history":[{"count":5,"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/pages\/987\/revisions"}],"predecessor-version":[{"id":995,"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/pages\/987\/revisions\/995"}],"wp:attachment":[{"href":"https:\/\/stringtimecrystal.com\/stringtimecrystal\/wp-json\/wp\/v2\/media?parent=987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}