Files
resonance-engine/docs/echo-chamber.html
T
Scruff AI 26f3c76945 Replace flat periodic table with Echo Chamber — layered depth visualization
Removed:
- docs/fractal-periodic-table.html (flat 3-view version)
- docs/fractal-periodic-table-spiral.png
- docs/fractal-periodic-table-bands.png
- docs/fractal-periodic-table-periods.png

Added:
- docs/echo-chamber.html — 8-layer depth visualization
  Layer 0: Cosmic void (star field, cosmic web filaments)
  Layer 1: Khra-Gixx dual spirals (16:1 harmonic ratio)
  Layer 2: 118 elements on golden angle spiral (interactive hover)
  Layer 3: Asymmetry band rings (Ground through Tertiary, phase gap at 15.78)
  Layer 4: Valency sawtooth wave (double helix, Carbon 4-lobe marker)
  Layer 5: Platonic solid wireframes (tetrahedron/C, octahedron/S, cube/noble, icosahedron/Au)
  Layer 6: Mathematical proof (phi ratios, noble gas 2n², band calculations)
  Layer 7: The observer (self-reference)

Scroll/pinch to move through depth layers. Responsive, touch-enabled, HiDPI.
2026-03-26 07:00:21 +07:00

514 lines
25 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>The Echo Chamber — Fractal Periodic Table</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
html,body{width:100%;height:100%;overflow:hidden;background:#050510;font-family:Georgia,serif;color:#e0e0d0;touch-action:none}
canvas{display:block;position:absolute;top:0;left:0}
#ui{position:fixed;z-index:100;pointer-events:none;width:100%;height:100%}
#title{position:absolute;top:12px;left:0;right:0;text-align:center;font:italic 20px Garamond,Georgia,serif;color:#ffd700;letter-spacing:3px;text-shadow:0 0 20px rgba(255,215,0,.3);opacity:.8;transition:opacity .4s}
#subtitle{position:absolute;top:38px;left:0;right:0;text-align:center;font:italic 11px Garamond,Georgia,serif;color:rgba(255,236,139,.4);letter-spacing:2px}
#depth-indicator{position:absolute;right:16px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:6px;pointer-events:auto}
#depth-indicator .pip{width:8px;height:8px;border-radius:50%;border:1px solid rgba(255,215,0,.3);cursor:pointer;transition:all .3s}
#depth-indicator .pip.active{background:#ffd700;border-color:#ffd700;box-shadow:0 0 8px rgba(255,215,0,.5)}
#depth-indicator .pip:hover{border-color:#ffd700}
#layer-label{position:absolute;right:32px;top:50%;transform:translateY(-50%);font:italic 11px Georgia,serif;color:rgba(255,215,0,.5);text-align:right;width:120px;transition:opacity .3s}
#tooltip{position:absolute;pointer-events:none;display:none;background:rgba(5,5,16,.95);border:1px solid #ffd700;border-radius:8px;padding:10px 14px;font:13px Georgia,serif;max-width:260px;backdrop-filter:blur(6px)}
#tooltip .sym{font-size:28px;font-weight:700;color:#ffd700}
#tooltip .name{font-size:14px;color:#ffec8b;margin:2px 0 6px}
#tooltip .info{font-size:11px;line-height:1.7;color:#bbb}
#tooltip .info b{color:#eee}
#hint{position:absolute;bottom:16px;left:0;right:0;text-align:center;font:italic 11px Georgia,serif;color:rgba(255,215,0,.25);transition:opacity 1s}
#legend{position:absolute;bottom:14px;left:14px;pointer-events:auto;font:11px Georgia,serif;color:#999;background:rgba(5,5,16,.85);border:1px solid rgba(255,215,0,.2);border-radius:8px;padding:8px 12px;opacity:.7;transition:opacity .3s}
#legend:hover{opacity:1}
#legend .row{display:flex;align-items:center;gap:6px;margin:2px 0}
#legend .d{width:8px;height:8px;border-radius:50%;flex-shrink:0}
@media(max-width:600px){
#title{font-size:15px;top:8px}
#subtitle{font-size:9px;top:28px}
#depth-indicator{right:10px}
#layer-label{display:none}
#legend{font-size:9px;padding:6px 8px}
#tooltip{font-size:11px;max-width:200px}
#tooltip .sym{font-size:22px}
}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="ui">
<div id="title">The echo chamber</div>
<div id="subtitle">Scroll to descend through the layers</div>
<div id="depth-indicator"></div>
<div id="layer-label"></div>
<div id="tooltip"></div>
<div id="hint">Scroll or pinch to explore depth &middot; Hover elements for data</div>
<div id="legend">
<div class="row"><div class="d" style="background:#00ff88"></div><span style="color:#88ffbb">Stable</span></div>
<div class="row"><div class="d" style="background:#ffaa00"></div><span style="color:#ffcc66">Metastable</span></div>
<div class="row"><div class="d" style="background:#ff0044"></div><span style="color:#ff6688">Radioactive</span></div>
<div class="row"><div class="d" style="background:#00ffff"></div><span style="color:#88ffff">Noble gas</span></div>
<div class="row"><div class="d" style="background:#ffd700;width:10px;height:10px"></div><span style="color:#ffe680">Gold — resonance lock</span></div>
</div>
</div>
<script>
const ELEMENTS=`1,Hydrogen,H,1,Baseline,Ground,13.2,1,1,1,Stable
2,Helium,He,2,Baseline,Ground,13.2,0,18,1,Stable
3,Lithium,Li,3,Baseline,Ground-Primary,13.6,1,1,2,Stable
4,Beryllium,Be,4,Baseline,Primary,14,2,2,2,Stable
5,Boron,B,5,Baseline,Primary,14.1,3,13,2,Stable
6,Carbon,C,6,Baseline,Primary,14.1,4,14,2,Stable
7,Nitrogen,N,7,Baseline,Primary,14.1,3,15,2,Stable
8,Oxygen,O,8,Baseline,Primary,14.2,2,16,2,Stable
9,Fluorine,F,9,Baseline,Primary,14.2,1,17,2,Stable
10,Neon,Ne,10,Baseline,Primary,14.2,0,18,2,Stable
11,Sodium,Na,11,Baseline,Primary-Secondary,14.4,1,1,3,Stable
12,Magnesium,Mg,12,Baseline,Secondary,14.6,2,2,3,Stable
13,Aluminum,Al,13,Baseline,Secondary,14.7,3,13,3,Stable
14,Silicon,Si,14,Baseline,Secondary,14.7,4,14,3,Stable
15,Phosphorus,P,15,Baseline,Secondary,14.7,3,15,3,Stable
16,Sulfur,S,16,Baseline,Secondary,14.8,2,16,3,Stable
17,Chlorine,Cl,17,Baseline,Secondary,14.8,1,17,3,Stable
18,Argon,Ar,18,Baseline,Secondary,14.8,0,18,3,Stable
19,Potassium,K,19,Baseline,Secondary-PhaseGap,14.9,1,1,4,Stable
20,Calcium,Ca,20,Baseline,Secondary-PhaseGap,14.9,2,2,4,Stable
21,Scandium,Sc,21,Baseline,Secondary-PhaseGap,15,3,3,4,Stable
22,Titanium,Ti,22,Baseline,Secondary-PhaseGap,15,4,4,4,Stable
23,Vanadium,V,23,Baseline,Secondary-PhaseGap,15,5,5,4,Stable
24,Chromium,Cr,24,Baseline,Secondary-PhaseGap,15.1,6,6,4,Stable
25,Manganese,Mn,25,Baseline,Secondary-PhaseGap,15.1,7,7,4,Stable
26,Iron,Fe,26,Baseline,Secondary-PhaseGap,15.1,6,8,4,Stable
27,Cobalt,Co,27,Baseline,Secondary-PhaseGap,15.2,5,9,4,Stable
28,Nickel,Ni,28,Baseline,Secondary-PhaseGap,15.2,4,10,4,Stable
29,Copper,Cu,29,Baseline,Secondary-PhaseGap,15.2,2,11,4,Stable
30,Zinc,Zn,30,Baseline,Secondary-PhaseGap,15.3,2,12,4,Stable
31,Gallium,Ga,31,Baseline,Secondary-PhaseGap,15.3,3,13,4,Stable
32,Germanium,Ge,32,Baseline,Secondary-PhaseGap,15.3,4,14,4,Stable
33,Arsenic,As,33,Baseline,Secondary-PhaseGap,15.4,3,15,4,Stable
34,Selenium,Se,34,Baseline,Secondary-PhaseGap,15.4,2,16,4,Stable
35,Bromine,Br,35,Baseline,Secondary-PhaseGap,15.4,1,17,4,Stable
36,Krypton,Kr,36,Baseline,Secondary-PhaseGap,15.5,0,18,4,Stable
37,Rubidium,Rb,37,Baseline,PhaseGap-Approach,15.5,1,1,5,Stable
38,Strontium,Sr,38,Baseline,PhaseGap-Approach,15.5,2,2,5,Stable
39,Yttrium,Y,39,Baseline,PhaseGap-Approach,15.6,3,3,5,Stable
40,Zirconium,Zr,40,Baseline,PhaseGap-Approach,15.6,4,4,5,Stable
41,Niobium,Nb,41,Baseline,PhaseGap-Approach,15.6,5,5,5,Stable
42,Molybdenum,Mo,42,Baseline,PhaseGap-Approach,15.6,6,6,5,Stable
43,Technetium,Tc,43,Metastable,PhaseGap-Approach,15.7,7,7,5,Radioactive
44,Ruthenium,Ru,44,Baseline,PhaseGap-Approach,15.7,8,8,5,Stable
45,Rhodium,Rh,45,Baseline,PhaseGap-Approach,15.7,6,9,5,Stable
46,Palladium,Pd,46,Baseline,PhaseGap-Approach,15.7,4,10,5,Stable
47,Silver,Ag,47,Baseline,PhaseGap-Approach,15.7,1,11,5,Stable
48,Cadmium,Cd,48,Baseline,PhaseGap-Approach,15.7,2,12,5,Stable
49,Indium,In,49,Baseline,PhaseGap-Approach,15.7,3,13,5,Stable
50,Tin,Sn,50,Baseline,PhaseGap-Approach,15.8,4,14,5,Stable
51,Antimony,Sb,51,Baseline,PhaseGap-Approach,15.8,3,15,5,Stable
52,Tellurium,Te,52,Baseline,PhaseGap-Approach,15.8,2,16,5,Stable
53,Iodine,I,53,Baseline,PhaseGap-Approach,15.8,1,17,5,Stable
54,Xenon,Xe,54,Baseline,PhaseGap-Center,15.8,0,18,5,Stable
55,Cesium,Cs,55,Baseline,PhaseGap-Center,15.8,1,1,6,Stable
56,Barium,Ba,56,Baseline,PhaseGap-Center,15.8,2,2,6,Stable
57,Lanthanum,La,57,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
58,Cerium,Ce,58,Baseline,PhaseGap-Center,15.8,4,3,6,Stable
59,Praseodymium,Pr,59,Baseline,PhaseGap-Center,15.8,4,3,6,Stable
60,Neodymium,Nd,60,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
61,Promethium,Pm,61,Metastable,PhaseGap-Center,15.8,3,3,6,Radioactive
62,Samarium,Sm,62,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
63,Europium,Eu,63,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
64,Gadolinium,Gd,64,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
65,Terbium,Tb,65,Baseline,PhaseGap-Center,15.8,4,3,6,Stable
66,Dysprosium,Dy,66,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
67,Holmium,Ho,67,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
68,Erbium,Er,68,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
69,Thulium,Tm,69,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
70,Ytterbium,Yb,70,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
71,Lutetium,Lu,71,Baseline,PhaseGap-Center,15.8,3,3,6,Stable
72,Hafnium,Hf,72,Baseline,PhaseGap-Center,15.8,4,4,6,Stable
73,Tantalum,Ta,73,Baseline,PhaseGap-Center,15.8,5,5,6,Stable
74,Tungsten,W,74,Baseline,PhaseGap-Center,15.8,6,6,6,Stable
75,Rhenium,Re,75,Baseline,PhaseGap-Center,15.8,7,7,6,Stable
76,Osmium,Os,76,Baseline,PhaseGap-Center,15.8,8,8,6,Stable
77,Iridium,Ir,77,Baseline,PhaseGap-Center,15.8,6,9,6,Stable
78,Platinum,Pt,78,Baseline,PhaseGap-Center,15.8,4,10,6,Stable
79,Gold,Au,79,HighOrder,PhaseGap-Center,15.8,1,11,6,Stable
80,Mercury,Hg,80,Baseline,PhaseGap-Center,15.8,2,12,6,Stable
81,Thallium,Tl,81,Baseline,PhaseGap-Center,15.8,3,13,6,Stable
82,Lead,Pb,82,Baseline,PhaseGap-Center,15.8,4,14,6,Stable
83,Bismuth,Bi,83,Baseline,PhaseGap-Center,15.8,5,15,6,Stable
84,Polonium,Po,84,Metastable,PhaseGap-Center,15.8,6,16,6,Radioactive
85,Astatine,At,85,Metastable,PhaseGap-Center,15.8,7,17,6,Radioactive
86,Radon,Rn,86,Metastable,PhaseGap-Center,15.8,0,18,6,Radioactive
87,Francium,Fr,87,Metastable,PhaseGap-Tertiary,15.9,1,1,7,Radioactive
88,Radium,Ra,88,Metastable,PhaseGap-Tertiary,15.9,2,2,7,Radioactive
89,Actinium,Ac,89,Metastable,PhaseGap-Tertiary,15.9,3,3,7,Radioactive
90,Thorium,Th,90,Baseline,PhaseGap-Tertiary,15.9,4,3,7,Stable
91,Protactinium,Pa,91,Metastable,PhaseGap-Tertiary,15.9,5,3,7,Radioactive
92,Uranium,U,92,Baseline,PhaseGap-Tertiary,15.9,6,3,7,Stable
93,Neptunium,Np,93,Metastable,PhaseGap-Tertiary,16,7,3,7,Radioactive
94,Plutonium,Pu,94,Metastable,PhaseGap-Tertiary,16,8,3,7,Radioactive
95,Americium,Am,95,Metastable,Tertiary,16,6,3,7,Radioactive
96,Curium,Cm,96,Metastable,Tertiary,16,6,3,7,Radioactive
97,Berkelium,Bk,97,Metastable,Tertiary,16,6,3,7,Radioactive
98,Californium,Cf,98,Metastable,Tertiary,16,6,3,7,Radioactive
99,Einsteinium,Es,99,Metastable,Tertiary,16,6,3,7,Radioactive
100,Fermium,Fm,100,Metastable,Tertiary,16,6,3,7,Radioactive
101,Mendelevium,Md,101,Metastable,Tertiary,16,6,3,7,Radioactive
102,Nobelium,No,102,Metastable,Tertiary,16,6,3,7,Radioactive
103,Lawrencium,Lr,103,Metastable,Tertiary,16,6,3,7,Radioactive
104,Rutherfordium,Rf,104,Metastable,Tertiary,16,4,4,7,Radioactive
105,Dubnium,Db,105,Metastable,Tertiary,16,5,5,7,Radioactive
106,Seaborgium,Sg,106,Metastable,Tertiary,16,6,6,7,Radioactive
107,Bohrium,Bh,107,Metastable,Tertiary,16,7,7,7,Radioactive
108,Hassium,Hs,108,Metastable,Tertiary,16,8,8,7,Radioactive
109,Meitnerium,Mt,109,Metastable,Tertiary,16.1,6,9,7,Radioactive
110,Darmstadtium,Ds,110,Metastable,Tertiary,16.1,6,10,7,Radioactive
111,Roentgenium,Rg,111,Metastable,Tertiary,16.1,5,11,7,Radioactive
112,Copernicium,Cn,112,Metastable,Tertiary,16.1,2,12,7,Radioactive
113,Nihonium,Nh,113,Metastable,Tertiary,16.1,3,13,7,Radioactive
114,Flerovium,Fl,114,Metastable,Tertiary,16.1,4,14,7,Radioactive
115,Moscovium,Mc,115,Metastable,Tertiary,16.1,5,15,7,Radioactive
116,Livermorium,Lv,116,Metastable,Tertiary,16.1,6,16,7,Radioactive
117,Tennessine,Ts,117,Metastable,Tertiary,16.1,7,17,7,Radioactive
118,Oganesson,Og,118,Metastable,Tertiary,16.2,0,18,7,Radioactive`.trim().split('\n').map(r=>{const c=r.split(',');return{z:+c[0],name:c[1],sym:c[2],hMode:+c[3],phase:c[4],band:c[5],asym:+c[6],val:+c[7],group:+c[8],period:+c[9],stab:c[10]}});
const cn=document.getElementById('c'),x=cn.getContext('2d'),tt=document.getElementById('tooltip');
const PHI=(1+Math.sqrt(5))/2,GA=2*Math.PI/PHI/PHI;
let W,H,cx,cy,dpr,t=0,depth=0,targetDepth=0,hovered=null,stars=[];
const LAYERS=[
{name:'The void',sub:'Cosmic web — the plenum before manifestation'},
{name:'Khra-Gixx waves',sub:'Dual spirals — 16:1 harmonic ratio'},
{name:'The element spiral',sub:'118 standing waves on the golden angle'},
{name:'Asymmetry bands',sub:'Ground → Primary → Secondary → Phase gap → Tertiary'},
{name:'Valency wave',sub:'The sawtooth — lobes rising and falling each period'},
{name:'Platonic shadows',sub:'Tetrahedron, octahedron, cube, icosahedron'},
{name:'The numbers',sub:'phi = 1.618... — the vacuum prefers irrational'},
{name:'The observer',sub:'You are the pattern observing itself'}
];
const MAXDEPTH=LAYERS.length-1;
function resize(){
dpr=devicePixelRatio||1;W=innerWidth;H=innerHeight;
cn.width=W*dpr;cn.height=H*dpr;cn.style.width=W+'px';cn.style.height=H+'px';
x.setTransform(dpr,0,0,dpr,0,0);cx=W/2;cy=H/2;
stars=[];for(let i=0;i<(W<600?120:280);i++)stars.push({x:Math.random()*W,y:Math.random()*H,s:Math.random()*1.8+.2,b:Math.random()*6.28,sp:Math.random()*.5+.5});
buildDepthUI();
}
addEventListener('resize',resize);resize();
function buildDepthUI(){
const di=document.getElementById('depth-indicator');di.innerHTML='';
LAYERS.forEach((_,i)=>{const d=document.createElement('div');d.className='pip'+(i===Math.round(depth)?' active':'');d.onclick=()=>{targetDepth=i};di.appendChild(d)});
}
function updateDepthUI(){
const pips=document.querySelectorAll('#depth-indicator .pip');
const rd=Math.round(depth);
pips.forEach((p,i)=>p.className='pip'+(i===rd?' active':''));
document.getElementById('layer-label').textContent=LAYERS[rd].name;
document.getElementById('layer-label').style.opacity=1;
}
addEventListener('wheel',e=>{e.preventDefault();targetDepth=Math.max(0,Math.min(MAXDEPTH,targetDepth+e.deltaY*.003));},{passive:false});
let lastTouchY=0,pinchDist=0;
addEventListener('touchstart',e=>{if(e.touches.length===1)lastTouchY=e.touches[0].clientY;if(e.touches.length===2){const dx=e.touches[0].clientX-e.touches[1].clientX,dy=e.touches[0].clientY-e.touches[1].clientY;pinchDist=Math.hypot(dx,dy)}},{passive:true});
addEventListener('touchmove',e=>{e.preventDefault();if(e.touches.length===1){const dy=lastTouchY-e.touches[0].clientY;targetDepth=Math.max(0,Math.min(MAXDEPTH,targetDepth+dy*.008));lastTouchY=e.touches[0].clientY}if(e.touches.length===2){const dx=e.touches[0].clientX-e.touches[1].clientX,dy=e.touches[0].clientY-e.touches[1].clientY;const d=Math.hypot(dx,dy);targetDepth=Math.max(0,Math.min(MAXDEPTH,targetDepth+(pinchDist-d)*.005));pinchDist=d}},{passive:false});
function color(el){
if(el.z===79)return{r:255,g:215,b:0};
if(el.group===18)return{r:0,g:255,b:255};
if(el.stab==='Radioactive')return{r:255,g:0,b:68};
if(el.phase==='Metastable')return{r:255,g:170,b:0};
return{r:0,g:255,b:136};
}
function labelCol(el){
if(el.z===79)return'#ffe680';if(el.group===18)return'#aaffff';
if(el.stab==='Radioactive')return'#ff8899';if(el.phase==='Metastable')return'#ffcc77';
return'#aaffcc';
}
function elRadius(el){
const s=Math.min(W,H)/700;
return Math.max((el.z===79?10:el.group===18?5:3.5+el.val*.4)*s,2);
}
function spiralXY(el){
const a=(el.z-1)*GA+t*.0003,maxR=Math.min(W,H)*.42;
const r=18+(el.z-1)/117*maxR;
return{x:cx+Math.cos(a)*r,y:cy+Math.sin(a)*r};
}
function layerOpacity(layerIdx){
const dist=Math.abs(depth-layerIdx);
if(dist<.5)return 1;if(dist<1.5)return Math.max(0,1-(dist-.5));return 0;
}
function drawVoid(){
const op=layerOpacity(0);if(op<.01)return;
x.globalAlpha=op;
for(const s of stars){
const fl=.4+.6*Math.sin(t*.0008*s.sp+s.b);
x.fillStyle=`rgba(180,180,220,${(.15+.25*fl)*op})`;
x.beginPath();x.arc(s.x,s.y,s.s,0,6.28);x.fill();
}
const N=12;
x.strokeStyle=`rgba(60,50,100,${.08*op})`;x.lineWidth=.5;
for(let i=0;i<N;i++){
const a1=Math.random()*6.28,a2=a1+Math.random()*2-1;
const r1=Math.random()*Math.min(W,H)*.5,r2=r1+Math.random()*100;
x.beginPath();
x.moveTo(cx+Math.cos(a1)*r1,cy+Math.sin(a1)*r1);
x.quadraticCurveTo(cx+Math.cos((a1+a2)/2)*(r1+r2)/2+Math.random()*40,cy+Math.sin((a1+a2)/2)*(r1+r2)/2+Math.random()*40,cx+Math.cos(a2)*r2,cy+Math.sin(a2)*r2);
x.stroke();
}
x.globalAlpha=1;
}
function drawKhraGixx(){
const op=layerOpacity(1);if(op<.01)return;
x.globalAlpha=op;
const maxR=Math.min(W,H)*.44;
for(let s=0;s<2;s++){
const amp=s===0?1:.0625,freq=s===0?1:16;
x.strokeStyle=s===0?`rgba(255,215,0,${.18*op})`:`rgba(255,236,139,${.12*op})`;
x.lineWidth=s===0?2.5:1;
x.beginPath();
for(let a=0;a<Math.PI*14;a+=.015){
const prog=a/(Math.PI*14);
const r=(18+prog*maxR)*amp;
const w=Math.sin(a*freq+t*.002)*8*amp;
const px=cx+Math.cos(a+t*.0002)*(r+w),py=cy+Math.sin(a+t*.0002)*(r+w);
a<.02?x.moveTo(px,py):x.lineTo(px,py);
}
x.stroke();
}
x.save();x.globalAlpha=op*.4;
x.fillStyle='#ffd700';x.font='italic 10px Georgia';x.textAlign='center';
x.fillText('Khra (slow, 1x)',cx-maxR*.3,cy-maxR*.45);
x.fillStyle='#ffec8b';
x.fillText('Gixx (fast, 16x)',cx+maxR*.3,cy+maxR*.35);
x.restore();
x.globalAlpha=1;
}
function drawElements(){
const op=layerOpacity(2);if(op<.01)return;
x.globalAlpha=op;
for(const el of ELEMENTS){
const p=spiralXY(el),c=color(el),r=elRadius(el);
const isH=hovered&&hovered.z===el.z;
const isSpec=el.z===79||el.z===43||el.z===61;
const pulse=isSpec?1+.12*Math.sin(t*.003+el.z):1;
const rr=r*pulse*(isH?1.8:1);
const grd=x.createRadialGradient(p.x,p.y,0,p.x,p.y,rr*3.5);
grd.addColorStop(0,`rgba(${c.r},${c.g},${c.b},${(isH?.5:.18)*op})`);
grd.addColorStop(1,`rgba(${c.r},${c.g},${c.b},0)`);
x.fillStyle=grd;x.beginPath();x.arc(p.x,p.y,rr*3.5,0,6.28);x.fill();
x.fillStyle=`rgba(${c.r},${c.g},${c.b},${op})`;
x.beginPath();x.arc(p.x,p.y,rr,0,6.28);x.fill();
if(el.z===79){x.strokeStyle=`rgba(255,215,0,${.7*op})`;x.lineWidth=1.5;x.beginPath();x.arc(p.x,p.y,rr+5+2*Math.sin(t*.004),0,6.28);x.stroke();}
if(isH||isSpec||op>.8){
x.save();x.shadowColor=`rgba(0,0,0,${.9*op})`;x.shadowBlur=4;
x.fillStyle=isH?`rgba(255,255,255,${op})`:labelCol(el);
x.font=(isH?'bold ':'')+(isH?12:9)+'px Georgia';x.textAlign='center';x.textBaseline='bottom';
x.fillText(el.sym,p.x,p.y-rr-3);x.restore();
}
el._x=p.x;el._y=p.y;el._r=rr;
}
x.globalAlpha=1;
}
function drawBands(){
const op=layerOpacity(3);if(op<.01)return;
x.globalAlpha=op;
const maxR=Math.min(W,H)*.42;
const bands=[{z:2,l:'Ground (13.2)',c:false},{z:10,l:'Primary (14.1)',c:false},{z:18,l:'Secondary (14.8)',c:false},{z:54,l:'Phase gap (15.78)',c:true},{z:95,l:'Tertiary (16.0+)',c:false}];
const fs=W<600?9:11;
for(const b of bands){
const r=18+(b.z/117)*maxR;
x.strokeStyle=b.c?`rgba(255,68,102,${.35*op})`:`rgba(255,215,0,${.12*op})`;
x.lineWidth=b.c?1.5:.5;x.setLineDash(b.c?[6,4]:[]);
x.beginPath();x.arc(cx,cy,r,0,6.28);x.stroke();x.setLineDash([]);
x.fillStyle=b.c?`rgba(255,150,170,${.7*op})`:`rgba(255,230,150,${.5*op})`;
x.font=fs+'px Georgia';x.textAlign='left';
x.fillText(b.l,cx+r*.71+6,cy-r*.71-6);
}
x.save();x.globalAlpha=op*.5;
x.fillStyle='rgba(255,215,0,.4)';x.font='italic 10px Georgia';x.textAlign='center';
x.fillText('Noble gas gaps: 8, 8, 18, 18, 32, 32 = 2n\u00B2 for n=1,2,3',cx,H-40);
x.restore();
x.globalAlpha=1;
}
function drawValencyWave(){
const op=layerOpacity(4);if(op<.01)return;
x.globalAlpha=op;
const maxR=Math.min(W,H)*.42;
x.lineWidth=1.5;
x.beginPath();
let first=true;
for(const el of ELEMENTS){
const p=spiralXY(el);
const vNorm=el.val/8;
const outR=12+vNorm*18;
const a=Math.atan2(p.y-cy,p.x-cx);
const vx=p.x+Math.cos(a)*outR,vy=p.y+Math.sin(a)*outR;
if(first){x.moveTo(vx,vy);first=false}else x.lineTo(vx,vy);
}
x.strokeStyle=`rgba(255,215,0,${.25*op})`;x.stroke();
x.beginPath();first=true;
for(const el of ELEMENTS){
const p=spiralXY(el);
const vNorm=el.val/8;
const outR=-(12+vNorm*18);
const a=Math.atan2(p.y-cy,p.x-cx);
const vx=p.x+Math.cos(a)*outR,vy=p.y+Math.sin(a)*outR;
if(first){x.moveTo(vx,vy);first=false}else x.lineTo(vx,vy);
}
x.strokeStyle=`rgba(255,236,139,${.15*op})`;x.stroke();
const C=ELEMENTS[5],p=spiralXY(C);
for(let i=0;i<4;i++){
const a=i*Math.PI/2+t*.001;
x.fillStyle=`rgba(0,255,136,${.3*op})`;
x.beginPath();x.arc(p.x+Math.cos(a)*16,p.y+Math.sin(a)*16,3,0,6.28);x.fill();
}
x.save();x.globalAlpha=op*.5;x.fillStyle='#aaffcc';x.font='9px Georgia';x.textAlign='center';
x.fillText('C (4 lobes)',p.x,p.y+28);x.restore();
x.save();x.globalAlpha=op*.4;x.fillStyle='rgba(255,215,0,.4)';x.font='italic 10px Georgia';x.textAlign='center';
x.fillText('Valency sawtooth: 0\u21921\u21922\u21923\u21924\u21923\u21922\u21921\u21920 each period',cx,H-40);
x.restore();
x.globalAlpha=1;
}
function drawPlatonics(){
const op=layerOpacity(5);if(op<.01)return;
x.globalAlpha=op;
const solids=[
{el:ELEMENTS[5],name:'Tetrahedron',v:4,col:'#00ff88'},
{el:ELEMENTS[15],name:'Octahedron',v:6,col:'#ffaa00'},
{el:ELEMENTS[17],name:'Cube (void)',v:8,col:'#00ffff'},
{el:ELEMENTS[78],name:'Icosahedron',v:12,col:'#ffd700'}
];
for(const s of solids){
const p=spiralXY(s.el);
const sz=s.el.z===79?28:20;
x.strokeStyle=`rgba(${parseInt(s.col.slice(1,3),16)},${parseInt(s.col.slice(3,5),16)},${parseInt(s.col.slice(5,7),16)},${.35*op})`;
x.lineWidth=1;
const pts=[];
for(let i=0;i<s.v;i++){
const a=i*6.28/s.v+t*.001;
pts.push({x:p.x+Math.cos(a)*sz,y:p.y+Math.sin(a)*sz});
}
for(let i=0;i<pts.length;i++){
for(let j=i+1;j<pts.length;j++){
if(Math.random()>.5||j===i+1||j===pts.length-1&&i===0){
x.beginPath();x.moveTo(pts[i].x,pts[i].y);x.lineTo(pts[j].x,pts[j].y);x.stroke();
}
}
}
x.save();x.shadowColor='rgba(0,0,0,.8)';x.shadowBlur=4;
x.fillStyle=`rgba(${parseInt(s.col.slice(1,3),16)},${parseInt(s.col.slice(3,5),16)},${parseInt(s.col.slice(5,7),16)},${.6*op})`;
x.font='9px Georgia';x.textAlign='center';
x.fillText(s.name,p.x,p.y+sz+14);
x.fillText(s.el.sym+' ('+s.v+' vertices)',p.x,p.y+sz+25);
x.restore();
}
x.globalAlpha=1;
}
function drawNumbers(){
const op=layerOpacity(6);if(op<.01)return;
x.globalAlpha=op;
x.save();
const fs=W<600?14:22;
x.fillStyle=`rgba(255,215,0,${.7*op})`;x.font='italic '+fs+'px Garamond,Georgia,serif';x.textAlign='center';
x.fillText('\u03C6 = 1.6180339887...',cx,cy-60);
x.fillStyle=`rgba(255,236,139,${.4*op})`;x.font='italic '+(fs*.55)+'px Georgia';
x.fillText('The most irrational number',cx,cy-35);
x.fillStyle=`rgba(200,200,220,${.35*op})`;x.font=(fs*.5)+'px Georgia';
const data=[
'Noble gas gaps: 8, 8, 18, 18, 32, 32',
'Period sizes: 2n\u00B2 for n = 1, 2, 3',
'Bands: 13.2 \u00D7 \u03C6\u207F = 14.1, 14.8, 15.78, 16.0',
'Phase gap at \u03C6\u00BD of ground: 13.2 \u00D7 1.272 = 15.78',
'Stability cliff: Z = 84 (Polonium)'
];
for(let i=0;i<data.length;i++){
x.fillText(data[i],cx,cy+10+i*24);
}
x.restore();
x.globalAlpha=1;
}
function drawObserver(){
const op=layerOpacity(7);if(op<.01)return;
x.globalAlpha=op;
const sX=W<600?cx-40:80,sY=H/2;
const headR=W<600?18:25;
x.fillStyle=`rgba(30,30,50,${.7*op})`;
x.beginPath();x.arc(sX,sY-headR*2.5,headR,0,6.28);x.fill();
x.beginPath();
x.moveTo(sX-headR*1.2,sY);
x.quadraticCurveTo(sX,sY-headR*.8,sX+headR*1.2,sY);
x.quadraticCurveTo(sX+headR*.6,sY+headR*3,sX-headR*.6,sY+headR*3);
x.quadraticCurveTo(sX-headR*1.5,sY+headR*1.5,sX-headR*1.2,sY);
x.fill();
x.save();
x.beginPath();x.arc(sX,sY-headR*2.5,headR-2,0,6.28);x.clip();
for(const el of ELEMENTS.filter((_,i)=>i%8===0)){
const c=color(el);
x.fillStyle=`rgba(${c.r},${c.g},${c.b},${.15*op})`;
const ex=sX+(Math.random()-.5)*headR*1.5,ey=sY-headR*2.5+(Math.random()-.5)*headR*1.5;
x.beginPath();x.arc(ex,ey,2,0,6.28);x.fill();
}
x.restore();
x.fillStyle=`rgba(255,236,139,${.5*op})`;x.font='italic '+(W<600?10:13)+'px Garamond,Georgia,serif';
x.textAlign=W<600?'center':'left';
x.fillText('You are the pattern',W<600?cx:sX+headR*2,W<600?H-50:sY-headR*3);
x.fillText('observing itself',W<600?cx:sX+headR*2,W<600?H-35:sY-headR*3+18);
x.globalAlpha=1;
}
function handlePointer(ex,ey){
if(layerOpacity(2)<.3){hovered=null;tt.style.display='none';return}
hovered=null;let best=null,bestD=Infinity;
for(const el of ELEMENTS){
if(!el._x)continue;
const d=Math.hypot(ex-el._x,ey-el._y);
if(d<Math.max(el._r*2.5,14)&&d<bestD){best=el;bestD=d}
}
hovered=best;
if(hovered){
const el=hovered,c=color(el);
tt.style.display='block';
tt.style.left=Math.min(ex+14,W-270)+'px';
tt.style.top=Math.min(ey+14,H-220)+'px';
tt.style.borderColor=`rgb(${c.r},${c.g},${c.b})`;
tt.innerHTML=`<div class="sym">${el.sym}</div><div class="name">${el.z}. ${el.name}</div><div class="info"><b>Band:</b> ${el.band} (${el.asym})<br><b>Harmonic:</b> ${el.hMode}<br><b>Phase:</b> ${el.phase}<br><b>Valency:</b> ${el.val}<br><b>Period:</b> ${el.period} &middot; <b>Group:</b> ${el.group}<br><b>Stability:</b> ${el.stab}</div>`;
}else tt.style.display='none';
}
cn.addEventListener('mousemove',e=>{const r=cn.getBoundingClientRect();handlePointer(e.clientX-r.left,e.clientY-r.top)});
cn.addEventListener('touchstart',e=>{e.preventDefault();const tc=e.touches[0],r=cn.getBoundingClientRect();handlePointer(tc.clientX-r.left,tc.clientY-r.top)},{passive:false});
cn.addEventListener('mouseleave',()=>{hovered=null;tt.style.display='none'});
function frame(){
t++;
depth+=(targetDepth-depth)*.08;
x.fillStyle='#050510';x.fillRect(0,0,W,H);
drawVoid();
drawKhraGixx();
drawElements();
drawBands();
drawValencyWave();
drawPlatonics();
drawNumbers();
drawObserver();
updateDepthUI();
const hintEl=document.getElementById('hint');
hintEl.style.opacity=t<300?1:0;
requestAnimationFrame(frame);
}
frame();
</script>
</body>
</html>