Files
.profile/public/scripts/hero-effects.js
T
SowinskiBraedenandClaude Opus 5 54c00bf16f pull the terminal styling back and add an ASCII backdrop
The first pass applied terminal decoration to everything, which read as
costume rather than design. Strip it back to a few deliberate cues and
let an animated backdrop carry the character instead:

- Drop the prefix glyphs from links, tags, nav items, badges and
  headings, and restore plain section names in place of snake_case.
- Keep one prompt in the hero, the ~/ on the wordmark, ISO dates and
  status dots; everything else is ordinary type.
- Restore depth: acrylic surfaces over soft radial light, 6px radii,
  and an accent glow on the primary action and status dots.
- Draw a dithered ASCII field behind the page. A fixed per-cell dither
  value decides which cells are lit so coverage stays even, while slow
  interfering waves move brightness through it. It idles when the tab
  is hidden and stays still under prefers-reduced-motion.
- Remove the nested panel boxes on the projects page and size the entry
  page to its article column.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-17 23:55:06 -07:00

70 lines
1.7 KiB
JavaScript

(function() {
const stream = document.querySelector(".term__stream");
if (!stream) {
return;
}
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (prefersReducedMotion) {
return;
}
const CHAR_DELAY = 18;
const AFTER_COMMAND_DELAY = 90;
const AFTER_OUTPUT_DELAY = 130;
// Build the playback script before hiding anything, so a thrown error here
// leaves the page in its fully rendered state.
// Commands type into their own span so the blinking caret beside them
// survives the text rewrites.
const steps = Array.from(stream.children).map((element) => {
const target = element.querySelector(".cmd__text");
return {
element,
target: target || element,
isCommand: element.classList.contains("cmd"),
text: (target || element).textContent
};
});
if (!steps.some((step) => step.isCommand)) {
return;
}
steps.forEach((step) => {
if (step.isCommand) {
step.target.textContent = "";
return;
}
step.element.classList.add("is-typing-hidden");
});
const wait = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms));
const typeCommand = async (element, text) => {
for (let index = 0; index < text.length; index += 1) {
element.textContent = text.slice(0, index + 1);
await wait(CHAR_DELAY);
}
};
const play = async () => {
for (const step of steps) {
if (step.isCommand) {
await typeCommand(step.target, step.text);
await wait(AFTER_COMMAND_DELAY);
continue;
}
step.element.classList.remove("is-typing-hidden");
await wait(AFTER_OUTPUT_DELAY);
}
};
play();
})();