Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/views/break_escape/games/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<link rel="stylesheet" href="/break_escape/css/esd-pushbutton-minigame.css">
<link rel="stylesheet" href="/break_escape/css/command-board-minigame.css">
<link rel="stylesheet" href="/break_escape/css/infusion-pump-minigame.css">
<link rel="stylesheet" href="/break_escape/css/network-architecture-minigame.css">
<link rel="stylesheet" href="/break_escape/css/text-file-minigame.css">
<link rel="stylesheet" href="/break_escape/css/npc-barks.css">
<link rel="stylesheet" href="/break_escape/css/objectives.css">
Expand Down
314 changes: 314 additions & 0 deletions public/break_escape/css/network-architecture-minigame.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
/* =========================================================
NETWORK ARCHITECTURE DIAGRAM — MG-06
Purdue Model visualization. Dark industrial aesthetic.
Pixel-art style: no border-radius on UI chrome.
SVG nodes use rx:2 for diagram readability only.
========================================================= */

/* ── Container ─────────────────────────────────────────── */
.nad-minigame-container {
background: #070b14;
height: 100%;
box-sizing: border-box;
}

.nad-game-container {
height: 100%;
box-sizing: border-box;
}

.nad-wrap {
display: flex;
flex-direction: column;
height: 100%;
box-sizing: border-box;
background: #070b14;
}

/* ── Header ────────────────────────────────────────────── */
.nad-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 8px 14px;
background: #0a0f1e;
border-bottom: 2px solid #1e3a5a;
flex-shrink: 0;
flex-wrap: wrap;
}

.nad-title {
font-family: 'Press Start 2P', monospace;
font-size: 8px;
color: #e2e8f0;
letter-spacing: 0.5px;
line-height: 1.4;
}

/* ── Legend ────────────────────────────────────────────── */
.nad-legend {
display: flex;
align-items: center;
gap: 14px;
flex-wrap: wrap;
flex-shrink: 0;
}

.nad-leg-item {
display: flex;
align-items: center;
gap: 5px;
font-family: monospace;
font-size: 10px;
color: #94a3b8;
}

.nad-leg-line {
display: inline-block;
width: 28px;
height: 2px;
flex-shrink: 0;
}

.nad-leg-normal { background: #94a3b8; }
.nad-leg-boundary { background: #f59e0b; }
.nad-leg-legacy { background: #f97316;
background: repeating-linear-gradient(90deg, #f97316 0, #f97316 6px, transparent 6px, transparent 10px); }
.nad-leg-hardwired { background: #22c55e; }
.nad-leg-attack { background: #ef4444; }

/* ── Body ──────────────────────────────────────────────── */
.nad-body {
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
overflow: hidden;
}

.nad-svg-wrap {
flex: 1;
min-height: 0;
overflow: auto;
padding: 6px;
box-sizing: border-box;
}

.nad-svg {
display: block;
width: 100%;
height: auto;
min-width: 700px;
}

/* ── SVG: Zones ────────────────────────────────────────── */
.nad-zone {
/* fill and stroke set inline per zone */
}

.nad-zone-label {
font-family: 'Press Start 2P', monospace;
font-size: 6px;
fill: #64748b;
letter-spacing: 0.3px;
pointer-events: none;
}

/* ── SVG: Connection lines ─────────────────────────────── */
.nad-line {
fill: none;
stroke-width: 1.5;
transition: opacity 0.2s;
}

.nad-line-normal { stroke: #475569; }
.nad-line-boundary { stroke: #f59e0b; stroke-width: 2; }
.nad-line-legacy { stroke: #f97316; stroke-width: 2; }
.nad-line-hardwired { stroke: #22c55e; stroke-width: 2; }

/* Dim base lines when a path is active and they're not in it */
.nad-line:not(.nad-line-in-path) {
opacity: 1;
transition: opacity 0.25s;
}

.nad-line.nad-line-in-path {
opacity: 1;
}

.nad-line-label {
font-family: monospace;
font-size: 7px;
fill: #64748b;
text-anchor: middle;
pointer-events: none;
}

/* ── SVG: Attack path overlay lines ────────────────────── */
.nad-line-attack {
fill: none;
stroke: #ef4444;
stroke-width: 2.5;
stroke-dasharray: 10 6;
marker-end: url(#nad-arrow);
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}

.nad-line-attack.nad-path-active {
opacity: 1;
animation: nad-march 0.6s linear infinite;
}

@keyframes nad-march {
from { stroke-dashoffset: 0; }
to { stroke-dashoffset: -16; }
}

/* ── SVG: Node groups ──────────────────────────────────── */
.nad-node {
transition: opacity 0.25s;
}

.nad-node.nad-node-dim {
opacity: 0.3;
}

.nad-node-rect {
stroke-width: 1.5;
transition: stroke 0.2s, stroke-width 0.2s;
}

/* Zone colouring */
.nad-node-it .nad-node-rect { fill: #2a1515; stroke: #7f1d1d; }
.nad-node-ot .nad-node-rect { fill: #1a1a08; stroke: #78650a; }
.nad-node-safe .nad-node-rect{ fill: #0a1a0a; stroke: #15803d; }

/* Hover */
.nad-node:hover .nad-node-rect {
stroke: #e2e8f0;
stroke-width: 2;
}

/* Selected */
.nad-node.nad-node-selected .nad-node-rect {
stroke: #f59e0b;
stroke-width: 2.5;
}

/* Node text */
.nad-node-label {
font-family: monospace;
font-size: 9px;
fill: #e2e8f0;
text-anchor: middle;
pointer-events: none;
}

.nad-node-sub {
font-family: monospace;
font-size: 7px;
fill: #94a3b8;
text-anchor: middle;
pointer-events: none;
}

.nad-node-warn {
font-size: 9px;
fill: #f59e0b;
pointer-events: none;
}

/* ── Detail panel ──────────────────────────────────────── */
.nad-detail {
background: #0a0f1e;
border-top: 2px solid #1e3a5a;
padding: 10px 14px;
min-height: 110px;
max-height: 170px;
overflow-y: auto;
flex-shrink: 0;
box-sizing: border-box;
font-family: monospace;
font-size: 11px;
color: #94a3b8;
line-height: 1.5;
}

.nad-detail-hint {
color: #334155;
font-style: italic;
font-size: 11px;
padding: 8px 0;
}

.nad-detail-name {
font-family: 'Press Start 2P', monospace;
font-size: 8px;
color: #e2e8f0;
margin-bottom: 6px;
line-height: 1.5;
}

.nad-detail-desc {
color: #94a3b8;
margin-bottom: 8px;
}

.nad-detail-vuln {
background: #1c0a00;
border: 1px solid #92400e;
padding: 6px 8px;
margin-bottom: 8px;
}

.nad-detail-vuln-badge {
font-family: 'Press Start 2P', monospace;
font-size: 7px;
color: #f59e0b;
display: block;
margin-bottom: 4px;
}

.nad-detail-vuln-text {
color: #fbbf24;
font-size: 11px;
line-height: 1.5;
}

.nad-detail-paths-title {
font-family: 'Press Start 2P', monospace;
font-size: 7px;
color: #64748b;
margin-bottom: 6px;
letter-spacing: 0.3px;
}

.nad-detail-no-paths {
color: #334155;
font-style: italic;
}

.nad-detail-path {
border-left: 2px solid #ef4444;
padding-left: 8px;
margin-bottom: 6px;
}

.nad-path-label {
color: #ef4444;
font-weight: bold;
}

.nad-path-claim {
color: #f59e0b;
font-size: 10px;
}

.nad-path-desc {
color: #94a3b8;
font-size: 10px;
margin-top: 2px;
}
3 changes: 3 additions & 0 deletions public/break_escape/js/minigames/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { BackupRecoveryMinigame } from './backup-recovery/backup-recovery-miniga
export { CommandBoardMinigame } from './command-board/command-board-minigame.js';
export { EsdPushbuttonMinigame } from './esd-pushbutton/esd-pushbutton-minigame.js';
export { InfusionPumpMinigame } from './infusion-pump/infusion-pump-minigame.js';
export { NetworkArchitectureMinigame } from './network-architecture/network-architecture-minigame.js';

// Initialize the global minigame framework for backward compatibility
import { MinigameFramework } from './framework/minigame-manager.js';
Expand Down Expand Up @@ -96,6 +97,7 @@ import { SiemDashboardMinigame } from './siem/siem-dashboard-minigame.js';
import { EhrTerminalMinigame } from './ehr-terminal/ehr-terminal-minigame.js';
import { CommandBoardMinigame } from './command-board/command-board-minigame.js';
import { InfusionPumpMinigame } from './infusion-pump/infusion-pump-minigame.js';
import { NetworkArchitectureMinigame } from './network-architecture/network-architecture-minigame.js';

// Import ransomware display minigame
import { RansomwareDisplayMinigame } from './ransomware-display/ransomware-display-minigame.js';
Expand Down Expand Up @@ -130,6 +132,7 @@ MinigameFramework.registerScene('backup-recovery', BackupRecoveryMinigame);
MinigameFramework.registerScene('command-board', CommandBoardMinigame);
MinigameFramework.registerScene('esd-pushbutton', EsdPushbuttonMinigame);
MinigameFramework.registerScene('infusion-pump', InfusionPumpMinigame);
MinigameFramework.registerScene('network-architecture', NetworkArchitectureMinigame);

// Make minigame functions available globally
window.startNotesMinigame = startNotesMinigame;
Expand Down
Loading
Loading