nitro_kit 2.0.0.alpha.2 → 2.0.0.alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +229 -1
  3. data/README.md +25 -10
  4. data/STYLE_GUIDE.md +47 -5
  5. data/app/assets/stylesheets/nitro_kit-tailwind-v4.css +3 -3
  6. data/app/assets/stylesheets/nitro_kit.css +2820 -1816
  7. data/app/components/nitro_kit/accordion.rb +2 -26
  8. data/app/components/nitro_kit/alert.rb +1 -11
  9. data/app/components/nitro_kit/app_navigation.rb +45 -11
  10. data/app/components/nitro_kit/app_shell.rb +1 -7
  11. data/app/components/nitro_kit/appearance_picker.rb +11 -12
  12. data/app/components/nitro_kit/avatar.rb +6 -1
  13. data/app/components/nitro_kit/avatar_stack.rb +3 -0
  14. data/app/components/nitro_kit/badge.rb +13 -4
  15. data/app/components/nitro_kit/button_group.rb +2 -2
  16. data/app/components/nitro_kit/checkbox.rb +7 -4
  17. data/app/components/nitro_kit/checkbox_group.rb +0 -25
  18. data/app/components/nitro_kit/combobox.rb +4 -33
  19. data/app/components/nitro_kit/command_palette.rb +42 -59
  20. data/app/components/nitro_kit/component.rb +57 -5
  21. data/app/components/nitro_kit/danger_zone.rb +5 -1
  22. data/app/components/nitro_kit/data_section.rb +28 -4
  23. data/app/components/nitro_kit/details_table.rb +19 -8
  24. data/app/components/nitro_kit/dialog.rb +23 -19
  25. data/app/components/nitro_kit/dropdown.rb +1 -6
  26. data/app/components/nitro_kit/dropzone.rb +4 -15
  27. data/app/components/nitro_kit/empty_state.rb +21 -2
  28. data/app/components/nitro_kit/field.rb +35 -11
  29. data/app/components/nitro_kit/form_builder.rb +1 -2
  30. data/app/components/nitro_kit/progressive_image.rb +2 -2
  31. data/app/components/nitro_kit/radio_button.rb +7 -4
  32. data/app/components/nitro_kit/radio_button_group.rb +0 -25
  33. data/app/components/nitro_kit/select.rb +4 -17
  34. data/app/components/nitro_kit/settings_layout.rb +17 -4
  35. data/app/components/nitro_kit/{form_section.rb → settings_section.rb} +18 -11
  36. data/app/components/nitro_kit/sheet.rb +29 -20
  37. data/app/components/nitro_kit/stat_grid.rb +18 -2
  38. data/app/components/nitro_kit/table.rb +22 -3
  39. data/app/components/nitro_kit/tabs.rb +2 -13
  40. data/app/components/nitro_kit/toast.rb +4 -2
  41. data/app/components/nitro_kit/toolbar.rb +2 -0
  42. data/app/components/nitro_kit/tooltip.rb +7 -10
  43. data/app/javascript/controllers/nk/app_shell_controller.js +3 -3
  44. data/app/javascript/controllers/nk/appearance_controller.js +6 -0
  45. data/app/javascript/controllers/nk/combobox_controller.js +51 -1
  46. data/app/javascript/controllers/nk/command_palette_controller.js +25 -11
  47. data/app/javascript/controllers/nk/dialog_controller.js +54 -0
  48. data/app/javascript/controllers/nk/dropdown_controller.js +45 -0
  49. data/app/javascript/controllers/nk/dropzone_controller.js +2 -2
  50. data/app/javascript/controllers/nk/progressive_image_controller.js +11 -7
  51. data/app/javascript/controllers/nk/tabs_controller.js +21 -2
  52. data/app/javascript/controllers/nk/tooltip_controller.js +9 -0
  53. data/config/locales/en.yml +4 -1
  54. data/docs/agent_guide.md +63 -123
  55. data/docs/agent_native_spec.md +72 -383
  56. data/docs/browser_support.md +82 -0
  57. data/docs/component_contracts.md +108 -82
  58. data/docs/customization.md +689 -91
  59. data/docs/hotwire.md +50 -76
  60. data/docs/initialization_prompt.md +26 -31
  61. data/docs/migration_1_to_2.md +88 -30
  62. data/docs/patterns/application_foundation.md +45 -119
  63. data/docs/patterns/crud_resource.md +44 -126
  64. data/docs/patterns/destructive_action.md +45 -77
  65. data/docs/patterns/flash_and_toast.md +18 -36
  66. data/docs/patterns/inline_edit.md +21 -44
  67. data/docs/patterns/queryable_collection.md +65 -161
  68. data/docs/patterns/resource_form.md +33 -81
  69. data/docs/rails_conventions.md +38 -75
  70. data/docs/rails_integration.md +96 -446
  71. data/lib/generators/nitro_kit/upgrade_smoke_tests_generator.rb +12 -0
  72. data/lib/nitro_kit/installation.rb +20 -7
  73. data/lib/nitro_kit/migration_inventory.rb +275 -8
  74. data/lib/nitro_kit/upgrade_smoke_test.rb +10 -12
  75. data/lib/nitro_kit/version.rb +1 -1
  76. data/lib/rails/commands/nitro_kit/nitro_kit_command.rb +10 -3
  77. data/plugins/nitro-kit/skills/nitro-kit-hotwire/SKILL.md +4 -0
  78. data/plugins/nitro-kit/skills/nitro-kit-rails/SKILL.md +13 -1
  79. data/plugins/nitro-kit/skills/nitro-kit-ui/SKILL.md +32 -15
  80. data/src/stylesheets/nitro_kit/components/accordion.css +44 -44
  81. data/src/stylesheets/nitro_kit/components/alert.css +27 -36
  82. data/src/stylesheets/nitro_kit/components/app_navigation.css +92 -20
  83. data/src/stylesheets/nitro_kit/components/app_shell.css +199 -196
  84. data/src/stylesheets/nitro_kit/components/appearance_picker.css +61 -39
  85. data/src/stylesheets/nitro_kit/components/auth_shell.css +2 -2
  86. data/src/stylesheets/nitro_kit/components/avatar.css +15 -11
  87. data/src/stylesheets/nitro_kit/components/avatar_stack.css +48 -29
  88. data/src/stylesheets/nitro_kit/components/badge.css +13 -9
  89. data/src/stylesheets/nitro_kit/components/button.css +121 -79
  90. data/src/stylesheets/nitro_kit/components/button_group.css +19 -14
  91. data/src/stylesheets/nitro_kit/components/card.css +12 -6
  92. data/src/stylesheets/nitro_kit/components/checkbox.css +54 -67
  93. data/src/stylesheets/nitro_kit/components/checkbox_group.css +16 -16
  94. data/src/stylesheets/nitro_kit/components/combobox.css +39 -29
  95. data/src/stylesheets/nitro_kit/components/command_palette.css +110 -51
  96. data/src/stylesheets/nitro_kit/components/container.css +6 -6
  97. data/src/stylesheets/nitro_kit/components/control_group.css +61 -67
  98. data/src/stylesheets/nitro_kit/components/danger_zone.css +8 -8
  99. data/src/stylesheets/nitro_kit/components/data_section.css +4 -4
  100. data/src/stylesheets/nitro_kit/components/details_table.css +17 -15
  101. data/src/stylesheets/nitro_kit/components/dialog.css +8 -5
  102. data/src/stylesheets/nitro_kit/components/dropdown.css +36 -30
  103. data/src/stylesheets/nitro_kit/components/dropzone.css +78 -35
  104. data/src/stylesheets/nitro_kit/components/empty_state.css +7 -7
  105. data/src/stylesheets/nitro_kit/components/field.css +32 -28
  106. data/src/stylesheets/nitro_kit/components/field_group.css +13 -0
  107. data/src/stylesheets/nitro_kit/components/fieldset.css +8 -2
  108. data/src/stylesheets/nitro_kit/components/flex.css +1 -1
  109. data/src/stylesheets/nitro_kit/components/grid.css +1 -1
  110. data/src/stylesheets/nitro_kit/components/icon.css +5 -5
  111. data/src/stylesheets/nitro_kit/components/input.css +42 -8
  112. data/src/stylesheets/nitro_kit/components/layout.css +165 -165
  113. data/src/stylesheets/nitro_kit/components/page_header.css +7 -7
  114. data/src/stylesheets/nitro_kit/components/pagination.css +58 -49
  115. data/src/stylesheets/nitro_kit/components/pagination_bar.css +9 -9
  116. data/src/stylesheets/nitro_kit/components/palette.css +145 -77
  117. data/src/stylesheets/nitro_kit/components/progressive_image.css +45 -55
  118. data/src/stylesheets/nitro_kit/components/radio_button.css +48 -46
  119. data/src/stylesheets/nitro_kit/components/radio_button_group.css +49 -49
  120. data/src/stylesheets/nitro_kit/components/rich_text_area.css +16 -1
  121. data/src/stylesheets/nitro_kit/components/select.css +24 -15
  122. data/src/stylesheets/nitro_kit/components/settings_layout.css +26 -23
  123. data/src/stylesheets/nitro_kit/components/settings_section.css +84 -0
  124. data/src/stylesheets/nitro_kit/components/sheet.css +30 -10
  125. data/src/stylesheets/nitro_kit/components/stat_grid.css +11 -10
  126. data/src/stylesheets/nitro_kit/components/switch.css +60 -62
  127. data/src/stylesheets/nitro_kit/components/table.css +43 -35
  128. data/src/stylesheets/nitro_kit/components/tabs.css +48 -40
  129. data/src/stylesheets/nitro_kit/components/textarea.css +20 -5
  130. data/src/stylesheets/nitro_kit/components/toast.css +11 -47
  131. data/src/stylesheets/nitro_kit/components/toolbar.css +16 -41
  132. data/src/stylesheets/nitro_kit/components/tooltip.css +38 -29
  133. data/src/stylesheets/nitro_kit/components/typeset.css +150 -4
  134. data/src/stylesheets/nitro_kit/reset.css +15 -15
  135. data/src/stylesheets/nitro_kit/tokens.css +501 -79
  136. metadata +4 -4
  137. data/docs/new_app_strategy.md +0 -22
  138. data/src/stylesheets/nitro_kit/components/form_section.css +0 -71
@@ -1,5 +1,9 @@
1
1
  # Customizing Nitro Kit
2
2
 
3
+ **Audience:** Application developers and coding agents changing Nitro Kit
4
+ themes or composing application-owned UI. The first sections are task guidance;
5
+ the final token tables are exhaustive reference.
6
+
3
7
  Nitro Kit owns component Ruby, markup, behavior, and default CSS. Applications customize the system by overriding the public `--nk-*` custom properties, composing components into application UI, and occasionally creating a narrow subclass. Applications do not copy or edit Nitro components.
4
8
 
5
9
  ## Stylesheet order
@@ -13,7 +17,8 @@ Load browser styles in this order:
13
17
  5. Application styles, including Nitro token overrides.
14
18
 
15
19
  `NitroKit::AppearanceBootstrap` precedes every entry in this list. The install
16
- generator owns this ordering and can safely be rerun. For example, an
20
+ generator applies this order when it can identify conventional layout entries
21
+ unambiguously; otherwise it reports manual work. For example, an
17
22
  application with Lexxy and no Tailwind has exactly three stylesheet entries:
18
23
 
19
24
  ```erb
@@ -79,7 +84,15 @@ Color tokens need a light value, a no-JavaScript system fallback, and a dark val
79
84
 
80
85
  The media query matters when JavaScript or the appearance bootstrap is unavailable. When the runtime is active, `data-theme` is always the resolved `light` or `dark` appearance. `system` is a stored preference in `data-theme-preference`, not a third palette and never a `data-theme="system"` selector.
81
86
 
82
- Raised default Buttons have their own tokens, so their dark treatment can change without recoloring cards, dialogs, menus, or data-entry controls:
87
+ Buttons can also preserve a product-specific shape without changing inputs or surfaces:
88
+
89
+ ```css
90
+ :root {
91
+ --nk-button-radius: var(--nk-radius-full);
92
+ }
93
+ ```
94
+
95
+ Raised default Buttons have their own color tokens, so their dark treatment can change without recoloring cards, dialogs, menus, or data-entry controls:
83
96
 
84
97
  ```css
85
98
  @media (prefers-color-scheme: dark) {
@@ -187,16 +200,18 @@ Treat related tokens as a system:
187
200
  - Accent changes usually set `--nk-color-primary`, `--nk-color-primary-foreground`, and `--nk-color-focus` for both appearances. The default hover value is derived automatically; set `--nk-color-primary-hover` only when the derived color is unsuitable.
188
201
  - Neutral changes should coordinate canvas, surface, elevated, foreground, muted, border, and neutral-content pairs for both appearances.
189
202
  - Default Button changes use the `--nk-button-default-*` tokens. They are separate from `--nk-color-surface` so a raised neutral action can change without recoloring inputs, cards, dialogs, and menus.
190
- - Radius changes should move `--nk-radius-xs` through `--nk-radius-xl` together. Leave `--nk-radius-full` alone unless pills and circular controls should stop being fully rounded.
203
+ - Radius changes should move `--nk-radius-xs` through `--nk-radius-xl` together. Leave `--nk-radius-full` alone unless pills and circular controls should stop being fully rounded. Set `--nk-button-radius` when buttons intentionally use a distinct shape, such as a pill treatment, without changing inputs and surfaces.
191
204
  - Density changes should coordinate `--nk-space` with all five control-height tokens. Changing one component's internal gap is not a public theme contract.
192
205
  - Font changes normally set `--nk-font-sans`; set `--nk-font-mono`, text sizes, line heights, or weights only when the whole type system calls for it.
193
206
 
194
- Check foreground pairs and focus indicators for contrast in both appearances. The semantic names describe use, not a fixed hue: `danger` can be a project-appropriate destructive color, but it should remain recognizably destructive everywhere it appears.
207
+ Check foreground pairs and focus indicators for contrast in both appearances. The semantic names describe use, not a fixed hue: `destructive` can be a project-appropriate red, but it should remain recognizably destructive everywhere it appears.
195
208
 
196
209
  ## Theme customizer
197
210
 
198
- The interactive theme customizer lives on the documentation site at
199
- [nitrokit.dev/customize](https://nitrokit.dev/customize). Pick an accent, neutral, radius, density, font, and application shell, watch a complete workspace update, then copy deterministic CSS containing only changed public tokens plus a copyable `AppShell` composition for the selected layout.
211
+ The interactive theme customizer lives at
212
+ [nitrokit.dev/customize](https://nitrokit.dev/customize). It previews accent,
213
+ neutral, radius, density, typography, and appearance choices, then copies the
214
+ changed public tokens.
200
215
 
201
216
  Paste the CSS into an application-owned stylesheet such as `app/assets/stylesheets/nitro_theme.css`, then load that stylesheet after Nitro Kit and any compiled Tailwind CSS:
202
217
 
@@ -413,7 +428,11 @@ end
413
428
 
414
429
  Change only `layout:` to `:topbar` or `:hybrid`; the same `brand`, `navigation`, `topbar`, and `main` declarations remain valid. Nitro owns the responsive breakpoint, narrow drawer, focus management, sticky regions, and one reflowed navigation DOM tree. Do not clone navigation for mobile or add route registries to the shell.
415
430
 
416
- The gallery has complete executable examples for [sidebar](/gallery/compositions/application-sidebar), [topbar](/gallery/compositions/application-topbar), and [hybrid](/gallery/compositions/application-hybrid) applications. Each route contains multiple populated, empty, loading, long-content, missing-content, or error combinations.
431
+ The gallery has executable examples for
432
+ [sidebar](https://gallery.nitrokit.dev/gallery/compositions/application-sidebar),
433
+ [topbar](https://gallery.nitrokit.dev/gallery/compositions/application-topbar),
434
+ and [hybrid](https://gallery.nitrokit.dev/gallery/compositions/application-hybrid)
435
+ applications.
417
436
 
418
437
  ## Rails forms and Hotwire
419
438
 
@@ -449,7 +468,10 @@ import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading";
449
468
  eagerLoadControllersFrom("controllers", application);
450
469
  ```
451
470
 
452
- This registers Nitro's `controllers/nk/*` modules together with application controllers. Without importmap, Ruby and CSS still work, but a bundler-based application must expose and register those Stimulus modules itself. Nitro Kit ships no third-party JavaScript runtime, and Nitro Kit 2.0 has no JavaScript-package entrypoint.
471
+ This registers Nitro's `controllers/nk/*` modules together with application controllers. Without importmap, server-rendered HTML and CSS remain available, but controller-dependent behavior and compatibility bridges are unavailable unless a bundler-based application exposes and registers those Stimulus modules itself. Nitro Kit ships no third-party JavaScript runtime, and Nitro Kit 2.0 has no JavaScript-package entrypoint.
472
+
473
+ For the resulting behavior when those modules are not registered, use the
474
+ canonical no-JavaScript matrix in [`browser_support.md`](browser_support.md).
453
475
 
454
476
  ## Optional Tailwind CSS v4 adapter
455
477
 
@@ -471,104 +493,680 @@ Use `@theme inline` when a Tailwind theme variable references another custom pro
471
493
 
472
494
  ## Public token reference
473
495
 
474
- The following 84 variables are the complete public token set. Theme-independent tokens are declared on `:root`. Appearance tokens have light, dark, and system-fallback values. Derived tokens have defaults expressed in terms of other public tokens and remain overrideable.
496
+ The following variables are the complete public token set. Theme-independent tokens are declared on `:root`. Appearance tokens have light, dark, and system-fallback values. Derived tokens have defaults expressed in terms of other public tokens and remain overrideable.
475
497
 
476
498
  ### Typography
477
499
 
478
- | Token | Role |
479
- | --------------------------- | ---------------------------------- |
480
- | `--nk-font-sans` | Default UI font family. |
481
- | `--nk-font-mono` | Monospace font family. |
482
- | `--nk-text-xs` | Extra-small text size. |
483
- | `--nk-text-sm` | Small text size. |
484
- | `--nk-text-base` | Base text size. |
485
- | `--nk-text-lg` | Large text size. |
486
- | `--nk-text-xl` | Extra-large text size. |
487
- | `--nk-text-2xl` | Largest shipped display text size. |
488
- | `--nk-leading-tight` | Tight line-height ratio. |
489
- | `--nk-leading-normal` | Default line-height ratio. |
490
- | `--nk-leading-relaxed` | Relaxed line-height ratio. |
491
- | `--nk-font-weight-normal` | Normal text weight. |
492
- | `--nk-font-weight-medium` | Medium text weight. |
493
- | `--nk-font-weight-semibold` | Semibold text weight. |
494
- | `--nk-font-weight-bold` | Bold text weight. |
495
- | `--nk-typeset-font-body` | Typeset body font family. |
496
- | `--nk-typeset-font-heading` | Typeset heading font family. |
497
- | `--nk-typeset-font-mono` | Typeset code font family. |
498
- | `--nk-typeset-size` | Typeset base text size. |
499
- | `--nk-typeset-leading` | Typeset body line-height ratio. |
500
- | `--nk-typeset-flow` | Typeset vertical rhythm unit. |
500
+ | Token | Role |
501
+ | --------------------------- | -------------------------------------------------------------------- |
502
+ | `--nk-font-sans` | Default UI font family. |
503
+ | `--nk-font-mono` | Monospace font family. |
504
+ | `--nk-text-xs` | Extra-small text size. |
505
+ | `--nk-text-sm` | Small text size. |
506
+ | `--nk-text-base` | Base text size. |
507
+ | `--nk-text-lg` | Large text size. |
508
+ | `--nk-text-xl` | Extra-large text size. |
509
+ | `--nk-text-2xl` | Largest shipped display text size. |
510
+ | `--nk-leading-tight` | Tight line-height ratio. |
511
+ | `--nk-leading-normal` | Default line-height ratio. |
512
+ | `--nk-leading-relaxed` | Relaxed line-height ratio. |
513
+ | `--nk-font-weight-normal` | Normal text weight. |
514
+ | `--nk-font-weight-medium` | Medium text weight. |
515
+ | `--nk-font-weight-semibold` | Semibold text weight. |
516
+ | `--nk-font-weight-bold` | Bold text weight. |
517
+ | `--nk-title-page-size` | Page title size; the one top-level heading. |
518
+ | `--nk-title-page-weight` | Page title weight. |
519
+ | `--nk-title-section-size` | Section title size: data, settings, and danger sections. |
520
+ | `--nk-title-section-weight` | Section title weight. |
521
+ | `--nk-title-surface-size` | Surface title size: cards, dialogs, sheets, empty states, fieldsets. |
522
+ | `--nk-title-surface-weight` | Surface title weight. |
523
+ | `--nk-title-compact-size` | Compact title size: legends, alert and toast titles. |
524
+ | `--nk-title-compact-weight` | Compact title weight. |
525
+ | `--nk-typeset-font-body` | Typeset body font family. |
526
+ | `--nk-typeset-font-heading` | Typeset heading font family. |
527
+ | `--nk-typeset-font-mono` | Typeset code font family. |
528
+ | `--nk-typeset-size` | Typeset base text size. |
529
+ | `--nk-typeset-leading` | Typeset body line-height ratio. |
530
+ | `--nk-typeset-flow` | Typeset vertical rhythm unit. |
501
531
 
502
532
  ### Spacing and dimensions
503
533
 
504
- | Token | Role |
505
- | ------------------------ | --------------------------------------------------------------- |
506
- | `--nk-space` | Base spacing unit multiplied throughout components and layouts. |
507
- | `--nk-control-height-xs` | Extra-small control height. |
508
- | `--nk-control-height-sm` | Small control height. |
509
- | `--nk-control-height-md` | Default control height. |
510
- | `--nk-control-height-lg` | Large control height. |
511
- | `--nk-control-height-xl` | Extra-large control height. |
512
- | `--nk-content-sm` | Small Container maximum width. |
513
- | `--nk-content-md` | Medium Container maximum width. |
514
- | `--nk-content-lg` | Large Container maximum width. |
515
- | `--nk-content-xl` | Extra-large Container maximum width. |
534
+ | Token | Role |
535
+ | ----------------------------- | --------------------------------------------------------------- |
536
+ | `--nk-space` | Base spacing unit multiplied throughout components and layouts. |
537
+ | `--nk-control-height-xs` | Extra-small control height. |
538
+ | `--nk-control-height-sm` | Small control height. |
539
+ | `--nk-control-height-md` | Default control height. |
540
+ | `--nk-control-height-lg` | Large control height. |
541
+ | `--nk-control-height-xl` | Extra-large control height. |
542
+ | `--nk-choice-size-md` | Checkbox and radio box size. |
543
+ | `--nk-choice-size-lg` | Large checkbox and radio box size. |
544
+ | `--nk-icon-size-xs` | Extra-small Icon size. |
545
+ | `--nk-icon-size-sm` | Small Icon size. |
546
+ | `--nk-icon-size-md` | Default Icon size; also sizes owned status icons. |
547
+ | `--nk-icon-size-lg` | Large Icon size. |
548
+ | `--nk-icon-size-xl` | Extra-large Icon size. |
549
+ | `--nk-avatar-size-xs` | Extra-small Avatar size. |
550
+ | `--nk-avatar-size-sm` | Small Avatar size. |
551
+ | `--nk-avatar-size-md` | Default Avatar size. |
552
+ | `--nk-avatar-size-lg` | Large Avatar size. |
553
+ | `--nk-control-padding-inline` | Inline padding shared by buttons and data-entry controls. |
554
+ | `--nk-content-sm` | Small Container maximum width. |
555
+ | `--nk-content-md` | Medium Container maximum width. |
556
+ | `--nk-content-lg` | Large Container maximum width. |
557
+ | `--nk-content-xl` | Extra-large Container maximum width. |
516
558
 
517
559
  ### Shape, borders, and focus
518
560
 
519
- | Token | Role |
520
- | ------------------- | ----------------------------------- |
521
- | `--nk-radius-xs` | Extra-small corner radius. |
522
- | `--nk-radius-sm` | Small corner radius. |
523
- | `--nk-radius-md` | Default control corner radius. |
524
- | `--nk-radius-lg` | Large surface corner radius. |
525
- | `--nk-radius-xl` | Extra-large overlay corner radius. |
526
- | `--nk-radius-full` | Fully rounded pills and circles. |
527
- | `--nk-border-width` | Default border and separator width. |
528
- | `--nk-focus-width` | Focus-ring width. |
529
- | `--nk-focus-offset` | Focus-ring offset. |
561
+ | Token | Role |
562
+ | ----------------------- | ------------------------------------------------------------------------------------------ |
563
+ | `--nk-radius-xs` | Extra-small corner radius. |
564
+ | `--nk-radius-sm` | Small corner radius. |
565
+ | `--nk-radius-md` | Default control corner radius. |
566
+ | `--nk-radius-lg` | Large surface corner radius. |
567
+ | `--nk-radius-xl` | Extra-large overlay corner radius. |
568
+ | `--nk-radius-full` | Fully rounded pills and circles. |
569
+ | `--nk-button-radius` | Optional Button-only radius override; the default `initial` preserves size-specific radii. |
570
+ | `--nk-border-width` | Default border and separator width. |
571
+ | `--nk-focus-width` | Focus-ring width. |
572
+ | `--nk-focus-offset` | Focus-ring offset. |
573
+ | `--nk-disabled-opacity` | Opacity of disabled controls and options. |
530
574
 
531
575
  ### Elevation and motion
532
576
 
533
- | Token | Role |
534
- | ---------------------- | ------------------------------------- |
535
- | `--nk-shadow-sm` | Low surface elevation. |
536
- | `--nk-shadow-md` | Medium floating elevation. |
537
- | `--nk-shadow-lg` | High overlay elevation. |
538
- | `--nk-duration-fast` | Fast interaction duration. |
539
- | `--nk-duration-normal` | Default interaction duration. |
540
- | `--nk-duration-slow` | Deliberate overlay or image duration. |
541
- | `--nk-ease` | Default transition timing function. |
577
+ | Token | Role |
578
+ | ---------------------- | -------------------------------------------------- |
579
+ | `--nk-shadow-xs` | Raised control shadow, such as the default Button. |
580
+ | `--nk-shadow-sm` | Low surface elevation. |
581
+ | `--nk-shadow-md` | Medium floating elevation. |
582
+ | `--nk-shadow-lg` | High overlay elevation. |
583
+ | `--nk-duration-fast` | Fast interaction duration. |
584
+ | `--nk-duration-normal` | Default interaction duration. |
585
+ | `--nk-duration-slow` | Deliberate overlay or image duration. |
586
+ | `--nk-ease` | Default transition timing function. |
542
587
 
543
588
  ### Semantic colors
544
589
 
545
- | Token | Role |
546
- | ------------------------------- | ---------------------------------------------------------------------- |
547
- | `--nk-color-canvas` | Page canvas and overscroll; light zinc uses a zinc-25-like near-white. |
548
- | `--nk-color-surface` | Default component surface. |
549
- | `--nk-color-surface-hover` | Derived interactive surface hover. |
550
- | `--nk-color-elevated` | Raised or inset-neutral surface. |
551
- | `--nk-color-foreground` | Primary text and icon color. |
552
- | `--nk-color-muted` | Quiet fill. |
553
- | `--nk-color-muted-foreground` | Secondary text and icon color. |
554
- | `--nk-color-border` | Borders and separators. |
555
- | `--nk-color-focus` | Focus indicator. |
556
- | `--nk-color-primary` | Primary action and selected-state fill. |
557
- | `--nk-color-primary-hover` | Derived primary interaction hover. |
558
- | `--nk-color-primary-foreground` | Content placed on primary fill. |
559
- | `--nk-color-neutral` | Neutral status fill or marker. |
560
- | `--nk-color-neutral-content` | Strong neutral status content. |
561
- | `--nk-color-info` | Informational status fill or marker. |
562
- | `--nk-color-info-content` | Informational status content. |
563
- | `--nk-color-success` | Successful status fill or marker. |
564
- | `--nk-color-success-content` | Successful status content. |
565
- | `--nk-color-warning` | Warning status fill or marker. |
566
- | `--nk-color-warning-content` | Warning status content. |
567
- | `--nk-color-danger` | Destructive action and error fill. |
568
- | `--nk-color-danger-hover` | Derived destructive interaction hover. |
569
- | `--nk-color-danger-foreground` | Content placed on destructive fill. |
570
- | `--nk-color-danger-content` | Error and destructive status content. |
571
- | `--nk-color-overlay` | Modal and drawer backdrop. |
590
+ | Token | Role |
591
+ | ----------------------------------- | ---------------------------------------------------------------------- |
592
+ | `--nk-color-canvas` | Page canvas and overscroll; light zinc uses a zinc-25-like near-white. |
593
+ | `--nk-color-surface` | Default component surface. |
594
+ | `--nk-color-surface-hover` | Derived interactive surface hover. |
595
+ | `--nk-color-elevated` | Raised or inset-neutral surface. |
596
+ | `--nk-color-foreground` | Primary text and icon color. |
597
+ | `--nk-color-muted` | Quiet fill. |
598
+ | `--nk-color-muted-foreground` | Secondary text and icon color. |
599
+ | `--nk-color-border` | Borders and separators. |
600
+ | `--nk-color-focus` | Focus indicator. |
601
+ | `--nk-color-primary` | Primary action and selected-state fill. |
602
+ | `--nk-color-primary-hover` | Derived primary interaction hover. |
603
+ | `--nk-color-primary-foreground` | Content placed on primary fill. |
604
+ | `--nk-color-neutral` | Neutral status fill or marker. |
605
+ | `--nk-color-neutral-content` | Strong neutral status content. |
606
+ | `--nk-color-info` | Informational status fill or marker. |
607
+ | `--nk-color-info-content` | Informational status content. |
608
+ | `--nk-color-success` | Successful status fill or marker. |
609
+ | `--nk-color-success-content` | Successful status content. |
610
+ | `--nk-color-warning` | Warning status fill or marker. |
611
+ | `--nk-color-warning-content` | Warning status content. |
612
+ | `--nk-color-destructive` | Destructive action and error fill. |
613
+ | `--nk-color-destructive-hover` | Derived destructive interaction hover. |
614
+ | `--nk-color-destructive-foreground` | Content placed on destructive fill. |
615
+ | `--nk-color-destructive-content` | Error and destructive status content. |
616
+ | `--nk-color-overlay` | Modal and drawer backdrop. |
617
+
618
+ The five status families — neutral, info, success, warning, and destructive — carry
619
+ two roles each. `--nk-color-{family}` is the fill axis: strong marks, icons, and
620
+ fills such as the destructive Button or an upload marker. The tint axis
621
+ `--nk-palette-{family}` drives the soft surfaces of `Badge`, `Alert`, and
622
+ `Toast::Item`, and defaults to the same scale steps as the matching hue family,
623
+ so an `info` badge renders exactly like a `blue` badge out of the box:
624
+
625
+ ```css
626
+ :root {
627
+ --nk-palette-success: var(--nk-teal-400);
628
+ }
629
+ :root,
630
+ [data-theme="light"] {
631
+ --nk-palette-success-content: var(--nk-teal-800);
632
+ }
633
+ @media (prefers-color-scheme: dark) {
634
+ :root:not([data-theme]) {
635
+ --nk-palette-success-content: var(--nk-teal-200);
636
+ }
637
+ }
638
+ [data-theme="dark"] {
639
+ --nk-palette-success-content: var(--nk-teal-200);
640
+ }
641
+ ```
642
+
643
+ That override retints successful badges, alerts, and toasts together — and only
644
+ them; a decorative `green` badge stays green, and success fills elsewhere keep
645
+ following `--nk-color-success`. The paired `-content` role carries the
646
+ foreground, so change both to keep contrast in hand. Components tint at their
647
+ own strength — a Badge reads more strongly than an Alert — but they never
648
+ disagree about the hue.
649
+
650
+ ### Color scales
651
+
652
+ Every color in the system samples these scales. The five neutral families —
653
+ slate, gray, zinc, neutral, and stone — and the seventeen chromatic families
654
+ each ship all eleven steps. Steps 50-200 are tints and surfaces, 400-600 are
655
+ accents and markers, and 700-950 are content colors. Scale steps are
656
+ appearance independent; the semantic roles above sample different steps per
657
+ appearance.
658
+
659
+ White and black anchor the poles. Overriding them retints every pure-white
660
+ surface and every overlay, for warm-paper or true-black themes:
661
+
662
+ | Token | Value |
663
+ | ------------ | ------ |
664
+ | `--nk-white` | `#fff` |
665
+ | `--nk-black` | `#000` |
666
+
667
+ The default theme is zinc: `--nk-color-foreground` is `--nk-zinc-900`,
668
+ `--nk-color-border` is `--nk-zinc-200`, and so on. Swapping the neutral or the
669
+ accent means re-pointing roles at another family, not inventing values:
670
+
671
+ ```css
672
+ /* A cooler, slate-based neutral in both appearances. */
673
+ :root,
674
+ [data-theme="light"] {
675
+ --nk-color-foreground: var(--nk-slate-900);
676
+ --nk-color-muted: var(--nk-slate-100);
677
+ --nk-color-muted-foreground: var(--nk-slate-500);
678
+ --nk-color-border: var(--nk-slate-200);
679
+ --nk-color-neutral: var(--nk-slate-500);
680
+ --nk-color-neutral-content: var(--nk-slate-700);
681
+ --nk-palette-neutral: var(--nk-slate-400);
682
+ --nk-palette-neutral-content: var(--nk-slate-700);
683
+ }
684
+
685
+ @media (prefers-color-scheme: dark) {
686
+ :root:not([data-theme]) {
687
+ --nk-color-canvas: var(--nk-slate-950);
688
+ --nk-color-surface: color-mix(
689
+ in oklab,
690
+ var(--nk-slate-950) 45%,
691
+ var(--nk-slate-900)
692
+ );
693
+ --nk-color-elevated: var(--nk-slate-900);
694
+ --nk-color-foreground: var(--nk-slate-100);
695
+ --nk-color-muted: var(--nk-slate-800);
696
+ --nk-color-muted-foreground: var(--nk-slate-400);
697
+ --nk-color-border: var(--nk-slate-700);
698
+ --nk-color-neutral: var(--nk-slate-400);
699
+ --nk-color-neutral-content: var(--nk-slate-200);
700
+ --nk-palette-neutral-content: var(--nk-slate-200);
701
+ }
702
+ }
703
+
704
+ [data-theme="dark"] {
705
+ --nk-color-canvas: var(--nk-slate-950);
706
+ --nk-color-surface: color-mix(
707
+ in oklab,
708
+ var(--nk-slate-950) 45%,
709
+ var(--nk-slate-900)
710
+ );
711
+ --nk-color-elevated: var(--nk-slate-900);
712
+ --nk-color-foreground: var(--nk-slate-100);
713
+ --nk-color-muted: var(--nk-slate-800);
714
+ --nk-color-muted-foreground: var(--nk-slate-400);
715
+ --nk-color-border: var(--nk-slate-700);
716
+ --nk-color-neutral: var(--nk-slate-400);
717
+ --nk-color-neutral-content: var(--nk-slate-200);
718
+ --nk-palette-neutral-content: var(--nk-slate-200);
719
+ }
720
+ ```
721
+
722
+ A neutral swap is most visible in dark appearance, where canvas and surfaces
723
+ sit on the 800-950 steps and the families genuinely diverge — slate carries
724
+ many times the chroma of zinc there. In light appearance the default canvas
725
+ and surface are near-white customs with no family identity, so the swap shows
726
+ only in borders, muted fills, and text. For a light canvas that follows the
727
+ family too, add `--nk-color-canvas: var(--nk-slate-50)`.
728
+
729
+ An accent works the same way through the primary role:
730
+
731
+ ```css
732
+ :root,
733
+ [data-theme="light"] {
734
+ --nk-color-primary: var(--nk-indigo-600);
735
+ --nk-color-primary-foreground: white;
736
+ --nk-color-focus: var(--nk-indigo-600);
737
+ }
738
+
739
+ @media (prefers-color-scheme: dark) {
740
+ :root:not([data-theme]) {
741
+ --nk-color-primary: var(--nk-indigo-500);
742
+ --nk-color-primary-foreground: var(--nk-indigo-50);
743
+ --nk-color-focus: var(--nk-indigo-500);
744
+ }
745
+ }
746
+
747
+ [data-theme="dark"] {
748
+ --nk-color-primary: var(--nk-indigo-500);
749
+ --nk-color-primary-foreground: var(--nk-indigo-50);
750
+ --nk-color-focus: var(--nk-indigo-500);
751
+ }
752
+ ```
753
+
754
+ Values mirror `src/stylesheets/nitro_kit/tokens.css`, which is authoritative.
755
+
756
+ #### Slate
757
+
758
+ | Token | Value |
759
+ | ---------------- | -------------------------- |
760
+ | `--nk-slate-50` | `oklch(98.4% 0.004 247.3)` |
761
+ | `--nk-slate-100` | `oklch(96.8% 0.006 249.8)` |
762
+ | `--nk-slate-200` | `oklch(93.6% 0.013 252.5)` |
763
+ | `--nk-slate-300` | `oklch(85.9% 0.023 254.2)` |
764
+ | `--nk-slate-400` | `oklch(71.2% 0.038 255.7)` |
765
+ | `--nk-slate-500` | `oklch(55.7% 0.045 257.6)` |
766
+ | `--nk-slate-600` | `oklch(45% 0.045 257.1)` |
767
+ | `--nk-slate-700` | `oklch(36.4% 0.043 257.5)` |
768
+ | `--nk-slate-800` | `oklch(28.5% 0.042 260.9)` |
769
+ | `--nk-slate-900` | `oklch(20.6% 0.042 263.3)` |
770
+ | `--nk-slate-950` | `oklch(12.9% 0.042 265.8)` |
771
+
772
+ #### Gray
773
+
774
+ | Token | Value |
775
+ | --------------- | -------------------------- |
776
+ | `--nk-gray-50` | `oklch(98.5% 0.002 250.4)` |
777
+ | `--nk-gray-100` | `oklch(96.7% 0.002 260.5)` |
778
+ | `--nk-gray-200` | `oklch(93.6% 0.005 264.1)` |
779
+ | `--nk-gray-300` | `oklch(86.2% 0.011 259.5)` |
780
+ | `--nk-gray-400` | `oklch(71.4% 0.02 261.5)` |
781
+ | `--nk-gray-500` | `oklch(55.6% 0.027 261.6)` |
782
+ | `--nk-gray-600` | `oklch(44.9% 0.031 260.0)` |
783
+ | `--nk-gray-700` | `oklch(36.4% 0.033 256.9)` |
784
+ | `--nk-gray-800` | `oklch(28.6% 0.034 260.1)` |
785
+ | `--nk-gray-900` | `oklch(20.7% 0.033 261.5)` |
786
+ | `--nk-gray-950` | `oklch(13% 0.028 262.7)` |
787
+
788
+ #### Zinc
789
+
790
+ | Token | Value |
791
+ | --------------- | -------------------------- |
792
+ | `--nk-zinc-50` | `oklch(98.5% 0 none)` |
793
+ | `--nk-zinc-100` | `oklch(96.7% 0.001 286.4)` |
794
+ | `--nk-zinc-200` | `oklch(93% 0.003 286.3)` |
795
+ | `--nk-zinc-300` | `oklch(86.1% 0.007 286.3)` |
796
+ | `--nk-zinc-400` | `oklch(71.4% 0.013 286.1)` |
797
+ | `--nk-zinc-500` | `oklch(55.5% 0.017 285.9)` |
798
+ | `--nk-zinc-600` | `oklch(44.7% 0.016 285.8)` |
799
+ | `--nk-zinc-700` | `oklch(36% 0.012 285.9)` |
800
+ | `--nk-zinc-800` | `oklch(28.2% 0.008 285.9)` |
801
+ | `--nk-zinc-900` | `oklch(20.8% 0.005 285.9)` |
802
+ | `--nk-zinc-950` | `oklch(14% 0.005 285.8)` |
803
+
804
+ #### Neutral
805
+
806
+ | Token | Value |
807
+ | ------------------ | --------------------- |
808
+ | `--nk-neutral-50` | `oklch(98.5% 0 none)` |
809
+ | `--nk-neutral-100` | `oklch(97% 0 none)` |
810
+ | `--nk-neutral-200` | `oklch(93.2% 0 none)` |
811
+ | `--nk-neutral-300` | `oklch(86% 0 none)` |
812
+ | `--nk-neutral-400` | `oklch(71.6% 0 none)` |
813
+ | `--nk-neutral-500` | `oklch(55.7% 0 none)` |
814
+ | `--nk-neutral-600` | `oklch(44.7% 0 none)` |
815
+ | `--nk-neutral-700` | `oklch(36.1% 0 none)` |
816
+ | `--nk-neutral-800` | `oklch(27.8% 0 none)` |
817
+ | `--nk-neutral-900` | `oklch(20.7% 0 none)` |
818
+ | `--nk-neutral-950` | `oklch(14.3% 0 none)` |
819
+
820
+ #### Stone
821
+
822
+ | Token | Value |
823
+ | ---------------- | -------------------------- |
824
+ | `--nk-stone-50` | `oklch(98.5% 0.001 114.2)` |
825
+ | `--nk-stone-100` | `oklch(97% 0.001 85.2)` |
826
+ | `--nk-stone-200` | `oklch(93.3% 0.003 64.5)` |
827
+ | `--nk-stone-300` | `oklch(85.9% 0.005 52.4)` |
828
+ | `--nk-stone-400` | `oklch(71.5% 0.01 56.1)` |
829
+ | `--nk-stone-500` | `oklch(55.7% 0.012 62.1)` |
830
+ | `--nk-stone-600` | `oklch(45% 0.012 71.1)` |
831
+ | `--nk-stone-700` | `oklch(36.4% 0.01 62.3)` |
832
+ | `--nk-stone-800` | `oklch(27.8% 0.007 44.5)` |
833
+ | `--nk-stone-900` | `oklch(21.1% 0.006 46.3)` |
834
+ | `--nk-stone-950` | `oklch(14.7% 0.004 51.8)` |
835
+
836
+ #### Red
837
+
838
+ | Token | Value |
839
+ | -------------- | ------------------------- |
840
+ | `--nk-red-50` | `oklch(97% 0.013 17.5)` |
841
+ | `--nk-red-100` | `oklch(93.9% 0.029 17.5)` |
842
+ | `--nk-red-200` | `oklch(88.4% 0.061 18.3)` |
843
+ | `--nk-red-300` | `oklch(80.2% 0.113 19.7)` |
844
+ | `--nk-red-400` | `oklch(71% 0.183 22.3)` |
845
+ | `--nk-red-500` | `oklch(63.6% 0.237 25.3)` |
846
+ | `--nk-red-600` | `oklch(57.5% 0.235 27.3)` |
847
+ | `--nk-red-700` | `oklch(50.7% 0.207 27.6)` |
848
+ | `--nk-red-800` | `oklch(45.3% 0.178 26.7)` |
849
+ | `--nk-red-900` | `oklch(38.6% 0.14 25.9)` |
850
+ | `--nk-red-950` | `oklch(26.8% 0.093 25.8)` |
851
+
852
+ #### Orange
853
+
854
+ | Token | Value |
855
+ | ----------------- | ------------------------- |
856
+ | `--nk-orange-50` | `oklch(98.1% 0.015 73.9)` |
857
+ | `--nk-orange-100` | `oklch(95.2% 0.038 74.5)` |
858
+ | `--nk-orange-200` | `oklch(90.3% 0.075 71.7)` |
859
+ | `--nk-orange-300` | `oklch(83% 0.124 65.1)` |
860
+ | `--nk-orange-400` | `oklch(75.3% 0.173 56.1)` |
861
+ | `--nk-orange-500` | `oklch(70.5% 0.203 47.6)` |
862
+ | `--nk-orange-600` | `oklch(64.6% 0.212 41.1)` |
863
+ | `--nk-orange-700` | `oklch(55.3% 0.185 38.4)` |
864
+ | `--nk-orange-800` | `oklch(48% 0.158 37.7)` |
865
+ | `--nk-orange-900` | `oklch(39.8% 0.122 37.7)` |
866
+ | `--nk-orange-950` | `oklch(27.6% 0.079 36.7)` |
867
+
868
+ #### Amber
869
+
870
+ | Token | Value |
871
+ | ---------------- | ------------------------- |
872
+ | `--nk-amber-50` | `oklch(98.8% 0.016 94.9)` |
873
+ | `--nk-amber-100` | `oklch(96% 0.069 96.5)` |
874
+ | `--nk-amber-200` | `oklch(92.4% 0.118 95.3)` |
875
+ | `--nk-amber-300` | `oklch(87.9% 0.167 92.1)` |
876
+ | `--nk-amber-400` | `oklch(82.8% 0.179 84.4)` |
877
+ | `--nk-amber-500` | `oklch(76.9% 0.178 70.1)` |
878
+ | `--nk-amber-600` | `oklch(66.6% 0.169 58.3)` |
879
+ | `--nk-amber-700` | `oklch(55.5% 0.153 49.1)` |
880
+ | `--nk-amber-800` | `oklch(48.1% 0.135 46.1)` |
881
+ | `--nk-amber-900` | `oklch(40.4% 0.112 45.4)` |
882
+ | `--nk-amber-950` | `oklch(28.9% 0.077 46.2)` |
883
+
884
+ #### Yellow
885
+
886
+ | Token | Value |
887
+ | ----------------- | -------------------------- |
888
+ | `--nk-yellow-50` | `oklch(98.7% 0.021 102.2)` |
889
+ | `--nk-yellow-100` | `oklch(97.3% 0.071 103.1)` |
890
+ | `--nk-yellow-200` | `oklch(94.5% 0.13 101.7)` |
891
+ | `--nk-yellow-300` | `oklch(90.4% 0.175 97.8)` |
892
+ | `--nk-yellow-400` | `oklch(85.2% 0.189 91.9)` |
893
+ | `--nk-yellow-500` | `oklch(79.5% 0.174 86.0)` |
894
+ | `--nk-yellow-600` | `oklch(68.1% 0.152 75.8)` |
895
+ | `--nk-yellow-700` | `oklch(55.6% 0.125 66.6)` |
896
+ | `--nk-yellow-800` | `oklch(48.3% 0.111 61.5)` |
897
+ | `--nk-yellow-900` | `oklch(41.1% 0.094 57.5)` |
898
+ | `--nk-yellow-950` | `oklch(29.6% 0.067 54.1)` |
899
+
900
+ #### Lime
901
+
902
+ | Token | Value |
903
+ | --------------- | -------------------------- |
904
+ | `--nk-lime-50` | `oklch(98.6% 0.026 120.7)` |
905
+ | `--nk-lime-100` | `oklch(96.8% 0.076 122.4)` |
906
+ | `--nk-lime-200` | `oklch(93.8% 0.129 124.4)` |
907
+ | `--nk-lime-300` | `oklch(89.7% 0.195 126.6)` |
908
+ | `--nk-lime-400` | `oklch(84.1% 0.228 128.9)` |
909
+ | `--nk-lime-500` | `oklch(76.8% 0.223 130.8)` |
910
+ | `--nk-lime-600` | `oklch(64.8% 0.19 131.7)` |
911
+ | `--nk-lime-700` | `oklch(53.5% 0.147 131.5)` |
912
+ | `--nk-lime-800` | `oklch(46.2% 0.125 131.0)` |
913
+ | `--nk-lime-900` | `oklch(39.5% 0.1 131.1)` |
914
+ | `--nk-lime-950` | `oklch(28.4% 0.073 132.0)` |
915
+
916
+ #### Green
917
+
918
+ | Token | Value |
919
+ | ---------------- | -------------------------- |
920
+ | `--nk-green-50` | `oklch(98.1% 0.017 155.9)` |
921
+ | `--nk-green-100` | `oklch(96.3% 0.046 156.6)` |
922
+ | `--nk-green-200` | `oklch(92.6% 0.088 156.1)` |
923
+ | `--nk-green-300` | `oklch(86.7% 0.151 154.3)` |
924
+ | `--nk-green-400` | `oklch(79.8% 0.204 151.8)` |
925
+ | `--nk-green-500` | `oklch(72.3% 0.209 149.6)` |
926
+ | `--nk-green-600` | `oklch(62.7% 0.184 149.2)` |
927
+ | `--nk-green-700` | `oklch(52.9% 0.145 150.0)` |
928
+ | `--nk-green-800` | `oklch(45.6% 0.121 151.4)` |
929
+ | `--nk-green-900` | `oklch(38.3% 0.094 152.4)` |
930
+ | `--nk-green-950` | `oklch(27.6% 0.066 153.1)` |
931
+
932
+ #### Emerald
933
+
934
+ | Token | Value |
935
+ | ------------------ | -------------------------- |
936
+ | `--nk-emerald-50` | `oklch(97.9% 0.019 165.4)` |
937
+ | `--nk-emerald-100` | `oklch(95% 0.056 164.5)` |
938
+ | `--nk-emerald-200` | `oklch(90.6% 0.095 164.0)` |
939
+ | `--nk-emerald-300` | `oklch(84.2% 0.143 164.5)` |
940
+ | `--nk-emerald-400` | `oklch(76.7% 0.167 163.3)` |
941
+ | `--nk-emerald-500` | `oklch(69.6% 0.16 162.5)` |
942
+ | `--nk-emerald-600` | `oklch(59.6% 0.135 163.2)` |
943
+ | `--nk-emerald-700` | `oklch(50.8% 0.108 165.5)` |
944
+ | `--nk-emerald-800` | `oklch(44% 0.09 167.0)` |
945
+ | `--nk-emerald-900` | `oklch(36.9% 0.074 169.2)` |
946
+ | `--nk-emerald-950` | `oklch(27.1% 0.052 172.3)` |
947
+
948
+ #### Teal
949
+
950
+ | Token | Value |
951
+ | --------------- | -------------------------- |
952
+ | `--nk-teal-50` | `oklch(98.3% 0.011 180.8)` |
953
+ | `--nk-teal-100` | `oklch(95.5% 0.057 180.5)` |
954
+ | `--nk-teal-200` | `oklch(91.1% 0.097 180.6)` |
955
+ | `--nk-teal-300` | `oklch(85.2% 0.136 181.0)` |
956
+ | `--nk-teal-400` | `oklch(77.8% 0.142 181.9)` |
957
+ | `--nk-teal-500` | `oklch(70.3% 0.13 182.5)` |
958
+ | `--nk-teal-600` | `oklch(60.1% 0.108 184.6)` |
959
+ | `--nk-teal-700` | `oklch(51% 0.089 186.6)` |
960
+ | `--nk-teal-800` | `oklch(44.5% 0.077 187.6)` |
961
+ | `--nk-teal-900` | `oklch(37.6% 0.062 189.0)` |
962
+ | `--nk-teal-950` | `oklch(28.6% 0.047 192.0)` |
963
+
964
+ #### Cyan
965
+
966
+ | Token | Value |
967
+ | --------------- | -------------------------- |
968
+ | `--nk-cyan-50` | `oklch(98.3% 0.017 201.2)` |
969
+ | `--nk-cyan-100` | `oklch(95.8% 0.045 202.8)` |
970
+ | `--nk-cyan-200` | `oklch(91.8% 0.083 205.0)` |
971
+ | `--nk-cyan-300` | `oklch(86.2% 0.126 207.5)` |
972
+ | `--nk-cyan-400` | `oklch(78.9% 0.144 211.5)` |
973
+ | `--nk-cyan-500` | `oklch(71.5% 0.133 215.3)` |
974
+ | `--nk-cyan-600` | `oklch(61% 0.116 221.6)` |
975
+ | `--nk-cyan-700` | `oklch(52% 0.097 223.4)` |
976
+ | `--nk-cyan-800` | `oklch(45.5% 0.085 224.7)` |
977
+ | `--nk-cyan-900` | `oklch(38.8% 0.07 227.1)` |
978
+ | `--nk-cyan-950` | `oklch(30.9% 0.056 229.8)` |
979
+
980
+ #### Sky
981
+
982
+ | Token | Value |
983
+ | -------------- | -------------------------- |
984
+ | `--nk-sky-50` | `oklch(97.8% 0.011 237.7)` |
985
+ | `--nk-sky-100` | `oklch(94.9% 0.026 234.2)` |
986
+ | `--nk-sky-200` | `oklch(90% 0.059 232.1)` |
987
+ | `--nk-sky-300` | `oklch(82.7% 0.108 230.2)` |
988
+ | `--nk-sky-400` | `oklch(75.3% 0.153 232.8)` |
989
+ | `--nk-sky-500` | `oklch(68.5% 0.159 237.3)` |
990
+ | `--nk-sky-600` | `oklch(58.8% 0.148 242.0)` |
991
+ | `--nk-sky-700` | `oklch(50.1% 0.124 242.7)` |
992
+ | `--nk-sky-800` | `oklch(44.5% 0.104 241.2)` |
993
+ | `--nk-sky-900` | `oklch(38.1% 0.089 241.3)` |
994
+ | `--nk-sky-950` | `oklch(30.1% 0.067 242.7)` |
995
+
996
+ #### Blue
997
+
998
+ | Token | Value |
999
+ | --------------- | -------------------------- |
1000
+ | `--nk-blue-50` | `oklch(96.8% 0.015 255.3)` |
1001
+ | `--nk-blue-100` | `oklch(93.6% 0.03 254.3)` |
1002
+ | `--nk-blue-200` | `oklch(88.2% 0.059 253.8)` |
1003
+ | `--nk-blue-300` | `oklch(80.4% 0.101 252.6)` |
1004
+ | `--nk-blue-400` | `oklch(70.9% 0.155 254.7)` |
1005
+ | `--nk-blue-500` | `oklch(62.1% 0.205 259.4)` |
1006
+ | `--nk-blue-600` | `oklch(54.9% 0.244 262.8)` |
1007
+ | `--nk-blue-700` | `oklch(48.4% 0.239 264.6)` |
1008
+ | `--nk-blue-800` | `oklch(43.2% 0.201 265.2)` |
1009
+ | `--nk-blue-900` | `oklch(37% 0.15 266.0)` |
1010
+ | `--nk-blue-950` | `oklch(28.8% 0.087 267.6)` |
1011
+
1012
+ #### Indigo
1013
+
1014
+ | Token | Value |
1015
+ | ----------------- | -------------------------- |
1016
+ | `--nk-indigo-50` | `oklch(96.2% 0.018 272.3)` |
1017
+ | `--nk-indigo-100` | `oklch(93% 0.033 272.8)` |
1018
+ | `--nk-indigo-200` | `oklch(87% 0.063 273.7)` |
1019
+ | `--nk-indigo-300` | `oklch(78% 0.112 275.2)` |
1020
+ | `--nk-indigo-400` | `oklch(67.6% 0.173 276.7)` |
1021
+ | `--nk-indigo-500` | `oklch(58.4% 0.23 277.2)` |
1022
+ | `--nk-indigo-600` | `oklch(51.4% 0.257 277.0)` |
1023
+ | `--nk-indigo-700` | `oklch(45.3% 0.241 277.0)` |
1024
+ | `--nk-indigo-800` | `oklch(40.7% 0.196 277.4)` |
1025
+ | `--nk-indigo-900` | `oklch(34.9% 0.146 278.8)` |
1026
+ | `--nk-indigo-950` | `oklch(26.4% 0.088 281.2)` |
1027
+
1028
+ #### Violet
1029
+
1030
+ | Token | Value |
1031
+ | ----------------- | -------------------------- |
1032
+ | `--nk-violet-50` | `oklch(96.8% 0.016 294.0)` |
1033
+ | `--nk-violet-100` | `oklch(94.5% 0.027 293.9)` |
1034
+ | `--nk-violet-200` | `oklch(89.2% 0.058 293.8)` |
1035
+ | `--nk-violet-300` | `oklch(80.8% 0.106 293.4)` |
1036
+ | `--nk-violet-400` | `oklch(70.3% 0.173 293.4)` |
1037
+ | `--nk-violet-500` | `oklch(60.6% 0.24 292.7)` |
1038
+ | `--nk-violet-600` | `oklch(54.2% 0.279 292.7)` |
1039
+ | `--nk-violet-700` | `oklch(48.8% 0.269 292.7)` |
1040
+ | `--nk-violet-800` | `oklch(43.8% 0.234 293.2)` |
1041
+ | `--nk-violet-900` | `oklch(37.1% 0.192 292.8)` |
1042
+ | `--nk-violet-950` | `oklch(28.8% 0.139 291.6)` |
1043
+
1044
+ #### Purple
1045
+
1046
+ | Token | Value |
1047
+ | ----------------- | -------------------------- |
1048
+ | `--nk-purple-50` | `oklch(97.4% 0.014 308.2)` |
1049
+ | `--nk-purple-100` | `oklch(95.2% 0.029 307.4)` |
1050
+ | `--nk-purple-200` | `oklch(90.1% 0.061 306.7)` |
1051
+ | `--nk-purple-300` | `oklch(82.1% 0.114 306.3)` |
1052
+ | `--nk-purple-400` | `oklch(71.4% 0.193 305.5)` |
1053
+ | `--nk-purple-500` | `oklch(62.7% 0.255 303.9)` |
1054
+ | `--nk-purple-600` | `oklch(55.7% 0.286 302.3)` |
1055
+ | `--nk-purple-700` | `oklch(49.6% 0.261 302.2)` |
1056
+ | `--nk-purple-800` | `oklch(44.1% 0.22 303.7)` |
1057
+ | `--nk-purple-900` | `oklch(37.3% 0.182 304.0)` |
1058
+ | `--nk-purple-950` | `oklch(29.5% 0.145 303.3)` |
1059
+
1060
+ #### Fuchsia
1061
+
1062
+ | Token | Value |
1063
+ | ------------------ | -------------------------- |
1064
+ | `--nk-fuchsia-50` | `oklch(97.7% 0.017 319.8)` |
1065
+ | `--nk-fuchsia-100` | `oklch(95.2% 0.035 319.4)` |
1066
+ | `--nk-fuchsia-200` | `oklch(90.3% 0.075 319.7)` |
1067
+ | `--nk-fuchsia-300` | `oklch(82.9% 0.143 321.2)` |
1068
+ | `--nk-fuchsia-400` | `oklch(74.3% 0.228 322.1)` |
1069
+ | `--nk-fuchsia-500` | `oklch(66.5% 0.291 322.3)` |
1070
+ | `--nk-fuchsia-600` | `oklch(59.1% 0.283 322.9)` |
1071
+ | `--nk-fuchsia-700` | `oklch(51.8% 0.243 323.8)` |
1072
+ | `--nk-fuchsia-800` | `oklch(45.9% 0.211 324.8)` |
1073
+ | `--nk-fuchsia-900` | `oklch(39.1% 0.171 325.5)` |
1074
+ | `--nk-fuchsia-950` | `oklch(30.1% 0.135 325.7)` |
1075
+
1076
+ #### Pink
1077
+
1078
+ | Token | Value |
1079
+ | --------------- | -------------------------- |
1080
+ | `--nk-pink-50` | `oklch(97.1% 0.015 343.1)` |
1081
+ | `--nk-pink-100` | `oklch(94.9% 0.027 342.4)` |
1082
+ | `--nk-pink-200` | `oklch(89.9% 0.062 343.3)` |
1083
+ | `--nk-pink-300` | `oklch(81.7% 0.125 346.0)` |
1084
+ | `--nk-pink-400` | `oklch(72.6% 0.196 349.7)` |
1085
+ | `--nk-pink-500` | `oklch(65.2% 0.242 354.8)` |
1086
+ | `--nk-pink-600` | `oklch(59.2% 0.239 0.2)` |
1087
+ | `--nk-pink-700` | `oklch(52.5% 0.213 3.9)` |
1088
+ | `--nk-pink-800` | `oklch(46.8% 0.188 3.7)` |
1089
+ | `--nk-pink-900` | `oklch(39.8% 0.152 3.1)` |
1090
+ | `--nk-pink-950` | `oklch(29.3% 0.109 3.2)` |
1091
+
1092
+ #### Rose
1093
+
1094
+ | Token | Value |
1095
+ | --------------- | ------------------------- |
1096
+ | `--nk-rose-50` | `oklch(96.9% 0.015 12.9)` |
1097
+ | `--nk-rose-100` | `oklch(94.2% 0.027 11.4)` |
1098
+ | `--nk-rose-200` | `oklch(89% 0.058 10.9)` |
1099
+ | `--nk-rose-300` | `oklch(80.7% 0.112 11.2)` |
1100
+ | `--nk-rose-400` | `oklch(71.3% 0.184 13.5)` |
1101
+ | `--nk-rose-500` | `oklch(64.5% 0.244 16.2)` |
1102
+ | `--nk-rose-600` | `oklch(58.6% 0.243 17.6)` |
1103
+ | `--nk-rose-700` | `oklch(51.4% 0.212 16.9)` |
1104
+ | `--nk-rose-800` | `oklch(46.4% 0.185 13.4)` |
1105
+ | `--nk-rose-900` | `oklch(40% 0.157 10.9)` |
1106
+ | `--nk-rose-950` | `oklch(28.1% 0.107 11.4)` |
1107
+
1108
+ ### Tint palette
1109
+
1110
+ `Badge` carries two color vocabularies on one `color:` option. The semantic
1111
+ families answer "what does this mean"; the seventeen decorative hues answer
1112
+ "which color is this", for categorical labelling where meaning is not the
1113
+ point. Both resolve through `--nk-palette-*` tint roles.
1114
+
1115
+ The distinction is deliberate: `color: :destructive` follows `--nk-palette-destructive`
1116
+ and moves when an application rethemes its destructive tint, while `color:
1117
+ :red` follows `--nk-palette-red` and stays red. By default the two agree —
1118
+ each semantic family samples the same scale steps as its hue family, so
1119
+ `destructive` and `red` render identically until a theme separates them.
1120
+
1121
+ Each tint is appearance independent; the paired `-content` foreground resolves
1122
+ per appearance so labels stay readable in both.
1123
+
1124
+ | Token | Role |
1125
+ | ---------------------------------- | ----------------------------------------- |
1126
+ | `--nk-palette-neutral` | Neutral status tint; defaults to zinc. |
1127
+ | `--nk-palette-neutral-content` | Neutral status content on that tint. |
1128
+ | `--nk-palette-info` | Info status tint; defaults to blue. |
1129
+ | `--nk-palette-info-content` | Info status content on that tint. |
1130
+ | `--nk-palette-success` | Success status tint; defaults to green. |
1131
+ | `--nk-palette-success-content` | Success status content on that tint. |
1132
+ | `--nk-palette-warning` | Warning status tint; defaults to amber. |
1133
+ | `--nk-palette-warning-content` | Warning status content on that tint. |
1134
+ | `--nk-palette-destructive` | Destructive status tint; defaults to red. |
1135
+ | `--nk-palette-destructive-content` | Destructive status content on that tint. |
1136
+ | `--nk-palette-red` | Red tint and marker. |
1137
+ | `--nk-palette-red-content` | Red content on that tint. |
1138
+ | `--nk-palette-orange` | Orange tint and marker. |
1139
+ | `--nk-palette-orange-content` | Orange content on that tint. |
1140
+ | `--nk-palette-amber` | Amber tint and marker. |
1141
+ | `--nk-palette-amber-content` | Amber content on that tint. |
1142
+ | `--nk-palette-yellow` | Yellow tint and marker. |
1143
+ | `--nk-palette-yellow-content` | Yellow content on that tint. |
1144
+ | `--nk-palette-lime` | Lime tint and marker. |
1145
+ | `--nk-palette-lime-content` | Lime content on that tint. |
1146
+ | `--nk-palette-green` | Green tint and marker. |
1147
+ | `--nk-palette-green-content` | Green content on that tint. |
1148
+ | `--nk-palette-emerald` | Emerald tint and marker. |
1149
+ | `--nk-palette-emerald-content` | Emerald content on that tint. |
1150
+ | `--nk-palette-teal` | Teal tint and marker. |
1151
+ | `--nk-palette-teal-content` | Teal content on that tint. |
1152
+ | `--nk-palette-cyan` | Cyan tint and marker. |
1153
+ | `--nk-palette-cyan-content` | Cyan content on that tint. |
1154
+ | `--nk-palette-sky` | Sky tint and marker. |
1155
+ | `--nk-palette-sky-content` | Sky content on that tint. |
1156
+ | `--nk-palette-blue` | Blue tint and marker. |
1157
+ | `--nk-palette-blue-content` | Blue content on that tint. |
1158
+ | `--nk-palette-indigo` | Indigo tint and marker. |
1159
+ | `--nk-palette-indigo-content` | Indigo content on that tint. |
1160
+ | `--nk-palette-violet` | Violet tint and marker. |
1161
+ | `--nk-palette-violet-content` | Violet content on that tint. |
1162
+ | `--nk-palette-purple` | Purple tint and marker. |
1163
+ | `--nk-palette-purple-content` | Purple content on that tint. |
1164
+ | `--nk-palette-fuchsia` | Fuchsia tint and marker. |
1165
+ | `--nk-palette-fuchsia-content` | Fuchsia content on that tint. |
1166
+ | `--nk-palette-pink` | Pink tint and marker. |
1167
+ | `--nk-palette-pink-content` | Pink content on that tint. |
1168
+ | `--nk-palette-rose` | Rose tint and marker. |
1169
+ | `--nk-palette-rose-content` | Rose content on that tint. |
572
1170
 
573
1171
  ### Default button colors
574
1172