From 39407585f2682380f650c1cde0a72a72b7daaaba Mon Sep 17 00:00:00 2001
From: Raffael Sheikh
Date: Sun, 24 May 2026 00:07:24 +0200
Subject: [PATCH] Add subtle interface polish and clean URLs
---
public/datenschutz.html | 6 +-
public/gamejam.html | 71 ++++++++++++++---
public/impressum.html | 4 +-
public/index.html | 28 ++++---
public/script.js | 46 +++++++++++
public/styles.css | 171 +++++++++++++++++++++++++++++++++++++++-
public/techday.html | 16 ++--
server.js | 36 ++++++++-
8 files changed, 338 insertions(+), 40 deletions(-)
diff --git a/public/datenschutz.html b/public/datenschutz.html
index b7b8701..a9b4065 100644
--- a/public/datenschutz.html
+++ b/public/datenschutz.html
@@ -39,7 +39,7 @@
76646 Bruchsal
E-Mail: info@tool-ctrl.de
- Die vollständigen Anbieterangaben finden Sie im Impressum.
+ Die vollständigen Anbieterangaben finden Sie im Impressum.
2. Hosting und Server-Logfiles
@@ -158,8 +158,8 @@
© 2026 ToolCTRL
Startseite ·
- Impressum ·
- Datenschutz
+ Impressum ·
+ Datenschutz
diff --git a/public/gamejam.html b/public/gamejam.html
index 8157b2b..92fbb36 100644
--- a/public/gamejam.html
+++ b/public/gamejam.html
@@ -115,15 +115,18 @@
.hero .kicker {
font-family: 'Space Mono', monospace; font-size: 13px; letter-spacing: 4px;
text-transform: uppercase; color: var(--ac); margin-bottom: 26px;
+ animation: heroRise .24s cubic-bezier(.2, 0, 0, 1) both;
}
.hero h1 {
font-size: clamp(52px, 11vw, 142px); font-weight: 700; line-height: 0.93;
letter-spacing: -0.04em; text-transform: uppercase; margin-bottom: 24px;
+ animation: heroRise .24s cubic-bezier(.2, 0, 0, 1) .04s both;
}
.hero h1 .ln2 { color: var(--ac); }
.hero .hsub {
font-size: clamp(15px, 2vw, 19px); color: var(--muted);
max-width: 540px; margin-bottom: 56px;
+ animation: heroRise .24s cubic-bezier(.2, 0, 0, 1) .08s both;
}
.hero .hsub b { color: var(--text); font-weight: 600; }
@@ -132,6 +135,7 @@
position: relative; background: var(--panel);
border: 1px solid var(--line2); padding: 36px 56px;
min-width: min(560px, 92vw);
+ animation: heroRise .26s cubic-bezier(.2, 0, 0, 1) .12s both;
}
.hud .cn {
position: absolute; width: 14px; height: 14px;
@@ -159,6 +163,10 @@
font-family: 'Space Mono', monospace; font-weight: 700;
font-size: clamp(54px, 11vw, 108px); line-height: 1;
letter-spacing: -0.02em; color: var(--text);
+ font-variant-numeric: tabular-nums;
+ }
+ .hud .timer.tick {
+ animation: timerTick .16s cubic-bezier(.2, 0, 0, 1);
}
.hud .tl {
font-family: 'Space Mono', monospace; font-size: 11px; letter-spacing: 2px;
@@ -166,6 +174,7 @@
}
.hmeta {
margin-top: 44px; display: flex; gap: 14px; flex-wrap: wrap; justify-content: center;
+ animation: heroRise .24s cubic-bezier(.2, 0, 0, 1) .16s both;
}
.hmeta span {
display: inline-flex; align-items: center; gap: 8px;
@@ -199,6 +208,7 @@
.tl-row.done { opacity: 0.38; }
.tl-row.active {
background: var(--panel); border-left-color: var(--ac);
+ box-shadow: inset 10px 0 18px -18px rgba(0,0,0,.45);
}
.tl-row.active .tt { color: var(--ac); }
.tl-row.active .tn { color: var(--text); }
@@ -279,13 +289,20 @@
.field input {
width: 100%; background: var(--bg2); border: 1px solid var(--line2);
padding: 13px 15px; color: var(--text); font-size: 15px; font-family: inherit;
+ transition: border-color .15s ease, background .15s ease;
}
- .field input:focus { outline: none; border-color: var(--ac); }
+ .field input:focus { outline: none; border-color: var(--ac); background: #fff; }
.dropzone {
border: 1.5px dashed var(--line2); padding: 40px 24px; text-align: center;
- cursor: pointer; transition: all .15s; background: var(--bg2);
+ cursor: pointer;
+ transition: border-color .15s ease, background .15s ease, transform .15s ease;
+ background: var(--bg2);
+ }
+ .dropzone:hover, .dropzone.drag {
+ border-color: var(--ac);
+ background: var(--panel);
+ transform: translateY(-2px);
}
- .dropzone:hover, .dropzone.drag { border-color: var(--ac); background: var(--panel); }
.dropzone .dzi { color: var(--ac); margin-bottom: 12px; }
.dropzone .dzi svg.ic { width: 28px; height: 28px; }
.dropzone .big { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
@@ -294,9 +311,10 @@
background: var(--ac); color: #ffffff; border: none;
padding: 13px 30px; font-size: 14px; font-weight: 700; cursor: pointer;
font-family: inherit; text-transform: uppercase; letter-spacing: 1px;
- transition: opacity .15s;
+ transition: opacity .15s ease, transform .12s ease;
}
- .btn:hover { opacity: 0.82; }
+ .btn:hover { opacity: 0.82; transform: translateY(-1px); }
+ .btn:active { transform: scale(.96); }
.btn:disabled { background: var(--line2); color: var(--muted); cursor: not-allowed; }
.status {
font-family: 'Space Mono', monospace; font-size: 13px; margin-top: 16px; min-height: 20px;
@@ -310,8 +328,9 @@
padding: 10px 16px; font-size: 12px; font-weight: 600; cursor: pointer;
font-family: 'Space Mono', monospace; text-transform: uppercase; letter-spacing: 1px;
display: inline-flex; align-items: center; gap: 8px;
+ transition: border-color .15s ease, transform .12s ease;
}
- .btn-ghost:hover { border-color: var(--ac); }
+ .btn-ghost:hover { border-color: var(--ac); transform: translateY(-1px); }
.btn-ghost svg.ic { width: 13px; height: 13px; }
.games { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 6px; }
@@ -346,6 +365,15 @@
letter-spacing: 0.5px;
}
+ @keyframes heroRise {
+ from { opacity: 0; transform: translateY(6px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
+ @keyframes timerTick {
+ from { opacity: .78; }
+ to { opacity: 1; }
+ }
+
@media (max-width: 820px) {
.steps { grid-template-columns: 1fr; }
.step + .step { padding-left: 0; border-left: none; border-top: 1px solid var(--line); }
@@ -358,6 +386,17 @@
section { padding: 70px 0; }
.topbar .ev { display: none; }
}
+
+ @media (prefers-reduced-motion: reduce) {
+ html { scroll-behavior: auto; }
+ *,
+ *::before,
+ *::after {
+ animation-duration: .001ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: .001ms !important;
+ }
+ }
@@ -585,13 +624,13 @@ function renderHud() {
nowLabelEl.innerHTML = DOT + "Startet bald";
nameEl.textContent = "Gleich geht's los";
subEl.textContent = "Die AI GameJam beginnt um " + PHASES[0].t + " Uhr";
- timerEl.textContent = fmt(start - now);
+ setTimerText(timerEl, fmt(start - now));
timerLabelEl.textContent = "bis Start";
} else if (now >= end) {
nowLabelEl.innerHTML = DOT + "Vorbei";
nameEl.textContent = "Event beendet";
subEl.textContent = "Danke an alle — die Games gibt's unten zum Spielen";
- timerEl.textContent = "//";
+ setTimerText(timerEl, "//");
timerLabelEl.textContent = "bis bald";
} else {
let idx = 0;
@@ -603,14 +642,26 @@ function renderHud() {
nameEl.textContent = cur.name;
subEl.textContent = cur.sub;
if (next) {
- timerEl.textContent = fmt(phaseDate(next.t) - now);
+ setTimerText(timerEl, fmt(phaseDate(next.t) - now));
timerLabelEl.textContent = "bis: " + next.name;
- } else { timerEl.textContent = ""; timerLabelEl.textContent = ""; }
+ } else { setTimerText(timerEl, ""); timerLabelEl.textContent = ""; }
}
renderSchedule(now);
}
const CHECK = '';
+let lastTimerText = "";
+
+function setTimerText(el, text) {
+ if (el.textContent === text) return;
+ el.textContent = text;
+ if (lastTimerText) {
+ el.classList.remove("tick");
+ void el.offsetWidth;
+ el.classList.add("tick");
+ }
+ lastTimerText = text;
+}
function renderSchedule(now) {
const box = document.getElementById("schedule");
diff --git a/public/impressum.html b/public/impressum.html
index 84ea71c..5e00ffa 100644
--- a/public/impressum.html
+++ b/public/impressum.html
@@ -93,8 +93,8 @@
© 2026 ToolCTRL
Startseite ·
- Impressum ·
- Datenschutz
+ Impressum ·
+ Datenschutz
diff --git a/public/index.html b/public/index.html
index fe38668..b42dd89 100644
--- a/public/index.html
+++ b/public/index.html
@@ -20,8 +20,8 @@
Leistungen
Vorgehen
Organisation
- TechDay
- GameJam
+ TechDay
+ GameJam
Kontakt aufnehmen