From 05d8732e8521c754cbc7ba4dfdcbbc7f5c8e320b Mon Sep 17 00:00:00 2001 From: samantha42 Date: Sun, 24 May 2026 21:35:04 +0200 Subject: [PATCH] new animations --- static/about.html | 155 +++++++++++--------- static/about.js | 301 +++++++++++++++++++++++++++++++++++++-- static/style/styles.css | 4 +- static/style/styles2.css | 21 ++- 4 files changed, 397 insertions(+), 84 deletions(-) diff --git a/static/about.html b/static/about.html index 98c27c2..96ac742 100644 --- a/static/about.html +++ b/static/about.html @@ -128,23 +128,23 @@

education

-
2025 —
present
+
2025 — present
Bachelor of Economics & Business Administration (HA)
Aalborg University · Expected 2028
-
2024 — 2025
+
2024 — 2025
discontinued
Mathematics-Technology (BSc)
Aalborg University · 1 semester
- discontinued +
-
2020 —
2023
+
2020 — 2023
HTX – Technical Upper Secondary Education
Viden Gymnasier
@@ -163,9 +163,9 @@
-
+

interests

-
+
cinema tv shows Economics @@ -214,73 +214,82 @@

- -

Movie/Show Top list

-
-

Top 5 Movies

-
-
-
- Blade Runner 2049 -

Blade Runner 2049

-
-
- A Cure of Wellness -

A Cure of Wellness

-
-
- matrix -

The Matrix

-
-
- Dracula: A Love Tale -

Dracula: A Love Tale

-
-
- Girl with a Dragon Tattoos -

Girl with a Dragon Tattoo

+
+ +

Movie/Show Top list

+
+

Top 5 Movies

+
+
+
+ Blade Runner 2049 +

Blade Runner 2049

+
+
+ A Cure of Wellness +

A Cure of Wellness

+
+
+ matrix +

The Matrix

+
+
+ Dracula: A Love Tale +

Dracula: A Love Tale

+
+
+ Girl with a Dragon Tattoos +

Girl with a Dragon Tattoo

+
-
-
-

Top 5 Shows

-
-
-
- Succession -

Succession

-
-
- Chernobyl -

Chernobyl

-
-
- Breaking Bad -

Breaking Bad

-
-
- Avatar: The Last Airbender -

Avatar: The Last Airbender

-
-
- Adolescence -

Adolescence

+
+

Top 5 Shows

+
+
+
+ Succession +

Succession

+
+
+ Chernobyl +

Chernobyl

+
+
+ Breaking Bad +

Breaking Bad

+
+
+ Avatar: The Last Airbender +

Avatar: The Last Airbender

+
+
+ Adolescence +

Adolescence

+
-
-

Lunix rice

-
-
-

I love my custom Linux setup. I use Hyprland, which automatically arranges app windows on my screen so everything stays organized without dragging things around. I also use Quickshell, which lets me customize menus, shortcuts, and system controls to work exactly how I want. - My system is based on Arch Linux or Manjaro Linux, which are versions of Linux that give you more control and customization than a typical computer setup. The result is a clean, fast, and super efficient desktop that’s hard to go back from. - Git repo -

-
+

Lunix rice

+
+
+

I love my custom Linux setup. I use Hyprland, which automatically arranges app windows on my screen so everything stays organized without dragging things around. I also use Quickshell, which lets me customize menus, shortcuts, and system controls to work exactly how I want. + My system is based on Arch Linux or Manjaro Linux, which are versions of Linux that give you more control and customization than a typical computer setup. The result is a clean, fast, and super efficient desktop that’s hard to go back from. + Git repo +

+
+
+
+
42
+
+

So long, and thanks for all the fish.

+

Douglas Adams  ·  The Hitchhiker's Guide to the Galaxy

+ +
+

shhh. i have a secret to share — follow me

+
+
+ +
diff --git a/static/about.js b/static/about.js index e4613be..dd0eab4 100644 --- a/static/about.js +++ b/static/about.js @@ -40,27 +40,270 @@ // just some fun. console.log("%c👀 hi there!", "font-size:20px") +function cureClick() { + if (document.getElementById('cure-canvas')) return; + const el = document.getElementById('interest'); + el.textContent = "Actually... I'm feeling much better now!" + startWater(); + isDay = false; + applyState(); + setTimeout(() => { + el.textContent = 'interest'; + stopWater(); + }, 10000); +} - function draculaClick() { - const el = document.getElementById('interest'); - if (!el) return; // el is a DOM node, never a string - el.textContent = '🦇 interest 🦇'; +let cureCanvas, cureCtx, cureAnimFrame; - setTimeout(() => { - el.textContent = "interest"; - }, 5000); +function startWater() { + cureCanvas = document.createElement('canvas'); + cureCanvas.id = 'cure-canvas'; + cureCanvas.width = window.innerWidth; + cureCanvas.height = window.innerHeight; + Object.assign(cureCanvas.style, { + position: 'fixed', + top: 0, + left: 0, + pointerEvents: 'none', + zIndex: -1, // behind everything + opacity: '0', + transition: 'opacity 1.4s ease' + }); + document.body.appendChild(cureCanvas); + cureCtx = cureCanvas.getContext('2d'); + requestAnimationFrame(() => { cureCanvas.style.opacity = '1'; }); + + const W = cureCanvas.width; + const H = cureCanvas.height; + + // waterline sits at 38% from the top + const waterlineY = H * 0.38; + + // floating particles below the surface + const particles = Array.from({ length: 55 }, () => ({ + x: Math.random() * W, + y: waterlineY + 20 + Math.random() * (H - waterlineY - 20), + r: 1 + Math.random() * 2.5, + speedX: (Math.random() - 0.5) * 0.3, + speedY: -0.08 - Math.random() * 0.18, // slow upward drift + opacity: 0.08 + Math.random() * 0.18 + })); + + function drawFrame(ts) { + cureCtx.clearRect(0, 0, W, H); + + // ── sky above waterline (very subtle, mostly transparent) ────────── + const sky = cureCtx.createLinearGradient(0, 0, 0, waterlineY); + sky.addColorStop(0, 'rgba(190, 230, 255, 0.06)'); + sky.addColorStop(1, 'rgba(190, 230, 255, 0.01)'); + cureCtx.fillStyle = sky; + cureCtx.fillRect(0, 0, W, waterlineY); + + // ── water body below waterline ───────────────────────────────────── + const water = cureCtx.createLinearGradient(0, waterlineY, 0, H); + water.addColorStop(0, 'rgba(80, 190, 220, 0.28)'); + water.addColorStop(0.35, 'rgba(40, 140, 190, 0.22)'); + water.addColorStop(0.7, 'rgba(20, 90, 150, 0.20)'); + water.addColorStop(1, 'rgba(10, 50, 110, 0.22)'); + cureCtx.fillStyle = water; + cureCtx.fillRect(0, waterlineY, W, H - waterlineY); + + // ── caustic shimmer streaks ──────────────────────────────────────── + const numStreaks = 10; + for (let i = 0; i < numStreaks; i++) { + const phase = (ts * 0.0004 + i * 0.63) % 1; + const x = (i / numStreaks) * W + Math.sin(ts * 0.0008 + i) * 60; + const yTop = waterlineY + 10 + Math.sin(ts * 0.001 + i * 1.3) * 18; + const yBot = yTop + 40 + Math.sin(ts * 0.0007 + i * 0.9) * 30; + const streak = cureCtx.createLinearGradient(x, yTop, x + 6, yBot); + streak.addColorStop(0, 'rgba(200, 245, 255, 0)'); + streak.addColorStop(0.4, `rgba(200, 245, 255, ${0.05 + 0.06 * Math.sin(ts * 0.002 + i)})`); + streak.addColorStop(1, 'rgba(200, 245, 255, 0)'); + cureCtx.fillStyle = streak; + cureCtx.fillRect(x, yTop, 5, yBot - yTop); + } + + // ── floating particles ───────────────────────────────────────────── + particles.forEach(p => { + p.x += p.speedX; + p.y += p.speedY; + // reset when reaching the surface + if (p.y < waterlineY + 5) { + p.y = H - 10; + p.x = Math.random() * W; + } + if (p.x < 0) p.x = W; + if (p.x > W) p.x = 0; + + const depth = (p.y - waterlineY) / (H - waterlineY); // 0 = surface, 1 = bottom + cureCtx.beginPath(); + cureCtx.arc(p.x, p.y, p.r, 0, Math.PI * 2); + cureCtx.fillStyle = `rgba(180, 240, 255, ${p.opacity * (0.4 + 0.6 * (1 - depth))})`; + cureCtx.fill(); + }); + + // ── animated surface waves (2 layers, different speeds & amplitudes) ─ + function drawWaveLine(amp, freq, speed, lineW, alpha) { + cureCtx.beginPath(); + for (let x = 0; x <= W; x += 3) { + const y = waterlineY + + Math.sin(x * freq + ts * speed) * amp + + Math.sin(x * freq * 1.7 + ts * speed * 0.6) * (amp * 0.4); + x === 0 ? cureCtx.moveTo(x, y) : cureCtx.lineTo(x, y); + } + cureCtx.strokeStyle = `rgba(210, 245, 255, ${alpha})`; + cureCtx.lineWidth = lineW; + cureCtx.stroke(); + } + + // primary wave + drawWaveLine(7, 0.012, 0.0018, 2.0, 0.70); + // secondary wave (slightly offset phase) + drawWaveLine(4, 0.018, 0.0024, 1.2, 0.40); + // micro ripple + drawWaveLine(2, 0.030, 0.0032, 0.7, 0.25); + + // ── foam/highlight on the crest ──────────────────────────────────── + cureCtx.beginPath(); + for (let x = 0; x <= W; x += 3) { + const y = waterlineY + + Math.sin(x * 0.012 + ts * 0.0018) * 7 + + Math.sin(x * 0.020 + ts * 0.0024) * 3; + x === 0 ? cureCtx.moveTo(x, y - 1) : cureCtx.lineTo(x, y - 1); + } + cureCtx.strokeStyle = 'rgba(255, 255, 255, 0.18)'; + cureCtx.lineWidth = 1; + cureCtx.stroke(); + + if (cureCanvas) cureAnimFrame = requestAnimationFrame(drawFrame); } + cureAnimFrame = requestAnimationFrame(drawFrame); +} + +function stopWater() { + if (!cureCanvas) return; + cureCanvas.style.opacity = '0'; + cancelAnimationFrame(cureAnimFrame); + setTimeout(() => { + cureCanvas.remove(); + cureCanvas = null; + }, 1400); +} + +function draculaClick() { + if (document.getElementById('lightning-canvas')) return; + const el = document.getElementById('interest'); + el.textContent = 'children of the night'; + startLightning(); + isDay = false; + applyState(); + setTimeout(() => { + el.textContent = 'interest'; + stopLightning(); + }, 10000); +} + +let lightningCanvas, lightningCtx, lightningInterval, lightningFlashTimeout; + +function startLightning() { + lightningCanvas = document.createElement('canvas'); + lightningCanvas.id = 'lightning-canvas'; + lightningCanvas.width = window.innerWidth; + lightningCanvas.height = window.innerHeight; + Object.assign(lightningCanvas.style, { + position: 'fixed', top: 0, left: 0, + pointerEvents: 'none', zIndex: 9999, + opacity: '0', transition: 'opacity 0.3s ease' + }); + document.body.appendChild(lightningCanvas); + lightningCtx = lightningCanvas.getContext('2d'); + requestAnimationFrame(() => { lightningCanvas.style.opacity = '1'; }); + + function drawBolt(x1, y1, x2, y2, roughness, depth) { + if (depth === 0) { + lightningCtx.beginPath(); + lightningCtx.moveTo(x1, y1); + lightningCtx.lineTo(x2, y2); + lightningCtx.stroke(); + return; + } + const mx = (x1 + x2) / 2 + (Math.random() - 0.5) * roughness; + const my = (y1 + y2) / 2 + (Math.random() - 0.5) * roughness; + drawBolt(x1, y1, mx, my, roughness / 2, depth - 1); + drawBolt(mx, my, x2, y2, roughness / 2, depth - 1); + // random fork branch + if (depth > 2 && Math.random() < 0.4) { + const fx = mx + (Math.random() - 0.3) * roughness * 2; + const fy = my + Math.random() * roughness * 2; + lightningCtx.save(); + lightningCtx.globalAlpha *= 0.5; + drawBolt(mx, my, fx, fy, roughness / 2, depth - 2); + lightningCtx.restore(); + } + } + + function flashStrike() { + lightningCtx.clearRect(0, 0, lightningCanvas.width, lightningCanvas.height); + + const numBolts = 1 + Math.floor(Math.random() * 3); + for (let i = 0; i < numBolts; i++) { + const startX = lightningCanvas.width * (0.1 + Math.random() * 0.8); + const endX = startX + (Math.random() - 0.5) * 300; + const color = Math.random() < 0.6 + ? `rgba(220, 180, 255, ${0.6 + Math.random() * 0.4})` // purple + : `rgba(255, 255, 255, ${0.7 + Math.random() * 0.3})`; // white + + lightningCtx.strokeStyle = color; + lightningCtx.lineWidth = 0.5 + Math.random() * 2; + lightningCtx.shadowColor = color; + lightningCtx.shadowBlur = 18 + Math.random() * 30; + lightningCtx.globalAlpha = 1; + + drawBolt(startX, 0, endX, lightningCanvas.height * (0.4 + Math.random() * 0.5), 120, 7); + } + + // ambient flash on the body + document.body.style.transition = 'background 0.05s'; + document.body.style.background = `rgba(80, 0, 120, 0.08)`; + setTimeout(() => { document.body.style.background = ''; }, 80); + + // fade the bolt out + lightningFlashTimeout = setTimeout(() => { + lightningCtx.clearRect(0, 0, lightningCanvas.width, lightningCanvas.height); + }, 80 + Math.random() * 120); + } + + // irregular strike cadence — like real lightning + function scheduleStrike() { + flashStrike(); + const delay = 600 + Math.random() * 2200; + lightningInterval = setTimeout(scheduleStrike, delay); + } + scheduleStrike(); +} + +function stopLightning() { + if (!lightningCanvas) return; + lightningCanvas.style.opacity = '0'; + clearTimeout(lightningInterval); + clearTimeout(lightningFlashTimeout); + setTimeout(() => { + lightningCanvas.remove(); + lightningCanvas = null; + }, 800); +} + function matrixClick() { const sub = document.getElementById('interest-sub'); - const col = sub.color - sub.textContent = `Do not try and bend the spoon. That's impossible. Instead... only try to realize the truth.` + sub.style.display = "none" + const matrixsub = document.getElementById('matrix-hidden'); + matrixsub.style.display = "block" - sub.style.color = "green" setTimeout(() => { - sub.textContent = "Fav lists" - sub.style.color = "#6b6560" + matrixsub.style.display = "none" + sub.style.display = "block" }, 15000); } @@ -73,6 +316,9 @@ startRain(); + isDay = false + applyState(); + setTimeout(() => { el.textContent = "interest"; stopRain(); @@ -182,3 +428,34 @@ function dragonClick() { }, 300); }; } + + +function unhide42() { + const alicegameSection = document.getElementById('alice'); + const tetrisSection = document.getElementById('tetris'); + const experiencesection = document.getElementById('experience'); + + const educationsection = document.getElementById('education'); + const automationsection = document.getElementById('automation'); + const interestssection = document.getElementById('interests'); + const opinionsection = document.getElementById('opinion'); + const interestlistsection = document.getElementById('interestlist'); + + const hiddenssection = document.getElementById('secret'); + + if (hiddenssection.style.display == 'none') { + hiddenssection.style.display = 'block'; + } else { + hiddenssection.style.display = 'none'; + } + alicegameSection.style.display = 'none'; + tetrisSection.style.display = 'none'; + experiencesection.style.display = 'none'; + educationsection.style.display = 'none'; + automationsection.style.display = 'none'; + interestssection.style.display = 'none'; + + opinionsection.style.display = 'none'; + interestlistsection.style.display = 'none'; + +} \ No newline at end of file diff --git a/static/style/styles.css b/static/style/styles.css index 900f30f..a8b28ad 100644 --- a/static/style/styles.css +++ b/static/style/styles.css @@ -1156,10 +1156,10 @@ nav .section-label { display: inline-block; margin-top: 8px; font-family: 'DM Mono', monospace; - font-size: 10px; + font-size: 8px; letter-spacing: 0.1em; text-transform: uppercase; - padding: 3px 8px; + padding: 3px 5px; border-radius: 3px; } diff --git a/static/style/styles2.css b/static/style/styles2.css index d17c99b..a24a46d 100644 --- a/static/style/styles2.css +++ b/static/style/styles2.css @@ -262,10 +262,10 @@ footer{ display: inline-block; margin-top: 8px; font-family: 'DM Mono', monospace; - font-size: 10px; + font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; - padding: 3px 8px; + padding: 3px 5px; border-radius: 3px; } @@ -575,4 +575,19 @@ a{ background: transparent; color: var(--color-text-secondary); } - .copy-btn:hover { background: var(--color-background-secondary); } \ No newline at end of file + .copy-btn:hover { background: var(--color-background-secondary); } + +.Hitchhiker { + max-width: 480px; + width: 100%; + text-align: center; + display: none; +} +.matrix-hidden { + display: none; + color: green; + font-family: var(--ff-mono); + font-size: 0.72rem; + letter-spacing: 0.08em; + padding-left: 1.1rem; +} \ No newline at end of file