fix(ui): move all :is(.dark) component class rules outside @layer
Rules inside @layer components lose to unlayered styles in the CSS cascade, causing dark mode overrides to be silently ignored. Move ALL :is(.dark) rules for app-surface, app-surface-strong, app-toolbar, app-input, app-select, app-label, app-page-title, app-page-subtitle, app-data-table, and action classes outside @layer — the same fix that resolved app-data-table white bg. Also switch app-surface/strong from background: shorthand to separate background-color + background-image to ensure the dark surface-card base color is always applied independently of the gradient overlay. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -435,38 +435,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
|
/* Light mode only — dark overrides are ALL outside @layer to ensure they win */
|
||||||
|
|
||||||
.app-surface {
|
.app-surface {
|
||||||
@apply rounded-2xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900/90;
|
@apply rounded-2xl border border-gray-200 bg-white;
|
||||||
background: linear-gradient(145deg, #ffffff 0%, #fdfdfd 100%);
|
background-image: linear-gradient(145deg, #ffffff 0%, #fdfdfd 100%);
|
||||||
--tw-shadow: 0 1px 3px rgb(var(--accent-400) / 0.06), 0 4px 16px rgb(var(--accent-400) / 0.04);
|
--tw-shadow: 0 1px 3px rgb(var(--accent-400) / 0.06), 0 4px 16px rgb(var(--accent-400) / 0.04);
|
||||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-surface {
|
|
||||||
background: linear-gradient(135deg, rgba(255,255,255,0.055) 0%, rgba(255,255,255,0.018) 100%);
|
|
||||||
backdrop-filter: blur(16px);
|
|
||||||
-webkit-backdrop-filter: blur(16px);
|
|
||||||
border-color: rgba(255,255,255,0.09);
|
|
||||||
--tw-shadow: 0 2px 8px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.05), inset 0 1px 0 rgba(255,255,255,0.07);
|
|
||||||
box-shadow: var(--tw-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-surface-strong {
|
.app-surface-strong {
|
||||||
@apply rounded-3xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900;
|
@apply rounded-3xl border border-gray-200 bg-white;
|
||||||
background: linear-gradient(145deg, #ffffff 0%, #fdfdfd 100%);
|
background-image: linear-gradient(145deg, #ffffff 0%, #fdfdfd 100%);
|
||||||
--tw-shadow: 0 2px 8px rgb(var(--accent-400) / 0.06), 0 8px 24px rgb(var(--accent-400) / 0.04);
|
--tw-shadow: 0 2px 8px rgb(var(--accent-400) / 0.06), 0 8px 24px rgb(var(--accent-400) / 0.04);
|
||||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-surface-strong {
|
|
||||||
background: linear-gradient(135deg, rgba(255,255,255,0.065) 0%, rgba(255,255,255,0.022) 100%);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
border-color: rgba(255,255,255,0.10);
|
|
||||||
--tw-shadow: 0 4px 16px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.06), inset 0 1px 0 rgba(255,255,255,0.08);
|
|
||||||
box-shadow: var(--tw-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-toolbar {
|
.app-toolbar {
|
||||||
@apply sticky top-0 z-10 rounded-2xl border p-4;
|
@apply sticky top-0 z-10 rounded-2xl border p-4;
|
||||||
background: rgb(255 255 255 / 0.85);
|
background: rgb(255 255 255 / 0.85);
|
||||||
@@ -476,14 +460,6 @@
|
|||||||
box-shadow: 0 1px 3px rgb(var(--accent-400) / 0.06);
|
box-shadow: 0 1px 3px rgb(var(--accent-400) / 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-toolbar {
|
|
||||||
background: rgb(16 17 19 / 0.82);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
border-color: rgba(255,255,255,0.08);
|
|
||||||
box-shadow: 0 1px 0 rgba(255,255,255,0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-input {
|
.app-input {
|
||||||
@apply w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none transition;
|
@apply w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none transition;
|
||||||
}
|
}
|
||||||
@@ -494,41 +470,15 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-input {
|
|
||||||
background-color: rgb(var(--surface-input));
|
|
||||||
border-color: rgb(var(--border-input));
|
|
||||||
color: rgb(var(--text-primary));
|
|
||||||
}
|
|
||||||
|
|
||||||
:is(.dark) .app-input:focus {
|
|
||||||
border-color: rgb(var(--accent-400));
|
|
||||||
box-shadow: 0 0 0 3px rgba(var(--accent-400), 0.20), inset 0 0 8px rgba(var(--accent-400), 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-select {
|
.app-select {
|
||||||
@apply rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none transition;
|
@apply rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none transition;
|
||||||
@apply focus:border-brand-500 focus:ring-4 focus:ring-brand-100/80;
|
@apply focus:border-brand-500 focus:ring-4 focus:ring-brand-100/80;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-select {
|
|
||||||
background-color: rgb(var(--surface-input));
|
|
||||||
border-color: rgb(var(--border-input));
|
|
||||||
color: rgb(var(--text-primary));
|
|
||||||
}
|
|
||||||
|
|
||||||
:is(.dark) .app-select:focus {
|
|
||||||
border-color: rgb(var(--accent-400));
|
|
||||||
box-shadow: 0 0 0 3px rgb(var(--accent-400) / 0.20);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-label {
|
.app-label {
|
||||||
@apply mb-1.5 block text-[11px] font-semibold uppercase tracking-[0.18em] text-gray-500;
|
@apply mb-1.5 block text-[11px] font-semibold uppercase tracking-[0.18em] text-gray-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-label {
|
|
||||||
color: rgb(var(--text-very-muted));
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-page {
|
.app-page {
|
||||||
@apply p-6 md:p-8;
|
@apply p-6 md:p-8;
|
||||||
}
|
}
|
||||||
@@ -541,32 +491,14 @@
|
|||||||
@apply font-display text-3xl font-semibold text-gray-900;
|
@apply font-display text-3xl font-semibold text-gray-900;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-page-title {
|
|
||||||
background: linear-gradient(135deg, rgb(var(--accent-200)) 0%, rgb(var(--accent-100)) 50%, rgb(237 242 247) 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-clip: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-page-subtitle {
|
.app-page-subtitle {
|
||||||
@apply text-sm text-gray-500;
|
@apply text-sm text-gray-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-page-subtitle {
|
|
||||||
color: rgb(var(--text-muted));
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-data-table {
|
.app-data-table {
|
||||||
@apply overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm;
|
@apply overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Explicit dark rule — @apply dark: inside @layer components is unreliable */
|
|
||||||
:is(.dark) .app-data-table {
|
|
||||||
background-color: rgb(var(--surface-card));
|
|
||||||
border-color: rgb(var(--border-subtle));
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-data-table table {
|
.app-data-table table {
|
||||||
@apply min-w-full text-sm;
|
@apply min-w-full text-sm;
|
||||||
}
|
}
|
||||||
@@ -575,19 +507,11 @@
|
|||||||
@apply bg-gray-50/90;
|
@apply bg-gray-50/90;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-data-table thead tr {
|
|
||||||
background: rgba(255,255,255,0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-data-table th {
|
.app-data-table th {
|
||||||
@apply text-[11px] font-semibold uppercase tracking-[0.16em] text-gray-500;
|
@apply text-[11px] font-semibold uppercase tracking-[0.16em] text-gray-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(.dark) .app-data-table th {
|
/* ─── Semantic action classes (light mode only) ──────────────────────── */
|
||||||
color: rgb(var(--text-very-muted));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ─── Semantic action classes ─────────────────────────────────────────── */
|
|
||||||
|
|
||||||
.app-action-edit {
|
.app-action-edit {
|
||||||
@apply text-xs font-medium cursor-pointer transition-colors;
|
@apply text-xs font-medium cursor-pointer transition-colors;
|
||||||
@@ -597,8 +521,6 @@
|
|||||||
color: rgb(37 99 235);
|
color: rgb(37 99 235);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
:is(.dark) .app-action-edit { color: rgb(96 165 250); }
|
|
||||||
:is(.dark) .app-action-edit:hover { color: rgb(147 197 253); }
|
|
||||||
|
|
||||||
.app-action-delete {
|
.app-action-delete {
|
||||||
@apply text-xs font-medium cursor-pointer transition-colors;
|
@apply text-xs font-medium cursor-pointer transition-colors;
|
||||||
@@ -608,8 +530,6 @@
|
|||||||
color: rgb(185 28 28);
|
color: rgb(185 28 28);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
:is(.dark) .app-action-delete { color: rgb(248 113 113); }
|
|
||||||
:is(.dark) .app-action-delete:hover { color: rgb(252 165 165); }
|
|
||||||
|
|
||||||
.app-action-danger-btn {
|
.app-action-danger-btn {
|
||||||
@apply rounded px-2 py-1 text-sm font-medium cursor-pointer transition-colors;
|
@apply rounded px-2 py-1 text-sm font-medium cursor-pointer transition-colors;
|
||||||
@@ -619,12 +539,99 @@
|
|||||||
color: rgb(185 28 28);
|
color: rgb(185 28 28);
|
||||||
background-color: rgb(254 242 242);
|
background-color: rgb(254 242 242);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Dark overrides for component classes — ALL outside @layer ──────────────
|
||||||
|
Rules inside @layer components are lower priority than unlayered styles.
|
||||||
|
Placing :is(.dark) rules here (unlayered) ensures they always win.
|
||||||
|
─────────────────────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
|
:is(.dark) .app-surface {
|
||||||
|
background-color: rgb(var(--surface-card));
|
||||||
|
background-image: linear-gradient(135deg, rgba(255,255,255,0.045) 0%, rgba(255,255,255,0.015) 100%);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
-webkit-backdrop-filter: blur(16px);
|
||||||
|
border-color: rgba(255,255,255,0.09);
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.05), inset 0 1px 0 rgba(255,255,255,0.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-surface-strong {
|
||||||
|
background-color: rgb(var(--surface-card));
|
||||||
|
background-image: linear-gradient(135deg, rgba(255,255,255,0.055) 0%, rgba(255,255,255,0.018) 100%);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border-color: rgba(255,255,255,0.10);
|
||||||
|
box-shadow: 0 4px 16px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.06), inset 0 1px 0 rgba(255,255,255,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-toolbar {
|
||||||
|
background: rgb(16 17 19 / 0.82);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border-color: rgba(255,255,255,0.08);
|
||||||
|
box-shadow: 0 1px 0 rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-input {
|
||||||
|
background-color: rgb(var(--surface-input));
|
||||||
|
border-color: rgb(var(--border-input));
|
||||||
|
color: rgb(var(--text-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-input:focus {
|
||||||
|
border-color: rgb(var(--accent-400));
|
||||||
|
box-shadow: 0 0 0 3px rgba(var(--accent-400), 0.20), inset 0 0 8px rgba(var(--accent-400), 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-select {
|
||||||
|
background-color: rgb(var(--surface-input));
|
||||||
|
border-color: rgb(var(--border-input));
|
||||||
|
color: rgb(var(--text-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-select:focus {
|
||||||
|
border-color: rgb(var(--accent-400));
|
||||||
|
box-shadow: 0 0 0 3px rgb(var(--accent-400) / 0.20);
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-label {
|
||||||
|
color: rgb(var(--text-very-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-page-title {
|
||||||
|
background-image: linear-gradient(135deg, rgb(var(--accent-200)) 0%, rgb(var(--accent-100)) 50%, rgb(237 242 247) 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-page-subtitle {
|
||||||
|
color: rgb(var(--text-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-data-table {
|
||||||
|
background-color: rgb(var(--surface-card));
|
||||||
|
border-color: rgb(var(--border-subtle));
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-data-table thead tr {
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-data-table th {
|
||||||
|
color: rgb(var(--text-very-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.dark) .app-action-edit { color: rgb(96 165 250); }
|
||||||
|
:is(.dark) .app-action-edit:hover { color: rgb(147 197 253); }
|
||||||
|
:is(.dark) .app-action-delete { color: rgb(248 113 113); }
|
||||||
|
:is(.dark) .app-action-delete:hover { color: rgb(252 165 165); }
|
||||||
:is(.dark) .app-action-danger-btn { color: rgb(248 113 113); }
|
:is(.dark) .app-action-danger-btn { color: rgb(248 113 113); }
|
||||||
:is(.dark) .app-action-danger-btn:hover {
|
:is(.dark) .app-action-danger-btn:hover {
|
||||||
color: rgb(252 165 165);
|
color: rgb(252 165 165);
|
||||||
background-color: rgb(127 29 29 / 0.2);
|
background-color: rgb(127 29 29 / 0.2);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* ─── Timeline utilities (unchanged) ────────────────────────────────────── */
|
/* ─── Timeline utilities (unchanged) ────────────────────────────────────── */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user