diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/package.json b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/package.json
index b2d6c562..e61195bb 100644
--- a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/package.json
+++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/package.json
@@ -19,6 +19,8 @@
"dependencies": {
"@tanstack/react-query": "^5.90.12",
"axios": "^1.13.0",
+ "d3-array": "^3.2.4",
+ "d3-scale": "^4.0.2",
"react": "^19.2.1",
"react-dom": "^19.2.0",
"react-error-boundary": "^6.0.0",
@@ -34,6 +36,8 @@
"devDependencies": {
"@biomejs/biome": "^2.3.8",
"@tanstack/react-query-devtools": "^5.91.1",
+ "@types/d3-array": "^3.2.2",
+ "@types/d3-scale": "^4.0.9",
"@types/node": "^24.10.2",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/pnpm-lock.yaml b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/pnpm-lock.yaml
index 0d03bdab..54596339 100644
--- a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/pnpm-lock.yaml
+++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/pnpm-lock.yaml
@@ -17,6 +17,12 @@ importers:
axios:
specifier: ^1.13.0
version: 1.13.2
+ d3-array:
+ specifier: ^3.2.4
+ version: 3.2.4
+ d3-scale:
+ specifier: ^4.0.2
+ version: 4.0.2
react:
specifier: ^19.2.1
version: 19.2.1
@@ -57,6 +63,12 @@ importers:
'@tanstack/react-query-devtools':
specifier: ^5.91.1
version: 5.91.1(@tanstack/react-query@5.90.12(react@19.2.1))(react@19.2.1)
+ '@types/d3-array':
+ specifier: ^3.2.2
+ version: 3.2.2
+ '@types/d3-scale':
+ specifier: ^4.0.9
+ version: 4.0.9
'@types/node':
specifier: ^24.10.2
version: 24.10.2
@@ -572,6 +584,15 @@ packages:
'@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+ '@types/d3-array@3.2.2':
+ resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==}
+
+ '@types/d3-scale@4.0.9':
+ resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
+
+ '@types/d3-time@3.0.4':
+ resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
+
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
@@ -2264,6 +2285,14 @@ snapshots:
'@types/deep-eql': 4.0.2
assertion-error: 2.0.1
+ '@types/d3-array@3.2.2': {}
+
+ '@types/d3-scale@4.0.9':
+ dependencies:
+ '@types/d3-time': 3.0.4
+
+ '@types/d3-time@3.0.4': {}
+
'@types/deep-eql@4.0.2': {}
'@types/estree@1.0.8': {}
diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/Panel.module.scss b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/Panel.module.scss
new file mode 100644
index 00000000..1187f67e
--- /dev/null
+++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/Panel.module.scss
@@ -0,0 +1,60 @@
+// ©AngelaMos | 2026
+// Panel.module.scss
+
+.panel {
+ display: flex;
+ flex-direction: column;
+ border-bottom: 1px solid var(--fg-4);
+ min-height: 0;
+}
+
+.head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 28px;
+ padding: 0 8px;
+ background: var(--bg);
+ border-bottom: 1px solid var(--fg-4);
+}
+
+.title {
+ font-size: var(--type-label);
+ letter-spacing: var(--letter-spacing-label);
+ text-transform: uppercase;
+ color: var(--fg-2);
+}
+
+.subtitle {
+ color: var(--fg-3);
+}
+
+.meta {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ color: var(--fg-3);
+}
+
+.rawLink {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--fg-3);
+
+ &:hover {
+ color: var(--fg-1);
+ }
+
+ &:focus-visible {
+ outline: 1px solid var(--fg-2);
+ outline-offset: 1px;
+ }
+}
+
+.body {
+ flex: 1;
+ overflow: auto;
+ padding: 4px 0;
+ min-height: 0;
+}
diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/Panel.tsx b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/Panel.tsx
new file mode 100644
index 00000000..d9485b86
--- /dev/null
+++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/Panel.tsx
@@ -0,0 +1,55 @@
+// ©AngelaMos | 2026
+// Panel.tsx
+
+import type { ReactNode } from 'react'
+import { FiExternalLink } from 'react-icons/fi'
+import styles from './Panel.module.scss'
+import { StaleIndicator } from './shared/StaleIndicator'
+
+export interface PanelProps {
+ title: string
+ subtitle?: string
+ rawHref?: string
+ rawLabel?: string
+ isStale?: boolean
+ lastTickAt?: number
+ children: ReactNode
+}
+
+export function Panel({
+ title,
+ subtitle,
+ rawHref,
+ rawLabel,
+ isStale,
+ lastTickAt,
+ children,
+}: PanelProps): React.ReactElement {
+ return (
+