7 Commits

Author SHA1 Message Date
Joel Brock
89d7e8d8ca Videos: 2-per-row default, featured opt-in to wide layout
Reverted the global youtube wide treatment per user direction.
Videos default to span 6 (pair layout) at 600px+ again. Items with
`featured: true` in JSON get a new `card--wide` class that opts
them into the same 78%-centered + vertical-breathing layout
portfolio uses — meant to promote a hero video without making
every video imposing.
2026-05-18 20:13:12 -07:00
Joel Brock
ff0abee349 Drop turtle, honor ?template= URL param, add warp easter egg
- Removed the cosmos turtle (CSS rules + auto-load probe + JS hook).
  Reduced-motion turtle branch removed too.
- ?template=editorial|swiss|cosmos URL param now wins over the value
  in data/links.json (and the cached localStorage fallback). Wired in
  both the pre-paint boot script and main() so deep links work
  without flashing the wrong template.
- New hidden easter egg: type the letters w-a-r-p anywhere on the
  page (no input focused) and the page reloads on the next template
  in the cycle editorial -> swiss -> cosmos -> editorial. The URL is
  updated with the new ?template= param so the override survives
  refresh and is shareable. A small "↯ <name>" toast pops up after
  the reload via sessionStorage handoff, fades after ~2.5s, respects
  prefers-reduced-motion.
- README documents both the URL param and the warp keyword.
2026-05-16 09:35:45 -07:00
Joel Brock
c16ee37096 Cosmos: aurora cursor, card tilt, comets, ripples, turtle; headless sections
Pushed the cosmos theme further:

- Cursor aurora — 600px soft cyan/violet/magenta halo follows the
  pointer with lag (mix-blend-mode: screen, blur 8px). Fades in on
  first move, fades out on pointerleave.
- Card 3D tilt — every cosmos card rotates up to ~6deg toward the
  cursor on hover via custom-property-driven rotateX/rotateY, with a
  cursor-tracking radial shimmer painted inside via mix-blend-mode:
  screen. RAF-throttled. Skipped for testimonial + client tiles since
  they have no chrome.
- Hero parallax — name, tagline, and drift-orb all shift relative to
  cursor position via --cm-x / --cm-y custom properties set globally
  from the pointer move handler.
- Shader: doubled the gravity-well strength (0.03 -> 0.06) and added
  a click-driven ripple — pointerdown sets u_ripple_pos/u_ripple_age
  uniforms; the shader propagates a cyan/magenta luminous ring of
  displacement that decays over ~2s.
- Comets — 3 CSS-only streaks crossing the page on staggered 14/22/
  19s loops with cyan/violet drop-shadow trails.
- Turtle — new .cosmos-turtle img auto-loads if assets/img/turtle.png
  resolves (or theme.turtle URL is set). Floats in from the left,
  arcs across, fades out off the right; pulses its aurora glow on a
  4s bob. Reduced-motion users see it positioned statically.
- All new chrome respects prefers-reduced-motion: halo/comets hidden,
  card tilt + parallax disabled, turtle pinned static.

Also adds section.headless = true (per user request): renders the
section body with no header/kicker chrome and a tighter top margin so
the contents read as nested under the prior section. Example JSON now
uses this to slide the testimonials carousel under the clients wall.
2026-05-16 09:26:11 -07:00
Joel Brock
e1b3bc7d43 Add testimonial item type with crossfade carousel layout
New `type: "testimonial"` with structured attribution
(quote/name/role/org/url/image/date) plus a `layout: "testimonials"`
section behavior that renders the items as a tasteful crossfade
carousel — one quote at a time, 7s auto-advance, prev/next nav, dot
indicators, swipe support, ←/→ keys, pause on hover/focus, ARIA
live region.

Reduced-motion users automatically get .carousel--stacked: every
testimonial visible at once, controls hidden, no auto-advance. A
single-item section also skips the carousel chrome.

Per-template treatment: editorial uses Fraunces italic for the curly
quote mark and the body, swiss strips uppercase from titles per prior
fix, cosmos glows the mark with the cyan/violet accent stack.

Section auto-detects the layout when the first item is a testimonial,
matching how the clients layout already works.
2026-05-15 17:12:13 -07:00
Joel Brock
1346f7a40c Add Singularity template: WebGL nebula + holographic cards
Third theme template scoped to :root[data-template="cosmos"], joining
editorial and swiss. Set "theme.template": "cosmos" in links.json to
activate.

Background — full-viewport WebGL fragment shader running a 5-octave
warped fBm nebula in indigo/violet/magenta/cyan, with a two-layer
procedural starfield (small dense + sparse blue-white halo) twinkling
on independent phases. Pointer-tracking gravity well subtly perturbs
sampling around the cursor. Pixel ratio capped at 1.5x for fill-rate;
loop pauses on visibility change.

UI — Orbitron display + Geist body, glassmorphic cards with
backdrop-filter, conic-gradient holographic borders driven by
@property --cosmos-hue rotating on hover, gradient-clip section
numbers and project titles, chromatic-split hero last name on hover
(::before + ::after pseudos with mix-blend-mode screen using a
data-text attr), glowing drift-orb in place of the editorial asterism,
animated section-head accent line.

Fallbacks — prefers-reduced-motion or WebGL-unavailable triggers the
.cosmos-static class with a CSS-only radial-gradient nebula and all
heavy animations disabled. Always-dark regardless of theme toggle.

README documents the new template; links.example.json unchanged.
2026-05-15 17:01:30 -07:00
Joel Brock
543d3bd8e1 Refine Swiss + Editorial themes; add optional date field
Swiss: drop all-caps on titles, soften heavy ink borders to muted rules
or remove them where background contrast carries the form, balance hero
name weights (smaller lighter first name vs heavier italic last name),
fix unreadable white description text on portfolio hover.

Editorial: enlarge the section "No" mark and set it in italic Fraunces so
it reads as typography instead of a tick, swap the first name into DM
Serif Display for a different J, sharpen the section number caption.

Client tile: contain custom logos at 86% so wide marks like
"The Cooperative Way" stop getting cropped to "operative".

New: optional `date` field on every item type (link/card/portfolio/
youtube/client). Accepts YYYY, YYYY-MM, or YYYY-MM-DD. Rendered
human-friendly with the raw ISO preserved in <time datetime>.
Documented in README and demonstrated in links.example.json.
2026-05-15 16:33:53 -07:00
Joel Brock
36084013c8 Initial commit: dlstack file-driven link index
A hand-rolled linktree alternative — pure static HTML/CSS/JS, no build
step. Drop on any shared host via SFTP and edit data/links.json to update.

Features
- File-driven content via data/links.json (links, projects, YouTube,
  client tiles, portfolio pieces)
- Two interchangeable templates: editorial (Fraunces + paper + vermilion)
  and swiss (Archivo grotesque, all-caps poster)
- Auto/light/dark theme toggle with no-flash boot script
- Auto-fetched favicons via Google S2 (with image-URL override)
- Lazy YouTube facades (no third-party JS until clicked)
- Adaptive client-logo grid
- Scroll-triggered reveal animations
- ~40 KB total payload, ~12 KB gzipped

The repo ships links.example.json as a demo; data/links.json is
gitignored so personal content stays out of the public repo.
2026-05-15 13:37:09 -07:00