[Overview](https://rickylabs.github.io/netscript/design-system/)[Guidelines](https://rickylabs.github.io/netscript/design-system/guidelines/)[Token contract](https://rickylabs.github.io/netscript/design-system/token-contract/)[Docs kit](https://rickylabs.github.io/netscript/design-system/docs-kit/)[Theme builder](https://rickylabs.github.io/netscript/create/)[Components](https://rickylabs.github.io/netscript/design-system/components/)[Create your own theme](https://rickylabs.github.io/netscript/design-system/create-your-own-theme/)[Studio](https://rickylabs.github.io/netscript/design-system/themes/studio/)[Tonal](https://rickylabs.github.io/netscript/design-system/themes/tonal/)[Bloom](https://rickylabs.github.io/netscript/design-system/themes/bloom/)[Cupertino](https://rickylabs.github.io/netscript/design-system/themes/cupertino/)[Liquid](https://rickylabs.github.io/netscript/design-system/themes/liquid/)[Fluent](https://rickylabs.github.io/netscript/design-system/themes/fluent/)[Brutal](https://rickylabs.github.io/netscript/design-system/themes/brutal/)[Filigrane](https://rickylabs.github.io/netscript/design-system/themes/filigrane/)[Terminal](https://rickylabs.github.io/netscript/design-system/themes/terminal/)[Pixel](https://rickylabs.github.io/netscript/design-system/themes/pixel/)[Tactile](https://rickylabs.github.io/netscript/design-system/themes/tactile/)

# Studio

Seven product flavors that share one component anatomy and differ in ground, shape, type, density and component variants, built on shadcn/ui and Linear conventions. Utility is the NetScript default.

[DESIGN.md](https://raw.githubusercontent.com/rickylabs/netscript/main/docs/design-system/themes/studio/DESIGN.md) [SKILL.md](https://raw.githubusercontent.com/rickylabs/netscript/main/docs/design-system/themes/studio/SKILL.md)

On this page

- [Studio flavors](#design-specimens)
- [Theme values](#design-values)
- [Values: Colors](#values-colors)
- [Values: Typography](#values-typography)
- [Values: Radii](#values-rounded)
- [Values: Spacing](#values-spacing)
- [Values: Component recipes](#values-components)
- [Overview](#overview)
- [Colors](#colors)
- [Typography](#typography)
- [Layout](#layout)
- [Elevation & Depth](#elevation-depth)
- [Shapes](#shapes)
- [Components](#components)
- [Do's and Don'ts](#dos-and-donts)
- [Flavors](#flavors)
- [Utility (neutral-ink) · NetScript default · Neutral × Ink, Compact](#utility-neutral-ink-netscript-default-neutral-ink-compact)
- [Cloud (slate-blue) · Slate × Blue, Comfortable](#cloud-slate-blue-slate-blue-comfortable)
- [Workshop (sand-orange) · Sand × Orange, Chunky](#workshop-sand-orange-sand-orange-chunky)
- [Playful (mauve-violet) · Mauve × Violet, Chunky](#playful-mauve-violet-mauve-violet-chunky)
- [Ledger (ledger) · Slate × Indigo, Dense](#ledger-ledger-slate-indigo-dense)
- [Atelier (atelier) · Sand × Tomato, Airy](#atelier-atelier-sand-tomato-airy)
- [Signal (signal) · Neutral × Lime, Dense](#signal-signal-neutral-lime-dense)
- [Iconography & Imagery](#iconography-imagery)
- [Motion & States](#motion-states)
- [Accessibility](#accessibility)
- [NetScript Mapping](#netscript-mapping)
- [Sources](#sources)

## Studio flavors

### Studio · Utility · NetScript default

![Studio · Utility Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-utility--light.webp)

*Light*

![Studio · Utility Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-utility--dark.webp)

*Dark*

### Studio · Cloud

![Studio · Cloud Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-cloud--light.webp)

*Light*

![Studio · Cloud Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-cloud--dark.webp)

*Dark*

### Studio · Workshop

![Studio · Workshop Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-workshop--light.webp)

*Light*

![Studio · Workshop Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-workshop--dark.webp)

*Dark*

### Studio · Playful

![Studio · Playful Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-playful--light.webp)

*Light*

![Studio · Playful Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-playful--dark.webp)

*Dark*

### Studio · Ledger

![Studio · Ledger Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-ledger--light.webp)

*Light*

![Studio · Ledger Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-ledger--dark.webp)

*Dark*

### Studio · Atelier

![Studio · Atelier Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-atelier--light.webp)

*Light*

![Studio · Atelier Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-atelier--dark.webp)

*Dark*

### Studio · Signal

![Studio · Signal Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-signal--light.webp)

*Light*

![Studio · Signal Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/studio-signal--dark.webp)

*Dark*

Specification values · alpha

## Theme values

### Values: Colors

**Studio · Colors · Utility flavor**

| Property | Value |
| --- | --- |
| `bg` | `#ffffff` |
| `bg-dark` | `#18181a` |
| `surface` | `#f6f6f6` |
| `surface-dark` | `#1e1e21` |
| `card` | `#ffffff` |
| `card-dark` | `#18181a` |
| `surface-raised` | `#ffffff` |
| `surface-raised-dark` | `#222225` |
| `muted` | `#f0f0f0` |
| `muted-dark` | `#26262a` |
| `selected` | `#f0f0f0` |
| `selected-dark` | `#2a2a2a` |
| `fg` | `#202020` |
| `fg-dark` | `#eeeeee` |
| `muted-fg` | `#646464` |
| `muted-fg-dark` | `#b4b4b4` |
| `border` | `#d9d9d9` |
| `border-dark` | `#3a3a3a` |
| `border-subtle` | `#e4e4e4` |
| `border-subtle-dark` | `#2c2c30` |
| `input-border` | `#838383` |
| `input-border-dark` | `#7b7b7b` |
| `ring` | `#202020` |
| `ring-dark` | `#7b7b7b` |
| `primary` | `#202020` |
| `primary-dark` | `#313131` |
| `primary-hover` | `#3f3f3f` |
| `primary-hover-dark` | `#3a3a3a` |
| `primary-fg` | `#fcfcfc` |
| `primary-fg-dark` | `#eeeeee` |
| `success-text` | `#2a7e3b` |
| `success-text-dark` | `#71d083` |
| `warning-subtle` | `#fff7c2` |
| `warning-subtle-dark` | `#302008` |
| `warning-text` | `#4f3422` |
| `warning-text-dark` | `#ffca16` |
| `destructive` | `#e5484d` |
| `destructive-text` | `#641723` |
| `destructive-text-dark` | `#ff9592` |
| `info-text` | `#113264` |
| `info-text-dark` | `#70b8ff` |
| `studio-signal-brand` | `#da291c` |
| `studio-signal-brand-dark` | `#e5332a` |
| `studio-signal-marker` | `#202020` |
| `studio-signal-marker-dark` | `#eeeeee` |
| `studio-signal-underline` | `#bbbbbb` |
| `studio-signal-underline-dark` | `#606060` |
| `studio-input-border` | `#8d8d8d` |
| `studio-input-border-dark` | `#6e6e6e` |
| `studio-primary-bg` | `#202020` |
| `studio-primary-bg-dark` | `#313131` |
| `studio-primary-fg` | `#fcfcfc` |
| `studio-primary-fg-dark` | `#eeeeee` |
| `studio-primary-stroke` | `#202020` |
| `studio-primary-stroke-dark` | `#7b7b7b` |
| `studio-topbar-rule` | `#e0e0e0` |
| `studio-topbar-rule-dark` | `#313131` |
| `studio-table-head-rule` | `#e0e0e0` |
| `studio-table-head-rule-dark` | `#313131` |
| `studio-table-row-rule` | `#f0f0f0` |
| `studio-table-row-rule-dark` | `#2a2a2a` |
| `studio-card-border` | `#e0e0e0` |
| `studio-card-border-dark` | `#313131` |
| `studio-code-scroll-thumb` | `#838383` |
| `studio-code-scroll-thumb-dark` | `#7b7b7b` |
| `studio-topbar-bg` | `#ffffff` |
| `studio-topbar-bg-dark` | `#18181a` |

### Values: Typography

**Studio · Typography · Utility flavor**

| Property | Value |
| --- | --- |
| `title.fontFamily` | `Host Grotesk` |
| `title.fontSize` | `48px` |
| `title.fontWeight` | `500` |
| `title.lineHeight` | `52px` |
| `title.letterSpacing` | `-0.025em` |
| `heading.fontFamily` | `Host Grotesk` |
| `heading.fontSize` | `15px` |
| `heading.fontWeight` | `600` |
| `heading.lineHeight` | `22px` |
| `heading.letterSpacing` | `-0.2px` |
| `kpi.fontFamily` | `Host Grotesk` |
| `kpi.fontSize` | `40px` |
| `kpi.fontWeight` | `400` |
| `kpi.lineHeight` | `44px` |
| `kpi.letterSpacing` | `-0.025em` |
| `kpi.fontFeature` | `"tnum" 1, "lnum" 1` |
| `body.fontFamily` | `Host Grotesk` |
| `body.fontSize` | `14px` |
| `body.fontWeight` | `400` |
| `body.lineHeight` | `22px` |
| `strong.fontFamily` | `Host Grotesk` |
| `strong.fontSize` | `14px` |
| `strong.fontWeight` | `500` |
| `strong.lineHeight` | `22px` |
| `small.fontFamily` | `Host Grotesk` |
| `small.fontSize` | `13px` |
| `small.fontWeight` | `400` |
| `small.lineHeight` | `18px` |
| `label.fontFamily` | `Fragment Mono` |
| `label.fontSize` | `11px` |
| `label.fontWeight` | `400` |
| `label.lineHeight` | `16px` |
| `label.letterSpacing` | `0.6px` |
| `data.fontFamily` | `Fragment Mono` |
| `data.fontSize` | `13px` |
| `data.fontWeight` | `400` |
| `data.lineHeight` | `18px` |
| `data.fontFeature` | `"tnum" 1` |
| `prose-body.fontFamily` | `Host Grotesk` |
| `prose-body.fontSize` | `16px` |
| `prose-body.fontWeight` | `400` |
| `prose-body.lineHeight` | `26px` |
| `prose-lede.fontFamily` | `Host Grotesk` |
| `prose-lede.fontSize` | `19px` |
| `prose-lede.fontWeight` | `400` |
| `prose-lede.lineHeight` | `30px` |
| `prose-h1-sm.fontFamily` | `Host Grotesk` |
| `prose-h1-sm.fontSize` | `36px` |
| `prose-h1-sm.fontWeight` | `500` |
| `prose-h1-sm.lineHeight` | `40px` |
| `prose-h2.fontFamily` | `Host Grotesk` |
| `prose-h2.fontSize` | `26px` |
| `prose-h2.fontWeight` | `500` |
| `prose-h2.lineHeight` | `34px` |
| `prose-h2.letterSpacing` | `-0.4px` |
| `prose-h3.fontFamily` | `Host Grotesk` |
| `prose-h3.fontSize` | `19px` |
| `prose-h3.fontWeight` | `500` |
| `prose-h3.lineHeight` | `28px` |
| `prose-h3.letterSpacing` | `-0.2px` |
| `prose-h4.fontFamily` | `Host Grotesk` |
| `prose-h4.fontSize` | `16px` |
| `prose-h4.fontWeight` | `500` |
| `prose-h4.lineHeight` | `24px` |
| `prose-code.fontFamily` | `Fragment Mono` |
| `prose-code.fontSize` | `13px` |
| `prose-code.fontWeight` | `400` |
| `prose-code.lineHeight` | `22px` |

### Values: Radii

**Studio · Radii · Utility flavor**

| Property | Value |
| --- | --- |
| `control` | `0px` |
| `input` | `0px` |
| `card` | `0px` |
| `badge` | `2px` |
| `checkbox` | `2px` |
| `full` | `9999px` |

### Values: Spacing

**Studio · Spacing · Utility flavor**

| Property | Value |
| --- | --- |
| `control-height` | `32px` |
| `control-height-sm` | `28px` |
| `control-padding-x` | `12px` |
| `inline-gap` | `8px` |
| `section-gap` | `16px` |
| `card-padding` | `16px` |
| `page-padding-x` | `24px` |
| `table-row-height` | `44px` |
| `topbar-height` | `48px` |
| `badge-height` | `20px` |
| `kpi-gap` | `24px` |
| `marker-size` | `6px` |
| `marker-gap` | `8px` |
| `selected-bar-width` | `2px` |
| `focus-ring-width` | `2px` |
| `focus-ring-offset` | `2px` |
| `icon-stroke` | `1.5px` |
| `prose-measure` | `544px` |
| `prose-wide` | `720px` |

### Values: Component recipes

**Studio · Component recipes · Utility flavor**

| Property | Value |
| --- | --- |
| `button-primary.backgroundColor` | `{colors.studio-primary-bg}` |
| `button-primary.textColor` | `{colors.studio-primary-fg}` |
| `button-primary.typography` | `{typography.strong}` |
| `button-primary.rounded` | `{rounded.control}` |
| `button-primary.height` | `32px` |
| `button-primary.padding` | `0 12px` |
| `button-primary-dark.backgroundColor` | `{colors.studio-primary-bg-dark}` |
| `button-primary-dark.textColor` | `{colors.studio-primary-fg-dark}` |
| `button-primary-dark.rounded` | `{rounded.control}` |
| `button-primary-dark.height` | `32px` |
| `button-secondary.backgroundColor` | `{colors.card}` |
| `button-secondary.textColor` | `{colors.fg}` |
| `button-secondary.typography` | `{typography.strong}` |
| `button-secondary.rounded` | `{rounded.control}` |
| `button-secondary.height` | `32px` |
| `input.backgroundColor` | `{colors.card}` |
| `input.textColor` | `{colors.fg}` |
| `input.typography` | `{typography.body}` |
| `input.rounded` | `{rounded.input}` |
| `input.height` | `32px` |
| `input.padding` | `0 12px` |
| `input-dark.backgroundColor` | `{colors.card-dark}` |
| `input-dark.textColor` | `{colors.fg-dark}` |
| `input-dark.rounded` | `{rounded.input}` |
| `input-dark.height` | `32px` |
| `nav-item-active.textColor` | `{colors.fg}` |
| `nav-item-active.typography` | `{typography.strong}` |
| `nav-item-active.height` | `30px` |
| `nav-item-active.padding` | `6px 10px` |
| `location-marker.backgroundColor` | `{colors.studio-signal-marker}` |
| `location-marker.rounded` | `{rounded.control}` |
| `location-marker.width` | `{spacing.marker-size}` |
| `location-marker.height` | `{spacing.marker-size}` |
| `location-marker-dark.backgroundColor` | `{colors.studio-signal-marker-dark}` |
| `location-marker-dark.rounded` | `{rounded.control}` |
| `location-marker-dark.width` | `{spacing.marker-size}` |
| `location-marker-dark.height` | `{spacing.marker-size}` |
| `eyebrow.textColor` | `{colors.muted-fg}` |
| `eyebrow.typography` | `{typography.label}` |
| `link.textColor` | `{colors.fg}` |
| `link.typography` | `{typography.strong}` |
| `table-header.textColor` | `{colors.muted-fg}` |
| `table-header.typography` | `{typography.label}` |
| `table-header.height` | `32px` |
| `table-row-selected.backgroundColor` | `{colors.selected}` |
| `table-row-selected.textColor` | `{colors.fg}` |
| `table-row-selected.typography` | `{typography.small}` |
| `table-row-selected.height` | `44px` |
| `table-row-selected-dark.backgroundColor` | `{colors.selected-dark}` |
| `table-row-selected-dark.textColor` | `{colors.fg-dark}` |
| `table-row-selected-dark.typography` | `{typography.small}` |
| `table-row-selected-dark.height` | `44px` |
| `file-path-chip.backgroundColor` | `{colors.surface}` |
| `file-path-chip.textColor` | `{colors.fg}` |
| `file-path-chip.typography` | `{typography.data}` |
| `file-path-chip.rounded` | `{rounded.badge}` |
| `badge-success.textColor` | `{colors.success-text}` |
| `badge-success.typography` | `{typography.label}` |
| `badge-success.rounded` | `{rounded.badge}` |
| `badge-success.height` | `20px` |
| `badge-success.padding` | `0 6px` |
| `kpi-value.textColor` | `{colors.fg}` |
| `kpi-value.typography` | `{typography.kpi}` |
| `notice-warning.backgroundColor` | `{colors.warning-subtle}` |
| `notice-warning.textColor` | `{colors.fg}` |
| `notice-warning.rounded` | `{rounded.card}` |
| `notice-warning.padding` | `12px 14px` |
| `topbar.backgroundColor` | `{colors.studio-topbar-bg}` |
| `topbar.textColor` | `{colors.fg}` |
| `topbar.height` | `48px` |

Read YAML values and notes

```text
version: alpha
name: Studio
description: Seven product flavors that share one component anatomy and differ in ground, shape, type, density and component variants, built on shadcn/ui and Linear conventions. Utility is the NetScript default.
colors:
  # Flavor Utility = Theme Studio × Base gray Neutral × Base accent Ink × Density Compact, the
  # NetScript default. Light value, then the Dark twin (`-dark`). "measured" = sampled on rendered
  # pixels; other values are resolved Figma variables.
  bg: '#ffffff'
  bg-dark: '#18181a'
  surface: '#f6f6f6'
  surface-dark: '#1e1e21'
  card: '#ffffff'
  card-dark: '#18181a'
  surface-raised: '#ffffff'
  surface-raised-dark: '#222225'
  muted: '#f0f0f0'
  muted-dark: '#26262a'
  selected: '#f0f0f0' # selected-row fill, measured
  selected-dark: '#2a2a2a'
  fg: '#202020'
  fg-dark: '#eeeeee'
  muted-fg: '#646464' # text/subtle resolves to the same value
  muted-fg-dark: '#b4b4b4'
  border: '#d9d9d9' # gray 6: soft borders on toolbar buttons, kbd and chips, measured
  border-dark: '#3a3a3a'
  border-subtle: '#e4e4e4' # resolved variable; not sampled on pixels
  border-subtle-dark: '#2c2c30'
  input-border: '#838383' # core role (gray 10); Utility fields read studio-input-border
  input-border-dark: '#7b7b7b'
  ring: '#202020' # 2px ink focus ring with a 2px gap, measured
  ring-dark: '#7b7b7b'
  primary: '#202020'
  primary-dark: '#313131'
  primary-hover: '#3f3f3f'
  primary-hover-dark: '#3a3a3a'
  primary-fg: '#fcfcfc'
  primary-fg-dark: '#eeeeee'
  success-text: '#2a7e3b'
  success-text-dark: '#71d083'
  warning-subtle: '#fff7c2'
  warning-subtle-dark: '#302008'
  warning-text: '#4f3422'
  warning-text-dark: '#ffca16'
  destructive: '#e5484d' # error boundary; with destructive-text, the only red besides the logo
  destructive-text: '#641723'
  destructive-text-dark: '#ff9592'
  info-text: '#113264'
  info-text-dark: '#70b8ff'
  studio-signal-brand: '#da291c' # Swiss red, logo square only, measured
  studio-signal-brand-dark: '#e5332a'
  studio-signal-marker: '#202020' # 6px location square and 2px selected-row bar, measured
  studio-signal-marker-dark: '#eeeeee'
  studio-signal-underline: '#bbbbbb' # link underline, gray 8
  studio-signal-underline-dark: '#606060'
  studio-input-border: '#8d8d8d' # gray 9: field, checkbox and switch boundaries, measured (3.32:1)
  studio-input-border-dark: '#6e6e6e' # measured, 3.48:1 on #18181a
  studio-primary-bg: '#202020'
  studio-primary-bg-dark: '#313131'
  studio-primary-fg: '#fcfcfc'
  studio-primary-fg-dark: '#eeeeee'
  studio-primary-stroke: '#202020'
  studio-primary-stroke-dark: '#7b7b7b' # dark primary keyline
  studio-topbar-rule: '#e0e0e0' # gray 5 structural hairline, 1px, measured
  studio-topbar-rule-dark: '#313131'
  studio-table-head-rule: '#e0e0e0' # measured
  studio-table-head-rule-dark: '#313131'
  studio-table-row-rule: '#f0f0f0' # quiet row rule, measured
  studio-table-row-rule-dark: '#2a2a2a'
  studio-card-border: '#e0e0e0' # 1px top hairline on cards and KPI columns, measured
  studio-card-border-dark: '#313131'
  studio-code-scroll-thumb: '#838383' # docs code-block scrollbar thumb, gray 10: 3.51:1 on #f6f6f6
  studio-code-scroll-thumb-dark: '#7b7b7b' # 3.93:1 on #1e1e21
  studio-topbar-bg: '#ffffff'
  studio-topbar-bg-dark: '#18181a'
typography:
  title: {
    fontFamily: Host Grotesk,
    fontSize: 48px,
    fontWeight: 500,
    lineHeight: 52px,
    letterSpacing: -0.025em,
  }
  heading: {
    fontFamily: Host Grotesk,
    fontSize: 15px,
    fontWeight: 600,
    lineHeight: 22px,
    letterSpacing: -0.2px,
  }
  kpi: {
    fontFamily: Host Grotesk,
    fontSize: 40px,
    fontWeight: 400,
    lineHeight: 44px,
    letterSpacing: -0.025em,
    fontFeature: '"tnum" 1, "lnum" 1',
  }
  body: { fontFamily: Host Grotesk, fontSize: 14px, fontWeight: 400, lineHeight: 22px }
  strong: { fontFamily: Host Grotesk, fontSize: 14px, fontWeight: 500, lineHeight: 22px }
  small: { fontFamily: Host Grotesk, fontSize: 13px, fontWeight: 400, lineHeight: 18px }
  label: {
    fontFamily: Fragment Mono,
    fontSize: 11px,
    fontWeight: 400,
    lineHeight: 16px,
    letterSpacing: 0.6px,
  }
  data: {
    fontFamily: Fragment Mono,
    fontSize: 13px,
    fontWeight: 400,
    lineHeight: 18px,
    fontFeature: '"tnum" 1',
  }
  prose-body: { fontFamily: Host Grotesk, fontSize: 16px, fontWeight: 400, lineHeight: 26px }
  prose-lede: { fontFamily: Host Grotesk, fontSize: 19px, fontWeight: 400, lineHeight: 30px }
  prose-h1-sm: { fontFamily: Host Grotesk, fontSize: 36px, fontWeight: 500, lineHeight: 40px }
  prose-h2: {
    fontFamily: Host Grotesk,
    fontSize: 26px,
    fontWeight: 500,
    lineHeight: 34px,
    letterSpacing: -0.4px,
  }
  prose-h3: {
    fontFamily: Host Grotesk,
    fontSize: 19px,
    fontWeight: 500,
    lineHeight: 28px,
    letterSpacing: -0.2px,
  }
  prose-h4: { fontFamily: Host Grotesk, fontSize: 16px, fontWeight: 500, lineHeight: 24px }
  prose-code: { fontFamily: Fragment Mono, fontSize: 13px, fontWeight: 400, lineHeight: 22px }
rounded: { control: 0px, input: 0px, card: 0px, badge: 2px, checkbox: 2px, full: 9999px }
spacing:
  control-height: 32px
  control-height-sm: 28px
  control-padding-x: 12px
  inline-gap: 8px
  section-gap: 16px
  card-padding: 16px
  page-padding-x: 24px
  table-row-height: 44px
  topbar-height: 48px
  badge-height: 20px
  kpi-gap: 24px
  marker-size: 6px
  marker-gap: 8px
  selected-bar-width: 2px
  focus-ring-width: 2px
  focus-ring-offset: 2px
  icon-stroke: 1.5px
  prose-measure: 544px
  prose-wide: 720px
components:
  button-primary: {
    backgroundColor: '{colors.studio-primary-bg}',
    textColor: '{colors.studio-primary-fg}',
    typography: '{typography.strong}',
    rounded: '{rounded.control}',
    height: 32px,
    padding: 0 12px,
  }
  button-primary-dark: {
    backgroundColor: '{colors.studio-primary-bg-dark}',
    textColor: '{colors.studio-primary-fg-dark}',
    rounded: '{rounded.control}',
    height: 32px,
  }
  button-secondary: {
    backgroundColor: '{colors.card}',
    textColor: '{colors.fg}',
    typography: '{typography.strong}',
    rounded: '{rounded.control}',
    height: 32px,
  }
  input: {
    backgroundColor: '{colors.card}',
    textColor: '{colors.fg}',
    typography: '{typography.body}',
    rounded: '{rounded.input}',
    height: 32px,
    padding: 0 12px,
  }
  input-dark: {
    backgroundColor: '{colors.card-dark}',
    textColor: '{colors.fg-dark}',
    rounded: '{rounded.input}',
    height: 32px,
  }
  nav-item-active: {
    textColor: '{colors.fg}',
    typography: '{typography.strong}',
    height: 30px,
    padding: 6px 10px,
  }
  location-marker: {
    backgroundColor: '{colors.studio-signal-marker}',
    rounded: '{rounded.control}',
    width: '{spacing.marker-size}',
    height: '{spacing.marker-size}',
  }
  location-marker-dark: {
    backgroundColor: '{colors.studio-signal-marker-dark}',
    rounded: '{rounded.control}',
    width: '{spacing.marker-size}',
    height: '{spacing.marker-size}',
  }
  eyebrow: { textColor: '{colors.muted-fg}', typography: '{typography.label}' }
  link: { textColor: '{colors.fg}', typography: '{typography.strong}' }
  table-header: { textColor: '{colors.muted-fg}', typography: '{typography.label}', height: 32px }
  table-row-selected: {
    backgroundColor: '{colors.selected}',
    textColor: '{colors.fg}',
    typography: '{typography.small}',
    height: 44px,
  }
  table-row-selected-dark: {
    backgroundColor: '{colors.selected-dark}',
    textColor: '{colors.fg-dark}',
    typography: '{typography.small}',
    height: 44px,
  }
  file-path-chip: {
    backgroundColor: '{colors.surface}',
    textColor: '{colors.fg}',
    typography: '{typography.data}',
    rounded: '{rounded.badge}',
  }
  badge-success: {
    textColor: '{colors.success-text}',
    typography: '{typography.label}',
    rounded: '{rounded.badge}',
    height: 20px,
    padding: 0 6px,
  }
  kpi-value: { textColor: '{colors.fg}', typography: '{typography.kpi}' }
  notice-warning: {
    backgroundColor: '{colors.warning-subtle}',
    textColor: '{colors.fg}',
    rounded: '{rounded.card}',
    padding: 12px 14px,
  }
  topbar: { backgroundColor: '{colors.studio-topbar-bg}', textColor: '{colors.fg}', height: 48px }
```

## Overview

- **Thesis:** seven flavors share one component anatomy. Each flavor changes the ground, shape, type pairing, density and component variants of the same Orders screen, so that it reads as a different product at a 480px thumbnail.
- Utility is the NetScript default theme.

  The docs site is the first product to use it. Its chrome is monochrome and sharp, with one red mark; its content keeps semantic colour:

  - radius 0 on controls, inputs and cards; 2px on badges, kbd, chips and checkboxes;
  - 1px hairlines: structural rules #e0e0e0 / #313131 (gray 5), row rules #f0f0f0 / #2a2a2a;
  - a 6px ink square marks the active nav lane, tab, segment and filter, and a 2px ink bar marks the selected row;
  - a 2px ink focus ring with a 2px gap (#202020 / #7b7b7b);
  - field, checkbox and switch boundaries in gray 9 (#8d8d8d / #6e6e6e, ≥ 3:1);
  - **red only in the logo (#DA291C / #E5332A) and in the `destructive` tone** (errors, destructive actions, CAUTION callouts);
  - status tones in callouts, alerts, badges, toasts and inline notices; syntax colours in code; coloured kind tags in API references (see *Content colour*);
  - a Medium title and Regular KPI numerals, both at −2.5% tracking;
  - Fragment Mono for eyebrows, IDs, column heads, breadcrumbs, kbd and chips;
  - 1.5px icon strokes, and file-path and `data-*` attribute chips as copy-source cues.
- Signature moves:

  1. **Variant-by-variable.** Card, KPI, tabs, table, badge and top bar change anatomy through the `Studio flavor` collection (border sides, row gap and radius, tab track, corner ticks, hard offsets, signal and prose variables), not through forked components.
  2. **Exact detailing.** 1px-exact rules, one neutral ramp with step roles, a restrained accent, a complete 2px/2px focus ring and `⌘K` key hints, following the shadcn and Linear anchors.
  3. **Tinted dark grounds.** Each flavor has its own dark ground hue (graphite, navy, roasted brown, aubergine, teal-black, olive-black, green-black). Dark primaries are graphite or deep keys with an accent edge or ink, never a pale slab.
- **Anchor:** shadcn/ui 2026 styles (MIT) and Linear (observed only), with Geist (OFL fonts) and AlignUI (MIT code only). Take ring borders, one neutral ramp with step roles, label/mono pairs, restrained accent, key hints. Never copy the Vercel marks, Linear chrome or AlignUI's Figma Pro.
- **Family:** System. **Best for:** SaaS, admin and docs (Utility). **Avoid:** Playful for formal finance, Ledger for consumer onboarding. **Feel (Utility):** exact and quiet, Swiss, like a printed spec sheet you can interact with.

## Colors

- **Ladder (Utility):** canvas `bg` #ffffff → `surface` #f6f6f6 → `muted` #f0f0f0 → `container-highest` #e0e0e0. Cards have **no fill** (`studio/card/bg` transparent); structure comes from rules. Dark: #18181a → #1e1e21 → #26262a → #313131; raised #222225.
- **Accent policy (Utility):** Base accent Ink sets `primary` to ink (#202020, dark #313131). Location, selection, links and focus also use ink: `studio/signal/marker` #202020 / #eeeeee. **Red appears only in the logo and in the `destructive` tone** (errors, destructive actions, CAUTION callouts). There are no red markers, links, hairlines or focus rings. Monochrome applies to the chrome: header, navigation, rules, markers, links, focus and selection. Content primitives keep their semantic colour (next bullet).
- **Content colour (Utility).** A callout, status badge or code block that drops its tone loses meaning and contrast, so Utility colours its content primitives. Neutral stays correct where nothing is signalled: plain identifiers, punctuation, module and namespace kinds, neutral badges.

  - **Status tones.** Callouts, alerts, toasts and inline notices use `info`, `success`, `warning` and `destructive`: `*-subtle` fill, `*-border` edge, `*-text` icon and title, body in `fg`.
  - **Status badges** keep Utility's badge anatomy (see *Components*): no fill, a 1px outline and a 6px square dot in the tone's `*-text` colour, radius 2.
  - **Docs callouts** map GitHub alert types to tones: NOTE `info`, TIP `success`, IMPORTANT `important` (violet), WARNING `warning`, CAUTION `destructive`.

    | Role | Light | Dark |
    | --- | --- | --- |
    | `important/subtle` | #f4f0fe violet 3 | #291f43 violet 3 |
    | `important/border` | #d4cafe violet 6 | #473876 violet 6 |
    | `important/text` | #2f265f violet 12 | #baa7ff violet 11 |
  - **Syntax colours.** Code blocks sit on `code/bg` (#ffffff / #191919) under a `surface` header. Every token colour reaches 4.5:1 on `code/bg`. No syntax role is red.

    | Role | Tokens | Light | Dark |
    | --- | --- | --- | --- |
    | `code/syntax/keyword` | keywords, `this`, modifiers | #6550b9 violet 11 | #baa7ff violet 11 |
    | `code/syntax/function` | function and method names | #0d74ce blue 11 | #70b8ff blue 11 |
    | `code/syntax/type` | types, classes, built-ins, shell commands | #008573 teal 11 | #0bd8b6 teal 11 |
    | `code/syntax/string` | strings, template literals | #2a7e3b grass 11 | #71d083 grass 11 |
    | `code/syntax/number` | numbers, literals, regexps, variables | #cc4e00 orange 11 | #ffa057 orange 11 |
    | `code/syntax/comment` | comments (italic) | #646464 gray 11 | #b4b4b4 gray 11 |
    | `code/syntax/punctuation` | operators, punctuation | #646464 gray 11 | #b4b4b4 gray 11 |

    Properties, attributes and plain identifiers stay `fg`.
  - **Kind tags.** API references tag each symbol's kind with the badge anatomy (1px outline, 6px square dot, radius 2, Fragment Mono 11) in its syntax colour: function and method `function`, class `type`, interface and type alias `keyword`, variable, constant and enum `number`, module and namespace `fg`. Names and types read at full `fg` contrast, with types in syntax colours. The owner-authorized docs adapter generates `--ns-studio-api-kind-{keyword,function,type,number}-text` from those same exported ramps. Keep step 11 when it reaches 4.5:1 on both canvas and `surface`; otherwise use step 12 for tag text, dot and outline. Light function, type and number need step 12; light keyword and all dark tags keep step 11. Code syntax roles stay unchanged. This docs-adapter exception remains under token-consolidation debt #2450.
- **Logo red and error red** are separate roles that differ in form as well as hue:

  | Role | Light | Dark | Use |
  | --- | --- | --- | --- |
  | `studio/signal/brand` (`--ns-studio-signal-brand`, primitive `color/swiss-red/{l,d}/9`) | #DA291C | #E5332A | Logo only: a filled 24px square carrying the N (4.87:1 on #ffffff, 4.09:1 on #18181a; logos are exempt) |
  | `destructive` | #E5484D | #E5484D | Invalid field boundary, destructive solid |
  | `destructive-text` | #641723 | #FF9592 | Error message text, always with an icon and a message |
- **Accent policy (other flavors):** the accent appears on primary actions, the focus ring, the selected-row tint and the brand mark. It fills large surfaces only in Playful's KPI tiles and hero.
- **Status (Radix, shared by all flavors):** text roles are step 12 light / step 11 dark (`success-text` #2a7e3b / #71d083, `warning-text` #4f3422 / #ffca16, `destructive-text` #641723 / #ff9592, `info-text` #113264 / #70b8ff). Field error borders use `destructive` #e5484d.
- **Dark design notes:** grounds are tinted, never #000. Elevation uses a lighter tint (`surface-raised`) instead of a shadow. Utility dark primary is graphite #313131 with a #7b7b7b keyline; dark markers and the selected-row bar are light ink #eeeeee, and the dark focus ring is gray #7b7b7b. Signal dark primary is a #222222 key with lime #bde56c ink, and Signal's core `primary` uses the same #222222 key. Workshop dark solid badges use deep-tone pairs (e.g. #25482d with #71d083).

## Typography

Each flavor has one type pairing (see *Flavors*), bound through `font/{sans,heading,label,data,kpi,mono}`. Every family is OFL on Google Fonts (Host Grotesk, Fragment Mono, Figtree, Manrope, Instrument Sans, Bricolage Grotesque, Nunito, Fredoka, IBM Plex Sans Condensed/Mono, Hanken Grotesk, Newsreader, Geist Mono, Space Mono, DM Mono). Fallbacks: `system-ui, sans-serif`; `ui-monospace, monospace`.

- **Utility scale:** title 48/52 Medium at −2.5% (−1.2px); KPI 40/44 Regular at −2.5% (−1px); heading 15/22 SemiBold; body 14/22; small 13/18 (table cells, nav); caption 12/16.
- **Utility mono:** Fragment Mono for eyebrows and column heads (11/16, +0.6px, uppercase, `muted-fg`), IDs, paths, commands, breadcrumbs, kbd and chips (13px in table cells; 12/16 for chips and breadcrumbs). Utility does not use JetBrains Mono.
- **Prose scale** (`--ns-studio-prose-*`, identical in every flavor; the docs site uses it):

  | Role | Size / line / tracking | Weight | Token |
  | --- | --- | --- | --- |
  | Body | 16 / 26 | Regular | `--ns-studio-prose-body-{size,line}` |
  | Lede | 19 / 30 | Regular | `--ns-studio-prose-lede-{size,line}` |
  | H1, mobile | 36 / 40 | Medium | `--ns-studio-prose-h1-sm-{size,line}` |
  | H2 | 26 / 34 / −0.4px | Medium | `--ns-studio-prose-h2-{size,line,tracking}` |
  | H3 | 19 / 28 / −0.2px | Medium | `--ns-studio-prose-h3-*` |
  | H4 | 16 / 24 | Medium | `--ns-studio-prose-h4-*` |
  | Code | Fragment Mono 13 / 22 | Regular | `--ns-studio-prose-code-{size,line}` |
  | Measure / wide column | 544px (≈ 72 characters) / 720px | — | `--ns-studio-prose-measure`, `--ns-studio-prose-wide` |
- **Numerals:** KPI, totals and IDs must be tabular lining figures (`font-variant-numeric: tabular-nums lining-nums`). Figma cannot set this; the code tokens are pending in #2414 and #2416.
- **Label case:** sentence case for UI labels. Utility eyebrows and column heads are uppercase mono; Signal uppercases badge words inside brackets (`[PAID]`).

## Layout

- **Fixture (1280px):** top bar → page header (breadcrumb, title, subtitle, two actions) → four KPIs → orders table card (segmented filter, filter input, Status, date range; 6 rows; footer with pagination) → bottom row: order form card (≈ 2/3) beside a side column with a warning notice and a recent-activity card.
- **Density is set per flavor** (Density collection): Utility Compact (control 32, row 44, card padding 16, page padding 24/20); Cloud Comfortable (36/52/20/32); Workshop and Playful Chunky (44/56/24/32); Ledger and Signal Dense (28/32/12/20); Atelier Airy (40/56/28/56).
- **Rhythm:** 4px grid. Utility KPI gap 24, tab gap 20, field rows 78 (label 18 + 6 + input 32 + 6 + helper 16). Vertical lists reserve a 6px marker slot plus an 8px gap, so labels never shift when the marker appears. Cloud adds a 16px frame inset so the top bar floats.

## Elevation & Depth

Depth is set per flavor. Only elements that float or press get a shadow; everything else is separated by rules or tint.

| Flavor | Recipe (CSS) | Applied to |
| --- | --- | --- |
| Utility, Ledger, Atelier, Signal | none (`shadow/blur` 0) | nothing; structure is rules and tints |
| Cloud | `0 12px 32px #1428501f` (dark `#02041099`); top bar `0 6px 24px`; tab thumb `0 1px 2px` | white platters, floating top bar, selected tab |
| Workshop | hard offset `4px 4px 0 #3a2e22` (dark `#050301f2`); buttons `3px 3px 0` | cards, KPIs, table, buttons |
| Playful | none; depth by pastel tint and the dark-pinned hero | KPI tiles, hero |

**Focus (all flavors):** a 2px `ring` at a 2px offset, drawn as `box-shadow: 0 0 0 2px var(--ns-card), 0 0 0 4px var(--ns-ring)` (or `outline: 2px solid var(--ns-ring); outline-offset: 2px`), with sharp corners in Utility. It covers all four sides of the control and is never clipped. Utility's ring is ink #202020 in light and gray #7b7b7b in dark. Atelier's ring is ink/gray through the flavor `ring/{l,d}` variables.

## Shapes

- **Radius sets** (control / input / card / badge): Utility 0/0/0/2, Cloud 10/10/20/999, Workshop 6/6/6/4, Playful 999/18/28/999, Ledger 2/2/2/2, Atelier 0/0/0/0, Signal 2/2/2/0. Checkboxes are 4px and switches full in every flavor.
- Strokes:

  border/width

  1px (Workshop 1.5px). Utility separates surfaces with quiet 1px hairlines:

  - structural rules (top bar, card and KPI top rules, table head rule) in `studio/topbar/rule`, `studio/card/border` and `studio/table/head-rule`: #e0e0e0 / #313131 (gray 5);
  - row rules in `studio/table/row-rule`: #f0f0f0 / #2a2a2a;
  - no black rules. Ink strokes are reserved for state: the 2px selected-row bar, the 6px location marker and the 2px focus ring.
- **Utility checkboxes** render at about a 2px radius; badges, kbd and chips use `--ns-radius-badge` (2px).
- **Concentricity:** Cloud's tab track (r999, pad 3) holds r999 thumbs. Playful's table (r28, inset 8) holds r14 rows, which is not strictly concentric (28 − 8 = 20); keep it as drawn.

## Components

Shared anatomy for all flavors; per-flavor variants are in *Flavors*. States come from each flavor's Light and Dark state sheets.

- **Buttons** (Primary, Secondary, Outline, Ghost): Primary = `studio/primary/bg` + 1px inside `studio/primary/stroke`, hover swaps to `bg-hover`; other kinds hover with an 8% layer clipped to the button shape. Focus 2/2 ring; disabled 38%.
- **Input, select, textarea:** `card` fill, 1px boundary in `studio/input/border` (`--ns-studio-input-border`: gray 9 #8d8d8d / #6e6e6e in Utility, gray 10 in the other flavors); hover = stroke only; invalid = 1px `destructive` + `destructive-text` helper; invalid + focus keeps both; disabled = `muted` fill. IDs and codes in `font/data`. Textarea hugs content, 12/12 padding, min 80. Toolbar buttons that only open a menu (Status, date range) use the soft `border` (#d9d9d9 / #3a3a3a), not the field boundary.
- **Checkbox 16px** (Utility radius 2; other flavors radius 4), boundary in `studio/input/border`; checked = `primary` + 1px `primary-text` (Utility dark keyline #7b7b7b). **Switch** 32×18, off track edge in `studio/input/border`, 14px thumb.
- **Tabs and segmented filters:** Utility marks the selected item with the 6px ink marker, a Medium label and a mono count; there is no underline, track or fill. Other flavors use the variants in *Flavors*, never fill alone. Disabled 0.38, no hover. Focus is the complete 2px/2px perimeter around the segment's bounds: #202020 16.29:1 light, #7b7b7b 4.19:1 dark. The marker wrapper must not clip the ring; a clipping wrapper leaves the ring visible on one side only.
- **Table row:** Utility hover fill #f9f9f9 / #222222 (measured); selected = `selected` fill (#f0f0f0 / #2a2a2a) + a 2px ink bar on the left (`studio/signal/marker`) + checked box. Other flavors hover at 4%. **Nav item:** 30px, 6/10 padding; Utility active = 6px ink marker + Medium `fg`, no fill; other flavors use `studio/nav/active`. **Notice:** `warning-subtle`, 1px `warning-border`, 12/14 padding, action in `fg` + underline. Badge, KPI, card and top bar are flavor variants.
- **Links (Utility):** ink, Medium, with a 1px underline at a 4px offset in `studio/signal/underline` (gray 8, #bbbbbb / #606060); on hover the underline becomes `studio/signal/marker`. The text colour never changes; the underline and the weight are the non-colour cues.
- **Copy-source cues (Utility):** file-path chips (Fragment Mono 12, copy icon 14px, `surface` fill, 1px `border-subtle`, radius 2) and `data-*` attribute chips (`data-variant=` in `muted-fg`, `"value"` in `fg`). Kbd: mono 11/16 `muted-fg`, 1px `border`, `card` fill, radius 2, 20px high.
- **Dialog/sheet:** not drawn. Use the flavor card plus `overlay` (#000 @ 40% / 66%); anatomy pending in #2416.
- **Signature objects:** Utility's ink location marker, red square N and copy-source chips; Signal ticks and block bars, Workshop offsets, Cloud floating bar, Playful hero and pastel tiles, Ledger joined KPI strip, Atelier serif numerals.

## Do's and Don'ts

- **Do** keep Utility's chrome monochrome: red only in the logo and in the `destructive` tone.
- **Do** give content primitives their semantic colour: status tones on callouts, alerts, notices and status badges; syntax colours in code; coloured kind tags in API references.
- **Don't** drop the tone from a callout, alert, notice or status badge, or render highlighted code without its syntax colours. Neutral identifiers, punctuation, module and namespace kinds and neutral badges are correct.
- **Do** keep Utility sharp and quiet: radii 0–2px, 1px gray-5 structural hairlines, quiet row rules, no shadows. Separations must not read stronger than the content they separate.
- **Don't** use 2px ink rules, underline tabs, a Bold title, Medium KPI numerals or JetBrains Mono in Utility.
- **Do** mark location with the 6px ink square (reserve its slot) and selection with the 2px ink bar; never with red or colour alone.
- **Do** vary ground, shapes, sizes, type and component variants per flavor. Symptom to avoid: flavors that look too close to tell apart.
- **Do** design each dark ground with its own hue; dark is not pure black. Symptom to avoid: every flavor's dark mode looks the same.
- **Don't** outline a dark primary in white. Utility dark keyline is `studio/primary/stroke` #7b7b7b on #313131.
- **Don't** fill a dark primary with a pale accent. Signal dark is #222222 / hover #2a2a2a, label #bde56c, 1px #7b7b7b edge; lime stays for selection, checkmarks and focus.
- **Don't** reuse light saturated solid badges in dark; Workshop dark uses the deep-tone `studio/badge-solid/*` pairs.
- **Do** hover Primary by changing its fill; give other buttons an 8% layer at inset 0, below the label, clipped to the button radius.
- **Do** draw input, checkbox and switch boundaries with `studio/input/border` (≥ 3:1: Utility gray 9, 3.32:1 / 3.48:1 measured; other flavors gray 10), never `border` or `border-subtle`; `fg-subtle` is step 11.
- **Do** use accent step 11 for light rings and for blue/orange/tomato solids carrying white text. Utility and Atelier rings are ink/gray instead (flavor `ring/*`).
- **Do** keep the focus ring complete on four sides; no ancestor may clip it.
- **Don't** let disabled nav items or segments look enabled, or mark a selected segment by colour alone. Let textareas grow; render numerals tabular.
- **Don't** ship a flavor that differs only in hue at 480px (GUIDELINES §4.3 thumbnail test).
- **Do** seed every bound paint with its resolved colour after any mode change (Figma). An unseeded paint can keep a stale value: a primary button bound to `primary/text` can paint a #ffffff perimeter.

## Flavors

All flavors: Theme mode `Studio`, `data-flavor` = flavor name (provisional). The id in parentheses is the flavor's config id. "L / D" = light / dark.

### Utility (`neutral-ink`) · NetScript default · Neutral × Ink, Compact

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #ffffff / #18181a · graphite |
| Radius | 0 / 0 / 0 / 2 (checkbox about 2) |
| Type pairing | Host Grotesk (title 48/52 Medium −2.5%, KPI 40/44 Regular −2.5%, body 14/22) + Fragment Mono (eyebrows, column heads, IDs, breadcrumbs, kbd, chips) |
| Card | no fill, 1px gray-5 top hairline (#e0e0e0 / #313131) |
| Button | square, 32px; ink primary #202020 (dark #313131 + #7b7b7b keyline); secondary and toolbar buttons 1px #d9d9d9 / #3a3a3a |
| Tabs | 6px ink marker before the selected label, Medium label, mono counts; no underline, no track; gap 20 |
| Table | no fill; mono uppercase head; 1px #e0e0e0 / #313131 head rule; #f0f0f0 / #2a2a2a row rules; 44px rows; selected row = #f0f0f0 / #2a2a2a fill + 2px ink left bar |
| Badge | 1px outline in the status text colour, 6px square dot, radius 2, 11px +0.6 |
| KPI | open column under a 1px #e0e0e0 / #313131 hairline; mono uppercase eyebrow; 40/44 Regular value |
| Top bar | white / #18181a, 48px, 1px #e0e0e0 / #313131 bottom hairline; active lane = 6px ink marker + Medium; red square "N" mark (#DA291C / #E5332A) |
| Inputs | 1px gray 9 boundary #8d8d8d / #6e6e6e (3.32:1 / 3.48:1) |
| Icons | Lucide, 1.5px stroke (`--ns-studio-icon-stroke`) |
| Accent / ring | ink; 2px ring with a 2px gap, #202020 / #7b7b7b |

### Cloud (`slate-blue`) · Slate × Blue, Comfortable

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #edf1f7 / #111830 · navy |
| Radius | 10 / 10 / 20 / 999 |
| Type pairing | Manrope (heading, KPI 32/38 Bold) + Figtree (body, labels) + Geist Mono |
| Card | white platter r20, no border, `0 12px 32px #1428501f`; footer #f7f9fc |
| Button | r10, 36px; primary #0d74ce (dark #0090ff, ink #111113) |
| Tabs | pill track #e4eaf3 (pad 3) with a white thumb and `0 1px 2px` shadow |
| Table | white r20 card; header #f7f9fc; row hover #f1f6fe; 52px rows |
| Badge | pill, `*-subtle` fill + 6px dot |
| KPI | white platter r20 with sparkline |
| Top bar | floating white bar r16, 16px inset, `0 6px 24px` |
| Accent / ring | blue; ring #0d74ce / #70b8ff |
| Page header | Not clipped. Never clip a header container that carries a card radius: with the 20px `radius/card` and 0 padding, the clip cuts the leading glyphs of the header text (the C of "Commerce", the F of "Fulfilment"). Unclipped, they render in full at the x48 anchor, and Create order shows its own r10 corner |

### Workshop (`sand-orange`) · Sand × Orange, Chunky

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #f4ede1 / #1f160e · roasted brown |
| Radius | 6 / 6 / 6 / 4 |
| Type pairing | Bricolage Grotesque ExtraBold (title 40/44, KPI 44/48) + Instrument Sans + Space Mono |
| Card | paper #fbf6ee, 2px #3a2e22 border, hard `4px 4px 0` shadow |
| Button | radius 6, 44px, 1.5px border, `3px 3px 0` shadow; primary #cc4e00 (dark #f76b15, ink #111110) |
| Tabs | separate chips: 1.5px #cdbfa7 idle; selected #fce1c0 + 1.5px ink |
| Table | header band #e9dcc4 with 3px rule; 56px rows |
| Badge | solid, radius 4: e.g. #2a7e3b + #fbf6ee; dark deep tone #25482d + #71d083 |
| KPI | cream #fff8ec card, 2px border, 4/4 offset |
| Top bar | #e9dcc4 band, 64px, 3px rule (dark #2e2217 with orange #e07b2a rule) |
| Accent / ring | orange; ring #cc4e00 / #ffa057 |

### Playful (`mauve-violet`) · Mauve × Violet, Chunky

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #f1ecfd / #1a1226 · aubergine |
| Radius | 999 / 18 / 28 / 999 |
| Type pairing | Fredoka SemiBold (title 44/48, KPI 54/58) + Nunito + DM Mono |
| Card | white r28, no border, no shadow |
| Button | pill, 44px; primary #6e56cf with white label |
| Tabs | pill track #e3d8ff (pad 4), white thumb |
| Table | rows are separate white r14 pills, 6px apart, 8px inset on #f6f2fe; no rules |
| Badge | pill, `*-subtle` fill + dot, Nunito Bold 12 |
| KPI | four pastel tiles r28: #ffe1ec, #d9f4e3, #fff0c2, #dceaff (dark #3a1d30, #173126, #352a12, #18284a) |
| Top bar | transparent, 64px; nav on a white pill track |
| Accent / ring | violet; ring #6550b9 / #baa7ff; page header is a violet hero #33236e, pinned to Scheme Dark in both schemes |

### Ledger (`ledger`) · Slate × Indigo, Dense

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #f4f6f9 / #08171f · teal-black |
| Radius | 2 / 2 / 2 / 2 |
| Type pairing | IBM Plex Sans Condensed (title 20/26) + IBM Plex Mono for data and KPI 22/26 |
| Card | white, 1px #c5cfdc border all sides |
| Button | radius 2, 28px, 12px condensed label; primary #3e63dd |
| Tabs | radius-2 track #e3e9f1; selected white + 1px #9aa8bc |
| Table | header #e3e9f1, zebra #f3f6fa (dark #0f222d), 32px rows |
| Badge | `*-subtle` fill + 1px `*-border`, radius 2, no dot, 10/14 |
| KPI | one joined strip: 0 gap, shared 1px borders |
| Top bar | navy #04101a, 40px, pinned to Scheme Dark in both schemes |
| Accent / ring | indigo; ring #3a5bc7 / #9eb1ff |

### Atelier (`atelier`) · Sand × Tomato, Airy

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #f8f5ee / #191813 · olive-black |
| Radius | 0 / 0 / 0 / 0 |
| Type pairing | Newsreader Light (title 60/64, KPI 44/48) + Hanken Grotesk (body 15/24) + IBM Plex Mono |
| Card | no fill, 1px ink top rule (#1f1c18; dark #8f8778) |
| Button | radius 0, 40px; primary is text + 1px outline in `primary-text` (#d13415 / #ff977d), fill hidden |
| Tabs | 1px underline, gap 24 |
| Table | no fill, #ded7ca row rules, 56px rows |
| Badge | 1px `success-border`-style outline, radius 0, dot, Regular 11 |
| KPI | open, 1px top rule, 40px gap |
| Top bar | transparent, 72px, 1px #ded7ca hairline |
| Accent / ring | tomato accent (primary outline #d13415 / #ff977d); focus ring ink #21201c / gray #7c7b74 through the flavor `ring/{l,d}` variables (measured 14.97:1 / 4.18:1) |

### Signal (`signal`) · Neutral × Lime, Dense

| Property | Value |
| --- | --- |
| Ground L / D · dark hue | #ecf0ec / #090e0a · green-black |
| Radius | 2 / 2 / 2 / 0 |
| Type pairing | Geist Mono throughout (title 22/28, KPI 28/32 SemiBold) |
| Card | #f7f9f6, 1px #a9b4aa border, 12px corner ticks (#1b1f1c; dark lime #bdee63) |
| Button | radius 2, 28px, bracket labels `[ Create order ]`; light lime #bdee63 + #37401c ink + #5c7c2f edge; dark #222222 + #bde56c + #7b7b7b |
| Tabs | bracketed `[All]`, selected #e4f5bd fill, no track |
| Table | header #e3e9e3, row and vertical cell rules #d3dcd3, 32px rows |
| Badge | no box: uppercase bracket text `[PAID]` in the status text colour |
| KPI | bordered cell, corner ticks, 8px segmented block-bar meter |
| Top bar | black #050806, 40px, 1px lime #9be22d rule, pinned to Scheme Dark |
| Accent / ring | lime; ring #5c7c2f / #bdee63. Core `primary` dark is #222222 |
| Logo glyph | The N binds `studio/brand/on` (`--ns-studio-brand-on`) = #0b0f0b in both schemes: 14.32:1 on the lime tile, where lime #bde56c would be 1.07:1. This is a logo legibility rule, not a WCAG requirement. The other flavors' glyphs bind `primary/fg`; their `brand-on` values mirror that chain |

## Iconography & Imagery

Lucide stroke icons (ISC), 16px (`icon/plus`, `icon/bell`); 24px only in the Tonal language. The stroke comes from the flavor `icon/stroke` variable (`--ns-studio-icon-stroke`): 1.5px in Utility, 2px in the other flavors. Avatars are initials on `muted`, shaped by `studio/avatar/radius` (0 Utility, Signal; 2 Ledger; 6 Workshop; 10 Playful; 999 Cloud, Atelier). Brand mark: a 24px square in `studio/signal/brand` (which aliases the flavor `brand`) with a letter (Northwind is invented fixture branding). No illustration or photo.

## Motion & States

From the state sheets: hover = 8% layer (row 4%), Primary hover = fill swap, focus = 2/2 ring, disabled = 38%, selected = `selected` tint plus a non-colour marker. Durations and easing are not specified yet; the anchor's 100ms and `translate-y-px` press are a starting point only. Motion, reduced motion (no translate) and RTL are pending in #2419.

## Accessibility

WCAG 2.x ratios from resolved variables *(token)*, except where marked *measured* on rendered pixels:

| Flavor L / D | `fg` on `bg` | `muted-fg` on `card` | `primary-fg` on primary | `input-border` on `card` | `ring` on `bg` |
| --- | --- | --- | --- | --- | --- |
| Utility | 16.29 / 15.28 | 5.92 / 8.55 | 15.88 / 11.21 | 3.32 / 3.48 (gray 9, `studio/input/border`, *measured*) | 16.29 / 4.19 (*measured*) |
| Cloud | 14.46 / 15.11 | 5.94 / 7.42 | 4.77 / 5.78 | 3.78 / 3.64 | 4.20 / 8.34 |
| Workshop | 14.01 / 15.33 | 5.61 / 7.67 | 4.51 / 6.36 | 3.59 / 3.79 | 3.88 / 8.83 |
| Playful | 14.09 / 15.64 | 5.69 / 7.84 | 5.39 / 5.39 | 3.64 / 3.88 | 5.34 / 8.68 |
| Ledger | 15.14 / 15.69 | 5.94 / 8.10 | 5.21 / 5.21 | 3.78 / 3.98 | 5.54 / 8.84 |
| Atelier | 14.97 / 15.30 | 5.55 / 8.48 | 4.98 / 4.89 | 3.55 / 4.18 | 14.97 / 4.18 (ink/gray ring, *measured*) |
| Signal | 14.15 / 16.78 | 5.59 / 8.94 | 8.14 / 11.05 | 3.58 / 4.38 | 4.17 / 14.44 |

Signal light's lime fill is 1.17:1 on its ground; its 1px #5c7c2f edge (4.17:1) is the boundary. Utility link underlines are #bbbbbb / #606060 (1.92:1 / 2.82:1); the underline's presence and the Medium weight are the non-colour cues, and hover turns it ink. The logo reds are 4.87:1 / 4.09:1 (logotypes are exempt). Hit targets: Dense flavors use 28px controls and 24px small controls (meets the 24px minimum; use Comfortable or larger for touch). A full contrast matrix is pending in #2414.

## NetScript Mapping

| Layer | Value |
| --- | --- |
| Figma Theme mode | `Studio` |
| Base gray × accent | per flavor (Utility Neutral × Ink) |
| Density | per flavor (Utility Compact) |
| Flavor | `Studio flavor`: Utility, Cloud, Workshop, Playful, Ledger, Atelier, Signal |
| `data-theme` | `studio` (+ `data-flavor`, provisional) |
| Language roles | Role manifest (GUIDELINES §2.4): `studio/{card,kpi,table,tabs,topbar,nav,hero,brand,button,deco,primary}/*`, `studio/badge-solid/{success,warning,info,destructive,neutral}/{bg,fg}`, `studio/signal/{brand,marker,underline}`, `studio/input/border`, `studio/brand/on`, `studio/code/scroll-thumb`, docs-adapter `studio/api-kind/{keyword,function,type,number}/text` (exported step 11/12 AA policy above, #2450) → `--ns-studio-*`; scheme-independent flavor variables `--ns-studio-prose-*` and `--ns-studio-icon-stroke`; flavor `ring/{l,d}` (Utility and Atelier ink/gray rings) |

- **Code syntax:** every `studio/*` Scheme role, and every scheme-independent, non-boolean Studio flavor variable without a Theme twin, has the code syntax `var(--ns-studio-<path>)`. The `studio-*` keys in the front matter follow that rule. All of them must be registered in the tokens build (#2414). Flavor geometry booleans (border sides, ticks, sparkline, block bars) exist only in the flavor collection for now.
- **Studio variables:** primitives `color/swiss-red/{l,d}/9`; flavor variables `signal/{l,d}/{brand,marker,underline}`, `input/{l,d}/border`, `icon/stroke`, `prose/*` and `ring/{l,d}`, with values in all seven flavor modes; Scheme roles `studio/signal/*`, `studio/input/border`, `studio/brand/on` (flavor `brand-on/{l,d}`: Signal #0b0f0b, the other flavors mirror their `primary/fg` chain) and `studio/code/scroll-thumb` (→ `gray/{l,d}/10`).
- **Docs-site roles (Utility):** the dark primary keyline binds `studio/primary/stroke` #7b7b7b, 3.07:1 on the #313131 fill and 4.19:1 on the page. The code-block scrollbar thumb binds `studio/code/scroll-thumb`: gray/l/10 #838383, 3.51:1 on #f6f6f6; gray/d/10 #7b7b7b, 3.93:1 on #1e1e21. The thumb geometry is 3px.
- **Status:** values come from the NetScript Figma library. Token export, fonts, numerals and the contrast matrix are tracked in #2414; canonical states, dialog and sheet anatomy and semantics in #2416; runtime checks (keyboard, motion, RTL) in #2419. Runtime behaviour stays unproven until #2419.

## Sources

- **References:** ui.shadcn.com (MIT), vercel.com/geist (OFL fonts), linear.app (observed only), alignui.com (MIT code only). What to take from them and what never to copy is listed under *Overview* → Anchor.
- **Fonts and icons:** the families listed under *Typography* (OFL, Google Fonts); Lucide icons (ISC).
- **Invented fixture content:** Northwind, the six customers, SO-10477…10482, amounts, emails, the tracking number and AUTUMN24.
