Files
policy-ui/app/assets/css/main.css
Jordan Weingarten 67482f6629 WIP jordan
2026-04-16 11:11:44 -05:00

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 */ }