clanker / static /index.html
deucebucket's picture
fix: creature no longer screen-shakes at neutral mood (tantrum FSM tuned for the real engine)
58182e8 verified
Raw
History Blame Contribute Delete
20.1 kB
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>clanker · a deterministic emotional creature</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Press+Start+2P&family=VT323&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/styles.css?v=22">
<script src="/static/app.js?v=22" defer></script>
</head>
<body>
<div id="root" style="position:relative;min-height:100vh;width:100%;background:var(--bg,#211710);color:var(--ink,#f4e8d6);font-family:var(--fbody,'JetBrains Mono',monospace);padding:18px;display:flex;flex-direction:column;gap:16px;overflow-x:hidden;">
<!-- ===== HEADER ===== -->
<header style="display:flex;align-items:center;gap:14px;flex-wrap:wrap;">
<div style="display:flex;align-items:center;gap:11px;">
<div style="width:34px;height:34px;border-radius:11px;background:var(--accent,#ffd21e);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(255,200,60,.35);">
<svg width="22" height="22" viewBox="0 0 24 24"><circle cx="12" cy="12" r="11" fill="#26190d"></circle><circle cx="8.5" cy="11" r="1.7" fill="#ffd21e"></circle><circle cx="15.5" cy="11" r="1.7" fill="#ffd21e"></circle><path d="M7.5 15 Q12 19 16.5 15" stroke="#ffd21e" stroke-width="1.8" fill="none" stroke-linecap="round"></path></svg>
</div>
<div>
<div id="creatureName" style="font-family:var(--fhead,'Fredoka',sans-serif);font-weight:700;font-size:20px;letter-spacing:.3px;line-height:1;">Huggy</div>
<div style="font-size:11px;color:var(--dim,#a9967c);margin-top:3px;letter-spacing:.4px;">a deterministic emotional creature · powered by VADUGWI</div>
</div>
</div>
<div data-tip="VADUGWI: 7 deterministic dimensions (0&ndash;255, 128 neutral). 4,563-word vocabulary, 66 chess-like structural patterns, proximity fields (0.9&times; decay/word), phase system &amp; Force Flow. Fully explainable. The live Space calls the real clanker engine + clanker-soul on the backend." style="cursor:help;font-size:10.5px;color:var(--dim,#a9967c);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:999px;padding:5px 11px;display:flex;align-items:center;gap:6px;">
<span style="width:7px;height:7px;border-radius:50%;background:#5fd08a;box-shadow:0 0 8px #5fd08a;"></span>7D engine · how it works
</div>
<div style="flex:1;"></div>
<button id="soundBtn" title="toggle babble sound" style="cursor:pointer;border:1px solid var(--line,rgba(255,210,140,.16));background:var(--panel2,#1a120b);color:var(--ink,#f4e8d6);border-radius:11px;width:38px;height:34px;font-size:15px;">&#128266;</button>
</header>
<!-- ===== GRID ===== -->
<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:stretch;flex:1;">
<!-- LEFT: VADUGWI live -->
<section style="flex:1 1 300px;max-width:360px;min-width:268px;background:var(--panel,#2c2016);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:var(--rad,18px);padding:16px;display:flex;flex-direction:column;gap:13px;">
<div style="display:flex;align-items:baseline;justify-content:space-between;">
<div style="font-family:var(--fhead,'Fredoka',sans-serif);font-weight:700;font-size:14px;letter-spacing:1.5px;">VADUGWI</div>
<div style="font-size:9.5px;color:var(--accent,#ffd21e);letter-spacing:2px;display:flex;align-items:center;gap:5px;"><span style="width:6px;height:6px;border-radius:50%;background:var(--accent,#ffd21e);animation:floaty 1.6s ease-in-out infinite;"></span>LIVE</div>
</div>
<div style="font-size:11px;color:var(--dim,#a9967c);line-height:1.5;">this message read as<br><span id="readPhrase" style="color:var(--ink,#f4e8d6);font-size:13px;font-weight:600;">waiting&hellip;</span></div>
<!-- meters (JS fills 7 rows) -->
<div id="meters"></div>
<!-- needs -->
<div style="border-top:1px solid var(--line,rgba(255,210,140,.16));padding-top:11px;display:flex;flex-direction:column;gap:8px;">
<div data-tip="Tamagotchi-style needs decay over time. Feed, water, play with and pet it to keep them up &mdash; neglect pulls its mood down." style="cursor:help;font-size:11px;letter-spacing:1.5px;color:var(--dim,#a9967c);font-weight:600;">NEEDS</div>
<div id="needs"></div>
</div>
<!-- soul / mood distance -->
<div data-tip="Three timescales (clanker-soul): the Conversational score &rarr; Mood (minutes&ndash;hours, blends &amp; cushions) &rarr; Soul (the persistent baseline mood drifts back toward). Heavy events during a wound can breach straight into Soul." style="cursor:help;border-top:1px solid var(--line,rgba(255,210,140,.16));padding-top:11px;display:flex;align-items:center;justify-content:space-between;font-size:11px;color:var(--dim,#a9967c);">
<span>mood &#10230; soul drift</span>
<span id="soulDistance" style="color:var(--ink,#f4e8d6);font-weight:600;">&Delta; 0</span>
</div>
</section>
<!-- CENTER: room -->
<section style="flex:3 1 460px;min-width:320px;display:flex;flex-direction:column;gap:13px;">
<div id="stage" style="position:relative;width:100%;aspect-ratio:4/3;border-radius:var(--rad,18px);overflow:hidden;border:1px solid var(--line,rgba(255,210,140,.16));background:var(--wall2,#e9bd72);box-shadow:inset 0 0 80px rgba(40,20,0,.25);touch-action:none;user-select:none;">
<!-- room scene -->
<svg viewBox="0 0 400 300" preserveAspectRatio="xMidYMid slice" style="position:absolute;inset:0;width:100%;height:100%;">
<defs>
<linearGradient id="wallg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--wall1,#ffe8b0)"></stop><stop offset="100%" stop-color="var(--wall2,#e9bd72)"></stop>
</linearGradient>
<linearGradient id="skyg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--sky1,#bfe3ff)"></stop><stop offset="100%" stop-color="var(--sky2,#ffd98a)"></stop>
</linearGradient>
<radialGradient id="sung" cx="50%" cy="50%" r="50%"><stop offset="0%" stop-color="#fff4c2"></stop><stop offset="100%" stop-color="#ffcf5e"></stop></radialGradient>
<radialGradient id="lightg" cx="50%" cy="14%" r="62%"><stop offset="0%" stop-color="rgba(255,244,200,.34)"></stop><stop offset="100%" stop-color="rgba(255,244,200,0)"></stop></radialGradient>
<radialGradient id="vigg" cx="50%" cy="52%" r="72%"><stop offset="52%" stop-color="rgba(40,20,0,0)"></stop><stop offset="100%" stop-color="rgba(30,15,0,.34)"></stop></radialGradient>
</defs>
<rect x="0" y="0" width="400" height="196" fill="url(#wallg)"></rect>
<rect x="0" y="196" width="400" height="104" fill="var(--floor,#c9a06a)"></rect>
<rect x="0" y="193" width="400" height="4" fill="rgba(90,55,18,.32)"></rect>
<!-- window, centered + aligned -->
<g>
<rect x="150" y="26" width="100" height="84" rx="7" fill="#fff" opacity=".5"></rect>
<rect x="155" y="31" width="90" height="74" rx="4" fill="url(#skyg)"></rect>
<circle cx="225" cy="52" r="13" fill="url(#sung)"></circle>
<path d="M170 96 q12 -16 24 -4 q10 -14 24 -2 l0 12 -48 0 z" fill="#fff" opacity=".5"></path>
<rect x="197" y="31" width="6" height="74" fill="#fff" opacity=".55"></rect>
<rect x="155" y="64" width="90" height="6" fill="#fff" opacity=".55"></rect>
<rect x="146" y="108" width="108" height="7" rx="3" fill="#caa46a"></rect>
</g>
<!-- shelf right -->
<g>
<rect x="300" y="60" width="86" height="7" rx="2" fill="#a9763f"></rect>
<rect x="310" y="40" width="9" height="20" rx="2" fill="#cf6a5a"></rect>
<rect x="321" y="36" width="9" height="24" rx="2" fill="#6aa6cf"></rect>
<rect x="332" y="43" width="9" height="17" rx="2" fill="#7dbf72"></rect>
<circle cx="360" cy="52" r="8" fill="#d8975a"></circle><rect x="356" y="50" width="8" height="10" fill="#b97e44"></rect>
</g>
<!-- plant lower-left -->
<g>
<path d="M30 196 q-16 -34 -6 -56 q8 12 6 30 q10 -22 24 -28 q-6 18 -18 34 q14 -10 26 -8 q-12 14 -28 24z" fill="#5a9a52"></path>
<path d="M30 196 l-12 0 6 -26 12 0 z" fill="#bf6a4a"></path>
</g>
<!-- rug -->
<ellipse cx="200" cy="252" rx="118" ry="26" fill="#d9544e" opacity=".22"></ellipse>
<ellipse cx="200" cy="252" rx="92" ry="19" fill="#e8a23a" opacity=".22"></ellipse>
<rect x="0" y="0" width="400" height="300" fill="url(#lightg)" pointer-events="none"></rect>
<rect x="0" y="0" width="400" height="300" fill="url(#vigg)" pointer-events="none"></rect>
</svg>
<!-- aura -->
<div id="aura" style="position:absolute;left:50%;top:54%;width:42%;height:42%;border-radius:50%;background:radial-gradient(circle,hsl(48 70% 60% / .55),transparent 68%);transform:translate(-50%,-50%);mix-blend-mode:screen;pointer-events:none;animation:auraPulse 3.4s ease-in-out infinite;filter:blur(4px);"></div>
<!-- creature -->
<svg id="creature" viewBox="0 0 200 240" style="position:absolute;left:50%;bottom:13%;width:30%;transform:translateX(-50%);overflow:visible;cursor:pointer;z-index:4;">
<ellipse id="shadow" cx="100" cy="224" rx="62" ry="11" fill="rgba(0,0,0,.28)"></ellipse>
<g id="blob">
<circle id="body" cx="100" cy="120" r="78" fill="var(--accent,#ffd21e)" stroke="var(--cstroke-col,transparent)" stroke-width="var(--cstroke,0)"></circle>
<circle id="emoteGlow" cx="100" cy="122" r="70" fill="hsl(48 80% 55%)" opacity="0" pointer-events="none"></circle>
<ellipse cx="78" cy="84" rx="18" ry="11" fill="#fff" opacity=".26" transform="rotate(-16 78 84)"></ellipse>
<ellipse id="cheekL" cx="62" cy="138" rx="14" ry="9" fill="#ff9bb0" opacity=".35"></ellipse>
<ellipse id="cheekR" cx="138" cy="138" rx="14" ry="9" fill="#ff9bb0" opacity=".35"></ellipse>
<g id="armL"><path d="M52 150 Q34 152 24 138" stroke="var(--accent,#ffd21e)" stroke-width="15" stroke-linecap="round" fill="none"></path><ellipse cx="22" cy="136" rx="15" ry="13" fill="var(--accent,#ffd21e)"></ellipse></g>
<g id="armR"><path d="M148 150 Q166 152 176 138" stroke="var(--accent,#ffd21e)" stroke-width="15" stroke-linecap="round" fill="none"></path><ellipse cx="178" cy="136" rx="15" ry="13" fill="var(--accent,#ffd21e)"></ellipse></g>
<line id="browL" x1="62" y1="96" x2="86" y2="96" stroke="#2a1a0c" stroke-width="5" stroke-linecap="round"></line>
<line id="browR" x1="114" y1="96" x2="138" y2="96" stroke="#2a1a0c" stroke-width="5" stroke-linecap="round"></line>
<ellipse id="eyeL" cx="74" cy="112" rx="9" ry="11" fill="#2a1a0c"></ellipse>
<ellipse id="eyeR" cx="126" cy="112" rx="9" ry="11" fill="#2a1a0c"></ellipse>
<circle id="glintL" cx="77" cy="108" r="3" fill="#fff"></circle>
<circle id="glintR" cx="129" cy="108" r="3" fill="#fff"></circle>
<path id="mouth" d="M82 150 Q100 166 118 150" stroke="#2a1a0c" stroke-width="5" fill="none" stroke-linecap="round"></path>
<path id="tearL" d="M70 124 q-4 6 0 9 q4 -3 0 -9Z" fill="#7ec8f5" opacity="0"></path>
<path id="tearR" d="M130 124 q-4 6 0 9 q4 -3 0 -9Z" fill="#7ec8f5" opacity="0"></path>
</g>
<circle id="steamL" cx="44" cy="64" r="6" fill="#cfd8e0" opacity="0"></circle>
<circle id="steamR" cx="156" cy="64" r="6" fill="#cfd8e0" opacity="0"></circle>
<g id="hearts" opacity="0"><path d="M100 44 c-5 -8 -16 -2 -10 6 l10 10 10 -10 c6 -8 -5 -14 -10 -6Z" fill="#ff7aa8"></path></g>
<text id="zzz" x="150" y="60" font-size="26" fill="#cfe0ff" opacity="0" font-family="Fredoka,sans-serif">z</text>
</svg>
<!-- items (toys — draggable; JS fills) -->
<div id="items"></div>
<!-- feeding stations (fixed — click to fill) -->
<div id="foodBowl" data-tip="Click to fill the food bowl. Huggy walks over and eats on his own when there's food and he's hungry." style="position:absolute;left:14%;bottom:5%;width:10%;cursor:pointer;z-index:3;filter:drop-shadow(0 4px 5px rgba(0,0,0,.3));">
<div id="foodFill" style="width:100%;"></div>
</div>
<div id="waterBowl" data-tip="Click to fill the water bowl. Huggy drinks automatically when thirsty." style="position:absolute;left:25%;bottom:4%;width:10%;cursor:pointer;z-index:3;filter:drop-shadow(0 4px 5px rgba(0,0,0,.3));">
<div id="waterFill" style="width:100%;"></div>
</div>
<!-- mood chip -->
<div style="position:absolute;top:12px;right:12px;background:var(--panel,#2c2016);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:999px;padding:7px 14px;font-size:13px;font-weight:600;font-family:var(--fhead,'Fredoka',sans-serif);display:flex;align-items:center;gap:8px;z-index:6;">
<span id="moodDot" style="width:9px;height:9px;border-radius:50%;background:hsl(48 70% 55%);box-shadow:0 0 9px hsl(48 70% 55%);"></span><span id="moodWord">calm</span>
</div>
<!-- remembers-you hint (welcome back / known device) -->
<div id="remembersHint" style="display:none;position:absolute;top:12px;left:12px;background:var(--panel,#2c2016);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:999px;padding:6px 12px;font-size:11px;font-weight:600;font-family:var(--fhead,'Fredoka',sans-serif);color:var(--ink,#f4e8d6);z-index:6;">it remembers you &#129293;</div>
<!-- emoticon bubble -->
<div id="bubble" style="position:absolute;left:50%;top:18%;transform:translate(-50%,-50%);background:#fff;color:#2a1a0c;border-radius:14px;padding:7px 13px;font-family:var(--fbody,monospace);font-size:17px;font-weight:600;opacity:0;pointer-events:none;z-index:7;box-shadow:0 6px 18px rgba(0,0,0,.25);">&middot;_&middot;</div>
<!-- simlish -->
<div id="simlish" style="position:absolute;left:50%;top:30%;transform:translate(-50%,-50%);color:#fff;font-family:var(--fhead,'Fredoka',sans-serif);font-size:15px;font-weight:600;opacity:0;pointer-events:none;z-index:7;text-shadow:0 2px 6px rgba(20,12,4,.8);white-space:nowrap;"></div>
<!-- hint -->
<div style="position:absolute;bottom:10px;left:50%;transform:translateX(-50%);background:rgba(26,18,11,.66);backdrop-filter:blur(3px);border-radius:999px;padding:6px 14px;font-size:10.5px;color:#f4e8d6;z-index:6;white-space:nowrap;">drag a toy onto <span class="cn">Huggy</span> &mdash; he plays with it, then sets it down &middot; click the bowls to fill them &middot; tap <span class="cn">Huggy</span> to pet</div>
</div>
<!-- dock -->
<div style="display:flex;flex-direction:column;gap:9px;">
<div style="display:flex;gap:9px;align-items:center;background:var(--panel,#2c2016);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:14px;padding:7px 7px 7px 15px;">
<input id="msg" placeholder="say something to Huggy&hellip;" autocomplete="off" style="flex:1;background:none;border:none;outline:none;color:var(--ink,#f4e8d6);font-family:var(--fbody,monospace);font-size:14px;">
<button id="send" style="cursor:pointer;border:none;background:var(--accent,#ffd21e);color:#1a120b;border-radius:10px;padding:9px 18px;font-family:var(--fhead,'Fredoka',sans-serif);font-weight:700;font-size:13px;">send</button>
</div>
</div>
</section>
<!-- RIGHT: detection + diary -->
<section style="flex:1 1 300px;max-width:368px;min-width:268px;display:flex;flex-direction:column;gap:16px;">
<div style="background:var(--panel,#2c2016);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:var(--rad,18px);padding:16px;display:flex;flex-direction:column;gap:12px;">
<div style="font-family:var(--fhead,'Fredoka',sans-serif);font-weight:700;font-size:14px;letter-spacing:.5px;">what it detected</div>
<div style="display:flex;flex-direction:column;gap:6px;">
<div style="font-size:10px;letter-spacing:1.5px;color:var(--dim,#a9967c);">WORDS · roles</div>
<div id="traceWords" style="display:flex;flex-wrap:wrap;gap:5px;min-height:24px;">
<span style="font-size:11px;color:var(--dim,#a9967c);">talk to it and the structural read shows up here.</span>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:6px;">
<div style="font-size:10px;letter-spacing:1.5px;color:var(--dim,#a9967c);">STRUCTURES · <span id="structCount">0</span> of 66 patterns</div>
<div id="traceStructs" style="display:flex;flex-wrap:wrap;gap:5px;min-height:18px;">
<span style="font-size:11px;color:var(--dim,#a9967c);">&mdash; none in this message</span>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:6px;">
<div style="font-size:10px;letter-spacing:1.5px;color:var(--dim,#a9967c);">TOP CONTRIBUTORS</div>
<div id="traceContribs"></div>
</div>
<!-- why -->
<div data-tip="Every output is explainable &mdash; this is the single biggest reason the read landed where it did." style="cursor:help;background:var(--panel2,#1a120b);border-radius:10px;padding:9px 11px;font-size:11px;line-height:1.5;color:var(--ink,#f4e8d6);">
<span style="color:var(--accent,#ffd21e);font-weight:700;">why:</span> <span id="whyText">say something, give it a toy, or pet it &mdash; every read is explainable.</span>
</div>
<!-- crisis gradient -->
<div id="crisisWrap" data-tip="Continuous 0&ndash;1 concern gradient informed by the CARE / TCI framework. Tuned for 0% false-positive on safe text, dark humour and metaphor. A screening signal, not a diagnosis." style="cursor:help;display:flex;flex-direction:column;gap:5px;">
<div style="display:flex;justify-content:space-between;font-size:10px;letter-spacing:1.5px;color:var(--dim,#a9967c);"><span>CRISIS GRADIENT</span><span id="crisisLabel" style="color:#5fd08a;font-weight:600;">calm</span></div>
<div style="height:8px;border-radius:5px;background:var(--panel2,#1a120b);overflow:hidden;">
<div id="crisisBar" style="height:100%;width:0%;background:#5fd08a;border-radius:5px;transition:width .5s ease,background .5s ease;"></div>
</div>
</div>
</div>
<!-- diary -->
<div style="background:var(--panel,#2c2016);border:1px solid var(--line,rgba(255,210,140,.16));border-radius:var(--rad,18px);padding:16px;display:flex;flex-direction:column;gap:10px;flex:1;min-height:150px;">
<div style="font-family:var(--fhead,'Fredoka',sans-serif);font-weight:700;font-size:14px;">diary</div>
<div id="diary" style="display:flex;flex-direction:column;gap:8px;overflow-y:auto;max-height:230px;">
<span style="font-size:11px;color:var(--dim,#a9967c);">moments you share will be remembered here.</span>
</div>
</div>
</section>
</div>
<div style="font-size:10px;color:var(--dim,#a9967c);text-align:center;opacity:.8;">the production Space calls the real clanker engine + clanker-soul on the backend · every read is deterministic and explainable</div>
<!-- floating tooltip -->
<div id="tooltip" style="position:fixed;left:0px;top:0px;max-width:248px;background:#120c06;color:#f4e8d6;border:1px solid rgba(255,210,140,.28);border-radius:10px;padding:9px 12px;font-size:11px;line-height:1.5;font-family:var(--fbody,monospace);pointer-events:none;opacity:0;transform:translateY(-50%);transition:opacity .12s;z-index:90;box-shadow:0 10px 30px rgba(0,0,0,.45);"></div>
</div>
</body></html>