diff --git a/site-web/console/cockpit.js b/site-web/console/cockpit.js
new file mode 100644
index 0000000..1645956
--- /dev/null
+++ b/site-web/console/cockpit.js
@@ -0,0 +1,297 @@
+// FORGIUM CLOUD COCKPIT CONTROLLER
+const FORGIUM_API_BASE = 'https://panel.forgium.fr/api/client';
+const DEFAULT_KEY = 'ptlc_8mAbydxokymforgium_144010543bd11119f4fe424b643e49d6d2e17c8271224b81';
+
+class ForgiumCockpit {
+ constructor() {
+ this.apiKey = localStorage.getItem('forgium_cockpit_key') || DEFAULT_KEY;
+ this.servers = [];
+ this.currentServer = null;
+ this.socket = null;
+ this.pollInterval = null;
+
+ this.initDOMElements();
+ this.bindEvents();
+ this.checkAuthAndStart();
+ }
+
+ initDOMElements() {
+ this.fleetView = document.getElementById('fleet-view');
+ this.serverView = document.getElementById('server-view');
+ this.serversGrid = document.getElementById('servers-grid');
+ this.configModal = document.getElementById('config-modal');
+ this.apiKeyInput = document.getElementById('api-key-input');
+
+ // Detail View Elements
+ this.backBtn = document.getElementById('back-to-fleet');
+ this.serverTitle = document.getElementById('server-detail-title');
+ this.serverDesc = document.getElementById('server-detail-desc');
+ this.serverBadge = document.getElementById('server-detail-badge');
+ this.terminalOutput = document.getElementById('terminal-output');
+ this.terminalInput = document.getElementById('terminal-input');
+
+ // Stat counters
+ this.countTotal = document.getElementById('stat-total-servers');
+ this.countRunning = document.getElementById('stat-running-servers');
+
+ // Detail Gauges
+ this.gaugeCpu = document.getElementById('gauge-cpu');
+ this.gaugeCpuFill = document.getElementById('gauge-cpu-fill');
+ this.gaugeRam = document.getElementById('gauge-ram');
+ this.gaugeRamFill = document.getElementById('gauge-ram-fill');
+ this.gaugeDisk = document.getElementById('gauge-disk');
+ this.gaugeDiskFill = document.getElementById('gauge-disk-fill');
+
+ // Power Buttons
+ this.btnStart = document.getElementById('btn-power-start');
+ this.btnRestart = document.getElementById('btn-power-restart');
+ this.btnStop = document.getElementById('btn-power-stop');
+ }
+
+ bindEvents() {
+ document.getElementById('save-key-btn').addEventListener('click', () => {
+ const key = this.apiKeyInput.value.trim();
+ if (key) {
+ this.apiKey = key;
+ localStorage.setItem('forgium_cockpit_key', key);
+ this.configModal.classList.add('hidden');
+ this.loadFleet();
+ }
+ });
+
+ document.getElementById('btn-settings').addEventListener('click', () => {
+ this.apiKeyInput.value = this.apiKey;
+ this.configModal.classList.remove('hidden');
+ });
+
+ this.backBtn.addEventListener('click', () => {
+ this.showFleetView();
+ });
+
+ this.terminalInput.addEventListener('keydown', (e) => {
+ if (e.key === 'Enter') {
+ const cmd = this.terminalInput.value.trim();
+ if (cmd) {
+ this.sendCommand(cmd);
+ this.terminalInput.value = '';
+ }
+ }
+ });
+
+ this.btnStart.addEventListener('click', () => this.sendPowerSignal('start'));
+ this.btnRestart.addEventListener('click', () => this.sendPowerSignal('restart'));
+ this.btnStop.addEventListener('click', () => this.sendPowerSignal('stop'));
+ }
+
+ checkAuthAndStart() {
+ if (!this.apiKey) {
+ this.configModal.classList.remove('hidden');
+ } else {
+ this.loadFleet();
+ }
+ }
+
+ async apiRequest(endpoint, method = 'GET', body = null) {
+ const headers = {
+ 'Authorization': `Bearer ${this.apiKey}`,
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ };
+
+ const res = await fetch(`${FORGIUM_API_BASE}${endpoint}`, {
+ method,
+ headers,
+ body: body ? JSON.stringify(body) : null
+ });
+
+ if (!res.ok) {
+ if (res.status === 401 || res.status === 403) {
+ this.configModal.classList.remove('hidden');
+ }
+ throw new Error(`Erreur API: ${res.status}`);
+ }
+
+ return res.json();
+ }
+
+ async loadFleet() {
+ try {
+ const data = await this.apiRequest('');
+ this.servers = data.data.map(item => item.attributes);
+ this.renderFleet();
+ } catch (err) {
+ console.error('Erreur chargement flotte:', err);
+ }
+ }
+
+ async renderFleet() {
+ this.serversGrid.innerHTML = '';
+ this.countTotal.textContent = this.servers.length;
+ let onlineCount = 0;
+
+ for (const s of this.servers) {
+ const card = document.createElement('div');
+ card.className = 'server-card';
+
+ // Récupérer ressources en temps réel
+ let resState = 'offline';
+ let cpu = '0.0%';
+ let ram = '0 Mo';
+ try {
+ const stats = await this.apiRequest(`/servers/${s.identifier}/resources`);
+ resState = stats.attributes.current_state;
+ if (resState === 'running' || resState === 'starting') {
+ onlineCount++;
+ }
+ cpu = (stats.attributes.resources.cpu_absolute || 0).toFixed(1) + '%';
+ const ramMb = (stats.attributes.resources.memory_bytes / 1024 / 1024).toFixed(0);
+ ram = `${ramMb} Mo / ${s.limits.memory} Mo`;
+ } catch (e) {
+ console.log('Stats offline:', s.name);
+ }
+
+ const isOnline = resState === 'running' || resState === 'starting';
+ const badgeClass = isOnline ? 'status-running' : 'status-offline';
+ const badgeText = isOnline ? 'EN LIGNE' : 'ARRÊTÉ';
+
+ const defaultAlloc = s.relationships?.allocations?.data[0]?.attributes;
+ const alias = defaultAlloc ? `node.forgium.fr:${defaultAlloc.port}` : 'Réseau Dédié';
+
+ card.innerHTML = `
+
+
+
${s.name}
+ AMD RYZEN 7 3700X • ${s.docker_image.split('/').pop().replace('yolks:', '')}
+
+
+
+ ${badgeText}
+
+
+
+
+ CPU
+ ${cpu}
+
+
+ RAM
+ ${ram}
+
+
+ DISQUE
+ ${s.limits.disk} Mo
+
+
+
+ ${alias}
+
+
+ `;
+
+ card.addEventListener('click', () => this.openServerCockpit(s));
+ this.serversGrid.appendChild(card);
+ }
+
+ this.countRunning.textContent = onlineCount;
+ }
+
+ openServerCockpit(server) {
+ this.currentServer = server;
+ this.fleetView.style.display = 'none';
+ this.serverView.classList.add('active');
+
+ this.serverTitle.textContent = server.name;
+ this.serverDesc.textContent = server.description || `Instance Cloud haute performance sur AMD Ryzen 7 3700X`;
+ this.terminalOutput.textContent = `[Forgium Console Gateway] Connexion au nœud Wings sécurisé...\n[Forgium Console Gateway] Authentification TLS / WebSocket pour le serveur [${server.name}] (UUID: ${server.identifier})\n`;
+
+ this.startTelemetryPoll();
+ }
+
+ showFleetView() {
+ this.stopTelemetryPoll();
+ this.serverView.classList.remove('active');
+ this.fleetView.style.display = 'block';
+ this.currentServer = null;
+ this.loadFleet();
+ }
+
+ startTelemetryPoll() {
+ this.updateTelemetry();
+ this.pollInterval = setInterval(() => this.updateTelemetry(), 3000);
+ }
+
+ stopTelemetryPoll() {
+ if (this.pollInterval) {
+ clearInterval(this.pollInterval);
+ this.pollInterval = null;
+ }
+ }
+
+ async updateTelemetry() {
+ if (!this.currentServer) return;
+ try {
+ const stats = await this.apiRequest(`/servers/${this.currentServer.identifier}/resources`);
+ const res = stats.attributes.resources;
+ const state = stats.attributes.current_state;
+
+ const isOnline = state === 'running' || state === 'starting';
+ this.serverBadge.className = `status-badge ${isOnline ? 'status-running' : 'status-offline'}`;
+ this.serverBadge.innerHTML = ` ${isOnline ? 'EN LIGNE' : 'ARRÊTÉ'}`;
+
+ // CPU
+ const cpuPercent = (res.cpu_absolute || 0).toFixed(1);
+ this.gaugeCpu.textContent = `${cpuPercent}% / ${this.currentServer.limits.cpu}%`;
+ this.gaugeCpuFill.style.width = `${Math.min(100, (res.cpu_absolute / this.currentServer.limits.cpu) * 100)}%`;
+
+ // RAM
+ const ramMb = (res.memory_bytes / 1024 / 1024).toFixed(1);
+ const ramMax = this.currentServer.limits.memory;
+ this.gaugeRam.textContent = `${ramMb} Mo / ${ramMax} Mo`;
+ this.gaugeRamFill.style.width = `${Math.min(100, (ramMb / ramMax) * 100)}%`;
+
+ // DISK
+ const diskMb = (res.disk_bytes / 1024 / 1024).toFixed(1);
+ const diskMax = this.currentServer.limits.disk;
+ this.gaugeDisk.textContent = `${diskMb} Mo / ${diskMax} Mo`;
+ this.gaugeDiskFill.style.width = `${Math.min(100, (diskMb / diskMax) * 100)}%`;
+
+ // Log stream imitation for testing
+ if (isOnline && Math.random() > 0.4) {
+ this.appendTerminal(`[Node ${this.currentServer.node}] Heartbeat sync: CPU=${cpuPercent}% | RAM=${ramMb}Mo | Uptime=${(res.uptime / 60).toFixed(0)}m`);
+ }
+ } catch (e) {
+ console.error('Erreur télémétrie serveur:', e);
+ }
+ }
+
+ appendTerminal(text) {
+ this.terminalOutput.textContent += `${text}\n`;
+ this.terminalOutput.scrollTop = this.terminalOutput.scrollHeight;
+ }
+
+ async sendPowerSignal(signal) {
+ if (!this.currentServer) return;
+ this.appendTerminal(`[Forgium Cockpit] Envoi du signal d'alimentation: ${signal.toUpperCase()}...`);
+ try {
+ await this.apiRequest(`/servers/${this.currentServer.identifier}/power`, 'POST', { signal });
+ this.appendTerminal(`[Forgium Cockpit] Ordre ${signal.toUpperCase()} exécuté avec succès par Wings.`);
+ setTimeout(() => this.updateTelemetry(), 1000);
+ } catch (e) {
+ this.appendTerminal(`[Forgium Cockpit] ERREUR signal ${signal}: ${e.message}`);
+ }
+ }
+
+ async sendCommand(command) {
+ if (!this.currentServer) return;
+ this.appendTerminal(`> ${command}`);
+ try {
+ await this.apiRequest(`/servers/${this.currentServer.identifier}/command`, 'POST', { command });
+ } catch (e) {
+ this.appendTerminal(`[Forgium Cockpit] Erreur commande: ${e.message}`);
+ }
+ }
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ window.cockpit = new ForgiumCockpit();
+});
diff --git a/site-web/console/index.html b/site-web/console/index.html
new file mode 100644
index 0000000..a1efc42
--- /dev/null
+++ b/site-web/console/index.html
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+ Cockpit & Console | Forgium Cloud
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Charge Processeur
+ --
+
+
+
AMD Ryzen 7 3700X High Performance Core
+
+
+
+
+ Mémoire Vive (RAM)
+ --
+
+
+
Allocation stricte isolée sans dépassement
+
+
+
+
+ Espace Disque SSD
+ --
+
+
+
NVMe Local haute vitesse
+
+
+
+
+
+
+
+
+
+
+
Authentification Forgium
+
Renseignez votre clé d'accès sécurisée pour connecter ce cockpit à vos instances de calcul isolées.
+
+
+
+
+
+
+
+
+
diff --git a/site-web/console/style-console.css b/site-web/console/style-console.css
new file mode 100644
index 0000000..3d2129e
--- /dev/null
+++ b/site-web/console/style-console.css
@@ -0,0 +1,633 @@
+:root {
+ --bg-deep: #030712;
+ --bg-surface: #0a101f;
+ --bg-card: rgba(13, 22, 41, 0.75);
+ --bg-card-hover: rgba(18, 30, 56, 0.85);
+ --border: rgba(56, 189, 248, 0.15);
+ --border-hover: rgba(56, 189, 248, 0.4);
+ --accent-cyan: #38bdf8;
+ --accent-blue: #2563eb;
+ --accent-green: #10b981;
+ --accent-amber: #f59e0b;
+ --accent-rose: #f43f5e;
+ --text-main: #f8fafc;
+ --text-muted: #94a3b8;
+ --text-dim: #64748b;
+ --glow-cyan: 0 0 25px rgba(56, 189, 248, 0.25);
+ --glow-green: 0 0 20px rgba(16, 185, 129, 0.3);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
+ background-color: var(--bg-deep);
+ background-image:
+ radial-gradient(circle at 15% 15%, rgba(56, 189, 248, 0.08) 0%, transparent 45%),
+ radial-gradient(circle at 85% 85%, rgba(37, 99, 235, 0.08) 0%, transparent 45%);
+ color: var(--text-main);
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+/* NAVBAR COCKPIT */
+.cockpit-header {
+ background: rgba(10, 16, 31, 0.8);
+ backdrop-filter: blur(16px);
+ -webkit-backdrop-filter: blur(16px);
+ border-bottom: 1px solid var(--border);
+ position: sticky;
+ top: 0;
+ z-index: 100;
+}
+
+.header-container {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 0.8rem 1.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.brand-area {
+ display: flex;
+ align-items: center;
+ gap: 1.2rem;
+}
+
+.brand-link {
+ display: flex;
+ align-items: center;
+ gap: 0.6rem;
+ text-decoration: none;
+ color: var(--text-main);
+ font-weight: 800;
+ font-size: 1.2rem;
+ letter-spacing: -0.5px;
+}
+
+.brand-badge {
+ background: rgba(56, 189, 248, 0.12);
+ border: 1px solid var(--border);
+ color: var(--accent-cyan);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 0.7rem;
+ padding: 0.2rem 0.6rem;
+ border-radius: 6px;
+ font-weight: 700;
+}
+
+.node-status {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.8rem;
+ color: var(--text-muted);
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.pulse-indicator {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--accent-green);
+ box-shadow: var(--glow-green);
+ animation: pulse 2s infinite;
+}
+
+@keyframes pulse {
+ 0% { transform: scale(0.95); opacity: 0.8; }
+ 50% { transform: scale(1.2); opacity: 1; }
+ 100% { transform: scale(0.95); opacity: 0.8; }
+}
+
+.user-area {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.user-chip {
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ padding: 0.4rem 0.9rem;
+ border-radius: 100px;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.85rem;
+ font-weight: 600;
+}
+
+.user-avatar {
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.7rem;
+ font-weight: 800;
+}
+
+/* LAYOUT PRINCIPAL */
+.cockpit-main {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 2rem 1.5rem;
+ flex: 1;
+ width: 100%;
+}
+
+/* VUE LISTE SERVEURS (FLEET OVERVIEW) */
+.fleet-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-end;
+ margin-bottom: 2rem;
+}
+
+.fleet-title h1 {
+ font-size: 1.8rem;
+ font-weight: 800;
+ letter-spacing: -0.5px;
+ margin-bottom: 0.3rem;
+}
+
+.fleet-title p {
+ color: var(--text-muted);
+ font-size: 0.95rem;
+}
+
+.fleet-stats {
+ display: flex;
+ gap: 1.5rem;
+}
+
+.stat-pill {
+ background: var(--bg-card);
+ border: 1px solid var(--border);
+ padding: 0.6rem 1.2rem;
+ border-radius: 12px;
+ backdrop-filter: blur(8px);
+}
+
+.stat-label {
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.stat-value {
+ font-size: 1.2rem;
+ font-weight: 700;
+ font-family: 'JetBrains Mono', monospace;
+ color: var(--accent-cyan);
+}
+
+/* GRILLE DE CARTES SERVEURS */
+.servers-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
+ gap: 1.5rem;
+}
+
+.server-card {
+ background: var(--bg-card);
+ border: 1px solid var(--border);
+ border-radius: 18px;
+ padding: 1.6rem;
+ backdrop-filter: blur(14px);
+ transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+}
+
+.server-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: linear-gradient(90deg, var(--accent-cyan), var(--accent-blue));
+ opacity: 0;
+ transition: opacity 0.3s;
+}
+
+.server-card:hover {
+ border-color: var(--border-hover);
+ transform: translateY(-4px);
+ box-shadow: var(--glow-cyan);
+}
+
+.server-card:hover::before {
+ opacity: 1;
+}
+
+.card-top {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 1.2rem;
+}
+
+.server-info h3 {
+ font-size: 1.2rem;
+ font-weight: 700;
+ margin-bottom: 0.3rem;
+}
+
+.server-type {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4rem;
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.status-badge {
+ padding: 0.3rem 0.7rem;
+ border-radius: 100px;
+ font-size: 0.75rem;
+ font-weight: 700;
+ display: flex;
+ align-items: center;
+ gap: 0.4rem;
+}
+
+.status-running {
+ background: rgba(16, 185, 129, 0.15);
+ border: 1px solid rgba(16, 185, 129, 0.3);
+ color: var(--accent-green);
+}
+
+.status-offline {
+ background: rgba(100, 116, 139, 0.15);
+ border: 1px solid rgba(100, 116, 139, 0.3);
+ color: var(--text-dim);
+}
+
+.metrics-row {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 0.8rem;
+ background: rgba(0, 0, 0, 0.3);
+ padding: 0.9rem;
+ border-radius: 12px;
+ border: 1px solid rgba(255, 255, 255, 0.04);
+ margin-bottom: 1.2rem;
+}
+
+.metric-item {
+ display: flex;
+ flex-direction: column;
+}
+
+.metric-name {
+ font-size: 0.7rem;
+ color: var(--text-muted);
+ margin-bottom: 0.2rem;
+}
+
+.metric-val {
+ font-size: 0.95rem;
+ font-weight: 700;
+ font-family: 'JetBrains Mono', monospace;
+ color: var(--text-main);
+}
+
+.card-actions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.conn-alias {
+ font-size: 0.8rem;
+ font-family: 'JetBrains Mono', monospace;
+ color: var(--accent-cyan);
+ background: rgba(56, 189, 248, 0.08);
+ padding: 0.2rem 0.5rem;
+ border-radius: 6px;
+}
+
+.btn-manage {
+ background: linear-gradient(135deg, rgba(56, 189, 248, 0.2), rgba(37, 99, 235, 0.2));
+ border: 1px solid var(--border);
+ color: var(--text-main);
+ padding: 0.4rem 0.9rem;
+ border-radius: 8px;
+ font-size: 0.85rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.btn-manage:hover {
+ background: var(--accent-cyan);
+ color: #000;
+ box-shadow: var(--glow-cyan);
+}
+
+/* VUE DÉTAIL SERVEUR (COCKPIT VIEW) */
+.server-view {
+ display: none;
+}
+
+.server-view.active {
+ display: block;
+}
+
+.server-navbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1.5rem;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.back-btn {
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--border);
+ color: var(--text-main);
+ padding: 0.5rem 1rem;
+ border-radius: 8px;
+ font-size: 0.85rem;
+ cursor: pointer;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ gap: 0.4rem;
+}
+
+.back-btn:hover {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+.power-controls {
+ display: flex;
+ gap: 0.6rem;
+}
+
+.btn-power {
+ padding: 0.5rem 1rem;
+ border-radius: 8px;
+ font-size: 0.85rem;
+ font-weight: 700;
+ cursor: pointer;
+ border: none;
+ display: flex;
+ align-items: center;
+ gap: 0.4rem;
+ transition: all 0.2s;
+}
+
+.btn-start {
+ background: var(--accent-green);
+ color: #000;
+}
+.btn-start:hover {
+ box-shadow: var(--glow-green);
+ filter: brightness(1.1);
+}
+
+.btn-restart {
+ background: var(--accent-amber);
+ color: #000;
+}
+
+.btn-stop {
+ background: var(--accent-rose);
+ color: #fff;
+}
+
+/* COCKPIT GRID : CONSOLE + FILE/METRICS TABS */
+.cockpit-grid {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ gap: 1.5rem;
+}
+
+/* CONSOLE CYBERPUNK */
+.terminal-window {
+ background: #02040a;
+ border: 1px solid rgba(56, 189, 248, 0.2);
+ border-radius: 16px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ height: 600px;
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
+}
+
+.terminal-header {
+ background: rgba(13, 22, 41, 0.95);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.06);
+ padding: 0.8rem 1.2rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.terminal-title {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 0.85rem;
+ color: var(--accent-cyan);
+ display: flex;
+ align-items: center;
+ gap: 0.6rem;
+}
+
+.terminal-dots {
+ display: flex;
+ gap: 6px;
+}
+
+.terminal-dots span {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+}
+.dot-red { background: #ef4444; }
+.dot-yellow { background: #f59e0b; }
+.dot-green { background: #10b981; }
+
+.terminal-output {
+ flex: 1;
+ padding: 1.2rem;
+ overflow-y: auto;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 0.85rem;
+ line-height: 1.6;
+ color: #cbd5e1;
+ white-space: pre-wrap;
+ word-break: break-word;
+}
+
+.terminal-input-bar {
+ background: rgba(10, 16, 31, 0.9);
+ border-top: 1px solid rgba(255, 255, 255, 0.06);
+ padding: 0.8rem 1.2rem;
+ display: flex;
+ align-items: center;
+ gap: 0.8rem;
+}
+
+.terminal-prompt {
+ color: var(--accent-cyan);
+ font-family: 'JetBrains Mono', monospace;
+ font-weight: 700;
+}
+
+.terminal-input {
+ flex: 1;
+ background: transparent;
+ border: none;
+ color: var(--text-main);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 0.9rem;
+ outline: none;
+}
+
+/* SIDE PANEL : METRIQUES EN DIRECT */
+.side-panel {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.gauge-box {
+ background: var(--bg-card);
+ border: 1px solid var(--border);
+ border-radius: 16px;
+ padding: 1.5rem;
+ backdrop-filter: blur(14px);
+}
+
+.gauge-box h4 {
+ font-size: 0.95rem;
+ font-weight: 700;
+ margin-bottom: 1rem;
+ display: flex;
+ justify-content: space-between;
+}
+
+.progress-bar-bg {
+ background: rgba(255, 255, 255, 0.05);
+ height: 10px;
+ border-radius: 100px;
+ overflow: hidden;
+ margin-bottom: 0.5rem;
+}
+
+.progress-bar-fill {
+ height: 100%;
+ border-radius: 100px;
+ background: linear-gradient(90deg, var(--accent-cyan), var(--accent-blue));
+ transition: width 0.5s cubic-bezier(0.16, 1, 0.3, 1);
+}
+
+/* MODAL CONFIG / TOKEN */
+.config-modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.85);
+ backdrop-filter: blur(12px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 999;
+}
+
+.config-modal.hidden {
+ display: none;
+}
+
+.modal-content {
+ background: var(--bg-surface);
+ border: 1px solid var(--border);
+ border-radius: 20px;
+ padding: 2.5rem;
+ max-width: 480px;
+ width: 90%;
+ box-shadow: var(--glow-cyan);
+}
+
+.modal-content h2 {
+ font-size: 1.5rem;
+ font-weight: 800;
+ margin-bottom: 0.8rem;
+}
+
+.modal-content p {
+ color: var(--text-muted);
+ font-size: 0.9rem;
+ margin-bottom: 1.5rem;
+ line-height: 1.5;
+}
+
+.input-field {
+ width: 100%;
+ background: rgba(0, 0, 0, 0.5);
+ border: 1px solid var(--border);
+ padding: 0.8rem 1rem;
+ border-radius: 10px;
+ color: var(--text-main);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 0.85rem;
+ margin-bottom: 1.2rem;
+ outline: none;
+}
+
+.input-field:focus {
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 10px rgba(56, 189, 248, 0.2);
+}
+
+.modal-btn {
+ width: 100%;
+ background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
+ border: none;
+ color: #000;
+ font-weight: 800;
+ padding: 0.9rem;
+ border-radius: 10px;
+ cursor: pointer;
+ font-size: 1rem;
+ transition: all 0.2s;
+}
+
+.modal-btn:hover {
+ filter: brightness(1.1);
+ box-shadow: var(--glow-cyan);
+}
+
+@media (max-width: 900px) {
+ .cockpit-grid {
+ grid-template-columns: 1fr;
+ }
+ .fleet-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
+ .terminal-window {
+ height: 450px;
+ }
+}