Files
web_template/base.css
T
jared 0eb91f1937 v1.1: Add 10 new feature modules + 18 CSS component sections
JS modules added:
- lt.theme    — dark/light toggle, OS preference sync, localStorage persist
- lt.notif    — notification badge (set/inc/clear) on any element
- lt.rightDrawer — right-side detail panel with focus trap + return focus
- lt.contextMenu — right-click custom menu, keyboard nav, danger variant
- lt.offline  — navigator.onLine banner + event hooks
- lt.ws       — WebSocket manager with exponential backoff reconnect
- lt.combobox — multi-select with search, tag chips, keyboard nav
- lt.typeahead — async/sync autocomplete with match highlighting
- lt.cookie   — get/set/del with SameSite/Secure helpers
- lt.splitPane — pointer-events resizable split pane (horizontal/vertical)
- Toast queue: max-stack, progress bar drain animation, auto-drain

CSS sections added (51–68):
- Light theme (html[data-theme="light"]) with full variable overrides
- Theme toggle button (.lt-theme-btn)
- Skeleton loader variants (card, row, text, title, avatar, btn, badge)
- Empty state component (.lt-empty-state, --sm variant)
- Nav notification badge (.lt-notif-wrap / .lt-notif-badge)
- Right-side drawer (.lt-drawer-right + overlay)
- Sticky table header (.lt-table-sticky-wrap)
- Multi-select combobox (.lt-combobox, tags, dropdown)
- Context menu (.lt-context-menu, divider, label, danger)
- Offline banner (.lt-offline-banner)
- Timeline / activity feed (.lt-timeline, color variants)
- Avatar + avatar group + status ring (.lt-avatar)
- Split pane (.lt-split, .lt-split-divider with pointer drag)
- Chart container (.lt-chart-wrap, legend, axis, loading state)
- Toast queue stack + progress drain bar
- Autocomplete / typeahead (.lt-typeahead-dropdown, match highlight)
- WebSocket status indicator (.lt-ws-status, data-state variants)
- Print enhancements (extended @media print rules)

HTML demo sections for all new components added to base.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 22:29:55 -04:00

4196 lines
125 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ================================================================
LOTUSGUILD TERMINAL DESIGN SYSTEM v1.2 — base.css
Aesthetic: Anduril x Hacker Terminal — dark military-tech,
multi-accent neon, angular frames, glitch effects.
Apps: Tinker Tickets (PHP), PULSE (Node.js), GANDALF (Flask)
Prefix: .lt-* (LotusGuild Terminal)
TABLE OF CONTENTS
01. CSS Custom Properties 27. Progress Bars
02. Reset & Base 28. Tooltips
03. CRT / Grid / Scanline 29. Breadcrumbs
04. Typography 30. Pagination
05. Layout Primitives 31. Accordion
06. Header & Navigation 32. Alert Banners
07. ASCII Frame System 33. Toggle Switch
08. Card Component 34. Range Slider
09. Buttons 35. File Upload / Dropzone
10. Forms & Inputs 36. Command Palette
11. Tables 37. Code Blocks
12. Status Badges / Chips 38. Tags / Chips
13. Modals 39. Notification Badges
14. Toast Notifications 40. Stepper / Wizard
15. Tab Navigation 41. List Groups
16. Sidebar / Filter Panel 42. Key-Value Pairs
17. Stats Widgets 43. Hero / Banner
18. Inline Messages 44. Divider with Label
19. Loading & Empty States 45. Custom Scrollbar
20. Boot Sequence Overlay 46. Responsive Table Cards
21. Log / Timeline Entries 47. Gauge / Meter
22. Animations (keyframes) 48. Spinners / Loaders
23. Responsive Design 49. Tab Bar
24. Utility Classes 50. Utility Additions
25. Print Styles
26. Accessibility
================================================================ */
/* ----------------------------------------------------------------
01. CSS CUSTOM PROPERTIES
---------------------------------------------------------------- */
:root {
/* --- Backgrounds --- */
--bg-primary: #030508;
--bg-secondary: #060c14;
--bg-tertiary: #0d1520;
--bg-card: #07101a;
--bg-terminal: #010304;
--bg-overlay: rgba(3,5,8,0.94);
/* --- Primary accent: Anduril Orange --- */
--accent-orange: #FF6B00;
--accent-orange-bright: #FF8C2B;
--accent-orange-dim: rgba(255,107,0,0.12);
--accent-orange-border: rgba(255,107,0,0.35);
--accent-amber: #FFB300;
--accent-amber-dim: rgba(255,179,0,0.10);
/* --- Secondary accent: Ice Cyan --- */
--accent-cyan: #00D4FF;
--accent-cyan-bright: #33DFFF;
--accent-cyan-dim: rgba(0,212,255,0.10);
--accent-cyan-border: rgba(0,212,255,0.22);
/* --- Tertiary accent: Matrix Green --- */
--accent-green: #00FF88;
--accent-green-bright: #33FFAA;
--accent-green-dim: rgba(0,255,136,0.10);
--accent-green-border: rgba(0,255,136,0.22);
/* --- Error / Critical --- */
--accent-red: #FF2D55;
--accent-red-dim: rgba(255,45,85,0.12);
/* --- Warning --- */
--accent-gold: #FFD700;
--accent-gold-dim: rgba(255,215,0,0.10);
/* --- Purple (admin / misc) --- */
--accent-purple: #BF5FFF;
--accent-purple-dim: rgba(191,95,255,0.10);
/* Legacy aliases — keeps all existing component HTML working */
--terminal-green: var(--accent-green);
--terminal-green-dim: var(--accent-green-dim);
--terminal-green-dark: #00cc66;
--terminal-green-muted: #007744;
--terminal-amber: var(--accent-amber);
--terminal-amber-dim: var(--accent-amber-dim);
--terminal-cyan: var(--accent-cyan);
--terminal-cyan-dim: var(--accent-cyan-dim);
--terminal-red: var(--accent-red);
--terminal-red-dim: var(--accent-red-dim);
--terminal-orange: var(--accent-orange);
--terminal-orange-dim: var(--accent-orange-dim);
/* --- Text --- */
--text-primary: #c4d9ee;
--text-secondary: #7fa3bf;
--text-muted: #3e607a;
--text-dim: #1e3347;
/* --- Borders --- */
--border-color: rgba(0,212,255,0.16);
--border-color-hi: var(--accent-cyan);
--border-color-dim: rgba(0,212,255,0.07);
--border-dim: rgba(0,212,255,0.07); /* alias for v1.2+ components */
--border-orange: var(--accent-orange-border);
/* --- Workflow / status colours --- */
--status-open: var(--accent-green);
--status-pending: var(--accent-purple);
--status-in-progress: var(--accent-amber);
--status-closed: var(--accent-red);
--status-online: var(--accent-green);
--status-offline: var(--accent-red);
--status-running: var(--accent-amber);
--status-completed: var(--accent-cyan);
--status-failed: var(--accent-red);
--status-waiting: var(--accent-gold);
/* --- Priority colours --- */
--priority-1: #FF2D55;
--priority-2: #FF6B00;
--priority-3: #00D4FF;
--priority-4: #00FF88;
--priority-5: #3e607a;
/* --- Glow: text-shadow stacks --- */
--glow-orange: 0 0 6px #FF6B00, 0 0 16px rgba(255,107,0,0.55);
--glow-orange-intense: 0 0 8px #FF6B00, 0 0 22px #FF6B00, 0 0 40px rgba(255,107,0,0.45);
--glow-cyan: 0 0 6px #00D4FF, 0 0 16px rgba(0,212,255,0.45);
--glow-cyan-intense: 0 0 8px #00D4FF, 0 0 22px #00D4FF, 0 0 38px rgba(0,212,255,0.35);
--glow-green: 0 0 6px #00FF88, 0 0 16px rgba(0,255,136,0.45);
--glow-green-intense: 0 0 8px #00FF88, 0 0 22px #00FF88, 0 0 36px rgba(0,255,136,0.35);
--glow-amber: 0 0 6px #FFB300, 0 0 14px rgba(255,179,0,0.40);
--glow-amber-intense: 0 0 8px #FFB300, 0 0 20px #FFB300, 0 0 34px rgba(255,179,0,0.45);
--glow-red: 0 0 6px #FF2D55, 0 0 16px rgba(255,45,85,0.45);
/* --- Glow: box-shadow halos --- */
--box-glow-orange: 0 0 18px rgba(255,107,0,0.22), 0 0 36px rgba(255,107,0,0.08);
--box-glow-cyan: 0 0 18px rgba(0,212,255,0.18), 0 0 36px rgba(0,212,255,0.06);
--box-glow-green: 0 0 18px rgba(0,255,136,0.18), 0 0 36px rgba(0,255,136,0.06);
--box-glow-red: 0 0 18px rgba(255,45,85,0.22), 0 0 36px rgba(255,45,85,0.08);
--box-glow-amber: 0 0 18px rgba(255,179,0,0.18), 0 0 36px rgba(255,179,0,0.06);
/* --- Typography --- */
--font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Courier New', monospace;
--font-display: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
/* --- Spacing --- */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
/* --- Layout --- */
--sidebar-width: 240px;
--sidebar-width-sm: 200px;
--header-height: 56px;
--container-max: 1600px;
/* --- Transitions --- */
--transition-fast: all 0.12s ease;
--transition-default: all 0.25s ease;
/* --- Z-index ladder --- */
--z-base: 1;
--z-dropdown: 100;
--z-sticky: 200;
--z-fixed: 300;
--z-modal-backdrop: 10010; /* above nav drawer (10002) so modals always accessible */
--z-modal: 10011;
--z-popover: 10012;
--z-tooltip: 10013;
--z-toast: 10014;
--z-overlay: 9999; /* scanlines / CRT effects */
}
/* ----------------------------------------------------------------
02. RESET & BASE
---------------------------------------------------------------- */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 14px;
scroll-behavior: smooth;
/* Dot-grid tactical background */
background-color: var(--bg-primary);
background-image:
radial-gradient(circle, rgba(0,212,255,0.055) 1px, transparent 1px);
background-size: 28px 28px;
}
body {
background-color: transparent;
color: var(--text-primary);
font-family: var(--font-mono);
font-size: 0.875rem;
line-height: 1.65;
min-height: 100vh;
overflow-x: hidden;
position: relative;
}
a {
color: var(--accent-cyan);
text-decoration: none;
transition: var(--transition-fast);
}
a:hover {
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
ul, ol { list-style: none; }
img, svg { display: block; max-width: 100%; }
button { cursor: pointer; font-family: var(--font-mono); }
/* ----------------------------------------------------------------
03. CRT / GRID / SCANLINE EFFECTS
---------------------------------------------------------------- */
/* Horizontal scanlines — fixed, non-interactive overlay */
body::before {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0,0,0,0.07) 0px,
rgba(0,0,0,0.07) 1px,
transparent 1px,
transparent 3px
);
pointer-events: none;
z-index: var(--z-overlay);
}
/* Corner vignette */
body::after {
content: '';
position: fixed;
inset: 0;
background: radial-gradient(
ellipse at center,
transparent 55%,
rgba(0,0,0,0.60) 100%
);
pointer-events: none;
z-index: calc(var(--z-overlay) - 1);
}
/* ----------------------------------------------------------------
04. TYPOGRAPHY
---------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-display);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.10em;
line-height: 1.25;
}
h1 {
font-size: 1.5rem;
color: var(--accent-orange);
text-shadow: var(--glow-orange-intense);
}
h1::before { content: '>> '; color: var(--accent-cyan); text-shadow: var(--glow-cyan); }
h2 {
font-size: 1.15rem;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
h2::before { content: '> '; color: var(--accent-cyan); opacity: 0.65; }
h3 {
font-size: 0.95rem;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
}
h4 {
font-size: 0.85rem;
color: var(--text-secondary);
}
p { margin-bottom: var(--space-md); }
p:last-child { margin-bottom: 0; }
code, pre {
font-family: var(--font-mono);
font-size: 0.8rem;
background: var(--bg-terminal);
border: 1px solid var(--border-color);
color: var(--accent-green);
}
code {
padding: 0.1em 0.35em;
}
pre {
padding: var(--space-md);
overflow-x: auto;
white-space: pre-wrap;
border-left: 2px solid var(--accent-green);
text-shadow: var(--glow-green);
}
hr {
border: none;
border-top: 1px solid var(--border-color-dim);
margin: var(--space-lg) 0;
}
/* ----------------------------------------------------------------
05. LAYOUT PRIMITIVES
---------------------------------------------------------------- */
.lt-container {
max-width: var(--container-max);
margin: 0 auto;
padding: var(--space-lg) var(--space-xl);
}
.lt-main {
padding-top: calc(var(--header-height) + var(--space-lg));
}
.lt-layout {
display: flex;
gap: var(--space-lg);
align-items: flex-start;
}
.lt-content { flex: 1; min-width: 0; }
.lt-grid-2 { display: grid; grid-template-columns: repeat(2,1fr); gap: var(--space-lg); }
.lt-grid-3 { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space-lg); }
.lt-grid-4 { display: grid; grid-template-columns: repeat(4,1fr); gap: var(--space-lg); }
.lt-flex { display: flex; align-items: center; }
.lt-flex-between { display: flex; align-items: center; justify-content: space-between; }
.lt-flex-center { display: flex; align-items: center; justify-content: center; }
.lt-flex-col { display: flex; flex-direction: column; }
.lt-flex-wrap { flex-wrap: wrap; }
.lt-gap-sm { gap: var(--space-sm); }
.lt-gap-md { gap: var(--space-md); }
.lt-gap-lg { gap: var(--space-lg); }
.lt-mt-sm { margin-top: var(--space-sm); }
.lt-mt-md { margin-top: var(--space-md); }
.lt-mb-sm { margin-bottom: var(--space-sm); }
.lt-mb-md { margin-bottom: var(--space-md); }
.lt-p-md { padding: var(--space-md); }
.lt-divider {
border: none;
border-top: 1px solid var(--border-color-dim);
margin: var(--space-xl) 0;
}
/* ----------------------------------------------------------------
06. HEADER & NAVIGATION
---------------------------------------------------------------- */
.lt-header {
position: fixed;
top: 0; left: 0; right: 0;
height: var(--header-height);
background: rgba(3,5,8,0.96);
backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--space-xl);
z-index: var(--z-fixed);
box-shadow: 0 4px 32px rgba(0,0,0,0.7);
}
/* Gradient rule along bottom edge */
.lt-header::after {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent 0%,
var(--accent-cyan) 20%,
var(--accent-orange) 50%,
var(--accent-cyan) 80%,
transparent 100%
);
opacity: 0.55;
}
.lt-header-left {
display: flex;
align-items: center;
gap: var(--space-xl);
}
.lt-header-right {
display: flex;
align-items: center;
gap: var(--space-md);
}
/* Brand */
.lt-brand { display: flex; flex-direction: column; line-height: 1.1; }
.lt-brand-title {
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
.lt-brand-title::before { content: '[ '; color: var(--accent-cyan); text-shadow: var(--glow-cyan); }
.lt-brand-title::after { content: ' ]'; color: var(--accent-cyan); text-shadow: var(--glow-cyan); }
.lt-brand-subtitle {
font-size: 0.58rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.22em;
}
/* Nav links */
.lt-nav {
display: flex;
align-items: center;
gap: 2px;
}
.lt-nav-link {
display: inline-block;
padding: 0.35rem 0.8rem;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.13em;
color: var(--text-secondary);
border: 1px solid transparent;
transition: var(--transition-fast);
position: relative;
}
.lt-nav-link::after {
content: '';
position: absolute;
bottom: -1px;
left: 50%; right: 50%;
height: 1px;
background: var(--accent-cyan);
transition: var(--transition-fast);
}
.lt-nav-link:hover {
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
border-color: var(--accent-cyan-border);
background: var(--accent-cyan-dim);
}
.lt-nav-link:hover::after { left: 0; right: 0; box-shadow: var(--glow-cyan); }
.lt-nav-link.active {
color: var(--accent-orange);
text-shadow: var(--glow-orange);
border-color: var(--accent-orange-border);
background: var(--accent-orange-dim);
}
.lt-nav-link.active::after {
left: 0; right: 0;
background: var(--accent-orange);
box-shadow: var(--glow-orange);
}
/* Dropdown */
.lt-nav-dropdown { position: relative; }
.lt-nav-dropdown-menu {
display: none;
position: absolute;
top: calc(100% + 4px);
left: 0;
min-width: 180px;
background: rgba(6,12,20,0.98);
border: 1px solid var(--accent-cyan-border);
box-shadow: var(--box-glow-cyan), 0 16px 40px rgba(0,0,0,0.8);
z-index: var(--z-dropdown);
}
.lt-nav-dropdown-menu::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 1px;
background: var(--accent-cyan);
box-shadow: var(--glow-cyan);
}
.lt-nav-dropdown:hover .lt-nav-dropdown-menu { display: block; }
.lt-nav-dropdown-menu li a {
display: block;
padding: 0.5rem 0.9rem;
font-size: 0.7rem;
color: var(--text-secondary);
border-bottom: 1px solid var(--border-color-dim);
text-transform: uppercase;
letter-spacing: 0.09em;
transition: var(--transition-fast);
}
.lt-nav-dropdown-menu li:last-child a { border-bottom: none; }
.lt-nav-dropdown-menu li a:hover {
color: var(--accent-orange);
background: var(--accent-orange-dim);
text-shadow: var(--glow-orange);
padding-left: 1.1rem;
}
/* Header user + admin badge */
.lt-header-user {
font-size: 0.7rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.11em;
}
.lt-header-user::before {
content: 'OP: ';
color: var(--accent-green);
text-shadow: var(--glow-green);
font-size: 0.62rem;
}
.lt-badge-admin {
font-size: 0.58rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.16em;
padding: 0.15rem 0.5rem;
color: var(--accent-purple);
border: 1px solid rgba(191,95,255,0.45);
background: rgba(191,95,255,0.08);
text-shadow: 0 0 6px var(--accent-purple);
box-shadow: 0 0 10px rgba(191,95,255,0.18);
}
/* Page header row */
.lt-page-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-lg);
padding-bottom: var(--space-md);
border-bottom: 1px solid var(--border-color-dim);
}
.lt-page-title {
font-size: 1.3rem;
color: var(--accent-orange);
text-shadow: var(--glow-orange-intense);
text-transform: uppercase;
letter-spacing: 0.13em;
}
.lt-page-title::before {
content: '// ';
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
}
/* ----------------------------------------------------------------
07. ASCII FRAME SYSTEM
---------------------------------------------------------------- */
.lt-frame {
position: relative;
border: 1px solid var(--border-color);
background: var(--bg-card);
margin-bottom: var(--space-lg);
clip-path: polygon(
0 0,
calc(100% - 14px) 0,
100% 14px,
100% 100%,
14px 100%,
0 calc(100% - 14px)
);
}
/* Top-right corner pip */
.lt-frame::before {
content: '◈';
position: absolute;
top: -1px; right: 3px;
font-size: 0.52rem;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
line-height: 1;
pointer-events: none;
}
.lt-frame-bl,
.lt-frame-br {
position: absolute;
bottom: 4px;
font-size: 0.65rem;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
line-height: 1;
pointer-events: none;
}
.lt-frame-bl { left: 6px; }
.lt-frame-br { right: 6px; }
.lt-section-header {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.20em;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
padding: 0.5rem 1rem;
border-bottom: 1px solid var(--border-color);
background: rgba(255,107,0,0.05);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.lt-section-header::before {
content: '▸';
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
}
/* Right padding accounts for the 14px clip-path corner cut on .lt-frame */
.lt-section-body { padding: var(--space-md); padding-right: 22px; }
/* Inner / nested frame */
.lt-frame-inner {
border: 1px solid var(--border-color-dim);
margin: var(--space-md);
background: rgba(0,212,255,0.018);
}
.lt-subsection-header {
font-size: 0.63rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.18em;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
padding: 0.4rem 0.9rem;
border-bottom: 1px solid var(--border-color-dim);
background: rgba(0,212,255,0.03);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.lt-subsection-header::before {
content: '◦';
color: var(--accent-cyan);
opacity: 0.55;
}
/* ----------------------------------------------------------------
08. CARD COMPONENT
---------------------------------------------------------------- */
.lt-card {
position: relative;
background: var(--bg-card);
border: 1px solid var(--border-color);
padding: var(--space-md);
transition: var(--transition-fast);
clip-path: polygon(
0 0,
calc(100% - 10px) 0,
100% 10px,
100% 100%,
0 100%
);
}
/* Corner accent — top-right triangle */
.lt-card::before {
content: '';
position: absolute;
top: 0; right: 0;
width: 0; height: 0;
border-style: solid;
border-width: 0 10px 10px 0;
border-color: transparent var(--accent-cyan) transparent transparent;
opacity: 0.4;
transition: var(--transition-fast);
}
.lt-card:hover {
border-color: var(--accent-cyan-border);
background: var(--bg-tertiary);
box-shadow: var(--box-glow-cyan);
}
.lt-card:hover::before {
opacity: 1;
border-right-color: var(--accent-orange);
}
/* ----------------------------------------------------------------
09. BUTTONS
---------------------------------------------------------------- */
.lt-btn {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
padding: 0.4rem 0.9rem;
font-family: var(--font-mono);
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--accent-cyan);
background: transparent;
border: 1px solid var(--accent-cyan-border);
transition: var(--transition-fast);
cursor: pointer;
text-decoration: none;
white-space: nowrap;
position: relative;
clip-path: polygon(
0 0,
calc(100% - 7px) 0,
100% 7px,
100% 100%,
7px 100%,
0 calc(100% - 7px)
);
}
.lt-btn:hover {
color: var(--accent-cyan-bright);
border-color: var(--accent-cyan);
background: var(--accent-cyan-dim);
box-shadow: var(--box-glow-cyan);
text-shadow: var(--glow-cyan);
text-decoration: none;
}
.lt-btn:active { transform: translateY(1px); }
.lt-btn:disabled,
.lt-btn[disabled] {
opacity: 0.30;
cursor: not-allowed;
box-shadow: none;
}
/* Primary — orange */
.lt-btn-primary {
color: var(--accent-orange);
border-color: var(--accent-orange-border);
}
.lt-btn-primary:hover {
color: var(--accent-orange-bright);
border-color: var(--accent-orange);
background: var(--accent-orange-dim);
box-shadow: var(--box-glow-orange);
text-shadow: var(--glow-orange);
}
/* Danger — red */
.lt-btn-danger {
color: var(--accent-red);
border-color: rgba(255,45,85,0.32);
}
.lt-btn-danger:hover {
border-color: var(--accent-red);
background: var(--accent-red-dim);
box-shadow: var(--box-glow-red);
text-shadow: var(--glow-red);
}
/* Ghost — minimal */
.lt-btn-ghost {
color: var(--text-muted);
border-color: var(--border-color-dim);
clip-path: none;
}
.lt-btn-ghost:hover {
color: var(--text-secondary);
border-color: var(--border-color);
background: rgba(196,217,238,0.03);
box-shadow: none;
text-shadow: none;
}
/* Small */
.lt-btn-sm {
padding: 0.22rem 0.6rem;
font-size: 0.62rem;
}
.lt-btn-group {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
flex-wrap: wrap;
}
/* ----------------------------------------------------------------
10. FORMS & INPUTS
---------------------------------------------------------------- */
.lt-form-group {
display: flex;
flex-direction: column;
gap: var(--space-xs);
margin-bottom: var(--space-md);
}
.lt-label {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--text-secondary);
}
.lt-label-required::after { content: ' *'; color: var(--accent-red); }
.lt-input,
.lt-select,
.lt-textarea {
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--text-primary);
background: var(--bg-terminal);
border: 1px solid var(--border-color);
padding: 0.45rem 0.8rem;
width: 100%;
outline: none;
transition: var(--transition-fast);
clip-path: polygon(0 0, calc(100% - 7px) 0, 100% 7px, 100% 100%, 0 100%);
}
.lt-input:focus,
.lt-select:focus,
.lt-textarea:focus {
border-color: var(--accent-cyan);
box-shadow: var(--box-glow-cyan);
background: rgba(0,212,255,0.025);
}
.lt-input::placeholder,
.lt-textarea::placeholder { color: var(--text-dim); }
.lt-select {
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2300D4FF'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.75rem center;
padding-right: 2rem;
color-scheme: dark;
}
/* Style the native option list — works on Chrome/Firefox/Edge on Windows & Linux.
macOS always uses OS-native rendering and ignores these. */
.lt-select option,
select option {
background: #0d1117;
color: #c9d1d9;
}
.lt-select option:hover,
.lt-select option:focus,
.lt-select option:checked,
select option:checked {
background: #1a2030;
color: #FF6B00;
}
.lt-textarea {
min-height: 100px;
resize: vertical;
clip-path: none;
}
.lt-form-hint {
font-size: 0.63rem;
color: var(--text-muted);
letter-spacing: 0.04em;
}
/* Search */
.lt-search { position: relative; }
.lt-search-input { padding-left: 2rem; }
.lt-search::before {
content: '⌕';
position: absolute;
left: 0.6rem;
top: 50%;
transform: translateY(-50%);
color: var(--text-muted);
pointer-events: none;
font-size: 0.9rem;
z-index: 1;
}
/* Checkbox */
.lt-checkbox {
appearance: none;
width: 14px;
height: 14px;
border: 1px solid var(--accent-cyan-border);
background: var(--bg-terminal);
cursor: pointer;
position: relative;
flex-shrink: 0;
vertical-align: middle;
transition: var(--transition-fast);
}
.lt-checkbox:checked {
background: var(--accent-cyan-dim);
border-color: var(--accent-cyan);
}
.lt-checkbox:checked::after {
content: '✓';
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.6rem;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
}
.lt-checkbox:hover { border-color: var(--accent-cyan); }
/* ----------------------------------------------------------------
11. TABLES
---------------------------------------------------------------- */
.lt-table-wrap { overflow-x: auto; }
.lt-table {
width: 100%;
border-collapse: collapse;
font-size: 0.78rem;
}
.lt-table thead {
border-bottom: 1px solid var(--accent-cyan-border);
background: rgba(0,212,255,0.04);
}
.lt-table th {
padding: 0.6rem 0.85rem;
text-align: left;
font-size: 0.62rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
white-space: nowrap;
cursor: default;
}
.lt-table th[data-sort-key] { cursor: pointer; }
.lt-table th[data-sort-key]:hover {
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
.lt-table td {
padding: 0.55rem 0.85rem;
border-bottom: 1px solid var(--border-color-dim);
color: var(--text-primary);
vertical-align: middle;
overflow-wrap: break-word;
word-break: break-word;
max-width: 280px; /* prevent single cell from expanding table beyond viewport */
}
.lt-table tbody tr { transition: var(--transition-fast); }
.lt-table tbody tr:hover {
background: rgba(0,212,255,0.04);
outline: 1px solid var(--border-color-dim);
outline-offset: -1px;
}
/* Row priority accent bars */
.lt-row-critical, .lt-row-p1 {
border-left: 2px solid var(--priority-1) !important;
background: rgba(255,45,85,0.035) !important;
}
.lt-row-warning, .lt-row-p2 { border-left: 2px solid var(--priority-2) !important; }
.lt-row-p3 { border-left: 2px solid var(--priority-3) !important; }
.lt-row-p4 { border-left: 2px solid var(--priority-4) !important; }
/* Compact data table */
.lt-data-table {
width: 100%;
border-collapse: collapse;
font-size: 0.75rem;
}
.lt-data-table td {
padding: 0.3rem 0.5rem;
border-bottom: 1px solid var(--border-color-dim);
}
.lt-data-table thead tr { border-bottom: 1px solid var(--border-color); }
.lt-data-table th {
font-size: 0.62rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent-cyan);
padding: 0.35rem 0.5rem;
}
.lt-data-table-wrapper { padding: 0 var(--space-xs); }
/* ----------------------------------------------------------------
12. STATUS BADGES, CHIPS, PRIORITY
---------------------------------------------------------------- */
.lt-status {
display: inline-block;
padding: 0.14rem 0.5rem;
font-size: 0.58rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.15em;
border: 1px solid currentColor;
background: transparent;
white-space: nowrap;
}
.lt-status-open { color: var(--status-open); background: rgba(0,255,136,0.07); }
.lt-status-pending { color: var(--status-pending); background: rgba(191,95,255,0.07); }
.lt-status-in-progress { color: var(--status-in-progress); background: rgba(255,179,0,0.07); }
.lt-status-closed { color: var(--status-closed); background: rgba(255,45,85,0.07); }
.lt-status-online { color: var(--status-online); background: rgba(0,255,136,0.07); text-shadow: var(--glow-green); }
.lt-status-offline { color: var(--status-offline); background: rgba(255,45,85,0.07); }
.lt-status-running { color: var(--status-running); background: rgba(255,179,0,0.07); animation: pulse-amber 2s infinite; }
.lt-status-completed { color: var(--status-completed); background: rgba(0,212,255,0.07); }
.lt-status-failed { color: var(--status-failed); background: rgba(255,45,85,0.07); }
/* Priority badges */
.lt-priority,
.lt-p1, .lt-p2, .lt-p3, .lt-p4, .lt-p5 {
display: inline-block;
padding: 0.12rem 0.45rem;
font-size: 0.58rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
border: 1px solid currentColor;
}
.lt-p1 { color: var(--priority-1); background: rgba(255,45,85,0.09); border-color: rgba(255,45,85,0.4); text-shadow: var(--glow-red); }
.lt-p2 { color: var(--priority-2); background: rgba(255,107,0,0.09); border-color: rgba(255,107,0,0.38); }
.lt-p3 { color: var(--priority-3); background: rgba(0,212,255,0.07); border-color: rgba(0,212,255,0.30); }
.lt-p4 { color: var(--priority-4); background: rgba(0,255,136,0.07); border-color: rgba(0,255,136,0.30); }
.lt-p5 { color: var(--priority-5); background: rgba(62,96,122,0.09); border-color: rgba(62,96,122,0.30); }
/* Chips */
.lt-chip {
display: inline-flex;
align-items: center;
padding: 0.15rem 0.5rem;
font-size: 0.58rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
border: 1px solid currentColor;
}
.lt-chip-ok { color: var(--accent-green); background: var(--accent-green-dim); text-shadow: var(--glow-green); }
.lt-chip-warn { color: var(--accent-amber); background: var(--accent-amber-dim); }
.lt-chip-critical { color: var(--accent-red); background: var(--accent-red-dim); text-shadow: var(--glow-red); }
.lt-chip-info { color: var(--accent-cyan); background: var(--accent-cyan-dim); text-shadow: var(--glow-cyan); }
/* Generic badges */
.lt-badge {
display: inline-block;
padding: 0.1rem 0.4rem;
font-size: 0.56rem;
font-weight: 700;
letter-spacing: 0.1em;
border: 1px solid currentColor;
}
.lt-badge-green { color: var(--accent-green); }
.lt-badge-amber { color: var(--accent-amber); }
.lt-badge-red { color: var(--accent-red); }
/* Status dots */
.lt-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.lt-dot-up { background: var(--accent-green); box-shadow: 0 0 6px var(--accent-green), 0 0 14px var(--accent-green); animation: pulse-green 2.2s ease-in-out infinite; }
.lt-dot-down { background: var(--accent-red); box-shadow: 0 0 6px var(--accent-red), 0 0 12px var(--accent-red); }
.lt-dot-warn { background: var(--accent-amber); box-shadow: 0 0 6px var(--accent-amber), 0 0 12px var(--accent-amber); animation: pulse-amber 2.2s ease-in-out infinite; }
.lt-dot-idle { background: var(--text-muted); box-shadow: none; }
/* ----------------------------------------------------------------
13. MODALS
---------------------------------------------------------------- */
.lt-modal-overlay {
display: none;
position: fixed;
inset: 0;
background: var(--bg-overlay);
backdrop-filter: blur(8px);
z-index: var(--z-modal-backdrop);
align-items: center;
justify-content: center;
}
.lt-modal-overlay.is-open { display: flex; }
.lt-modal {
position: relative;
background: var(--bg-secondary);
border: 1px solid var(--accent-cyan-border);
width: min(520px, 92vw);
max-height: 85vh;
display: flex;
flex-direction: column;
box-shadow: var(--box-glow-cyan), 0 40px 80px rgba(0,0,0,0.85);
clip-path: polygon(
0 0,
calc(100% - 18px) 0,
100% 18px,
100% 100%,
18px 100%,
0 calc(100% - 18px)
);
animation: modal-in 0.18s ease;
}
.lt-modal::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
box-shadow: var(--glow-cyan);
}
.lt-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--border-color);
background: rgba(0,212,255,0.035);
flex-shrink: 0;
}
.lt-modal-title {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
.lt-modal-close {
background: none;
border: none;
color: var(--text-muted);
font-size: 0.85rem;
line-height: 1;
cursor: pointer;
padding: 0.2rem 0.4rem;
transition: var(--transition-fast);
}
.lt-modal-close:hover { color: var(--accent-red); text-shadow: var(--glow-red); }
.lt-modal-body {
padding: var(--space-lg);
overflow-y: auto;
flex: 1;
}
.lt-modal-footer {
display: flex;
align-items: center;
justify-content: flex-end;
gap: var(--space-sm);
padding: 0.75rem 1rem;
border-top: 1px solid var(--border-color-dim);
background: rgba(0,0,0,0.25);
flex-shrink: 0;
}
/* ----------------------------------------------------------------
14. TOAST NOTIFICATIONS
---------------------------------------------------------------- */
#lt-toast-container {
position: fixed;
bottom: var(--space-lg);
right: var(--space-lg);
display: flex;
flex-direction: column;
gap: var(--space-sm);
z-index: var(--z-toast);
pointer-events: none;
}
.lt-toast {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: 0.5rem 0.9rem;
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
min-width: 240px;
max-width: 380px;
border-left: 2px solid currentColor;
background: rgba(6,12,20,0.97);
backdrop-filter: blur(8px);
border-top: 1px solid rgba(255,255,255,0.04);
border-right: 1px solid rgba(255,255,255,0.04);
border-bottom: 1px solid rgba(255,255,255,0.04);
pointer-events: all;
animation: toast-in 0.2s ease;
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
.lt-toast-success { color: var(--accent-green); border-left-color: var(--accent-green); box-shadow: var(--box-glow-green); }
.lt-toast-error { color: var(--accent-red); border-left-color: var(--accent-red); box-shadow: var(--box-glow-red); }
.lt-toast-warning { color: var(--accent-amber); border-left-color: var(--accent-amber); box-shadow: var(--box-glow-amber); }
.lt-toast-info { color: var(--accent-cyan); border-left-color: var(--accent-cyan); box-shadow: var(--box-glow-cyan); }
/* ----------------------------------------------------------------
15. TAB NAVIGATION
---------------------------------------------------------------- */
.lt-tabs {
display: flex;
align-items: flex-end;
gap: 2px;
border-bottom: 1px solid var(--border-color);
margin-bottom: var(--space-lg);
}
.lt-tab {
padding: 0.45rem 0.9rem;
font-family: var(--font-mono);
font-size: 0.67rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.14em;
color: var(--text-muted);
background: transparent;
border: 1px solid transparent;
border-bottom: none;
cursor: pointer;
transition: var(--transition-fast);
}
.lt-tab:hover {
color: var(--text-secondary);
background: rgba(0,212,255,0.04);
border-color: var(--border-color-dim);
}
.lt-tab.active {
color: var(--accent-orange);
text-shadow: var(--glow-orange);
background: var(--bg-card);
border-color: var(--accent-orange-border);
border-bottom-color: var(--bg-card);
}
.lt-tab-panel { display: none; }
.lt-tab-panel.active { display: block; }
/* ----------------------------------------------------------------
16. SIDEBAR / FILTER PANEL
---------------------------------------------------------------- */
.lt-sidebar {
width: var(--sidebar-width);
flex-shrink: 0;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
transition: var(--transition-default);
}
.lt-sidebar.collapsed { width: 32px; overflow: hidden; }
.lt-sidebar-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5rem 0.75rem;
font-size: 0.63rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.18em;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
border-bottom: 1px solid var(--border-color);
background: rgba(0,212,255,0.035);
}
.lt-sidebar-toggle {
background: none;
border: none;
color: var(--text-muted);
font-size: 0.65rem;
cursor: pointer;
padding: 0.1rem 0.3rem;
transition: var(--transition-fast);
}
.lt-sidebar-toggle:hover { color: var(--accent-cyan); text-shadow: var(--glow-cyan); }
.lt-sidebar-body { padding: var(--space-md); }
.lt-filter-group {
margin-bottom: var(--space-md);
padding-bottom: var(--space-md);
border-bottom: 1px solid var(--border-color-dim);
}
.lt-filter-group:last-child { border-bottom: none; }
.lt-filter-label {
display: block;
font-size: 0.6rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.15em;
color: var(--accent-orange);
margin-bottom: var(--space-sm);
}
.lt-filter-option {
display: flex;
align-items: center;
gap: var(--space-sm);
font-size: 0.75rem;
color: var(--text-secondary);
margin-bottom: var(--space-xs);
cursor: pointer;
transition: var(--transition-fast);
}
.lt-filter-option:hover { color: var(--text-primary); }
/* ----------------------------------------------------------------
17. STATS WIDGETS
---------------------------------------------------------------- */
.lt-stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
gap: var(--space-md);
margin-bottom: var(--space-lg);
}
.lt-stat-card {
position: relative;
display: flex;
align-items: center;
gap: var(--space-md);
padding: var(--space-md);
background: var(--bg-card);
border: 1px solid var(--border-color);
cursor: pointer;
transition: var(--transition-fast);
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
overflow: hidden;
}
/* Left accent bar */
.lt-stat-card::before {
content: '';
position: absolute;
top: 0; left: 0;
width: 2px; height: 0%;
background: var(--accent-cyan);
box-shadow: var(--glow-cyan);
transition: height 0.3s ease;
}
.lt-stat-card:hover,
.lt-stat-card.active {
background: var(--bg-tertiary);
border-color: var(--accent-cyan-border);
box-shadow: var(--box-glow-cyan);
}
.lt-stat-card:hover::before,
.lt-stat-card.active::before { height: 100%; }
.lt-stat-card.active {
border-color: var(--accent-orange-border);
box-shadow: var(--box-glow-orange);
}
.lt-stat-card.active::before {
background: var(--accent-orange);
box-shadow: var(--glow-orange);
}
.lt-stat-icon { font-size: 1.3rem; line-height: 1; opacity: 0.80; }
.lt-stat-info { display: flex; flex-direction: column; }
.lt-stat-value {
font-size: 1.6rem;
font-weight: 700;
line-height: 1;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
.lt-stat-label {
font-size: 0.58rem;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--text-muted);
margin-top: 2px;
}
/* ----------------------------------------------------------------
18. INLINE MESSAGES
---------------------------------------------------------------- */
.lt-msg {
padding: 0.5rem 0.85rem;
font-size: 0.75rem;
border-left: 2px solid currentColor;
margin-bottom: var(--space-sm);
display: flex;
align-items: flex-start;
gap: var(--space-sm);
}
.lt-msg::before { flex-shrink: 0; font-weight: 700; }
.lt-msg-error { color: var(--accent-red); background: var(--accent-red-dim); border-left-color: var(--accent-red); }
.lt-msg-success { color: var(--accent-green); background: var(--accent-green-dim); border-left-color: var(--accent-green); }
.lt-msg-warning { color: var(--accent-amber); background: var(--accent-amber-dim); border-left-color: var(--accent-amber); }
.lt-msg-info { color: var(--accent-cyan); background: var(--accent-cyan-dim); border-left-color: var(--accent-cyan); }
.lt-msg-error::before { content: '✗'; }
.lt-msg-success::before { content: '✓'; }
.lt-msg-warning::before { content: '!'; }
.lt-msg-info::before { content: 'i'; }
/* ----------------------------------------------------------------
19. LOADING & EMPTY STATES
---------------------------------------------------------------- */
.lt-loading {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
color: var(--text-muted);
font-size: 0.72rem;
}
.lt-loading::before {
content: '';
display: inline-block;
width: 14px; height: 14px;
border: 2px solid var(--border-color);
border-top-color: var(--accent-cyan);
border-radius: 50%;
animation: spin 0.75s linear infinite;
}
.lt-loading::after {
content: 'Loading...';
text-transform: uppercase;
letter-spacing: 0.1em;
}
.lt-skeleton {
background: linear-gradient(
90deg,
var(--bg-secondary) 25%,
var(--bg-tertiary) 50%,
var(--bg-secondary) 75%
);
background-size: 300% 100%;
animation: shimmer 1.8s ease-in-out infinite;
}
.lt-empty {
color: var(--text-dim);
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.12em;
text-align: center;
padding: var(--space-xl);
}
.lt-empty::before { content: '[ '; color: var(--text-muted); }
.lt-empty::after { content: ' ]'; color: var(--text-muted); }
/* ----------------------------------------------------------------
20. BOOT SEQUENCE OVERLAY
---------------------------------------------------------------- */
.lt-boot-overlay {
position: fixed;
inset: 0;
background: #000;
z-index: calc(var(--z-overlay) + 1);
display: flex;
align-items: flex-start;
justify-content: flex-start;
padding: var(--space-2xl);
animation: boot-fade 0.5s ease 2.2s forwards;
}
.lt-boot-text {
font-family: var(--font-mono);
font-size: 0.78rem;
color: var(--accent-green);
text-shadow: var(--glow-green);
line-height: 1.7;
white-space: pre-wrap;
overflow: hidden;
}
/* ----------------------------------------------------------------
21. LOG / TIMELINE ENTRIES
---------------------------------------------------------------- */
.lt-log-entry {
padding: 0.5rem 0.75rem;
border-left: 2px solid var(--border-color);
margin-bottom: 2px;
font-size: 0.75rem;
background: rgba(0,0,0,0.2);
transition: var(--transition-fast);
}
.lt-log-entry:hover { background: rgba(0,212,255,0.025); }
.lt-log-entry.success { border-left-color: var(--accent-green); }
.lt-log-entry.warning { border-left-color: var(--accent-amber); }
.lt-log-entry.error { border-left-color: var(--accent-red); }
.lt-log-ts {
font-size: 0.6rem;
color: var(--text-muted);
margin-bottom: 2px;
letter-spacing: 0.04em;
}
.lt-log-output {
font-size: 0.67rem;
color: var(--accent-green);
background: var(--bg-terminal);
padding: 0.2rem 0.45rem;
margin-top: 0.35rem;
border-left: 1px solid var(--accent-green-border);
text-shadow: var(--glow-green);
}
/* Toolbar row */
.lt-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-md);
padding: var(--space-sm) 0;
margin-bottom: var(--space-md);
}
.lt-toolbar-left,
.lt-toolbar-right {
display: flex;
align-items: center;
gap: var(--space-sm);
}
/* Running / pulsing row */
.lt-item-running { animation: running-pulse 3s ease-in-out infinite; }
/* ----------------------------------------------------------------
22. ANIMATIONS (KEYFRAMES)
---------------------------------------------------------------- */
@keyframes pulse-green {
0%, 100% { box-shadow: 0 0 4px var(--accent-green), 0 0 8px var(--accent-green); }
50% { box-shadow: 0 0 8px var(--accent-green), 0 0 22px var(--accent-green), 0 0 36px rgba(0,255,136,0.35); }
}
@keyframes pulse-amber {
0%, 100% { box-shadow: 0 0 4px var(--accent-amber), 0 0 8px var(--accent-amber); }
50% { box-shadow: 0 0 8px var(--accent-amber), 0 0 20px var(--accent-amber); }
}
@keyframes running-pulse {
0%, 100% { border-color: var(--border-color); }
50% { border-color: rgba(255,179,0,0.25); box-shadow: 0 0 14px rgba(255,179,0,0.12); }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes shimmer {
0% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
@keyframes toast-in {
from { opacity: 0; transform: translateX(16px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes modal-in {
from { opacity: 0; transform: scale(0.96) translateY(-10px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes boot-fade {
to { opacity: 0; pointer-events: none; }
}
@keyframes blink {
0%, 49% { opacity: 1; }
50%, 100% { opacity: 0; }
}
@keyframes glitch-1 {
0%, 90%, 100% { clip-path: inset(0); transform: skewX(0); }
92% { clip-path: inset(15% 0 72% 0); transform: skewX(-4deg); }
94% { clip-path: inset(54% 0 22% 0); transform: skewX(3deg); }
96% { clip-path: inset(30% 0 48% 0); transform: skewX(-2deg); }
}
@keyframes glitch-2 {
0%, 90%, 100% { clip-path: inset(0); transform: skewX(0); }
92% { clip-path: inset(60% 0 8% 0); transform: skewX(3deg); }
94% { clip-path: inset(8% 0 68% 0); transform: skewX(-3deg); }
96% { clip-path: inset(42% 0 38% 0); transform: skewX(1deg); }
}
/* ================================================================
23. RESPONSIVE DESIGN
Breakpoint system (desktop-first with mobile-first enhancements):
xs: ≤ 479px tiny phones (iPhone SE 1st gen, Galaxy A)
sm: 480767px phones (iPhone 14, Pixel 7, Galaxy S)
md: 7681023px tablets (iPad mini/Air portrait)
lg: 10241279px laptops (iPad Pro landscape, MacBook Air 11")
xl: 12801535px desktops (MacBook Pro 13", 1080p portrait)
2xl: 15361919px large (27" iMac, 1440p)
3xl: 19202559px full HD (1080p monitor, 24")
4k: ≥ 2560px 4K/ultrawide (4K, 1440p ultrawide)
================================================================ */
/* ── Breakpoint tokens (read by JS lt.viewport module) ── */
:root {
--bp-xs: 479;
--bp-sm: 480;
--bp-md: 768;
--bp-lg: 1024;
--bp-xl: 1280;
--bp-2xl: 1536;
--bp-3xl: 1920;
--bp-4k: 2560;
}
/* ── Mobile nav drawer ── */
.lt-menu-btn {
display: none;
flex-direction: column;
justify-content: center;
gap: 5px;
width: 36px; height: 36px;
padding: 6px;
background: none;
border: 1px solid var(--border-dim);
cursor: pointer;
flex-shrink: 0;
}
.lt-menu-btn span {
display: block;
height: 1px;
background: var(--accent-cyan);
transition: transform 0.2s ease, opacity 0.2s ease;
box-shadow: var(--glow-cyan);
}
.lt-menu-btn:focus-visible { outline: 1px solid var(--accent-cyan); outline-offset: 2px; }
.lt-menu-btn.open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.lt-menu-btn.open span:nth-child(2) { opacity: 0; }
.lt-menu-btn.open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.lt-nav-drawer {
position: fixed;
top: 0; left: 0; bottom: 0;
width: 280px;
background: var(--bg-secondary);
border-right: 1px solid var(--border-color);
box-shadow: 4px 0 32px rgba(0,0,0,0.8);
z-index: calc(var(--z-overlay) + 3);
transform: translateX(-100%);
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
display: flex;
flex-direction: column;
}
.lt-nav-drawer.open { transform: translateX(0); }
.lt-nav-drawer-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-md) var(--space-lg);
border-bottom: 1px solid var(--border-color);
min-height: var(--header-height);
}
.lt-nav-drawer-close {
background: none;
border: 1px solid var(--border-dim);
color: var(--text-dim);
cursor: pointer;
width: 44px; height: 44px; /* 44px touch target */
font-size: 0.9rem;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
transition: color 0.15s, border-color 0.15s;
}
.lt-nav-drawer-close:hover { color: var(--accent-red); border-color: var(--accent-red); }
.lt-nav-drawer-close:focus-visible { outline: 1px solid var(--accent-cyan); outline-offset: 2px; }
.lt-nav-drawer-links { padding: var(--space-sm) 0; flex: 1; }
.lt-nav-drawer-link {
display: flex;
align-items: center;
padding: 0.75rem var(--space-lg);
font-family: var(--font-mono);
font-size: 0.8rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-secondary);
text-decoration: none;
transition: color 0.15s, background 0.15s, padding-left 0.15s;
border-left: 2px solid transparent;
min-height: 44px;
}
.lt-nav-drawer-link:hover { color: var(--accent-cyan); background: rgba(0,212,255,0.06); padding-left: calc(var(--space-lg) + 4px); }
.lt-nav-drawer-link:focus-visible { outline: none; color: var(--accent-cyan); background: rgba(0,212,255,0.10); box-shadow: inset 3px 0 0 var(--accent-cyan); }
.lt-nav-drawer-link.active,
.lt-nav-drawer-link[aria-current="page"] { color: var(--accent-orange); border-left-color: var(--accent-orange); background: rgba(255,107,0,0.06); }
.lt-nav-drawer-link--indent { padding-left: calc(var(--space-lg) + var(--space-md)); font-size: 0.75rem; font-weight: 400; text-transform: none; letter-spacing: 0; }
.lt-nav-drawer-section {
padding: var(--space-sm) var(--space-lg) var(--space-xs);
font-family: var(--font-mono);
font-size: 0.6rem;
text-transform: uppercase;
letter-spacing: 0.15em;
color: var(--text-dim);
border-top: 1px solid var(--border-dim);
margin-top: var(--space-xs);
}
.lt-nav-drawer-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.75);
backdrop-filter: blur(2px);
z-index: calc(var(--z-overlay) + 2);
}
.lt-nav-drawer-overlay.open { display: block; }
/* ── Safe areas (iPhone notch / Dynamic Island / home bar) ── */
@supports (padding: env(safe-area-inset-left)) {
/* Header: pad for notch in landscape, Dynamic Island on top */
.lt-header {
padding-left: max(var(--space-xl), env(safe-area-inset-left));
padding-right: max(var(--space-xl), env(safe-area-inset-right));
}
/* Main content: header-height already includes safe-area-top via header height —
only add safe-area-top once to avoid double-counting */
.lt-main {
padding-top: calc(var(--header-height) + env(safe-area-inset-top) + var(--space-lg));
}
/* Nav drawer: account for notch on both top and left (landscape) */
.lt-nav-drawer {
padding-top: max(var(--header-height), env(safe-area-inset-top));
padding-left: env(safe-area-inset-left);
}
/* Toast: stay above home bar */
#lt-toast-container {
bottom: max(var(--space-lg), calc(env(safe-area-inset-bottom) + var(--space-sm)));
right: max(var(--space-lg), env(safe-area-inset-right));
right: max(var(--space-sm), env(safe-area-inset-right)); /* SM override merged */
}
/* Bottom-fixed UI (modals, cmd palette at XS) */
.lt-modal-overlay.bottom-safe,
.lt-cmd-overlay.bottom-safe {
padding-bottom: env(safe-area-inset-bottom);
}
}
/* ── Touch / coarse pointer (finger-friendly tap targets) ── */
@media (pointer: coarse) {
.lt-btn, .lt-input, .lt-select, .lt-textarea { min-height: 44px; }
.lt-btn-sm { min-height: 36px; }
.lt-nav-link { padding: 0 var(--space-md); min-height: 44px; display: inline-flex; align-items: center; }
.lt-accordion-header { min-height: 48px; }
.lt-tab { min-height: 44px; padding: var(--space-sm) var(--space-lg); }
.lt-list-item { min-height: 44px; }
.lt-page-btn { min-height: 36px; min-width: 36px; }
.lt-checkbox, .lt-radio { width: 20px; height: 20px; }
input[type="range"].lt-range { height: 8px; }
input[type="range"].lt-range::-webkit-slider-thumb { width: 22px; height: 22px; }
}
/* ── No-hover / touch devices ── */
@media (hover: none) {
/* Suppress hover-only decorations on touch */
[data-tooltip]::before,
[data-tooltip]::after { display: none; }
/* Glitch causes expensive repaints on mobile — disable */
.lt-glitch::before,
.lt-glitch::after { display: none; }
/* Suppress padding-left shift on touch (causes layout jank on tap) */
.lt-nav-drawer-link:hover { padding-left: var(--space-lg); }
}
/* ── Coarse pointer — additional touch performance tweaks ── */
@media (pointer: coarse) {
/* Disable infinite animations that drain battery on mobile */
.lt-dot-up, .lt-dot-warn { animation: none; }
.lt-status-running { animation: none; }
.lt-item-running { animation: none; }
/* Use simple pulsing glow instead for coarse-pointer devices */
.lt-dot-up { box-shadow: 0 0 6px var(--accent-green); }
.lt-dot-warn { box-shadow: 0 0 6px var(--accent-amber); }
}
/* ── High-DPI / Retina ── */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.lt-header::after { height: 0.5px; }
.lt-frame, .lt-card, .lt-input, .lt-select, .lt-btn { border-width: 0.5px; }
.lt-frame::before { font-size: 0.6rem; }
}
/* ── Landscape phone (short viewport) ── */
@media (max-height: 500px) and (orientation: landscape) {
:root { --header-height: 42px; }
.lt-main { padding-top: calc(42px + var(--space-md)); }
.lt-boot-overlay { display: none; }
.lt-modal {
align-items: flex-start;
padding-top: 48px;
overflow-y: auto;
}
.lt-modal .lt-modal { max-height: calc(100vh - 56px); overflow-y: auto; }
}
/* ── LG — laptops 10241279px ── */
@media (max-width: 1279px) {
.lt-grid-4 { grid-template-columns: repeat(2, 1fr); }
.lt-container { padding: var(--space-lg); }
}
/* ── MD — tablets portrait 7681023px ── */
@media (max-width: 1023px) {
.lt-menu-btn { display: flex; }
.lt-nav { display: none; }
.lt-grid-3, .lt-grid-4 { grid-template-columns: repeat(2, 1fr); }
.lt-stats-grid { grid-template-columns: repeat(2, 1fr); }
.lt-container { padding: var(--space-md) var(--space-lg); }
.lt-header { padding: 0 var(--space-lg); }
/* Sidebar becomes off-canvas on tablets */
.lt-sidebar {
position: fixed;
top: var(--header-height);
left: 0; bottom: 0;
width: var(--sidebar-width);
transform: translateX(-100%);
transition: transform 0.25s ease;
z-index: var(--z-fixed);
border-right: 1px solid var(--border-color);
overflow-y: auto;
}
.lt-sidebar.open { transform: translateX(0); }
.lt-layout { display: block; }
.lt-content { width: 100%; }
}
/* ── SM — phones 480767px ── */
@media (max-width: 767px) {
:root { --header-height: 50px; }
.lt-main { padding-top: calc(50px + var(--space-md)); }
.lt-container { padding: var(--space-md); }
.lt-header { padding: 0 var(--space-md); }
.lt-brand-subtitle { display: none; }
.lt-grid-2, .lt-grid-3, .lt-grid-4 { grid-template-columns: 1fr; }
.lt-stats-grid { grid-template-columns: repeat(2, 1fr); }
.lt-toolbar { flex-direction: column; align-items: stretch; gap: var(--space-sm); }
.lt-page-header { flex-direction: column; align-items: flex-start; gap: var(--space-sm); }
.lt-btn-group { flex-wrap: wrap; }
/* Full-width modals on phone */
.lt-modal {
width: 96vw;
max-height: 90vh;
overflow-y: auto;
}
/* Command palette full-width */
.lt-cmd-palette {
max-width: 96vw;
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px));
}
/* Smaller clip corners feel better on mobile */
.lt-frame {
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 8px));
}
.lt-card {
clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%);
}
/* Toast full-width on phone */
#lt-toast-container {
left: var(--space-sm);
right: var(--space-sm);
bottom: var(--space-md);
}
.lt-toast { width: 100%; }
/* Stepper goes vertical on small screens */
.lt-stepper { flex-direction: column; gap: var(--space-sm); }
.lt-step { flex-direction: row; align-items: center; gap: var(--space-md); text-align: left; }
.lt-step:not(:last-child)::after {
display: none;
}
.lt-step-num { margin-bottom: 0; flex-shrink: 0; }
/* KV grid stacks on mobile */
.lt-kv-grid { grid-template-columns: 1fr; }
.lt-kv-key { border-right: none; border-bottom: 1px solid var(--border-dim); padding: var(--space-xs) 0 2px; }
.lt-kv-val { padding: 2px 0 var(--space-sm); }
/* Pagination compact — show fewer buttons via CSS */
.lt-page-btn:not(.active):not(:first-child):not(:last-child):not([disabled]) {
display: none;
}
.lt-page-btn.active,
.lt-page-btn:first-child,
.lt-page-btn:last-child { display: inline-flex; }
/* Dropzone: smaller on mobile */
.lt-dropzone { padding: var(--space-lg) var(--space-md); }
.lt-dropzone-icon { font-size: 1.5rem; }
/* Section body: tighter on mobile */
.lt-section-body { padding: var(--space-sm); padding-right: var(--space-md); }
/* Data table card mode already at 640px; also reduce font */
.lt-data-table th,
.lt-data-table td { padding: 0.5rem 0.6rem; font-size: 0.75rem; }
/* Hero */
.lt-hero { padding: var(--space-lg) 0; }
.lt-hero-actions { flex-direction: column; align-items: stretch; }
/* Code block: tighter font on phone */
.lt-code-block pre { font-size: 0.72rem; }
/* Stats grid gap tighter */
.lt-stats-grid { gap: var(--space-sm); }
.lt-stat-card { padding: var(--space-sm); }
.lt-stat-value { font-size: 1.6rem; }
}
/* ── XS — tiny phones ≤ 479px ── */
@media (max-width: 479px) {
:root { --header-height: 46px; }
.lt-main { padding-top: calc(46px + var(--space-sm)); }
.lt-container { padding: var(--space-sm); }
.lt-stats-grid { grid-template-columns: 1fr 1fr; gap: var(--space-xs); }
.lt-stat-card { padding: var(--space-xs) var(--space-sm); }
.lt-stat-value { font-size: 1.4rem; }
.lt-frame { clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px)); }
/* Ensure content clears the 6px clipped corner */
.lt-section-body { padding: var(--space-xs) var(--space-sm); padding-right: 14px; }
/* Full-width drawer on tiny phones */
.lt-nav-drawer { width: 100%; max-width: 100vw; }
/* Btn groups stack vertically only in primary action areas, not everywhere */
.lt-page-header .lt-btn-group { flex-direction: column; width: 100%; }
.lt-page-header .lt-btn-group .lt-btn { width: 100%; }
/* Full-screen bottom-sheet modal on XS */
.lt-modal-overlay { align-items: flex-end; padding: 0; }
.lt-modal {
width: 100%;
max-width: 100vw;
max-height: 92vh;
overflow-y: auto;
clip-path: none;
border: none;
border-top: 1px solid var(--border-color);
border-radius: 0;
/* Bottom sheet rounding illusion via top corners */
clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%, 0 8px);
}
.lt-modal-body { max-height: calc(92vh - 120px); overflow-y: auto; }
/* Full-screen bottom-sheet command palette on XS */
.lt-cmd-overlay { align-items: flex-end; padding-top: 0; }
.lt-cmd-palette {
max-width: 100%;
width: 100%;
clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%, 0 8px);
border-bottom: none;
}
.lt-data-table th,
.lt-data-table td { padding: 0.35rem 0.5rem; font-size: 0.7rem; }
.lt-tab { padding: var(--space-xs) var(--space-sm); font-size: 0.65rem; }
}
/* ── 2XL — large desktops 15361919px ── */
@media (min-width: 1536px) {
:root { --container-max: 1800px; }
.lt-header { padding: 0 var(--space-2xl); }
.lt-stats-grid { grid-template-columns: repeat(5, 1fr); }
}
/* ── 3XL — full HD 19202559px ── */
@media (min-width: 1920px) {
:root { --container-max: 2000px; }
.lt-stats-grid { grid-template-columns: repeat(6, 1fr); }
.lt-grid-4 { grid-template-columns: repeat(4, 1fr); }
.lt-container { padding: var(--space-xl) var(--space-2xl); }
}
/* ── 4K / ULTRA-WIDE ≥ 2560px ── */
@media (min-width: 2560px) {
html { font-size: 18px; } /* scales all rem-based values ~12% larger */
:root {
--container-max: 2400px;
--header-height: 4rem; /* 72px at 18px base — was 64px hardcoded */
--sidebar-width: 17.5rem; /* 315px at 18px base — was 280px hardcoded */
}
/* Clip-path corners scale proportionally */
.lt-frame {
clip-path: polygon(0 0, calc(100% - 1.25rem) 0, 100% 1.25rem, 100% 100%, 1.25rem 100%, 0 calc(100% - 1.25rem));
}
.lt-card {
clip-path: polygon(0 0, calc(100% - 0.75rem) 0, 100% 0.75rem, 100% 100%, 0 100%);
}
.lt-stats-grid { grid-template-columns: repeat(8, 1fr); }
/* Scale hardcoded-px elements explicitly at 4K */
.lt-dot { width: 0.6rem; height: 0.6rem; } /* was 8px */
.lt-menu-btn { width: 2.5rem; height: 2.5rem; } /* was 36px */
.lt-nav-drawer-close { width: 3rem; height: 3rem; } /* was 44px */
.lt-step-num { width: 2rem; height: 2rem; } /* was 28px */
.lt-spinner { width: 1.75rem; height: 1.75rem; } /* was 24px */
.lt-spinner--sm { width: 1rem; height: 1rem; } /* was 14px */
.lt-spinner--lg { width: 2.75rem; height: 2.75rem; } /* was 40px */
.lt-checkbox, .lt-radio { width: 1.1rem; height: 1.1rem; } /* was 14px */
/* More pronounced glows at 4K */
:root {
--glow-orange: 0 0 8px #FF6B00, 0 0 24px rgba(255,107,0,0.6);
--glow-cyan: 0 0 8px #00D4FF, 0 0 24px rgba(0,212,255,0.6);
--glow-green: 0 0 8px #00FF88, 0 0 22px rgba(0,255,136,0.55);
--glow-red: 0 0 8px #FF2D55, 0 0 22px rgba(255,45,85,0.55);
--glow-orange-intense: 0 0 10px #FF6B00, 0 0 28px #FF6B00, 0 0 50px rgba(255,107,0,0.5);
--glow-cyan-intense: 0 0 10px #00D4FF, 0 0 28px #00D4FF, 0 0 48px rgba(0,212,255,0.4);
--glow-green-intense: 0 0 10px #00FF88, 0 0 26px #00FF88, 0 0 44px rgba(0,255,136,0.4);
--glow-amber-intense: 0 0 10px #FFB300, 0 0 24px #FFB300, 0 0 42px rgba(255,179,0,0.5);
}
}
/* ── Breakpoint visibility utilities ── */
/* Hide at specific breakpoints */
@media (max-width: 479px) { .lt-hide-xs { display: none !important; } }
@media (max-width: 767px) { .lt-hide-sm { display: none !important; } }
@media (max-width: 1023px) { .lt-hide-md { display: none !important; } }
@media (max-width: 1279px) { .lt-hide-lg { display: none !important; } }
@media (min-width: 480px) { .lt-show-xs { display: none !important; } }
@media (min-width: 768px) { .lt-show-sm { display: none !important; } }
@media (min-width: 1024px) { .lt-show-md { display: none !important; } }
@media (min-width: 1280px) { .lt-show-lg { display: none !important; } }
/* Touch-only / desktop-only */
@media (pointer: fine) { .lt-touch-only { display: none !important; } }
@media (pointer: coarse) { .lt-mouse-only { display: none !important; } }
/* ----------------------------------------------------------------
24. UTILITY CLASSES
---------------------------------------------------------------- */
.lt-text-orange { color: var(--accent-orange); text-shadow: var(--glow-orange); }
.lt-text-amber { color: var(--accent-amber); text-shadow: var(--glow-amber); }
.lt-text-cyan { color: var(--accent-cyan); text-shadow: var(--glow-cyan); }
.lt-text-green { color: var(--accent-green); text-shadow: var(--glow-green); }
.lt-text-red { color: var(--accent-red); text-shadow: var(--glow-red); }
.lt-text-muted { color: var(--text-muted); }
.lt-text-dim { color: var(--text-dim); }
.lt-text-xs { font-size: 0.63rem; }
.lt-text-sm { font-size: 0.78rem; }
.lt-text-lg { font-size: 1rem; }
.lt-text-xl { font-size: 1.2rem; }
.lt-text-upper { text-transform: uppercase; letter-spacing: 0.1em; }
.lt-hidden { display: none !important; }
.lt-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; }
/* Cursor blink */
.lt-cursor::after {
content: '█';
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
animation: blink 1s step-start infinite;
font-size: 0.85em;
margin-left: 1px;
}
/* Glitch text effect */
.lt-glitch { position: relative; }
.lt-glitch::before,
.lt-glitch::after {
content: attr(data-text);
position: absolute;
top: 0; left: 0;
width: 100%;
overflow: hidden;
}
.lt-glitch::before {
color: var(--accent-cyan);
opacity: 0.65;
animation: glitch-1 4s infinite;
}
.lt-glitch::after {
color: var(--accent-orange);
opacity: 0.65;
animation: glitch-2 4s 0.12s infinite;
}
/* ----------------------------------------------------------------
25. PRINT STYLES
---------------------------------------------------------------- */
@media print {
body::before, body::after { display: none; }
html { background-image: none; background-color: white; }
body { background: white; color: black; }
.lt-header, .lt-boot-overlay, #lt-toast-container { display: none; }
.lt-frame, .lt-card { border: 1px solid #ccc; clip-path: none; }
}
/* ----------------------------------------------------------------
26. ACCESSIBILITY
---------------------------------------------------------------- */
:focus-visible {
outline: 1px solid var(--accent-cyan);
outline-offset: 2px;
box-shadow: var(--box-glow-cyan);
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* ----------------------------------------------------------------
27. PROGRESS BARS
---------------------------------------------------------------- */
.lt-progress {
width: 100%;
height: 6px;
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
overflow: hidden;
position: relative;
}
.lt-progress-bar {
height: 100%;
background: var(--accent-orange);
box-shadow: var(--glow-orange);
transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
}
.lt-progress-bar::after {
content: '';
position: absolute;
top: 0; right: 0;
width: 20px;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4));
}
.lt-progress--cyan .lt-progress-bar { background: var(--accent-cyan); box-shadow: var(--glow-cyan); }
.lt-progress--green .lt-progress-bar { background: var(--accent-green); box-shadow: var(--glow-green); }
.lt-progress--red .lt-progress-bar { background: var(--accent-red); box-shadow: var(--glow-red); }
.lt-progress--striped .lt-progress-bar {
background-image: repeating-linear-gradient(
45deg, transparent, transparent 4px,
rgba(0,0,0,0.25) 4px, rgba(0,0,0,0.25) 8px
);
}
.lt-progress--lg { height: 12px; }
.lt-progress--sm { height: 3px; }
.lt-progress-label {
display: flex;
justify-content: space-between;
font-size: 0.7rem;
color: var(--text-dim);
margin-bottom: var(--space-xs);
font-family: var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* ----------------------------------------------------------------
28. TOOLTIPS
---------------------------------------------------------------- */
[data-tooltip] {
position: relative;
cursor: help;
}
[data-tooltip]::before,
[data-tooltip]::after {
position: absolute;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease, transform 0.15s ease;
z-index: var(--z-tooltip);
}
[data-tooltip]::before {
content: attr(data-tooltip);
background: var(--bg-secondary);
border: 1px solid var(--accent-cyan);
box-shadow: var(--box-glow-cyan);
color: var(--text-primary);
font-family: var(--font-mono);
font-size: 0.7rem;
padding: 4px 8px;
white-space: nowrap;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%) translateY(4px);
clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%);
}
[data-tooltip]::after {
content: '';
border: 5px solid transparent;
border-top-color: var(--accent-cyan);
bottom: calc(100% + 3px);
left: 50%;
transform: translateX(-50%) translateY(4px);
}
[data-tooltip]:hover::before,
[data-tooltip]:hover::after {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
[data-tooltip][data-tooltip-pos="bottom"]::before {
bottom: auto;
top: calc(100% + 8px);
transform: translateX(-50%) translateY(-4px);
clip-path: polygon(0 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%);
}
[data-tooltip][data-tooltip-pos="bottom"]::after {
bottom: auto;
top: calc(100% + 3px);
border-top-color: transparent;
border-bottom-color: var(--accent-cyan);
transform: translateX(-50%) translateY(-4px);
}
[data-tooltip][data-tooltip-pos="bottom"]:hover::before,
[data-tooltip][data-tooltip-pos="bottom"]:hover::after {
transform: translateX(-50%) translateY(0);
}
/* ----------------------------------------------------------------
29. BREADCRUMBS
---------------------------------------------------------------- */
.lt-breadcrumb {
display: flex;
align-items: center;
gap: var(--space-xs);
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--text-dim);
flex-wrap: wrap;
}
.lt-breadcrumb-item { display: flex; align-items: center; gap: var(--space-xs); }
.lt-breadcrumb-item a {
color: var(--text-dim);
text-decoration: none;
transition: color 0.15s;
}
.lt-breadcrumb-item a:hover { color: var(--accent-cyan); }
.lt-breadcrumb-item.active { color: var(--accent-orange); }
.lt-breadcrumb-sep { color: var(--border-dim); }
.lt-breadcrumb-sep::before { content: '/'; }
/* ----------------------------------------------------------------
30. PAGINATION
---------------------------------------------------------------- */
.lt-pagination {
display: flex;
align-items: center;
gap: 4px;
font-family: var(--font-mono);
font-size: 0.75rem;
}
.lt-page-btn {
padding: 4px 10px;
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
color: var(--text-secondary);
cursor: pointer;
transition: all 0.15s;
text-decoration: none;
clip-path: polygon(0 0, calc(100% - 4px) 0, 100% 4px, 100% 100%, 0 100%);
}
.lt-page-btn:hover {
border-color: var(--accent-cyan);
color: var(--accent-cyan);
box-shadow: var(--box-glow-cyan);
}
.lt-page-btn.active {
background: var(--accent-orange);
border-color: var(--accent-orange);
color: var(--bg-primary);
box-shadow: var(--glow-orange);
font-weight: 700;
}
.lt-page-btn:disabled,
.lt-page-btn[aria-disabled="true"] {
opacity: 0.35;
cursor: not-allowed;
pointer-events: none;
}
/* ----------------------------------------------------------------
31. ACCORDION
---------------------------------------------------------------- */
.lt-accordion { border: 1px solid var(--border-dim); }
.lt-accordion + .lt-accordion { border-top: none; }
.lt-accordion-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-sm) var(--space-md);
background: var(--bg-secondary);
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.8rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-primary);
transition: background 0.15s, color 0.15s;
user-select: none;
border: none;
width: 100%;
text-align: left;
}
.lt-accordion-header:hover { background: var(--bg-tertiary); color: var(--accent-cyan); }
.lt-accordion-header[aria-expanded="true"] { color: var(--accent-orange); }
.lt-accordion-icon {
width: 14px;
height: 14px;
transition: transform 0.25s ease;
flex-shrink: 0;
}
.lt-accordion-header[aria-expanded="true"] .lt-accordion-icon { transform: rotate(180deg); }
.lt-accordion-body {
overflow: hidden;
height: 0;
transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: var(--bg-primary);
}
/* .is-open height is set dynamically by JS (scrollHeight) */
.lt-accordion-body.is-open { height: auto; }
.lt-accordion-content { padding: var(--space-md); }
/* ----------------------------------------------------------------
32. ALERT BANNERS
---------------------------------------------------------------- */
.lt-alert {
display: flex;
align-items: flex-start;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
border-left: 3px solid var(--accent-cyan);
background: rgba(0,212,255,0.06);
font-family: var(--font-mono);
font-size: 0.8rem;
position: relative;
overflow: hidden;
transition: max-height 0.3s ease, opacity 0.3s ease, padding 0.3s ease;
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
}
.lt-alert--warning { border-left-color: var(--accent-orange); background: rgba(255,107,0,0.06); }
.lt-alert--error { border-left-color: var(--accent-red); background: rgba(255,45,85,0.06); }
.lt-alert--success { border-left-color: var(--accent-green); background: rgba(0,255,136,0.06); }
.lt-alert--purple { border-left-color: var(--accent-purple); background: rgba(191,95,255,0.06); }
.lt-alert-icon { font-size: 1rem; flex-shrink: 0; margin-top: 1px; }
.lt-alert-body { flex: 1; }
.lt-alert-title { font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-primary); margin-bottom: 2px; }
.lt-alert-msg { color: var(--text-secondary); }
.lt-alert-close {
background: none;
border: none;
color: var(--text-dim);
cursor: pointer;
font-size: 1rem;
padding: 0 0 0 var(--space-sm);
line-height: 1;
flex-shrink: 0;
transition: color 0.15s;
}
.lt-alert-close:hover { color: var(--accent-red); }
.lt-alert.dismissed { max-height: 0 !important; opacity: 0; padding-top: 0; padding-bottom: 0; pointer-events: none; }
/* ----------------------------------------------------------------
33. TOGGLE SWITCH
---------------------------------------------------------------- */
.lt-toggle {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.8rem;
}
.lt-toggle input { display: none; }
.lt-toggle-track {
width: 36px;
height: 18px;
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
border-radius: 0;
position: relative;
transition: all 0.2s ease;
clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%);
}
.lt-toggle input:checked ~ .lt-toggle-track {
background: var(--accent-orange);
border-color: var(--accent-orange);
box-shadow: var(--glow-orange);
}
.lt-toggle-thumb {
position: absolute;
top: 2px; left: 2px;
width: 12px; height: 12px;
background: var(--text-dim);
transition: transform 0.2s ease, background 0.2s ease;
}
.lt-toggle input:checked ~ .lt-toggle-track .lt-toggle-thumb {
transform: translateX(18px);
background: var(--bg-primary);
}
.lt-toggle-label { color: var(--text-secondary); user-select: none; }
.lt-toggle input:checked ~ .lt-toggle-label { color: var(--text-primary); }
/* ----------------------------------------------------------------
34. RANGE SLIDER
---------------------------------------------------------------- */
.lt-range-wrap { display: flex; flex-direction: column; gap: var(--space-xs); }
.lt-range-header { display: flex; justify-content: space-between; font-family: var(--font-mono); font-size: 0.75rem; }
.lt-range-label { color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; }
.lt-range-value { color: var(--accent-orange); font-weight: 700; }
input[type="range"].lt-range {
-webkit-appearance: none;
width: 100%;
height: 4px;
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
outline: none;
cursor: pointer;
}
input[type="range"].lt-range::-webkit-slider-thumb {
-webkit-appearance: none;
width: 14px; height: 14px;
background: var(--accent-orange);
box-shadow: var(--glow-orange);
cursor: pointer;
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
transition: transform 0.15s;
}
input[type="range"].lt-range::-webkit-slider-thumb:hover { transform: scale(1.3); }
input[type="range"].lt-range::-moz-range-thumb {
width: 14px; height: 14px;
background: var(--accent-orange);
border: none;
cursor: pointer;
}
/* ----------------------------------------------------------------
35. FILE UPLOAD / DROPZONE
---------------------------------------------------------------- */
.lt-dropzone {
border: 2px dashed var(--border-dim);
background: var(--bg-secondary);
padding: var(--space-xl);
text-align: center;
cursor: pointer;
transition: all 0.2s ease;
font-family: var(--font-mono);
position: relative;
clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 16px 100%, 0 calc(100% - 16px));
}
.lt-dropzone:hover,
.lt-dropzone.drag-over {
border-color: var(--accent-cyan);
background: rgba(0,212,255,0.05);
box-shadow: var(--box-glow-cyan);
}
.lt-dropzone-icon { font-size: 2rem; margin-bottom: var(--space-sm); opacity: 0.5; }
.lt-dropzone-text { color: var(--text-secondary); font-size: 0.8rem; }
.lt-dropzone-text strong { color: var(--accent-cyan); }
.lt-dropzone-hint { font-size: 0.7rem; color: var(--text-dim); margin-top: var(--space-xs); }
.lt-dropzone input[type="file"] {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
}
.lt-file-list { margin-top: var(--space-sm); display: flex; flex-direction: column; gap: 4px; }
.lt-file-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px var(--space-sm);
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
font-size: 0.75rem;
font-family: var(--font-mono);
}
.lt-file-item-name { color: var(--text-secondary); }
.lt-file-item-size { color: var(--text-dim); }
.lt-file-item-remove { background: none; border: none; color: var(--accent-red); cursor: pointer; padding: 0; font-size: 0.9rem; }
/* ----------------------------------------------------------------
36. COMMAND PALETTE
---------------------------------------------------------------- */
.lt-cmd-overlay {
position: fixed;
inset: 0;
background: rgba(3,5,8,0.85);
backdrop-filter: blur(4px);
z-index: var(--z-modal);
display: none;
align-items: flex-start;
justify-content: center;
padding-top: 12vh;
}
.lt-cmd-overlay.is-open { display: flex; }
.lt-cmd-palette {
width: 100%;
max-width: 560px;
background: var(--bg-secondary);
border: 1px solid var(--accent-cyan);
box-shadow: var(--box-glow-cyan);
clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 16px 100%, 0 calc(100% - 16px));
}
.lt-cmd-input-wrap {
display: flex;
align-items: center;
padding: var(--space-sm) var(--space-md);
border-bottom: 1px solid var(--border-dim);
gap: var(--space-sm);
}
.lt-cmd-prompt { color: var(--accent-cyan); font-family: var(--font-mono); font-size: 1rem; }
.lt-cmd-input {
flex: 1;
background: none;
border: none;
outline: none;
color: var(--text-primary);
font-family: var(--font-mono);
font-size: 0.9rem;
caret-color: var(--accent-orange);
}
.lt-cmd-results { max-height: 320px; overflow-y: auto; }
.lt-cmd-group-label {
padding: var(--space-xs) var(--space-md);
font-family: var(--font-mono);
font-size: 0.65rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-dim);
border-bottom: 1px solid var(--border-dim);
}
.lt-cmd-item {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.8rem;
transition: background 0.1s;
}
.lt-cmd-item:hover,
.lt-cmd-item.is-selected {
background: rgba(0,212,255,0.08);
color: var(--accent-cyan);
}
.lt-cmd-item-icon { width: 16px; text-align: center; opacity: 0.6; flex-shrink: 0; }
.lt-cmd-item-label { flex: 1; }
.lt-cmd-item-kbd {
font-size: 0.65rem;
padding: 2px 5px;
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
color: var(--text-dim);
}
.lt-cmd-footer {
display: flex;
gap: var(--space-md);
padding: var(--space-xs) var(--space-md);
border-top: 1px solid var(--border-dim);
font-family: var(--font-mono);
font-size: 0.65rem;
color: var(--text-dim);
}
.lt-cmd-footer kbd { background: var(--bg-tertiary); border: 1px solid var(--border-dim); padding: 1px 4px; margin: 0 2px; }
.lt-cmd-empty {
padding: var(--space-lg);
text-align: center;
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--text-dim);
}
/* ----------------------------------------------------------------
37. CODE BLOCKS
---------------------------------------------------------------- */
.lt-code-block {
position: relative;
background: var(--bg-secondary);
border: 1px solid var(--border-dim);
overflow: hidden;
}
.lt-code-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px var(--space-md);
background: var(--bg-tertiary);
border-bottom: 1px solid var(--border-dim);
}
.lt-code-lang {
font-family: var(--font-mono);
font-size: 0.65rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent-orange);
}
.lt-code-copy {
background: none;
border: 1px solid var(--border-dim);
color: var(--text-dim);
font-family: var(--font-mono);
font-size: 0.65rem;
padding: 2px 8px;
cursor: pointer;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: all 0.15s;
}
.lt-code-copy:hover { border-color: var(--accent-cyan); color: var(--accent-cyan); }
.lt-code-copy.copied { border-color: var(--accent-green); color: var(--accent-green); }
.lt-code-block pre {
margin: 0;
padding: var(--space-md);
overflow-x: auto;
overflow-y: auto;
font-family: var(--font-mono);
font-size: 0.8rem;
line-height: 1.6;
color: var(--text-secondary);
max-height: 400px;
}
.lt-code-block code { background: none; border: none; padding: 0; color: inherit; }
/* Syntax highlight tokens */
.tok-kw { color: var(--accent-cyan); }
.tok-str { color: var(--accent-green); }
.tok-num { color: var(--accent-orange); }
.tok-cmt { color: #5c8c6a; font-style: italic; }
.tok-fn { color: var(--accent-purple); }
/* ----------------------------------------------------------------
38. TAGS / CHIPS
---------------------------------------------------------------- */
.lt-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.lt-tag {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 8px;
font-family: var(--font-mono);
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.05em;
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
color: var(--text-secondary);
clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 0 100%);
white-space: nowrap;
}
.lt-tag--orange { border-color: var(--accent-orange); color: var(--accent-orange); background: rgba(255,107,0,0.08); }
.lt-tag--cyan { border-color: var(--accent-cyan); color: var(--accent-cyan); background: rgba(0,212,255,0.08); }
.lt-tag--green { border-color: var(--accent-green); color: var(--accent-green); background: rgba(0,255,136,0.08); }
.lt-tag--red { border-color: var(--accent-red); color: var(--accent-red); background: rgba(255,45,85,0.08); }
.lt-tag--purple { border-color: var(--accent-purple); color: var(--accent-purple); background: rgba(191,95,255,0.08); }
.lt-tag-remove {
background: none;
border: none;
color: inherit;
cursor: pointer;
padding: 0;
font-size: 0.8rem;
opacity: 0.6;
line-height: 1;
}
.lt-tag-remove:hover { opacity: 1; }
/* ----------------------------------------------------------------
39. NOTIFICATION BADGES
---------------------------------------------------------------- */
.lt-badge-wrap { position: relative; display: inline-flex; }
/* Notification counter badge — only absolute when inside .lt-badge-wrap */
.lt-badge-wrap .lt-badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 4px;
font-family: var(--font-mono);
font-size: 0.65rem;
font-weight: 700;
background: var(--accent-red);
color: var(--bg-primary);
position: absolute;
top: -6px; right: -8px;
box-shadow: 0 0 6px var(--accent-red);
}
.lt-badge-wrap .lt-badge--orange { background: var(--accent-orange); box-shadow: var(--glow-orange); }
.lt-badge-wrap .lt-badge--cyan { background: var(--accent-cyan); box-shadow: var(--glow-cyan); color: var(--bg-primary); }
.lt-badge-wrap .lt-badge--green { background: var(--accent-green); box-shadow: var(--glow-green); color: var(--bg-primary); }
.lt-badge-inline {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
font-family: var(--font-mono);
font-size: 0.65rem;
font-weight: 700;
background: var(--accent-orange);
color: var(--bg-primary);
vertical-align: middle;
}
/* ----------------------------------------------------------------
40. STEPPER / WIZARD
---------------------------------------------------------------- */
.lt-stepper {
display: flex;
align-items: flex-start;
gap: 0;
}
.lt-step {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
font-family: var(--font-mono);
font-size: 0.7rem;
text-align: center;
}
.lt-step:not(:last-child)::after {
content: '';
position: absolute;
top: 14px;
left: calc(50% + 14px);
right: calc(-50% + 14px);
height: 1px;
background: var(--border-dim);
}
.lt-step.complete:not(:last-child)::after { background: var(--accent-orange); }
.lt-step-num {
width: 28px; height: 28px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border-dim);
background: var(--bg-secondary);
color: var(--text-dim);
font-weight: 700;
margin-bottom: 6px;
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
.lt-step.active .lt-step-num {
border-color: var(--accent-orange);
background: var(--accent-orange);
color: var(--bg-primary);
box-shadow: var(--glow-orange);
}
.lt-step.complete .lt-step-num {
border-color: var(--accent-green);
background: var(--bg-secondary);
color: var(--accent-green);
box-shadow: var(--glow-green);
}
.lt-step-label { color: var(--text-dim); }
.lt-step.active .lt-step-label { color: var(--text-primary); }
.lt-step.complete .lt-step-label { color: var(--text-secondary); }
/* ----------------------------------------------------------------
41. LIST GROUPS
---------------------------------------------------------------- */
.lt-list-group { border: 1px solid var(--border-dim); }
.lt-list-item {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
border-bottom: 1px solid var(--border-dim);
font-family: var(--font-mono);
font-size: 0.8rem;
transition: background 0.12s;
}
.lt-list-item:last-child { border-bottom: none; }
.lt-list-item:hover { background: var(--bg-tertiary); }
.lt-list-item a {
color: var(--text-primary);
text-decoration: none;
flex: 1;
}
.lt-list-item a:hover { color: var(--accent-cyan); }
.lt-list-item-meta { color: var(--text-dim); font-size: 0.7rem; margin-left: auto; }
.lt-list-item--active { background: rgba(255,107,0,0.06); border-left: 2px solid var(--accent-orange); }
/* ----------------------------------------------------------------
42. KEY-VALUE PAIRS / DATA GRID
---------------------------------------------------------------- */
.lt-kv-grid {
display: grid;
grid-template-columns: max-content 1fr;
gap: 1px;
font-family: var(--font-mono);
font-size: 0.8rem;
}
.lt-kv-key {
padding: var(--space-xs) var(--space-md) var(--space-xs) 0;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.7rem;
white-space: nowrap;
border-right: 1px solid var(--border-dim);
}
.lt-kv-val {
padding: var(--space-xs) 0 var(--space-xs) var(--space-md);
color: var(--text-primary);
}
.lt-kv-val--orange { color: var(--accent-orange); }
.lt-kv-val--cyan { color: var(--accent-cyan); }
.lt-kv-val--green { color: var(--accent-green); }
.lt-kv-val--red { color: var(--accent-red); }
/* ----------------------------------------------------------------
43. HERO / BANNER SECTION
---------------------------------------------------------------- */
.lt-hero {
position: relative;
padding: var(--space-xl) 0;
text-align: center;
overflow: hidden;
}
.lt-hero::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(ellipse 60% 40% at 50% 0%, rgba(255,107,0,0.08) 0%, transparent 70%);
pointer-events: none;
}
.lt-hero-eyebrow {
font-family: var(--font-mono);
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.2em;
color: var(--accent-orange);
margin-bottom: var(--space-sm);
}
.lt-hero-title {
font-family: var(--font-mono);
font-size: clamp(1.8rem, 5vw, 3.5rem);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-primary);
text-shadow: var(--glow-orange);
line-height: 1.1;
margin-bottom: var(--space-md);
}
.lt-hero-sub {
font-family: var(--font-mono);
font-size: 0.9rem;
color: var(--text-secondary);
max-width: 560px;
margin: 0 auto var(--space-lg);
line-height: 1.6;
}
.lt-hero-actions { display: flex; gap: var(--space-md); justify-content: center; flex-wrap: wrap; }
/* ----------------------------------------------------------------
44. DIVIDER WITH LABEL
---------------------------------------------------------------- */
.lt-divider {
display: flex;
align-items: center;
gap: var(--space-md);
margin: var(--space-lg) 0;
}
.lt-divider::before,
.lt-divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--border-dim);
}
.lt-divider-label {
font-family: var(--font-mono);
font-size: 0.65rem;
text-transform: uppercase;
letter-spacing: 0.15em;
color: var(--text-dim);
white-space: nowrap;
}
.lt-divider--orange::before,
.lt-divider--orange::after { background: var(--accent-orange); }
.lt-divider--orange .lt-divider-label { color: var(--accent-orange); }
/* ----------------------------------------------------------------
45. CUSTOM SCROLLBAR
---------------------------------------------------------------- */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-primary); }
::-webkit-scrollbar-thumb { background: var(--bg-tertiary); }
::-webkit-scrollbar-thumb:hover { background: var(--accent-orange); }
/* ----------------------------------------------------------------
46. RESPONSIVE TABLE → CARD MODE
---------------------------------------------------------------- */
@media (max-width: 640px) {
.lt-table-responsive thead { display: none; }
.lt-table-responsive tbody tr {
display: block;
border: 1px solid var(--border-dim);
margin-bottom: var(--space-sm);
background: var(--bg-secondary);
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
.lt-table-responsive td {
display: flex;
justify-content: space-between;
padding: var(--space-xs) var(--space-sm);
border-bottom: 1px solid var(--border-dim);
font-size: 0.75rem;
}
.lt-table-responsive td:last-child { border-bottom: none; }
.lt-table-responsive td::before {
content: attr(data-label);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-dim);
font-size: 0.7rem;
flex-shrink: 0;
margin-right: var(--space-sm);
}
}
/* ----------------------------------------------------------------
47. GAUGE / METER
---------------------------------------------------------------- */
.lt-gauge-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-xs); }
.lt-gauge {
position: relative;
width: 100px;
height: 55px;
overflow: visible;
}
.lt-gauge svg { overflow: visible; }
.lt-gauge-track { fill: none; stroke: var(--bg-tertiary); stroke-width: 8; }
.lt-gauge-fill { fill: none; stroke: var(--accent-orange); stroke-width: 8; stroke-linecap: butt;
transition: stroke-dashoffset 0.6s cubic-bezier(0.4,0,0.2,1); }
.lt-gauge-label {
position: absolute;
bottom: 0; left: 50%;
transform: translateX(-50%);
font-family: var(--font-mono);
font-size: 1rem;
font-weight: 700;
color: var(--accent-orange);
text-shadow: var(--glow-orange);
white-space: nowrap;
}
.lt-gauge-caption { font-family: var(--font-mono); font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-dim); }
/* ----------------------------------------------------------------
48. SPINNERS / LOADERS
---------------------------------------------------------------- */
.lt-spinner {
display: inline-block;
width: 24px; height: 24px;
border: 2px solid var(--bg-tertiary);
border-top-color: var(--accent-orange);
border-radius: 50%;
animation: lt-spin 0.7s linear infinite;
}
.lt-spinner--cyan { border-top-color: var(--accent-cyan); }
.lt-spinner--green { border-top-color: var(--accent-green); }
.lt-spinner--sm { width: 14px; height: 14px; border-width: 1.5px; }
.lt-spinner--lg { width: 40px; height: 40px; border-width: 3px; }
@keyframes lt-spin { to { transform: rotate(360deg); } }
.lt-pulse-dot {
display: inline-block;
width: 8px; height: 8px;
background: var(--accent-green);
border-radius: 50%;
animation: lt-pulse 1.4s ease-in-out infinite;
box-shadow: 0 0 6px var(--accent-green);
}
@keyframes lt-pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(0.7); }
}
.lt-bar-loader {
display: flex;
gap: 3px;
align-items: flex-end;
height: 20px;
}
.lt-bar-loader span {
width: 4px;
background: var(--accent-orange);
box-shadow: var(--glow-orange);
animation: lt-bars 1s ease-in-out infinite;
}
.lt-bar-loader span:nth-child(2) { animation-delay: 0.1s; }
.lt-bar-loader span:nth-child(3) { animation-delay: 0.2s; }
.lt-bar-loader span:nth-child(4) { animation-delay: 0.3s; }
@keyframes lt-bars {
0%, 100% { height: 4px; }
50% { height: 20px; }
}
/* ----------------------------------------------------------------
49. TAB BAR
---------------------------------------------------------------- */
.lt-tab-bar {
display: flex;
border-bottom: 1px solid var(--border-dim);
gap: 0;
overflow-x: auto;
scrollbar-width: none;
}
.lt-tab-bar::-webkit-scrollbar { display: none; }
.lt-tab {
padding: var(--space-sm) var(--space-md);
font-family: var(--font-mono);
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-dim);
cursor: pointer;
border: none;
background: none;
border-bottom: 2px solid transparent;
transition: all 0.15s;
white-space: nowrap;
text-decoration: none;
display: inline-block;
}
.lt-tab:hover { color: var(--text-secondary); }
.lt-tab.active,
.lt-tab[aria-selected="true"] {
color: var(--accent-orange);
border-bottom-color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
.lt-tab-panels .lt-tab-panel { display: none; }
.lt-tab-panels .lt-tab-panel.active { display: block; }
/* ----------------------------------------------------------------
50. UTILITY CLASSES
---------------------------------------------------------------- */
/* Text colors */
.lt-text-orange { color: var(--accent-orange); }
.lt-text-cyan { color: var(--accent-cyan); }
.lt-text-green { color: var(--accent-green); }
.lt-text-red { color: var(--accent-red); }
.lt-text-purple { color: var(--accent-purple); }
.lt-text-dim { color: var(--text-dim); }
.lt-text-muted { color: var(--text-secondary); }
/* Glow text */
.lt-glow-orange { text-shadow: var(--glow-orange); }
.lt-glow-cyan { text-shadow: var(--glow-cyan); }
.lt-glow-green { text-shadow: var(--glow-green); }
.lt-glow-red { text-shadow: var(--glow-red); }
/* Backgrounds */
.lt-bg-secondary { background: var(--bg-secondary); }
.lt-bg-tertiary { background: var(--bg-tertiary); }
/* Border accents */
.lt-border-orange { border-color: var(--accent-orange) !important; }
.lt-border-cyan { border-color: var(--accent-cyan) !important; }
.lt-border-green { border-color: var(--accent-green) !important; }
.lt-border-red { border-color: var(--accent-red) !important; }
/* Display */
.lt-hidden { display: none !important; }
.lt-visible { display: block !important; }
.lt-flex { display: flex; }
.lt-grid { display: grid; }
.lt-inline { display: inline; }
.lt-iflex { display: inline-flex; }
/* Flex helpers */
.lt-gap-xs { gap: var(--space-xs); }
.lt-gap-sm { gap: var(--space-sm); }
.lt-gap-md { gap: var(--space-md); }
.lt-gap-lg { gap: var(--space-lg); }
.lt-align-center { align-items: center; }
.lt-align-start { align-items: flex-start; }
.lt-justify-between { justify-content: space-between; }
.lt-justify-center { justify-content: center; }
.lt-justify-end { justify-content: flex-end; }
.lt-wrap { flex-wrap: wrap; }
/* Spacing */
.lt-mt-xs { margin-top: var(--space-xs); }
.lt-mt-sm { margin-top: var(--space-sm); }
.lt-mt-md { margin-top: var(--space-md); }
.lt-mt-lg { margin-top: var(--space-lg); }
.lt-mb-xs { margin-bottom: var(--space-xs); }
.lt-mb-sm { margin-bottom: var(--space-sm); }
.lt-mb-md { margin-bottom: var(--space-md); }
.lt-mb-lg { margin-bottom: var(--space-lg); }
.lt-p-sm { padding: var(--space-sm); }
.lt-p-md { padding: var(--space-md); }
.lt-p-lg { padding: var(--space-lg); }
/* Text helpers */
.lt-mono { font-family: var(--font-mono); }
.lt-uppercase { text-transform: uppercase; }
.lt-bold { font-weight: 700; }
.lt-small { font-size: 0.75rem; }
.lt-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lt-no-wrap { white-space: nowrap; }
.lt-text-center { text-align: center; }
.lt-text-right { text-align: right; }
/* Opacity */
.lt-opacity-50 { opacity: 0.5; }
.lt-opacity-75 { opacity: 0.75; }
/* Cursor */
.lt-cursor-pointer { cursor: pointer; }
.lt-cursor-help { cursor: help; }
/* Width helpers */
.lt-w-full { width: 100%; }
.lt-w-auto { width: auto; }
/* Status dot */
.lt-dot {
display: inline-block;
width: 8px; height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.lt-dot--green { background: var(--accent-green); box-shadow: 0 0 6px var(--accent-green); }
.lt-dot--orange { background: var(--accent-orange); box-shadow: var(--glow-orange); }
.lt-dot--red { background: var(--accent-red); box-shadow: 0 0 6px var(--accent-red); }
.lt-dot--dim { background: var(--text-dim); }
/* Monospace table-style number alignment */
.lt-num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
/* ================================================================
v1.1 COMPONENT EXTENSIONS
51. Light Theme
52. Theme Toggle Button
53. Skeleton Loader Variants
54. Empty State Enhancements
55. Nav Notification Badge
56. Right-Side Drawer
57. Sticky Table
58. Multi-Select / Combobox
59. Context Menu
60. Offline Banner
61. Timeline / Activity Feed
62. Avatar
63. Split Pane
64. Chart Container
65. Toast Queue
66. Autocomplete / Typeahead
67. WebSocket Status
68. Print Enhancements
================================================================ */
/* ----------------------------------------------------------------
51. LIGHT THEME
---------------------------------------------------------------- */
html[data-theme="light"] {
--bg-primary: #eef1f6;
--bg-secondary: #e2e6ed;
--bg-tertiary: #d5dae3;
--bg-card: #ffffff;
--bg-terminal: #f7f9fc;
--bg-overlay: rgba(238,241,246,0.96);
--bg-input: #ffffff;
--text-primary: #1a2035;
--text-secondary: #3a4a6a;
--text-muted: #647898;
--text-dim: #8fa0b8;
--border-color: rgba(0,100,180,0.20);
--border-color-hi: var(--accent-cyan);
--border-color-dim: rgba(0,100,180,0.10);
--border-dim: rgba(0,100,180,0.10);
/* Slightly muted glows for light bg */
--glow-orange: 0 0 4px rgba(255,107,0,0.6), 0 0 10px rgba(255,107,0,0.3);
--glow-cyan: 0 0 4px rgba(0,150,200,0.6), 0 0 10px rgba(0,150,200,0.3);
--glow-green: 0 0 4px rgba(0,180,80,0.5), 0 0 10px rgba(0,180,80,0.25);
--glow-red: 0 0 4px rgba(220,0,50,0.5), 0 0 10px rgba(220,0,50,0.25);
--glow-amber: 0 0 4px rgba(200,130,0,0.5), 0 0 10px rgba(200,130,0,0.25);
color-scheme: light;
}
/* Hide CRT overlays in light mode */
html[data-theme="light"] body::before,
html[data-theme="light"] body::after { display: none; }
/* Soften dot grid */
html[data-theme="light"] body {
background-image: radial-gradient(circle, rgba(0,80,160,0.10) 1px, transparent 1px);
}
/* Nav / header adjustments */
html[data-theme="light"] .lt-header {
background: rgba(238,241,246,0.96);
border-bottom-color: var(--border-color);
}
html[data-theme="light"] .lt-nav-link,
html[data-theme="light"] .lt-nav-link:hover { color: var(--text-secondary); }
html[data-theme="light"] .lt-nav-link.active { color: var(--accent-orange); }
html[data-theme="light"] .lt-sidebar { background: var(--bg-secondary); border-color: var(--border-color); }
html[data-theme="light"] .lt-card,
html[data-theme="light"] .lt-frame { background: var(--bg-card); border-color: var(--border-color); }
html[data-theme="light"] .lt-section { background: var(--bg-card); border-color: var(--border-color); }
html[data-theme="light"] .lt-input,
html[data-theme="light"] .lt-select,
html[data-theme="light"] .lt-textarea { background: var(--bg-input); border-color: var(--border-color); color: var(--text-primary); }
html[data-theme="light"] .lt-table th { background: var(--bg-secondary); }
html[data-theme="light"] .lt-table tr:hover td { background: rgba(0,100,200,0.04); }
html[data-theme="light"] .lt-nav-drawer { background: var(--bg-card); }
html[data-theme="light"] code,
html[data-theme="light"] .lt-code-block { background: var(--bg-secondary); color: var(--text-primary); }
/* ----------------------------------------------------------------
52. THEME TOGGLE BUTTON
---------------------------------------------------------------- */
.lt-theme-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px; height: 32px;
border-radius: 4px;
border: 1px solid var(--border-color);
background: transparent;
color: var(--accent-cyan);
font-size: 1rem;
cursor: pointer;
transition: var(--transition-fast);
flex-shrink: 0;
}
.lt-theme-btn:hover {
background: var(--accent-cyan-dim);
border-color: var(--accent-cyan-border);
box-shadow: var(--box-glow-cyan);
}
.lt-theme-btn:focus-visible {
outline: 1px solid var(--accent-cyan);
outline-offset: 2px;
}
@media (pointer: coarse) {
.lt-theme-btn { width: 44px; height: 44px; font-size: 1.2rem; }
}
/* ----------------------------------------------------------------
53. SKELETON LOADER VARIANTS
(Extends existing .lt-skeleton in section 19)
---------------------------------------------------------------- */
/* Override section 19 shimmer with improved cyan-tinted version */
.lt-skeleton {
background: linear-gradient(
90deg,
var(--bg-secondary) 25%,
rgba(0,212,255,0.05) 50%,
var(--bg-secondary) 75%
);
background-size: 200% 100%;
animation: lt-shimmer 1.6s ease-in-out infinite;
border-radius: 2px;
display: block;
}
@keyframes lt-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
.lt-skeleton { animation: none; background: var(--bg-secondary); }
}
@media (pointer: coarse) {
.lt-skeleton { animation: none; }
}
/* Size variants */
.lt-skeleton-text { height: 0.8rem; width: 100%; margin-bottom: 0.4rem; }
.lt-skeleton-title { height: 1.1rem; width: 55%; margin-bottom: 0.6rem; }
.lt-skeleton-avatar { height: 2.25rem; width: 2.25rem; border-radius: 50%; flex-shrink: 0; }
.lt-skeleton-btn { height: 1.9rem; width: 5.5rem; }
.lt-skeleton-badge { height: 1.1rem; width: 4rem; border-radius: 999px; }
.lt-skeleton-line-sm { height: 0.7rem; width: 40%; margin-bottom: 0.3rem; }
.lt-skeleton-line-lg { height: 0.8rem; width: 80%; margin-bottom: 0.4rem; }
/* Card skeleton */
.lt-skeleton-card {
background: var(--bg-card);
border: 1px solid var(--border-dim);
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
padding: 1rem;
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.lt-skeleton-card-header {
display: flex;
gap: 0.75rem;
align-items: center;
margin-bottom: 0.4rem;
}
/* Table row skeleton */
.lt-skeleton-row {
display: grid;
grid-template-columns: 1.5rem 1fr 2.5fr 1fr 1fr 1fr;
gap: 1rem;
padding: 0.65rem 1rem;
border-bottom: 1px solid var(--border-dim);
align-items: center;
}
@media (max-width: 639px) {
.lt-skeleton-row { grid-template-columns: 1fr 2fr; gap: 0.5rem; }
}
/* ----------------------------------------------------------------
54. EMPTY STATE ENHANCEMENTS
(Extends existing .lt-empty in section 19)
---------------------------------------------------------------- */
.lt-empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 3rem 2rem;
text-align: center;
gap: 0.6rem;
}
.lt-empty-state-icon {
font-size: 2.5rem;
opacity: 0.35;
margin-bottom: 0.25rem;
line-height: 1;
}
.lt-empty-state-title {
color: var(--text-secondary);
font-size: 0.8rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
}
.lt-empty-state-body {
color: var(--text-muted);
font-size: 0.72rem;
max-width: 30ch;
line-height: 1.7;
}
.lt-empty-state .lt-btn { margin-top: 0.5rem; }
/* Small inline variant */
.lt-empty-state--sm {
padding: 1.5rem 1rem;
}
.lt-empty-state--sm .lt-empty-state-icon { font-size: 1.5rem; }
.lt-empty-state--sm .lt-empty-state-title { font-size: 0.72rem; }
/* ----------------------------------------------------------------
55. NAV NOTIFICATION BADGE
---------------------------------------------------------------- */
.lt-notif-wrap {
position: relative;
display: inline-flex;
}
.lt-notif-badge {
position: absolute;
top: -4px;
right: -4px;
min-width: 1rem;
height: 1rem;
padding: 0 0.2rem;
background: var(--accent-red);
color: #fff;
font-size: 0.58rem;
font-weight: 700;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
border: 1.5px solid var(--bg-primary);
pointer-events: none;
animation: lt-notif-pulse 2.5s ease-in-out infinite;
}
.lt-notif-badge[data-count="0"],
.lt-notif-badge:empty { display: none; }
@keyframes lt-notif-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(255,45,85,0.7); }
50% { box-shadow: 0 0 0 5px rgba(255,45,85,0); }
}
@media (pointer: coarse) { .lt-notif-badge { animation: none; } }
/* ----------------------------------------------------------------
56. RIGHT-SIDE DRAWER
---------------------------------------------------------------- */
.lt-drawer-right {
position: fixed;
top: var(--header-height);
right: 0;
height: calc(100vh - var(--header-height));
width: 400px;
max-width: 92vw;
background: var(--bg-card);
border-left: 1px solid var(--border-color);
clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
transform: translateX(100%);
transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
z-index: calc(var(--z-overlay) + 2); /* 10001 — same level as nav overlay */
display: flex;
flex-direction: column;
overflow: hidden;
}
.lt-drawer-right.is-open { transform: translateX(0); }
.lt-drawer-right-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--border-dim);
flex-shrink: 0;
}
.lt-drawer-right-title {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent-cyan);
text-shadow: var(--glow-cyan);
}
.lt-drawer-right-close {
width: 32px; height: 32px;
display: flex; align-items: center; justify-content: center;
background: none;
border: 1px solid transparent;
color: var(--text-muted);
font-size: 1rem;
cursor: pointer;
border-radius: 2px;
transition: var(--transition-fast);
}
.lt-drawer-right-close:hover { color: var(--accent-red); border-color: var(--accent-red); }
.lt-drawer-right-close:focus-visible { outline: 1px solid var(--accent-cyan); outline-offset: 2px; }
.lt-drawer-right-body {
flex: 1;
overflow-y: auto;
padding: 1rem;
overscroll-behavior: contain;
}
.lt-drawer-right-footer {
padding: 0.75rem 1rem;
border-top: 1px solid var(--border-dim);
display: flex;
gap: 0.5rem;
justify-content: flex-end;
flex-shrink: 0;
}
/* Overlay for right drawer */
.lt-drawer-right-overlay {
position: fixed;
inset: 0;
background: rgba(3,5,8,0.65);
z-index: calc(var(--z-overlay) + 1); /* 10000 */
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease;
}
.lt-drawer-right-overlay.is-open { opacity: 1; pointer-events: auto; }
@media (max-width: 479px) {
.lt-drawer-right { width: 100vw; max-width: 100vw; top: 0; height: 100vh; border-left: none; border-top: 1px solid var(--border-color); }
}
@media (pointer: coarse) {
.lt-drawer-right-close { width: 44px; height: 44px; }
}
/* ----------------------------------------------------------------
57. STICKY TABLE
---------------------------------------------------------------- */
.lt-table-sticky-wrap {
max-height: 420px;
overflow-y: auto;
overflow-x: auto;
overscroll-behavior: contain;
border: 1px solid var(--border-dim);
border-radius: 2px;
}
.lt-table-sticky-wrap .lt-table { margin: 0; border: none; }
.lt-table-sticky-wrap .lt-table thead th {
position: sticky;
top: 0;
z-index: 2;
background: var(--bg-tertiary);
backdrop-filter: blur(6px);
border-bottom: 2px solid var(--border-color);
box-shadow: 0 2px 8px rgba(3,5,8,0.5);
}
/* Custom scrollbar inside sticky wrap */
.lt-table-sticky-wrap::-webkit-scrollbar { width: 6px; height: 6px; }
.lt-table-sticky-wrap::-webkit-scrollbar-track { background: var(--bg-primary); }
.lt-table-sticky-wrap::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 3px; }
/* ----------------------------------------------------------------
58. MULTI-SELECT / COMBOBOX
---------------------------------------------------------------- */
.lt-combobox {
position: relative;
display: block;
}
.lt-combobox-input-wrap {
display: flex;
flex-wrap: wrap;
gap: 4px;
align-items: center;
min-height: 36px;
padding: 4px 8px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
cursor: text;
transition: border-color 0.15s;
}
.lt-combobox-input-wrap:focus-within {
border-color: var(--accent-cyan);
box-shadow: var(--box-glow-cyan);
}
.lt-combobox-input-wrap .lt-combobox-input {
flex: 1;
min-width: 80px;
background: none;
border: none;
outline: none;
color: var(--text-primary);
font-family: var(--font-mono);
font-size: 0.8rem;
padding: 2px 0;
}
/* Selected tag chips inside the input */
.lt-combobox-tag {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 1px 6px;
background: var(--accent-cyan-dim);
border: 1px solid var(--accent-cyan-border);
color: var(--accent-cyan);
font-size: 0.7rem;
border-radius: 2px;
white-space: nowrap;
}
.lt-combobox-tag-remove {
background: none; border: none; cursor: pointer;
color: var(--text-muted); font-size: 0.75rem; padding: 0; line-height: 1;
display: flex; align-items: center;
}
.lt-combobox-tag-remove:hover { color: var(--accent-red); }
/* Dropdown list */
.lt-combobox-dropdown {
position: absolute;
top: calc(100% + 2px);
left: 0; right: 0;
background: var(--bg-card);
border: 1px solid var(--border-color);
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
z-index: var(--z-dropdown);
max-height: 200px;
overflow-y: auto;
display: none;
}
.lt-combobox-dropdown.is-open { display: block; }
.lt-combobox-option {
padding: 0.4rem 0.75rem;
font-size: 0.78rem;
color: var(--text-secondary);
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: background 0.1s;
}
.lt-combobox-option:hover,
.lt-combobox-option.is-focused { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-combobox-option.is-selected::before {
content: '✓';
color: var(--accent-green);
font-size: 0.7rem;
width: 0.8rem;
flex-shrink: 0;
}
.lt-combobox-option:not(.is-selected)::before { content: ''; width: 0.8rem; display: inline-block; flex-shrink: 0; }
.lt-combobox-empty {
padding: 0.6rem 0.75rem;
font-size: 0.72rem;
color: var(--text-muted);
text-align: center;
}
/* ----------------------------------------------------------------
59. CONTEXT MENU
---------------------------------------------------------------- */
.lt-context-menu {
position: fixed;
background: var(--bg-card);
border: 1px solid var(--border-color);
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
min-width: 160px;
z-index: var(--z-tooltip);
box-shadow: 0 8px 32px rgba(0,0,0,0.45);
padding: 4px 0;
display: none;
}
.lt-context-menu.is-open { display: block; }
.lt-context-menu-item {
display: flex;
align-items: center;
gap: 0.6rem;
padding: 0.4rem 0.75rem;
font-size: 0.78rem;
color: var(--text-secondary);
cursor: pointer;
transition: background 0.1s;
user-select: none;
white-space: nowrap;
}
.lt-context-menu-item:hover { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-context-menu-item.is-danger:hover { background: var(--accent-red-dim); color: var(--accent-red); }
.lt-context-menu-item .icon { width: 1rem; text-align: center; opacity: 0.7; font-size: 0.75rem; }
.lt-context-menu-item kbd {
margin-left: auto;
font-size: 0.6rem;
color: var(--text-muted);
background: var(--bg-tertiary);
border: 1px solid var(--border-dim);
padding: 1px 4px;
border-radius: 2px;
}
.lt-context-menu-divider {
height: 1px;
background: var(--border-dim);
margin: 4px 0;
}
.lt-context-menu-label {
padding: 0.25rem 0.75rem;
font-size: 0.62rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-muted);
pointer-events: none;
}
/* ----------------------------------------------------------------
60. OFFLINE BANNER
---------------------------------------------------------------- */
.lt-offline-banner {
position: fixed;
top: var(--header-height);
left: 0; right: 0;
padding: 0.4rem 1rem;
background: var(--accent-red-dim);
border-top: 1px solid var(--accent-red);
border-bottom: 1px solid var(--accent-red);
color: var(--accent-red);
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.1em;
text-align: center;
z-index: var(--z-fixed);
transform: translateY(-100%);
transition: transform 0.25s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.lt-offline-banner.is-visible { transform: translateY(0); }
.lt-offline-banner .lt-dot--red {
animation: lt-pulse 1s ease-in-out infinite;
}
@keyframes lt-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s ease; }
/* ----------------------------------------------------------------
61. TIMELINE / ACTIVITY FEED
---------------------------------------------------------------- */
.lt-timeline {
display: flex;
flex-direction: column;
gap: 0;
padding-left: 1.25rem;
border-left: 1px solid var(--border-dim);
margin-left: 0.5rem;
}
.lt-timeline-item {
position: relative;
padding: 0 0 1.25rem 1.25rem;
}
.lt-timeline-item:last-child { padding-bottom: 0; }
/* Connector dot */
.lt-timeline-item::before {
content: '';
position: absolute;
left: -5px;
top: 4px;
width: 8px; height: 8px;
border-radius: 50%;
background: var(--accent-cyan);
box-shadow: 0 0 6px var(--accent-cyan);
border: 1.5px solid var(--bg-primary);
}
.lt-timeline-item--orange::before { background: var(--accent-orange); box-shadow: var(--glow-orange); }
.lt-timeline-item--green::before { background: var(--accent-green); box-shadow: var(--glow-green); }
.lt-timeline-item--red::before { background: var(--accent-red); box-shadow: var(--glow-red); }
.lt-timeline-item--dim::before { background: var(--text-muted); box-shadow: none; }
.lt-timeline-meta {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.68rem;
color: var(--text-muted);
margin-bottom: 0.2rem;
flex-wrap: wrap;
}
.lt-timeline-actor { color: var(--accent-cyan); }
.lt-timeline-time { margin-left: auto; white-space: nowrap; }
.lt-timeline-body { font-size: 0.78rem; color: var(--text-secondary); line-height: 1.5; }
.lt-timeline-body code { font-size: 0.72rem; color: var(--accent-green); }
/* ----------------------------------------------------------------
62. AVATAR
---------------------------------------------------------------- */
.lt-avatar {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: var(--bg-tertiary);
border: 1.5px solid var(--border-color);
color: var(--accent-cyan);
font-weight: 700;
font-size: 0.75rem;
text-transform: uppercase;
overflow: hidden;
flex-shrink: 0;
user-select: none;
}
.lt-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Sizes */
.lt-avatar--xs { width: 1.5rem; height: 1.5rem; font-size: 0.55rem; }
.lt-avatar--sm { width: 2rem; height: 2rem; font-size: 0.65rem; }
.lt-avatar { width: 2.5rem; height: 2.5rem; font-size: 0.75rem; } /* default */
.lt-avatar--lg { width: 3.5rem; height: 3.5rem; font-size: 1rem; }
.lt-avatar--xl { width: 5rem; height: 5rem; font-size: 1.4rem; }
/* Color variants */
.lt-avatar--orange { background: var(--accent-orange-dim); border-color: var(--accent-orange-border); color: var(--accent-orange); }
.lt-avatar--green { background: var(--accent-green-dim); border-color: var(--accent-green-border); color: var(--accent-green); }
.lt-avatar--red { background: var(--accent-red-dim); border-color: var(--accent-red); color: var(--accent-red); }
.lt-avatar--purple { background: var(--accent-purple-dim); border-color: var(--accent-purple); color: var(--accent-purple); }
/* Avatar group (overlapping row) */
.lt-avatar-group { display: flex; }
.lt-avatar-group .lt-avatar {
margin-left: -0.5rem;
border: 2px solid var(--bg-primary);
transition: transform 0.15s;
}
.lt-avatar-group .lt-avatar:first-child { margin-left: 0; }
.lt-avatar-group .lt-avatar:hover { transform: translateY(-2px) scale(1.08); z-index: 1; }
/* Status ring */
.lt-avatar-wrap {
position: relative;
display: inline-flex;
flex-shrink: 0;
}
.lt-avatar-status {
position: absolute;
bottom: 1px; right: 1px;
width: 9px; height: 9px;
border-radius: 50%;
border: 1.5px solid var(--bg-primary);
background: var(--text-muted);
}
.lt-avatar-status--online { background: var(--accent-green); box-shadow: 0 0 4px var(--accent-green); }
.lt-avatar-status--away { background: var(--accent-amber); }
.lt-avatar-status--busy { background: var(--accent-red); }
/* ----------------------------------------------------------------
63. SPLIT PANE
---------------------------------------------------------------- */
.lt-split {
display: flex;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.lt-split--vertical { flex-direction: column; }
.lt-split-pane {
overflow: auto;
flex: 1;
min-width: 0;
min-height: 0;
}
.lt-split-divider {
flex: 0 0 5px;
background: var(--border-dim);
cursor: col-resize;
transition: background 0.15s;
position: relative;
user-select: none;
touch-action: none;
}
.lt-split-divider::after {
content: '⠿';
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
color: var(--text-muted);
font-size: 0.6rem;
pointer-events: none;
}
.lt-split-divider:hover,
.lt-split-divider.is-dragging { background: var(--accent-cyan-border); }
.lt-split--vertical .lt-split-divider { cursor: row-resize; }
/* On mobile, stack vertically and hide divider */
@media (max-width: 767px) {
.lt-split:not(.lt-split--vertical) { flex-direction: column; }
.lt-split:not(.lt-split--vertical) .lt-split-divider { display: none; }
.lt-split:not(.lt-split--vertical) .lt-split-pane { flex: 0 0 auto; }
}
/* ----------------------------------------------------------------
64. CHART CONTAINER
---------------------------------------------------------------- */
.lt-chart-wrap {
position: relative;
background: var(--bg-card);
border: 1px solid var(--border-dim);
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
padding: 1rem;
overflow: hidden;
}
.lt-chart-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.75rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.lt-chart-title {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-secondary);
}
.lt-chart-legend {
display: flex;
gap: 1rem;
font-size: 0.68rem;
color: var(--text-muted);
flex-wrap: wrap;
}
.lt-chart-legend-item {
display: flex;
align-items: center;
gap: 0.35rem;
}
.lt-chart-legend-dot {
width: 8px; height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.lt-chart-body {
position: relative;
width: 100%;
}
/* Sparkline — inline mini chart */
.lt-sparkline {
display: inline-block;
vertical-align: middle;
}
/* Axis labels */
.lt-chart-axis {
display: flex;
justify-content: space-between;
font-size: 0.62rem;
color: var(--text-muted);
margin-top: 0.25rem;
}
/* Loading / no-data states */
.lt-chart-wrap.is-loading .lt-chart-body { min-height: 120px; }
.lt-chart-wrap.is-loading .lt-chart-body::after {
content: 'LOADING DATA...';
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.68rem;
color: var(--text-muted);
letter-spacing: 0.1em;
}
/* ----------------------------------------------------------------
65. TOAST QUEUE (enhanced multi-toast stack)
---------------------------------------------------------------- */
/* Toast container already exists in section 14; these are addons */
#lt-toast-container {
/* Stack from bottom — newest on top */
display: flex;
flex-direction: column-reverse;
gap: 0.5rem;
}
.lt-toast + .lt-toast { margin-top: 0; } /* gap handles spacing */
/* Progress bar on toast (auto-dismiss countdown) */
.lt-toast-progress {
position: absolute;
bottom: 0; left: 0;
height: 2px;
background: currentColor;
opacity: 0.4;
animation: lt-toast-drain linear forwards;
}
@keyframes lt-toast-drain {
from { width: 100%; }
to { width: 0; }
}
/* Pause on hover */
.lt-toast:hover .lt-toast-progress { animation-play-state: paused; }
/* ----------------------------------------------------------------
66. AUTOCOMPLETE / TYPEAHEAD
---------------------------------------------------------------- */
.lt-typeahead {
position: relative;
display: block;
}
.lt-typeahead-dropdown {
position: absolute;
top: calc(100% + 2px);
left: 0; right: 0;
background: var(--bg-card);
border: 1px solid var(--border-color);
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
z-index: var(--z-dropdown);
max-height: 220px;
overflow-y: auto;
display: none;
}
.lt-typeahead-dropdown.is-open { display: block; }
.lt-typeahead-item {
padding: 0.4rem 0.75rem;
font-size: 0.78rem;
color: var(--text-secondary);
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: background 0.1s;
}
.lt-typeahead-item:hover,
.lt-typeahead-item.is-focused { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-typeahead-item mark {
background: none;
color: var(--accent-orange);
font-weight: 700;
}
.lt-typeahead-item .icon {
font-size: 0.75rem;
opacity: 0.6;
width: 1rem;
text-align: center;
flex-shrink: 0;
}
.lt-typeahead-empty {
padding: 0.6rem 0.75rem;
font-size: 0.72rem;
color: var(--text-muted);
text-align: center;
letter-spacing: 0.05em;
}
/* Loading state in dropdown */
.lt-typeahead-loading {
padding: 0.6rem 0.75rem;
font-size: 0.72rem;
color: var(--text-muted);
display: flex;
align-items: center;
gap: 0.5rem;
}
.lt-typeahead-loading::before {
content: '';
width: 10px; height: 10px;
border: 1.5px solid var(--border-color);
border-top-color: var(--accent-cyan);
border-radius: 50%;
animation: spin 0.7s linear infinite;
flex-shrink: 0;
}
/* ----------------------------------------------------------------
67. WEBSOCKET STATUS INDICATOR
---------------------------------------------------------------- */
.lt-ws-status {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
padding: 2px 8px;
border: 1px solid var(--border-dim);
border-radius: 2px;
}
.lt-ws-status .lt-dot { flex-shrink: 0; }
.lt-ws-status[data-state="connected"] { color: var(--accent-green); border-color: var(--accent-green-border); }
.lt-ws-status[data-state="connecting"] { color: var(--accent-amber); border-color: var(--accent-amber-dim); }
.lt-ws-status[data-state="disconnected"] { color: var(--accent-red); border-color: var(--accent-red-dim); }
.lt-ws-status[data-state="connected"] .lt-dot { background: var(--accent-green); box-shadow: var(--glow-green); }
.lt-ws-status[data-state="connecting"] .lt-dot { background: var(--accent-amber); box-shadow: var(--glow-amber); animation: lt-pulse 0.8s ease-in-out infinite; }
.lt-ws-status[data-state="disconnected"] .lt-dot { background: var(--accent-red); }
/* ----------------------------------------------------------------
68. PRINT ENHANCEMENTS
(Extends section 25)
---------------------------------------------------------------- */
@media print {
.lt-sidebar, .lt-nav, .lt-header-right,
.lt-btn-group, .lt-menu-btn,
.lt-nav-drawer, .lt-nav-drawer-overlay,
.lt-offline-banner, .lt-context-menu,
[data-modal-open], [data-tooltip] { display: none !important; }
.lt-section, .lt-card, .lt-frame {
break-inside: avoid;
box-shadow: none;
clip-path: none;
border: 1px solid #999;
}
.lt-table { border-collapse: collapse; }
.lt-table th, .lt-table td { border: 1px solid #ccc; }
.lt-table thead th { background: #eee !important; color: black !important; }
a[href]::after { content: " (" attr(href) ")"; font-size: 0.7em; color: #666; }
a[href^="#"]::after, a[href^="javascript"]::after { content: ""; }
.lt-code-block { white-space: pre-wrap; word-break: break-all; }
.lt-page-header { border-bottom: 2px solid #333; padding-bottom: 0.5rem; margin-bottom: 1rem; }
}