Files
bootnode/console/app/globals.css
zeekayandHanzo Dev 7d293212cb refactor: web/ is now console/ — bootnode/bootnode is the backend, bootnode/console the frontend
Names the two halves for what they are. The repo already holds both (12407e9 merged
bootnode/bootnode into this history); this makes the frontend directory say so, so the layout
reads the way the owner describes the system: backend and frontend separate, one repo.

git mv throughout — 187 renames, history preserved. Every path reference follows: hanzo.yml
build context and dockerfile, compose.yml, compose.prod.yml, start.sh, LLM.md,
infra/k8s/web-deployments.yaml, infra/cloud/deploy.sh, and the Dockerfile's own COPY paths.
Image and container names (bootnode-web, the -web tag suffix) are deliberately NOT renamed here:
those are a deploy contract the App CR and ingress bind to on port 3001, and breaking them is a
separate, staged change.

Console builds green after the move; the Go tree builds.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-26 17:47:51 -07:00

241 lines
7.7 KiB
CSS

@import "tailwindcss";
@plugin "tailwindcss-animate";
@custom-variant dark (&:is(.dark *));
/* ===========================================================================
DESIGN TOKENS — the lux.cloud design language, expressed once.
Ported from lux/cloud/apps/web/src/styles.css. That file states its palette
as raw literals (#000 / #f5f5f5 / rgba(255,255,255,.08)); here the same
values are the token layer every Tailwind utility already reads, so the
whole app inherits the look without a single page being edited. There is no
second class system — `bg-background`, `border-border`, `text-muted-
foreground` ARE the lux.cloud palette now.
The scheme is dark-first, matching lux.cloud (its <html> ships class="dark"
and `color-scheme: dark`). Light is a faithful inversion, kept because
bootnode ships a theme toggle and dropping it would lose a feature.
=========================================================================== */
@theme inline {
/* lux.cloud declares "Basel Grotesk" but self-hosts no @font-face, so it
renders the system stack. Geist is already bundled here and is the closest
available neo-grotesque, so it takes that slot: Basel first for the day it
is hosted, Geist as the real-world resolution. */
--font-sans: "Basel Grotesk", var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
/* Radii, from lux.cloud's measured geometry: 8px side-nav rows, 10px
buttons/inputs, 16px panels and cards. */
--radius-sm: calc(var(--radius) - 4px); /* 6px */
--radius-md: calc(var(--radius) - 2px); /* 8px */
--radius-lg: var(--radius); /* 10px */
--radius-xl: calc(var(--radius) + 6px); /* 16px — .panel / .card */
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-success: var(--success);
--color-warning: var(--warning);
--color-border: var(--border);
--color-border-strong: var(--border-strong);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;
/* Shell geometry — one source of truth for the header/sidebar contract, so
the sidebar's sticky offset can never drift from the header's height. */
--header-h: 57px;
--sidebar-w: 236px;
}
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
/* --- light ---------------------------------------------------------------
The inversion of the dark scheme, not a separate design: same hairline
borders, same near-monochrome surfaces, same accent semantics. */
:root {
--radius: 0.625rem; /* 10px */
--background: #ffffff;
--foreground: #0a0a0a;
--card: #ffffff;
--card-foreground: #0a0a0a;
--popover: #ffffff;
--popover-foreground: #0a0a0a;
--primary: #0a0a0a;
--primary-foreground: #ffffff;
--secondary: #f5f5f5;
--secondary-foreground: #0a0a0a;
--muted: #f5f5f5;
--muted-foreground: rgba(10, 10, 10, 0.55);
--accent: #f2f2f2;
--accent-foreground: #0a0a0a;
--destructive: #d1242f;
--destructive-foreground: #ffffff;
--success: #1a7f37;
--warning: #9a6700;
--border: rgba(0, 0, 0, 0.1);
--border-strong: rgba(0, 0, 0, 0.22);
--input: rgba(0, 0, 0, 0.16);
--ring: rgba(0, 0, 0, 0.4);
--chart-1: #0a0a0a;
--chart-2: #525252;
--chart-3: #737373;
--chart-4: #a3a3a3;
--chart-5: #d4d4d4;
--sidebar: #ffffff;
--sidebar-foreground: #0a0a0a;
--sidebar-primary: #0a0a0a;
--sidebar-primary-foreground: #ffffff;
--sidebar-accent: #f2f2f2;
--sidebar-accent-foreground: #0a0a0a;
--sidebar-border: rgba(0, 0, 0, 0.1);
--sidebar-ring: rgba(0, 0, 0, 0.4);
}
/* --- dark (the lux.cloud scheme, verbatim) -------------------------------
Pure black ground, #f5f5f5 ink, 55% muted, 8% hairline / 18% strong border,
#1a1a1a active fill, and lux.cloud's status greens/ambers/reds. */
.dark {
--background: #000000;
--foreground: #f5f5f5;
--card: #000000;
--card-foreground: #f5f5f5;
/* Popovers/menus sit ON the black ground, so they lift to #0a0a0a — the same
one-step lift lux.cloud gives .try-lux-panel and .org-menu. */
--popover: #0a0a0a;
--popover-foreground: #f5f5f5;
--primary: #f5f5f5;
--primary-foreground: #000000;
--secondary: #0a0a0a;
--secondary-foreground: #f5f5f5;
--muted: #0a0a0a;
--muted-foreground: rgba(245, 245, 245, 0.55);
--accent: #1a1a1a;
--accent-foreground: #f5f5f5;
--destructive: #ff7b72;
--destructive-foreground: #000000;
--success: #3fb950;
--warning: #d29922;
--border: rgba(255, 255, 255, 0.08);
--border-strong: rgba(255, 255, 255, 0.18);
--input: rgba(255, 255, 255, 0.18);
--ring: rgba(245, 245, 245, 0.6);
--chart-1: #f5f5f5;
--chart-2: #a8a8ff;
--chart-3: #8bffd1;
--chart-4: #ffd18b;
--chart-5: #ff8bc0;
--sidebar: #000000;
--sidebar-foreground: #f5f5f5;
--sidebar-primary: #f5f5f5;
--sidebar-primary-foreground: #000000;
--sidebar-accent: #1a1a1a;
--sidebar-accent-foreground: #f5f5f5;
--sidebar-border: rgba(255, 255, 255, 0.08);
--sidebar-ring: rgba(245, 245, 245, 0.6);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
html {
color-scheme: light;
}
html.dark {
color-scheme: dark;
}
body {
@apply bg-background text-foreground;
/* lux.cloud's type voice: 1.5 leading, -0.01em tracking, no synthetic
weights, smoothed. */
line-height: 1.5;
letter-spacing: -0.01em;
font-synthesis-weight: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
/* Display type. lux.cloud sizes its headings with clamp() so a 40px h1 does
not eat a third of a 390px phone; the same curve applies here to every
heading rather than page by page. Tailwind's text-* utilities still win
wherever a page sets one explicitly. */
h1 {
font-size: clamp(1.75rem, 5.5vw, 2.5rem);
letter-spacing: -0.02em;
line-height: 1.1;
}
h2 {
letter-spacing: -0.02em;
}
.container {
margin-inline: auto;
width: 100%;
max-width: 1400px;
padding-inline: 2rem;
}
}
@layer components {
/* The console's horizontal section strip below the sidebar breakpoint hides
its scrollbar (lux.cloud does the same) — the active row is scrolled into
view instead, so the affordance is position, not a scrollbar. */
.no-scrollbar {
scrollbar-width: none;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
}