add formatting

This commit is contained in:
2026-05-30 21:32:35 -04:00
parent f34ac3210e
commit 13a7306d5b
3 changed files with 901 additions and 692 deletions
+571 -456
View File
File diff suppressed because it is too large Load Diff
+189 -189
View File
@@ -50,56 +50,56 @@ function createServerRack() {
const bgContainer = document.querySelector('.server-rack-bg');
const rackContainer = document.createElement('div');
rackContainer.className = 'rack-container';
const topBar = document.createElement('div');
topBar.className = 'rack-top-bar';
rackContainer.appendChild(topBar);
const unitHeight = 98;
const barHeight = 72;
const totalPageHeight = document.documentElement.scrollHeight;
const totalUnits = Math.max(Math.ceil((totalPageHeight - 100 - barHeight) / unitHeight), 10);
const brands = ['Framework'];
const services = ['Borg', 'Gitea', 'Nextcloud', 'Jellyfin', 'Open WebUI', 'llama.cpp', 'Immich', 'LiteLLM', 'Caddy', 'Nginx', 'Samba', 'Slopbox'];
for (let i = 0; i < totalUnits; i++) {
const unit = document.createElement('div');
unit.className = 'rack-unit';
const leftRail = document.createElement('div');
leftRail.className = 'rail left';
unit.appendChild(leftRail);
const rightRail = document.createElement('div');
rightRail.className = 'rail right';
unit.appendChild(rightRail);
const isSwitch = i > 0 && (i % 7 === 0 || i % 11 === 0);
if (isSwitch) {
if (isSwitch) {
const switchFace = document.createElement('div');
switchFace.className = 'eth-switch-face';
const powerLed = document.createElement('div');
powerLed.className = 'eth-switch-led';
switchFace.appendChild(powerLed);
const brandLabel = document.createElement('div');
brandLabel.className = 'eth-brand';
brandLabel.textContent = brands[Math.floor(Math.random() * brands.length)];
switchFace.appendChild(brandLabel);
const portCount = Math.floor(Math.random() * 4) + 5;
const cappedCount = Math.min(portCount, 8);
const row = document.createElement('div');
row.className = 'eth-port-row';
for (let p = 0; p < cappedCount; p++) {
const port = document.createElement('div');
port.className = 'eth-port';
const led = document.createElement('div');
led.className = 'eth-port-led';
if (Math.random() > 0.3) {
@@ -110,32 +110,32 @@ function createServerRack() {
}
led.style.animationDelay = `${Math.random() * 2}s`;
port.appendChild(led);
row.appendChild(port);
}
switchFace.appendChild(row);
const label = document.createElement('div');
label.className = 'eth-port-label';
label.textContent = `1-${cappedCount}`;
switchFace.appendChild(label);
unit.appendChild(switchFace);
} else {
const face = document.createElement('div');
face.className = 'server-face';
const serverType = Math.random();
const isTerminal = i === 0;
if (isTerminal) {
// Terminal display
const terminal = document.createElement('div');
terminal.className = 'terminal-display';
terminal.setAttribute('tabindex', '0');
const mobileInput = document.createElement('input');
mobileInput.type = 'text';
mobileInput.style.opacity = '0';
@@ -153,40 +153,40 @@ function createServerRack() {
mobileInput.autocapitalize = 'off';
terminal.appendChild(mobileInput);
terminal._mobileInput = mobileInput;
const content = document.createElement('div');
content.className = 'terminal-content';
const line1 = document.createElement('div');
line1.innerHTML = '<span class="terminal-prompt">$</span> uptime';
content.appendChild(line1);
const line2 = document.createElement('div');
line2.textContent = 'optional';
content.appendChild(line2);
const line3 = document.createElement('div');
line3.innerHTML = '<span class="terminal-prompt">$</span> ';
content.appendChild(line3);
const cursor = document.createElement('span');
cursor.className = 'terminal-cursor';
line3.appendChild(cursor);
terminal.appendChild(content);
face.appendChild(terminal);
activeTerminal = terminal;
terminal.addEventListener('click', () => {
mobileInput.focus();
});
const commandHistory = [];
let historyIndex = -1;
let isRoot = false;
let isLoginScreen = false;
terminal.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp') {
e.preventDefault();
@@ -201,7 +201,7 @@ function createServerRack() {
}
return;
}
if (e.key === 'ArrowDown') {
e.preventDefault();
if (historyIndex > 0) {
@@ -222,7 +222,7 @@ function createServerRack() {
}
return;
}
if (e.key === 'Enter') {
e.preventDefault();
mobileInput.value = '';
@@ -230,14 +230,14 @@ function createServerRack() {
const lastLine = content.lastElementChild;
const oldCursor = lastLine?.querySelector('.terminal-cursor');
if (oldCursor) oldCursor.remove();
const cmdText = lastLine.textContent.replace(/^[\$#]\s*/, '').trim();
if (cmdText) {
commandHistory.unshift(cmdText);
historyIndex = -1;
}
if (cmdText.startsWith('ls')) {
const output = [
'total 20K',
@@ -252,14 +252,14 @@ function createServerRack() {
'-rw-r--r-- 1 reese reese 42K May 28 14:25 style.css',
'drwxr-xr-x 2 reese reese 4.0K May 27 09:00 src'
].join('\n');
const outLine = document.createElement('div');
outLine.style.whiteSpace = 'pre-wrap';
outLine.style.color = '#ccc';
outLine.textContent = output;
content.appendChild(outLine);
}
if (cmdText.startsWith('ss')) {
const output = 'Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port\ntcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:443 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:222 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:3000 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:3001 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:3002 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:8081 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:8096 0.0.0.0:*\ntcp LISTEN 0 128 0.0.0.0:9090 0.0.0.0:*\ntcp LISTEN 0 128 [::]:22 [::]:*';
const outLine = document.createElement('div');
@@ -268,105 +268,105 @@ function createServerRack() {
outLine.textContent = output;
content.appendChild(outLine);
}
if (cmdText === 'clear') {
content.innerHTML = '';
}
if (cmdText === 'exit') {
if (!isRoot) {
const newAchievements = checkAchievements(cmdText, false);
if (newAchievements.length > 0) {
revealAchievements();
newAchievements.forEach(a => showToast(a));
}
isLoginScreen = true;
document.body.innerHTML = '';
document.body.style.background = '#000';
document.body.style.color = '#fff';
document.body.style.fontFamily = 'monospace';
document.body.style.padding = '20px';
document.body.style.minHeight = '100vh';
document.body.style.margin = '0';
document.body.style.lineHeight = '1.6';
const loginContainer = document.createElement('div');
loginContainer.style.marginBottom = '10px';
loginContainer.textContent = 'homelab tty1';
document.body.appendChild(loginContainer);
const loginInput = document.createElement('input');
loginInput.type = 'text';
loginInput.style.background = 'transparent';
loginInput.style.border = 'none';
loginInput.style.outline = 'none';
loginInput.style.color = '#fff';
loginInput.style.fontFamily = 'monospace';
loginInput.style.fontSize = '14px';
loginInput.style.width = '300px';
loginInput.style.caretColor = '#fff';
loginInput.autofocus = true;
const loginLine = document.createElement('div');
loginLine.style.marginBottom = '20px';
loginLine.appendChild(document.createTextNode('homelab login: '));
loginLine.appendChild(loginInput);
document.body.appendChild(loginLine);
loginInput.focus();
const handleLogin = (e) => {
if (e.key === 'Enter') {
const deniedLine = document.createElement('div');
deniedLine.textContent = 'Access denied';
deniedLine.style.marginTop = '10px';
document.body.appendChild(deniedLine);
const newLoginLine = document.createElement('div');
newLoginLine.style.marginTop = '10px';
const newInput = document.createElement('input');
newInput.type = 'text';
newInput.style.background = 'transparent';
newInput.style.border = 'none';
newInput.style.outline = 'none';
newInput.style.color = '#fff';
newInput.style.fontFamily = 'monospace';
newInput.style.fontSize = '14px';
newInput.style.width = '300px';
newInput.style.caretColor = '#fff';
newInput.autofocus = true;
newLoginLine.appendChild(document.createTextNode('homelab login: '));
newLoginLine.appendChild(newInput);
document.body.appendChild(newLoginLine);
loginInput.remove();
newInput.focus();
newInput.addEventListener('keydown', handleLogin);
}
};
loginInput.addEventListener('keydown', handleLogin);
return;
} else {
isRoot = false;
}
const newLine = document.createElement('div');
newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
content.appendChild(newLine);
const newCursor = document.createElement('span');
newCursor.className = 'terminal-cursor';
newLine.appendChild(newCursor);
content.scrollTop = content.scrollHeight;
return;
}
if (cmdText === 'exit') {
if (!isRoot) {
const newAchievements = checkAchievements(cmdText, false);
if (newAchievements.length > 0) {
revealAchievements();
newAchievements.forEach(a => showToast(a));
}
isLoginScreen = true;
document.body.innerHTML = '';
document.body.style.background = '#000';
document.body.style.color = '#fff';
document.body.style.fontFamily = 'monospace';
document.body.style.padding = '20px';
document.body.style.minHeight = '100vh';
document.body.style.margin = '0';
document.body.style.lineHeight = '1.6';
const loginContainer = document.createElement('div');
loginContainer.style.marginBottom = '10px';
loginContainer.textContent = 'homelab tty1';
document.body.appendChild(loginContainer);
const loginInput = document.createElement('input');
loginInput.type = 'text';
loginInput.style.background = 'transparent';
loginInput.style.border = 'none';
loginInput.style.outline = 'none';
loginInput.style.color = '#fff';
loginInput.style.fontFamily = 'monospace';
loginInput.style.fontSize = '14px';
loginInput.style.width = '300px';
loginInput.style.caretColor = '#fff';
loginInput.autofocus = true;
const loginLine = document.createElement('div');
loginLine.style.marginBottom = '20px';
loginLine.appendChild(document.createTextNode('homelab login: '));
loginLine.appendChild(loginInput);
document.body.appendChild(loginLine);
loginInput.focus();
const handleLogin = (e) => {
if (e.key === 'Enter') {
const deniedLine = document.createElement('div');
deniedLine.textContent = 'Access denied';
deniedLine.style.marginTop = '10px';
document.body.appendChild(deniedLine);
const newLoginLine = document.createElement('div');
newLoginLine.style.marginTop = '10px';
const newInput = document.createElement('input');
newInput.type = 'text';
newInput.style.background = 'transparent';
newInput.style.border = 'none';
newInput.style.outline = 'none';
newInput.style.color = '#fff';
newInput.style.fontFamily = 'monospace';
newInput.style.fontSize = '14px';
newInput.style.width = '300px';
newInput.style.caretColor = '#fff';
newInput.autofocus = true;
newLoginLine.appendChild(document.createTextNode('homelab login: '));
newLoginLine.appendChild(newInput);
document.body.appendChild(newLoginLine);
loginInput.remove();
newInput.focus();
newInput.addEventListener('keydown', handleLogin);
}
};
loginInput.addEventListener('keydown', handleLogin);
return;
} else {
isRoot = false;
}
const newLine = document.createElement('div');
newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
content.appendChild(newLine);
const newCursor = document.createElement('span');
newCursor.className = 'terminal-cursor';
newLine.appendChild(newCursor);
content.scrollTop = content.scrollHeight;
return;
}
if (cmdText === 'rm -rf /') {
if (!isRoot) {
const outLine = document.createElement('div');
@@ -385,7 +385,7 @@ function createServerRack() {
document.title = '';
}, 500);
}
const newLine = document.createElement('div');
if (isRoot) {
newLine.innerHTML = '<span class="terminal-prompt">#</span> ';
@@ -398,25 +398,25 @@ function createServerRack() {
newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
newLine.appendChild(newCursor);
content.scrollTop = content.scrollHeight;
const newAchievements = checkAchievements(cmdText, isRoot);
if (newAchievements.length > 0) {
revealAchievements();
newAchievements.forEach(a => showToast(a));
}
return;
}
if (cmdText === 'sudo su -' || cmdText === 'sudo -i') {
const outLine = document.createElement('div');
outLine.style.whiteSpace = 'pre-wrap';
outLine.style.color = '#ef4444';
outLine.textContent = 'I hope you know what you\'re doing';
content.appendChild(outLine);
isRoot = true;
const newLine = document.createElement('div');
newLine.innerHTML = '<span class="terminal-prompt">#</span> ';
newLine.style.color = '#ef4444';
@@ -425,16 +425,16 @@ function createServerRack() {
newCursor.className = 'terminal-cursor red';
newLine.appendChild(newCursor);
content.scrollTop = content.scrollHeight;
const newAchievements = checkAchievements(cmdText, isRoot);
if (newAchievements.length > 0) {
revealAchievements();
newAchievements.forEach(a => showToast(a));
}
return;
}
const commands = {
'pwd': '/home/reese/portfolio',
'whoami': 'reese',
@@ -464,7 +464,7 @@ function createServerRack() {
'sl': '____\n|DD|____T_\n|_ |_____|<\n @-@-@-oo\\',
'help': 'Available commands:\n ls List directory contents\n pwd Print working directory\n whoami Print current user\n hostname Print hostname\n date Print current date/time\n uname Print system information\n uptime Print system uptime\n id Print user identity\n cat Print file contents (try: cat /etc/os-release)\n docker List running containers\n podman List running pods\n systemctl List running systemd services\n ss Show listening ports\n ip Show network interfaces\n df Show disk usage\n free Show memory usage\n ps Show running processes\n neofetch System info display\n sl Steam locomotive\n help Show this help message',
};
if (cmdText.startsWith('echo ')) {
const output = cmdText.replace(/^echo\s+/, '');
const outLine = document.createElement('div');
@@ -484,13 +484,13 @@ function createServerRack() {
}
content.appendChild(outLine);
}
const newAchievements = checkAchievements(cmdText, isRoot);
if (newAchievements.length > 0) {
revealAchievements();
newAchievements.forEach(a => showToast(a));
}
const newLine = document.createElement('div');
if (isRoot) {
newLine.innerHTML = '<span class="terminal-prompt">#</span> ';
@@ -524,7 +524,7 @@ function createServerRack() {
}
}
});
terminal.addEventListener('focus', () => {
mobileInput.focus();
terminal.style.boxShadow = '0 0 8px rgba(234, 179, 8, 0.3), inset 0 0 20px rgba(34, 197, 94, 0.1)';
@@ -538,7 +538,7 @@ function createServerRack() {
document.getElementById('hero').classList.add('shifted');
document.querySelector('.rack-container')?.classList.add('opaque');
});
terminal.addEventListener('blur', () => {
if (heroMouseDown) return;
terminal.style.boxShadow = '';
@@ -552,13 +552,13 @@ function createServerRack() {
document.getElementById('hero').classList.remove('shifted');
document.querySelector('.rack-container')?.classList.remove('opaque');
});
mobileInput.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
mobileInput.blur();
}
});
mobileInput.addEventListener('blur', () => {
if (heroMouseDown) return;
terminal.style.boxShadow = '';
@@ -572,17 +572,17 @@ function createServerRack() {
document.getElementById('hero').classList.remove('shifted');
document.querySelector('.rack-container')?.classList.remove('opaque');
});
let lastInputValue = '';
mobileInput.addEventListener('input', () => {
const lastLine = content.lastElementChild;
if (!lastLine) return;
const cursorEl = lastLine.querySelector('.terminal-cursor');
const inputText = mobileInput.value;
const addedText = inputText.slice(lastInputValue.length);
if (addedText) {
if (cursorEl) cursorEl.remove();
lastLine.insertAdjacentText('beforeend', addedText);
@@ -590,10 +590,10 @@ function createServerRack() {
newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
lastLine.appendChild(newCursor);
}
lastInputValue = inputText;
});
} else if (serverType < 0.35) {
// Vertical grill + fans
const grillV = document.createElement('div');
@@ -608,7 +608,7 @@ function createServerRack() {
grillV.style.top = '50%';
grillV.style.transform = 'translateY(-50%)';
face.appendChild(grillV);
const fanContainer = document.createElement('div');
fanContainer.className = 'fan-container';
fanContainer.style.position = 'absolute';
@@ -616,46 +616,46 @@ function createServerRack() {
fanContainer.style.top = '50%';
fanContainer.style.transform = 'translateY(-50%)';
fanContainer.style.zIndex = '1';
const fanCount = Math.floor(Math.random() * 2) + 1;
const fanSpeeds = ['fan-slow', 'fan-medium', 'fan-fast'];
for (let f = 0; f < fanCount; f++) {
const fan = document.createElement('div');
fan.className = `fan ${fanSpeeds[Math.floor(Math.random() * fanSpeeds.length)]}`;
const blade = document.createElement('div');
blade.className = 'fan-blade';
fan.appendChild(blade);
const center = document.createElement('div');
center.className = 'fan-center';
fan.appendChild(center);
fanContainer.appendChild(fan);
}
face.appendChild(fanContainer);
const ledGroup = document.createElement('div');
ledGroup.className = 'led-group';
ledGroup.style.position = 'absolute';
ledGroup.style.top = '8px';
ledGroup.style.left = '50%';
ledGroup.style.transform = 'translateX(-50%)';
const ledCount = Math.floor(Math.random() * 3) + 1;
const blinkClasses = ['led-blink-1', 'led-blink-2', 'led-blink-3', 'led-blink-4'];
const colorClasses = ['led-green', 'led-blue', 'led-yellow', 'led-red'];
for (let l = 0; l < ledCount; l++) {
const led = document.createElement('div');
led.className = `led ${colorClasses[Math.floor(Math.random() * colorClasses.length)]} ${blinkClasses[Math.floor(Math.random() * blinkClasses.length)]}`;
led.style.animationDelay = `${Math.random() * 3}s`;
ledGroup.appendChild(led);
}
face.appendChild(ledGroup);
} else if (serverType < 0.7) {
// Horizontal grill
const grillH = document.createElement('div');
@@ -670,27 +670,27 @@ function createServerRack() {
grillH.style.top = '50%';
grillH.style.transform = 'translate(-50%, -50%)';
face.appendChild(grillH);
const ledGroup = document.createElement('div');
ledGroup.className = 'led-group';
ledGroup.style.position = 'absolute';
ledGroup.style.right = '16px';
ledGroup.style.top = '50%';
ledGroup.style.transform = 'translateY(-50%)';
const ledCount = Math.floor(Math.random() * 3) + 1;
const blinkClasses = ['led-blink-1', 'led-blink-2', 'led-blink-3', 'led-blink-4'];
const colorClasses = ['led-green', 'led-blue', 'led-yellow', 'led-red'];
for (let l = 0; l < ledCount; l++) {
const led = document.createElement('div');
led.className = `led ${colorClasses[Math.floor(Math.random() * colorClasses.length)]} ${blinkClasses[Math.floor(Math.random() * blinkClasses.length)]}`;
led.style.animationDelay = `${Math.random() * 3}s`;
ledGroup.appendChild(led);
}
face.appendChild(ledGroup);
} else {
// Drive bays
const driveBayContainer = document.createElement('div');
@@ -701,7 +701,7 @@ function createServerRack() {
driveBayContainer.style.left = '50%';
driveBayContainer.style.top = '50%';
driveBayContainer.style.transform = 'translate(-50%, -50%)';
const driveBays = Math.floor(Math.random() * 3) + 6;
for (let b = 0; b < driveBays; b++) {
const bay = document.createElement('div');
@@ -709,60 +709,60 @@ function createServerRack() {
driveBayContainer.appendChild(bay);
}
face.appendChild(driveBayContainer);
const ledGroup = document.createElement('div');
ledGroup.className = 'led-group';
ledGroup.style.position = 'absolute';
ledGroup.style.right = '10px';
ledGroup.style.top = '50%';
ledGroup.style.transform = 'translateY(-50%)';
const ledCount = Math.floor(Math.random() * 3) + 1;
const blinkClasses = ['led-blink-1', 'led-blink-2', 'led-blink-3', 'led-blink-4'];
const colorClasses = ['led-green', 'led-blue', 'led-yellow', 'led-red'];
for (let l = 0; l < ledCount; l++) {
const led = document.createElement('div');
led.className = `led ${colorClasses[Math.floor(Math.random() * colorClasses.length)]} ${blinkClasses[Math.floor(Math.random() * blinkClasses.length)]}`;
led.style.animationDelay = `${Math.random() * 3}s`;
ledGroup.appendChild(led);
}
face.appendChild(ledGroup);
}
if (!isTerminal) {
const serviceLabel = document.createElement('div');
serviceLabel.className = 'service-label';
serviceLabel.textContent = services[Math.floor(Math.random() * services.length)];
face.appendChild(serviceLabel);
}
unit.appendChild(face);
}
rackContainer.appendChild(unit);
}
const bottomBar = document.createElement('div');
bottomBar.className = 'rack-bottom-bar';
rackContainer.appendChild(bottomBar);
bgContainer.appendChild(rackContainer);
let ticking = false;
// Update the parallax scroll position of the rack container
function updateParallax() {
const scrolled = window.pageYOffset;
const parallaxSpeed = 0.3;
const translateY = scrolled * parallaxSpeed;
rackContainer.style.transform = `translateX(-50%) translateY(${-translateY}px)`;
ticking = false;
}
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(updateParallax);
+141 -47
View File
@@ -1,4 +1,6 @@
*, *::before, *::after {
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
@@ -225,13 +227,11 @@ body {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0, 0, 0, 0.15) 2px,
rgba(0, 0, 0, 0.15) 4px
);
background: repeating-linear-gradient(0deg,
transparent,
transparent 2px,
rgba(0, 0, 0, 0.15) 2px,
rgba(0, 0, 0, 0.15) 4px);
z-index: 1;
pointer-events: none;
}
@@ -270,8 +270,15 @@ body {
}
@keyframes cursorBlink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
.eth-brand {
@@ -305,7 +312,7 @@ body {
position: relative;
display: flex;
align-items: center;
box-shadow:
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.03),
0 2px 8px rgba(0, 0, 0, 0.4);
overflow: visible;
@@ -506,8 +513,13 @@ body {
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.fan-slow {
@@ -572,25 +584,59 @@ body {
}
@keyframes blink1 {
0%, 100% { opacity: 1; }
50% { opacity: 0.2; }
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.2;
}
}
@keyframes blink2 {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
0%,
100% {
opacity: 0.3;
}
50% {
opacity: 1;
}
}
@keyframes blink3 {
0%, 100% { opacity: 1; }
30% { opacity: 0.1; }
60% { opacity: 0.8; }
0%,
100% {
opacity: 1;
}
30% {
opacity: 0.1;
}
60% {
opacity: 0.8;
}
}
@keyframes blink4 {
0%, 100% { opacity: 0.5; }
25% { opacity: 1; }
75% { opacity: 0.2; }
0%,
100% {
opacity: 0.5;
}
25% {
opacity: 1;
}
75% {
opacity: 0.2;
}
}
.rack-mount {
@@ -649,13 +695,11 @@ body {
left: 0;
right: 0;
bottom: 0;
background: repeating-linear-gradient(
180deg,
transparent,
transparent 20px,
rgba(0, 0, 0, 0.3) 20px,
rgba(0, 0, 0, 0.3) 21px
);
background: repeating-linear-gradient(180deg,
transparent,
transparent 20px,
rgba(0, 0, 0, 0.3) 20px,
rgba(0, 0, 0, 0.3) 21px);
}
.rack-label {
@@ -808,8 +852,15 @@ nav .nav-inner {
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.4;
}
}
.hero h1 {
@@ -1234,12 +1285,30 @@ section {
line-height: 1.8;
}
.code-keyword { color: #c084fc; }
.code-function { color: #60a5fa; }
.code-string { color: #34d399; }
.code-comment { color: #52525b; font-style: italic; }
.code-variable { color: #f472b6; }
.code-operator { color: #fbbf24; }
.code-keyword {
color: #c084fc;
}
.code-function {
color: #60a5fa;
}
.code-string {
color: #34d399;
}
.code-comment {
color: #52525b;
font-style: italic;
}
.code-variable {
color: #f472b6;
}
.code-operator {
color: #fbbf24;
}
.project-info {
padding: 1.5rem;
@@ -1625,6 +1694,7 @@ footer p {
opacity: 0;
transform: translateX(100px) scale(0.9);
}
to {
opacity: 1;
transform: translateX(0) scale(1);
@@ -1636,6 +1706,7 @@ footer p {
opacity: 1;
transform: translateX(0) scale(1);
}
to {
opacity: 0;
transform: translateX(100px) scale(0.9);
@@ -1679,14 +1750,37 @@ footer p {
transform: translateY(0);
}
.nav-links.active li:nth-child(1) { transition-delay: 0.05s; }
.nav-links.active li:nth-child(2) { transition-delay: 0.1s; }
.nav-links.active li:nth-child(3) { transition-delay: 0.15s; }
.nav-links.active li:nth-child(4) { transition-delay: 0.2s; }
.nav-links.active li:nth-child(5) { transition-delay: 0.25s; }
.nav-links.active li:nth-child(6) { transition-delay: 0.3s; }
.nav-links.active li:nth-child(7) { transition-delay: 0.35s; }
.nav-links.active li:nth-child(8) { transition-delay: 0.4s; }
.nav-links.active li:nth-child(1) {
transition-delay: 0.05s;
}
.nav-links.active li:nth-child(2) {
transition-delay: 0.1s;
}
.nav-links.active li:nth-child(3) {
transition-delay: 0.15s;
}
.nav-links.active li:nth-child(4) {
transition-delay: 0.2s;
}
.nav-links.active li:nth-child(5) {
transition-delay: 0.25s;
}
.nav-links.active li:nth-child(6) {
transition-delay: 0.3s;
}
.nav-links.active li:nth-child(7) {
transition-delay: 0.35s;
}
.nav-links.active li:nth-child(8) {
transition-delay: 0.4s;
}
.hamburger {
display: flex;
@@ -1780,4 +1874,4 @@ footer p {
.about-stats {
grid-template-columns: 1fr;
}
}
}