Shape & depth
StableCorner sizes from 4 to 24 px plus the 22 px app-icon tile, four elevation steps, and the brand’s Lift shadow.
Depth comes from surface tone and hairlines first; shadows stay faint. The four --lux-shadow steps share one light source straight above and switch to lit edges in dark mode. Lift is the brand’s own shadow for app-icon tiles and the mark on its own. The surface classes that use these steps live in Cards & elevation.
Updated View source
Elevation
/** * Four steps of elevation, one light source straight above. In light mode each step adds a * softer, wider shadow; in dark mode it is a lit top edge and a ring, with shadows only to ground it. */const steps = [ { n: 1, shadow: 'shadow-[var(--lux-shadow-1)]', name: 'Flat', where: 'Quiet cards, wells', cls: 'lux-card-flat' }, { n: 2, shadow: 'shadow-[var(--lux-shadow-2)]', name: 'Card', where: 'Cards, previews', cls: 'lux-card' }, { n: 3, shadow: 'shadow-[var(--lux-shadow-3)]', name: 'Hover', where: 'A card under the pointer', cls: 'lux-lift' }, { n: 4, shadow: 'shadow-[var(--lux-shadow-4)]', name: 'Float', where: 'Menus, popovers, dialogs', cls: 'lux-float' },]
export default function Elevation() { return ( <div className="@container w-full"> <ol className="grid grid-cols-2 gap-5 pb-10 @2xl:grid-cols-4"> {steps.map((s) => ( <li key={s.n} className={`flex min-h-32 min-w-0 flex-col justify-between gap-6 rounded-2xl bg-raised p-4 ${s.shadow}`}> <code className="font-mono text-[11.5px] text-fg-3">--lux-shadow-{s.n}</code> <span className="flex flex-col gap-0.5"> <span className="text-[15px] font-semibold tracking-[-0.01em] text-fg">{s.name}</span> <span className="text-[12.5px] text-fg-3">{s.where}</span> <code className="mt-1 font-mono text-[11.5px] text-fg-2">.{s.cls}</code> </span> </li> ))} </ol> </div> )}Usage
import '@rchursin/product.css' // brand tokens, fonts, the finishing layer and the app tokens<div className="rounded-2xl bg-raised shadow-[var(--lux-shadow-2)]">…</div><div className="rounded-tile bg-raised shadow-lift dark:shadow-lift-dark">…</div>Examples
Corners
The radii in use, smallest first. Bigger things get rounder corners.
/** The corner sizes in use, smallest first, with the parts that use each one. */const radii = [ { cls: 'rounded-sm', px: '4 px', where: 'Checkboxes, chips, swatches' }, { cls: 'rounded-md', px: '6 px', where: 'Menu and list rows' }, { cls: 'rounded-lg', px: '8 px', where: 'Buttons, fields, nav items' }, { cls: 'rounded-[10px]', px: '10 px', where: 'Large buttons, segmented control' }, { cls: 'rounded-xl', px: '12 px', where: 'Popovers, code blocks' }, { cls: 'rounded-2xl', px: '16 px', where: 'Cards, dialogs, previews' }, { cls: 'rounded-tile', px: '22 px', where: 'App-icon tiles' }, { cls: 'rounded-3xl', px: '24 px', where: 'Large panels and figures' }, { cls: 'rounded-full', px: 'pill', where: 'Avatars, switches, pills' },]
export default function Radius() { return ( <div className="@container w-full"> <ul className="grid grid-cols-2 gap-x-4 gap-y-6 @lg:grid-cols-3 @3xl:grid-cols-5"> {radii.map((r) => ( <li key={r.cls} className="flex min-w-0 flex-col gap-2.5"> <span aria-hidden="true" className={`size-16 border border-line-strong bg-sunken ${r.cls}`} /> <span className="flex items-baseline justify-between gap-2"> <code className="truncate font-mono text-[12px] font-medium text-fg">{r.cls}</code> <span className="shrink-0 font-mono text-[11px] text-fg-3 tabular-nums">{r.px}</span> </span> <span className="text-[12.5px]/5 text-pretty text-fg-3">{r.where}</span> </li> ))} </ul> </div> )}Lift
The brand shadow, for boxes and for bare shapes. Its dark twin needs a dark: variant: the one place one is expected.
import { Logo } from '@rchursin/brand/Logo'
/** * The brand's own depth, "Lift": shadow-lift for boxes (app-icon tiles, hero cards) and * drop-shadow-lift for shapes without a box (the mark on its own). Each has a dark twin, * so this is the one place a dark: variant is expected. */export default function Lift() { return ( <div className="flex flex-wrap items-end justify-center gap-x-14 gap-y-8 pb-4"> <figure className="flex flex-col items-center gap-4"> <div className="flex size-22 items-center justify-center rounded-tile bg-raised text-fg shadow-lift ring-1 ring-line dark:shadow-lift-dark"> <Logo variant="mark" title="" className="size-10" /> </div> <figcaption className="flex flex-col items-center gap-0.5 text-center"> <code className="font-mono text-[12px] text-fg">rounded-tile shadow-lift</code> <span className="text-[12px] text-fg-3">A box: app icons, tiles</span> </figcaption> </figure> <figure className="flex flex-col items-center gap-4"> <div className="flex size-22 items-center justify-center"> <Logo variant="mark" title="" className="size-14 text-fg drop-shadow-lift dark:drop-shadow-lift-dark" /> </div> <figcaption className="flex flex-col items-center gap-0.5 text-center"> <code className="font-mono text-[12px] text-fg">drop-shadow-lift</code> <span className="text-[12px] text-fg-3">A shape: follows the mark’s outline</span> </figcaption> </figure> </div> )}API
CSS
| Class or variable | What it does |
|---|---|
--lux-shadow-1 | Flat: a 1px ring and a hairline shadow. Used by lux-card-flat. |
--lux-shadow-2 | Card: adds two soft layers. Used by lux-card. |
--lux-shadow-3 | Hover: deeper and wider. lux-lift switches to it under a mouse; task cards and events use it on hover. |
--lux-shadow-4 | Float: menus, popovers (rc-pop-panel), dialogs (lux-float) and dragged cards. |
rounded-tile · --radius-tile | 1.375rem (22px): app-icon tiles, as at 96px. |
shadow-lift · shadow-lift-dark | The Lift box shadow and its dark twin (an inset top light, a white ring at 10%, a deep shadow). Pair them: shadow-lift dark:shadow-lift-dark. |
drop-shadow-lift · drop-shadow-lift-dark | Lift as a filter, so it follows the outline of a shape with no box, like the mark. |
rounded-sm … rounded-3xl | Tailwind’s scale: 4, 6, 8, 12, 16 and 24px. Rows use 6, buttons and fields 8 (10 at the larger sizes), popovers 12, cards and dialogs 16. |
Accessibility
- Shadows never carry meaning on their own: every elevation step includes a 1px ring, so edges stay visible on bright screens where soft shadows wash out.
- The lux-lift hover movement (2px up) only runs when the visitor allows motion.
Guidelines
Do
- Nest radii: an inner corner is the outer corner minus the padding between them.
- Use step 4 only for things that float above the page: menus, popovers, dialogs.
- Prefer the --lux-shadow steps in interface code; they flip with the theme on their own.
Don’t
- Don’t stack a shadow step on a surface that already has one (lux-card plus shadow-lg).
- Don’t use shadow-lift without its dark twin.
- Don’t round small controls past 10px; save large radii for large surfaces.
In use
Related
- Cards & elevationCards on one four-step elevation scale: lux-card, a lower lux-card-flat, lux-lift on hover and lux-float for overlays.
- ColourTwelve semantic greys that switch with the theme, and six fixed brand values for the logo and brand panels.
- LogoThe 09 Frame mark and the RChursin_ wordmark in four lockups, drawn as one SVG that takes the text colour.
- PopoverA panel beside its trigger, on the native popover API: never clipped, closed by Esc or a click outside, and it hands focus back.
Source
The component’s own files, exactly as they run on this site.
/* RChursin_ brand tokens (from the brand kit) for Tailwind CSS v4. Every token becomes a utility: bg-ink, text-paper, bg-graphite, text-fog, rounded-tile, shadow-lift, drop-shadow-lift … Fonts are loaded with next/font in src/styles/fonts.ts and wired up in globals.css.
Brand rules: black and white only — greys are for UI surfaces and text. The logo is one colour at a time, never with gradients, glows or effects.*/
@theme { /* Colour */ --color-ink: #0a0a0a; /* primary black: logo, text on light, dark backgrounds */ --color-paper: #ffffff; /* primary white: logo on dark, light backgrounds */ --color-graphite: #171716; /* raised dark surface: cards, sidebars */ --color-board: #1f1f1e; /* presentation / canvas background */ --color-fog: #a3a3a3; /* secondary text on dark (≥ 4.5:1 on ink) */ --color-stone: #737373; /* secondary text on light (≥ 4.5:1 on paper) */
/* Shape */