# TOKENS: RJ DTC Admin

Every custom property in `tokens.css` (kit v3), in file order, with its value and the note the kit gives it. Colour roles are shadcn-style bare HSL triples: write `hsl(var(--primary))`, or `hsl(var(--primary) / .12)` for a tint. The authored hex is in the note. Contrast for every on-colour pairing is on `guidelines/colors-pairings.card.html` and in docs › Foundations › Colour.


## shadcn core roles

| Token | Value | Note |
|---|---|---|
| `--background` | `0 0% 100%` | #FFFFFF  page surface (clean white canvas) |
| `--foreground` | `222 43% 10%` | #0F1626  body text, headings |
| `--card` | `0 0% 100%` | #FFFFFF |
| `--card-foreground` | `222 43% 10%` | #0F1626 |
| `--popover` | `0 0% 100%` | #FFFFFF  menus, sheets, dialogs, toasts |
| `--popover-foreground` | `222 43% 10%` | #0F1626 |
| `--primary` | `220 49% 11%` | #0E1729  RJ midnight navy (--rj-ink): every primary action |
| `--primary-foreground` | `60 17% 98%` | #FAFAF8 |
| `--primary-hover` | `223 42% 18%` | #1A2540  --rj-ink-hover |
| `--secondary` | `0 0% 100%` | #FFFFFF  outlined secondary button ground |
| `--secondary-foreground` | `220 49% 11%` | #0E1729 |
| `--muted` | `225 22% 96%` | #F4F5F8  table header, wells, hover |
| `--muted-foreground` | `221 17% 38%` | #505A70  quiet text (>= 5.9:1 on white) |
| `--accent` | `224 38% 94%` | #EBEEF6  selection, active filter |
| `--accent-foreground` | `220 49% 11%` | #0E1729 |
| `--destructive` | `353 53% 42%` | #A2323F |
| `--destructive-foreground` | `0 0% 100%` | #FFFFFF |
| `--border` | `220 20% 91%` | #E4E7ED  hairlines |
| `--input` | `219 14% 59%` | #8892A5  control borders: 3.1:1 on white (WCAG 1.4.11); was #C6CCD7 at 1.6:1 |
| `--input-hover` | `223 17% 45%` | #5F6A86  field / checkbox / select border on hover |
| `--secondary-border` | `219 14% 79%` | #C2C7D1  outlined secondary button edge (board 3, text-labelled so exempt from 3:1) |
| `--secondary-border-hover` | `220 10% 70%` | #ABB0BA |
| `--ring` | `221 45% 45%` | #3F5FA6  focus |
| `--radius` | `0.375rem` | 6px  (shadcn --radius) |

## status roles (each has a -foreground for text ON a solid fill)

| Token | Value | Note |
|---|---|---|
| `--success` | `158 51% 26%` | #21654C |
| `--success-foreground` | `0 0% 100%` |  |
| `--warning` | `36 79% 29%` | #83550F  also the STAGING badge |
| `--warning-foreground` | `0 0% 100%` |  |
| `--info` | `218 49% 39%` | #335794 |
| `--info-foreground` | `0 0% 100%` |  |
| `--neutral` | `222 13% 39%` | #575F72 |
| `--neutral-foreground` | `0 0% 100%` |  |
| `--draft` | `var(--info)` | Draft     = info blue |
| `--available` | `var(--success)` | Available = green |
| `--retired` | `var(--neutral)` | Retired   = slate |
| `--locked` | `var(--neutral)` | "locked" banner + lock chip |
| `--not-wired` | `var(--warning)` | "not wired" banner (feature exists, backend not connected) |
| `--status-soft-alpha` | `.12` |  |

## sidebar (shadcn sidebar block)

| Token | Value | Note |
|---|---|---|
| `--sidebar` | `220 49% 11%` | #0E1729 |
| `--sidebar-background` | `var(--sidebar)` | older shadcn name |
| `--sidebar-foreground` | `222 19% 82%` | #C9CEDA  --rj-mist |
| `--sidebar-primary` | `221 54% 75%` | #9FB4E2  active-item rail + icon tint |
| `--sidebar-primary-foreground` | `220 49% 11%` |  |
| `--sidebar-accent` | `222 43% 19%` | #1B2744 |
| `--sidebar-accent-foreground` | `60 17% 98%` | #FAFAF8 |
| `--sidebar-border` | `222 33% 22%` | #253049 |
| `--sidebar-ring` | `221 54% 75%` |  |
| `--sidebar-sheen` | `linear-gradient(180deg, #131D33 0%, #0E1729 52%, #0C1425 100%)` |  |
| `--sidebar-sheen-light` | `radial-gradient(closest-side, rgba(130,160,220,.11), transparent)` |  |

## charts (shadcn --chart-1..5)

| Token | Value | Note |
|---|---|---|
| `--chart-1` | `219 61% 47%` | #2F62C0  blue |
| `--chart-2` | `166 76% 36%` | #16A07F  teal |
| `--chart-3` | `20 70% 53%` | #DB6B35  coral |
| `--chart-4` | `229 62% 68%` | #7C8FE0  periwinkle |
| `--chart-5` | `334 58% 58%` | #D2588C  rose |
| `--chart-muted` | `221 25% 58%` | #7A8BB0  steel: previous period, reference lines, never a category |

## presentation (kit pages only, not product UI)

| Token | Value | Note |
|---|---|---|
| `--canvas` | `214 24% 94%` | #EDF0F4  page behind specimen cards |
| `--studio` | `radial-gradient(120% 90% at 50% 18%, #f7f8fa 0%, #e3e7ee 80%)` | garment photo ground |

## type

| Token | Value | Note |
|---|---|---|
| `--font-title` | `'Archivo', system-ui, sans-serif` | titles, buttons, menu, labels, table headers |
| `--font-voice` | `var(--font-title)` |  |
| `--font-ui` | `'IBM Plex Sans', system-ui, sans-serif` | reading text, tables, prices |
| `--font-code` | `'IBM Plex Mono', ui-monospace, monospace` | cloth codes, handles, versions, ids |
| `--font-stretch-title` | `100%` | Frank 2026-10-11: Archivo is NEVER set wide |
| `--title-w` | `600` |  |
| `--text-display` | `40px` |  |
| `--lh-display` | `1.05` |  |
| `--tr-display` | `-.02em` | kit page H1 only |
| `--text-page` | `26px` |  |
| `--lh-page` | `1.15` |  |
| `--tr-page` | `-.015em` | page title in the app |
| `--text-section` | `16px` |  |
| `--lh-section` | `1.25` |  |
| `--tr-section` | `-.005em` | sheet / dialog / panel title |
| `--text-card` | `13.5px` |  |
| `--lh-card` | `1.3` | card title, panel h3 |
| `--text-body` | `13px` |  |
| `--lh-body` | `1.45` | default UI text (Plex) |
| `--text-read` | `15px` |  |
| `--lh-read` | `1.55` | help drawer, long copy |
| `--text-label` | `13px` | form label (Archivo 600) |
| `--text-small` | `12px` | meta, table secondary |
| `--text-kpi` | `28px` |  |
| `--text-hero` | `30px` | KPI value / chart headline figure (raised by data-display) |
| `--text-step-m` | `17px` | phone compact step title (raised by wizard-stepper) |
| `--text-input-m` | `16px` | phone text fields: iOS never zooms at >= 16px |
| `--text-micro` | `11.5px` | chips, counts, th |
| `--text-code` | `12px` |  |
| `--text-btn` | `13.5px` |  |
| `--text-btn-sm` | `12.5px` |  |
| `--text-btn-lg` | `15px` |  |
| `--w-regular` | `400` |  |
| `--w-medium` | `500` |  |
| `--w-semibold` | `600` |  |
| `--w-bold` | `700` |  |

## spacing: 4px grid

| Token | Value | Note |
|---|---|---|
| `--s-0` | `0` |  |
| `--s-1` | `4px` |  |
| `--s-2` | `8px` |  |
| `--s-3` | `12px` |  |
| `--s-4` | `16px` |  |
| `--s-5` | `20px` |  |
| `--s-6` | `24px` |  |
| `--s-7` | `28px` |  |
| `--s-8` | `32px` |  |
| `--s-10` | `40px` |  |
| `--s-12` | `48px` |  |
| `--s-16` | `64px` |  |
| `--s-18` | `72px` |  |

## sizes

| Token | Value | Note |
|---|---|---|
| `--control-h` | `40px` | button, input, select (desktop) |
| `--control-h-sm` | `34px` | small button, row actions |
| `--control-h-m` | `44px` | phone minimum tap target |
| `--control-h-m-lg` | `48px` | phone primary / sheet buttons |
| `--row` | `44px` | table row |
| `--row-th` | `36px` | table header |
| `--topbar-h` | `56px` |  |
| `--sidebar-w` | `232px` |  |
| `--sheet-w` | `404px` |  |
| `--dialog-w` | `480px` |  |
| `--help-w` | `380px` |  |
| `--sheet-w-md` | `532px` | medium side sheet: detail views (raised by overlays) |
| `--sheet-w-lg` | `856px` | large side sheet: create key, long forms (raised by overlays) |
| `--row-compact` | `36px` | compact table density (raised by data-table) |
| `--control-h-xs` | `28px` | inline buttons inside photo slots, compact pills (raised by form-controls) |
| `--chip-h` | `22px` |  |
| `--chip-h-lg` | `26px` | header-size chip (raised by status-feedback) |
| `--pbar-h` | `52px` | phone top bar (raised by specimens) |
| `--tabbar-h` | `62px` | phone tab bar incl. padding (raised by specimens) |
| `--content-max` | `1280px` | page content stops growing past this (raised by specimens; build lane) |

## radius

| Token | Value | Note |
|---|---|---|
| `--r-chip` | `4px` | square chips |
| `--r-control` | `6px` | buttons, inputs, menu items, filter chips |
| `--r-card` | `8px` | cards, table wrap, popovers (= radius + 2) |
| `--r-frame` | `15px` | panels, app frame, specimen cards |
| `--r-pill` | `999px` | switch, avatar |
| `--r-media` | `4px` | photos inside cards |
| `--r-card-inner` | `calc(var(--r-card) - 1px)` | photo corners inside a 1px-bordered card (raised by cards-gallery) |

## elevation

| Token | Value | Note |
|---|---|---|
| `--e-0` | `none` |  |
| `--e-1` | `0 1px 2px rgba(14,23,41,.04)` | card |
| `--e-btn` | `0 1px 2px rgba(14,23,41,.20)` | primary button |
| `--e-btn-2` | `0 1px 1px rgba(14,23,41,.05)` | secondary button |
| `--e-frame` | `0 0 0 1px rgba(14,23,41,.05), 0 16px 36px -24px rgba(14,23,41,.20)` | app frame |
| `--e-pop` | `0 12px 32px -10px rgba(14,23,41,.25)` | dropdown, combobox |
| `--e-toast` | `0 12px 28px -14px rgba(14,23,41,.35)` |  |
| `--e-sheet` | `-24px 0 60px -20px rgba(14,23,41,.35)` | side sheet, help drawer |
| `--e-dialog` | `0 24px 64px -20px rgba(14,23,41,.40)` |  |
| `--e-phone-sheet` | `0 -20px 50px -20px rgba(14,23,41,.50)` | phone bottom sheet |
| `--e-card-hover` | `0 10px 24px -14px rgba(14,23,41,.28)` | lifted card / kanban card (raised by cards-gallery + data-display) |
| `--sticky-edge` | `hsl(var(--foreground) / .09)` | frozen-column edge shade (raised by data-table) |
| `--scrim` | `rgba(10,14,24,.38)` |  |
| `--focus-ring` | `0 0 0 1px hsl(var(--ring)), 0 0 0 4px hsl(var(--ring) / .14)` |  |

## motion: crisp set (Satin Lapel), approved as-is

| Token | Value | Note |
|---|---|---|
| `--ease-standard` | `cubic-bezier(.2,0,0,1)` |  |
| `--ease-in` | `cubic-bezier(.22,1,.36,1)` | entering: soft landing |
| `--ease-out` | `cubic-bezier(.4,0,1,1)` | leaving |
| `--motion-hover` | `120ms var(--ease-standard)` |  |
| `--motion-press` | `80ms var(--ease-standard)` |  |
| `--motion-focus` | `140ms var(--ease-standard)` |  |
| `--motion-pop-in` | `160ms var(--ease-in)` |  |
| `--motion-pop-out` | `110ms var(--ease-out)` |  |
| `--motion-sheet-in` | `260ms var(--ease-in)` |  |
| `--motion-sheet-out` | `180ms var(--ease-out)` |  |
| `--motion-toast-in` | `200ms var(--ease-in)` |  |
| `--motion-toast-out` | `140ms var(--ease-out)` |  |
| `--toast-dwell` | `2600ms` |  |
| `--toast-dwell-undo` | `5200ms` | an Undo toast stays twice as long (raised by status-feedback) |
| `--toast-gap` | `8px` | gap between stacked toasts (raised by status-feedback) |
| `--tooltip-delay` | `400ms` | hover delay before a tooltip; keyboard focus shows it at once (raised by overlays + page-help) |
| `--hovercard-delay` | `500ms` | (raised by overlays) |
| `--motion-skeleton` | `1.6s var(--ease-standard) infinite alternate` | skeleton pulse (raised by data-table + cards-gallery) |
| `--press-shift` | `1px` | button settles 1px on press |
| `--pop-shift` | `-4px` | dropdown drops 4px |
| `--toast-shift` | `8px` | toast rises 8px |
| `--lift-shift` | `-2px` | card hover lift (raised by cards-gallery) |

## stacking (raised by overlays: a guard dialog sits above an open sheet)

| Token | Value | Note |
|---|---|---|
| `--z-sticky` | `3` |  |
| `--z-pop` | `20` |  |
| `--z-tip` | `25` |  |
| `--z-scrim` | `30` |  |
| `--z-sheet` | `31` |  |
| `--z-guard-scrim` | `40` |  |
| `--z-guard` | `41` |  |
| `--z-toast` | `50` |  |

## kit v2 page primitives (Round 4 promotion, see KIT-CHANGELOG.md § v2)

| Token | Value | Note |
|---|---|---|
| `--tab-h` | `40px` | page / section tab strip (.tabs) |
| `--tab-h-m` | `44px` | phone tab strip, thumb height |
| `--kv-label` | `120px` | key/value aside label column (.k-kv) |
| `--kv-label-m` | `104px` |  |
| `--li-min-h` | `72px` | phone list row without a thumbnail (.k-li) |
| `--actbar-blur` | `8px` | phone action bar / phone save bar glass |

## kit v3 · icon sizes (Lucide on a 24px grid, 1.75 stroke; see KIT-CHANGELOG.md § v3)

| Token | Value | Note |
|---|---|---|
| `--icon-12` | `12px` | surface literal (svg width=12) |
| `--icon-13` | `13px` | surface literal (svg width=13) |
| `--icon-14` | `14px` | contract size inside chips, menus and small buttons |
| `--icon-15` | `15px` | surface literal (svg width=15), the most used off-contract size |
| `--icon-16` | `16px` | contract default |
| `--icon-18` | `18px` | surface literal (svg width=18) |
| `--icon-19` | `19px` | surface literal (svg width=19) |
| `--icon-20` | `20px` | contract size in empty states |
| `--icon-22` | `22px` | surface literal (svg width=22) |
| `--icon-28` | `28px` | surface literal (svg width=28) |

## kit v3 · type literals (off the main scale; named so every use can be found)

| Token | Value | Note |
|---|---|---|
| `--text-8` | `8px` | initials in the empty garment placeholder (.dt-ph.none) |
| `--text-8-5` | `8.5px` | initials in the empty garment placeholder (.dt-ph.none) |
| `--text-9` | `9px` | initials in the large empty garment placeholder (.dt-ph.lg.none) |
| `--text-9-5` | `9.5px` | small mono badge |
| `--text-10` | `10px` | tab bar badge, tiny avatar |
| `--text-10-5` | `10.5px` | STAGING / environment badge, tab bar label, filter counts |
| `--text-11` | `11px` | kbd, chip count, step mark |
| `--text-14` | `14px` | phone lede, phone list title |
| `--text-18` | `18px` | phone sheet and ticket title |
| `--text-19` | `19px` | surface-only literal |
| `--text-20` | `20px` | ticket head, mini error page title |
| `--text-22` | `22px` | stacked KPI value, error page title |
| `--text-24` | `24px` | phone page title |
| `--text-44` | `44px` | surface-only literal |
| `--text-52` | `52px` | surface-only literal |

## kit v3 · motion literals (animations and hand-off delays; reduced motion is handled per rule)

| Token | Value | Note |
|---|---|---|
| `--ease-enter` | `var(--ease-in)` | clearer name: the ENTERING curve (decelerates into place). --ease-in stays for compatibility |
| `--ease-exit` | `var(--ease-out)` | clearer name: the LEAVING curve (accelerates away). --ease-out stays for compatibility |
| `--ease-linear` | `linear` | spinners and rotations only |
| `--ease-blink` | `steps(1)` | text caret blink |
| `--motion-spin` | `.8s` | spinner turn |
| `--motion-spin-reduced` | `2.4s` | spinner turn under prefers-reduced-motion |
| `--motion-flash` | `900ms` | row / card "just changed" flash |
| `--motion-shake` | `360ms` | shake animation on the surfaces (pg-shake) |
| `--motion-rotate` | `1.2s` | rotation animation on the surfaces (wb-rot) |
| `--motion-indeterminate` | `1.5s` | indeterminate progress bar sweep |
| `--motion-loadbar` | `1.4s` | top load bar sweep |
| `--motion-caret` | `1.1s` | command palette caret blink |
| `--motion-handoff` | `.2s` | visibility hand-off after a menu, tooltip or dialog closes |
| `--motion-handoff-sheet` | `.3s` | visibility hand-off after a side sheet closes |
| `--skeleton-stagger` | `.12s` | delay step between skeleton rows |

## kit v3 · glass blur

| Token | Value | Note |
|---|---|---|
| `--blur-glass` | `10px` | desktop top bar glass |
| `--blur-soft` | `6px` | glass blur written on the surfaces |

## kit v3 · selection rails and row focus (box-shadow)

| Token | Value | Note |
|---|---|---|
| `--e-rail` | `inset 2px 0 0 hsl(var(--primary))` | 2px primary rail: selected row (.fc-cp-tbl) |
| `--e-rail-warning` | `inset 2px 0 0 hsl(var(--warning))` | 2px warning rail (surfaces) |
| `--e-rail-strong` | `inset 3px 0 0 hsl(var(--primary))` | 3px primary rail (surfaces) |
| `--e-rail-strong-info` | `inset 3px 0 0 hsl(var(--info))` |  |
| `--e-rail-strong-warning` | `inset 3px 0 0 hsl(var(--warning))` | stale card |
| `--e-rail-strong-destructive` | `inset 3px 0 0 hsl(var(--destructive))` | blocked card |
| `--e-row-focus` | `inset 0 1px 0 hsl(var(--ring)),inset 0 -1px 0 hsl(var(--ring))` | keyboard-focused table row cell |
| `--e-row-focus-first` | `inset 2px 0 0 hsl(var(--ring)),inset 0 1px 0 hsl(var(--ring)),inset 0 -1px 0 hsl(var(--ring))` | its first cell |

## kit v3 · sidebar light and brand mark (exact board values, sidebar only, never on buttons)

| Token | Value | Note |
|---|---|---|
| `--e-sidebar-edge` | `inset -1px 0 0 rgba(201,206,218,.07)` | the sidebar's inner right edge |
| `--sidebar-item-on` | `rgba(255,255,255,.07)` | active menu item ground |
| `--e-sidebar-item-on` | `inset 0 0 0 1px rgba(201,206,218,.09),0 6px 18px -12px rgba(110,140,210,.22)` | active menu item edge + soft glow |
| `--sidebar-item-on-icon` | `#B7C7EA` | active menu item icon |
| `--brand-mark` | `linear-gradient(145deg,#EEF1F8,#CBD5EA)` | RJ brand mark tile |
| `--brand-mark-foreground` | `#0E1729` | RJ initials on the brand mark |
| `--e-brand-mark` | `0 0 12px -4px rgba(150,175,225,.22)` | brand mark glow |

## viewports (dedicated compositions, never a responsive collapse)

| Token | Value | Note |
|---|---|---|
| `--vp-desktop` | `1440px` |  |
| `--vp-phone` | `390px` |  |

## Reduced motion

Under `prefers-reduced-motion: reduce` every `--motion-*` transition token becomes `1ms linear`, the shift tokens become `0px`, the tooltip and hover-card delays `0ms`, and `--motion-skeleton` `none` (see `tokens/motion.css`).
