-
-
-

-
Succession
-
-
-

-
Chernobyl
-
-
-

-
Breaking Bad
-
-
-

-
Avatar: The Last Airbender
-
-
-

-
Adolescence
+
+
Top 5 Shows
+
+
+
+

+
Succession
+
+
+

+
Chernobyl
+
+
+

+
Breaking Bad
+
+
+

+
Avatar: The Last Airbender
+
+
+

+
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
+
+
+
Want to play a game Alice?!
@@ -294,6 +303,18 @@
This game is
+
+ 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