Workbench · admin theme overview · v2.11
Workbench · admin theme · pairs with design-admin.md

Calm structure
for consequential work.

Workbench is the precise, durable workspace theme for operators, owners, editors, and support teams. A neutral palette keeps attention on the work; compact rhythm makes dense information easy to scan; restrained motion makes every outcome feel immediate. Cedar appears only where it adds meaning: links, the first data series, and Cedra's presence. This page is the theme's preview and its brand guideline in one — read it top to bottom to decide whether Workbench is your theme, then keep it open as the reference while you work in it. The paired design-admin.md is the implementation standard agents follow when styling inside the theme, and this two-file pair is the format every Cedros theme ships.

Neutral palette Compact rhythm Light + dark Keyboard-first WCAG 2.2 AA shadcn-inspired Cedar links + data Sentence case Durable by design
The theme at work

One screen tells the story

A content library rendered entirely in Workbench: the quiet shell, one primary action, placeholder-labeled filters, publish state at a glance, mono identifiers, tabular numerics, and a single promoted action per row. Cedar appears exactly where it means something — links, data, and Cedra. This is the composition a marketplace preview captures.

Everything above is live CSS — toggle dark in the header and the whole composition holds. Hover the first row for the 800ms update flash; the first ⋯ opens a real menu (destructive item red, last, below a separator). In the sidebar, Forms carries a needs-attention badge and Products is capability-locked at 0.48 opacity with its reason in the tooltip.

Theme identity

Quiet at rest. Immediate in use.

Workbench borrows shadcn's composure and translates it into a Cedros workspace: denser, more operational, and ready for first-party or extension-owned surfaces. Familiarity is part of the aesthetic—new capabilities should feel as though they have always belonged.

Promise

Dense work feels clear

Alignment, compact scales, and visible state make complex operations easy to scan without making the workspace feel compressed.

Personality

Neutral · precise · capable

Confident without being loud. Helpful without performing. Warmth appears in language and meaningful accents, not decoration.

Signature

Hairlines, rhythm, restraint

Tabular data, concentric corners, measured elevation, and one cedar accent create a recognizable system in either mode.

Neutral surfaces, semantic color, compact hierarchy Gradients, glass, ornamental color, oversized type
Principles

Seven rules that settle arguments

Every ambiguous design choice in Workbench resolves against these rules. They are why the theme stays coherent as it grows — and why a page built by an extension author is indistinguishable in kind from a page built by Cedros.

W1 · The primitive wins

One component per job. If it can't do the job, extend the primitive — never fork a local copy.

W2 · The scale is the law

Eight type sizes, seven spacing steps, three radii, four elevations, two role-based control heights. Off-scale values are out of character even when they look fine alone.

W3 · Aligned at rest

Ordinary action buttons are 32px, single-line fields are 36px, and mixed rows align their centers. Labels share one baseline and numbers one right edge.

W4 · Dense, calm, scannable

13–14px body, 32px buttons, 36px fields, ~40px rows — density paid for with hierarchy, never with clutter.

W5 · State over chrome

Only states that need attention may attract it: unsaved, running, failed, needs review. Everything decorative stays neutral.

W6 · Instant, keyboard-first, both modes

≤100ms acknowledgment, visible focus only on keyboard, full keyboard parity, WCAG 2.2 AA in light and dark alike.

W7 · Boring by design

The workspace should look barely different year over year. New capabilities feel like they were always here.

Foundations · 01 — tokens

A neutral foundation with one meaningful accent

The palette is shadcn's default neutral — the mapping is exact and deliberate. Toggle dark in the header: every swatch is a live token. Semantic status colors carry outcomes; chart/art tokens carry non-semantic series and decoration; --cd-link is the sole cedar accent; a named z-scale keeps every layer predictable.

--cd-bgbackground
--cd-card-bgcard
--cd-muted-bgmuted
--cd-accentaccent · surface, never text
--cd-borderborder
--cd-ringring
--cd-mutedmuted-foreground
--cd-primaryprimary
--cd-successcompleted · healthy
--cd-warningsurface tints
--cd-warning-fgreadable warning text
--cd-errorstatus error · tints
Aa
--cd-danger-bg/-fgpaired destructive button
--cd-infoinfo
--cd-linkthe only cedar here
--cd-chart-1cedar · chart/art only
--cd-chart-2gold · chart/art only
--cd-chart-3sage · chart/art only
--cd-chart-4clay · chart/art only
--cd-chart-5indigo · chart/art only
--cd-chart-6mist · chart/art only
Foundations · 02 — scales

Eight sizes, two heights, three radii

A small, deliberate scale creates Workbench's visual rhythm. Eight type roles establish hierarchy; two role-based control heights keep like controls consistent; three structural radii make nested surfaces feel cut from the same material.

Type — 8 sizes · uppercase only where the eye scans columns

2xs 11px 600 capsTable header · stat label · nav group
xs 12pxCaptions, chip text
sm 13px 400–500Controls, cells, form labels (sentence case), help
base 14px · 600=titlesCard & section titles
md 16px 600Emphasized values
lg 18.4px 600Page & dialog titles
xl 24px 600Stat values
2xl 32px 700 tabular12,418
SITE TITLE — uppercase form labels Site title — sentence case, 13px/500

Control heights — 32px buttons · 36px single-line fields

Every ordinary action button uses the same 32px outer height. Single-line fields remain 36px; mixed button-field rows align their centers.

Radius 7 derived · 8 · 12 · pill

Concentric children share the parent's curve center: child radius = parent radius − the actual outer-edge inset, including the parent border.

Workbench chrome is guarded by npm run lint:admin-corner-radii; authored/public previews require an explicit reviewed exception.

Elevation

e0border only
e1cards
e2menus
e3dialogs · toasts
Foundations · 03 — mono & numbers

Quantities read. Identifiers copy.

Typography follows meaning. Numbers you read — counts, money, dates, stats — are the UI sans with tabular-nums, right-aligned in columns, never mono. Strings you copy or compare character-by-character — slugs, refs, keys, payloads — are --cd-font-mono, one step smaller, muted in table cells.

Sans + tabular-nums — quantities

MetricValue
Revenue · 7 days$8,940.00
Orders1,284
Conversion3.4%
Avg session1m 42s
Visitors12.4k

Money is never mono. Abbreviate at five digits (12.4k) with the exact value on hover. Locale formatters only — no hand-built number strings.

Mono — identifiers, one step smaller

Slug chip/privacy-policy
Referencereq_8f3a Copy
Secret · entry
Secret · saved Saved · updated Jun 12
Versionv2.4.1
Inline chipContact support with code pub_4t2c.

Identifiers earn copy buttons (hover the copy icon — tooltip); secrets are write-only: an eye toggle while entering, then a mask with Replace / Remove — a stored secret is never re-shown and never copied. Emails and names stay sans; ISO timestamps in logs may be mono.

Code block — filename, language, one copy control per block

cedros.config.json json
{
  "site": "cabrillo.coffee",
  "webhooks": [
    { "event": "order.created", "url": "https://api.cabrillo.coffee/hooks" }  // retries ×3
  ]
}

Read-only code: muted wash, hairline frame, mono 0.72–0.75rem, scrolls inside its own frame; "Copy" flips to "Copied". Editable JSON is the code textarea with "Format JSON" + inline validity. Logs are compact tables (status dot · time · area · message), never a <pre> wall.

Foundations · 04 — icons

Lucide geometry, 16px, currentColor

Stroke 2, round caps and joins, drawn on a 24 grid, fill="none". 16px default; 13–14px inside sm controls and menu items; nothing over 20px in chrome. Icons assist labels — icon-only controls require aria-label + a tooltip. Extension nav icons are Lucide names from the manifest (sections[].icon) and render identically to core items. No fills, no emoji, no duotone, no brand glyphs in the nav.

16px · stroke 2 20px max muted 0.75 at rest → full on hover/active
Composition · 05 — template A, the list page

A dense workspace that stays quiet

The cover composition at the top of this page is Template A rendered whole. Its grammar: a page header (title, one-sentence subtitle, one primary action) → one toolbar row with 36px fields and 32px buttons → the table → pagination. The active destination uses a plain accent fill; keyboard focus appears only when needed. And when rows support bulk work, the toolbar itself becomes the selection bar:

Labels stacked above toolbar controls Rows crowded with equal-weight actions placeholder toolbar · Edit + ⋯ · sentence case · :focus-visible only

Selection & bulk actions — the toolbar becomes the selection bar

TitleViews
Home1,284
About412
Contact96

Header checkbox = select-all with the indeterminate state; Esc clears; destructive bulk actions confirm with the count ("Delete 12 pages?"). Selection is a toolbar state, not a separate visual language.

Composition · 06 — template B, the settings page

Focused forms with room to think

Segmented tabs hug their content; a 45rem column keeps fields comfortable; labels use sentence case; select triggers stay single-line with help below; every mutable card ends in a Save footer, disabled until dirty.

Full-bleed fields and boxed full-width tab bars Uppercase form labels and multi-line triggers 45rem column · sentence labels · single-line select + help · hugging tabs · Save per card

Site

Manage business info and public contact details.

Business info

The public identity used in search results, link previews, and site metadata.

Used as the homepage meta description and the public summary for this site.
Sets the schema markup for your pages. "Not specified" uses generic markup.
No image
Shown when your site is shared in search, texts, and social feeds. 1200×630px works best.

Public contact

Contact details shown on your public contact page.

Hours Choose the days and time ranges shown with your contact details.
9:00 – 17:00
9:00 – 17:00
Unavailable

Danger zone

These actions affect your live site and can't always be undone.

Delete this site and all of its content. This can't be undone.
Components · 07 — buttons

Five variants, sentence case, one primary per action cluster

Competing primary actions; tinted destructive buttons Noun-first Title Case labels primary · outline · ghost · destructive · link — sentence case

Destructive is solid (shadcn) and rare — it confirms destructive work. It uses the paired --cd-danger-bg/--cd-danger-fg button tokens; --cd-error remains the status and tint color. Row-level deletes live in the ⋯ menu as red items, not as buttons. Disabled buttons say what unlocks them, or stay enabled and validate on click. Page headers, dialog footers, card footers, and toolbars each get at most one primary; independent settings cards may each own Save.

Components · 08 — tabs

One quiet segmented language

Section-specific tab shapes and heavy type One segmented control — 32px triggers, weight 500, hugs content

Track: 3px padding, hairline border, 4% wash. Active: background fill + hairline inset + e1. Roving tabindex + arrow keys follow the WAI-ARIA convention. Indicator movement 220ms.

Components · 09 — form controls

One input, one select, one switch, one checkbox

Help text sits here. Errors replace it in place — no layout jump.
Enter a valid email address, like ana@cabrillo.coffee.
Descriptions live here — never inside the trigger.
Mismatched heights and decorative input tint 36px · --cd-input-bg · primary-fill checks

Specialized fields — dates picked, times typed, no OS popovers

Schedule publish The trigger wears the input anatomy and opens the 280px calendar popover — keyboard grid, month/year fast-nav, Clear/Today, typed time row. Time-of-day fields are typed segments; the OS popup never appears.
Monday hours
to
retries
Enter a 3- or 6-digit hex like #0f172a.

Tags — chip strip + one add control · 18 tones

Coffee Wholesale Newsletter VIP ext Loyalty member

Tones run slate → rose (18; unknown falls back to slate). Every chip has its ✕; extension-managed tags carry the ext badge and aren't hand-removable. Adding goes through the standard select — never freetext typed into the strip.

Components · 10 — toggles & selection

Five controls, chosen by rule

Switch = applies immediately, never behind Save. Checkbox = saved with the form, or list multi-select. Radio = 2–5 choices in a form. Segmented = 2–5 instant views. More than five options → select or combobox. Checked state is always --cd-primary — never cedar, never green.

Labeled switch rows — the one composition

Public siteVisitors can reach your site right now.
Search engine indexingApplies immediately — no Save needed.
Customer accountsInstall cedros-login to enable accounts.

Icon toggles — aria-pressed tool states

Pressed = accent fill + hairline inset — a standalone segmented trigger. A working switch (0.55 opacity, wait cursor) must settle within ~1s.

Checkboxes — batched with Save · select-all indeterminate

Radio group — 2–5 choices in a form

Instant switches hidden behind a Save button one switch · labeled row · decision table
Components · 12 — cards, badges, chips

Structured surfaces, restrained depth

Default card

0.9rem 1rem padding · e1

Live
Header divider, body, optional footer. One subject per card.

Interactive

hover: −1px to e2

Draft
Fully clickable, not just the title.

Subtle well

4% wash, no shadow — secondary context.

Three jobs, three names

Published Needs review Payment failed Processing Archived Publish dot — content lists only

Badge = read-only status (pill, tinted). Chip = interactive/removable (filters, tags). Dot = compact publish state before titles in content lists — tokenized --cd-success, never #16a34a. One status treatment per table, never two.

Setup-locked row — one labeled doorway

StatusRoutineActions
Needs setup Analytics reporter

A record-specific setup blocker replaces its unavailable control and row menu with one outline CTA. Other actions disappear, blocked data mutes, and the row keeps the neutral table surface. Page-wide blockers use one Setup notice instead.

Choice tiles — radio semantics, ring selection, no checkmark

Selected = border ring + 2px ring wash at 24% — nothing else. The applied option wears a separate "Current" badge when applying is its own step. 2–6 options; beyond that it's a tile grid in a picker dialog.

Media tiles — the table's visual twin · same ring when selected

One button per tile (accessible name = the record's name); name truncates, meta stays muted. Gallery / grid / list views toggle in the toolbar — the list view is the standard table. Picker dialogs (680px) embed this same grid.

Components · 13 — dialogs & side panels

Decisions get focus without drama

One overlay (rgb(0 0 0 / .45), no blur), one panel with a ✕ close, three widths, one animation (in 240ms, out 160ms ease-in). Long content scrolls in the body between a sticky header and footer; a dirty form confirms discard before closing; dialogs never stack. List-context detail uses the side panel instead. .

Three widths — nothing else

420 · confirms, short forms
560 · standard forms, uploads
680 · pickers, review

Header: title lg/600 + optional description + ✕ (icon-sm ghost, disabled while an operation runs). Footer: ghost Cancel, then the verb button — destructive confirms focus Cancel. Esc cancels; backdrop-click closes only when the dialog holds no input; Enter submits single-input dialogs; type-to-confirm is reserved for the catastrophic tier. Max height min(85dvh, 44rem).

Long content — sticky header & footer, body scrolls

Side panel — list-context detail · 420 / 480 · 30% backdrop

Slides in 220ms; Esc or backdrop closes (dirty-form guard applies); the list keeps its scroll position. Panels never open panels — deeper work promotes to a page.

Components · 14 — feedback & states

Status without wallpaper

Transient outcomes use the host-owned bottom-right stack — . Alerts are status tints; empties have three contexts and two visual weights; progress is honest — determinate bars, step lists, one summary toast per batch, and never an indeterminate bar.

Inline alerts — status tints, --cd-warning-fg text

Import finished: 236 of 240 products added 4 were skipped — see what happened.
Cedros couldn't publish this page Your draft is safe. Try again — code pub_4t2c.

First-run empty — ambient two-tone glyph + copy + at most one action

No forms yet Create a form to start collecting responses from your site.

The glyph is 64-viewBox stroke art: base lines muted, one accent detail in --chart-5. It enters once (220ms rise/scale) then drifts on the 5s ambient float — the one decorative loop — and is simply present in reduced motion. Micro empty remains one muted line: "No links yet."

Progress — determinate only, tabular label

62% · 148 of 240

Unknown duration = spinner or skeleton. A bar parked at 90% is a lie, and lies are banned.

Step list — long work with live states

Validate file240 rows · 0 errors
Import products148 of 240 · you can leave this page — we'll keep going
Publish to site
Failure, expanded in place4 rows skipped — missing price. Fix the rows and retry; imported rows are safe.

Empty tables — first run vs filtered result

ThemeVersionStatus
No marketplace themes yet Submitted and published themes will appear here.
ThemeVersionStatus
No themes match your filters.

First run spans every column and lets the table frame own the border; filtered empty keeps columns and controls, but drops the icon and create action.

Toasts — one event, one transient outcome

Settings saved
Applied to your live site.
Import needs review
4 of 240 products were skipped.
Page wasn't published
Your draft is safe. Try again.

Bottom-right; six retained with the newest three collapsed; hover, focus, or touch intent expands the stack. Stable ids update retries. Every tone defaults to 4s; one optional verb action extends that to 8s; persistence is explicit. Focus never moves here. Extensions publish through the host SDK and never mount a toaster or ship toast CSS.

Upload — dropzone, drag state, file rows (filenames mono)

Drag images here or browse files · PNG, JPG, WebP up to 25MB
Drop to upload
spring-menu-hero.webp1.2 MB
cabrillo-logo.svg14 KB

Concurrent uploads finish with one summary toast, not one per file.

Loading — route skeletons mirror layout · working buttons

Skeletons appear within a frame of navigation; content arrives with a 160ms fade and zero layout shift. Text only past 1s, naming the work.

Route-level failure — shared boundary, never a blank pane

The shared error boundary (.cedros-admin-shell__section-error) — resets on navigation. Unknown routes get a block empty + "Go to dashboard".

Capability-locked — setup notice · view-only banner

Take payments on your site

Install cedros-pay to add products, subscriptions, and checkout.

You have view-only access Ask an owner to make changes. Controls stay visible, disabled with this reason.

One setup notice per page, maximum. Driven by requiredPermission / requiredExtensionId / disabledReason — the same reasons the disabled nav shows.

Autosave chip — six states, one chip per save scope

Unsaved changes Saving… Saved just now Offline — changes will sync Conflict — review changes Save failed — retry

Text crossfades 160ms; role="status", aria-live="polite". Failure escalates to the inline retry banner (Retry / Discard) beside the work — never only a toast; a conflict opens its review dialog. Explicit Save or autosave per page, never both.

The same leave guard runs everywhere a dirty surface can be abandoned — dialog ✕/Esc, side panel, Back breadcrumb, nav, tab close (beforeunload). Autosaving surfaces never ask; they save.

Components · 15 — furniture

The small parts, one way each

Tooltips are inverted and mandatory on icon-only controls; pagination is one quiet row; avatars come in three sizes; disclosures hide configuration, never status; stat cards count once and never loop.

Tooltip — inverted, 300ms hover / instant focus

Edit E Analytics hover or tab — required on every icon-only control

Keyboard hints

⌘K palette Esc close ↵ submit ⌘↵ submit textarea

Back breadcrumb — canonical parent, one level

Above the title; use a link when People has a route, a button only for ephemeral drill-in. Restore filters, page, and scroll; never pair it with a multi-item trail.

Pagination — one quiet row

Showing 1–25 of 214 …

Tables paginate; infinite scroll is for feeds only.

Avatars — 20 / 24 / 28 · stack −6px

MR DP SO MR DP SM +4

Disclosure — config only, never status

Advanced
Cache TTL, custom headers, and other expert knobs live here — closed by default, chevron rotates 160ms, state persists per user per surface.

Metric tiles — neutral, attention, unknown

Visitors12,418 ▲ 8% vs prior 7 days
Pending review3 Needs attention
Install latency— Not measured yet

Three tiles are the preferred overview set. 0 is data; — is unknown. Tone marks attention, not decoration. Eligible non-negative quantities count up for 500ms once; money, compliance values, reduced motion, and refreshes stay exact, and screen readers hear only the final value.

Links

Inline links are cedar, underline on hover; external links carry a 12px ↗; links inside table cells stay foreground with underline-on-hover so columns read calm.

Reorder — grip drags, keyboard moves, a 2px line marks the drop

Home
Menu · picked up, e2
Contact

Space/Enter picks up, ↑↓ moves, Esc cancels — announced politely ("Picked up Menu. Position 2 of 3."). Short lists may use the ↑/↓ button pair instead. Order persists automatically: "Changes save automatically."

Inbox & activity rows — unread is a dot + weight, never a tint

Form response · Contact"Do you offer wholesale pricing for cafés?" 2h ago
Cedra drafted a replyWaiting for your review before sending. 2h ago
Import finished236 of 240 products added. Yesterday

The quiet list for streams (form inbox, completed AI work) — hairline separators, accent hover, whole row activates, relative time with absolute on hover. Feeds are the one surface where infinite scroll is allowed; tables paginate.

Composition · 16 — dashboard contribution cards

Current state, direction, then one doorway

A polished extension contribution is an operational summary, not a row of inventory counters. It answers one recurring question in five seconds: what owns this space, whether anything is wrong, the primary value and window, the direction on a like-for-like comparison, and the one place to act. One–three metrics lead; one evidence region earns the rest of the space.

Five equal counts · repeated zeroes · no period · decorative chart 1–3 decisions · explicit window · honest delta · one evidence region · one action

Polished contribution specimen · illustrative data

Fleet Manager

Fleet health and control-plane activity.

Degraded
Managed sites 66 Right now
Availability▲ 0.4 pp
95.5% 63 of 66 · vs prior 30 days
Open incidents+11 open
22 63 opened · 52 resolved
Incident movement2-day buckets · Jul 21–Aug 19
840Jul 21Aug 5Aug 19 OpenedResolved
Incident movement in two-day buckets from July 21 through August 19
Bucket startOpenedResolved
July 2110
July 2321
July 2512
July 2731
July 2923
July 3142
August 234
August 453
August 645
August 864
August 1056
August 1275
August 1467
August 1685
August 1864

The status is threshold-backed, not decorative. Availability is a rate with its numerator/denominator and percentage-point comparison; open incidents are a stock with absolute movement; the chart shows flows opened and resolved. The production interaction gives pointer, touch, and Left/Right/Home/End access to the same values. This specimen also includes the required screen-reader data table even though the visible chart stays compact.

The visual chooser

SparklineDirection beside one KPI · 8–30 points
Line / stepStock, rate, duration · ≤2 series · ≤60 points
BarsFlow by bucket · 7–31 buckets
StackComposition · 2–4 stable categories
RowsNext exceptions · 3 maximum

No pie/donut, gauge, radar, dual axis, 3D, map, heatmap, or decorative area chart in a dashboard contribution. Specialized analysis belongs on the extension page.

Configuration boundary

Card-ownedUseful preset window; rarely 2–3 series toggles
Host-ownedReorder · show/hide · size, when the host exposes them
Detail pageCustom dates · export · thresholds · filters · investigation
Never a preferenceChart type · color · smoothing · axis · bucket density

Every view states its window and source freshness. Range changes are immediate view state: keep the previous plot, mark it busy, and swap without replaying first-paint motion. Refresh failures retain last-good data, identify the failed refresh, and become stale only after the declared maximum age.

Expression · 17 — charts

Series one is cedar. No gradients.

Hairline horizontal grid only; 2xs tabular sans labels; direct labels beat legends; tooltips are e2; one draw-in ≤500ms, then values crossfade; area fills are the series color at ≤12% opacity.

Decorative gradients and unrelated categorical hues series 1 = --cd-link · status tokens for semantic series · flat fills ≤12%

Line — direct label, last-dot only

2k 0 Visitors 12.4k

Bars — one hue, muted comparison

Empty chart = flat hairline at zero + one micro-empty line — never an unlabeled sample. Specialized viz (the visitor globe) is palette-exempt, but its chrome consumes tokens like everything else.

Expression · 18 — voice

A capable colleague, in sentence case

Plain, confident, warm, specific, calm. The user is "you"; the system is "Cedros". Delete is permanent · archive is recoverable · uninstall is for extensions · extension, never "plugin". Formulas: page subtitle = verb + object + the capability that matters (≤60ch); card description = one sentence of consequence; empty = what → working state → one action; errors = what happened → your stuff is safe → next step (+ mono ref).

WeakStandard
"Manage Your Pages Here!"Pages — Manage site pages with revisions, preview, and publish state.
"An error occurred while fetching data."Cedros couldn't load your pages. Try again — code pg_2f1c.
"Successfully Created New Page!"Page created — Undo
"Are you sure?"Delete this page? It's removed from your site and navigation. This can't be undone.
"Feature unavailable."Install cedros-pay to enable Products. + [View extensions]
"Loading data, please wait…"(skeleton) then, past 1s: "Importing 240 products…"
Expression · 19 — motion

Same tokens as the brand — felt, not watched

Durations 100 / 160 / 200 / 220 / 240 / 400 / 500 / 800ms, expo-out entrances, ease-in exits at ~70%. A table may reveal its rows once per browser document: rise 8px over 220ms with 45ms between rows. Every row takes part, and the turns are budgeted across the rows on screen rather than the full row count — otherwise a 500-row table spends its whole cascade on rows nobody can see and the visible ones arrive in a single flash. The cascade lands inside 500ms; rows below the fold share the last turn and settle before you can scroll to them. Back navigation, sort, filter, refetch, and route changes stay instant. Hover a card to replay its recipe.

Menu enter
180ms · scale .97 + y −4hover to replay
Dialog enter
240ms · scale .98 + y 8hover to replay
Toast rise (bottom-right)
400ms · y 100% + .98 · exit 200mshover to replay
Saved
Row update flash
800ms · info 22% → 0hover to replay
Order #2214Processing
Expression · 20 — access & reduced motion

Non-negotiables

Focus doctrine — visible when it helps

Style :focus-visible, never :focus. Clicking must not leave a ring; tabbing must always show one. Tab through this board—every control demonstrates the same quiet ring.

ring: 0 0 0 3px ring/14%, instant

The floor

WCAG 2.2 AA both modes · keyboard parity (roving tabindex in tabs/menus/tables) · targets ≥24px, ≥32px in dense rows · color never the only signal · 11 locales via catalogs, RTL-ready · prefers-reduced-motion collapses every duration to 1ms and stops the shimmer and spinner — this board obeys; turn it on and reload.

Integration · 21 — extensibility

Built to grow without changing character

Extension admin pages mirror the host class + ARIA contract on --cd-* tokens — no private component imports, no own dark mode, no hardcoded motion, sentence case throughout. The full contract is design-admin.md §11; registration mechanics live in docs/extension-authoring/12 + reference/admin-ui-patterns.md.

root = my-ext-admin cedros-data + data-extension-id bridge var(--cd-x, fallback) — never re-declare host tokens self-inject one id-guarded <style> host classes first · BEM namespace · scoped selectors motion via --motion-* · icons via manifest Lucide names host toaster only · never mount an extension queue 0 ≠ unknown · first-run empty ≠ filtered empty own dark class · prefers-color-scheme · --cedros-runtime-* in admin

Root, bridge, and injection — the whole recipe

<div class="loyalty-admin cedros-data"
     data-extension-id="cedros-loyalty">
  …your page, built from the §11 class contract…
</div>

/* consume host tokens; never re-emit them */
.loyalty-admin {
  --loyalty-accent: var(--cd-link, #2F6C7D);
}

/* self-inject once, id-guarded; ?inline must
   resolve nested @imports so every rule ships. */
import css from "./admin.css?inline";
const ID = "loyalty-admin-styles";
if (typeof document !== "undefined"
    && !document.getElementById(ID)) {
  const tag = document.createElement("style");
  tag.id = ID;
  tag.textContent = css;
  document.head.appendChild(tag);
}

An extension page renders native

Loyalty

Reward repeat customers with points and perks.

Members1,082
Points issued48.2k
Redemptions312
Connected to People New customers earn points automatically.

Every element above is a host pattern — nothing custom but the data. Dashboard cards ship the full state matrix (loading skeleton · micro empty · error status with retry · capability-locked with reason) or they're not done.

Reference · 22 — theme blueprint

Workbench at a glance

The complete brand signature in one scan. The order this page follows — identity → principles → foundations → composition → components → expression → integration → reference — is the narrative every Cedros theme overview uses, and this pair is the format's reference implementation.

Theme facetWorkbench expression
PromiseCalm structure for consequential work
AudienceOperators · owners · editors · support teams · extension authors
PersonalityNeutral · precise · quiet · durable · capable
Inspirationshadcn restraint, translated into Cedros' dense operational workspace
PaletteNeutral surfaces · four semantic outcomes · cedar links and data only
TypographyEight sans roles · sentence case · mono only for identifiers
Density13–14px body · 32px buttons · 36px fields · ~40px table rows
Shape7px derived controls · 8/12px concentric radii · pills only for compact state
DepthHairlines first · four restrained elevation levels · no colored glow
IconsLucide geometry · 16px · currentColor · label-supporting
ShellSidebar + content · spacing-led groups · quiet active fill
CompositionOne clear page title · one primary action · named container widths
ControlsOne primitive per job · aligned heights · visible keyboard focus
NavigationSegmented subviews · one-level Back breadcrumb · shallow menus
DataTabular quantities · explicit 0/— semantics · cedar series one
FeedbackInline conditions · host-owned bottom-right outcomes · honest progress
Empty statesOne-shot icon doorway · filtered row · quiet micro line
Motion100–400ms interaction · 500–800ms emphasis · table rows may reveal once, turns budgeted on-screen, ≤500ms · nothing decorative loops
VoiceA capable colleague: plain, specific, calm, sentence case
Modes & accessLight + dark parity · WCAG 2.2 AA · keyboard and reduced-motion first
ExtensibilityPortable BEM + ARIA contract on host-owned tokens and feedback

The two-file overview every theme ships

Markdown for agents

Normative tokens, anatomy, decision rules, states, accessibility, runtime availability, integration contracts, and acceptance checklists.

HTML for people

A cohesive theme story, realistic specimens, both modes, concise brand guidance, and a source-ready marketplace preview.

Marketplace boundary: today, a Cedros theme manifest's preview points to a root-relative static image (3:2 recommended). This HTML page is the canonical source preview for future ingestion; until that support ships, capture the cover composition at the top of this page as the image and do not invent an unsupported manifest key.

Page deleted