mirror of
https://github.com/hanzoai/bootnode.git
synced 2026-10-25 02:31:30 +00:00
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]>
241 lines
7.7 KiB
CSS
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;
|
|
}
|
|
}
|