1023 lines
36 KiB
HTML
1023 lines
36 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8"/>
|
|
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
|
|
<title>noctura.dev — Portfolio</title>
|
|
<meta name="description" content="Portfolio für Web, Systeme und Infrastruktur."/>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
|
|
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@300;400;500;600&family=Geist+Mono:wght@300;400&display=swap" rel="stylesheet"/>
|
|
<style>
|
|
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
|
:root{
|
|
--ink:#0a0a0c;
|
|
--ink-soft:#141417;
|
|
--ink-mid:#1c1c22;
|
|
--ink-border:rgba(255,255,255,0.07);
|
|
--ink-border-hi:rgba(255,255,255,0.14);
|
|
--text:#f0ede8;
|
|
--text-dim:#8a8780;
|
|
--text-muted:#5a5855;
|
|
--gold:#c9a96e;
|
|
--gold-dim:rgba(201,169,110,0.15);
|
|
--gold-glow:rgba(201,169,110,0.08);
|
|
--teal:#5ec4a8;
|
|
--teal-dim:rgba(94,196,168,0.12);
|
|
--ff-serif:'Instrument Serif',Georgia,serif;
|
|
--ff-sans:'Geist',system-ui,sans-serif;
|
|
--ff-mono:'Geist Mono',monospace;
|
|
--ease-out:cubic-bezier(0.16,1,0.3,1);
|
|
}
|
|
html{scroll-behavior:smooth;font-size:16px}
|
|
body{
|
|
background:var(--ink);
|
|
color:var(--text);
|
|
font-family:var(--ff-sans);
|
|
line-height:1.6;
|
|
min-height:100vh;
|
|
overflow-x:hidden;
|
|
}
|
|
::selection{background:rgba(201,169,110,0.22);color:#fff}
|
|
a{color:inherit;text-decoration:none}
|
|
img{display:block}
|
|
|
|
/* ── NOISE TEXTURE ───────────────────────────── */
|
|
body::after{
|
|
content:'';
|
|
position:fixed;inset:0;
|
|
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E");
|
|
opacity:0.028;
|
|
pointer-events:none;
|
|
z-index:999;
|
|
}
|
|
|
|
/* ── CANVAS ──────────────────────────────────── */
|
|
#c{position:fixed;inset:0;z-index:0;pointer-events:none}
|
|
|
|
/* ── NAV ─────────────────────────────────────── */
|
|
nav{
|
|
position:fixed;top:0;left:0;right:0;z-index:100;
|
|
padding:0 2.5rem;
|
|
height:60px;
|
|
display:flex;align-items:center;justify-content:space-between;
|
|
border-bottom:1px solid var(--ink-border);
|
|
background:rgba(10,10,12,0.82);
|
|
backdrop-filter:blur(24px);
|
|
}
|
|
.nav-logo{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.78rem;
|
|
letter-spacing:0.12em;
|
|
color:var(--text-dim);
|
|
}
|
|
.nav-logo span{color:var(--gold)}
|
|
.nav-links{
|
|
display:flex;gap:2.5rem;
|
|
list-style:none;
|
|
}
|
|
.nav-links a{
|
|
font-size:0.72rem;
|
|
letter-spacing:0.1em;
|
|
text-transform:uppercase;
|
|
color:var(--text-muted);
|
|
transition:color 0.2s;
|
|
}
|
|
.nav-links a:hover{color:var(--text)}
|
|
|
|
/* ── LAYOUT ─────────────────────────────────── */
|
|
.container{
|
|
position:relative;z-index:1;
|
|
max-width:1140px;
|
|
margin:0 auto;
|
|
padding:0 2.5rem;
|
|
}
|
|
|
|
/* ── HERO ───────────────────────────────────── */
|
|
.hero{
|
|
padding:148px 0 100px;
|
|
display:grid;
|
|
grid-template-columns:1fr 360px;
|
|
gap:3rem;
|
|
align-items:start;
|
|
}
|
|
.hero-eyebrow{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.68rem;
|
|
letter-spacing:0.18em;
|
|
text-transform:uppercase;
|
|
color:var(--gold);
|
|
margin-bottom:1.75rem;
|
|
display:flex;align-items:center;gap:0.75rem;
|
|
opacity:0;animation:up 0.7s var(--ease-out) 0.1s forwards;
|
|
}
|
|
.hero-eyebrow::before{
|
|
content:'';width:24px;height:1px;
|
|
background:var(--gold);opacity:0.5;
|
|
}
|
|
.hero h1{
|
|
font-family:var(--ff-serif);
|
|
font-size:clamp(3.5rem,7vw,6rem);
|
|
font-weight:400;
|
|
line-height:0.95;
|
|
letter-spacing:-0.02em;
|
|
margin-bottom:2rem;
|
|
opacity:0;animation:up 0.8s var(--ease-out) 0.25s forwards;
|
|
}
|
|
.hero h1 em{
|
|
font-style:italic;
|
|
color:var(--gold);
|
|
}
|
|
.hero-desc{
|
|
font-size:1rem;
|
|
color:var(--text-dim);
|
|
line-height:1.85;
|
|
max-width:560px;
|
|
margin-bottom:2.5rem;
|
|
opacity:0;animation:up 0.8s var(--ease-out) 0.4s forwards;
|
|
}
|
|
.hero-desc strong{color:var(--text);font-weight:500}
|
|
.hero-actions{
|
|
display:flex;gap:1rem;flex-wrap:wrap;
|
|
opacity:0;animation:up 0.8s var(--ease-out) 0.55s forwards;
|
|
}
|
|
.btn{
|
|
display:inline-flex;align-items:center;gap:8px;
|
|
padding:0.78rem 1.5rem;
|
|
font-family:var(--ff-sans);
|
|
font-size:0.8rem;
|
|
font-weight:500;
|
|
letter-spacing:0.03em;
|
|
border-radius:4px;
|
|
transition:all 0.2s var(--ease-out);
|
|
cursor:pointer;border:none;
|
|
}
|
|
.btn-gold{
|
|
background:var(--gold);
|
|
color:#0a0a0c;
|
|
}
|
|
.btn-gold:hover{background:#d4b07c;transform:translateY(-1px)}
|
|
.btn-ghost{
|
|
background:transparent;
|
|
color:var(--text-dim);
|
|
border:1px solid var(--ink-border-hi);
|
|
}
|
|
.btn-ghost:hover{color:var(--text);border-color:rgba(255,255,255,0.28);transform:translateY(-1px)}
|
|
|
|
/* Hero metrics row */
|
|
.hero-metrics{
|
|
display:flex;gap:0;
|
|
border:1px solid var(--ink-border);
|
|
border-radius:6px;
|
|
overflow:hidden;
|
|
margin-top:3rem;
|
|
opacity:0;animation:up 0.8s var(--ease-out) 0.7s forwards;
|
|
}
|
|
.hero-metric{
|
|
flex:1;
|
|
padding:1.2rem 1.5rem;
|
|
border-right:1px solid var(--ink-border);
|
|
}
|
|
.hero-metric:last-child{border-right:none}
|
|
.hero-metric-label{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.6rem;
|
|
letter-spacing:0.14em;
|
|
text-transform:uppercase;
|
|
color:var(--teal);
|
|
margin-bottom:0.5rem;
|
|
}
|
|
.hero-metric-val{font-size:0.88rem;font-weight:500;margin-bottom:0.2rem}
|
|
.hero-metric-copy{font-size:0.76rem;color:var(--text-muted);line-height:1.5}
|
|
|
|
/* ── HERO CARD ───────────────────────────────── */
|
|
.hero-card{
|
|
opacity:0;animation:up 0.8s var(--ease-out) 0.6s forwards;
|
|
position:sticky;top:80px;
|
|
border:1px solid var(--ink-border);
|
|
border-radius:10px;
|
|
overflow:hidden;
|
|
background:var(--ink-soft);
|
|
}
|
|
.hc-bar{
|
|
height:3px;
|
|
background:linear-gradient(90deg,var(--gold),var(--teal));
|
|
}
|
|
.hc-body{padding:1.5rem}
|
|
.hc-top{
|
|
display:flex;align-items:center;justify-content:space-between;
|
|
margin-bottom:1.25rem;
|
|
}
|
|
.hc-name{font-size:0.92rem;font-weight:500}
|
|
.hc-sub{font-size:0.75rem;color:var(--text-muted);margin-top:2px}
|
|
.hc-badge{
|
|
display:inline-flex;align-items:center;gap:6px;
|
|
padding:0.3rem 0.7rem;
|
|
border-radius:99px;
|
|
background:rgba(94,196,168,0.1);
|
|
border:1px solid rgba(94,196,168,0.2);
|
|
font-family:var(--ff-mono);
|
|
font-size:0.63rem;
|
|
letter-spacing:0.06em;
|
|
color:var(--teal);
|
|
}
|
|
.hc-badge::before{
|
|
content:'';width:6px;height:6px;border-radius:50%;
|
|
background:var(--teal);
|
|
animation:blink 2s ease-in-out infinite;
|
|
}
|
|
@keyframes blink{0%,100%{opacity:1}50%{opacity:0.35}}
|
|
.hc-grid{display:grid;grid-template-columns:1fr 1fr;gap:0.6rem;margin-bottom:1rem}
|
|
.hc-cell{
|
|
padding:0.85rem;
|
|
border-radius:6px;
|
|
background:var(--ink-mid);
|
|
border:1px solid var(--ink-border);
|
|
}
|
|
.hc-cell-label{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.6rem;letter-spacing:0.12em;text-transform:uppercase;
|
|
color:var(--gold);margin-bottom:0.35rem;
|
|
}
|
|
.hc-cell-val{font-size:0.82rem;font-weight:500;margin-bottom:0.15rem}
|
|
.hc-cell-copy{font-size:0.72rem;color:var(--text-muted);line-height:1.45}
|
|
.hc-list{display:grid;gap:0.5rem}
|
|
.hc-list-item{
|
|
padding:0.75rem;border-radius:6px;
|
|
background:var(--ink-mid);border:1px solid var(--ink-border);
|
|
font-size:0.76rem;color:var(--text-muted);line-height:1.5;
|
|
}
|
|
.hc-list-item strong{display:block;color:var(--text);font-weight:500;margin-bottom:2px;font-size:0.78rem}
|
|
|
|
/* ── SECTION COMMONS ─────────────────────────── */
|
|
section{padding:96px 0;position:relative;z-index:1}
|
|
.divider{
|
|
height:1px;
|
|
background:linear-gradient(90deg,transparent,var(--ink-border) 30%,var(--ink-border) 70%,transparent);
|
|
}
|
|
.s-label{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.66rem;
|
|
letter-spacing:0.18em;
|
|
text-transform:uppercase;
|
|
color:var(--gold);
|
|
margin-bottom:1rem;
|
|
}
|
|
.s-title{
|
|
font-family:var(--ff-serif);
|
|
font-size:clamp(2rem,3.5vw,3rem);
|
|
font-weight:400;
|
|
line-height:1.1;
|
|
letter-spacing:-0.02em;
|
|
margin-bottom:0.75rem;
|
|
}
|
|
.s-title em{font-style:italic;color:var(--gold)}
|
|
.s-subtitle{
|
|
font-size:0.95rem;
|
|
color:var(--text-dim);
|
|
max-width:640px;
|
|
line-height:1.75;
|
|
margin-bottom:3.5rem;
|
|
}
|
|
|
|
/* ── ABOUT ───────────────────────────────────── */
|
|
.about-grid{
|
|
display:grid;
|
|
grid-template-columns:1fr 1fr;
|
|
gap:1px;
|
|
background:var(--ink-border);
|
|
border:1px solid var(--ink-border);
|
|
border-radius:10px;
|
|
overflow:hidden;
|
|
margin-bottom:1px;
|
|
}
|
|
.about-cell{
|
|
background:var(--ink-soft);
|
|
padding:2rem;
|
|
}
|
|
.about-cell p{font-size:0.9rem;color:var(--text-dim);line-height:1.85;margin-bottom:1rem}
|
|
.about-cell p:last-child{margin-bottom:0}
|
|
.about-cell p strong{color:var(--text);font-weight:500}
|
|
.about-notes{
|
|
background:var(--ink-soft);
|
|
border:1px solid var(--ink-border);
|
|
border-top:none;
|
|
border-radius:0 0 10px 10px;
|
|
padding:1.5rem 2rem;
|
|
}
|
|
.notes-label{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.62rem;letter-spacing:0.14em;text-transform:uppercase;
|
|
color:var(--teal);margin-bottom:1rem;
|
|
}
|
|
.notes-list{display:flex;flex-wrap:wrap;gap:0.5rem;list-style:none}
|
|
.notes-list li{
|
|
padding:0.4rem 0.85rem;
|
|
border-radius:4px;
|
|
border:1px solid var(--ink-border-hi);
|
|
font-size:0.78rem;
|
|
color:var(--text-dim);
|
|
}
|
|
.principles{
|
|
display:grid;grid-template-columns:repeat(3,1fr);
|
|
gap:1px;
|
|
background:var(--ink-border);
|
|
border:1px solid var(--ink-border);
|
|
border-radius:10px;
|
|
overflow:hidden;
|
|
margin-top:1rem;
|
|
}
|
|
.principle{
|
|
background:var(--ink-soft);
|
|
padding:1.75rem;
|
|
}
|
|
.p-num{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.62rem;letter-spacing:0.14em;
|
|
color:var(--text-muted);
|
|
margin-bottom:0.85rem;
|
|
}
|
|
.p-title{font-weight:500;font-size:0.92rem;margin-bottom:0.5rem}
|
|
.p-copy{font-size:0.82rem;color:var(--text-muted);line-height:1.65}
|
|
|
|
/* ── SKILLS ──────────────────────────────────── */
|
|
.skills-grid{
|
|
display:grid;grid-template-columns:repeat(3,1fr);
|
|
gap:1px;
|
|
background:var(--ink-border);
|
|
border:1px solid var(--ink-border);
|
|
border-radius:10px;
|
|
overflow:hidden;
|
|
}
|
|
.skill{
|
|
background:var(--ink-soft);
|
|
padding:2.25rem 2rem;
|
|
transition:background 0.25s;
|
|
}
|
|
.skill:hover{background:var(--ink-mid)}
|
|
.skill-icon{
|
|
font-family:var(--ff-mono);
|
|
font-size:1.1rem;
|
|
color:var(--gold);
|
|
margin-bottom:1.25rem;
|
|
display:block;
|
|
}
|
|
.skill-name{font-size:1rem;font-weight:500;margin-bottom:0.6rem}
|
|
.skill-desc{font-size:0.83rem;color:var(--text-dim);line-height:1.7;margin-bottom:1.5rem}
|
|
.tags{display:flex;flex-wrap:wrap;gap:6px}
|
|
.tag{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.62rem;letter-spacing:0.04em;
|
|
padding:4px 8px;border-radius:3px;
|
|
}
|
|
.tag-gold{background:var(--gold-dim);color:var(--gold);border:1px solid rgba(201,169,110,0.25)}
|
|
.tag-teal{background:var(--teal-dim);color:var(--teal);border:1px solid rgba(94,196,168,0.25)}
|
|
.tag-dim{background:rgba(255,255,255,0.04);color:var(--text-muted);border:1px solid var(--ink-border-hi)}
|
|
|
|
/* ── PROJECTS ────────────────────────────────── */
|
|
.projects-grid{
|
|
display:grid;grid-template-columns:repeat(2,1fr);
|
|
gap:1px;
|
|
background:var(--ink-border);
|
|
border:1px solid var(--ink-border);
|
|
border-radius:10px;
|
|
overflow:hidden;
|
|
}
|
|
.project{
|
|
background:var(--ink-soft);
|
|
padding:2rem;
|
|
display:flex;flex-direction:column;
|
|
gap:1rem;
|
|
transition:background 0.25s;
|
|
position:relative;
|
|
}
|
|
.project::before{
|
|
content:'';
|
|
position:absolute;top:0;left:0;right:0;
|
|
height:2px;
|
|
background:linear-gradient(90deg,var(--gold),transparent);
|
|
opacity:0;
|
|
transition:opacity 0.25s;
|
|
}
|
|
.project:hover{background:var(--ink-mid)}
|
|
.project:hover::before{opacity:1}
|
|
.proj-top{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}
|
|
.proj-icon{
|
|
width:44px;height:44px;
|
|
border-radius:8px;
|
|
border:1px solid var(--ink-border-hi);
|
|
display:flex;align-items:center;justify-content:center;
|
|
font-family:var(--ff-mono);
|
|
font-size:0.78rem;
|
|
color:var(--text-dim);
|
|
flex-shrink:0;
|
|
}
|
|
.proj-eyebrow{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.62rem;letter-spacing:0.1em;text-transform:uppercase;
|
|
color:var(--text-muted);margin-bottom:4px;
|
|
}
|
|
.proj-name{font-size:1.05rem;font-weight:500}
|
|
.proj-desc{font-size:0.83rem;color:var(--text-dim);line-height:1.7;flex:1}
|
|
.proj-tags{display:flex;flex-wrap:wrap;gap:6px}
|
|
.proj-pts{list-style:none;display:grid;gap:0.5rem}
|
|
.proj-pts li{
|
|
font-size:0.78rem;color:var(--text-muted);
|
|
padding-left:1rem;position:relative;line-height:1.55;
|
|
}
|
|
.proj-pts li::before{
|
|
content:'';position:absolute;
|
|
left:0;top:0.55rem;
|
|
width:4px;height:4px;border-radius:50%;
|
|
background:var(--teal);
|
|
}
|
|
.proj-foot{
|
|
display:flex;align-items:center;justify-content:space-between;
|
|
margin-top:auto;padding-top:0.25rem;
|
|
}
|
|
.proj-status{
|
|
display:flex;align-items:center;gap:6px;
|
|
font-family:var(--ff-mono);font-size:0.62rem;color:var(--text-muted);
|
|
}
|
|
.dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}
|
|
.dot-live{background:#4ade80;box-shadow:0 0 5px #4ade80}
|
|
.dot-wip{background:#facc15;box-shadow:0 0 5px #facc15}
|
|
.dot-plan{background:var(--text-muted)}
|
|
.proj-link{
|
|
font-family:var(--ff-mono);font-size:0.65rem;letter-spacing:0.06em;
|
|
text-transform:uppercase;color:var(--text-muted);
|
|
transition:color 0.2s;
|
|
}
|
|
.project:hover .proj-link{color:var(--gold)}
|
|
|
|
/* proof band */
|
|
.proof-band{
|
|
display:grid;grid-template-columns:repeat(3,1fr);
|
|
gap:1px;background:var(--ink-border);
|
|
border:1px solid var(--ink-border);
|
|
border-top:none;
|
|
border-radius:0 0 10px 10px;
|
|
overflow:hidden;
|
|
}
|
|
.proof-item{background:var(--ink-soft);padding:1.25rem 1.5rem}
|
|
.proof-label{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.6rem;letter-spacing:0.14em;text-transform:uppercase;
|
|
color:var(--teal);margin-bottom:0.5rem;
|
|
}
|
|
.proof-copy{font-size:0.8rem;color:var(--text-muted);line-height:1.6}
|
|
|
|
/* ── SNAPSHOT ────────────────────────────────── */
|
|
.snapshot-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--ink-border);border:1px solid var(--ink-border);border-radius:10px;overflow:hidden}
|
|
.snap{
|
|
background:var(--ink-soft);padding:1.75rem 1.5rem;
|
|
transition:background 0.25s;
|
|
}
|
|
.snap:hover{background:var(--ink-mid)}
|
|
.snap-kicker{
|
|
font-family:var(--ff-mono);font-size:0.6rem;letter-spacing:0.14em;text-transform:uppercase;
|
|
color:var(--gold);margin-bottom:0.75rem;
|
|
}
|
|
.snap-val{
|
|
font-family:var(--ff-serif);font-size:1.4rem;font-weight:400;font-style:italic;
|
|
line-height:1.2;margin-bottom:0.6rem;
|
|
}
|
|
.snap-desc{font-size:0.78rem;color:var(--text-muted);line-height:1.6}
|
|
|
|
/* ── CONTACT ─────────────────────────────────── */
|
|
.contact-box{
|
|
position:relative;overflow:hidden;
|
|
border:1px solid var(--ink-border);
|
|
border-radius:10px;
|
|
padding:5rem 3rem;
|
|
text-align:center;
|
|
background:var(--ink-soft);
|
|
}
|
|
.contact-box::before{
|
|
content:'';position:absolute;
|
|
top:-80px;left:50%;transform:translateX(-50%);
|
|
width:500px;height:200px;
|
|
background:radial-gradient(ellipse,rgba(201,169,110,0.07),transparent 70%);
|
|
pointer-events:none;
|
|
}
|
|
.contact-box h2{
|
|
font-family:var(--ff-serif);
|
|
font-size:clamp(2rem,4vw,3.2rem);
|
|
font-weight:400;letter-spacing:-0.02em;
|
|
margin-bottom:1rem;position:relative;
|
|
}
|
|
.contact-box h2 em{font-style:italic;color:var(--gold)}
|
|
.contact-box p{
|
|
font-size:0.95rem;color:var(--text-dim);
|
|
max-width:560px;margin:0 auto 2.5rem;
|
|
line-height:1.8;position:relative;
|
|
}
|
|
.contact-email{
|
|
font-family:var(--ff-mono);
|
|
font-size:0.78rem;letter-spacing:0.08em;
|
|
color:var(--text-dim);
|
|
margin-top:1.5rem;
|
|
display:block;
|
|
position:relative;
|
|
}
|
|
|
|
/* ── FOOTER ──────────────────────────────────── */
|
|
footer{
|
|
border-top:1px solid var(--ink-border);
|
|
padding:2rem 0;
|
|
}
|
|
.footer-inner{
|
|
max-width:1140px;margin:0 auto;padding:0 2.5rem;
|
|
display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;
|
|
}
|
|
.footer-inner span{
|
|
font-family:var(--ff-mono);font-size:0.65rem;letter-spacing:0.06em;
|
|
color:var(--text-muted);
|
|
}
|
|
|
|
/* ── REVEAL ──────────────────────────────────── */
|
|
.reveal{
|
|
opacity:0;transform:translateY(28px);
|
|
transition:opacity 0.7s var(--ease-out),transform 0.7s var(--ease-out);
|
|
}
|
|
.reveal.in{opacity:1;transform:none}
|
|
@keyframes up{
|
|
from{opacity:0;transform:translateY(22px)}
|
|
to{opacity:1;transform:none}
|
|
}
|
|
|
|
/* ── RESPONSIVE ──────────────────────────────── */
|
|
@media(max-width:1060px){
|
|
.hero{grid-template-columns:1fr}
|
|
.hero-card{position:static}
|
|
.hero-metrics{flex-wrap:wrap}
|
|
.hero-metric{flex:1 1 160px}
|
|
.snapshot-grid{grid-template-columns:repeat(2,1fr)}
|
|
}
|
|
@media(max-width:760px){
|
|
nav{padding:0 1.25rem}
|
|
.nav-links{display:none}
|
|
.container{padding:0 1.25rem}
|
|
.hero{padding:100px 0 64px}
|
|
section{padding:72px 0}
|
|
.about-grid,.skills-grid,.projects-grid,.proof-band,.principles,.snapshot-grid{
|
|
grid-template-columns:1fr
|
|
}
|
|
.hc-grid{grid-template-columns:1fr}
|
|
.contact-box{padding:3rem 1.5rem}
|
|
.footer-inner{padding:0 1.25rem}
|
|
}
|
|
@media(prefers-reduced-motion:reduce){
|
|
*,*::before,*::after{
|
|
animation-duration:0.01ms!important;
|
|
transition-duration:0.01ms!important;
|
|
}
|
|
.reveal,.hero-eyebrow,.hero h1,.hero-desc,.hero-actions,.hero-metrics,.hero-card{
|
|
opacity:1;transform:none;animation:none;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<canvas id="c"></canvas>
|
|
|
|
<nav>
|
|
<a href="#" class="nav-logo">noctura<span>.dev</span></a>
|
|
<ul class="nav-links">
|
|
<li><a href="#about">Über mich</a></li>
|
|
<li><a href="#skills">Skills</a></li>
|
|
<li><a href="#projects">Projekte</a></li>
|
|
<li><a href="#snapshot">Profil</a></li>
|
|
<li><a href="#contact">Kontakt</a></li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<div class="container">
|
|
|
|
<!-- HERO -->
|
|
<section class="hero">
|
|
<div class="hero-copy">
|
|
<div class="hero-eyebrow">Persönliches Portfolio · Web · Systeme · Infrastruktur</div>
|
|
<h1>Interfaces mit<br><em>Haltung.</em><br>Systeme mit<br>Substanz.</h1>
|
|
<p class="hero-desc">Ich baue digitale Arbeiten, die nicht bei schöner Oberfläche aufhören. Mich interessieren <strong>klare Nutzerführung, saubere Entscheidungen und Betrieb ohne Blackbox</strong> — Frontend, Backend und Deployment als zusammenhängendes System gedacht.</p>
|
|
<div class="hero-actions">
|
|
<a href="#projects" class="btn btn-gold">Arbeiten ansehen</a>
|
|
<a href="#contact" class="btn btn-ghost">Kontakt aufnehmen</a>
|
|
</div>
|
|
<div class="hero-metrics">
|
|
<div class="hero-metric">
|
|
<div class="hero-metric-label">Fokus</div>
|
|
<div class="hero-metric-val">End-to-End</div>
|
|
<div class="hero-metric-copy">Interface bis Deployment, in einem Zug.</div>
|
|
</div>
|
|
<div class="hero-metric">
|
|
<div class="hero-metric-label">Arbeitsweise</div>
|
|
<div class="hero-metric-val">Präzise & direkt</div>
|
|
<div class="hero-metric-copy">Klare Entscheidungen, echte Umsetzung.</div>
|
|
</div>
|
|
<div class="hero-metric">
|
|
<div class="hero-metric-label">Stack</div>
|
|
<div class="hero-metric-val">HTML · CSS · JS · Linux</div>
|
|
<div class="hero-metric-copy">Fokussiert genug für gute Details.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<aside class="hero-card">
|
|
<div class="hc-bar"></div>
|
|
<div class="hc-body">
|
|
<div class="hc-top">
|
|
<div>
|
|
<div class="hc-name">noctura.dev</div>
|
|
<div class="hc-sub">Portfolio · eigene Infrastruktur</div>
|
|
</div>
|
|
<div class="hc-badge">Aktiv</div>
|
|
</div>
|
|
<div class="hc-grid">
|
|
<div class="hc-cell">
|
|
<div class="hc-cell-label">Schwerpunkt</div>
|
|
<div class="hc-cell-val">Produktnahe Webprojekte</div>
|
|
<div class="hc-cell-copy">Interfaces mit klarer technischer Kante.</div>
|
|
</div>
|
|
<div class="hc-cell">
|
|
<div class="hc-cell-label">Umfeld</div>
|
|
<div class="hc-cell-val">Self-hosted</div>
|
|
<div class="hc-cell-copy">Design, Code und Betrieb direkt vereint.</div>
|
|
</div>
|
|
<div class="hc-cell">
|
|
<div class="hc-cell-label">Anspruch</div>
|
|
<div class="hc-cell-val">Belegen statt zeigen</div>
|
|
<div class="hc-cell-copy">Entscheidungen sichtbar, nicht nur Ergebnisse.</div>
|
|
</div>
|
|
<div class="hc-cell">
|
|
<div class="hc-cell-label">Ideal für</div>
|
|
<div class="hc-cell-val">Einstieg mit Verantwortung</div>
|
|
<div class="hc-cell-copy">Teams mit Eigeninitiative und technischem Anspruch.</div>
|
|
</div>
|
|
</div>
|
|
<div class="hc-list">
|
|
<div class="hc-list-item">
|
|
<strong>Ziel dieser Seite</strong>
|
|
Entwicklerprofil mit Persönlichkeit statt generischer Agentur-Sprache.
|
|
</div>
|
|
<div class="hc-list-item">
|
|
<strong>Was zählt</strong>
|
|
Verständliche Projekte, saubere Struktur, Signale für technische Tiefe.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- ABOUT -->
|
|
<div class="container">
|
|
<section id="about">
|
|
<div class="reveal">
|
|
<div class="s-label">// Über mich</div>
|
|
<h2 class="s-title">Ein Portfolio sollte zeigen,<br>wie jemand <em>denkt.</em></h2>
|
|
<p class="s-subtitle">Nicht was er aufzählen kann. Technische Haltung, Lernkurve und Umsetzungskompetenz sichtbar gemacht.</p>
|
|
</div>
|
|
<div class="reveal">
|
|
<div class="about-grid">
|
|
<div class="about-cell">
|
|
<p>Ich entwickle Oberflächen mit Blick auf Wirkung — aber genauso auf Aufbau, Wartbarkeit und Übergabe. Webentwicklung endet für mich nicht am Browserfenster, sondern schließt APIs, Server, Sicherheit und Deployment ein.</p>
|
|
<p>Gerade deshalb passt ein <strong>persönliches Portfolio</strong> besser zu mir als eine sterile Leistungsseite. Es darf Charakter haben, solange die Technik dahinter belastbar bleibt und die Aussagen durch Projekte gedeckt sind.</p>
|
|
</div>
|
|
<div class="about-cell" style="border-left:1px solid var(--ink-border)">
|
|
<div class="notes-label">Was Recruiter hier schnell erfassen sollen</div>
|
|
<ul class="notes-list">
|
|
<li>Gestalten, bauen, deployen und begründen.</li>
|
|
<li>Eigenständig, schnell lernend, in Systemen denkend.</li>
|
|
<li>Projekte zeigen technische Reife, nicht nur Optik.</li>
|
|
<li>Keine Platzhalter — echte Entscheidungen.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="about-notes">
|
|
<div class="notes-label">Stack & Kontext</div>
|
|
<ul class="notes-list">
|
|
<li>HTML / CSS / JavaScript</li>
|
|
<li>Node.js / REST APIs</li>
|
|
<li>Docker & Compose</li>
|
|
<li>Debian Linux</li>
|
|
<li>Caddy / systemd</li>
|
|
<li>Forgejo</li>
|
|
<li>ufw / fail2ban</li>
|
|
<li>SSH-Härtung</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="principles reveal">
|
|
<div class="principle">
|
|
<div class="p-num">01 —</div>
|
|
<div class="p-title">Klarheit vor Effekthascherei</div>
|
|
<p class="p-copy">Gutes Design darf auffallen, muss aber immer lesbar, navigierbar und argumentierbar bleiben.</p>
|
|
</div>
|
|
<div class="principle" style="border-left:1px solid var(--ink-border)">
|
|
<div class="p-num">02 —</div>
|
|
<div class="p-title">Technik sichtbar mitdenken</div>
|
|
<p class="p-copy">Lösungen, bei denen man nicht nur das Ergebnis, sondern auch die Struktur dahinter ernst nehmen kann.</p>
|
|
</div>
|
|
<div class="principle" style="border-left:1px solid var(--ink-border)">
|
|
<div class="p-num">03 —</div>
|
|
<div class="p-title">Wartbarkeit ist Qualität</div>
|
|
<p class="p-copy">Sauberer Code, nachvollziehbare Entscheidungen und robuste Deployments sind kein Bonus, sondern Standard.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- SKILLS -->
|
|
<div class="container">
|
|
<section id="skills">
|
|
<div class="reveal">
|
|
<div class="s-label">// Fähigkeiten</div>
|
|
<h2 class="s-title">Breit genug für ganze Produkte.<br><em>Präzise</em> genug für gute Details.</h2>
|
|
<p class="s-subtitle">Interface, Logik und Betrieb als Einheit — das ist der Bereich, in dem ich am stärksten arbeite.</p>
|
|
</div>
|
|
<div class="skills-grid reveal">
|
|
<div class="skill">
|
|
<span class="skill-icon"></></span>
|
|
<div class="skill-name">Frontend & Interface Design</div>
|
|
<p class="skill-desc">Responsive Oberflächen mit Charakter, sauberer Informationshierarchie und einem klaren Gefühl für visuelle Spannung ohne Unordnung.</p>
|
|
<div class="tags">
|
|
<span class="tag tag-gold">HTML / CSS</span>
|
|
<span class="tag tag-gold">JavaScript</span>
|
|
<span class="tag tag-gold">UI Systems</span>
|
|
<span class="tag tag-gold">Responsive</span>
|
|
</div>
|
|
</div>
|
|
<div class="skill" style="border-left:1px solid var(--ink-border)">
|
|
<span class="skill-icon">⬡</span>
|
|
<div class="skill-name">Backend & Infrastruktur</div>
|
|
<p class="skill-desc">Services verbinden, Datenflüsse strukturieren und Hosting so aufsetzen, dass Anwendungen nicht nur laufen, sondern verständlich betrieben werden können.</p>
|
|
<div class="tags">
|
|
<span class="tag tag-teal">Docker</span>
|
|
<span class="tag tag-teal">Node.js</span>
|
|
<span class="tag tag-teal">REST APIs</span>
|
|
<span class="tag tag-teal">Caddy</span>
|
|
<span class="tag tag-teal">Forgejo</span>
|
|
</div>
|
|
</div>
|
|
<div class="skill" style="border-left:1px solid var(--ink-border)">
|
|
<span class="skill-icon">$_</span>
|
|
<div class="skill-name">Linux & Betrieb</div>
|
|
<p class="skill-desc">Server einrichten, absichern und nachhaltig betreiben. Self-hosting, Deployments und die Wartbarkeit echter Systeme — das ist der Kern.</p>
|
|
<div class="tags">
|
|
<span class="tag tag-dim">Debian Linux</span>
|
|
<span class="tag tag-dim">SSH</span>
|
|
<span class="tag tag-dim">systemd</span>
|
|
<span class="tag tag-dim">ufw / fail2ban</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- PROJECTS -->
|
|
<div class="container">
|
|
<section id="projects">
|
|
<div class="reveal">
|
|
<div class="s-label">// Portfolio</div>
|
|
<h2 class="s-title">Ausgewählte Arbeiten mit<br>technischer und <em>gestalterischer</em> Aussage.</h2>
|
|
<p class="s-subtitle">Kein Produktkatalog. Ein verdichteter Blick darauf, wie ich Probleme angehe und Qualität bewerte.</p>
|
|
</div>
|
|
<div class="reveal">
|
|
<div class="projects-grid">
|
|
<article class="project">
|
|
<div class="proj-top">
|
|
<div>
|
|
<div class="proj-eyebrow">Tooling</div>
|
|
<div class="proj-name">Developer Utilities</div>
|
|
</div>
|
|
<div class="proj-icon">⌘</div>
|
|
</div>
|
|
<p class="proj-desc">Kleine Web-Tools mit klarer UX, schneller Interaktion und pragmatischem Produktgedanken. Der Fokus liegt auf Nutzbarkeit statt Marketing-Schichten.</p>
|
|
<div class="proj-tags">
|
|
<span class="tag tag-gold">Utility-first</span>
|
|
<span class="tag tag-dim">Schnelle Interaktion</span>
|
|
<span class="tag tag-dim">Klares UI</span>
|
|
</div>
|
|
<ul class="proj-pts">
|
|
<li>Macht Produktgefühl und Reduktion auf das Wesentliche sichtbar.</li>
|
|
<li>Zeigt, dass auch kleine Projekte sorgfältige Informationsarchitektur brauchen.</li>
|
|
</ul>
|
|
<div class="proj-foot">
|
|
<div class="proj-status"><span class="dot dot-wip"></span>In Entwicklung</div>
|
|
<span class="proj-link">Work in progress ↗</span>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="project">
|
|
<div class="proj-top">
|
|
<div>
|
|
<div class="proj-eyebrow">Backend</div>
|
|
<div class="proj-name">Custom Backend API</div>
|
|
</div>
|
|
<div class="proj-icon" style="font-size:0.65rem">API</div>
|
|
</div>
|
|
<p class="proj-desc">Eine eigene API-Struktur für persönliche Anwendungen — Routing, Datenmodelle und Hosting nicht ausgelagert, sondern bewusst kontrolliert.</p>
|
|
<div class="proj-tags">
|
|
<span class="tag tag-teal">Routing</span>
|
|
<span class="tag tag-teal">Datenmodelle</span>
|
|
<span class="tag tag-dim">Eigenes Hosting</span>
|
|
</div>
|
|
<ul class="proj-pts">
|
|
<li>Technische Entscheidungen nicht nur verwenden, sondern selbst tragen.</li>
|
|
<li>Verbindet Frontend-Anforderungen mit sauberem Service-Aufbau.</li>
|
|
</ul>
|
|
<div class="proj-foot">
|
|
<div class="proj-status"><span class="dot dot-wip"></span>In Entwicklung</div>
|
|
<span class="proj-link">Architekturaufbau ↗</span>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="project">
|
|
<div class="proj-top">
|
|
<div>
|
|
<div class="proj-eyebrow">Experiment</div>
|
|
<div class="proj-name">Lab / Playground</div>
|
|
</div>
|
|
<div class="proj-icon">△</div>
|
|
</div>
|
|
<p class="proj-desc">Prototypen, visuelle Versuche und technische Experimente. Hier wird sichtbar, wie ich neue Themen erschließe und Entscheidungen teste.</p>
|
|
<div class="proj-tags">
|
|
<span class="tag tag-dim">Prototyping</span>
|
|
<span class="tag tag-dim">Designstudien</span>
|
|
<span class="tag tag-gold">Lernsystem</span>
|
|
</div>
|
|
<ul class="proj-pts">
|
|
<li>Neugier und Iteration sichtbar statt nur fertige Ergebnisse.</li>
|
|
<li>Dort laufen Stil, Technik und persönliche Handschrift am direktesten zusammen.</li>
|
|
</ul>
|
|
<div class="proj-foot">
|
|
<div class="proj-status"><span class="dot dot-plan"></span>Geplant</div>
|
|
<span class="proj-link">In Vorbereitung ↗</span>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="project">
|
|
<div class="proj-top">
|
|
<div>
|
|
<div class="proj-eyebrow">Infrastruktur</div>
|
|
<div class="proj-name">noctura.dev Infrastruktur</div>
|
|
</div>
|
|
<div class="proj-icon">▣</div>
|
|
</div>
|
|
<p class="proj-desc">Selbst verwalteter VPS mit realen Services, Sicherheitsmaßnahmen und einer Umgebung, die mehr kann als statische Auslieferung.</p>
|
|
<div class="proj-tags">
|
|
<span class="tag tag-dim">VPS</span>
|
|
<span class="tag tag-teal">Deployment</span>
|
|
<span class="tag tag-dim">Security</span>
|
|
</div>
|
|
<ul class="proj-pts">
|
|
<li>Belegt, dass ich nicht nur UI baue, sondern Betrieb mitdenke.</li>
|
|
<li>Relevant für Rollen, in denen Eigenständigkeit und technisches Verständnis zählen.</li>
|
|
</ul>
|
|
<div class="proj-foot">
|
|
<div class="proj-status"><span class="dot dot-live"></span>Live</div>
|
|
<span class="proj-link">Produktiv im Einsatz ↗</span>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
<div class="proof-band">
|
|
<div class="proof-item">
|
|
<div class="proof-label">Portfolio-Ziel</div>
|
|
<p class="proof-copy">Arbeiten, die nach echter Substanz aussehen — nicht nach Platzhaltern mit hübschem Rahmen.</p>
|
|
</div>
|
|
<div class="proof-item" style="border-left:1px solid var(--ink-border)">
|
|
<div class="proof-label">Signalwirkung</div>
|
|
<p class="proof-copy">Jede Karte trägt eine erkennbare Perspektive: Produkt, Architektur, Lernen oder Betrieb.</p>
|
|
</div>
|
|
<div class="proof-item" style="border-left:1px solid var(--ink-border)">
|
|
<div class="proof-label">Wirkung im Gespräch</div>
|
|
<p class="proof-copy">Inhalte als Einstieg für Fachgespräche — statt austauschbarer Selbstdarstellung.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- SNAPSHOT -->
|
|
<div class="container">
|
|
<section id="snapshot">
|
|
<div class="reveal">
|
|
<div class="s-label">// Profil</div>
|
|
<h2 class="s-title">Die komprimierte Version — für den<br><em>schnellen Eindruck.</em></h2>
|
|
<p class="s-subtitle">Vier kurze Aussagen, die im Kopf bleiben sollen, wenn sich jemand nur wenige Minuten Zeit nimmt.</p>
|
|
</div>
|
|
<div class="snapshot-grid reveal">
|
|
<div class="snap">
|
|
<div class="snap-kicker">Arbeitsweise</div>
|
|
<div class="snap-val">Hands-on</div>
|
|
<p class="snap-desc">Lernen über echte Umsetzung, Fehleranalyse und Iteration — nicht über Tutorial-Nachbauen.</p>
|
|
</div>
|
|
<div class="snap">
|
|
<div class="snap-kicker">Stärke</div>
|
|
<div class="snap-val">Frontend plus Betrieb</div>
|
|
<p class="snap-desc">Entscheidungen vom Interface bis zum Deployment zusammenhängend betrachten und daraus bessere Lösungen ableiten.</p>
|
|
</div>
|
|
<div class="snap">
|
|
<div class="snap-kicker">Motivation</div>
|
|
<div class="snap-val">Systeme wirklich verstehen</div>
|
|
<p class="snap-desc">Technik reizt mich, wenn ich sie nicht nur benutze, sondern selbst strukturieren und betreiben kann.</p>
|
|
</div>
|
|
<div class="snap">
|
|
<div class="snap-kicker">Eindruck</div>
|
|
<div class="snap-val">Substanz vor Buzzwords</div>
|
|
<p class="snap-desc">Diese Seite zeigt, wie ich arbeite und entscheide — nicht nur welche Begriffe ich aufzählen könnte.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- CONTACT -->
|
|
<div class="container">
|
|
<section id="contact">
|
|
<div class="contact-box reveal">
|
|
<h2>Kontakt für <em>Bewerbungen,</em><br>Zusammenarbeit und technische Gespräche</h2>
|
|
<p>Wenn du einen Entwickler suchst, der Design nicht von Technik trennt und Verantwortung auch hinter der Oberfläche übernimmt — schreib mir direkt.</p>
|
|
<a href="mailto:kontakt@noctura.dev" class="btn btn-gold">kontakt@noctura.dev</a>
|
|
<span class="contact-email">noctura.dev — persönliches Portfolio</span>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<footer>
|
|
<div class="footer-inner">
|
|
<span>noctura.dev — Persönliches Portfolio mit eigener Infrastruktur</span>
|
|
<span>HTML · CSS · JavaScript · Debian 12</span>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// Particle canvas
|
|
(function(){
|
|
const canvas=document.getElementById('c');
|
|
const ctx=canvas.getContext('2d');
|
|
let W,H,stars=[];
|
|
const rm=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
|
|
function init(){
|
|
W=canvas.width=window.innerWidth;
|
|
H=canvas.height=window.innerHeight;
|
|
const n=Math.floor((W*H)/14000);
|
|
stars=Array.from({length:n},()=>({
|
|
x:Math.random()*W,
|
|
y:Math.random()*H,
|
|
r:Math.random()*1.1+0.15,
|
|
o:Math.random()*0.45+0.08,
|
|
s:Math.random()*0.4+0.05,
|
|
t:Math.random()*Math.PI*2
|
|
}));
|
|
}
|
|
|
|
function draw(){
|
|
ctx.clearRect(0,0,W,H);
|
|
stars.forEach(s=>{
|
|
s.t+=0.007*s.s;
|
|
const op=s.o*(0.55+0.45*Math.sin(s.t));
|
|
ctx.beginPath();
|
|
ctx.arc(s.x,s.y,s.r,0,Math.PI*2);
|
|
ctx.fillStyle=`rgba(240,237,232,${op})`;
|
|
ctx.fill();
|
|
});
|
|
requestAnimationFrame(draw);
|
|
}
|
|
|
|
window.addEventListener('resize',init);
|
|
init();
|
|
if(!rm) draw();
|
|
})();
|
|
|
|
// Reveal on scroll
|
|
(function(){
|
|
const els=document.querySelectorAll('.reveal');
|
|
const rm=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
if(rm){els.forEach(e=>e.classList.add('in'));return;}
|
|
const io=new IntersectionObserver((entries)=>{
|
|
entries.forEach((e,i)=>{
|
|
if(e.isIntersecting){
|
|
setTimeout(()=>e.target.classList.add('in'),i*80);
|
|
io.unobserve(e.target);
|
|
}
|
|
});
|
|
},{threshold:0.1});
|
|
els.forEach(e=>io.observe(e));
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|