@import "tailwindcss" layer(tailwind); @import "../styles/tokens.css"; @plugin "tailwindcss-animate"; /* * Scan the @luxfi/ui component library for Tailwind classes. * * @luxfi/ui ships pre-built components whose className strings use arbitrary * Tailwind utilities that resolve design tokens — e.g. the popover / menu / * drawer surfaces are styled with bg-[var(--color-popover-bg)], * bg-[var(--color-drawer-bg)], shadow-[var(--shadow-popover)] and * border-[var(--color-popover-border)]. Tailwind v4 does not scan node_modules * by default, so without this @source those utilities are purged and every * floating panel (Sign-in popover, Blockchain menu, chain/network selectors, * mobile nav drawer) renders with a transparent background — the page bleeds * through and the content is unreadable. Sourcing the package makes Tailwind * emit the utilities so the panels get their solid token-driven backgrounds. */ @source "../node_modules/@luxfi/ui"; /* * Tailwind v4 theme configuration * * Breakpoints match Chakra: sm=415px, lg=1000px, xl=1440px, 2xl=1920px * Dark mode via .dark class (next-themes "class" strategy) * * The block below is the TAILWIND BRIDGE: names registered so a call site can * write `text-good` or `bg-gray-100` and get a utility, with the values coming * from @luxfi/ui. It exists because Tailwind is here and it goes when Tailwind * goes. The other @theme, in styles/tokens.css, is a different thing with a * different lifetime — it binds a reader's own settings to the ramps, and it * outlives Tailwind. Two blocks, two reasons; Tailwind merges them. */ @theme { /* --- Breakpoints --- */ --breakpoint-sm: 415px; --breakpoint-lg: 1000px; --breakpoint-xl: 1440px; --breakpoint-2xl: 1920px; /* --- Font Families --- */ --font-sans: Zen, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-sans: Zen, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-mono: Zen Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; /* --- State. The only two hues Lux keeps, plus the achromatic warn. Registered here so a call site can say `text-good` instead of `text-[var(--color-status-good)]`, which is the same token and shorter than the `text-green-500` it replaced. --- */ --color-good: var(--color-status-good); --color-bad: var(--color-status-bad); --color-warn: var(--color-status-warn); /* --- Colors (mapped from CSS custom properties) --- */ --color-bg-primary: var(--color-bg-primary); --color-bg-info: var(--color-bg-info); --color-bg-body: var(--color-bg-body); --color-fg-info: var(--color-fg-info); --color-text-primary: var(--color-text-primary); --color-text-secondary: var(--color-text-secondary); --color-text-error: var(--color-text-error); --color-text-success: var(--color-text-success); --color-heading: var(--color-heading); --color-icon-primary: var(--color-icon-primary); --color-icon-secondary: var(--color-icon-secondary); --color-border-divider: var(--color-border-divider); --color-border-error: var(--color-border-error); --color-border-info: var(--color-border-info); --color-link-primary: var(--color-link-primary); --color-link-primary-hover: var(--color-link-primary-hover); --color-link-secondary: var(--color-link-secondary); --color-hover: var(--color-hover); --color-selected-control-bg: var(--color-selected-control-bg); --color-selected-control-text: var(--color-selected-control-text); --color-selected-option-bg: var(--color-selected-option-bg); --color-button-solid-bg: var(--color-button-solid-bg); --color-button-solid-text: var(--color-button-solid-text); --color-button-outline-fg: var(--color-button-outline-fg); --color-button-subtle-fg: var(--color-button-subtle-fg); --color-button-subtle-bg: var(--color-button-subtle-bg); --color-button-dropdown-fg: var(--color-button-dropdown-fg); --color-button-dropdown-border: var(--color-button-dropdown-border); --color-button-header-fg: var(--color-button-header-fg); --color-button-header-fg-selected: var(--color-button-header-fg-selected); --color-button-header-fg-highlighted: var(--color-button-header-fg-highlighted); --color-button-header-border: var(--color-button-header-border); --color-button-header-bg-selected: var(--color-button-header-bg-selected); --color-button-header-bg-highlighted: var(--color-button-header-bg-highlighted); --color-button-pagination-fg: var(--color-button-pagination-fg); --color-button-pagination-border: var(--color-button-pagination-border); --color-button-hero-bg: var(--color-button-hero-bg); --color-button-hero-fg: var(--color-button-hero-fg); --color-button-hero-bg-hover: var(--color-button-hero-bg-hover); --color-button-hero-fg-hover: var(--color-button-hero-fg-hover); --color-button-hero-bg-selected: var(--color-button-hero-bg-selected); --color-button-hero-fg-selected: var(--color-button-hero-fg-selected); --color-button-segmented-fg: var(--color-button-segmented-fg); --color-button-icon-bg: var(--color-button-icon-bg); --color-button-icon-background-bg: var(--color-button-icon-background-bg); --color-nav-bg-selected: var(--color-nav-bg-selected); --color-nav-text-selected: var(--color-nav-text-selected); --color-input-fg: var(--color-input-fg); --color-input-bg: var(--color-input-bg); --color-input-border: var(--color-input-border); --color-input-border-hover: var(--color-input-border-hover); --color-input-placeholder: var(--color-input-placeholder); --color-dialog-bg: var(--color-dialog-bg); --color-dialog-fg: var(--color-dialog-fg); --color-popover-bg: var(--color-popover-bg); --color-drawer-bg: var(--color-drawer-bg); --color-tooltip-bg: var(--color-tooltip-bg); --color-tooltip-fg: var(--color-tooltip-fg); --color-table-header-bg: var(--color-table-header-bg); --color-table-header-fg: var(--color-table-header-fg); --color-alert-fg: var(--color-alert-fg); --color-alert-bg-info: var(--color-alert-bg-info); --color-alert-bg-warning: var(--color-alert-bg-warning); --color-alert-bg-success: var(--color-alert-bg-success); --color-alert-bg-error: var(--color-alert-bg-error); --color-skeleton-start: var(--color-skeleton-start); --color-skeleton-end: var(--color-skeleton-end); --color-progress-track: var(--color-progress-track); --color-stats-bg: var(--color-stats-bg); --color-topbar-bg: var(--color-topbar-bg); --color-graph-line: var(--color-graph-line); --color-graph-gradient-start: var(--color-graph-gradient-start); --color-graph-gradient-stop: var(--color-graph-gradient-stop); --color-scrollbar-thumb: var(--color-scrollbar-thumb); --color-selection-bg: var(--color-selection-bg); /* --- Tabs colors --- */ --color-tabs-solid-fg: var(--color-tabs-solid-fg); --color-tabs-secondary-fg: var(--color-tabs-secondary-fg); --color-tabs-secondary-border: var(--color-tabs-secondary-border); /* --- Badge colors --- */ --color-badge-gray-bg: var(--color-badge-gray-bg); --color-badge-gray-fg: var(--color-badge-gray-fg); --color-badge-green-bg: var(--color-badge-green-bg); --color-badge-green-fg: var(--color-badge-green-fg); --color-badge-red-bg: var(--color-badge-red-bg); --color-badge-red-fg: var(--color-badge-red-fg); --color-badge-purple-bg: var(--color-badge-purple-bg); --color-badge-purple-fg: var(--color-badge-purple-fg); --color-badge-orange-bg: var(--color-badge-orange-bg); --color-badge-orange-fg: var(--color-badge-orange-fg); --color-badge-blue-bg: var(--color-badge-blue-bg); --color-badge-blue-fg: var(--color-badge-blue-fg); --color-badge-yellow-bg: var(--color-badge-yellow-bg); --color-badge-yellow-fg: var(--color-badge-yellow-fg); --color-badge-teal-bg: var(--color-badge-teal-bg); --color-badge-teal-fg: var(--color-badge-teal-fg); --color-badge-cyan-bg: var(--color-badge-cyan-bg); --color-badge-cyan-fg: var(--color-badge-cyan-fg); --color-badge-pink-bg: var(--color-badge-pink-bg); --color-badge-pink-fg: var(--color-badge-pink-fg); --color-badge-purple-alt-bg: var(--color-badge-purple-alt-bg); --color-badge-purple-alt-fg: var(--color-badge-purple-alt-fg); --color-badge-blue-alt-bg: var(--color-badge-blue-alt-bg); --color-badge-blue-alt-fg: var(--color-badge-blue-alt-fg); --color-badge-bright-gray-bg: var(--color-badge-bright-gray-bg); --color-badge-bright-gray-fg: var(--color-badge-bright-gray-fg); --color-badge-bright-green-bg: var(--color-badge-bright-green-bg); --color-badge-bright-green-fg: var(--color-badge-bright-green-fg); --color-badge-bright-red-bg: var(--color-badge-bright-red-bg); --color-badge-bright-red-fg: var(--color-badge-bright-red-fg); --color-badge-bright-blue-bg: var(--color-badge-bright-blue-bg); --color-badge-bright-blue-fg: var(--color-badge-bright-blue-fg); --color-badge-bright-yellow-bg: var(--color-badge-bright-yellow-bg); --color-badge-bright-yellow-fg: var(--color-badge-bright-yellow-fg); --color-badge-bright-teal-bg: var(--color-badge-bright-teal-bg); --color-badge-bright-teal-fg: var(--color-badge-bright-teal-fg); --color-badge-bright-cyan-bg: var(--color-badge-bright-cyan-bg); --color-badge-bright-cyan-fg: var(--color-badge-bright-cyan-fg); --color-badge-bright-orange-bg: var(--color-badge-bright-orange-bg); --color-badge-bright-orange-fg: var(--color-badge-bright-orange-fg); --color-badge-bright-purple-bg: var(--color-badge-bright-purple-bg); --color-badge-bright-purple-fg: var(--color-badge-bright-purple-fg); --color-badge-bright-pink-bg: var(--color-badge-bright-pink-bg); --color-badge-bright-pink-fg: var(--color-badge-bright-pink-fg); /* --- Palette rungs --- Self-references, like the badge block above: they exist so Tailwind emits the `bg-gray-100` / `text-red-500` utilities, while the VALUES come from @luxfi/ui/tokens.css (imported outside any @layer at the top, so it wins). This block used to hold literals, which is how the explorer kept its own browns after the token set went monochrome: --color-orange-50 #FFFAF0 --color-orange-100 #FEEBCB --color-orange-500 #DD6B20 --color-yellow-400 #ECC94B */ --color-gray-50: var(--color-gray-50); --color-gray-100: var(--color-gray-100); --color-gray-200: var(--color-gray-200); --color-gray-300: var(--color-gray-300); --color-gray-400: var(--color-gray-400); --color-gray-500: var(--color-gray-500); --color-gray-600: var(--color-gray-600); --color-gray-700: var(--color-gray-700); --color-gray-800: var(--color-gray-800); --color-gray-900: var(--color-gray-900); --color-green-50: var(--color-green-50); --color-green-100: var(--color-green-100); --color-green-200: var(--color-green-200); --color-green-500: var(--color-green-500); --color-green-800: var(--color-green-800); --color-red-50: var(--color-red-50); --color-red-100: var(--color-red-100); --color-red-200: var(--color-red-200); --color-red-500: var(--color-red-500); --color-red-600: var(--color-red-600); --color-red-800: var(--color-red-800); --color-orange-50: var(--color-orange-50); --color-orange-100: var(--color-orange-100); --color-orange-500: var(--color-orange-500); --color-yellow-400: var(--color-yellow-400); --color-white: var(--color-white); --color-black: var(--color-black); /* --- Shadows --- */ --shadow-action-bar: var(--shadow-action-bar); --shadow-popover: var(--shadow-popover); --shadow-drawer: var(--shadow-drawer); } /* * Motion lives in @luxfi/ui/tokens.css (imported above via styles/tokens.css): * durations, curves, enter/exit, hover/press, the skeleton, and one global * prefers-reduced-motion rule. Add a move to the design system, never here. * * What this replaced: a local `skeleton-shimmer` that animated * background-position on a 200%-wide gradient. The explorer mounts ~1460 * skeletons, so that was ~1460 full-box repaints per frame on the main thread. */ /* * Dark mode: use .dark class (next-themes) * Tailwind v4 default is prefers-color-scheme; override to class-based. */ @custom-variant dark (&:is(.dark *)); /* * Scope Tailwind to a layer so it does not override Chakra styles. * Chakra styles have no layer, so they win by default cascade rules. * New Tailwind components explicitly opt in via utility classes. */ /* * Global font and body styles. * Apply it universally so Chakra components inherit it too. */ html, body { font-family: Zen, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* ── light mode: Tamagui text was painting white on white ────────────────── The gui provider pins `t_dark` on
CLIENT-SIDE in BOTH schemes (the server sends a bare ), and its theme block reads: .t_dark { --color: var(--c-color-background) } -> #ffffff .t_light { --color: var(--c-color-text) } -> #000000 :root { --c-color-background:#ffffff; --c-color-text:#000000 } invariant so every Tamagui text component (is_H1 / is_H3 / is_Text) resolved --color to #ffffff unconditionally — right by accident on dark, invisible on light. Measured at 1.00:1 across all four widths on /address/*, /validators and the landing page: "Address details", the ADDRESS ITSELF, "Validators", and six section headings. A user clicking a Safe link from lux.cloud landed on a page that never showed which address they were looking at. The page BACKGROUND is not affected — that follows the Tailwind --lux-* layer, which already tracks html.light/html.dark correctly. Only the text colour is wrong, so only --color is corrected here. Both selectors are covered because the class is applied by script: html.light is the explicit signal, and the media query catches the pre-hydration frame. Remove this the day the provider stops hard-pinning t_dark. */ /* NOT `body.t_dark` — measured 2026-08-06: the provider mounts a SECOND `` INSIDE , and `:root .t_dark` matches both. A body-scoped rule sets --color on body correctly (verified #000000 there) and the nested span immediately re-sets it to #ffffff, which every heading then inherits. Scoping to `.t_dark` reaches every Theme wrapper; (0,2,1) still beats `:root .t_dark` (0,2,0). */ /* ⚠️ THIS RULE DOES NOT REACH THE BUNDLE. Do not trust it. Three forms have now been shipped and none appear in the served CSS: v1.1.20 html.light body.t_dark v1.1.21 html.light .t_dark v1.1.22 html[class~="light"] .t_dark In every build `.t_dark` occurs exactly ONCE in the output — the media-query rule below — while the file's OTHER top-level rule (html,body{font-family: Zen, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif}) survives intact, so top-level rules are not dropped wholesale. Running this file through the real postcss + @tailwindcss/postcss pipeline locally KEEPS both rules, so Tailwind is not the cause; something later in the Next build removes it. Root cause not yet found. What it is FOR, once it works: OS-dark + stored-theme-light. There gets class="light" so the background turns white, but prefers-color-scheme is false, so the media rule below is inert and --color stays #ffffff — the original white-on-white, measured 1.00:1 with 11,232/11,232 pure-white pixels in the h1 band. Injecting this rule into that state live fixes it (1.00 -> 21.00, and forcing html.dark still gives 17.93), which is the only sense in which it is "verified" — by injection, NOT by the shipped bundle. Not currently user-reachable: there is no theme toggle in the signed-out UI, so the site follows the OS. But localStorage.theme IS honoured, so a returning user carrying a stale value already lands here, and it goes live the moment a toggle ships. */ html[class~="light"] .t_dark { --color: var(--c-color-text); } @media (prefers-color-scheme: light) { html:not(.dark) .t_dark { --color: var(--c-color-text); } }