FILES: - index.html - assets/style.css - assets/app.js - assets/favicon.svg --- path: index.html --- Nova Frame
Nova Frame

Creative systems • thoughtful software • modern web

Building clean digital experiences with a sharp technical edge.

A lightweight personal landing page with a studio-like feel — designed to look polished, responsive, and calm under any screen size.

About: I design and prototype elegant tools, interfaces, and ideas that feel both precise and human.

What this page signals

A landing page that feels current without feeling noisy.

Polished presence

Strong first impression with restrained motion, refined spacing, and a modern visual language.

Subpath-safe

Every asset path is relative, so the site works cleanly from a versioned subdirectory.

Fast by default

Pure HTML, CSS, and JavaScript with no build pipeline, no runtime dependencies, and minimal weight.

Selected work

Projects

Concept

Signal Atlas

A speculative dashboard for organizing research notes, maps, and visual references into a unified workspace.

Explore idea
Prototype

Quiet Terminal

A minimal command-centered interface for personal workflows, designed around clarity, rhythm, and speed.

See direction
Studio

Pixel Current

A visual identity experiment blending editorial typography, immersive gradients, and lightweight interactivity.

Start a conversation

Get in touch

Have an idea worth building?

I’m interested in thoughtful collaborations across product, design, and creative technology.

Email Me

No forms. No backend. Just a direct line.

--- path: assets/style.css --- :root { --bg: #07101f; --bg-elev: rgba(16, 24, 44, 0.72); --bg-elev-2: rgba(18, 28, 50, 0.86); --card: rgba(255, 255, 255, 0.06); --card-strong: rgba(255, 255, 255, 0.09); --text: #ecf2ff; --muted: #a7b4d6; --line: rgba(255, 255, 255, 0.1); --accent: #7c9cff; --accent-2: #67e8f9; --accent-3: #c084fc; --shadow: 0 20px 60px rgba(0, 0, 0, 0.35); --radius: 24px; --radius-sm: 16px; --container: 1160px; --hero-glow: radial-gradient(circle at 20% 20%, rgba(124, 156, 255, 0.22), transparent 35%), radial-gradient(circle at 80% 30%, rgba(103, 232, 249, 0.16), transparent 28%), radial-gradient(circle at 50% 80%, rgba(192, 132, 252, 0.12), transparent 26%); --bg-gradient: linear-gradient(180deg, #07101f 0%, #0a1326 45%, #08101d 100%); } body.light { --bg: #f4f7ff; --bg-elev: rgba(255, 255, 255, 0.75); --bg-elev-2: rgba(255, 255, 255, 0.9); --card: rgba(10, 16, 35, 0.04); --card-strong: rgba(10, 16, 35, 0.07); --text: #10182b; --muted: #5e6b89; --line: rgba(16, 24, 43, 0.1); --accent: #4f6df5; --accent-2: #0ea5b7; --accent-3: #8b5cf6; --shadow: 0 18px 40px rgba(26, 36, 66, 0.1); --hero-glow: radial-gradient(circle at 20% 20%, rgba(79, 109, 245, 0.14), transparent 35%), radial-gradient(circle at 80% 30%, rgba(14, 165, 183, 0.12), transparent 28%), radial-gradient(circle at 50% 80%, rgba(139, 92, 246, 0.09), transparent 26%); --bg-gradient: linear-gradient(180deg, #f8fbff 0%, #eef4ff 46%, #f6f9ff 100%); } * { box-sizing: border-box; } html { scroll-behavior: smooth; } html, body { margin: 0; min-height: 100%; } body { font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: var(--hero-glow), var(--bg-gradient); color: var(--text); line-height: 1.5; overflow-x: hidden; transition: background 280ms ease, color 280ms ease; } a { color: inherit; text-decoration: none; } button { font: inherit; } .site-shell { width: min(calc(100% - 2rem), var(--container)); margin: 0 auto; position: relative; } .topbar { position: sticky; top: 0; z-index: 30; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 0; backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); } .topbar::before { content: ""; position: absolute; inset: 0 -1rem; background: linear-gradient(to bottom, rgba(6, 10, 20, 0.52), rgba(6, 10, 20, 0)); z-index: -1; pointer-events: none; } body.light .topbar::before { background: linear-gradient(to bottom, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0)); } .brand { display: inline-flex; align-items: center; gap: 0.75rem; font-weight: 700; letter-spacing: 0.01em; } .brand-mark { width: 0.95rem; height: 0.95rem; border-radius: 999px; background: linear-gradient(135deg, var(--accent), var(--accent-2), var(--accent-3)); box-shadow: 0 0 32px rgba(124, 156, 255, 0.45); } .nav { display: inline-flex; align-items: center; gap: 1.25rem; } .nav a { color: var(--muted); font-size: 0.96rem; transition: color 180ms ease, transform 180ms ease; } .nav a:hover, .nav a:focus-visible { color: var(--text); transform: translateY(-1px); } .theme-toggle { width: 3.25rem; height: 2rem; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-elev-2); position: relative; cursor: pointer; box-shadow: var(--shadow); transition: background 200ms ease, border-color 200ms ease, transform 180ms ease; } .theme-toggle:hover, .theme-toggle:focus-visible { transform: translateY(-1px); } .theme-toggle-dot { position: absolute; top: 0.22rem; left: 0.24rem; width: 1.42rem; height: 1.42rem; border-radius: 50%; background: linear-gradient(135deg, var(--accent), var(--accent-2)); transition: transform 220ms ease; } body.light .theme-toggle-dot { transform: translateX(1.2rem); } .section { padding: 4.5rem 0; } .hero { min-height: calc(100vh - 5rem); display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 3rem; align-items: center; padding-top: 3rem; } .eyebrow { margin: 0 0 0.9rem; text-transform: uppercase; letter-spacing: 0.14em; font-size: 0.77rem; color: var(--accent-2); } .hero h1 { margin: 0; font-size: clamp(2.8rem, 6vw, 5.6rem); line-height: 0.95; letter-spacing: -0.045em; max-width: 10.5ch; } .lead { max-width: 42rem; margin: 1.4rem 0 0; color: var(--muted); font-size: clamp(1.02rem, 1.5vw, 1.15rem); } .hero-actions { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 1.8rem; } .btn { display: inline-flex; align-items: center; justify-content: center; min-height: 3rem; padding: 0.9rem 1.2rem; border-radius: 999px; border: 1px solid var(--line); transition: transform 180ms ease, box-shadow 200ms ease, border-color 200ms ease, background 200ms ease; font-weight: 600; } .btn:hover, .btn:focus-visible { transform: translateY(-2px); box-shadow: var(--shadow); } .btn-primary { background: linear-gradient(135deg, var(--accent), var(--accent-3)); color: white; border-color: transparent; } .btn-secondary { background: var(--bg-elev); color: var(--text); } .about-line { margin-top: 1.5rem; color: var(--muted); max-width: 45rem; } .hero-visual { position: relative; min-height: 420px; display: grid; place-items: center; } .orb { position: absolute; border-radius: 999px; filter: blur(14px); opacity: 0.8; animation: float 8s ease-in-out infinite; } .orb-one { width: 10rem; height: 10rem; background: rgba(124, 156, 255, 0.34); top: 8%; left: 10%; } .orb-two { width: 7rem; height: 7rem; background: rgba(103, 232, 249, 0.3); right: 9%; top: 20%; animation-delay: -2s; } .orb-three { width: 8rem; height: 8rem; background: rgba(192, 132, 252, 0.26); bottom: 10%; left: 25%; animation-delay: -4s; } .glass-panel { width: min(100%, 420px); padding: 1rem; border-radius: 28px; background: linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0.05)); border: 1px solid rgba(255,255,255,0.12); box-shadow: var(--shadow); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); transform: perspective(1000px) rotateY(-10deg) rotateX(4deg); } body.light .glass-panel { background: linear-gradient(180deg, rgba(255,255,255,0.85), rgba(255,255,255,0.65)); border: 1px solid rgba(16,24,43,0.08); } .panel-header { display: flex; gap: 0.45rem; padding: 0.2rem 0 0.9rem; } .panel-header span { width: 0.72rem; height: 0.72rem; border-radius: 50%; background: rgba(255,255,255,0.5); } body.light .panel-header span { background: rgba(16,24,43,0.15); } .panel-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.9rem; } .mini-card { min-height: 112px; padding: 1rem; border-radius: 18px; background: var(--card); border: 1px solid var(--line); } .mini-card.active { background: linear-gradient(180deg, rgba(124,156,255,0.22), rgba(255,255,255,0.06)); } .mini-label { color: var(--muted); font-size: 0.82rem; } .mini-value { margin-top: 1rem; font-size: 1.1rem; font-weight: 700; letter-spacing: -0.02em; } .pulse-card .mini-value::after { content: ""; display: inline-block; width: 0.55rem; height: 0.55rem; margin-left: 0.55rem; border-radius: 50%; background: var(--accent-2); box-shadow: 0 0 0 0 rgba(103, 232, 249, 0.55); animation: pulse 2s infinite; vertical-align: middle; } .section-heading h2 { margin: 0; font-size: clamp(1.8rem, 4vw, 3rem); letter-spacing: -0.035em; max-width: 16ch; } .section-grid { display: grid; gap: 2rem; } .feature-grid, .projects-grid { display: grid; gap: 1rem; } .feature-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .feature-card, .project-card, .contact-card { background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); } .feature-card { padding: 1.4rem; min-height: 220px; } .feature-icon { width: 2.25rem; height: 2.25rem; border-radius: 14px; display: grid; place-items: center; background: var(--card-strong); margin-bottom: 1rem; font-size: 1rem; } .feature-card h3, .project-card h3 { margin: 0 0 0.65rem; letter-spacing: -0.02em; } .feature-card p, .project-card p, .contact-card p, .footer, .about-line { color: var(--muted); } .projects-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 1.4rem; } .project-card { position: relative; overflow: hidden; padding: 1.4rem; min-height: 260px; transition: transform 220ms ease, border-color 220ms ease; } .project-card::before { content: ""; position: absolute; inset: auto -20% -45% auto; width: 180px; height: 180px; background: radial-gradient(circle, rgba(124,156,255,0.22), transparent 70%); pointer-events: none; } .project-card:hover, .project-card:focus-within { transform: translateY(-4px); border-color: rgba(124, 156, 255, 0.3); } .project-tag { display: inline-flex; align-items: center; min-height: 1.9rem; padding: 0.3rem 0.7rem; border-radius: 999px; background: var(--card); border: 1px solid var(--line); font-size: 0.8rem; color: var(--muted); margin-bottom: 1rem; } .project-link { display: inline-block; margin-top: 1rem; font-weight: 600; } .project-link:hover, .project-link:focus-visible { text-decoration: underline; } .contact-section { padding-bottom: 3rem; } .contact-card { padding: 1.6rem; display: grid; grid-template-columns: 1.25fr 0.75fr; gap: 1rem; align-items: center; } .contact-actions { display: flex; flex-direction: column; gap: 0.9rem; align-items: flex-start; } .contact-note { margin: 0; font-size: 0.95rem; } .footer { display: flex; justify-content: space-between; gap: 1rem; padding: 1rem 0 2.2rem; border-top: 1px solid var(--line); font-size: 0.92rem; } kbd { padding: 0.15rem 0.38rem; border-radius: 6px; border: 1px solid var(--line); background: var(--card); color: var(--text); font-family: inherit; font-size: 0.85em; } .reveal { opacity: 0; transform: translateY(18px); transition: opacity 650ms ease, transform 650ms ease; } .reveal.in-view { opacity: 1; transform: translateY(0); } .glow-mode .site-shell::after { content: ""; position: fixed; inset: -10%; pointer-events: none; background: radial-gradient(circle at 15% 25%, rgba(124, 156, 255, 0.12), transparent 24%), radial-gradient(circle at 80% 20%, rgba(103, 232, 249, 0.1), transparent 22%), radial-gradient(circle at 50% 80%, rgba(192, 132, 252, 0.08), transparent 25%); animation: shimmer 6s linear infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(103, 232, 249, 0.45); } 70% { box-shadow: 0 0 0 12px rgba(103, 232, 249, 0); } 100% { box-shadow: 0 0 0 0 rgba(103, 232, 249, 0); } } @keyframes float { 0%, 100% { transform: translateY(0px) translateX(0px); } 50% { transform: translateY(-14px) translateX(5px); } } @keyframes shimmer { 0% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(0, -1%, 0) scale(1.02); } 100% { transform: translate3d(0, 0, 0) scale(1); } } @media (max-width: 980px) { .hero, .contact-card, .feature-grid, .projects-grid { grid-template-columns: 1fr; } .hero { min-height: auto; padding-top: 2rem; } .hero h1 { max-width: 12ch; } .hero-visual { min-height: 320px; } .glass-panel { transform: none; } .footer { flex-direction: column; } } @media (max-width: 720px) { .site-shell { width: min(calc(100% - 1.1rem), var(--container)); } .topbar { flex-wrap: wrap; } .nav { order: 3; width: 100%; justify-content: center; padding-top: 0.2rem; } .section { padding: 3.5rem 0; } .hero-actions { width: 100%; } .btn { width: 100%; } .panel-grid { grid-template-columns: 1fr 1fr; } } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } *, *::before, *::after { animation: none !important; transition: none !important; } .reveal { opacity: 1; transform: none; } } --- path: assets/app.js --- (function () { const body = document.body; const yearEl = document.getElementById("year"); const toggle = document.getElementById("themeToggle"); const storedTheme = localStorage.getItem("nova-theme"); const revealEls = document.querySelectorAll(".reveal"); const tiltCards = document.querySelectorAll(".tilt-card"); if (yearEl) { yearEl.textContent = String(new Date().getFullYear()); } function applyTheme(theme) { const light = theme === "light"; body.classList.toggle("light", light); localStorage.setItem("nova-theme", light ? "light" : "dark"); } if (storedTheme) { applyTheme(storedTheme); } else { const prefersLight = window.matchMedia && window.matchMedia("(prefers-color-scheme: light)").matches; applyTheme(prefersLight ? "light" : "dark"); } if (toggle) { toggle.addEventListener("click", function () { const next = body.classList.contains("light") ? "dark" : "light"; applyTheme(next); }); } if ("IntersectionObserver" in window) { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("in-view"); observer.unobserve(entry.target); } }); }, { threshold: 0.16 } ); revealEls.forEach((el) => observer.observe(el)); } else { revealEls.forEach((el) => el.classList.add("in-view")); } tiltCards.forEach((card) => { card.addEventListener("mousemove", (e) => { if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; const rect = card.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const px = x / rect.width; const py = y / rect.height; const rotateY = (px - 0.5) * 8; const rotateX = (0.5 - py) * 8; card.style.transform = "translateY(-4px) perspective(900px) rotateX(" + rotateX.toFixed(2) + "deg) rotateY(" + rotateY.toFixed(2) + "deg)"; }); card.addEventListener("mouseleave", () => { card.style.transform = ""; }); }); let glowTimeout = null; document.addEventListener("keydown", (e) => { if (e.key.toLowerCase() === "g") { body.classList.add("glow-mode"); clearTimeout(glowTimeout); glowTimeout = setTimeout(() => { body.classList.remove("glow-mode"); }, 3200); } }); })(); --- path: assets/favicon.svg ---