Files
tinker_tickets/assets/css/base.css
Jared Vititoe 68ff89b48c Fix persistent blink: scanline animation still active via base.css cascade
Root cause: removing 'animation' from dashboard.css body::before did NOT disable
the scanline — it just stopped overriding base.css which still had
'animation: scanline 8s linear infinite'. CSS cascade means the base.css value
remained active. Fixed by setting 'animation: none' explicitly in dashboard.css.

Also fix base.css (used by all pages including ticket page):
- Set body::before animation: none (removes GPU compositing layer from scanline)
- Change corner-pulse/subtle-pulse/pulse-glow/pulse-red keyframes from text-shadow
  and box-shadow animations to opacity (GPU composited, zero CPU repaint overhead)
- Change exec-running-pulse from box-shadow to opacity
- Remove box-shadow from .lt-table tr:hover, .lt-card:hover, .lt-stat-card:hover
- Remove text-shadow/box-shadow/transform from .lt-btn:hover and variants
- Remove text-shadow from a:hover

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 12:12:44 -04:00

1716 lines
50 KiB
CSS

/* ================================================================
LOTUSGUILD TERMINAL DESIGN SYSTEM v1.0 — base.css
Unified CSS for all LotusGuild web applications
Apps: Tinker Tickets (PHP), PULSE (Node.js), GANDALF (Flask)
Aesthetic: Retro CRT terminal, phosphor green, ASCII art borders
Prefix: .lt-* (LotusGuild Terminal)
TABLE OF CONTENTS
01. CSS Custom Properties
02. Reset & Base
03. CRT & Terminal Effects
04. Typography
05. Layout Primitives
06. Header & Navigation
07. ASCII Frame System
08. Card Component
09. Buttons
10. Forms & Inputs
11. Tables
12. Status Badges, Chips, Priority
13. Modals
14. Toast Notifications
15. Tab Navigation
16. Sidebar / Filter Panel
17. Stats Widgets
18. Inline Messages
19. Loading & Empty States
20. Boot Sequence Overlay
21. Log / Timeline Entries
22. Animations (keyframes)
23. Responsive Design
24. Utility Classes
25. Print Styles
26. Accessibility
================================================================ */
/* ----------------------------------------------------------------
01. CSS CUSTOM PROPERTIES
---------------------------------------------------------------- */
:root {
/* --- Backgrounds --- */
--bg-primary: #0a0a0a; /* Main background: near-black */
--bg-secondary: #1a1a1a; /* Surface: dark grey */
--bg-tertiary: #2a2a2a; /* Raised surface / hover states */
--bg-terminal: #001a00; /* Deep green-tinted black for terminal panels */
/* --- Terminal Green (Primary accent) --- */
--terminal-green: #00ff41;
--terminal-green-dim: rgba(0, 255, 65, 0.15);
--terminal-green-dark: #00cc33;
--terminal-green-muted: #008822;
/* --- Amber (Secondary / highlight / headings) --- */
--terminal-amber: #ffb000;
--terminal-amber-dim: rgba(255, 176, 0, 0.15);
/* --- Cyan (Tertiary / uplinks / info) --- */
--terminal-cyan: #00ffff;
--terminal-cyan-dim: rgba(0, 255, 255, 0.12);
/* --- Red (Error / critical / closed) --- */
--terminal-red: #ff4444;
--terminal-red-dim: rgba(255, 68, 68, 0.15);
/* --- Orange (Warning) --- */
--terminal-orange: #ff8c00;
--terminal-orange-dim: rgba(255, 140, 0, 0.15);
/* --- Text --- */
--text-primary: #00ff41; /* Body text */
--text-secondary: #00cc33; /* Subdued text */
--text-muted: #00bb33; /* Muted / placeholder text */
/* --- Borders --- */
--border-color: rgba(0, 255, 65, 0.35); /* Default border (semi-transparent) */
--border-color-hi: #00ff41; /* Highlighted / focused border */
--border-color-dim: rgba(0, 255, 65, 0.12); /* Subtle row separator */
/* --- Ticket / workflow status colours --- */
--status-open: #28a745;
--status-pending: #9c27b0;
--status-in-progress: #ffc107;
--status-closed: #dc3545;
--status-online: #28a745;
--status-offline: #dc3545;
--status-running: #ffc107;
--status-completed: #28a745;
--status-failed: #dc3545;
--status-waiting: #ffc107;
/* --- Priority colours (P1 critical → P5 minimal) --- */
--priority-1: #ff4d4d; /* Critical */
--priority-2: #ffa726; /* High */
--priority-3: #42a5f5; /* Medium */
--priority-4: #66bb6a; /* Low */
--priority-5: #9e9e9e; /* Minimal */
/* --- Glow — text-shadow stacks --- */
--glow-green: 0 0 5px #00ff41, 0 0 10px #00ff41, 0 0 15px #00ff41;
--glow-green-intense: 0 0 8px #00ff41, 0 0 16px #00ff41, 0 0 24px #00ff41,
0 0 32px rgba(0, 255, 65, 0.5);
--glow-amber: 0 0 5px #ffb000, 0 0 10px #ffb000, 0 0 15px #ffb000;
--glow-amber-intense: 0 0 8px #ffb000, 0 0 16px #ffb000, 0 0 24px #ffb000;
--glow-cyan: 0 0 5px #00ffff, 0 0 10px rgba(0, 255, 255, 0.4);
--glow-red: 0 0 5px #ff4444, 0 0 10px #ff4444;
/* --- Glow — box-shadow (element halos) --- */
--box-glow-green: 0 0 12px rgba(0, 255, 65, 0.3);
--box-glow-amber: 0 0 12px rgba(255, 176, 0, 0.3);
--box-glow-red: 0 0 12px rgba(255, 68, 68, 0.3);
--box-glow-cyan: 0 0 12px rgba(0, 255, 255, 0.25);
/* --- Typography --- */
--font-mono: 'Courier New', 'Consolas', 'Monaco', 'Menlo', monospace;
/* --- Spacing scale --- */
--space-xs: 0.25rem; /* 4px */
--space-sm: 0.5rem; /* 8px */
--space-md: 1rem; /* 16px */
--space-lg: 1.5rem; /* 24px */
--space-xl: 2rem; /* 32px */
--space-2xl: 3rem; /* 48px */
/* --- Layout --- */
--sidebar-width: 240px;
--sidebar-width-sm: 200px;
--header-height: 58px;
--container-max: 1600px;
/* --- Transitions --- */
--transition-fast: all 0.15s ease;
--transition-default: all 0.3s ease;
/* --- Z-index ladder --- */
--z-base: 1;
--z-dropdown: 100;
--z-sticky: 200;
--z-fixed: 300;
--z-modal-backdrop: 400;
--z-modal: 500;
--z-popover: 600;
--z-tooltip: 700;
--z-toast: 800;
--z-overlay: 9999;
}
/* ----------------------------------------------------------------
02. RESET & BASE
---------------------------------------------------------------- */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
font-family: var(--font-mono);
line-height: 1.6;
min-height: 100vh;
overflow-x: hidden;
}
a {
color: var(--terminal-green);
text-decoration: none;
transition: var(--transition-fast);
}
a:hover {
color: var(--terminal-amber);
}
ul, ol { list-style: none; }
img, svg { display: block; max-width: 100%; }
/* ----------------------------------------------------------------
03. CRT & TERMINAL EFFECTS
---------------------------------------------------------------- */
/* Horizontal scanline overlay — fixed over the entire viewport */
body::before {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.15) 0px,
rgba(0, 0, 0, 0.15) 1px,
transparent 1px,
transparent 2px
);
pointer-events: none;
z-index: var(--z-overlay);
animation: none;
}
/* Binary data-stream watermark — bottom-right corner */
body::after {
content: '10101010';
position: fixed;
bottom: 10px;
right: 14px;
font-family: var(--font-mono);
font-size: 0.55rem;
color: var(--terminal-green);
opacity: 0.07;
pointer-events: none;
letter-spacing: 2px;
animation: data-stream 3s steps(1) infinite;
}
/* ----------------------------------------------------------------
04. TYPOGRAPHY
---------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-mono);
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.08em;
line-height: 1.3;
}
h1 {
font-size: 1.5rem;
color: var(--terminal-amber);
text-shadow: var(--glow-amber-intense);
}
h1::before { content: '>> '; color: var(--terminal-green); text-shadow: var(--glow-green); }
h2 {
font-size: 1.2rem;
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
}
h3 {
font-size: 1rem;
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
}
h3::before { content: '═══ '; color: var(--terminal-green); }
h3::after { content: ' ═══'; color: var(--terminal-green); }
h4 {
font-size: 0.9rem;
color: var(--terminal-amber);
letter-spacing: 0.07em;
}
p {
color: var(--text-primary);
margin-bottom: var(--space-md);
}
code {
font-family: var(--font-mono);
background: var(--bg-terminal);
color: var(--terminal-green);
padding: 2px 6px;
border: 1px solid var(--border-color-dim);
font-size: 0.9em;
}
pre {
font-family: var(--font-mono);
background: var(--bg-terminal);
color: var(--terminal-green);
padding: var(--space-md);
border: 1px solid var(--border-color);
overflow-x: auto;
line-height: 1.5;
}
/* ----------------------------------------------------------------
05. LAYOUT PRIMITIVES
---------------------------------------------------------------- */
.lt-container {
max-width: var(--container-max);
margin: 0 auto;
padding: 0 var(--space-lg);
}
.lt-main {
padding: var(--space-lg);
min-height: calc(100vh - var(--header-height));
}
/* Sidebar + content split */
.lt-layout {
display: flex;
gap: var(--space-md);
align-items: flex-start;
}
.lt-content { flex: 1; min-width: 0; }
/* Page header (below nav, above content) */
.lt-page-header {
margin-bottom: var(--space-lg);
padding-bottom: var(--space-md);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-md);
flex-wrap: wrap;
}
.lt-page-title {
font-size: 1.05rem;
font-weight: bold;
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.lt-page-title::before { content: '>> '; color: var(--terminal-green); }
/* ----------------------------------------------------------------
06. HEADER & NAVIGATION
---------------------------------------------------------------- */
.lt-header {
height: var(--header-height);
background: var(--bg-secondary);
border-bottom: 2px solid var(--terminal-green);
box-shadow: 0 2px 16px rgba(0, 255, 65, 0.12);
padding: 0 var(--space-lg);
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
top: 0;
z-index: var(--z-fixed);
}
/* Animated glow underline on header */
.lt-header::after {
content: '';
position: absolute;
bottom: -2px;
left: 0; right: 0;
height: 2px;
background: linear-gradient(
90deg,
transparent 0%,
var(--terminal-green) 20%,
var(--terminal-green) 80%,
transparent 100%
);
box-shadow: var(--glow-green);
}
.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 / App Title --- */
.lt-brand { display: flex; flex-direction: column; }
.lt-brand-title {
font-size: 1.2rem;
font-weight: bold;
color: var(--terminal-amber);
text-shadow: var(--glow-amber-intense);
letter-spacing: 0.1em;
white-space: nowrap;
animation: subtle-pulse 3s ease-in-out infinite;
}
.lt-brand-title::before {
content: '>> ';
color: var(--terminal-green);
text-shadow: var(--glow-green);
}
.lt-brand-subtitle {
font-size: 0.6rem;
color: var(--text-muted);
letter-spacing: 0.12em;
text-transform: uppercase;
}
/* --- Nav links (horizontal bar) --- */
.lt-nav {
display: flex;
align-items: center;
gap: var(--space-xs);
}
.lt-nav-link {
display: inline-block;
color: var(--text-muted);
padding: 4px 10px;
border: 1px solid transparent;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.06em;
transition: var(--transition-fast);
white-space: nowrap;
}
.lt-nav-link::before { content: '[ '; }
.lt-nav-link::after { content: ' ]'; }
.lt-nav-link:hover {
color: var(--terminal-green);
border-color: var(--border-color);
background: var(--terminal-green-dim);
text-shadow: var(--glow-green);
}
.lt-nav-link.active {
color: var(--terminal-amber);
border-color: var(--terminal-amber);
background: var(--terminal-amber-dim);
text-shadow: var(--glow-amber);
}
/* --- Dropdown nav --- */
.lt-nav-dropdown { position: relative; }
.lt-nav-dropdown-menu {
display: none;
position: absolute;
top: calc(100% + 4px);
left: 0;
min-width: 200px;
background: var(--bg-secondary);
border: 1px solid var(--border-color-hi);
box-shadow: var(--box-glow-green), 0 8px 24px rgba(0,0,0,0.6);
z-index: var(--z-dropdown);
list-style: none;
}
.lt-nav-dropdown:hover .lt-nav-dropdown-menu,
.lt-nav-dropdown.open .lt-nav-dropdown-menu { display: block; }
.lt-nav-dropdown-menu li a {
display: block;
padding: 8px 14px;
color: var(--text-secondary);
font-size: 0.8rem;
border-bottom: 1px solid var(--border-color-dim);
transition: var(--transition-fast);
}
.lt-nav-dropdown-menu li a::before { content: '> '; color: var(--terminal-amber); }
.lt-nav-dropdown-menu li a:hover {
background: var(--terminal-green-dim);
color: var(--terminal-green);
text-shadow: var(--glow-green);
}
.lt-nav-dropdown-menu li:last-child a { border-bottom: none; }
/* --- User info widget --- */
.lt-header-user {
font-size: 0.78rem;
color: var(--text-secondary);
white-space: nowrap;
}
.lt-header-user::before { content: '[user: '; color: var(--terminal-amber); }
.lt-header-user::after { content: ']'; color: var(--terminal-amber); }
/* --- Admin badge --- */
.lt-badge-admin {
display: inline-block;
color: var(--terminal-red);
border: 1px solid var(--terminal-red);
padding: 2px 8px;
font-size: 0.7rem;
font-weight: bold;
text-shadow: var(--glow-red);
letter-spacing: 0.05em;
text-transform: uppercase;
}
.lt-badge-admin::before { content: '['; }
.lt-badge-admin::after { content: ']'; }
/* ----------------------------------------------------------------
07. ASCII FRAME SYSTEM
---------------------------------------------------------------- */
/* Outer frame — double-line border, for major page sections */
.lt-frame {
position: relative;
border: 3px double var(--terminal-green);
background: var(--bg-primary);
margin-bottom: var(--space-xl);
animation: boot-up 0.8s ease-out;
}
.lt-frame::before {
content: '╔';
position: absolute;
top: -5px; left: -5px;
font-size: 1.3rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
animation: corner-pulse 3s ease-in-out infinite;
line-height: 1;
}
.lt-frame::after {
content: '╗';
position: absolute;
top: -5px; right: -5px;
font-size: 1.3rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
animation: corner-pulse 3s ease-in-out infinite;
line-height: 1;
}
/* Bottom corners require explicit child elements:
<span class="lt-frame-bl">╚</span>
<span class="lt-frame-br">╝</span> */
.lt-frame-bl,
.lt-frame-br {
position: absolute;
bottom: -5px;
font-size: 1.3rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
line-height: 1;
}
.lt-frame-bl { left: -5px; }
.lt-frame-br { right: -5px; }
/* Inner frame — single-line, for sub-panels inside a .lt-frame */
.lt-frame-inner {
position: relative;
border: 2px solid var(--terminal-green);
background: var(--bg-secondary);
padding: var(--space-md);
margin: var(--space-md);
}
.lt-frame-inner::before {
content: '┌';
position: absolute;
top: -3px; left: -3px;
color: var(--terminal-green);
line-height: 1;
}
.lt-frame-inner::after {
content: '┐';
position: absolute;
top: -3px; right: -3px;
color: var(--terminal-green);
line-height: 1;
}
/* Section header — full-width amber title bar inside a frame */
.lt-section-header {
padding: 0.75rem 1.5rem;
background: var(--bg-primary);
border-bottom: 2px solid var(--terminal-green);
font-weight: bold;
font-size: 0.9rem;
color: var(--terminal-amber);
text-shadow: var(--glow-amber-intense);
text-transform: uppercase;
letter-spacing: 0.1em;
animation: subtle-pulse 3s ease-in-out infinite;
}
.lt-section-header::before {
content: '╠═══ ';
color: var(--terminal-green);
text-shadow: var(--glow-green);
}
.lt-section-header::after {
content: ' ═══╣';
color: var(--terminal-green);
text-shadow: var(--glow-green);
}
/* Subsection header */
.lt-subsection-header {
padding: 0.5rem var(--space-md);
background: var(--bg-secondary);
border-bottom: 1px solid var(--terminal-green);
font-weight: bold;
font-size: 0.85rem;
color: var(--terminal-green);
text-transform: uppercase;
letter-spacing: 0.07em;
}
.lt-subsection-header::before { content: '├─── '; }
.lt-subsection-header::after { content: ' ───┤'; }
/* Horizontal divider with ASCII end-caps */
.lt-divider {
height: 1px;
background: var(--border-color);
margin: var(--space-lg) 0;
position: relative;
}
.lt-divider::before {
content: '╞═══';
position: absolute;
left: -2px; top: -10px;
font-size: 0.7rem;
color: var(--text-muted);
line-height: 1;
}
.lt-divider::after {
content: '═══╡';
position: absolute;
right: -2px; top: -10px;
font-size: 0.7rem;
color: var(--text-muted);
line-height: 1;
}
/* Content body inside a frame / section */
.lt-section-body { padding: var(--space-md) var(--space-lg); }
/* ----------------------------------------------------------------
08. CARD COMPONENT
---------------------------------------------------------------- */
.lt-card {
position: relative;
background: var(--bg-secondary);
border: 2px solid var(--border-color);
padding: var(--space-lg);
transition: var(--transition-default);
}
.lt-card::before {
content: '┌';
position: absolute;
top: -3px; left: -3px;
color: var(--terminal-green);
line-height: 1;
}
.lt-card::after {
content: '┐';
position: absolute;
top: -3px; right: -3px;
color: var(--terminal-green);
line-height: 1;
}
.lt-card:hover {
border-color: var(--terminal-green);
}
.lt-card-title {
font-size: 0.95rem;
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: var(--space-md);
padding-bottom: var(--space-sm);
border-bottom: 1px solid var(--border-color);
}
.lt-card-title::before { content: '═══ '; color: var(--terminal-green); }
.lt-card-title::after { content: ' ═══'; color: var(--terminal-green); }
/* Card grid wrappers */
.lt-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--space-md); }
.lt-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-md); }
.lt-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-md); }
.lt-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-md); }
/* ----------------------------------------------------------------
09. BUTTONS
---------------------------------------------------------------- */
.lt-btn {
display: inline-flex;
align-items: center;
background: transparent;
color: var(--terminal-green);
border: 2px solid var(--terminal-green);
border-radius: 0; /* NO rounded corners — terminal style */
padding: 10px 20px;
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.9rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.05em;
text-decoration: none;
transition: var(--transition-default);
white-space: nowrap;
user-select: none;
}
.lt-btn::before { content: '[ '; flex-shrink: 0; }
.lt-btn::after { content: ' ]'; flex-shrink: 0; }
.lt-btn:hover {
background: var(--terminal-green-dim);
color: var(--terminal-amber);
border-color: var(--terminal-amber);
}
.lt-btn:active {
opacity: 0.85;
}
.lt-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
/* Amber (primary call-to-action) */
.lt-btn-primary {
color: var(--terminal-amber);
border-color: var(--terminal-amber);
text-shadow: var(--glow-amber);
}
.lt-btn-primary::before { content: '> '; }
.lt-btn-primary:hover {
background: var(--terminal-amber-dim);
}
/* Red (destructive / danger) */
.lt-btn-danger {
color: var(--terminal-red);
border-color: var(--terminal-red);
}
.lt-btn-danger:hover {
background: var(--terminal-red-dim);
color: var(--terminal-red);
border-color: var(--terminal-red);
}
/* Small variant */
.lt-btn-sm { padding: 5px 10px; font-size: 0.75rem; border-width: 1px; }
/* Ghost (border only, no fill on hover either) */
.lt-btn-ghost { border-color: var(--border-color); color: var(--text-muted); }
/* Button group */
.lt-btn-group { display: flex; gap: var(--space-sm); flex-wrap: wrap; align-items: center; }
/* ----------------------------------------------------------------
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.75rem;
font-weight: bold;
color: var(--terminal-amber);
text-transform: uppercase;
letter-spacing: 0.07em;
text-shadow: var(--glow-amber);
}
.lt-label-required::after { content: ' *'; color: var(--terminal-red); }
.lt-input,
.lt-textarea,
.lt-select {
font-family: var(--font-mono);
font-size: 0.9rem;
background: var(--bg-primary);
color: var(--terminal-green);
border: 2px solid var(--terminal-green);
border-radius: 0;
padding: 10px var(--space-md);
width: 100%;
transition: var(--transition-fast);
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.5);
}
.lt-input:focus,
.lt-textarea:focus,
.lt-select:focus {
outline: none;
border-color: var(--terminal-amber);
box-shadow: var(--glow-amber), inset 0 0 10px rgba(0, 0, 0, 0.5);
background: rgba(0, 255, 65, 0.03);
animation: focus-pulse 2s ease-in-out infinite;
}
.lt-input::placeholder,
.lt-textarea::placeholder { color: var(--text-muted); opacity: 0.7; }
.lt-textarea { min-height: 100px; resize: vertical; }
.lt-select option {
background: var(--bg-secondary);
color: var(--terminal-green);
}
/* Checkbox */
.lt-checkbox {
appearance: none;
width: 18px; height: 18px;
border: 2px solid var(--terminal-green);
background: var(--bg-primary);
cursor: pointer;
border-radius: 0;
flex-shrink: 0;
transition: var(--transition-fast);
}
.lt-checkbox:checked {
background: var(--terminal-green-dim);
border-color: var(--terminal-amber);
}
.lt-checkbox:checked::before {
content: '✓';
display: flex;
align-items: center;
justify-content: center;
width: 100%; height: 100%;
color: var(--terminal-amber);
font-size: 0.8rem;
line-height: 1;
}
/* Search input with prompt prefix */
.lt-search { position: relative; }
.lt-search-input { padding-left: 2.2rem; }
.lt-search::before {
content: '>';
position: absolute;
left: 10px;
top: 50%; transform: translateY(-50%);
color: var(--terminal-amber);
font-weight: bold;
pointer-events: none;
z-index: 1;
}
/* Form hint */
.lt-form-hint {
font-size: 0.7rem;
color: var(--text-muted);
margin-top: var(--space-xs);
}
/* Toolbar row */
.lt-toolbar {
display: flex;
align-items: center;
gap: var(--space-md);
flex-wrap: wrap;
margin-bottom: var(--space-md);
justify-content: space-between;
}
.lt-toolbar-left,
.lt-toolbar-right { display: flex; align-items: center; gap: var(--space-sm); }
/* ----------------------------------------------------------------
11. TABLES
---------------------------------------------------------------- */
/* Standard table — full-grid borders, good for simple data */
.lt-table {
width: 100%;
border-collapse: collapse;
font-family: var(--font-mono);
background: var(--bg-secondary);
border: 2px solid var(--terminal-green);
}
.lt-table th {
background: var(--bg-primary);
padding: 10px 14px;
font-size: 0.8rem;
font-weight: bold;
color: var(--terminal-amber);
text-transform: uppercase;
letter-spacing: 0.1em;
text-shadow: var(--glow-amber);
border: 1px solid var(--border-color);
border-bottom: 2px solid var(--terminal-green);
white-space: nowrap;
}
.lt-table th::before { content: '> '; color: var(--terminal-green); }
.lt-table th:has(input[type="checkbox"])::before { content: none; }
.lt-table td {
padding: 10px 14px;
font-size: 0.88rem;
color: var(--text-primary);
border: 1px solid var(--border-color-dim);
word-break: break-word;
}
.lt-table tbody tr:hover {
background: rgba(0, 255, 65, 0.06);
}
/* Data table — compact, row-only separators, good for dense data */
.lt-data-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); }
.lt-data-table th {
padding: 8px 12px;
font-size: 0.72rem;
font-weight: bold;
color: var(--terminal-amber);
text-transform: uppercase;
letter-spacing: 0.08em;
text-shadow: var(--glow-amber);
background: var(--bg-tertiary);
border-bottom: 1px solid var(--border-color);
}
.lt-data-table th::before { content: '> '; color: var(--terminal-green); }
.lt-data-table td {
padding: 7px 12px;
font-size: 0.85rem;
border-bottom: 1px solid rgba(0, 255, 65, 0.08);
}
.lt-data-table tbody tr:hover { background: rgba(0, 255, 65, 0.05); }
/* Priority left-border accent (apply to <tr>) */
.lt-table tbody tr td:first-child,
.lt-data-table tbody tr td:first-child { border-left: 4px solid transparent; }
.lt-row-p1 td:first-child { border-left-color: var(--priority-1) !important; }
.lt-row-p2 td:first-child { border-left-color: var(--priority-2) !important; }
.lt-row-p3 td:first-child { border-left-color: var(--priority-3) !important; }
.lt-row-p4 td:first-child { border-left-color: var(--priority-4) !important; }
.lt-row-p5 td:first-child { border-left-color: var(--priority-5) !important; }
/* Row state tints */
.lt-row-critical td { background: rgba(255, 68, 68, 0.03); }
.lt-row-warning td { background: rgba(255, 140, 0, 0.03); }
.lt-row-success td { background: rgba(40, 167, 69, 0.03); }
/* Keyboard-selected row (vim-style navigation) */
.lt-row-selected {
background: rgba(0, 255, 65, 0.12) !important;
outline: 2px solid var(--terminal-green);
outline-offset: -2px;
}
/* Scrollable table wrapper */
.lt-table-wrap { overflow-x: auto; border: 2px solid var(--terminal-green); }
/* Sortable column header */
.lt-table th[data-sort] { cursor: pointer; }
.lt-table th[data-sort]:hover { color: var(--terminal-green); text-shadow: var(--glow-green); }
.lt-table th[data-sort="asc"]::after { content: ' ▲'; color: var(--terminal-green); }
.lt-table th[data-sort="desc"]::after { content: ' ▼'; color: var(--terminal-green); }
/* ----------------------------------------------------------------
12. STATUS BADGES, CHIPS, PRIORITY
---------------------------------------------------------------- */
/* Full status badge */
.lt-status {
display: inline-block;
padding: 4px 12px;
border: 2px solid;
font-family: var(--font-mono);
font-size: 0.82rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.04em;
white-space: nowrap;
}
.lt-status::before { content: '['; }
.lt-status::after { content: ']'; }
.lt-status-open { color: var(--status-open); border-color: var(--status-open); text-shadow: 0 0 5px var(--status-open), 0 0 10px var(--status-open); }
.lt-status-open::before { content: '[●'; }
.lt-status-pending { color: var(--status-pending); border-color: var(--status-pending); }
.lt-status-pending::before { content: '[○'; }
.lt-status-in-progress { color: var(--status-in-progress); border-color: var(--status-in-progress); }
.lt-status-in-progress::before { content: '[◐'; animation: spin-status 2s linear infinite; }
.lt-status-closed { color: var(--status-closed); border-color: var(--status-closed); }
.lt-status-closed::before { content: '[✓'; }
.lt-status-online { color: var(--status-online); border-color: var(--status-online); text-shadow: 0 0 5px var(--status-online); }
.lt-status-online::before { content: '[●'; }
.lt-status-offline { color: var(--status-offline); border-color: var(--status-offline); text-shadow: 0 0 5px var(--status-offline); animation: pulse-red 1.5s infinite; }
.lt-status-offline::before { content: '[○'; }
.lt-status-running { color: var(--status-running); border-color: var(--status-running); }
.lt-status-running::before { content: '[◐'; animation: spin-status 2s linear infinite; }
.lt-status-completed { color: var(--status-completed); border-color: var(--status-completed); }
.lt-status-completed::before { content: '[✓'; }
.lt-status-failed { color: var(--status-failed); border-color: var(--status-failed); text-shadow: 0 0 5px var(--status-failed); }
.lt-status-failed::before { content: '[✗'; }
/* Chip (small, compact status tag) */
.lt-chip {
display: inline-block;
padding: 2px 8px;
border: 1px solid;
font-size: 0.75rem;
font-weight: bold;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.lt-chip::before { content: '['; }
.lt-chip::after { content: ']'; }
.lt-chip-ok { color: var(--terminal-green); border-color: var(--terminal-green); text-shadow: var(--glow-green); }
.lt-chip-warn { color: var(--terminal-orange); border-color: var(--terminal-orange); }
.lt-chip-critical { color: var(--terminal-red); border-color: var(--terminal-red); text-shadow: var(--glow-red); animation: pulse-glow 2s infinite; }
.lt-chip-info { color: var(--terminal-cyan); border-color: var(--terminal-cyan); text-shadow: var(--glow-cyan); }
/* Badge (inline label, smallest) */
.lt-badge {
display: inline-block;
padding: 1px 6px;
border: 1px solid;
font-size: 0.7rem;
font-weight: bold;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.lt-badge::before { content: '['; }
.lt-badge::after { content: ']'; }
.lt-badge-green { color: var(--terminal-green); border-color: var(--terminal-green); }
.lt-badge-amber { color: var(--terminal-amber); border-color: var(--terminal-amber); }
.lt-badge-red { color: var(--terminal-red); border-color: var(--terminal-red); }
.lt-badge-cyan { color: var(--terminal-cyan); border-color: var(--terminal-cyan); }
.lt-badge-muted { color: var(--text-muted); border-color: var(--border-color); }
/* Priority badge */
.lt-priority {
display: inline-block;
padding: 3px 10px;
border: 1px solid;
font-size: 0.78rem;
font-weight: bold;
letter-spacing: 0.04em;
text-transform: uppercase;
white-space: nowrap;
}
.lt-priority::before { content: '['; }
.lt-priority::after { content: ']'; }
.lt-p1 { color: var(--priority-1); border-color: var(--priority-1); text-shadow: 0 0 5px var(--priority-1); animation: pulse-glow 2s infinite; }
.lt-p1::before { content: '[▲▲ P1 CRITICAL'; }
.lt-p2 { color: var(--priority-2); border-color: var(--priority-2); }
.lt-p2::before { content: '[▲ P2 HIGH'; }
.lt-p3 { color: var(--priority-3); border-color: var(--priority-3); }
.lt-p3::before { content: '[● P3 MED'; }
.lt-p4 { color: var(--priority-4); border-color: var(--priority-4); }
.lt-p4::before { content: '[▼ P4 LOW'; }
.lt-p5 { color: var(--priority-5); border-color: var(--priority-5); }
.lt-p5::before { content: '[▼▼ P5 MIN'; }
/* Inline status dot */
.lt-dot {
display: inline-block;
width: 8px; height: 8px;
border-radius: 50%;
border: 2px solid;
flex-shrink: 0;
}
.lt-dot-up { background: var(--terminal-green); border-color: var(--terminal-green); box-shadow: 0 0 4px var(--terminal-green); }
.lt-dot-down { background: var(--terminal-red); border-color: var(--terminal-red); animation: pulse-red 1.5s infinite; }
.lt-dot-warn { background: var(--terminal-orange); border-color: var(--terminal-orange); }
.lt-dot-idle { background: transparent; border-color: var(--text-muted); }
/* ----------------------------------------------------------------
13. MODALS
---------------------------------------------------------------- */
.lt-modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.88);
z-index: var(--z-modal-backdrop);
display: none;
align-items: center;
justify-content: center;
backdrop-filter: blur(2px);
}
.lt-modal-overlay.show { display: flex; }
.lt-modal {
position: relative;
background: var(--bg-secondary);
border: 3px double var(--terminal-green);
box-shadow: 0 0 30px rgba(0, 255, 65, 0.2), 0 8px 40px rgba(0, 0, 0, 0.8);
width: 560px;
max-width: 95vw;
max-height: 90vh;
overflow-y: auto;
animation: modal-slide-in 0.3s ease;
}
/* Double-line corner decorations */
.lt-modal::before {
content: '╔';
position: absolute;
top: -5px; left: -5px;
font-size: 1.2rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
line-height: 1;
}
.lt-modal::after {
content: '╗';
position: absolute;
top: -5px; right: -5px;
font-size: 1.2rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
line-height: 1;
}
.lt-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-md) var(--space-lg);
border-bottom: 2px solid var(--terminal-green);
background: var(--bg-primary);
}
.lt-modal-title {
font-size: 0.9rem;
font-weight: bold;
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.lt-modal-title::before { content: '>> '; color: var(--terminal-green); }
.lt-modal-close {
background: transparent;
border: 1px solid var(--border-color);
color: var(--text-muted);
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.85rem;
padding: 2px 8px;
transition: var(--transition-fast);
}
.lt-modal-close::before,
.lt-modal-close::after { content: ''; } /* Override global btn brackets */
.lt-modal-close:hover { color: var(--terminal-red); border-color: var(--terminal-red); text-shadow: var(--glow-red); transform: none; }
.lt-modal-body { padding: var(--space-lg); }
.lt-modal-footer {
display: flex;
gap: var(--space-sm);
justify-content: flex-end;
padding: var(--space-md) var(--space-lg);
border-top: 1px solid var(--border-color);
background: var(--bg-primary);
}
/* Wide variant */
.lt-modal-lg { width: 800px; }
/* ----------------------------------------------------------------
14. TOAST NOTIFICATIONS
---------------------------------------------------------------- */
.lt-toast-container {
position: fixed;
bottom: var(--space-lg);
right: var(--space-lg);
z-index: var(--z-toast);
display: flex;
flex-direction: column;
gap: var(--space-sm);
pointer-events: none;
}
.lt-toast {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: 10px 16px;
background: var(--bg-secondary);
border: 2px solid;
font-family: var(--font-mono);
font-size: 0.85rem;
font-weight: bold;
max-width: 420px;
pointer-events: all;
animation: slide-in-right 0.2s ease-out;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
}
.lt-toast::before { content: '>> '; flex-shrink: 0; }
.lt-toast-success { color: var(--terminal-green); border-color: var(--terminal-green); text-shadow: var(--glow-green); }
.lt-toast-error { color: var(--terminal-red); border-color: var(--terminal-red); text-shadow: var(--glow-red); }
.lt-toast-warning { color: var(--terminal-amber); border-color: var(--terminal-amber); text-shadow: var(--glow-amber); }
.lt-toast-info { color: var(--terminal-cyan); border-color: var(--terminal-cyan); text-shadow: var(--glow-cyan); }
.lt-toast-icon { font-size: 1rem; flex-shrink: 0; }
.lt-toast-msg { flex: 1; }
.lt-toast-close {
background: transparent; border: none;
color: inherit; cursor: pointer;
font-family: var(--font-mono);
opacity: 0.6; font-size: 0.85rem;
padding: 0 0 0 var(--space-sm);
}
.lt-toast-close::before,
.lt-toast-close::after { content: ''; }
.lt-toast-close:hover { opacity: 1; transform: none; }
/* ----------------------------------------------------------------
15. TAB NAVIGATION
---------------------------------------------------------------- */
.lt-tabs {
display: flex;
gap: var(--space-sm);
flex-wrap: wrap;
background: var(--bg-secondary);
border: 2px solid var(--border-color);
padding: var(--space-sm);
margin-bottom: var(--space-lg);
}
.lt-tab {
display: inline-flex;
align-items: center;
padding: 8px 18px;
background: transparent;
color: var(--text-muted);
border: 1px solid var(--border-color);
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.82rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: var(--transition-fast);
}
.lt-tab::before { content: '[ '; }
.lt-tab::after { content: ' ]'; }
.lt-tab:hover {
color: var(--terminal-green);
border-color: var(--border-color-hi);
background: var(--terminal-green-dim);
}
.lt-tab.active {
color: var(--terminal-amber);
border-color: var(--terminal-amber);
background: var(--terminal-amber-dim);
text-shadow: var(--glow-amber);
}
.lt-tab-panel { display: none; }
.lt-tab-panel.active { display: block; }
/* ----------------------------------------------------------------
16. SIDEBAR / FILTER PANEL
---------------------------------------------------------------- */
.lt-sidebar {
width: var(--sidebar-width);
background: var(--bg-secondary);
border: 2px solid var(--terminal-green);
flex-shrink: 0;
overflow-y: auto;
max-height: calc(100vh - var(--header-height) - 2rem);
position: sticky;
top: calc(var(--header-height) + var(--space-md));
}
.lt-sidebar-header {
padding: var(--space-sm) var(--space-md);
background: var(--bg-primary);
border-bottom: 1px solid var(--border-color);
font-size: 0.75rem;
font-weight: bold;
color: var(--terminal-amber);
text-transform: uppercase;
letter-spacing: 0.08em;
display: flex;
align-items: center;
justify-content: space-between;
}
.lt-sidebar-header::before { content: '╠═ '; color: var(--terminal-green); }
.lt-sidebar-body { padding: var(--space-md); }
.lt-filter-group { margin-bottom: var(--space-lg); }
.lt-filter-label {
display: block;
font-size: 0.75rem;
font-weight: bold;
color: var(--terminal-amber);
text-transform: uppercase;
letter-spacing: 0.07em;
margin-bottom: var(--space-sm);
padding-bottom: var(--space-xs);
border-bottom: 1px solid var(--border-color-dim);
}
.lt-filter-option {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-xs) 0;
cursor: pointer;
color: var(--text-primary);
font-size: 0.85rem;
transition: var(--transition-fast);
}
.lt-filter-option:hover { color: var(--terminal-amber); }
/* Collapse toggle */
.lt-sidebar.collapsed .lt-sidebar-body { display: none; }
.lt-sidebar-toggle {
background: transparent;
border: none;
color: var(--text-muted);
cursor: pointer;
font-family: var(--font-mono);
font-size: 0.8rem;
padding: 0;
}
.lt-sidebar-toggle::before,
.lt-sidebar-toggle::after { content: ''; }
/* ----------------------------------------------------------------
17. STATS WIDGETS
---------------------------------------------------------------- */
.lt-stats-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: var(--space-md);
margin-bottom: var(--space-lg);
}
.lt-stat-card {
background: var(--bg-secondary);
border: 2px solid var(--border-color);
padding: var(--space-md);
display: flex;
align-items: center;
gap: var(--space-md);
position: relative;
transition: var(--transition-default);
cursor: pointer;
}
.lt-stat-card::before {
content: '┌';
position: absolute;
top: -3px; left: -3px;
color: var(--terminal-green);
line-height: 1;
}
.lt-stat-card::after {
content: '┐';
position: absolute;
top: -3px; right: -3px;
color: var(--terminal-green);
line-height: 1;
}
.lt-stat-card:hover {
border-color: var(--terminal-amber);
}
.lt-stat-card.active {
background: var(--terminal-amber-dim);
border-color: var(--terminal-amber);
}
.lt-stat-icon { font-size: 1.8rem; }
.lt-stat-info { display: flex; flex-direction: column; gap: 2px; }
.lt-stat-value {
font-size: 1.6rem;
font-weight: bold;
color: var(--terminal-green);
text-shadow: 0 0 4px currentColor;
line-height: 1;
}
.lt-stat-label {
font-size: 0.68rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.07em;
}
/* ----------------------------------------------------------------
18. INLINE MESSAGES
---------------------------------------------------------------- */
.lt-msg {
padding: var(--space-md) var(--space-lg);
border: 2px solid;
font-family: var(--font-mono);
margin: var(--space-md) 0;
}
.lt-msg-error { color: var(--terminal-red); border-color: var(--terminal-red); background: var(--terminal-red-dim); }
.lt-msg-success { color: var(--status-open); border-color: var(--status-open); background: rgba(40, 167, 69, 0.08); }
.lt-msg-warning { color: var(--terminal-amber); border-color: var(--terminal-amber); background: var(--terminal-amber-dim); }
.lt-msg-info { color: var(--terminal-cyan); border-color: var(--terminal-cyan); background: var(--terminal-cyan-dim); }
.lt-msg-error::before { content: '[✗] ERROR: '; font-weight: bold; }
.lt-msg-success::before { content: '[✓] SUCCESS: '; font-weight: bold; }
.lt-msg-warning::before { content: '[!] WARNING: '; font-weight: bold; }
.lt-msg-info::before { content: '[i] INFO: '; font-weight: bold; }
/* ----------------------------------------------------------------
19. LOADING & EMPTY STATES
---------------------------------------------------------------- */
.lt-loading {
text-align: center;
padding: var(--space-xl);
color: var(--terminal-green);
}
.lt-loading::before { content: '[ LOADING'; display: block; margin-bottom: var(--space-sm); }
.lt-loading::after { content: '...'; animation: loading-dots 1.5s steps(4, end) infinite; }
.lt-empty {
text-align: center;
padding: var(--space-xl) var(--space-lg);
color: var(--text-muted);
}
.lt-empty::before {
content: '[ NO DATA ]';
display: block;
font-size: 1.1rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
margin-bottom: var(--space-sm);
}
/* Skeleton shimmer for async content */
.lt-skeleton {
background: linear-gradient(
90deg,
rgba(0, 255, 65, 0.04) 0%,
rgba(0, 255, 65, 0.10) 50%,
rgba(0, 255, 65, 0.04) 100%
);
background-size: 200% 100%;
animation: skeleton-shimmer 1.5s ease-in-out infinite;
border: 1px solid var(--border-color-dim);
color: transparent;
user-select: none;
}
/* ----------------------------------------------------------------
20. BOOT SEQUENCE OVERLAY
---------------------------------------------------------------- */
.lt-boot-overlay {
position: fixed;
inset: 0;
background: var(--bg-primary);
z-index: 99999;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.5s ease;
}
.lt-boot-overlay.fade-out { opacity: 0; pointer-events: none; }
.lt-boot-text {
font-family: var(--font-mono);
font-size: 0.9rem;
color: var(--terminal-green);
text-shadow: var(--glow-green);
line-height: 1.7;
white-space: pre;
padding: var(--space-xl);
}
/* ----------------------------------------------------------------
21. LOG / TIMELINE ENTRIES
---------------------------------------------------------------- */
.lt-log-entry {
padding: var(--space-md);
background: var(--bg-secondary);
border-left: 3px solid var(--terminal-green);
margin-bottom: var(--space-sm);
font-size: 0.88rem;
transition: var(--transition-fast);
}
.lt-log-entry::before { content: '> '; color: var(--terminal-amber); font-weight: bold; }
.lt-log-entry:hover { background: var(--terminal-green-dim); border-left-width: 5px; }
.lt-log-entry.error { border-left-color: var(--terminal-red); }
.lt-log-entry.warning { border-left-color: var(--terminal-amber); }
.lt-log-entry.success { border-left-color: var(--status-open); }
.lt-log-ts {
font-size: 0.78rem;
color: var(--terminal-amber);
margin-bottom: var(--space-xs);
}
.lt-log-output {
background: var(--bg-terminal);
border: 1px solid var(--border-color-dim);
padding: var(--space-sm);
margin-top: var(--space-sm);
max-height: 300px;
overflow-y: auto;
font-size: 0.82rem;
}
/* Timeline (vertical) */
.lt-timeline { position: relative; padding-left: var(--space-xl); }
.lt-timeline::before {
content: '';
position: absolute;
left: 8px; top: 0; bottom: 0;
width: 1px;
background: var(--border-color);
}
.lt-timeline-item {
position: relative;
margin-bottom: var(--space-md);
}
.lt-timeline-item::before {
content: '●';
position: absolute;
left: calc(-1 * var(--space-xl) + 2px);
color: var(--terminal-green);
font-size: 0.6rem;
top: 0.4rem;
}
/* ----------------------------------------------------------------
22. ANIMATIONS
---------------------------------------------------------------- */
@keyframes scanline {
0% { transform: translateY(0); }
100% { transform: translateY(4px); }
}
@keyframes flicker {
0% { opacity: 1; }
10% { opacity: 0.95; }
20% { opacity: 1; }
30% { opacity: 0.97; }
40% { opacity: 1; }
}
@keyframes data-stream {
0% { content: '10101010'; opacity: 0.07; }
25% { content: '01010101'; opacity: 0.10; }
50% { content: '11001100'; opacity: 0.07; }
75% { content: '00110011'; opacity: 0.10; }
100% { content: '10101010'; opacity: 0.07; }
}
@keyframes boot-up {
0% { opacity: 0; filter: brightness(2) saturate(0); }
30% { opacity: 1; filter: brightness(1.5) saturate(0.5); }
100% { opacity: 1; filter: brightness(1) saturate(1); }
}
@keyframes modal-slide-in {
from { transform: translateY(-30px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes slide-in-right {
from { transform: translateX(30px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes corner-pulse {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
@keyframes subtle-pulse {
0%, 100% { opacity: 0.75; }
50% { opacity: 1; }
}
@keyframes pulse-glow {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
@keyframes pulse-red {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
@keyframes focus-pulse {
0%, 100% { box-shadow: var(--glow-amber), inset 0 0 10px rgba(0, 0, 0, 0.5); }
50% { box-shadow: var(--glow-amber-intense), inset 0 0 10px rgba(0, 0, 0, 0.5); }
}
@keyframes spin-status {
0% { content: '[◐'; }
25% { content: '[◓'; }
50% { content: '[◑'; }
75% { content: '[◒'; }
100% { content: '[◐'; }
}
@keyframes spin-full {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes loading-dots {
0%, 20% { content: '.'; }
40% { content: '..'; }
60%, 100% { content: '...'; }
}
@keyframes skeleton-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
@keyframes cursor-blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
/* Item pulse for actively running tasks */
@keyframes exec-running-pulse {
0%, 100% { border-color: var(--terminal-green); opacity: 0.7; }
50% { border-color: var(--status-running); opacity: 1; }
}
.lt-item-running { animation: exec-running-pulse 2s ease-in-out infinite; }
/* ----------------------------------------------------------------
23. RESPONSIVE DESIGN
---------------------------------------------------------------- */
@media (max-width: 1400px) {
.lt-grid-4 { grid-template-columns: repeat(3, 1fr); }
.lt-stats-grid { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 1200px) {
.lt-sidebar { width: var(--sidebar-width-sm); }
.lt-grid-4, .lt-grid-3 { grid-template-columns: repeat(2, 1fr); }
.lt-stats-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 1024px) {
.lt-layout { flex-direction: column; }
.lt-sidebar { width: 100%; max-height: none; position: static; }
.lt-stats-grid { grid-template-columns: repeat(2, 1fr); }
.lt-grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
:root { --header-height: 50px; }
.lt-header { padding: 0 var(--space-md); }
.lt-nav { display: none; } /* Replace with hamburger menu on mobile */
.lt-brand-subtitle { display: none; }
.lt-main { padding: var(--space-md); }
.lt-grid-2 { grid-template-columns: 1fr; }
.lt-stats-grid { grid-template-columns: repeat(2, 1fr); }
.lt-modal { width: 100%; max-width: none; margin: var(--space-md); }
.lt-table { font-size: 0.8rem; }
.lt-table th, .lt-table td { padding: 8px; }
}
@media (max-width: 480px) {
.lt-main { padding: var(--space-sm); }
.lt-stats-grid { grid-template-columns: 1fr 1fr; }
.lt-btn { padding: 8px 14px; font-size: 0.8rem; }
.lt-toast-container { left: var(--space-sm); right: var(--space-sm); bottom: var(--space-sm); }
.lt-toast { max-width: none; }
}
/* ----------------------------------------------------------------
24. UTILITY CLASSES
---------------------------------------------------------------- */
.lt-text-green { color: var(--terminal-green) !important; text-shadow: var(--glow-green); }
.lt-text-amber { color: var(--terminal-amber) !important; text-shadow: var(--glow-amber); }
.lt-text-red { color: var(--terminal-red) !important; }
.lt-text-cyan { color: var(--terminal-cyan) !important; }
.lt-text-muted { color: var(--text-muted) !important; }
.lt-text-mono { font-family: var(--font-mono) !important; }
.lt-text-upper { text-transform: uppercase; letter-spacing: 0.06em; }
.lt-text-sm { font-size: 0.8rem; }
.lt-text-xs { font-size: 0.7rem; }
.lt-no-wrap { white-space: nowrap; }
.lt-flex { display: flex; align-items: center; }
.lt-flex-between { display: flex; align-items: center; justify-content: space-between; }
.lt-flex-wrap { flex-wrap: wrap; }
.lt-gap-xs { gap: var(--space-xs); }
.lt-gap-sm { gap: var(--space-sm); }
.lt-gap-md { gap: var(--space-md); }
.lt-mt-sm { margin-top: var(--space-sm); }
.lt-mt-md { margin-top: var(--space-md); }
.lt-mb-md { margin-bottom: var(--space-md); }
.lt-mb-lg { margin-bottom: var(--space-lg); }
.lt-p-md { padding: var(--space-md); }
/* Screen reader only */
.lt-sr-only {
position: absolute; width: 1px; height: 1px;
padding: 0; margin: -1px; overflow: hidden;
clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
/* ----------------------------------------------------------------
25. PRINT STYLES
---------------------------------------------------------------- */
@media print {
body::before, body::after { display: none; }
.lt-header, .lt-sidebar, .lt-tabs,
.lt-modal-overlay, .lt-toast-container { display: none !important; }
.lt-main { padding: 0; }
body { background: white; color: black; animation: none; }
.lt-card, .lt-frame { border: 1px solid #333; box-shadow: none; }
a { color: black; }
}
/* ----------------------------------------------------------------
26. ACCESSIBILITY
---------------------------------------------------------------- */
:focus-visible {
outline: 2px solid var(--terminal-amber);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
body::before { animation: none; }
body { animation: none; }
}