/*
* obsidian.css β Production Design System
* sfpermits.ai Β· Obsidian Intelligence
*
* Source of truth: docs/DESIGN_TOKENS.md
* Generated from DESIGN_TOKENS.md sections 1β15.
* Both files coexist with design-system.css until all templates are migrated.
*
* Sections:
* Β§1 Reset & Base
* Β§2 Color Tokens (Β§1 in DESIGN_TOKENS.md)
* Β§3 Typography Tokens (Β§2)
* Β§4 Spacing & Radius Tokens (Β§3, Β§4)
* Β§5 Layout β Containers (Β§4)
* Β§6 Components β Glass Card (Β§5)
* Β§7 Components β Search Input (Β§5)
* Β§8 Components β Ghost Button / CTA (Β§5)
* Β§9 Components β Action Button (Β§5)
* Β§10 Components β Status Badge / Dot (Β§5)
* Β§11 Components β Chip / Type Badge (Β§5)
* Β§12 Components β Data Row (Β§5)
* Β§13 Components β Stat Counter (Β§5)
* Β§14 Components β Progress Bar (Β§5)
* Β§15 Components β Dropdown (Β§5)
* Β§16 Components β Section Divider (Β§5)
* Β§17 Components β Skeleton Screen (Β§5)
* Β§18 Components β Table (Β§5)
* Β§19 Components β Tabs (Β§5)
* Β§20 Components β Load More / Pagination (Β§5)
* Β§21 Components β Form Elements (Β§5)
* Β§22 Components β Toast / Notification (Β§5)
* Β§23 Components β Modal / Dialog (Β§5)
* Β§24 Components β Content Patterns (Β§5)
* Β§25 Navigation β Floating Nav Bar (Β§6)
* Β§26 Animation (Β§7)
* Β§27 Responsive Breakpoints (Β§8)
* Β§28 Print Styles
* Β§29 Accessibility β Reduced Motion & Focus (Β§15)
*/
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§1 RESET & BASE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
scrollbar-width: thin;
scrollbar-color: var(--glass-border) transparent;
}
body {
font-family: var(--sans);
background: var(--obsidian);
color: var(--text-primary);
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 1.5;
}
h1, h2, h3, h4 {
font-family: var(--sans);
line-height: 1.2;
}
h1 { font-size: var(--text-2xl); font-weight: 300; }
h2 { font-size: var(--text-xl); font-weight: 300; }
h3 { font-size: var(--text-lg); font-weight: 400; }
h4 { font-size: var(--text-base); font-weight: 500; }
a { color: inherit; text-decoration: none; }
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§2 COLOR TOKENS (DESIGN_TOKENS.md Β§1)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
:root {
/* Backgrounds */
--obsidian: #0a0a0f; /* page background β 90% of everything */
--obsidian-mid: #12121a; /* card/surface background */
--obsidian-light: #1a1a26; /* elevated elements (inputs, dropdowns, modals) */
--glass: rgba(255, 255, 255, 0.04); /* glassmorphism tint */
--glass-border: rgba(255, 255, 255, 0.06); /* card/container borders */
--glass-hover: rgba(255, 255, 255, 0.10); /* border on hover */
/* Text */
--text-primary: rgba(255, 255, 255, 0.92); /* headings, data values, primary content */
--text-secondary: rgba(255, 255, 255, 0.55); /* body copy, descriptions, labels */
--text-tertiary: rgba(255, 255, 255, 0.30); /* placeholders, hints, disabled */
--text-ghost: rgba(255, 255, 255, 0.15); /* wordmarks, footers, barely-there text */
/* Accent */
--accent: #5eead4; /* THE brand color β links, focus, active */
--accent-glow: rgba(94, 234, 212, 0.08); /* subtle teal glow for hover/focus bg */
--accent-ring: rgba(94, 234, 212, 0.30); /* focus ring border color */
/* Semantic signal β ONLY for their semantic purpose */
--signal-green: #34d399; /* on track, success, approved */
--signal-amber: #fbbf24; /* warning, stalled, pending */
--signal-red: #f87171; /* alert, violation, complaint */
--signal-blue: #60a5fa; /* informational, premium badge */
/* Higher-saturation dot variants for legibility at 6px */
--dot-green: #22c55e;
--dot-amber: #f59e0b;
--dot-red: #ef4444;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§3 TYPOGRAPHY TOKENS (DESIGN_TOKENS.md Β§2)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
:root {
--mono: 'JetBrains Mono', ui-monospace, 'Cascadia Code', monospace;
--sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
/* Fluid type scale */
--text-xs: clamp(0.65rem, 0.6rem + 0.2vw, 0.75rem); /* 10β12px */
--text-sm: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); /* 12β14px */
--text-base: clamp(0.8125rem, 0.75rem + 0.3vw, 1rem); /* 13β16px */
--text-lg: clamp(0.875rem, 0.8rem + 0.4vw, 1.125rem); /* 14β18px */
--text-xl: clamp(1.125rem, 1rem + 0.5vw, 1.5rem); /* 18β24px */
--text-2xl: clamp(1.5rem, 1.2rem + 1.2vw, 2.5rem); /* 24β40px */
--text-3xl: clamp(1.875rem, 1.5rem + 1.8vw, 3.75rem); /* 30β60px hero */
}
/* Section labels β mono uppercase, used across nav, tables, form labels */
.section-label {
font-family: var(--mono);
font-size: var(--text-xs);
font-weight: 400;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--text-tertiary);
margin-bottom: var(--space-4);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§4 SPACING & RADIUS TOKENS (DESIGN_TOKENS.md Β§3, Β§4)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
:root {
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
--space-20: 80px;
--space-24: 96px;
--space-32: 128px;
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-full: 9999px;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§5 LAYOUT β CONTAINERS (DESIGN_TOKENS.md Β§4)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* Public pages β focused reading width */
.obs-container {
max-width: 1000px;
margin: 0 auto;
padding: 0 var(--space-6);
}
/* Admin pages β wider for tables */
.obs-container-wide {
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--space-6);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§6 COMPONENTS β GLASS CARD (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.glass-card {
background: var(--obsidian-mid);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
padding: var(--space-8);
transition: border-color 0.3s;
}
.glass-card:hover {
border-color: var(--glass-hover);
}
/* Accent variant β teal-tinted */
.glass-card--accent {
background: var(--accent-glow);
border-color: var(--accent-ring);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§7 COMPONENTS β SEARCH INPUT (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.search-bar {
position: relative;
}
.search-input {
width: 100%;
padding: 16px 22px;
padding-right: 50px;
font-family: var(--mono);
font-size: 14px;
font-weight: 300;
color: var(--text-primary);
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
outline: none;
transition: border-color 0.4s, background 0.4s, box-shadow 0.4s;
}
.search-input::placeholder {
color: var(--text-tertiary);
font-weight: 300;
}
.search-input:focus {
border-color: var(--accent-ring);
background: rgba(255, 255, 255, 0.06);
box-shadow: 0 0 40px var(--accent-glow);
}
.search-bar .search-icon {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
color: var(--text-tertiary);
transition: color 0.3s;
pointer-events: none;
}
.search-input:focus ~ .search-icon {
color: var(--accent);
}
.kbd-hint {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
font-family: var(--mono);
font-size: 10px;
color: var(--text-tertiary);
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: 3px;
padding: 1px 5px;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§8 COMPONENTS β GHOST BUTTON / PRIMARY CTA (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.ghost-cta {
font-family: var(--mono);
font-size: var(--text-sm);
font-weight: 300;
color: var(--text-secondary); /* secondary (5.2:1) β interactive text must pass WCAG AA */
background: none;
border: none;
cursor: pointer;
padding-bottom: 1px;
border-bottom: 1px solid transparent;
transition: color 0.3s, border-color 0.3s;
letter-spacing: 0.04em;
text-decoration: none;
display: inline-block;
}
.ghost-cta:hover {
color: var(--accent);
border-bottom-color: var(--accent);
}
/* Always include arrow suffix in content: "View report β" */
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§9 COMPONENTS β ACTION BUTTON (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.action-btn {
font-family: var(--mono);
font-size: var(--text-sm);
font-weight: 400;
color: var(--text-secondary);
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
padding: 8px 16px;
cursor: pointer;
transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.action-btn:hover {
border-color: var(--glass-hover);
color: var(--text-primary);
background: var(--obsidian-light);
}
/* Destructive variant */
.action-btn--danger:hover {
border-color: rgba(248, 113, 113, 0.3);
color: var(--signal-red);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§10 COMPONENTS β STATUS BADGE / DOT (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* Dots use higher-saturation --dot-* for legibility at 6px */
.status-dot {
width: 6px;
height: 6px;
border-radius: var(--radius-full);
display: inline-block;
vertical-align: middle;
margin-right: var(--space-2);
}
.status-dot--green { background: var(--dot-green); }
.status-dot--amber { background: var(--dot-amber); }
.status-dot--red { background: var(--dot-red); }
/* Text uses standard signal colors */
.status-text--green { color: var(--signal-green); }
.status-text--amber { color: var(--signal-amber); }
.status-text--red { color: var(--signal-red); }
.status-text--blue { color: var(--signal-blue); }
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§11 COMPONENTS β CHIP / TYPE BADGE (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.chip {
font-family: var(--mono);
font-size: var(--text-xs);
font-weight: 400;
color: var(--text-tertiary);
background: var(--glass);
border: 1px solid var(--glass-border);
padding: 1px 7px;
border-radius: 3px;
white-space: nowrap;
display: inline-block;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§12 COMPONENTS β DATA ROW (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.data-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 0;
border-bottom: 1px solid var(--glass-border);
}
.data-row:last-child {
border-bottom: none;
}
.data-row__label {
font-family: var(--sans);
font-size: var(--text-base);
color: var(--text-secondary);
}
.data-row__value {
font-family: var(--mono);
font-size: var(--text-sm);
color: var(--text-primary);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§13 COMPONENTS β STAT COUNTER (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.stat-number {
font-family: var(--mono);
font-size: clamp(22px, 3vw, 36px);
font-weight: 300;
line-height: 1;
color: var(--text-primary);
}
.stat-label {
font-family: var(--sans);
font-size: var(--text-sm);
font-weight: 400;
color: var(--text-tertiary);
margin-top: var(--space-2);
}
/* Stats row layout helpers */
.stats-row {
display: flex;
align-items: center;
gap: var(--space-8);
}
.stat-divider {
width: 1px;
height: 32px;
background: var(--glass-border);
flex-shrink: 0;
}
.stat-item {
flex: 0 0 auto;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§14 COMPONENTS β PROGRESS BAR (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.progress-label {
display: flex;
justify-content: space-between;
margin-bottom: 6px;
}
.progress-label span {
font-family: var(--mono);
font-size: var(--text-xs);
color: var(--text-tertiary);
}
.progress-track {
height: 2px;
background: var(--glass);
border-radius: 1px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--accent), rgba(94, 234, 212, 0.4));
border-radius: 1px;
transition: width 1.6s cubic-bezier(0.16, 1, 0.3, 1);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§15 COMPONENTS β DROPDOWN (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.dropdown {
background: var(--obsidian-mid);
border: 1px solid var(--glass-border);
border-radius: 0 0 var(--radius-md) var(--radius-md);
overflow-y: auto;
max-height: 380px;
scrollbar-width: thin;
scrollbar-color: var(--glass-border) transparent;
}
.dropdown__item {
padding: 9px 22px;
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
transition: background 0.12s;
}
.dropdown__item:hover {
background: var(--glass);
}
.dropdown__label {
font-family: var(--mono);
font-size: var(--text-xs);
font-weight: 400;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--text-tertiary);
padding: 10px 22px 4px;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§16 COMPONENTS β SECTION DIVIDER (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.section-divider {
border: none;
border-top: 1px solid var(--glass-border);
margin: 0;
}
/* Gradient divider (preferred per anti-patterns Β§13) */
.divider {
border: none;
height: 1px;
margin: 0;
background: linear-gradient(90deg, transparent, var(--glass-border), transparent);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§17 COMPONENTS β SKELETON SCREEN (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.skeleton {
background: var(--glass);
border-radius: var(--radius-sm);
animation: skeleton-pulse 1.5s ease-in-out infinite;
}
.skeleton--heading { height: 20px; }
.skeleton--text { height: 12px; }
.skeleton--dot { width: 6px; height: 6px; border-radius: var(--radius-full); }
.skeleton-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 0;
border-bottom: 1px solid var(--glass-border);
}
@keyframes skeleton-pulse {
0%, 100% { opacity: 0.04; }
50% { opacity: 0.08; }
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§18 COMPONENTS β TABLE (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.obs-table {
width: 100%;
border-collapse: collapse;
font-family: var(--sans);
font-size: var(--text-sm);
}
.obs-table th {
font-family: var(--mono);
font-size: 10px;
font-weight: 400;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-secondary); /* tertiary fails WCAG AA at small sizes */
text-align: left;
padding: 6px var(--space-3);
border-bottom: 1px solid var(--glass-border);
}
.obs-table td {
padding: 9px var(--space-3);
color: var(--text-secondary);
border-bottom: 1px solid var(--glass-border);
}
.obs-table tr {
transition: background 0.12s;
cursor: pointer;
}
.obs-table tr:hover {
background: var(--glass);
}
.obs-table__mono {
font-family: var(--mono);
font-weight: 300;
color: var(--text-primary);
}
/* Address goes teal on hover */
.obs-table tr:hover .obs-table__mono:first-of-type {
color: var(--accent);
}
/* Sort indicators */
.obs-table th[data-sort] {
cursor: pointer;
user-select: none;
}
.obs-table th[data-sort]::after {
content: '';
display: inline-block;
width: 0;
height: 0;
margin-left: 6px;
vertical-align: middle;
border-left: 3.5px solid transparent;
border-right: 3.5px solid transparent;
border-top: 4px solid var(--text-tertiary);
transition: transform 0.2s, border-color 0.2s;
}
.obs-table th[data-sort]:hover::after {
border-top-color: var(--text-secondary);
}
.obs-table th[data-sort="asc"]::after {
border-top-color: var(--accent);
transform: rotate(180deg);
}
.obs-table th[data-sort="desc"]::after {
border-top-color: var(--accent);
}
/* Empty state row */
.obs-table__empty {
text-align: center;
padding: var(--space-8) var(--space-4);
color: var(--text-tertiary);
font-family: var(--sans);
font-size: var(--text-sm);
}
/* Mobile: horizontal scroll with shadow hint */
@media (max-width: 768px) {
.obs-table-wrap {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin: 0 calc(-1 * var(--space-4));
padding: 0 var(--space-4);
}
.obs-table { min-width: 600px; }
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§19 COMPONENTS β TABS (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.tabs {
display: flex;
gap: var(--space-6);
border-bottom: 1px solid var(--glass-border);
margin-bottom: var(--space-6);
}
.tab {
font-family: var(--mono);
font-size: var(--text-sm);
font-weight: 400;
color: var(--text-tertiary);
background: none;
border: none;
padding: var(--space-3) 0;
cursor: pointer;
position: relative;
transition: color 0.2s;
}
.tab:hover {
color: var(--text-secondary);
}
.tab--active {
color: var(--text-primary);
}
.tab--active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: var(--accent);
border-radius: 1px;
}
/* Tab count badge (optional) */
.tab__count {
font-size: var(--text-xs);
color: var(--text-tertiary);
margin-left: var(--space-2);
}
.tab--active .tab__count {
color: var(--accent);
}
@media (max-width: 480px) {
.tabs {
gap: var(--space-4);
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.tab {
white-space: nowrap;
flex-shrink: 0;
}
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§20 COMPONENTS β LOAD MORE / PAGINATION (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.load-more {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-3);
padding: var(--space-6) 0;
}
.load-more__count {
font-family: var(--mono);
font-size: var(--text-xs);
color: var(--text-tertiary);
}
/* .load-more__btn inherits ghost-cta styles */
.load-more__spinner {
display: none;
}
.htmx-request .load-more__btn { display: none; }
.htmx-request .load-more__spinner { display: block; }
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§21 COMPONENTS β FORM ELEMENTS (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* --- Text label --- */
.form-label {
display: block;
font-family: var(--mono);
font-size: var(--text-xs);
font-weight: 400;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-tertiary);
margin-bottom: var(--space-2);
}
/* --- Text input --- */
.form-input {
width: 100%;
padding: 10px 14px;
font-family: var(--mono);
font-size: var(--text-sm);
font-weight: 300;
color: var(--text-primary);
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
outline: none;
transition: border-color 0.3s, box-shadow 0.3s;
}
.form-input:focus {
border-color: var(--accent-ring);
box-shadow: 0 0 0 3px rgba(94, 234, 212, 0.1);
}
.form-input::placeholder {
color: var(--text-tertiary);
}
/* --- Checkbox --- */
.form-check {
display: flex;
align-items: center;
gap: var(--space-3);
cursor: pointer;
padding: 6px 0;
}
.form-check__input { display: none; }
.form-check__box {
width: 16px;
height: 16px;
border-radius: 3px;
flex-shrink: 0;
border: 1px solid var(--glass-border);
background: var(--glass);
transition: border-color 0.2s, background 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
.form-check__input:checked + .form-check__box {
border-color: var(--accent);
background: var(--accent-glow);
}
.form-check__input:checked + .form-check__box::after {
content: 'β';
font-size: 10px;
color: var(--accent);
}
.form-check__label {
font-family: var(--sans);
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* --- Toggle switch --- */
.form-toggle {
display: flex;
align-items: center;
gap: var(--space-3);
cursor: pointer;
padding: 6px 0;
}
.form-toggle__input { display: none; }
.form-toggle__track {
width: 28px;
height: 14px;
border-radius: 7px;
flex-shrink: 0;
background: var(--glass-border);
position: relative;
transition: background 0.2s;
}
.form-toggle__input:checked + .form-toggle__track {
background: var(--accent);
}
.form-toggle__thumb {
width: 10px;
height: 10px;
border-radius: var(--radius-full);
background: var(--text-tertiary);
position: absolute;
top: 2px;
left: 2px;
transition: left 0.2s, background 0.2s;
}
.form-toggle__input:checked + .form-toggle__track .form-toggle__thumb {
left: 16px;
background: var(--obsidian);
}
.form-toggle__label {
font-family: var(--sans);
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* --- Select / dropdown input --- */
.form-select {
width: 100%;
padding: 10px 14px;
font-family: var(--mono);
font-size: var(--text-sm);
font-weight: 300;
color: var(--text-primary);
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
outline: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.3)' stroke-width='2' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 14px center;
cursor: pointer;
transition: border-color 0.3s;
}
.form-select:focus {
border-color: var(--accent-ring);
}
/* --- File upload zone --- */
.form-upload__input { display: none; }
.form-upload__zone {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
padding: var(--space-8) var(--space-6);
border: 1px dashed var(--glass-border);
border-radius: var(--radius-md);
cursor: pointer;
text-align: center;
transition: border-color 0.3s, background 0.3s;
}
.form-upload__zone:hover {
border-color: var(--accent-ring);
background: var(--accent-glow);
}
.form-upload__icon {
font-size: 20px;
color: var(--text-tertiary);
}
.form-upload__text {
font-family: var(--sans);
font-size: var(--text-sm);
color: var(--text-secondary);
}
.form-upload__hint {
font-family: var(--mono);
font-size: var(--text-xs);
color: var(--text-tertiary);
}
/* --- Form group spacing --- */
.form-group {
display: flex;
flex-direction: column;
gap: var(--space-2);
margin-bottom: var(--space-4);
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§22 COMPONENTS β TOAST / NOTIFICATION (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.toast {
position: fixed;
top: var(--space-6);
left: 50%;
transform: translateX(-50%);
z-index: 100;
display: flex;
align-items: center;
gap: var(--space-3);
padding: 10px var(--space-5);
background: var(--obsidian-mid);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
backdrop-filter: blur(12px);
animation: toast-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);
max-width: min(420px, calc(100vw - 32px));
}
.toast--success { border-left: 2px solid var(--signal-green); }
.toast--error { border-left: 2px solid var(--signal-red); }
.toast--info { border-left: 2px solid var(--signal-blue); }
.toast__icon {
font-size: var(--text-sm);
}
.toast--success .toast__icon { color: var(--signal-green); }
.toast--error .toast__icon { color: var(--signal-red); }
.toast--info .toast__icon { color: var(--signal-blue); }
.toast__message {
font-family: var(--sans);
font-size: var(--text-sm);
color: var(--text-primary);
}
.toast__action {
font-family: var(--mono);
font-size: var(--text-xs);
color: var(--accent);
text-decoration: none;
margin-left: var(--space-2);
white-space: nowrap;
}
.toast__action:hover { text-decoration: underline; }
.toast__dismiss {
background: none;
border: none;
color: var(--text-tertiary);
font-size: 16px;
cursor: pointer;
padding: 0 0 0 var(--space-2);
transition: color 0.2s;
}
.toast__dismiss:hover { color: var(--text-primary); }
.toast.toast--exit {
animation: toast-out 0.25s ease-in forwards;
}
@keyframes toast-in {
from { opacity: 0; transform: translateX(-50%) translateY(-12px); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes toast-out {
to { opacity: 0; transform: translateX(-50%) translateY(-12px); }
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§23 COMPONENTS β MODAL / DIALOG (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* Backdrop */
.modal-backdrop {
position: fixed;
inset: 0;
z-index: 90;
background: rgba(0, 0, 0, 0.60);
backdrop-filter: blur(4px);
display: flex;
align-items: center;
justify-content: center;
animation: backdrop-in 0.2s ease-out;
}
/* Modal β desktop (centered fade) */
.modal {
background: var(--obsidian-mid);
border: 1px solid var(--glass-border);
border-radius: var(--radius-lg);
max-width: 440px;
width: calc(100vw - 32px);
max-height: calc(100vh - 64px);
overflow-y: auto;
animation: modal-fade-in 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.modal__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-6) var(--space-6) 0;
}
.modal__title {
font-family: var(--sans);
font-size: var(--text-lg);
font-weight: 400;
color: var(--text-primary);
margin: 0;
}
.modal__close {
background: none;
border: none;
color: var(--text-tertiary);
font-size: 20px;
cursor: pointer;
padding: 0;
transition: color 0.2s;
}
.modal__close:hover { color: var(--text-primary); }
.modal__body {
padding: var(--space-4) var(--space-6);
font-family: var(--sans);
font-size: var(--text-sm);
color: var(--text-secondary);
line-height: 1.5;
}
.modal__footer {
display: flex;
justify-content: flex-end;
gap: var(--space-3);
padding: 0 var(--space-6) var(--space-6);
}
/* Mobile β slide-up sheet */
@media (max-width: 768px) {
.modal-backdrop {
align-items: flex-end;
}
.modal {
max-width: 100%;
width: 100%;
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
max-height: 85vh;
animation: modal-slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.modal__header {
padding-top: var(--space-5);
}
/* Drag handle hint */
.modal::before {
content: '';
display: block;
width: 32px;
height: 4px;
background: var(--glass-hover);
border-radius: 2px;
margin: var(--space-3) auto 0;
}
}
@keyframes backdrop-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes modal-fade-in {
from { opacity: 0; transform: scale(0.96); }
to { opacity: 1; transform: scale(1); }
}
@keyframes modal-slide-up {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§24 COMPONENTS β CONTENT PATTERNS (DESIGN_TOKENS.md Β§5)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* --- Insight Callout --- */
.insight {
padding: var(--space-3) var(--space-4);
border-radius: var(--radius-sm);
margin-bottom: var(--space-4);
border-left: 2px solid;
}
.insight--green { background: rgba(52, 211, 153, 0.06); border-left-color: var(--signal-green); }
.insight--amber { background: rgba(251, 191, 36, 0.06); border-left-color: var(--signal-amber); }
.insight--red { background: rgba(248, 113, 113, 0.06); border-left-color: var(--signal-red); }
.insight--info { background: rgba(96, 165, 250, 0.06); border-left-color: var(--signal-blue); }
.insight__label {
font-family: var(--mono);
font-size: var(--text-xs);
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 4px;
}
.insight--green .insight__label { color: var(--signal-green); }
.insight--amber .insight__label { color: var(--signal-amber); }
.insight--red .insight__label { color: var(--signal-red); }
.insight--info .insight__label { color: var(--signal-blue); }
.insight__body {
font-family: var(--sans);
font-size: var(--text-sm);
font-weight: 300;
color: var(--text-secondary);
line-height: 1.5;
}
/* --- Expandable Section --- */
.expandable {
border-bottom: 1px solid var(--glass-border);
}
.expandable__summary {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-3) 0;
cursor: pointer;
list-style: none;
}
.expandable__summary::-webkit-details-marker { display: none; }
.expandable__title {
font-family: var(--mono);
font-size: var(--text-sm);
font-weight: 400;
color: var(--text-secondary);
transition: color 0.2s;
}
.expandable__summary:hover .expandable__title { color: var(--accent); }
.expandable__arrow {
font-size: 10px;
color: var(--text-tertiary);
transition: transform 0.3s;
}
.expandable[open] .expandable__arrow { transform: rotate(180deg); }
.expandable__body {
padding: 0 0 var(--space-4);
font-family: var(--sans);
font-size: var(--text-sm);
font-weight: 300;
color: var(--text-secondary);
line-height: 1.5;
}
/* --- Risk Flag --- */
.risk-flag {
display: flex;
align-items: center;
gap: var(--space-2);
padding: 4px 0;
}
.risk-flag__dot {
width: 6px;
height: 6px;
border-radius: var(--radius-full);
flex-shrink: 0;
}
.risk-flag--high .risk-flag__dot { background: var(--dot-red); }
.risk-flag--medium .risk-flag__dot { background: var(--dot-amber); }
.risk-flag--low .risk-flag__dot { background: var(--dot-green); }
.risk-flag__text {
font-family: var(--sans);
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* --- Action Prompt --- */
.action-prompt {
display: flex;
flex-direction: column;
gap: var(--space-2);
padding: var(--space-4) 0;
}
.action-prompt__context {
font-family: var(--sans);
font-size: var(--text-xs);
color: var(--text-tertiary);
}
/* --- Data Freshness Footer --- */
.freshness {
font-family: var(--mono);
font-size: 11px;
color: var(--text-ghost);
text-align: center;
padding: var(--space-10) 0;
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
}
.freshness-dot {
width: 6px;
height: 6px;
border-radius: var(--radius-full);
background: var(--signal-green);
display: inline-block;
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§25 NAVIGATION β FLOATING NAV BAR (DESIGN_TOKENS.md Β§6)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
.nav-float {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 50;
padding: 12px var(--space-6);
display: flex;
align-items: center;
justify-content: space-between;
background: rgba(10, 10, 15, 0.85);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--glass-border);
transition: opacity 0.4s, transform 0.4s;
}
/* Hidden state (landing hero β no nav above fold) */
.nav-float--hidden {
opacity: 0;
transform: translateY(-100%);
pointer-events: none;
}
.nav-float__wordmark {
font-family: var(--mono);
font-size: var(--text-xs);
font-weight: 300;
letter-spacing: 0.35em;
text-transform: uppercase;
color: var(--text-tertiary);
text-decoration: none;
transition: color 0.3s;
}
.nav-float__wordmark:hover { color: var(--text-secondary); }
.nav-float__links {
display: flex;
align-items: center;
gap: var(--space-6);
}
.nav-float__link {
font-family: var(--sans);
font-size: var(--text-sm);
font-weight: 400;
color: var(--text-secondary);
text-decoration: none;
transition: color 0.3s;
}
.nav-float__link:hover { color: var(--accent); }
.nav-float__avatar {
width: 28px;
height: 28px;
border-radius: var(--radius-full);
background: var(--glass);
border: 1px solid var(--glass-border);
display: flex;
align-items: center;
justify-content: center;
font-family: var(--mono);
font-size: 10px;
font-weight: 400;
color: var(--text-tertiary);
}
@media (max-width: 768px) {
.nav-float__links .nav-float__link { display: none; }
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§26 ANIMATION (DESIGN_TOKENS.md Β§7)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* Scroll Reveal β apply class="reveal" to content sections */
.reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
/* Staggered delays for sibling elements */
.reveal-delay-1 { transition-delay: 0.1s; }
.reveal-delay-2 { transition-delay: 0.2s; }
.reveal-delay-3 { transition-delay: 0.3s; }
.reveal-delay-4 { transition-delay: 0.4s; }
/* Ambient Glow β landing page ONLY */
.ambient {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.ambient::before {
content: '';
position: absolute;
top: -40%;
left: -20%;
width: 80%;
height: 80%;
background: radial-gradient(ellipse, rgba(94, 234, 212, 0.03) 0%, transparent 70%);
animation: drift 25s ease-in-out infinite;
}
@keyframes drift {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(40px, 20px); }
}
/* Fade In β staggered hero elements */
@keyframes fadeIn { to { opacity: 1; } }
/* Usage: opacity: 0; animation: fadeIn 2s 0.7s cubic-bezier(0.16, 1, 0.3, 1) forwards; */
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§27 RESPONSIVE BREAKPOINTS (DESIGN_TOKENS.md Β§8)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* Tablet and below (β€768px) */
@media (max-width: 768px) {
.obs-container {
padding: 0 var(--space-4);
}
.glass-card {
padding: var(--space-6);
}
.data-row {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.stats-row {
flex-wrap: wrap;
gap: 24px;
justify-content: center;
}
.stat-divider { display: none; }
.stat-item { flex: 0 0 40%; }
/* Capability list (cap-item/cap-num) */
.cap-item { grid-template-columns: 1fr; gap: 6px; }
.cap-num { display: none; }
/* Demo body */
.demo-body { padding: 20px 16px; }
/* Search dropdown */
.dropdown { max-height: 320px; }
/* Intel grid */
.intel-grid { grid-template-columns: 1fr !important; }
}
/* Phone (β€480px) */
@media (max-width: 480px) {
.obs-container {
padding: 0 var(--space-4);
}
.glass-card {
padding: var(--space-4);
}
.stat-item {
flex: 0 0 100%;
}
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§28 PRINT STYLES (DESIGN_TOKENS.md Β§5 β Print Styles)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
@media print {
/* Invert palette */
body {
background: #fff !important;
color: #1a1a1a !important;
}
/* Hide chrome */
.nav-float,
.ambient,
.toast,
.modal-backdrop,
.ghost-cta,
.action-btn,
footer,
.search-bar,
.kbd-hint { display: none !important; }
/* Cards become bordered containers */
.glass-card {
background: #fff !important;
border: 1px solid #ddd !important;
break-inside: avoid;
}
/* Text colors for print */
.data-row__label,
.obs-table td { color: #555 !important; }
.data-row__value,
.obs-table__mono,
.stat-number { color: #1a1a1a !important; }
/* Table headers */
.obs-table th {
color: #777 !important;
border-bottom: 1px solid #ccc !important;
}
.obs-table tr:hover { background: none !important; }
/* Status colors stay semantic */
.status-text--green { color: #16a34a !important; }
.status-text--amber { color: #d97706 !important; }
.status-text--red { color: #dc2626 !important; }
/* Status dots β darker for print */
.status-dot--green { background: #16a34a !important; }
.status-dot--amber { background: #d97706 !important; }
.status-dot--red { background: #dc2626 !important; }
/* Links show URLs */
a[href]:not(.ghost-cta)::after {
content: " (" attr(href) ")";
font-size: 9px;
color: #888;
}
/* Disable animations */
.reveal { opacity: 1 !important; transform: none !important; }
/* Page breaks */
h2, h3 { break-after: avoid; }
.glass-card { break-inside: avoid; }
/* Data freshness footer β keep visible */
.data-freshness { display: block !important; color: #999 !important; }
}
/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β§29 ACCESSIBILITY β REDUCED MOTION & FOCUS (DESIGN_TOKENS.md Β§15)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
.reveal {
opacity: 1;
transform: none;
}
.ambient {
display: none;
}
}
/* Focus indicators β all interactive elements */
:focus-visible {
outline: none;
box-shadow: 0 0 0 3px var(--accent-ring);
}