Color
Two gardens, one palette, and the glass between them.
Two gardens
Phloom has two palettes, and they are not a light theme and its inverted copy. Garden Morning is warm cream paper at oklch(0.985 0.005 80), not white; the hue is on the yellow side, so the whole light theme reads as paper rather than as a screen. Twilight Garden is a deep plum-violet, not neutral black, so the pink sits in the same family as its background instead of glowing off it.
Everything is authored in oklch. That is load-bearing rather than fashionable: the team palette is derived from one hue with oklch(from var(--brand) L C h) and calc(h - 30) style hue rotations, which is only possible in a perceptual space where holding lightness constant actually holds lightness constant.
Every value below is read out of the running document, so this page cannot disagree with the stylesheet. The number after resolvedis the browser's own canonical form, not the authored one: Tailwind registers theme colours as <color>, so Chrome reports lab(). The oklch() you would edit lives in app/globals.css. The chip itself is painted with var(--token), so the swatch is the browser resolving the variable rather than us re-serialising it.
--backgroundresolved …The page itself. Cream in light, deep plum in dark.--foregroundresolved …Body text. Never pure black or pure white.--cardresolved …Opaque raised surface.--card-foregroundresolved …--popoverresolved …Menus and floating panels.--popover-foregroundresolved …--mutedresolved …Recessed fills: inert tiles, table zebra, inset panels.--muted-foregroundresolved …Secondary copy. The most-used text colour after --foreground.--borderresolved …An alpha value, not a solid: it tints whatever it sits on.--inputresolved …Slightly stronger than --border so fields read as editable.--brandresolved …Phloom Pink. Re-pointed per team by TeamPaletteProvider.--brand-foregroundresolved …Text and lettering placed ON brand pink.--primaryresolved …--primary-foregroundresolved …--accentresolved …Derived: oklch(from var(--brand) 0.94 0.02 h). Hover tint.--accent-foregroundresolved …--ringresolved …Focus. A colour-mix of --brand, so focus follows the team.--secondaryresolved …Quiet fills that must not read as brand.--primary is an alias of --brand, which is what keeps shadcn's primary-* classes on-brand without a second colour to maintain. Interactive controls use bloom pink; there is no separate lavender accent any more.
Semantic roles come in pairs
A status colour is never used on its own. Each one has a foreground token measured against it, and the pair is the unit you reach for. Reaching for --warn without --warn-foreground is how you end up with amber text on amber, which is why these are shown as plates rather than as chips.
--success: …--success-foreground: …--warn: …--warn-foreground: …--info: …--info-foreground: …--destructive: …--destructive-foreground: …--brand: …--brand-foreground: …--muted: …--muted-foreground: …These are the real Badge and Button primitives, not restyled copies. If a variant changes, this row changes with it.
The glass system
The app shell is frosted glass: a translucent slab with a blur behind it, a sheen across the top, and an inner hairline that catches light on the upper edge. It is built from four layers, and the reason it holds up is that none of them is a single flat colour. --shell-glass-bg is a 168° gradient from white through white to a brand-tinted corner, so the slab has a direction to it.
The one rule that matters when extending it: never feed a backdrop-filter chain into an SVG filter. That combination lags by design. Refract a static copy through a CSS filter instead.
--glass-chromeresolved …Sidebar and topbar base translucency.--glass-chrome-strongresolved …Where nav has to stay legible over busy content.--glass-overlayresolved …Page-interior cards. This section is drawn on it.--glass-borderresolved …The hairline around a glass surface.--shell-panel-borderresolved …--shell-panel-ringresolved …The plate underneath is a brand-hued gradient standing in for page content. Glass only reads as glass when there is something behind it to blur, which is why a swatch cannot show this and a specimen can.
Colour derived from one hue
A team can set its own brand colour, and the shell follows without a second palette being authored. Thirty-odd tokens are stated as functions of --brand rather than as values, so re-pointing one variable rotates the scrollbar rail, the sidebar ambient wash, the focus ring, the accent tint, and the glass corners together.
The offsets are chosen so the default pink reproduces the hand-tuned original exactly. calc(h - 30) in the scrollbar preserves the warm-to-deep travel the original 350-to-320 gradient had, at any hue.
--accentresolved …oklch(from var(--brand) 0.94 0.02 h): brand hue, near-white lightness.--ringresolved …color-mix(in oklch, var(--brand) 50%, transparent).--sidebar-ambient-aresolved …Brand hue at 0.78 L.--sidebar-ambient-bresolved …calc(h + 45), the warm side of the fan.--sidebar-ambient-cresolved …calc(h - 60), the cool side.--chart-1resolved …--chart-2resolved …--chart-3resolved …--chart-4resolved …--chart-5resolved …Five hues, spaced for categorical data rather than for a gradient. Series 1 is brand pink, so the first series in any chart is on-brand by default.
--bloom-stop-1resolved …--bloom-stop-2resolved …Two stops consumed by both the body::before pseudo-element and the BloomBackdrop component, so a palette change reaches both implementations without touching either.
Theming
Theme is a class on <html>, set by next-themes with defaultTheme="system". Every token above is declared twice, once in :root and once in .dark, which is why the 144 token names come to 221 declarations.
Switching themes plays a frost veil: an opacity-only overlay that covers, swaps mid-cover, and uncovers, so the change never reads as a flash of the wrong colours. It is opacity-only on purpose. A blur there would be the expensive thing in the one moment the whole page is repainting.
Everything on this page re-reads itself when the class changes, so the theme toggle in the header above is the demo. Flip it and watch the values, not just the chips.
Garden Morning
Warm cream paper, ink on the plum side of black.
Twilight Garden
Deep plum-violet, so the pink belongs to its background.
Both plates are painted with the same token names. Only the theme class differs, and the dark plate forces it locally.