Design system
How LetzAI should look and behave in the product.
v2 · September 2026 · Public brand guidelines
Principles
- Monochrome. Ink is the accent (
--accentcolor=--color). Colour comes from the work — images and video — never from chrome. Green, red and amber mean feedback and nothing else. - One primary per surface. Only the single action the surface exists for is filled with ink: Send, Share. Everything else is a ghost.
- Ghost, tint, stronger tint. Controls are transparent at rest, take
--control-hover-bgon hover and--control-active-bgwhen chosen. No borders, no underlines, no grey blocks. - Solid surfaces. A surface is a hairline and one shadow (
--elevation-*), not glass. - Two typefaces. Space Grotesk for marketing headlines, never in all caps. Inter for everything in the product.
- One icon set, tokens only. Icons come from
components/icons; colours, sizes and radii come fromstyles/tokens/. No hex in component CSS.
Where things live
| Tokens | styles/tokens/ |
| Controls | styles/components/app-controls.css |
| Shared UI | styles/components/app-*.css |
| Icons | components/icons |
| Popup header, ⋯ menu | components/shared/PopupHeader, MenuButton |
| Brand files | public/brand/ |
Legacy — keeps working, don't extend
| .stdbutton / .altbutton | .app-btn / .app-btn--primary |
| FontAwesome | components/icons |
| Frosted glass (.app-glass-*, --blur-*) | Solid surface + --elevation-* |
| Classic canvas chrome (.cv-*) | ?ui=next (canvas-next.css) |
| Marketing purple (--marketing-accent) | Ink on black, as on the landing |
| New rules in styles.css | A file in styles/components/ |
Color
Live values for the preview theme. The media stage stays near-black in both themes so letterboxing never tints the picture.
Ink
--colorPrimary text, the accent--text-secondarySecondary text--text-tertiaryHints, meta, labelsSurfaces
--bgPage--surface-raisedComposer, cards--popupbgMenus, popups--hairlineDividers, surface edges--bordercolorOutlined controlsStates
--control-hover-bgHover--control-active-bgChosen--stdbuttonbgPrimary fill--stdbuttoncolorPrimary textMedia stage (both themes)
--media-stage-bgViewer stage--media-stage-inkControls on the stageFeedback only
--color-successSuccess--color-errorError--color-warningWarningType
Marketing headlines are Space Grotesk 600 with tight tracking, as on the landing page, and never in all caps. The product is Inter throughout: headings are steps in size and weight of the same family.
Marketing
Create what you love.
Space Grotesk 600 · --text-display-hero · --tracking-display-heroBuilt for professionals.
Space Grotesk 600 · --text-display-section · --tracking-display-sectionGenerate the shots, cut them, export the film.
Inter 400 · 1rem–1.25rem · muted inkProduct
Create what you love.
Inter 500 · 24–30px · -0.02emEnter your image prompt
Inter 400 · 17px · 1.55I generated three looks and put them in a slideshow beside the chat.
Inter 400 · 15.5px · 1.7 (--chat-text)Generations Upscales Assets
Inter 500 · 13px2 min ago · 4 images
Inter 400 · 12px · --text-tertiaryRecents
Inter 600 · 11px · uppercase · 0.04em · --text-tertiarySpace & shape
Spacing — 4px grid
--space-14px--space-28px--space-312px--space-416px--space-624px--space-832px--space-1248px--space-1664pxRadius
--control-radius8px · Every control--radius-xl12px · Menus, floating chrome--radius-2xl16px · Composer card--radius-fullfull · Avatars, status dotsElevation — a hairline and one shadow
--elevation-raisedComposer, cards--elevation-floatPopups, docked bars--elevation-menuMenusPage widths
Pick one: --page-narrow 720px for linear pages, --page-default 960px for entity pages, --page-nav 1200px for settings and hubs, --page-wide 1440px for dense grids. Long copy inside any of them sits on --page-column 800px. Never invent a width.
Icons
One line set on a 24-unit grid with a 1.5 stroke, drawn at 12, 14, 16 or 24px. Icons take currentColor, so they follow the control they sit in. Click an icon to copy its component.
12px14px16px24pxButtons & tabs
One height (--control-height-md 34px, --control-height-sm 28px for chips and card overlays), one radius (--control-radius 8px), 13px Inter 500. Keyboard focus is --focus-ring.
.app-btn · .app-btn--primary · .app-btn--sm · .app-icon-btn · .app-icon-btn--sm.app-tabs · .app-tab[aria-selected] — the chosen tab gets a tint, never an underlineFields
.app-input · textarea.stdtextarea (--compact · --longform)AppListSelect — never a native <select> · .app-segmentedMenus & popups
Every popup closes in the same place: the X, last on the right, labelled “Close (Esc)”. Escape closes the top layer only — an open menu first, then the popup.
PopupHeader — what you're looking at on the left, actions on the right, the close X always last · MenuButton for the one ⋯ menuFeedback
showToast() from lib/toastStore — the link is a word inside the sentence, not a button beside it.app-alert--* · .app-chip--* — colour is for feedback, nothing elseNo bookmarks yet
Saved images and videos show up here.
.app-empty · .app-empty-title · .app-empty-body — one line, no illustrationLogo
Black and white only, with clear space equal to the height of the L. Usage rules are on the public brand guidelines; the full kit is on the press page.

/brand/l-icon-dark.png
/brand/l-icon-light.png
/brand/letzai-lockup-white.png
/brand/letzai-icon-white.png
/brand/letzai-lockup-white-large.pngTokens
| Token | Dark value | Used by |
|---|---|---|
--color | Text, primary fill, focus ring | |
--text-secondary | Controls at rest | |
--text-tertiary | Meta, section labels | |
--bg | Page | |
--surface-raised | Composer, cards | |
--popupbg | Menus, popups | |
--hairline | Dividers, surface edges | |
--control-hover-bg | Hover | |
--control-active-bg | Chosen tab or option | |
--stdbuttonbg | .app-btn--primary | |
--focus-ring | Keyboard focus | |
--media-stage-bg | Media Modal, canvas rooms | |
--font-sans | Inter — all product UI | |
--font-title | Space Grotesk — marketing headlines | |
--text-display-hero | Landing hero | |
--text-display-section | Landing sections | |
--control-height-md | Buttons, tabs, fields | |
--control-height-sm | Chips, card overlays | |
--control-radius | Every control | |
--radius-xl | Menus, floating chrome | |
--radius-2xl | Composer card | |
--space-2 | Gaps inside a control row | |
--space-4 | Default gap | |
--space-8 | Between sections | |
--elevation-raised | Composer, cards | |
--elevation-float | Popups, docked bars | |
--elevation-menu | Menus | |
--duration-fast | Hover and press | |
--duration-normal | Most transitions | |
--ease-default | Every transition | |
--page-narrow | Linear pages | |
--page-default | Entity pages | |
--page-nav | Settings, hubs | |
--page-wide | Dense grids | |
--page-column | Reading column |
The theme is data-theme="light" | "dark" on <html>, stored in localStorage.theme for signed-in visitors. Pages for visitors without a session are always dark. The switch above only changes this page.