/* ===================================================================== PULSE — shell additions on top of /web_template/base.css --------------------------------------------------------------------- Rules here are Pulse-specific only. No `.lt-*` base rule is redefined; `.lt-*` selectors appear only as ancestors/descendants of a `.pulse-*` class, or as scoped layout tweaks inside the Pulse header cluster. Page-specific styles live in /assets/pages/.css. ===================================================================== */ /* --------------------------------------------------------------------- 1. Header right cluster — WS status, last-refreshed stamp, buttons --------------------------------------------------------------------- */ .pulse-header-right, .lt-header-right:has(#pulse-ws-status) { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: var(--space-sm); min-width: 0; row-gap: 2px; } #pulse-last-refreshed { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; color: var(--text-dim); white-space: nowrap; flex-shrink: 0; } /* The stamp is the first thing to go when space runs out. */ @media (max-width: 767px) { #pulse-last-refreshed { display: none; } } @media (max-width: 479px) { .pulse-header-right, .lt-header-right:has(#pulse-ws-status) { gap: var(--space-xs); } } /* --------------------------------------------------------------------- 2. Confirm / alert modal (built by Pulse.confirm / Pulse.alertModal) --------------------------------------------------------------------- */ .pulse-confirm .lt-modal-header { border-bottom: 1px solid var(--border-color); } .pulse-confirm .pulse-confirm-msg { margin: 0; font-size: 0.82rem; line-height: 1.55; color: var(--text-secondary); overflow-wrap: anywhere; } .pulse-confirm .lt-modal-footer { gap: var(--space-sm); } .pulse-confirm--warning .lt-modal { border-top: 2px solid var(--accent-amber); } .pulse-confirm--error .lt-modal { border-top: 2px solid var(--accent-red); } .pulse-confirm--info .lt-modal { border-top: 2px solid var(--accent-cyan); } /* --------------------------------------------------------------------- 3. Compact meta line (base.css already provides .lt-kv-grid for key/value blocks — use that; this is only for inline meta strings) --------------------------------------------------------------------- */ .pulse-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs) var(--space-md); font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-dim); } .pulse-meta > span { white-space: nowrap; } .pulse-meta-label { text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); } .pulse-meta-val { color: var(--text-secondary); } /* --------------------------------------------------------------------- 4. Log viewer wrapper — caps the height of a long .lt-log-output run --------------------------------------------------------------------- */ .pulse-log { max-height: 420px; overflow-y: auto; overflow-x: auto; background: var(--bg-terminal); border: 1px solid var(--border-dim); padding: var(--space-sm); } .pulse-log .lt-log-output { white-space: pre-wrap; overflow-wrap: anywhere; } .pulse-log--sm { max-height: 220px; } .pulse-log--lg { max-height: 60vh; } @media (max-width: 767px) { .pulse-log { max-height: 300px; } } /* --------------------------------------------------------------------- 5. Running rows — amber left-border pulse (port of exec-running-pulse) --------------------------------------------------------------------- */ .pulse-running { border-left: 2px solid var(--accent-amber); animation: pulse-running-border 2s ease-in-out infinite; } @keyframes pulse-running-border { 0%, 100% { border-left-color: var(--accent-green); box-shadow: none; } 50% { border-left-color: var(--accent-amber); box-shadow: -2px 0 8px rgba(255, 179, 0, 0.35); } } @media (prefers-reduced-motion: reduce) { .pulse-running { animation: none; border-left-color: var(--accent-amber); } } /* --------------------------------------------------------------------- 6. Utilities --------------------------------------------------------------------- */ .is-hidden { display: none !important; } .pulse-nowrap { white-space: nowrap; } .pulse-mono { font-family: var(--font-mono); } .pulse-dim { color: var(--text-dim); } .pulse-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; } /* --------------------------------------------------------------------- 7. Shared component gap-fillers (base.css does not ship these) --------------------------------------------------------------------- `.lt-modal-lg` — base.css ships .lt-modal-xs/.lt-modal-sm only, but several Pulse pages need a wide modal (JSON editors, log viewers, side-by-side compare). Sized the same way base.css sizes its own modifiers, and re-capped at the two breakpoints base.css caps `.lt-modal` at, because this selector is more specific than those. `.lt-field-error` / `.is-invalid` — base.css references a field-error hook but ships no visual style for it. Both are candidates for upstreaming into base.css. --------------------------------------------------------------------- */ .lt-modal.lt-modal-lg { width: min(900px, 95vw); max-width: 900px; } @media (max-width: 767px) { .lt-modal.lt-modal-lg { max-width: 96vw; } } @media (max-width: 479px) { .lt-modal.lt-modal-lg { max-width: 100vw; } } .lt-field-error { color: var(--accent-red); font-size: 0.72rem; letter-spacing: 0.02em; margin-top: 4px; } .lt-input.is-invalid, .lt-textarea.is-invalid, .lt-select.is-invalid { border-color: var(--accent-red); } /* --------------------------------------------------------------------- 8. Light theme overrides for the additions above --------------------------------------------------------------------- */ html[data-theme="light"] #pulse-last-refreshed { color: var(--text-muted); } html[data-theme="light"] .pulse-confirm .pulse-confirm-msg { color: var(--text-secondary); } html[data-theme="light"] .pulse-log { background: var(--bg-tertiary); border-color: var(--border-color); } html[data-theme="light"] .pulse-meta { color: var(--text-muted); } html[data-theme="light"] .pulse-meta-val { color: var(--text-primary); } html[data-theme="light"] .pulse-dim { color: var(--text-muted); } html[data-theme="light"] .pulse-running { box-shadow: none; }