Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and

### Changed

- Intros: the readout card in both the site intro and the vault's unlock now matches the vault gate: no box, the four viewfinder corner ticks, the rain fading to dark behind it, a blinking tag (RECOVERY · ARCHIVE_404 / KEY ACCEPTED · SOURCE VAULT), a small title (RECOVERING FILES. / DECRYPTING VAULT.) and a gradient bar that fills with the 00 → 20 count.
- Source Vault on phones: the chapter buttons wrap onto two rows instead of running off the screen, and the vault now always opens at the top after unlocking (typing the key had left the page scrolled down).
- Source Vault stems: the remastered stems are in. Each track's zip holds its WAV stems and MIDI files (10–12 stems per track, every one as WAV + MIDI), and the stem lists now match the real files. ALL STEMS hands over the 20 track zips one after another (a chapter zip would pass GitHub's 2 GB per-file cap). The per-stem WAV / MIDI chips are labels now, not mock-up buttons.
- Source Vault phone menu: one link is always lit with the gradient, like the site's menu. At the top of the page that's PROMPTS, the first section.
- Source Vault phone menu: it now opens exactly like the site's menu: full screen with the slat wipe, the SYS::OPEN chip, big outlined poster links with numbered captions (the section you're on fills with the gradient), and the split buttons at the bottom.
Expand Down
36 changes: 26 additions & 10 deletions src/components/BootSequence.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,20 +173,36 @@ export function BootSequence({ onComplete }) {
aria-hidden="true"
/>
<span className="e-bscan" aria-hidden={true} />
<div className={"e-bterm" + (draining ? " out" : "")} aria-hidden="true">
<div>
<b>&gt;</b> RECOVERING ARCHIVE_404
<div className={"e-icard" + (draining ? " out" : "")} aria-hidden="true">
<span className="e-icard-vf" />
<div className="e-icard-tg">
<i />
RECOVERY · ARCHIVE_404
</div>
<div>
<b>&gt;</b> FILE <i>{pad(count)}/20</i>
{count > 0 && <span className="e-bterm-t">{TITLES[count - 1]}</span>}
<div className="e-icard-h">
RECOVERING <span className="e-grad">FILES.</span>
</div>
{done && (
<div className="e-icard-l">
<div>
<b>&gt;</b> <i>20/20 FILES INTACT</i>
<b>&gt;</b> RECOVERING ARCHIVE_404
</div>
)}
<span className="e-bterm-cur" />
<div>
<b>&gt;</b> FILE <i>{pad(count)}/20</i>
{count > 0 && <span className="e-icard-t">{TITLES[count - 1]}</span>}
</div>
{done && (
<div>
<b>&gt;</b> <i>20/20 FILES INTACT</i>
</div>
)}
</div>
<div className="e-icard-bar">
<b style={{ width: `${(count / TITLES.length) * 100}%` }} />
</div>
<div className="e-icard-tk">
<span>20 FILES</span>
<span>{pad(count)}/20</span>
</div>
</div>
<p className="sr-only">Recovering ARCHIVE_404: 20 of 20 files intact.</p>
{/* visually hidden; appears only when focused, e.g. by a screen reader (tap / any key also skips) */}
Expand Down
149 changes: 128 additions & 21 deletions src/styles/overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -2904,53 +2904,160 @@ body {
}

/* ===== intro M3: terminal readout over the tracklist rain (BootSequence) ===== */
.e-bterm {
/* intro readout card (site intro + vault unlock): the vault gate's viewfinder card. No box, four
corner ticks, the rain fading to dark behind the text; a tag, a small title, the readout lines and
a gradient bar that fills with the 00 → 20 count. */
.e-icard {
position: absolute;
left: 50%;
top: 50%;
z-index: 3;
transform: translate(-50%, -50%);
padding: 18px 22px;
min-width: min(440px, calc(100vw - 48px));
background: rgba(3, 4, 9, 0.78);
border: 1px solid rgba(244, 244, 248, 0.12);
width: min(330px, calc(100vw - 40px));
padding: 18px 18px 14px;
background: radial-gradient(closest-side, rgba(3, 4, 9, 0.92), rgba(3, 4, 9, 0.75) 70%, transparent);
font-family:
Space Mono,
monospace;
font-size: clamp(11px, 1.3vw, 15px);
color: #f4f4f8;
transition: opacity 0.4s;
}
@media (min-width: 768px) {
.e-icard {
width: 380px;
padding: 22px 22px 16px;
}
}
.e-icard.out {
opacity: 0;
}
.e-icard::before,
.e-icard::after,
.e-icard-vf::before,
.e-icard-vf::after {
content: "";
position: absolute;
width: 14px;
height: 14px;
border: 1px solid #ff00e5;
pointer-events: none;
}
.e-icard::before {
top: -1px;
left: -1px;
border-right: 0;
border-bottom: 0;
}
.e-icard::after {
bottom: -1px;
right: -1px;
border-left: 0;
border-top: 0;
border-color: #00efff;
}
.e-icard-vf {
position: absolute;
inset: -1px;
pointer-events: none;
}
.e-icard-vf::before {
top: 0;
right: 0;
border-left: 0;
border-bottom: 0;
border-color: #00efff;
}
.e-icard-vf::after {
bottom: 0;
left: 0;
border-right: 0;
border-top: 0;
}
.e-icard-tg {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
font-size: 8px;
letter-spacing: 0.32em;
color: #ff00e5;
white-space: nowrap;
}
.e-icard-tg i {
width: 6px;
height: 6px;
flex: none;
background: #4ade80;
box-shadow: 0 0 8px #4ade80;
animation: e4-blink 1.2s steps(1) infinite;
}
.e-icard-h {
font-family: "Bebas Neue", sans-serif;
font-weight: 400;
font-size: 1.7rem;
line-height: 0.86;
margin-bottom: 10px;
}
.e-icard-l {
min-height: 66px;
font-size: 11px;
letter-spacing: 0.08em;
line-height: 2;
color: #f4f4f8;
white-space: nowrap;
text-shadow: 0 0 10px rgba(255, 0, 229, 0.5);
transition: opacity 0.4s;
}
.e-bterm.out {
opacity: 0;
@media (min-width: 768px) {
.e-icard-h {
font-size: 2rem;
}
.e-icard-l {
font-size: 12px;
min-height: 72px;
}
}
.e-bterm b {
.e-icard-l b {
font-weight: 400;
color: #ff00e5;
}
.e-bterm i {
.e-icard-l i {
font-style: normal;
color: #00efff;
}
.e-bterm-t {
.e-icard-l .ok {
color: #4ade80;
}
.e-icard-t {
display: block;
margin-left: 1.4em;
overflow: hidden;
text-overflow: ellipsis;
color: rgba(244, 244, 248, 0.6);
}
.e-bterm-cur {
display: inline-block;
width: 0.6em;
height: 1.1em;
margin-top: 4px;
.e-icard-bar {
position: relative;
height: 2px;
margin-top: 12px;
background: rgba(244, 244, 248, 0.1);
}
.e-icard-bar b {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: linear-gradient(90deg, #ff00e5, #00efff);
vertical-align: -0.2em;
animation: e4-blink 1s steps(1) infinite;
box-shadow: 0 0 8px rgba(255, 0, 229, 0.7);
transition: width 0.15s;
}
.e-icard-tk {
display: flex;
justify-content: space-between;
margin-top: 6px;
font-size: 8px;
letter-spacing: 0.2em;
color: rgba(244, 244, 248, 0.28);
}
@media (prefers-reduced-motion: reduce) {
.e-bterm-cur {
.e-icard-tg i {
animation: none;
}
}
Expand Down
20 changes: 15 additions & 5 deletions src/vault/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const mb = (b) => (b >= 1e9 ? (b / 1e9).toFixed(2) + " GB" : Math.round(b / 1e6)
const esc = (s) =>
s.replace(/[&<>"]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[c]);
const REDUCE = matchMedia("(prefers-reduced-motion: reduce)").matches;
// The vault always opens at the top: typing the key on a phone scrolls the page behind the gate
// (the keyboard pushes the field into view), and the browser may restore an old position on return.
if ("scrollRestoration" in history) history.scrollRestoration = "manual";
const toTop = () => scrollTo({ top: 0, left: 0, behavior: "instant" });
const toast = (t) => {
const el = $("#toast");
el.textContent = t;
Expand Down Expand Up @@ -187,6 +191,7 @@ let revealed = false;
function reveal() {
if (revealed) return;
revealed = true;
toTop();
$("#gate").classList.add("out");
stopGateRain();
document.body.classList.remove("locked");
Expand Down Expand Up @@ -338,20 +343,25 @@ function unlockSequence() {
term = $("#viTerm");
ov.hidden = false;
ov.classList.remove("out");
toTop();
$("#gate").classList.add("out");
stopGateRain();
const rain = vaultRain($("canvas", ov), stems.concat(titles));
const T = [];
const at = (ms, f) => T.push(setTimeout(f, ms));
const line = (i, extra = "") =>
`<div><b>&gt;</b> KEY ACCEPTED · <span class="ok">ACCESS Nº004</span></div><div><b>&gt;</b> DECRYPTING <i>${pad(i)}/20</i>${i ? `<span class="t">${titles[i - 1]}_STEMS.ZIP</span>` : ""}</div>${extra}<span class="cur"></span>`;
const line = (i, extra = "") => {
$("#viBar").style.width = (i / 20) * 100 + "%";
$("#viCount").textContent = `${pad(i)}/20`;
return `<div><b>&gt;</b> KEY ACCEPTED · <span class="ok">ACCESS Nº004</span></div><div><b>&gt;</b> DECRYPTING <i>${pad(i)}/20</i>${i ? `<span class="e-icard-t">${titles[i - 1]}_STEMS.ZIP</span>` : ""}</div>${extra}`;
};
const lines = $("#viLines");
term.classList.remove("out");
term.innerHTML = line(0);
for (let i = 1; i <= 20; i++) at(250 + (i - 1) * 150, () => (term.innerHTML = line(i)));
lines.innerHTML = line(0);
for (let i = 1; i <= 20; i++) at(250 + (i - 1) * 150, () => (lines.innerHTML = line(i)));
at(
250 + 20 * 150,
() =>
(term.innerHTML = line(
(lines.innerHTML = line(
20,
'<div><b>&gt;</b> <span class="ok">VAULT OPEN</span> · 20 FILES · WAV + MIDI</div>',
)),
Expand Down
58 changes: 7 additions & 51 deletions src/vault/vault.css
Original file line number Diff line number Diff line change
Expand Up @@ -399,57 +399,6 @@ a {
pointer-events: none;
background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.3) 0 1px, transparent 1px 3px);
}
.vi-term {
position: absolute;
left: 50%;
top: 50%;
z-index: 3;
transform: translate(-50%, -50%);
padding: 18px 22px;
min-width: min(460px, calc(100vw - 48px));
background: rgba(3, 4, 9, 0.78);
border: 1px solid rgba(244, 244, 248, 0.12);
font-family: var(--mono);
font-size: clamp(11px, 1.3vw, 15px);
letter-spacing: 0.08em;
line-height: 2;
color: var(--ghost);
white-space: nowrap;
text-shadow: 0 0 10px rgba(255, 0, 229, 0.5);
transition: opacity 0.4s;
}
.vi-term.out {
opacity: 0;
}
.vi-term b {
font-weight: 400;
color: var(--mag);
}
.vi-term i {
font-style: normal;
color: var(--cyan);
}
.vi-term .ok {
color: var(--led);
}
.vi-term .t {
margin-left: 1.2em;
color: rgba(244, 244, 248, 0.6);
}
@media (max-width: 520px) {
.vi-term .t {
display: block;
margin-left: 1.4em;
}
}
.vi-term .cur {
display: inline-block;
width: 0.6em;
height: 1.1em;
background: var(--grad);
vertical-align: -0.2em;
animation: blink 1s steps(2) infinite;
}
.sr-only {
position: absolute;
width: 1px;
Expand Down Expand Up @@ -1089,8 +1038,15 @@ details.fold[open] summary::after {
.toolbar {
flex-wrap: wrap;
}
/* chapter buttons wrap onto a second row instead of scrolling off the edge */
.chips-scroll {
flex: 1 1 100%;
flex-wrap: wrap;
overflow: visible;
}
.chips-scroll .gbtn {
flex: 1 1 auto;
justify-content: center;
}
.search {
flex: 1;
Expand Down
9 changes: 8 additions & 1 deletion vault/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@ <h1 id="gate-h">ACCESS <span class="grad">REQUIRED.</span></h1>
<canvas></canvas>
<div class="vi-vig"></div>
<div class="vi-scan"></div>
<div class="vi-term" id="viTerm"></div>
<div class="e-icard" id="viTerm">
<span class="e-icard-vf"></span>
<div class="e-icard-tg"><i></i>KEY ACCEPTED · SOURCE VAULT</div>
<div class="e-icard-h">DECRYPTING <span class="e-grad">VAULT.</span></div>
<div class="e-icard-l" id="viLines"></div>
<div class="e-icard-bar"><b id="viBar"></b></div>
<div class="e-icard-tk"><span>20 STEM ZIPS</span><span id="viCount">00/20</span></div>
</div>
</div>
<p class="sr-only" id="viStatus" role="status" aria-live="polite"></p>

Expand Down
Loading