diff options
| author | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-28 18:25:41 -0700 |
|---|---|---|
| committer | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-28 18:25:41 -0700 |
| commit | 34f0486f091ded7112442a00f8c5c5ecae342265 (patch) | |
| tree | e00129732e44609e76bcb22b25d2a18af5aa1df2 /index.css | |
| parent | 7b67d90f4f25eca2480d0d769ec5ab6305c4b4c6 (diff) | |
refactor: extract inline css/js from index.html
index.html shrank from 1650 to 349 lines. Inline <style>
moved to index.css, ARTICLES data to articles.js, the rest of
the inline script to index.js. Also:
- drop unused bindMusicToggle from aero.js
- collapse duplicate click+dblclick icon handlers
- dedup music-toggle gradient via .mt-btn.on class
- replace inline styles in films/podcast/now-playing renderers
with semantic classes (.film-when, .pod-ep, .np-row, etc.)
- precompute article readMin and plainTitle once instead of on
every render
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Diffstat (limited to 'index.css')
| -rw-r--r-- | index.css | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/index.css b/index.css new file mode 100644 index 0000000..a38a327 --- /dev/null +++ b/index.css @@ -0,0 +1,292 @@ + /* ============= LOCKED PALETTE ============= */ + :root { + --sky: url("img/wallpaper.png") center / cover no-repeat, linear-gradient(180deg, oklch(78% 0.10 215) 0%, oklch(88% 0.14 145) 100%); + --sun: radial-gradient(circle, oklch(99% 0.02 215) 0%, oklch(94% 0.05 215 / 0) 60%); + --icon-blue: linear-gradient(135deg, oklch(92% 0.06 215), oklch(72% 0.13 220) 60%, oklch(48% 0.13 230)); + --icon-orange: linear-gradient(135deg, oklch(94% 0.10 145), oklch(78% 0.18 145) 55%, oklch(52% 0.16 150)); + --icon-green: linear-gradient(135deg, oklch(94% 0.12 130), oklch(76% 0.18 140) 55%, oklch(50% 0.16 150)); + --icon-pink: linear-gradient(135deg, oklch(88% 0.08 195), oklch(68% 0.13 200) 60%, oklch(45% 0.13 210)); + --icon-silver: linear-gradient(135deg, oklch(98% 0.005 220), oklch(85% 0.015 220) 60%, oklch(62% 0.03 225)); + --title-bar: linear-gradient(to bottom, oklch(94% 0.05 195), oklch(78% 0.10 200) 50%, oklch(60% 0.12 215)); + --start-btn: linear-gradient(to bottom, oklch(94% 0.10 145) 0%, oklch(75% 0.18 145) 48%, oklch(50% 0.16 150) 52%, oklch(68% 0.18 145) 100%); + --start-border: oklch(40% 0.14 150); + } + .desk { position: fixed; inset: 0; overflow: hidden; background: var(--sky); background-size: cover; background-position: center; } + .icons { position: absolute; left: 24px; top: 24px; display: grid; grid-template-columns: 1fr; gap: 18px; z-index: 10; } + .icon { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 80px; cursor: pointer; text-align: center; } + .icon .glyph { + width: 56px; height: 56px; border-radius: 14px; + background: linear-gradient(135deg, oklch(88% 0.10 220), oklch(70% 0.14 230) 60%, oklch(50% 0.13 240)); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), inset 0 -3px 6px rgba(40,80,140,0.4), 0 4px 14px rgba(40,80,140,0.35); + display: flex; align-items: center; justify-content: center; + font-size: 26px; color: white; text-shadow: 0 1px 2px rgba(0,0,0,0.4); + position: relative; + } + .icon .glyph::before { content: ""; position: absolute; left: 4px; right: 4px; top: 3px; height: 40%; border-radius: 12px; background: linear-gradient(to bottom, rgba(255,255,255,0.75), transparent); } + .icon .glyph.orange { background: linear-gradient(135deg, oklch(92% 0.08 70), oklch(75% 0.16 55) 60%, oklch(55% 0.15 35)); } + .icon .glyph.green { background: linear-gradient(135deg, oklch(90% 0.10 145), oklch(75% 0.15 145) 60%, oklch(50% 0.13 155)); } + .icon .glyph.pink { background: linear-gradient(135deg, oklch(90% 0.10 350), oklch(75% 0.16 350) 60%, oklch(55% 0.16 340)); } + .icon .glyph.silver { background: linear-gradient(135deg, oklch(95% 0.01 240), oklch(78% 0.03 240) 60%, oklch(55% 0.04 240)); } + .icon .label { font-size: 12px; color: white; text-shadow: 0 1px 3px rgba(0,0,0,0.6); font-weight: 500; } + .icon:hover .glyph { transform: translateY(-2px) scale(1.04); transition: transform 200ms; } + + .win { position: absolute; min-width: 320px; z-index: 50; } + /* When a window has been resized, it switches to a flex column so the + body becomes a scroll region — keeps content from getting clipped */ + .win.resized { + display: flex; flex-direction: column; + overflow: hidden; + border-radius: 18px; + } + .win.resized .body { + flex: 1; min-height: 0; + overflow-y: auto; + border-radius: 0 0 18px 18px; + } + /* The browser window is already a flex column internally; let it fill */ + .win.resized > .browser { flex: 1; min-height: 0; } + /* RESIZE HANDLES */ + .rs { position: absolute; z-index: 5; } + .rs-e { right: -3px; top: 14px; bottom: 18px; width: 8px; cursor: ew-resize; } + .rs-s { left: 14px; right: 18px; bottom: -3px; height: 8px; cursor: ns-resize; } + .rs-se { + right: 0; bottom: 0; width: 22px; height: 22px; + cursor: nwse-resize; + background-image: + linear-gradient(135deg, transparent 0 38%, rgba(40,80,140,0.85) 38% 48%, transparent 48% 60%, rgba(40,80,140,0.75) 60% 70%, transparent 70%, rgba(40,80,140,0.6) 82% 92%, transparent 92%); + border-radius: 0 0 18px 0; + opacity: 0.65; + transition: opacity 150ms, filter 150ms; + } + .rs-se:hover { opacity: 1; filter: drop-shadow(0 0 4px rgba(120,170,220,0.8)); } + body.rs-cursor-e, body.rs-cursor-e * { cursor: ew-resize !important; } + body.rs-cursor-s, body.rs-cursor-s * { cursor: ns-resize !important; } + body.rs-cursor-se, body.rs-cursor-se * { cursor: nwse-resize !important; } + .win .titlebar { + height: 32px; padding: 0 12px; display: flex; align-items: center; gap: 8px; + border-radius: 18px 18px 0 0; + background: var(--title-bar); + color: var(--title-fg, white); font-size: 13px; font-weight: 600; text-shadow: 0 1px 2px var(--title-shadow, rgba(0,0,0,0.3)); + cursor: grab; user-select: none; + border-bottom: 1px solid rgba(0,0,0,0.15); + } + .win .titlebar .dots { display: flex; gap: 6px; margin-right: 8px; } + .win .titlebar .dot { width: 13px; height: 13px; border-radius: 50%; border: 1px solid rgba(0,0,0,0.35); cursor: pointer; box-shadow: inset 0 1px 0 rgba(255,255,255,0.7); } + .win .titlebar .dot.r { background: radial-gradient(circle at 35% 30%, oklch(85% 0.18 30), oklch(55% 0.18 30)); } + .win .titlebar .dot.y { background: radial-gradient(circle at 35% 30%, oklch(95% 0.15 95), oklch(70% 0.18 80)); } + .win .titlebar .dot.g { background: radial-gradient(circle at 35% 30%, oklch(90% 0.18 145), oklch(60% 0.18 150)); } + .win .body { padding: 16px; font-size: 13px; line-height: 1.55; color: oklch(22% 0.04 240); border-radius: 0 0 18px 18px; } + + .taskbar { + position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); + height: 56px; padding: 0 12px; display: flex; align-items: center; gap: 10px; + border-radius: 28px; + background: linear-gradient(to bottom, rgba(255,255,255,0.55), rgba(180,210,240,0.45)); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255,255,255,0.85); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), 0 12px 36px rgba(40,80,140,0.3); + z-index: 200; + } + .taskbar .start { + height: 40px; padding: 0 18px 0 14px; display: inline-flex; align-items: center; gap: 8px; + border-radius: 20px; + background: var(--start-btn); + color: white; text-shadow: 0 1px 2px rgba(0,0,0,0.4); font-weight: 700; font-size: 13px; + border: 1px solid var(--start-border); cursor: pointer; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.85), 0 3px 10px rgba(180,90,40,0.3); + } + .taskbar .sep { width: 1px; height: 32px; background: linear-gradient(to bottom, transparent, rgba(60,100,160,0.4), transparent); } + .tray { display: inline-flex; align-items: center; gap: 8px; padding: 0 12px; font-size: 12px; color: oklch(25% 0.05 240); } + .clock { font-family: "Segoe UI", Tahoma; font-weight: 600; } + + /* SERVER ROW */ + .srv-row { + display: flex; align-items: center; gap: 10px; padding: 7px 0; + border-bottom: 1px dotted oklch(72% 0.05 220); font-size: 12px; + } + .srv-row:last-child { border-bottom: 0; } + .srv-led { + width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.7); + animation: led-pulse 2.2s ease-in-out infinite; + } + .srv-led.ok { background: radial-gradient(circle at 30% 30%, oklch(96% 0.18 145), oklch(60% 0.18 150)); box-shadow: inset 0 1px 0 rgba(255,255,255,0.7), 0 0 8px oklch(70% 0.18 145 / 0.7); } + .srv-led.warn { background: radial-gradient(circle at 30% 30%, oklch(95% 0.16 85), oklch(70% 0.18 75)); box-shadow: inset 0 1px 0 rgba(255,255,255,0.7), 0 0 8px oklch(70% 0.18 80 / 0.6); } + @keyframes led-pulse { 50% { opacity: 0.55; } } + .srv-host { font-family: 'Courier New', monospace; flex: 1; color: oklch(25% 0.05 230); } + .srv-meta { font-size: 10px; opacity: 0.7; } + + /* FILM DIARY ROW */ + .film-row { + display: flex; gap: 10px; padding: 8px 0; + border-bottom: 1px dotted oklch(72% 0.05 220); + } + .film-row:last-child { border-bottom: 0; } + .film-poster { + width: 38px; height: 56px; border-radius: 4px; flex-shrink: 0; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), 0 2px 6px rgba(40,80,140,0.2); + } + .film-meta { flex: 1; min-width: 0; font-size: 12px; line-height: 1.45; } + .film-title { font-weight: 700; color: oklch(25% 0.06 230); font-size: 13px; } + .film-year { font-weight: 400; opacity: 0.6; font-size: 11px; margin-left: 3px; } + .film-rating { font-size: 11px; margin: 1px 0 2px; } + .film-rating .star { color: oklch(80% 0.04 230); } + .film-rating .star.on { color: oklch(72% 0.16 60); text-shadow: 0 0 4px oklch(80% 0.18 70 / 0.5); } + .film-rating .star.half { background: linear-gradient(90deg, oklch(72% 0.16 60) 50%, oklch(80% 0.04 230) 50%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; } + .film-note { font-size: 11px; opacity: 0.75; font-style: italic; } + + /* ============= FAUX BROWSER ============= */ + .browser { display: flex; flex-direction: column; height: 100%; } + .browser .titlebar { border-bottom: 1px solid rgba(0,0,0,0.18); } + .browser-toolbar { + display: flex; align-items: center; gap: 8px; + padding: 8px 12px; + background: linear-gradient(to bottom, oklch(96% 0.005 220), oklch(86% 0.015 225) 50%, oklch(78% 0.025 230)); + border-bottom: 1px solid oklch(60% 0.04 230); + box-shadow: inset 0 -1px 0 rgba(255,255,255,0.5); + } + .nav-btn { + width: 28px; height: 24px; border-radius: 12px; + display: inline-flex; align-items: center; justify-content: center; + background: linear-gradient(to bottom, oklch(99% 0.005 220), oklch(88% 0.015 225) 50%, oklch(74% 0.03 230)); + border: 1px solid oklch(55% 0.05 230); + color: oklch(35% 0.05 235); font-size: 13px; line-height: 1; + cursor: pointer; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), 0 1px 2px rgba(40,80,140,0.25); + transition: transform 100ms, box-shadow 100ms; + } + .nav-btn:hover { transform: translateY(-0.5px); } + .nav-btn:active { transform: translateY(0.5px); box-shadow: inset 0 1px 3px rgba(40,80,140,0.4); } + .nav-btn[disabled] { opacity: 0.35; cursor: default; transform: none !important; } + .nav-btn.refresh.spinning svg { animation: spin 700ms linear; } + @keyframes spin { to { transform: rotate(360deg); } } + .url-bar { + flex: 1; height: 26px; display: flex; align-items: center; gap: 6px; + padding: 0 10px; + background: linear-gradient(to bottom, oklch(99% 0.003 220), oklch(94% 0.008 220)); + border: 1px solid oklch(60% 0.04 230); + border-radius: 13px; + box-shadow: inset 0 1px 2px rgba(40,80,140,0.18); + font: 12px "IBM Plex Mono", "Courier New", monospace; + color: oklch(28% 0.05 235); + overflow: hidden; min-width: 0; + } + .url-bar .lock { font-size: 10px; color: oklch(58% 0.16 145); flex-shrink: 0; } + .url-bar .url-scheme { opacity: 0.55; } + .url-bar .url-host { color: oklch(30% 0.08 240); font-weight: 600; } + .url-bar .url-path { opacity: 0.85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .url-bar .caret { width: 1px; height: 14px; background: oklch(40% 0.08 240); animation: blink 1s steps(2) infinite; } + @keyframes blink { 50% { opacity: 0; } } + .browser-bookmarks { + display: flex; align-items: center; gap: 2px; + padding: 4px 10px; + background: linear-gradient(to bottom, oklch(94% 0.01 220), oklch(86% 0.02 225)); + border-bottom: 1px solid oklch(62% 0.04 230); + font-size: 11px; + overflow-x: auto; scrollbar-width: none; + } + .browser-bookmarks::-webkit-scrollbar { display: none; } + .bm { + display: inline-flex; align-items: center; gap: 5px; + padding: 3px 8px; border-radius: 8px; + color: oklch(28% 0.06 235); white-space: nowrap; cursor: pointer; + border: 1px solid transparent; + transition: background 120ms, border-color 120ms; + } + .bm:hover { background: rgba(255,255,255,0.6); border-color: rgba(255,255,255,0.95); } + .bm.active { background: linear-gradient(to bottom, rgba(255,255,255,0.7), rgba(200,230,255,0.4)); border-color: rgba(120,170,220,0.5); } + .bm .favicon { width: 12px; height: 12px; border-radius: 3px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.6); } + .bm.home .favicon { background: linear-gradient(135deg, oklch(85% 0.10 220), oklch(55% 0.14 235)); } + .browser-page { + flex: 1; min-height: 0; overflow-y: auto; + background: oklch(98% 0.004 220); + color: oklch(20% 0.03 240); + font: 14px "Georgia", "Times New Roman", serif; + line-height: 1.65; + padding: 0; + position: relative; + } + .browser-page::-webkit-scrollbar { width: 12px; } + .browser-page::-webkit-scrollbar-track { background: linear-gradient(to right, oklch(92% 0.01 220), oklch(96% 0.005 220)); } + .browser-page::-webkit-scrollbar-thumb { background: linear-gradient(to right, oklch(82% 0.03 225), oklch(70% 0.05 230)); border-radius: 6px; border: 2px solid oklch(94% 0.008 220); } + .browser-status { + height: 22px; padding: 0 12px; + display: flex; align-items: center; justify-content: space-between; + background: linear-gradient(to bottom, oklch(90% 0.01 220), oklch(80% 0.02 225)); + border-top: 1px solid oklch(60% 0.04 230); + font: 11px "Segoe UI", Tahoma, sans-serif; + color: oklch(35% 0.05 235); + border-radius: 0 0 18px 18px; + } + .browser-status .progress { + flex: 1; max-width: 80px; height: 8px; margin: 0 8px; + background: oklch(82% 0.02 225); border-radius: 4px; + border: 1px solid oklch(65% 0.04 230); + overflow: hidden; box-shadow: inset 0 1px 2px rgba(40,80,140,0.15); + } + .browser-status .progress-bar { + height: 100%; width: 100%; + background: linear-gradient(to bottom, oklch(82% 0.13 220), oklch(58% 0.14 235)); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.65); + } + /* index page */ + .idx-hero { + padding: 32px 40px 24px; + background: + radial-gradient(60% 80% at 100% 0%, oklch(88% 0.10 215 / 0.5) 0%, transparent 60%), + linear-gradient(to bottom, oklch(94% 0.03 220), oklch(98% 0.004 220)); + border-bottom: 1px solid oklch(88% 0.02 220); + } + .idx-eyebrow { font: 500 10px "IBM Plex Mono", monospace; letter-spacing: 2px; text-transform: uppercase; color: oklch(45% 0.10 230); margin-bottom: 8px; } + .idx-title { font: 700 38px/1.05 "Georgia", "Times New Roman", serif; color: oklch(22% 0.06 235); letter-spacing: -1px; margin: 0 0 10px; } + .idx-title em { font-style: italic; font-weight: 400; color: oklch(45% 0.12 220); } + .idx-sub { font: italic 14px/1.5 "Georgia", serif; color: oklch(40% 0.04 235); max-width: 440px; margin: 0; } + .idx-list { padding: 16px 40px 40px; } + .idx-art { display: grid; grid-template-columns: 60px 1fr auto; gap: 18px; padding: 18px 0; border-bottom: 1px solid oklch(90% 0.015 220); cursor: pointer; transition: padding 120ms; } + .idx-art:last-child { border-bottom: 0; } + .idx-art:hover { padding-left: 6px; } + .idx-art:hover .idx-art-title { color: oklch(40% 0.16 230); text-decoration: underline; text-decoration-color: oklch(70% 0.13 220 / 0.5); text-underline-offset: 3px; } + .idx-art-num { font: 600 28px/1 "IBM Plex Mono", monospace; color: oklch(80% 0.04 225); padding-top: 4px; } + .idx-art-title { font: 700 18px/1.25 "Georgia", serif; color: oklch(22% 0.06 235); margin: 0 0 4px; letter-spacing: -0.2px; } + .idx-art-excerpt { font: 13px/1.55 "Georgia", serif; color: oklch(40% 0.04 235); margin: 4px 0 0; } + .idx-art-meta { font: 11px "IBM Plex Mono", monospace; color: oklch(55% 0.06 230); text-align: right; padding-top: 4px; line-height: 1.6; white-space: nowrap; } + .idx-art-tag { display: inline-block; padding: 1px 6px; border-radius: 3px; background: oklch(92% 0.04 220); color: oklch(40% 0.10 230); font-size: 10px; text-transform: lowercase; letter-spacing: 0.5px; } + /* article page */ + .art-page { padding: 36px 56px 60px; max-width: 620px; margin: 0 auto; } + .art-back { display: inline-flex; align-items: center; gap: 6px; font: 500 11px "IBM Plex Mono", monospace; color: oklch(45% 0.10 230); text-decoration: none; margin-bottom: 24px; cursor: pointer; letter-spacing: 1px; text-transform: uppercase; } + .art-back:hover { color: oklch(35% 0.16 230); } + .art-eyebrow { font: 500 10px "IBM Plex Mono", monospace; letter-spacing: 2px; text-transform: uppercase; color: oklch(55% 0.10 220); margin-bottom: 12px; } + .art-title { font: 700 32px/1.15 "Georgia", "Times New Roman", serif; color: oklch(20% 0.06 235); letter-spacing: -0.6px; margin: 0 0 14px; } + .art-byline { font: italic 13px/1.5 "Georgia", serif; color: oklch(48% 0.04 235); margin: 0 0 32px; padding-bottom: 16px; border-bottom: 1px solid oklch(88% 0.015 220); } + .art-body { font-size: 15px; line-height: 1.75; color: oklch(22% 0.03 240); } + .art-body p { margin: 0 0 18px; text-wrap: pretty; } + .art-body p:first-of-type::first-letter { font-size: 56px; font-weight: 700; float: left; line-height: 0.9; padding: 4px 8px 0 0; color: oklch(40% 0.14 220); font-family: "Georgia", serif; } + .art-body em { color: oklch(35% 0.10 230); } + .art-body a, .art-body .ilink { color: oklch(40% 0.16 230); text-decoration: underline; text-decoration-color: oklch(70% 0.13 220 / 0.4); text-underline-offset: 2px; cursor: pointer; } + .art-body h2 { font: 700 18px "Georgia", serif; color: oklch(22% 0.06 235); margin: 32px 0 12px; letter-spacing: -0.2px; } + .art-body blockquote { margin: 24px 0; padding: 0 0 0 18px; border-left: 3px solid oklch(78% 0.10 220); font-style: italic; color: oklch(38% 0.06 230); } + .art-body code { font: 13px "IBM Plex Mono", monospace; background: oklch(94% 0.01 220); padding: 1px 5px; border-radius: 3px; color: oklch(35% 0.10 230); } + .art-foot { margin-top: 40px; padding-top: 20px; border-top: 1px solid oklch(88% 0.015 220); font: 12px "IBM Plex Mono", monospace; color: oklch(55% 0.06 230); display: flex; justify-content: space-between; align-items: center; } + .art-foot .more { color: oklch(40% 0.16 230); cursor: pointer; } + + /* music toggle button — on-state gradient (off-state is set inline by Aero.musicToggleHTML) */ + .mt-btn.on { background: radial-gradient(circle at 30% 25%, white, oklch(75% 0.14 55) 60%, oklch(55% 0.15 35)) !important; } + + /* film row trailing date */ + .film-when { opacity: 0.6; margin-left: 8px; } + /* films stats numerals */ + #films-stats strong { color: oklch(28% 0.08 230); font-size: 13px; } + + /* podcast episode rows */ + .pod-ep { display: flex; justify-content: space-between; gap: 8px; } + .pod-ep a { color: inherit; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .pod-dur { opacity: 0.6; flex-shrink: 0; } + + /* "now playing" recent list */ + .np-recent-label { margin-top: 14px; font-size: 11px; opacity: 0.75; text-transform: uppercase; letter-spacing: 1px; } + #np-recent { margin-top: 6px; display: flex; flex-direction: column; gap: 6px; font-size: 12px; } + .np-row { display: flex; justify-content: space-between; } + .np-ago { opacity: 0.6; } + + /* generic empty/loading message used in fetched lists */ + .empty-msg { opacity: 0.5; font-style: italic; } |
