From a7ef2c9d7f459145fac5b8a78679aa71b292397c Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Tue, 26 May 2026 20:11:26 -0700 Subject: browser+resize: implement proper faux browser + resizable windows per design handoff Browser window (w-browser, Internet icon): - Full aqua browser chrome: toolbar with back/fwd/reload/home SVG nav buttons, URL bar (lock + scheme + host + path + blinking caret), bookmark chips with colored 12x12 favicon squares, scrollable page surface, status bar with animated progress bar - History stack (back/forward state, disable at ends) - Delegated click handler via data-go attributes for in-page navigation - Refresh button spins 700ms via CSS animation - Address bar + title bar update on every navigation - ARTICLES array with 4 entries (self-hosting, jazz, cooking, film) with drop-cap, Georgia body, IBM Plex Mono metadata, blockquotes, inline ilinks - Chrome theme: brushed mercury toolbar, dark navy article surface with iridescent radial hotspots, Audiowide titles with chromeShimmer drop-cap, Michroma UI labels, iridescent progress bar, custom scrollbar Resizable windows: - makeResizable() in aero.js: appends .rs-e (right edge), .rs-s (bottom edge), .rs-se (SE grip) handles; tracks mousedown/move/up; enforces minW/minH - .win.resized flex-column flip: body fills remaining height and scrolls - Aero grip (3-stripe diagonal, blue); Chrome grip (iridescent purple/cyan/pink) - Body cursor forced via body.rs-cursor-* classes during drag CSS in aero.css: chrome overrides for resize handle + full browser window theme CSS in index.html: resize handle rules, full browser/article reading styles Co-Authored-By: Claude Sonnet 4.6 --- index.html | 506 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 406 insertions(+), 100 deletions(-) (limited to 'index.html') diff --git a/index.html b/index.html index e2ee661..6e2996d 100755 --- a/index.html +++ b/index.html @@ -41,6 +41,37 @@ .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; @@ -114,68 +145,139 @@ .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; } - /* ===== BROWSER / ARTICLE READER ===== */ + /* ============= 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: 6px 12px; - background: rgba(255,255,255,0.22); - border-bottom: 1px solid rgba(200,220,240,0.45); - } - .browser-url-bar { - flex: 1; height: 22px; padding: 0 10px; - border-radius: 11px; - background: rgba(255,255,255,0.62); border: 1px solid rgba(180,200,220,0.45); - font: 400 11px 'IBM Plex Mono', monospace; color: oklch(30% 0.05 230); - display: flex; align-items: center; overflow: hidden; - white-space: nowrap; text-overflow: ellipsis; + 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; gap: 5px; padding: 5px 12px; - background: rgba(255,255,255,0.15); - border-bottom: 1px solid rgba(200,220,240,0.35); - flex-wrap: wrap; - } - .browser-bm { - height: 20px; padding: 0 10px; - border-radius: 10px; border: 1px solid rgba(180,200,220,0.4); - background: rgba(255,255,255,0.55); - font: 600 10px 'Plus Jakarta Sans', sans-serif; color: oklch(30% 0.08 230); - cursor: pointer; letter-spacing: 0.3px; - transition: background 150ms, border-color 150ms; - } - .browser-bm:hover { background: rgba(255,255,255,0.88); } - .browser-bm.active { background: rgba(255,255,255,0.92); border-color: oklch(55% 0.12 220); color: oklch(22% 0.10 230); } - .browser-body { - overflow-y: auto; max-height: 440px; - padding: 16px 20px; border-radius: 0 0 18px 18px; - } - /* article typography inside the browser */ - .browser-body h1 { font-size: 17px; font-weight: 700; margin: 0 0 10px; color: oklch(24% 0.08 230); } - .browser-body h2 { font-size: 14px; font-weight: 700; margin: 16px 0 6px; color: oklch(27% 0.08 230); border-bottom: 1px solid rgba(120,160,200,0.3); padding-bottom: 4px; } - .browser-body h3 { font-size: 13px; font-weight: 600; margin: 12px 0 5px; color: oklch(29% 0.07 230); } - .browser-body h4 { font-size: 12px; font-weight: 600; margin: 10px 0 4px; color: oklch(31% 0.06 230); font-style: italic; } - .browser-body p { margin: 0 0 9px; font-size: 12px; line-height: 1.65; color: oklch(22% 0.04 240); } - .browser-body ul, .browser-body ol { padding-left: 18px; margin: 0 0 9px; } - .browser-body li { font-size: 12px; line-height: 1.7; color: oklch(22% 0.04 240); } - .browser-body img { max-width: 160px; border-radius: 8px; margin: 6px 0; display: block; box-shadow: 0 2px 8px rgba(40,80,140,0.15); } - .browser-body figure { margin: 8px 0; } - .browser-body figcaption { font-size: 10px; opacity: 0.65; margin-top: 3px; } - .browser-body a { color: oklch(42% 0.16 255); text-decoration: none; } - .browser-body a:hover { text-decoration: underline; } - .browser-body pre, .browser-body .body > p { font: 12px 'IBM Plex Mono', monospace; line-height: 1.65; white-space: pre-wrap; color: oklch(22% 0.04 240); } - .browser-body center { text-align: center; } - /* chrome theme overrides for browser */ - body[data-theme="chrome"] .browser-url-bar { background: rgba(195,202,215,0.5); border-color: oklch(50% 0.04 250); color: oklch(14% 0.03 250); } - body[data-theme="chrome"] .browser-bookmarks { background: rgba(195,202,215,0.15); border-bottom-color: oklch(60% 0.03 250); } - body[data-theme="chrome"] .browser-bm { font-family: 'Michroma', sans-serif; font-size: 8px; text-transform: uppercase; letter-spacing: 1px; border-color: oklch(55% 0.04 250); background: linear-gradient(to bottom, oklch(92% 0.01 240), oklch(78% 0.02 240)); color: oklch(18% 0.04 250); } - body[data-theme="chrome"] .browser-bm:hover { background: linear-gradient(to bottom, oklch(97% 0.01 240), oklch(86% 0.02 240)); } - body[data-theme="chrome"] .browser-bm.active { background: linear-gradient(to bottom, oklch(99% 0.01 240), oklch(90% 0.02 240)); border-color: oklch(40% 0.10 280); } - body[data-theme="chrome"] .browser-body h1, - body[data-theme="chrome"] .browser-body h2, - body[data-theme="chrome"] .browser-body h3, - body[data-theme="chrome"] .browser-body h4 { font-family: 'Michroma', sans-serif; text-transform: uppercase; letter-spacing: 0.5px; } - body[data-theme="chrome"] .browser-body p, - body[data-theme="chrome"] .browser-body li { font-family: 'Space Grotesk', sans-serif; } + 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; } @@ -193,8 +295,8 @@
🖥
My Servers
🎙
REEL MOUTH
🎞
Films
+
🌐
Internet
Contact
-
🌐
Articles
@@ -376,19 +478,50 @@ - -