@@ -118,6 +118,24 @@ import Footer from '../components/Footer.astro';
118118 75% { transform: translate(-6px, -6px) skew(-3deg); }
119119 100% { transform: translate(0); }
120120 }
121+ @keyframes pixelate {
122+ 0% { filter: none; transform: scale(1); image-rendering: auto; }
123+ 50% { filter: blur(2px); transform: scale(0.9); image-rendering: pixelated; }
124+ 100% { filter: none; transform: scale(1); image-rendering: auto; }
125+ }
126+ .animate-pixelate { animation: pixelate 0.8s steps(2) forwards; }
127+ /* matrix rain canvas overlay */
128+ #matrix-canvas {
129+ position: fixed;
130+ top: 0;
131+ left: 0;
132+ width: 100%;
133+ height: 100%;
134+ pointer-events: none;
135+ z-index: 60;
136+ opacity: 0;
137+ transition: opacity 0.3s ease-out;
138+ }
121139 </style >
122140 </head >
123141 <body class =" bg-background text-foreground font-sans" >
@@ -227,6 +245,34 @@ import Footer from '../components/Footer.astro';
227245
228246
229247 const glitchEl = document.getElementById('glitch-overlay');
248+ const matrixEl = document.createElement('canvas');
249+ matrixEl.id = 'matrix-canvas';
250+ document.body.append(matrixEl);
251+ const mCtx = matrixEl.getContext('2d');
252+ function matrixEffect(duration = 800) {
253+ matrixEl.width = window.innerWidth;
254+ matrixEl.height = window.innerHeight;
255+ const cols = Math.floor(matrixEl.width / 20) + 1;
256+ const drops = Array(cols).fill(0);
257+ matrixEl.style.opacity = '1';
258+ const draw = () => {
259+ mCtx.fillStyle = 'rgba(0,0,0,0.05)';
260+ mCtx.fillRect(0, 0, matrixEl.width, matrixEl.height);
261+ mCtx.fillStyle = '#0f0';
262+ mCtx.font = '15px monospace';
263+ drops.forEach((y, i) => {
264+ const text = String.fromCharCode(0x30A0 + Math.random() * 96);
265+ mCtx.fillText(text, i * 20, y * 20);
266+ drops[i] = y * 20 > matrixEl.height || Math.random() > 0.975 ? 0 : y + 1;
267+ });
268+ };
269+ const timer = setInterval(draw, 50);
270+ setTimeout(() => {
271+ clearInterval(timer);
272+ matrixEl.style.opacity = '0';
273+ mCtx.clearRect(0, 0, matrixEl.width, matrixEl.height);
274+ }, duration);
275+ }
230276 (function glitchLoop() {
231277 const timeout = Math.random() * 6000 + 2000;
232278 setTimeout(() => {
@@ -257,6 +303,16 @@ import Footer from '../components/Footer.astro';
257303 document.documentElement.addEventListener('animationend', () => {
258304 document.documentElement.classList.remove('animate-shake');
259305 }, { once: true });
306+ // random additional effect: matrix rain or pixelate
307+ const extra = Math.random();
308+ if (extra < 0.4) {
309+ matrixEffect(1000);
310+ } else if (extra < 0.8) {
311+ root.classList.add('animate-pixelate');
312+ root.addEventListener('animationend', () => {
313+ root.classList.remove('animate-pixelate');
314+ }, { once: true });
315+ }
260316 glitchEl.classList.add('animate-glitch');
261317 glitchEl.addEventListener('animationend', () => {
262318 glitchEl.classList.remove('animate-glitch');
0 commit comments