The dish
At rest. Deepens on hover.
Look 15, the kit sheet
One dip, four depths. Everything the look is made of, on one page. Every block below is the real markup from sections/ and components/, so if a page built from the look disagrees with this sheet, this sheet wins.
Palette
--bg --surface --surface-2 --text --accent#E8E2D6#F7F3EB#D8D0C0#101B33#2F5FBF#F7F3EBrgba(47, 95, 191, 0.45)rgba(47, 95, 191, 0.20)linear-gradient(180deg, #4D7ED4 0%, #2F5FBF 62%, #17357F 100%)linear-gradient(180deg, #6E9CDF 0%, #4D7ED4 55%, #2F5FBF 100%)inset 0 2px 0 rgba(255, 255, 255, 0.45), inset 0 -10px 14px rgba(8, 26, 69, 0.34), 0 12px 22px -8px rgba(16, 27, 51, 0.40)inset 0 2px 0 rgba(255, 255, 255, 0.55), inset 0 -10px 14px rgba(8, 26, 69, 0.30), 0 18px 28px -8px rgba(16, 27, 51, 0.45)#2F7A4F#9A6B12#B23A2ADecoration only. The four stops are four depths of one cobalt, from a kiss of glaze to a full dip, and the halo is the bloom the deepest one throws on the porcelain.
#17357F#2F5FBF#86AEE4#EDF2F8linear-gradient(90deg, #17357F 0%, #2F5FBF 34%, #86AEE4 67%, #EDF2F8 100%)radial-gradient(60% 55% at 50% 60%, rgba(47, 95, 191, 0.26), rgba(47, 95, 191, 0.07) 55%, rgba(47, 95, 191, 0) 78%)radial-gradient(120% 90% at 50% 40%, #F7F3EB 0%, #E8E2D6 55%, #D8D0C0 100%)url("data:image/svg+xmlType
Control Meter is the original face drawn for this look and ships in fonts/. The scale is closed: eyebrow, display, h2, lede, body, meta, price.
Everything at a depth.
Four colours, one scale, nothing decorated.
$125one of fifty
A look for sites built with Claude Code. Glazed stoneware you can press, bisque wells for everything chosen, four colours on porcelain, one cobalt per screen.
Raised is glazed stoneware: a hard gloss, the glaze pooling darker toward the bottom edge, one specular on top. Recessed is bisque, the matte well it sits in. There is no third material, and state is depth, never a colour.
Look 15, an edition of fifty
Materials
Icons
24-unit grid, solid silhouettes, no strokes: each one dipped to its own depth, the bare clay at .38 of currentColor above the line and solid below. Use inline as <svg class="bl-icon"><use href="#i-name"/></svg> or as the files in assets/icons/.
Motion
Everything is drawn up out of the glaze: pieces rise the last few pixels into place, and headline words come up cobalt and drain to ink. Headlines rise word by word (.bl-words). Blocks fan in (.bl-reveal, staggered by .bl-stagger). Eyebrows and ledes follow (.bl-rise). The film comes up with the page (.bl-hero__film). A glazed surface lifts and deepens a stop on hover (.bl-hover-lift). Keys sink into bisque when pressed. Reduced motion lands everything instantly.
.bl-reveal .bl-words .bl-rise .bl-rise--x .bl-rise--late .bl-hover-liftReplay
Everything at a depth.
Click to play it again.
.bl-skeleton .bl-spinner .bl-progressComponents
Helper classes (.is-hover, .is-focus, .is-active, .is-selected, .is-disabled, .is-loading, .is-invalid, .is-open, .is-checked) draw each state without a pointer. theme.css styles the helper and the real pseudo-class identically.
Buttons are glazed keys: a gloss on top, the glaze pooling darker at the bottom edge, a shadow under. The primary is the cobalt glaze with dark ink and is the one hit per screen. Hover lifts and deepens a stop; pressed sinks the key into bisque. Loading swaps the label for a spinner.
components/buttons.htmlFields are bisque wells. Focus lights the floor of the well cobalt; invalid draws an error line along it; disabled dims. The checkbox is a small well that fills with an cobalt disc when checked.
components/inputs.htmlThat does not look like an email.
No mailing list. We only write back.
Cards are glazed tiles with a bisque window in them. Media is the halo, the dip or an icon on the pattern, never a photograph. Hover lifts and deepens; selected sinks the whole card into bisque.
components/cards.htmlAt rest. Deepens on hover.
Hover, drawn.
Selected, sunk into bisque.
Badges are small bisque wells with a tile in them. The plain badge carries a dim disc; ok, warn and err colour it. They are the only place the status colours appear besides toasts and field errors.
components/badges.htmlTabs are keys on a glazed strip. The active tab has been pressed into bisque. Hover darkens the ink, focus rings in the cobalt line, disabled dims.
components/tabs.htmlThe accordion is a stack of glazed tiles. The open item sinks into bisque and its plus becomes an cobalt minus.
components/accordion.htmlFifty sites get to wear Salt Glaze. Yours is one of them, with its own edition number and licence key.
CLAUDE.md is a set of rules with teeth. If a part does not exist, Claude stops and says so.
Because a scale with more stops is a gradient, and a gradient is not a decision.
The modal is a glazed panel over a scrim. The static modifier renders it inline on the sheet, in a bisque well with the halo behind it.
components/modal.htmlWhen the fiftieth copy sells, Salt Glaze is archived for good and a new look takes its place on the rack. This cannot be undone.
Toasts are small glazed slabs with a tile. Plain, ok, warn and err. The static modifier renders them inline.
components/toast.htmlThe table is the shelf, set in a bisque well. Numbers are in Control Meter Regular and ranged right. Hover deepens a row; selected lifts it out of the well as a glazed strip.
components/table.html| Look | Status | Copies | Left |
|---|---|---|---|
| Aura Glow | Edition open | 50 | 43 |
| Radio | Edition open | 50 | 50 |
| Salt Glaze | Twelve left | 50 | 12 |
| Plinth | Archived | 50 | 0 |
Sections
Variant A is what the demo uses. Variant B is the alternative for the same job. Page recipes are in CLAUDE.md.
Variant A
Variant B
The opening screen. A is the dip, full bleed: the film behind everything, the dip across the top of the screen, and the headline, lede, keys and the scale centred under it on a scrim. Until the film ships the video carries its poster alone, which is also what reduced motion shows; when it lands, a <source> for ../motion/salt-glaze-hero.mp4 goes inside the video. B is the split hero for inner pages: headline left, three bisque stats right, no film. Headlines use .bl-words so they rise word by word.
sections/hero.htmlVariant A
Look 15 from Bandana
One dip, four depths, and the porcelain they were cut from. Salt Glaze is a locked look for sites built with Claude Code: glazed stoneware you can press, bisque wells for everything chosen, one cobalt per screen. One folder, one prompt, fifty copies.
Variant B
Look 15, inner page
The split hero. Headline on the left, three bisque wells on the right, one cobalt key. For pricing, about and work pages.
The parts of the look, one per glazed tile. A is six tiles in a grid, each with a dipped icon in a bisque well and a number; hover deeps the tile one stop. B is the same six as rows for a narrower page, icon left, text right.
sections/feature-grid.htmlVariant A
The parts
A look is one folder. Everything in it obeys one file, and the file is not negotiable.
Glazed stoneware: a hard gloss, the glaze pooling darker toward the bottom edge, one specular on top. And bisque, the matte well it sits in. Keys are glazed, fields are bisque, and anything chosen sinks into bisque. State is depth, never a colour.
Deep, mid, shallow, kiss. Four stops and nothing between them. The cobalt is the accent and lands once per screen, at the front of the dip.
A condensed rounded monoline, drawn from scratch for Bandana and bundled with the look. Headlines, prices, big numbers. Never a paragraph.
Dipped: solid silhouettes, no strokes, and every line cut into the geometry. Dish, stack, fan, kiln, glaze, chip, ring, foot, tong, shelf, cone, drip. One drawing each.
Everything is drawn up out of the glaze: pieces rise the last few pixels into place, and headline words come up cobalt and drain to ink. Headlines rise word by word. Nothing fades from nowhere and nothing slides in from off-screen. Presets only.
Native is the salt kiln, porcelain. The other is the same tiles on porcelain stock in daylight. Only the colour tokens change; the film stays dark in both.
Variant B
The parts, as a list
Raised and recessed. There is no third material.
Four stops. The cobalt is the one hit per screen.
Two cuts, display only, bundled.
Tiles only. None is a variation of another.
From the stack, one stop deeper each.
The kiln room, and the same tiles in daylight.
The rules, made visible. A is six glazed tiles on a three-column grid: the keys and their states, the face, the dip drawn in CSS, the scale, the three status tiles, and the halo. B is four equal tiles for a shorter page.
sections/bento.htmlVariant A
The rules, made visible
A key is a glazed key: a gloss on top, the glaze pooling at the bottom edge. Press it and it sinks into bisque. Every field is bisque too, and the cobalt comes up along its floor on focus.
Regular for prices and stats, Bold for headlines and the mark.
Four tiles, cobalt in front. Drawn in CSS wherever a page needs the signature small.
The one gradient the look allows, and only as a bar: progress, the toggle dot, a bullet. Never on text, never behind a paragraph.
Ok, warn and err exist for badges, toasts and field errors, and nowhere else. They are never the accent.
The cobalt bloom under the dip. Hero and CTA backdrops, tile art, card media. Never behind a paragraph.
Variant B
Four rules
The cobalt lands on the primary key and nowhere else.
Selected, active, current: bisque, every time.
Headlines, prices, numbers. Body copy is Figtree.
Nothing between the stops and nothing off the scale.
The kiln, close up. A is six glazed tiles with bisque windows, each holding one of the look's objects drawn in CSS: the dip, a glazed key, a bisque well on focus, the scale, the digits, the key in the halo. B is four wide tiles.
sections/gallery.htmlVariant A
The kiln, close up
Variant B
Wide tiles
The editions. A is three glazed plans side by side; the chosen one has sunk into bisque and carries the one cobalt key. B is the same three as rows.
sections/pricing.htmlVariant A
Editions
Every look on the rack is sold fifty times and archived. No reprints, no free tier, no second firing.
$125Salt Glaze
$300any three
$425any five
Variant B
Editions, as rows
A rule, set large, on one glazed slab. Not a customer quote: the look speaks for itself. A is one centred slab. B is two side by side, ranged left.
sections/testimonial.htmlVariant A
It refuses a fifth depth. Deep, mid, shallow, kiss, and the porcelain they are cut from.
Variant B
Nothing on the page is ever cold.
State is depth. Chosen sinks into bisque.
Questions. A is the split: the head on the left, the accordion on the right; shut items are glazed, the open one has sunk into bisque and its plus has become an cobalt minus. B is a plain two-column definition list, no accordion.
sections/faq.htmlVariant A
Questions
Short answers. The long ones are in the file.
Variant B
Questions, flat
The close. A is one glazed slab with the halo under it, the headline left and the one cobalt key right. B is a full-width band, centred, for the foot of an inner page.
sections/cta.htmlVariant A
Look 15
Fifty copies. When they are gone, Salt Glaze is archived and the rack moves on.
Variant B
Look 15
One folder, one prompt, fifty copies.
Variant A
Variant B
Write to us. A is the split: the head on the left, the form on the right, every field a bisque well and the one cobalt key to send. B is the form alone on a glazed slab, for a contact page.
sections/contact-form.htmlVariant A
Write to us
Tell us what you are building and which looks you have your eye on. We answer within a day.
Variant B
Write to us
Tokens
Native values first; the light scheme overrides only the colour tokens. The same list is in theme.json.
| Token | Group | Native | light |
|---|---|---|---|
| --bg | canvas | #E8E2D6 | #121A2B |
| --surface | canvas | #F7F3EB | #1A2440 |
| --surface-2 | canvas | #D8D0C0 | #0C1220 |
| --text | canvas | #101B33 | #E7EDF7 |
| --text-2 | canvas | rgba(16, 27, 51, 0.70) | rgba(231, 237, 247, 0.70) |
| --text-3 | canvas | rgba(16, 27, 51, 0.46) | rgba(231, 237, 247, 0.44) |
| --line | canvas | rgba(16, 27, 51, 0.12) | rgba(231, 237, 247, 0.12) |
| --accent | accent | #2F5FBF | #6E9CDF |
| --accent-ink | accent | #F7F3EB | #0C1220 |
| --accent-line | accent | rgba(47, 95, 191, 0.45) | rgba(110, 156, 223, 0.45) |
| --accent-glow | accent | rgba(47, 95, 191, 0.20) | rgba(110, 156, 223, 0.26) |
| --accent-bg | accent | linear-gradient(180deg, #4D7ED4 0%, #2F5FBF 62%, #17357F 100%) | linear-gradient(180deg, #86AEE4 0%, #6E9CDF 62%, #3E6DC9 100%) |
| --accent-bg-up | accent | linear-gradient(180deg, #6E9CDF 0%, #4D7ED4 55%, #2F5FBF 100%) | linear-gradient(180deg, #A8C6EE 0%, #86AEE4 55%, #6E9CDF 100%) |
| --accent-shadow | accent | inset 0 2px 0 rgba(255, 255, 255, 0.45), inset 0 -10px 14px rgba(8, 26, 69, 0.34), 0 12px 22px -8px rgba(16, 27, 51, 0.40) | inset 0 2px 0 rgba(255, 255, 255, 0.45), inset 0 -10px 14px rgba(8, 26, 69, 0.34), 0 12px 22px -8px rgba(16, 27, 51, 0.40) |
| --accent-shadow-up | accent | inset 0 2px 0 rgba(255, 255, 255, 0.55), inset 0 -10px 14px rgba(8, 26, 69, 0.30), 0 18px 28px -8px rgba(16, 27, 51, 0.45) | inset 0 2px 0 rgba(255, 255, 255, 0.55), inset 0 -10px 14px rgba(8, 26, 69, 0.30), 0 18px 28px -8px rgba(16, 27, 51, 0.45) |
| --deep | aura | #17357F | #2F5FBF |
| --mid | aura | #2F5FBF | #5C8FD8 |
| --shallow | aura | #86AEE4 | #A8C6EE |
| --kiss | aura | #EDF2F8 | #E7EDF7 |
| --ramp | aura | linear-gradient(90deg, #17357F 0%, #2F5FBF 34%, #86AEE4 67%, #EDF2F8 100%) | linear-gradient(90deg, #2F5FBF 0%, #5C8FD8 34%, #A8C6EE 67%, #E7EDF7 100%) |
| --halo | aura | radial-gradient(60% 55% at 50% 60%, rgba(47, 95, 191, 0.26), rgba(47, 95, 191, 0.07) 55%, rgba(47, 95, 191, 0) 78%) | radial-gradient(60% 55% at 50% 60%, rgba(110, 156, 223, 0.34), rgba(110, 156, 223, 0.10) 55%, rgba(110, 156, 223, 0) 78%) |
| --pattern | aura | radial-gradient(120% 90% at 50% 40%, #F7F3EB 0%, #E8E2D6 55%, #D8D0C0 100%) | radial-gradient(120% 90% at 50% 40%, #1A2440 0%, #121A2B 55%, #0C1220 100%) |
| --grain | aura | url("data:image/svg+xml | url("data:image/svg+xml |
| --grain-opacity | other | 0.05 | 0.07 |
| --hero-text | other | #101B33 | #E7EDF7 |
| --hero-text-2 | other | rgba(16, 27, 51, 0.72) | rgba(231, 237, 247, 0.72) |
| --hero-scrim | other | linear-gradient(90deg, var(--bg) 0 24%, rgba(232, 226, 214, 0.84) 42%, rgba(232, 226, 214, 0.16) 58%, rgba(232, 226, 214, 0) 72%) | linear-gradient(90deg, var(--bg) 0 28%, rgba(18, 26, 43, 0.92) 46%, rgba(18, 26, 43, 0.66) 66%, rgba(18, 26, 43, 0.52) 100%) |
| --ok | status | #2F7A4F | #7FC79A |
| --warn | status | #9A6B12 | #E0B15A |
| --err | status | #B23A2A | #E8836F |
| --raised-bg | materials | linear-gradient(180deg, #FFFFFF 0%, #F7F3EB 55%, #E9E2D5 100%) | linear-gradient(180deg, #24304F 0%, #1B2540 55%, #151D34 100%) |
| --raised-bg-up | materials | linear-gradient(180deg, #FFFFFF 0%, #FBF8F2 55%, #F0EADE 100%) | linear-gradient(180deg, #2C3A5E 0%, #212C4B 55%, #1A2440 100%) |
| --raised-flat | materials | #F7F3EB | #1B2540 |
| --raised-ink | materials | #101B33 | #E7EDF7 |
| --raised-ink-2 | materials | rgba(16, 27, 51, 0.70) | rgba(231, 237, 247, 0.70) |
| --raised-shadow | materials | inset 0 1px 0 #FFFFFF, inset 0 -12px 18px -8px rgba(16, 27, 51, 0.20), 0 1px 0 rgba(16, 27, 51, 0.12), 0 18px 30px -12px rgba(16, 27, 51, 0.32) | inset 0 1px 0 rgba(231, 237, 247, 0.18), inset 0 -12px 18px -8px rgba(0, 0, 0, 0.55), 0 1px 0 rgba(0, 0, 0, 0.4), 0 18px 30px -12px rgba(0, 0, 0, 0.6) |
| --raised-shadow-up | materials | inset 0 1px 0 #FFFFFF, inset 0 -12px 18px -8px rgba(16, 27, 51, 0.16), 0 1px 0 rgba(16, 27, 51, 0.12), 0 26px 40px -14px rgba(16, 27, 51, 0.38) | inset 0 1px 0 rgba(231, 237, 247, 0.26), inset 0 -12px 18px -8px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(0, 0, 0, 0.4), 0 26px 40px -14px rgba(0, 0, 0, 0.65) |
| --raised-hit | materials | inset 0 1px 0 #FFFFFF, inset 0 -12px 18px -8px rgba(16, 27, 51, 0.20), 0 0 0 2px var(--accent-line), 0 18px 30px -12px rgba(16, 27, 51, 0.32) | inset 0 1px 0 rgba(231, 237, 247, 0.18), inset 0 -12px 18px -8px rgba(0, 0, 0, 0.55), 0 0 0 2px var(--accent-line), 0 18px 30px -12px rgba(0, 0, 0, 0.6) |
| --gloss | materials | radial-gradient(70% 60% at 30% 0%, rgba(255, 255, 255, 0.72), rgba(255, 255, 255, 0) 70%) | radial-gradient(70% 60% at 30% 0%, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 70%) |
| --gloss-strong | materials | radial-gradient(60% 50% at 35% 0%, rgba(255, 255, 255, 0.90), rgba(255, 255, 255, 0) 70%) | radial-gradient(60% 50% at 35% 0%, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0) 70%) |
| --recessed-bg | materials | #D7CFC0 | #0E1626 |
| --recessed-shadow | materials | inset 0 3px 6px rgba(16, 27, 51, 0.26), inset 0 1px 0 rgba(16, 27, 51, 0.16), inset 0 -1px 0 #FFFFFF, 0 1px 0 #FFFFFF | inset 0 3px 6px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(0, 0, 0, 0.5), inset 0 -1px 0 rgba(231, 237, 247, 0.10), 0 1px 0 rgba(231, 237, 247, 0.06) |
| --recessed-shadow-deep | materials | inset 0 5px 10px rgba(16, 27, 51, 0.30), inset 0 1px 0 rgba(16, 27, 51, 0.20), inset 0 -1px 0 #FFFFFF, 0 1px 0 #FFFFFF | inset 0 5px 10px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(0, 0, 0, 0.6), inset 0 -1px 0 rgba(231, 237, 247, 0.12), 0 1px 0 rgba(231, 237, 247, 0.06) |
| --recessed-lit | materials | inset 0 3px 6px rgba(16, 27, 51, 0.26), inset 0 -1px 0 var(--accent), inset 0 -14px 24px -14px var(--accent-glow), 0 1px 0 #FFFFFF | inset 0 3px 6px rgba(0, 0, 0, 0.6), inset 0 -1px 0 var(--accent), inset 0 -14px 24px -14px var(--accent-glow), 0 1px 0 rgba(231, 237, 247, 0.06) |
| --scrim | materials | rgba(247, 243, 235, 0.82) | rgba(12, 18, 32, 0.80) |
| --chevron | materials | url("data:image/svg+xml | url("data:image/svg+xml |
| --font-display | type | "Control Meter", "IBM Plex Sans Condensed", "Arial Narrow", sans-serif | "Control Meter", "IBM Plex Sans Condensed", "Arial Narrow", sans-serif |
| --font-body | type | "Figtree", system-ui, sans-serif | "Figtree", system-ui, sans-serif |
| --display-weight | type | 700 | 700 |
| --text-xs | type | .75rem | .75rem |
| --text-sm | type | .875rem | .875rem |
| --text-md | type | 1.0625rem | 1.0625rem |
| --text-lg | type | 1.1875rem | 1.1875rem |
| --text-xl | type | 1.5rem | 1.5rem |
| --text-h3 | type | 1.75rem | 1.75rem |
| --text-h2 | type | clamp(2.2rem, 4.4vw, 3.8rem) | clamp(2.2rem, 4.4vw, 3.8rem) |
| --text-display | type | clamp(3rem, 7vw, 6.4rem) | clamp(3rem, 7vw, 6.4rem) |
| --text-price | type | 3rem | 3rem |
| --track-caps | type | .16em | .16em |
| --leading-tight | type | .98 | .98 |
| --leading-body | type | 1.55 | 1.55 |
| --radius | shape | 22px | 22px |
| --radius-sm | shape | 14px | 14px |
| --radius-pill | shape | 999px | 999px |
| --rule | shape | 1px | 1px |
| --space-1 | space | .25rem | .25rem |
| --space-2 | space | .5rem | .5rem |
| --space-3 | space | .75rem | .75rem |
| --space-4 | space | 1rem | 1rem |
| --space-5 | space | 1.5rem | 1.5rem |
| --space-6 | space | 2rem | 2rem |
| --space-7 | space | 3rem | 3rem |
| --space-8 | space | 4.5rem | 4.5rem |
| --space-9 | space | 7rem | 7rem |
| --wrap | space | 1200px | 1200px |
| --control | space | 50px | 50px |
| --control-sm | space | 38px | 38px |
| --icon | space | 22px | 22px |
| --dur-fast | motion | 160ms | 160ms |
| --dur | motion | 420ms | 420ms |
| --dur-slow | motion | 820ms | 820ms |
| --ease | motion | cubic-bezier(.2, .7, .2, 1) | cubic-bezier(.2, .7, .2, 1) |
| --ease-fan | motion | cubic-bezier(.16, 1, .3, 1) | cubic-bezier(.16, 1, .3, 1) |
| --reveal-y | motion | 0px | 0px |