From 3d165f92e0acb50db6e668df760a95578822c129 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Sat, 10 Oct 2026 19:58:54 +0800 Subject: [PATCH] fix(theme): use opaque surface tokens for modals and sticky layers The elevated surface tokens (--bg-elevated / --surface-elevated) are translucent, so sticky modal footers and table headers double-composited over the modal surface and showed a visible lighter seam in light themes. Add derived opaque tokens (--bg-elevated-solid / --surface-elevated-solid, aliased as --lora-surface-solid) and use them for .modal-content, the download/import modal sticky action footers, and the refresh result table's sticky header, so the modal surface and its sticky layers always share one opaque color across every theme and preset. --- static/css/base.css | 2 ++ static/css/components/import-modal.css | 5 ++++- static/css/components/metadata-refresh-result.css | 6 ++++-- static/css/components/modal/_base.css | 7 +++++-- static/css/components/modal/download-modal.css | 5 ++++- static/css/tokens/colors.css | 11 +++++++++++ 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/static/css/base.css b/static/css/base.css index 8dc5f0f1..22e351bf 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -65,6 +65,7 @@ body { --lora-accent: var(--color-accent); --lora-surface: var(--bg-elevated); + --lora-surface-solid: var(--bg-elevated-solid); --lora-border: var(--border-subtle); --lora-text: var(--text-primary); --lora-error: var(--color-error); @@ -93,6 +94,7 @@ body { --lora-accent: var(--color-accent); --lora-surface: var(--bg-elevated); + --lora-surface-solid: var(--bg-elevated-solid); --lora-border: var(--border-subtle); --lora-text: var(--text-primary); --lora-error: var(--color-error); diff --git a/static/css/components/import-modal.css b/static/css/components/import-modal.css index 2af575ce..81cf1fe5 100644 --- a/static/css/components/import-modal.css +++ b/static/css/components/import-modal.css @@ -24,7 +24,10 @@ position: sticky; bottom: 0; z-index: 1; - background: var(--lora-surface); + /* Solid surface: must fully mask the step content scrolling underneath; + the translucent --lora-surface would double-composite over the modal + surface and show a seam in light themes. */ + background: var(--lora-surface-solid); border-top: 1px solid var(--lora-border); padding-top: var(--space-2); padding-bottom: var(--space-1); diff --git a/static/css/components/metadata-refresh-result.css b/static/css/components/metadata-refresh-result.css index b33bf85d..40077614 100644 --- a/static/css/components/metadata-refresh-result.css +++ b/static/css/components/metadata-refresh-result.css @@ -100,7 +100,9 @@ .failure-table th { position: sticky; top: 0; - background: var(--lora-surface); + /* Solid surface: the sticky header must fully mask the rows scrolling + underneath; translucent --lora-surface would let them bleed through. */ + background: var(--lora-surface-solid); border-bottom: 1px solid var(--lora-border); padding: var(--space-1) var(--space-2); text-align: left; @@ -163,7 +165,7 @@ } [data-theme="dark"] .failure-table th { - background: var(--lora-surface); + background: var(--lora-surface-solid); } [data-theme="dark"] .failure-table td { diff --git a/static/css/components/modal/_base.css b/static/css/components/modal/_base.css index bd37b52b..5161f913 100644 --- a/static/css/components/modal/_base.css +++ b/static/css/components/modal/_base.css @@ -37,7 +37,10 @@ body.modal-open { height: auto; max-height: calc(100vh - var(--header-height, 48px) - 5.5rem); /* Subtract header height and modal margins */ margin: 1rem auto; /* Keep reduced top margin */ - background: var(--lora-surface); + /* Opaque surface: the modal stacks above the backdrop, and sticky layers + inside (action footers, table headers) share this same solid token so + they cannot double-composite into a visible seam (light themes). */ + background: var(--lora-surface-solid); border-radius: var(--border-radius-base); padding: var(--space-3); border: 1px solid var(--lora-border); @@ -174,7 +177,7 @@ body.modal-open { /* Dark theme unified styles */ [data-theme="dark"] .modal-content { - background: var(--lora-surface); + background: var(--lora-surface-solid); border: 1px solid var(--lora-border); } diff --git a/static/css/components/modal/download-modal.css b/static/css/components/modal/download-modal.css index 1ea968ff..0258942c 100644 --- a/static/css/components/modal/download-modal.css +++ b/static/css/components/modal/download-modal.css @@ -789,7 +789,10 @@ position: sticky; bottom: 0; z-index: 1; - background: var(--lora-surface); + /* Solid surface: must fully mask the step content scrolling underneath; + the translucent --lora-surface would double-composite over the modal + surface and show a seam in light themes. */ + background: var(--lora-surface-solid); border-top: 1px solid var(--lora-border); padding-top: var(--space-2); padding-bottom: var(--space-1); diff --git a/static/css/tokens/colors.css b/static/css/tokens/colors.css index 6310a347..61d95094 100644 --- a/static/css/tokens/colors.css +++ b/static/css/tokens/colors.css @@ -82,6 +82,17 @@ --favorite-glow: oklch(65% 0.15 85 / 0.5); } +/* Opaque variants of the elevated surfaces. The elevated tokens are + translucent; a layer stacked on top of an elevated surface (sticky modal + footers, sticky table headers) must use the solid variant, otherwise the + translucent layer double-composites over the surface and shows as a + visible seam in light themes. Derived here so every theme/preset override + of the source tokens is picked up automatically. */ +:root { + --bg-elevated-solid: oklch(from var(--bg-elevated) l c h / 1); + --surface-elevated-solid: oklch(from var(--surface-elevated) l c h / 1); +} + :root[data-theme="dark"] { --bg-base: #1a1a1a; --bg-elevated: oklch(25% 0.02 256 / 0.98);