Color & material
White light, the Iris key light, six spectral domain bands, status colors, dispersion and the spectrum bar; five levels of optical glass, frosted glass, scrim, specular light and z-index.
Every color pair below has been checked for contrast by script. Code references tokens; components never hard-code color values.
White light (neutrals)
| Token | Light | Dark (darkroom) | Use |
|---|---|---|---|
canvas | #f3f6fb | #0c0f14 | The table: page and sidebar background |
surface | #ffffff | #16191f | Glass slabs: cards, lists, popovers |
container | #edf0f6 | #1f232b | Inputs, segmented tracks, tonal buttons, row hover |
container-high | #e4e7ef | #282d36 | Hover / pressed on a container |
separator | #e0e3ea | #2c3039 | Inset list separators (the only permanent line allowed) |
ink | #191e29 | #f2f3f7 | Headings, body text, numbers |
ink-2 | #515763 | #b1b6bf | Secondary text and columns |
ink-3 | #656a75 | #8e929b | Labels, timestamps, axes; only on canvas / surface / container, never on container-high (4.4:1) |
Key light (Iris)
| Token | Light | Dark | Use |
|---|---|---|---|
brand | #415ae0 | #6b89f9 | Primary button, current nav icon, links, focus ring |
brand-hover | #384ecf | #7d9bff | Primary button hover |
brand-tint | #e6eeff | #1f2a53 | Selection: chips, selected rows, the refracted fill of a selected segment |
on-brand-tint | #3043bc | #bccfff | Text and icons on brand-tint |
on-brand | #ffffff | #0c0f14 | Primary button text; also text on solid status colors (count badges) |
White text on solid danger fails contrast in dark mode, so text on any solid status color uses on-brand.
Spectrum (domain colors)
Ordered by wavelength, long to short. Each domain has three steps: solid (icons, chart lines), -tint (icon tile and badge fill) and on-*-tint (text on the tint).
| Band | Domain | Hue | Solid light / dark | Tint light / dark | On-tint light / dark | Used for |
|---|---|---|---|---|---|---|
| Orange | distribution | 50 | #c25600 / #e9884d | #ffeadc / #43210d | #883600 / #ffc09c | Social distribution, platform accounts |
| Amber | billing | 80 | #aa6b00 / #d29922 | #fdeed6 / #3b2700 | #774700 / #f0cb8d | Subscriptions, orders, commissions |
| Green | cluster | 155 | #00944d / #4ebe7d | #dff8e6 / #0c341e | #006630 / #a1e3b7 | Cluster sites, domains |
| Cyan | search | 205 | #0092a7 / #00bdce | #d6f8fb / #003339 | #006474 / #85e2ed | SEO, GSC, keywords, sites |
| Blue | content | 250 | #0d7dd4 / #59aaf8 | #dff3ff / #112d48 | #005496 / #a4d6ff | Articles, categories, media, collection, review |
| Violet | ai (AI / GEO) | 300 | #8a5fc9 / #b28fef | #f3ebff / #302445 | #5f3d8e / #dac4ff | AI generation, GEO suggestions, MCP |
- Display order (legends, spectrum bars, module lists): by wavelength, distribution → billing → cluster → search → content → ai.
- Chart series order (so neighbouring series stay distinguishable): content → ai → search → distribution → cluster → billing.
- In light mode, solid search and cluster reach only 3.7–3.9:1 on surface. Use domain solids only for icons, charts and text ≥ 24px; text always uses
on-*-tint.
Status colors
| Status | Solid light / dark | Tint light / dark | On-tint light / dark |
|---|---|---|---|
success | #0e8c41 / #62c37a | #e2f9e6 / #0f3118 | #005e26 / #aae5b5 |
warning | #bc7400 / #e19b34 | #ffefd9 / #3b2300 | #7a4400 / #f9cb92 |
danger | #bc4945 / #f7857d | #ffe9e6 / #421c19 | #822b2a / #ffbeb6 |
info | #007dc2 / #47b5fa | #def6ff / #042c43 | #005387 / #9dddff |
A status badge is tint fill + on-tint text + icon, with no border.
Dispersion
--dispersion: linear-gradient(90deg, distribution, billing, cluster, search, content, ai)
Dispersion is Prism's only gradient, and it appears in three places only:
| Where | Form |
|---|---|
| AI-generated content | A 2px dispersion edge on the card's top edge (class .dispersion-edge, inset 16px on each side) |
| Brand mark and website hero | The spectrum inside the prism mark; the refraction illustration in the hero |
| Success confirmation | One light sweep in dispersion colors, 600ms, played once |
No other gradients. The vertical fade of area charts (24% at the top → 0 at the bottom) does not count as dispersion.
Spectrum bar
Shows how one piece of content splits across channels: a segmented bar 8px high with 2px gaps, fully rounded ends, segments in display order and widths proportional to the values, with a legend below (dot + name + share). It is the data graphic unique to this language, used for distribution reach, traffic sources, AI citation sources and quota breakdowns. Class .spectrum; each child i sets --w (weight) and data-tone.
Color rules
- Brand covers ≤ 10% of a screen: usually one primary button, the current nav item and the focus ring.
- Domain colors appear only where they identify something: icon tiles beside card titles, charts, category badges, spectrum bars. Never fill large areas with them.
- At most 4 domain colors per screen (except the dashboard, which summarises every domain).
- Status colors express status only, never emphasis.
- Selection uses
brand-tint; the current location is a "lit slab" (surface +elev-1). Don't mix the two. - Dark is not an inversion: surfaces get brighter as they rise (surface → container), and brand and domain colors step up one level in lightness.
Contrast (WCAG 2.1)
| Foreground | Background | Light | Dark | Required |
|---|---|---|---|---|
ink | canvas | 15.40 | 17.31 | 4.5 |
ink-2 | surface | 7.26 | 8.64 | 4.5 |
ink-3 | canvas | 5.01 | 6.16 | 4.5 |
ink-3 | container | 4.75 | 5.05 | 4.5 |
ink-3 | container-high | 4.38 | 4.43 | Not allowed |
ink-2 | container-high | 5.87 | 6.79 | 4.5 |
on-brand | brand | 5.58 | 6.01 | 4.5 |
on-brand | brand-hover | 6.65 | 7.32 | 4.5 |
on-brand-tint | brand-tint | 6.79 | 8.92 | 4.5 |
brand (links) | surface | 5.58 | 5.51 | 4.5 |
on-content-tint | content-tint | 6.79 | 9.14 | 4.5 |
on-search-tint | search-tint | 6.07 | 9.20 | 4.5 |
on-ai-tint | ai-tint | 7.13 | 9.10 | 4.5 |
on-distribution-tint | distribution-tint | 7.01 | 9.08 | 4.5 |
on-cluster-tint | cluster-tint | 6.36 | 9.30 | 4.5 |
on-billing-tint | billing-tint | 6.84 | 9.23 | 4.5 |
| Domain solid (icon tile) | Matching tint | 3.29–3.98 | 5.51–5.98 | 3 (icons) |
search / cluster (icons) | surface | 3.70 / 3.93 | 7.69 / 7.53 | 3 (icons) |
on-success-tint | success-tint | 7.20 | 9.90 | 4.5 |
on-warning-tint | warning-tint | 7.01 | 9.80 | 4.5 |
on-danger-tint | danger-tint | 7.75 | 9.42 | 4.5 |
on-info-tint | info-tint | 7.24 | 9.83 | 4.5 |
on-brand | danger (count badge) | 5.03 | 7.87 | 4.5 |
on-inverse | inverse (toast, tooltip) | 15.40 | 17.31 | 4.5 |
Five levels of optical glass
Light comes from above and slightly to the left; shadows fall downward. Each level = surface color + shadow + top-edge highlight.
| Level | Name | Surface | Shadow (light) | Highlight | Use |
|---|---|---|---|---|---|
| 0 | Table | canvas | None | None | Page background, sidebar |
| 1 | Slab | surface | elev-1: 0 1px 2px rgb(16 24 40/.04), 0 2px 6px rgb(16 24 40/.05) | inset 0 1px 0 var(--edge) | Cards, list cards, current sidebar item |
| 2 | Raised | surface | elev-2: 0 2px 4px rgb(16 24 40/.05), 0 8px 20px -4px rgb(16 24 40/.10) | Same | Hovered cards, sticky bars, selected segment thumb |
| 3 | Float | surface | elev-3: 0 4px 8px -2px rgb(16 24 40/.08), 0 16px 32px -8px rgb(16 24 40/.16) | Same + inset 0 0 0 1px var(--hairline) | Menus, dropdowns, popovers, a dragged row |
| 4 | Overlay | surface | elev-4: 0 8px 16px -4px rgb(16 24 40/.10), 0 32px 64px -12px rgb(16 24 40/.28) | Same as 3 | Dialogs, drawers, bottom sheets |
--edge: lightrgb(255 255 255 / .7), darkrgb(255 255 255 / .06). The 1px lit top edge that replaces borders.--hairline: lightrgb(25 30 41 / .06), darkrgb(255 255 255 / .07). Only for levels 3 and 4, which float above content, so they don't merge into what's beneath.- Dark: shadow opacity ×2; higher levels get brighter surfaces (level 4 may use
container). - Never nest a shadowed card inside a card; for sub-groups use an inset
containerarea or a grouped list.
Frosted glass
--glass (surface at 72%) + backdrop-filter: blur(20px) saturate(180%).
| Used on | When it appears |
|---|---|
| Top bar | Fully transparent at rest, blending into the table; frosted with elev-1 once the page scrolls > 4px |
| Mobile bottom action bar | Always |
| Bulk action bar, save bar, floating toolbars | While shown |
Scrim
--scrim: oklch(0.18 0.02 265 / 0.40) + backdrop-filter: blur(4px). The same in both themes, so it never gets lighter in dark mode.
Specular light
Clickable cards (class .lift) show a soft light that follows the pointer on hover, under @media (hover: hover): radial-gradient(280px circle at the pointer, var(--specular), transparent 60%). --specular is rgb(255 255 255/.55) in light and rgb(255 255 255/.05) in dark, fading in over 150ms. Only on clickable cards, never on table rows or buttons; off under reduced motion.
Z-index
| Token | Value | Use |
|---|---|---|
z-sticky | 1020 | Top bar, sticky table headers, save bar |
z-drawer | 1030 | Drawers, mobile navigation |
z-dialog | 1040 | Dialogs |
z-popover | 1045 | Menus, dropdowns, popovers (including dropdowns inside dialogs) |
z-toast | 1050 | Toasts |
z-tooltip | 1060 | Tooltips |
Prism design language
The design language of the GEO platform, built on one image: a single beam of light refracted into a spectrum. Core metaphor, five principles, references and the interactive demo.
Type, shape & icons
Geist with system CJK fonts, the console type scale and typesetting rules; radius tokens and the concentric rule; Lucide icons and icon tiles.