557 lines
18 KiB
CSS
557 lines
18 KiB
CSS
@import "tailwindcss";
|
|
@import "@nuxt/ui";
|
|
|
|
/* ── Nuxt UI primary color — teal ───────────────────────────────────────── */
|
|
@theme {
|
|
--color-primary-50: #eefbfb;
|
|
--color-primary-100: #d4f3f4;
|
|
--color-primary-200: #a8e7e9;
|
|
--color-primary-300: #6dd5d8;
|
|
--color-primary-400: #33bdc2;
|
|
--color-primary-500: #019fa6;
|
|
--color-primary-600: #018388;
|
|
--color-primary-700: #01696f;
|
|
--color-primary-800: #015358;
|
|
--color-primary-900: #014044;
|
|
--color-primary-950: #002a2d;
|
|
/* Hijack green so Nuxt UI var(--color-green-*, fallback) resolves here */
|
|
--color-green-50: #eefbfb;
|
|
--color-green-100: #d4f3f4;
|
|
--color-green-200: #a8e7e9;
|
|
--color-green-300: #6dd5d8;
|
|
--color-green-400: #33bdc2;
|
|
--color-green-500: #019fa6;
|
|
--color-green-600: #018388;
|
|
--color-green-700: #01696f;
|
|
--color-green-800: #015358;
|
|
--color-green-900: #014044;
|
|
--color-green-950: #002a2d;
|
|
}
|
|
:root, :host {
|
|
--ui-color-primary-50: #eefbfb !important;
|
|
--ui-color-primary-100: #d4f3f4 !important;
|
|
--ui-color-primary-200: #a8e7e9 !important;
|
|
--ui-color-primary-300: #6dd5d8 !important;
|
|
--ui-color-primary-400: #33bdc2 !important;
|
|
--ui-color-primary-500: #019fa6 !important;
|
|
--ui-color-primary-600: #018388 !important;
|
|
--ui-color-primary-700: #01696f !important;
|
|
--ui-color-primary-800: #015358 !important;
|
|
--ui-color-primary-900: #014044 !important;
|
|
--ui-color-primary-950: #002a2d !important;
|
|
--ui-color-neutral-50: #f8f7f4 !important;
|
|
--ui-color-neutral-100: #f5f3ef !important;
|
|
--ui-color-neutral-200: #e8e6e2 !important;
|
|
--ui-color-neutral-300: #d0d0cc !important;
|
|
--ui-color-neutral-400: #a0a09c !important;
|
|
--ui-color-neutral-500: #8a8a86 !important;
|
|
--ui-color-neutral-600: #6b6b68 !important;
|
|
--ui-color-neutral-700: #4a4a48 !important;
|
|
--ui-color-neutral-800: #2e2e2c !important;
|
|
--ui-color-neutral-900: #1a1a18 !important;
|
|
--ui-color-neutral-950: #0f0f0e !important;
|
|
}
|
|
|
|
/* ── Override Tailwind/Nuxt UI default ring color ────────────────────────── */
|
|
:root {
|
|
--tw-ring-color: var(--brand, #0d5c63) !important;
|
|
}
|
|
|
|
/* ── Design tokens (normalized app chrome) ───────────────────────────────── */
|
|
:root,
|
|
[data-theme="light"] {
|
|
color-scheme: light;
|
|
--page-bg: #f8f7f4;
|
|
--surface: #ffffff;
|
|
--surface-elevated: #ffffff;
|
|
--sidebar-bg: #f5f3ef;
|
|
--sidebar-border: rgba(0, 0, 0, 0.04);
|
|
--topbar-bg: rgba(248, 247, 244, 0.94);
|
|
--text-primary: #1a1a18;
|
|
--text-secondary: #6b6b68;
|
|
--text-muted: #a0a09c;
|
|
--text-faint: #c0c0bc;
|
|
--brand: #01696f;
|
|
--brand-hover: #015358;
|
|
--brand-soft: rgba(1, 105, 111, 0.08);
|
|
--brand-faint: rgba(1, 105, 111, 0.04);
|
|
--nav-active-bg: rgba(1, 105, 111, 0.08);
|
|
--nav-active-fg: #01696f;
|
|
--nav-hover-bg: rgba(0, 0, 0, 0.05);
|
|
--logo-chrome-bg: linear-gradient(135deg, rgba(1, 105, 111, 0.05) 0%, rgba(255, 255, 255, 0) 55%);
|
|
--logo-blend: multiply;
|
|
--accent-ridge: rgba(1, 105, 111, 0.25);
|
|
|
|
/* ── Extended tokens ── */
|
|
--input-bg: #ffffff;
|
|
--input-border: rgba(0, 0, 0, 0.08);
|
|
--input-focus-ring: rgba(1, 105, 111, 0.20);
|
|
--input-placeholder: #a0a09c;
|
|
--card-border: rgba(0, 0, 0, 0.06);
|
|
--card-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
|
|
--card-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.04);
|
|
--badge-muted-bg: rgba(0, 0, 0, 0.05);
|
|
--badge-muted-fg: #6b6b68;
|
|
--divider: rgba(0, 0, 0, 0.06);
|
|
--focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand);
|
|
--btn-neutral-bg: #f5f3ef;
|
|
--btn-neutral-border: rgba(0, 0, 0, 0.12);
|
|
--btn-neutral-hover: #eeedea;
|
|
--success: #01696f;
|
|
--success-soft: rgba(1, 105, 111, 0.08);
|
|
--warning: #964219;
|
|
--warning-soft: rgba(150, 66, 25, 0.08);
|
|
--error: #c13838;
|
|
--error-soft: rgba(193, 56, 56, 0.08);
|
|
--info: #01696f;
|
|
--info-soft: rgba(1, 105, 111, 0.06);
|
|
--urgent: #dc2626;
|
|
--urgent-soft: rgba(220, 38, 38, 0.06);
|
|
--pending: #d97706;
|
|
--pending-soft: rgba(217, 119, 6, 0.06);
|
|
--skeleton: rgba(0, 0, 0, 0.04);
|
|
--scrollbar-thumb: rgba(0, 0, 0, 0.12);
|
|
--scrollbar-track: transparent;
|
|
}
|
|
|
|
[data-theme="purple"] {
|
|
color-scheme: light;
|
|
--page-bg: #f3f1ee;
|
|
--surface: #f9f8f6;
|
|
--surface-elevated: #ffffff;
|
|
--sidebar-bg: #f5f3f0;
|
|
--sidebar-border: rgba(100, 90, 80, 0.10);
|
|
--topbar-bg: rgba(245, 243, 240, 0.92);
|
|
--text-primary: #1a1a1a;
|
|
--text-muted: #6b5f55;
|
|
--brand: #5b3a8c;
|
|
--brand-hover: #4a2d75;
|
|
--brand-soft: rgba(91, 58, 140, 0.10);
|
|
--brand-faint: rgba(91, 58, 140, 0.05);
|
|
--nav-active-bg: rgba(91, 58, 140, 0.07);
|
|
--nav-active-fg: #5b3a8c;
|
|
--nav-hover-bg: rgba(100, 90, 80, 0.04);
|
|
--logo-chrome-bg: linear-gradient(135deg, rgba(91, 58, 140, 0.06) 0%, rgba(255, 255, 255, 0) 55%);
|
|
--logo-blend: multiply;
|
|
--accent-ridge: rgba(91, 58, 140, 0.28);
|
|
|
|
--input-bg: #ffffff;
|
|
--input-border: rgba(100, 90, 80, 0.16);
|
|
--input-focus-ring: rgba(91, 58, 140, 0.25);
|
|
--input-placeholder: #8c857d;
|
|
--card-border: rgba(100, 90, 80, 0.10);
|
|
--card-shadow: 0 1px 2px rgba(100, 90, 80, 0.06);
|
|
--card-shadow-hover: 0 4px 12px rgba(100, 90, 80, 0.10), 0 1px 3px rgba(100, 90, 80, 0.06);
|
|
--badge-muted-bg: rgba(100, 90, 80, 0.08);
|
|
--badge-muted-fg: #6b5f55;
|
|
--divider: rgba(100, 90, 80, 0.08);
|
|
--focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand);
|
|
--btn-neutral-bg: #f5f3f0;
|
|
--btn-neutral-border: rgba(100, 90, 80, 0.14);
|
|
--btn-neutral-hover: #edeae6;
|
|
--success: #0f7b5f;
|
|
--success-soft: rgba(15, 123, 95, 0.10);
|
|
--warning: #c27b1a;
|
|
--warning-soft: rgba(194, 123, 26, 0.10);
|
|
--error: #c13838;
|
|
--error-soft: rgba(193, 56, 56, 0.10);
|
|
--info: #5b3a8c;
|
|
--info-soft: rgba(91, 58, 140, 0.08);
|
|
--urgent: #dc2626;
|
|
--urgent-soft: rgba(220, 38, 38, 0.06);
|
|
--pending: #c27b1a;
|
|
--pending-soft: rgba(194, 123, 26, 0.06);
|
|
--skeleton: rgba(100, 90, 80, 0.06);
|
|
--scrollbar-thumb: rgba(100, 90, 80, 0.18);
|
|
--scrollbar-track: transparent;
|
|
}
|
|
|
|
[data-theme="dark"] {
|
|
color-scheme: dark;
|
|
--page-bg: #111110;
|
|
--surface: #1a1918;
|
|
--surface-elevated: #222120;
|
|
--sidebar-bg: #161514;
|
|
--sidebar-border: rgba(168, 162, 155, 0.10);
|
|
--topbar-bg: rgba(22, 21, 20, 0.94);
|
|
--text-primary: #e8e4df;
|
|
--text-muted: #8c857d;
|
|
--brand: #2dd4bf;
|
|
--brand-hover: #5eead4;
|
|
--brand-soft: rgba(45, 212, 191, 0.12);
|
|
--brand-faint: rgba(45, 212, 191, 0.06);
|
|
--nav-active-bg: rgba(45, 212, 191, 0.10);
|
|
--nav-active-fg: #5eead4;
|
|
--nav-hover-bg: rgba(168, 162, 155, 0.06);
|
|
--logo-chrome-bg: linear-gradient(135deg, rgba(45, 212, 191, 0.08) 0%, rgba(255, 255, 255, 0) 50%);
|
|
--logo-blend: screen;
|
|
--accent-ridge: rgba(45, 212, 191, 0.35);
|
|
|
|
--input-bg: #222120;
|
|
--input-border: rgba(168, 162, 155, 0.14);
|
|
--input-focus-ring: rgba(45, 212, 191, 0.30);
|
|
--input-placeholder: #6b6560;
|
|
--card-border: rgba(168, 162, 155, 0.08);
|
|
--card-shadow: 0 1px 3px rgba(0, 0, 0, 0.30);
|
|
--card-shadow-hover: 0 4px 16px rgba(0, 0, 0, 0.35), 0 2px 6px rgba(0, 0, 0, 0.20);
|
|
--badge-muted-bg: rgba(168, 162, 155, 0.10);
|
|
--badge-muted-fg: #8c857d;
|
|
--divider: rgba(168, 162, 155, 0.06);
|
|
--focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand);
|
|
--btn-neutral-bg: #222120;
|
|
--btn-neutral-border: rgba(168, 162, 155, 0.12);
|
|
--btn-neutral-hover: #2a2928;
|
|
--success: #2dd4a8;
|
|
--success-soft: rgba(45, 212, 168, 0.12);
|
|
--warning: #f0b429;
|
|
--warning-soft: rgba(240, 180, 41, 0.12);
|
|
--error: #f87171;
|
|
--error-soft: rgba(248, 113, 113, 0.12);
|
|
--info: #2dd4bf;
|
|
--info-soft: rgba(45, 212, 191, 0.08);
|
|
--urgent: #f87171;
|
|
--urgent-soft: rgba(248, 113, 113, 0.10);
|
|
--pending: #f0b429;
|
|
--pending-soft: rgba(240, 180, 41, 0.10);
|
|
--skeleton: rgba(168, 162, 155, 0.06);
|
|
--scrollbar-thumb: rgba(168, 162, 155, 0.18);
|
|
--scrollbar-track: transparent;
|
|
}
|
|
|
|
[data-theme="dark-purple"] {
|
|
color-scheme: dark;
|
|
--page-bg: #13111a;
|
|
--surface: #1c1926;
|
|
--surface-elevated: #252230;
|
|
--sidebar-bg: #17141e;
|
|
--sidebar-border: rgba(160, 148, 180, 0.10);
|
|
--topbar-bg: rgba(23, 20, 30, 0.94);
|
|
--text-primary: #ede8f4;
|
|
--text-muted: #918899;
|
|
--brand: #b898e8;
|
|
--brand-hover: #d0b8f8;
|
|
--brand-soft: rgba(184, 152, 232, 0.12);
|
|
--brand-faint: rgba(184, 152, 232, 0.06);
|
|
--nav-active-bg: rgba(184, 152, 232, 0.10);
|
|
--nav-active-fg: #d0b8f8;
|
|
--nav-hover-bg: rgba(160, 148, 180, 0.06);
|
|
--logo-chrome-bg: linear-gradient(135deg, rgba(184, 152, 232, 0.08) 0%, rgba(255, 255, 255, 0) 50%);
|
|
--logo-blend: screen;
|
|
--accent-ridge: rgba(184, 152, 232, 0.30);
|
|
|
|
--input-bg: #252230;
|
|
--input-border: rgba(160, 148, 180, 0.14);
|
|
--input-focus-ring: rgba(184, 152, 232, 0.30);
|
|
--input-placeholder: #6b6075;
|
|
--card-border: rgba(160, 148, 180, 0.08);
|
|
--card-shadow: 0 1px 3px rgba(0, 0, 0, 0.30);
|
|
--card-shadow-hover: 0 4px 16px rgba(0, 0, 0, 0.35), 0 2px 6px rgba(0, 0, 0, 0.20);
|
|
--badge-muted-bg: rgba(160, 148, 180, 0.10);
|
|
--badge-muted-fg: #918899;
|
|
--divider: rgba(160, 148, 180, 0.06);
|
|
--focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand);
|
|
--btn-neutral-bg: #252230;
|
|
--btn-neutral-border: rgba(160, 148, 180, 0.12);
|
|
--btn-neutral-hover: #2e2a3a;
|
|
--success: #34d399;
|
|
--success-soft: rgba(52, 211, 153, 0.12);
|
|
--warning: #f0b429;
|
|
--warning-soft: rgba(240, 180, 41, 0.12);
|
|
--error: #f87171;
|
|
--error-soft: rgba(248, 113, 113, 0.12);
|
|
--info: #b898e8;
|
|
--info-soft: rgba(184, 152, 232, 0.08);
|
|
--urgent: #f87171;
|
|
--urgent-soft: rgba(248, 113, 113, 0.10);
|
|
--pending: #f0b429;
|
|
--pending-soft: rgba(240, 180, 41, 0.10);
|
|
--skeleton: rgba(160, 148, 180, 0.06);
|
|
--scrollbar-thumb: rgba(160, 148, 180, 0.18);
|
|
--scrollbar-track: transparent;
|
|
}
|
|
|
|
/* ── Global reset & base ─────────────────────────────────────────────────── */
|
|
html {
|
|
background-color: var(--page-bg);
|
|
color: var(--text-primary);
|
|
transition: background-color 150ms ease, color 150ms ease;
|
|
}
|
|
|
|
/* Smooth theme transitions */
|
|
body,
|
|
.app-sidebar-link,
|
|
aside,
|
|
header,
|
|
main,
|
|
[class*="rounded-xl"] {
|
|
transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, box-shadow 150ms ease;
|
|
}
|
|
|
|
/* ── Custom scrollbar ────────────────────────────────────────────────────── */
|
|
* {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
|
}
|
|
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
::-webkit-scrollbar-track { background: var(--scrollbar-track); }
|
|
::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 999px; }
|
|
::-webkit-scrollbar-thumb:hover { background: var(--brand-soft); }
|
|
|
|
/* ── Nuxt UI component overrides (theme-aware) ──────────────────────────── */
|
|
|
|
/* Buttons — global refinements for Nuxt UI buttons */
|
|
[data-theme] button,
|
|
[data-theme] [role="button"],
|
|
[data-theme] a[class*="UButton"],
|
|
[data-theme] .ui-button-solid-primary,
|
|
[data-theme] button[class*="bg-[var(--brand)]"] {
|
|
transition: all 150ms ease;
|
|
border-radius: 0.5rem;
|
|
letter-spacing: -0.005em;
|
|
}
|
|
/* Solid primary buttons — deeper shadow for depth */
|
|
[data-theme] [class*="bg-primary"] {
|
|
box-shadow: 0 1px 2px color-mix(in srgb, var(--brand) 20%, transparent);
|
|
}
|
|
[data-theme] [class*="bg-primary"]:hover {
|
|
box-shadow: 0 2px 6px color-mix(in srgb, var(--brand) 28%, transparent);
|
|
}
|
|
|
|
/* Inputs & selects */
|
|
[data-theme] input:not([type="checkbox"]):not([type="radio"]),
|
|
[data-theme] textarea,
|
|
[data-theme] select,
|
|
[data-theme] [role="combobox"] {
|
|
background-color: var(--input-bg) !important;
|
|
border-color: var(--input-border) !important;
|
|
color: var(--text-primary) !important;
|
|
transition: border-color 150ms ease, box-shadow 150ms ease, background-color 150ms ease !important;
|
|
}
|
|
[data-theme] input:not([type="checkbox"]):not([type="radio"]):focus,
|
|
[data-theme] textarea:focus,
|
|
[data-theme] select:focus,
|
|
[data-theme] [role="combobox"]:focus {
|
|
border-color: var(--brand) !important;
|
|
box-shadow: 0 0 0 3px var(--input-focus-ring) !important;
|
|
}
|
|
[data-theme] input::placeholder,
|
|
[data-theme] textarea::placeholder {
|
|
color: var(--input-placeholder) !important;
|
|
}
|
|
|
|
/* Cards — universal card treatment */
|
|
.app-card {
|
|
background: #ffffff;
|
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
border-radius: 12px;
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
|
|
transition: border-color 150ms ease, box-shadow 150ms ease;
|
|
}
|
|
.app-card:hover {
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
}
|
|
.app-card-interactive:hover {
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
border-color: rgba(0, 0, 0, 0.10);
|
|
}
|
|
|
|
/* Badge helpers */
|
|
.app-badge {
|
|
font-size: 0.6875rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
padding: 0.125rem 0.5rem;
|
|
border-radius: 9999px;
|
|
transition: background-color 150ms ease, color 150ms ease;
|
|
}
|
|
|
|
/* Dividers */
|
|
.app-divider {
|
|
border-color: var(--divider);
|
|
}
|
|
|
|
/* ── Logo: soften white box PNGs — blend into sidebar chrome ─────────────── */
|
|
.app-logo-chrome {
|
|
background: var(--logo-chrome-bg);
|
|
border-radius: 0.75rem;
|
|
padding: 0.35rem 0.6rem;
|
|
isolation: isolate;
|
|
}
|
|
.app-logo-chrome img {
|
|
mix-blend-mode: var(--logo-blend);
|
|
max-height: 2rem;
|
|
width: auto;
|
|
max-width: 10rem;
|
|
object-fit: contain;
|
|
object-position: left center;
|
|
filter: contrast(1.05) saturate(1.02);
|
|
}
|
|
|
|
/* ── Typography helpers ──────────────────────────────────────────────────── */
|
|
|
|
.app-heading {
|
|
color: var(--text-primary);
|
|
font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.app-body-muted {
|
|
color: var(--text-secondary);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* Tabular nums on dashboard container */
|
|
.app-dashboard-nums {
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* ── Ridge accent on chrome buttons (top bar) ────────────────────────────── */
|
|
.app-chrome-btn {
|
|
position: relative;
|
|
overflow: visible;
|
|
}
|
|
.app-chrome-btn::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 2px;
|
|
right: 2px;
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 2px;
|
|
background: linear-gradient(135deg, var(--accent-ridge) 0%, transparent 55%);
|
|
opacity: 0.85;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* ── Sidebar navigation ──────────────────────────────────────────────────── */
|
|
.app-sidebar-link {
|
|
border-radius: 8px;
|
|
transition: background-color 150ms ease;
|
|
outline: none !important;
|
|
}
|
|
.app-sidebar-link:hover {
|
|
background-color: rgba(0, 0, 0, 0.05);
|
|
}
|
|
.app-sidebar-link:focus-visible {
|
|
outline: 2px solid var(--brand) !important;
|
|
outline-offset: -1px;
|
|
}
|
|
|
|
.app-sidebar-link-active {
|
|
background-color: rgba(0, 0, 0, 0.045);
|
|
color: var(--text-primary) !important;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Sidebar child link active — text only, no pill */
|
|
.app-sidebar-child-active {
|
|
color: #01696f !important;
|
|
font-weight: 500;
|
|
background: transparent !important;
|
|
}
|
|
|
|
/* Section header labels in sidebar */
|
|
.app-sidebar-section-label {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: #a0a09c;
|
|
margin-top: 24px;
|
|
margin-bottom: 8px;
|
|
padding: 0 12px;
|
|
user-select: none;
|
|
}
|
|
|
|
/* ── KPI card treatment ──────────────────────────────────────────────────── */
|
|
.app-kpi-card {
|
|
background: var(--surface);
|
|
border: 1px solid var(--card-border);
|
|
border-radius: 0.75rem;
|
|
padding: 0.875rem 1rem;
|
|
box-shadow: var(--card-shadow);
|
|
transition: box-shadow 150ms ease, border-color 150ms ease;
|
|
}
|
|
.app-kpi-card:hover {
|
|
box-shadow: var(--card-shadow-hover);
|
|
}
|
|
|
|
/* ── Quick-link tiles ────────────────────────────────────────────────────── */
|
|
.app-quick-link {
|
|
background: var(--surface);
|
|
border: 1px solid var(--card-border);
|
|
border-radius: 0.75rem;
|
|
padding: 1.25rem;
|
|
box-shadow: var(--card-shadow);
|
|
transition: all 150ms ease;
|
|
}
|
|
.app-quick-link:hover {
|
|
border-color: var(--brand);
|
|
box-shadow: var(--card-shadow-hover);
|
|
}
|
|
.app-quick-link:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
/* ── Theme picker card ───────────────────────────────────────────────────── */
|
|
.app-theme-card {
|
|
background: var(--surface);
|
|
border: 1px solid var(--card-border);
|
|
border-radius: 0.75rem;
|
|
padding: 1.25rem;
|
|
box-shadow: var(--card-shadow);
|
|
transition: all 150ms ease;
|
|
cursor: pointer;
|
|
}
|
|
.app-theme-card:hover {
|
|
box-shadow: var(--card-shadow-hover);
|
|
border-color: var(--brand);
|
|
}
|
|
.app-theme-card-selected {
|
|
border-color: var(--brand) !important;
|
|
box-shadow: 0 0 0 2px var(--brand), var(--card-shadow);
|
|
}
|
|
|
|
/* ── Animated skeleton ───────────────────────────────────────────────────── */
|
|
@keyframes app-shimmer {
|
|
0% { background-position: -200% 0; }
|
|
100% { background-position: 200% 0; }
|
|
}
|
|
.app-skeleton {
|
|
background: linear-gradient(90deg, var(--skeleton) 25%, transparent 50%, var(--skeleton) 75%);
|
|
background-size: 200% 100%;
|
|
animation: app-shimmer 1.8s ease-in-out infinite;
|
|
border-radius: 0.375rem;
|
|
}
|
|
|
|
/* ── Focus visible ring ──────────────────────────────────────────────────── */
|
|
.app-focus-ring:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring);
|
|
}
|
|
|
|
/* Kill all default blue focus rings — use brand color everywhere */
|
|
*:focus {
|
|
outline-color: var(--brand) !important;
|
|
}
|
|
*:focus-visible {
|
|
outline-color: var(--brand) !important;
|
|
}
|
|
button:focus,
|
|
a:focus,
|
|
[role="button"]:focus,
|
|
button:focus-visible,
|
|
a:focus-visible,
|
|
[role="button"]:focus-visible {
|
|
outline: 2px solid color-mix(in srgb, var(--brand) 50%, transparent) !important;
|
|
outline-offset: 2px;
|
|
}
|
|
/* Sidebar buttons — suppress focus outline in favor of hover state */
|
|
.app-sidebar-link:focus:not(:focus-visible) {
|
|
outline: none !important;
|
|
}
|
|
|
|
/* ── Entrance animations (disabled per spec — no entrance animations) ──── */
|
|
.app-animate-in { /* no-op */ }
|
|
.app-stagger > * { /* no-op */ }
|