Untitled
Anonymous
plain_text
09/14/2026 9:44 AM
17.6 KB
2
Indexable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Serene Flow - A Satisfying Well-Being Experience</title>
<style>
* {
box-sizing: border-box;
user-select: none;
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: #0f172a;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
color: #f8fafc;
}
#canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.ui-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
pointer-events: none;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 30px;
}
.header {
text-align: center;
background: rgba(15, 23, 42, 0.65);
backdrop-filter: blur(12px);
padding: 15px 30px;
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.1);
align-self: center;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
}
h1 {
margin: 0;
font-size: 1.5rem;
font-weight: 400;
letter-spacing: 2px;
color: #38bdf8;
}
p.subtitle {
margin: 5px 0 0 0;
font-size: 0.85rem;
color: #94a3b8;
}
.hud {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 15px;
}
.stat {
display: flex;
flex-direction: column;
align-items: center;
}
.stat-label {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 1px;
color: #cbd5e1;
margin-bottom: 5px;
}
.stat-bar {
width: 140px;
height: 8px;
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
overflow: hidden;
}
.stat-fill {
height: 100%;
width: 50%;
border-radius: 4px;
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.6s ease;
}
#harmony-fill { background: linear-gradient(90deg, #38bdf8, #34d399); }
#calm-fill { background: linear-gradient(90deg, #a78bfa, #f472b6); }
.toast {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(16px);
border: 1px solid rgba(56, 189, 248, 0.3);
padding: 16px 28px;
border-radius: 30px;
text-align: center;
max-width: 500px;
width: 90%;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
opacity: 0;
transition: opacity 0.5s ease, transform 0.5s ease;
pointer-events: auto;
}
.toast.show {
opacity: 1;
transform: translateX(-50%) translateY(-10px);
}
.toast-title {
font-weight: 600;
font-size: 1rem;
color: #38bdf8;
margin-bottom: 4px;
}
.toast-body {
font-size: 0.88rem;
color: #e2e8f0;
line-height: 1.4;
}
.start-prompt {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.1rem;
color: #94a3b8;
background: rgba(15, 23, 42, 0.8);
padding: 15px 30px;
border-radius: 30px;
border: 1px solid rgba(255, 255, 255, 0.1);
pointer-events: none;
transition: opacity 0.5s ease;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="ui-layer">
<div class="header">
<h1>SERENE FLOW</h1>
<p class="subtitle">Pop floating energy nodes to nurture well-being & harmony</p>
<div class="hud">
<div class="stat">
<span class="stat-label">Harmony & Purpose</span>
<div class="stat-bar"><div id="harmony-fill" class="stat-fill" style="width: 50%;"></div></div>
</div>
<div class="stat">
<span class="stat-label">Inner Calm</span>
<div class="stat-bar"><div id="calm-fill" class="stat-fill" style="width: 50%;"></div></div>
</div>
</div>
</div>
<div id="start-prompt" class="start-prompt">Click or Tap anywhere to begin soothing sound</div>
<div id="toast" class="toast">
<div id="toast-title" class="toast-title">Welcome</div>
<div id="toast-body" class="toast-body">Glide your cursor or tap nodes to build personal health and workplace synergy.</div>
</div>
</div>
<script>
// --- Audio Engine (Web Audio API Pentatonic Chimes) ---
let audioCtx = null;
const pentatonicScale = [261.63, 293.66, 329.63, 392.00, 440.00, 523.25, 587.33, 659.25]; // C Major / A Minor Pentatonic
function initAudio() {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
document.getElementById('start-prompt').style.opacity = '0';
}
function playChime(freqIndex, isPositive = true) {
if (!audioCtx) return;
const freq = pentatonicScale[freqIndex % pentatonicScale.length];
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = isPositive ? 'sine' : 'triangle';
osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
// Soft envelope
gain.gain.setValueAtTime(0, audioCtx.currentTime);
gain.gain.linearRampToValueAtTime(isPositive ? 0.25 : 0.15, audioCtx.currentTime + 0.05);
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + (isPositive ? 1.5 : 0.8));
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + (isPositive ? 1.5 : 0.8));
}
// --- Well-Being Knowledge Base ---
const nodeData = [
// HHS Framework Essentials
{ category: "Protection from Harm", title: "Psychological Safety", body: "Creating environment where open voice and mental health are normalized. (HHS Essential)", color: "#38bdf8", type: "positive" },
{ category: "Connection & Community", title: "Belonging & Trust", body: "Fostering prosocial inclusion and peer social support builds resilience. (HHS Essential)", color: "#34d399", type: "positive" },
{ category: "Work-Life Harmony", title: "Autonomy & Rest", body: "Flexible schedules and respecting non-work boundaries protect against burnout. (HHS Essential)", color: "#a78bfa", type: "positive" },
{ category: "Mattering at Work", title: "Dignity & Gratitude", body: "Knowing your work matters and receiving authentic recognition boosts morale. (HHS Essential)", color: "#f472b6", type: "positive" },
{ category: "Opportunity for Growth", title: "Learning & Mentorship", body: "Clear pathways for skill advancement build optimism and pride. (HHS Essential)", color: "#fbbf24", type: "positive" },
// Narconon Healthy Choice Principles
{ category: "Life Choice", title: "Natural Stress Relief", body: "Replacing harmful substance coping with exercise, art, and deep breathing. (Narconon Guide)", color: "#34d399", type: "positive" },
{ category: "Life Choice", title: "Genuine Connection", body: "Engaging in face-to-face relationships instead of chemical isolation. (Narconon Guide)", color: "#38bdf8", type: "positive" },
{ category: "Life Choice", title: "Passion Projects", body: "Investing time in creative hobbies builds natural dopamine and self-worth. (Narconon Guide)", color: "#fbbf24", type: "positive" },
// Mild Stressor / Reframing Nodes
{ category: "Workplace Hazard", title: "Unpredictable Work Hours", body: "Constant schedule flux increases anxiety. Rebalance with clear boundary setting.", color: "#f87171", type: "stressor" },
{ category: "Life Hazard", title: "Chemical Fatigue Loop", body: "Relying on stimulants or sedatives harms physical health. Choose true rest.", color: "#fb923c", type: "stressor" }
];
// --- Canvas Engine & Particles ---
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let width, height;
let nodes = [];
let particles = [];
let ripples = [];
let harmony = 50;
let calm = 50;
function resize() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
class Node {
constructor(data) {
this.data = data;
this.radius = Math.random() * 20 + 35;
this.x = Math.random() * (width - this.radius * 2) + this.radius;
this.y = Math.random() * (height - this.radius * 2) + this.radius;
this.vx = (Math.random() - 0.5) * 0.8;
this.vy = (Math.random() - 0.5) * 0.8;
this.pulse = Math.random() * Math.PI * 2;
this.color = data.color;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.pulse += 0.02;
if (this.x - this.radius < 0 || this.x + this.radius > width) this.vx *= -1;
if (this.y - this.radius < 0 || this.y + this.radius > height) this.vy *= -1;
}
draw() {
ctx.save();
ctx.beginPath();
const currentRadius = this.radius + Math.sin(this.pulse) * 4;
// Outer Glow
const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, currentRadius * 1.5);
gradient.addColorStop(0, this.color + '88');
gradient.addColorStop(0.5, this.color + '33');
gradient.addColorStop(1, 'transparent');
ctx.fillStyle = gradient;
ctx.arc(this.x, this.y, currentRadius * 1.5, 0, Math.PI * 2);
ctx.fill();
// Inner Core
ctx.beginPath();
ctx.arc(this.x, this.y, currentRadius * 0.7, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowColor = this.color;
ctx.shadowBlur = 15;
ctx.fill();
ctx.restore();
}
}
class Particle {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
this.radius = Math.random() * 4 + 2;
this.vx = (Math.random() - 0.5) * 4;
this.vy = (Math.random() - 0.5) * 4;
this.alpha = 1;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.alpha -= 0.015;
}
draw() {
ctx.save();
ctx.globalAlpha = Math.max(0, this.alpha);
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
}
}
class Ripple {
constructor(x, y) {
this.x = x;
this.y = y;
this.radius = 5;
this.alpha = 0.5;
}
update() {
this.radius += 2.5;
this.alpha -= 0.01;
}
draw() {
ctx.save();
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.strokeStyle = `rgba(56, 189, 248, ${Math.max(0, this.alpha)})`;
ctx.lineWidth = 1.5;
ctx.stroke();
ctx.restore();
}
}
// Populate initial nodes
function spawnNodes() {
nodes = [];
nodeData.forEach(data => {
nodes.push(new Node(data));
});
}
spawnNodes();
// --- Main Loop ---
function animate() {
ctx.clearRect(0, 0, width, height);
// Background subtle grid/stars
ctx.fillStyle = 'rgba(255, 255, 255, 0.03)';
for (let i = 0; i < 20; i++) {
ctx.fillRect((i * 137) % width, (i * 241) % height, 2, 2);
}
// Update & Draw Ripples
ripples.forEach((r, i) => {
r.update();
r.draw();
if (r.alpha <= 0) ripples.splice(i, 1);
});
// Update & Draw Particles
particles.forEach((p, i) => {
p.update();
p.draw();
if (p.alpha <= 0) particles.splice(i, 1);
});
// Update & Draw Nodes
nodes.forEach(node => {
node.update();
node.draw();
});
requestAnimationFrame(animate);
}
animate();
// --- Interaction Handler ---
function handleInteraction(e) {
initAudio();
const rect = canvas.getBoundingClientRect();
const x = (e.clientX || e.touches[0].clientX) - rect.left;
const y = (e.clientY || e.touches[0].clientY) - rect.top;
ripples.push(new Ripple(x, y));
// Check collision with nodes
for (let i = nodes.length - 1; i >= 0; i--) {
const node = nodes[i];
const dist = Math.hypot(node.x - x, node.y - y);
if (dist < node.radius * 1.3) {
// Create Burst Particles
for (let p = 0; p < 18; p++) {
particles.push(new Particle(node.x, node.y, node.color));
}
// Audio & Gameplay Stats
const isPositive = node.data.type === 'positive';
playChime(Math.floor(Math.random() * pentatonicScale.length), isPositive);
if (isPositive) {
harmony = Math.min(100, harmony + 8);
calm = Math.min(100, calm + 6);
} else {
calm = Math.max(20, calm - 4);
}
updateHUD();
// Show Toast Info
showToast(node.data.title, `${node.data.category}: ${node.data.body}`);
// Respawn Node smoothly
const data = node.data;
nodes.splice(i, 1);
setTimeout(() => {
nodes.push(new Node(data));
}, 2500);
break;
}
}
}
function updateHUD() {
document.getElementById('harmony-fill').style.width = harmony + '%';
document.getElementById('calm-fill').style.width = calm + '%';
}
let toastTimeout;
function showToast(title, body) {
const toast = document.getElementById('toast');
document.getElementById('toast-title').innerText = title;
document.getElementById('toast-body').innerText = body;
toast.classList.add('show');
clearTimeout(toastTimeout);
toastTimeout = setTimeout(() => {
toast.classList.remove('show');
}, 4500);
}
window.addEventListener('click', handleInteraction);
window.addEventListener('touchstart', (e) => handleInteraction(e), { passive: true });
</script>
</body>
</html>Editor is loading...
Leave a Comment