diff --git a/pepsi.jpg b/Pepsi/Pepsi-1.jpg similarity index 100% rename from pepsi.jpg rename to Pepsi/Pepsi-1.jpg diff --git a/Pepsi/Pepsi-10.jpg b/Pepsi/Pepsi-10.jpg new file mode 100644 index 0000000..20ce575 Binary files /dev/null and b/Pepsi/Pepsi-10.jpg differ diff --git a/Pepsi/Pepsi-11.jpg b/Pepsi/Pepsi-11.jpg new file mode 100644 index 0000000..761b2c9 Binary files /dev/null and b/Pepsi/Pepsi-11.jpg differ diff --git a/Pepsi/Pepsi-12.jpg b/Pepsi/Pepsi-12.jpg new file mode 100644 index 0000000..9122fbd Binary files /dev/null and b/Pepsi/Pepsi-12.jpg differ diff --git a/Pepsi/Pepsi-13.jpg b/Pepsi/Pepsi-13.jpg new file mode 100644 index 0000000..c2896b4 Binary files /dev/null and b/Pepsi/Pepsi-13.jpg differ diff --git a/Pepsi/Pepsi-14.jpg b/Pepsi/Pepsi-14.jpg new file mode 100644 index 0000000..e5c6935 Binary files /dev/null and b/Pepsi/Pepsi-14.jpg differ diff --git a/Pepsi/Pepsi-15.jpg b/Pepsi/Pepsi-15.jpg new file mode 100644 index 0000000..845fb07 Binary files /dev/null and b/Pepsi/Pepsi-15.jpg differ diff --git a/Pepsi/Pepsi-2.jpg b/Pepsi/Pepsi-2.jpg new file mode 100644 index 0000000..8f991e8 Binary files /dev/null and b/Pepsi/Pepsi-2.jpg differ diff --git a/Pepsi/Pepsi-3.jpg b/Pepsi/Pepsi-3.jpg new file mode 100644 index 0000000..bcbb714 Binary files /dev/null and b/Pepsi/Pepsi-3.jpg differ diff --git a/Pepsi/Pepsi-4.jpg b/Pepsi/Pepsi-4.jpg new file mode 100644 index 0000000..f316b5f Binary files /dev/null and b/Pepsi/Pepsi-4.jpg differ diff --git a/Pepsi/Pepsi-5.jpg b/Pepsi/Pepsi-5.jpg new file mode 100644 index 0000000..f3422a6 Binary files /dev/null and b/Pepsi/Pepsi-5.jpg differ diff --git a/Pepsi/Pepsi-6.jpg b/Pepsi/Pepsi-6.jpg new file mode 100644 index 0000000..a4d4497 Binary files /dev/null and b/Pepsi/Pepsi-6.jpg differ diff --git a/Pepsi/Pepsi-7.jpg b/Pepsi/Pepsi-7.jpg new file mode 100644 index 0000000..976b5a5 Binary files /dev/null and b/Pepsi/Pepsi-7.jpg differ diff --git a/Pepsi/Pepsi-8.jpg b/Pepsi/Pepsi-8.jpg new file mode 100644 index 0000000..71be080 Binary files /dev/null and b/Pepsi/Pepsi-8.jpg differ diff --git a/Pepsi/Pepsi-9.jpg b/Pepsi/Pepsi-9.jpg new file mode 100644 index 0000000..14600fd Binary files /dev/null and b/Pepsi/Pepsi-9.jpg differ diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..c77e39d Binary files /dev/null and b/favicon.ico differ diff --git a/fonts/dm-mono-400.woff2 b/fonts/dm-mono-400.woff2 new file mode 100644 index 0000000..03e4859 Binary files /dev/null and b/fonts/dm-mono-400.woff2 differ diff --git a/fonts/dm-mono-500.woff2 b/fonts/dm-mono-500.woff2 new file mode 100644 index 0000000..67698d8 Binary files /dev/null and b/fonts/dm-mono-500.woff2 differ diff --git a/fonts/firacode-400.woff2 b/fonts/firacode-400.woff2 deleted file mode 100644 index 383fa3a..0000000 Binary files a/fonts/firacode-400.woff2 and /dev/null differ diff --git a/fonts/firacode-500.woff2 b/fonts/firacode-500.woff2 deleted file mode 100644 index 6012445..0000000 Binary files a/fonts/firacode-500.woff2 and /dev/null differ diff --git a/fonts/fonts.css b/fonts/fonts.css index d811972..a86f950 100644 --- a/fonts/fonts.css +++ b/fonts/fonts.css @@ -1,28 +1,12 @@ @font-face { - font-family: 'Outfit'; font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/outfit-400.woff2') format('woff2'); + font-family: 'Space Grotesk'; font-style: normal; font-weight: 300 700; font-display: swap; + src: url('/fonts/space-grotesk-var.woff2') format('woff2-variations'); } @font-face { - font-family: 'Outfit'; font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/outfit-500.woff2') format('woff2'); + font-family: 'DM Mono'; font-style: normal; font-weight: 400; font-display: swap; + src: url('/fonts/dm-mono-400.woff2') format('woff2'); } @font-face { - font-family: 'Outfit'; font-style: normal; font-weight: 700; font-display: swap; - src: url('/fonts/outfit-700.woff2') format('woff2'); + font-family: 'DM Mono'; font-style: normal; font-weight: 500; font-display: swap; + src: url('/fonts/dm-mono-500.woff2') format('woff2'); } -@font-face { - font-family: 'Outfit'; font-style: normal; font-weight: 800; font-display: swap; - src: url('/fonts/outfit-800.woff2') format('woff2'); -} -@font-face { - font-family: 'Outfit'; font-style: normal; font-weight: 900; font-display: swap; - src: url('/fonts/outfit-900.woff2') format('woff2'); -} -@font-face { - font-family: 'Fira Code'; font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/firacode-400.woff2') format('woff2'); -} -@font-face { - font-family: 'Fira Code'; font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/firacode-500.woff2') format('woff2'); -} \ No newline at end of file diff --git a/fonts/outfit-400.woff2 b/fonts/outfit-400.woff2 deleted file mode 100644 index 2c401f5..0000000 Binary files a/fonts/outfit-400.woff2 and /dev/null differ diff --git a/fonts/outfit-500.woff2 b/fonts/outfit-500.woff2 deleted file mode 100644 index 264ce74..0000000 Binary files a/fonts/outfit-500.woff2 and /dev/null differ diff --git a/fonts/outfit-700.woff2 b/fonts/outfit-700.woff2 deleted file mode 100644 index 8674e73..0000000 Binary files a/fonts/outfit-700.woff2 and /dev/null differ diff --git a/fonts/outfit-800.woff2 b/fonts/outfit-800.woff2 deleted file mode 100644 index fddb805..0000000 Binary files a/fonts/outfit-800.woff2 and /dev/null differ diff --git a/fonts/outfit-900.woff2 b/fonts/outfit-900.woff2 deleted file mode 100644 index 768bdf9..0000000 Binary files a/fonts/outfit-900.woff2 and /dev/null differ diff --git a/fonts/space-grotesk-var.woff2 b/fonts/space-grotesk-var.woff2 new file mode 100644 index 0000000..0f3474e Binary files /dev/null and b/fonts/space-grotesk-var.woff2 differ diff --git a/index.html b/index.html index 451d83d..0e8651c 100644 --- a/index.html +++ b/index.html @@ -15,7 +15,12 @@ - + + + + + + @@ -48,7 +53,7 @@
-

Nikolaj Gade

+

Nikolaj Gade

Software Developer

they/them · he/him

@@ -68,7 +73,7 @@ LinkedIn - + nikolaj@gade.gg
@@ -77,7 +82,7 @@
- Nikolaj Gade, a very handsome (and extremely hireable) person. + Nikolaj Gade, a very handsome (and extremely hireable) person.
@@ -100,7 +105,7 @@
- Pepsi, a black cat with large yellow eyes. + Pepsi, a black cat with large yellow eyes.

Full name: Pepsi Max Lime Gade

diff --git a/script.js b/script.js index 63fad0a..4d8e625 100644 --- a/script.js +++ b/script.js @@ -3,7 +3,8 @@ const canvas = document.getElementById('bgCanvas'); const ctx = canvas.getContext('2d'); - const COLORS = ['#e63946', '#f4722b', '#ffbe0b', '#ff006e', '#e07b39', '#ffd166']; + const COLORS = ['#ffd84d', '#8cbcff', '#ff9fca', '#a9e76c', '#b99cff', '#ff9d57']; + const INK = '#171717'; const COUNT = 1000; // number of sprinkles const MIN_LEN = 12; // px const MAX_LEN = 18; // px @@ -63,10 +64,14 @@ ctx.beginPath(); ctx.moveTo(0, -s.len / 2); ctx.lineTo(0, s.len / 2); - ctx.strokeStyle = s.color; - ctx.lineWidth = s.width; ctx.lineCap = 'round'; ctx.globalAlpha = s.alpha; + // Ink outline under the colored fill (sticker look): same path, two strokes + ctx.strokeStyle = INK; + ctx.lineWidth = s.width + 3; + ctx.stroke(); + ctx.strokeStyle = s.color; + ctx.lineWidth = s.width; ctx.stroke(); ctx.restore(); @@ -223,3 +228,59 @@ }); })(); + + +// ── Pepsi gallery: shuffled on load, swipe cycles through on click ─ +(function () { + const COUNT = 15; + const img = document.querySelector('.pepsi-placeholder img'); + if (!img) return; + const box = img.parentElement; + const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); + const src = (n) => `Pepsi/Pepsi-${n}.jpg`; + + // Fisher–Yates shuffle of [1..COUNT]; clicks cycle through this order + const order = Array.from({ length: COUNT }, (_, i) => i + 1); + for (let i = order.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [order[i], order[j]] = [order[j], order[i]]; + } + let pos = 0; + img.src = src(order[pos]); + + let busy = false; + box.addEventListener('click', () => { + if (busy) return; + pos = (pos + 1) % order.length; + const next = order[pos]; + + if (reduceMotion.matches) { + img.src = src(next); + return; + } + + busy = true; + const incoming = new Image(); + incoming.src = src(next); + incoming.alt = img.alt; + incoming.draggable = false; + incoming.className = 'pepsi-incoming'; + // Decode before animating so the swipe never reveals a half-loaded frame + incoming.decode().then(() => { + box.appendChild(incoming); + const opts = { duration: 300, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' }; + img.animate( + [{ transform: 'translateX(0)' }, { transform: 'translateX(-100%)' }], + opts + ); + incoming.animate( + [{ transform: 'translateX(100%)' }, { transform: 'translateX(0)' }], + opts + ).finished.then(() => { + img.src = incoming.src; // already decoded, swaps instantly + incoming.remove(); + busy = false; + }); + }).catch(() => { busy = false; }); + }); +})(); diff --git a/style.css b/style.css index a85ca57..1aab8f2 100644 --- a/style.css +++ b/style.css @@ -1,25 +1,29 @@ :root { - --red: #e63946; - --orange: #f4722b; - --orange-deep: #a84a0c; /* text-safe orange: ≥4.5:1 on cream */ - --yellow: #ffbe0b; - --pink: #ff006e; - --cream: #fefee3; - --ink: #1a0a00; - --ink-soft: #3d2010; - --glass-bg: rgba(254, 254, 227, 0.75); - --glass-border: rgba(244, 114, 43, 0.25); - --card-shadow: 0 8px 32px rgba(230, 57, 70, 0.10); - --grad: linear-gradient(135deg, var(--red), var(--orange), var(--yellow)); - --font: 'Outfit', sans-serif; - --mono: 'Fira Code', monospace; - --radius-sm: 6px; - --radius-md: 12px; - --radius-lg: 18px; - --radius-pill: 999px; - --nav-h: 64px; - --max-w: 1100px; - --ease: cubic-bezier(0.25, 0.46, 0.45, 0.94); + --ink: #171717; + --paper: #f4efe4; + --white: #fffdf8; + --yellow: #ffd84d; + --blue: #8cbcff; + --pink: #ff9fca; + --green: #a9e76c; + --purple: #b99cff; + --orange: #ff9d57; + --accent: #d75d35; /* display-size fills only: 3.3:1 on paper, fails AA as small text */ + + --border: 3px solid var(--ink); + --border-thin: 2px solid var(--ink); + --shadow: 7px 7px 0 var(--ink); + --shadow-sm: 4px 4px 0 var(--ink); + --radius-lg: 18px; + --radius-md: 8px; + --radius-pill: 999px; + + --font: 'Space Grotesk', sans-serif; + --mono: 'DM Mono', monospace; + + --nav-h: 64px; + --max-w: 1100px; + --ease: cubic-bezier(0.25, 0.46, 0.45, 0.94); } /* ── Reset ──────────────────────────────────────────────────── */ @@ -27,9 +31,9 @@ html { scroll-behavior: smooth; font-size: 17px; } body { font-family: var(--font); - background: var(--cream); + background: var(--paper); color: var(--ink); - line-height: 1.7; + line-height: 1.6; overflow-x: hidden; -webkit-font-smoothing: antialiased; } @@ -37,6 +41,11 @@ a { color: inherit; text-decoration: none; } ul { list-style: none; } button { font-family: var(--font); cursor: pointer; border: none; background: none; } +a:focus-visible, button:focus-visible, [data-tip]:focus-visible { + outline: 3px solid var(--ink); + outline-offset: 3px; +} + /* ── Canvas ─────────────────────────────────────────────────── */ #bgCanvas { position: fixed; @@ -44,22 +53,21 @@ button { font-family: var(--font); cursor: pointer; border: none; background: no width: 100%; height: 100%; z-index: 0; pointer-events: none; - opacity: 0.3; + opacity: 0.45; } /* ── Nav ────────────────────────────────────────────────────── */ #header { - background: rgba(254, 254, 227, 0); + background: transparent; + border-bottom: 3px solid transparent; position: fixed; top: 0; left: 0; right: 0; height: var(--nav-h); z-index: 1000; - transition: background 0.3s, box-shadow 0.3s; + transition: background 0.3s, border-color 0.3s; } #header.scrolled { - backdrop-filter: blur(30px); - -webkit-backdrop-filter: blur(30px); - background: rgba(254, 254, 227, 0.75); - box-shadow: 0 2px 20px rgba(230, 57, 70, 0.08); + background: var(--paper); + border-bottom-color: var(--ink); } nav { max-width: var(--max-w); @@ -72,10 +80,8 @@ nav { font-size: 1.2rem; font-weight: 700; color: var(--ink); - transition: color 0.2s; } -.nav-logo .bracket { color: var(--orange); } -.nav-logo:hover { color: var(--red); } +.nav-logo .bracket { color: var(--accent); } .nav-links { display: flex; gap: 0.1rem; } @@ -90,36 +96,32 @@ nav { } } .nav-link { - font-weight: 700; - font-size: 0.75rem; - letter-spacing: 0.05em; + font-family: var(--mono); + font-weight: 500; + font-size: 0.76rem; + letter-spacing: 0.08em; text-transform: uppercase; padding: 0.5rem 0.75rem; - border-radius: var(--radius-sm); - color: var(--ink-soft); + color: var(--ink); position: relative; - transition: color 0.2s; } .nav-link::after { content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%); - width: 0; height: 2px; - background: var(--grad); - border-radius: var(--radius-pill); + width: 0; height: 3px; + background: var(--ink); transition: width 0.25s var(--ease); } -.nav-link:hover, -.nav-link.active { color: var(--red); } .nav-link:hover::after, .nav-link.active::after { width: 70%; } .burger { display: none; flex-direction: column; gap: 5px; padding: 8px; } -.burger span { display: block; width: 22px; height: 2px; background: var(--ink); border-radius: var(--radius-pill); transition: all 0.3s var(--ease); } -.burger.open span:nth-child(1) { transform: rotate(45deg) translate(5px, 5px); } +.burger span { display: block; width: 22px; height: 3px; background: var(--ink); transition: all 0.3s var(--ease); } +.burger.open span:nth-child(1) { transform: rotate(45deg) translate(5.5px, 5.5px); } .burger.open span:nth-child(2) { opacity: 0; } -.burger.open span:nth-child(3) { transform: rotate(-45deg) translate(5px, -5px); } +.burger.open span:nth-child(3) { transform: rotate(-45deg) translate(5.5px, -5.5px); } /* ── Layout ─────────────────────────────────────────────────── */ main { position: relative; z-index: 1; } @@ -127,18 +129,18 @@ main { position: relative; z-index: 1; } .section { padding: 7rem 0; position: relative; - background: rgba(254, 254, 227, 0.5); } .section-inner { max-width: var(--max-w); margin: 0 auto; padding: 0 2rem; } .section-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem; } .section-title { - font-size: clamp(1.8rem, 3vw, 2.4rem); - font-weight: 900; - letter-spacing: -0.02em; + font-size: clamp(2.2rem, 4vw, 3.2rem); + font-weight: 700; + letter-spacing: -0.055em; + line-height: 1; white-space: nowrap; } -.section-rule { flex: 1; height: 2px; background: linear-gradient(to right, var(--orange), transparent); border-radius: var(--radius-pill); } +.section-rule { flex: 1; height: 3px; background: var(--ink); } /* ── Hero ───────────────────────────────────────────────────── */ .hero { @@ -154,19 +156,26 @@ main { position: relative; z-index: 1; } .hero-visual { flex: 0 0 300px; display: flex; align-items: center; justify-content: center; position: relative; } .hero-name { - font-size: clamp(3rem, 5.5vw, 5rem); - font-weight: 900; - line-height: 1; - letter-spacing: -0.03em; + font-size: clamp(2.8rem, 5.5vw, 5rem); + font-weight: 700; + line-height: 0.88; + letter-spacing: -0.06em; margin-top: 3rem; - margin-bottom: 0.75rem; + margin-bottom: 1rem; +} +.hero-name-accent { + color: var(--accent); + -webkit-text-stroke: 2px var(--ink); + text-shadow: 4px 4px 0 var(--yellow); } .hero-role { - font-size: clamp(1rem, 2vw, 1.3rem); - font-weight: 700; - color: var(--orange-deep); + font-family: var(--mono); + font-weight: 500; + font-size: 0.9rem; + color: var(--ink); + margin-left: 0.5rem; margin-bottom: 0.5rem; - letter-spacing: 0.06em; + letter-spacing: 0.08em; text-transform: uppercase; } /* Hero social links */ @@ -179,55 +188,59 @@ main { position: relative; z-index: 1; } display: inline-flex; align-items: center; gap: 0.5rem; - padding: 0.5rem 1rem; + padding: 0.6rem 1.1rem; border-radius: var(--radius-pill); font-size: 0.85rem; font-weight: 700; letter-spacing: 0.03em; - border: 1.5px solid var(--glass-border); - background: var(--glass-bg); - backdrop-filter: blur(8px); + border: var(--border); + background: var(--white); + box-shadow: var(--shadow-sm); color: var(--ink); - transition: all 0.2s var(--ease); + /* No transform/box-shadow transition: interpolating a hard offset shadow + against a composited translate causes subpixel jitter — snap instead */ + transition: background 150ms ease; } -.hero-link i { color: var(--orange); font-size: 0.9rem; } -.hero-link:hover { - background: var(--orange); - border-color: var(--orange); - color: #fff; - transform: translateY(-2px); +.hero-link i { color: var(--ink); font-size: 0.9rem; } +/* Oversized invisible hit area: the hover/active translate is ±2px, so + without this the edge retreats from the cursor and hover flickers. + will-change keeps the buttons on a compositor layer at rest, so applying + the hover transform doesn't re-rasterize (and shift) their contents */ +.hero-link, .project-link { position: relative; will-change: transform; } +.hero-link::after, .project-link::after { + content: ''; + position: absolute; + inset: -4px; + border-radius: inherit; } -.hero-link:hover i { color: #fff; } +.hero-link--primary { background: var(--yellow); } +.hero-link:hover { transform: translate(-2px, -2px); box-shadow: 5px 5px 0 var(--ink); } +.hero-link:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); } -.gitea-bg { fill: white; } -.gitea-fg { fill: var(--orange); } - -.hero-link:hover .gitea-bg { fill: var(--orange); } -.hero-link:hover .gitea-fg { fill: white; } +.gitea-bg { fill: var(--white); } +.gitea-fg { fill: var(--ink); } /* Avatar */ .avatar-ring { width: 350px; height: 350px; border-radius: 50%; position: relative; - background: var(--glass-bg); - border: 2px solid var(--glass-border); - backdrop-filter: blur(12px); + background: var(--white); + border: var(--border); + box-shadow: var(--shadow); + overflow: hidden; display: flex; align-items: center; justify-content: center; } - .avatar-placeholder { - width: 330px; height: 330px; + width: 100%; height: 100%; border-radius: 50%; - background: rgba(255, 255, 255, 0.35); - display: flex; align-items: center; justify-content: center; - font-size: 4.5rem; - color: rgba(244, 114, 43, 0.45); overflow: hidden; } .avatar-placeholder img { width: 100%; height: 100%; object-fit: cover; } -.avatar-ring.spinning { animation: avatarSpin 0.8s var(--ease); } +/* Spin the image inside the ring, not the ring itself: the ring's hard + offset shadow would visibly orbit if the shadowed element rotated */ +.avatar-ring.spinning .avatar-placeholder { animation: avatarSpin 0.8s var(--ease); } /* rotate is only keyed at 0%/100% so it sweeps through the scale midpoint without easing to a stop at 180° */ @keyframes avatarSpin { @@ -236,13 +249,14 @@ main { position: relative; z-index: 1; } 100% { rotate: 360deg; scale: 1; } } @media (prefers-reduced-motion: reduce) { - .avatar-ring.spinning { animation: none; } + .avatar-ring.spinning .avatar-placeholder { animation: none; } } .hero-pronouns { - font-size: 0.85rem; - color: var(--ink-soft); + font-family: var(--mono); + font-size: 0.78rem; + color: var(--ink); margin-left: 0.5rem; margin-bottom: 0.75rem; letter-spacing: 0.06em; @@ -251,52 +265,79 @@ main { position: relative; z-index: 1; } /* ── About ──────────────────────────────────────────────────── */ .about-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3.5rem; align-items: start; } .about-right { display: flex; flex-direction: column; gap: 1.25rem; } -.about-text p { font-size: 0.95rem; color: var(--ink-soft); margin-bottom: 1rem; } -.about-text strong { color: var(--ink); } +.about-text { + background: var(--white); + border: var(--border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow); + padding: 1.75rem; +} +.about-text p { font-size: 0.95rem; margin-bottom: 1rem; } +.about-text p:last-child { margin-bottom: 0; } .pepsi-card { - background: var(--glass-bg); - border: 1px solid var(--glass-border); - backdrop-filter: blur(12px); + background: var(--pink); + border: var(--border); border-radius: var(--radius-lg); overflow: hidden; - box-shadow: var(--card-shadow); + box-shadow: var(--shadow); text-align: center; } .pepsi-placeholder { height: 400px; - background: rgba(255,255,255,0.3); - display: flex; align-items: center; justify-content: center; - font-size: 4rem; - color: rgba(244, 114, 43, 0.4); + border-bottom: var(--border); + position: relative; + overflow: hidden; + cursor: pointer; +} +.pepsi-incoming { position: absolute; inset: 0; } + +/* Clickable photos shouldn't ghost-drag or get text-selected */ +.avatar-placeholder img, .pepsi-placeholder img { + -webkit-user-drag: none; + user-select: none; + -webkit-user-select: none; } .pepsi-placeholder img { - width: 100%; height: 100%; object-fit: cover; + width: 100%; height: 100%; object-fit: cover; display: block; } .pepsi-caption { - padding: 0.5rem 1rem; - font-size: 0.85rem; - font-style: italic; - color: var(--ink-soft); + padding: 0.75rem 1rem; + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.06em; + text-transform: uppercase; } /* ── Skills ─────────────────────────────────────────────────── */ .skill-card { - background: var(--glass-bg); border: 1px solid var(--glass-border); - border-radius: var(--radius-lg); padding: 1.75rem; - box-shadow: var(--card-shadow); + background: var(--yellow); + border: var(--border); + border-radius: var(--radius-lg); + padding: 1.75rem; + box-shadow: var(--shadow); } -.skill-card-icon { width: 42px; height: 42px; border-radius: var(--radius-md); background: var(--grad); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 1.1rem; margin-bottom: 0.75rem; } -.skill-card h3 { font-size: 1.05rem; font-weight: 800; margin-bottom: 1.25rem; } +.skill-card-icon { + width: 46px; height: 46px; + border-radius: 50%; + background: var(--white); + border: var(--border); + display: flex; align-items: center; justify-content: center; + color: var(--ink); font-size: 1.1rem; + margin-bottom: 0.75rem; +} +.skill-card h3 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: 1.25rem; } /* ── Projects (list layout) ─────────────────────────────────── */ .projects-list { display: flex; flex-direction: column; gap: 2rem; } .project-card { - background: var(--glass-bg); border: 1px solid var(--glass-border); + background: var(--white); + border: var(--border); border-radius: var(--radius-lg); padding: 2rem; - box-shadow: var(--card-shadow); + box-shadow: var(--shadow); } .project-header { @@ -305,107 +346,167 @@ main { position: relative; z-index: 1; } } .project-icon { width: 46px; height: 46px; flex-shrink: 0; - border-radius: var(--radius-md); background: var(--grad); + border-radius: 50%; + background: var(--blue); + border: var(--border); display: flex; align-items: center; justify-content: center; - color: #fff; font-size: 1.1rem; + color: var(--ink); font-size: 1.1rem; } .project-title-row { flex: 1; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; } -.project-title-row h3 { font-size: 1.2rem; font-weight: 800; } +.project-title-row h3 { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.03em; } .project-ext-links { display: flex; gap: 0.5rem; flex-wrap: wrap; } .project-link { display: inline-flex; align-items: center; gap: 0.5rem; - font-size: 0.75rem; font-weight: 700; - padding: 0.25rem 0.75rem; border-radius: var(--radius-pill); - border: 1.5px solid var(--glass-border); - background: rgba(255,255,255,0.4); - color: var(--ink-soft); - transition: all 0.2s; + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.05em; + text-transform: uppercase; + padding: 0.35rem 0.8rem; + border-radius: var(--radius-pill); + border: var(--border-thin); + background: var(--white); + color: var(--ink); + box-shadow: 3px 3px 0 var(--ink); + transition: background 150ms ease; } -.project-link:hover { background: var(--orange); border-color: var(--orange); color: #fff; } +.project-link:hover { transform: translate(-2px, -2px); box-shadow: 4px 4px 0 var(--ink); background: var(--yellow); } +.project-link:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); } .project-badge { display: inline-flex; align-items: center; gap: 0.5rem; - font-size: 0.75rem; font-weight: 700; - padding: 0.25rem 0.75rem; border-radius: var(--radius-pill); - background: rgba(244, 114, 43, 0.12); - color: var(--orange-deep); - border: 1px solid rgba(244, 114, 43, 0.25); + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.05em; + text-transform: uppercase; + padding: 0.35rem 0.8rem; + border-radius: var(--radius-pill); + background: var(--blue); + border: var(--border-thin); + color: var(--ink); } .project-body { margin-bottom: 1.25rem; } .project-body p { - font-size: 0.95rem; color: var(--ink-soft); + font-size: 0.95rem; margin-bottom: 0.75rem; } .project-body p:last-child { margin-bottom: 0; } +.project-body a { + text-decoration: underline; + text-decoration-thickness: 2px; + text-underline-offset: 3px; +} .project-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; } .project-tags span, .timeline-tags span { - font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em; - padding: 0.25rem 0.75rem; border-radius: var(--radius-pill); - background: rgba(26,10,0,0.07); color: var(--ink-soft); - border: 1px solid rgba(244, 114, 43, 0.18); - transition: all 0.2s var(--ease); -} -.project-tags span:hover, .timeline-tags span:hover, -.project-tags span.tip-open, .timeline-tags span.tip-open { - background: var(--orange); - border-color: var(--orange); - color: #fff; + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.06em; + text-transform: uppercase; + padding: 0.3rem 0.75rem; + border-radius: var(--radius-pill); + background: var(--white); + border: var(--border-thin); + color: var(--ink); + transition: background 150ms ease; } +#projects .project-tags span:hover, +#projects .project-tags span.tip-open { background: var(--blue); } +#experience .timeline-tags span:hover, +#experience .timeline-tags span.tip-open { background: var(--green); } /* ── Timeline / Experience ──────────────────────────────────── */ .timeline { position: relative; padding-left: 1.75rem; } .timeline::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; - width: 2px; background: linear-gradient(to bottom, var(--orange), var(--yellow), transparent); - border-radius: var(--radius-pill); + width: 3px; background: var(--ink); } .timeline-item { position: relative; padding-left: 2.25rem; padding-bottom: 3rem; } .timeline-item:last-child { padding-bottom: 0; } .timeline-marker { - position: absolute; left: -2.16rem; top: 0rem; - width: 16px; height: 16px; border-radius: 50%; - background: var(--orange); border: 3px solid var(--cream); + position: absolute; left: calc(-1.75rem - 7.5px); top: 0rem; + width: 18px; height: 18px; border-radius: 50%; + background: var(--green); border: 3px solid var(--ink); } .timeline-card { - background: var(--glass-bg); border: 1px solid var(--glass-border); - border-radius: var(--radius-lg); padding: 1.75rem; - box-shadow: var(--card-shadow); + background: var(--white); + border: var(--border); + border-radius: var(--radius-lg); + padding: 1.75rem; + box-shadow: var(--shadow); } .timeline-meta { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem; } -.timeline-date { font-size: 0.75rem; font-weight: 700; color: var(--orange-deep); } -.timeline-tag { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; background: rgba(244,114,43,0.12); color: var(--orange-deep); border-radius: var(--radius-pill); padding: 0.25rem 0.75rem; } -.timeline-role { font-size: 1.2rem; font-weight: 900; letter-spacing: -0.01em; margin-bottom: 0.25rem; } -.timeline-company { font-size: 0.85rem; color: var(--ink-soft); margin-bottom: 0.75rem; } -.timeline-desc { font-size: 0.95rem; color: var(--ink-soft); margin-bottom: 1rem; } +.timeline-date { + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.06em; + text-transform: uppercase; +} +.timeline-tag { + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.06em; + text-transform: uppercase; + background: var(--green); + border: var(--border-thin); + border-radius: var(--radius-pill); + padding: 0.3rem 0.75rem; +} +.timeline-role { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.03em; margin-bottom: 0.25rem; } +.timeline-company { font-size: 0.85rem; margin-bottom: 0.75rem; } +.timeline-desc { font-size: 0.95rem; margin-bottom: 1rem; } .timeline-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; } /* ── Education ──────────────────────────────────────────────── */ .education-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; } .edu-card { - background: var(--glass-bg); border: 1px solid var(--glass-border); - border-radius: var(--radius-lg); padding: 1.75rem; - box-shadow: var(--card-shadow); + background: var(--purple); + border: var(--border); + border-radius: var(--radius-lg); + padding: 1.75rem; + box-shadow: var(--shadow); display: flex; gap: 1.25rem; align-items: flex-start; } -.edu-icon { width: 46px; height: 46px; flex-shrink: 0; border-radius: var(--radius-md); background: var(--grad); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 1.1rem; } -.edu-body h3 { font-size: 1.05rem; font-weight: 800; margin-bottom: 0.25rem; } -.edu-school { font-weight: 700; color: var(--orange-deep); font-size: 0.85rem; margin-bottom: 0.25rem; } -.edu-date { font-size: 0.75rem; font-weight: 700; color: var(--ink-soft); margin-bottom: 0.75rem; } -.edu-desc { font-size: 0.85rem; color: var(--ink-soft); } +.edu-icon { + width: 46px; height: 46px; flex-shrink: 0; + border-radius: 50%; + background: var(--white); + border: var(--border); + display: flex; align-items: center; justify-content: center; + color: var(--ink); font-size: 1.1rem; +} +.edu-body h3 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: 0.25rem; } +.edu-school { font-weight: 700; font-size: 0.85rem; margin-bottom: 0.25rem; } +.edu-date { + font-family: var(--mono); + font-weight: 500; + font-size: 0.72rem; + letter-spacing: 0.06em; + text-transform: uppercase; + margin-bottom: 0.75rem; +} +.edu-desc { font-size: 0.85rem; } .edu-links { margin-top: 0.75rem; display: flex; flex-wrap: wrap; gap: 0.5rem; } /* ── Footer ─────────────────────────────────────────────────── */ footer { position: relative; z-index: 1; - background: var(--ink); color: rgba(255,255,255,0.45); - text-align: center; padding: 1.75rem 2rem; font-size: 0.85rem; + background: var(--ink); color: var(--white); + font-family: var(--mono); + font-size: 0.78rem; + letter-spacing: 0.05em; + text-transform: uppercase; + text-align: center; padding: 2.5rem 2rem; } /* ── Responsive ─────────────────────────────────────────────── */ @@ -418,20 +519,24 @@ footer { @media (max-width: 768px) { html { font-size: 14px; } + :root { + --shadow: 5px 5px 0 var(--ink); + --shadow-sm: 3px 3px 0 var(--ink); + --radius-lg: 14px; + } + .hero-name-accent { -webkit-text-stroke-width: 1.5px; text-shadow: 3px 3px 0 var(--yellow); } .nav-links { position: fixed; top: var(--nav-h); left: 0; right: 0; - background: rgba(254, 254, 227, 0.75);; - backdrop-filter: blur(30px); - -webkit-backdrop-filter: blur(30px); + background: var(--paper); flex-direction: column; align-items: center; padding: 1.5rem; gap: 0.4rem; transform: translateY(-140%); transition: transform 0.4s var(--ease); - border-bottom: 1px solid var(--glass-border); + border-bottom: var(--border); z-index: 999; } .nav-links.open { @@ -447,14 +552,18 @@ footer { .section-rule { display: none; } .timeline { padding-left: 1rem; } .timeline-item { padding-left: 1.5rem; } - .timeline-marker { left: -1.55rem; } + .timeline-marker { left: calc(-1rem - 7.5px); } } .skills-intro { font-size: 1.05rem; - color: var(--ink-soft); max-width: 680px; margin-bottom: 2rem; + background: var(--white); + border: var(--border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow); + padding: 1.25rem 1.75rem; } .lang-cloud { @@ -465,23 +574,21 @@ footer { } .lang-tag { - font-size: 0.95rem; - font-weight: 700; - padding: 0.5rem 1.25rem; + font-family: var(--mono); + font-weight: 500; + font-size: 0.85rem; + letter-spacing: 0.05em; + padding: 0.5rem 1.1rem; border-radius: var(--radius-pill); - background: var(--glass-bg); - border: 1.5px solid var(--glass-border); - backdrop-filter: blur(8px); + background: var(--white); + border: var(--border-thin); color: var(--ink); - transition: all 0.2s var(--ease); + transition: background 150ms ease; } .lang-tag:hover, -.lang-tag.tip-open { - background: var(--orange); - border-color: var(--orange); - color: #fff; -} +.lang-tag:focus-visible, +.lang-tag.tip-open { background: var(--yellow); } /* ── Skill pills: shared behavior (no select + tooltip anchor) ─── */ .lang-tag, .project-tags span, .timeline-tags span { @@ -505,7 +612,7 @@ footer { padding: 0.5rem 0.75rem; border-radius: var(--radius-md); background: var(--ink); - color: var(--cream); + color: var(--white); font-family: var(--font); font-size: 0.75rem; font-weight: 500; @@ -514,7 +621,6 @@ footer { text-transform: none; text-align: center; white-space: normal; - box-shadow: var(--card-shadow); z-index: 10; pointer-events: none; } @@ -547,8 +653,15 @@ footer { .project-body code { font-family: var(--mono); font-size: 0.88em; - background: rgba(26, 10, 0, 0.07); + background: #e6e0d0; padding: 0.1em 0.4em; - border-radius: var(--radius-sm); - color: var(--orange); -} \ No newline at end of file + border-radius: var(--radius-md); +} + +/* ── Reduced motion ─────────────────────────────────────────── */ +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + .hero-link, .project-link, .lang-tag, + .project-tags span, .timeline-tags span, + .nav-link::after, #header { transition: none; } +}