@tailwind base; @tailwind components; @tailwind utilities; :root { --font-scale: 1.06; } /* Make native controls (date picker, scrollbars) follow the theme. */ html[data-theme="dark"] { color-scheme: dark; } html[data-theme="light"] { color-scheme: light; } html { font-size: calc(16px * var(--font-scale)); background: var(--bg); } body { margin: 0; color: var(--fg); /* Ambient backdrop so translucent "glass" surfaces have soft color to refract. Kept subtle but a touch richer (three soft pools, incl. a bottom glow) now that the nav, header and dialogs are all frosted glass and refract it. */ background: radial-gradient(1100px 620px at 10% -10%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 60%), radial-gradient(1000px 720px at 115% 10%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 55%), radial-gradient(900px 640px at 50% 118%, color-mix(in srgb, var(--accent) 11%, transparent), transparent 60%), var(--bg); background-attachment: fixed; } /* ===== Liquid-glass surface system (theme-aware, GPU-light) ===== */ .glass { /* Frosted overlay surface: translucent enough that the blurred backdrop shows through (the glassy look), opaque enough that the background isn't distracting. The strong blur turns whatever is behind into soft colour, not a sharp image. */ background: color-mix(in srgb, var(--surface) 78%, transparent); backdrop-filter: blur(30px) saturate(1.8); -webkit-backdrop-filter: blur(30px) saturate(1.8); border: 1px solid color-mix(in srgb, var(--border) 78%, transparent); box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 16%, transparent), 0 18px 44px -16px rgba(0, 0, 0, 0.6); } .glass-card { /* No backdrop-filter here: cards render in bulk (feed grid) over a solid background where blur adds almost nothing visually but is GPU-expensive and triggers reflow. Translucency + border + depth keep the look; blur is reserved for .glass overlays. */ background: color-mix(in srgb, var(--card) 84%, transparent); border: 1px solid color-mix(in srgb, var(--border) 65%, transparent); box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent), 0 8px 22px -14px rgba(0, 0, 0, 0.45); } .glass-menu { /* Floating menus/popovers hover over undimmed content (no backdrop scrim like dialogs), so they must be near-opaque to stay readable — only a hint of translucency + the blur. */ background: color-mix(in srgb, var(--surface) 92%, transparent); backdrop-filter: blur(30px) saturate(1.8); -webkit-backdrop-filter: blur(30px) saturate(1.8); border: 1px solid color-mix(in srgb, var(--border) 80%, transparent); box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 14%, transparent), 0 18px 44px -16px rgba(0, 0, 0, 0.6); } .glass-hover:hover { border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent), 0 14px 30px -14px rgba(0, 0, 0, 0.5); } /* Dark mode: the ambient accent pools are faint over a near-black bg, so the docked frosted chrome (nav/header) barely reads — there's no content behind it to refract, unlike dialogs which sit over the feed. Strengthen the pools and let a touch more bleed through the glass. (The full "videos behind glass everywhere" effect is Phase 2 / end-of-project polish.) */ html[data-theme="dark"] body { background: radial-gradient(1100px 620px at 10% -10%, color-mix(in srgb, var(--accent) 34%, transparent), transparent 60%), radial-gradient(1000px 720px at 115% 10%, color-mix(in srgb, var(--accent) 24%, transparent), transparent 55%), radial-gradient(900px 640px at 50% 118%, color-mix(in srgb, var(--accent) 18%, transparent), transparent 60%), var(--bg); background-attachment: fixed; } /* Dark glass reads faint because the blurred backdrop is itself dark; lift its brightness so the frosted sheen shows even over dark UI (over colourful content it just looks richer). */ html[data-theme="dark"] .glass, html[data-theme="dark"] .glass-menu { backdrop-filter: blur(30px) saturate(1.7) brightness(1.4); -webkit-backdrop-filter: blur(30px) saturate(1.7) brightness(1.4); } /* Performance mode (Settings → Appearance) drops the expensive blur + soft shadows. */ html[data-perf="1"] .glass, html[data-perf="1"] .glass-menu, html[data-perf="1"] .glass-card { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--surface); box-shadow: 0 2px 8px -4px rgba(0, 0, 0, 0.4); } html[data-perf="1"] body { background: var(--bg); } /* Skip layout/paint for off-screen feed cards so long lists stay smooth while scrolling. contain-intrinsic-size reserves an approximate box so the scrollbar stays stable; `auto` lets the browser remember each card's real size after it has rendered once. */ .cv-card { content-visibility: auto; contain-intrinsic-size: auto 320px; } .cv-row { content-visibility: auto; contain-intrinsic-size: auto 96px; } /* ===== Motion ===== */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes overlayIn { from { opacity: 0; } to { opacity: 1; } } @keyframes overlayOut { from { opacity: 1; } to { opacity: 0; } } @keyframes panelIn { from { transform: translateX(100%); } to { transform: translateX(0); } } @keyframes panelOut { from { transform: translateX(0); } to { transform: translateX(100%); } } @keyframes popIn { from { opacity: 0; transform: translateY(-6px) scale(0.97); } to { opacity: 1; transform: none; } } /* ===== Color schemes (accent + neutrals), each with dark + light ===== */ /* Midnight — deep navy/slate with blue accent (default) */ html[data-scheme="midnight"][data-theme="dark"] { --bg: #0b1020; --surface: #121a2e; --card: #161f38; --border: #243049; --fg: #e6e9f0; --muted: #97a3c0; --accent: #6d8cff; --accent-fg: #0b1020; } html[data-scheme="midnight"][data-theme="light"] { --bg: #f4f6fc; --surface: #ffffff; --card: #ffffff; --border: #dde3f0; --fg: #1a2238; --muted: #5b6685; --accent: #3b5bdb; --accent-fg: #ffffff; } /* Forest — dark slate with teal/green accent */ html[data-scheme="forest"][data-theme="dark"] { --bg: #0a1512; --surface: #0f1f1a; --card: #12241e; --border: #1f3a30; --fg: #e6f0ec; --muted: #90b1a4; --accent: #2dd4bf; --accent-fg: #04110d; } html[data-scheme="forest"][data-theme="light"] { --bg: #f1f7f4; --surface: #ffffff; --card: #ffffff; --border: #d6e7e0; --fg: #102a22; --muted: #4d6b60; --accent: #0d9488; --accent-fg: #ffffff; } /* Slate — neutral grey with warm orange accent (muted in dark) */ html[data-scheme="slate"][data-theme="dark"] { --bg: #15171c; --surface: #1b1e25; --card: #1f232b; --border: #2c313b; --fg: #e7e9ee; --muted: #9aa1ad; --accent: #e8913c; --accent-fg: #1a1206; } html[data-scheme="slate"][data-theme="light"] { --bg: #f6f7f9; --surface: #ffffff; --card: #ffffff; --border: #e3e6eb; --fg: #1c1f26; --muted: #5d636e; --accent: #d97706; --accent-fg: #ffffff; } /* YouTube — near-black with red accent */ html[data-scheme="youtube"][data-theme="dark"] { --bg: #0f0f0f; --surface: #181818; --card: #1f1f1f; --border: #303030; --fg: #f1f1f1; --muted: #aaaaaa; --accent: #ff3b46; --accent-fg: #ffffff; } html[data-scheme="youtube"][data-theme="light"] { --bg: #ffffff; --surface: #f9f9f9; --card: #ffffff; --border: #e5e5e5; --fg: #0f0f0f; --muted: #606060; --accent: #ff0033; --accent-fg: #ffffff; } /* Toast auto-dismiss countdown bar (shrinks left-to-right to zero) */ @keyframes toastbar { from { transform: scaleX(1); } to { transform: scaleX(0); } } /* Thin, theme-aware scrollbars */ * { scrollbar-color: var(--border) transparent; } *::-webkit-scrollbar { width: 10px; height: 10px; } *::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; }