v3: modernized smooth theme — surface ladder, hairline borders, soft tabs, calmer accents, focus ring, AA contrast

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
khannurien
2026-09-19 19:25:53 +00:00
parent 21fb0c6e16
commit 971cc4988e
4 changed files with 198 additions and 130 deletions

View File

@@ -87,6 +87,20 @@
padding-left: 1.2em; padding-left: 1.2em;
} }
/* ── Panels ──
Large surface blocks that have no border of their own. Themes that want
them outlined set --panel-ring (an inset shadow, so blocks that sit flush
against each other keep their spacing). */
.dump-post-header,
.dump-rich-content,
.form-page-header,
.dump-edit-preview,
.form-page .form,
.playlist-detail-header,
.comment-node-inner {
box-shadow: var(--panel-ring), var(--card-shadow);
}
/* ── Dump detail page ── */ /* ── Dump detail page ── */
.dump-detail { .dump-detail {
display: flex; display: flex;
@@ -182,9 +196,9 @@
.profile-email-input, .profile-email-input,
.playlist-edit-input, .playlist-edit-input,
.playlist-edit-textarea { .playlist-edit-textarea {
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
background: var(--color-bg); background: var(--color-surface-sunken);
color: var(--color-text); color: var(--color-text);
font-family: inherit; font-family: inherit;
outline: none; outline: none;
@@ -253,7 +267,7 @@
display: inline-block; display: inline-block;
word-break: break-all; word-break: break-all;
padding: 1rem; padding: 1rem;
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
@@ -338,8 +352,8 @@
box-sizing: border-box; box-sizing: border-box;
padding: 0.65rem 1rem; padding: 0.65rem 1rem;
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
background-color: var(--color-bg); background-color: var(--color-surface-sunken);
color: var(--color-text); color: var(--color-text);
font-size: var(--text-base); font-size: var(--text-base);
font-family: var(--font-body); font-family: var(--font-body);
@@ -376,11 +390,7 @@
.form input:focus, .form input:focus,
.form textarea:focus { .form textarea:focus {
border-color: var(--color-accent); border-color: var(--color-accent);
background-color: color-mix( background-color: var(--input-focus-bg);
in srgb,
var(--color-accent) 4%,
var(--color-bg) 96%
);
box-shadow: 0 0 0 3px box-shadow: 0 0 0 3px
color-mix(in srgb, var(--color-accent) 18%, transparent); color-mix(in srgb, var(--color-accent) 18%, transparent);
} }
@@ -900,7 +910,7 @@
var(--color-accent) 8%, var(--color-accent) 8%,
var(--color-surface) 92% var(--color-surface) 92%
); );
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: 0 0 var(--radius-xl) var(--radius-xl); border-radius: 0 0 var(--radius-xl) var(--radius-xl);
} }
@@ -920,7 +930,7 @@
width: 100%; width: 100%;
border-radius: 0 0 var(--radius-xl) var(--radius-xl); border-radius: 0 0 var(--radius-xl) var(--radius-xl);
overflow: hidden; overflow: hidden;
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
position: relative; position: relative;
} }
@@ -990,7 +1000,7 @@
var(--color-surface) 92% var(--color-surface) 92%
); );
border-radius: 0 0 var(--radius-xl) var(--radius-xl); border-radius: 0 0 var(--radius-xl) var(--radius-xl);
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
min-width: 0; min-width: 0;
@@ -1175,7 +1185,7 @@
height: 80vh; height: 80vh;
min-height: 600px; min-height: 600px;
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
display: block; display: block;
} }
@@ -1205,7 +1215,7 @@
.rich-content-card { .rich-content-card {
display: flex; display: flex;
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
overflow: hidden; overflow: hidden;
transition: border-color var(--dur-slow); transition: border-color var(--dur-slow);
@@ -1263,7 +1273,7 @@
max-width: 860px; max-width: 860px;
z-index: var(--z-modal); z-index: var(--z-modal);
background: var(--color-surface); background: var(--color-surface);
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
box-shadow: var(--shadow-3); box-shadow: var(--shadow-3);
animation: player-enter 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) both; animation: player-enter 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) both;
@@ -1787,7 +1797,7 @@ body.has-player .chat-fab {
align-items: center; align-items: center;
gap: 0.3rem; gap: 0.3rem;
padding: 0.25rem 0.6rem; padding: 0.25rem 0.6rem;
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-md); border-radius: var(--radius-md);
background: transparent; background: transparent;
color: var(--color-text); color: var(--color-text);
@@ -1985,7 +1995,7 @@ body.has-player .chat-fab {
.profile-tabs-scroller { .profile-tabs-scroller {
margin-top: 0.5rem; margin-top: 0.5rem;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
border-bottom: 2px solid var(--color-border); border-bottom: var(--border-width) solid var(--color-border);
} }
.profile-columns { .profile-columns {
@@ -2112,7 +2122,7 @@ body.has-player .chat-fab {
.profile-section > h2, .profile-section > h2,
.profile-section-header { .profile-section-header {
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
border-bottom: 2px solid var(--color-border); border-bottom: var(--border-width) solid var(--color-border);
padding-bottom: 0.4rem; padding-bottom: 0.4rem;
} }
@@ -2565,8 +2575,8 @@ body.has-player .chat-fab {
gap: 1rem; gap: 1rem;
padding: 0 1.25rem; padding: 0 1.25rem;
min-height: 3.75rem; min-height: 3.75rem;
background: var(--color-surface); background: var(--header-bg);
border-bottom: 2px solid var(--color-border); border-bottom: var(--border-width) solid var(--color-border);
} }
@media (min-width: 860px) { @media (min-width: 860px) {
@@ -2614,8 +2624,8 @@ body.has-player .chat-fab {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
background: var(--color-surface); background: var(--header-bg);
border-bottom: 2px solid var(--color-border); border-bottom: var(--border-width) solid var(--color-border);
} }
.header-search-below .search-bar { .header-search-below .search-bar {
@@ -2792,7 +2802,7 @@ body.has-player .chat-fab {
right: 0; right: 0;
min-width: 150px; min-width: 150px;
background: var(--color-surface); background: var(--color-surface);
border: 2px solid var(--color-border-subtle); border: var(--border-width) solid var(--color-border-subtle);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
padding: 0.35rem; padding: 0.35rem;
display: flex; display: flex;
@@ -2823,7 +2833,7 @@ body.has-player .chat-fab {
min-width: 180px; min-width: 180px;
overflow-y: auto; overflow-y: auto;
background: var(--color-surface); background: var(--color-surface);
border: 2px solid var(--color-border-subtle); border: var(--border-width) solid var(--color-border-subtle);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
padding: 0.35rem; padding: 0.35rem;
display: flex; display: flex;
@@ -2882,7 +2892,7 @@ body.has-player .chat-fab {
flex-direction: column; flex-direction: column;
gap: 1.25rem; gap: 1.25rem;
background: var(--color-surface); background: var(--color-surface);
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
padding: 2rem; padding: 2rem;
} }
@@ -3089,14 +3099,12 @@ body.has-player .chat-fab {
background: var(--color-accent); background: var(--color-accent);
color: var(--color-on-accent); color: var(--color-on-accent);
border: none; border: none;
box-shadow: 0 2px 8px box-shadow: var(--btn-primary-shadow);
color-mix(in srgb, var(--color-accent) 40%, transparent);
} }
.btn-primary:hover { .btn-primary:hover {
background: var(--color-accent-hover); background: var(--color-accent-hover);
box-shadow: 0 4px 14px box-shadow: var(--btn-primary-shadow-hover);
color-mix(in srgb, var(--color-accent) 50%, transparent);
transform: translateY(-1px); transform: translateY(-1px);
} }
@@ -3130,6 +3138,7 @@ body.has-player .chat-fab {
.btn-danger:hover { .btn-danger:hover {
background: var(--color-danger-hover); background: var(--color-danger-hover);
color: var(--color-on-danger);
} }
/* ── Ghost button — chromeless icon/toggle action (e.g. global player) ── */ /* ── Ghost button — chromeless icon/toggle action (e.g. global player) ── */
@@ -3284,23 +3293,27 @@ body.has-player .chat-fab {
.feed-sort-btn { .feed-sort-btn {
padding: 0.25rem 0.8rem; padding: 0.25rem 0.8rem;
border-radius: var(--radius-md); border-radius: var(--radius-md);
border: 2px solid var(--color-border); border: var(--border-width) solid var(--tab-border);
background: transparent; background: transparent;
color: var(--color-text-secondary); color: var(--color-text-secondary);
cursor: pointer; cursor: pointer;
font-size: var(--text-xs); font-size: var(--text-xs);
font-weight: 600; font-weight: 600;
letter-spacing: 0.04em; letter-spacing: var(--tab-tracking);
text-transform: uppercase; text-transform: var(--tab-text-transform);
transition: border-color var(--dur-base), background var(--dur-base), color var(--dur-base); transition: border-color var(--dur-base), background var(--dur-base), color var(--dur-base);
white-space: nowrap; white-space: nowrap;
flex-shrink: 0; flex-shrink: 0;
} }
.feed-sort-btn:hover:not(.active) {
color: var(--color-text);
}
.feed-sort-btn.active { .feed-sort-btn.active {
border-color: var(--color-accent); border-color: var(--tab-active-border, var(--color-accent));
background: var(--color-accent); background: var(--tab-active-bg);
color: var(--color-on-accent); color: var(--tab-active-fg);
} }
/* ── Dump feed ── */ /* ── Dump feed ── */
@@ -3343,15 +3356,16 @@ body.has-player .chat-fab {
/* ── Shared card skin (dump-card + playlist-card) ── */ /* ── Shared card skin (dump-card + playlist-card) ── */
.dump-card, .dump-card,
.playlist-card { .playlist-card {
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
background: var(--color-surface); background: var(--color-surface);
box-shadow: var(--card-shadow);
min-width: 0; min-width: 0;
} }
.dump-card:hover, .dump-card:hover,
.playlist-card:hover { .playlist-card:hover {
border-color: var(--color-accent); border-color: var(--card-hover-border);
} }
/* Card-specific layout */ /* Card-specific layout */
@@ -3640,7 +3654,7 @@ body.has-player .chat-fab {
.playlist-card-description { .playlist-card-description {
margin: 0; margin: 0;
font-size: var(--text-sm); font-size: var(--text-sm);
opacity: 0.65; color: var(--color-text-secondary);
word-break: break-word; word-break: break-word;
line-height: 1.4; line-height: 1.4;
} }
@@ -3659,7 +3673,7 @@ body.has-player .chat-fab {
.dump-card-date, .dump-card-date,
.playlist-card-meta { .playlist-card-meta {
font-size: var(--text-xs); font-size: var(--text-xs);
opacity: 0.45; color: var(--color-text-muted);
margin-top: 0.2rem; margin-top: 0.2rem;
} }
@@ -3781,6 +3795,7 @@ body.has-player .chat-fab {
position: fixed; position: fixed;
inset: 0; inset: 0;
background: var(--color-overlay); background: var(--color-overlay);
backdrop-filter: var(--overlay-filter);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -3792,6 +3807,7 @@ body.has-player .chat-fab {
.modal-card, .modal-card,
.confirm-modal { .confirm-modal {
background: var(--color-surface); background: var(--color-surface);
border: var(--border-width) solid var(--modal-border);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
box-shadow: var(--shadow-3); box-shadow: var(--shadow-3);
width: 100%; width: 100%;
@@ -4588,7 +4604,7 @@ body.has-player .chat-fab {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0.25rem 0.6rem; padding: 0.25rem 0.6rem;
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
background: none; background: none;
cursor: pointer; cursor: pointer;
@@ -4643,7 +4659,7 @@ body.has-player .chat-fab {
.related-section { .related-section {
margin-top: 2.5rem; margin-top: 2.5rem;
padding-top: 1.75rem; padding-top: 1.75rem;
border-top: 2px solid var(--color-border); border-top: var(--border-width) solid var(--color-border);
} }
.comment-section-title, .comment-section-title,
@@ -5239,7 +5255,7 @@ body.has-player .chat-fab {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border: 2px solid var(--color-border); border: var(--border-width) solid var(--color-border);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
background: var(--color-surface); background: var(--color-surface);
overflow: hidden; overflow: hidden;
@@ -5968,7 +5984,7 @@ body.has-player .chat-fab {
flex: 1; flex: 1;
padding: 0.3rem 0.7rem; padding: 0.3rem 0.7rem;
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
border: 2px solid var(--color-border-subtle); border: var(--border-width) solid var(--color-border-subtle);
background: var(--color-bg); background: var(--color-bg);
color: var(--color-text); color: var(--color-text);
font-size: var(--text-sm); font-size: var(--text-sm);
@@ -6010,7 +6026,7 @@ body.has-player .chat-fab {
.search-bar-btn { .search-bar-btn {
padding: 0.3rem 0.55rem; padding: 0.3rem 0.55rem;
background: transparent; background: transparent;
border: 2px solid var(--color-border-subtle); border: var(--border-width) solid var(--color-border-subtle);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
cursor: pointer; cursor: pointer;
font-size: var(--text-sm); font-size: var(--text-sm);
@@ -6064,7 +6080,7 @@ body.has-player .chat-fab {
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
background: var(--color-surface); background: var(--color-surface);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
border: 2px solid var(--color-border-subtle); border: var(--border-width) solid var(--color-border-subtle);
text-decoration: none; text-decoration: none;
color: var(--color-text); color: var(--color-text);
transition: border-color var(--dur-base); transition: border-color var(--dur-base);
@@ -6202,7 +6218,7 @@ body.has-player .chat-fab {
flex-direction: column; flex-direction: column;
gap: 0.15rem; gap: 0.15rem;
background: var(--color-surface); background: var(--color-surface);
border: 2px solid var(--color-border-subtle); border: var(--border-width) solid var(--color-border-subtle);
border-radius: var(--radius-xl); border-radius: var(--radius-xl);
box-shadow: var(--shadow-2); box-shadow: var(--shadow-2);
} }

View File

@@ -11,6 +11,8 @@ body {
scrollbar-gutter: stable; scrollbar-gutter: stable;
background-color: var(--color-bg); background-color: var(--color-bg);
color: var(--color-text); color: var(--color-text);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} }
#root { #root {
@@ -37,19 +39,29 @@ h1 {
button { button {
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
border: 1px solid var(--color-border); border: var(--border-width) solid var(--color-border);
padding: 0.6em 1.2em; padding: 0.6em 1.2em;
font-size: 1em; font-size: 1em;
font-weight: 500; font-weight: 500;
font-family: inherit; font-family: inherit;
color: inherit;
background-color: var(--color-surface); background-color: var(--color-surface);
cursor: pointer; cursor: pointer;
transition: border-color 0.25s, background-color var(--dur-slow); transition:
border-color var(--dur-base),
background-color var(--dur-base);
} }
button:hover { button:hover {
border-color: var(--color-accent); border-color: var(--color-accent);
} }
button:focus,
button:focus-visible { /* One keyboard focus ring for every interactive element. Mouse clicks don't
outline: 4px auto -webkit-focus-ring-color; trigger :focus-visible on buttons, so pointer users never see it. */
:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
::selection {
background: color-mix(in srgb, var(--color-accent) 30%, transparent);
} }

View File

@@ -2,95 +2,101 @@
Smooth theme — clean, modern, Saira typeface Smooth theme — clean, modern, Saira typeface
Dark: Prussian Blue · Deep Teal · Jasmine · Brick Ember · Blood Red Dark: Prussian Blue · Deep Teal · Jasmine · Brick Ember · Blood Red
Light: Cream · Deep Teal · Terracotta Light: Cream · Deep Teal · Terracotta
Applied when data-style is absent or "smooth". Also the base every other Applied when data-style is absent or "smooth".
theme builds on: anything a theme leaves unset falls back to these.
Every colour is `light-dark(<light>, <dark>)`, resolved against the Every colour is `light-dark(<light>, <dark>)`, resolved against the
root `color-scheme` (see tokens.css), so auto / light / dark share this root `color-scheme` (see tokens.css), so auto / light / dark share this
one block. one block.
══════════════════════════════════════════════════════════════════════ */ ══════════════════════════════════════════════════════════════════════ */
:root, :root:not([data-style]),
:root[data-style="smooth"] { :root[data-style="smooth"] {
--font-body: "Saira", sans-serif; --font-body: "Saira", sans-serif;
--font-mono: monospace;
font-family: var(--font-body);
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
line-height: 1.5;
/* Text */ /* Text */
--color-text: light-dark(#0e3a42, #eef0f3); --color-text: light-dark(#0e3a42, #e9eef2);
--color-text-secondary: light-dark(#2c6671, #8aaabb); --color-text-secondary: light-dark(#35626b, #a3b9c7);
--color-text-muted: light-dark(#5c8a91, #506878); --color-text-muted: light-dark(#4d7178, #7b93a6);
--color-on-accent: light-dark(#fef8e6, #001427); --color-on-accent: light-dark(#fffaf0, #001427);
/* Surfaces */ /* Surfaces — sunken (inputs, wells) < bg < surface (cards) < raised
--color-bg: light-dark(#fef8e6, #001427); (menus, modals, hovered chips). Dark tiers step up in Prussian Blue;
--color-surface: light-dark(#fffdf6, #0a1f35); light tiers step from cream to white. */
--color-bg: light-dark(#faf5e9, #01152a);
--color-surface: light-dark(#fffdf8, #0a2139);
--color-surface-raised: light-dark(#ffffff, #112a46);
--color-surface-sunken: light-dark(#f3ecdd, #000f20);
/* Borders */ /* Borders — hairlines tinted from the text colour */
--color-border: transparent; --color-border: light-dark(rgb(14 58 66 / 0.13), rgb(163 185 199 / 0.14));
--color-border-subtle: light-dark( --color-border-subtle: light-dark(
rgba(48, 144, 161, 0.18), rgb(14 58 66 / 0.08),
rgba(112, 141, 129, 0.2) rgb(163 185 199 / 0.09)
); );
/* Accent */ /* Accent — Jasmine (dark) / Terracotta (light) */
--color-accent: light-dark(#bc5148, #f4d58d); --color-accent: light-dark(#b54a41, #f4d58d);
--color-accent-hover: light-dark(#97392f, #d4aa5a); --color-accent-hover: light-dark(#a3423a, #f8e2ae);
--color-accent-soft: light-dark(
rgb(181 74 65 / 0.1),
rgb(244 213 141 / 0.12)
);
--color-focus-ring: light-dark(
rgb(181 74 65 / 0.35),
rgb(244 213 141 / 0.4)
);
/* Links */ /* Links */
--color-link: light-dark(#bc5148, #f4d58d); --color-link: light-dark(#b54a41, #f4d58d);
--color-link-hover: light-dark(#97392f, #d4aa5a); --color-link-hover: light-dark(#a3423a, #f8e2ae);
/* Danger */ /* Danger — Brick Ember, lifted for legibility on Prussian Blue */
--color-danger: light-dark(#bc5148, #bf0603); --color-danger: light-dark(#b3392f, #f0706a);
--color-danger-bg: light-dark(#f8e3e0, #220404); --color-danger-bg: light-dark(#f9e3df, rgb(191 6 3 / 0.18));
--color-danger-hover: light-dark(#97392f, #8d0801); --color-danger-hover: light-dark(#b3392f, #bf0603);
/* Success */ /* Success — Deep Teal */
--color-success: light-dark(#2e8a86, #708d81); --color-success: light-dark(#25746f, #8fb3a3);
--color-success-bg: light-dark(#ddf2f1, #0d2820); --color-success-bg: light-dark(#dff1ef, rgb(112 141 129 / 0.18));
--color-success-hover: light-dark(#1f6b67, #8aaa9a); --color-success-hover: light-dark(#1f6b67, #a6c6b8);
--color-warning: light-dark(#a86a00, #e8b44f);
/* Overlays */ /* Overlays */
--color-overlay: light-dark(rgba(14, 58, 66, 0.35), rgba(0, 10, 20, 0.55)); --color-overlay: light-dark(rgb(24 30 34 / 0.32), rgb(0 6 14 / 0.6));
--color-header-user-bg: light-dark( --color-header-user-bg: transparent;
rgba(188, 81, 72, 0.08),
rgba(244, 213, 141, 0.06)
);
--color-header-user-bg-hover: light-dark( --color-header-user-bg-hover: light-dark(
rgba(188, 81, 72, 0.15), rgb(14 58 66 / 0.07),
rgba(244, 213, 141, 0.12) rgb(233 238 242 / 0.08)
); );
/* Misc */ /* Misc */
--color-option-bg: light-dark(#fff9ec, #0d2340); --color-option-bg: light-dark(#fffdf8, #112a46);
--color-option-border: light-dark(#ece4cc, #001427); --color-option-border: light-dark(rgb(14 58 66 / 0.08), rgb(163 185 199 / 0.09));
/* Service brand colors (fixed, not theme-dependent). `on-brand` is the /* Shape & depth */
foreground for text sitting on any of these — also fixed, so the contrast --border-width: 1px;
never flips with the theme's text colour. */ --shadow-color: light-dark(rgb(14 58 66 / 0.16), rgb(0 0 0 / 0.5));
--color-youtube: #c00; --shadow-color-soft: light-dark(rgb(14 58 66 / 0.07), rgb(0 0 0 / 0.3));
--color-youtube-hover: #f00; --shadow-color-strong: light-dark(rgb(14 58 66 / 0.26), rgb(0 0 0 / 0.7));
--color-bandcamp: #1da0c3; --shadow-1: 0 1px 2px var(--shadow-color-soft);
--color-bandcamp-hover: #25c8f0; --shadow-2: 0 8px 24px -6px var(--shadow-color), 0 1px 2px var(--shadow-color-soft);
--color-soundcloud: #f50; --shadow-3: 0 24px 56px -12px var(--shadow-color-strong), 0 2px 6px var(--shadow-color-soft);
--color-soundcloud-hover: #f73;
--color-on-brand: #fff; /* Component skins */
} --header-bg: var(--color-bg);
--card-shadow: var(--shadow-1);
/* ══════════════════════════════════════════════════════════════════════ --panel-ring: inset 0 0 0 1px var(--color-border);
Structural overrides --card-hover-border: color-mix(in srgb, var(--color-text) 24%, transparent);
══════════════════════════════════════════════════════════════════════ */ --input-focus-bg: var(--color-surface);
--overlay-filter: blur(3px);
/* On hover the danger button fills with the solid dark danger colour. The --modal-border: var(--color-border);
resting text colour is --color-text, which is dark in the light variant, --tab-border: transparent;
so force white on hover to keep it legible. */ --tab-active-bg: var(--color-accent-soft);
:root:not([data-style]) .btn-danger:hover, --tab-active-fg: var(--color-accent);
:root[data-style="smooth"] .btn-danger:hover { --tab-active-border: transparent;
color: #fff; --tab-text-transform: none;
--tab-tracking: 0;
--btn-primary-shadow: var(--shadow-1);
--btn-primary-shadow-hover: var(--shadow-1);
} }

View File

@@ -10,6 +10,12 @@
palette block covers auto, forced-light and forced-dark. */ palette block covers auto, forced-light and forced-dark. */
color-scheme: light dark; color-scheme: light dark;
font-family: var(--font-body);
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
line-height: 1.5;
/* ── Space (4px grid) ── */ /* ── Space (4px grid) ── */
--space-1: 0.25rem; --space-1: 0.25rem;
--space-2: 0.5rem; --space-2: 0.5rem;
@@ -56,6 +62,17 @@
--font-display: var(--font-body); --font-display: var(--font-body);
--font-mono: ui-monospace, "SFMono-Regular", Menlo, monospace; --font-mono: ui-monospace, "SFMono-Regular", Menlo, monospace;
/* ── Service brand colors ──
Fixed across themes and schemes. `on-brand` is the foreground for text
sitting on any of them — also fixed, so contrast never flips. */
--color-youtube: #c00;
--color-youtube-hover: #f00;
--color-bandcamp: #1da0c3;
--color-bandcamp-hover: #25c8f0;
--color-soundcloud: #f50;
--color-soundcloud-hover: #f73;
--color-on-brand: #fff;
/* ── Elevation ── */ /* ── Elevation ── */
--shadow-1: 0 1px 2px rgb(0 0 0 / 0.12); --shadow-1: 0 1px 2px rgb(0 0 0 / 0.12);
--shadow-2: 0 4px 16px rgb(0 0 0 / 0.2); --shadow-2: 0 4px 16px rgb(0 0 0 / 0.2);
@@ -78,25 +95,42 @@
--z-popover: 1100; --z-popover: 1100;
--z-toast: 9999; --z-toast: 9999;
/* ── Borders ── */
--border-width: 2px;
/* ── Derived colors ── /* ── Derived colors ──
Defaults computed from each theme's base palette, so every theme gets Defaults reproduce the flat two-level (bg / surface) look; a theme that
the full semantic set; a theme overrides any of these when the derived wants more depth sets its own raised/sunken tiers. */
value isn't right for it. */ --color-surface-raised: var(--color-surface);
--color-surface-raised: color-mix( --color-surface-sunken: var(--color-bg);
in srgb,
var(--color-surface) 94%,
var(--color-text)
);
--color-surface-sunken: color-mix(
in srgb,
var(--color-bg) 96%,
var(--color-text)
);
--color-accent-soft: color-mix(in srgb, var(--color-accent) 14%, transparent); --color-accent-soft: color-mix(in srgb, var(--color-accent) 14%, transparent);
--color-focus-ring: color-mix(in srgb, var(--color-accent) 45%, transparent); --color-focus-ring: color-mix(in srgb, var(--color-accent) 45%, transparent);
--color-warning: #d4a017; --color-warning: #d4a017;
--color-on-danger: #fff; --color-on-danger: #fff;
/* ── Component skins ──
Knobs for the handful of treatments themes disagree on. */
--header-bg: var(--color-surface);
--card-shadow: 0 0 #0000;
--panel-ring: 0 0 #0000;
--card-hover-border: var(--color-accent);
--input-focus-bg: color-mix(
in srgb,
var(--color-accent) 4%,
var(--color-surface-sunken) 96%
);
--overlay-filter: none;
--modal-border: transparent;
--tab-border: var(--color-border);
--tab-active-bg: var(--color-accent);
--tab-active-fg: var(--color-on-accent);
--tab-text-transform: uppercase;
--tab-tracking: 0.04em;
--btn-primary-shadow: 0 2px 8px
color-mix(in srgb, var(--color-accent) 40%, transparent);
--btn-primary-shadow-hover: 0 4px 14px
color-mix(in srgb, var(--color-accent) 50%, transparent);
/* Legacy names still referenced by a few rules. */ /* Legacy names still referenced by a few rules. */
--color-muted: var(--color-text-muted); --color-muted: var(--color-text-muted);
--color-error: var(--color-danger); --color-error: var(--color-danger);