Compare commits

..

20 Commits

Author SHA1 Message Date
0d84daea6a Add 17 new playlist pages; update hub to 21 playlists / 1601 tracks
- Wire all new PlaylistPirate-generated pages into playlists.html hub
- Update subtitle count (4 → 21 playlists, 269 → 1601 tracks)
- Add missing back-link to ../index.html with target="_top"
- Cards sorted alphabetically; eclectica-experimenti updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 20:16:55 +02:00
eb1609f652 Add Creatorlists section: 44 Greats; wire into homepage star map
44greats.html: 44 YouTube creator cards, auto-fill grid, mobile responsive.
index.html: wire Creatorlists star node to Creatorlists/44greats.html.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:49:20 +02:00
334929292e Add mobile responsiveness to ToolsnToys hub pages; fix table overflow in guides
Add 680px breakpoint to toolsntoys, foss-tools, guides, jl-early-tools:
header stacks, stats bar collapses to 2-col, sidebar/content grid stacks.
Fix table overflow in 3 guide pages: move overflow-x:hidden from body to
.guide-wrap so .guide-table-wrap scroll containers work on mobile Safari.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:21:33 +02:00
73f653ff23 Flatten ToolsnToys structure; add edu toys, dendritic, legacy artifacts
Move 6 guide pages from Guides/ to ToolsnToys/ root; fix back-links.
Add edu-toys.html (museum-style iframe exhibit for 4 legacy edu toy pages).
Add 4 edu toy artifacts, dendritic curio, docker-cheatsheet-enhanced.
Wire foss-tools, guides, edu-toys, and dendritic hrefs in toolsntoys.html.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:08:20 +02:00
0a7769d4f2 Wire ToolsnToys star node into homepage star map
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 16:47:48 +02:00
0290b29395 Add ToolsnToys section — hub, tools, guides, FOSS catalog, 6 guide pages
Hub (toolsntoys.html), JL's early tools (jl-early-tools.html), guides hub
(guides.html), FOSS Arsenal catalog (foss-tools.html), and 6 individual
guide pages covering AppImage, Linux install/uninstall, Docker, and
Facebook streaming. All pages use the night-sky adaptation of the
adventurers_toolbox3 aesthetic with dimmed ember alpha (0.38/0.65).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 14:14:21 +02:00
c1a7098ebe Fix iframe recursion and remove all localStorage/cookies site-wide
- Add target="_top" to all ← SPACE / back-to-root links so navigating
  back to index.html breaks out of the content iframe instead of loading
  it recursively inside itself (Images, Music, Watchlists hubs)
- Remove all localStorage usage: visited-star tracking in index.html
  (resets each visit, no persistence without storage), and lightbox
  "show once" guards in all section pages (lightboxes now show on every
  load — Videos, Watchlists, Music). build.py templates updated so
  future generated pages stay clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 16:03:17 +02:00
1e776bee83 Add Music section: hub, template, build pipeline, and homepage wire
Music/build.py parses *-music.md files and generates collection pages supporting
YouTube video embeds (lazy IntersectionObserver) and FileBrowser audio cards with
floating media player (prev/next/auto-advance). Music star node wired in index.html.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 15:23:37 +02:00
aec3300e40 Add playlist link button to watchlist pages; fix LastCinema slug
- Each panel now has a full-width '→ OPEN FULL PLAYLIST ON YOUTUBE' link
  below the embed — resolves YouTube showing single video instead of playlist
- Link inherits panel accent color, inverts on hover
- Renamed TheLastCinema-watchlist.md → LastCinema-watchlist.md so build.py
  generates lastcinema.html (matching hub link)
- Regenerated all 5 collection pages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 14:32:20 +02:00
dd51655792 Add Watchlists section — hub, 5 collection pages, build pipeline
- watchlists-hub.html: comic book panel grid, neon-teal/green/toucan palette,
  Rambla-only type hierarchy, CSS stagger entrance, wired to star map
- 5 collection pages built from *-watchlist.md sources via build.py:
  contentaddictionarchive, analogfrontier, culturaldecay,
  soundscapeanomalies, lastcinema
- build.py: parses MD files, generates self-contained HTML pages,
  updates hub subtitle with live counts
- index.html: Watchlists star node wired to Watchlists/watchlists-hub.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 14:22:02 +02:00
bdb39c8c08 Ignore fontlist.md and design reference files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 12:45:43 +02:00
fd47895207 Add Playlists section; clean up build artifacts from repo
- Wire Playlists star in index.html → Playlists/playlists.html
- Hub page: Aladin font, dynamic cards via build.py injection, no back-link
- 4 playlist pages: eclectica-experimenti, daydreamsoftime, soosfynwyn, theelfladymadeusdoit
- build.py: scans folder, extracts title+track count, regenerates hub cards in place
- Remove 21 tracked CSVs (moved with PlaylistPirate to ToolsnToys)
- Untrack Images/GEMINI.md, GEMINI-FIX.md, script-guide.md (agent artifacts)
- .gitignore: global rules for GEMINI*.md, HANDOVER.md, script-guide.md; Playlists build dirs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 12:14:34 +02:00
855f0bdba9 Add mobile dropdown nav to image collection pages
Desktop: two nav buttons side by side (unchanged).
Mobile: collapses to a ☰ Menu toggle, dropdown reveals both links.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:42:06 +02:00
781d3ef1e7 Simplify image galleries: folder download link, no per-image download
Remove FileBrowser API fetch, async lightbox logic, and per-image
download button. Add a single folder share link per collection page
next to Back to Hub. Lightbox is now fully synchronous.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:33:49 +02:00
696bc9c2a7 Fix FileBrowser download URL pattern in image galleries
/api/public/dl/{token}?files=/{name} returns empty ZIP.
Correct pattern is /api/public/dl/{token}/{name} (path-style).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:22:45 +02:00
e57d2b0a72 Add Images section — hub + 4 collection galleries, wire nav star
- Images/images.html: hub page linking all 4 collections
- Images/wayback.html, nomad-soul.html, myster-wizzard.html, exopraxist.html: collection galleries
- 429 thumbnails (360px) committed across 4 collections
- Gallery renders from baked filename arrays (no on-load fetch)
- Lightbox lazy-fetches FileBrowser for full-res on click, falls back to thumbnail
- .gitignore: allow Images/*/thumbnails/, anchor /GEMINI.md to root only, add .venv/
- index.html: wire Images star node to Images/images.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:06:19 +02:00
8242492712 Fix lightbox overflow on Renegade and Nomad mobile
align-items: center clips content at both ends when taller than viewport.
Switch to align-items: flex-start + overflow-y: auto so gate scrolls from top.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:07:40 +02:00
cb77460e35 SkyFishing fonts, remove escape duplicate, add life_in_alexandra
- SkyFishing: Cormorant Garamond → Estonia (display/headings), IBM Plex Mono → Share Tech Mono
- Remove escape-annotated-minimalist.html (duplicate of v2); rename Escape II → Escape in nav
- .gitignore: unblock Writings/life_in_alexandra.html (large but the one and only exception)
- life_in_alexandra.html now tracked

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 15:57:48 +02:00
fc60904e69 Font refactor: replace generic display fonts across Videos + Writings
Renegade Storyteller:
- Ribeye Marrow → Amarante (Art Nouveau, cleaner mobile rendering)
- h1 floor reduced 4rem → 3rem
- h1::before letter-spacing tightened on mobile (was overflowing narrow screens)

Writings (11 files via script):
- Bebas Neue → Fredericka the Great (4 files)
- Anton → Rubik Glitch (2 files)
- Cinzel / Cinzel Decorative → Glass Antiqua (5 files)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 15:50:20 +02:00
2f5c06fee8 Videos: font swap from JL's list + lightbox QoL fixes
Fonts (display/heading only — body untouched):
- Cringe Pit: Bebas Neue → Protest Revolution
- Renegade: Bebas Neue → Ribeye Marrow, Barlow Condensed → Faculty Glyphic (headings), Rambla (body)
- Nomad Soul: Bebas Neue → Trade Winds, Rye → Babylonica
- Hub: Bebas Neue → Workbench

Lightbox fixes (3 collection pages):
- window.onload → DOMContentLoaded (fires before iframes load, fixes slow mobile)
- lightbox-content: max-height 90vh + overflow-y auto (fixes off-screen on small viewports)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 15:44:17 +02:00
529 changed files with 64956 additions and 2808 deletions

27
.gitignore vendored
View File

@@ -9,10 +9,17 @@ DumperCan/
PARENT.md
SONNET.md
GEMINI.md
GEMINI-*.md
**/GEMINI.md
**/GEMINI-*.md
HANDOVER.md
**/HANDOVER.md
**/script-guide.md
SPORE_SYSTEM_SPEC_v0.2.md
SEEDS.md
*-JL-notes.md
HomePage-JL-notes.md
fontlist.md
# Large media files — use FileBrowser (files.exopraxist.org) instead
*.jpg
@@ -23,6 +30,15 @@ HomePage-JL-notes.md
*.PNG
*.gif
*.GIF
# Thumbnails are small (360px) and live in git
!Images/*/thumbnails/
!Images/*/thumbnails/*.jpg
!Images/*/thumbnails/*.JPG
!Images/*/thumbnails/*.jpeg
!Images/*/thumbnails/*.JPEG
!Images/*/thumbnails/*.png
!Images/*/thumbnails/*.PNG
*.mp3
*.mp4
*.webm
@@ -31,12 +47,16 @@ HomePage-JL-notes.md
*.woff2
*.otf
# Oversized HTML (embedded images)
Writings/life_in_alexandra.html
# Binaries
DumperCan/WAMEX/WAMEX
# Playlists build artifacts — regenerated locally, not for deployment
Playlists/cache.json
Playlists/mb_cache.json
Playlists/_playlist-template.html
Playlists/playlistpirate/
Playlists/dist/
# Claude Code local settings
.claude/settings.local.json
@@ -45,3 +65,4 @@ DumperCan/WAMEX/WAMEX
Thumbs.db
*.swp
*~
.venv/

687
Creatorlists/44greats.html Normal file
View File

@@ -0,0 +1,687 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>44 GREATS // SINGULAR PARTICULAR</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Sixtyfour&family=Share+Tech+Mono&family=Rambla:ital,wght@0,400;0,700;1,400;1,700&family=Noto+Emoji&display=swap" rel="stylesheet">
<style>
:root {
--bg-deep: #030812;
--bg-mid: #060f1a;
--bg-surface: #081524;
--bg-panel: #0d1e32;
--text-main: #c8d8e8;
--text-muted: #3a5570;
--neon-green: #32dc8c;
--neon-green-dim: #229966;
--fire-amber: #e8943a;
--fire-amber-dim: #b06020;
--toucan: #ffcf40;
--fire-coral: #d4654a;
--neon-teal: #2ac4b3;
--border-neon: rgba(50,220,140,0.3);
--border-amber: rgba(232,148,58,0.4);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg-deep);
color: var(--text-main);
font-family: 'Rambla', sans-serif;
min-height: 100vh;
overflow-x: hidden;
}
body::before {
content: '';
position: fixed;
inset: 0;
background:
radial-gradient(ellipse 60% 50% at 50% 80%, rgba(232,148,58,0.05) 0%, transparent 70%),
radial-gradient(ellipse 100% 60% at 20% 0%, rgba(3,8,18,0.9) 0%, transparent 60%),
radial-gradient(ellipse 100% 60% at 80% 0%, rgba(3,8,18,0.9) 0%, transparent 60%),
repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.12) 2px, rgba(0,0,0,0.12) 4px);
pointer-events: none;
z-index: 0;
}
body::after {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(to bottom, transparent 0px, transparent 3px, rgba(0,0,0,0.15) 3px, rgba(0,0,0,0.15) 4px);
pointer-events: none;
z-index: 1000;
animation: scanline 15s linear infinite;
}
@keyframes scanline { 0% { background-position: 0 0; } 100% { background-position: 0 400px; } }
.noise {
position: fixed; inset: 0; opacity: 0.04;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
pointer-events: none; z-index: 999;
}
.campfire-glow {
position: fixed; bottom: -100px; left: 50%; transform: translateX(-50%);
width: 600px; height: 400px;
background: radial-gradient(ellipse at center bottom, rgba(232,148,58,0.12) 0%, transparent 70%);
pointer-events: none; z-index: 0;
animation: glowPulse 4s ease-in-out infinite;
}
@keyframes glowPulse { 0%,100% { opacity:0.5; } 50% { opacity:0.9; transform:translateX(-50%) scale(1.05); } }
#embers { position: fixed; inset: 0; pointer-events: none; z-index: 3; }
.app {
position: relative; z-index: 1;
max-width: 1100px; margin: 0 auto;
padding: 2rem 1.5rem;
}
.back-link {
display: inline-flex; align-items: center; gap: 0.5rem;
font-family: 'Share Tech Mono', monospace;
color: var(--text-muted); text-decoration: none;
margin-bottom: 1.5rem; transition: color 150ms;
letter-spacing: 0.1em;
}
.back-link:hover { color: var(--neon-green); }
.header {
display: flex; align-items: flex-start; justify-content: space-between;
margin-bottom: 2rem; padding-bottom: 1rem;
border-bottom: 1px solid var(--border-neon);
position: relative;
}
.header::after {
content: ''; position: absolute; bottom: -1px; left: 0;
width: 40%; height: 1px;
background: var(--neon-green); box-shadow: 0 0 10px var(--neon-green);
animation: headerGlow 4s ease-in-out infinite alternate;
}
@keyframes headerGlow { from { opacity:0.4; width:25%; } to { opacity:1; width:55%; } }
.unit-tag {
font-family: 'Share Tech Mono', monospace; font-size: 0.9rem;
color: var(--fire-amber); letter-spacing: 0.25em; text-transform: uppercase;
margin-bottom: 0.4rem;
}
.title {
font-family: 'Sixtyfour', cursive; font-size: 1.8rem; font-weight: 400;
color: var(--neon-green);
text-shadow: 0 0 8px var(--neon-green), 0 0 20px rgba(50,220,140,0.6);
line-height: 1.2; margin-bottom: 0.5rem;
}
.subtitle {
font-family: 'Share Tech Mono', monospace; font-size: 0.9rem;
color: var(--text-muted); letter-spacing: 0.2em; text-transform: uppercase;
}
.header-right {
text-align: right; display: flex; flex-direction: column;
gap: 0.5rem; align-items: flex-end;
}
.status-badge {
font-family: 'Share Tech Mono', monospace; font-size: 1rem;
padding: 0.25rem 0.8rem;
border: 1px solid var(--neon-green); color: var(--neon-green);
letter-spacing: 0.15em; text-shadow: 0 0 8px var(--neon-green);
box-shadow: inset 0 0 10px rgba(50,220,140,0.15);
animation: badgePulse 2.5s ease-in-out infinite;
}
@keyframes badgePulse { 0%,100% { opacity:0.8; } 50% { opacity:1; box-shadow:inset 0 0 16px rgba(50,220,140,0.3), 0 0 12px rgba(50,220,140,0.4); } }
.coord {
font-family: 'Share Tech Mono', monospace; font-size: 0.9rem;
color: var(--text-muted); letter-spacing: 0.1em;
}
.creator-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 1rem;
}
.creator-card {
background: var(--bg-panel);
border: 1px solid rgba(50,220,140,0.15);
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px));
display: flex; flex-direction: column;
transition: border-color 200ms, background 200ms;
position: relative;
overflow: hidden;
}
.creator-card::before {
content: ''; position: absolute; top: 0; right: 0;
width: 0; height: 0; border-style: solid;
border-width: 0 10px 10px 0;
border-color: transparent var(--bg-deep) transparent transparent;
}
.creator-card:hover {
border-color: rgba(50,220,140,0.5);
background: var(--bg-surface);
}
.card-accent {
height: 3px;
background: linear-gradient(90deg, var(--fire-amber) 0%, var(--fire-amber-dim) 100%);
box-shadow: 0 0 6px rgba(232,148,58,0.4);
}
.card-body {
padding: 1rem; flex: 1; display: flex; flex-direction: column; gap: 0.5rem;
}
.creator-name {
font-family: 'Rambla', sans-serif; font-weight: 700; font-size: 1rem;
color: var(--text-main); line-height: 1.3;
}
.creator-tag {
font-family: 'Share Tech Mono', monospace; font-size: 0.75rem;
color: var(--text-muted); letter-spacing: 0.12em;
margin-top: auto; padding-top: 0.5rem;
}
.visit-btn {
display: block; margin-top: 0.75rem;
font-family: 'Share Tech Mono', monospace; font-size: 0.9rem;
padding: 0.5rem; text-align: center;
background: transparent;
border: 1px solid var(--fire-amber); color: var(--fire-amber);
text-decoration: none; letter-spacing: 0.15em; text-transform: uppercase;
transition: all 150ms;
}
.visit-btn:hover {
background: rgba(232,148,58,0.1);
box-shadow: 0 0 15px rgba(232,148,58,0.3);
text-shadow: 0 0 8px var(--fire-amber);
}
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: var(--bg-deep); }
::-webkit-scrollbar-thumb { background: var(--text-muted); }
@media (max-width: 680px) {
.header { flex-direction: column; gap: 0.75rem; }
.header-right { align-items: flex-start; text-align: left; }
.creator-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 400px) {
.creator-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="noise"></div>
<div class="campfire-glow"></div>
<canvas id="embers"></canvas>
<div class="app">
<a href="../index.html" class="back-link" target="_top">← SPACE</a>
<header class="header">
<div class="header-left">
<div class="unit-tag">▶ CREATORLISTS // SINGULAR PARTICULAR</div>
<h1 class="title">44 GREATS</h1>
<div class="subtitle">FORTY-FOUR CHANNELS WORTH YOUR TIME</div>
</div>
<div class="header-right">
<div class="status-badge">● 44 CHANNELS</div>
<div class="coord">PLATFORM: YOUTUBE</div>
</div>
</header>
<div class="creator-grid">
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Hank Green</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@hankschannel" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">TeamFourStar</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@TeamFourStar" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Benn Jordan</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@BennJordan" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Kyla Scanlon</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@KylaScanlon" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">John Green</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@johnschannel1007" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Dr. Fatima</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@dr.fatima" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Medlife Crisis</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@MedlifeCrisis" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">William Spaniel</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@Gametheory101" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Jeremy Fielding</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@Jeremy_Fielding" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Politically Aweh</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@PoliticallyAweh" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Fireship</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@Fireship" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Casual Geographic</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@mndiaye_97" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">The Crafsman Steady Craftin</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@TheCrafsMan" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">UsefulCharts</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@UsefulCharts" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Xyla Foxlin</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@xylafoxlin" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Tibees</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@tibees" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">NotesByNiba</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@NotesByNiba" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Shut Up & Sit Down</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@shutupandsitdown" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">People Make Games</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@PeopleMakeGames" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Up and Atom</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@upandatom" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Viva La Dirt League</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@VivaLaDirtLeague" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Ginny Di</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@GinnyDi" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Ze Frank</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@zefrank" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Sanaea Bubber</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@sanaeabubber69" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">SmarterEveryDay</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@smartereveryday" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">ContraPoints</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@ContraPoints" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Tom Scott</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@TomScottGo" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Dan McClellan</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@maklelan" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Simon Clark</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@SimonClark" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Elephants in Rooms - Ken LaCorte</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@ElephantsInRooms" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Rational Animations</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@RationalAnimations" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Atun-Shei Films</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@AtunSheiFilms" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Simone Giertz</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@simonegiertz" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Howtown</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@Howtown" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Laura Kampf</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@laurakampf" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">ESOTERICA</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@TheEsotericaChannel" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Noodle</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@noodlefunny" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">J. Draper</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@JDraper" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Stuff Made Here</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@StuffMadeHere" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Aaed Musa</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@aaedmusa" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Heather Cox Richardson</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@heathercoxrichardson" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Steve Mould</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@SteveMould" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">Technology Connections</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@TechnologyConnections" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
<div class="creator-card">
<div class="card-accent"></div>
<div class="card-body">
<div class="creator-name">No Boilerplate</div>
<div class="creator-tag">▶ YOUTUBE</div>
<a href="https://www.youtube.com/@NoBoilerplate" class="visit-btn" target="_blank" rel="noopener">VISIT ↗</a>
</div>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('embers');
const ctx = canvas.getContext('2d');
function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }
resize();
window.addEventListener('resize', resize);
const EMBER_COUNT = 60;
const embers = [];
const mouse = { x: -9999, y: -9999 };
window.addEventListener('mousemove', ev => { mouse.x = ev.clientX; mouse.y = ev.clientY; });
const ZONES = [
{ r: 40, strength: 0.012 },
{ r: 90, strength: 0.004 },
{ r: 130, strength: 0.001 },
];
const COLORS = [
{ r: 232, g: 148, b: 58 },
{ r: 212, g: 101, b: 74 },
{ r: 255, g: 207, b: 64 },
{ r: 197, g: 88, b: 217 },
];
function randomEmber() {
const col = COLORS[Math.floor(Math.random() * COLORS.length)];
return {
x: Math.random() * canvas.width, y: canvas.height + 10,
vx: (Math.random() - 0.5) * 0.8, vy: -(0.4 + Math.random() * 1.2),
life: 0, maxLife: 200 + Math.random() * 300,
size: 1 + Math.random() * 2,
r: col.r, g: col.g, b: col.b,
wobble: Math.random() * Math.PI * 2,
wobbleSpeed: 0.02 + Math.random() * 0.02,
trail: [],
};
}
for (let i = 0; i < EMBER_COUNT; i++) {
const e = randomEmber();
e.y = Math.random() * canvas.height;
e.life = Math.random() * e.maxLife;
embers.push(e);
}
function drawEmber(e) {
const progress = e.life / e.maxLife;
const alpha = progress < 0.1 ? progress / 0.1 : progress > 0.8 ? (1 - progress) / 0.2 : 1;
if (alpha <= 0) return;
const gAlpha = alpha * 0.38;
const glow = ctx.createRadialGradient(e.x, e.y, 0, e.x, e.y, e.size * 5);
glow.addColorStop(0, `rgba(${e.r},${e.g},${e.b},${gAlpha})`);
glow.addColorStop(1, `rgba(${e.r},${e.g},${e.b},0)`);
ctx.beginPath();
ctx.arc(e.x, e.y, e.size * 5, 0, Math.PI * 2);
ctx.fillStyle = glow; ctx.fill();
ctx.fillStyle = `rgba(${e.r},${e.g},${e.b},${Math.min(0.65, gAlpha * 1.4)})`;
const ps = Math.max(1, Math.round(e.size));
ctx.fillRect(Math.round(e.x) - ps, Math.round(e.y) - ps, ps * 2, ps * 2);
for (let t = 0; t < e.trail.length; t++) {
const pt = e.trail[t];
ctx.fillStyle = `rgba(${e.r},${e.g},${e.b},${(t / e.trail.length) * gAlpha * 0.3})`;
ctx.fillRect(Math.round(pt.x), Math.round(pt.y), 2, 2);
}
}
function tick() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const e of embers) {
if (e.life % 6 === 0) { e.trail.push({ x: e.x, y: e.y }); if (e.trail.length > 5) e.trail.shift(); }
const dx = mouse.x - e.x, dy = mouse.y - e.y, d = Math.sqrt(dx*dx+dy*dy);
if (d < ZONES[2].r) {
let s = 0;
for (const z of ZONES) if (d < z.r) { s = z.strength; break; }
e.vx += (dx/d)*s; e.vy += (dy/d)*s;
e.vx *= 0.98; e.vy *= 0.98;
}
e.wobble += e.wobbleSpeed;
e.x += e.vx + Math.sin(e.wobble) * 0.3;
e.y += e.vy;
e.life++;
if (e.life >= e.maxLife || e.y < -20) Object.assign(e, randomEmber());
drawEmber(e);
}
requestAnimationFrame(tick);
}
tick();
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Some files were not shown because too many files have changed in this diff Show More