feat: enhance scheduler functionality and UI improvements

- Updated scheduler.js to improve tab switching and content display.
- Refactored script fetching logic to handle new data structure.
- Enhanced schedule creation and editing with updated payload structure.
- Improved trigger testing and creation with consistent naming conventions.
- Added new CSS styles for actions and plugins pages to enhance UI/UX.
- Introduced responsive design adjustments for better mobile experience.
This commit is contained in:
infinition
2026-03-19 16:59:55 +01:00
parent b0584a1a8e
commit b541ec1f61
14 changed files with 2178 additions and 1286 deletions

View File

@@ -13,8 +13,10 @@
@import url("./pages/files.css");
@import url("./pages/compat.css");
@import url("./pages/backup.css");
@import url("./pages/actions.css");
@import url("./pages/actions-studio.css");
@import url("./pages/sentinel.css");
@import url("./pages/bifrost.css");
@import url("./pages/loki.css");
@import url("./pages/llm.css");
@import url("./pages/plugins.css");

688
web/css/pages/actions.css Normal file
View File

@@ -0,0 +1,688 @@
/* ==========================================================================
ACTIONS LAUNCHER (.actions-container)
Viewport-locked layout: sidebar + multi-console, no page-level scroll.
========================================================================== */
/* ── Root container ── */
.actions-container.page-with-sidebar {
--page-sidebar-w: 280px;
height: calc(100vh - var(--h-topbar, 56px) - var(--h-bottombar, 56px) - 24px);
max-height: calc(100vh - var(--h-topbar, 56px) - var(--h-bottombar, 56px) - 24px);
min-height: 0;
overflow: hidden;
}
/* ── Sidebar (locked to viewport, internally scrollable) ── */
.actions-container .al-sidebar.page-sidebar {
display: flex;
flex-direction: column;
max-height: 100%;
overflow: hidden;
}
.actions-container .sideheader {
padding: 8px 10px 6px;
border-bottom: 1px dashed var(--c-border);
flex-shrink: 0;
}
.actions-container .al-side-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 6px;
}
.actions-container .al-side-meta .sidetitle {
color: var(--acid);
font-weight: 800;
letter-spacing: .05em;
font-size: 13px;
}
/* ── Sidebar tabs ── */
.actions-container .tabs-container {
display: flex;
gap: 4px;
flex-wrap: nowrap;
padding: 0;
margin: 0;
border: none;
border-radius: 0;
background: transparent;
box-shadow: none;
min-height: 0;
position: static;
}
.actions-container .tab-btn {
all: unset;
cursor: pointer;
padding: 5px 10px;
border-radius: 8px;
background: var(--c-pill-bg, color-mix(in oklab, var(--c-panel-2) 70%, transparent));
border: 1px solid var(--c-border);
color: var(--muted);
font-size: 11px;
font-weight: 600;
white-space: nowrap;
transition: background .15s, color .15s;
}
.actions-container .tab-btn:hover {
color: var(--ink);
background: color-mix(in oklab, var(--c-panel-2) 90%, transparent);
}
.actions-container .tab-btn.active {
color: var(--acid);
background: var(--grad-chip-selected, color-mix(in oklab, var(--acid) 14%, var(--c-panel-2)));
border-color: color-mix(in oklab, var(--acid) 45%, transparent);
}
/* ── Search ── */
.actions-container .al-search {
display: flex;
gap: 8px;
padding: 6px 10px 8px;
}
.actions-container .al-input {
flex: 1;
background: var(--c-panel);
border: 1px solid var(--c-border-strong);
color: var(--ink);
padding: 6px 10px;
border-radius: var(--control-r, 8px);
font: inherit;
font-size: 12px;
}
.actions-container .al-input:focus {
outline: none;
box-shadow: 0 0 0 2px color-mix(in oklab, var(--acid) 55%, transparent) inset;
}
/* ── Sidebar content (scrollable area) ── */
.actions-container .sidecontent {
padding: 6px;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
flex: 1;
}
.actions-container .sidebar-page {
display: block;
}
/* ── Actions list ── */
.actions-container .al-list {
display: flex;
flex-direction: column;
gap: 4px;
}
/* ── Action row (compact) ── */
.actions-container .al-row {
position: relative;
display: grid;
grid-template-columns: 36px 1fr auto;
align-items: center;
gap: 8px;
padding: 6px 8px;
background: var(--c-panel-2);
border-radius: 8px;
cursor: pointer;
border: 1px solid transparent;
transition: background .12s, border-color .12s;
}
.actions-container .al-row:hover {
background: color-mix(in oklab, var(--c-panel-2) 80%, var(--acid) 6%);
border-color: color-mix(in oklab, var(--acid) 18%, transparent);
}
.actions-container .al-row.selected {
border-color: color-mix(in oklab, var(--acid) 40%, transparent);
background: color-mix(in oklab, var(--c-panel-2) 70%, var(--acid) 8%);
}
.actions-container .al-row .ic {
width: 36px;
height: 36px;
display: grid;
place-items: center;
border-radius: 6px;
background: var(--c-panel);
overflow: hidden;
flex-shrink: 0;
}
.actions-container .ic-img {
width: 28px;
height: 28px;
object-fit: cover;
display: block;
}
.actions-container .al-row > div:nth-child(2) {
min-width: 0;
display: flex;
flex-direction: column;
gap: 1px;
}
.actions-container .name {
font-weight: 700;
color: var(--acid-2, var(--acid));
font-size: 12px;
line-height: 1.2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.actions-container .desc {
color: var(--muted);
font-size: 11px;
line-height: 1.2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ── Status chip (inside row) ── */
.actions-container .al-row .chip {
position: static;
transform: none;
padding: 2px 6px;
border-radius: 999px;
border: 1px solid var(--c-border);
background: var(--c-chip-bg, color-mix(in oklab, var(--c-panel) 80%, transparent));
color: var(--muted);
font-size: 10px;
line-height: 1;
pointer-events: none;
white-space: nowrap;
flex-shrink: 0;
}
.actions-container .chip.ok {
color: var(--ok, #22c55e);
border-color: color-mix(in oklab, var(--ok, #22c55e) 50%, transparent);
}
.actions-container .chip.err {
color: var(--danger, #ef4444);
border-color: color-mix(in oklab, var(--danger, #ef4444) 50%, transparent);
}
.actions-container .chip.run {
color: var(--acid);
border-color: color-mix(in oklab, var(--acid) 50%, transparent);
}
/* ── Format badge for custom scripts ── */
.actions-container .al-row .format-badge {
font-size: 9px;
text-transform: uppercase;
letter-spacing: .04em;
background: color-mix(in oklab, var(--acid) 12%, transparent);
color: var(--acid);
border-color: color-mix(in oklab, var(--acid) 30%, transparent);
}
/* ── Section divider (Custom Scripts header) ── */
.actions-container .al-section-divider {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 8px 4px 4px;
margin-top: 4px;
}
.actions-container .al-section-title {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .06em;
color: var(--muted);
}
.actions-container .al-upload-btn {
font-size: 10px;
padding: 3px 8px;
}
.actions-container .al-delete-btn {
font-size: 12px;
padding: 2px 6px;
opacity: .5;
background: transparent;
border: none;
color: var(--muted);
cursor: pointer;
}
.actions-container .al-delete-btn:hover {
opacity: 1;
color: var(--danger, #ef4444);
}
/* ── Buttons (shared) ── */
.actions-container .al-btn {
background: var(--c-btn, var(--c-panel));
color: var(--ink);
border: 1px solid var(--c-border-strong);
border-radius: var(--control-r, 8px);
padding: 5px 10px;
display: inline-flex;
align-items: center;
gap: 6px;
cursor: pointer;
transition: .15s;
font: inherit;
font-size: 11px;
}
.actions-container .al-btn:hover {
background: color-mix(in oklab, var(--c-btn, var(--c-panel)) 85%, var(--acid) 15%);
border-color: color-mix(in oklab, var(--acid) 40%, var(--c-border-strong));
}
.actions-container .al-btn.warn {
background: linear-gradient(180deg, color-mix(in oklab, var(--warning, #f59e0b) 22%, var(--c-btn, var(--c-panel))), var(--c-btn, var(--c-panel)));
color: var(--warning, #f59e0b);
border-color: color-mix(in oklab, var(--warning, #f59e0b) 45%, var(--c-border));
}
/* ── Main area + center panel (fills viewport remainder) ── */
.actions-container #actionsLauncher {
min-height: 0;
height: 100%;
display: flex;
flex-direction: column;
}
.actions-container .panel {
background: var(--grad-card, var(--c-panel));
border: 1px solid var(--c-border);
border-radius: var(--radius, 12px);
box-shadow: var(--shadow);
overflow: hidden;
}
.actions-container .center {
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
flex: 1;
}
/* ── Toolbar (split selector) ── */
.actions-container .toolbar2 {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border-bottom: 1px solid var(--c-border);
background: var(--c-panel);
flex-shrink: 0;
}
.actions-container .spacer {
flex: 1;
}
.actions-container .seg {
display: flex;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--c-border);
}
.actions-container .seg button {
background: var(--c-panel);
color: var(--muted);
padding: 4px 10px;
border: none;
border-right: 1px solid var(--c-border);
cursor: pointer;
font: inherit;
font-size: 12px;
}
.actions-container .seg button:last-child {
border-right: none;
}
.actions-container .seg button.active {
color: var(--ink-invert, #000);
background: linear-gradient(90deg, var(--acid-2, var(--acid)), color-mix(in oklab, var(--acid-2, var(--acid)) 60%, white));
}
/* ── Multi-console grid (fills remaining height) ── */
.actions-container .multiConsole {
flex: 1;
padding: 8px;
display: grid;
gap: 8px;
min-height: 0;
grid-auto-flow: row;
grid-auto-rows: 1fr;
grid-template-rows: repeat(var(--rows, 1), 1fr);
overflow: hidden;
}
.actions-container .split-1 { grid-template-columns: 1fr; }
.actions-container .split-2 { grid-template-columns: 1fr 1fr; }
.actions-container .split-3 { grid-template-columns: 1fr 1fr 1fr; }
.actions-container .split-4 { grid-template-columns: 1fr 1fr; }
/* ── Console pane ── */
.actions-container .pane {
position: relative;
border: 1px solid var(--c-border);
border-radius: 10px;
background: var(--grad-console, var(--c-panel));
display: flex;
flex-direction: column;
min-height: 0;
overflow: hidden;
}
.actions-container .paneHeader {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 6px 8px;
border-bottom: 1px solid var(--c-border);
background: linear-gradient(180deg, color-mix(in oklab, var(--acid-2, var(--acid)) 6%, transparent), transparent);
flex-shrink: 0;
flex-wrap: wrap;
}
.actions-container .paneTitle {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
flex: 1;
}
.actions-container .paneTitle .dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.actions-container .paneIcon {
width: 28px;
height: 28px;
border-radius: 4px;
object-fit: cover;
flex-shrink: 0;
}
.actions-container .titleBlock {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.actions-container .titleLine strong {
font-size: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.actions-container .metaLine {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.actions-container .metaLine .chip {
position: static;
transform: none;
border: 1px solid var(--c-border-strong);
background: var(--c-chip-bg, color-mix(in oklab, var(--c-panel) 80%, transparent));
color: var(--muted);
padding: 1px 6px;
border-radius: 999px;
font-size: 10px;
}
.actions-container .paneBtns {
display: flex;
flex-wrap: wrap;
gap: 4px;
justify-content: flex-end;
flex-shrink: 0;
}
.actions-container .paneBtns .al-btn {
padding: 3px 7px;
font-size: 10px;
}
/* ── Log output ── */
.actions-container .paneLog {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 4px 8px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
font-size: 11px;
min-height: 0;
}
.actions-container .logline {
white-space: pre-wrap;
word-break: break-word;
padding: 2px 4px;
line-height: 1.35;
color: var(--ink);
}
.actions-container .logline.info { color: #bfefff; }
.actions-container .logline.ok { color: #9ff7c5; }
.actions-container .logline.warn { color: #ffd27a; }
.actions-container .logline.err { color: #ff99b3; }
.actions-container .logline.dim { color: #6a8596; }
/* ── Pane drag highlight ── */
.actions-container .paneHighlight {
box-shadow:
0 0 0 2px var(--acid-2, var(--acid)),
0 0 20px color-mix(in oklab, var(--acid-2, var(--acid)) 40%, transparent) inset;
animation: al-hi 700ms ease-out 1;
}
@keyframes al-hi {
0% { transform: scale(1); }
50% { transform: scale(1.005); }
100% { transform: scale(1); }
}
/* ── Arguments tab ── */
.actions-container .section {
padding: 10px;
border-bottom: 1px dashed var(--c-border);
}
.actions-container .h {
font-weight: 800;
letter-spacing: .5px;
color: var(--acid-2, var(--acid));
font-size: 13px;
}
.actions-container .sub {
color: var(--muted);
font-size: 11px;
}
.actions-container .builder {
padding: 10px;
display: grid;
gap: 10px;
}
.actions-container .field {
display: grid;
gap: 4px;
}
.actions-container .label {
font-size: 11px;
color: var(--muted);
}
.actions-container .ctl,
.actions-container .select,
.actions-container .range {
background: var(--c-panel);
color: var(--ink);
border: 1px solid var(--c-border-strong);
border-radius: var(--control-r, 8px);
padding: 6px 10px;
font: inherit;
font-size: 12px;
}
.actions-container .ctl:focus,
.actions-container .select:focus {
outline: none;
box-shadow: 0 0 0 2px color-mix(in oklab, var(--acid) 55%, transparent) inset;
}
.actions-container .chips {
display: flex;
gap: 6px;
flex-wrap: wrap;
padding: 8px 10px;
}
.actions-container .chip2 {
padding: 4px 10px;
border-radius: 999px;
background: var(--c-chip-bg, color-mix(in oklab, var(--c-panel) 80%, transparent));
border: 1px solid var(--c-border-hi, var(--c-border-strong));
cursor: pointer;
font-size: 11px;
transition: .15s;
}
.actions-container .chip2:hover {
border-color: color-mix(in oklab, var(--acid) 50%, var(--c-border));
color: var(--acid);
}
/* ── Mobile responsive ── */
@media (max-width: 860px) {
.actions-container.page-with-sidebar {
height: calc(100vh - var(--h-topbar, 56px) - var(--h-bottombar, 56px) - 12px);
max-height: calc(100vh - var(--h-topbar, 56px) - var(--h-bottombar, 56px) - 12px);
}
.actions-container #actionsLauncher {
min-height: 0;
}
.actions-container .toolbar2 {
display: none !important;
}
.actions-container .paneHeader {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.actions-container .paneBtns {
justify-content: flex-start;
width: 100%;
}
.actions-container .paneBtns .al-btn {
padding: 3px 6px;
font-size: 10px;
}
.actions-container .multiConsole {
padding: 6px;
}
}
/* ===== Per-Pane Focus ===== */
.actions-container .pane.paneFocused {
border-color: color-mix(in oklab, var(--acid) 40%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--acid) 15%, transparent);
}
.args-pane-label {
font-size: 11px;
font-weight: 700;
color: var(--acid);
padding: 4px 0 6px;
border-bottom: 1px solid var(--c-border);
margin-bottom: 6px;
}
/* ===== Custom Scripts Split Layout ===== */
.actions-container #tab-actions.al-split-layout {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
overflow: hidden;
}
.actions-container .al-builtins-scroll {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
}
.actions-container .al-custom-section {
flex-shrink: 0;
max-height: 180px;
border-top: 1px dashed var(--c-border);
display: flex;
flex-direction: column;
}
.actions-container .al-custom-scroll {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
}
.actions-container .al-section-divider {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 10px;
background: color-mix(in oklab, var(--c-panel-2, var(--c-panel)) 50%, transparent);
flex-shrink: 0;
}
.actions-container .al-section-title {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--muted);
}

View File

@@ -1768,9 +1768,7 @@
}
/* ---- Final parity aliases ---- */
.actions-container .sidebar-page {
display: block;
}
/* .actions-container .sidebar-page moved to actions.css */
.vuln-container.page-with-sidebar {
--page-sidebar-w: 300px;

View File

@@ -1622,514 +1622,7 @@
}
}
/* ==========================================================================
ACTIONS LAUNCHER (.actions-container)
========================================================================== */
.actions-container #actionsLauncher {
min-height: 0;
height: 100%;
display: grid;
grid-template-columns: 1fr;
gap: var(--gap-3, 10px);
}
.actions-container .panel {
background: var(--grad-card, var(--c-panel));
border: 1px solid var(--c-border);
border-radius: var(--radius, 14px);
box-shadow: var(--elev, 0 10px 30px var(--acid-1a, #00ff9a1a), inset 0 0 0 1px var(--acid-22, #00ff9a22));
overflow: clip;
}
.actions-container .sideheader {
padding: 10px 10px 6px;
border-bottom: 1px dashed var(--c-border);
}
.actions-container .al-side-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 8px;
}
.actions-container .al-side-meta .sidetitle {
color: var(--acid);
font-weight: 800;
letter-spacing: .05em;
}
.actions-container .tabs-container {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.actions-container .tab-btn {
all: unset;
cursor: pointer;
padding: 6px 10px;
border-radius: 10px;
background: var(--c-pill-bg);
border: 1px solid var(--c-border);
color: var(--muted);
}
.actions-container .tab-btn.active {
background: var(--grad-chip-selected);
outline: 2px solid color-mix(in oklab, var(--acid) 55%, transparent);
outline-offset: 0;
}
.actions-container .al-search {
display: flex;
gap: 10px;
padding: 10px;
}
.actions-container .al-input {
flex: 1;
background: var(--c-panel);
border: 1px solid var(--c-border-strong);
color: var(--ink);
padding: 10px 12px;
border-radius: var(--control-r, 10px);
font: inherit;
}
.actions-container .al-input:focus {
outline: none;
box-shadow: 0 0 0 2px color-mix(in oklab, var(--acid) 55%, transparent) inset;
}
.actions-container .sidecontent {
padding: 8px;
overflow: auto;
}
.actions-container .al-list {
display: flex;
flex-direction: column;
gap: 10px;
padding-right: 4px;
}
.actions-container .al-row {
position: relative;
display: grid;
grid-template-columns: 84px 1fr;
gap: 12px;
padding: 10px;
background: var(--c-panel-2);
border-radius: 12px;
cursor: pointer;
transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.actions-container .al-row:hover {
transform: translateY(-1px);
border-color: color-mix(in oklab, var(--accent) 25%, var(--c-border));
box-shadow: 0 10px 26px var(--glow-weak);
}
.actions-container .al-row.selected {
outline: 2px solid color-mix(in oklab, var(--acid) 35%, transparent);
box-shadow: 0 12px 30px color-mix(in oklab, var(--acid) 25%, transparent);
}
.actions-container .al-row .ic {
width: 84px;
height: 84px;
display: grid;
place-items: center;
border-radius: 12px;
background: var(--c-panel);
overflow: hidden;
}
.actions-container .ic-img {
width: 70px;
height: 70px;
object-fit: cover;
display: block;
}
.actions-container .al-row>div:nth-child(2) {
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
}
.actions-container .name {
font-weight: 800;
color: var(--acid-2);
font-size: 14px;
line-height: 1.2;
}
.actions-container .desc {
color: var(--muted);
font-size: 13px;
line-height: 1.25;
}
.actions-container .al-row .chip {
position: absolute;
top: 6px;
left: calc(84px/2 + 10px);
transform: translateX(-50%);
padding: 2px 8px;
border-radius: 999px;
border: 1px solid var(--c-border);
background: var(--c-chip-bg);
color: var(--muted);
font-size: 11px;
line-height: 1;
pointer-events: none;
}
.actions-container .chip.ok {
color: var(--ok);
border-color: color-mix(in oklab, var(--ok) 60%, transparent);
}
.actions-container .chip.err {
color: var(--danger);
border-color: color-mix(in oklab, var(--danger) 60%, transparent);
}
.actions-container .chip.run {
color: var(--acid);
border-color: color-mix(in oklab, var(--acid) 60%, transparent);
}
.actions-container .center {
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
}
.actions-container .toolbar2 {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
border-bottom: 1px solid var(--c-border);
background: var(--c-panel);
flex-wrap: wrap;
}
.actions-container .seg {
display: flex;
border-radius: 10px;
overflow: hidden;
border: 1px solid var(--c-border);
}
.actions-container .seg button {
background: var(--c-panel);
color: var(--muted);
padding: 8px 10px;
border: none;
border-right: 1px solid var(--c-border);
cursor: pointer;
font: inherit;
}
.actions-container .seg button:last-child {
border-right: none;
}
.actions-container .seg button.active {
color: var(--ink-invert);
background: linear-gradient(90deg, var(--acid-2), color-mix(in oklab, var(--acid-2) 60%, white));
}
.actions-container .al-btn {
background: var(--c-btn);
color: var(--ink);
border: 1px solid var(--c-border-strong);
border-radius: var(--control-r, 10px);
padding: 8px 12px;
display: inline-flex;
align-items: center;
gap: 8px;
cursor: pointer;
transition: .18s;
box-shadow: var(--elev);
font: inherit;
}
.actions-container .al-btn:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-hover);
}
.actions-container .al-btn.warn {
background: linear-gradient(180deg, color-mix(in oklab, var(--warning) 28%, var(--c-btn)), var(--c-btn));
color: var(--warning);
border-color: color-mix(in oklab, var(--warning) 55%, var(--c-border));
}
.actions-container .multiConsole {
flex: 1;
padding: 10px;
display: grid;
gap: 10px;
height: 100%;
grid-auto-flow: row;
grid-auto-rows: 1fr;
grid-template-rows: repeat(var(--rows, 1), 1fr);
}
.actions-container .split-1 {
grid-template-columns: 1fr;
}
.actions-container .split-2 {
grid-template-columns: 1fr 1fr;
}
.actions-container .split-3 {
grid-template-columns: 1fr 1fr 1fr;
}
.actions-container .split-4 {
grid-template-columns: 1fr 1fr;
}
.actions-container .pane {
position: relative;
border: 1px solid var(--c-border);
border-radius: 12px;
background: var(--grad-console);
display: flex;
flex-direction: column;
box-shadow: inset 0 0 0 1px var(--c-border-muted);
}
.actions-container .paneHeader {
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
gap: 10px;
padding: 8px 10px;
border-bottom: 1px solid var(--c-border);
background: linear-gradient(180deg, color-mix(in oklab, var(--acid-2) 8%, transparent), transparent);
}
.actions-container .paneTitle {
display: grid;
grid-template-columns: auto auto 1fr;
align-items: center;
gap: 10px;
min-width: 0;
}
.actions-container .paneTitle .dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex: 0 0 auto;
}
.actions-container .paneIcon {
width: 70px;
height: 70px;
border-radius: 6px;
object-fit: cover;
opacity: .95;
}
.actions-container .titleBlock {
display: flex;
flex-direction: column;
gap: 4px;
min-width: 0;
}
.actions-container .titleLine strong {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.actions-container .metaLine {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.actions-container .metaLine .chip {
border: 1px solid var(--c-border-strong);
background: var(--c-chip-bg);
color: var(--muted);
padding: 3px 8px;
border-radius: 999px;
}
.actions-container .paneBtns {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: flex-end;
}
.actions-container .paneBtns .al-btn {
padding: 6px 8px;
font-size: .9rem;
}
.actions-container .paneLog {
flex: 1;
overflow: auto;
padding: 6px 8px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
font-size: .92rem;
}
.actions-container .logline {
white-space: pre-wrap;
word-break: break-word;
padding: 4px 6px;
line-height: 1.32;
color: var(--ink);
}
.actions-container .logline.info {
color: #bfefff;
}
.actions-container .logline.ok {
color: #9ff7c5;
}
.actions-container .logline.warn {
color: #ffd27a;
}
.actions-container .logline.err {
color: #ff99b3;
}
.actions-container .logline.dim {
color: #6a8596;
}
.actions-container .paneHighlight {
box-shadow: 0 0 0 2px var(--acid-2), 0 0 24px color-mix(in oklab, var(--acid-2) 55%, transparent) inset, 0 0 40px color-mix(in oklab, var(--acid-2) 35%, transparent);
animation: al-hi 900ms ease-out 1;
}
@keyframes al-hi {
0% {
transform: scale(1);
}
50% {
transform: scale(1.01);
}
100% {
transform: scale(1);
}
}
.actions-container .section {
padding: 12px;
border-bottom: 1px dashed var(--c-border);
}
.actions-container .h {
font-weight: 800;
letter-spacing: .5px;
color: var(--acid-2);
}
.actions-container .sub {
color: var(--muted);
font-size: .9rem;
}
.actions-container .builder {
padding: 12px;
display: grid;
gap: 12px;
}
.actions-container .field {
display: grid;
gap: 6px;
}
.actions-container .label {
font-size: .85rem;
color: var(--muted);
}
.actions-container .ctl,
.actions-container .select,
.actions-container .range {
background: var(--c-panel);
color: var(--ink);
border: 1px solid var(--c-border-strong);
border-radius: var(--control-r, 10px);
padding: 10px 12px;
font: inherit;
}
.actions-container .ctl:focus,
.actions-container .select:focus {
outline: none;
box-shadow: 0 0 0 2px color-mix(in oklab, var(--acid) 55%, transparent) inset;
}
.actions-container .chips {
display: flex;
gap: 8px;
flex-wrap: wrap;
padding: 10px;
}
.actions-container .chip2 {
padding: 6px 10px;
border-radius: 999px;
background: var(--c-chip-bg);
border: 1px solid var(--c-border-hi);
cursor: pointer;
transition: .18s;
}
.actions-container .chip2:hover {
box-shadow: 0 0 0 1px var(--c-border-hi) inset, 0 8px 22px var(--glow-weak);
}
@media (max-width: 860px) {
.actions-container #actionsLauncher {
grid-template-columns: 1fr;
}
.actions-container .toolbar2 {
display: none !important;
}
.actions-container .paneHeader {
grid-template-columns: 1fr;
row-gap: 8px;
}
.actions-container .paneBtns {
justify-content: flex-start;
}
.actions-container .paneBtns .al-btn {
padding: 5px 6px;
font-size: .85rem;
}
}
/* Actions launcher styles moved to actions.css */
/* ==========================================================================
ACTIONS STUDIO (.studio-container)

277
web/css/pages/plugins.css Normal file
View File

@@ -0,0 +1,277 @@
/* ==========================================================================
PLUGINS PAGE
========================================================================== */
.plugins-page {
padding: 1rem;
max-width: 900px;
margin: 0 auto;
}
.plugins-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: .5rem;
}
.plugins-header h1 {
font-size: 1.4rem;
font-weight: 800;
margin: 0;
color: var(--ink);
}
.plugins-actions {
display: flex;
gap: 6px;
}
.plugins-actions .btn {
padding: 5px 14px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: var(--c-panel);
color: var(--ink);
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.plugins-actions .btn:hover { border-color: var(--acid); color: var(--acid); }
.plugins-actions .btn-primary {
background: color-mix(in oklab, var(--acid) 15%, transparent);
border-color: var(--acid);
color: var(--acid);
}
.plugins-actions .btn-primary:hover { background: color-mix(in oklab, var(--acid) 25%, transparent); }
.plugins-count {
color: var(--muted);
font-size: 12px;
margin: 0 0 12px;
}
.plugins-empty {
text-align: center;
color: var(--muted);
padding: 2rem;
font-size: 13px;
}
.plugins-grid {
display: flex;
flex-direction: column;
gap: 8px;
}
/* ===== Plugin card ===== */
.plugin-card {
border: 1px solid var(--c-border);
border-radius: 10px;
background: var(--c-panel);
padding: 12px 14px;
display: flex;
flex-direction: column;
gap: 6px;
transition: border-color .15s;
}
.plugin-card:hover { border-color: var(--c-border-strong); }
.plugin-card.plugin-disabled { opacity: .55; }
.plugin-card-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.plugin-card-title {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.plugin-card-title strong {
font-size: 13px;
color: var(--ink);
}
.plugin-type-badge {
display: inline-block;
padding: 1px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
background: color-mix(in oklab, var(--acid) 15%, transparent);
color: var(--acid);
}
.badge-action { background: color-mix(in oklab, #3b82f6 15%, transparent); color: #3b82f6; }
.badge-notifier { background: color-mix(in oklab, #f59e0b 15%, transparent); color: #f59e0b; }
.badge-enricher { background: color-mix(in oklab, #8b5cf6 15%, transparent); color: #8b5cf6; }
.badge-exporter { background: color-mix(in oklab, #06b6d4 15%, transparent); color: #06b6d4; }
.badge-widget { background: color-mix(in oklab, #ec4899 15%, transparent); color: #ec4899; }
.plugin-status {
font-size: 10px;
font-weight: 600;
padding: 1px 6px;
border-radius: 3px;
}
.plugin-status.status-loaded { background: color-mix(in oklab, #22c55e 18%, transparent); color: #22c55e; }
.plugin-status.status-disabled { background: color-mix(in oklab, var(--muted) 15%, transparent); color: var(--muted); }
.plugin-status.status-error { background: color-mix(in oklab, #ef4444 18%, transparent); color: #ef4444; }
.plugin-status.status-missing { background: color-mix(in oklab, #f59e0b 18%, transparent); color: #f59e0b; }
.plugin-card-info { font-size: 12px; }
.plugin-desc { color: var(--ink); margin: 0 0 4px; line-height: 1.4; }
.plugin-meta { color: var(--muted); font-size: 11px; display: flex; gap: 8px; }
.plugin-hooks {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.hook-badge {
padding: 1px 6px;
border: 1px solid var(--c-border);
border-radius: 3px;
font-size: 10px;
color: var(--muted);
font-family: monospace;
}
.plugin-error {
padding: 6px 8px;
background: color-mix(in oklab, #ef4444 10%, transparent);
border: 1px solid color-mix(in oklab, #ef4444 30%, transparent);
border-radius: 5px;
color: #fca5a5;
font-size: 11px;
}
.plugin-deps-warn {
padding: 4px 8px;
background: color-mix(in oklab, #f59e0b 10%, transparent);
border: 1px solid color-mix(in oklab, #f59e0b 30%, transparent);
border-radius: 5px;
color: #fcd34d;
font-size: 11px;
}
.plugin-card-actions {
display: flex;
gap: 4px;
margin-top: 2px;
}
.plugin-card-actions button {
padding: 4px 10px;
border: 1px solid var(--c-border);
border-radius: 5px;
background: transparent;
color: var(--muted);
font-size: 11px;
cursor: pointer;
}
.plugin-card-actions button:hover { color: var(--ink); border-color: var(--c-border-strong); }
.plugin-card-actions .btn-danger { color: #ef4444; border-color: color-mix(in oklab, #ef4444 40%, transparent); }
.plugin-card-actions .btn-danger:hover { background: color-mix(in oklab, #ef4444 12%, transparent); }
/* ===== Plugin toggle ===== */
.plugin-toggle {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
cursor: pointer;
flex-shrink: 0;
}
.plugin-toggle input { opacity: 0; width: 0; height: 0; position: absolute; }
.plugin-toggle-track {
position: absolute;
inset: 0;
border-radius: 10px;
background: var(--c-border);
transition: background .2s;
}
.plugin-toggle-track::before {
content: '';
position: absolute;
width: 16px;
height: 16px;
left: 2px;
bottom: 2px;
border-radius: 50%;
background: var(--ink);
transition: transform .2s;
}
.plugin-toggle input:checked + .plugin-toggle-track { background: var(--acid); }
.plugin-toggle input:checked + .plugin-toggle-track::before { transform: translateX(16px); }
/* ===== Config modal ===== */
.plugin-config-overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.plugin-config-modal {
width: min(600px, 90vw);
max-height: 80vh;
background: var(--panel);
border: 1px solid var(--c-border-strong);
border-radius: 12px;
box-shadow: 0 20px 56px rgba(0,0,0,.6);
display: flex;
flex-direction: column;
overflow: hidden;
}
.plugin-config-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
border-bottom: 1px solid var(--c-border);
font-weight: 700;
}
.plugin-config-body {
padding: 14px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px;
}
.plugin-config-field label {
display: flex;
flex-direction: column;
gap: 3px;
font-size: 11px;
color: var(--muted);
font-weight: 600;
}
.plugin-config-field input,
.plugin-config-field select,
.plugin-config-field textarea {
padding: 5px 8px;
border: 1px solid var(--c-border);
border-radius: 5px;
background: var(--bg);
color: var(--ink);
font-size: 12px;
width: 100%;
}
.plugin-config-footer {
display: flex;
justify-content: flex-end;
gap: 6px;
padding: 10px 14px;
border-top: 1px solid var(--c-border);
}
/* Hidden file input for plugin install */
.plugins-page input[type="file"] { display: none; }

View File

@@ -976,3 +976,297 @@
}
}
/* ===== Schedules & Triggers form panels ===== */
.schedules-panel,
.triggers-panel {
display: flex;
flex-direction: column;
gap: 12px;
}
.schedules-form,
.triggers-form {
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px 14px;
border: 1px solid var(--c-border);
border-radius: 10px;
background: var(--c-panel);
}
.schedules-form h3,
.triggers-form h3 {
margin: 0 0 4px;
font-size: 13px;
font-weight: 700;
color: var(--acid);
}
.schedules-form .form-row,
.triggers-form .form-row {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.schedules-form label,
.triggers-form label {
font-size: 11px;
color: var(--muted);
font-weight: 600;
min-width: 110px;
}
.schedules-form input,
.schedules-form select,
.triggers-form input,
.triggers-form select {
padding: 5px 8px;
border: 1px solid var(--c-border);
border-radius: 5px;
background: var(--bg);
color: var(--ink);
font-size: 12px;
}
.schedules-form input:focus,
.triggers-form input:focus,
.schedules-form select:focus,
.triggers-form select:focus {
outline: 1px solid var(--acid);
border-color: var(--acid);
}
/* Toggle switch (used in schedule/trigger cards) */
.scheduler-container .toggle-switch {
position: relative;
display: inline-block;
width: 32px;
height: 18px;
cursor: pointer;
flex-shrink: 0;
}
.scheduler-container .toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.scheduler-container .toggle-slider {
position: absolute;
inset: 0;
border-radius: 9px;
background: var(--c-border);
transition: background .2s;
}
.scheduler-container .toggle-slider::before {
content: '';
position: absolute;
width: 14px;
height: 14px;
left: 2px;
bottom: 2px;
border-radius: 50%;
background: var(--ink);
transition: transform .2s;
}
.scheduler-container .toggle-switch input:checked + .toggle-slider { background: var(--acid); }
.scheduler-container .toggle-switch input:checked + .toggle-slider::before { transform: translateX(14px); }
/* ===== Condition builder ===== */
.cond-editor {
border: 1px solid var(--c-border);
border-radius: 8px;
padding: 8px;
background: color-mix(in oklab, var(--bg) 80%, var(--c-panel));
}
.cond-group {
border-left: 3px solid var(--acid);
padding: 6px 8px;
margin: 4px 0;
border-radius: 4px;
background: color-mix(in oklab, var(--acid) 4%, transparent);
}
.cond-group-or { border-left-color: #f59e0b; background: color-mix(in oklab, #f59e0b 4%, transparent); }
.cond-group-header {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 6px;
}
.cond-op-toggle {
padding: 2px 6px;
border: 1px solid var(--c-border);
border-radius: 4px;
background: var(--bg);
color: var(--acid);
font-size: 11px;
font-weight: 700;
}
.cond-children {
display: flex;
flex-direction: column;
gap: 4px;
}
.cond-item-wrapper {
display: flex;
align-items: flex-start;
gap: 4px;
}
.cond-item-wrapper > :first-child { flex: 1; }
.cond-delete-btn {
background: transparent;
border: 1px solid var(--c-border);
border-radius: 4px;
color: #ef4444;
cursor: pointer;
padding: 2px 6px;
font-size: 12px;
line-height: 1;
flex-shrink: 0;
margin-top: 2px;
}
.cond-delete-btn:hover { background: color-mix(in oklab, #ef4444 15%, transparent); }
.cond-block {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
padding: 4px 8px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: var(--c-panel);
}
.cond-source-select {
padding: 3px 6px;
border: 1px solid var(--c-border);
border-radius: 4px;
background: var(--bg);
color: var(--ink);
font-size: 11px;
}
.cond-params {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.cond-param-label {
display: flex;
align-items: center;
gap: 3px;
font-size: 10px;
color: var(--muted);
}
.cond-param-name { font-weight: 600; }
.cond-param-input {
padding: 3px 6px;
border: 1px solid var(--c-border);
border-radius: 4px;
background: var(--bg);
color: var(--ink);
font-size: 11px;
width: 80px;
}
.cond-param-input[type="number"] { width: 60px; }
.cond-add-btn {
padding: 3px 10px;
border: 1px dashed var(--c-border);
border-radius: 4px;
background: transparent;
color: var(--muted);
font-size: 11px;
cursor: pointer;
}
.cond-add-btn:hover { color: var(--acid); border-color: var(--acid); }
.cond-group-actions {
display: flex;
gap: 4px;
margin-top: 4px;
}
/* ===== Packages tab (in Actions page) ===== */
.pkg-install-form {
display: flex;
gap: 6px;
align-items: center;
padding: 8px 0;
}
.pkg-install-form input {
flex: 1;
padding: 5px 8px;
border: 1px solid var(--c-border);
border-radius: 5px;
background: var(--bg);
color: var(--ink);
font-size: 12px;
}
.pkg-install-btn {
padding: 5px 12px;
border: 1px solid var(--acid);
border-radius: 5px;
background: color-mix(in oklab, var(--acid) 15%, transparent);
color: var(--acid);
font-weight: 600;
cursor: pointer;
font-size: 12px;
}
.pkg-install-btn:hover { background: color-mix(in oklab, var(--acid) 25%, transparent); }
.pkg-console {
background: #0a0d10;
border: 1px solid var(--c-border);
border-radius: 6px;
padding: 8px;
font-family: monospace;
font-size: 11px;
color: var(--acid);
max-height: 200px;
overflow-y: auto;
white-space: pre-wrap;
display: none;
}
.pkg-console.active { display: block; }
.pkg-list {
list-style: none;
padding: 0;
margin: 8px 0 0;
display: flex;
flex-direction: column;
gap: 4px;
}
.pkg-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 10px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: var(--c-panel);
font-size: 12px;
}
.pkg-item .pkg-name { font-weight: 600; color: var(--ink); }
.pkg-item .pkg-version { color: var(--muted); font-size: 11px; }
.pkg-item .pkg-uninstall {
padding: 2px 8px;
border: 1px solid #ef4444;
border-radius: 4px;
background: transparent;
color: #ef4444;
font-size: 10px;
cursor: pointer;
}
.pkg-item .pkg-uninstall:hover { background: color-mix(in oklab, #ef4444 15%, transparent); }

View File

@@ -1,493 +1,9 @@
/* ==========================================================================
ZOMBIELAND (C2 Module) CSS
ZOMBIELAND C2 Dashboard (pages/ copy)
NOTE: The authoritative version lives at /web/css/zombieland.css and is
loaded dynamically by zombieland.js via loadStylesheet().
This file is kept in sync for consistency but is NOT imported in pages.css
because the JS handles its own stylesheet lifecycle.
========================================================================== */
/* Main layout constraints */
.zombieland-container.page-with-sidebar {
height: calc(100vh - var(--h-topbar, 56px) - var(--h-bottombar, 56px) - 24px);
display: flex;
min-height: 0;
}
.zl-sidebar.page-sidebar {
width: 260px;
flex-shrink: 0;
display: flex;
flex-direction: column;
background: var(--grad-card);
border: 1px solid var(--c-border);
border-radius: 12px;
overflow-y: auto;
}
.zl-main.page-main {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 12px;
}
/* Sidebar structure */
.zl-stats-grid {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
margin-bottom: 15px;
}
.stat-item {
background: rgba(0, 0, 0, 0.2);
border: 1px solid var(--c-border);
padding: 10px;
border-radius: 8px;
display: flex;
justify-content: space-between;
align-items: center;
}
.stat-item .stat-value {
font-weight: bold;
color: var(--acid);
font-size: 1.1rem;
}
.stat-item .stat-label {
font-size: 0.8rem;
color: var(--muted);
text-transform: uppercase;
}
.zl-toolbar {
display: flex;
flex-direction: column;
gap: 6px;
}
/* Modals */
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background: var(--grad-card);
border: 1px solid var(--c-border);
padding: 20px;
border-radius: 12px;
width: 100%;
max-width: 400px;
}
/* Main Grid Layout */
.zl-main-grid {
display: grid;
grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
gap: 12px;
flex: 1;
/* Takes available space except logs */
min-height: 0;
}
.zl-console-panel,
.zl-agents-panel,
.zl-logs-panel {
border: 1px solid var(--c-border);
border-radius: 12px;
background: var(--c-panel);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* Log Panel underneath */
.zl-logs-panel {
height: 150px;
flex-shrink: 0;
}
.zl-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
background: rgba(0, 0, 0, 0.2);
border-bottom: 1px solid var(--c-border);
flex-shrink: 0;
}
.zl-panel-title {
font-weight: bold;
font-size: 0.9rem;
color: var(--acid);
}
.zl-quickbar {
display: flex;
gap: 4px;
}
.quick-cmd {
background: transparent;
border: 1px solid var(--c-border-strong);
color: var(--muted);
font-size: 0.7rem;
padding: 2px 6px;
border-radius: 4px;
cursor: pointer;
transition: 0.2s;
}
.quick-cmd:hover {
color: var(--acid);
border-color: var(--acid);
}
.zl-console-output,
.zl-logs-output {
flex: 1;
overflow-y: auto;
padding: 10px;
font-family: 'Fira Code', monospace;
font-size: 0.8rem;
background: #020406;
min-height: 0;
}
/* Controls */
.zl-console-input-row {
display: flex;
gap: 8px;
padding: 8px;
border-top: 1px solid var(--c-border);
background: var(--c-panel-2);
flex-shrink: 0;
}
.zl-target-select,
.zl-cmd-input,
.zl-search-input {
background: #000;
color: #fff;
border: 1px solid var(--c-border-strong);
padding: 6px 10px;
border-radius: 6px;
}
.zl-cmd-input {
flex: 1;
}
.zl-toolbar-left {
display: flex;
position: relative;
flex: 1;
max-width: 200px;
margin-left: 10px;
}
.zl-search-input {
width: 100%;
border-radius: 6px;
padding: 4px 20px 4px 8px;
font-size: 0.8rem;
}
.zl-search-clear {
position: absolute;
right: 5px;
top: 5px;
color: var(--muted);
background: none;
border: none;
cursor: pointer;
}
.zl-agents-list {
flex: 1;
overflow-y: auto;
padding: 10px;
display: flex;
flex-direction: column;
gap: 8px;
}
/* Agent Card Styles */
.zl-agent-card {
background: rgba(0, 0, 0, 0.3);
border: 1px solid var(--c-border);
border-radius: 8px;
padding: 8px 12px;
display: flex;
flex-direction: column;
gap: 6px;
transition: 0.2s ease-out;
}
.zl-agent-card.selected {
border-color: var(--acid);
background: rgba(0, 255, 160, 0.05);
}
.zl-agent-card:hover {
border-color: var(--c-border-hi);
}
.zl-card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.zl-card-identity {
display: flex;
flex-direction: column;
gap: 2px;
line-height: 1;
}
.zl-card-hostname {
font-weight: bold;
color: #fff;
font-size: 0.9rem;
}
.zl-card-id {
font-size: 0.7rem;
color: var(--muted);
}
.zl-pill {
padding: 2px 8px;
border-radius: 12px;
font-size: 0.7rem;
font-weight: bold;
background: #222;
}
.zl-pill.online {
color: #00ffa0;
background: rgba(0, 255, 160, 0.1);
}
.zl-pill.idle {
color: #ffcc00;
background: rgba(255, 204, 0, 0.1);
}
.zl-pill.offline {
color: #ff3333;
background: rgba(255, 51, 51, 0.1);
}
/* ECG Animation */
.zl-ecg-row {
display: flex;
align-items: center;
gap: 8px;
}
.ecg {
width: 100%;
height: 24px;
max-width: 140px;
position: relative;
overflow: hidden;
background: rgba(0, 0, 0, 0.5);
border-radius: 6px;
border: 1px solid #111;
}
.ecg-wrapper {
display: flex;
width: 300%;
animation: ecg-slide linear infinite;
}
.ecg svg {
width: 33.33%;
height: 100%;
}
.ecg path {
fill: none;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
}
.ecg.green path {
stroke: #00ffa0;
filter: drop-shadow(0 0 2px #00ffa0);
}
.ecg.yellow path {
stroke: #ffcc00;
filter: drop-shadow(0 0 2px #ffcc00);
}
.ecg.orange path {
stroke: #ff8800;
filter: drop-shadow(0 0 2px #ff8800);
}
.ecg.red path {
stroke: #ff3333;
}
.ecg.flat .ecg-wrapper {
animation: none;
}
@keyframes ecg-slide {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-33.33%);
}
}
.zl-ecg-counter {
font-size: 0.7rem;
color: var(--muted);
font-family: monospace;
}
.zl-card-info {
display: flex;
justify-content: space-between;
font-size: 0.75rem;
color: #ccc;
background: rgba(0, 0, 0, 0.2);
padding: 4px 8px;
border-radius: 4px;
}
.zl-card-actions {
display: flex;
justify-content: flex-end;
gap: 4px;
margin-top: 4px;
}
/* Console output items */
.console-line {
margin-bottom: 4px;
display: flex;
gap: 8px;
}
.console-time {
color: var(--muted);
}
.console-type {
font-weight: bold;
}
.console-type.tx {
color: var(--acid);
}
.console-type.rx {
color: #00aaff;
}
.console-type.info {
color: #ccc;
}
.console-type.error {
color: #ff3333;
}
.console-type.success {
color: #00ffa0;
}
.console-target {
color: #aaa;
}
.console-content pre {
margin: 0;
white-space: pre-wrap;
font-family: inherit;
}
.zl-log-line {
display: flex;
gap: 8px;
margin-bottom: 4px;
}
/* Mobile Optimization */
@media (max-width: 900px) {
.zombieland-container.page-with-sidebar {
height: auto;
flex-direction: column;
}
.zombieland-container .zl-sidebar {
width: 100%;
max-height: none;
flex-shrink: 0;
border-radius: 8px;
}
.zl-stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.zl-toolbar {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
}
.zl-main-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.zl-console-panel {
height: 350px;
flex: none;
}
.zl-agents-panel {
height: 350px;
flex: none;
}
.zl-console-input-row {
flex-wrap: wrap;
}
.zl-target-select,
.zl-cmd-input {
width: 100%;
box-sizing: border-box;
}
.zl-card-header {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.zl-card-info {
flex-direction: column;
gap: 2px;
}
}
/* Intentionally empty — see /web/css/zombieland.css */

File diff suppressed because it is too large Load Diff