fix(decnet_web/css): sweep rgba colour literals to tokens app-wide

Pre-this-commit, ~80 rgba() literals across 24 files were
hardcoding alert-red, warn-amber, info-cyan, panel-dark, and
white-text-with-alpha shades that bypassed the token cascade.
Net effect in light mode: the .eml/SESSREC drawers, AttackerDetail
verdict pills, MazeNET net-box headers, OPEN/REPLAY action
buttons, threat-intel cards, and all the dim 'whitish' overlays
stayed on their dark-mode hex values, producing the unreadable
panels in the screenshots.

Sweep maps each rgba colour family onto the existing token by
alpha bucket — rgba(13,17,23,*) -> var(--panel),
rgba(255,65,65,*) -> var(--alert)/-tint-10,
rgba(255,170,0,*) and rgba(224,160,64,*) -> var(--warn)/-tint-10,
rgba(0,200,255,*) -> var(--info)/-tint-10,
rgba(255,255,255,*) -> var(--fg-N)/var(--matrix-tint-N) by alpha.

VERDICT_TONE in AttackerDetail (MALICIOUS/SUSPICIOUS/BENIGN/
NO SIGNAL) was the worst offender — string literals
'#ff4d4d'/'#ffae42'/'#5fd07a'/rgba(255,255,255,0.4) baked into
inline JS styles. Now resolves at render time via var(--alert)/
var(--warn)/var(--ok)/var(--fg-4).

New tokens in :root:
 - --bg-color (alias of --bg) — drawers used this name with
   #0d1117 fallback that fired in every browser because nothing
   defined --bg-color. Adding the alias makes drawers re-tone.
 - --info / --info-tint-10 / --info-tint-30 — REPLAY buttons and
   any future neutral-secondary use.
 - --ok — semantic alias for 'verified good' (matrix in dark,
   emerald in light) so BENIGN pills stay readable across themes.

Login.css left intentionally — pre-auth surface, not themed.
This commit is contained in:
2026-05-09 03:48:05 -04:00
parent 11b2da7d54
commit aa0b22aacb
26 changed files with 142 additions and 119 deletions

View File

@@ -27,7 +27,7 @@ function decodeMeta(fields: Record<string, any>): Record<string, any> | null {
} }
const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => ( const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => (
<div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}> <div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid var(--matrix-tint-5)' }}>
<div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div> <div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div>
<div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div> <div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div>
</div> </div>
@@ -120,9 +120,9 @@ const ArtifactDrawer: React.FC<ArtifactDrawerProps> = ({ decky, storedAs, fields
<div style={{ <div style={{
display: 'flex', alignItems: 'center', gap: '8px', display: 'flex', alignItems: 'center', gap: '8px',
padding: '8px 12px', marginBottom: '16px', padding: '8px 12px', marginBottom: '16px',
border: '1px solid rgba(255, 170, 0, 0.3)', border: '1px solid var(--warn)',
backgroundColor: 'rgba(255, 170, 0, 0.05)', backgroundColor: 'var(--warn-tint-10)',
fontSize: '0.75rem', color: '#ffaa00', fontSize: '0.75rem', color: 'var(--warn)',
}}> }}>
<AlertTriangle size={14} /> <AlertTriangle size={14} />
Attacker-controlled content. Download at your own risk. Attacker-controlled content. Download at your own risk.
@@ -176,7 +176,7 @@ const ArtifactDrawer: React.FC<ArtifactDrawerProps> = ({ decky, storedAs, fields
<h3 style={{ fontSize: '0.8rem', letterSpacing: '0.1em', color: 'var(--dim-color)', marginBottom: '8px' }}> <h3 style={{ fontSize: '0.8rem', letterSpacing: '0.1em', color: 'var(--dim-color)', marginBottom: '8px' }}>
CONCURRENT SESSIONS ({concurrent.length}) CONCURRENT SESSIONS ({concurrent.length})
</h3> </h3>
<pre style={{ fontSize: '0.75rem', background: 'rgba(255,255,255,0.03)', padding: '8px', overflowX: 'auto' }}> <pre style={{ fontSize: '0.75rem', background: 'var(--matrix-tint-5)', padding: '8px', overflowX: 'auto' }}>
{JSON.stringify(concurrent, null, 2)} {JSON.stringify(concurrent, null, 2)}
</pre> </pre>
</section> </section>
@@ -187,7 +187,7 @@ const ArtifactDrawer: React.FC<ArtifactDrawerProps> = ({ decky, storedAs, fields
<h3 style={{ fontSize: '0.8rem', letterSpacing: '0.1em', color: 'var(--dim-color)', marginBottom: '8px' }}> <h3 style={{ fontSize: '0.8rem', letterSpacing: '0.1em', color: 'var(--dim-color)', marginBottom: '8px' }}>
SS SNAPSHOT ({ssSnapshot.length}) SS SNAPSHOT ({ssSnapshot.length})
</h3> </h3>
<pre style={{ fontSize: '0.75rem', background: 'rgba(255,255,255,0.03)', padding: '8px', overflowX: 'auto' }}> <pre style={{ fontSize: '0.75rem', background: 'var(--matrix-tint-5)', padding: '8px', overflowX: 'auto' }}>
{JSON.stringify(ssSnapshot, null, 2)} {JSON.stringify(ssSnapshot, null, 2)}
</pre> </pre>
</section> </section>

View File

@@ -1292,10 +1292,10 @@ type IntelRow = {
}; };
const VERDICT_TONE: Record<string, { color: string; label: string }> = { const VERDICT_TONE: Record<string, { color: string; label: string }> = {
malicious: { color: '#ff4d4d', label: 'MALICIOUS' }, malicious: { color: 'var(--alert)', label: 'MALICIOUS' },
suspicious: { color: '#ffae42', label: 'SUSPICIOUS' }, suspicious: { color: 'var(--warn)', label: 'SUSPICIOUS' },
benign: { color: '#5fd07a', label: 'BENIGN' }, benign: { color: 'var(--ok)', label: 'BENIGN' },
unknown: { color: 'rgba(255,255,255,0.4)', label: 'NO SIGNAL' }, unknown: { color: 'var(--fg-4)', label: 'NO SIGNAL' },
}; };
const fmtTs = (iso?: string | null): string => { const fmtTs = (iso?: string | null): string => {
@@ -1317,7 +1317,7 @@ const ProviderRow: React.FC<{
gridTemplateColumns: '160px 1fr auto', gridTemplateColumns: '160px 1fr auto',
gap: '12px', gap: '12px',
padding: '10px 16px', padding: '10px 16px',
borderTop: '1px solid rgba(255,255,255,0.05)', borderTop: '1px solid var(--matrix-tint-5)',
alignItems: 'center', alignItems: 'center',
fontSize: '0.85rem', fontSize: '0.85rem',
}}> }}>
@@ -1391,7 +1391,7 @@ const IntelPanel: React.FC<{ uuid: string }> = ({ uuid }) => {
alignItems: 'center', alignItems: 'center',
gap: '12px', gap: '12px',
padding: '14px 16px', padding: '14px 16px',
borderBottom: '1px solid rgba(255,255,255,0.05)', borderBottom: '1px solid var(--matrix-tint-5)',
}}> }}>
<Shield size={16} style={{ color: tone.color }} /> <Shield size={16} style={{ color: tone.color }} />
<span style={{ <span style={{
@@ -2310,11 +2310,11 @@ const AttackerDetail: React.FC = () => {
style={{ style={{
display: 'flex', alignItems: 'center', gap: '6px', display: 'flex', alignItems: 'center', gap: '6px',
fontSize: '0.7rem', fontSize: '0.7rem',
backgroundColor: 'rgba(255, 170, 0, 0.1)', backgroundColor: 'var(--warn-tint-10)',
padding: '2px 8px', padding: '2px 8px',
borderRadius: '4px', borderRadius: '4px',
border: '1px solid rgba(255, 170, 0, 0.5)', border: '1px solid var(--warn)',
color: '#ffaa00', color: 'var(--warn)',
cursor: 'pointer', cursor: 'pointer',
}} }}
> >
@@ -2449,11 +2449,11 @@ const AttackerDetail: React.FC = () => {
style={{ style={{
display: 'flex', alignItems: 'center', gap: '6px', display: 'flex', alignItems: 'center', gap: '6px',
fontSize: '0.7rem', fontSize: '0.7rem',
backgroundColor: 'rgba(255, 170, 0, 0.1)', backgroundColor: 'var(--warn-tint-10)',
padding: '2px 8px', padding: '2px 8px',
borderRadius: '4px', borderRadius: '4px',
border: '1px solid rgba(255, 170, 0, 0.5)', border: '1px solid var(--warn)',
color: '#ffaa00', color: 'var(--warn)',
cursor: 'pointer', cursor: 'pointer',
}} }}
> >
@@ -2532,11 +2532,11 @@ const AttackerDetail: React.FC = () => {
style={{ style={{
display: 'flex', alignItems: 'center', gap: '6px', display: 'flex', alignItems: 'center', gap: '6px',
fontSize: '0.7rem', fontSize: '0.7rem',
backgroundColor: 'rgba(0, 200, 255, 0.1)', backgroundColor: 'var(--info-tint-10)',
padding: '2px 8px', padding: '2px 8px',
borderRadius: '4px', borderRadius: '4px',
border: '1px solid rgba(0, 200, 255, 0.5)', border: '1px solid var(--info)',
color: '#00c8ff', color: 'var(--info)',
cursor: 'pointer', cursor: 'pointer',
}} }}
> >

View File

@@ -44,7 +44,7 @@ interface Props {
} }
const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => ( const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => (
<div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}> <div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid var(--matrix-tint-5)' }}>
<div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div> <div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div>
<div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div> <div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div>
</div> </div>
@@ -291,8 +291,8 @@ const CanaryTokenDrawer: React.FC<Props> = ({ token, onClose, onRevoked }) => {
key={t.uuid} key={t.uuid}
style={{ style={{
padding: '8px 12px', padding: '8px 12px',
border: '1px solid rgba(255,255,255,0.08)', border: '1px solid var(--matrix-tint-5)',
background: 'rgba(255,255,255,0.02)', background: 'var(--matrix-tint-5)',
fontSize: '0.8rem', fontSize: '0.8rem',
}} }}
> >

View File

@@ -458,9 +458,9 @@ const UploadModal: React.FC<UploadModalProps> = ({ onClose, onUploaded }) => {
<div style={{ <div style={{
display: 'flex', alignItems: 'center', gap: '8px', display: 'flex', alignItems: 'center', gap: '8px',
padding: '8px 12px', marginBottom: '16px', padding: '8px 12px', marginBottom: '16px',
border: '1px solid rgba(255, 170, 0, 0.3)', border: '1px solid var(--warn)',
backgroundColor: 'rgba(255, 170, 0, 0.05)', backgroundColor: 'var(--warn-tint-10)',
fontSize: '0.75rem', color: '#ffaa00', fontSize: '0.75rem', color: 'var(--warn)',
}}> }}>
<AlertTriangle size={14} /> <AlertTriangle size={14} />
DECNET injects the callback server-side; the original bytes stay on the master. DECNET injects the callback server-side; the original bytes stay on the master.
@@ -811,9 +811,9 @@ const FileDropModal: React.FC<FileDropModalProps> = ({ deckies, topologies, onCl
<div style={{ <div style={{
display: 'flex', alignItems: 'center', gap: '8px', display: 'flex', alignItems: 'center', gap: '8px',
padding: '8px 12px', marginBottom: '16px', padding: '8px 12px', marginBottom: '16px',
border: '1px solid rgba(255, 170, 0, 0.3)', border: '1px solid var(--warn)',
backgroundColor: 'rgba(255, 170, 0, 0.05)', backgroundColor: 'var(--warn-tint-10)',
fontSize: '0.7rem', color: '#ffaa00', fontSize: '0.7rem', color: 'var(--warn)',
}}> }}>
<AlertTriangle size={14} /> <AlertTriangle size={14} />
File drops bypass canary instrumentation bytes land verbatim. The list below is local only. File drops bypass canary instrumentation bytes land verbatim. The list below is local only.
@@ -1052,7 +1052,7 @@ const CanaryTokens: React.FC = () => {
alignItems: 'center', gap: '12px', alignItems: 'center', gap: '12px',
padding: '10px 14px', padding: '10px 14px',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
background: 'rgba(255,255,255,0.02)', background: 'var(--matrix-tint-5)',
color: 'var(--text-color)', color: 'var(--text-color)',
cursor: 'pointer', cursor: 'pointer',
textAlign: 'left', textAlign: 'left',
@@ -1114,7 +1114,7 @@ const CanaryTokens: React.FC = () => {
alignItems: 'center', gap: '12px', alignItems: 'center', gap: '12px',
padding: '10px 14px', padding: '10px 14px',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
background: 'rgba(255,255,255,0.02)', background: 'var(--matrix-tint-5)',
fontSize: '0.8rem', fontSize: '0.8rem',
}} }}
> >
@@ -1189,7 +1189,7 @@ const CanaryTokens: React.FC = () => {
alignItems: 'center', gap: '12px', alignItems: 'center', gap: '12px',
padding: '10px 14px', padding: '10px 14px',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
background: 'rgba(255,255,255,0.02)', background: 'var(--matrix-tint-5)',
fontSize: '0.8rem', fontSize: '0.8rem',
}} }}
> >
@@ -1281,7 +1281,7 @@ const INPUT_STYLE: React.CSSProperties = {
width: '100%', width: '100%',
padding: '8px 10px', padding: '8px 10px',
marginBottom: '12px', marginBottom: '12px',
background: 'rgba(255,255,255,0.03)', background: 'var(--matrix-tint-5)',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
color: 'var(--text-color)', color: 'var(--text-color)',
fontSize: '0.85rem', fontSize: '0.85rem',
@@ -1324,7 +1324,7 @@ const Stat: React.FC<{ label: string; value: number | string; color: string }> =
flex: '1 1 120px', flex: '1 1 120px',
padding: '12px 16px', padding: '12px 16px',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
background: 'rgba(255,255,255,0.02)', background: 'var(--matrix-tint-5)',
}}> }}>
<div style={{ fontSize: '0.7rem', color: 'var(--dim-color)', letterSpacing: '0.1em' }}>{label}</div> <div style={{ fontSize: '0.7rem', color: 'var(--dim-color)', letterSpacing: '0.1em' }}>{label}</div>
<div style={{ fontSize: '1.4rem', fontWeight: 'bold', color, marginTop: '4px' }}>{value}</div> <div style={{ fontSize: '1.4rem', fontWeight: 'bold', color, marginTop: '4px' }}>{value}</div>

View File

@@ -165,7 +165,7 @@
.action-btn.danger:hover { .action-btn.danger:hover {
background: #ff4141; background: #ff4141;
color: var(--background-color); color: var(--background-color);
box-shadow: 0 0 10px rgba(255, 65, 65, 0.5); box-shadow: 0 0 10px var(--alert);
} }
/* Add User Form */ /* Add User Form */
@@ -260,7 +260,7 @@
font-size: 0.75rem; font-size: 0.75rem;
padding: 6px 12px; padding: 6px 12px;
border: 1px solid #ff4141; border: 1px solid #ff4141;
background: rgba(255, 65, 65, 0.1); background: var(--alert-tint-10);
display: inline-block; display: inline-block;
} }

View File

@@ -635,7 +635,7 @@ const RealismBadge: React.FC<{
const breaker = realism.llm_breaker_state ?? 'closed'; const breaker = realism.llm_breaker_state ?? 'closed';
const breakerColor = const breakerColor =
breaker === 'open' ? '#ff5555' breaker === 'open' ? '#ff5555'
: breaker === 'half_open' ? '#ffaa00' : breaker === 'half_open' ? 'var(--warn)'
: 'var(--matrix)'; : 'var(--matrix)';
const tooltip = [ const tooltip = [
`Backend: ${realism.llm_backend ?? '?'}`, `Backend: ${realism.llm_backend ?? '?'}`,
@@ -793,8 +793,8 @@ const WorkersPanel: React.FC<WorkersPanelProps> = ({ pushToast }) => {
margin: '16px 20px 0', margin: '16px 20px 0',
padding: '10px 14px', padding: '10px 14px',
border: '1px solid #ffaa00', border: '1px solid #ffaa00',
background: 'rgba(255, 170, 0, 0.08)', background: 'var(--warn-tint-10)',
color: '#ffaa00', color: 'var(--warn)',
fontSize: '0.72rem', fontSize: '0.72rem',
letterSpacing: 1, letterSpacing: 1,
lineHeight: 1.5, lineHeight: 1.5,
@@ -906,8 +906,8 @@ const WorkersPanel: React.FC<WorkersPanelProps> = ({ pushToast }) => {
</td> </td>
<td style={{ <td style={{
color: w.status === 'ok' ? 'var(--matrix)' color: w.status === 'ok' ? 'var(--matrix)'
: w.status === 'stale' ? '#ffaa00' : w.status === 'stale' ? 'var(--warn)'
: 'rgba(255,255,255,0.4)', : 'var(--fg-4)',
letterSpacing: 1, letterSpacing: 1,
}}> }}>
{w.status.toUpperCase()} {w.status.toUpperCase()}
@@ -927,8 +927,8 @@ const WorkersPanel: React.FC<WorkersPanelProps> = ({ pushToast }) => {
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
gap: 4, gap: 4,
color: canStop ? '#ff4d4d' : '#ff4d4d', color: canStop ? 'var(--alert)' : 'var(--alert)',
borderColor: canStop ? '#ff4d4d' : 'rgba(255, 77, 77, 0.4)', borderColor: canStop ? 'var(--alert)' : 'rgba(255, 77, 77, 0.4)',
opacity: canStop ? 1 : 0.3, opacity: canStop ? 1 : 0.3,
cursor: canStop ? 'pointer' : 'not-allowed', cursor: canStop ? 'pointer' : 'not-allowed',
}} }}

View File

@@ -75,7 +75,7 @@
.chip.alert-chip { .chip.alert-chip {
border-color: var(--alert); border-color: var(--alert);
color: var(--alert); color: var(--alert);
background: rgba(255, 65, 65, 0.1); background: var(--alert-tint-10);
} }
/* Key-value chips in the live-feed event column. Values are unbounded /* Key-value chips in the live-feed event column. Values are unbounded
@@ -96,7 +96,7 @@
/* Breach banner */ /* Breach banner */
.breach-banner { .breach-banner {
background: rgba(255, 65, 65, 0.1); background: var(--alert-tint-10);
border: 1px solid var(--alert); border: 1px solid var(--alert);
padding: 12px 20px; padding: 12px 20px;
display: flex; display: flex;
@@ -128,7 +128,7 @@
} }
.breach-banner button:hover { .breach-banner button:hover {
background: rgba(255, 65, 65, 0.15); background: var(--alert-tint-10);
} }
/* Stats */ /* Stats */
@@ -155,7 +155,7 @@
} }
.stat-card.alert { .stat-card.alert {
border-color: rgba(255, 65, 65, 0.4); border-color: var(--alert);
} }
.stat-card .row { .stat-card .row {
@@ -370,7 +370,7 @@
.status-dot.warn { .status-dot.warn {
background: var(--warn); background: var(--warn);
box-shadow: 0 0 6px rgba(255, 170, 0, 0.6); box-shadow: 0 0 6px var(--warn);
} }
.status-dot.hot { .status-dot.hot {

View File

@@ -399,11 +399,11 @@ const Dashboard: React.FC<DashboardProps> = ({ searchQuery }) => {
style={{ style={{
display: 'inline-flex', alignItems: 'center', gap: 4, display: 'inline-flex', alignItems: 'center', gap: 4,
fontSize: '0.62rem', fontSize: '0.62rem',
backgroundColor: 'rgba(255, 170, 0, 0.1)', backgroundColor: 'var(--warn-tint-10)',
padding: '2px 8px', padding: '2px 8px',
borderRadius: 4, borderRadius: 4,
border: '1px solid rgba(255, 170, 0, 0.5)', border: '1px solid var(--warn)',
color: '#ffaa00', color: 'var(--warn)',
cursor: 'pointer', cursor: 'pointer',
letterSpacing: 1, letterSpacing: 1,
}} }}

View File

@@ -56,7 +56,7 @@
.fleet-root .btn.violet { border-color: var(--violet); color: var(--violet); } .fleet-root .btn.violet { border-color: var(--violet); color: var(--violet); }
.fleet-root .btn.violet:hover { background: var(--violet); color: var(--bg); box-shadow: var(--violet-glow); } .fleet-root .btn.violet:hover { background: var(--violet); color: var(--bg); box-shadow: var(--violet-glow); }
.fleet-root .btn.alert { border-color: var(--alert); color: var(--alert); } .fleet-root .btn.alert { border-color: var(--alert); color: var(--alert); }
.fleet-root .btn.alert:hover { background: var(--alert); color: var(--bg); box-shadow: 0 0 10px rgba(255, 65, 65, 0.5); } .fleet-root .btn.alert:hover { background: var(--alert); color: var(--bg); box-shadow: 0 0 10px var(--alert); }
.fleet-root .btn.ghost { border-color: var(--border); color: var(--matrix); opacity: 0.7; } .fleet-root .btn.ghost { border-color: var(--border); color: var(--matrix); opacity: 0.7; }
.fleet-root .btn.ghost:hover { color: var(--matrix); opacity: 1; border-color: var(--matrix); box-shadow: var(--matrix-glow); background: transparent; } .fleet-root .btn.ghost:hover { color: var(--matrix); opacity: 1; border-color: var(--matrix); box-shadow: var(--matrix-glow); background: transparent; }
.fleet-root .btn.small { padding: 4px 10px; font-size: 0.68rem; } .fleet-root .btn.small { padding: 4px 10px; font-size: 0.68rem; }
@@ -137,7 +137,7 @@
line-height: 1; line-height: 1;
padding: 2px 8px; padding: 2px 8px;
border-color: var(--border); border-color: var(--border);
color: var(--text-dim, rgba(255,255,255,0.5)); color: var(--text-dim, var(--fg-3));
letter-spacing: 0; letter-spacing: 0;
} }
.tarpit-menu-btn:hover { .tarpit-menu-btn:hover {
@@ -173,14 +173,14 @@
.tarpit-dropdown-item:last-child { border-bottom: none; } .tarpit-dropdown-item:last-child { border-bottom: none; }
.tarpit-dropdown-item:hover { background: rgba(57,255,20,0.08); } .tarpit-dropdown-item:hover { background: rgba(57,255,20,0.08); }
.tarpit-dropdown-item.alert { color: var(--alert); } .tarpit-dropdown-item.alert { color: var(--alert); }
.tarpit-dropdown-item.alert:hover { background: rgba(255,65,65,0.08); } .tarpit-dropdown-item.alert:hover { background: var(--alert-tint-10); }
/* Tarpit enable form — rendered below the card footer */ /* Tarpit enable form — rendered below the card footer */
.tarpit-form { .tarpit-form {
margin-top: 8px; margin-top: 8px;
padding: 10px; padding: 10px;
border: 1px solid var(--alert); border: 1px solid var(--alert);
background: rgba(255,65,65,0.04); background: var(--alert-tint-10);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
@@ -194,7 +194,7 @@
.tarpit-form input.input { .tarpit-form input.input {
font-size: 0.72rem; font-size: 0.72rem;
padding: 4px 6px; padding: 4px 6px;
background: rgba(255,255,255,0.04); background: var(--matrix-tint-10);
border: 1px solid var(--border); border: 1px solid var(--border);
color: var(--text-color); color: var(--text-color);
} }
@@ -204,7 +204,7 @@
Modal portal; PersonaGeneration.css scopes its own copy under Modal portal; PersonaGeneration.css scopes its own copy under
.persona-gen-root, which doesn't match the modal's DOM location. */ .persona-gen-root, which doesn't match the modal's DOM location. */
.info-banner { .info-banner {
background: rgba(255, 255, 255, 0.02); background: var(--matrix-tint-5);
border: 1px solid var(--border); border: 1px solid var(--border);
border-left: 3px solid var(--violet); border-left: 3px solid var(--violet);
padding: 10px 14px; padding: 10px 14px;
@@ -222,7 +222,7 @@
display: flex; align-items: center; gap: 8px; display: flex; align-items: center; gap: 8px;
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
background: rgba(255, 255, 255, 0.02); background: var(--matrix-tint-5);
border: none; border: none;
color: inherit; color: inherit;
font-family: var(--font-mono); font-family: var(--font-mono);
@@ -232,7 +232,7 @@
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
} }
.wizard-svc-toggle:hover { background: rgba(255, 255, 255, 0.05); } .wizard-svc-toggle:hover { background: var(--matrix-tint-10); }
.wizard-svc-toggle.open { border-bottom: 1px solid var(--border); } .wizard-svc-toggle.open { border-bottom: 1px solid var(--border); }
.wizard-svc-caret { color: var(--violet); width: 10px; } .wizard-svc-caret { color: var(--violet); width: 10px; }
.wizard-svc-name { color: var(--matrix); flex: 1; } .wizard-svc-name { color: var(--matrix); flex: 1; }

View File

@@ -519,7 +519,7 @@ const DeckyCard: React.FC<DeckyCardProps> = ({
onChange={(e) => setAddSlug(e.target.value)} onChange={(e) => setAddSlug(e.target.value)}
style={{ style={{
flex: 1, fontSize: '0.75rem', padding: '4px 6px', flex: 1, fontSize: '0.75rem', padding: '4px 6px',
background: 'rgba(255,255,255,0.04)', background: 'var(--matrix-tint-10)',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
color: 'var(--text-color)', color: 'var(--text-color)',
}} }}

View File

@@ -94,7 +94,7 @@
color: var(--alert); color: var(--alert);
border: 1px solid var(--alert); border: 1px solid var(--alert);
padding: 1px 5px; padding: 1px 5px;
background: rgba(255, 65, 65, 0.1); background: var(--alert-tint-10);
letter-spacing: 1px; letter-spacing: 1px;
margin-left: auto; margin-left: auto;
} }
@@ -286,7 +286,7 @@
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--alert); border: 1px solid var(--alert);
color: var(--alert); color: var(--alert);
background: rgba(255, 65, 65, 0.08); background: var(--alert-tint-10);
text-transform: uppercase; text-transform: uppercase;
} }

View File

@@ -137,15 +137,15 @@
font-size: 0.68rem; font-size: 0.68rem;
padding: 2px 8px; padding: 2px 8px;
border-radius: 3px; border-radius: 3px;
background: rgba(255, 170, 0, 0.1); background: var(--warn-tint-10);
border: 1px solid rgba(255, 170, 0, 0.5); border: 1px solid var(--warn);
color: var(--warn); color: var(--warn);
cursor: pointer; cursor: pointer;
font-family: inherit; font-family: inherit;
} }
.logs-root .artifact-btn:hover { .logs-root .artifact-btn:hover {
background: rgba(255, 170, 0, 0.2); background: var(--warn-tint-10);
box-shadow: 0 0 8px rgba(255, 170, 0, 0.4); box-shadow: 0 0 8px var(--warn);
} }
/* Empty state */ /* Empty state */

View File

@@ -31,7 +31,7 @@ function parseAttachments(fields: Record<string, any>): AttachmentManifest[] {
} }
const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => ( const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => (
<div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}> <div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid var(--matrix-tint-5)' }}>
<div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div> <div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div>
<div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div> <div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div>
</div> </div>
@@ -125,9 +125,9 @@ const MailDrawer: React.FC<MailDrawerProps> = ({ decky, storedAs, fields, onClos
<div style={{ <div style={{
display: 'flex', alignItems: 'center', gap: '8px', display: 'flex', alignItems: 'center', gap: '8px',
padding: '8px 12px', marginBottom: '16px', padding: '8px 12px', marginBottom: '16px',
border: '1px solid rgba(255, 170, 0, 0.3)', border: '1px solid var(--warn)',
backgroundColor: 'rgba(255, 170, 0, 0.05)', backgroundColor: 'var(--warn-tint-10)',
fontSize: '0.75rem', color: '#ffaa00', fontSize: '0.75rem', color: 'var(--warn)',
}}> }}>
<AlertTriangle size={14} /> <AlertTriangle size={14} />
Attacker-controlled content. Phishing kits / malware likely. Attacker-controlled content. Phishing kits / malware likely.
@@ -184,8 +184,8 @@ const MailDrawer: React.FC<MailDrawerProps> = ({ decky, storedAs, fields, onClos
key={idx} key={idx}
style={{ style={{
padding: '8px 12px', padding: '8px 12px',
border: '1px solid rgba(255,255,255,0.08)', border: '1px solid var(--matrix-tint-5)',
background: 'rgba(255,255,255,0.02)', background: 'var(--matrix-tint-5)',
fontSize: '0.8rem', fontSize: '0.8rem',
}} }}
> >

View File

@@ -211,7 +211,7 @@ const Inspector: React.FC<Props> = ({
onChange={(e) => setAddSlug(e.target.value)} onChange={(e) => setAddSlug(e.target.value)}
style={{ style={{
flex: 1, fontSize: '0.75rem', padding: '4px 6px', flex: 1, fontSize: '0.75rem', padding: '4px 6px',
background: 'rgba(255,255,255,0.04)', background: 'var(--matrix-tint-10)',
border: '1px solid var(--border-color, #30363d)', border: '1px solid var(--border-color, #30363d)',
color: 'var(--text-color)', color: 'var(--text-color)',
}} }}

View File

@@ -151,7 +151,7 @@ body.maze-fullscreen .maze-shell {
.maze-net-box { .maze-net-box {
position: absolute; position: absolute;
border: 1px dashed var(--border); border: 1px dashed var(--border);
background: rgba(13, 17, 23, 0.6); background: var(--panel);
padding: 32px 16px 16px; padding: 32px 16px 16px;
min-width: 220px; min-height: 140px; min-width: 220px; min-height: 140px;
transition: border-color 0.2s; transition: border-color 0.2s;
@@ -165,14 +165,14 @@ body.maze-fullscreen .maze-shell {
border-color: var(--matrix); background: var(--matrix-tint-5); border-color: var(--matrix); background: var(--matrix-tint-5);
} }
.maze-net-box.internet { .maze-net-box.internet {
border-color: var(--alert); background: rgba(255, 65, 65, 0.04); border-color: var(--alert); background: var(--alert-tint-10);
} }
.maze-net-box.dmz { .maze-net-box.dmz {
border-color: var(--alert); background: rgba(255, 65, 65, 0.06); border-color: var(--alert); background: var(--alert-tint-10);
border-style: dashed; border-style: dashed;
} }
.maze-net-box.dmz .maze-net-box-head { .maze-net-box.dmz .maze-net-box-head {
color: var(--alert); border-bottom-color: rgba(255, 65, 65, 0.45); color: var(--alert); border-bottom-color: var(--alert);
} }
/* Deployed: topology is active/degraded — make it visually unmistakable. /* Deployed: topology is active/degraded — make it visually unmistakable.
* Subnet LANs glow matrix-green; DMZ stays hot red (and gets a stronger * Subnet LANs glow matrix-green; DMZ stays hot red (and gets a stronger
@@ -188,42 +188,42 @@ body.maze-fullscreen .maze-shell {
} }
.maze-net-box.deployed.dmz { .maze-net-box.deployed.dmz {
border-color: var(--alert); border-color: var(--alert);
background: rgba(255, 65, 65, 0.09); background: var(--alert-tint-10);
box-shadow: 0 0 0 1px rgba(255, 65, 65, 0.35) inset, box-shadow: 0 0 0 1px var(--alert) inset,
0 0 16px rgba(255, 65, 65, 0.5); 0 0 16px var(--alert);
} }
.maze-net-box.deployed.dmz .maze-net-box-head { .maze-net-box.deployed.dmz .maze-net-box-head {
color: var(--alert); border-bottom-color: rgba(255, 65, 65, 0.55); color: var(--alert); border-bottom-color: var(--alert);
} }
.maze-net-box.inactive { .maze-net-box.inactive {
opacity: 0.42; filter: grayscale(0.7); border-style: dotted; opacity: 0.42; filter: grayscale(0.7); border-style: dotted;
} }
.maze-net-box.inactive .maze-net-box-head { color: rgba(255, 255, 255, 0.5); } .maze-net-box.inactive .maze-net-box-head { color: var(--fg-3); }
/* Optimistic placeholder for an enqueued LAN-add. Amber tint matches /* Optimistic placeholder for an enqueued LAN-add. Amber tint matches
* the REAP button voice — clearly "in-flight, not committed" without * the REAP button voice — clearly "in-flight, not committed" without
* collapsing into the dimmed-out 'inactive' style which means the * collapsing into the dimmed-out 'inactive' style which means the
* opposite (no traffic on a deployed LAN). */ * opposite (no traffic on a deployed LAN). */
.maze-net-box.pending { .maze-net-box.pending {
border-color: var(--warn, #e0a040); border-color: var(--warn, #e0a040);
background: rgba(224, 160, 64, 0.04); background: var(--warn-tint-10);
border-style: dashed; border-style: dashed;
filter: none; opacity: 1; filter: none; opacity: 1;
} }
.maze-net-box.pending .maze-net-box-head { .maze-net-box.pending .maze-net-box-head {
color: var(--warn, #e0a040); color: var(--warn, #e0a040);
border-bottom-color: rgba(224, 160, 64, 0.45); border-bottom-color: var(--warn);
} }
.maze-net-box.pending .cidr { color: rgba(224, 160, 64, 0.7); } .maze-net-box.pending .cidr { color: var(--warn); }
.maze-net-box-head { .maze-net-box-head {
position: absolute; top: 0; left: 0; right: 0; position: absolute; top: 0; left: 0; right: 0;
padding: 6px 12px; border-bottom: 1px dashed var(--border); padding: 6px 12px; border-bottom: 1px dashed var(--border);
display: flex; align-items: center; gap: 8px; justify-content: space-between; display: flex; align-items: center; gap: 8px; justify-content: space-between;
font-size: 0.65rem; letter-spacing: 1.5px; opacity: 0.8; font-size: 0.65rem; letter-spacing: 1.5px; opacity: 0.8;
background: rgba(13, 17, 23, 0.8); cursor: move; background: var(--panel); cursor: move;
} }
.maze-net-box-head .cidr { opacity: 0.5; font-size: 0.6rem; letter-spacing: 1px; } .maze-net-box-head .cidr { opacity: 0.5; font-size: 0.6rem; letter-spacing: 1px; }
.maze-net-box.internet .maze-net-box-head { .maze-net-box.internet .maze-net-box-head {
color: var(--alert); border-bottom-color: rgba(255, 65, 65, 0.4); color: var(--alert); border-bottom-color: var(--alert);
} }
/* ── Network resize handles ─────────────────── */ /* ── Network resize handles ─────────────────── */
@@ -271,8 +271,8 @@ body.maze-fullscreen .maze-shell {
.maze-node.deployed .mn-head { color: var(--matrix); } .maze-node.deployed .mn-head { color: var(--matrix); }
.maze-node.deployed.dmz-gateway { .maze-node.deployed.dmz-gateway {
border-color: var(--alert); border-color: var(--alert);
box-shadow: 0 0 12px rgba(255, 65, 65, 0.55); box-shadow: 0 0 12px var(--alert);
background: rgba(255, 65, 65, 0.06); background: var(--alert-tint-10);
} }
.maze-node.deployed.dmz-gateway .mn-head { color: var(--alert); } .maze-node.deployed.dmz-gateway .mn-head { color: var(--alert); }
.maze-node .mn-head { .maze-node .mn-head {
@@ -322,7 +322,7 @@ body.maze-fullscreen .maze-shell {
} }
.maze-legend { .maze-legend {
position: absolute; bottom: 12px; right: 12px; z-index: 5; position: absolute; bottom: 12px; right: 12px; z-index: 5;
background: rgba(13, 17, 23, 0.85); border: 1px solid var(--border); background: var(--panel); border: 1px solid var(--border);
padding: 8px 10px; font-size: 0.6rem; letter-spacing: 1px; padding: 8px 10px; font-size: 0.6rem; letter-spacing: 1px;
display: flex; flex-direction: column; gap: 4px; display: flex; flex-direction: column; gap: 4px;
} }
@@ -425,7 +425,7 @@ body.maze-fullscreen .maze-shell {
.ghost-edge.snap { stroke: var(--matrix); opacity: 0.9; } .ghost-edge.snap { stroke: var(--matrix); opacity: 0.9; }
.ctx-item:hover { background: var(--violet-tint-10); color: var(--violet); } .ctx-item:hover { background: var(--violet-tint-10); color: var(--violet); }
.ctx-item.danger { color: var(--alert); } .ctx-item.danger { color: var(--alert); }
.ctx-item.danger:hover { background: rgba(255, 65, 65, 0.12); } .ctx-item.danger:hover { background: var(--alert-tint-10); }
.ctx-item.disabled { opacity: 0.35; cursor: not-allowed; } .ctx-item.disabled { opacity: 0.35; cursor: not-allowed; }
.ctx-item.disabled:hover { background: transparent; color: inherit; } .ctx-item.disabled:hover { background: transparent; color: inherit; }
.ctx-divider { height: 1px; background: var(--border); margin: 4px 0; } .ctx-divider { height: 1px; background: var(--border); margin: 4px 0; }
@@ -453,7 +453,7 @@ body.maze-fullscreen .maze-shell {
.inspector-close-btn { .inspector-close-btn {
background: transparent; background: transparent;
border: 1px solid var(--border); border: 1px solid var(--border);
color: rgba(255, 255, 255, 0.5); color: var(--fg-3);
padding: 3px 5px; padding: 3px 5px;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@@ -550,7 +550,7 @@ body.maze-fullscreen .maze-shell {
padding: 1px 5px; padding: 1px 5px;
border: 1px solid var(--border); border: 1px solid var(--border);
letter-spacing: 1px; letter-spacing: 1px;
color: rgba(255, 255, 255, 0.55); color: var(--fg-3);
} }
/* Inspector buttons */ /* Inspector buttons */
@@ -563,7 +563,7 @@ body.maze-fullscreen .maze-shell {
.maze-btn.alert:hover { .maze-btn.alert:hover {
background: var(--alert); background: var(--alert);
color: var(--bg); color: var(--bg);
box-shadow: 0 0 10px rgba(255, 65, 65, 0.5); box-shadow: 0 0 10px var(--alert);
opacity: 1; opacity: 1;
} }
@@ -606,8 +606,8 @@ body.maze-fullscreen .maze-shell {
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
padding: 8px; padding: 8px;
background: rgba(255, 65, 65, 0.04); background: var(--alert-tint-10);
border: 1px solid rgba(255, 65, 65, 0.3); border: 1px solid var(--alert);
} }
.inspector-tarpit-field { .inspector-tarpit-field {
display: flex; display: flex;
@@ -617,7 +617,7 @@ body.maze-fullscreen .maze-shell {
.maze-input { .maze-input {
font-size: 0.72rem; font-size: 0.72rem;
padding: 4px 6px; padding: 4px 6px;
background: rgba(255, 255, 255, 0.04); background: var(--matrix-tint-5);
border: 1px solid var(--border); border: 1px solid var(--border);
color: var(--text-color, #e0e0e0); color: var(--text-color, #e0e0e0);
font-family: inherit; font-family: inherit;

View File

@@ -56,7 +56,7 @@ const NetBox: React.FC<Props> = ({
<span>{net.label}</span> <span>{net.label}</span>
{inactive && !net.pending && ( {inactive && !net.pending && (
<span className="chip-mini" <span className="chip-mini"
style={{ marginLeft: 4, borderColor: 'var(--border)', color: 'rgba(255,255,255,0.45)' }}> style={{ marginLeft: 4, borderColor: 'var(--border)', color: 'var(--fg-4)' }}>
INACTIVE INACTIVE
</span> </span>
)} )}

View File

@@ -81,7 +81,7 @@
letter-spacing: 1.5px; letter-spacing: 1.5px;
border: 1px solid var(--alert); border: 1px solid var(--alert);
color: var(--alert); color: var(--alert);
background: rgba(255, 65, 65, 0.06); background: var(--alert-tint-10);
text-transform: uppercase; text-transform: uppercase;
} }
@@ -192,9 +192,9 @@
} }
.orchestrator-root .logs-table tr:hover td { background: var(--matrix-tint-5); } .orchestrator-root .logs-table tr:hover td { background: var(--matrix-tint-5); }
.orchestrator-root .logs-table tr.fail td { .orchestrator-root .logs-table tr.fail td {
background: rgba(255, 65, 65, 0.05); background: var(--alert-tint-10);
} }
.orchestrator-root .logs-table tr.fail:hover td { background: rgba(255, 65, 65, 0.08); } .orchestrator-root .logs-table tr.fail:hover td { background: var(--alert-tint-10); }
/* Live-prepended row tint — fades back to neutral after a moment via opacity. */ /* Live-prepended row tint — fades back to neutral after a moment via opacity. */
.orchestrator-root .logs-table tr.fresh td { .orchestrator-root .logs-table tr.fresh td {

View File

@@ -6,7 +6,7 @@
/* Info banner explaining scope (non-MazeNET) + showing pool path. */ /* Info banner explaining scope (non-MazeNET) + showing pool path. */
.persona-gen-root .info-banner { .persona-gen-root .info-banner {
background: rgba(255, 255, 255, 0.02); background: var(--matrix-tint-5);
border: 1px solid var(--border); border: 1px solid var(--border);
border-left: 3px solid var(--violet); border-left: 3px solid var(--violet);
padding: 10px 14px; padding: 10px 14px;

View File

@@ -5,7 +5,7 @@
.realism-config-root .mono { font-family: var(--font-mono); } .realism-config-root .mono { font-family: var(--font-mono); }
.realism-config-root .info-banner { .realism-config-root .info-banner {
background: rgba(255, 255, 255, 0.02); background: var(--matrix-tint-5);
border: 1px solid var(--border); border: 1px solid var(--border);
border-left: 3px solid var(--violet); border-left: 3px solid var(--violet);
padding: 10px 14px; padding: 10px 14px;

View File

@@ -29,7 +29,7 @@ interface TranscriptPage {
const PAGE_SIZE = 500; const PAGE_SIZE = 500;
const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => ( const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => (
<div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}> <div style={{ display: 'flex', gap: '12px', padding: '6px 0', borderBottom: '1px solid var(--matrix-tint-5)' }}>
<div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div> <div style={{ minWidth: '140px', color: 'var(--dim-color)', fontSize: '0.75rem', textTransform: 'uppercase' }}>{label}</div>
<div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div> <div style={{ flex: 1, fontSize: '0.85rem', wordBreak: 'break-all' }}>{value ?? <span style={{ opacity: 0.4 }}></span>}</div>
</div> </div>
@@ -204,9 +204,9 @@ const SessionDrawer: React.FC<SessionDrawerProps> = ({ decky, sid, fields, onClo
<div style={{ <div style={{
display: 'flex', alignItems: 'center', gap: '8px', display: 'flex', alignItems: 'center', gap: '8px',
padding: '8px 12px', marginBottom: '16px', padding: '8px 12px', marginBottom: '16px',
border: '1px solid rgba(255, 170, 0, 0.3)', border: '1px solid var(--warn)',
backgroundColor: 'rgba(255, 170, 0, 0.05)', backgroundColor: 'var(--warn-tint-10)',
fontSize: '0.75rem', color: '#ffaa00', fontSize: '0.75rem', color: 'var(--warn)',
}}> }}>
<AlertTriangle size={14} /> <AlertTriangle size={14} />
Session exceeded 10 MB cap playback is truncated. Session exceeded 10 MB cap playback is truncated.

View File

@@ -31,7 +31,7 @@
justify-content: space-between; justify-content: space-between;
gap: 12px; gap: 12px;
padding: 4px 0; padding: 4px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.04); border-bottom: 1px solid var(--matrix-tint-10);
font-size: 0.8rem; font-size: 0.8rem;
} }
@@ -50,8 +50,8 @@
font-size: 0.7rem; font-size: 0.7rem;
letter-spacing: 0.05em; letter-spacing: 0.05em;
padding: 2px 6px; padding: 2px 6px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--matrix-tint-10);
background: rgba(255, 255, 255, 0.03); background: var(--matrix-tint-10);
color: var(--text-color); color: var(--text-color);
border-radius: 3px; border-radius: 3px;
min-width: 20px; min-width: 20px;

View File

@@ -5,7 +5,7 @@
.synthetic-files-root .mono { font-family: var(--font-mono); } .synthetic-files-root .mono { font-family: var(--font-mono); }
.synthetic-files-root .info-banner { .synthetic-files-root .info-banner {
background: rgba(255, 255, 255, 0.02); background: var(--matrix-tint-5);
border: 1px solid var(--border); border: 1px solid var(--border);
border-left: 3px solid var(--violet); border-left: 3px solid var(--violet);
padding: 10px 14px; padding: 10px 14px;
@@ -69,7 +69,7 @@
text-transform: uppercase; text-transform: uppercase;
} }
.synthetic-files-root .files-table tbody tr { .synthetic-files-root .files-table tbody tr {
border-bottom: 1px solid rgba(255, 255, 255, 0.04); border-bottom: 1px solid var(--matrix-tint-5);
cursor: pointer; cursor: pointer;
transition: background 0.1s; transition: background 0.1s;
} }
@@ -194,7 +194,7 @@
font-family: var(--font-mono); font-family: var(--font-mono);
white-space: pre-wrap; white-space: pre-wrap;
word-break: break-word; word-break: break-word;
background: rgba(255, 255, 255, 0.03); background: var(--matrix-tint-5);
border: 1px solid var(--border); border: 1px solid var(--border);
padding: 12px; padding: 12px;
font-size: 0.78rem; font-size: 0.78rem;

View File

@@ -80,7 +80,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
background: rgba(255, 255, 255, 0.015); background: var(--matrix-tint-5);
} }
.ttp-tag-card .ttp-card-head { .ttp-tag-card .ttp-card-head {

View File

@@ -57,7 +57,7 @@
.tlist-btn.danger:hover { background: var(--alert, #e74c3c); color: var(--bg); box-shadow: 0 0 10px rgba(231, 76, 60, 0.5); } .tlist-btn.danger:hover { background: var(--alert, #e74c3c); color: var(--bg); box-shadow: 0 0 10px rgba(231, 76, 60, 0.5); }
.tlist-btn.danger.armed { background: var(--alert, #e74c3c); color: #000; } .tlist-btn.danger.armed { background: var(--alert, #e74c3c); color: #000; }
.tlist-btn.warn { border-color: var(--warn, #e0a040); color: var(--warn, #e0a040); } .tlist-btn.warn { border-color: var(--warn, #e0a040); color: var(--warn, #e0a040); }
.tlist-btn.warn:hover { background: var(--warn, #e0a040); color: var(--bg); box-shadow: 0 0 10px rgba(224, 160, 64, 0.5); } .tlist-btn.warn:hover { background: var(--warn, #e0a040); color: var(--bg); box-shadow: 0 0 10px var(--warn); }
.tlist-btn.warn.armed { background: var(--warn, #e0a040); color: #000; } .tlist-btn.warn.armed { background: var(--warn, #e0a040); color: #000; }
.tlist-create-row { .tlist-create-row {

View File

@@ -57,7 +57,7 @@
.webhooks-root .btn.alert { border-color: var(--alert, #ff4d4d); color: var(--alert, #ff4d4d); } .webhooks-root .btn.alert { border-color: var(--alert, #ff4d4d); color: var(--alert, #ff4d4d); }
.webhooks-root .btn.alert:hover { background: var(--alert, #ff4d4d); color: var(--bg); box-shadow: 0 0 10px rgba(255, 77, 77, 0.5); } .webhooks-root .btn.alert:hover { background: var(--alert, #ff4d4d); color: var(--bg); box-shadow: 0 0 10px rgba(255, 77, 77, 0.5); }
.webhooks-root .btn.warn { border-color: var(--warn, #e0a040); color: var(--warn, #e0a040); } .webhooks-root .btn.warn { border-color: var(--warn, #e0a040); color: var(--warn, #e0a040); }
.webhooks-root .btn.warn:hover { background: var(--warn, #e0a040); color: var(--bg); box-shadow: 0 0 10px rgba(224, 160, 64, 0.5); } .webhooks-root .btn.warn:hover { background: var(--warn, #e0a040); color: var(--bg); box-shadow: 0 0 10px var(--warn); }
.webhooks-root .btn.ghost { border-color: var(--border-color); color: var(--matrix); opacity: 0.7; } .webhooks-root .btn.ghost { border-color: var(--border-color); color: var(--matrix); opacity: 0.7; }
.webhooks-root .btn.ghost:hover { opacity: 1; border-color: var(--matrix); background: transparent; box-shadow: var(--matrix-glow); } .webhooks-root .btn.ghost:hover { opacity: 1; border-color: var(--matrix); background: transparent; box-shadow: var(--matrix-glow); }
.webhooks-root .btn:disabled { opacity: 0.3; cursor: not-allowed; } .webhooks-root .btn:disabled { opacity: 0.3; cursor: not-allowed; }
@@ -67,7 +67,7 @@
} }
.webhooks-root .webhooks-warning-banner { .webhooks-root .webhooks-warning-banner {
background: rgba(224, 160, 64, 0.08); background: var(--warn-tint-10);
border: 1px solid var(--warn, #e0a040); border: 1px solid var(--warn, #e0a040);
color: var(--warn, #e0a040); color: var(--warn, #e0a040);
padding: 10px 14px; padding: 10px 14px;
@@ -167,7 +167,7 @@
.webhooks-root .wh-chip.status-warn { .webhooks-root .wh-chip.status-warn {
border-color: var(--warn, #e0a040); border-color: var(--warn, #e0a040);
background: rgba(224, 160, 64, 0.1); background: var(--warn-tint-10);
color: var(--warn, #e0a040); color: var(--warn, #e0a040);
} }

View File

@@ -14,11 +14,24 @@
/* Back-compat names used across the codebase */ /* Back-compat names used across the codebase */
--background-color: var(--bg); --background-color: var(--bg);
--bg-color: var(--bg); /* used by drawers and other inline styles */
--text-color: var(--matrix); --text-color: var(--matrix);
--accent-color: var(--violet); --accent-color: var(--violet);
--secondary-color: var(--panel); --secondary-color: var(--panel);
--border-color: var(--border); --border-color: var(--border);
/* Cyan/info — REPLAY buttons, neutral status that's neither
* "good/active" (matrix) nor "stop" (alert). */
--info: #22d3ee;
--info-tint-10: rgba(34, 211, 238, 0.10);
--info-tint-30: rgba(34, 211, 238, 0.30);
/* Benign/healthy — semantic alias for "verified good". Stays
* matrix in dark, picks up a darker emerald in light so a
* BENIGN pill still reads as "green check" without the dark-mode
* neon. */
--ok: var(--matrix);
/* ── Foreground opacities ──────────────────────── */ /* ── Foreground opacities ──────────────────────── */
--fg-1: var(--matrix); --fg-1: var(--matrix);
--fg-2: rgba(0, 255, 65, 0.80); --fg-2: rgba(0, 255, 65, 0.80);
@@ -151,6 +164,16 @@ html[data-theme="light"] {
--warn-tint-10: rgba(180, 83, 9, 0.12); --warn-tint-10: rgba(180, 83, 9, 0.12);
--crit-tint-10: rgba(185, 28, 28, 0.10); --crit-tint-10: rgba(185, 28, 28, 0.10);
/* Cyan/info dims to slate in light mode so REPLAY buttons read
* as a calm secondary against cream rather than an electric pop. */
--info: #155e75;
--info-tint-10: rgba(21, 94, 117, 0.10);
--info-tint-30: rgba(21, 94, 117, 0.20);
/* Benign in light mode — emerald, the one "happy green" we keep,
* tuned dark enough to read on cream. */
--ok: #047857;
/* Glows no-op'd — kept defined so .btn:hover etc. don't /* Glows no-op'd — kept defined so .btn:hover etc. don't
* break, just produce no halo. */ * break, just produce no halo. */
--matrix-glow: none; --matrix-glow: none;