refactor: restructure project into muxplex/ subdir with brand integration

- Move coordinator/, frontend/, Caddyfile, pyproject.toml, requirements.txt,
  docs/ into muxplex/ subdir in prep for packaging/sharing
- Add brand assets to frontend/: favicon.ico, pwa-192/512.png,
  apple-touch-icon.png, wordmark-on-dark.svg
- Update app: title → muxplex, header → wordmark SVG, brand color tokens
  in style.css, manifest.json updated with muxplex name and brand icons
- Add design system: assets/branding/tokens.css (101 CSS custom properties),
  tokens.json (127 tokens), DESIGN-SYSTEM.md (856-line spec)
- Add assets/branding/: SVG sources, rendered PNGs (icons, favicons, PWA, OG)
- Add scripts/render-brand-assets.py for reproducible PNG generation
- Add muxplex/README.md
This commit is contained in:
Brian Krabach
2026-03-27 15:06:00 -07:00
commit 8234e2ec05
76 changed files with 17006 additions and 0 deletions
+355
View File
@@ -0,0 +1,355 @@
/* ================================================================
muxplex — Design Tokens
================================================================
Single source of truth for all visual properties.
Dark mode is the default. Light mode via prefers-color-scheme.
Manual override: set `data-theme="light"` on <html>.
Usage:
<link rel="stylesheet" href="tokens.css">
<!-- then reference vars anywhere: color: var(--color-text-primary); -->
Last updated: 2026-03-27
================================================================ */
/* ----------------------------------------------------------------
1. COLOR — Dark mode (default)
---------------------------------------------------------------- */
:root {
/* Backgrounds — luminance stepping (lighter = more elevated) */
--color-bg-base: #0D1117; /* Page background, deepest layer */
--color-bg-elevated: #10131C; /* Cards, panels, icon bg */
--color-bg-surface: #1A1F2B; /* Raised surfaces, hover states */
--color-bg-muted: #222433; /* Subtle fills, secondary panels */
/* Text — three-tier hierarchy */
--color-text-primary: #F0F6FF; /* Primary text, headings, wordmark 17.4:1 on bg-base */
--color-text-secondary: #8E95A3; /* Secondary labels, timestamps 6.3:1 on bg-base */
--color-text-disabled: #4A5060; /* Disabled controls, placeholder 2.4:1 — decorative */
/* Accents */
--color-accent-cyan: #00D9F5; /* Primary accent, links, focus rings 11.0:1 on bg-base */
--color-accent-amber: #F1A640; /* Notifications, activity indicators 9.3:1 on bg-base */
/* Borders — decorative, not relied upon for meaning */
--color-border-subtle: #1E2430; /* Dividers within a surface */
--color-border-default: #2A3040; /* Card outlines, input borders */
--color-border-strong: #3A4050; /* Emphasized borders, active outlines */
/* State / semantic — GitHub Primeradjacent, tested on bg-base */
--color-success: #3FB950; /* 7.5:1 on bg-base */
--color-error: #F85149; /* 5.7:1 on bg-base */
--color-warning: #F1A640; /* 9.3:1 (= amber) */
--color-info: #58A6FF; /* 7.5:1 on bg-base */
/* State backgrounds — low-opacity tints for banners, badges */
--color-success-bg: rgba(63, 185, 80, 0.12);
--color-error-bg: rgba(248, 81, 73, 0.12);
--color-warning-bg: rgba(241, 166, 64, 0.12);
--color-info-bg: rgba(88, 166, 255, 0.12);
/* Overlay */
--color-backdrop: rgba(0, 0, 0, 0.60);
--color-scrim: rgba(13, 17, 23, 0.80);
/* Focus ring */
--color-focus-ring: #00D9F5;
}
/* ----------------------------------------------------------------
2. COLOR — Light mode
----------------------------------------------------------------
Activated by OS preference or data-theme="light" on <html>.
Accent-accessible variants darken cyan/amber to pass 4.5:1 on
white. Use these for TEXT set in accent colors; the bright values
remain available for decorative/non-text use.
---------------------------------------------------------------- */
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) {
--color-bg-base: #FFFFFF;
--color-bg-elevated: #F0F0F0;
--color-bg-surface: #E8E9EE;
--color-bg-muted: #DADCE0;
--color-text-primary: #0D1117; /* 18.9:1 on bg-base */
--color-text-secondary: #4A5060; /* 8.1:1 on bg-base */
--color-text-disabled: #8E95A3; /* 2.6:1 — decorative */
/* Bright values kept for icons, decorative indicators */
--color-accent-cyan: #007D8C; /* 4.9:1 on #FFF — AA text */
--color-accent-amber: #946000; /* 5.3:1 on #FFF — AA text */
--color-border-subtle: #E0E2E8;
--color-border-default: #D0D2D8;
--color-border-strong: #B0B4BC;
--color-success: #1A7F37;
--color-error: #CF222E;
--color-warning: #946000;
--color-info: #0969DA;
--color-success-bg: rgba(26, 127, 55, 0.10);
--color-error-bg: rgba(207, 34, 46, 0.10);
--color-warning-bg: rgba(148, 96, 0, 0.10);
--color-info-bg: rgba(9, 105, 218, 0.10);
--color-backdrop: rgba(0, 0, 0, 0.30);
--color-scrim: rgba(255, 255, 255, 0.80);
--color-focus-ring: #007D8C;
}
}
/* Manual override */
[data-theme="light"] {
--color-bg-base: #FFFFFF;
--color-bg-elevated: #F0F0F0;
--color-bg-surface: #E8E9EE;
--color-bg-muted: #DADCE0;
--color-text-primary: #0D1117;
--color-text-secondary: #4A5060;
--color-text-disabled: #8E95A3;
--color-accent-cyan: #007D8C;
--color-accent-amber: #946000;
--color-border-subtle: #E0E2E8;
--color-border-default: #D0D2D8;
--color-border-strong: #B0B4BC;
--color-success: #1A7F37;
--color-error: #CF222E;
--color-warning: #946000;
--color-info: #0969DA;
--color-success-bg: rgba(26, 127, 55, 0.10);
--color-error-bg: rgba(207, 34, 46, 0.10);
--color-warning-bg: rgba(148, 96, 0, 0.10);
--color-info-bg: rgba(9, 105, 218, 0.10);
--color-backdrop: rgba(0, 0, 0, 0.30);
--color-scrim: rgba(255, 255, 255, 0.80);
--color-focus-ring: #007D8C;
}
/* ----------------------------------------------------------------
3. TYPOGRAPHY
---------------------------------------------------------------- */
:root {
/* Font stacks */
--font-display: 'Urbanist', system-ui, -apple-system, sans-serif;
--font-ui: 'DM Sans', 'Inter', system-ui, -apple-system, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Menlo', monospace;
/* Font weights */
--weight-regular: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
/* Type scale — DM Sans base (UI text) */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.8125rem; /* 13px */
--text-base: 0.875rem; /* 14px — default UI text */
--text-md: 1rem; /* 16px */
--text-lg: 1.25rem; /* 20px */
--text-xl: 1.5rem; /* 24px */
--text-2xl: 1.875rem; /* 30px — Urbanist headings start here */
--text-3xl: 2.25rem; /* 36px */
/* Line heights */
--leading-none: 1;
--leading-tight: 1.2;
--leading-snug: 1.375;
--leading-base: 1.5;
--leading-relaxed: 1.625;
/* Letter spacing */
--tracking-tight: -0.01em;
--tracking-normal: 0;
--tracking-wide: 0.02em;
--tracking-wider: 0.04em; /* All-caps labels */
/* Terminal-specific */
--tile-font-size: 10.5px; /* Monospace in overview tiles */
--terminal-font-size: 14px; /* Monospace in expanded xterm.js */
}
/* ----------------------------------------------------------------
4. SPACING
----------------------------------------------------------------
4px base unit. Use semantic names for layout constants,
numeric names for general-purpose spacing.
---------------------------------------------------------------- */
:root {
/* Scale */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
/* Layout constants (from layout spec) */
--tile-min-width: 360px;
--tile-height: 300px;
--grid-gap: 8px;
--page-margin: 16px;
--app-bar-height: 48px;
--status-bar-height: 36px;
--tile-header-height: 28px;
--picker-width: 400px;
--picker-row-height: 36px;
--picker-row-height-touch: 48px;
--breakpoint-list: 640px;
}
/* ----------------------------------------------------------------
5. BORDER RADIUS
---------------------------------------------------------------- */
:root {
--radius-none: 0;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-full: 9999px;
}
/* ----------------------------------------------------------------
6. SHADOWS / ELEVATION
----------------------------------------------------------------
Dark mode: luminance stepping is the primary depth cue.
Shadows serve as supplementary reinforcement on overlays.
---------------------------------------------------------------- */
:root {
--shadow-none: none;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.30);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.35),
0 1px 2px rgba(0, 0, 0, 0.20);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.40),
0 2px 4px rgba(0, 0, 0, 0.25);
--shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.50),
0 4px 8px rgba(0, 0, 0, 0.30);
/* Glow — for bell indicator, focus ring */
--glow-cyan: 0 0 8px rgba(0, 217, 245, 0.35);
--glow-amber: 0 0 8px rgba(241, 166, 64, 0.40);
}
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) {
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08),
0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.10),
0 2px 4px rgba(0, 0, 0, 0.06);
--shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.14),
0 4px 8px rgba(0, 0, 0, 0.08);
--glow-cyan: 0 0 8px rgba(0, 125, 140, 0.25);
--glow-amber: 0 0 8px rgba(148, 96, 0, 0.25);
}
}
[data-theme="light"] {
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08),
0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.10),
0 2px 4px rgba(0, 0, 0, 0.06);
--shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.14),
0 4px 8px rgba(0, 0, 0, 0.08);
--glow-cyan: 0 0 8px rgba(0, 125, 140, 0.25);
--glow-amber: 0 0 8px rgba(148, 96, 0, 0.25);
}
/* ----------------------------------------------------------------
7. MOTION / TRANSITIONS
----------------------------------------------------------------
GPU-accelerated properties only (transform, opacity).
Respect prefers-reduced-motion.
---------------------------------------------------------------- */
:root {
/* Durations */
--duration-instant: 75ms; /* Hover color shifts */
--duration-fast: 150ms; /* Button press, toggle, focus */
--duration-moderate: 250ms; /* Tile zoom, panel slide */
--duration-slow: 400ms; /* Page transitions, complex */
/* Easing */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* Decelerate — zoom in */
--ease-in-out: cubic-bezier(0.45, 0, 0.55, 1); /* Symmetric — zoom out */
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* Overshoot — picker appear */
--ease-linear: linear;
/* Convenience shorthands */
--transition-colors: color var(--duration-instant) var(--ease-out),
background-color var(--duration-instant) var(--ease-out),
border-color var(--duration-instant) var(--ease-out);
--transition-opacity: opacity var(--duration-fast) var(--ease-out);
--transition-transform: transform var(--duration-moderate) var(--ease-out);
}
/* Reduced motion — collapse all durations to near-zero */
@media (prefers-reduced-motion: reduce) {
:root {
--duration-instant: 0ms;
--duration-fast: 0ms;
--duration-moderate: 0ms;
--duration-slow: 0ms;
}
}
/* ----------------------------------------------------------------
8. Z-INDEX LAYERS
---------------------------------------------------------------- */
:root {
--z-base: 0;
--z-tile: 1;
--z-app-bar: 10;
--z-expanding: 20; /* Tile during zoom transition */
--z-backdrop: 30;
--z-picker: 40; /* Command palette overlay */
--z-toast: 50;
--z-tooltip: 60;
}
/* ----------------------------------------------------------------
9. FOCUS STYLES
----------------------------------------------------------------
Global focus-visible ring. 2px offset ensures it doesn't
overlap content. Uses accent cyan for maximum visibility.
---------------------------------------------------------------- */
:focus-visible {
outline: 2px solid var(--color-focus-ring);
outline-offset: 2px;
}
/* Remove default outlines — :focus-visible handles it */
:focus:not(:focus-visible) {
outline: none;
}