A Pen by mode-mercury on CodePen.
Created
December 11, 2025 07:00
-
-
Save mode-mercury/982a744610b7f8559d99ce6b08a0fba1 to your computer and use it in GitHub Desktop.
Untitled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <title>Glitch//Initiatives Console</title> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <style> | |
| :root { | |
| --bg: #04060b; | |
| --panel-bg: #11151f; | |
| --panel-border: #3a3f50; | |
| --accent: #ff7b3a; | |
| --accent2: #3affc7; | |
| --accent3: #ffd447; | |
| --danger: #ff3355; | |
| --led-red: #ff4b3a; | |
| --led-green: #37ff8b; | |
| --led-amber: #ffcf3a; | |
| --text-dim: #a3b0d0; | |
| --slot-height: 40px; | |
| --radius: 18px; | |
| --font-main: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", | |
| sans-serif; | |
| --font-mono: "Share Tech Mono", "Space Mono", "Courier New", monospace; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| body { | |
| margin: 0; | |
| min-height: 100vh; | |
| background: radial-gradient(circle at top, #20263a 0%, #02030a 52%, #000 100%); | |
| font-family: var(--font-main); | |
| color: #fff; | |
| display: flex; | |
| align-items: stretch; | |
| justify-content: center; | |
| padding: 10px; | |
| } | |
| .console-shell { | |
| width: 100%; | |
| max-width: 520px; | |
| min-height: 96vh; | |
| background: linear-gradient(145deg, #111821 0%, #05070c 55%, #181b25 100%); | |
| border-radius: 24px; | |
| border: 2px solid #454b63; | |
| box-shadow: | |
| 0 0 0 2px #000 inset, | |
| 0 20px 40px rgba(0, 0, 0, 0.8); | |
| padding: 10px 10px 14px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .console-shell::before { | |
| content: ""; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| background: repeating-linear-gradient( | |
| 135deg, | |
| rgba(255, 255, 255, 0.03), | |
| rgba(255, 255, 255, 0.03) 1px, | |
| transparent 1px, | |
| transparent 4px | |
| ); | |
| mix-blend-mode: soft-light; | |
| opacity: 0.5; | |
| pointer-events: none; | |
| } | |
| .console-head { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 8px; | |
| padding: 4px 8px; | |
| border-radius: 18px; | |
| background: linear-gradient(90deg, #181f2b, #050609, #181f2b); | |
| border: 1px solid #343b4e; | |
| box-shadow: 0 0 8px rgba(0, 0, 0, 0.7); | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .brand-block { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 2px; | |
| } | |
| .brand-title { | |
| font-family: var(--font-mono); | |
| letter-spacing: 0.15em; | |
| font-size: 0.76rem; | |
| text-transform: uppercase; | |
| color: var(--accent2); | |
| text-shadow: | |
| 0 0 6px rgba(58, 255, 199, 0.9), | |
| 0 0 14px rgba(58, 255, 199, 0.6); | |
| } | |
| .brand-sub { | |
| font-size: 0.60rem; | |
| text-transform: uppercase; | |
| color: #8ea0d9; | |
| } | |
| .status-lights { | |
| display: flex; | |
| gap: 4px; | |
| align-items: center; | |
| } | |
| .status-dot { | |
| width: 9px; | |
| height: 9px; | |
| border-radius: 50%; | |
| box-shadow: | |
| 0 0 6px currentColor, | |
| 0 0 12px rgba(0,0,0,0.9) inset; | |
| } | |
| .status-dot.green { | |
| color: #30ff8d; | |
| background: radial-gradient(circle at 30% 10%, #fff, #30ff8d 60%, #08542c 100%); | |
| } | |
| .status-dot.red { | |
| color: #ff3355; | |
| background: radial-gradient(circle at 30% 10%, #fff, #ff3355 60%, #6a001b 100%); | |
| } | |
| .status-dot.amber { | |
| color: #ffcf3a; | |
| background: radial-gradient(circle at 30% 10%, #fff, #ffcf3a 60%, #7f5b00 100%); | |
| } | |
| .status-label { | |
| font-size: 0.6rem; | |
| font-family: var(--font-mono); | |
| color: #d2d7f0; | |
| opacity: 0.8; | |
| } | |
| /* SLOT CLUSTER */ | |
| .slot-cluster { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 5px; | |
| padding: 6px; | |
| border-radius: 18px; | |
| background: radial-gradient(circle at top, #262f3f, #090b11 60%, #05060a 100%); | |
| border: 1px solid #33384b; | |
| box-shadow: | |
| 0 0 0 1px #000 inset, | |
| 0 12px 24px rgba(0, 0, 0, 0.7); | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .slot-row { | |
| display: grid; | |
| grid-template-columns: 82px minmax(0, 1fr) 70px; | |
| gap: 4px; | |
| align-items: stretch; | |
| } | |
| .slot-label { | |
| font-size: 0.6rem; | |
| text-transform: uppercase; | |
| color: #97a0c0; | |
| font-family: var(--font-mono); | |
| letter-spacing: 0.11em; | |
| align-self: center; | |
| } | |
| .slot-window { | |
| position: relative; | |
| height: var(--slot-height); | |
| border-radius: 12px; | |
| padding: 2px 6px; | |
| background: linear-gradient(180deg, #050608 0%, #181b22 36%, #050608 100%); | |
| border: 1px solid #444a5e; | |
| box-shadow: | |
| 0 0 0 1px #000 inset, | |
| 0 8px 12px rgba(0, 0, 0, 0.85); | |
| overflow: hidden; | |
| display: flex; | |
| align-items: center; | |
| } | |
| .led-strip { | |
| font-family: var(--font-mono); | |
| font-size: 1.1rem; | |
| letter-spacing: 0.14em; | |
| text-transform: uppercase; | |
| white-space: nowrap; | |
| width: 100%; | |
| display: flex; | |
| justify-content: center; | |
| color: var(--led-amber); | |
| text-shadow: | |
| 0 0 6px rgba(255, 207, 58, 0.9), | |
| 0 0 16px rgba(255, 207, 58, 0.8); | |
| transform: translateY(0); | |
| transition: transform 0.35s ease-out; | |
| } | |
| .led-strip.green { | |
| color: var(--led-green); | |
| text-shadow: | |
| 0 0 6px rgba(55, 255, 139, 0.9), | |
| 0 0 16px rgba(55, 255, 139, 0.8); | |
| } | |
| .led-strip.red { | |
| color: var(--led-red); | |
| text-shadow: | |
| 0 0 6px rgba(255, 75, 58, 0.9), | |
| 0 0 16px rgba(255, 75, 58, 0.8); | |
| } | |
| .led-char { | |
| display: inline-block; | |
| min-width: 0.6em; | |
| text-align: center; | |
| transition: transform 0.25s ease-out; | |
| } | |
| .led-char.rolling { | |
| animation: charRoll 0.3s linear infinite; | |
| } | |
| @keyframes charRoll { | |
| 0% { transform: translateY(-40%); opacity: 0.35; } | |
| 50% { transform: translateY(25%); opacity: 1; } | |
| 100% { transform: translateY(-40%); opacity: 0.35; } | |
| } | |
| .slot-row .spin-btn { | |
| justify-self: stretch; | |
| height: var(--slot-height); | |
| } | |
| /* Spin buttons */ | |
| .spin-btn, | |
| .spin-all-btn { | |
| border-radius: 999px; | |
| border: 1px solid #535b73; | |
| background: radial-gradient(circle at 30% 0, #444c63, #141824 70%, #05070a 100%); | |
| color: #fefefe; | |
| font-family: var(--font-mono); | |
| font-size: 0.72rem; | |
| text-transform: uppercase; | |
| letter-spacing: 0.14em; | |
| padding: 6px 10px; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 4px; | |
| cursor: pointer; | |
| position: relative; | |
| overflow: hidden; | |
| box-shadow: | |
| 0 2px 0 #000, | |
| 0 0 14px rgba(0,0,0,0.9); | |
| } | |
| .spin-btn::before, | |
| .spin-all-btn::before { | |
| content: ""; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient(120deg, | |
| rgba(255,255,255,0.18), | |
| transparent 40%, | |
| transparent 60%, | |
| rgba(255,255,255,0.1) | |
| ); | |
| mix-blend-mode: soft-light; | |
| opacity: 0; | |
| transition: opacity 0.25s ease-out; | |
| } | |
| .spin-btn:active, | |
| .spin-all-btn:active { | |
| transform: translateY(1px); | |
| box-shadow: | |
| 0 1px 0 #000, | |
| 0 0 10px rgba(0,0,0,0.8); | |
| } | |
| .spin-btn:hover::before, | |
| .spin-all-btn:hover::before { | |
| opacity: 1; | |
| } | |
| .spin-all-row { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| gap: 6px; | |
| margin-top: 4px; | |
| } | |
| .spin-all-btn { | |
| flex: 1; | |
| background: radial-gradient(circle at 30% 0, #ff7b3a, #b0331b 60%, #3b0900 100%); | |
| border-color: #ffb48a; | |
| box-shadow: | |
| 0 0 8px rgba(255,123,58,0.7), | |
| 0 0 20px rgba(255,123,58,0.5), | |
| 0 2px 0 #000; | |
| } | |
| .spin-all-btn span { | |
| font-size: 0.8rem; | |
| } | |
| .tiny-led { | |
| font-family: var(--font-mono); | |
| font-size: 0.56rem; | |
| text-transform: uppercase; | |
| letter-spacing: 0.16em; | |
| color: #8af3cb; | |
| text-shadow: 0 0 6px rgba(145,255,220,0.8); | |
| white-space: nowrap; | |
| } | |
| /* MAIN CONTENT PANEL (scrollable) */ | |
| .content-panel { | |
| flex: 1; | |
| min-height: 0; | |
| margin-top: 4px; | |
| display: grid; | |
| grid-template-rows: auto 1fr auto; | |
| gap: 6px; | |
| } | |
| .gauges-row { | |
| display: flex; | |
| gap: 6px; | |
| } | |
| .gauge { | |
| flex: 1; | |
| background: radial-gradient(circle at 10% 0, #2b3547, #060712 70%); | |
| border-radius: 14px; | |
| border: 1px solid #343b4e; | |
| padding: 6px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| box-shadow: | |
| 0 0 0 1px #000 inset, | |
| 0 10px 16px rgba(0,0,0,0.85); | |
| } | |
| .gauge-label { | |
| font-family: var(--font-mono); | |
| font-size: 0.56rem; | |
| text-transform: uppercase; | |
| color: #a5b3df; | |
| letter-spacing: 0.16em; | |
| } | |
| .gauge-bar { | |
| position: relative; | |
| height: 8px; | |
| border-radius: 999px; | |
| background: #080a11; | |
| overflow: hidden; | |
| } | |
| .gauge-bar-fill { | |
| position: absolute; | |
| inset: 1px; | |
| border-radius: 999px; | |
| background: linear-gradient(90deg, #27ff99, #ffe666, #ff3366); | |
| box-shadow: | |
| 0 0 8px rgba(39,255,153,0.7), | |
| 0 0 16px rgba(255,51,102,0.5); | |
| transform-origin: left center; | |
| transform: scaleX(0.66); | |
| } | |
| .gauge-readout { | |
| font-family: var(--font-mono); | |
| font-size: 0.58rem; | |
| color: #d5ddff; | |
| display: flex; | |
| justify-content: space-between; | |
| } | |
| .idea-window { | |
| position: relative; | |
| border-radius: 18px; | |
| background: radial-gradient(circle at top, #131724, #05060c 65%, #000 100%); | |
| border: 1px solid #383f54; | |
| box-shadow: | |
| 0 0 0 1px #000 inset, | |
| 0 12px 20px rgba(0,0,0,0.9); | |
| padding: 8px 10px; | |
| overflow: hidden; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| } | |
| .idea-header-row { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| gap: 4px; | |
| margin-bottom: 4px; | |
| } | |
| .idea-title { | |
| font-family: var(--font-mono); | |
| font-size: 0.7rem; | |
| text-transform: uppercase; | |
| color: var(--accent2); | |
| letter-spacing: 0.16em; | |
| } | |
| .idea-meta { | |
| font-size: 0.55rem; | |
| color: #9ba7d0; | |
| text-transform: uppercase; | |
| font-family: var(--font-mono); | |
| } | |
| .idea-scroll { | |
| flex: 1; | |
| min-height: 120px; | |
| max-height: 220px; | |
| overflow-y: auto; | |
| padding-right: 4px; | |
| font-size: 0.8rem; | |
| line-height: 1.4; | |
| color: #dbe1ff; | |
| scrollbar-width: thin; | |
| scrollbar-color: #4a566f #050712; | |
| } | |
| .idea-scroll::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .idea-scroll::-webkit-scrollbar-track { | |
| background: #050712; | |
| } | |
| .idea-scroll::-webkit-scrollbar-thumb { | |
| background: #4a566f; | |
| border-radius: 999px; | |
| } | |
| .idea-scroll p { | |
| margin: 0 0 4px; | |
| } | |
| .idea-scroll p:last-child { | |
| margin-bottom: 0; | |
| } | |
| .footer-row { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| gap: 6px; | |
| font-size: 0.6rem; | |
| color: var(--text-dim); | |
| } | |
| .port-row { | |
| display: flex; | |
| gap: 3px; | |
| align-items: center; | |
| } | |
| .port { | |
| width: 9px; | |
| height: 9px; | |
| border-radius: 2px; | |
| background: radial-gradient(circle at 30% 0, #fff, #444 50%, #050608 100%); | |
| box-shadow: | |
| 0 0 2px rgba(0,0,0,0.9), | |
| 0 0 4px rgba(0,0,0,0.8) inset; | |
| position: relative; | |
| } | |
| .port::after { | |
| content: ""; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: 1px; | |
| background: #050608; | |
| } | |
| .port.usb { | |
| background: radial-gradient(circle at 30% 0, #fff, #7fe6ff 55%, #05334a 100%); | |
| } | |
| .port.aux { | |
| background: radial-gradient(circle at 30% 0, #fff, #ff7b3a 55%, #4b1d00 100%); | |
| } | |
| .mini-text { | |
| font-size: 0.55rem; | |
| letter-spacing: 0.14em; | |
| text-transform: uppercase; | |
| font-family: var(--font-mono); | |
| color: #8088aa; | |
| } | |
| @media (max-width: 420px) { | |
| .slot-row { | |
| grid-template-columns: 1fr; | |
| } | |
| .slot-row .spin-btn { | |
| height: 34px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="console-shell"> | |
| <header class="console-head"> | |
| <div class="brand-block"> | |
| <div class="brand-title">GLITCH//INITIATIVES</div> | |
| <div class="brand-sub">culture error vending console</div> | |
| </div> | |
| <div class="status-lights"> | |
| <div class="status-dot.green"></div> | |
| <div class="status-dot.amber"></div> | |
| <div class="status-dot.red"></div> | |
| <span class="status-label">status: semi-stable</span> | |
| </div> | |
| </header> | |
| <!-- Slots --> | |
| <section class="slot-cluster"> | |
| <div class="slot-row"> | |
| <div class="slot-label">FRAMEWORK</div> | |
| <div class="slot-window"> | |
| <div id="frameworkDisplay" class="led-strip amber"></div> | |
| </div> | |
| <button id="spinFramework" class="spin-btn"> | |
| <span>SPIN</span> | |
| </button> | |
| </div> | |
| <div class="slot-row"> | |
| <div class="slot-label">CHANNEL</div> | |
| <div class="slot-window"> | |
| <div id="channelDisplay" class="led-strip green"></div> | |
| </div> | |
| <button id="spinChannel" class="spin-btn"> | |
| <span>SPIN</span> | |
| </button> | |
| </div> | |
| <div class="slot-row"> | |
| <div class="slot-label">PAYLOAD</div> | |
| <div class="slot-window"> | |
| <div id="tacticDisplay" class="led-strip red"></div> | |
| </div> | |
| <button id="spinTactic" class="spin-btn"> | |
| <span>SPIN</span> | |
| </button> | |
| </div> | |
| <div class="spin-all-row"> | |
| <button id="spinAll" class="spin-all-btn"> | |
| <span>RANDOMIZE INITIATIVE</span> | |
| </button> | |
| <div class="tiny-led">slot: armed // audio: on</div> | |
| </div> | |
| </section> | |
| <!-- Main content --> | |
| <section class="content-panel"> | |
| <div class="gauges-row"> | |
| <div class="gauge"> | |
| <div class="gauge-label">SIGNAL DENSITY</div> | |
| <div class="gauge-bar"> | |
| <div id="gaugeSignal" class="gauge-bar-fill"></div> | |
| </div> | |
| <div class="gauge-readout"> | |
| <span>street & screen</span> | |
| <span id="signalValue">66%</span> | |
| </div> | |
| </div> | |
| <div class="gauge"> | |
| <div class="gauge-label">SPECTRAL IMPACT</div> | |
| <div class="gauge-bar"> | |
| <div id="gaugeSpectral" class="gauge-bar-fill"></div> | |
| </div> | |
| <div class="gauge-readout"> | |
| <span>emotional resonance</span> | |
| <span id="spectralValue">74%</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="idea-window"> | |
| <div class="idea-header-row"> | |
| <div class="idea-title" id="ideaTitle">INITIATIVE: waiting for spin…</div> | |
| <div class="idea-meta" id="ideaMeta">framework: — | channel: —</div> | |
| </div> | |
| <div class="idea-scroll" id="ideaScroll"> | |
| <p> | |
| Tap <strong>RANDOMIZE INITIATIVE</strong> to let the console crunch frameworks, | |
| guerrilla channels, sensory hooks, and mystic-hacker stunts into one deployable glitch. | |
| </p> | |
| <p> | |
| Each spin mutates: <em>framework</em>, <em>channel</em>, and <em>payload</em>. | |
| You get a fully-formed culture error prompt you can run IRL or in fiction. | |
| </p> | |
| </div> | |
| </div> | |
| <div class="footer-row"> | |
| <div class="port-row"> | |
| <span class="mini-text">ports:</span> | |
| <div class="port usb" title="NFC / Bluetooth dead-drops"></div> | |
| <div class="port aux" title="pirate audio jack"></div> | |
| <div class="port" title="projection out"></div> | |
| </div> | |
| <div class="mini-text">v0.4 – arrays fused / spin extended / sound added</div> | |
| </div> | |
| </section> | |
| </div> | |
| <script> | |
| const pick = (arr) => arr[Math.floor(Math.random() * arr.length)]; | |
| // ───── arrays you pasted ───── | |
| const frameworks = [ | |
| "Ghostfloor – unnoticed background workers as living billboards", | |
| "Parallax Faith – different truths revealed from different angles", | |
| "Signal Pantry – stocking shared spaces with encoded symbolism", | |
| "Parade of Errors – deliberate ‘mistakes’ as conversation fuel", | |
| "Understory Theatre – scripts that only make sense in hindsight", | |
| "Mirrorfeed – reflecting people’s own posts back as prophecy", | |
| "Latency Liturgy – rituals that only trigger after a delay", | |
| "Breadcrumb Commons – community-built, permanent ARG trails", | |
| "Anamorphic Myth – images that resolve only from one secret spot", | |
| "Backdoor Carnival – playful exploits inside boring systems", | |
| "Mythglitch – corrupted belief / recursive prophecy", | |
| "Damnarchitecture – haunted infrastructure & symbolic space", | |
| "Traumadvertising – hijacked ads & emotional slogans", | |
| "Disinformationist – fake headlines & psychic newsfeeds", | |
| "Childgod – naive prophecy & crayon cults", | |
| "Humormonger – surreal comedy & poetic breakdowns", | |
| "Projectionist – building-size light rituals", | |
| "Spectacult – cult-flavored brand hijacks", | |
| "Medikult – pharmaceutical-grade spiritual products", | |
| "TagTrace – semiotic tagging & trace routes", | |
| "DeadDrop Doctrine – physical media caches as scripture", | |
| "Errorcore Broadcast – glitch music / video as public memo", | |
| "Codex Cipher – codebreaking & encryption as ritual", | |
| "Ambient Occultism – low-signal sacred graffiti", | |
| "Street-Ritual Theater – public spells as performance", | |
| "Subvert-Billboard Grail – ad-hijack scripture", | |
| "Projectionist Haunt – ghost-lit facades & sky-glyphs", | |
| "Network-Mythscape Node – city as distributed ARG altar", | |
| "Sensory Swarm – multi-sense immersion & overwhelm", | |
| "Complex-System Meme Engine – evolving, reactive mythcode", | |
| "Analog Pirate Cult – FM / AM / CB broadcast hauntings", | |
| "NFC Sigil Mesh – tap-to-unlock pocket dimensions", | |
| "Bluetooth Dead-Drop Choir – devices singing in secret", | |
| "USB Fossil Field – safe, art-only data “relic” drops", | |
| "Drone Halo – sky-pixel messages & sound halos", | |
| "Projection Mapping Oracle – responsive light prophecy", | |
| "Kinect Ghost Chamber – motion-reactive ritual space", | |
| "QR Spore Trail – scannable breadcrumb myths", | |
| "Sticker Semiotics – micro-glyph theory in public", | |
| "Sensory Marketing Warp – hacked scent / sound / touch", | |
| "Community Seed – actions that birth local micro-cultures", | |
| "Ambient Guerrilla – unexpected surfaces as billboards", | |
| "Wild Posting – walls as layered palimpsest of posters", | |
| "Experiential Flux – pop-up worlds for bodies to wander", | |
| "Undercover Drift – stealth presence disguised as normality", | |
| "Presence Field – just being there, loudly, strangely", | |
| "Alternative Arcades – turning odd spaces into interaction", | |
| "Ambush Event – hijacking someone else’s spotlight", | |
| "Viral Sporecraft – ideas designed to self-propagate", | |
| "Presume Theater – make the audience assume they opted in", | |
| "Swarm Logic – crowd behaviour as brushstroke", | |
| "Game-Theory Gambit – payoff matrices disguised as art", | |
| "Network Topology – connection graphs as choreography", | |
| "Pattern Formation – emergent visuals & chants", | |
| "Evolutionary Drift – projects that mutate with each run" | |
| ]; | |
| const channels = [ | |
| // Extra channels | |
| "Library return shelves seeded with marked-up paperbacks", | |
| "Thrift-store clothing racks with hidden-stitched messages", | |
| "Café tabletops layered with transparent symbol overlays", | |
| "Taxi and rideshare back seats with subtle story prompts", | |
| "Apartment buzzer panels disguised as character directories", | |
| "Campus notice boards woven into a single slow comic strip", | |
| "Parking meter rows turned into numbered divination path", | |
| "Grocery store price-tag rails spelling out quiet manifestos", | |
| "Rooftop access doors marked as gateways in an unseen map", | |
| "Escalator handrails lined with micro-stickers as ‘pulse line’", | |
| "Subway tunnel murals & platform light-leaks", | |
| "Alleyway sound corridor with motion-triggered whispers", | |
| "Sidewalk stencil paths leading to “nowhere” nodes", | |
| "Manhole-ring projections of rotating sigils", | |
| "Crosswalk button micro-posters and glyph stickers", | |
| "Bus-shelter ad-box with hand-drawn subvert insert", | |
| "Abandoned storefront transformed into ritual window", | |
| "Parking-garage stairwells as echo chambers", | |
| "Public restroom mirror etchings + AR overlays", | |
| "Wild posting wall that slowly forms a larger icon", | |
| "Sticker constellation across a whole neighborhood", | |
| "Window-cling sigils in laundromats and diners", | |
| "Stencil series on bike lanes and skate spots", | |
| "Flyer campaign that looks like a missing person poster for ‘Truth’", | |
| "Zines hidden in free newspaper racks", | |
| "NFC tags hidden on lampposts and benches", | |
| "Bluetooth beacons pinging opt-in phones with audio sigils", | |
| "Safe USB drops labelled ‘LOST FUTURE – AUDIO ONLY’", | |
| "QR codes that resolve to AR overlays on familiar buildings", | |
| "DIY Wi-Fi captive portal delivering poem-payloads", | |
| "Local web server on a Raspberry Pi in a backpack", | |
| "Kinect or depth camera watching a hallway, projecting ghosts", | |
| "Old payphone rewired to trigger sound loops on pickup", | |
| "Pirate FM broadcast covering a few city blocks", | |
| "Low-power AM station hidden in a thrift-store radio", | |
| "Temporary rooftop ‘radio altar’ with looped sermons", | |
| "Pop-up hotspot named like a government project with portal page", | |
| "Bluetooth speaker hidden in a planter broadcasting soft chants", | |
| "Night-bus projection loop on passing architecture", | |
| "Projection mapping on statues or trees in a park", | |
| "DIY LED strip around windows pulsing in morse code", | |
| "Drone halo spelling glitch-words with LED panels", | |
| "Laser pointer constellation drawing temporary glyphs on clouds", | |
| "Open-mic night secretly seeded with coordinated ‘visions’", | |
| "Buskers using the same riff as a memetic motif across town", | |
| "Flash-mob style freeze ritual in a shopping mall", | |
| "Silent disco in a parking lot broadcasting pirate radio", | |
| "Guerrilla ‘press conference’ at a random fountain", | |
| "Fake ribbon-cutting ceremony for an invisible monument", | |
| "Community fridge or free-store turned myth node", | |
| "Skatepark ritual line with chalk sigils & music loop", | |
| "Pop-up listening station at a library or bookshop", | |
| "Mutual-aid table disguised as a product launch", | |
| "Night-time picnic in an empty corporate plaza" | |
| ]; | |
| const payloads = [ | |
| "memetic zine-drop with QR portals", | |
| "looped audio confession hiding in the noise floor", | |
| "shortwave-style emergency poem broadcast", | |
| "projection-mapped myth chapter onto brick", | |
| "crayon-level manifesto translated into glitch-type", | |
| "holographic-look sticker set that tessellates a sigil", | |
| "NFC-unlocked mixtape of found-sound & machine hymnals", | |
| "Bluetooth-triggered notification that links to an AR scene", | |
| "LED strip choreography synced to field recordings", | |
| "USB-stored folder of instructions and ambient albums", | |
| "morse-coded LED window routine", | |
| "fold-up micro-ritual booklet with instructions & map", | |
| "interactive codebreaking puzzle pointing to a mutual-aid spot", | |
| "fake PSA video about “illegal empathy”", | |
| "pirate-radio bedtime story for insomnia cities", | |
| "cryptic fundraising game where people ‘unlock’ new art layers", | |
| "choose-your-own-adventure voicemail tree", | |
| "scavenger hunt that ends at a community resource hub", | |
| "street mixtape of local musicians tied to map pins", | |
| "AR graffiti that only appears at certain times of day" | |
| ]; | |
| const sensoryBias = [ | |
| // Extra payloads | |
| "micro-pamphlet of fake product recalls for harmful ideas", | |
| "voicemail monologue that updates weekly with new clues", | |
| "polaroid-style photo set with hand-scratched coordinates", | |
| "looping projector of scrolling ‘patch notes’ for reality", | |
| "pocket-sized foldout city map annotated like a dungeon crawl", | |
| "ambient playlist that secretly encodes a phone number in track order", | |
| "fortune-cookie slips that reference local landmarks and dates", | |
| "chalk timeline across a plaza marking alternate history events", | |
| "deck of shuffled cards, each card a rule for the surrounding space", | |
| "series of receipts printed with one-line prophecies and URLs", | |
| "Sound-heavy: bass drones, whispered vox, glitch chimes", | |
| "Scent-weighted: incense, coffee, rainwater, or citrus ghosts", | |
| "Sight-first: color burns, LED halos, projection scars", | |
| "Touch-centered: textured posters, braille-like dots, rough paper", | |
| "Taste-adjacent: free candy / coffee tied to the ritual copy", | |
| "Multi-sense rush blending sound, light, and temperature shift", | |
| "Silence as weapon: removing expected sound from a space", | |
| "Kinetic bias: things only trigger when people move", | |
| "Ambient hum: very slight tone or vibration in the background" | |
| ]; | |
| const objectives = [ | |
| "seed a micro-community around mutual aid & art", | |
| "question how brands own our senses", | |
| "invite strangers to co-write a myth about the block", | |
| "turn everyday commuters into momentary conspirators for kindness", | |
| "make people feel seen, not sold to", | |
| "raise support for a local cause via weirdness instead of guilt", | |
| "prove that awe can be free and collectively built", | |
| "teach people a simple cipher so they can hide love notes in public", | |
| "map hidden resources (free libraries, fridges, shelters) as lore", | |
| "turn routine routes into exploratory quests", | |
| // Extra objectives | |
| "remind people that ‘normal’ is just heavily funded design", | |
| "give shy creatives a low-stakes way to publish in public", | |
| "turn a forgettable block into a recurring pilgrimage site", | |
| "reframe anxiety as proof that the signal is coming through", | |
| "let strangers feel briefly like co-authors of the city", | |
| "smuggle history lessons inside playful urban legends", | |
| "prototype healthier rituals to replace doomscrolling", | |
| "nudge local businesses toward collaboration via shared myth", | |
| "help kids discover they can alter their own environment safely", | |
| "document a neighborhood’s soul before gentrification edits it" | |
| ]; | |
| const tones = [ | |
| "tone: melancholic but mischievous", | |
| "tone: ecstatic, neon cult-choir", | |
| "tone: quiet, library-of-ghosts", | |
| "tone: comedic dread with soft landings", | |
| "tone: earnest, almost embarrassingly hopeful", | |
| "tone: cosmic pirate radio sermon", | |
| "tone: analog-hacker workshop in disguise", | |
| "tone: dreamy, shoegaze ARG drifting through town", | |
| "tone: documentary prank that never fully explains itself", | |
| "tone: glitchy bedtime story told by a tired satellite", | |
| "tone: clerk-behind-the-counter deadpan, secretly divine", | |
| "tone: anxious stand-up set delivered by the neighborhood itself", | |
| "tone: soft apocalypse where nobody panics, they just remix", | |
| "tone: fanfiction of capitalism written by a bored warehouse robot", | |
| "tone: warm nostalgia hacked with tiny, unsettling edits", | |
| "tone: late-night pirate lecture from a kind conspiracy theorist", | |
| "tone: workplace training video that slowly remembers it has feelings", | |
| "tone: museum audio-guide for objects that don’t officially exist" | |
| ]; | |
| const guardrails = [ | |
| "Stay non-destructive: use removable / reversible materials.", | |
| "Avoid targeting individuals; ideas & systems only.", | |
| "Ensure consent where bodies & faces are involved.", | |
| "Keep police-bait low; keep community-care high.", | |
| "Make exit paths clear for anyone overwhelmed.", | |
| "Coordinate with venue-owners when possible; surprise perception, not people’s livelihoods.", | |
| "Keep data harmless: no tracking, no harvesting, just art.", | |
| "Never impersonate emergency or essential services.", | |
| "Leave spaces cleaner or kinder than you found them.", | |
| "Make it opt-in whenever possible; curiosity counts as consent, confusion does not.", | |
| "If a stunt could embarrass someone, offer them a way to become the hero instead.", | |
| "Never punch down; if the joke requires a powerless target, rewrite the joke.", | |
| "Assume someone is always filming—design as if your kindest intent will be replayed.", | |
| "Check local laws before you climb, glue, or tape anything; clever beats criminal.", | |
| "If staff will have to clean it, make their experience pleasant or rewarding too.", | |
| "Design with accessibility in mind; mystery shouldn’t rely on perfect eyesight or hearing.", | |
| "Treat anonymity as a shield, not a weapon—don’t hide to harm.", | |
| "Leave behind clear cues that this is art, not emergency, once the reveal lands." | |
| ]; | |
| const titleBitsA = [ | |
| "Static","Neon","Sigil","Dead-Drop","Quiet","Frequency","Occult", | |
| "Lo-Fi","Delta","Proxy","Feral","Memory","NFC","Bluetooth","Drone", | |
| "Spectral","Subway","Lantern","Sensor","Guerrilla","Ambient","Complex","Errorcore","Protocol", | |
| "Loopstation","Drift","Commons","MythOS","Handshake","Relaypoint","Interruption","Subroutine", | |
| "Wake" | |
| :] | |
| const titleBitsB = [ | |
| "Choir","Bloom","Initiative","Ritual","Beacon","Circuit","Orchard", | |
| "Broadcast","Loop","Line","Shrine","Archive","Carousel","Node", | |
| "Kernel","Cascade","Waltz","Mesh","Relay","Spiral","Trace","Swarm","Consortium","Staticline", "Overpass", | |
| "Backroom","Candlecode","Ghostshift","Metro","Paperclip", | |
| "Sleeper", | |
| "Patchnote", | |
| "Analog" | |
| ]; | |
| // decrypt animation (spin made longer here) | |
| const randomChars = "ABCDEFGHJKLMNOPRSTUVWXYZ0123456789-_/|"; | |
| function animateDecrypt(element, finalText, options = {}) { | |
| const duration = options.duration || 950; // longer spin | |
| const stepTime = options.stepTime || 45; | |
| const stripBounce = options.stripBounce !== false; | |
| element.innerHTML = ""; | |
| const chars = finalText.toUpperCase().split(""); | |
| const spans = chars.map((ch) => { | |
| const span = document.createElement("span"); | |
| span.className = "led-char rolling"; | |
| span.textContent = pick(randomChars); | |
| element.appendChild(span); | |
| return span; | |
| }); | |
| if (stripBounce) { | |
| element.style.transform = "translateY(40%)"; | |
| requestAnimationFrame(() => { | |
| element.style.transform = "translateY(0)"; | |
| }); | |
| } | |
| const totalSteps = Math.ceil(duration / stepTime); | |
| let currentStep = 0; | |
| const timer = setInterval(() => { | |
| currentStep++; | |
| spans.forEach((span, i) => { | |
| if (currentStep < totalSteps - 2 - i * 0.4) { | |
| span.textContent = pick(randomChars); | |
| } else { | |
| span.textContent = chars[i]; | |
| span.classList.remove("rolling"); | |
| } | |
| }); | |
| if (currentStep >= totalSteps) { | |
| clearInterval(timer); | |
| } | |
| }, stepTime); | |
| } | |
| // Slot DOM | |
| const frameworkDisplay = document.getElementById("frameworkDisplay"); | |
| const channelDisplay = document.getElementById("channelDisplay"); | |
| const tacticDisplay = document.getElementById("tacticDisplay"); | |
| const spinFrameworkBtn = document.getElementById("spinFramework"); | |
| const spinChannelBtn = document.getElementById("spinChannel"); | |
| const spinTacticBtn = document.getElementById("spinTactic"); | |
| const spinAllBtn = document.getElementById("spinAll"); | |
| const ideaScroll = document.getElementById("ideaScroll"); | |
| const ideaTitle = document.getElementById("ideaTitle"); | |
| const ideaMeta = document.getElementById("ideaMeta"); | |
| const gaugeSignal = document.getElementById("gaugeSignal"); | |
| const gaugeSpectral = document.getElementById("gaugeSpectral"); | |
| const signalValue = document.getElementById("signalValue"); | |
| const spectralValue = document.getElementById("spectralValue"); | |
| // sound | |
| let audioCtx = null; | |
| function playSpinSound() { | |
| try { | |
| if (!audioCtx) { | |
| const AC = window.AudioContext || window.webkitAudioContext; | |
| if (!AC) return; | |
| audioCtx = new AC(); | |
| } | |
| const ctx = audioCtx; | |
| const osc = ctx.createOscillator(); | |
| const gain = ctx.createGain(); | |
| osc.type = "triangle"; | |
| const now = ctx.currentTime; | |
| osc.frequency.setValueAtTime(220, now); | |
| osc.frequency.linearRampToValueAtTime(660, now + 0.35); | |
| gain.gain.setValueAtTime(0.001, now); | |
| gain.gain.exponentialRampToValueAtTime(0.22, now + 0.06); | |
| gain.gain.exponentialRampToValueAtTime(0.001, now + 0.45); | |
| osc.connect(gain); | |
| gain.connect(ctx.destination); | |
| osc.start(now); | |
| osc.stop(now + 0.5); | |
| } catch (e) { | |
| // fail silently; audio not critical | |
| } | |
| } | |
| // gauges | |
| function nudgeGauge(el, labelEl) { | |
| const value = 40 + Math.floor(Math.random() * 51); // 40–90 | |
| el.style.transform = "scaleX(" + value / 100 + ")"; | |
| labelEl.textContent = value + "%"; | |
| } | |
| function generateIdea() { | |
| const framework = pick(frameworks); | |
| const channel = pick(channels); | |
| const payload = pick(payloads); | |
| const sensory = pick(sensoryBias); | |
| const objective = pick(objectives); | |
| const tone = pick(tones); | |
| const guard = pick(guardrails); | |
| const title = | |
| pick(titleBitsA) + " " + pick(titleBitsB); | |
| const html = ` | |
| <p><strong>Working Title:</strong> ${title}</p> | |
| <p><strong>Core Framework:</strong> ${framework}.</p> | |
| <p><strong>Primary Channel:</strong> ${channel}.</p> | |
| <p><strong>Payload:</strong> ${payload}, tuned toward <em>${sensory}</em>.</p> | |
| <p><strong>Objective:</strong> ${objective}.</p> | |
| <p><strong>Execution Sketch:</strong> Treat this as a modular ritual. The framework gives the myth-logic, the channel gives the body, the payload is the nervous system. Translate it into your medium — music, video, projection, stickers, pirate radio, NFC tags, Kinect ghosts, flyers — but keep the action reversible, deniable, and kind.</p> | |
| <p><strong>Tone:</strong> ${tone}.</p> | |
| <p style="font-size:0.72rem;opacity:0.85;"><strong>Guardrail:</strong> ${guard}</p> | |
| `; | |
| return { | |
| title, | |
| framework, | |
| channel, | |
| payload, | |
| html | |
| }; | |
| } | |
| function spinFrameworkOnly() { | |
| playSpinSound(); | |
| const text = pick(frameworks).split("–")[0].trim(); | |
| animateDecrypt(frameworkDisplay, text); | |
| nudgeGauge(gaugeSignal, signalValue); | |
| } | |
| function spinChannelOnly() { | |
| playSpinSound(); | |
| const text = pick(channels).toUpperCase(); | |
| animateDecrypt(channelDisplay, text); | |
| nudgeGauge(gaugeSpectral, spectralValue); | |
| } | |
| function spinTacticOnly() { | |
| playSpinSound(); | |
| const text = pick(payloads).split(" ")[0].trim(); | |
| animateDecrypt(tacticDisplay, text); | |
| nudgeGauge(gaugeSignal, signalValue); | |
| nudgeGauge(gaugeSpectral, spectralValue); | |
| } | |
| spinFrameworkBtn.addEventListener("click", spinFrameworkOnly); | |
| spinChannelBtn.addEventListener("click", spinChannelOnly); | |
| spinTacticBtn.addEventListener("click", spinTacticOnly); | |
| spinAllBtn.addEventListener("click", () => { | |
| playSpinSound(); | |
| const idea = generateIdea(); | |
| animateDecrypt( | |
| frameworkDisplay, | |
| idea.framework.split("–")[0].trim() | |
| ); | |
| animateDecrypt( | |
| channelDisplay, | |
| idea.channel.split(" ")[0].trim() | |
| ); | |
| animateDecrypt( | |
| tacticDisplay, | |
| idea.payload.split(" ")[0].trim() | |
| ); | |
| ideaTitle.textContent = "INITIATIVE: " + idea.title; | |
| ideaMeta.textContent = | |
| "framework: " + | |
| idea.framework.split("–")[0].trim() + | |
| " | channel: " + | |
| idea.channel.toLowerCase(); | |
| ideaScroll.innerHTML = idea.html; | |
| nudgeGauge(gaugeSignal, signalValue); | |
| nudgeGauge(gaugeSpectral, spectralValue); | |
| }); | |
| // initial seed | |
| animateDecrypt(frameworkDisplay, "MYTHGLITCH"); | |
| animateDecrypt(channelDisplay, "STREET"); | |
| animateDecrypt(tacticDisplay, "PAYLOAD"); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment