Skip to content

Commit 105c737

Browse files
Kabuki94claude
andcommitted
feat(palette): MiOS unified color palette -- Hokusai + operator neutrals
Adds the canonical MiOS color palette as a user-defined SSOT in mios.toml [colors] (defaults to the just-defined globals), applied across every console / terminal / oh-my-posh / configurator surface. Palette sources: Operator neutrals: #1A407F deep-blue #E0E0E0 silver #B7C9D7 pale blue-grey #948E8E warm grey #734F39 brown Hokusai "Great Wave": #3E7765 wave-green #E7DFD3 foam-cream #F35C15 sunset-orange #DC271B coral-red #282262 deep-indigo Combined: 12 named tokens (bg, fg, accent, cursor, success, warning, error, info, muted, subtle, earth, silver) + 16 ANSI slot mappings (ansi_0_black through ansi_15_bright_white). Files: usr/share/mios/mios.toml [colors] block (vendor SSOT) etc/profile.d/mios-colors.sh OSC-4 / OSC-10 / OSC-11 / OSC-12 emitter (every interactive shell repaints to MiOS palette via xterm escape sequences). Skipped on TERM=linux (tty0 has its own vconsole.conf palette) and on non-interactive shells. usr/share/mios/oh-my-posh/ Rich two-line prompt + right-aligned mios.omp.json dev language rollup. MiOS-owned segments (shell/path/git/exec/ status/os/time) recolored to MiOS palette; language-version segments (Node/Python/Go/Rust/.NET/kubectl/ AWS) keep brand colors so green- Node / yellow-Python etc. stay instantly recognizable. usr/share/mios/configurator/ [colors] fieldset added with index.html <input type="color"> pickers for every named + ANSI slot. Defaults populate from COLOR_DEFAULTS when no existing mios.toml override has loaded. Two preset buttons: "Reset to MiOS defaults" and "Pure Hokusai (no neutrals)". emitToml section order updated to place [colors] right after [desktop]. Operator workflow: 1. Open the configurator (Epiphany on MiOS-DEV via WSLg, or default browser fallback). 2. Edit color pickers under the new "colors" fieldset. 3. Save -> writes mios.toml [colors] override at ~/Downloads/mios.toml (dev VM) or %APPDATA%\MiOS\mios.toml (Windows fallback browser). 4. Next interactive shell -> /etc/profile.d/mios-colors.sh emits the OSC sequences -> terminal repaints. 5. PowerShell on Windows host gets the same palette via the Install-WindowsBranding-staged %APPDATA%\MiOS\mios.omp.json. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 649ef00 commit 105c737

4 files changed

Lines changed: 455 additions & 70 deletions

File tree

etc/profile.d/mios-colors.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# /etc/profile.d/mios-colors.sh
2+
#
3+
# Repaint the operator's terminal to the MiOS unified palette
4+
# (Hokusai + operator neutrals) on every interactive shell start.
5+
# Works on every emulator that honors the OSC color escape sequences:
6+
# xterm, Konsole, Ptyxis, GNOME Terminal, kitty, alacritty, foot,
7+
# Windows Terminal (via WSL), Ptyxis-via-WSLg, ssh sessions, etc.
8+
#
9+
# Sequences emitted:
10+
# OSC 4 ; <slot> ; <hex> set ANSI 16-color palette slot
11+
# OSC 10 ; <hex> default foreground
12+
# OSC 11 ; <hex> default background
13+
# OSC 12 ; <hex> cursor color
14+
# OSC 17 ; <hex> highlight (selected) background
15+
#
16+
# Skipped on:
17+
# - non-interactive shells (cron, scripts, sudo non-tty)
18+
# - Linux console (TERM=linux) -- tty0 has its own kernel palette
19+
# wired via /etc/vconsole.conf; OSC4 doesn't apply there
20+
# - Already-applied sessions (idempotent via $MIOS_COLORS_APPLIED)
21+
#
22+
# Palette is the SSOT in mios.toml [colors]; sync via `mios-sync-env`
23+
# if the operator overrides via the configurator HTML.
24+
25+
[ -t 1 ] || return 0
26+
case "${TERM:-}" in linux|dumb|"") return 0 ;; esac
27+
[ -n "${MIOS_COLORS_APPLIED:-}" ] && return 0
28+
29+
# Helper: emit OSC <code>;<value> with the trailing BEL terminator.
30+
_mios_osc() { printf '\033]%s;%s\007' "$1" "$2"; }
31+
32+
# ── ANSI 16-color slots (OSC 4 ; <0..15> ; <#rgb>) ────────────────────────
33+
_mios_osc 4 '0;#282262' # 0 black -- deep indigo
34+
_mios_osc 4 '1;#DC271B' # 1 red -- coral red
35+
_mios_osc 4 '2;#3E7765' # 2 green -- wave green
36+
_mios_osc 4 '3;#F35C15' # 3 yellow -- sunset orange (warning)
37+
_mios_osc 4 '4;#1A407F' # 4 blue -- operator blue
38+
_mios_osc 4 '5;#734F39' # 5 magenta -- brown
39+
_mios_osc 4 '6;#B7C9D7' # 6 cyan -- pale blue-grey
40+
_mios_osc 4 '7;#E7DFD3' # 7 white -- cream
41+
_mios_osc 4 '8;#948E8E' # 8 bright black -- warm grey
42+
_mios_osc 4 '9;#FF6B5C' # 9 bright red -- lighter coral
43+
_mios_osc 4 '10;#5FAA8E' # 10 bright green -- lighter wave-green
44+
_mios_osc 4 '11;#FF8540' # 11 bright yellow -- lighter sunset
45+
_mios_osc 4 '12;#3D6BA8' # 12 bright blue -- lighter operator blue
46+
_mios_osc 4 '13;#9D7660' # 13 bright magenta -- lighter brown
47+
_mios_osc 4 '14;#E0E0E0' # 14 bright cyan -- operator silver
48+
_mios_osc 4 '15;#FFFFFF' # 15 bright white -- pure white
49+
50+
# ── Defaults (foreground / background / cursor / highlight) ───────────────
51+
_mios_osc 10 '#E7DFD3' # default fg -- cream
52+
_mios_osc 11 '#282262' # default bg -- deep indigo
53+
_mios_osc 12 '#F35C15' # cursor -- sunset orange (high contrast)
54+
_mios_osc 17 '#1A407F' # selection -- operator blue (readable both ways)
55+
56+
unset -f _mios_osc
57+
export MIOS_COLORS_APPLIED=1

usr/share/mios/configurator/index.html

Lines changed: 166 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,38 @@ <h1>MiOS configurator <span class="v" id="v-meta">schema 1.2.0 / mios 0.2.2</spa
168168
<div class="checkbox-row"><input type="checkbox" id="f-net-rdp" data-key="network.allow_rdp"><label for="f-net-rdp">allow_rdp (3389/tcp)</label></div>
169169
</fieldset>
170170

171+
<fieldset style="grid-column: 1 / -1">
172+
<legend>colors (palette applied across every console / terminal / tty / oh-my-posh)</legend>
173+
<p style="color: var(--muted); font-size: 12px; margin: 0 0 8px;">
174+
Defaults are the MiOS unified palette: operator neutrals
175+
(#1A407F deep-blue, #E0E0E0 silver, #B7C9D7 pale blue-grey,
176+
#948E8E warm grey, #734F39 brown) combined with Hokusai's
177+
"The Great Wave off Kanagawa" (#3E7765 wave-green, #E7DFD3
178+
foam-cream, #F35C15 sunset-orange, #DC271B coral-red, #282262
179+
deep-indigo). Edit any color below; on save, /etc/profile.d/
180+
mios-colors.sh reads these values and emits OSC-4 / OSC-10 /
181+
OSC-11 / OSC-12 escape sequences at every interactive shell
182+
start so bash / zsh / PowerShell / Windows Terminal / Ptyxis
183+
all repaint. The oh-my-posh theme + Cockpit dark theme + the
184+
configurator HTML itself read the same SSOT.
185+
</p>
186+
187+
<div style="margin-bottom: 16px; color: var(--accent); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .5px;">
188+
Named tokens
189+
</div>
190+
<div id="colors-named" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px 16px;"></div>
191+
192+
<div style="margin: 16px 0 8px; color: var(--accent); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .5px;">
193+
ANSI 16-color slots (terminal palette)
194+
</div>
195+
<div id="colors-ansi" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px 16px;"></div>
196+
197+
<div style="margin-top: 12px;">
198+
<button type="button" id="btn-colors-reset" style="margin-right: 8px;">Reset to MiOS defaults</button>
199+
<button type="button" id="btn-colors-hokusai">Pure Hokusai (no neutrals)</button>
200+
</div>
201+
</fieldset>
202+
171203
<fieldset style="grid-column: 1 / -1">
172204
<legend>desktop (session + Flatpak applications)</legend>
173205
<div style="display:grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px;">
@@ -242,6 +274,77 @@ <h1>MiOS configurator <span class="v" id="v-meta">schema 1.2.0 / mios 0.2.2</spa
242274
"guacamole-postgres", "guacd"
243275
];
244276

277+
// ── Color palette: defaults + named-token / ANSI-slot definitions ─────────────
278+
// Defaults match the canonical [colors] block in mios.toml SSOT
279+
// (Hokusai "Great Wave" + operator neutrals). Configurator color pickers
280+
// initialize from these unless an existing mios.toml override has loaded.
281+
const COLOR_DEFAULTS = {
282+
bg: "#282262", fg: "#E7DFD3",
283+
accent: "#1A407F", cursor: "#F35C15",
284+
success: "#3E7765", warning: "#F35C15",
285+
error: "#DC271B", info: "#1A407F",
286+
muted: "#948E8E", subtle: "#B7C9D7",
287+
earth: "#734F39", silver: "#E0E0E0",
288+
ansi_0_black: "#282262",
289+
ansi_1_red: "#DC271B",
290+
ansi_2_green: "#3E7765",
291+
ansi_3_yellow: "#F35C15",
292+
ansi_4_blue: "#1A407F",
293+
ansi_5_magenta: "#734F39",
294+
ansi_6_cyan: "#B7C9D7",
295+
ansi_7_white: "#E7DFD3",
296+
ansi_8_bright_black: "#948E8E",
297+
ansi_9_bright_red: "#FF6B5C",
298+
ansi_10_bright_green: "#5FAA8E",
299+
ansi_11_bright_yellow: "#FF8540",
300+
ansi_12_bright_blue: "#3D6BA8",
301+
ansi_13_bright_magenta: "#9D7660",
302+
ansi_14_bright_cyan: "#E0E0E0",
303+
ansi_15_bright_white: "#FFFFFF"
304+
};
305+
306+
// Pure Hokusai variant: drops the operator neutrals, picks from the wave
307+
// alone. One-click button in the configurator for operators who want the
308+
// strict Hokusai aesthetic on their MiOS surface.
309+
const COLOR_HOKUSAI = {
310+
bg: "#282262", fg: "#E7DFD3", accent: "#3E7765", cursor: "#F35C15",
311+
success: "#3E7765", warning: "#F35C15", error: "#DC271B", info: "#3E7765",
312+
muted: "#948E8E", subtle: "#E7DFD3", earth: "#734F39", silver: "#E7DFD3",
313+
ansi_0_black: "#282262", ansi_1_red: "#DC271B",
314+
ansi_2_green: "#3E7765", ansi_3_yellow: "#F35C15",
315+
ansi_4_blue: "#282262", ansi_5_magenta: "#DC271B",
316+
ansi_6_cyan: "#E7DFD3", ansi_7_white: "#E7DFD3",
317+
ansi_8_bright_black: "#948E8E", ansi_9_bright_red: "#FF6B5C",
318+
ansi_10_bright_green: "#5FAA8E", ansi_11_bright_yellow: "#FF8540",
319+
ansi_12_bright_blue: "#3E7765", ansi_13_bright_magenta: "#FF6B5C",
320+
ansi_14_bright_cyan: "#E7DFD3", ansi_15_bright_white: "#FFFFFF"
321+
};
322+
323+
const COLOR_NAMED_LABELS = {
324+
bg: "background", fg: "foreground", accent: "accent",
325+
cursor: "cursor", success: "success", warning: "warning",
326+
error: "error", info: "info", muted: "muted",
327+
subtle: "subtle", earth: "earth", silver: "silver"
328+
};
329+
const COLOR_ANSI_LABELS = {
330+
ansi_0_black: "0 black",
331+
ansi_1_red: "1 red",
332+
ansi_2_green: "2 green",
333+
ansi_3_yellow: "3 yellow",
334+
ansi_4_blue: "4 blue",
335+
ansi_5_magenta: "5 magenta",
336+
ansi_6_cyan: "6 cyan",
337+
ansi_7_white: "7 white",
338+
ansi_8_bright_black: "8 br.black",
339+
ansi_9_bright_red: "9 br.red",
340+
ansi_10_bright_green: "10 br.green",
341+
ansi_11_bright_yellow: "11 br.yellow",
342+
ansi_12_bright_blue: "12 br.blue",
343+
ansi_13_bright_magenta: "13 br.magenta",
344+
ansi_14_bright_cyan: "14 br.cyan",
345+
ansi_15_bright_white: "15 br.white"
346+
};
347+
245348
// ── Flatpak catalog ───────────────────────────────────────────────────────────
246349
// Every Flatpak referenced anywhere in the MiOS codebase. The 'def' field
247350
// marks the MINIMAL pre-selected set baked into the image as defaults; all
@@ -364,7 +467,8 @@ <h1>MiOS configurator <span class="v" id="v-meta">schema 1.2.0 / mios 0.2.2</spa
364467
function emitToml(sections) {
365468
// Emit a deterministic TOML block in MiOS section order.
366469
const order = ["meta", "identity", "locale", "auth", "network", "ai",
367-
"desktop", "image", "bootstrap", "profile", "quadlets.enable", "env"];
470+
"desktop", "colors", "image", "bootstrap", "profile",
471+
"quadlets.enable", "env"];
368472
const lines = [];
369473
const known = new Set(order);
370474
// Meta header preamble (matches the canonical template).
@@ -450,6 +554,9 @@ <h1>MiOS configurator <span class="v" id="v-meta">schema 1.2.0 / mios 0.2.2</spa
450554
}
451555
// Flatpak checkboxes
452556
renderFlatpaks();
557+
// Color palette pickers (defaults populate from COLOR_DEFAULTS when no
558+
// mios.toml override has loaded; values bind two-way into DATA.colors.*).
559+
renderColors();
453560
renderRaw();
454561
}
455562

@@ -477,6 +584,64 @@ <h1>MiOS configurator <span class="v" id="v-meta">schema 1.2.0 / mios 0.2.2</spa
477584
return s;
478585
}
479586

587+
// ── Color palette: render the [colors] fieldset and bind inputs ──────────────
588+
function renderColors() {
589+
const named = document.getElementById("colors-named");
590+
const ansi = document.getElementById("colors-ansi");
591+
if (!named || !ansi) return;
592+
named.innerHTML = "";
593+
ansi.innerHTML = "";
594+
595+
// Initialize DATA.colors from defaults if missing -- so the saved
596+
// mios.toml always carries the full [colors] block even if the
597+
// operator never opens this fieldset.
598+
DATA.colors = DATA.colors || {};
599+
for (const k of Object.keys(COLOR_DEFAULTS)) {
600+
if (!DATA.colors[k]) DATA.colors[k] = COLOR_DEFAULTS[k];
601+
}
602+
603+
const renderRow = (parent, key, label) => {
604+
const id = `f-color-${key}`;
605+
const val = DATA.colors[key] || COLOR_DEFAULTS[key] || "#000000";
606+
const row = document.createElement("div");
607+
row.style.cssText = "display: flex; align-items: center; gap: 8px;";
608+
row.innerHTML =
609+
`<input type="color" id="${id}" value="${val}" style="width: 32px; height: 28px; padding: 0; border: 1px solid var(--border); border-radius: 4px; cursor: pointer;">` +
610+
`<label for="${id}" style="margin: 0; flex: 1; font-family: var(--mono); font-size: 12px; color: var(--text);">${label}</label>` +
611+
`<code style="font-size: 10px; color: var(--muted); font-family: var(--mono);">${val}</code>`;
612+
parent.appendChild(row);
613+
const input = row.querySelector("input");
614+
const code = row.querySelector("code");
615+
input.addEventListener("input", e => {
616+
DATA.colors = DATA.colors || {};
617+
DATA.colors[key] = e.target.value.toUpperCase();
618+
code.textContent = DATA.colors[key];
619+
renderRaw();
620+
});
621+
};
622+
623+
for (const [key, label] of Object.entries(COLOR_NAMED_LABELS)) renderRow(named, key, label);
624+
for (const [key, label] of Object.entries(COLOR_ANSI_LABELS)) renderRow(ansi, key, label);
625+
626+
// Reset buttons (idempotent: re-binds on every renderColors call).
627+
const resetBtn = document.getElementById("btn-colors-reset");
628+
if (resetBtn) {
629+
resetBtn.onclick = () => {
630+
DATA.colors = { ...COLOR_DEFAULTS };
631+
renderColors();
632+
renderRaw();
633+
};
634+
}
635+
const hokusaiBtn = document.getElementById("btn-colors-hokusai");
636+
if (hokusaiBtn) {
637+
hokusaiBtn.onclick = () => {
638+
DATA.colors = { ...COLOR_HOKUSAI };
639+
renderColors();
640+
renderRaw();
641+
};
642+
}
643+
}
644+
480645
function renderFlatpaks() {
481646
const grid = document.getElementById("flatpak-grid");
482647
if (!grid) return;

usr/share/mios/mios.toml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,58 @@ sections = [
238238
"cockpit-plugins-build", "k3s-selinux-build", "uki",
239239
]
240240

241+
# ----------------------------------------------------------------------------
242+
# [colors] -- MiOS unified palette applied to every console / terminal /
243+
# tty surface (bash, zsh, PowerShell, Windows Terminal, Ptyxis, Cockpit,
244+
# the configurator HTML, the oh-my-posh prompt, fastfetch logo color).
245+
# Sourced from:
246+
# - Operator neutrals: #1A407F deep-blue, #E0E0E0 silver,
247+
# #B7C9D7 pale blue-grey, #948E8E warm grey, #734F39 brown
248+
# - Hokusai "The Great Wave off Kanagawa": #3E7765 wave-green,
249+
# #E7DFD3 foam-cream, #F35C15 sunset-orange, #DC271B coral-red,
250+
# #282262 deep-indigo
251+
# Combined into one coherent palette where every tone has a role.
252+
# /etc/profile.d/mios-colors.sh emits OSC-4 / OSC-10 / OSC-11 / OSC-12
253+
# escape sequences at every interactive shell start so the operator's
254+
# terminal repaints to MiOS palette regardless of which emulator
255+
# launched it. Ptyxis / GNOME Terminal also read this same TOML via
256+
# the configurator HTML when the operator picks a custom override.
257+
# ----------------------------------------------------------------------------
258+
[colors]
259+
# ── Named tokens (the configurator HTML, OSC-aware apps, theming) ─────────
260+
bg = "#282262" # deep indigo (Hokusai sky) [main bg]
261+
fg = "#E7DFD3" # cream (Hokusai foam) [main fg]
262+
accent = "#1A407F" # operator blue (interactive / link)
263+
cursor = "#F35C15" # sunset orange (visible cursor)
264+
success = "#3E7765" # wave green
265+
warning = "#F35C15" # sunset orange
266+
error = "#DC271B" # coral red
267+
info = "#1A407F" # operator blue
268+
muted = "#948E8E" # warm grey
269+
subtle = "#B7C9D7" # pale blue-grey
270+
earth = "#734F39" # brown
271+
silver = "#E0E0E0" # operator silver
272+
273+
# ── ANSI 16-color slot mapping (terminal palette via OSC-4) ───────────────
274+
# Slot 0..7 are the canonical low colors; 8..15 are the bright variants.
275+
# Programs that emit `\e[31m` etc. resolve through these slots.
276+
ansi_0_black = "#282262" # deep indigo
277+
ansi_1_red = "#DC271B" # coral red
278+
ansi_2_green = "#3E7765" # wave green
279+
ansi_3_yellow = "#F35C15" # sunset orange
280+
ansi_4_blue = "#1A407F" # operator blue
281+
ansi_5_magenta = "#734F39" # brown
282+
ansi_6_cyan = "#B7C9D7" # pale blue-grey
283+
ansi_7_white = "#E7DFD3" # cream
284+
ansi_8_bright_black = "#948E8E" # warm grey
285+
ansi_9_bright_red = "#FF6B5C" # lighter coral
286+
ansi_10_bright_green = "#5FAA8E" # lighter wave-green
287+
ansi_11_bright_yellow = "#FF8540" # lighter sunset
288+
ansi_12_bright_blue = "#3D6BA8" # lighter operator blue
289+
ansi_13_bright_magenta = "#9D7660" # lighter brown
290+
ansi_14_bright_cyan = "#E0E0E0" # operator silver
291+
ansi_15_bright_white = "#FFFFFF" # pure white
292+
241293
# ----------------------------------------------------------------------------
242294
# [bootstrap] -- behavior of mios-bootstrap.git/install.sh during Phase-0.
243295
# mode: auto | bootc | fhs

0 commit comments

Comments
 (0)