From de95879baf0355d402b7eaf0f8cd3e309e24fc40 Mon Sep 17 00:00:00 2001 From: lauriliikane Date: Tue, 18 Aug 2026 20:30:56 +0000 Subject: [PATCH] Refactor duplicated CSS/JS patterns into shared rules and tokens Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- index.html | 85 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/index.html b/index.html index eb4c6b4..17e27f8 100644 --- a/index.html +++ b/index.html @@ -19,8 +19,12 @@ --accent: #7c9cff; --accent-2: #57e1c1; --border: rgba(255, 255, 255, 0.1); + --surface: rgba(255, 255, 255, 0.05); --shadow: 0 18px 60px rgba(0, 0, 0, 0.35); --radius: 24px; + --radius-lg: 28px; + --radius-pill: 999px; + --ease: 0.2s ease; } * { box-sizing: border-box; } @@ -48,10 +52,32 @@ background: rgba(7, 17, 31, 0.65); border-bottom: 1px solid rgba(255, 255, 255, 0.06); } - .nav-inner { + /* Shared surface: translucent panel used by pills, stats and list rows. */ + .eyebrow, .stat, .work-item { + background: var(--surface); + border: 1px solid var(--border); + } + + /* Shared panel: larger translucent card with elevation. */ + .hero-card, .contact, .contact-card { + border: 1px solid var(--border); + border-radius: var(--radius-lg); + } + + /* Shared row: label/value split onto opposite ends of a line. */ + .nav-inner, .section-head, .work-item { display: flex; - align-items: center; justify-content: space-between; + } + + /* Shared centering for the hero avatar layers. */ + .avatar, .avatar-inner { + display: grid; + place-items: center; + } + + .nav-inner { + align-items: center; gap: 16px; padding: 16px 0; } @@ -87,16 +113,14 @@ align-items: center; gap: 10px; padding: 10px 14px; - border: 1px solid var(--border); - background: rgba(255, 255, 255, 0.05); - border-radius: 999px; + border-radius: var(--radius-pill); color: var(--muted); font-size: 0.95rem; } .eyebrow-dot { width: 10px; height: 10px; - border-radius: 999px; + border-radius: var(--radius-pill); background: linear-gradient(135deg, var(--accent), var(--accent-2)); box-shadow: 0 0 0 8px rgba(124, 156, 255, 0.12); } @@ -123,7 +147,7 @@ border-radius: 16px; font-weight: 700; border: 1px solid transparent; - transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease; + transition: transform var(--ease), border-color var(--ease), background var(--ease); } .btn:hover { transform: translateY(-2px); } .btn-primary { @@ -139,8 +163,6 @@ .hero-card { background: linear-gradient(180deg, rgba(255,255,255,0.08), rgba(255,255,255,0.04)); - border: 1px solid rgba(255,255,255,0.1); - border-radius: 28px; padding: 22px; box-shadow: var(--shadow); position: relative; @@ -162,12 +184,10 @@ .avatar { aspect-ratio: 1; width: 100%; - border-radius: 24px; + border-radius: var(--radius); background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.18), transparent 24%), linear-gradient(145deg, rgba(124,156,255,0.9), rgba(87,225,193,0.85)); - display: grid; - place-items: center; min-height: 310px; } .avatar-inner { @@ -176,8 +196,6 @@ border-radius: 32px; background: rgba(7, 17, 31, 0.35); border: 1px solid rgba(255,255,255,0.15); - display: grid; - place-items: center; text-align: center; padding: 22px; backdrop-filter: blur(12px); @@ -191,8 +209,6 @@ } .stat { padding: 16px; - background: rgba(255,255,255,0.05); - border: 1px solid var(--border); border-radius: 18px; text-align: center; } @@ -201,8 +217,6 @@ section { padding: 28px 0; } .section-head { - display: flex; - justify-content: space-between; gap: 14px; align-items: end; margin-bottom: 18px; @@ -228,21 +242,17 @@ .work-list { display: grid; gap: 14px; } .work-item { - display: flex; - justify-content: space-between; gap: 16px; align-items: center; padding: 18px 20px; border-radius: 20px; - background: rgba(255,255,255,0.05); - border: 1px solid var(--border); } .work-item strong { display: block; margin-bottom: 6px; } .work-item span { color: var(--muted); } .tag { flex: none; padding: 10px 14px; - border-radius: 999px; + border-radius: var(--radius-pill); background: rgba(124,156,255,0.14); border: 1px solid rgba(124,156,255,0.22); color: #dce6ff; @@ -254,8 +264,6 @@ text-align: center; padding: 30px; background: linear-gradient(180deg, rgba(124,156,255,0.13), rgba(87,225,193,0.08)); - border: 1px solid var(--border); - border-radius: 28px; } .contact p { color: var(--muted); max-width: 760px; margin: 12px auto 24px; line-height: 1.8; } @@ -265,8 +273,6 @@ .contact-card { background: rgba(255, 255, 255, 0.06); - border: 1px solid rgba(255, 255, 255, 0.12); - border-radius: 28px; padding: 28px; backdrop-filter: blur(14px); box-shadow: 0 18px 60px rgba(0, 0, 0, 0.25); @@ -311,7 +317,7 @@ padding: 14px 16px; font: inherit; outline: none; - transition: border-color 0.2s ease, transform 0.2s ease, background 0.2s ease; + transition: border-color var(--ease), transform var(--ease), background var(--ease); } .field input::placeholder, @@ -553,25 +559,28 @@

Kirjuta ja küsi nõu

const successMsg = document.getElementById('formSuccess'); const errorMsg = document.getElementById('formError'); + const showFormMessage = (visibleMsg) => { + [successMsg, errorMsg].forEach((msg) => { + msg.hidden = msg !== visibleMsg; + }); + }; + form.addEventListener('submit', async (e) => { e.preventDefault(); - successMsg.hidden = true; - errorMsg.hidden = true; - const formData = new FormData(form); + showFormMessage(null); try { const response = await fetch(form.action, { method: form.method, - body: formData, + body: new FormData(form), headers: { Accept: 'application/json' } }); - if (response.ok) { - form.reset(); - successMsg.hidden = false; - } else { - errorMsg.hidden = false; + if (!response.ok) { + throw new Error('Request failed: ' + response.status); } + form.reset(); + showFormMessage(successMsg); } catch (err) { - errorMsg.hidden = false; + showFormMessage(errorMsg); } });