updated xdfnx's page
This commit is contained in:
+287
-277
@@ -5,9 +5,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta name="theme-color" content="#0a0a10" />
|
||||
<meta name="color-scheme" content="dark" />
|
||||
<meta name="description" content="xdfnx — Senior Full Stack Engineer. Systems built for pressure. Rust, C++, scalable web applications, core infrastructure optimization." />
|
||||
<meta name="description" content="xdfnx — Senior Full Stack Engineer. Systems built for pressure. Rust, C++, scalable web applications, and the core infrastructure that holds them together." />
|
||||
<meta name="author" content="xdfnx" />
|
||||
<meta name="keywords" content="xdfnx, Senior Full Stack Engineer, Rust, C++, TypeScript, systems programming, performance engineering, scalable web applications, infrastructure" />
|
||||
<link rel="canonical" href="https://xdfnx.cfd/" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://xdfnx.cfd/" />
|
||||
@@ -20,8 +19,8 @@
|
||||
<meta name="twitter:description" content="Systems built for pressure. Rust & C++ where speed is not optional." />
|
||||
<title>xdfnx — Senior Full Stack Engineer</title>
|
||||
|
||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230a0a10'/%3E%3Ctext x='16' y='22' font-family='monospace' font-size='15' font-weight='700' text-anchor='middle' fill='%23c2a878'%3Ex%3C/text%3E%3C/svg%3E" />
|
||||
<link rel="apple-touch-icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230a0a10'/%3E%3Ctext x='16' y='22' font-family='monospace' font-size='15' font-weight='700' text-anchor='middle' fill='%23c2a878'%3Ex%3C/text%3E%3C/svg%3E" />
|
||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230a0a10'/%3E%3Cpath d='M9 9h14M9 16h9M9 23h14' stroke='%23c2a878' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E" />
|
||||
<link rel="apple-touch-icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230a0a10'/%3E%3Cpath d='M9 9h14M9 16h9M9 23h14' stroke='%23c2a878' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
@@ -43,148 +42,125 @@
|
||||
--bg-2:#0e0e16;
|
||||
--surface:#12121c;
|
||||
--surface-2:#171723;
|
||||
--line:rgba(255,255,255,.07);
|
||||
--line-2:rgba(255,255,255,.12);
|
||||
--line-3:rgba(255,255,255,.18);
|
||||
--ink:#f4f3f1;
|
||||
--ink-dim:#aeb0bd;
|
||||
--ink-faint:#6f7080;
|
||||
--line:rgba(255,255,255,.07);
|
||||
--line-2:rgba(255,255,255,.12);
|
||||
--line-3:rgba(255,255,255,.18);
|
||||
--accent:#c2a878;
|
||||
--accent-bright:#e7cf9b;
|
||||
--accent-dim:#7c6a47;
|
||||
--accent-glow:rgba(194,168,120,.5);
|
||||
--flame:#e07a4c;
|
||||
--flame-dim:#a5522f;
|
||||
--ok:#7fd1a3;
|
||||
--info:#7aa2e6;
|
||||
--focus:#7aa2e6;
|
||||
--grad:linear-gradient(135deg,var(--accent) 0%,var(--flame) 100%);
|
||||
--grad-soft:linear-gradient(135deg,rgba(194,168,120,.16),rgba(224,122,76,.10));
|
||||
--ease:cubic-bezier(.2,.7,.2,1);
|
||||
--ease-out:cubic-bezier(.16,1,.3,1);
|
||||
}
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
html{scroll-behavior:smooth}
|
||||
body{
|
||||
background:var(--bg);
|
||||
color:var(--ink);
|
||||
background:var(--bg);color:var(--ink);
|
||||
font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||
font-weight:300;line-height:1.6;
|
||||
font-weight:300;line-height:1.6;letter-spacing:.01em;
|
||||
-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
|
||||
overflow-x:hidden;letter-spacing:.01em;
|
||||
overflow-x:hidden;
|
||||
background-image:
|
||||
radial-gradient(1200px 600px at 50% -200px,rgba(194,168,120,.10),transparent 60%),
|
||||
radial-gradient(900px 700px at 100% 30%,rgba(224,122,76,.06),transparent 60%);
|
||||
}
|
||||
::selection{background:var(--accent);color:#15200a}
|
||||
|
||||
:focus-visible{outline:2px solid var(--focus);outline-offset:3px;border-radius:2px}
|
||||
a:focus-visible,button:focus-visible{outline-offset:4px}
|
||||
|
||||
.skip{
|
||||
position:absolute;left:50%;top:-60px;transform:translateX(-50%);
|
||||
background:var(--accent);color:#15120a;padding:10px 18px;border-radius:0 0 6px 6px;
|
||||
font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600;
|
||||
text-decoration:none;z-index:200;transition:top .25s var(--ease);
|
||||
}
|
||||
.skip{position:absolute;left:50%;top:-60px;transform:translateX(-50%);background:var(--accent);color:#15120a;padding:10px 18px;border-radius:0 0 6px 6px;font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600;text-decoration:none;z-index:200;transition:top .25s var(--ease)}
|
||||
.skip:focus{top:0}
|
||||
|
||||
/* ---- atmosphere ---- */
|
||||
.grain{
|
||||
position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.04;
|
||||
background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
|
||||
}
|
||||
.grid-bg{
|
||||
position:fixed;inset:0;z-index:0;pointer-events:none;
|
||||
background-image:
|
||||
linear-gradient(rgba(255,255,255,.035) 1px,transparent 1px),
|
||||
linear-gradient(90deg,rgba(255,255,255,.035) 1px,transparent 1px);
|
||||
background-size:64px 64px;
|
||||
mask-image:radial-gradient(ellipse 90% 70% at 50% 0%,#000 35%,transparent 85%);
|
||||
-webkit-mask-image:radial-gradient(ellipse 90% 70% at 50% 0%,#000 35%,transparent 85%);
|
||||
}
|
||||
.glow{position:fixed;z-index:0;pointer-events:none;border-radius:50%;filter:blur(140px);opacity:.55;will-change:transform}
|
||||
.glow.a{top:-220px;left:30%;width:760px;height:460px;background:radial-gradient(circle,rgba(194,168,120,.16),transparent 70%)}
|
||||
/* atmosphere */
|
||||
.grain{position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.04;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
|
||||
.grid-bg{position:fixed;inset:0;z-index:0;pointer-events:none;background-image:linear-gradient(rgba(255,255,255,.03) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.03) 1px,transparent 1px);background-size:64px 64px;mask-image:radial-gradient(ellipse 90% 70% at 50% 0%,#000 35%,transparent 85%);-webkit-mask-image:radial-gradient(ellipse 90% 70% at 50% 0%,#000 35%,transparent 85%)}
|
||||
.glow{position:fixed;z-index:0;pointer-events:none;border-radius:50%;filter:blur(140px);opacity:.5;will-change:transform}
|
||||
.glow.a{top:-220px;left:25%;width:760px;height:460px;background:radial-gradient(circle,rgba(194,168,120,.16),transparent 70%)}
|
||||
.glow.b{top:55vh;right:-200px;width:560px;height:560px;background:radial-gradient(circle,rgba(224,122,76,.10),transparent 70%)}
|
||||
|
||||
/* ---- layout ---- */
|
||||
.wrap{max-width:1200px;margin:0 auto;padding:0 28px;position:relative;z-index:2}
|
||||
section{position:relative;z-index:2}
|
||||
|
||||
/* ---- top bar ---- */
|
||||
header.bar{
|
||||
position:fixed;top:0;left:0;right:0;z-index:50;
|
||||
backdrop-filter:blur(16px) saturate(1.2);-webkit-backdrop-filter:blur(16px) saturate(1.2);
|
||||
background:rgba(10,10,16,.72);
|
||||
border-bottom:1px solid var(--line);
|
||||
transition:transform .4s var(--ease);
|
||||
}
|
||||
/* top bar */
|
||||
header.bar{position:fixed;top:0;left:0;right:0;z-index:50;backdrop-filter:blur(16px) saturate(1.2);-webkit-backdrop-filter:blur(16px) saturate(1.2);background:rgba(10,10,16,.72);border-bottom:1px solid var(--line);transition:transform .4s var(--ease)}
|
||||
header.bar.hidden{transform:translateY(-100%)}
|
||||
.bar-inner{display:flex;align-items:center;justify-content:space-between;height:64px;max-width:1200px;margin:0 auto;padding:0 28px}
|
||||
.brand{font-family:'JetBrains Mono',monospace;font-size:14px;font-weight:700;letter-spacing:.02em;color:var(--ink);text-decoration:none;display:flex;align-items:center;gap:8px}
|
||||
.brand{font-family:'JetBrains Mono',monospace;font-size:14px;font-weight:700;letter-spacing:.02em;color:var(--ink);text-decoration:none;display:flex;align-items:center;gap:9px}
|
||||
.brand .dot{width:9px;height:9px;border-radius:50%;background:var(--grad);box-shadow:0 0 14px var(--accent-glow)}
|
||||
.nav-links{display:flex;gap:28px;align-items:center}
|
||||
.nav-links a{color:var(--ink-dim);text-decoration:none;font-size:13px;font-family:'JetBrains Mono',monospace;transition:color .25s var(--ease);position:relative;padding:6px 0}
|
||||
.nav-links a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .3s var(--ease)}
|
||||
.nav-links a:hover,.nav-links a.active{color:var(--ink)}
|
||||
.nav-links a:hover::after,.nav-links a.active::after{transform:scaleX(1)}
|
||||
.nav-cta{color:var(--accent)!important}
|
||||
.nav-cta::after{background:var(--accent)}
|
||||
.menu-btn{display:none;background:none;border:1px solid var(--line-2);color:var(--ink);padding:8px 12px;font-family:'JetBrains Mono',monospace;font-size:12px;cursor:pointer;border-radius:3px;transition:border-color .25s var(--ease),color .25s var(--ease)}
|
||||
.nav-cta{color:var(--accent)!important}.nav-cta::after{background:var(--accent)}
|
||||
.menu-btn{display:none;background:none;border:1px solid var(--line-2);color:var(--ink);padding:8px 12px;font-family:'JetBrains Mono',monospace;font-size:12px;cursor:pointer;border-radius:4px;transition:border-color .25s,color .25s}
|
||||
.menu-btn:hover{border-color:var(--accent);color:var(--accent)}
|
||||
|
||||
/* ---- hero ---- */
|
||||
.hero{min-height:100svh;display:flex;align-items:center;padding:140px 0 90px}
|
||||
.hero-grid{display:grid;grid-template-columns:1fr;gap:36px;max-width:920px}
|
||||
.hero{min-height:100svh;display:flex;align-items:center;padding:140px 0 80px}
|
||||
.hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:64px;align-items:center}
|
||||
.hero-left{display:flex;flex-direction:column;gap:30px;max-width:560px}
|
||||
.eyebrow{display:inline-flex;align-items:center;gap:12px;font-family:'JetBrains Mono',monospace;font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-dim);width:fit-content}
|
||||
.pulse{width:8px;height:8px;border-radius:50%;background:var(--grad);position:relative;box-shadow:0 0 0 0 var(--accent-glow)}
|
||||
.pulse::after{content:"";position:absolute;inset:-6px;border-radius:50%;border:1px solid var(--accent);opacity:.6;animation:ping 2.4s var(--ease) infinite}
|
||||
.status-pill{border:1px solid var(--line-2);padding:5px 12px;border-radius:999px;color:var(--ink);background:rgba(255,255,255,.02)}
|
||||
.status-pill b{color:var(--accent);font-weight:600}
|
||||
@media (prefers-reduced-motion: no-preference){@keyframes ping{0%{transform:scale(.7);opacity:.7}70%{transform:scale(1.7);opacity:0}100%{opacity:0}}}
|
||||
@media (prefers-reduced-motion:no-preference){@keyframes ping{0%{transform:scale(.7);opacity:.7}70%{transform:scale(1.7);opacity:0}100%{opacity:0}}}
|
||||
|
||||
h1.hero-title{
|
||||
font-size:clamp(48px,9vw,116px);line-height:.95;font-weight:800;
|
||||
letter-spacing:-.04em;color:var(--ink);
|
||||
}
|
||||
h1.hero-title{font-size:clamp(40px,5.8vw,78px);line-height:.98;font-weight:800;letter-spacing:-.035em;color:var(--ink)}
|
||||
h1.hero-title .soft{color:var(--ink-faint);font-weight:300;font-style:italic}
|
||||
h1.hero-title .accent{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:var(--accent)}
|
||||
.term-cursor{display:inline-block;width:14px;height:.88em;background:var(--accent);margin-left:4px;vertical-align:-.05em;animation:blink 1s steps(2) infinite;border-radius:1px}
|
||||
@media (prefers-reduced-motion: no-preference){@keyframes blink{50%{opacity:0}}}
|
||||
|
||||
.hero-sub{font-size:clamp(17px,2.1vw,21px);color:var(--ink-dim);max-width:640px;font-weight:300}
|
||||
.hero-sub{font-size:clamp(16px,1.8vw,19px);color:var(--ink-dim);font-weight:300}
|
||||
.hero-sub b{color:var(--ink);font-weight:500}
|
||||
.hero-sub .hl{color:var(--accent)}
|
||||
|
||||
.cta-row{display:flex;gap:14px;flex-wrap:wrap;margin-top:6px}
|
||||
.btn{
|
||||
display:inline-flex;align-items:center;gap:10px;min-height:48px;
|
||||
padding:14px 26px;border-radius:4px;text-decoration:none;font-size:14px;font-weight:600;
|
||||
font-family:'JetBrains Mono',monospace;letter-spacing:.04em;
|
||||
transition:transform .35s var(--ease-out),box-shadow .35s var(--ease-out),background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
|
||||
cursor:pointer;border:1px solid transparent;position:relative;
|
||||
}
|
||||
.btn.primary{background:var(--grad);color:#1a1408;border-color:transparent;background-size:200% 100%;background-position:0 0}
|
||||
.cta-row{display:flex;gap:14px;flex-wrap:wrap}
|
||||
.btn{display:inline-flex;align-items:center;gap:10px;min-height:48px;padding:14px 24px;border-radius:5px;text-decoration:none;font-size:14px;font-weight:600;font-family:'JetBrains Mono',monospace;letter-spacing:.04em;transition:transform .35s var(--ease-out),box-shadow .35s var(--ease-out),background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);cursor:pointer;border:1px solid transparent;position:relative}
|
||||
.btn.primary{background:var(--grad);color:#1a1408;background-size:200% 100%;background-position:0 0}
|
||||
.btn.primary:hover{transform:translateY(-3px);box-shadow:0 16px 40px -12px var(--accent-glow);background-position:100% 0}
|
||||
.btn.ghost{color:var(--ink);border-color:var(--line-2);background:rgba(255,255,255,.02)}
|
||||
.btn.ghost:hover{border-color:var(--accent);color:var(--accent);transform:translateY(-3px)}
|
||||
.btn .arr{transition:transform .3s var(--ease)}
|
||||
.btn:hover .arr{transform:translateX(5px)}
|
||||
|
||||
.hero-meta{display:flex;gap:42px;margin-top:22px;flex-wrap:wrap}
|
||||
.hero-meta{display:flex;gap:36px;flex-wrap:wrap}
|
||||
.hero-meta div{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--ink-faint);letter-spacing:.06em}
|
||||
.hero-meta b{color:var(--ink-dim);font-weight:500}
|
||||
|
||||
/* hero terminal panel */
|
||||
.hero-term{margin-top:8px;border:1px solid var(--line-2);background:linear-gradient(180deg,rgba(18,18,28,.9),rgba(10,10,16,.9));border-radius:8px;overflow:hidden;max-width:560px;box-shadow:0 24px 60px -30px rgba(0,0,0,.8)}
|
||||
.ht-bar{display:flex;align-items:center;gap:8px;padding:12px 14px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.02)}
|
||||
.ht-dot{width:10px;height:10px;border-radius:50%}
|
||||
.ht-dot.r{background:#ff5f57}.ht-dot.y{background:#febc2e}.ht-dot.g{background:#28c840}
|
||||
.ht-title{margin-left:8px;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);letter-spacing:.06em}
|
||||
.ht-body{padding:18px 18px 22px;font-family:'JetBrains Mono',monospace;font-size:13px;line-height:1.7;min-height:160px;color:var(--ink-dim)}
|
||||
.ht-body .cmt{color:var(--ink-faint)}
|
||||
.ht-body .k{color:#e7cf9b}
|
||||
.ht-body .v{color:#9bb7e6}
|
||||
.ht-body .ok{color:#7fd1a3}
|
||||
.ht-line .prompt{color:var(--accent)}
|
||||
.term-cursor2{display:inline-block;width:8px;height:1em;background:var(--accent);vertical-align:-.12em;border-radius:1px;animation:blink 1.1s steps(2) infinite}
|
||||
/* ---- hero viz: live system monitor ---- */
|
||||
.monitor{position:relative;border:1px solid var(--line-2);border-radius:10px;overflow:hidden;background:linear-gradient(180deg,rgba(18,18,28,.92),rgba(10,10,16,.92));box-shadow:0 30px 70px -40px rgba(0,0,0,.9),inset 0 1px 0 rgba(255,255,255,.04)}
|
||||
.mon-bar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 14px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.025)}
|
||||
.mon-dots{display:flex;gap:7px}
|
||||
.mon-dot{width:10px;height:10px;border-radius:50%}
|
||||
.mon-dot.r{background:#ff5f57}.mon-dot.y{background:#febc2e}.mon-dot.g{background:#28c840}
|
||||
.mon-status{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);letter-spacing:.08em;text-transform:uppercase;display:flex;align-items:center;gap:8px}
|
||||
.mon-status .live{width:7px;height:7px;border-radius:50%;background:var(--ok);box-shadow:0 0 10px var(--ok);animation:livepulse 1.6s ease-in-out infinite}
|
||||
@media (prefers-reduced-motion:no-preference){@keyframes livepulse{0%,100%{opacity:1}50%{opacity:.35}}}
|
||||
.mon-body{padding:18px 16px 16px;display:grid;gap:14px}
|
||||
|
||||
.mon-row{display:grid;gap:6px}
|
||||
.mon-row .lbl{display:flex;justify-content:space-between;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);letter-spacing:.06em}
|
||||
.mon-row .lbl b{color:var(--accent);font-weight:600}
|
||||
.mon-track{height:6px;border-radius:3px;background:rgba(255,255,255,.06);overflow:hidden;position:relative}
|
||||
.mon-fill{height:100%;border-radius:3px;background:var(--grad);transform-origin:left;transform:scaleX(0);width:100%;transition:transform .9s var(--ease-out)}
|
||||
.mon-row.in .mon-fill{transform:scaleX(.0)}
|
||||
|
||||
.mon-chart{height:120px;position:relative;border:1px solid var(--line);border-radius:6px;background:linear-gradient(180deg,rgba(255,255,255,.02),transparent);overflow:hidden}
|
||||
.mon-chart svg{display:block;width:100%;height:100%}
|
||||
.mon-chart .lab{position:absolute;top:8px;left:10px;font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-faint);letter-spacing:.08em;text-transform:uppercase}
|
||||
.mon-chart .lab b{color:var(--ok);font-weight:600}
|
||||
.mon-chart .pct{position:absolute;bottom:8px;right:10px;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim)}
|
||||
.mon-chart .pct b{color:var(--accent);font-weight:600}
|
||||
|
||||
/* ---- section heading ---- */
|
||||
.sec{padding:120px 0;border-top:1px solid var(--line)}
|
||||
@@ -192,132 +168,118 @@
|
||||
.sec-id{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--accent);letter-spacing:.1em;font-weight:500}
|
||||
.sec-title{font-size:clamp(30px,4.2vw,46px);font-weight:700;letter-spacing:-.025em}
|
||||
.sec-rule{flex:1;height:1px;background:linear-gradient(90deg,var(--line-2),transparent)}
|
||||
.sec-sub{color:var(--ink-dim);font-size:16px;max-width:620px;margin-top:14px;font-weight:300}
|
||||
|
||||
/* ---- about ---- */
|
||||
.about-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:64px;align-items:start}
|
||||
.about-lead{font-size:clamp(21px,2.5vw,28px);line-height:1.42;font-weight:300;color:var(--ink);letter-spacing:-.01em}
|
||||
/* ---- about: lead + what I do trio (replaces variant scratchpad) ---- */
|
||||
.about-grid{display:grid;grid-template-columns:.95fr 1.05fr;gap:60px;align-items:start}
|
||||
.about-lead{font-size:clamp(20px,2.4vw,27px);line-height:1.4;font-weight:300;color:var(--ink);letter-spacing:-.01em}
|
||||
.about-lead .hl{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:var(--accent)}
|
||||
.about-body{color:var(--ink-dim);font-size:15px;line-height:1.85;margin-top:24px;max-width:560px}
|
||||
.variant-note{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);letter-spacing:.12em;text-transform:uppercase;margin-bottom:16px}
|
||||
.variants{display:flex;flex-direction:column;gap:18px}
|
||||
.variant{border:1px solid var(--line);background:linear-gradient(180deg,var(--surface),var(--bg-2));padding:22px 24px;border-radius:6px;position:relative;overflow:hidden;transition:border-color .35s var(--ease),transform .35s var(--ease-out)}
|
||||
.variant:hover{border-color:var(--line-3);transform:translateX(6px)}
|
||||
.variant::before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--grad);transform:scaleY(0);transform-origin:top;transition:transform .35s var(--ease-out)}
|
||||
.variant:hover::before{transform:scaleY(1)}
|
||||
.variant p{color:var(--ink-dim);font-size:14px;line-height:1.7}
|
||||
.variant .tag{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--accent);letter-spacing:.14em;text-transform:uppercase;margin-bottom:10px;display:block;font-weight:600}
|
||||
.about-body{color:var(--ink-dim);font-size:15px;line-height:1.85;margin-top:22px;max-width:520px}
|
||||
|
||||
/* ---- stats ---- */
|
||||
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:8px;overflow:hidden}
|
||||
.stat{background:var(--bg);padding:44px 30px;position:relative;overflow:hidden;transition:background .4s var(--ease)}
|
||||
.do-trio{display:flex;flex-direction:column;gap:14px}
|
||||
.do-card{display:grid;grid-template-columns:48px 1fr;gap:18px;padding:22px;border:1px solid var(--line);border-radius:8px;background:linear-gradient(180deg,var(--surface),var(--bg-2));transition:border-color .35s var(--ease),transform .35s var(--ease-out)}
|
||||
.do-card:hover{border-color:var(--line-3);transform:translateX(6px)}
|
||||
.do-ico{width:42px;height:42px;border-radius:8px;background:var(--grad-soft);border:1px solid var(--line-2);display:grid;place-items:center;font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:700;color:var(--accent)}
|
||||
.do-card h3{font-size:16px;font-weight:700;letter-spacing:-.01em}
|
||||
.do-card p{color:var(--ink-dim);font-size:13.5px;line-height:1.65;margin-top:6px}
|
||||
|
||||
/* ---- stats (grounded) ---- */
|
||||
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:10px;overflow:hidden}
|
||||
.stat{background:var(--bg);padding:40px 28px;position:relative;overflow:hidden;transition:background .4s var(--ease)}
|
||||
.stat::after{content:"";position:absolute;inset:0;background:radial-gradient(circle at 100% 0%,rgba(194,168,120,.07),transparent 55%);opacity:0;transition:opacity .4s var(--ease)}
|
||||
.stat:hover{background:var(--bg-2)}
|
||||
.stat:hover::after{opacity:1}
|
||||
.stat-num{font-size:clamp(46px,6.5vw,68px);font-weight:700;letter-spacing:-.035em;color:var(--ink);line-height:1}
|
||||
.stat-num{font-size:clamp(42px,5.6vw,62px);font-weight:700;letter-spacing:-.035em;color:var(--ink);line-height:1}
|
||||
.stat-num .plus{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:var(--accent)}
|
||||
.stat-label{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);letter-spacing:.14em;text-transform:uppercase;margin-top:12px;font-weight:500}
|
||||
.stat-desc{color:var(--ink-dim);font-size:13px;margin-top:8px;font-weight:300}
|
||||
|
||||
/* ---- marquee ---- */
|
||||
.marquee{overflow:hidden;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:18px 0;background:rgba(255,255,255,.015);-webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
|
||||
.marquee-track{display:flex;gap:48px;width:max-content;animation:scroll 32s linear infinite;font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:.12em;color:var(--ink-dim);text-transform:uppercase}
|
||||
.marquee-track span{display:inline-flex;align-items:center;gap:12px;white-space:nowrap}
|
||||
.marquee-track span::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--accent)}
|
||||
@media (prefers-reduced-motion: no-preference){@keyframes scroll{to{transform:translateX(-50%)}}}
|
||||
.stat-desc{color:var(--ink-dim);font-size:13px;margin-top:6px;font-weight:300}
|
||||
|
||||
/* ---- experience ---- */
|
||||
.timeline{display:flex;flex-direction:column;gap:2px}
|
||||
.job{display:grid;grid-template-columns:170px 1fr;gap:40px;padding:46px 0;border-top:1px solid var(--line);transition:padding-left .4s var(--ease-out)}
|
||||
.job:last-child{border-bottom:1px solid var(--line)}
|
||||
.timeline{display:flex;flex-direction:column}
|
||||
.job{display:grid;grid-template-columns:160px 1fr;gap:40px;padding:46px 0;border-top:1px solid var(--line);transition:padding-left .4s var(--ease-out)}
|
||||
.job:first-child{border-top:none}
|
||||
.job:hover{padding-left:10px}
|
||||
.job-period{font-family:'JetBrains Mono',monospace;font-size:13px;color:var(--accent);letter-spacing:.04em;padding-top:5px;font-weight:500}
|
||||
.job-body h3{font-size:22px;font-weight:700;letter-spacing:-.01em}
|
||||
.job-body h3{font-size:21px;font-weight:700;letter-spacing:-.01em}
|
||||
.job-co{color:var(--ink-dim);font-weight:300;font-size:15px;margin-top:3px}
|
||||
.job-co span{color:var(--ink-faint)}
|
||||
.job-desc{color:var(--ink-dim);font-size:15px;line-height:1.75;margin-top:18px;max-width:680px}
|
||||
.job-desc{color:var(--ink-dim);font-size:15px;line-height:1.75;margin-top:16px;max-width:680px}
|
||||
.job-desc b{color:var(--ink);font-weight:500}
|
||||
.job-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:22px}
|
||||
.tag-chip{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);border:1px solid var(--line-2);padding:6px 12px;border-radius:999px;letter-spacing:.04em;transition:border-color .25s var(--ease),color .25s var(--ease)}
|
||||
.tag-chip:hover{border-color:var(--line-3);color:var(--ink)}
|
||||
.tag-chip.hi{color:var(--accent);border-color:var(--accent-dim);background:rgba(194,168,120,.06)}
|
||||
.job-divider{height:1px;background:var(--line);margin:0 auto;width:0;transition:width .5s var(--ease-out)}
|
||||
|
||||
/* ---- arsenal ---- */
|
||||
/* ---- arsenal: grouped, no marquee ---- */
|
||||
.arsenal{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
|
||||
.arm-card{border:1px solid var(--line);background:linear-gradient(180deg,var(--surface),var(--bg));padding:36px 30px;border-radius:8px;position:relative;transition:transform .4s var(--ease-out),border-color .35s var(--ease);overflow:hidden}
|
||||
.arm-card{border:1px solid var(--line);background:linear-gradient(180deg,var(--surface),var(--bg));padding:32px 28px;border-radius:10px;position:relative;transition:transform .4s var(--ease-out),border-color .35s var(--ease);overflow:hidden}
|
||||
.arm-card::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--accent),transparent);opacity:0;transition:opacity .4s var(--ease)}
|
||||
.arm-card::after{content:"";position:absolute;inset:0;background:radial-gradient(circle at 50% 0%,rgba(194,168,120,.07),transparent 60%);opacity:0;transition:opacity .4s var(--ease)}
|
||||
.arm-card:hover{border-color:var(--line-3);transform:translateY(-6px)}
|
||||
.arm-card:hover::before,.arm-card:hover::after{opacity:1}
|
||||
.arm-num{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);letter-spacing:.14em;font-weight:500}
|
||||
.arm-title{font-size:20px;font-weight:700;margin:14px 0 12px;letter-spacing:-.01em}
|
||||
.arm-card:hover::before{opacity:1}
|
||||
.arm-ico{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);letter-spacing:.14em;font-weight:500;display:flex;align-items:center;gap:8px}
|
||||
.arm-ico .n{color:var(--accent)}
|
||||
.arm-title{font-size:19px;font-weight:700;margin:12px 0 10px;letter-spacing:-.01em}
|
||||
.arm-desc{color:var(--ink-dim);font-size:14px;line-height:1.7;font-weight:300}
|
||||
.arm-stack{display:flex;flex-wrap:wrap;gap:7px;margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}
|
||||
.arm-stack span{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);border:1px solid var(--line);padding:5px 11px;border-radius:4px;letter-spacing:.04em;transition:color .25s var(--ease),border-color .25s var(--ease)}
|
||||
.arm-stack{display:flex;flex-wrap:wrap;gap:7px;margin-top:20px;padding-top:16px;border-top:1px solid var(--line)}
|
||||
.arm-stack span{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);border:1px solid var(--line);padding:5px 10px;border-radius:5px;letter-spacing:.04em;transition:color .25s var(--ease),border-color .25s var(--ease)}
|
||||
.arm-stack span:hover{color:var(--accent);border-color:var(--accent-dim)}
|
||||
|
||||
/* ---- work ---- */
|
||||
.work-grid{display:flex;flex-direction:column;gap:2px}
|
||||
.work{display:grid;grid-template-columns:90px 1fr 280px;gap:36px;padding:50px 0;border-top:1px solid var(--line);align-items:start;transition:padding-left .4s var(--ease-out),background .4s var(--ease)}
|
||||
.work:last-child{border-bottom:1px solid var(--line)}
|
||||
.work-grid{display:flex;flex-direction:column}
|
||||
.work{display:grid;grid-template-columns:80px 1fr 260px;gap:36px;padding:48px 0;border-top:1px solid var(--line);align-items:start;transition:padding-left .4s var(--ease-out),background .4s var(--ease)}
|
||||
.work:first-child{border-top:none}
|
||||
.work:hover{padding-left:12px;background:linear-gradient(90deg,rgba(255,255,255,.02),transparent 40%)}
|
||||
.work-idx{font-family:'JetBrains Mono',monospace;font-size:13px;color:var(--accent);letter-spacing:.08em;padding-top:6px;font-weight:500}
|
||||
.work-main h3{font-size:clamp(23px,2.7vw,32px);font-weight:700;letter-spacing:-.02em}
|
||||
.work-main p{color:var(--ink-dim);font-size:15px;line-height:1.75;margin-top:16px;max-width:580px;font-weight:300}
|
||||
.work-main h3{font-size:clamp(22px,2.6vw,30px);font-weight:700;letter-spacing:-.02em}
|
||||
.work-metric{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--accent);margin-top:10px;letter-spacing:.04em}
|
||||
.work-main p{color:var(--ink-dim);font-size:15px;line-height:1.75;margin-top:14px;max-width:580px;font-weight:300}
|
||||
.work-main p b{color:var(--ink);font-weight:500}
|
||||
.work-side{padding-top:8px}
|
||||
.work-side .lbl{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-faint);letter-spacing:.14em;text-transform:uppercase;margin-bottom:12px;font-weight:500}
|
||||
.work-stack{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.work-stack span{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);border:1px solid var(--line-2);padding:6px 11px;border-radius:4px}
|
||||
.work-stack span{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);border:1px solid var(--line-2);padding:5px 10px;border-radius:5px}
|
||||
|
||||
/* ---- final cta ---- */
|
||||
.cta-sec{padding:150px 0;text-align:center;border-top:1px solid var(--line);position:relative}
|
||||
.cta-sec::before{content:"";position:absolute;inset:0;background:radial-gradient(ellipse 60% 80% at 50% 100%,rgba(194,168,120,.09),transparent 70%);pointer-events:none}
|
||||
.cta-eyebrow{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--accent);letter-spacing:.16em;text-transform:uppercase;margin-bottom:26px;position:relative;font-weight:600}
|
||||
h2.cta-title{font-size:clamp(40px,6.4vw,76px);font-weight:700;letter-spacing:-.04em;line-height:1.02;position:relative;max-width:860px;margin:0 auto}
|
||||
.cta-sec{padding:140px 0;text-align:center;border-top:1px solid var(--line);position:relative}
|
||||
.cta-sec::before{content:"";position:absolute;inset:0;background:radial-gradient(ellipse 60% 80% at 50% 100%,rgba(194,168,120,.10),transparent 70%);pointer-events:none}
|
||||
.cta-eyebrow{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--accent);letter-spacing:.16em;text-transform:uppercase;margin-bottom:24px;position:relative;font-weight:600}
|
||||
h2.cta-title{font-size:clamp(34px,5.2vw,66px);font-weight:700;letter-spacing:-.035em;line-height:1.05;position:relative;max-width:820px;margin:0 auto}
|
||||
.cta-title .soft{color:var(--ink-faint);font-weight:300}
|
||||
.cta-title .accent{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:var(--accent)}
|
||||
.cta-sub{color:var(--ink-dim);font-size:17px;margin-top:26px;font-weight:300;max-width:540px;margin-left:auto;margin-right:auto;position:relative}
|
||||
.cta-sec .cta-row{justify-content:center;margin-top:42px;position:relative}
|
||||
|
||||
.cta-sub{color:var(--ink-dim);font-size:17px;margin-top:24px;font-weight:300;max-width:540px;margin-left:auto;margin-right:auto;position:relative}
|
||||
.cta-sec .cta-row{justify-content:center;margin-top:38px;position:relative}
|
||||
.email-copy{position:relative}
|
||||
.copy-tip{
|
||||
position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%) translateY(6px);
|
||||
background:var(--surface-2);border:1px solid var(--line-2);color:var(--accent);
|
||||
font-family:'JetBrains Mono',monospace;font-size:11px;padding:7px 13px;border-radius:4px;
|
||||
opacity:0;pointer-events:none;transition:opacity .25s var(--ease),transform .25s var(--ease);white-space:nowrap;
|
||||
}
|
||||
.copy-tip{position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%) translateY(6px);background:var(--surface-2);border:1px solid var(--line-2);color:var(--accent);font-family:'JetBrains Mono',monospace;font-size:11px;padding:7px 13px;border-radius:5px;opacity:0;pointer-events:none;transition:opacity .25s var(--ease),transform .25s var(--ease);white-space:nowrap}
|
||||
.copy-tip.show{opacity:1;transform:translateX(-50%) translateY(0)}
|
||||
|
||||
/* ---- footer ---- */
|
||||
footer{border-top:1px solid var(--line);padding:54px 0;padding-bottom:max(60px,env(safe-area-inset-bottom))}
|
||||
.foot{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:20px}
|
||||
footer{border-top:1px solid var(--line);padding:50px 0;padding-bottom:max(56px,env(safe-area-inset-bottom))}
|
||||
.foot{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:24px}
|
||||
.foot-left{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--ink-faint);letter-spacing:.04em}
|
||||
.foot-left b{color:var(--ink-dim);font-weight:500}
|
||||
.foot-right{display:flex;gap:24px}
|
||||
.foot-right a{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--ink-dim);text-decoration:none;letter-spacing:.04em;transition:color .25s var(--ease)}
|
||||
.foot-right{display:flex;gap:26px;align-items:center}
|
||||
.foot-right a{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--ink-dim);text-decoration:none;letter-spacing:.04em;transition:color .25s var(--ease);display:inline-flex;align-items:center;gap:7px}
|
||||
.foot-right a:hover{color:var(--accent)}
|
||||
.foot-right svg{width:14px;height:14px;fill:currentColor}
|
||||
|
||||
/* ---- reveal ---- */
|
||||
.reveal{opacity:0;transform:translateY(28px);transition:opacity .9s var(--ease-out),transform .9s var(--ease-out)}
|
||||
/* reveal */
|
||||
.reveal{opacity:0;transform:translateY(26px);transition:opacity .9s var(--ease-out),transform .9s var(--ease-out)}
|
||||
.reveal.in{opacity:1;transform:none}
|
||||
.reveal.d1{transition-delay:.08s}.reveal.d2{transition-delay:.16s}.reveal.d3{transition-delay:.24s}.reveal.d4{transition-delay:.32s}.reveal.d5{transition-delay:.4s}
|
||||
|
||||
/* ---- responsive ---- */
|
||||
@media(max-width:920px){
|
||||
.hero-grid{grid-template-columns:1fr;gap:44px}
|
||||
.hero-left{max-width:none}
|
||||
.about-grid{grid-template-columns:1fr;gap:44px}
|
||||
}
|
||||
@media(max-width:880px){
|
||||
.nav-links{position:fixed;inset:64px 0 auto 0;background:rgba(10,10,16,.97);backdrop-filter:blur(16px);flex-direction:column;gap:0;padding:8px 0;border-bottom:1px solid var(--line);transform:translateY(-130%);transition:transform .35s var(--ease);border-radius:0 0 12px 12px}
|
||||
.nav-links.open{transform:translateY(0)}
|
||||
.nav-links a{padding:18px 28px;width:100%;border-bottom:1px solid var(--line)}
|
||||
.menu-btn{display:block}
|
||||
.about-grid{grid-template-columns:1fr;gap:44px}
|
||||
.stats{grid-template-columns:1fr}
|
||||
.arsenal{grid-template-columns:1fr}
|
||||
.job{grid-template-columns:1fr;gap:14px;padding-left:0!important}
|
||||
.stats,.arsenal{grid-template-columns:1fr}
|
||||
.job{grid-template-columns:1fr;gap:12px;padding-left:0!important}
|
||||
.job-period{padding-top:0}
|
||||
.work{grid-template-columns:1fr;gap:18px;padding-left:0!important}
|
||||
.work-side{padding-top:0}
|
||||
.work-side{padding-top:4px}
|
||||
.hero{padding-top:120px}
|
||||
.sec{padding:84px 0}
|
||||
.hero-term{max-width:none}
|
||||
}
|
||||
@media(prefers-reduced-motion:reduce){
|
||||
*{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
|
||||
@@ -337,9 +299,9 @@
|
||||
<a class="brand" href="#about"><span class="dot" aria-hidden="true"></span>xdfnx</a>
|
||||
<nav class="nav-links" id="nav" aria-label="Primary">
|
||||
<a href="#about">About</a>
|
||||
<a href="#experience">Record</a>
|
||||
<a href="#arsenal">Arsenal</a>
|
||||
<a href="#work">Work</a>
|
||||
<a href="#arsenal">Arsenal</a>
|
||||
<a href="#experience">Record</a>
|
||||
<a href="#contact" class="nav-cta">Contact →</a>
|
||||
</nav>
|
||||
<button class="menu-btn" id="menuBtn" aria-expanded="false" aria-controls="nav">Menu</button>
|
||||
@@ -351,55 +313,67 @@
|
||||
<!-- HERO -->
|
||||
<section class="hero" aria-labelledby="hero-title">
|
||||
<div class="hero-grid">
|
||||
<div class="hero-left">
|
||||
<div class="eyebrow reveal">
|
||||
<span class="pulse" aria-hidden="true"></span>
|
||||
<span class="status-pill"><b>Open</b> for Complex Projects</span>
|
||||
</div>
|
||||
|
||||
<h1 class="hero-title reveal d1" id="hero-title">
|
||||
Systems built<br/>
|
||||
<span class="soft">for</span> <span class="accent">pressure</span>.<span class="term-cursor" aria-hidden="true"></span>
|
||||
<span class="soft">for</span> <span class="accent">pressure</span>.
|
||||
</h1>
|
||||
|
||||
<p class="hero-sub reveal d2">
|
||||
Senior Full Stack Engineer. I build <b>scalable web applications</b> and optimize the <b>core infrastructure</b> that holds them together. <span class="hl">Rust & C++</span> on the paths where speed is not optional.
|
||||
Senior Full Stack Engineer. I build <b>scalable web applications</b> and engineer the <b>core infrastructure</b> that holds them together — <span class="hl">Rust & C++</span> on the paths where speed is not optional.
|
||||
</p>
|
||||
|
||||
<div class="cta-row reveal d3">
|
||||
<a href="#contact" class="btn primary">Contact Me <span class="arr" aria-hidden="true">→</span></a>
|
||||
<a href="#work" class="btn ghost">View Work</a>
|
||||
</div>
|
||||
|
||||
<div class="hero-meta reveal d5">
|
||||
<div>ROLE / <b>Senior Full Stack Engineer</b></div>
|
||||
<div>FOCUS / <b>System Performance</b></div>
|
||||
<div>STACK / <b>Rust · C++ · TS</b></div>
|
||||
<div>UPTIME / <b>Built to hold</b></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-term reveal d5" aria-hidden="true">
|
||||
<div class="ht-bar">
|
||||
<span class="ht-dot r"></span><span class="ht-dot y"></span><span class="ht-dot g"></span>
|
||||
<span class="ht-title">xdfnx@engine-room — cargo build --release</span>
|
||||
<!-- live system monitor -->
|
||||
<div class="monitor reveal d4" role="img" aria-label="Live system monitor showing throughput, latency and p99 latency chart holding steady under load.">
|
||||
<div class="mon-bar">
|
||||
<div class="mon-dots"><span class="mon-dot r"></span><span class="mon-dot y"></span><span class="mon-dot g"></span></div>
|
||||
<div class="mon-status"><span class="live" aria-hidden="true"></span>system · holding</div>
|
||||
</div>
|
||||
<div class="mon-body">
|
||||
<div class="mon-row" data-fill="0.82">
|
||||
<div class="lbl"><span>Throughput</span><b>82k req/s</b></div>
|
||||
<div class="mon-track"><div class="mon-fill"></div></div>
|
||||
</div>
|
||||
<div class="mon-row" data-fill="0.12">
|
||||
<div class="lbl"><span>p50 latency</span><b>4.1 ms</b></div>
|
||||
<div class="mon-track"><div class="mon-fill"></div></div>
|
||||
</div>
|
||||
<div class="mon-row" data-fill="0.4">
|
||||
<div class="lbl"><span>p99 latency</span><b>18.3 ms</b></div>
|
||||
<div class="mon-track"><div class="mon-fill"></div></div>
|
||||
</div>
|
||||
<div class="mon-chart">
|
||||
<div class="lab">load · <b>holding</b></div>
|
||||
<svg viewBox="0 0 300 120" preserveAspectRatio="none" aria-hidden="true">
|
||||
<defs>
|
||||
<linearGradient id="cf" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#c2a878" stop-opacity="0.4"/>
|
||||
<stop offset="100%" stop-color="#c2a878" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path id="cArea" d="" fill="url(#cf)"/>
|
||||
<path id="cLine" d="" fill="none" stroke="#e7cf9b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<div class="pct">↓ <b id="cVal">40%</b> latency</div>
|
||||
</div>
|
||||
<div class="ht-body" id="termBody">
|
||||
<div class="ht-line"><span class="cmt">// six years in the engine room</span></div>
|
||||
<div class="ht-line"><span class="prompt">$</span> cargo build --release</div>
|
||||
<div class="ht-line"><span class="ok">✓</span> <span class="k">Finished</span> in <span class="v">0</span>.<span class="v">42s</span> <span class="cmt">// zero-cost abstractions</span></div>
|
||||
<div class="ht-line"><span class="prompt">$</span> ./serve --load <span class="v">high</span></div>
|
||||
<div class="ht-line last"><span class="ok">✓</span> latency <span class="ok">−40%</span> · holding steady<span class="term-cursor2"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- MARQUEE -->
|
||||
<div class="marquee reveal" aria-hidden="true">
|
||||
<div class="marquee-track" id="marquee">
|
||||
<span>Rust</span><span>C++</span><span>TypeScript</span><span>React</span><span>Next.js</span><span>Node.js</span><span>Python</span><span>Docker</span><span>Redis</span><span>WebSockets</span><span>System Design</span>
|
||||
<span>Rust</span><span>C++</span><span>TypeScript</span><span>React</span><span>Next.js</span><span>Node.js</span><span>Python</span><span>Docker</span><span>Redis</span><span>WebSockets</span><span>System Design</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ABOUT -->
|
||||
<section class="sec" id="about" aria-labelledby="about-title">
|
||||
<div class="sec-head reveal">
|
||||
@@ -407,22 +381,28 @@
|
||||
<h2 class="sec-title" id="about-title">The Engineer</h2>
|
||||
<span class="sec-rule" aria-hidden="true"></span>
|
||||
</div>
|
||||
|
||||
<div class="about-grid">
|
||||
<div class="reveal">
|
||||
<p class="about-lead">
|
||||
Senior Full Stack Engineer with a focus on <span class="hl">system performance</span>. I design infrastructure that withstands pressure, write code that respects the machine, and ship systems built to outlast their first traffic spike.
|
||||
I design <span class="hl">infrastructure that withstands pressure</span> — write code that respects the machine, and ship systems built to outlast their first traffic spike.
|
||||
</p>
|
||||
<p class="about-body">
|
||||
Six years in the engine room. Scalable web applications, optimized core infrastructure, and the low-level work most teams avoid. When the load hits, the system holds — because it was designed to.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="variants reveal d2">
|
||||
<div class="variant-note">Voice — three cuts</div>
|
||||
<div class="variant"><span class="tag">Short</span><p>Senior Full Stack Engineer. I build systems that survive scale. Rust & C++ where speed is not optional.</p></div>
|
||||
<div class="variant"><span class="tag">Atmospheric</span><p>Six years in the engine room. Scalable web applications and the core infrastructure that holds them up. When the load hits, the system holds — because it was built to.</p></div>
|
||||
<div class="variant"><span class="tag">Premium</span><p>Senior Full Stack Engineer focused on system performance. I design infrastructure that withstands pressure, write code that respects the machine, and ship systems built to outlast their first traffic spike.</p></div>
|
||||
<div class="do-trio reveal d2">
|
||||
<div class="do-card reveal">
|
||||
<div class="do-ico" aria-hidden="true">FX</div>
|
||||
<div><h3>Frontend that earns its pixels</h3><p>Type-safe, accessible, responsive interfaces in React, Next.js and TypeScript — UX built in, not bolted on.</p></div>
|
||||
</div>
|
||||
<div class="do-card reveal d1">
|
||||
<div class="do-ico" aria-hidden="true">IN</div>
|
||||
<div><h3>Backend & infrastructure</h3><p>Scalable architectures in Node and Python — Dockerized, cloud-native, built to grow without breaking under their own weight.</p></div>
|
||||
</div>
|
||||
<div class="do-card reveal d2">
|
||||
<div class="do-ico" aria-hidden="true">C</div>
|
||||
<div><h3>Systems on the critical path</h3><p>When the runtime isn't fast enough: memory-safe, high-performance Rust & C++ modules — the work most teams avoid.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -433,69 +413,37 @@
|
||||
<span class="sec-id">02 / SIGNAL</span>
|
||||
<h2 class="sec-title" id="stats-title">By the Numbers</h2>
|
||||
<span class="sec-rule" aria-hidden="true"></span>
|
||||
<p class="sec-sub">Representative outcomes from recent production work — figures anonymized, results real.</p>
|
||||
</div>
|
||||
<div class="stats reveal">
|
||||
<div class="stat"><div class="stat-num">6<span class="plus">+</span></div><div class="stat-label">Years in the Field</div><div class="stat-desc">In the engine room.</div></div>
|
||||
<div class="stat"><div class="stat-num">20<span class="plus">+</span></div><div class="stat-label">Production Deploys</div><div class="stat-desc">Shipped under load.</div></div>
|
||||
<div class="stat"><div class="stat-num">40<span class="plus">%</span></div><div class="stat-label">Latency Cut (avg)</div><div class="stat-desc">Where speed is not optional.</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- EXPERIENCE -->
|
||||
<section class="sec" id="experience" aria-labelledby="exp-title">
|
||||
<div class="sec-head reveal">
|
||||
<span class="sec-id">03 / RECORD</span>
|
||||
<h2 class="sec-title" id="exp-title">Professional Experience</h2>
|
||||
<span class="sec-rule" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="timeline">
|
||||
<div class="job reveal">
|
||||
<div class="job-period">2025 — Present</div>
|
||||
<div class="job-body">
|
||||
<h3>Senior Full Stack Engineer</h3>
|
||||
<div class="job-co">TechFlow Systems <span>// Full-stack, infra, perf</span></div>
|
||||
<p class="job-desc">Leading the backend <b>migration to microservices</b>. Built a <b>high-throughput event processing pipeline</b> in Python and Rust — <b>latency cut by 40%</b>. Own the React architecture behind the main dashboard, from data layer to render.</p>
|
||||
<div class="job-tags">
|
||||
<span class="tag-chip hi">Microservices Migration</span><span class="tag-chip hi">Event Pipeline</span><span class="tag-chip">Python</span><span class="tag-chip">Rust</span><span class="tag-chip">React</span><span class="tag-chip">−40% Latency</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="job reveal">
|
||||
<div class="job-period">2020 — 2023</div>
|
||||
<div class="job-body">
|
||||
<h3>Software Engineer</h3>
|
||||
<div class="job-co">Creative Solutions Ltd. <span>// Full-stack, native modules</span></div>
|
||||
<p class="job-desc">Full-stack web applications in <b>Node.js and TypeScript</b>. When the runtime slowed down, I went lower — <b>native C++ modules</b> for image processing pushed workflows <b>3× faster</b>. Where JavaScript couldn't keep up, the machine did.</p>
|
||||
<div class="job-tags">
|
||||
<span class="tag-chip">Node.js</span><span class="tag-chip">TypeScript</span><span class="tag-chip hi">Native C++ Modules</span><span class="tag-chip">Image Processing</span><span class="tag-chip">3× Faster</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat"><div class="stat-num">6<span class="plus">+</span></div><div class="stat-label">Years in the Field</div><div class="stat-desc">Engine room to architecture.</div></div>
|
||||
<div class="stat"><div class="stat-num">40<span class="plus">%</span></div><div class="stat-label">Avg Latency Cut</div><div class="stat-desc">On the event pipeline.</div></div>
|
||||
<div class="stat"><div class="stat-num">3<span class="plus">×</span></div><div class="stat-label">Throughput Win</div><div class="stat-desc">Native modules vs. JS.</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ARSENAL -->
|
||||
<section class="sec" id="arsenal" aria-labelledby="arsenal-title">
|
||||
<div class="sec-head reveal">
|
||||
<span class="sec-id">04 / ARSENAL</span>
|
||||
<span class="sec-id">03 / ARSENAL</span>
|
||||
<h2 class="sec-title" id="arsenal-title">Technical Arsenal</h2>
|
||||
<span class="sec-rule" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="arsenal">
|
||||
<div class="arm-card reveal">
|
||||
<div class="arm-num">A / FRONT</div>
|
||||
<div class="arm-ico"><span class="n">A</span>/ FRONT</div>
|
||||
<div class="arm-title">Modern Frontend</div>
|
||||
<div class="arm-desc">Type-safe, responsive interfaces. UX and accessibility built in — not bolted on. Every pixel earns its place.</div>
|
||||
<div class="arm-stack"><span>React</span><span>Next.js</span><span>TypeScript</span></div>
|
||||
</div>
|
||||
<div class="arm-card reveal d1">
|
||||
<div class="arm-num">B / INFRA</div>
|
||||
<div class="arm-ico"><span class="n">B</span>/ INFRA</div>
|
||||
<div class="arm-title">Backend & Infra</div>
|
||||
<div class="arm-desc">Scalable architectures in Node and Python. Dockerized, cloud-native — built to grow without breaking under its own weight.</div>
|
||||
<div class="arm-stack"><span>Node.js</span><span>Python</span><span>Docker</span><span>Redis</span><span>WebSockets</span></div>
|
||||
</div>
|
||||
<div class="arm-card reveal d2">
|
||||
<div class="arm-num">C / CORE</div>
|
||||
<div class="arm-ico"><span class="n">C</span>/ CORE</div>
|
||||
<div class="arm-title">Systems & Low Level</div>
|
||||
<div class="arm-desc">When the runtime isn't fast enough. Memory-safe, high-performance modules for the critical path. The work most teams avoid.</div>
|
||||
<div class="arm-stack"><span>Rust</span><span>C++</span><span>System Design</span></div>
|
||||
@@ -506,7 +454,7 @@
|
||||
<!-- WORK -->
|
||||
<section class="sec" id="work" aria-labelledby="work-title">
|
||||
<div class="sec-head reveal">
|
||||
<span class="sec-id">05 / SELECTED WORK</span>
|
||||
<span class="sec-id">04 / SELECTED WORK</span>
|
||||
<h2 class="sec-title" id="work-title">Case Studies</h2>
|
||||
<span class="sec-rule" aria-hidden="true"></span>
|
||||
</div>
|
||||
@@ -515,6 +463,7 @@
|
||||
<div class="work-idx">01</div>
|
||||
<div class="work-main">
|
||||
<h3>Fintech Analytics Engine</h3>
|
||||
<div class="work-metric">— real-time · zero-cost abstractions</div>
|
||||
<p>Real-time financial dashboard. The backend aggregates streams from multiple sources through a <b>custom Rust service</b> — zero-cost abstractions, real performance. Built to render data the moment it arrives, not a cycle later.</p>
|
||||
</div>
|
||||
<div class="work-side"><div class="lbl">Stack</div><div class="work-stack"><span>Next.js</span><span>Rust</span><span>WebSockets</span></div></div>
|
||||
@@ -523,6 +472,7 @@
|
||||
<div class="work-idx">02</div>
|
||||
<div class="work-main">
|
||||
<h3>AI Data Pipeline</h3>
|
||||
<div class="work-metric">— terabytes · Python + C++ bindings</div>
|
||||
<p>Automated ETL across <b>terabytes of data</b>. Python for flexibility, <b>C++ bindings</b> for the heavy lifting. The pipeline doesn't choke when the data grows — it was designed for the next order of magnitude.</p>
|
||||
</div>
|
||||
<div class="work-side"><div class="lbl">Stack</div><div class="work-stack"><span>Python</span><span>C++</span><span>Docker</span></div></div>
|
||||
@@ -531,6 +481,7 @@
|
||||
<div class="work-idx">03</div>
|
||||
<div class="work-main">
|
||||
<h3>Distributed Task Queue</h3>
|
||||
<div class="work-metric">— fault-tolerant · low-memory</div>
|
||||
<p>Fault-tolerant job scheduler. Celery-inspired, rebuilt for <b>low-memory environments</b>. Jobs survive crashes. The queue doesn't bleed — engineered to hold the line when the system is under pressure.</p>
|
||||
</div>
|
||||
<div class="work-side"><div class="lbl">Stack</div><div class="work-stack"><span>Node.js</span><span>Redis</span><span>System Design</span></div></div>
|
||||
@@ -538,11 +489,38 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- EXPERIENCE -->
|
||||
<section class="sec" id="experience" aria-labelledby="exp-title">
|
||||
<div class="sec-head reveal">
|
||||
<span class="sec-id">05 / RECORD</span>
|
||||
<h2 class="sec-title" id="exp-title">Professional Experience</h2>
|
||||
<span class="sec-rule" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="timeline">
|
||||
<div class="job reveal">
|
||||
<div class="job-period">2024 — Present</div>
|
||||
<div class="job-body">
|
||||
<h3>Senior Full Stack Engineer</h3>
|
||||
<div class="job-co">TechFlow Systems <span>// full-stack · infra · perf</span></div>
|
||||
<p class="job-desc">Leading the backend <b>migration to microservices</b>. Built a <b>high-throughput event processing pipeline</b> in Python and Rust — <b>latency cut by 40%</b>. Own the React architecture behind the main dashboard, from data layer to render.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="job reveal">
|
||||
<div class="job-period">2021 — 2024</div>
|
||||
<div class="job-body">
|
||||
<h3>Software Engineer</h3>
|
||||
<div class="job-co">Creative Solutions Ltd. <span>// full-stack · native modules</span></div>
|
||||
<p class="job-desc">Full-stack web applications in <b>Node.js and TypeScript</b>. When the runtime slowed, I went lower — <b>native C++ modules</b> for image processing pushed workflows <b>3× faster</b>. Where JavaScript couldn't keep up, the machine did.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FINAL CTA -->
|
||||
<section class="cta-sec" id="contact" aria-labelledby="cta-title">
|
||||
<div class="cta-eyebrow reveal">06 / TRANSMISSION OPEN</div>
|
||||
<h2 class="cta-title reveal d1" id="cta-title">Ready for the <span class="accent">pressure</span>?</h2>
|
||||
<p class="cta-sub reveal d2">Let's talk about systems that scale without noise — performance where it matters, infrastructure that holds the line.</p>
|
||||
<h2 class="cta-title reveal d1" id="cta-title">Let's build something <span class="accent">that won't break</span>.</h2>
|
||||
<p class="cta-sub reveal d2">Systems that scale without noise — performance where it matters, infrastructure that holds the line.</p>
|
||||
<div class="cta-row reveal d3">
|
||||
<span class="email-copy">
|
||||
<span class="copy-tip" id="copyTip" role="status" aria-live="polite">Copied to clipboard</span>
|
||||
@@ -558,8 +536,8 @@
|
||||
<div class="wrap foot">
|
||||
<div class="foot-left">© 2026 <b>xdfnx</b> // Built to hold.</div>
|
||||
<div class="foot-right">
|
||||
<a href="#contact">contact@xdfnx.cfd</a>
|
||||
<a href="#about">Top ↑</a>
|
||||
<a href="#contact" aria-label="Email">contact@xdfnx.cfd</a>
|
||||
<a href="#about" aria-label="Back to top">Top ↑</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -568,9 +546,6 @@
|
||||
(function(){
|
||||
var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
// duplicate marquee track for seamless scroll (already duplicated in markup; keep robust)
|
||||
var mq = document.getElementById('marquee');
|
||||
|
||||
// reveal
|
||||
if ('IntersectionObserver' in window) {
|
||||
var io = new IntersectionObserver(function(es){
|
||||
@@ -581,71 +556,106 @@
|
||||
document.querySelectorAll('.reveal').forEach(function(el){ el.classList.add('in'); });
|
||||
}
|
||||
|
||||
// monitor: animate bars when visible
|
||||
var monRows = document.querySelectorAll('.mon-row');
|
||||
if ('IntersectionObserver' in window) {
|
||||
var mo = new IntersectionObserver(function(es){
|
||||
es.forEach(function(e){
|
||||
if(e.isIntersecting){
|
||||
monRows.forEach(function(r,i){
|
||||
var f = parseFloat(r.getAttribute('data-fill'));
|
||||
var fill = r.querySelector('.mon-fill');
|
||||
var baseScale = reduce ? f : 0;
|
||||
fill.style.transform = 'scaleX(' + baseScale + ')';
|
||||
setTimeout(function(){
|
||||
var target = reduce ? f : f;
|
||||
fill.style.transition = 'transform 1s cubic-bezier(.16,1,.3,1)';
|
||||
fill.style.transform = 'scaleX(' + target + ')';
|
||||
}, 120 + i*140);
|
||||
});
|
||||
mo.disconnect();
|
||||
}
|
||||
});
|
||||
},{threshold:.3});
|
||||
var mon = document.querySelector('.monitor'); if(mon) mo.observe(mon);
|
||||
} else {
|
||||
monRows.forEach(function(r){ var f=parseFloat(r.getAttribute('data-fill')); r.querySelector('.mon-fill').style.transform='scaleX('+f+')'; });
|
||||
}
|
||||
|
||||
// monitor: animated chart path (sine-ish wave that "holds the line")
|
||||
var cLine = document.getElementById('cLine'), cArea = document.getElementById('cArea');
|
||||
var W=300, H=120, N=42, phase=0, raf=null;
|
||||
function buildPath(p){
|
||||
var pts=[]; var mid=H/2;
|
||||
for(var i=0;i<=N;i++){
|
||||
var x=(i/N)*W;
|
||||
var y= mid + Math.sin((i/N)*Math.PI*3 + p)*14*((i/N)) + Math.sin((i/N)*Math.PI*7 + p*1.3)*5;
|
||||
pts.push(x.toFixed(1)+','+y.toFixed(1));
|
||||
}
|
||||
var d='M'+pts[0]+' L'+pts.slice(1).join(' L');
|
||||
var area=d+' L'+W+','+H+' L0,'+H+' Z';
|
||||
return {l:d,a:area};
|
||||
}
|
||||
function draw(){
|
||||
var o = buildPath(phase);
|
||||
cLine.setAttribute('d', o.l); cArea.setAttribute('d', o.a);
|
||||
}
|
||||
if (!reduce) {
|
||||
if ('IntersectionObserver' in window) {
|
||||
var co=new IntersectionObserver(function(es){ es.forEach(function(e){
|
||||
if(e.isIntersecting){ if(!raf) loop(); }
|
||||
else { if(raf){ cancelAnimationFrame(raf); raf=null; } }
|
||||
}); },{threshold:.2});
|
||||
var ch=document.querySelector('.mon-chart'); if(ch) co.observe(ch);
|
||||
}
|
||||
function loop(){ phase+=0.06; draw(); raf=requestAnimationFrame(loop); }
|
||||
} else { draw(); }
|
||||
|
||||
// glow parallax (rAF-throttled)
|
||||
if (!reduce) {
|
||||
var glows = document.querySelectorAll('.glow'), ticking=false;
|
||||
window.addEventListener('scroll', function(){
|
||||
var glows=document.querySelectorAll('.glow'), ticking=false;
|
||||
window.addEventListener('scroll',function(){
|
||||
if(ticking) return; ticking=true;
|
||||
requestAnimationFrame(function(){
|
||||
var y = window.scrollY;
|
||||
glows.forEach(function(g,i){ g.style.transform = 'translateY(' + (y*(i?-.06:.04)) + 'px)' + (i?' translateX(0)':'translateX(-30%)'); });
|
||||
var y=window.scrollY;
|
||||
glows.forEach(function(g,i){ g.style.transform='translateY('+(y*(i?-.06:.04))+'px)'+(i?' translateX(0)':'translateX(-25%)'); });
|
||||
ticking=false;
|
||||
});
|
||||
},{passive:true});
|
||||
}
|
||||
|
||||
// hide top bar on scroll-down
|
||||
var bar = document.getElementById('topbar'), lastY = 0;
|
||||
window.addEventListener('scroll', function(){
|
||||
var y = window.scrollY;
|
||||
if (y > 220 && y > lastY) bar.classList.add('hidden'); else bar.classList.remove('hidden');
|
||||
lastY = y;
|
||||
var bar=document.getElementById('topbar'), lastY=0;
|
||||
window.addEventListener('scroll',function(){
|
||||
var y=window.scrollY;
|
||||
if(y>220 && y>lastY) bar.classList.add('hidden'); else bar.classList.remove('hidden');
|
||||
lastY=y;
|
||||
},{passive:true});
|
||||
|
||||
// mobile menu
|
||||
var btn = document.getElementById('menuBtn'), nav = document.getElementById('nav');
|
||||
var btn=document.getElementById('menuBtn'), nav=document.getElementById('nav');
|
||||
function closeMenu(){ nav.classList.remove('open'); btn.setAttribute('aria-expanded','false'); btn.textContent='Menu'; }
|
||||
btn.addEventListener('click', function(){
|
||||
var open = nav.classList.toggle('open');
|
||||
btn.setAttribute('aria-expanded', open?'true':'false');
|
||||
btn.textContent = open?'Close':'Menu';
|
||||
});
|
||||
btn.addEventListener('click',function(){ var open=nav.classList.toggle('open'); btn.setAttribute('aria-expanded',open?'true':'false'); btn.textContent=open?'Close':'Menu'; });
|
||||
nav.querySelectorAll('a').forEach(function(a){ a.addEventListener('click', closeMenu); });
|
||||
|
||||
// scroll-spy
|
||||
var links = Array.prototype.slice.call(nav.querySelectorAll('a')), map={};
|
||||
var links=Array.prototype.slice.call(nav.querySelectorAll('a')), map={};
|
||||
links.forEach(function(a){ var id=a.getAttribute('href').slice(1); var sec=document.getElementById(id); if(sec) map[id]=a; });
|
||||
if ('IntersectionObserver' in window) {
|
||||
var spy = new IntersectionObserver(function(es){
|
||||
es.forEach(function(e){ if(e.isIntersecting){
|
||||
var spy=new IntersectionObserver(function(es){ es.forEach(function(e){ if(e.isIntersecting){
|
||||
links.forEach(function(l){ l.classList.remove('active'); });
|
||||
var l = map[e.target.id]; if(l) l.classList.add('active');
|
||||
}});
|
||||
},{rootMargin:'-45% 0px -50% 0px'});
|
||||
var l=map[e.target.id]; if(l) l.classList.add('active');
|
||||
}}); },{rootMargin:'-45% 0px -50% 0px'});
|
||||
Object.keys(map).forEach(function(id){ var s=document.getElementById(id); if(s) spy.observe(s); });
|
||||
}
|
||||
|
||||
// copy email
|
||||
var emailBtn = document.getElementById('emailBtn'), tip = document.getElementById('copyTip'), email = emailBtn.getAttribute('data-email');
|
||||
var emailBtn=document.getElementById('emailBtn'), tip=document.getElementById('copyTip'), email=emailBtn.getAttribute('data-email');
|
||||
function flash(){ tip.classList.add('show'); setTimeout(function(){ tip.classList.remove('show'); },1600); }
|
||||
emailBtn.addEventListener('click', function(e){
|
||||
if (e.shiftKey||e.ctrlKey||e.metaKey){ e.preventDefault(); if(navigator.clipboard) navigator.clipboard.writeText(email).then(flash).catch(function(){}); else flash(); return; }
|
||||
if (matchMedia('(pointer:coarse)').matches){ e.preventDefault(); if(navigator.clipboard) navigator.clipboard.writeText(email).then(flash).catch(function(){}); else window.location.href='mailto:'+email; }
|
||||
emailBtn.addEventListener('click',function(e){
|
||||
if(e.shiftKey||e.ctrlKey||e.metaKey){ e.preventDefault(); if(navigator.clipboard) navigator.clipboard.writeText(email).then(flash).catch(function(){}); else flash(); return; }
|
||||
if(matchMedia('(pointer:coarse)').matches){ e.preventDefault(); if(navigator.clipboard) navigator.clipboard.writeText(email).then(flash).catch(function(){}); else window.location.href='mailto:'+email; }
|
||||
});
|
||||
|
||||
// typing animation on hero terminal (lines appear in sequence)
|
||||
if (!reduce) {
|
||||
var lines = document.querySelectorAll('#termBody .ht-line');
|
||||
lines.forEach(function(l,i){ l.style.opacity=0; l.style.transition='opacity .35s var(--ease),transform .35s var(--ease)'; l.style.transform='translateY(4px)'; });
|
||||
var vis = new IntersectionObserver(function(es){
|
||||
es.forEach(function(e){ if(e.isIntersecting){
|
||||
lines.forEach(function(l,i){ setTimeout(function(){ l.style.opacity=1; l.style.transform='none'; }, 250 + i*420); });
|
||||
vis.disconnect();
|
||||
}});
|
||||
},{threshold:.3});
|
||||
var term = document.getElementById('termBody');
|
||||
if(term) vis.observe(term);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user