418 lines
11 KiB
SCSS
418 lines
11 KiB
SCSS
// Three themes on one attribute: <html data-theme="jambotron-light | jambotron-dark | synthwave">.
|
|
// The grid is painted only by --jt-* variables (its defaults sit on :where(:root), so any value below wins);
|
|
// Material (checkboxes, buttons, dialog, snack bar of the grid) takes its colors from the same variables.
|
|
@use '@angular/material' as mat;
|
|
@use '@jambotron/aria-grid/styles/aria-grid';
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// Jambotron light — the tokens of jambotron.com (_tokens.scss), the part the grid and this page use
|
|
[data-theme='jambotron-light'] {
|
|
color-scheme: light;
|
|
--app-bg: radial-gradient(1200px 600px at 10% -10%, #d7f6fb 0%, transparent 60%),
|
|
radial-gradient(900px 500px at 110% 10%, #fde9c4 0%, transparent 55%), #eef2f7;
|
|
--app-panel: #e7edf3c2;
|
|
--app-panel-border: rgba(10, 16, 48, 0.12);
|
|
--app-surface: #f3f6fa;
|
|
--app-code-bg: rgba(10, 16, 48, 0.05);
|
|
--app-font: Roboto, 'Helvetica Neue', sans-serif;
|
|
--app-font-display: Orbitron, Roboto, sans-serif;
|
|
--app-title: #0b6e80;
|
|
|
|
--jt-accent: #14c8e6;
|
|
--jt-accent-text: #074b5a;
|
|
--jt-on-accent: #050a24;
|
|
--jt-on-accent-text: #ffffff;
|
|
--jt-danger: #ef4444;
|
|
--jt-danger-text: #8a1414;
|
|
--jt-success: #22c55e;
|
|
--jt-success-text: #0c4f26;
|
|
--jt-warning: #ff9a2e;
|
|
--jt-warning-text: #6b3a00;
|
|
--jt-text: #141a33;
|
|
--jt-text-muted: #39425f;
|
|
--jt-text-disabled: rgba(20, 26, 51, 0.45);
|
|
--jt-divider: rgba(10, 16, 48, 0.12);
|
|
--jt-field-bg: rgba(255, 255, 255, 0.55);
|
|
--jt-field-border: rgba(10, 16, 48, 0.28);
|
|
--jt-focus-ring: 0 0 0 3px rgba(20, 200, 230, 0.45);
|
|
--jt-glow-accent: 0 0 10px rgba(20, 200, 230, 0.35);
|
|
--jt-popup-bg: #eef2f7e6;
|
|
--jt-popup-border: rgba(10, 16, 48, 0.12);
|
|
--jt-shadow-lg: 0 16px 48px rgba(10, 16, 48, 0.2);
|
|
}
|
|
|
|
// Jambotron dark — night sky, neon cyan
|
|
[data-theme='jambotron-dark'] {
|
|
color-scheme: dark;
|
|
--app-bg: radial-gradient(1200px 700px at 15% -10%, #1c2a6b 0%, transparent 60%),
|
|
radial-gradient(900px 600px at 110% 0%, #3b1d5e 0%, transparent 55%), #050a24;
|
|
--app-panel: rgba(10, 16, 44, 0.72);
|
|
--app-panel-border: rgba(62, 230, 255, 0.22);
|
|
--app-surface: #0c1234;
|
|
--app-code-bg: rgba(5, 10, 36, 0.6);
|
|
--app-font: Roboto, 'Helvetica Neue', sans-serif;
|
|
--app-font-display: Orbitron, Roboto, sans-serif;
|
|
--app-title: #7ff0ff;
|
|
|
|
--jt-accent: #3ee6ff;
|
|
--jt-accent-text: #7ff0ff;
|
|
--jt-on-accent: #050a24;
|
|
--jt-on-accent-text: #050a24;
|
|
--jt-danger: #f87171;
|
|
--jt-danger-text: #fecaca;
|
|
--jt-success: #34d399;
|
|
--jt-success-text: #86efac;
|
|
--jt-warning: #ff9a2e;
|
|
--jt-warning-text: #ffd98a;
|
|
--jt-text: #eef2ff;
|
|
--jt-text-muted: #ccd4ec;
|
|
--jt-text-disabled: rgba(238, 242, 255, 0.45);
|
|
--jt-divider: rgba(195, 204, 230, 0.16);
|
|
--jt-field-bg: rgba(5, 10, 36, 0.55);
|
|
--jt-field-border: rgba(195, 204, 230, 0.3);
|
|
--jt-focus-ring: 0 0 0 3px rgba(62, 230, 255, 0.5);
|
|
--jt-glow-accent: 0 0 14px rgba(62, 230, 255, 0.55);
|
|
--jt-popup-bg: rgba(8, 12, 36, 0.95);
|
|
--jt-popup-border: rgba(62, 230, 255, 0.22);
|
|
--jt-shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.55);
|
|
}
|
|
|
|
// Synthwave — the colors of reactive-mail-server's web mail (frontend/src/material.scss there)
|
|
[data-theme='synthwave'] {
|
|
color-scheme: dark;
|
|
--app-bg: linear-gradient(180deg, transparent 55%, rgba(255, 0, 127, 0.18) 100%),
|
|
repeating-linear-gradient(90deg, rgba(255, 0, 127, 0.12) 0 1px, transparent 1px 64px),
|
|
repeating-linear-gradient(0deg, rgba(0, 240, 255, 0.08) 0 1px, transparent 1px 64px), #0d0221;
|
|
--app-panel: rgba(15, 12, 35, 0.78);
|
|
--app-panel-border: rgba(255, 0, 127, 0.4);
|
|
--app-surface: #140a2e;
|
|
--app-code-bg: rgba(2, 6, 23, 0.7);
|
|
--app-font: Rajdhani, sans-serif;
|
|
--app-font-display: Orbitron, sans-serif;
|
|
--app-title: #ff007f;
|
|
|
|
--jt-accent: #00f0ff;
|
|
--jt-accent-text: #00f0ff;
|
|
--jt-on-accent: #0d0221;
|
|
--jt-on-accent-text: #0d0221;
|
|
--jt-danger: #ff4d6d;
|
|
--jt-danger-text: #ff8fa3;
|
|
--jt-success: #00ff88;
|
|
--jt-success-text: #7dffbf;
|
|
--jt-warning: #ffbe0b;
|
|
--jt-warning-text: #ffd76a;
|
|
--jt-text: #e2e8f0;
|
|
--jt-text-muted: #94a3b8;
|
|
--jt-text-disabled: rgba(226, 232, 240, 0.4);
|
|
--jt-divider: rgba(0, 240, 255, 0.14);
|
|
--jt-field-bg: rgba(2, 6, 23, 0.6);
|
|
--jt-field-border: rgba(0, 240, 255, 0.35);
|
|
--jt-focus-ring: 0 0 0 3px #ffbe0b;
|
|
--jt-glow-accent: 0 0 12px rgba(0, 240, 255, 0.6);
|
|
--jt-popup-bg: rgba(10, 5, 24, 0.97);
|
|
--jt-popup-border: rgba(255, 0, 127, 0.45);
|
|
--jt-shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.6), 0 0 20px rgba(255, 0, 127, 0.25);
|
|
--jt-radius-sm: 8px;
|
|
--jt-radius-md: 12px;
|
|
|
|
.jt-table {
|
|
font-size: 0.95rem;
|
|
|
|
th {
|
|
font-family: Orbitron, sans-serif;
|
|
font-size: 0.68rem;
|
|
letter-spacing: 0.08em;
|
|
color: #00f0ff;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// Material: light or dark by color-scheme (set by the theme above), roles mapped to the --jt-* variables
|
|
html {
|
|
@include mat.theme(
|
|
(
|
|
color: (primary: mat.$cyan-palette, tertiary: mat.$violet-palette, theme-type: color-scheme),
|
|
typography: (plain-family: var(--app-font), brand-family: var(--app-font-display)),
|
|
density: 0,
|
|
),
|
|
(
|
|
primary: var(--jt-accent-text),
|
|
on-primary: var(--jt-on-accent-text),
|
|
error: var(--jt-danger-text),
|
|
on-error: var(--jt-on-accent-text),
|
|
background: var(--app-surface),
|
|
on-background: var(--jt-text),
|
|
surface: var(--app-surface),
|
|
on-surface: var(--jt-text),
|
|
on-surface-variant: var(--jt-text-muted),
|
|
surface-container: var(--app-surface),
|
|
surface-container-high: var(--app-surface),
|
|
surface-container-highest: var(--app-surface),
|
|
outline: var(--jt-field-border),
|
|
outline-variant: var(--jt-divider),
|
|
inverse-surface: var(--jt-text),
|
|
inverse-on-surface: var(--app-surface),
|
|
)
|
|
);
|
|
@include mat.checkbox-overrides((
|
|
selected-icon-color: var(--jt-accent),
|
|
selected-hover-icon-color: var(--jt-accent),
|
|
selected-focus-icon-color: var(--jt-accent),
|
|
selected-checkmark-color: var(--jt-on-accent),
|
|
));
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// Page
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
margin: 0;
|
|
min-height: 100%;
|
|
}
|
|
|
|
body {
|
|
background: var(--app-bg);
|
|
background-attachment: fixed;
|
|
color: var(--jt-text);
|
|
font-family: var(--app-font);
|
|
line-height: 1.5;
|
|
transition: background var(--jt-duration-base) var(--jt-easing), color var(--jt-duration-base) var(--jt-easing);
|
|
}
|
|
|
|
a {
|
|
color: var(--jt-accent-text);
|
|
}
|
|
|
|
code {
|
|
font-family: 'JetBrains Mono', Consolas, monospace;
|
|
font-size: 0.85em;
|
|
}
|
|
|
|
.top {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
max-width: 1180px;
|
|
margin: 0 auto;
|
|
padding: 28px 16px 8px;
|
|
}
|
|
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
|
|
h1 {
|
|
margin: 0;
|
|
font-family: var(--app-font-display);
|
|
font-size: clamp(1.2rem, 3vw, 1.7rem);
|
|
color: var(--app-title);
|
|
text-shadow: var(--jt-glow-accent);
|
|
}
|
|
|
|
p {
|
|
margin: 2px 0 0;
|
|
color: var(--jt-text-muted);
|
|
}
|
|
}
|
|
|
|
.brand-mark {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 44px;
|
|
height: 44px;
|
|
border-radius: var(--jt-radius-md);
|
|
background: var(--jt-accent);
|
|
color: var(--jt-on-accent);
|
|
font-size: 1.6rem;
|
|
box-shadow: var(--jt-glow-accent);
|
|
}
|
|
|
|
.switches {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
|
|
jt-select {
|
|
min-width: 220px;
|
|
}
|
|
}
|
|
|
|
main {
|
|
display: grid;
|
|
gap: 24px;
|
|
max-width: 1180px;
|
|
margin: 0 auto;
|
|
padding: 16px;
|
|
}
|
|
|
|
.panel {
|
|
min-width: 0;
|
|
padding: 20px;
|
|
border: 1px solid var(--app-panel-border);
|
|
border-radius: var(--jt-radius-md);
|
|
background: var(--app-panel);
|
|
backdrop-filter: blur(8px);
|
|
|
|
h2 {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin: 0 0 6px;
|
|
font-family: var(--app-font-display);
|
|
font-size: 1.05rem;
|
|
letter-spacing: 0.02em;
|
|
|
|
span {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 26px;
|
|
height: 26px;
|
|
border-radius: 50%;
|
|
background: var(--jt-accent);
|
|
color: var(--jt-on-accent);
|
|
font-size: 0.8rem;
|
|
}
|
|
}
|
|
}
|
|
|
|
.lead {
|
|
margin: 0 0 16px;
|
|
color: var(--jt-text-muted);
|
|
max-width: 85ch;
|
|
}
|
|
|
|
.filter {
|
|
display: inline-flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
margin-bottom: 12px;
|
|
font-size: 0.8rem;
|
|
color: var(--jt-text-muted);
|
|
|
|
input {
|
|
width: min(320px, 80vw);
|
|
padding: 8px 12px;
|
|
border: 1px solid var(--jt-field-border);
|
|
border-radius: var(--jt-radius-sm);
|
|
background: var(--jt-field-bg);
|
|
color: var(--jt-text);
|
|
font: inherit;
|
|
font-size: 0.95rem;
|
|
|
|
&:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--jt-focus-ring);
|
|
}
|
|
}
|
|
}
|
|
|
|
.chip {
|
|
display: inline-block;
|
|
margin-right: 4px;
|
|
padding: 1px 8px;
|
|
border-radius: var(--jt-radius-pill);
|
|
font-size: 0.75rem;
|
|
font-weight: 500;
|
|
border: 1px solid currentColor;
|
|
}
|
|
|
|
.chip--running {
|
|
color: var(--jt-success-text);
|
|
}
|
|
|
|
.chip--stopped {
|
|
color: var(--jt-text-muted);
|
|
}
|
|
|
|
.chip--error {
|
|
color: var(--jt-danger-text);
|
|
}
|
|
|
|
.chip--locked {
|
|
color: var(--jt-warning-text);
|
|
}
|
|
|
|
// CPU load bar
|
|
.meter {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
width: 90px;
|
|
height: 18px;
|
|
padding: 0 6px;
|
|
border-radius: var(--jt-radius-sm);
|
|
background: linear-gradient(90deg, color-mix(in srgb, var(--jt-accent) 35%, transparent) calc(var(--value) * 1%), var(--jt-divider) 0);
|
|
font-variant-numeric: tabular-nums;
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.log {
|
|
min-height: 1.5em;
|
|
margin: 12px 0 4px;
|
|
color: var(--jt-text-muted);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.details {
|
|
margin-top: 12px;
|
|
padding: 10px 14px;
|
|
border-left: 3px solid var(--jt-accent);
|
|
border-radius: var(--jt-radius-sm);
|
|
background: color-mix(in srgb, var(--jt-accent) 10%, transparent);
|
|
}
|
|
|
|
.link {
|
|
margin-left: 8px;
|
|
padding: 0;
|
|
border: 0;
|
|
background: none;
|
|
color: var(--jt-accent-text);
|
|
font: inherit;
|
|
text-decoration: underline;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.code {
|
|
margin-top: 12px;
|
|
|
|
summary {
|
|
cursor: pointer;
|
|
color: var(--jt-accent-text);
|
|
font-weight: 500;
|
|
}
|
|
|
|
pre {
|
|
overflow-x: auto;
|
|
margin: 8px 0 0;
|
|
padding: 14px;
|
|
border: 1px solid var(--jt-divider);
|
|
border-radius: var(--jt-radius-sm);
|
|
background: var(--app-code-bg);
|
|
font-size: 0.82rem;
|
|
line-height: 1.45;
|
|
}
|
|
}
|
|
|
|
// The grid's own empty state uses this class
|
|
.jt-muted {
|
|
color: var(--jt-text-muted);
|
|
}
|
|
|
|
.foot {
|
|
max-width: 1180px;
|
|
margin: 0 auto;
|
|
padding: 8px 16px 32px;
|
|
color: var(--jt-text-muted);
|
|
font-size: 0.85rem;
|
|
}
|