style(dashboard): replace remaining hardcoded colors with design tokens
Continued CSS tokenization pass across ambient, fleet, live, simple, integrations pages and their component stylesheets. Replaces hardcoded `white`, `#1a1a2e`, and raw rgba values with semantic tokens from tokens.css. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
55675943ce
commit
dd2fdd789c
13 changed files with 334 additions and 306 deletions
|
|
@ -9,7 +9,7 @@
|
|||
<link rel="stylesheet" href="css/ambient.css">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="theme-color" content="#1a1a2e">
|
||||
<meta name="theme-color" content="#18191b">
|
||||
</head>
|
||||
<body class="ambient-mode">
|
||||
<div class="app-shell app-shell--full">
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
padding: 16px 24px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.ap-detection-icon {
|
||||
|
|
@ -161,7 +161,7 @@
|
|||
}
|
||||
|
||||
.ap-btn-primary {
|
||||
background: white;
|
||||
background: var(--slate-12);
|
||||
color: var(--blue-7);
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +173,7 @@
|
|||
|
||||
.ap-btn-secondary {
|
||||
background: var(--border-strong);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
border: 1px solid var(--slate-7);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@
|
|||
|
||||
.contributing-yes .contributing-badge {
|
||||
background: var(--ok);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.contributing-no .contributing-badge {
|
||||
|
|
|
|||
|
|
@ -849,7 +849,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(135deg, var(--alert), var(--alert-muted));
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 16px 20px;
|
||||
z-index: 5000;
|
||||
display: flex;
|
||||
|
|
@ -915,7 +915,7 @@
|
|||
|
||||
.alert-banner-btn-acknowledge {
|
||||
background: var(--border-strong);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.alert-banner-btn-acknowledge:hover {
|
||||
|
|
@ -923,7 +923,7 @@
|
|||
}
|
||||
|
||||
.alert-banner-btn-view {
|
||||
background: white;
|
||||
background: var(--slate-12);
|
||||
color: var(--alert);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@
|
|||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--blue-10);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 10px 20px;
|
||||
border-radius: var(--radius-modal);
|
||||
font-size: var(--text-sm);
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(135deg, var(--alert), var(--alert));
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 16px 20px;
|
||||
z-index: 5000;
|
||||
display: flex;
|
||||
|
|
@ -369,7 +369,7 @@
|
|||
|
||||
.alert-banner-btn.acknowledge {
|
||||
background: var(--border-strong);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.alert-banner-btn.acknowledge:hover {
|
||||
|
|
@ -377,12 +377,12 @@
|
|||
}
|
||||
|
||||
.alert-banner-btn.view {
|
||||
background: white;
|
||||
background: var(--slate-12);
|
||||
color: var(--alert);
|
||||
}
|
||||
|
||||
.alert-banner-btn.view:hover {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: var(--slate-12);
|
||||
}
|
||||
|
||||
/* ── Security Mode Indicator (full page overlay when armed) ──────────────────────── */
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ body.simple-mode {
|
|||
/* ===== Alert Banner ===== */
|
||||
.simple-alert-banner {
|
||||
background: linear-gradient(135deg, var(--simple-accent-red), var(--alert));
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 16px;
|
||||
border-radius: var(--radius-card);
|
||||
margin-bottom: 16px;
|
||||
|
|
@ -154,7 +154,7 @@ body.simple-mode {
|
|||
.simple-alert-banner .alert-dismiss {
|
||||
background: var(--border-strong);
|
||||
border: none;
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
|
|
@ -173,7 +173,7 @@ body.simple-mode {
|
|||
/* ===== Morning Briefing Card ===== */
|
||||
.simple-morning-briefing {
|
||||
background: linear-gradient(135deg, var(--blue-7), var(--blue-9));
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 20px;
|
||||
border-radius: var(--radius-modal);
|
||||
margin-bottom: 16px;
|
||||
|
|
@ -252,7 +252,7 @@ body.simple-mode {
|
|||
margin-top: 8px;
|
||||
background: var(--border-strong);
|
||||
border: none;
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 8px 16px;
|
||||
border-radius: var(--radius-card);
|
||||
font-size: var(--text-sm);
|
||||
|
|
@ -386,7 +386,7 @@ body.simple-mode {
|
|||
justify-content: center;
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.simple-room-card .room-activity {
|
||||
|
|
@ -450,7 +450,7 @@ body.simple-mode {
|
|||
|
||||
.simple-activity-feed .filter-btn.active {
|
||||
background: var(--simple-accent-blue);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.simple-activity-feed .feed-empty {
|
||||
|
|
@ -629,7 +629,7 @@ body.simple-mode {
|
|||
top: 4px;
|
||||
right: 4px;
|
||||
background: var(--simple-accent-red);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
padding: 2px 6px;
|
||||
|
|
@ -641,7 +641,7 @@ body.simple-mode {
|
|||
/* ===== Sleep Summary Card ===== */
|
||||
.simple-sleep-summary {
|
||||
background: linear-gradient(135deg, var(--blue-10), var(--blue-8));
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 20px;
|
||||
border-radius: var(--radius-modal);
|
||||
margin-bottom: 16px;
|
||||
|
|
@ -723,7 +723,7 @@ body.simple-mode {
|
|||
margin-top: 12px;
|
||||
background: var(--border-strong);
|
||||
border: none;
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
padding: 10px 16px;
|
||||
border-radius: var(--radius-card);
|
||||
font-size: var(--text-sm);
|
||||
|
|
@ -922,12 +922,12 @@ body.simple-mode {
|
|||
|
||||
.simple-security-toggle .security-toggle-btn.disarmed {
|
||||
background: var(--simple-accent-green);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.simple-security-toggle .security-toggle-btn.armed {
|
||||
background: var(--simple-accent-red);
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.simple-security-toggle .security-status {
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@
|
|||
/* Event Count Badge */
|
||||
.timeline-count {
|
||||
background: var(--accent-color, var(--blue-9));
|
||||
color: white;
|
||||
color: var(--text-on-accent);
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 2px 6px;
|
||||
|
|
|
|||
|
|
@ -35,78 +35,77 @@
|
|||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Page Header -->
|
||||
<header class="fleet-header">
|
||||
<div class="header-content">
|
||||
<h1>Fleet Status</h1>
|
||||
<div class="fleet-summary">
|
||||
<span class="summary-item">
|
||||
<span class="summary-label">Total:</span>
|
||||
<span class="summary-value" id="fleet-total">0</span>
|
||||
</span>
|
||||
<span class="summary-item">
|
||||
<span class="summary-label">Online:</span>
|
||||
<span class="summary-value online" id="fleet-online">0</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button id="fleet-refresh-btn" class="btn btn-secondary" title="Refresh fleet data">
|
||||
<span class="icon">↻</span>
|
||||
<span class="label">Refresh</span>
|
||||
</button>
|
||||
<button id="fleet-update-all-btn" class="btn btn-action" title="Update all nodes to latest firmware">
|
||||
<span class="icon">↑</span>
|
||||
<span class="label">Update All</span>
|
||||
</button>
|
||||
<button id="fleet-download-btn" class="btn btn-secondary" title="Download CSV report">
|
||||
<span class="icon">↓</span>
|
||||
<span class="label">Download Report</span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Filter and Sort Bar -->
|
||||
<div class="fleet-toolbar" id="fleet-toolbar" style="display: none;">
|
||||
<div class="toolbar-section">
|
||||
<div class="filter-group">
|
||||
<input type="text" id="fleet-search" class="search-input" placeholder="Search by label or MAC...">
|
||||
<select id="filter-status" class="filter-select">
|
||||
<option value="">All Status</option>
|
||||
<option value="online">Online</option>
|
||||
<option value="offline">Offline</option>
|
||||
<option value="updating">Updating</option>
|
||||
</select>
|
||||
<select id="filter-firmware" class="filter-select">
|
||||
<option value="">All Firmware</option>
|
||||
<option value="outdated">Outdated Only</option>
|
||||
</select>
|
||||
<select id="filter-role" class="filter-select" multiple>
|
||||
<option value="tx">TX</option>
|
||||
<option value="rx">RX</option>
|
||||
<option value="tx_rx">TX-RX</option>
|
||||
<option value="passive">Passive</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="active-filters" id="active-filters"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bulk Actions Bar (shown when nodes are selected) -->
|
||||
<div class="bulk-actions-bar" id="bulk-actions-bar" style="display: none;">
|
||||
<div class="bulk-content">
|
||||
<span class="bulk-count"><span id="bulk-selected-count">0</span> nodes selected</span>
|
||||
<div class="bulk-buttons">
|
||||
<button id="bulk-ota-btn" class="btn btn-action">Update Selected</button>
|
||||
<button id="bulk-role-btn" class="btn btn-secondary">Re-assign Roles</button>
|
||||
<button id="bulk-remove-btn" class="btn btn-danger">Remove Selected</button>
|
||||
<button id="bulk-clear-btn" class="btn btn-link">Clear Selection</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fleet Table -->
|
||||
<main class="app-main fleet-main">
|
||||
<header class="fleet-header">
|
||||
<div class="header-content">
|
||||
<h1>Fleet Status</h1>
|
||||
<div class="fleet-summary">
|
||||
<span class="summary-item">
|
||||
<span class="summary-label">Total:</span>
|
||||
<span class="summary-value" id="fleet-total">0</span>
|
||||
</span>
|
||||
<span class="summary-item">
|
||||
<span class="summary-label">Online:</span>
|
||||
<span class="summary-value online" id="fleet-online">0</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button id="fleet-refresh-btn" class="btn btn-secondary" title="Refresh fleet data">
|
||||
<span class="icon">↻</span>
|
||||
<span class="label">Refresh</span>
|
||||
</button>
|
||||
<button id="fleet-update-all-btn" class="btn btn-action" title="Update all nodes to latest firmware">
|
||||
<span class="icon">↑</span>
|
||||
<span class="label">Update All</span>
|
||||
</button>
|
||||
<button id="fleet-download-btn" class="btn btn-secondary" title="Download CSV report">
|
||||
<span class="icon">↓</span>
|
||||
<span class="label">Download Report</span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Filter and Sort Bar -->
|
||||
<div class="fleet-toolbar" id="fleet-toolbar" style="display: none;">
|
||||
<div class="toolbar-section">
|
||||
<div class="filter-group">
|
||||
<input type="text" id="fleet-search" class="search-input" placeholder="Search by label or MAC...">
|
||||
<select id="filter-status" class="filter-select">
|
||||
<option value="">All Status</option>
|
||||
<option value="online">Online</option>
|
||||
<option value="offline">Offline</option>
|
||||
<option value="updating">Updating</option>
|
||||
</select>
|
||||
<select id="filter-firmware" class="filter-select">
|
||||
<option value="">All Firmware</option>
|
||||
<option value="outdated">Outdated Only</option>
|
||||
</select>
|
||||
<select id="filter-role" class="filter-select" multiple>
|
||||
<option value="tx">TX</option>
|
||||
<option value="rx">RX</option>
|
||||
<option value="tx_rx">TX-RX</option>
|
||||
<option value="passive">Passive</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="active-filters" id="active-filters"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bulk Actions Bar (shown when nodes are selected) -->
|
||||
<div class="bulk-actions-bar" id="bulk-actions-bar" style="display: none;">
|
||||
<div class="bulk-content">
|
||||
<span class="bulk-count"><span id="bulk-selected-count">0</span> nodes selected</span>
|
||||
<div class="bulk-buttons">
|
||||
<button id="bulk-ota-btn" class="btn btn-action">Update Selected</button>
|
||||
<button id="bulk-role-btn" class="btn btn-secondary">Re-assign Roles</button>
|
||||
<button id="bulk-remove-btn" class="btn btn-danger">Remove Selected</button>
|
||||
<button id="bulk-clear-btn" class="btn btn-link">Clear Selection</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-container">
|
||||
<table class="fleet-table" id="fleet-table">
|
||||
<thead>
|
||||
|
|
@ -164,7 +163,9 @@
|
|||
</div>
|
||||
</main>
|
||||
|
||||
<!-- OTA Confirmation Modal -->
|
||||
</div><!-- /.app-shell -->
|
||||
|
||||
<!-- Modals and toasts (outside grid shell) -->
|
||||
<div class="modal" id="ota-modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
|
@ -195,7 +196,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Role Assignment Modal -->
|
||||
<div class="modal" id="role-modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
|
@ -234,7 +234,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Remove Confirmation Modal -->
|
||||
<div class="modal" id="remove-modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
|
@ -253,11 +252,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notifications -->
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
|
||||
</div><!-- /.app-shell -->
|
||||
|
||||
<!-- Mobile bottom nav -->
|
||||
<nav class="app-mobile-nav" aria-label="Main navigation">
|
||||
<ul class="app-mobile-nav__list">
|
||||
|
|
|
|||
|
|
@ -384,18 +384,18 @@
|
|||
</div>
|
||||
</main>
|
||||
|
||||
<!-- ── Mobile bottom nav ── -->
|
||||
<nav class="app-mobile-nav">
|
||||
<ul class="app-mobile-nav__list">
|
||||
<li class="app-mobile-nav__item"><a href="/" class="app-mobile-nav__link">Home</a></li>
|
||||
<li class="app-mobile-nav__item"><a href="/live" class="app-mobile-nav__link">Live</a></li>
|
||||
<li class="app-mobile-nav__item"><a href="/fleet" class="app-mobile-nav__link">Fleet</a></li>
|
||||
<li class="app-mobile-nav__item"><a href="/integrations" class="app-mobile-nav__link app-mobile-nav__link--active">Integrations</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</div><!-- /.app-shell -->
|
||||
|
||||
<!-- ── Mobile bottom nav (outside grid) ── -->
|
||||
<nav class="app-mobile-nav">
|
||||
<ul class="app-mobile-nav__list">
|
||||
<li class="app-mobile-nav__item"><a href="/" class="app-mobile-nav__link">Home</a></li>
|
||||
<li class="app-mobile-nav__item"><a href="/live" class="app-mobile-nav__link">Live</a></li>
|
||||
<li class="app-mobile-nav__item"><a href="/fleet" class="app-mobile-nav__link">Fleet</a></li>
|
||||
<li class="app-mobile-nav__item"><a href="/integrations" class="app-mobile-nav__link app-mobile-nav__link--active">Integrations</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<script src="js/integrations.js"></script>
|
||||
<script>
|
||||
// Override the panel rendering for standalone page
|
||||
|
|
|
|||
|
|
@ -1352,70 +1352,102 @@
|
|||
// Seek Handler (Time-Travel)
|
||||
// ============================================
|
||||
function handleSeek(timestamp, entryElement) {
|
||||
// Convert timestamp to ISO8601
|
||||
const targetDate = new Date(timestamp);
|
||||
const iso8601 = targetDate.toISOString();
|
||||
if (state.dashboardMode !== 'expert') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a replay window around the event timestamp
|
||||
const windowMs = CONFIG.replaySeekWindowSec * 1000;
|
||||
const fromDate = new Date(timestamp - windowMs);
|
||||
const toDate = new Date(timestamp + windowMs);
|
||||
// Highlight selected event
|
||||
clearSelectedEvent();
|
||||
if (entryElement) {
|
||||
entryElement.classList.add('timeline-event-selected');
|
||||
state.replay.selectedEventId = entryElement.dataset.id;
|
||||
}
|
||||
|
||||
// Create replay session
|
||||
const startPayload = {
|
||||
from_iso8601: fromDate.toISOString(),
|
||||
to_iso8601: toDate.toISOString(),
|
||||
speed: 1
|
||||
// Use jump-to-time API for single-call replay session creation
|
||||
var payload = {
|
||||
timestamp_ms: timestamp,
|
||||
window_ms: CONFIG.replaySeekWindowSec * 1000
|
||||
};
|
||||
|
||||
fetch('/api/replay/start', {
|
||||
fetch('/api/replay/jump-to-time', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(startPayload)
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then(function(res) {
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to start replay session');
|
||||
throw new Error('Failed to jump to time');
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
const sessionId = data.session_id;
|
||||
state.replay.activeSessionId = data.session_id;
|
||||
state.replay.isReplaying = true;
|
||||
state.replay.replayTimestamp = timestamp;
|
||||
|
||||
// Seek to the specific timestamp
|
||||
return fetch('/api/replay/seek', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
session_id: sessionId,
|
||||
timestamp_iso8601: iso8601
|
||||
})
|
||||
});
|
||||
})
|
||||
.then(function(res) {
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to seek in replay');
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
// Navigate to replay mode
|
||||
// Show "Now replaying" chip
|
||||
showNowReplayingChip(timestamp);
|
||||
|
||||
// Navigate to replay mode if router available
|
||||
if (window.SpaxelRouter) {
|
||||
SpaxelRouter.navigate('replay');
|
||||
}
|
||||
|
||||
// Notify replay module about the jump
|
||||
if (window.SpaxelReplay && SpaxelReplay.onJumpToTime) {
|
||||
SpaxelReplay.onJumpToTime(data.session_id, timestamp);
|
||||
}
|
||||
|
||||
if (window.SpaxelApp && SpaxelApp.showToast) {
|
||||
SpaxelApp.showToast('Replay mode: viewing ' + formatTimestamp(timestamp), 'info');
|
||||
SpaxelApp.showToast('Viewing ' + formatTimestamp(timestamp), 'info');
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error('[Timeline] Replay seek failed:', err);
|
||||
console.error('[Timeline] Jump to time failed:', err);
|
||||
if (window.SpaxelApp && SpaxelApp.showToast) {
|
||||
SpaxelApp.showToast('Failed to jump to replay: ' + err.message, 'warning');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Selected Event Highlighting
|
||||
// ============================================
|
||||
function clearSelectedEvent() {
|
||||
if (elements.eventsList) {
|
||||
var prev = elements.eventsList.querySelector('.timeline-event-selected');
|
||||
if (prev) {
|
||||
prev.classList.remove('timeline-event-selected');
|
||||
}
|
||||
}
|
||||
state.replay.selectedEventId = null;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Now Replaying Chip
|
||||
// ============================================
|
||||
function showNowReplayingChip(timestampMs) {
|
||||
var chip = elements.nowReplayingChip;
|
||||
if (!chip) return;
|
||||
|
||||
var timeStr = formatTimestamp(timestampMs);
|
||||
chip.innerHTML = '<span class="now-replaying-dot"></span> Now replaying: ' + timeStr;
|
||||
chip.style.display = 'inline-flex';
|
||||
chip.classList.add('visible');
|
||||
}
|
||||
|
||||
function hideNowReplayingChip() {
|
||||
var chip = elements.nowReplayingChip;
|
||||
if (!chip) return;
|
||||
|
||||
chip.classList.remove('visible');
|
||||
chip.style.display = 'none';
|
||||
state.replay.isReplaying = false;
|
||||
state.replay.activeSessionId = null;
|
||||
state.replay.replayTimestamp = null;
|
||||
clearSelectedEvent();
|
||||
}
|
||||
|
||||
function updateFilterOptions(events) {
|
||||
// Extract unique values from events
|
||||
const types = new Set();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -17,7 +17,7 @@
|
|||
.wizard-close:hover{color:var(--text-primary)}
|
||||
#wizard-steps{display:flex;align-items:center;justify-content:center;margin-bottom:var(--space-6);gap:0}
|
||||
.wizard-step-dot{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:var(--fw-heading);background:var(--bg-active);color:var(--slate-7);transition:all .3s;flex-shrink:0}
|
||||
.wizard-step-dot.active{background:var(--color-primary);color:var(--text-on-accent);box-shadow:0 0 12px rgba(62,150,232,.5)}
|
||||
.wizard-step-dot.active{background:var(--color-primary);color:var(--text-on-accent);box-shadow:0 0 12px var(--blue-border)}
|
||||
.wizard-step-dot.completed{background:var(--ok);color:var(--text-on-accent)}
|
||||
.wizard-step-line{width:20px;height:2px;background:var(--bg-active);flex-shrink:0}
|
||||
.wizard-step-line.completed{background:var(--ok)}
|
||||
|
|
@ -48,12 +48,12 @@
|
|||
</style>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="theme-color" content="#f5f5f7">
|
||||
<meta name="theme-color" content="#18191b">
|
||||
</head>
|
||||
<body class="simple-mode has-mobile-nav">
|
||||
<div class="app-shell app-shell--full">
|
||||
<!-- Header (grid header area) -->
|
||||
<header id="simple-mode-header" class="simple-mode-header">
|
||||
<header id="simple-mode-header" class="simple-mode-header app-header">
|
||||
<h1>🏠 Spaxel</h1>
|
||||
<div class="mode-toggle">
|
||||
<button class="mode-toggle-btn active" data-mode="simple">Simple</button>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue