Graphite theme. Theme consolidation

This commit is contained in:
Borys Levytskyi
2025-11-27 22:25:01 -05:00
parent 98675cafc7
commit 0192c51933
15 changed files with 640 additions and 452 deletions

View File

235
src/css/index.css Normal file
View File

@@ -0,0 +1,235 @@
body { padding:0; margin:0; height: 100%; overflow: hidden; }
html { height: 100% }
/* Theme bundles */
@import './theme-light.css';
@import './theme-dark.css';
@import './theme-midnight.css';
@import './theme-bladerunner.css';
@import './theme-graphite.css';
@import './theme.css';
.app-root {
font-family: var(--font-family, Verdana);
font-size: 0.8em;
margin: 0;
padding: 0px 30px;
height: 100%;
overflow: auto;
position: relative;
}
/* Centered vs stretched layout */
.app-root.layout-centered { }
/* Constrain and center top-level sections while keeping full-width theme background */
.app-root.layout-centered > * {
max-width: clamp(70rem, 92vw, 100rem);
margin-left: auto;
margin-right: auto;
}
/* Theme-specific overrides are moved into their theme-*.css files */
.app-root.layout-stretched {
max-width: none;
margin: 0;
}
/* Theme-scoped code styling to avoid cross-theme overrides */
.light code, .dark code, .midnight code, .bladerunner code, .graphite code { font-size: 1.2em; font-weight: bold; }
h1 { font-family: Impact, Verdana;
text-transform: uppercase;
font-weight: lighter;
}
.icon { margin-right: 5px; vertical-align: middle; }
.header-cmd { color: #c5c5c5 }
.mono { font-family: monospace; font-size: 1.3em }
.button {
padding: 10px;
border: solid 1px white;
border-radius: 5px;
text-decoration: none;
display: inline-block;
}
.button { padding: 5px;}
.button svg { margin: 0; margin-right: 5px; }
.button-large { padding: 10px; }
.expressionInput {
padding: 3px;
outline: none;
border: none;
border-bottom: solid 1px rgba(255, 255, 255, 0.5);
z-index: 100;
padding-left: 15px;
padding-bottom: 5px;
width: 600px;
background: rgba(0, 0, 0, 0);
}
.hidden { display: none;}
.result { margin: 10px 10px 30px; }
.result .input { margin-bottom: 10px; }
.result .content { padding-left: 10px}
.result .cur { margin-right: 5px; }
.input-string { margin-right: 10px;}
.hashLink { text-decoration: none; margin-left: 8px; visibility: hidden; margin-right: 0; padding: 0; text-decoration: none; }
a.hashLink { font-size: 1.1em;}
.hashLink .icon { margin: 0;}
.hashLink:hover { text-decoration: underline; background: none; }
.result:hover .hashLink { visibility: visible }
.expression { font-size: 1.7em; font-family: monospace }
.expression button { font-family: monospace; font-size: 0.9em;}
.expression .label { font-weight: bold; padding-right: 5px; text-align: right; }
.expression .bin { letter-spacing: 3px; }
.expression .info { font-size: 0.9em; color: teal; }
.expression .byte { margin: 0 3px; }
.expression-result td { border-top: dotted 1px gray; }
.expression .prefix { font-weight: normal; display: none; font-size: 0.9em }
.expression .other { font-size: 0.9em}
.expression .sign { text-align: right; padding-right: 5px;}
.flipable { cursor: pointer; opacity: 1 }
.flipable { cursor: pointer; opacity: 1 }
.flipable:hover { opacity: 0.8 }
.hex .prefix { display: inline; }
.indicator { padding: 0px 5px; background: transparent; border: none; cursor: pointer; vertical-align: middle; color:rgba(0, 0, 0, 0.25) }
.expanded { display: block;}
.collapsed { display: none;}
.error { color: maroon; }
.soft { opacity: 0.7 }
.small-text { font-size: 0.8em;}
#view { padding: 10px}
.cur { color: var(--cur-color, lightgray); }
button { border: none; }
button.link-button {text-decoration: underline;}
.settings-button {
margin-left: -20px;
}
/* When Settings is active (no .soft), remove any button border/outline */
.settings-button button,
.settings-button .command-link {
border: none;
outline: none;
box-shadow: none;
}
.undo button {
opacity: 0.4;
padding: 0;
margin-left: 5px;
}
.solid-border { border: solid 1px rgba(255, 255, 255, 0.8); border-radius: 5px;}
.solid-border-soft { border: solid 1px rgba(255, 255, 255, 0.5); border-radius: 5px;}
.zero { opacity: 0.5}
.dim-extra-bits .extra-bit { opacity: 0.1;}
/* Light theme moved to theme-light.css */
/* Dark theme moved to theme-dark.css */
/* Midnight theme moved to theme-midnight.css */
/* Blade Runner theme moved to theme-bladerunner.css */
.bladerunner .bladerunner-easter-egg {display: none;}
.bladerunner-easter-egg {
position: absolute;
right: 1em;
bottom: 1em;
opacity: 0.3;
}
.bladerunner-easter-egg:hover {
opacity: 1;
}
button {
border: none;
background: none;
cursor: pointer;
}
button:focus {outline:0;}
/* Remove blue focus ring from the Blade Runner easter egg button */
.bladerunner-easter-egg button:focus,
.bladerunner-easter-egg button:focus-visible {
outline: none !important;
box-shadow: none !important;
}
/* Anchor the Blade Runner easter egg to bottom-right regardless of scrolling */
.bladerunner-easter-egg {
position: fixed;
right: 20px;
bottom: 20px;
z-index: 1000;
}
/* Top Links Shrink */
@media (max-width: 800px) {
.top-links .link-text { display: none }
.debug-indicators { display: none;}
.app-root {padding: 10px; }
}
.social-container{ position:fixed; bottom:20px; right:20px }
/* Remove margin space on body. Inline top links with header */
@media (max-width: 700px) {
/*.expressionInput { width: 450px; } */
}
/* Further shrink */
@media (max-width: 500px) {
.expressionInput { width: 400px; }
.top-links a { display: inline-block; padding: 5px 10px}
}
@media (max-width: 450px) {
.expressionInput { width: 350px; }
}
#output {
padding: 30px 30px;
}
.input-p {
display:inline;
z-index: 101;
position: absolute;
margin-right: -10px;
margin-top: 3px;
opacity: 0.5;
}

View File

@@ -0,0 +1,140 @@
/* Blade Runner theme tokens */
.app-root.bladerunner {
--bg-color: #0b0f14;
--text-color: #e6f0ff;
--solid-bg-color: #0b0f14;
--font-family: Verdana, sans-serif;
--header-cmd-color: #ff7fb0a8; /* lights-on override remains below */
--anchor-color: #00d1f2;
--button-color: #00eaff;
--indicator-color: #0e6e7e;
--on-color: white;
--prefix-color: #00d1f2;
--other-color: #6c8497;
--hashlink-color: #52687b;
--hashlink-hover-color: #5fc2e9;
--top-links-li-hover-bg: transparent;
--error-color: #d83e8f;
--btn-color: #00eaff;
--btn-hover-bg: #11222c;
--btn-disabled-color: #0e6e7e;
--accent1-color: #e3a600;
--accent-background: #131a22;
--button-border-color: #00eaff;
--solid-border-color: #1f3b4a;
--help-code-color: #e3a600;
--input-border-color: #1f3b4a;
--input-text-color: white;
--expression-color: #e6f0ff;
--button-hover-bg: var(--top-links-li-hover-bg);
--cur-color: #6c8497;
--panel-bg-color: #0e161d;
--label-color: #7ac9d6;
--command-link-color: #5fc2e9;
--top-links-color: #dce7f5;
--top-links-hover-color: hsl(45, 100%, 50%);
--soft-color: #aebed0;
--zero-color: #b9cfe2;
--placeholder-color: #7e95a7;
--settings-button-color: #b9cfe2;
--lights-on-header-color: #ff7fb0;
--settings-accent-color: #ffbf69;
}
/* Blade Runner header effects */
.bladerunner .header-cmd { color: var(--header-cmd-color) !important; }
.bladerunner .lights-on .header-cmd { color: var(--lights-on-header-color) !important; }
.bladerunner .header.lights-on { text-shadow: 0 0 4px rgba(255, 127, 176, 0.35), 0 0 9px rgba(255, 127, 176, 0.22); }
.bladerunner .header h1 { text-transform: uppercase; color: #66d9e8a8; cursor: pointer; position: relative; z-index: 1; font-weight: bold; user-select: none;}
.bladerunner .header h1.lights-on { color: #66d9e8; text-shadow: 0 0 4px rgba(102, 217, 232, 0.35), 0 0 9px rgba(102, 217, 232, 0.22); }
.bladerunner .header h1.lights-on::after {
content: "";
animation: flicker 1s forwards;
position: absolute;
left: 0;
top: 50%;
transform: translate(-30%, -50%);
width: 20%;
height: 120%;
pointer-events: none;
z-index: 0;
background:
radial-gradient(ellipse at center,
rgba(102, 217, 232, 0.70) 0%,
rgba(102, 217, 232, 0.45) 22%,
rgba(0, 0, 0, 0) 60%),
radial-gradient(ellipse at center,
rgba(255, 127, 176, 0.55) 0%,
rgba(255, 127, 176, 0.35) 35%,
rgba(0, 0, 0, 0) 72%);
filter: blur(35px);
}
@keyframes flicker {
20%, 24%, 55% { opacity: 0; }
40% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 1; }
}
/* Blade Runner-specific component tweaks */
.bladerunner .accent1 button:hover { text-shadow: 0 0 2px #e3a600 }
.bladerunner .command-link:hover,
.bladerunner .command-link:focus { text-shadow: 0 0 2px rgba(69, 243, 255, 0.949); }
.bladerunner button.hashLink:hover, .bladerunner .undo button:hover, .bladerunner a.hashLink:hover {
--text-shadow: 0 0 2px currentColor;
text-shadow: 0 0 2px rgb(229, 33, 0.5);
color: var(--hashlink-hover-color);
}
.bladerunner .undo button:hover { opacity: 1; }
/* Blade Runner: subtle glow for SVG icons inside hash links on hover/focus */
.bladerunner .hashLink:hover .icon,
.bladerunner .hashLink:focus .icon,
.bladerunner .hashLink:hover svg,
.bladerunner .undo:hover svg,
.bladerunner .hashLink:focus svg {
filter: drop-shadow(0 0 2px currentColor);
}
/* Blade Runner: neon hover glow for top-links controls */
.bladerunner .top-links a, .bladerunner .top-links a:visited { color: var(--top-links-color); }
.bladerunner .top-links button { color: var(--top-links-color); }
.bladerunner .top-links a:hover,
.bladerunner .top-links a:focus,
.bladerunner .top-links button:hover,
.bladerunner .top-links button:focus {
text-shadow: 0 0 2px rgb(229, 33, 0.5);
color: var(--top-links-hover-color);
}
/* Optional: prototype radial glow kept commented
.bladerunner .top-links li {position: relative;}
.bladerunner .top-links button:hover::after, .bladerunner .top-links a:hover::after {
content: "";
position: absolute;
right: 50%;
top: 50%;
transform: translate(50%, -50%);
white-space: nowrap;
width: 200%;
height: 120%;
pointer-events: none;
z-index: 0;
background: radial-gradient(ellipse at center, rgba(227, 166, 0, 0.85) 0%, rgba(227, 166, 0, 0.55) 22%, rgba(0, 0, 0, 0) 60%);
filter: blur(20px);
}
*/
/* Blade Runner: add matching glow to SVG icons inside top-links on hover/focus */
.bladerunner .top-links a:hover .icon,
.bladerunner .top-links a:focus .icon,
.bladerunner .top-links button:hover .icon,
.bladerunner .top-links button:focus .icon,
.bladerunner .top-links a:hover svg,
.bladerunner .top-links a:focus svg,
.bladerunner .top-links button:hover svg,
.bladerunner .top-links button:focus svg {
color: amber !important;
filter: drop-shadow(0 0 2px rgba(255, 127, 176, 0.5));
}

27
src/css/theme-dark.css Normal file
View File

@@ -0,0 +1,27 @@
/* Dark theme tokens */
.app-root.dark {
--bg-color: #121212;
--text-color: white;
--solid-bg-color: #121212;
--font-family: Verdana, sans-serif;
--header-cmd-color: #c5c5c5; /* default fallback used for header-cmd unless overridden */
--anchor-color: white;
--button-color: white;
--indicator-color: #555;
--on-color: white;
--prefix-color: #999;
--other-color: #777;
--hashlink-color: #555;
--hashlink-hover-color: #999;
--top-links-li-hover-bg: #333;
--error-color: #d83e8f;
--btn-color: white;
--btn-hover-bg: #333;
--btn-disabled-color: #999;
--accent1-color: mediumseagreen;
--help-code-color: mediumseagreen;
--input-border-color: rgba(255, 255, 255, 0.5);
--input-text-color: white;
--expression-color: white;
--button-hover-bg: rgba(255, 255, 255, 0.2);
}

View File

@@ -0,0 +1,42 @@
/* Graphite theme tokens */
.app-root.graphite {
--bg-color: #151617;
--solid-bg-color: #151617;
--text-color: #ececec;
--font-family: Verdana, sans-serif;
--header-cmd-color: #5f9ea0;
--anchor-color: #5f9ea0;
--button-color: #5f9ea0;
--indicator-color: #9aa0a3;
--on-color: #ececec;
--prefix-color: #5f9ea0;
--other-color: #7a8286;
--hashlink-color: #9aa0a3;
--hashlink-hover-color: #b4c6c9;
--top-links-li-hover-bg: #191c1d;
--error-color: #d83e8f;
--btn-color: #ececec;
--btn-hover-bg: #1f2324;
--btn-disabled-color: #9aa0a3;
--accent1-color: #5f9ea0;
--accent-background: #191c1d;
--button-border-color: #313639;
--solid-border-color: #313639;
--help-code-color: #b4c6c9;
--input-border-color: #313639;
--input-text-color: #ececec;
--expression-color: #ececec;
--button-hover-bg: #1f2324;
--cur-color: #5f9ea0;
--panel-bg-color: #1f2324;
--label-color: #b4c6c9;
--command-link-color: #5f9ea0;
--top-links-color: #ececec;
--top-links-hover-color: #5f9ea0;
--soft-color: #9aa0a3;
--zero-color: #b4c6c9;
--placeholder-color: #9aa0a3;
--settings-button-color: #b4c6c9;
--settings-accent-color: #5f9ea0;
--lights-on-header-color: #b4c6c9;
}

31
src/css/theme-light.css Normal file
View File

@@ -0,0 +1,31 @@
/* Light theme tokens */
.app-root.light {
--bg-color: #fafafa;
--text-color: #121212;
--solid-bg-color: var(--bg-color);
--font-family: Verdana, sans-serif;
--header-cmd-color: #919191;
--anchor-color: #222;
--button-color: #222;
--indicator-color: #ddd;
--on-color: #121212;
--prefix-color: #888;
--other-color: #bbb;
--hashlink-color: #aaa;
--hashlink-hover-color: #888;
--top-links-li-hover-bg: #ddd;
--error-color: #d83e8f;
--btn-color: black;
--btn-hover-bg: #ddd;
--btn-disabled-color: #888;
--accent1-color: green;
--accent-background: transparent;
--button-border-color: gray;
--solid-border-color: gray;
--help-code-color: green;
--input-border-color: rgba(0, 0, 0, 0.5);
--input-text-color: inherit;
--expression-color: var(--text-color);
--button-hover-bg: rgba(255, 255, 255, 0.2);
--cur-color: lightgray;
}

View File

@@ -0,0 +1,28 @@
/* Midnight theme tokens */
.app-root.midnight {
--bg-color: #2c3e50;
--text-color: white;
--solid-bg-color: #2c3e50;
--font-family: Verdana, sans-serif;
--header-cmd-color: #7ea3b5;
--anchor-color: white;
--button-color: white;
--indicator-color: #85a0ad;
--on-color: white;
--prefix-color: #85a0ad;
--other-color: #9FBAC7;
--hashlink-color: #85a0ad;
--hashlink-hover-color: #9FBAC7;
--top-links-li-hover-bg: #132537;
--error-color: #d83e8f;
--btn-color: white;
--btn-hover-bg: #132537;
--btn-disabled-color: #85a0ad;
--accent1-color: mediumseagreen;
--accent-background: #3b5268;
--help-code-color: mediumseagreen;
--input-border-color: rgba(255, 255, 255, 0.5);
--input-text-color: white;
--expression-color: white;
--button-hover-bg: rgba(255, 255, 255, 0.2);
}

110
src/css/theme.css Normal file
View File

@@ -0,0 +1,110 @@
/* Shared theme surface rules driven by CSS variables */
.app-root {
background: var(--bg-color);
color: var(--text-color);
}
.app-root .solid-background {
background: var(--solid-bg-color);
}
.app-root .header-cmd {
color: var(--header-cmd-color);
}
.app-root .lights-on .header-cmd,
.app-root .header-cmd.lights-on {
color: var(--lights-on-header-color, var(--header-cmd-color));
}
.app-root a,
.app-root a:visited,
.app-root button {
color: var(--anchor-color);
}
.app-root .indicator { color: var(--indicator-color); }
.app-root .on { color: var(--on-color); }
.app-root .prefix { color: var(--prefix-color); }
.app-root .other { color: var(--other-color); }
.app-root .expression { color: var(--expression-color); }
.app-root .accent-background { background-color: var(--accent-background, transparent); }
.app-root .hashLink,
.app-root .hashLink:visited {
color: var(--hashlink-color);
}
.app-root .hashLink:hover {
color: var(--hashlink-hover-color);
}
.app-root ul.top-links li:hover {
background: var(--top-links-li-hover-bg);
border-radius: 10px;
}
.app-root .error { color: var(--error-color); }
.app-root button.btn { color: var(--btn-color); }
.app-root button.btn:hover { background: var(--btn-hover-bg); }
.app-root button.btn:disabled {
color: var(--btn-disabled-color);
background-color: inherit;
}
.app-root .accent1 { color: var(--accent1-color); }
.app-root .accent1-border { border-color: var(--accent1-color); }
.app-root .expressionInput {
border-bottom: solid 1px var(--input-border-color);
color: var(--input-text-color);
}
.app-root .button {
border: solid 1px var(--button-border-color, var(--solid-border-color, currentColor));
}
.app-root .button:hover {
background: var(--button-hover-bg);
}
.app-root .solid-border {
border: solid 1px var(--solid-border-color, var(--button-border-color, currentColor));
background-color: var(--panel-bg-color, transparent);
}
.app-root .help code,
.app-root .help code a {
color: var(--help-code-color);
}
.app-root .cur { color: var(--cur-color, inherit); }
.app-root .soft { color: var(--soft-color, inherit); }
.app-root .label { color: var(--label-color, inherit); }
.app-root .zero { color: var(--zero-color, inherit); }
.app-root .command-link {
color: var(--command-link-color, var(--anchor-color));
}
.app-root .expressionInput::placeholder {
color: var(--placeholder-color, inherit);
}
.app-root .top-links a,
.app-root .top-links a:visited,
.app-root .top-links button {
color: var(--top-links-color, var(--anchor-color));
}
.app-root .top-links a:hover,
.app-root .top-links a:focus,
.app-root .top-links button:hover,
.app-root .top-links button:focus {
color: var(--top-links-hover-color, var(--anchor-color));
}
.app-root #settings button {
color: var(--settings-accent-color, inherit);
}

View File

@@ -1,443 +0,0 @@
body { padding:0; margin:0; height: 100%; overflow: hidden; }
html { height: 100% }
.app-root {
font-family: Verdana;
font-size: 0.8em;
margin: 0;
padding: 0px 30px;
height: 100%;
overflow: auto;
position: relative;
}
/* Centered vs stretched layout */
.app-root.layout-centered { }
/* Constrain and center top-level sections while keeping full-width theme background */
.app-root.layout-centered > * {
max-width: clamp(70rem, 92vw, 100rem);
margin-left: auto;
margin-right: auto;
}
/* Blade Runner theme overrides for Settings pane (centralized here per AGENTS.md) */
.app-root.bladerunner #settings button { color: #ffbf69 }
.app-root.layout-stretched {
max-width: none;
margin: 0;
}
/* Theme-scoped code styling to avoid cross-theme overrides */
.light code, .dark code, .midnight code, .bladerunner code { font-size: 1.2em; font-weight: bold; }
h1 { font-family: Impact, Verdana;
text-transform: uppercase;
font-weight: lighter;
}
.icon { margin-right: 5px; vertical-align: middle; }
.header-cmd { color: #c5c5c5 }
.mono { font-family: monospace; font-size: 1.3em }
.button {
padding: 10px;
border: solid 1px white;
border-radius: 5px;
text-decoration: none;
display: inline-block;
}
.button { padding: 5px;}
.button svg { margin: 0; margin-right: 5px; }
.button-large { padding: 10px; }
.expressionInput {
padding: 3px;
outline: none;
border: none;
border-bottom: solid 1px rgba(255, 255, 255, 0.5);
z-index: 100;
padding-left: 15px;
padding-bottom: 5px;
width: 600px;
background: rgba(0, 0, 0, 0);
}
.hidden { display: none;}
.result { margin: 10px 10px 30px; }
.result .input { margin-bottom: 10px; }
.result .content { padding-left: 10px}
.result .cur { margin-right: 5px; }
.input-string { margin-right: 10px;}
.hashLink { text-decoration: none; margin-left: 8px; visibility: hidden; margin-right: 0; padding: 0; text-decoration: none; }
a.hashLink { font-size: 1.1em;}
.hashLink .icon { margin: 0;}
.hashLink:hover { text-decoration: underline; background: none; }
.result:hover .hashLink { visibility: visible }
.expression { font-size: 1.7em; font-family: monospace }
.expression button { font-family: monospace; font-size: 0.9em;}
.expression .label { font-weight: bold; padding-right: 5px; text-align: right; }
.expression .bin { letter-spacing: 3px; }
.expression .info { font-size: 0.9em; color: teal; }
.expression .byte { margin: 0 3px; }
.expression-result td { border-top: dotted 1px gray; }
.expression .prefix { font-weight: normal; display: none; font-size: 0.9em }
.expression .other { font-size: 0.9em}
.expression .sign { text-align: right; padding-right: 5px;}
.flipable { cursor: pointer; opacity: 1 }
.flipable { cursor: pointer; opacity: 1 }
.flipable:hover { opacity: 0.8 }
.hex .prefix { display: inline; }
.indicator { padding: 0px 5px; background: transparent; border: none; cursor: pointer; vertical-align: middle; color:rgba(0, 0, 0, 0.25) }
.expanded { display: block;}
.collapsed { display: none;}
.error { color: maroon; }
.soft { opacity: 0.7 }
.small-text { font-size: 0.8em;}
#view { padding: 10px}
.cur { color: lightgray; }
button { border: none; }
button.link-button {text-decoration: underline;}
.settings-button {
margin-left: -20px;
}
/* When Settings is active (no .soft), remove any button border/outline */
.settings-button button,
.settings-button .command-link {
border: none;
outline: none;
box-shadow: none;
}
.undo button {
opacity: 0.4;
padding: 0;
margin-left: 5px;
}
.solid-border { border: solid 1px rgba(255, 255, 255, 0.8); border-radius: 5px;}
.solid-border-soft { border: solid 1px rgba(255, 255, 255, 0.5); border-radius: 5px;}
.zero { opacity: 0.5}
.dim-extra-bits .extra-bit { opacity: 0.1;}
/* Light */
.light { background: #fafafa; }
.light .solid-background {background: #fafafa;}
.light .header-cmd { color: #919191 }
.light a, .light a:visited, .light button { color: #222; }
.light .indicator { color: #ddd; }
.light .on { color: #121212; }
.light .prefix { color: #888}
.light .other { color: #bbb }
.light .hashLink, .light .hashLink:visited { color: #aaa; }
.light .hashLink:hover { color: #888 }
.light ul.top-links li:hover { background: #ddd }
.light .error { color: #d83e8f }
.light button.btn { color: black}
.light button.btn:hover { background: #ddd}
.light button.btn:disabled { color: #888; background-color: inherit; }
.light .accent1 { color:green}
.light .expressionInput { border-bottom: solid 1px rgba(0, 0, 0, 0.5);}
.light .button { border: solid 1px gray; }
.light .button:hover { background: rgba(0, 0, 0, 0.2);}
.light .solid-border { border: solid 1px gray;}
.light .accent1-border { border-color:green}
.light .help code, .light .help code a { color:green}
.light .button:hover { background: rgba(255, 255, 255, 0.2);}
/* Dark */
.dark { background: #121212; color: white;}
.dark .solid-background {background: #121212;}
.dark .expression { color: white;}
.dark .expressionInput { color: white; }
.dark a, .dark a:visited, .dark button { color: white; }
.dark .indicator { color: #555; }
.dark .on { color: white; }
.dark .prefix { color: #999}
.dark .other { color: #777;}
.dark .hashLink, .dark .hashLink:visited { color: #555 }
.dark .hashLink:hover { color: #999 }
.dark ul.top-links li:hover { background: #333 }
.dark .error { color: #d83e8f}
.dark button.btn { color: white}
.dark button.btn:hover { background: #333}
.dark button.btn:disabled { color: #999; background-color: inherit; }
.dark .accent1 { color:mediumseagreen}
.dark .accent1-border { border-color:mediumseagreen}
.dark .help code, .dark .help code a { color:mediumseagreen}
.dark .button:hover { background: rgba(255, 255, 255, 0.2);}
/*
Midnight Theme
*/
.midnight { background: #2c3e50; color: white }
.midnight .solid-background {background: #2c3e50;}
.midnight .header-cmd { color: #7ea3b5 !important }
.midnight .expression { color: white;}
.midnight .expressionInput { color: white;}
.midnight a, .dark a:visited, .midnight button { color: white; }
.midnight .indicator { color: #85a0ad; }
.midnight .on { color: white; }
.midnight .prefix { color: #85a0ad}
.midnight .other { color: #9FBAC7;}
.midnight .accent-background { background-color: #3b5268;}
.midnight .hashLink, .midnight .hashLink:visited { color: #85a0ad }
.midnight .hashLink:hover { color: #9FBAC7 }
.midnight ul.top-links li:hover { background: #132537 }
.midnight .error { color:#d83e8f}
.midnight .changelog .item-new .date { font-weight: bold }
.midnight button.btn { color: white}
.midnight button.btn:hover { background: #132537}
.midnight button.btn:disabled { color: #85a0ad; background-color: inherit; }
.midnight .accent1 { color:mediumseagreen}
.midnight .accent1-border { border-color:mediumseagreen}
.midnight .help code, .midnight .help code a { color:mediumseagreen}
.midnight .button:hover { background: rgba(255, 255, 255, 0.2);}
/*
Blade Runner Theme
*/
.bladerunner { background: #0b0f14; color: white }
.bladerunner .solid-background { background: #0b0f14; }
.bladerunner .header-cmd { color: #ff7fb0a8 !important; }
.bladerunner .lights-on .header-cmd { color: #ff7fb0 !important; }
.bladerunner .header.lights-on { text-shadow: 0 0 4px rgba(255, 127, 176, 0.35), 0 0 9px rgba(255, 127, 176, 0.22); }
.bladerunner .header h1 { text-transform: uppercase; color: #66d9e8a8; cursor: pointer; position: relative; z-index: 1; font-weight: bold; user-select: none;}
.bladerunner .header h1.lights-on { color: #66d9e8; text-shadow: 0 0 4px rgba(102, 217, 232, 0.35), 0 0 9px rgba(102, 217, 232, 0.22); }
.bladerunner .header h1.lights-on::after {
/* Neon-style halo: layered cyan + magenta radial glows */
content: "";
animation: flicker 1s forwards;
position: absolute;
left: 0;
top: 50%;
transform: translate(-30%, -50%);
width: 20%;
height: 120%;
pointer-events: none;
z-index: 0;
background:
radial-gradient(ellipse at center,
rgba(102, 217, 232, 0.70) 0%,
rgba(102, 217, 232, 0.45) 22%,
rgba(0, 0, 0, 0) 60%),
radial-gradient(ellipse at center,
rgba(255, 127, 176, 0.55) 0%,
rgba(255, 127, 176, 0.35) 35%,
rgba(0, 0, 0, 0) 72%);
filter: blur(35px);
}
@keyframes flicker {
20%, 24%, 55% {
opacity: 0;
}
40% {
opacity: 1;
}
80% {
opacity: 1;
}
100% {
opacity: 1;
}
}
.bladerunner {color: #e6f0ff;}
.bladerunner .expression { color: white; }
.bladerunner .expressionInput { color: white; }
.bladerunner a, .bladerunner a:visited { color: #00d1f2; }
.bladerunner button { color: #00eaff; }
.bladerunner .indicator { color: #0e6e7e; }
.bladerunner .on { color: white; }
.bladerunner .prefix { color: #00d1f2 }
.bladerunner .other { color: #6c8497}
.bladerunner .label { color: #7ac9d6 }
.bladerunner .accent-background { background-color: #131a22; }
.bladerunner .hashLink:hover { color: #33e1ff }
.bladerunner .error { color:#d83e8f }
.bladerunner .changelog .item-new .date { font-weight: bold }
.bladerunner button.btn { color: #00eaff }
.bladerunner button.btn:hover { background: #11222c }
.bladerunner button.btn:disabled { color: #0e6e7e; background-color: inherit; }
.bladerunner .accent1 { color: #e3a600 }
.bladerunner .accent1 button:hover { text-shadow: 0 0 2px #e3a600 }
.bladerunner .accent1-border { border-color: #e3a600 }
.bladerunner .button { border-color: #00eaff }
.bladerunner code { color: #e3a600 }
.bladerunner code a, .bladerunner code a:visited { color: #e3a600 }
.bladerunner .command-link { color: #5fc2e9 }
.bladerunner .command-link:hover,
.bladerunner .command-link:focus { text-shadow: 0 0 2px rgba(69, 243, 255, 0.949); }
.bladerunner .soft { color: #aebed0 }
.bladerunner .solid-border { background-color: #0e161d; border-color: #1f3b4a;}
.bladerunner .expressionInput {border-color: #1f3b4a;}
.bladerunner .expressionInput::placeholder {color: #7e95a7;}
.bladerunner .zero {color: #b9cfe2; }
.bladerunner .expression {color: #e6f0ff;}
.bladerunner .settings-button button {color: #b9cfe2;}
.bladerunner button.hashLink, .bladerunner a.hashLink, .bladerunner a.hashLink:visited { color: #52687b; }
.bladerunner button.hashLink:hover, .bladerunner .undo button:hover, .bladerunner a.hashLink:hover {
/* subtle glow derived from current hover color */
--text-shadow: 0 0 2px currentColor;
text-shadow:0 0 2px rgb(229, 33, 0.5);
color: #5fc2e9;
}
.bladerunner .undo button:hover { opacity: 1; }
.bladerunner .cur { color: #6c8497; }
/* Blade Runner: subtle glow for SVG icons inside hash links on hover/focus */
.bladerunner .hashLink:hover .icon,
.bladerunner .hashLink:focus .icon,
.bladerunner .hashLink:hover svg,
.bladerunner .undo:hover svg,
.bladerunner .hashLink:focus svg {
filter: drop-shadow(0 0 2px currentColor);
}
/* Blade Runner: neon hover glow for top-links controls */
.bladerunner .top-links a, .bladerunner .top-links a:visited { color: #dce7f5 }
.bladerunner .top-links button { color: #dce7f5 }
.bladerunner .top-links a:hover,
.bladerunner .top-links a:focus,
.bladerunner .top-links button:hover,
.bladerunner .top-links button:focus {
/* very dim magenta glow */
text-shadow:0 0 2px rgb(229, 33, 0.5);
color: hsl(45, 100%, 50%);
}
/*
.bladerunner .top-links li {position: relative;}
.bladerunner .top-links button:hover::after, .bladerunner .top-links a:hover::after {
content: "";
position: absolute;
right: 50%;
top: 50%;
transform: translate(50%, -50%);
white-space: nowrap;
width: 200%;
height: 120%;
pointer-events: none;
z-index: 0;
background:
radial-gradient(ellipse at center,
rgba(227, 166, 0, 0.85) 0%,
rgba(227, 166, 0, 0.55) 22%,
rgba(0, 0, 0, 0) 60%);
filter: blur(20px);
}*/
/* Blade Runner: add matching glow to SVG icons inside top-links on hover/focus */
.bladerunner .top-links a:hover .icon,
.bladerunner .top-links a:focus .icon,
.bladerunner .top-links button:hover .icon,
.bladerunner .top-links button:focus .icon,
.bladerunner .top-links a:hover svg,
.bladerunner .top-links a:focus svg,
.bladerunner .top-links button:hover svg,
.bladerunner .top-links button:focus svg {
color: amber !important;
filter: drop-shadow(0 0 2px rgba(255, 127, 176, 0.5));
}
.bladerunner .bladerunner-easter-egg {display: none;}
.bladerunner-easter-egg {
position: absolute;
right: 1em;
bottom: 1em;
opacity: 0.3;
}
.bladerunner-easter-egg:hover {
opacity: 1;
}
button {
border: none;
background: none;
cursor: pointer;
}
button:focus {outline:0;}
/* Remove blue focus ring from the Blade Runner easter egg button */
.bladerunner-easter-egg button:focus,
.bladerunner-easter-egg button:focus-visible {
outline: none !important;
box-shadow: none !important;
}
/* Anchor the Blade Runner easter egg to bottom-right regardless of scrolling */
.bladerunner-easter-egg {
position: fixed;
right: 20px;
bottom: 20px;
z-index: 1000;
}
/* Top Links Shrink */
@media (max-width: 800px) {
.top-links .link-text { display: none }
.debug-indicators { display: none;}
.app-root {padding: 10px; }
}
.social-container{ position:fixed; bottom:20px; right:20px }
/* Remove margin space on body. Inline top links with header */
@media (max-width: 700px) {
/*.expressionInput { width: 450px; } */
}
/* Further shrink */
@media (max-width: 500px) {
.expressionInput { width: 400px; }
.top-links a { display: inline-block; padding: 5px 10px}
}
@media (max-width: 450px) {
.expressionInput { width: 350px; }
}
#output {
padding: 30px 30px;
}
.input-p {
display:inline;
z-index: 101;
position: absolute;
margin-right: -10px;
margin-top: 3px;
opacity: 0.5;
}

View File

@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client';
import cmd, { CommandInput } from './shell/cmd';
import AppRoot from './shell/components/AppRoot';
import log from 'loglevel';
import './index.css';
import './css/index.css';
import networkingAppModule from './networking/module';
import expressionAppModule from './expression/module';
import shellModule from './shell/module';

View File

@@ -1,6 +1,6 @@
import log from 'loglevel';
export const APP_VERSION = 10;
export const APP_VERSION = 11;
export type PersistedAppData = {
emphasizeBytes: boolean;
@@ -49,7 +49,7 @@ export default class AppState {
this.env = env;
this.uiTheme = persistData.uiTheme;
this.uiTheme = normalizeTheme(persistData.uiTheme);
this.emphasizeBytes = !!persistData.emphasizeBytes;
this.persistedVersion = persistData.version || 0.1;
this.wasOldVersion = persistData.version !== null && persistData.version !== undefined && this.version > this.persistedVersion;
@@ -97,10 +97,12 @@ export default class AppState {
setUiTheme(theme: string) {
if(this.uiTheme === theme)
const normalized = normalizeTheme(theme);
if(this.uiTheme === normalized)
return;
this.uiTheme = theme;
this.uiTheme = normalized;
this.triggerChanged('uiTheme');
}
@@ -166,3 +168,8 @@ export default class AppState {
function generateKey(): number {
return Math.ceil(Math.random() * 10000000) ^ Date.now(); // Because why the hell not...
}
function normalizeTheme(theme: string): string {
if (theme === 'iron') return 'graphite';
return theme;
}

View File

@@ -1,6 +1,6 @@
.help ul { list-style-type: none; margin: 0; margin-left: 10px; margin-top: 0.2em; padding: 0; }
.help li { padding: 1px; margin-bottom: 5px;}
.light .help code, .light .help code a { color:green}
/* Theme-specific styling moved to src/index.css via CSS variables */
.help p { margin-top: 0.5em }
.help .section {padding: 1em;}
.help .panel-container {overflow: hidden;}

View File

@@ -32,6 +32,7 @@ function HelpResultView() {
<li><code><CommandLink text="light" /></code> set the Light color theme</li>
<li><code><CommandLink text="dark" /></code> set the Dark color theme</li>
<li><code><CommandLink text="midnight" /></code> set the Midnight color theme</li>
<li><code><CommandLink text="graphite" /></code> set the Graphite color theme</li>
</ul>
</div>
<div className="section">

View File

@@ -7,6 +7,14 @@ function WhatsNewResultView() {
return <div className="changelog">
<h3>Changelog</h3>
<div className='item item-new'>
<p>
<span className="soft date">Nov 28th, 2025</span> <br />
</p>
<ul>
<li>Introduced a new <CommandLink text="graphite" /> theme inspired by industrial gradients.</li>
</ul>
</div>
<div className='item'>
<p>
<span className="soft date">Nov 8th, 2025</span> <br />
</p>

View File

@@ -24,6 +24,8 @@ const shellModule = {
cmd.command("dark", () => appState.setUiTheme('dark'));
cmd.command("light", () => appState.setUiTheme('light'));
cmd.command("midnight", () => appState.setUiTheme('midnight'));
cmd.command("graphite", () => appState.setUiTheme('graphite'));
cmd.command("iron", () => appState.setUiTheme('graphite')); // legacy alias
cmd.command("settings", () => appState.toggleShowSettings());
cmd.command("bladerunner", () => appState.setUiTheme('bladerunner'));
cmd.command("bladerunner-easter", (c: CommandInput) => {