@stephen-netu/design-system 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +66 -0
  2. package/package.json +130 -0
  3. package/src/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +221 -0
  4. package/src/b0-app-shell/clarification-overlay/index.ts +1 -0
  5. package/src/b0-app-shell/command-bar/CommandBar.svelte +565 -0
  6. package/src/b0-app-shell/index.ts +14 -0
  7. package/src/base.css +152 -0
  8. package/src/d0-data-viz/BarChart.svelte +236 -0
  9. package/src/d0-data-viz/CheckpointBar.svelte +574 -0
  10. package/src/d0-data-viz/CheckpointPill.svelte +297 -0
  11. package/src/d0-data-viz/MetricCard.svelte +159 -0
  12. package/src/d0-data-viz/SparkLine.svelte +66 -0
  13. package/src/d0-data-viz/StorageMap.svelte +182 -0
  14. package/src/d0-data-viz/Timeline.svelte +188 -0
  15. package/src/d0-data-viz/checkpoint-types.ts +162 -0
  16. package/src/d0-data-viz/d0-tokens.css +32 -0
  17. package/src/d0-data-viz/index.ts +58 -0
  18. package/src/d0-data-viz/storage-map-types.ts +142 -0
  19. package/src/d0-data-viz/theme-integration.ts +134 -0
  20. package/src/d0-data-viz/types.ts +53 -0
  21. package/src/demos/BspSizingInfographic.svelte +386 -0
  22. package/src/demos/BspZoneDemo.svelte +255 -0
  23. package/src/demos/ControlRoomDemo.svelte +570 -0
  24. package/src/demos/NodepadBlocksShowcase.svelte +189 -0
  25. package/src/demos/index.ts +7 -0
  26. package/src/editor/CodeEditor.svelte +188 -0
  27. package/src/editor/FindReplaceDialog.svelte +516 -0
  28. package/src/editor/MarkdownEditor.svelte +660 -0
  29. package/src/editor/index.ts +2 -0
  30. package/src/entity-graph-view/WorldView.svelte +171 -0
  31. package/src/entity-graph-view/index.ts +6 -0
  32. package/src/entity-graph-view/types.ts +364 -0
  33. package/src/epistemic/index.ts +2 -0
  34. package/src/epistemic/types.ts +134 -0
  35. package/src/epistemic/utils.ts +32 -0
  36. package/src/f0-forms/checkbox/Checkbox.svelte +158 -0
  37. package/src/f0-forms/field/FormField.svelte +91 -0
  38. package/src/f0-forms/index.ts +11 -0
  39. package/src/f0-forms/radio/RadioGroup.svelte +192 -0
  40. package/src/f0-forms/search/SearchBar.svelte +99 -0
  41. package/src/f0-forms/select/Select.svelte +198 -0
  42. package/src/f0-forms/textarea/TextArea.svelte +170 -0
  43. package/src/f0-forms/toggle/FormToggle.svelte +147 -0
  44. package/src/f0-forms/validation/validate.ts +47 -0
  45. package/src/fabric/ai/ChatPanel.svelte +648 -0
  46. package/src/fabric/ai/index.ts +11 -0
  47. package/src/fabric/data/index.ts +21 -0
  48. package/src/fabric/feedback/StatusBar.svelte +274 -0
  49. package/src/fabric/feedback/ToastContainer.svelte +122 -0
  50. package/src/fabric/feedback/index.ts +14 -0
  51. package/src/fabric/index.ts +37 -0
  52. package/src/fabric/input/CommandBar.svelte +79 -0
  53. package/src/fabric/input/KeyboardShortcuts.svelte +388 -0
  54. package/src/fabric/input/index.ts +12 -0
  55. package/src/fabric/layout/GlassBox.svelte +193 -0
  56. package/src/fabric/layout/KanbanBoard.svelte +158 -0
  57. package/src/fabric/layout/KanbanCard.svelte +226 -0
  58. package/src/fabric/layout/KanbanColumn.svelte +278 -0
  59. package/src/fabric/layout/index.ts +17 -0
  60. package/src/fabric/navigation/ActivityRail.svelte +271 -0
  61. package/src/fabric/navigation/index.ts +11 -0
  62. package/src/g0-geo/SovereignMap.svelte +149 -0
  63. package/src/g0-geo/index.ts +2 -0
  64. package/src/index.ts +68 -0
  65. package/src/l0-layout/block-writer/BlockConnectionLines.svelte +98 -0
  66. package/src/l0-layout/block-writer/BlockContent.svelte +213 -0
  67. package/src/l0-layout/block-writer/BlockHeader.svelte +230 -0
  68. package/src/l0-layout/block-writer/BlockItem.svelte +177 -0
  69. package/src/l0-layout/block-writer/BlockWriter.svelte +219 -0
  70. package/src/l0-layout/block-writer/block-writer-types.ts +63 -0
  71. package/src/l0-layout/block-writer/index.ts +24 -0
  72. package/src/l0-layout/block-writer/markdown.ts +110 -0
  73. package/src/l0-layout/chat-view/ChatViewLayout.svelte +61 -0
  74. package/src/l0-layout/epistemic/AllayDetailPanel.svelte +113 -0
  75. package/src/l0-layout/epistemic/AssayDetailPanel.svelte +164 -0
  76. package/src/l0-layout/epistemic/AvenueTrace.svelte +253 -0
  77. package/src/l0-layout/epistemic/KnowledgeDetailPanel.svelte +204 -0
  78. package/src/l0-layout/epistemic/ParadigmLens.svelte +170 -0
  79. package/src/l0-layout/epistemic/ProvenanceChain.svelte +164 -0
  80. package/src/l0-layout/epistemic/TrustView.svelte +195 -0
  81. package/src/l0-layout/epistemic/index.ts +7 -0
  82. package/src/l0-layout/grove/AccordCard.svelte +156 -0
  83. package/src/l0-layout/grove/GroveCard.svelte +197 -0
  84. package/src/l0-layout/grove/MemberBadge.svelte +96 -0
  85. package/src/l0-layout/grove/MemberList.svelte +59 -0
  86. package/src/l0-layout/grove/grove-types.ts +29 -0
  87. package/src/l0-layout/grove/index.ts +14 -0
  88. package/src/l0-layout/index.ts +45 -0
  89. package/src/l0-layout/kanban/KanbanBoard.svelte +71 -0
  90. package/src/l0-layout/kanban/KanbanCard.svelte +276 -0
  91. package/src/l0-layout/kanban/KanbanColumn.svelte +198 -0
  92. package/src/l0-layout/kanban/KanbanViewLayout.svelte +61 -0
  93. package/src/l0-layout/workspace/WorkspaceLayout.svelte +93 -0
  94. package/src/n0-node-graph/GraphEditor.svelte +342 -0
  95. package/src/n0-node-graph/GraphHistory.svelte +122 -0
  96. package/src/n0-node-graph/Node.svelte +269 -0
  97. package/src/n0-node-graph/NodeCanvas.svelte +187 -0
  98. package/src/n0-node-graph/NodeEdge.svelte +152 -0
  99. package/src/n0-node-graph/NodePalette.svelte +318 -0
  100. package/src/n0-node-graph/NodePort.svelte +128 -0
  101. package/src/n0-node-graph/index.ts +33 -0
  102. package/src/n0-node-graph/n0-tokens.css +29 -0
  103. package/src/n0-node-graph/node-port-types.ts +19 -0
  104. package/src/n0-node-graph/types.ts +96 -0
  105. package/src/n0-node-graph/validate.test.ts +722 -0
  106. package/src/n0-node-graph/validate.ts +371 -0
  107. package/src/n1-flow-canvas/FlowCanvas.svelte +202 -0
  108. package/src/n1-flow-canvas/graph-state.svelte.ts +95 -0
  109. package/src/n1-flow-canvas/index.ts +21 -0
  110. package/src/n1-flow-canvas/layout.ts +118 -0
  111. package/src/n1-flow-canvas/layout.worker.ts +128 -0
  112. package/src/n1-flow-canvas/types.ts +102 -0
  113. package/src/n1-flow-canvas/utils.ts +146 -0
  114. package/src/n2-manifold-disk/ManifoldDisk.svelte +314 -0
  115. package/src/n2-manifold-disk/index.ts +6 -0
  116. package/src/n2-manifold-disk/poincare.ts +184 -0
  117. package/src/n3-force-graph/ForceGraph.svelte +180 -0
  118. package/src/n3-force-graph/GraphTooltip.svelte +99 -0
  119. package/src/n3-force-graph/animated-edge.ts +107 -0
  120. package/src/n3-force-graph/health-node.ts +128 -0
  121. package/src/n3-force-graph/index.ts +31 -0
  122. package/src/n3-force-graph/types.ts +94 -0
  123. package/src/n4-adaptive-manifold/AdaptiveManifold.svelte +1165 -0
  124. package/src/n4-adaptive-manifold/DetailCard.svelte +212 -0
  125. package/src/n4-adaptive-manifold/SuggestionIndicator.svelte +91 -0
  126. package/src/n4-adaptive-manifold/classifier.ts +139 -0
  127. package/src/n4-adaptive-manifold/index.ts +45 -0
  128. package/src/n4-adaptive-manifold/n4-tokens.css +155 -0
  129. package/src/n4-adaptive-manifold/orchestrator.ts +301 -0
  130. package/src/n4-adaptive-manifold/phase-theme.ts +92 -0
  131. package/src/n4-adaptive-manifold/pinnacle-events.ts +135 -0
  132. package/src/n4-adaptive-manifold/providers/gravitational-provider.ts +191 -0
  133. package/src/n4-adaptive-manifold/providers/manifold-provider.ts +276 -0
  134. package/src/n4-adaptive-manifold/transition.ts +90 -0
  135. package/src/n4-adaptive-manifold/types.ts +313 -0
  136. package/src/p0-primitives/index.ts +6 -0
  137. package/src/p0-primitives/tokens/control-room.css +309 -0
  138. package/src/p0-primitives/tokens/index.ts +6 -0
  139. package/src/p0-primitives/tokens/tokens.css +140 -0
  140. package/src/p0-primitives/tokens/tokens.json +132 -0
  141. package/src/p0-primitives/types/index.ts +123 -0
  142. package/src/p0-primitives/types/plugin-types.ts +74 -0
  143. package/src/p0-primitives/utils/index.ts +39 -0
  144. package/src/platform/hud-protocol.ts +20 -0
  145. package/src/platform/index.ts +3 -0
  146. package/src/s0-state/create-store.ts +84 -0
  147. package/src/s0-state/derived.ts +41 -0
  148. package/src/s0-state/index.ts +6 -0
  149. package/src/showcase/Showcase.svelte +401 -0
  150. package/src/spatial/BspTilingCanvas.svelte +232 -0
  151. package/src/spatial/ForceCanvas.svelte +289 -0
  152. package/src/spatial/LodRenderer.svelte +334 -0
  153. package/src/spatial/SnapZoomCamera.svelte +185 -0
  154. package/src/spatial/ZoneTiler.svelte +311 -0
  155. package/src/spatial/camera-types.ts +45 -0
  156. package/src/spatial/content-proportional-bsp.ts +253 -0
  157. package/src/spatial/force-canvas-types.ts +102 -0
  158. package/src/spatial/index.ts +15 -0
  159. package/src/spatial/lod-types.ts +70 -0
  160. package/src/spatial/zone-tiler-types.ts +177 -0
  161. package/src/stores/vaultStore.svelte +14 -0
  162. package/src/t0-transport/connection.ts +34 -0
  163. package/src/t0-transport/error.ts +37 -0
  164. package/src/t0-transport/events.ts +50 -0
  165. package/src/t0-transport/index.ts +6 -0
  166. package/src/t0-transport/invoke.ts +30 -0
  167. package/src/tauri/index.ts +13 -0
  168. package/src/u0-primitives/allay-gauge/AllayGauge.svelte +90 -0
  169. package/src/u0-primitives/allay-gauge/index.ts +1 -0
  170. package/src/u0-primitives/animated-icon/AnimatedIcon.svelte +273 -0
  171. package/src/u0-primitives/animated-icon/README.md +53 -0
  172. package/src/u0-primitives/animated-icon/index.ts +31 -0
  173. package/src/u0-primitives/assay-badge/AssayBadge.svelte +121 -0
  174. package/src/u0-primitives/assay-badge/AssaySignalBar.svelte +83 -0
  175. package/src/u0-primitives/assay-badge/index.ts +2 -0
  176. package/src/u0-primitives/avatar/Avatar.svelte +177 -0
  177. package/src/u0-primitives/badge/Badge.svelte +149 -0
  178. package/src/u0-primitives/button/Button.svelte +304 -0
  179. package/src/u0-primitives/card/Card.svelte +182 -0
  180. package/src/u0-primitives/dropdown/Dropdown.svelte +305 -0
  181. package/src/u0-primitives/expert-badge/ExpertBadge.svelte +89 -0
  182. package/src/u0-primitives/expert-badge/index.ts +1 -0
  183. package/src/u0-primitives/index.ts +35 -0
  184. package/src/u0-primitives/input/Input.svelte +237 -0
  185. package/src/u0-primitives/modal/Modal.svelte +331 -0
  186. package/src/u0-primitives/modal/index.ts +1 -0
  187. package/src/u0-primitives/spinner/Spinner.svelte +129 -0
  188. package/src/u0-primitives/tabs/Tabs.svelte +225 -0
  189. package/src/u0-primitives/tabs/tabs-types.ts +11 -0
  190. package/src/u0-primitives/toggle/Toggle.svelte +161 -0
  191. package/src/u0-primitives/tooltip/Tooltip.svelte +234 -0
  192. package/src/v0-diagrams/DiagramPanel.svelte +68 -0
  193. package/src/v0-diagrams/MarkmapDiagram.svelte +56 -0
  194. package/src/v0-diagrams/MermaidDiagram.svelte +53 -0
  195. package/src/v0-diagrams/index.ts +4 -0
  196. package/src/v0-diagrams/types.ts +28 -0
  197. package/src/v0-diagrams/v0-tokens.css +6 -0
  198. package/src/vite-env.d.ts +7 -0
  199. package/src/x0-enchanted-blocks/ENCHANTED_BLOCKS_SPEC.md +457 -0
  200. package/src/x0-enchanted-blocks/components/EnchantedBlock.svelte +485 -0
  201. package/src/x0-enchanted-blocks/components/NodepadBlock.svelte +262 -0
  202. package/src/x0-enchanted-blocks/core/block-layout.ts +211 -0
  203. package/src/x0-enchanted-blocks/core/block-types.ts +227 -0
  204. package/src/x0-enchanted-blocks/index.ts +46 -0
@@ -0,0 +1,570 @@
1
+ <script lang="ts">
2
+ // Control Room Demo — Telemetry Panel Aesthetic
3
+ // Demonstrates the brutalist/Palantir design language
4
+
5
+ interface SystemMetric {
6
+ id: string;
7
+ label: string;
8
+ value: string;
9
+ unit: string;
10
+ status: 'nominal' | 'caution' | 'critical' | 'offline';
11
+ trend?: 'up' | 'down' | 'stable';
12
+ }
13
+
14
+ interface LogEntry {
15
+ timestamp: string;
16
+ level: 'INFO' | 'WARN' | 'ERR' | 'SYS';
17
+ message: string;
18
+ source: string;
19
+ }
20
+
21
+ let {
22
+ systemId = 'SOV-ALPHA-01',
23
+ uptime = '47:23:18'
24
+ }: {
25
+ systemId?: string;
26
+ uptime?: string;
27
+ } = $props();
28
+
29
+ let activeTab = $state<'metrics' | 'logs' | 'network'>('metrics');
30
+ let systemStatus = $state<'ONLINE' | 'DEGRADED' | 'OFFLINE'>('ONLINE');
31
+ let currentTime = $state('--:--:--');
32
+ let metrics = $state<SystemMetric[]>([
33
+ { id: 'cpu', label: 'CPU_LOAD', value: '34', unit: '%', status: 'nominal', trend: 'stable' },
34
+ { id: 'mem', label: 'MEM_ALLOC', value: '12.4', unit: 'GB', status: 'nominal', trend: 'up' },
35
+ { id: 'net', label: 'NET_IO', value: '847', unit: 'MB/s', status: 'caution', trend: 'up' },
36
+ { id: 'temp', label: 'CORE_TEMP', value: '67', unit: '°C', status: 'nominal', trend: 'stable' },
37
+ { id: 'pwr', label: 'PWR_DRAW', value: '234', unit: 'W', status: 'nominal', trend: 'down' },
38
+ { id: 'fan', label: 'FAN_RPM', value: '2847', unit: 'RPM', status: 'critical', trend: 'up' },
39
+ ]);
40
+
41
+ let logs = $state<LogEntry[]>([
42
+ { timestamp: '14:23:47.284', level: 'INFO', message: 'INFERENCE_CYCLE_COMPLETE', source: 'r4-inference' },
43
+ { timestamp: '14:23:45.912', level: 'SYS', message: 'SKILL_ROUTER_REBALANCE', source: 'c1-skill-router' },
44
+ { timestamp: '14:23:12.445', level: 'WARN', message: 'LATENCY_SPIKE_DETECTED', source: 'mcp-server' },
45
+ { timestamp: '14:22:58.001', level: 'ERR', message: 'CONNECTION_DROPPED_NODE_7', source: 'gossip' },
46
+ { timestamp: '14:22:45.338', level: 'INFO', message: 'SIGCHAIN_ANCHOR_WRITTEN', source: 'assay' },
47
+ ]);
48
+
49
+ // Fix #2: SSR-safe time updates via $effect
50
+ $effect(() => {
51
+ const updateTime = () => {
52
+ currentTime = new Date().toISOString().split('T')[1].split('.')[0];
53
+ };
54
+ updateTime();
55
+ const interval = setInterval(updateTime, 1000);
56
+ return () => clearInterval(interval);
57
+ });
58
+
59
+ // Fix #7: Live data simulation
60
+ $effect(() => {
61
+ const interval = setInterval(() => {
62
+ // Update metrics with simulated fluctuations
63
+ metrics = metrics.map((m: SystemMetric) => {
64
+ const val = parseFloat(m.value);
65
+ const noise = (Math.random() - 0.5) * val * 0.1;
66
+ const newVal = Math.max(0, val + noise).toFixed(m.id === 'cpu' || m.id === 'temp' ? 0 : 1);
67
+ return { ...m, value: newVal };
68
+ });
69
+
70
+ // Add occasional log entry
71
+ if (Math.random() > 0.7) {
72
+ const now = new Date();
73
+ const ts = now.toISOString().split('T')[1].split('.')[0] + '.' + String(now.getMilliseconds()).padStart(3, '0');
74
+ const newLog: LogEntry = {
75
+ timestamp: ts,
76
+ level: Math.random() > 0.8 ? 'WARN' : 'INFO',
77
+ message: `METRIC_UPDATE_CYCLE_${Math.floor(Math.random() * 9999)}`,
78
+ source: 'telemetry'
79
+ };
80
+ logs = [newLog, ...logs].slice(0, 50);
81
+ }
82
+ }, 2000);
83
+ return () => clearInterval(interval);
84
+ });
85
+
86
+ // Fix #6: Tight function typing
87
+ function getStatusColor(status: SystemMetric['status'] | LogEntry['level'] | typeof systemStatus): string {
88
+ // Fix #4: Use CSS custom properties instead of hardcoded hex
89
+ switch (status) {
90
+ case 'nominal':
91
+ case 'ONLINE':
92
+ return 'var(--color-status-active)';
93
+ case 'caution':
94
+ case 'DEGRADED':
95
+ return 'var(--color-status-busy)';
96
+ case 'critical':
97
+ case 'ERR':
98
+ case 'OFFLINE':
99
+ return 'var(--color-status-alert)';
100
+ case 'WARN':
101
+ return 'var(--color-status-warn)';
102
+ default:
103
+ return 'var(--color-text-tertiary)';
104
+ }
105
+ }
106
+
107
+ function getTrendArrow(trend?: SystemMetric['trend']): string {
108
+ switch (trend) {
109
+ case 'up': return '▲';
110
+ case 'down': return '▼';
111
+ default: return '◆';
112
+ }
113
+ }
114
+
115
+ // Fix #3: Defensive CSS width calculation
116
+ function getStatusWidth(value: string): string {
117
+ const num = parseFloat(value);
118
+ if (isNaN(num) || num < 0) return '0%';
119
+ return `${Math.min(num / 2, 100)}%`;
120
+ }
121
+ </script>
122
+
123
+ <div class="telemetry-panel" data-theme="control-room">
124
+ <!-- HEADER: System Identity -->
125
+ <header class="panel-header">
126
+ <div class="header-left">
127
+ <div class="system-id">{systemId}</div>
128
+ <div class="status-line">
129
+ <span class="status-indicator" style="color: {getStatusColor(systemStatus)}">
130
+ ● {systemStatus}
131
+ </span>
132
+ <span class="uptime">UPTIME: {uptime}</span>
133
+ </div>
134
+ </div>
135
+ <div class="header-right">
136
+ <div class="coord-display">
137
+ <div>LOC: 40.7128°N, 74.0060°W</div>
138
+ <div>TS: {currentTime}</div>
139
+ </div>
140
+ </div>
141
+ </header>
142
+
143
+ <!-- HAZARD STRIPE DIVIDER -->
144
+ <div class="hazard-divider hazard-stripes"></div>
145
+
146
+ <!-- TAB NAVIGATION -->
147
+ <nav class="tab-bar">
148
+ {#each [['metrics', 'METRICS'], ['logs', 'EVENT_LOG'], ['network', 'NETWORK']] as [tab, label]}
149
+ <button
150
+ role="tab"
151
+ aria-selected={activeTab === tab}
152
+ aria-controls="{tab}-panel"
153
+ class="tab-btn"
154
+ class:active={activeTab === tab}
155
+ onclick={() => activeTab = tab as typeof activeTab}
156
+ >
157
+ {activeTab === tab ? '■' : '□'} {label}
158
+ </button>
159
+ {/each}
160
+ <div class="tab-spacer"></div>
161
+ <div class="hazard-badge">CLASS: OPERATOR</div>
162
+ </nav>
163
+
164
+ <!-- MAIN CONTENT AREA -->
165
+ <main class="content-area">
166
+ {#if activeTab === 'metrics'}
167
+ <div class="metrics-grid">
168
+ {#each metrics as metric}
169
+ <div class="metric-card" class:critical={metric.status === 'critical'}>
170
+ <div class="metric-header">
171
+ <span class="metric-label">{metric.label}</span>
172
+ <span class="metric-trend" style="color: {getStatusColor(metric.status)}">
173
+ {getTrendArrow(metric.trend)}
174
+ </span>
175
+ </div>
176
+ <div class="metric-value" style="color: {getStatusColor(metric.status)}">
177
+ {metric.value}<span class="metric-unit">{metric.unit}</span>
178
+ </div>
179
+ <div class="metric-status-bar">
180
+ <div
181
+ class="status-fill"
182
+ style="width: {getStatusWidth(metric.value)}; background: {getStatusColor(metric.status)}"
183
+ ></div>
184
+ </div>
185
+ </div>
186
+ {/each}
187
+ </div>
188
+
189
+ {:else if activeTab === 'logs'}
190
+ <div id="logs-panel" role="tabpanel" aria-labelledby="logs-tab">
191
+ <div class="log-container">
192
+ <div class="log-header">
193
+ <span>TIMESTAMP</span>
194
+ <span>LVL</span>
195
+ <span>SOURCE</span>
196
+ <span>MESSAGE</span>
197
+ </div>
198
+ {#each logs as log}
199
+ <div class="log-row">
200
+ <span class="log-ts">{log.timestamp}</span>
201
+ <span class="log-level" style="color: {getStatusColor(log.level)}">{log.level}</span>
202
+ <span class="log-source">{log.source}</span>
203
+ <span class="log-msg">{log.message}</span>
204
+ </div>
205
+ {/each}
206
+ </div>
207
+
208
+ </div>
209
+ {:else}
210
+ <div id="network-panel" role="tabpanel" aria-labelledby="network-tab" class="network-view">
211
+ <div class="network-node">
212
+ <div class="node-id">SOVEREIGN-CORE</div>
213
+ <div class="node-conn active">● ACTIVE</div>
214
+ <div class="node-lat">2.4ms</div>
215
+ </div>
216
+ <div class="network-link"></div>
217
+ <div class="network-node">
218
+ <div class="node-id">LEAP-MIDDLEWARE</div>
219
+ <div class="node-conn active">● ACTIVE</div>
220
+ <div class="node-lat">8.1ms</div>
221
+ </div>
222
+ <div class="network-link warning"></div>
223
+ <div class="network-node warning">
224
+ <div class="node-id">AGORA-CHANNEL</div>
225
+ <div class="node-conn degraded">● DEGRADED</div>
226
+ <div class="node-lat degraded">147ms</div>
227
+ </div>
228
+ </div>
229
+ {/if}
230
+ </main>
231
+
232
+ <!-- FOOTER: Metadata -->
233
+ <footer class="panel-footer">
234
+ <div class="footer-left">
235
+ <span class="hex-dump">HEX: 0x7F3A9E2D • 0x4B8C1F00 • 0x9E5D2A11</span>
236
+ </div>
237
+ <div class="footer-right">
238
+ <span>BUILD: v2.4.1-RC1</span>
239
+ <span>HASH: a7f3d9e</span>
240
+ </div>
241
+ </footer>
242
+ </div>
243
+
244
+ <style>
245
+ /* --- PANEL CONTAINER ---
246
+ * Uses theme tokens from control-room.css
247
+ * Layout only — all colors from CSS vars
248
+ */
249
+ .telemetry-panel {
250
+ width: 100%;
251
+ max-width: 900px;
252
+ background: var(--color-bg-app);
253
+ border: var(--border-default);
254
+ font-family: var(--font-mono);
255
+ font-size: var(--text-base);
256
+ color: var(--color-text-primary);
257
+ display: flex;
258
+ flex-direction: column;
259
+ clip-path: var(--clip-corner-md);
260
+ }
261
+
262
+ /* --- HEADER --- */
263
+ .panel-header {
264
+ display: flex;
265
+ justify-content: space-between;
266
+ align-items: flex-start;
267
+ padding: var(--space-2);
268
+ background: var(--color-bg-canvas);
269
+ border-bottom: var(--border-default);
270
+ }
271
+
272
+ .system-id {
273
+ font-size: var(--text-2xl);
274
+ font-weight: 600;
275
+ letter-spacing: 0.1em;
276
+ text-transform: uppercase;
277
+ }
278
+
279
+ .status-line {
280
+ display: flex;
281
+ gap: var(--space-2);
282
+ margin-top: var(--space-1);
283
+ font-size: var(--text-sm);
284
+ }
285
+
286
+ .status-indicator {
287
+ font-weight: 500;
288
+ }
289
+
290
+ .uptime {
291
+ color: var(--color-text-tertiary);
292
+ }
293
+
294
+ .coord-display {
295
+ text-align: right;
296
+ font-size: var(--text-xs);
297
+ color: var(--color-text-tertiary);
298
+ line-height: 1.6;
299
+ }
300
+
301
+ /* --- HAZARD STRIPE ---
302
+ * Uses theme .hazard-stripes utility class in markup,
303
+ * this is component-specific sizing only
304
+ */
305
+ .hazard-divider {
306
+ height: var(--size-hazard-divider-height);
307
+ /* Background comes from theme .hazard-stripes class */
308
+ }
309
+
310
+ /* --- TAB BAR --- */
311
+ .tab-bar {
312
+ display: flex;
313
+ gap: 0;
314
+ background: var(--color-bg-inset);
315
+ border-bottom: var(--border-subtle);
316
+ }
317
+
318
+ .tab-btn {
319
+ padding: var(--space-2) var(--space-3);
320
+ background: transparent;
321
+ border: none;
322
+ border-right: var(--border-subtle);
323
+ color: var(--color-text-tertiary);
324
+ font-family: inherit;
325
+ font-size: var(--text-sm);
326
+ text-transform: uppercase;
327
+ letter-spacing: 0.05em;
328
+ cursor: pointer;
329
+ transition: var(--transition-fast);
330
+ }
331
+
332
+ .tab-btn:hover {
333
+ background: var(--color-bg-canvas);
334
+ color: var(--color-text-secondary);
335
+ }
336
+
337
+ .tab-btn.active {
338
+ background: var(--color-bg-app);
339
+ color: var(--color-accent);
340
+ border-bottom: var(--border-width-thick) solid var(--color-accent);
341
+ margin-bottom: -1px;
342
+ }
343
+
344
+ .tab-spacer {
345
+ flex: 1;
346
+ }
347
+
348
+ .hazard-badge {
349
+ padding: var(--space-2) var(--space-2);
350
+ font-size: var(--text-xs);
351
+ color: var(--color-status-busy);
352
+ border-left: var(--border-subtle);
353
+ display: flex;
354
+ align-items: center;
355
+ }
356
+
357
+ /* --- CONTENT AREA --- */
358
+ .content-area {
359
+ flex: 1;
360
+ padding: var(--space-2);
361
+ background: var(--color-bg-app);
362
+ min-height: 300px;
363
+ }
364
+
365
+ /* --- METRICS GRID --- */
366
+ .metrics-grid {
367
+ display: grid;
368
+ grid-template-columns: repeat(3, 1fr);
369
+ gap: var(--size-grid-gap-subtle);
370
+ background: var(--divider-color);
371
+ border: var(--border-subtle);
372
+ }
373
+
374
+ .metric-card {
375
+ background: var(--color-card-bg);
376
+ padding: var(--space-2);
377
+ display: flex;
378
+ flex-direction: column;
379
+ gap: var(--space-1);
380
+ }
381
+
382
+ .metric-card.critical {
383
+ background: repeating-linear-gradient(
384
+ -45deg,
385
+ var(--color-card-bg),
386
+ var(--color-card-bg) var(--hazard-alt-stripe-band),
387
+ var(--color-status-alert-10) var(--hazard-alt-stripe-band),
388
+ var(--color-status-alert-10) var(--hazard-alt-stripe-width)
389
+ );
390
+ }
391
+
392
+ .metric-header {
393
+ display: flex;
394
+ justify-content: space-between;
395
+ align-items: center;
396
+ }
397
+
398
+ .metric-label {
399
+ font-size: var(--text-xs);
400
+ color: var(--color-text-tertiary);
401
+ letter-spacing: 0.1em;
402
+ }
403
+
404
+ .metric-trend {
405
+ font-size: var(--text-sm);
406
+ }
407
+
408
+ .metric-value {
409
+ font-size: var(--text-3xl);
410
+ font-weight: 600;
411
+ font-family: var(--font-data);
412
+ }
413
+
414
+ .metric-unit {
415
+ font-size: var(--text-sm);
416
+ color: var(--color-text-tertiary);
417
+ margin-left: 0.25rem;
418
+ }
419
+
420
+ .metric-status-bar {
421
+ height: var(--size-status-bar-height);
422
+ background: var(--divider-color);
423
+ margin-top: auto;
424
+ }
425
+
426
+ .status-fill {
427
+ height: 100%;
428
+ transition: var(--transition-normal);
429
+ }
430
+
431
+ /* --- LOGS --- */
432
+ .log-container {
433
+ font-size: var(--text-sm);
434
+ line-height: 1.8;
435
+ }
436
+
437
+ .log-header {
438
+ display: grid;
439
+ grid-template-columns: 100px 50px 150px 1fr;
440
+ gap: var(--space-2);
441
+ padding: var(--space-1) 0;
442
+ border-bottom: var(--border-subtle);
443
+ color: var(--color-text-tertiary);
444
+ font-size: var(--text-xs);
445
+ letter-spacing: 0.1em;
446
+ }
447
+
448
+ .log-row {
449
+ display: grid;
450
+ grid-template-columns: 100px 50px 150px 1fr;
451
+ gap: var(--space-2);
452
+ padding: var(--space-1) 0;
453
+ border-bottom: var(--border-subtle);
454
+ }
455
+
456
+ .log-row:hover {
457
+ background: var(--color-bg-canvas);
458
+ }
459
+
460
+ .log-ts {
461
+ color: var(--color-text-muted);
462
+ }
463
+
464
+ .log-level {
465
+ font-weight: 600;
466
+ }
467
+
468
+ .log-source {
469
+ color: var(--color-text-tertiary);
470
+ }
471
+
472
+ .log-msg {
473
+ color: var(--color-text-secondary);
474
+ }
475
+
476
+ /* --- NETWORK VIEW --- */
477
+ .network-view {
478
+ display: flex;
479
+ flex-direction: column;
480
+ gap: 0;
481
+ padding: var(--space-2);
482
+ }
483
+
484
+ .network-node {
485
+ display: flex;
486
+ align-items: center;
487
+ gap: var(--space-2);
488
+ padding: var(--space-2);
489
+ background: var(--color-bg-canvas);
490
+ border: var(--border-subtle);
491
+ border-left: var(--size-border-left-heavy) solid var(--color-status-active);
492
+ }
493
+
494
+ .network-node.warning {
495
+ border-left-color: var(--color-status-warn);
496
+ }
497
+
498
+ .node-id {
499
+ width: 200px;
500
+ font-weight: 500;
501
+ letter-spacing: 0.05em;
502
+ }
503
+
504
+ .node-conn {
505
+ font-size: var(--text-sm);
506
+ color: var(--color-text-tertiary);
507
+ }
508
+
509
+ .node-conn.active {
510
+ color: var(--color-status-active);
511
+ }
512
+
513
+ .node-conn.degraded,
514
+ .node-lat.degraded {
515
+ color: var(--color-status-warn);
516
+ }
517
+
518
+ .node-lat {
519
+ margin-left: auto;
520
+ font-family: var(--font-data);
521
+ color: var(--color-status-active);
522
+ }
523
+
524
+ .network-link {
525
+ width: var(--size-network-link-width);
526
+ height: var(--size-network-link-height);
527
+ background: var(--color-status-active);
528
+ margin-left: var(--space-2);
529
+ position: relative;
530
+ }
531
+
532
+ .network-link::before {
533
+ content: '▼';
534
+ position: absolute;
535
+ left: calc(var(--space-1) * -1);
536
+ top: 50%;
537
+ transform: translateY(-50%);
538
+ font-size: var(--text-2xs);
539
+ color: var(--color-status-active);
540
+ }
541
+
542
+ .network-link.warning {
543
+ background: var(--color-status-warn);
544
+ }
545
+
546
+ .network-link.warning::before {
547
+ color: var(--color-status-warn);
548
+ }
549
+
550
+ /* --- FOOTER --- */
551
+ .panel-footer {
552
+ display: flex;
553
+ justify-content: space-between;
554
+ padding: var(--space-1) var(--space-2);
555
+ background: var(--color-bg-inset);
556
+ border-top: var(--border-subtle);
557
+ font-size: var(--text-xs);
558
+ color: var(--color-text-muted);
559
+ }
560
+
561
+ .footer-right {
562
+ display: flex;
563
+ gap: var(--space-2);
564
+ }
565
+
566
+ .hex-dump {
567
+ font-family: var(--font-data);
568
+ letter-spacing: 0.1em;
569
+ }
570
+ </style>