From 21fb0c6e1641a92efa5d483cd57d71f9f4264e8b Mon Sep 17 00:00:00 2001 From: khannurien Date: Sat, 19 Sep 2026 19:15:33 +0000 Subject: [PATCH] =?UTF-8?q?v3:=20design=20tokens=20=E2=80=94=20shared=20ra?= =?UTF-8?q?dius,=20type,=20elevation,=20motion=20and=20layer=20scales;=20s?= =?UTF-8?q?ingle=20light-dark()=20palette=20for=20smooth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 --- src/App.css | 818 +++++++++++++++++++++--------------------- src/index.css | 4 +- src/main.tsx | 1 + src/themes/smooth.css | 164 ++------- src/tokens.css | 112 ++++++ 5 files changed, 563 insertions(+), 536 deletions(-) create mode 100644 src/tokens.css diff --git a/src/App.css b/src/App.css index 9b502bcf..277e6556 100644 --- a/src/App.css +++ b/src/App.css @@ -23,14 +23,14 @@ font-family: var(--font-mono, monospace); background: var(--color-bg); border: 1px solid var(--color-border); - border-radius: 3px; + border-radius: var(--radius-xs); padding: 0.1em 0.35em; font-size: 0.88em; } .md pre { background: var(--color-bg); border: 1px solid var(--color-border); - border-radius: 8px; + border-radius: var(--radius-lg); padding: 0.75rem 1rem; overflow-x: auto; margin: 0.6em 0; @@ -101,7 +101,7 @@ padding: 1.25rem; margin-bottom: 3px; background: var(--color-surface); - border-radius: 12px 12px 0 0; + border-radius: var(--radius-xl) var(--radius-xl) 0 0; } .dump-header-block { @@ -128,7 +128,7 @@ .dump-title { margin: 0; - font-size: 1.5rem; + font-size: var(--text-2xl); font-weight: 700; line-height: 1.25; word-break: break-word; @@ -139,7 +139,7 @@ display: inline-flex; align-items: center; gap: 0.4rem; - border-radius: 6px; + border-radius: var(--radius-md); max-width: 100%; /* Padding gives the hover box breathing room (incl. right of the pencil); the matching negative margin keeps the title's visual position unchanged. */ @@ -156,12 +156,12 @@ } .dump-title-edit-btn { - font-size: 0.85rem; + font-size: var(--text-sm); line-height: 1; flex-shrink: 0; color: var(--color-text-muted); opacity: 0; - transition: opacity 0.1s; + transition: opacity var(--dur-fast); pointer-events: none; } @@ -183,12 +183,12 @@ .playlist-edit-input, .playlist-edit-textarea { border: 2px solid var(--color-border); - border-radius: 8px; + border-radius: var(--radius-lg); background: var(--color-bg); color: var(--color-text); font-family: inherit; outline: none; - transition: border-color 0.2s; + transition: border-color var(--dur-slow); } .dump-title-input:focus, @@ -202,14 +202,14 @@ flex: 1; min-width: 12rem; padding: 0.4rem 0.6rem; - font-size: 1.25rem; + font-size: var(--text-xl); font-weight: 700; } .dump-title-error { width: 100%; margin: 0; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-danger); } @@ -234,7 +234,7 @@ } .dump-comment { - font-size: 1.05rem; + font-size: var(--text-base); line-height: 1.72; opacity: 0.85; border-left: 3px solid var(--color-accent); @@ -246,7 +246,7 @@ .dump-rich-content { padding: 1.25rem; background: var(--color-surface); - border-radius: 0 0 12px 12px; + border-radius: 0 0 var(--radius-xl) var(--radius-xl); } .dump-url-link { @@ -254,7 +254,7 @@ word-break: break-all; padding: 1rem; border: 2px solid var(--color-border); - border-radius: 8px; + border-radius: var(--radius-lg); width: 100%; box-sizing: border-box; } @@ -268,9 +268,9 @@ .dump-actions a { color: var(--color-text); text-decoration: none; - font-size: 0.9rem; + font-size: var(--text-md); opacity: 0.7; - transition: opacity 0.15s, color 0.15s; + transition: opacity var(--dur-base), color var(--dur-base); } .dump-actions a:hover { @@ -299,7 +299,7 @@ } .form-label { - font-size: 0.85rem; + font-size: var(--text-sm); font-weight: 600; opacity: 0.6; } @@ -317,7 +317,7 @@ border: none; padding: 0; cursor: pointer; - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 600; color: var(--color-text); opacity: 0.6; @@ -337,17 +337,17 @@ width: 100%; box-sizing: border-box; padding: 0.65rem 1rem; - border-radius: 8px; + border-radius: var(--radius-lg); border: 2px solid var(--color-border); background-color: var(--color-bg); color: var(--color-text); - font-size: 1rem; + font-size: var(--text-base); font-family: var(--font-body); font-optical-sizing: auto; font-weight: 400; font-style: normal; line-height: 1.5; - transition: border-color 0.2s, box-shadow 0.2s, background-color 0.2s; + transition: border-color var(--dur-slow), box-shadow var(--dur-slow), background-color var(--dur-slow); outline: none; } @@ -391,7 +391,7 @@ } .form-hint { - font-size: 0.8rem; + font-size: var(--text-xs); opacity: 0.7; margin-top: 0.1rem; } @@ -420,12 +420,12 @@ background: none; border: none; cursor: pointer; - font-size: 1rem; + font-size: var(--text-base); line-height: 1; color: var(--color-muted); - border-radius: 4px; + border-radius: var(--radius-sm); padding: 0.4rem; - transition: color 0.15s; + transition: color var(--dur-base); } .dump-create-title-edit-btn:hover { @@ -434,7 +434,7 @@ .dump-create-title { margin: 0; - font-size: 1.4rem; + font-size: var(--text-2xl); font-weight: 700; } @@ -444,7 +444,7 @@ .dump-create--drag { outline: 2px dashed var(--color-accent); outline-offset: 6px; - border-radius: 10px; + border-radius: var(--radius-xl); } .dump-create-draft, @@ -456,8 +456,8 @@ flex-wrap: wrap; margin-bottom: 0.9rem; padding: 0.55rem 0.75rem; - border-radius: 8px; - font-size: 0.85rem; + border-radius: var(--radius-lg); + font-size: var(--text-sm); } .dump-create-draft { @@ -494,7 +494,7 @@ /* Not reached, or reached with nothing worth showing. */ .preview-note { margin: 0; - font-size: 0.82rem; + font-size: var(--text-sm); color: var(--color-text-secondary); } @@ -503,13 +503,13 @@ display: flex; gap: 0.6rem; padding: 0.65rem 0.8rem; - border-radius: 9px; + border-radius: var(--radius-lg); background: color-mix(in srgb, var(--color-accent) 9%, transparent); border: 1px solid color-mix(in srgb, var(--color-accent) 35%, transparent); } .dump-duplicate-icon { - font-size: 1rem; + font-size: var(--text-base); line-height: 1.3; opacity: 0.8; } @@ -523,12 +523,12 @@ .dump-duplicate-lead { margin: 0; - font-size: 0.85rem; + font-size: var(--text-sm); font-weight: 600; } .dump-duplicate-link { - font-size: 0.85rem; + font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -537,7 +537,7 @@ .dump-duplicate-more, .dump-duplicate-hint { margin: 0; - font-size: 0.78rem; + font-size: var(--text-xs); color: var(--color-text-secondary); } @@ -556,7 +556,7 @@ align-items: center; gap: 0.4rem; min-width: 0; - font-size: 0.82rem; + font-size: var(--text-sm); color: var(--color-text-muted); } @@ -576,9 +576,9 @@ width: 1.35rem; height: 1.35rem; flex-shrink: 0; - border-radius: 999px; + border-radius: var(--radius-full); border: 1.5px solid var(--color-border-subtle); - font-size: 0.72rem; + font-size: var(--text-2xs); font-weight: 700; line-height: 1; } @@ -647,7 +647,7 @@ /* One line naming the thing the second panel's choices apply to. */ .dump-panel-recap { margin: 0; - font-size: 0.82rem; + font-size: var(--text-sm); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; @@ -659,7 +659,7 @@ display: flex; background: var(--color-bg); border: 1.5px solid var(--color-border); - border-radius: 9px; + border-radius: var(--radius-lg); padding: 3px; gap: 2px; } @@ -667,14 +667,14 @@ .visibility-toggle button { flex: 1; padding: 0.3rem 0.9rem; - border-radius: 6px; + border-radius: var(--radius-md); border: none; background: transparent; color: var(--color-text); cursor: pointer; - font-size: 0.88rem; + font-size: var(--text-sm); font-weight: 600; - transition: background 0.15s, color 0.15s; + transition: background var(--dur-base), color var(--dur-base); white-space: nowrap; } @@ -690,10 +690,10 @@ /* ── FileDropZone ── */ .fdz { border: 2px dashed var(--color-border-subtle); - border-radius: 10px; + border-radius: var(--radius-xl); background: var(--color-surface); cursor: pointer; - transition: border-color 0.15s, background 0.15s; + transition: border-color var(--dur-base), background var(--dur-base); outline: none; } @@ -735,13 +735,13 @@ .fdz__hint { margin: 0; - font-size: 0.9rem; + font-size: var(--text-md); font-weight: 500; } .fdz__browse { margin: 0; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-text-secondary); } @@ -753,7 +753,7 @@ .fdz__limit { margin: 0.25rem 0 0; - font-size: 0.78rem; + font-size: var(--text-xs); color: var(--color-text-muted); } @@ -765,7 +765,7 @@ } .fdz__file-icon { - font-size: 1.5rem; + font-size: var(--text-2xl); flex-shrink: 0; } @@ -778,7 +778,7 @@ } .fdz__file-name { - font-size: 0.9rem; + font-size: var(--text-md); font-weight: 600; overflow: hidden; text-overflow: ellipsis; @@ -786,7 +786,7 @@ } .fdz__file-size { - font-size: 0.78rem; + font-size: var(--text-xs); color: var(--color-text-muted); } @@ -796,10 +796,10 @@ border: none; cursor: pointer; color: var(--color-text-muted); - font-size: 0.8rem; + font-size: var(--text-xs); padding: 0.3rem 0.5rem; - border-radius: 4px; - transition: color 0.12s, background 0.12s; + border-radius: var(--radius-sm); + transition: color var(--dur-fast), background var(--dur-fast); line-height: 1; } @@ -811,7 +811,7 @@ /* ── Upload progress (second panel, while the file is being sent) ── */ .dump-upload-progress { height: 4px; - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-border-subtle); overflow: hidden; } @@ -819,9 +819,9 @@ .dump-upload-progress-fill { height: 100%; width: 0; - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-accent); - transition: width 0.2s ease-out; + transition: width var(--dur-slow) ease-out; } /* Length unknown, or the body is sent and the server is still thinking. */ @@ -848,14 +848,14 @@ width: 100%; max-height: 320px; object-fit: contain; - border-radius: 10px; + border-radius: var(--radius-xl); background: var(--color-bg); display: block; } .preview-loading { margin: 0; - font-size: 0.85rem; + font-size: var(--text-sm); opacity: 0.5; font-style: italic; } @@ -863,7 +863,7 @@ /* File previews (Dump page) */ .file-preview-image { max-width: 100%; - border-radius: 8px; + border-radius: var(--radius-lg); display: block; } @@ -875,7 +875,7 @@ background: #000; cursor: pointer; display: block; - border-radius: 8px; + border-radius: var(--radius-lg); overflow: hidden; } @@ -887,7 +887,7 @@ } .file-preview-play-btn .rich-content-play-overlay { - font-size: 3rem; + font-size: var(--text-display); } .audio-file-preview { @@ -901,7 +901,7 @@ var(--color-surface) 92% ); border: 2px solid var(--color-border); - border-radius: 0 0 12px 12px; + border-radius: 0 0 var(--radius-xl) var(--radius-xl); } /* When active, brighten only the *un-played* bars. Excluding played bars keeps @@ -918,7 +918,7 @@ /* ── Video player ── */ .video-player { width: 100%; - border-radius: 0 0 12px 12px; + border-radius: 0 0 var(--radius-xl) var(--radius-xl); overflow: hidden; border: 2px solid var(--color-border); position: relative; @@ -989,7 +989,7 @@ var(--color-accent) 8%, var(--color-surface) 92% ); - border-radius: 0 0 12px 12px; + border-radius: 0 0 var(--radius-xl) var(--radius-xl); border: 2px solid var(--color-border); width: 100%; box-sizing: border-box; @@ -1009,7 +1009,7 @@ display: grid; place-items: center; padding: 0.45rem; - transition: background 0.15s, transform 0.1s; + transition: background var(--dur-base), transform var(--dur-fast); } .audio-player-btn:hover { @@ -1024,7 +1024,7 @@ } .audio-player-time { - font-size: 0.78rem; + font-size: var(--text-xs); font-variant-numeric: tabular-nums; opacity: 0.6; flex-shrink: 0; @@ -1035,7 +1035,7 @@ flex: 1; min-width: 48px; height: 4px; - border-radius: 2px; + border-radius: var(--radius-xs); background: color-mix( in srgb, var(--color-accent) 20%, @@ -1064,7 +1064,7 @@ flex: 1; min-width: 0; height: 48px; - border-radius: 3px; + border-radius: var(--radius-xs); background: color-mix( in srgb, var(--color-accent) 12%, @@ -1080,7 +1080,7 @@ inset: 0 auto 0 0; background: var(--color-accent); opacity: 0.45; - transition: width 0.1s linear; + transition: width var(--dur-fast) linear; } /* Audio whose peaks can't be decoded (cross-origin streams). Boxed to the @@ -1098,7 +1098,7 @@ inset: 50% 0 auto 0; transform: translateY(-50%); height: 6px; - border-radius: 3px; + border-radius: var(--radius-xs); background: color-mix( in srgb, var(--color-accent) 12%, @@ -1110,8 +1110,8 @@ bottom: auto; transform: translateY(-50%); height: 6px; - border-radius: 3px; - z-index: 1; + border-radius: var(--radius-xs); + z-index: var(--z-raised); } .audio-player-track--volume { @@ -1123,7 +1123,7 @@ position: absolute; inset: 0 auto 0 0; background: var(--color-accent); - border-radius: 2px; + border-radius: var(--radius-xs); pointer-events: none; } @@ -1157,7 +1157,7 @@ place-items: center; padding: 0; opacity: 0.55; - transition: opacity 0.15s; + transition: opacity var(--dur-base); } .audio-player-vol-btn:hover { @@ -1174,7 +1174,7 @@ width: 100%; height: 80vh; min-height: 600px; - border-radius: 8px; + border-radius: var(--radius-lg); border: 2px solid var(--color-border); display: block; } @@ -1185,11 +1185,11 @@ gap: 0.5rem; padding: 0.75rem 1.5rem; border: 2px solid var(--color-accent); - border-radius: 8px; + border-radius: var(--radius-lg); color: var(--color-accent); text-decoration: none; font-weight: 500; - transition: background 0.15s, color 0.15s; + transition: background var(--dur-base), color var(--dur-base); } .file-download-link:hover { @@ -1199,16 +1199,16 @@ .dump-file-notice { margin: 0 0 0.25rem; - font-size: 0.9rem; + font-size: var(--text-md); opacity: 0.8; } .rich-content-card { display: flex; border: 2px solid var(--color-border); - border-radius: 10px; + border-radius: var(--radius-xl); overflow: hidden; - transition: border-color 0.2s; + transition: border-color var(--dur-slow); } .rich-content-card:has(.rich-content-body:hover) { @@ -1261,21 +1261,21 @@ transform: translateX(-50%); width: calc(100% - 2.5rem); max-width: 860px; - z-index: 1000; + z-index: var(--z-modal); background: var(--color-surface); border: 2px solid var(--color-border); - border-radius: 10px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.3); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-3); animation: player-enter 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) both; - transition: opacity 0.2s ease, box-shadow 0.2s ease; + transition: opacity var(--dur-slow) ease, box-shadow var(--dur-slow) ease; } .global-player--reduced { opacity: 0.6; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); + box-shadow: var(--shadow-2); } .global-player--reduced:hover { opacity: 1; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.3); + box-shadow: var(--shadow-3); } @keyframes player-enter { from { @@ -1294,7 +1294,7 @@ .global-player-title { flex: 1; font-weight: 600; - font-size: 0.9rem; + font-size: var(--text-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -1318,7 +1318,7 @@ a.global-player-title:hover { .global-player-media-wrap { overflow: hidden; min-height: 0; - border-radius: 0 0 8px 8px; + border-radius: 0 0 var(--radius-lg) var(--radius-lg); } /* Inside the global player the shell already draws the border — drop the @@ -1360,7 +1360,7 @@ a.global-player-title:hover { flex: none; } .global-player-subtitle { - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; @@ -1371,7 +1371,7 @@ a.global-player-title:hover { height: 36px; flex: none; object-fit: cover; - border-radius: 4px; + border-radius: var(--radius-sm); } .global-player-transport { display: flex; @@ -1380,7 +1380,7 @@ a.global-player-title:hover { flex: none; } .global-player-position { - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; @@ -1392,7 +1392,7 @@ a.global-player-title:hover { .global-player-status { margin: 0; padding: 0 1rem 0.5rem; - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-muted); } @@ -1414,7 +1414,7 @@ a.global-player-title:hover { border-left: 3px solid transparent; color: inherit; font: inherit; - font-size: 0.8rem; + font-size: var(--text-xs); text-align: left; cursor: pointer; } @@ -1448,7 +1448,7 @@ a.global-player-title:hover { text-align: center; padding: 1rem; color: var(--color-text-muted); - font-size: 0.85rem; + font-size: var(--text-sm); } body.has-player { @@ -1478,7 +1478,7 @@ body.has-player { 0px)); top: calc(100dvh - var(--fab-size) - 1.25rem - env(safe-area-inset-bottom, 0px)); - z-index: 900; + z-index: var(--z-fab); width: var(--fab-size); height: var(--fab-size); display: flex; @@ -1498,7 +1498,7 @@ body.has-player { opacity: 0; transform: translateY(1rem) scale(0.9); pointer-events: none; - transition: opacity 0.2s ease, transform 0.2s ease, background 0.15s ease, + transition: opacity var(--dur-slow) ease, transform var(--dur-slow) ease, background var(--dur-base) ease, top 0.4s cubic-bezier(0.4, 0, 0.2, 1); } @@ -1557,7 +1557,7 @@ body.has-fab .page-content { 0px)); top: calc(100dvh - var(--fab-size) * 2 - 2rem - env(safe-area-inset-bottom, 0px)); - z-index: 900; + z-index: var(--z-fab); width: var(--fab-size); height: var(--fab-size); display: flex; @@ -1575,7 +1575,7 @@ body.has-fab .page-content { opacity: 0; transform: translateY(1rem) scale(0.9); pointer-events: none; - transition: opacity 0.2s ease, transform 0.2s ease, background 0.15s ease, + transition: opacity var(--dur-slow) ease, transform var(--dur-slow) ease, background var(--dur-base) ease, top 0.4s cubic-bezier(0.4, 0, 0.2, 1); } @@ -1639,8 +1639,8 @@ body.has-player .chat-fab { justify-content: center; background: rgba(0, 0, 0, 0.25); color: #fff; - font-size: 1.75rem; - transition: background 0.18s ease; + font-size: var(--text-3xl); + transition: background var(--dur-slow) ease; } .rich-content-thumbnail-btn:hover .rich-content-play-overlay { @@ -1683,18 +1683,18 @@ body.has-player .chat-fab { display: inline-block; background: var(--color-accent); color: var(--color-on-accent); - font-size: 0.7rem; + font-size: var(--text-2xs); font-weight: 700; letter-spacing: 0.04em; padding: 0.15rem 0.5rem; - border-radius: 4px; + border-radius: var(--radius-sm); align-self: flex-start; } .rich-content-title { margin: 0; font-weight: 600; - font-size: 1rem; + font-size: var(--text-base); line-height: 1.35; overflow-wrap: break-word; word-break: break-word; @@ -1715,14 +1715,14 @@ body.has-player .chat-fab { .rich-content-description { margin: 0; - font-size: 0.85rem; + font-size: var(--text-sm); opacity: 0.75; -webkit-line-clamp: 2; line-clamp: 2; } .rich-content-url { - font-size: 0.75rem; + font-size: var(--text-xs); opacity: 0.5; white-space: nowrap; overflow: hidden; @@ -1752,13 +1752,13 @@ body.has-player .chat-fab { width: 36px; height: 36px; object-fit: cover; - border-radius: 4px; + border-radius: var(--radius-sm); border: 1px solid var(--color-border); display: block; } .rich-content-compact-icon { - font-size: 1rem; + font-size: var(--text-base); opacity: 0.6; } @@ -1788,13 +1788,13 @@ body.has-player .chat-fab { gap: 0.3rem; padding: 0.25rem 0.6rem; border: 2px solid var(--color-border); - border-radius: 6px; + border-radius: var(--radius-md); background: transparent; color: var(--color-text); - font-size: 0.85rem; + font-size: var(--text-sm); font-weight: 600; cursor: pointer; - transition: border-color 0.15s, background 0.15s, color 0.15s; + transition: border-color var(--dur-base), background var(--dur-base), color var(--dur-base); white-space: nowrap; flex-shrink: 0; font-variant-numeric: tabular-nums; @@ -1856,7 +1856,7 @@ body.has-player .chat-fab { align-items: center; flex-wrap: wrap; gap: 0.25rem 0.5rem; - font-size: 0.85rem; + font-size: var(--text-sm); opacity: 0.7; } @@ -1898,7 +1898,7 @@ body.has-player .chat-fab { border: 2px dashed var(--color-border); background: var(--color-bg); color: var(--color-text); - font-size: 1.5rem; + font-size: var(--text-2xl); opacity: 0.4; box-sizing: border-box; } @@ -1908,12 +1908,12 @@ body.has-player .chat-fab { inset: 0; background: var(--color-overlay); color: var(--color-on-accent); - font-size: 1.1rem; + font-size: var(--text-lg); display: flex; align-items: center; justify-content: center; opacity: 0; - transition: opacity 0.15s; + transition: opacity var(--dur-base); } .img-picker:hover .img-picker-overlay, @@ -1932,13 +1932,13 @@ body.has-player .chat-fab { border-radius: 50%; background: var(--color-overlay); color: var(--color-on-accent); - font-size: 1.1rem; + font-size: var(--text-lg); display: flex; align-items: center; justify-content: center; opacity: 0; cursor: pointer; - transition: opacity 0.15s; + transition: opacity var(--dur-base); } .profile-avatar-wrapper:hover .avatar-change-overlay { @@ -2051,7 +2051,7 @@ body.has-player .chat-fab { .profile-columns .dump-card-title { flex: 1 0 100%; - font-size: 0.9rem; + font-size: var(--text-md); line-height: 1.3; display: -webkit-box; -webkit-box-orient: vertical; @@ -2078,7 +2078,7 @@ body.has-player .chat-fab { .profile-columns .dump-card-date, .profile-columns .dump-card-comment-count { - font-size: 0.72rem; + font-size: var(--text-2xs); } .profile-columns .dump-card-categories { @@ -2087,12 +2087,12 @@ body.has-player .chat-fab { .profile-columns .dump-card-category-chip { padding: 0.05rem 0.4rem; - font-size: 0.68rem; + font-size: var(--text-2xs); } .profile-columns .vote-btn { padding: 0.15rem 0.45rem; - font-size: 0.78rem; + font-size: var(--text-xs); } } @@ -2105,7 +2105,7 @@ body.has-player .chat-fab { .empty-state { margin: 0; opacity: 0.5; - font-size: 0.9rem; + font-size: var(--text-md); } /* ── Profile section header (shared between bare h2 and wrapper div) ── */ @@ -2137,17 +2137,17 @@ body.has-player .chat-fab { .profile-username { margin: 0; - font-size: 1.25rem; + font-size: var(--text-xl); font-weight: 600; } /* Role badge — elevated roles only (see RoleChip) */ .profile-role-chip { padding: 0.1rem 0.55rem; - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-accent); color: var(--color-on-accent); - font-size: 0.72rem; + font-size: var(--text-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; @@ -2175,8 +2175,8 @@ body.has-player .chat-fab { .profile-description-view { position: relative; padding: 0.5rem 0.6rem; - border-radius: 6px; - font-size: 0.95rem; + border-radius: var(--radius-md); + font-size: var(--text-md); } .profile-description-view--editable { @@ -2203,10 +2203,10 @@ body.has-player .chat-fab { position: absolute; top: 0.55rem; right: 0.5rem; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-muted); opacity: 0; - transition: opacity 0.1s; + transition: opacity var(--dur-fast); pointer-events: none; } @@ -2224,11 +2224,11 @@ body.has-player .chat-fab { display: inline-flex; align-items: center; gap: 0.35rem; - font-size: 0.78rem; + font-size: var(--text-xs); color: var(--color-text-muted); margin: 0.1rem 0 0.4rem; cursor: pointer; - border-radius: 4px; + border-radius: var(--radius-sm); padding: 0.1rem 0.2rem; margin-left: -0.2rem; } @@ -2251,8 +2251,8 @@ body.has-player .chat-fab { .profile-email-input { width: min(260px, 100%); padding: 0.35rem 0.6rem; - border-radius: 6px; - font-size: 0.85rem; + border-radius: var(--radius-md); + font-size: var(--text-sm); line-height: 1.5; } @@ -2267,14 +2267,14 @@ body.has-player .chat-fab { justify-content: center; height: 1.75rem; padding: 0 0.65rem; - border-radius: 5px; + border-radius: var(--radius-sm); border: 1.5px solid; - font-size: 0.8rem; + font-size: var(--text-xs); font-family: inherit; font-weight: 500; cursor: pointer; box-sizing: border-box; - transition: background 0.15s, border-color 0.15s, color 0.15s; + transition: background var(--dur-base), border-color var(--dur-base), color var(--dur-base); } .profile-email-btn--save { @@ -2311,7 +2311,7 @@ body.has-player .chat-fab { } .profile-invited-by { - font-size: 0.78rem; + font-size: var(--text-xs); color: var(--color-text-muted); margin: 0.15rem 0 0.4rem; } @@ -2344,12 +2344,12 @@ body.has-player .chat-fab { .invite-btn { padding: 0.3rem 0.9rem; border: 1.5px solid var(--color-accent); - border-radius: 6px; + border-radius: var(--radius-md); background: transparent; color: var(--color-accent); - font-size: 0.85rem; + font-size: var(--text-sm); cursor: pointer; - transition: background 0.15s, color 0.15s; + transition: background var(--dur-base), color var(--dur-base); } .invite-btn:hover { background: var(--color-accent); @@ -2363,7 +2363,7 @@ body.has-player .chat-fab { max-width: 480px; } .invite-url { - font-size: 0.75rem; + font-size: var(--text-xs); font-family: var(--font-mono, monospace); color: var(--color-text-muted); flex: 1; @@ -2372,7 +2372,7 @@ body.has-player .chat-fab { white-space: nowrap; background: var(--color-surface); border: 1px solid var(--color-border-subtle); - border-radius: 6px; + border-radius: var(--radius-md); padding: 0.35rem 0.6rem; } /* Always-visible copy target. Sits first so it's the obvious tap. */ @@ -2381,13 +2381,13 @@ body.has-player .chat-fab { flex-shrink: 0; padding: 0.2rem 0.65rem; border: 1px solid var(--color-border-subtle); - border-radius: 4px; + border-radius: var(--radius-sm); background: transparent; color: var(--color-text); - font-size: 0.75rem; + font-size: var(--text-xs); cursor: pointer; white-space: nowrap; - transition: background 0.12s; + transition: background var(--dur-fast); } .invite-copy-btn:hover { background: var(--color-accent); @@ -2398,7 +2398,7 @@ body.has-player .chat-fab { /* ── Profile sub-pages (dumps / upvoted / playlists) ── */ .profile-subpage-back { display: inline-block; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-text-muted); text-decoration: none; margin-bottom: 0.75rem; @@ -2417,7 +2417,7 @@ body.has-player .chat-fab { .profile-subpage-title { margin: 0; - font-size: 1.4rem; + font-size: var(--text-2xl); font-weight: 700; flex: 1; } @@ -2426,7 +2426,7 @@ body.has-player .chat-fab { .profile-view-all { display: inline-block; margin-top: 0.75rem; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-text-muted); text-decoration: none; } @@ -2442,13 +2442,13 @@ body.has-player .chat-fab { justify-content: center; padding: 0.3rem 0.9rem; border: 1.5px solid var(--color-border); - border-radius: 6px; + border-radius: var(--radius-md); background: transparent; color: var(--color-text-muted); - font-size: 0.85rem; + font-size: var(--text-sm); font-family: inherit; cursor: pointer; - transition: border-color 0.15s, color 0.15s, background 0.15s; + transition: border-color var(--dur-base), color var(--dur-base), background var(--dur-base); } .btn-border:hover { @@ -2470,8 +2470,8 @@ body.has-player .chat-fab { background: var(--color-danger-bg); color: var(--color-text); padding: 0.7rem 1rem; - border-radius: 8px; - font-size: 0.9rem; + border-radius: var(--radius-lg); + font-size: var(--text-md); } .error-card-icon { @@ -2487,7 +2487,7 @@ body.has-player .chat-fab { .error-card-title { margin: 0; - font-size: 0.95rem; + font-size: var(--text-md); font-weight: 700; } @@ -2510,7 +2510,7 @@ body.has-player .chat-fab { width: calc(100% - 2rem); padding: 0.75rem 1rem; border: none; - border-radius: 10px; + border-radius: var(--radius-xl); background: var(--color-danger-bg); color: var(--color-text); line-height: 1.5; @@ -2519,7 +2519,7 @@ body.has-player .chat-fab { } .app-header-status strong { - font-size: 0.95rem; + font-size: var(--text-md); } .page-error-wrap { @@ -2581,7 +2581,7 @@ body.has-player .chat-fab { } .app-header-brand { - font-size: 1.15rem; + font-size: var(--text-lg); font-weight: 700; letter-spacing: -0.01em; flex-shrink: 0; @@ -2683,7 +2683,7 @@ body.has-player .chat-fab { display: inline-flex; align-items: center; justify-content: center; - font-size: 0.95rem; + font-size: var(--text-md); font-family: inherit; line-height: 1; } @@ -2715,9 +2715,9 @@ body.has-player .chat-fab { border: none; color: inherit; text-decoration: none; - font-size: 1rem; + font-size: var(--text-base); cursor: pointer; - border-radius: 6px; + border-radius: var(--radius-md); } .nav-search-btn:hover { @@ -2755,11 +2755,11 @@ body.has-player .chat-fab { text-decoration: none; color: var(--color-text); font-weight: 600; - font-size: 0.95rem; + font-size: var(--text-md); padding: 0.35rem 0.85rem; - border-radius: 8px; + border-radius: var(--radius-lg); background: var(--color-header-user-bg); - transition: background 0.15s; + transition: background var(--dur-base); } .app-header-user:hover { @@ -2776,10 +2776,10 @@ body.has-player .chat-fab { align-items: center; background: transparent; border: none; - border-radius: 8px; + border-radius: var(--radius-lg); padding: 0.25rem; cursor: pointer; - transition: background 0.15s; + transition: background var(--dur-base); } .user-menu-trigger:hover { @@ -2793,24 +2793,24 @@ body.has-player .chat-fab { min-width: 150px; background: var(--color-surface); border: 2px solid var(--color-border-subtle); - border-radius: 10px; + border-radius: var(--radius-xl); padding: 0.35rem; display: flex; flex-direction: column; gap: 0.15rem; - z-index: 100; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2); + z-index: var(--z-sticky); + box-shadow: var(--shadow-2); } .user-menu-item { display: block; padding: 0.45rem 0.75rem; - border-radius: 7px; + border-radius: var(--radius-md); text-decoration: none; color: var(--color-text); - font-size: 0.9rem; + font-size: var(--text-md); font-weight: 600; - transition: background 0.12s; + transition: background var(--dur-fast); } .user-menu-item:hover { @@ -2824,13 +2824,13 @@ body.has-player .chat-fab { overflow-y: auto; background: var(--color-surface); border: 2px solid var(--color-border-subtle); - border-radius: 10px; + border-radius: var(--radius-xl); padding: 0.35rem; display: flex; flex-direction: column; gap: 0.15rem; - z-index: 100; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2); + z-index: var(--z-sticky); + box-shadow: var(--shadow-2); } .user-list-popover-item { @@ -2838,12 +2838,12 @@ body.has-player .chat-fab { align-items: center; gap: 0.5rem; padding: 0.35rem 0.5rem; - border-radius: 7px; + border-radius: var(--radius-md); text-decoration: none; color: var(--color-text); - font-size: 0.85rem; + font-size: var(--text-sm); font-weight: 600; - transition: background 0.12s; + transition: background var(--dur-fast); } .user-list-popover-item:hover { @@ -2853,7 +2853,7 @@ body.has-player .chat-fab { .user-list-popover-status { margin: 0; padding: 0.5rem 0.6rem; - font-size: 0.8rem; + font-size: var(--text-xs); color: var(--color-text-muted); } @@ -2862,7 +2862,7 @@ body.has-player .chat-fab { border: none; cursor: pointer; padding: 0.4rem 0.6rem; - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 600; color: var(--color-accent); text-align: left; @@ -2883,20 +2883,20 @@ body.has-player .chat-fab { gap: 1.25rem; background: var(--color-surface); border: 2px solid var(--color-border); - border-radius: 12px; + border-radius: var(--radius-xl); padding: 2rem; } .auth-card-title { margin: 0; - font-size: 1.5rem; + font-size: var(--text-2xl); font-weight: 700; text-align: center; } .auth-card-footer { text-align: center; - font-size: 0.9rem; + font-size: var(--text-md); opacity: 0.7; margin: 0; } @@ -2930,7 +2930,7 @@ body.has-player .chat-fab { } .auth-reset-sent { - font-size: 0.9rem; + font-size: var(--text-md); text-align: center; margin: 0; opacity: 0.85; @@ -2964,19 +2964,19 @@ body.has-player .chat-fab { grid-column: 1 / -1; } .form-page--two-col .dump-edit-preview { - border-radius: 0 0 0 12px; + border-radius: 0 0 0 var(--radius-xl); } /* Higher specificity than the generic `.form-page .form` below so the form's bottom-left stays square where it meets the preview. */ .form-page.form-page--two-col .form { - border-radius: 0 0 12px 0; + border-radius: 0 0 var(--radius-xl) 0; } } .form-page-header { padding: 1.25rem; background: var(--color-surface); - border-radius: 12px 12px 0 0; + border-radius: var(--radius-xl) var(--radius-xl) 0 0; display: flex; flex-direction: column; gap: 0.2rem; @@ -2984,7 +2984,7 @@ body.has-player .chat-fab { .form-page-eyebrow { margin: 0; - font-size: 0.78rem; + font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; @@ -2993,7 +2993,7 @@ body.has-player .chat-fab { .form-page-title { margin: 0; - font-size: 1.4rem; + font-size: var(--text-2xl); font-weight: 700; word-break: break-word; } @@ -3002,7 +3002,7 @@ body.has-player .chat-fab { padding: 1.25rem; background: var(--color-surface); overflow: hidden; - border-radius: 0 0 12px 12px; + border-radius: 0 0 var(--radius-xl) var(--radius-xl); } .dump-edit-refresh { @@ -3011,7 +3011,7 @@ body.has-player .chat-fab { .dump-edit-refresh-error { margin-top: 0.5rem; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-danger); } @@ -3023,7 +3023,7 @@ body.has-player .chat-fab { .form-page .form { background: var(--color-surface); - border-radius: 0 0 12px 12px; + border-radius: 0 0 var(--radius-xl) var(--radius-xl); padding: 1.25rem; } @@ -3051,11 +3051,11 @@ body.has-player .chat-fab { border: none; padding: 0; cursor: pointer; - font-size: 0.9rem; + font-size: var(--text-md); color: var(--color-text); opacity: 0.6; text-decoration: none; - transition: opacity 0.15s; + transition: opacity var(--dur-base); } .form-cancel:hover { @@ -3072,17 +3072,17 @@ body.has-player .chat-fab { gap: 0.25em; white-space: nowrap; cursor: pointer; - border-radius: 8px; + border-radius: var(--radius-lg); font-family: inherit; - font-size: 0.9rem; + font-size: var(--text-md); font-weight: 600; padding: 0.4rem 1rem; transition: - background 0.15s, - color 0.15s, - border-color 0.15s, - box-shadow 0.15s, - transform 0.1s; + background var(--dur-base), + color var(--dur-base), + border-color var(--dur-base), + box-shadow var(--dur-base), + transform var(--dur-fast); } .btn-primary { @@ -3140,11 +3140,11 @@ body.has-player .chat-fab { background: none; border: none; padding: 0.3rem 0.55rem; - border-radius: 6px; + border-radius: var(--radius-md); color: var(--color-text); font-family: inherit; opacity: 0.7; - transition: opacity 0.15s, background 0.15s; + transition: opacity var(--dur-base), background var(--dur-base); } .btn--ghost:hover { @@ -3160,8 +3160,8 @@ body.has-player .chat-fab { border: none; cursor: pointer; line-height: 1; - border-radius: 4px; - transition: opacity 0.15s, color 0.15s; + border-radius: var(--radius-sm); + transition: opacity var(--dur-base), color var(--dur-base); } /* ── Index page ── */ @@ -3187,7 +3187,7 @@ body.has-player .chat-fab { display: block; flex-shrink: 0; margin-left: -10px; - transition: margin-left 0.2s ease, transform 0.2s ease; + transition: margin-left var(--dur-slow) ease, transform var(--dur-slow) ease; position: relative; } @@ -3283,16 +3283,16 @@ body.has-player .chat-fab { .feed-sort-btn { padding: 0.25rem 0.8rem; - border-radius: 6px; + border-radius: var(--radius-md); border: 2px solid var(--color-border); background: transparent; color: var(--color-text-secondary); cursor: pointer; - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; - transition: border-color 0.15s, background 0.15s, color 0.15s; + transition: border-color var(--dur-base), background var(--dur-base), color var(--dur-base); white-space: nowrap; flex-shrink: 0; } @@ -3344,7 +3344,7 @@ body.has-player .chat-fab { .dump-card, .playlist-card { border: 2px solid var(--color-border); - border-radius: 10px; + border-radius: var(--radius-xl); background: var(--color-surface); min-width: 0; } @@ -3359,7 +3359,7 @@ body.has-player .chat-fab { display: grid; grid-template-rows: 1fr; transition: - border-color 0.15s, + border-color var(--dur-base), grid-template-rows 0.32s ease, opacity 0.25s ease, filter 0.3s ease; @@ -3367,7 +3367,7 @@ body.has-player .chat-fab { .playlist-card { position: relative; - transition: border-color 0.15s; + transition: border-color var(--dur-base); } /* ── Shared card inner layout ── */ @@ -3464,13 +3464,13 @@ body.has-player .chat-fab { display: flex; align-items: center; justify-content: center; - border-radius: 6px; + border-radius: var(--radius-md); overflow: hidden; background: var(--color-bg); /* Subtle matte so any unfilled space (icons, off-ratio art) reads as intentional framing rather than a broken bar. */ box-shadow: inset 0 0 0 1px var(--color-border); - transition: transform 0.18s ease, box-shadow 0.18s ease; + transition: transform var(--dur-slow) ease, box-shadow var(--dur-slow) ease; } /* Feed thumbnails are mostly 16:9 (YouTube, og:image) — match that ratio so @@ -3496,7 +3496,7 @@ body.has-player .chat-fab { /* ── Shared card preview icon ── */ .dump-card-preview-icon, .playlist-card-icon { - font-size: 1.8rem; + font-size: var(--text-3xl); opacity: 0.7; line-height: 1; } @@ -3540,7 +3540,7 @@ body.has-player .chat-fab { } .thumb-placeholder-initials { - font-size: 1.25rem; + font-size: var(--text-xl); font-weight: 800; line-height: 1; opacity: 0.75; @@ -3550,15 +3550,15 @@ body.has-player .chat-fab { /* The initial has no intrinsic size, so scale it per surface. */ .dump-card-preview .thumb-placeholder-initials, .playlist-card-preview .thumb-placeholder-initials { - font-size: 1.9rem; + font-size: var(--text-3xl); } .journal-card-image .thumb-placeholder-initials { - font-size: 2.6rem; + font-size: var(--text-display); } .rich-content-thumbnail.thumb-placeholder .thumb-placeholder-initials { - font-size: 3rem; + font-size: var(--text-display); } /* `.rich-content-thumbnail` sizes an by width alone and lets the natural @@ -3608,11 +3608,11 @@ body.has-player .chat-fab { .dump-card-title, .playlist-card-title { font-weight: 600; - font-size: 1rem; + font-size: var(--text-base); color: var(--color-text); text-decoration: none; word-break: break-word; - transition: color 0.15s; + transition: color var(--dur-base); line-height: 1.35; } @@ -3639,7 +3639,7 @@ body.has-player .chat-fab { .dump-card-comment, .playlist-card-description { margin: 0; - font-size: 0.85rem; + font-size: var(--text-sm); opacity: 0.65; word-break: break-word; line-height: 1.4; @@ -3658,7 +3658,7 @@ body.has-player .chat-fab { /* ── Shared card meta row ── */ .dump-card-date, .playlist-card-meta { - font-size: 0.78rem; + font-size: var(--text-xs); opacity: 0.45; margin-top: 0.2rem; } @@ -3676,7 +3676,7 @@ body.has-player .chat-fab { .dump-edited-label, .playlist-edited-label { - font-size: 0.72rem; + font-size: var(--text-2xs); opacity: 0.5; font-style: italic; } @@ -3727,12 +3727,12 @@ body.has-player .chat-fab { /* ── Playlist badge ── */ .playlist-badge { display: inline-block; - font-size: 0.7rem; + font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; padding: 0.1rem 0.45rem; - border-radius: 4px; + border-radius: var(--radius-sm); background: color-mix(in srgb, var(--color-accent) 20%, transparent); color: var(--color-accent); } @@ -3763,7 +3763,7 @@ body.has-player .chat-fab { right: 0.4rem; color: var(--color-text); opacity: 0; - font-size: 0.8rem; + font-size: var(--text-xs); padding: 0.2rem 0.35rem; } @@ -3784,7 +3784,7 @@ body.has-player .chat-fab { display: flex; align-items: center; justify-content: center; - z-index: 1000; + z-index: var(--z-modal); padding: 1rem; } @@ -3792,8 +3792,8 @@ body.has-player .chat-fab { .modal-card, .confirm-modal { background: var(--color-surface); - border-radius: 12px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-3); width: 100%; } @@ -3810,7 +3810,7 @@ body.has-player .chat-fab { .dump-create-success { margin-bottom: 1rem; - font-size: 0.95rem; + font-size: var(--text-md); color: var(--color-text-muted); } @@ -3837,12 +3837,12 @@ body.has-player .chat-fab { .modal-title { font-weight: 700; - font-size: 1rem; + font-size: var(--text-base); } .modal-close-btn { color: var(--color-text); - font-size: 1rem; + font-size: var(--text-base); opacity: 0.6; padding: 0.25rem; } @@ -3927,7 +3927,7 @@ body.has-player .chat-fab { /* Brief highlight when a message is jumped to via a reply reference. */ .chat-message { - border-radius: 8px; + border-radius: var(--radius-lg); transition: background-color 0.4s ease; } @@ -3953,7 +3953,7 @@ body.has-player .chat-fab { } .chat-day-sep-label { - font-size: 0.7rem; + font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; @@ -3974,7 +3974,7 @@ body.has-player .chat-fab { .chat-message-author { font-weight: 700; - font-size: 0.85rem; + font-size: var(--text-sm); color: inherit; text-decoration: none; } @@ -3984,12 +3984,12 @@ body.has-player .chat-fab { } .chat-message-time { - font-size: 0.7rem; + font-size: var(--text-2xs); color: var(--color-text-muted); } .chat-message-text { - font-size: 0.9rem; + font-size: var(--text-md); } .chat-message-text.md { @@ -3997,7 +3997,7 @@ body.has-player .chat-fab { } .chat-message-edited { - font-size: 0.72rem; + font-size: var(--text-2xs); color: var(--color-text-muted); opacity: 0.7; font-style: italic; @@ -4011,7 +4011,7 @@ body.has-player .chat-fab { display: inline-flex; gap: 0.15rem; opacity: 0; - transition: opacity 0.15s; + transition: opacity var(--dur-base); } .chat-message:hover .chat-message-actions, @@ -4030,11 +4030,11 @@ body.has-player .chat-fab { background: none; border: none; padding: 0 0.1rem; - font-size: 0.8rem; + font-size: var(--text-xs); line-height: 1; color: var(--color-text-muted); cursor: pointer; - transition: color 0.15s; + transition: color var(--dur-base); } .chat-icon-btn:hover { @@ -4061,7 +4061,7 @@ body.has-player .chat-fab { bulky for the narrow message column. */ .chat-edit-actions .btn-primary, .chat-edit-actions .btn-secondary { - font-size: 0.8rem; + font-size: var(--text-xs); padding: 0.25rem 0.7rem; box-shadow: none; } @@ -4115,7 +4115,7 @@ body.has-player .chat-fab { background: none; border: none; font: inherit; - font-size: 0.74rem; + font-size: var(--text-xs); color: var(--color-text-muted); cursor: pointer; text-align: left; @@ -4139,7 +4139,7 @@ body.has-player .chat-fab { .chat-reply-ref-author { font-weight: 700; flex-shrink: 0; - transition: color 0.15s; + transition: color var(--dur-base); } .chat-reply-ref-text { @@ -4147,7 +4147,7 @@ body.has-player .chat-fab { text-overflow: ellipsis; white-space: nowrap; opacity: 0.85; - transition: color 0.15s; + transition: color var(--dur-base); } /* ── Reply composer bar (subtle, above the input) ── */ @@ -4158,9 +4158,9 @@ body.has-player .chat-fab { flex-shrink: 0; padding: 0.35rem 0.6rem; border-left: 2px solid var(--color-accent); - border-radius: 4px; + border-radius: var(--radius-sm); background: color-mix(in srgb, var(--color-accent) 8%, transparent); - font-size: 0.78rem; + font-size: var(--text-xs); color: var(--color-text-muted); } @@ -4193,7 +4193,7 @@ body.has-player .chat-fab { .chat-reply-bar-cancel { margin-left: auto; flex-shrink: 0; - font-size: 0.85rem; + font-size: var(--text-sm); } /* ── "Is typing" indicator (reuses presence avatars) ── */ @@ -4203,7 +4203,7 @@ body.has-player .chat-fab { gap: 0.45rem; flex-shrink: 0; min-height: 1.25rem; - font-size: 0.76rem; + font-size: var(--text-xs); color: var(--color-text-muted); } @@ -4315,7 +4315,7 @@ body.has-player .chat-fab { .confirm-modal-message { margin: 0; - font-size: 0.95rem; + font-size: var(--text-md); line-height: 1.5; } @@ -4342,9 +4342,9 @@ body.has-player .chat-fab { align-items: center; gap: 0.75rem; padding: 0.6rem 0.75rem; - border-radius: 8px; + border-radius: var(--radius-lg); cursor: pointer; - transition: background 0.15s; + transition: background var(--dur-base); } .playlist-membership-row:hover { @@ -4364,7 +4364,7 @@ body.has-player .chat-fab { } .playlist-membership-check { - font-size: 1rem; + font-size: var(--text-base); color: var(--color-accent); width: 1.2rem; text-align: center; @@ -4375,14 +4375,14 @@ body.has-player .chat-fab { .modal-new-item-toggle { background: none; border: 1px dashed var(--color-border-subtle); - border-radius: 8px; + border-radius: var(--radius-lg); color: var(--color-accent); cursor: pointer; padding: 0.6rem 1rem; - font-size: 0.9rem; + font-size: var(--text-md); text-align: left; width: 100%; - transition: border-color 0.15s, background 0.15s; + transition: border-color var(--dur-base), background var(--dur-base); } .modal-new-item-toggle:hover { @@ -4393,7 +4393,7 @@ body.has-player .chat-fab { /* ── Playlist detail page ── */ .playlist-detail-header { background: var(--color-surface); - border-radius: 12px; + border-radius: var(--radius-xl); padding: 1.25rem; } @@ -4408,7 +4408,7 @@ body.has-player .chat-fab { width: 72px; height: 72px; object-fit: cover; - border-radius: 8px; + border-radius: var(--radius-lg); border: 1px solid var(--color-border); } @@ -4426,13 +4426,13 @@ body.has-player .chat-fab { .playlist-detail-title { margin: 0; - font-size: 1.5rem; + font-size: var(--text-2xl); font-weight: 700; word-break: break-word; } .playlist-detail-description { - font-size: 1rem; + font-size: var(--text-base); margin: 0 0 0.5rem; opacity: 0.75; line-height: 1.75; @@ -4444,7 +4444,7 @@ body.has-player .chat-fab { display: flex; align-items: center; gap: 0.6rem; - font-size: 0.82rem; + font-size: var(--text-sm); opacity: 0.6; } @@ -4471,13 +4471,13 @@ body.has-player .chat-fab { .playlist-edit-btn { background: none; border: 1px solid var(--color-border-subtle); - border-radius: 6px; + border-radius: var(--radius-md); cursor: pointer; color: var(--color-text); - font-size: 0.85rem; + font-size: var(--text-sm); padding: 0.25rem 0.7rem; opacity: 0.7; - transition: opacity 0.15s, border-color 0.15s, color 0.15s; + transition: opacity var(--dur-base), border-color var(--dur-base), color var(--dur-base); } .playlist-edit-btn:hover, @@ -4490,7 +4490,7 @@ body.has-player .chat-fab { .playlist-edit-input, .playlist-edit-textarea { width: 100%; - font-size: 0.95rem; + font-size: var(--text-md); padding: 0.4rem 0.65rem; } @@ -4501,7 +4501,7 @@ body.has-player .chat-fab { } .playlist-edit-input { - font-size: 1.1rem; + font-size: var(--text-lg); font-weight: 700; } @@ -4527,8 +4527,8 @@ body.has-player .chat-fab { align-items: center; gap: 0.5rem; padding: 0 0.25rem; - transition: background 0.15s; - border-radius: 12px; + transition: background var(--dur-base); + border-radius: var(--radius-xl); } .playlist-dump-item--drag-over { @@ -4546,7 +4546,7 @@ body.has-player .chat-fab { flex-shrink: 0; color: var(--color-text); opacity: 0.4; - font-size: 0.85rem; + font-size: var(--text-sm); padding: 0.25rem 0.35rem; } @@ -4562,17 +4562,17 @@ body.has-player .chat-fab { cursor: pointer; color: var(--color-text); opacity: 0.7; - font-size: 0.78rem; + font-size: var(--text-xs); padding: 0.2rem 0.5rem; - border-radius: 4px; - transition: opacity 0.15s, border-color 0.15s, color 0.15s; + border-radius: var(--radius-sm); + transition: opacity var(--dur-base), border-color var(--dur-base), color var(--dur-base); white-space: nowrap; } .drag-handle { cursor: grab; opacity: 0.35; - font-size: 1.1rem; + font-size: var(--text-lg); flex-shrink: 0; user-select: none; padding: 0 0.25rem; @@ -4589,14 +4589,14 @@ body.has-player .chat-fab { justify-content: center; padding: 0.25rem 0.6rem; border: 2px solid var(--color-border); - border-radius: 8px; + border-radius: var(--radius-lg); background: none; cursor: pointer; color: var(--color-text); - font-size: 0.78rem; + font-size: var(--text-xs); font-weight: 600; white-space: nowrap; - transition: border-color 0.15s, color 0.15s; + transition: border-color var(--dur-base), color var(--dur-base); } .btn-add-playlist:hover { @@ -4610,9 +4610,9 @@ body.has-player .chat-fab { border: none; cursor: pointer; color: var(--color-accent); - font-size: 0.85rem; + font-size: var(--text-sm); padding: 0; - transition: opacity 0.15s; + transition: opacity var(--dur-base); white-space: nowrap; } @@ -4622,18 +4622,18 @@ body.has-player .chat-fab { /* ── Dump card comment count ── */ .dump-card-comment-count { - font-size: 0.72rem; + font-size: var(--text-2xs); color: var(--color-text-muted); } /* ── Dump card private badge ── */ .dump-card-private-badge { - font-size: 0.68rem; + font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.1em 0.45em; - border-radius: 4px; + border-radius: var(--radius-sm); background: color-mix(in srgb, var(--color-text-muted) 18%, transparent); color: var(--color-text-muted); } @@ -4648,7 +4648,7 @@ body.has-player .chat-fab { .comment-section-title, .related-section-title { - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 700; color: var(--color-text-muted); margin: 0 0 1.25rem; @@ -4671,10 +4671,10 @@ body.has-player .chat-fab { .related-section .dump-card { border-width: 1px; - border-radius: 8px; + border-radius: var(--radius-lg); background: transparent; opacity: 0.78; - transition: border-color 0.15s, opacity 0.15s; + transition: border-color var(--dur-base), opacity var(--dur-base); } .related-section .dump-card:hover { @@ -4693,12 +4693,12 @@ body.has-player .chat-fab { } .related-section .dump-card-title { - font-size: 0.88rem; + font-size: var(--text-sm); } /* Keep just enough description to orient, but only a single muted line. */ .related-section .dump-card-comment { - font-size: 0.78rem; + font-size: var(--text-xs); -webkit-line-clamp: 1; line-clamp: 1; } @@ -4715,10 +4715,10 @@ body.has-player .chat-fab { tightened treatment the backlink dump cards do. */ .collections-section .playlist-card { border-width: 1px; - border-radius: 8px; + border-radius: var(--radius-lg); background: transparent; opacity: 0.78; - transition: border-color 0.15s, opacity 0.15s; + transition: border-color var(--dur-base), opacity var(--dur-base); } .collections-section .playlist-card:hover { @@ -4737,15 +4737,15 @@ body.has-player .chat-fab { } .collections-section .playlist-card-icon { - font-size: 1.15rem; + font-size: var(--text-lg); } .collections-section .playlist-card-title { - font-size: 0.88rem; + font-size: var(--text-sm); } .collections-section .playlist-card-description { - font-size: 0.78rem; + font-size: var(--text-xs); -webkit-line-clamp: 1; line-clamp: 1; } @@ -4775,9 +4775,9 @@ body.has-player .chat-fab { display: flex; gap: 0.75rem; padding: 0.75rem 0.85rem; - border-radius: 8px; + border-radius: var(--radius-lg); background: var(--color-surface); - transition: background 0.12s; + transition: background var(--dur-fast); } .comment-node-inner:hover { @@ -4807,7 +4807,7 @@ body.has-player .chat-fab { .comment-author { font-weight: 700; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-accent); text-decoration: none; } @@ -4817,7 +4817,7 @@ body.has-player .chat-fab { } .comment-time { - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-muted); text-decoration: none; } @@ -4835,19 +4835,19 @@ body.has-player .chat-fab { } } .comment-node--highlight { - border-radius: 6px; + border-radius: var(--radius-md); animation: comment-highlight 2s ease-out forwards; } .comment-edited { - font-size: 0.72rem; + font-size: var(--text-2xs); color: var(--color-text-muted); opacity: 0.7; font-style: italic; } .comment-body { - font-size: 0.9rem; + font-size: var(--text-md); line-height: 1.65; color: var(--color-text); overflow-wrap: break-word; @@ -4863,13 +4863,13 @@ body.has-player .chat-fab { .comment-action-btn { background: none; border: 1px solid transparent; - border-radius: 4px; + border-radius: var(--radius-sm); padding: 0.15rem 0.45rem; - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-muted); cursor: pointer; font-family: inherit; - transition: color 0.1s, border-color 0.1s, background 0.1s; + transition: color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast); } .comment-action-btn:hover { @@ -4918,7 +4918,7 @@ body.has-player .chat-fab { margin-bottom: 1.5rem; padding: 1rem; background: var(--color-surface); - border-radius: 8px; + border-radius: var(--radius-lg); border: 1px solid var(--color-border-subtle); } @@ -4941,15 +4941,15 @@ body.has-player .chat-fab { box-sizing: border-box; background: var(--color-bg); border: 1px solid var(--color-border-subtle); - border-radius: 6px; + border-radius: var(--radius-md); padding: 0.55rem 0.75rem; font-family: inherit; - font-size: 0.875rem; + font-size: var(--text-sm); color: var(--color-text); resize: none; overflow: hidden; min-height: 2.4rem; - transition: border-color 0.15s, box-shadow 0.15s; + transition: border-color var(--dur-base), box-shadow var(--dur-base); } .comment-reply-textarea:focus { @@ -4969,13 +4969,13 @@ body.has-player .chat-fab { background: var(--color-accent); color: #fff; border: none; - border-radius: 6px; + border-radius: var(--radius-md); padding: 0.4rem 1rem; font-family: inherit; - font-size: 0.82rem; + font-size: var(--text-sm); font-weight: 700; cursor: pointer; - transition: background 0.15s, opacity 0.15s; + transition: background var(--dur-base), opacity var(--dur-base); letter-spacing: 0.02em; } @@ -4991,14 +4991,14 @@ body.has-player .chat-fab { .comment-cancel-btn { background: transparent; border: 1.5px solid var(--color-border-subtle); - border-radius: 6px; + border-radius: var(--radius-md); padding: 0.4rem 1rem; font-family: inherit; - font-size: 0.82rem; + font-size: var(--text-sm); color: var(--color-text); opacity: 0.6; cursor: pointer; - transition: opacity 0.15s; + transition: opacity var(--dur-base); } .comment-cancel-btn:hover { @@ -5019,7 +5019,7 @@ body.has-player .chat-fab { } .comment-deleted-placeholder { - font-size: 0.85rem; + font-size: var(--text-sm); font-style: italic; color: var(--color-text-muted); margin: 0; @@ -5042,7 +5042,7 @@ body.has-player .chat-fab { justify-content: space-between; gap: 0.75rem; padding: 0.4rem 0.5rem; - border-radius: 6px; + border-radius: var(--radius-md); } .followed-user-card-link { @@ -5060,7 +5060,7 @@ body.has-player .chat-fab { } .followed-user-card-name { - font-size: 0.9rem; + font-size: var(--text-md); font-weight: 600; overflow: hidden; text-overflow: ellipsis; @@ -5134,7 +5134,7 @@ body.has-player .chat-fab { gap: 0.5rem; color: var(--color-text); text-decoration: none; - font-size: 0.9rem; + font-size: var(--text-md); font-weight: 600; } @@ -5144,23 +5144,23 @@ body.has-player .chat-fab { .invite-tree-empty { color: var(--color-text-muted); - font-size: 0.9rem; + font-size: var(--text-md); } /* ── Follow button ── */ .follow-btn { padding: 0.25rem 0.9rem; - border-radius: 6px; + border-radius: var(--radius-md); border: 2px solid var(--color-accent); background: transparent; color: var(--color-accent); cursor: pointer; - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; font-family: inherit; - transition: background 0.15s, color 0.15s; + transition: background var(--dur-base), color var(--dur-base); } .follow-btn:hover, @@ -5240,23 +5240,23 @@ body.has-player .chat-fab { display: flex; flex-direction: column; border: 2px solid var(--color-border); - border-radius: 12px; + border-radius: var(--radius-xl); background: var(--color-surface); overflow: hidden; cursor: pointer; min-width: 0; - transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s; + transition: border-color var(--dur-base), transform var(--dur-base), box-shadow var(--dur-base); } .journal-card:hover { border-color: var(--color-accent); transform: translateY(-2px); - box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18); + box-shadow: var(--shadow-2); } .journal-card-title { font-weight: 600; - font-size: 0.95rem; + font-size: var(--text-md); color: var(--color-text); text-decoration: none; line-height: 1.3; @@ -5280,7 +5280,7 @@ body.has-player .chat-fab { display: flex; align-items: center; gap: 0.5rem; - font-size: 0.74rem; + font-size: var(--text-xs); color: var(--color-text-secondary); flex-wrap: wrap; min-width: 0; @@ -5341,7 +5341,7 @@ body.has-player .chat-fab { } .journal-card--image .journal-card-comment { - font-size: 0.82rem; + font-size: var(--text-sm); line-height: 1.4; margin: 0; color: rgba(255, 255, 255, 0.85); @@ -5350,13 +5350,13 @@ body.has-player .chat-fab { } .journal-card--feature .journal-card-title { - font-size: 1.25rem; + font-size: var(--text-xl); -webkit-line-clamp: 3; line-clamp: 3; } .journal-card--square.journal-card--image .journal-card-title { - font-size: 0.85rem; + font-size: var(--text-sm); } /* ── Quote cards — the note is the subject, on an accent wash ── */ @@ -5380,9 +5380,9 @@ body.has-player .chat-fab { .journal-card-quote-body { position: relative; - z-index: 1; + z-index: var(--z-raised); margin: 0; - font-size: 0.92rem; + font-size: var(--text-md); line-height: 1.45; color: var(--color-text); -webkit-line-clamp: 3; @@ -5391,7 +5391,7 @@ body.has-player .chat-fab { .journal-card--wide.journal-card--quote .journal-card-quote-body, .journal-card--feature.journal-card--quote .journal-card-quote-body { - font-size: 1rem; + font-size: var(--text-base); -webkit-line-clamp: 2; line-clamp: 2; } @@ -5405,7 +5405,7 @@ body.has-player .chat-fab { } .journal-card--quote .journal-card-title { - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 600; color: var(--color-text-secondary); -webkit-line-clamp: 1; @@ -5423,12 +5423,12 @@ body.has-player .chat-fab { } .journal-card-glyph { - font-size: 1.5rem; + font-size: var(--text-2xl); line-height: 1; } .journal-card--text .journal-card-title { - font-size: 0.92rem; + font-size: var(--text-md); -webkit-line-clamp: 3; line-clamp: 3; } @@ -5441,7 +5441,7 @@ body.has-player .chat-fab { .feed-end { text-align: center; padding: 1.5rem 1rem; - font-size: 0.82rem; + font-size: var(--text-sm); color: var(--color-text-secondary); opacity: 0.55; } @@ -5513,11 +5513,11 @@ body.has-player .chat-fab { background: var(--color-header-user-bg); border: none; cursor: pointer; - font-size: 0.95rem; + font-size: var(--text-md); font-weight: 600; padding: 0.35rem 0.85rem; - border-radius: 8px; - transition: background 0.15s; + border-radius: var(--radius-lg); + transition: background var(--dur-base); display: inline-flex; align-items: center; } @@ -5537,11 +5537,11 @@ body.has-player .chat-fab { right: -3px; background: var(--color-danger); color: #fff; - font-size: 0.6rem; + font-size: var(--text-2xs); font-weight: 700; min-width: 16px; height: 16px; - border-radius: 8px; + border-radius: var(--radius-lg); display: flex; align-items: center; justify-content: center; @@ -5557,11 +5557,11 @@ body.has-player .chat-fab { background: var(--color-header-user-bg); border: none; cursor: pointer; - font-size: 0.95rem; + font-size: var(--text-md); font-weight: 600; padding: 0.35rem 0.85rem; - border-radius: 8px; - transition: background 0.15s; + border-radius: var(--radius-lg); + transition: background var(--dur-base); display: inline-flex; align-items: center; } @@ -5586,7 +5586,7 @@ body.has-player .chat-fab { margin-bottom: 1.75rem; } .notifications-title { - font-size: 1.4rem; + font-size: var(--text-2xl); font-weight: 700; margin: 0; display: flex; @@ -5594,15 +5594,15 @@ body.has-player .chat-fab { gap: 0.5rem; } .notifications-title-bell { - font-size: 1.2rem; + font-size: var(--text-lg); } .notifications-unread-pill { - font-size: 0.75rem; + font-size: var(--text-xs); font-weight: 700; background: color-mix(in srgb, var(--color-danger) 18%, transparent); color: var(--color-danger); border: 1px solid color-mix(in srgb, var(--color-danger) 35%, transparent); - border-radius: 12px; + border-radius: var(--radius-xl); padding: 0.2rem 0.65rem; white-space: nowrap; } @@ -5612,7 +5612,7 @@ body.has-player .chat-fab { color: var(--color-text-muted); } .notifications-empty-icon { - font-size: 2.5rem; + font-size: var(--text-display); display: block; margin-bottom: 0.75rem; opacity: 0.5; @@ -5621,7 +5621,7 @@ body.has-player .chat-fab { margin: 0.25rem 0; } .notifications-empty-hint { - font-size: 0.85rem; + font-size: var(--text-sm); max-width: 340px; margin: 0.5rem auto 0 !important; line-height: 1.5; @@ -5631,7 +5631,7 @@ body.has-player .chat-fab { margin-bottom: 2rem; } .notif-group-label { - font-size: 0.68rem; + font-size: var(--text-2xs); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; @@ -5657,10 +5657,10 @@ body.has-player .chat-fab { } .notification-item { background: var(--color-surface); - border-radius: 10px; + border-radius: var(--radius-xl); border: 1px solid var(--color-border-subtle); border-left: 3px solid transparent; - transition: background 0.12s, border-color 0.12s; + transition: background var(--dur-fast), border-color var(--dur-fast); overflow: hidden; } .notification-item:hover { @@ -5702,7 +5702,7 @@ body.has-player .chat-fab { display: flex; align-items: center; justify-content: center; - font-size: 0.9rem; + font-size: var(--text-md); flex-shrink: 0; } .notif-icon--upvote { @@ -5731,12 +5731,12 @@ body.has-player .chat-fab { } .notification-content { flex: 1; - font-size: 0.875rem; + font-size: var(--text-sm); line-height: 1.5; min-width: 0; } .notification-time { - font-size: 0.72rem; + font-size: var(--text-2xs); color: var(--color-text-muted); white-space: nowrap; flex-shrink: 0; @@ -5747,11 +5747,11 @@ body.has-player .chat-fab { padding: 0.5rem 1.5rem; background: none; border: 1px solid var(--color-border-subtle); - border-radius: 6px; + border-radius: var(--radius-md); cursor: pointer; - font-size: 0.875rem; + font-size: var(--text-sm); color: var(--color-text-muted); - transition: border-color 0.15s, color 0.15s; + transition: border-color var(--dur-base), color var(--dur-base); } .load-more-btn:hover:not(:disabled) { border-color: var(--color-accent); @@ -5786,7 +5786,7 @@ body.has-player .chat-fab { .text-editor-count { display: block; text-align: right; - font-size: 0.7rem; + font-size: var(--text-2xs); color: var(--color-text-muted); margin-top: 2px; user-select: none; @@ -5805,15 +5805,15 @@ body.has-player .chat-fab { popup. Above the modal backdrop (1000), below tooltips (9999). */ .mention-dropdown { position: fixed; - z-index: 1100; + z-index: var(--z-popover); max-width: calc(100vw - 16px); list-style: none; margin: 0; padding: 4px 0; background: var(--color-surface); border: 1px solid var(--color-border); - border-radius: 8px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-2); max-height: var(--float-max-h, 220px); overflow-y: auto; } @@ -5823,14 +5823,14 @@ body.has-player .chat-fab { gap: 8px; padding: 6px 12px; cursor: pointer; - transition: background 0.1s; + transition: background var(--dur-fast); } .mention-dropdown-item:hover, .mention-dropdown-item--selected { background: var(--color-bg); } .mention-dropdown-username { - font-size: 0.9rem; + font-size: var(--text-md); color: var(--color-text); } @@ -5840,13 +5840,13 @@ body.has-player .chat-fab { Above the modal backdrop (1000), below tooltips (9999). */ .emoji-picker-float { position: fixed; - z-index: 1100; + z-index: var(--z-popover); width: 320px; max-width: calc(100vw - 16px); background: var(--color-surface); border: 1px solid var(--color-border); - border-radius: 8px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-2); overflow: hidden; } @@ -5865,7 +5865,7 @@ body.has-player .chat-fab { border: none; background: transparent; color: var(--color-text); - font-size: 0.9rem; + font-size: var(--text-md); outline: none; } .emoji-picker-float input::placeholder { @@ -5881,7 +5881,7 @@ body.has-player .chat-fab { color: var(--color-text); opacity: 0.45; cursor: pointer; - font-size: 0.75rem; + font-size: var(--text-xs); line-height: 1; } .emoji-picker-close-btn:hover { @@ -5894,7 +5894,7 @@ body.has-player .chat-fab { } .emoji-picker-float [frimousse-category-header] { padding: 4px 8px 2px; - font-size: 0.75rem; + font-size: var(--text-xs); font-weight: 600; color: var(--color-text-muted, #888); background: var(--color-surface); @@ -5909,8 +5909,8 @@ body.has-player .chat-fab { font-size: 1.35em; line-height: 1; cursor: pointer; - border-radius: 4px; - transition: background 0.1s; + border-radius: var(--radius-sm); + transition: background var(--dur-fast); } .emoji-picker-float [frimousse-emoji]:hover, .emoji-picker-float [frimousse-emoji][data-active] { @@ -5921,7 +5921,7 @@ body.has-player .chat-fab { display: block; padding: 16px; text-align: center; - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-text-muted, #888); } @@ -5936,13 +5936,13 @@ body.has-player .chat-fab { color: var(--color-text); border: 1px solid var(--color-border-subtle); padding: 0.3em 0.65em; - border-radius: 5px; - font-size: 0.78rem; + border-radius: var(--radius-sm); + font-size: var(--text-xs); font-style: normal; white-space: nowrap; pointer-events: none; - z-index: 9999; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); + z-index: var(--z-toast); + box-shadow: var(--shadow-2); } /* ── Search bar (in header center slot) ── */ @@ -5967,19 +5967,19 @@ body.has-player .chat-fab { .search-bar-input { flex: 1; padding: 0.3rem 0.7rem; - border-radius: 8px; + border-radius: var(--radius-lg); border: 2px solid var(--color-border-subtle); background: var(--color-bg); color: var(--color-text); - font-size: 0.875rem; + font-size: var(--text-sm); font-family: inherit; outline: none; transition: max-width 0.25s ease, - opacity 0.2s ease, + opacity var(--dur-slow) ease, padding 0.25s ease, border-width 0.25s ease, - border-color 0.15s; + border-color var(--dur-base); min-width: 0; } @@ -6011,11 +6011,11 @@ body.has-player .chat-fab { padding: 0.3rem 0.55rem; background: transparent; border: 2px solid var(--color-border-subtle); - border-radius: 8px; + border-radius: var(--radius-lg); cursor: pointer; - font-size: 0.875rem; + font-size: var(--text-sm); flex-shrink: 0; - transition: border-color 0.15s; + transition: border-color var(--dur-base); } .search-bar-btn:hover { @@ -6041,7 +6041,7 @@ body.has-player .chat-fab { padding: 3rem 1.25rem; color: var(--color-text-secondary); text-align: center; - font-size: 0.95rem; + font-size: var(--text-md); } /* ── User results ── */ @@ -6063,11 +6063,11 @@ body.has-player .chat-fab { gap: 0.2rem; padding: 0.75rem 1rem; background: var(--color-surface); - border-radius: 10px; + border-radius: var(--radius-xl); border: 2px solid var(--color-border-subtle); text-decoration: none; color: var(--color-text); - transition: border-color 0.15s; + transition: border-color var(--dur-base); } .user-result-item:hover { @@ -6076,11 +6076,11 @@ body.has-player .chat-fab { .user-result-name { font-weight: 600; - font-size: 0.95rem; + font-size: var(--text-md); } .user-result-description { - font-size: 0.85rem; + font-size: var(--text-sm); color: var(--color-text-secondary); white-space: nowrap; overflow: hidden; @@ -6116,7 +6116,7 @@ body.has-player .chat-fab { } .profile-appearance-label { - font-size: 0.85rem; + font-size: var(--text-sm); font-weight: 600; opacity: 0.7; } @@ -6172,7 +6172,7 @@ body.has-player .chat-fab { border-left: 0.26rem solid transparent; border-right: 0.26rem solid transparent; border-top: 0.3rem solid currentColor; - transition: transform 0.15s ease; + transition: transform var(--dur-base) ease; } .category-switcher-btn--open .category-switcher-caret { @@ -6184,14 +6184,14 @@ body.has-player .chat-fab { width: 2px; height: 1.05rem; background: var(--color-border); - border-radius: 1px; + border-radius: var(--radius-xs); flex-shrink: 0; } /* Themed popover (fixed-positioned so the row's overflow can't clip it). */ .category-switcher-menu { position: fixed; - z-index: 200; + z-index: var(--z-dropdown); min-width: 11rem; max-height: 60vh; overflow-y: auto; @@ -6203,8 +6203,8 @@ body.has-player .chat-fab { gap: 0.15rem; background: var(--color-surface); border: 2px solid var(--color-border-subtle); - border-radius: 10px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-2); } .category-switcher-option { @@ -6213,16 +6213,16 @@ body.has-player .chat-fab { text-align: left; padding: 0.45rem 0.75rem; border: none; - border-radius: 7px; + border-radius: var(--radius-md); background: transparent; color: var(--color-text); - font-size: 0.8rem; + font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; cursor: pointer; - transition: background 0.12s; + transition: background var(--dur-fast); } .category-switcher-option:hover { @@ -6244,10 +6244,10 @@ body.has-player .chat-fab { .category-chip-toggle { padding: 0.25rem 0.7rem; border: 1px solid var(--color-border); - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-bg); color: var(--color-text-secondary); - font-size: 0.85rem; + font-size: var(--text-sm); cursor: pointer; } @@ -6271,11 +6271,11 @@ body.has-player .chat-fab { .dump-card-category-chip { padding: 0.1rem 0.5rem; - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-header-user-bg); color: var(--color-text-secondary); text-decoration: none; - font-size: 0.75rem; + font-size: var(--text-xs); } .dump-card-category-chip:hover { @@ -6296,14 +6296,14 @@ body.has-player .chat-fab { align-items: center; padding: 0.35rem 0.85rem; border: 1px solid var(--color-border); - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-bg); color: var(--color-text); - font-size: 0.9rem; + font-size: var(--text-md); font-family: inherit; line-height: 1.4; cursor: pointer; - transition: border-color 0.15s, background 0.15s, color 0.15s, transform 0.1s; + transition: border-color var(--dur-base), background var(--dur-base), color var(--dur-base), transform var(--dur-fast); } .category-chip:hover:not(:disabled) { @@ -6347,7 +6347,7 @@ body.has-player .chat-fab { gap: 0.3rem; padding: 0.2rem 0.3rem 0.2rem 0.7rem; border: 1px solid var(--color-accent); - border-radius: 999px; + border-radius: var(--radius-full); background: var(--color-bg); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 16%, transparent); @@ -6371,7 +6371,7 @@ body.has-player .chat-fab { border: none; background: transparent; color: var(--color-text); - font-size: 0.9rem; + font-size: var(--text-md); font-family: inherit; padding: 0.2rem 0; outline: none; @@ -6407,13 +6407,13 @@ body.has-player .chat-fab { height: 1.75rem; padding: 0; border: none; - border-radius: 999px; + border-radius: var(--radius-full); background: transparent; color: var(--color-text-secondary); - font-size: 0.8rem; + font-size: var(--text-xs); line-height: 1; cursor: pointer; - transition: background 0.15s, color 0.15s, filter 0.15s; + transition: background var(--dur-base), color var(--dur-base), filter var(--dur-base); } .category-editor-btn:hover:not(:disabled) { diff --git a/src/index.css b/src/index.css index 79b66f1c..6c54514a 100644 --- a/src/index.css +++ b/src/index.css @@ -36,7 +36,7 @@ h1 { } button { - border-radius: 8px; + border-radius: var(--radius-lg); border: 1px solid var(--color-border); padding: 0.6em 1.2em; font-size: 1em; @@ -44,7 +44,7 @@ button { font-family: inherit; background-color: var(--color-surface); cursor: pointer; - transition: border-color 0.25s, background-color 0.2s; + transition: border-color 0.25s, background-color var(--dur-slow); } button:hover { border-color: var(--color-accent); diff --git a/src/main.tsx b/src/main.tsx index a89e1300..9a67ebf7 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,6 +5,7 @@ import { I18nProvider } from "@lingui/react"; import App from "./App.tsx"; import { i18n, loadCatalog } from "./i18n.ts"; +import "./tokens.css"; import "./index.css"; import "./themes/smooth.css"; import "./themes/brutalist.css"; diff --git a/src/themes/smooth.css b/src/themes/smooth.css index 22153464..923d29c2 100644 --- a/src/themes/smooth.css +++ b/src/themes/smooth.css @@ -1,14 +1,17 @@ /* ══════════════════════════════════════════════════════════════════════ Smooth theme — clean, modern, Saira typeface - Palette: Prussian Blue · Deep Teal · Jasmine · Brick Ember · Blood Red - Applied when data-style is absent or "smooth". + Dark: Prussian Blue · Deep Teal · Jasmine · Brick Ember · Blood Red + Light: Cream · Deep Teal · Terracotta + Applied when data-style is absent or "smooth". Also the base every other + theme builds on: anything a theme leaves unset falls back to these. + + Every colour is `light-dark(, )`, resolved against the + root `color-scheme` (see tokens.css), so auto / light / dark share this + one block. ══════════════════════════════════════════════════════════════════════ */ -/* ── Dark variant (default) ───────────────────────────────────────── */ :root, :root[data-style="smooth"] { - /* Global font defaults — other themes override --font-body; App.css styles - consume these variables rather than hard-coding font names. */ --font-body: "Saira", sans-serif; --font-mono: monospace; @@ -18,48 +21,55 @@ font-style: normal; line-height: 1.5; - color-scheme: light dark; - /* Text */ - --color-text: #eef0f3; - --color-text-secondary: #8aaabb; - --color-text-muted: #506878; - --color-on-accent: #001427; /* Prussian Blue on Jasmine */ + --color-text: light-dark(#0e3a42, #eef0f3); + --color-text-secondary: light-dark(#2c6671, #8aaabb); + --color-text-muted: light-dark(#5c8a91, #506878); + --color-on-accent: light-dark(#fef8e6, #001427); /* Surfaces */ - --color-bg: #001427; /* Prussian Blue */ - --color-surface: #0a1f35; + --color-bg: light-dark(#fef8e6, #001427); + --color-surface: light-dark(#fffdf6, #0a1f35); /* Borders */ --color-border: transparent; - --color-border-subtle: rgba(112, 141, 129, 0.2); /* Deep Teal tint */ + --color-border-subtle: light-dark( + rgba(48, 144, 161, 0.18), + rgba(112, 141, 129, 0.2) + ); /* Accent */ - --color-accent: #f4d58d; /* Jasmine */ - --color-accent-hover: #d4aa5a; + --color-accent: light-dark(#bc5148, #f4d58d); + --color-accent-hover: light-dark(#97392f, #d4aa5a); /* Links */ - --color-link: #f4d58d; - --color-link-hover: #d4aa5a; + --color-link: light-dark(#bc5148, #f4d58d); + --color-link-hover: light-dark(#97392f, #d4aa5a); /* Danger */ - --color-danger: #bf0603; /* Brick Ember */ - --color-danger-bg: #220404; - --color-danger-hover: #8d0801; /* Blood Red */ + --color-danger: light-dark(#bc5148, #bf0603); + --color-danger-bg: light-dark(#f8e3e0, #220404); + --color-danger-hover: light-dark(#97392f, #8d0801); /* Success */ - --color-success: #708d81; /* Deep Teal */ - --color-success-bg: #0d2820; - --color-success-hover: #8aaa9a; + --color-success: light-dark(#2e8a86, #708d81); + --color-success-bg: light-dark(#ddf2f1, #0d2820); + --color-success-hover: light-dark(#1f6b67, #8aaa9a); /* Overlays */ - --color-overlay: rgba(0, 10, 20, 0.55); - --color-header-user-bg: rgba(244, 213, 141, 0.06); - --color-header-user-bg-hover: rgba(244, 213, 141, 0.12); + --color-overlay: light-dark(rgba(14, 58, 66, 0.35), rgba(0, 10, 20, 0.55)); + --color-header-user-bg: light-dark( + rgba(188, 81, 72, 0.08), + rgba(244, 213, 141, 0.06) + ); + --color-header-user-bg-hover: light-dark( + rgba(188, 81, 72, 0.15), + rgba(244, 213, 141, 0.12) + ); /* Misc */ - --color-option-bg: #0d2340; - --color-option-border: #001427; + --color-option-bg: light-dark(#fff9ec, #0d2340); + --color-option-border: light-dark(#ece4cc, #001427); /* Service brand colors (fixed, not theme-dependent). `on-brand` is the foreground for text sitting on any of these — also fixed, so the contrast @@ -73,102 +83,6 @@ --color-on-brand: #fff; } -/* ── Light via system preference (auto color-scheme) ──────────────── */ -@media (prefers-color-scheme: light) { - :root:not([data-style]), - :root[data-style="smooth"]:not([data-color-scheme]) { - --color-text: #0e3a42; /* darkened deep teal */ - --color-text-secondary: #2c6671; - --color-text-muted: #5c8a91; - --color-on-accent: #fef8e6; /* cream on teal */ - - --color-bg: #fef8e6; /* cream */ - --color-surface: #fffdf6; - - --color-border: transparent; - --color-border-subtle: rgba(48, 144, 161, 0.18); - - --color-accent: #bc5148; /* terracotta — pops on cream bg */ - --color-accent-hover: #97392f; - - --color-link: #bc5148; - --color-link-hover: #97392f; - - --color-danger: #bc5148; /* terracotta */ - --color-danger-bg: #f8e3e0; - --color-danger-hover: #97392f; - - --color-success: #2e8a86; /* darkened light teal */ - --color-success-bg: #ddf2f1; - --color-success-hover: #1f6b67; - - --color-overlay: rgba(14, 58, 66, 0.35); - --color-header-user-bg: rgba(188, 81, 72, 0.08); - --color-header-user-bg-hover: rgba(188, 81, 72, 0.15); - - --color-option-bg: #fff9ec; - --color-option-border: #ece4cc; - } -} - -/* ── Manual dark override ─────────────────────────────────────────── */ -:root:not([data-style])[data-color-scheme="dark"], -:root[data-style="smooth"][data-color-scheme="dark"] { - color-scheme: dark; - --color-text: #eef0f3; - --color-text-secondary: #8aaabb; - --color-text-muted: #506878; - --color-on-accent: #001427; - --color-bg: #001427; - --color-surface: #0a1f35; - --color-border: transparent; - --color-border-subtle: rgba(112, 141, 129, 0.2); - --color-accent: #f4d58d; - --color-accent-hover: #d4aa5a; - --color-link: #f4d58d; - --color-link-hover: #d4aa5a; - --color-danger: #bf0603; - --color-danger-bg: #220404; - --color-danger-hover: #8d0801; - --color-success: #708d81; - --color-success-bg: #0d2820; - --color-success-hover: #8aaa9a; - --color-overlay: rgba(0, 10, 20, 0.55); - --color-header-user-bg: rgba(244, 213, 141, 0.06); - --color-header-user-bg-hover: rgba(244, 213, 141, 0.12); - --color-option-bg: #0d2340; - --color-option-border: #001427; -} - -/* ── Manual light override ────────────────────────────────────────── */ -:root:not([data-style])[data-color-scheme="light"], -:root[data-style="smooth"][data-color-scheme="light"] { - color-scheme: light; - --color-text: #0e3a42; - --color-text-secondary: #2c6671; - --color-text-muted: #5c8a91; - --color-on-accent: #fef8e6; - --color-bg: #fef8e6; - --color-surface: #fffdf6; - --color-border: transparent; - --color-border-subtle: rgba(48, 144, 161, 0.18); - --color-accent: #bc5148; - --color-accent-hover: #97392f; - --color-link: #bc5148; - --color-link-hover: #97392f; - --color-danger: #bc5148; - --color-danger-bg: #f8e3e0; - --color-danger-hover: #97392f; - --color-success: #2e8a86; - --color-success-bg: #ddf2f1; - --color-success-hover: #1f6b67; - --color-overlay: rgba(14, 58, 66, 0.35); - --color-header-user-bg: rgba(188, 81, 72, 0.08); - --color-header-user-bg-hover: rgba(188, 81, 72, 0.15); - --color-option-bg: #fff9ec; - --color-option-border: #ece4cc; -} - /* ══════════════════════════════════════════════════════════════════════ Structural overrides ══════════════════════════════════════════════════════════════════════ */ diff --git a/src/tokens.css b/src/tokens.css new file mode 100644 index 00000000..07b561db --- /dev/null +++ b/src/tokens.css @@ -0,0 +1,112 @@ +/* ══════════════════════════════════════════════════════════════════════ + Design tokens — shared by every theme. + Themes (src/themes/*.css) set the palette (`--color-*`) and may override + any of the shape/type/depth tokens below; App.css only consumes tokens. + ══════════════════════════════════════════════════════════════════════ */ + +:root { + /* ── Color scheme ── + `light-dark()` in the theme palettes resolves against this, so a single + palette block covers auto, forced-light and forced-dark. */ + color-scheme: light dark; + + /* ── Space (4px grid) ── */ + --space-1: 0.25rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-7: 2rem; + --space-8: 3rem; + + /* ── Radius ── */ + --radius-xs: 3px; + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-full: 999px; + + /* ── Type scale ── */ + --text-2xs: 0.7rem; + --text-xs: 0.78rem; + --text-sm: 0.85rem; + --text-md: 0.92rem; + --text-base: 1rem; + --text-lg: 1.15rem; + --text-xl: 1.25rem; + --text-2xl: 1.5rem; + --text-3xl: 2rem; + --text-display: 3rem; + + --leading-tight: 1.2; + --leading-snug: 1.35; + --leading-normal: 1.5; + + --weight-regular: 400; + --weight-medium: 500; + --weight-semibold: 600; + --weight-bold: 700; + + --tracking-caps: 0.06em; + + /* ── Fonts ── */ + --font-body: system-ui, sans-serif; + --font-display: var(--font-body); + --font-mono: ui-monospace, "SFMono-Regular", Menlo, monospace; + + /* ── Elevation ── */ + --shadow-1: 0 1px 2px rgb(0 0 0 / 0.12); + --shadow-2: 0 4px 16px rgb(0 0 0 / 0.2); + --shadow-3: 0 8px 32px rgb(0 0 0 / 0.45), 0 2px 8px rgb(0 0 0 / 0.3); + --shadow-focus: 0 0 0 3px var(--color-focus-ring); + + /* ── Motion ── */ + --ease-out: cubic-bezier(0.22, 1, 0.36, 1); + --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); + --dur-fast: 0.12s; + --dur-base: 0.15s; + --dur-slow: 0.2s; + + /* ── Layers ── */ + --z-raised: 1; + --z-sticky: 100; + --z-dropdown: 200; + --z-fab: 900; + --z-modal: 1000; + --z-popover: 1100; + --z-toast: 9999; + + /* ── Derived colors ── + Defaults computed from each theme's base palette, so every theme gets + the full semantic set; a theme overrides any of these when the derived + value isn't right for it. */ + --color-surface-raised: color-mix( + 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-focus-ring: color-mix(in srgb, var(--color-accent) 45%, transparent); + --color-warning: #d4a017; + --color-on-danger: #fff; + + /* Legacy names still referenced by a few rules. */ + --color-muted: var(--color-text-muted); + --color-error: var(--color-danger); + --color-surface-alt: var(--color-surface-raised); +} + +:root[data-color-scheme="light"] { + color-scheme: light; +} + +:root[data-color-scheme="dark"] { + color-scheme: dark; +}