From 010758b3e959184887c1cd601714339f0a6af413 Mon Sep 17 00:00:00 2001 From: ducoterra Date: Fri, 18 Sep 2026 17:23:37 -0400 Subject: [PATCH] Move server rack inline styles to CSS classes Replace the per-element inline positioning in createServerRack() with rack-*-pos utility classes in style.css. Also stop drawing a random switch face brand from a list (only Framework ships) and simplify the hero-click terminal toggle to use the shared expand/collapse helpers. --- src/script.js | 72 ++++++++++++--------------------------------------- src/style.css | 55 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 57 deletions(-) diff --git a/src/script.js b/src/script.js index 90398ec..e36af63 100644 --- a/src/script.js +++ b/src/script.js @@ -60,7 +60,8 @@ function createServerRack() { const totalPageHeight = document.documentElement.scrollHeight; const totalUnits = Math.max(Math.ceil((totalPageHeight - 100 - barHeight) / unitHeight), 10); - const brands = ['Framework']; + // Only one brand in the rack for now + const RACK_BRAND = 'Framework'; const services = ['Borg', 'Gitea', 'Nextcloud', 'Jellyfin', 'Open WebUI', 'llama.cpp', 'Immich', 'LiteLLM', 'Caddy', 'Nginx', 'Samba', 'Slopbox']; @@ -88,7 +89,7 @@ function createServerRack() { const brandLabel = document.createElement('div'); brandLabel.className = 'eth-brand'; - brandLabel.textContent = brands[Math.floor(Math.random() * brands.length)]; + brandLabel.textContent = RACK_BRAND; switchFace.appendChild(brandLabel); const portCount = Math.floor(Math.random() * 4) + 5; @@ -139,19 +140,12 @@ function createServerRack() { bar.className = 'grill-v-bar'; grillV.appendChild(bar); } - grillV.style.position = 'absolute'; - grillV.style.left = '16px'; - grillV.style.top = '50%'; - grillV.style.transform = 'translateY(-50%)'; + grillV.classList.add('rack-grill-v-pos'); face.appendChild(grillV); const fanContainer = document.createElement('div'); fanContainer.className = 'fan-container'; - fanContainer.style.position = 'absolute'; - fanContainer.style.right = '16px'; - fanContainer.style.top = '50%'; - fanContainer.style.transform = 'translateY(-50%)'; - fanContainer.style.zIndex = '1'; + fanContainer.classList.add('rack-fans-pos'); const fanCount = Math.floor(Math.random() * 2) + 1; const fanSpeeds = ['fan-slow', 'fan-medium', 'fan-fast']; @@ -174,10 +168,7 @@ function createServerRack() { 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%)'; + ledGroup.classList.add('rack-leds-pos-top'); const ledCount = Math.floor(Math.random() * 3) + 1; const blinkClasses = ['led-blink-1', 'led-blink-2', 'led-blink-3', 'led-blink-4']; @@ -201,18 +192,12 @@ function createServerRack() { bar.className = 'grill-h-bar'; grillH.appendChild(bar); } - grillH.style.position = 'absolute'; - grillH.style.left = '50%'; - grillH.style.top = '50%'; - grillH.style.transform = 'translate(-50%, -50%)'; + grillH.classList.add('rack-grill-h-pos'); 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%)'; + ledGroup.classList.add('rack-leds-pos-right'); const ledCount = Math.floor(Math.random() * 3) + 1; const blinkClasses = ['led-blink-1', 'led-blink-2', 'led-blink-3', 'led-blink-4']; @@ -230,13 +215,7 @@ function createServerRack() { } else { // Drive bays const driveBayContainer = document.createElement('div'); - driveBayContainer.style.display = 'flex'; - driveBayContainer.style.gap = '8px'; - driveBayContainer.style.alignItems = 'center'; - driveBayContainer.style.position = 'absolute'; - driveBayContainer.style.left = '50%'; - driveBayContainer.style.top = '50%'; - driveBayContainer.style.transform = 'translate(-50%, -50%)'; + driveBayContainer.className = 'rack-drives-pos'; const driveBays = Math.floor(Math.random() * 3) + 6; for (let b = 0; b < driveBays; b++) { @@ -248,10 +227,7 @@ function createServerRack() { 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%)'; + ledGroup.classList.add('rack-leds-pos-right-tight'); const ledCount = Math.floor(Math.random() * 3) + 1; const blinkClasses = ['led-blink-1', 'led-blink-2', 'led-blink-3', 'led-blink-4']; @@ -319,28 +295,12 @@ heroEl.addEventListener('mouseup', () => { heroMouseDown = false; }); // Toggle terminal expansion when clicking the hero section heroEl.addEventListener('click', (e) => { if (e.target.closest('.btn')) return; - if (activeTerminal && activeTerminal._mobileInput) { - if (activeTerminal.classList.contains('grown')) { - activeTerminal.classList.remove('grown'); - activeTerminal.classList.remove('opaque'); - const face = activeTerminal.closest('.server-face'); - const unit = face?.closest('.rack-unit'); - face?.classList.remove('grown'); - unit?.classList.remove('grown'); - heroEl.classList.remove('shifted'); - activeTerminal._mobileInput.blur(); - document.querySelector('.rack-container')?.classList.remove('opaque'); - } else { - activeTerminal._mobileInput.focus(); - activeTerminal.classList.add('grown'); - activeTerminal.classList.add('opaque'); - const face = activeTerminal.closest('.server-face'); - const unit = face?.closest('.rack-unit'); - face?.classList.add('grown'); - unit?.classList.add('grown'); - heroEl.classList.add('shifted'); - document.querySelector('.rack-container')?.classList.add('opaque'); - } + if (!activeTerminal) return; + if (activeTerminal.classList.contains('grown')) { + collapseTerminal(activeTerminal); + activeTerminal._mobileInput?.blur(); + } else { + expandTerminal(activeTerminal); } }); diff --git a/src/style.css b/src/style.css index 55334b7..576e80a 100644 --- a/src/style.css +++ b/src/style.css @@ -1881,4 +1881,57 @@ footer p { .about-stats { grid-template-columns: 1fr; } -} \ No newline at end of file +} +/* Rack decoration placement (moved out of inline styles in script.js) */ +.rack-grill-v-pos { + position: absolute; + left: 16px; + top: 50%; + transform: translateY(-50%); +} + +.rack-grill-h-pos { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} + +.rack-fans-pos { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + z-index: 1; +} + +.rack-leds-pos-top { + position: absolute; + top: 8px; + left: 50%; + transform: translateX(-50%); +} + +.rack-leds-pos-right { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); +} + +.rack-leds-pos-right-tight { + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); +} + +.rack-drives-pos { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + display: flex; + gap: 8px; + align-items: center; +}