Apply QA: brand-blue buttons, no DNA, theme-aware fireworks and footer

- Buttons return to the brand accent colors (primary fill, accent outline)
- Current Ventures shows only the copy beside the portfolio dashboard; the
  DNA helix and its library are removed
- The journey fireworks stage, pins and particles switch to a light palette
  in light mode
- The footer follows the theme instead of staying black

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alejandro Veras
2026-10-01 12:56:42 -04:00
parent d0357f1c52
commit 90be0ec4c7
7 changed files with 53 additions and 3949 deletions
+8 -17
View File
@@ -37,7 +37,7 @@ export default {
title: 'Dylan Mazzei | Founder, Operator &amp; Entrepreneur', title: 'Dylan Mazzei | Founder, Operator &amp; Entrepreneur',
description: 'Meet Dylan Mazzei, a founder and operator leading ventures across AI, software, spirits, education, cybersecurity, e-commerce, and more.', description: 'Meet Dylan Mazzei, a founder and operator leading ventures across AI, software, spirits, education, cybersecurity, e-commerce, and more.',
head: '<link rel="stylesheet" href="/assets/home.css">', head: '<link rel="stylesheet" href="/assets/home.css">',
scripts: '<script src="/assets/o2/three.min.js" defer></script>\n<script src="/assets/o2/dna-hero.min.js" defer></script>\n<script src="/assets/home.js" defer></script>', scripts: '<script src="/assets/o2/three.min.js" defer></script>\n<script src="/assets/home.js" defer></script>',
body: ` body: `
<div class="o2"> <div class="o2">
@@ -67,22 +67,14 @@ export default {
</section> </section>
<section id="building" aria-labelledby="building-title"> <section id="building" aria-labelledby="building-title">
<div class="wrap"> <div class="wrap bgrid">
<div class="bhead reveal"> <div class="bhead reveal">
<div class="stack-sm">${eyebrow('CURRENT VENTURES')}<h2 id="building-title" class="h-display">The Companies I’m Leading Today</h2></div> ${eyebrow('CURRENT VENTURES')}
<div class="stack-sm"> <h2 id="building-title" class="h-display">The Companies I’m Leading Today</h2>
<p class="lead">I like being close to the decisions that shape a company, especially when there is something new to figure out.</p> <p class="lead">I like being close to the decisions that shape a company, especially when there is something new to figure out.</p>
<div>${btn('EXPLORE MY VENTURES', '/portfolio/')}</div> <div>${btn('EXPLORE MY VENTURES', '/portfolio/')}</div>
</div>
</div> </div>
<div class="bgrid"> <div class="cluster-fit reveal">
<div class="bstack" id="bstack">
${'<span class="r" aria-hidden="true">Still building</span>'.repeat(6)}
<div class="bglow" aria-hidden="true"></div>
<dna-hero id="dna" class="dna3d" transparent interactive duration="20" aria-label="3D chrome DNA helix. Drag to rotate."></dna-hero>
<img class="helix" id="dnaFallback" hidden alt="" src="/assets/o2/dna-fallback.webp">
</div>
<div class="cluster-fit reveal">
<div class="cluster" aria-hidden="true"> <div class="cluster" aria-hidden="true">
<div class="panel dash"> <div class="panel dash">
<div class="panel-bar"><span class="lights"><i></i><i></i><i></i></span><span>Portfolio</span><span class="panel-url">dylanmazzei.com/portfolio</span></div> <div class="panel-bar"><span class="lights"><i></i><i></i><i></i></span><span>Portfolio</span><span class="panel-url">dylanmazzei.com/portfolio</span></div>
@@ -113,7 +105,6 @@ export default {
<pre class="code-pre"><span class="ln"><span class="p">{</span></span><span class="ln"> <span class="k">"role"</span><span class="p">:</span> <span class="s">"Founder &amp; Operator"</span><span class="p">,</span></span><span class="ln"> <span class="k">"exits"</span><span class="p">:</span> <span class="n">4</span><span class="p">,</span></span><span class="ln"> <span class="k">"industries"</span><span class="p">:</span> <span class="n">6</span><span class="p">,</span></span><span class="ln"> <span class="k">"yearsOperating"</span><span class="p">:</span> <span class="s">"8+"</span><span class="p">,</span></span><span class="ln"> <span class="k">"whereIWork"</span><span class="p">: [</span></span><span class="ln"> <span class="s">"Texas"</span><span class="p">,</span> <span class="s">"Florida"</span><span class="p">,</span></span><span class="ln"> <span class="s">"New York"</span><span class="p">,</span> <span class="s">"Dubai"</span></span><span class="ln"> <span class="p">],</span></span><span class="ln"> <span class="k">"finishedBuilding"</span><span class="p">:</span> <span class="n">false</span><span class="cursor"></span></span><span class="ln"><span class="p">}</span></span></pre> <pre class="code-pre"><span class="ln"><span class="p">{</span></span><span class="ln"> <span class="k">"role"</span><span class="p">:</span> <span class="s">"Founder &amp; Operator"</span><span class="p">,</span></span><span class="ln"> <span class="k">"exits"</span><span class="p">:</span> <span class="n">4</span><span class="p">,</span></span><span class="ln"> <span class="k">"industries"</span><span class="p">:</span> <span class="n">6</span><span class="p">,</span></span><span class="ln"> <span class="k">"yearsOperating"</span><span class="p">:</span> <span class="s">"8+"</span><span class="p">,</span></span><span class="ln"> <span class="k">"whereIWork"</span><span class="p">: [</span></span><span class="ln"> <span class="s">"Texas"</span><span class="p">,</span> <span class="s">"Florida"</span><span class="p">,</span></span><span class="ln"> <span class="s">"New York"</span><span class="p">,</span> <span class="s">"Dubai"</span></span><span class="ln"> <span class="p">],</span></span><span class="ln"> <span class="k">"finishedBuilding"</span><span class="p">:</span> <span class="n">false</span><span class="cursor"></span></span><span class="ln"><span class="p">}</span></span></pre>
</div> </div>
</div> </div>
</div>
</div> </div>
</div> </div>
</section> </section>
@@ -164,7 +155,7 @@ export default {
</div> </div>
<canvas id="fw" aria-hidden="true"></canvas> <canvas id="fw" aria-hidden="true"></canvas>
<p class="jfinal" id="jfinal">Others are growing. And I’m nowhere near finished building.</p> <p class="jfinal" id="jfinal">Others are growing. And I’m nowhere near finished building.</p>
<button class="btn btn-ghost-light btn-sm jreplay" id="jreplay" type="button">Replay</button> <button class="btn btn-ghost btn-sm jreplay" id="jreplay" type="button">Replay</button>
</div> </div>
<div class="jbody"> <div class="jbody">
<ul class="jlist"> <ul class="jlist">
+14 -22
View File
@@ -86,18 +86,10 @@
.w-top { position: absolute; left: max(var(--gutter), calc((100vw - var(--page-max)) / 2 + var(--gutter))); top: 2.5rem; z-index: 3; } .w-top { position: absolute; left: max(var(--gutter), calc((100vw - var(--page-max)) / 2 + var(--gutter))); top: 2.5rem; z-index: 3; }
@media (max-width: 700px) { .w-side { left: var(--gutter); right: var(--gutter); max-width: none; } } @media (max-width: 700px) { .w-side { left: var(--gutter); right: var(--gutter); max-width: none; } }
/* ---------- building: copy, DNA and the portfolio dashboard side by side ---------- */ /* ---------- building: copy beside the portfolio dashboard ---------- */
.bhead { display: grid; grid-template-columns: 1.1fr 1fr; gap: 3rem; align-items: end; margin-bottom: 3rem; } .bgrid { display: grid; grid-template-columns: 0.75fr 1.25fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.bhead > * { min-width: 0; }
.bgrid { display: grid; grid-template-columns: 0.8fr 1.2fr; gap: 2rem; align-items: center; }
.bgrid > * { min-width: 0; } .bgrid > * { min-width: 0; }
.bstack { position: relative; overflow: visible; height: min(78vh, 680px); display: flex; flex-direction: column; justify-content: center; } .bhead { display: flex; flex-direction: column; gap: 1.4rem; align-items: flex-start; }
.bstack .r { display: block; white-space: nowrap; font-weight: 500; font-size: clamp(2.6rem, 5.6vw, 6.2rem); line-height: .98; letter-spacing: -0.055em;
background: linear-gradient(180deg, var(--grad-a), #5fb4ff 70%, #1a7fff); -webkit-background-clip: text; background-clip: text; color: transparent; will-change: transform; }
.dna3d { position: absolute; left: 50%; top: 50%; height: 104%; width: auto; aspect-ratio: 2 / 3; transform: translate(-50%, -50%); z-index: 2; }
.helix { position: absolute; left: 50%; top: 50%; height: 104%; width: auto; pointer-events: none; transform: translate(-50%, -50%); filter: drop-shadow(0 0 40px rgba(26, 127, 255, .5)); }
.helix[hidden], .dna3d[hidden] { display: none; }
.bglow { position: absolute; left: 50%; top: 50%; width: 80%; height: 90%; transform: translate(-50%, -50%); background: radial-gradient(closest-side, rgba(26, 127, 255, .28), transparent); pointer-events: none; }
.cluster-fit { position: relative; width: 100%; } .cluster-fit { position: relative; width: 100%; }
.cluster-fit .cluster { margin: 0; width: 760px; height: 740px; max-width: none; transform-origin: 0 0; transform: scale(var(--s, 1)); } .cluster-fit .cluster { margin: 0; width: 760px; height: 740px; max-width: none; transform-origin: 0 0; transform: scale(var(--s, 1)); }
.cluster-fit .dash { left: 176px; top: 0; width: 540px; } .cluster-fit .dash { left: 176px; top: 0; width: 540px; }
@@ -106,9 +98,7 @@
.cluster-fit .dash-cols { grid-template-columns: 1.25fr 1fr; } .cluster-fit .dash-cols { grid-template-columns: 1.25fr 1fr; }
.cluster-fit .row { font-size: 12.5px; } .cluster-fit .row { font-size: 12.5px; }
@media (max-width: 1100px) { @media (max-width: 1100px) {
.bhead { grid-template-columns: 1fr; gap: 1.5rem; }
.bgrid { grid-template-columns: 1fr; } .bgrid { grid-template-columns: 1fr; }
.bstack { height: 62vh; }
.cluster-fit .cluster { width: auto; height: auto; transform: none; } .cluster-fit .cluster { width: auto; height: auto; transform: none; }
.cluster-fit .panel { left: auto; right: auto; top: auto; width: auto; } .cluster-fit .panel { left: auto; right: auto; top: auto; width: auto; }
.cluster-fit .profile { max-width: 340px; } .cluster-fit .profile { max-width: 340px; }
@@ -134,7 +124,6 @@
.vinfo p { color: #b3c0da; font-size: 1.08rem; max-width: 34ch; } .vinfo p { color: #b3c0da; font-size: 1.08rem; max-width: 34ch; }
.vinfo .vt { transition: opacity .3s, transform .3s; } .vinfo .vt { transition: opacity .3s, transform .3s; }
.vinfo .vt.out { opacity: 0; transform: translateY(10px); } .vinfo .vt.out { opacity: 0; transform: translateY(10px); }
.vinfo .btn-primary { background: #fff; color: #06101f; }
#vcanvas { position: relative; z-index: 1; width: 100%; height: 100%; min-height: 340px; cursor: grab; } #vcanvas { position: relative; z-index: 1; width: 100%; height: 100%; min-height: 340px; cursor: grab; }
.varrows { position: absolute; z-index: 3; right: 1.2rem; bottom: 1.2rem; display: flex; gap: .5rem; } .varrows { position: absolute; z-index: 3; right: 1.2rem; bottom: 1.2rem; display: flex; gap: .5rem; }
.varrows button { width: 44px; height: 44px; border: 1px solid rgba(255, 255, 255, .09); border-radius: 10px; background: rgba(10, 14, 26, .7); color: #fff; backdrop-filter: blur(8px); display: grid; place-items: center; cursor: pointer; transition: border-color .2s; } .varrows button { width: 44px; height: 44px; border: 1px solid rgba(255, 255, 255, .09); border-radius: 10px; background: rgba(10, 14, 26, .7); color: #fff; backdrop-filter: blur(8px); display: grid; place-items: center; cursor: pointer; transition: border-color .2s; }
@@ -147,8 +136,11 @@
.jgrid > * { min-width: 0; } .jgrid > * { min-width: 0; }
.jhead { grid-area: head; display: flex; flex-direction: column; gap: 1.1rem; align-items: flex-start; } .jhead { grid-area: head; display: flex; flex-direction: column; gap: 1.1rem; align-items: flex-start; }
.jbody { grid-area: body; } .jbody { grid-area: body; }
.jstage { grid-area: stage; position: relative; height: clamp(460px, 78vh, 680px); align-self: stretch; overflow: hidden; border-radius: 18px; border: 1px solid rgba(255, 255, 255, .09); color: #f3f7ff; .jstage { grid-area: stage; position: relative; height: clamp(460px, 78vh, 680px); align-self: stretch; overflow: hidden; border-radius: 18px; border: 1px solid var(--bd); color: var(--ink);
--floor-line: rgba(159, 230, 255, .26); --pin: #1fb7ff; --pin-label: #55627f; --pin-done: #fff; --final: #d6e8ff;
background: radial-gradient(70% 55% at 50% 100%, rgba(26, 127, 255, .18), transparent 70%), #060a14; } background: radial-gradient(70% 55% at 50% 100%, rgba(26, 127, 255, .18), transparent 70%), #060a14; }
:root[data-theme="light"] .jstage { --floor-line: rgba(26, 111, 224, .28); --pin: #1a7fff; --pin-label: #8896b3; --pin-done: #0b1220; --final: #13306b;
background: radial-gradient(70% 55% at 50% 100%, rgba(26, 127, 255, .14), transparent 70%), linear-gradient(180deg, #ffffff, #eef4fd); }
.jlist { display: grid; gap: .7rem; } .jlist { display: grid; gap: .7rem; }
.jx { display: flex; gap: 1rem; align-items: flex-start; padding: 1rem 1.2rem; border: 1px solid var(--bd); border-radius: 14px; background: var(--glass); opacity: .4; transition: opacity .6s, border-color .6s, box-shadow .6s, background .6s; } .jx { display: flex; gap: 1rem; align-items: flex-start; padding: 1rem 1.2rem; border: 1px solid var(--bd); border-radius: 14px; background: var(--glass); opacity: .4; transition: opacity .6s, border-color .6s, box-shadow .6s, background .6s; }
.jx .ji { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; border: 1px solid var(--bd); color: var(--o2-faint); transition: all .6s; } .jx .ji { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; border: 1px solid var(--bd); color: var(--o2-faint); transition: all .6s; }
@@ -158,18 +150,18 @@
.jx.lit { opacity: 1; border-color: rgba(31, 183, 255, .5); background: linear-gradient(150deg, rgba(26, 127, 255, .14), var(--glass)); box-shadow: 0 0 36px rgba(26, 127, 255, .14); } .jx.lit { opacity: 1; border-color: rgba(31, 183, 255, .5); background: linear-gradient(150deg, rgba(26, 127, 255, .14), var(--glass)); box-shadow: 0 0 36px rgba(26, 127, 255, .14); }
.jx.lit .ji { color: var(--ice); border-color: rgba(31, 183, 255, .55); box-shadow: 0 0 18px rgba(31, 183, 255, .4); } .jx.lit .ji { color: var(--ice); border-color: rgba(31, 183, 255, .55); box-shadow: 0 0 18px rgba(31, 183, 255, .4); }
.floor { position: absolute; left: -10%; right: -10%; bottom: -6%; height: 46%; transform: perspective(700px) rotateX(64deg); transform-origin: 50% 100%; .floor { position: absolute; left: -10%; right: -10%; bottom: -6%; height: 46%; transform: perspective(700px) rotateX(64deg); transform-origin: 50% 100%;
background: linear-gradient(rgba(159, 230, 255, .26) 1px, transparent 1px) 0 0 / 56px 56px, linear-gradient(90deg, rgba(159, 230, 255, .26) 1px, transparent 1px) 0 0 / 56px 56px; background: linear-gradient(var(--floor-line) 1px, transparent 1px) 0 0 / 56px 56px, linear-gradient(90deg, var(--floor-line) 1px, transparent 1px) 0 0 / 56px 56px;
-webkit-mask-image: radial-gradient(closest-side at 50% 70%, #000 35%, transparent); mask-image: radial-gradient(closest-side at 50% 70%, #000 35%, transparent); } -webkit-mask-image: radial-gradient(closest-side at 50% 70%, #000 35%, transparent); mask-image: radial-gradient(closest-side at 50% 70%, #000 35%, transparent); }
.pins { position: absolute; left: 0; right: 0; bottom: 17%; height: 0; } .pins { position: absolute; left: 0; right: 0; bottom: 17%; height: 0; }
.pn { position: absolute; bottom: 0; width: 0; } .pn { position: absolute; bottom: 0; width: 0; }
.pn i { position: absolute; left: 0; bottom: 0; width: 2px; height: 0; transform: translateX(-1px); background: linear-gradient(#1fb7ff, transparent); opacity: 0; } .pn i { position: absolute; left: 0; bottom: 0; width: 2px; height: 0; transform: translateX(-1px); background: linear-gradient(var(--pin), transparent); opacity: 0; }
.pn.rise i { height: var(--ph, 100px); opacity: 1; transition: height .8s cubic-bezier(.25, .7, .35, 1), opacity .2s; } .pn.rise i { height: var(--ph, 100px); opacity: 1; transition: height .8s cubic-bezier(.25, .7, .35, 1), opacity .2s; }
.pn b { position: absolute; left: -8px; bottom: var(--ph, 100px); width: 16px; height: 16px; margin-bottom: -8px; border-radius: 50%; background: #fff; border: 2px solid #1fb7ff; opacity: 0; transform: scale(.2); transition: opacity .3s, transform .5s cubic-bezier(.3, 1.6, .5, 1); } .pn b { position: absolute; left: -8px; bottom: var(--ph, 100px); width: 16px; height: 16px; margin-bottom: -8px; border-radius: 50%; background: #fff; border: 2px solid var(--pin); opacity: 0; transform: scale(.2); transition: opacity .3s, transform .5s cubic-bezier(.3, 1.6, .5, 1); }
.pn.done b { opacity: 1; transform: scale(1); box-shadow: 0 0 24px 6px #1fb7ff; } .pn.done b { opacity: 1; transform: scale(1); box-shadow: 0 0 24px 6px var(--pin); }
.pn em { position: absolute; top: 20px; left: 0; transform: translateX(-50%); width: 84px; text-align: center; line-height: 1.15; font-style: normal; font-size: .76rem; color: #55627f; transition: color .5s; } .pn em { position: absolute; top: 20px; left: 0; transform: translateX(-50%); width: 84px; text-align: center; line-height: 1.15; font-style: normal; font-size: .76rem; color: var(--pin-label); transition: color .5s; }
.pn.done em { color: #fff; } .pn.done em { color: var(--pin-done); }
#fw { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; } #fw { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.jfinal { position: absolute; left: 1.2rem; top: 1.2rem; max-width: 240px; font-size: .98rem; line-height: 1.35; color: #d6e8ff; opacity: 0; transform: translateY(8px); transition: opacity .8s, transform .8s; } .jfinal { position: absolute; left: 1.2rem; top: 1.2rem; max-width: 240px; font-size: .98rem; line-height: 1.35; color: var(--final); opacity: 0; transform: translateY(8px); transition: opacity .8s, transform .8s; }
.jfinal.show { opacity: 1; transform: none; } .jfinal.show { opacity: 1; transform: none; }
.jreplay { position: absolute; right: 1rem; top: 1rem; opacity: 0; pointer-events: none; transition: opacity .4s; } .jreplay { position: absolute; right: 1rem; top: 1rem; opacity: 0; pointer-events: none; transition: opacity .4s; }
.jreplay.show { opacity: 1; pointer-events: auto; } .jreplay.show { opacity: 1; pointer-events: auto; }
+10 -23
View File
@@ -60,20 +60,10 @@
sizeCluster(); sizeCluster();
addEventListener('resize', sizeCluster); addEventListener('resize', sizeCluster);
/* ---------- scroll-linked: "still building" rows + playbook word ---------- */ /* ---------- scroll-linked playbook word ---------- */
const bst = $('#bstack'), rows = bst ? $$('.r', bst) : [], pbSec = $('#playbook'), pbWord = $('#pbword'); const pbSec = $('#playbook'), pbWord = $('#pbword');
let ticking = false; let ticking = false;
function onScroll() { function onScroll() {
if (bst) {
const r = bst.getBoundingClientRect();
const k = clamp((innerHeight - r.top) / (innerHeight + r.height), 0, 1) - .5;
rows.forEach((el, i) => {
const dir = i % 2 ? 1 : -1;
const op = 1 - Math.abs(i - 2.5) / 3.2;
el.style.opacity = clamp(op, .18, 1).toFixed(2);
el.style.transform = reduce ? '' : 'translate3d(' + (k * dir * (120 + i * 14)).toFixed(1) + 'px,0,0)';
});
}
if (pbSec && pbWord) { if (pbSec && pbWord) {
const rp = pbSec.getBoundingClientRect(); const rp = pbSec.getBoundingClientRect();
const kp = clamp((innerHeight - rp.top) / (innerHeight + rp.height), 0, 1); const kp = clamp((innerHeight - rp.top) / (innerHeight + rp.height), 0, 1);
@@ -111,7 +101,9 @@
const pinEls = $$('.pn'), jx = $$('.jx'), jfinal = $('#jfinal'), jreplay = $('#jreplay'); const pinEls = $$('.pn'), jx = $$('.jx'), jfinal = $('#jfinal'), jreplay = $('#jreplay');
const cEx = $('#cEx'), cInd = $('#cInd'), cYr = $('#cYr'); const cEx = $('#cEx'), cInd = $('#cInd'), cYr = $('#cYr');
const PINX = [.12, .31, .5, .69, .88], PINF = [.22, .34, .46, .58, .72], LAUNCH = [200, 950, 1700, 2450, 3300]; const PINX = [.12, .31, .5, .69, .88], PINF = [.22, .34, .46, .58, .72], LAUNCH = [200, 950, 1700, 2450, 3300];
const COLORS = ['#ffffff', '#9fe6ff', '#1fb7ff', '#3d8bff', '#d6ecff']; const COLORS_DARK = ['#ffffff', '#9fe6ff', '#1fb7ff', '#3d8bff', '#d6ecff'];
const COLORS_LIGHT = ['#1a7fff', '#0b5fd0', '#1fb7ff', '#5b6cff', '#0870c4'];
const isLight = () => document.documentElement.getAttribute('data-theme') === 'light';
let FW = { w: 0, h: 0, floor: 0 }, PH = [0, 0, 0, 0, 0], rockets = [], parts = [], extra = []; let FW = { w: 0, h: 0, floor: 0 }, PH = [0, 0, 0, 0, 0], rockets = [], parts = [], extra = [];
let fwState = 'idle', fwStart = 0, fwVis = false, cleared = true, fwLaunched = [false, false, false, false, false], fwPlayed = false; let fwState = 'idle', fwStart = 0, fwVis = false, cleared = true, fwLaunched = [false, false, false, false, false], fwPlayed = false;
const countUp = (el, to, suf) => { const countUp = (el, to, suf) => {
@@ -133,6 +125,7 @@
pinEls.forEach((p, i) => { PH[i] = Math.round(FW.h * PINF[i] * .88); p.style.left = (PINX[i] * 100) + '%'; p.style.setProperty('--ph', PH[i] + 'px'); }); pinEls.forEach((p, i) => { PH[i] = Math.round(FW.h * PINF[i] * .88); p.style.left = (PINX[i] * 100) + '%'; p.style.setProperty('--ph', PH[i] + 'px'); });
} }
function burst(x, y, n, spread) { function burst(x, y, n, spread) {
const COLORS = isLight() ? COLORS_LIGHT : COLORS_DARK;
const base = COLORS[(Math.random() * COLORS.length) | 0], sp = spread || 1; const base = COLORS[(Math.random() * COLORS.length) | 0], sp = spread || 1;
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
const a = Math.random() * Math.PI * 2, v = (50 + Math.random() * 190) * sp; const a = Math.random() * Math.PI * 2, v = (50 + Math.random() * 190) * sp;
@@ -188,12 +181,13 @@
cleared = false; cleared = false;
if (fwState === 'play') { const el = now - fwStart; LAUNCH.forEach((t, i) => { if (!fwLaunched[i] && el >= t) { fwLaunched[i] = true; launch(i); } }); } if (fwState === 'play') { const el = now - fwStart; LAUNCH.forEach((t, i) => { if (!fwLaunched[i] && el >= t) { fwLaunched[i] = true; launch(i); } }); }
if (extra.length) { extra.forEach((e) => { e.t -= dt; }); extra = extra.filter((e) => { if (e.t <= 0) { burst(e.x * FW.w, e.y * FW.h, 70, 1.1); return false; } return true; }); } if (extra.length) { extra.forEach((e) => { e.t -= dt; }); extra = extra.filter((e) => { if (e.t <= 0) { burst(e.x * FW.w, e.y * FW.h, 70, 1.1); return false; } return true; }); }
fx.clearRect(0, 0, FW.w, FW.h); fx.globalCompositeOperation = 'lighter'; fx.lineCap = 'round'; const light = isLight();
fx.clearRect(0, 0, FW.w, FW.h); fx.globalCompositeOperation = light ? 'source-over' : 'lighter'; fx.lineCap = 'round';
rockets = rockets.filter((r) => { rockets = rockets.filter((r) => {
r.t += dt; const k = Math.min(1, r.t / r.dur), e = 1 - Math.pow(1 - k, 3); r.y = lerp(FW.floor, r.ty, e); r.t += dt; const k = Math.min(1, r.t / r.dur), e = 1 - Math.pow(1 - k, 3); r.y = lerp(FW.floor, r.ty, e);
r.trail.push({ x: r.x + (Math.random() - .5) * 1.5, y: r.y }); if (r.trail.length > 14) r.trail.shift(); r.trail.push({ x: r.x + (Math.random() - .5) * 1.5, y: r.y }); if (r.trail.length > 14) r.trail.shift();
for (let j = 1; j < r.trail.length; j++) { const a = j / r.trail.length; fx.strokeStyle = 'rgba(159,230,255,' + (a * .8) + ')'; fx.lineWidth = 2.4 * a; fx.beginPath(); fx.moveTo(r.trail[j - 1].x, r.trail[j - 1].y); fx.lineTo(r.trail[j].x, r.trail[j].y); fx.stroke(); } for (let j = 1; j < r.trail.length; j++) { const a = j / r.trail.length; fx.strokeStyle = (light ? 'rgba(26,127,255,' : 'rgba(159,230,255,') + (a * .8) + ')'; fx.lineWidth = 2.4 * a; fx.beginPath(); fx.moveTo(r.trail[j - 1].x, r.trail[j - 1].y); fx.lineTo(r.trail[j].x, r.trail[j].y); fx.stroke(); }
fx.fillStyle = '#fff'; fx.beginPath(); fx.arc(r.x, r.y, 2.6, 0, 6.283); fx.fill(); fx.fillStyle = light ? '#0b5fd0' : '#fff'; fx.beginPath(); fx.arc(r.x, r.y, 2.6, 0, 6.283); fx.fill();
if (k >= 1) { arrive(r.i); return false; } return true; if (k >= 1) { arrive(r.i); return false; } return true;
}); });
parts = parts.filter((p) => { parts = parts.filter((p) => {
@@ -207,13 +201,6 @@
fx.globalAlpha = 1; fx.globalCompositeOperation = 'source-over'; fx.globalAlpha = 1; fx.globalCompositeOperation = 'source-over';
} }
/* ---------- 3D DNA: fall back to the still image without WebGL ---------- */
setTimeout(() => {
const dna = $('#dna'), fb = $('#dnaFallback');
const ok = dna && dna.shadowRoot && dna.shadowRoot.querySelector('canvas');
if (!ok && fb) { if (dna) dna.hidden = true; fb.hidden = false; }
}, 1500);
/* ---------- main loop ---------- */ /* ---------- main loop ---------- */
let last = performance.now(); let last = performance.now();
(function loop(now) { (function loop(now) {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

-3851
View File
File diff suppressed because one or more lines are too long
+21 -15
View File
@@ -34,6 +34,8 @@
--code-dim: #8a8a8a; --code-dim: #8a8a8a;
--shadow-color: rgba(0, 0, 0, 0.12); --shadow-color: rgba(0, 0, 0, 0.12);
--bd: rgba(15, 23, 42, 0.08); --bd: rgba(15, 23, 42, 0.08);
--footer-bg: #eef2f8;
--footer-word: #e2e8f1;
--glass: rgba(255, 255, 255, 0.7); --glass: rgba(255, 255, 255, 0.7);
--glow: rgba(26, 127, 255, 0.10); --glow: rgba(26, 127, 255, 0.10);
--grid-line: rgba(15, 23, 42, 0.035); --grid-line: rgba(15, 23, 42, 0.035);
@@ -91,6 +93,8 @@
--nav-bg: rgba(4, 6, 12, 0.66); --nav-bg: rgba(4, 6, 12, 0.66);
--shadow-color: rgba(0, 0, 0, 0.6); --shadow-color: rgba(0, 0, 0, 0.6);
--bd: rgba(255, 255, 255, 0.09); --bd: rgba(255, 255, 255, 0.09);
--footer-bg: #000000;
--footer-word: #121212;
--glass: rgba(255, 255, 255, 0.035); --glass: rgba(255, 255, 255, 0.035);
--glow: rgba(26, 127, 255, 0.10); --glow: rgba(26, 127, 255, 0.10);
--grid-line: rgba(255, 255, 255, 0.028); --grid-line: rgba(255, 255, 255, 0.028);
@@ -120,6 +124,8 @@
--nav-bg: rgba(4, 6, 12, 0.66); --nav-bg: rgba(4, 6, 12, 0.66);
--shadow-color: rgba(0, 0, 0, 0.6); --shadow-color: rgba(0, 0, 0, 0.6);
--bd: rgba(255, 255, 255, 0.09); --bd: rgba(255, 255, 255, 0.09);
--footer-bg: #000000;
--footer-word: #121212;
--glass: rgba(255, 255, 255, 0.035); --glass: rgba(255, 255, 255, 0.035);
--glow: rgba(26, 127, 255, 0.10); --glow: rgba(26, 127, 255, 0.10);
--grid-line: rgba(255, 255, 255, 0.028); --grid-line: rgba(255, 255, 255, 0.028);
@@ -755,25 +761,24 @@ html:not(.js) .tabs { grid-template-columns: 1fr; }
.topic p { color: var(--graphite); font-size: 18px; line-height: 1.45; letter-spacing: -0.01em; grid-column: 2; } .topic p { color: var(--graphite); font-size: 18px; line-height: 1.45; letter-spacing: -0.01em; grid-column: 2; }
/* ---------- Footer ---------- */ /* ---------- Footer ---------- */
.footer { background: var(--obsidian); color: var(--on-dark); padding-block: 80px clamp(110px, 17vw, 250px); margin-top: var(--section-y); position: relative; overflow: hidden; } .footer { background: var(--footer-bg); color: var(--ink); padding-block: 80px clamp(110px, 17vw, 250px); margin-top: var(--section-y); position: relative; overflow: hidden; }
.foot-cta { display: flex; justify-content: space-between; align-items: end; gap: 32px; flex-wrap: wrap; padding-bottom: 64px; border-bottom: 1px solid #1f1f1f; } .foot-cta { display: flex; justify-content: space-between; align-items: end; gap: 32px; flex-wrap: wrap; padding-bottom: 64px; border-bottom: 1px solid #1f1f1f; }
.foot-cta h2 { color: var(--on-dark); max-width: 16ch; } .foot-cta h2 { color: var(--on-dark); max-width: 16ch; }
.foot-top { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 48px; } .foot-top { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 48px; }
.foot-top > * { min-width: 0; } .foot-top > * { min-width: 0; }
.footer .brand { color: var(--on-dark); } .footer .brand { color: var(--ink); }
.footer .brand-word b { color: var(--accent-bright); }
.foot-intro { display: grid; gap: 20px; align-content: start; } .foot-intro { display: grid; gap: 20px; align-content: start; }
.foot-intro p { color: var(--on-dark-muted); font-size: 13px; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; } .foot-intro p { color: var(--slate); font-size: 13px; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
.foot-col h4 { font-size: 12px; font-weight: 500; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--slate); margin-bottom: 18px; } .foot-col h4 { font-size: 12px; font-weight: 500; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--slate); margin-bottom: 18px; }
.foot-col ul { display: grid; gap: 12px; } .foot-col ul { display: grid; gap: 12px; }
.foot-col a { color: var(--on-dark); transition: color .15s ease; overflow-wrap: anywhere; } .foot-col a { color: var(--ink); transition: color .15s ease; overflow-wrap: anywhere; }
.foot-col a:hover { color: var(--accent-bright); } .foot-col a:hover { color: var(--accent); }
.foot-col .muted { color: var(--ash); } .foot-col .muted { color: var(--ash); }
.foot-big { margin-top: 72px; padding-top: 32px; border-top: 1px solid #1f1f1f; display: flex; justify-content: space-between; align-items: end; gap: 24px; flex-wrap: wrap; } .foot-big { margin-top: 72px; padding-top: 32px; border-top: 1px solid var(--bd); display: flex; justify-content: space-between; align-items: end; gap: 24px; flex-wrap: wrap; }
.foot-big .places { font-size: clamp(22px, 3.4vw, 40px); font-weight: 700; letter-spacing: -0.025em; line-height: 1.15; } .foot-big .places { font-size: clamp(22px, 3.4vw, 40px); font-weight: 700; letter-spacing: -0.025em; line-height: 1.15; }
.foot-big .places i { font-style: normal; color: var(--accent); padding-inline: 12px; } .foot-big .places i { font-style: normal; color: var(--accent); padding-inline: 12px; }
.foot-big small { color: var(--slate); font-size: 13px; } .foot-big small { color: var(--slate); font-size: 13px; }
.foot-word { position: absolute; left: 50%; bottom: -0.22em; translate: -50% 0; font-size: clamp(80px, 17vw, 250px); font-weight: 700; letter-spacing: -0.06em; line-height: 1; color: #121212; white-space: nowrap; pointer-events: none; user-select: none; } .foot-word { position: absolute; left: 50%; bottom: -0.22em; translate: -50% 0; font-size: clamp(80px, 17vw, 250px); font-weight: 700; letter-spacing: -0.06em; line-height: 1; color: var(--footer-word); white-space: nowrap; pointer-events: none; user-select: none; }
.footer .wrap { position: relative; z-index: 1; } .footer .wrap { position: relative; z-index: 1; }
/* ---------- Motion ---------- */ /* ---------- Motion ---------- */
@@ -839,12 +844,15 @@ h1, h2, h3, h4 { font-weight: 600; }
.btn .go svg { width: 14px; height: 14px; } .btn .go svg { width: 14px; height: 14px; }
.btn:hover .go { transform: translateX(3px); } .btn:hover .go { transform: translateX(3px); }
.btn:hover svg { transform: none; } .btn:hover svg { transform: none; }
.btn-primary { background: var(--ink); color: var(--porcelain); } .btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--ink); box-shadow: 0 0 36px rgba(159, 230, 255, .35); } .btn-primary:hover { background: var(--accent-press); box-shadow: 0 10px 30px -10px var(--accent-glow); }
.btn-ghost, .btn-ghost-light { background: var(--glass); color: var(--ink); border-color: var(--bd); padding: 8px 20px; } .btn-primary .go { background: color-mix(in srgb, var(--on-accent) 16%, transparent); color: var(--on-accent); }
.btn-ghost, .btn-ghost-light { padding: 8px 20px; }
.btn-ghost .go, .btn-ghost-light .go { display: none; } .btn-ghost .go, .btn-ghost-light .go { display: none; }
.btn-ghost:hover, .btn-ghost-light:hover { background: var(--glass); border-color: var(--sky); } .btn-ghost { background: transparent; color: var(--accent); border-color: var(--accent); }
.btn-ghost-light { color: #fff; border-color: rgba(255, 255, 255, .2); background: rgba(255, 255, 255, .03); } .btn-ghost:hover { background: var(--accent-soft); }
.btn-ghost-light { color: #fff; border-color: rgba(255, 255, 255, .35); background: transparent; }
.btn-ghost-light:hover { background: rgba(255, 255, 255, .08); border-color: #fff; }
.btn-light { background: #fff; color: #06101f; } .btn-light { background: #fff; color: #06101f; }
.btn-light:hover { background: #fff; box-shadow: 0 0 36px rgba(159, 230, 255, .35); } .btn-light:hover { background: #fff; box-shadow: 0 0 36px rgba(159, 230, 255, .35); }
.btn-sm { min-height: 40px; padding: 5px 5px 5px 16px; font-size: 11.5px; } .btn-sm { min-height: 40px; padding: 5px 5px 5px 16px; font-size: 11.5px; }
@@ -885,8 +893,6 @@ h1, h2, h3, h4 { font-weight: 600; }
.logo-img { display: none; height: 30px; width: auto; } .logo-img { display: none; height: 30px; width: auto; }
:root[data-theme="dark"] .brand .logo-img { display: block; } :root[data-theme="dark"] .brand .logo-img { display: block; }
:root[data-theme="dark"] .brand .logo-mark, :root[data-theme="dark"] .brand .brand-word { display: none; } :root[data-theme="dark"] .brand .logo-mark, :root[data-theme="dark"] .brand .brand-word { display: none; }
.footer .brand .logo-img { display: block; }
.footer .brand .logo-mark, .footer .brand .brand-word { display: none; }
.footer { border-top: 1px solid var(--bd); } .footer { border-top: 1px solid var(--bd); }
@@ -1,21 +0,0 @@
The MIT License
Copyright © 2010-2025 three.js authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.