silvery 0.19.2 → 0.21.0

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 (218) hide show
  1. package/README.md +9 -4
  2. package/dist/Text-Lq0dmj8-.mjs +239 -0
  3. package/dist/Text-Lq0dmj8-.mjs.map +1 -0
  4. package/dist/UPNG-Bo33r8rA.mjs +3 -0
  5. package/dist/UPNG-DosRPdF4.mjs +5075 -0
  6. package/dist/UPNG-DosRPdF4.mjs.map +1 -0
  7. package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs +6 -0
  8. package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs.map +1 -0
  9. package/dist/{animation-Cn64yepo.mjs → animation-ZMN2_XKv.mjs} +2 -2
  10. package/dist/animation-ZMN2_XKv.mjs.map +1 -0
  11. package/dist/{ansi-Cc33mW54.d.mts → ansi-2Xn0yatP.d.mts} +1 -1
  12. package/dist/{ansi-Cc33mW54.d.mts.map → ansi-2Xn0yatP.d.mts.map} +1 -1
  13. package/dist/{ansi-CLOitHKx.mjs → ansi-D1KQMAbf.mjs} +1 -1
  14. package/dist/{ansi-CLOitHKx.mjs.map → ansi-D1KQMAbf.mjs.map} +1 -1
  15. package/dist/ansi-yC4RyBNY.mjs +22441 -0
  16. package/dist/ansi-yC4RyBNY.mjs.map +1 -0
  17. package/dist/apng-CR08rIaH.mjs +58 -0
  18. package/dist/apng-CR08rIaH.mjs.map +1 -0
  19. package/dist/apng-DaHfVaVI.mjs +3 -0
  20. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  21. package/dist/assets/skia.darwin-arm64-DQs5sT6N.node +0 -0
  22. package/dist/backend-B-WYLUib.mjs +13396 -0
  23. package/dist/backend-B-WYLUib.mjs.map +1 -0
  24. package/dist/backends-CUtan80W.mjs +3 -0
  25. package/dist/backends-DIVYzKqd.mjs +1083 -0
  26. package/dist/backends-DIVYzKqd.mjs.map +1 -0
  27. package/dist/bound-term-0sPrrzH1.d.mts +4640 -0
  28. package/dist/bound-term-0sPrrzH1.d.mts.map +1 -0
  29. package/dist/canvas-1v7dPT-_.mjs +3 -0
  30. package/dist/canvas-CSuPOMNt.mjs +1442 -0
  31. package/dist/canvas-CSuPOMNt.mjs.map +1 -0
  32. package/dist/{chunk-Vs_PY4HZ.mjs → chunk-BSw8zbkd.mjs} +1 -1
  33. package/dist/cli-dvo0r2fs.mjs +4 -0
  34. package/dist/compare-CQodSH4G.mjs +376 -0
  35. package/dist/compare-CQodSH4G.mjs.map +1 -0
  36. package/dist/compare-DHlcxEYA.mjs +3 -0
  37. package/dist/context-BU5LkkIy.mjs.map +1 -1
  38. package/dist/devtools-CJdt5H0X.mjs +2 -0
  39. package/dist/{devtools-DxkSLXDA.mjs → devtools-DcQjgyjL.mjs} +5 -4
  40. package/dist/{devtools-DxkSLXDA.mjs.map → devtools-DcQjgyjL.mjs.map} +1 -1
  41. package/dist/easing-BI-ASGMO.d.mts +24 -0
  42. package/dist/easing-BI-ASGMO.d.mts.map +1 -0
  43. package/dist/{eta-Bb3RH3wh.mjs → eta-CJlGH06n.mjs} +1 -1
  44. package/dist/{eta-Bb3RH3wh.mjs.map → eta-CJlGH06n.mjs.map} +1 -1
  45. package/dist/flexily-zero-adapter-C3Vj0fPt.mjs +306 -0
  46. package/dist/flexily-zero-adapter-C3Vj0fPt.mjs.map +1 -0
  47. package/dist/{flexily-zero-adapter-CMxXhdOL.mjs → flexily-zero-adapter-C4lW_Ov5.mjs} +1 -1
  48. package/dist/fonts-BFmhXDv7.mjs +88 -0
  49. package/dist/fonts-BFmhXDv7.mjs.map +1 -0
  50. package/dist/gif-C_AjaT9d.mjs +188 -0
  51. package/dist/gif-C_AjaT9d.mjs.map +1 -0
  52. package/dist/gif-DaC4XrxA.mjs +3 -0
  53. package/dist/gifenc-BOUT-KFB.mjs +730 -0
  54. package/dist/gifenc-BOUT-KFB.mjs.map +1 -0
  55. package/dist/image-C2Birh2x.mjs +1252 -0
  56. package/dist/image-C2Birh2x.mjs.map +1 -0
  57. package/dist/index-BUMxS65f.d.mts +453 -0
  58. package/dist/index-BUMxS65f.d.mts.map +1 -0
  59. package/dist/{index-D3saHouR.d.mts → index-CSQf13CI.d.mts} +1057 -1133
  60. package/dist/index-CSQf13CI.d.mts.map +1 -0
  61. package/dist/{index-BXslOebb.d.mts → index-Cl9KKjQ_.d.mts} +4919 -3921
  62. package/dist/index-Cl9KKjQ_.d.mts.map +1 -0
  63. package/dist/index-XbNrPhWl.d.mts +336 -0
  64. package/dist/index-XbNrPhWl.d.mts.map +1 -0
  65. package/dist/index.d.mts +8 -5
  66. package/dist/index.d.mts.map +1 -1
  67. package/dist/index.mjs +14 -12
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/key-mapping-CS-YD_cD.mjs +132 -0
  70. package/dist/key-mapping-CS-YD_cD.mjs.map +1 -0
  71. package/dist/key-mapping-Yn-Jgrij.mjs +3 -0
  72. package/dist/{layout-engine-B6Cdz1yZ.mjs → layout-engine-C07LEXWT.mjs} +1 -1
  73. package/dist/layout-engine-C2px0RJE.mjs +67 -0
  74. package/dist/layout-engine-C2px0RJE.mjs.map +1 -0
  75. package/dist/layout-signals-Cnw6xk8Q.mjs +988 -0
  76. package/dist/layout-signals-Cnw6xk8Q.mjs.map +1 -0
  77. package/dist/mouse-events-Dki3ISIp.mjs +1044 -0
  78. package/dist/mouse-events-Dki3ISIp.mjs.map +1 -0
  79. package/dist/{multi-progress-Bq9Oi_WI.mjs → multi-progress-CIRjrzma.mjs} +3 -3
  80. package/dist/{multi-progress-Bq9Oi_WI.mjs.map → multi-progress-CIRjrzma.mjs.map} +1 -1
  81. package/dist/{multi-progress-DAQC7eap.d.mts → multi-progress-DHZ2xUT2.d.mts} +2 -2
  82. package/dist/{multi-progress-DAQC7eap.d.mts.map → multi-progress-DHZ2xUT2.d.mts.map} +1 -1
  83. package/dist/{node-BeWlnCPY.mjs → node-CjM5Rt-M.mjs} +4 -4
  84. package/dist/node-CjM5Rt-M.mjs.map +1 -0
  85. package/dist/playwright-D5YiZcNS.mjs +76397 -0
  86. package/dist/playwright-D5YiZcNS.mjs.map +1 -0
  87. package/dist/png-codec-Dp84742B.mjs +36 -0
  88. package/dist/png-codec-Dp84742B.mjs.map +1 -0
  89. package/dist/png-codec-QwOtJ8Zs.mjs +3 -0
  90. package/dist/progress-DB_Xo071.mjs +675 -0
  91. package/dist/progress-DB_Xo071.mjs.map +1 -0
  92. package/dist/{progress-bar-CXE5Qfkd.mjs → progress-bar-oJwq22CR.mjs} +4 -4
  93. package/dist/{progress-bar-CXE5Qfkd.mjs.map → progress-bar-oJwq22CR.mjs.map} +1 -1
  94. package/dist/rasterizer-BRXrDdWx.mjs +3 -0
  95. package/dist/rasterizer-CpEhJvdR.mjs +296 -0
  96. package/dist/rasterizer-CpEhJvdR.mjs.map +1 -0
  97. package/dist/reconciler-DldIJB93.mjs +2083 -0
  98. package/dist/reconciler-DldIJB93.mjs.map +1 -0
  99. package/dist/{render-string-CDCeYkS3.mjs → render-string-BcoCpjCB.mjs} +1 -1
  100. package/dist/{render-string-Darrg7ku.mjs → render-string-DkQacASz.mjs} +2707 -549
  101. package/dist/render-string-DkQacASz.mjs.map +1 -0
  102. package/dist/resvg-js-DkOndZI3.mjs +203 -0
  103. package/dist/resvg-js-DkOndZI3.mjs.map +1 -0
  104. package/dist/runtime.d.mts +3 -2
  105. package/dist/runtime.mjs +3 -3
  106. package/dist/schemes-JjNp4aSl.mjs +2611 -0
  107. package/dist/schemes-JjNp4aSl.mjs.map +1 -0
  108. package/dist/{spinner-CGo34vyR.d.mts → spinner-CZINHpkV.d.mts} +2 -2
  109. package/dist/{spinner-CGo34vyR.d.mts.map → spinner-CZINHpkV.d.mts.map} +1 -1
  110. package/dist/{spinner-CeOmcuw_.mjs → spinner-D9lrHr8s.mjs} +7 -7
  111. package/dist/spinner-D9lrHr8s.mjs.map +1 -0
  112. package/dist/src-5w9QR6_8.mjs +1071 -0
  113. package/dist/src-5w9QR6_8.mjs.map +1 -0
  114. package/dist/src-BNTToU7l.mjs +4387 -0
  115. package/dist/src-BNTToU7l.mjs.map +1 -0
  116. package/dist/{src-CF-6UN01.mjs → src-BR4xNwdG.mjs} +10436 -2622
  117. package/dist/src-BR4xNwdG.mjs.map +1 -0
  118. package/dist/{types-Bk2yw9Qj.mjs → src-DKp-_OFG.mjs} +34 -94
  119. package/dist/src-DKp-_OFG.mjs.map +1 -0
  120. package/dist/src-bt8wSrfJ.mjs +258 -0
  121. package/dist/src-bt8wSrfJ.mjs.map +1 -0
  122. package/dist/src-e33Y6kNJ.mjs +3 -0
  123. package/dist/src-iDwu25UD.mjs +1814 -0
  124. package/dist/src-iDwu25UD.mjs.map +1 -0
  125. package/dist/steps-Bp2uNqnn.d.mts +202 -0
  126. package/dist/steps-Bp2uNqnn.d.mts.map +1 -0
  127. package/dist/svg-15lZZzxq.mjs +486 -0
  128. package/dist/svg-15lZZzxq.mjs.map +1 -0
  129. package/dist/svg-Cz0UXcDj.mjs +255 -0
  130. package/dist/svg-Cz0UXcDj.mjs.map +1 -0
  131. package/dist/svg-DY72a4HK.mjs +3 -0
  132. package/dist/svg-g1D6ErwR.d.mts +82 -0
  133. package/dist/svg-g1D6ErwR.d.mts.map +1 -0
  134. package/dist/term.d.mts +3 -0
  135. package/dist/term.mjs +9 -0
  136. package/dist/term.mjs.map +1 -0
  137. package/dist/theme.d.mts +95 -2
  138. package/dist/theme.d.mts.map +1 -0
  139. package/dist/theme.mjs +9 -3
  140. package/dist/theme.mjs.map +1 -0
  141. package/dist/{types-BH_v3iMT.d.mts → types-kt_fKR37.d.mts} +2 -15
  142. package/dist/types-kt_fKR37.d.mts.map +1 -0
  143. package/dist/ui/animation.d.mts +2 -1
  144. package/dist/ui/animation.mjs +1 -1
  145. package/dist/ui/ansi.d.mts +1 -1
  146. package/dist/ui/ansi.mjs +1 -1
  147. package/dist/ui/cli.d.mts +3 -3
  148. package/dist/ui/cli.mjs +5 -5
  149. package/dist/ui/display.d.mts +1 -1
  150. package/dist/ui/image.d.mts +2 -2
  151. package/dist/ui/image.mjs +2 -2
  152. package/dist/ui/input.d.mts +1 -1
  153. package/dist/ui/input.mjs +4 -2
  154. package/dist/ui/input.mjs.map +1 -1
  155. package/dist/ui/progress.d.mts +5 -249
  156. package/dist/ui/progress.mjs +5 -858
  157. package/dist/ui/react.d.mts +1 -1
  158. package/dist/ui/react.mjs +2 -2
  159. package/dist/ui/recording-chrome-react.d.mts +21 -0
  160. package/dist/ui/recording-chrome-react.d.mts.map +1 -0
  161. package/dist/ui/recording-chrome-react.mjs +105 -0
  162. package/dist/ui/recording-chrome-react.mjs.map +1 -0
  163. package/dist/ui/recording-chrome.d.mts +2 -0
  164. package/dist/ui/recording-chrome.mjs +2 -0
  165. package/dist/ui/utils.mjs +1 -1
  166. package/dist/ui/wrappers.d.mts +3 -3
  167. package/dist/ui/wrappers.mjs +2 -2
  168. package/dist/ui.d.mts +7 -6
  169. package/dist/ui.mjs +8 -7
  170. package/dist/{useLatest-Bg2x4bfP.d.mts → useLatest-DRDDVwjh.d.mts} +5 -25
  171. package/dist/useLatest-DRDDVwjh.d.mts.map +1 -0
  172. package/dist/{with-text-input-CRfoiFFG.d.mts → with-text-input-YeohVLeo.d.mts} +4 -55
  173. package/dist/with-text-input-YeohVLeo.d.mts.map +1 -0
  174. package/dist/wrapper-C70ATkVv.mjs +3527 -0
  175. package/dist/wrapper-C70ATkVv.mjs.map +1 -0
  176. package/dist/{wrappers-UTADQkSY.mjs → wrappers-BCUYITrY.mjs} +5 -157
  177. package/dist/wrappers-BCUYITrY.mjs.map +1 -0
  178. package/dist/{yoga-adapter-8oRGRw8V.mjs → yoga-adapter-BnZX1PAY.mjs} +28 -2
  179. package/dist/yoga-adapter-BnZX1PAY.mjs.map +1 -0
  180. package/dist/yoga-adapter-DxgsQ_gg.mjs +2 -0
  181. package/dist/zipBundle-3nqeDRtm.mjs +3 -0
  182. package/dist/zipBundle-VNAYFmqJ.mjs +2003 -0
  183. package/dist/zipBundle-VNAYFmqJ.mjs.map +1 -0
  184. package/package.json +20 -9
  185. package/dist/animation-Cn64yepo.mjs.map +0 -1
  186. package/dist/cli-BKp0YtBD.mjs +0 -4
  187. package/dist/devtools-9QY4teqI.mjs +0 -2
  188. package/dist/flexily-zero-adapter-BlQa46nr.mjs +0 -3385
  189. package/dist/flexily-zero-adapter-BlQa46nr.mjs.map +0 -1
  190. package/dist/image-CTII5QWI.mjs +0 -477
  191. package/dist/image-CTII5QWI.mjs.map +0 -1
  192. package/dist/index-BXslOebb.d.mts.map +0 -1
  193. package/dist/index-BnA7mNpo.d.mts +0 -175
  194. package/dist/index-BnA7mNpo.d.mts.map +0 -1
  195. package/dist/index-D3saHouR.d.mts.map +0 -1
  196. package/dist/layout-engine-ClUgv6jB.mjs +0 -50
  197. package/dist/layout-engine-ClUgv6jB.mjs.map +0 -1
  198. package/dist/node-BeWlnCPY.mjs.map +0 -1
  199. package/dist/reconciler-Cwgm8hRR.mjs +0 -8459
  200. package/dist/reconciler-Cwgm8hRR.mjs.map +0 -1
  201. package/dist/render-string-Darrg7ku.mjs.map +0 -1
  202. package/dist/spinner-CeOmcuw_.mjs.map +0 -1
  203. package/dist/src-B5GjfG7g.mjs +0 -4305
  204. package/dist/src-B5GjfG7g.mjs.map +0 -1
  205. package/dist/src-CChwjk0Z.mjs +0 -738
  206. package/dist/src-CChwjk0Z.mjs.map +0 -1
  207. package/dist/src-CF-6UN01.mjs.map +0 -1
  208. package/dist/src-NCKb8kE5.mjs +0 -2660
  209. package/dist/src-NCKb8kE5.mjs.map +0 -1
  210. package/dist/types-BH_v3iMT.d.mts.map +0 -1
  211. package/dist/types-Bk2yw9Qj.mjs.map +0 -1
  212. package/dist/ui/progress.d.mts.map +0 -1
  213. package/dist/ui/progress.mjs.map +0 -1
  214. package/dist/useLatest-Bg2x4bfP.d.mts.map +0 -1
  215. package/dist/with-text-input-CRfoiFFG.d.mts.map +0 -1
  216. package/dist/wrappers-UTADQkSY.mjs.map +0 -1
  217. package/dist/yoga-adapter-8oRGRw8V.mjs.map +0 -1
  218. package/dist/yoga-adapter-D_CcxSt5.mjs +0 -2
@@ -1,136 +1,40 @@
1
- //#region packages/ansi/src/detection.d.ts
2
- interface TerminalCaps {
3
- /** Terminal program name (from TERM_PROGRAM) */
4
- program: string;
5
- /** TERM value */
6
- term: string;
7
- /** Color support level */
8
- colorLevel: "none" | "basic" | "256" | "truecolor";
9
- /** Kitty keyboard protocol supported */
10
- kittyKeyboard: boolean;
11
- /** Kitty graphics protocol (inline images) */
12
- kittyGraphics: boolean;
13
- /** Sixel graphics supported */
14
- sixel: boolean;
15
- /** OSC 52 clipboard */
16
- osc52: boolean;
17
- /** OSC 8 hyperlinks */
18
- hyperlinks: boolean;
19
- /** OSC 9/99 notifications */
20
- notifications: boolean;
21
- /** Bracketed paste mode */
22
- bracketedPaste: boolean;
23
- /** SGR mouse tracking */
24
- mouse: boolean;
25
- /** Synchronized output (DEC 2026) */
26
- syncOutput: boolean;
27
- /** Unicode/emoji support */
28
- unicode: boolean;
29
- /** SGR 4:x underline style subparameters (curly, dotted, dashed) */
30
- underlineStyles: boolean;
31
- /** SGR 58 underline color */
32
- underlineColor: boolean;
33
- /** Text-presentation emoji (⚠, ☑, ⭐) rendered as 2-wide.
34
- * Modern terminals (Ghostty, iTerm, Kitty) render these at emoji width (2 cells).
35
- * Terminal.app renders them at text width (1 cell). */
36
- textEmojiWide: boolean;
37
- /** OSC 66 text sizing protocol likely supported (Kitty 0.40+, Ghostty) */
38
- textSizingSupported: boolean;
39
- /** Heuristic: likely dark background (for theme selection) */
40
- darkBackground: boolean;
41
- /** Heuristic: likely has Nerd Font installed (for icon selection) */
42
- nerdfont: boolean;
43
- }
44
- /**
45
- * Default capabilities (assumes modern terminal with full support).
46
- */
47
- declare function defaultCaps(): TerminalCaps;
48
- /** Detect terminal capabilities from environment variables.
49
- * Synchronous. Minimal I/O: may run `defaults` on macOS for Apple_Terminal.
50
- */
51
- declare function detectTerminalCaps(): TerminalCaps;
52
- //#endregion
53
- //#region packages/ansi/src/types.d.ts
54
- /**
55
- * Type definitions for @silvery/ansi
56
- */
57
- /**
58
- * Color level supported by terminal.
59
- * - 'basic': 16 colors (SGR 30-37, 40-47)
60
- * - '256': 256 colors (SGR 38;5;n)
61
- * - 'truecolor': 16M colors (SGR 38;2;r;g;b)
62
- */
63
- type ColorLevel = "basic" | "256" | "truecolor";
64
- //#endregion
65
- //#region packages/ansi/src/color-maps.d.ts
66
- /**
67
- * Color tier for preview quantization.
68
- *
69
- * Mirrors the tiers a real terminal would resolve to when the output phase
70
- * emits ANSI: `truecolor` (pass-through), `256` (6×6×6 cube + grayscale ramp),
71
- * `ansi16` (nearest of 16 slots), `mono` (luminance → black/white).
72
- */
73
- type ColorTier = "truecolor" | "256" | "ansi16" | "mono";
1
+ //#region packages/ansi/src/emulator.d.ts
74
2
  /**
75
- * Hex-in / hex-out quantization for previews.
76
- *
77
- * Takes any hex color and returns the hex a real terminal at that tier would
78
- * actually emit. Used by the Sterling storybook to make the `1/2/3/4` tier
79
- * toggle visibly different in-process — the output phase already does this
80
- * when writing to a real TTY, but preview surfaces (theme swatches, rendered
81
- * components inside a storybook app) bypass output-phase quantization. Apply
82
- * `quantizeHex` at render time to mimic tier-specific terminal output.
3
+ * Terminal emulator identity facts about *what terminal this IS*, as
4
+ * opposed to {@link ./caps#TerminalCaps} which describes what it can DO.
83
5
  *
84
- * - `truecolor`: returns the input unchanged (normalized to `#rrggbb`).
85
- * - `256`: snaps to the nearest xterm-256 slot, then returns that slot's hex.
86
- * - `ansi16`: snaps to one of the 16 standard slots (canonical xterm RGB).
87
- * - `mono`: luminance threshold (>= 0.5 → `#ffffff`, else `#000000`).
6
+ * Identity doesn't gate rendering; it's what tests, diagnostics, and
7
+ * probe-cache keys discriminate on (e.g. `program@version` is the cache key
8
+ * used by `@silvery/ag-term/text-sizing` per km-silvery.unicode-plateau
9
+ * Phase 2).
88
10
  *
89
- * Returns the input unchanged if it cannot be parsed as a hex color.
11
+ * Resolved once by {@link ./profile#createTerminalProfile} and exposed as
12
+ * `profile.emulator` — no other module reads TERM / TERM_PROGRAM.
90
13
  */
91
- declare function quantizeHex(hex: string, tier: ColorTier): string;
92
14
  /**
93
- * Pre-quantize every hex leaf in a Theme (or any object tree) to the
94
- * requested color tier.
95
- *
96
- * Walks the input recursively — each string leaf matching `#rgb` / `#rrggbb`
97
- * is passed through {@link quantizeHex}; all other values (numbers, booleans,
98
- * non-hex strings like `"Nord"`, null/undefined, arrays of non-hex values)
99
- * pass through unchanged. Arrays and nested objects are rebuilt with
100
- * quantized leaves.
101
- *
102
- * Works on both the legacy ANSI Theme (flat hex tokens + `palette` array)
103
- * and the Sterling Theme (nested roles + flat tokens) — the structural rule
104
- * "any leaf that looks like a hex is a color value" holds for both.
105
- *
106
- * @example Pre-cache tier variants
107
- * ```ts
108
- * import { pickColorLevel } from "silvery"
109
- *
110
- * const themes = {
111
- * truecolor: theme,
112
- * ansi16: pickColorLevel(theme, "ansi16"),
113
- * mono: pickColorLevel(theme, "mono"),
114
- * }
115
- * ```
116
- *
117
- * @example Storybook — show multiple tiers simultaneously
118
- * ```tsx
119
- * <ThemeProvider theme={pickColorLevel(theme, "ansi16")}>
120
- * <AlertPreview />
121
- * </ThemeProvider>
122
- * ```
123
- *
124
- * Notes:
125
- * - `truecolor` is a no-op — returns the input unchanged (identity).
126
- * - The result is structurally identical to the input (same keys, same
127
- * nesting); only hex leaves are remapped.
128
- * - Idempotent per tier: `pickColorLevel(pickColorLevel(t, "ansi16"), "ansi16")`
129
- * yields the same hex values as `pickColorLevel(t, "ansi16")`.
130
- * - Does not freeze the returned object. Callers that want immutability
131
- * should `Object.freeze()` (or deep-freeze) the result themselves.
15
+ * Environment identity facts about what terminal this IS. Separate from
16
+ * {@link ./caps#TerminalCaps} because identity doesn't gate rendering; it's
17
+ * what tests, diagnostics, and probe-cache keys discriminate on.
18
+ *
19
+ * Post km-silvery.plateau-naming-polish (2026-04-23): renamed from
20
+ * `TerminalIdentity` `TerminalEmulator` (the thing IS a terminal emulator,
21
+ * matches `TERM_PROGRAM` provenance) and `termName` `TERM` (matches the
22
+ * env var name and shell convention).
132
23
  */
133
- declare function pickColorLevel<T>(theme: T, tier: ColorTier): T;
24
+ interface TerminalEmulator {
25
+ /** Terminal program name (from TERM_PROGRAM). */
26
+ readonly program: string;
27
+ /** Terminal program version string (from TERM_PROGRAM_VERSION). Empty when
28
+ * the host doesn't advertise a version. Together with `program`, forms the
29
+ * `program@version` fingerprint used as the probe-cache key in
30
+ * `@silvery/ag-term/text-sizing`. See km-silvery.unicode-plateau Phase 2. */
31
+ readonly version: string;
32
+ /** Value of the `TERM` env var (`"xterm-kitty"`, `"xterm-256color"`, …).
33
+ * Named `TERM` rather than `termName` to mirror the env-var name
34
+ * explicitly — the field's sole source is the `TERM` environment entry,
35
+ * resolved once by `createTerminalProfile`. */
36
+ readonly TERM: string;
37
+ }
134
38
  //#endregion
135
39
  //#region packages/ansi/src/flatten.d.ts
136
40
  /**
@@ -219,190 +123,405 @@ declare const defaultFlattenRule: FlattenRule;
219
123
  */
220
124
  declare function bakeFlat<T extends object>(theme: T, rule?: FlattenRule): T;
221
125
  //#endregion
222
- //#region packages/ansi/src/terminal-control.d.ts
126
+ //#region packages/ansi/src/sterling/types.d.ts
223
127
  /**
224
- * Enable mouse tracking with full hover support.
225
- *
226
- * Uses two modes:
227
- * - **1003** (any-event tracking): Reports ALL mouse motion — clicks, drags, AND hover.
228
- * This is what makes onMouseEnter/onMouseLeave work. Without it, only clicks are reported.
229
- * - **1006** (SGR encoding): Decimal coordinates with no 223-column limit.
128
+ * Surface-only state pair: only `bg` varies by state. Used by the status
129
+ * roles (`info`, `success`, `warning`, `error`) where state variants are
130
+ * meaningful only for surfaces (filled bg), never for text.
230
131
  *
231
- * WARNING: Do NOT replace 1003 with 1000+1002. The xterm mouse modes form a hierarchy:
232
- * 1000 = clicks only
233
- * 1002 = clicks + drag (motion while button held)
234
- * 1003 = clicks + drag + hover (ALL motion, even without button)
235
- * Mode 1003 supersedes 1000 and 1002. Using 1000+1002 instead of 1003 silently
236
- * disables hover — onMouseEnter/onMouseLeave stop firing with no error.
132
+ * Text tokens on status roles don't hover `fg-error` is a status color,
133
+ * not an interactive link. Keeping `fg.hover` / `fg.active` on those roles
134
+ * invited algorithmic over-generation that produced illegible results
135
+ * (e.g. catppuccin-frappe `warning.active.fg` collapsing to `#FFFFFF`).
237
136
  */
238
- declare function enableMouse(): string;
137
+ interface BgStatePair {
138
+ readonly bg: string;
139
+ }
239
140
  /**
240
- * Disable mouse tracking. Disables in reverse order of enabling.
141
+ * Interactive (link-like) state pair: both `fg` and `bg` vary by state.
142
+ * Used by `accent` — the canonical interactive-text role.
241
143
  */
242
- declare function disableMouse(): string;
144
+ interface StatePair {
145
+ readonly fg: string;
146
+ readonly bg: string;
147
+ }
243
148
  /**
244
- * Enable the Kitty keyboard protocol (push mode).
245
- *
246
- * Sends CSI > flags u to opt into the specified modes.
247
- * Supported by: Ghostty, Kitty, WezTerm, foot. Ignored by unsupported terminals.
248
- *
249
- * Flags are a bitfield:
250
- *
251
- * | Flag | Bit | Description |
252
- * | ---- | --- | ----------------------------------------- |
253
- * | 1 | 0 | Disambiguate escape codes |
254
- * | 2 | 1 | Report event types (press/repeat/release) |
255
- * | 4 | 2 | Report alternate keys |
256
- * | 8 | 3 | Report all keys as escape codes |
257
- * | 16 | 4 | Report associated text |
149
+ * A status role fg, bg, and `fgOn` (text color to draw when rendering ON
150
+ * a filled bg of this role). State variants apply to SURFACE (bg) only;
151
+ * text-color state variants are reserved for link-like roles (`accent`).
258
152
  *
259
- * @param flags Bitfield of Kitty keyboard flags
153
+ * Used for the four status families: `info`, `success`, `warning`, `error`.
260
154
  */
261
- declare function enableKittyKeyboard(flags?: number): string;
155
+ interface StatusRole {
156
+ /** Foreground hex — use for text/icon in this role. */
157
+ readonly fg: string;
158
+ /** Background hex — use as fill for emphasis. */
159
+ readonly bg: string;
160
+ /** Foreground to use when drawing ON `bg` (contrast-picked). */
161
+ readonly fgOn: string;
162
+ /** Hover state — surface only (adaptive ±L shift on bg). */
163
+ readonly hover: BgStatePair;
164
+ /** Active (pressed) state — surface only (adaptive ±L shift on bg). */
165
+ readonly active: BgStatePair;
166
+ }
262
167
  /**
263
- * Disable the Kitty keyboard protocol (pop mode stack).
264
- * Sends CSI < u to restore the previous keyboard mode.
168
+ * @deprecated Renamed to `StatusRole` for clarity (the family lacks the
169
+ * `fg.hover/active` interaction states the old name implied). The alias is
170
+ * retained for one cycle so external consumers don't break on rename.
265
171
  */
266
- declare function disableKittyKeyboard(): string;
267
- //#endregion
268
- //#region packages/ansi/src/style/style.d.ts
172
+ type InteractiveRole = StatusRole;
269
173
  /**
270
- * Resolve a color value against a theme — the canonical token resolver.
271
- *
272
- * If the color starts with `$`, looks up the token in the theme.
273
- * Supports `$primary`, `$surface-bg` (hyphens stripped), `$color0`–`$color15` (palette).
274
- * Non-`$` strings pass through unchanged. Returns undefined if no theme or unknown token.
275
- *
276
- * Compatible with @silvery/theme's Theme type (or any object with string properties).
174
+ * Accent — the canonical link-like interactive-text role. Has everything
175
+ * `StatusRole` does PLUS a focus-ring border AND `fg.hover` /
176
+ * `fg.active` text-color state variants (link hover treatments).
277
177
  */
278
- declare function resolveThemeColor(name: string | undefined, theme: object | undefined): string | undefined;
279
- //#endregion
280
- //#region packages/ansi/src/theme/types.d.ts
178
+ interface AccentRole {
179
+ /** Foreground hex — use for text/icon in accent. */
180
+ readonly fg: string;
181
+ /** Background hex — use as fill for emphasis. */
182
+ readonly bg: string;
183
+ /** Foreground to use when drawing ON `bg` (contrast-picked). */
184
+ readonly fgOn: string;
185
+ /** Border color for focus rings using this accent. */
186
+ readonly border: string;
187
+ /** Hover state — both fg (link hover) and bg (surface hover). */
188
+ readonly hover: StatePair;
189
+ /** Active (pressed) state — both fg and bg. */
190
+ readonly active: StatePair;
191
+ }
192
+ /** Surface hierarchy — `default` is the canvas, subtle/raised/overlay stack upward. */
193
+ interface SurfaceRole {
194
+ readonly default: string;
195
+ readonly subtle: string;
196
+ readonly raised: string;
197
+ readonly overlay: string;
198
+ readonly hover: string;
199
+ }
200
+ /** Border roles — `focus` is the focus-ring color; `default` is normal rule line. */
201
+ interface BorderRole {
202
+ readonly default: string;
203
+ readonly focus: string;
204
+ readonly muted: string;
205
+ }
206
+ /** Cursor colors. */
207
+ interface CursorRole {
208
+ readonly fg: string;
209
+ readonly bg: string;
210
+ }
211
+ /** Muted role — lower-emphasis text/bg for deemphasized content. */
212
+ interface MutedRole {
213
+ readonly fg: string;
214
+ readonly bg: string;
215
+ }
281
216
  /**
282
- * Core type definitions for the theme system.
283
- *
284
- * Two-layer architecture:
285
- * Layer 1: ColorScheme 22 terminal colors (what schemes expose; auto-detectable)
286
- * Layer 2: Theme — ~33 semantic tokens (what UI apps consume)
287
- *
288
- * Pipeline: Scheme catalog → ColorScheme (22) → deriveTheme() → Theme (33)
217
+ * Selected role the highlight surface for the cursor row, mouse selection,
218
+ * search-match highlight, and any "this is the active item" treatment.
219
+ * `fgOn` is the text color drawn on `bg`; `hover.bg` is the +0.04L shift used
220
+ * by SelectList row hover.
289
221
  */
290
- interface ColorScheme {
291
- name?: string;
292
- dark?: boolean;
293
- primary?: string;
294
- black: string;
295
- red: string;
296
- green: string;
297
- yellow: string;
298
- blue: string;
299
- magenta: string;
300
- cyan: string;
301
- white: string;
302
- brightBlack: string;
303
- brightRed: string;
304
- brightGreen: string;
305
- brightYellow: string;
306
- brightBlue: string;
307
- brightMagenta: string;
308
- brightCyan: string;
309
- brightWhite: string;
310
- foreground: string;
311
- background: string;
312
- cursorColor: string;
313
- cursorText: string;
314
- selectionBackground: string;
315
- selectionForeground: string;
222
+ interface SelectedRole {
223
+ readonly bg: string;
224
+ readonly fgOn: string;
225
+ readonly hover: BgStatePair;
316
226
  }
317
- declare const COLOR_SCHEME_FIELDS: readonly ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "brightBlack", "brightRed", "brightGreen", "brightYellow", "brightBlue", "brightMagenta", "brightCyan", "brightWhite", "foreground", "background", "cursorColor", "cursorText", "selectionBackground", "selectionForeground"];
318
- interface Theme$1 {
319
- name: string;
320
- bg: string;
321
- fg: string;
322
- muted: string;
323
- mutedbg: string;
324
- surface: string;
325
- surfacebg: string;
326
- popover: string;
327
- popoverbg: string;
328
- inverse: string;
329
- inversebg: string;
330
- cursor: string;
331
- cursorbg: string;
332
- selection: string;
333
- selectionbg: string;
334
- primary: string;
335
- primaryfg: string;
336
- secondary: string;
337
- secondaryfg: string;
338
- accent: string;
339
- accentfg: string;
340
- error: string;
341
- errorfg: string;
342
- warning: string;
343
- warningfg: string;
344
- success: string;
345
- successfg: string;
346
- info: string;
347
- infofg: string;
348
- border: string;
349
- inputborder: string;
350
- focusborder: string;
351
- link: string;
352
- disabledfg: string;
353
- palette: string[];
354
- brand: string;
355
- /** Kebab key for $brand-hover. Hover lightness shift (+0.04L OKLCH). */
356
- "brand-hover": string;
357
- /** Kebab key for $brand-active. Active lightness shift (+0.08L OKLCH). */
358
- "brand-active": string;
359
- /** Kebab key for $primary-hover. */
360
- "primary-hover": string;
361
- /** Kebab key for $primary-active. */
362
- "primary-active": string;
363
- /** Kebab key for $accent-hover. */
364
- "accent-hover": string;
365
- /** Kebab key for $accent-active. */
366
- "accent-active": string;
367
- /** Kebab key for $fg-hover. */
368
- "fg-hover": string;
369
- /** Kebab key for $fg-active. */
370
- "fg-active": string;
371
- /** Kebab key for $bg-selected-hover. */
372
- "bg-selected-hover": string;
373
- /** Kebab key for $bg-surface-hover. */
374
- "bg-surface-hover": string;
375
- red: string;
376
- orange: string;
377
- yellow: string;
378
- green: string;
379
- teal: string;
380
- blue: string;
381
- purple: string;
382
- pink: string;
383
- /**
384
- * Named typography variants — resolved by `<Text variant="h1">`.
385
- *
386
- * Each variant is a bundle of visual defaults (color, bold, italic, dim,
387
- * underlineStyle). Caller props always win over variant values — the variant
388
- * is the *default*, not an override.
389
- *
390
- * Apps extend variants via:
391
- * ```tsx
392
- * <ThemeProvider tokens={{ variants: { hero: { color: "$brand", bold: true } } }}>
393
- * ```
394
- */
395
- variants: Record<string, Variant$1>;
227
+ /**
228
+ * Inverse role — flipped surface used for status bars, modal chrome, the
229
+ * "you are here" inverse band. Subtle blend of fg into bg, with `fgOn`
230
+ * picked for AA contrast against the resulting surface.
231
+ */
232
+ interface InverseRole {
233
+ readonly bg: string;
234
+ readonly fgOn: string;
396
235
  }
397
236
  /**
398
- * Metadata describing how the active color scheme was determined.
399
- *
400
- * Returned by `detectScheme()` and surfaced at runtime via `useActiveScheme()`.
401
- * Lets apps log how the theme was detected ("catppuccin-mocha at 87% confidence via
402
- * fingerprint") or render a debug badge without re-running detection.
403
- *
404
- * @example
405
- * ```tsx
237
+ * Link role hyperlink text color. Distinct from `accent` so apps that want
238
+ * "link blue" (as opposed to the brand-derived accent) can opt in. Single
239
+ * `fg` slot links are text, not surfaces; if a link surface is ever needed,
240
+ * extend with `bg` + `fgOn` then.
241
+ */
242
+ interface LinkRole {
243
+ readonly fg: string;
244
+ }
245
+ /**
246
+ * Disabled role — neutral, deemphasized treatment for unavailable controls
247
+ * (read-only inputs, disabled buttons, inactive menu items). Composite-derived
248
+ * from the base interface tokens (`fg-default` / `border-default`) over
249
+ * `bg-surface-default`, NOT from accent/status families — disabled is meant
250
+ * to read as "absent / inactive", not as a muted error/success/etc.
251
+ *
252
+ * Derivation (per design-system.md §"Disabled derivation"):
253
+ * - `fg-disabled = composite(fg-default @ 0.38, bg-surface-default)`
254
+ * clamped to ≥3:1 contrast vs `bg-surface-default`
255
+ * - `border-disabled = composite(border-default @ 0.24, bg-surface-default)`
256
+ * - `bg-disabled = composite(border-default @ 0.12, bg-surface-default)`
257
+ */
258
+ interface DisabledRole {
259
+ readonly fg: string;
260
+ readonly bg: string;
261
+ readonly border: string;
262
+ }
263
+ /**
264
+ * The nested, programmatic form of a Theme. All leaf values are hex strings.
265
+ * Reached via `theme.accent.bg`, `theme.surface.raised`, etc.
266
+ */
267
+ interface Roles {
268
+ readonly accent: AccentRole;
269
+ readonly info: StatusRole;
270
+ readonly success: StatusRole;
271
+ readonly warning: StatusRole;
272
+ readonly error: StatusRole;
273
+ readonly muted: MutedRole;
274
+ readonly surface: SurfaceRole;
275
+ readonly border: BorderRole;
276
+ readonly cursor: CursorRole;
277
+ readonly selected: SelectedRole;
278
+ readonly inverse: InverseRole;
279
+ readonly link: LinkRole;
280
+ readonly disabled: DisabledRole;
281
+ }
282
+ /**
283
+ * Every flat hyphen-key that Sterling emits. String-literal union so that
284
+ * `theme["bg-accent"]` is type-checked and typos fail the compile.
285
+ *
286
+ * Grammar: `prefix-role[-state]` or `prefix-on-role` or `prefix-role-kind[-state]`.
287
+ * (See design-system.md §"Flattening rule".)
288
+ */
289
+ type FlatToken = "bg-surface-default" | "bg-surface-subtle" | "bg-surface-raised" | "bg-surface-overlay" | "bg-surface-hover" | "border-default" | "border-focus" | "border-muted" | "fg-cursor" | "bg-cursor" | "fg-muted" | "bg-muted" | "fg-accent" | "bg-accent" | "fg-on-accent" | "fg-accent-hover" | "bg-accent-hover" | "fg-accent-active" | "bg-accent-active" | "border-accent" | "fg-info" | "bg-info" | "fg-on-info" | "bg-info-hover" | "bg-info-active" | "fg-success" | "bg-success" | "fg-on-success" | "bg-success-hover" | "bg-success-active" | "fg-warning" | "bg-warning" | "fg-on-warning" | "bg-warning-hover" | "bg-warning-active" | "fg-error" | "bg-error" | "fg-on-error" | "bg-error-hover" | "bg-error-active" | "bg-selected" | "fg-on-selected" | "bg-selected-hover" | "bg-inverse" | "fg-on-inverse" | "fg-link" | "fg-disabled" | "bg-disabled" | "border-disabled" | "bg-backdrop" | "fg-default" | "bg-default";
290
+ /** The flat projection — every FlatToken maps to a hex string. */
291
+ type FlatTokens = { readonly [K in FlatToken]: string };
292
+ /**
293
+ * Per-token record of HOW a token was derived. Populated only when the
294
+ * derivation is called with `{ trace: true }`. Used by the Sterling
295
+ * storybook to visualize derivation rules.
296
+ */
297
+ interface DerivationStep {
298
+ /** Token path (e.g. `"accent.hover.bg"` or flat `"bg-accent-hover"`). */
299
+ readonly token: string;
300
+ /** Human-readable rule name (e.g. `"OKLCH +0.04L on accent.bg"`). */
301
+ readonly rule: string;
302
+ /** Input hex(es) the rule operated on. */
303
+ readonly inputs: readonly string[];
304
+ /** Output hex. */
305
+ readonly output: string;
306
+ /** If auto-lift adjusted this token, the original value before adjustment. */
307
+ readonly liftedFrom?: string;
308
+ /** If pinned by scheme author, true. */
309
+ readonly pinned?: boolean;
310
+ }
311
+ type DerivationTrace = readonly DerivationStep[];
312
+ /**
313
+ * Categorical color ring — 8 harmonious hues for tagging, chart series,
314
+ * calendar categories, priority levels — any CATEGORICAL color that isn't
315
+ * stateful. ensureContrast-adjusted against bg at derivation time. Consumers
316
+ * access these via `$red`, `$orange`, …, `$pink` or direct field access.
317
+ *
318
+ * Distinguish from:
319
+ * - `$color0..$color15` — raw terminal ANSI (user's theme verbatim)
320
+ * - `$error/$warning/$success` — semantic state (communicates meaning)
321
+ * - `$brand` — app identity anchor (one color)
322
+ */
323
+ interface CategoricalHues {
324
+ readonly red: string;
325
+ readonly orange: string;
326
+ readonly yellow: string;
327
+ readonly green: string;
328
+ readonly teal: string;
329
+ readonly blue: string;
330
+ readonly purple: string;
331
+ readonly pink: string;
332
+ }
333
+ /**
334
+ * The canonical Sterling Theme — Sterling flat tokens + nested roles on the
335
+ * same object, plus a small surface of non-token metadata and runtime
336
+ * convenience fields the framework depends on:
337
+ *
338
+ * Two access paths for every hex leaf:
339
+ * - Nested: `theme.accent.hover.bg`
340
+ * - Flat: `theme["bg-accent-hover"]`
341
+ * Both paths reference the same string (not copies). The object is frozen
342
+ * after derivation (see `flatten.ts`).
343
+ *
344
+ * Non-token metadata:
345
+ * - `name` — scheme display name (if derived from a named scheme)
346
+ * - `mode` — light/dark
347
+ * - `derivationTrace` — optional; present only when `{ trace: true }` was passed
348
+ * - `variants` — typography preset bundles (h1, body, code, …) resolved by
349
+ * `<Text variant="…">`
350
+ * - `palette` — 16-slot ANSI catalog used by `$color0` … `$color15`
351
+ * - categorical hues (`red`, `orange`, `yellow`, `green`, `teal`, `blue`,
352
+ * `purple`, `pink`) — hex strings for categorical UI
353
+ *
354
+ * Root pair:
355
+ * - `fg` — default text color (= `scheme.foreground`)
356
+ * - `bg` — default canvas color (= `scheme.background`; same value as
357
+ * `bg-surface-default` but exposed at the root for `$fg` / `$bg`
358
+ * JSX consumers and convenience access)
359
+ *
360
+ * The nested roles (`accent`, `muted`, `surface`, `border`, `cursor`, plus
361
+ * the status roles `info`/`success`/`warning`/`error`) are authoritative for
362
+ * stateful tokens. Legacy flat hex aliases for these roles (`theme.primary`,
363
+ * `theme.muted`, `theme.accent` as strings) are emitted as runtime
364
+ * conveniences via the scheme-builder but are not part of this type — they
365
+ * were deleted in silvery 0.19.0.
366
+ */
367
+ type Theme = FlatTokens & Roles & {
368
+ readonly name?: string;
369
+ readonly mode: "light" | "dark";
370
+ readonly derivationTrace?: DerivationTrace;
371
+ readonly variants: Record<string, Variant>;
372
+ readonly palette: readonly string[]; /** Default text color (= `scheme.foreground`). Heavily used as `$fg` in JSX. */
373
+ readonly fg: string;
374
+ /**
375
+ * Default canvas color (= `scheme.background`). Same value as
376
+ * `bg-surface-default`; exposed at the root for `$bg` JSX consumers and
377
+ * convenience access.
378
+ */
379
+ readonly bg: string;
380
+ } & CategoricalHues;
381
+ /**
382
+ * A typography variant — a named bundle of visual properties applied to a
383
+ * Text component via `variant="h1"`. The variant acts as a *default*: caller
384
+ * props always win over variant values.
385
+ *
386
+ * Color values follow the same syntax as `TextColor` — `$token` strings, hex
387
+ * values, ANSI names, or any string accepted by the color system.
388
+ */
389
+ interface Variant {
390
+ readonly color?: string;
391
+ readonly backgroundColor?: string;
392
+ readonly bold?: boolean;
393
+ readonly italic?: boolean;
394
+ readonly dim?: boolean;
395
+ readonly underlineStyle?: "single" | "double" | "curly" | "dotted" | "dashed";
396
+ }
397
+ /**
398
+ * Metadata describing a DesignSystem's Theme shape — for tooling (docs,
399
+ * storybook, CSS export). Plain data, no functions.
400
+ */
401
+ interface ThemeShape {
402
+ /** The list of FlatTokens this system emits. */
403
+ readonly flatTokens: readonly string[];
404
+ /** The list of role-object keys this system emits (e.g. `["accent", "info", ...]`). */
405
+ readonly roles: readonly string[];
406
+ /** The list of state variants used on interactive roles (e.g. `["hover", "active"]`). */
407
+ readonly states: readonly string[];
408
+ }
409
+ /** Contrast enforcement mode for derivation. See D3 in sterling-preflight.md. */
410
+ type ContrastMode = /** Throw on WCAG AA failure on core role pairs. Used by catalog tests. */"strict" /** Auto-lift failing tokens via OKLCH L shifts. Used for user schemes. */ | "auto-lift";
411
+ /** Options accepted by all derivation entry points. */
412
+ interface DeriveOptions {
413
+ /** Default: `"auto-lift"`. */
414
+ readonly contrast?: ContrastMode;
415
+ /** If true, attach `derivationTrace` to the returned Theme. Default: false. */
416
+ readonly trace?: boolean;
417
+ /**
418
+ * Per-role token pins. A scheme author can pin specific tokens (e.g.
419
+ * `{ "error.fg": "#bf616a" }`) to skip auto-adjustment. The path syntax is
420
+ * nested-style: `"accent.hover.bg"`, `"error.fg"`. Flat-form pins are
421
+ * also accepted: `{ "bg-accent": "#...", "fg-on-error": "#..." }`.
422
+ */
423
+ readonly pins?: Readonly<Record<string, string>>;
424
+ /**
425
+ * Force light/dark inference. By default inferred from
426
+ * `scheme.dark` or WCAG luminance of `scheme.background`.
427
+ */
428
+ readonly mode?: "light" | "dark";
429
+ }
430
+ /**
431
+ * The `DesignSystem` contract. Sterling is the default implementation; other
432
+ * packages (e.g. `@silvery/design-material`) publish alternatives matching
433
+ * this shape.
434
+ */
435
+ interface DesignSystem {
436
+ /** Display name for tooling (e.g. `"sterling"`). */
437
+ readonly name: string;
438
+ /** Metadata about this system's Theme shape. */
439
+ readonly shape: ThemeShape;
440
+ /**
441
+ * Whether the framework should auto-apply `bakeFlat` to each derivation's
442
+ * output — projecting hex leaves onto flat hyphen-keys on the same object.
443
+ *
444
+ * - `true` — use {@link defaultFlattenRule} (channel-role-state, Sterling style)
445
+ * - `FlattenRule` — system-specific rule (e.g. Material `onPrimary`)
446
+ * - `false` or omitted — no auto-flatten (system is responsible, or
447
+ * consumer only uses nested form)
448
+ *
449
+ * Sterling and anything modelled on it should set `flatten: true` —
450
+ * flat-projection-on-same-object is a universal feature of nested
451
+ * hex-leaf POJOs and Sterling users expect `theme["bg-accent"]` access.
452
+ */
453
+ readonly flatten?: boolean | FlattenRule;
454
+ /** Return a raw default Theme, no input required. */
455
+ defaults(mode?: "light" | "dark"): Theme;
456
+ /**
457
+ * Fill partial theme values with defaults. Useful for hand-curated themes
458
+ * that override a few roles.
459
+ */
460
+ theme(partial?: DeepPartial<Theme>, opts?: DeriveOptions): Theme;
461
+ /** Derive from a 22-color terminal scheme — Sterling's primary path. */
462
+ deriveFromScheme(scheme: ColorScheme, opts?: DeriveOptions): Theme;
463
+ /** Derive from a single seed color — Material-style. */
464
+ deriveFromColor(color: string, opts?: DeriveOptions & {
465
+ mode?: "light" | "dark";
466
+ }): Theme;
467
+ /** Derive from a light/dark scheme pair. */
468
+ deriveFromPair(light: ColorScheme, dark: ColorScheme, opts?: DeriveOptions): {
469
+ light: Theme;
470
+ dark: Theme;
471
+ };
472
+ /** Derive from a scheme plus a brand-color overlay (F — brand discipline). */
473
+ deriveFromSchemeWithBrand(scheme: ColorScheme, brand: string, opts?: DeriveOptions): Theme;
474
+ }
475
+ /** Utility: recursive `Partial` for nested Theme overrides. */
476
+ type DeepPartial<T> = T extends object ? T extends readonly unknown[] ? T : { [K in keyof T]?: DeepPartial<T[K]> } : T;
477
+ //#endregion
478
+ //#region packages/ansi/src/theme/types.d.ts
479
+ /**
480
+ * Core type definitions for the theme system.
481
+ *
482
+ * Two-layer architecture:
483
+ * Layer 1: ColorScheme — 22 terminal colors (what schemes expose; auto-detectable)
484
+ * Layer 2: Theme — ~33 semantic tokens (what UI apps consume)
485
+ *
486
+ * Pipeline: Scheme catalog → ColorScheme (22) → deriveTheme() → Theme (33)
487
+ */
488
+ interface ColorScheme {
489
+ name?: string;
490
+ dark?: boolean;
491
+ primary?: string;
492
+ black: string;
493
+ red: string;
494
+ green: string;
495
+ yellow: string;
496
+ blue: string;
497
+ magenta: string;
498
+ cyan: string;
499
+ white: string;
500
+ brightBlack: string;
501
+ brightRed: string;
502
+ brightGreen: string;
503
+ brightYellow: string;
504
+ brightBlue: string;
505
+ brightMagenta: string;
506
+ brightCyan: string;
507
+ brightWhite: string;
508
+ foreground: string;
509
+ background: string;
510
+ cursorColor: string;
511
+ cursorText: string;
512
+ selectionBackground: string;
513
+ selectionForeground: string;
514
+ }
515
+ declare const COLOR_SCHEME_FIELDS: readonly ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "brightBlack", "brightRed", "brightGreen", "brightYellow", "brightBlue", "brightMagenta", "brightCyan", "brightWhite", "foreground", "background", "cursorColor", "cursorText", "selectionBackground", "selectionForeground"];
516
+ /**
517
+ * Metadata describing how the active color scheme was determined.
518
+ *
519
+ * Returned by `detectScheme()` and surfaced at runtime via `useActiveScheme()`.
520
+ * Lets apps log how the theme was detected ("catppuccin-mocha at 87% confidence via
521
+ * fingerprint") or render a debug badge without re-running detection.
522
+ *
523
+ * @example
524
+ * ```tsx
406
525
  * const scheme = useActiveScheme()
407
526
  * if (scheme?.source === "fingerprint") {
408
527
  * console.log(`detected ${scheme.matchedName} at ${Math.round((scheme.confidence ?? 0) * 100)}%`)
@@ -421,94 +540,74 @@ interface ActiveScheme {
421
540
  }
422
541
  type AnsiPrimary = "yellow" | "cyan" | "magenta" | "green" | "red" | "blue" | "white";
423
542
  type HueName = "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "purple" | "pink";
424
- /**
425
- * A typography variant — a named bundle of visual properties that can be
426
- * applied to a Text component via `variant="h1"`. The variant acts as a
427
- * *default*: caller props always win over variant values.
428
- *
429
- * Color values follow the same syntax as `TextColor` — `$token` strings,
430
- * hex values, ANSI names, or any string accepted by the color system.
431
- */
432
- interface Variant$1 {
433
- color?: string;
434
- backgroundColor?: string;
435
- bold?: boolean;
436
- italic?: boolean;
437
- dim?: boolean;
438
- underlineStyle?: "single" | "double" | "curly" | "dotted" | "dashed";
439
- }
440
543
  //#endregion
441
- //#region packages/ansi/src/theme/derive.d.ts
442
- interface ThemeAdjustment {
443
- token: string;
444
- from: string;
445
- to: string;
446
- against: string;
447
- target: number;
448
- ratioBefore: number;
449
- ratioAfter: number;
544
+ //#region packages/ansi/src/theme/detect.d.ts
545
+ interface DetectedScheme {
546
+ fg: string | null;
547
+ bg: string | null;
548
+ ansi: (string | null)[];
549
+ dark: boolean;
550
+ palette: Partial<ColorScheme>;
450
551
  }
451
- declare function deriveTheme$1(palette: ColorScheme, mode?: "ansi16" | "truecolor", adjustments?: ThemeAdjustment[]): Theme$1;
452
- //#endregion
453
- //#region packages/ansi/src/theme/orchestrator.d.ts
454
- /** How the final scheme was decided. */
455
- type DetectSource = "override" | "fingerprint" | "probed" | "bg-mode" | "fallback";
456
- /** Where each slot's value came from. */
457
- type SlotSource = "probed" | "catalog" | "fallback";
458
- interface DetectSchemeResult {
459
- /** The resolved 22-slot color scheme. */
460
- scheme: ColorScheme;
461
- /** The derived, validated Theme (via loadTheme). */
462
- theme: Theme$1;
463
- /** How the scheme was determined overall. */
464
- source: DetectSource;
465
- /** 0–1 confidence heuristic (exact override = 1, fingerprint = match score, fallback = 0). */
466
- confidence: number;
467
- /** Per-slot provenance. Keys are ColorScheme field names. */
468
- slotSources: Partial<Record<keyof ColorScheme, SlotSource>>;
469
- /** If fingerprint matched, the catalog scheme name. */
470
- matchedName?: string;
552
+ /**
553
+ * Structural subset of `@silvery/ag-term/runtime` `InputOwner`. Defined
554
+ * locally so `@silvery/ansi` stays dependency-free — callers inside a silvery
555
+ * session can pass the real `InputOwner` and get nominal structural match;
556
+ * standalone callers who never heard of InputOwner are unaffected.
557
+ */
558
+ interface ProbeInputOwner {
559
+ probe<T>(opts: {
560
+ query: string;
561
+ parse: (acc: string) => {
562
+ result: T;
563
+ consumed: number;
564
+ } | null;
565
+ timeoutMs: number;
566
+ }): Promise<T | null>;
471
567
  }
472
- interface DetectSchemeOptions {
473
- /** Explicit override if provided, skips all probing. */
474
- override?: ColorScheme;
475
- /** Catalog to fingerprint against. If empty or undefined, skip fingerprinting. */
476
- catalog?: readonly ColorScheme[];
477
- /** OSC probe timeout (ms). Default 150. */
568
+ interface ProbeColorsOptions {
569
+ /** Per-OSC-query timeout in ms. Default 150. */
478
570
  timeoutMs?: number;
479
- /** Force dark/light inference when no bg is probed. */
480
- darkFallback?: boolean;
481
571
  /**
482
- * Apply strict invariant validation to the loaded Theme. Default `lenient`.
483
- * See `loadTheme`'s `enforce` parameter.
572
+ * Optional InputOwner (from `@silvery/ag-term/runtime`) that owns the stdin
573
+ * raw-mode + data listener for the enclosing session. When provided,
574
+ * probeColors routes OSC queries through `input.probe()` instead of
575
+ * touching `process.stdin` directly. This avoids the wasRaw race that kills
576
+ * host-TUI input when probeColors runs concurrently with a TUI session.
577
+ *
578
+ * When absent (e.g. CLI tool, non-TUI caller), probeColors falls back to
579
+ * the standalone race-safe `didSetRaw + listenerCount > 0` guard on
580
+ * `process.stdin`. The standalone path stays tested and supported.
484
581
  */
485
- enforce?: "strict" | "lenient" | "off";
486
- /** Add WCAG contrast check to the invariant validation. Default `false`. */
487
- wcag?: boolean;
582
+ input?: ProbeInputOwner;
488
583
  }
489
- //#endregion
490
- //#region packages/ansi/src/theme/tokens.d.ts
491
584
  /**
492
- * Built-in variant names the standard typography presets shipped by silvery.
493
- * These are the default keys in `Theme.variants`.
585
+ * Probe the terminal for its 22-slot color scheme via OSC 4/10/11 queries.
586
+ *
587
+ * Pure terminal primitive — no fingerprinting, no theme derivation. Returns the
588
+ * raw probed slots (or `null` if probing isn't available, e.g. non-TTY).
589
+ *
590
+ * For the full detection cascade (override → probe → fingerprint → fallback +
591
+ * theme derivation), use `detectScheme` from `@silvery/ansi` or
592
+ * `detectTheme` from `@silvery/theme`.
593
+ *
594
+ * `probeColors` is the canonical name; `detectTerminalScheme` is the legacy
595
+ * alias kept for backward compatibility.
596
+ *
597
+ * Call styles:
598
+ * await probeColors() // default timeout, standalone
599
+ * await probeColors(150) // legacy positional timeout
600
+ * await probeColors({ timeoutMs: 150 }) // options form
601
+ * await probeColors({ input: inputOwner, timeoutMs: 150 }) // routed through InputOwner
494
602
  */
495
- type VariantName = "h1" | "h2" | "h3" | "body" | "body-muted" | "fine-print" | "strong" | "em" | "link" | "key" | "code" | "kbd";
603
+ declare function probeColors(timeoutOrOpts?: number | ProbeColorsOptions): Promise<DetectedScheme | null>;
496
604
  /**
497
- * Any variant name built-in or app-defined. The `(string & {})` tail is the
498
- * Tailwind trick: preserves IDE autocomplete for the literal union while still
499
- * accepting any runtime string value.
605
+ * Legacy alias for {@link probeColors}. Prefer `probeColors` in new code
606
+ * the name says what it does (probes terminal color slots), and "detect" is
607
+ * reserved for the full cascade (`detectScheme`, `detectTheme`). Retained
608
+ * as a stable alias — no deprecation schedule.
500
609
  */
501
- type KnownVariant = VariantName | (string & {});
502
- //#endregion
503
- //#region packages/ansi/src/theme/detect.d.ts
504
- interface DetectedScheme {
505
- fg: string | null;
506
- bg: string | null;
507
- ansi: (string | null)[];
508
- dark: boolean;
509
- palette: Partial<ColorScheme>;
510
- }
511
- declare function detectTerminalScheme(timeoutMs?: number): Promise<DetectedScheme | null>;
610
+ declare const detectTerminalScheme: typeof probeColors;
512
611
  interface DetectThemeOptions {
513
612
  /** Fallback ColorScheme when detection fails or returns partial data.
514
613
  * Detected colors override matching fallback fields.
@@ -523,870 +622,695 @@ interface DetectThemeOptions {
523
622
  /** Timeout per OSC query in ms (default 150). */
524
623
  timeoutMs?: number;
525
624
  /** Terminal capabilities (from detectTerminalCaps). When provided:
526
- * - colorLevel "none"/"basic" skips OSC detection and returns ANSI 16 theme
625
+ * - colorLevel `"mono"` / `"ansi16"` skips OSC detection and returns ANSI 16 theme
527
626
  * - darkBackground informs fallback selection when detection fails */
528
627
  caps?: {
529
628
  colorLevel?: string;
530
629
  darkBackground?: boolean;
531
630
  };
631
+ /** Optional InputOwner — routes OSC queries through the session's stdin
632
+ * owner instead of directly mutating process.stdin raw mode. See
633
+ * {@link ProbeColorsOptions.input}. */
634
+ input?: ProbeInputOwner;
532
635
  }
636
+ declare function detectTheme(opts?: DetectThemeOptions): Promise<Theme>;
533
637
  //#endregion
534
- //#region packages/ansi/src/osc-palette.d.ts
535
- /**
536
- * OSC 4 Terminal Color Palette Query/Set — pure ANSI protocol.
537
- */
538
- declare function queryPaletteColor(index: number, write: (data: string) => void): void;
539
- declare function queryMultiplePaletteColors(indices: number[], write: (data: string) => void): void;
540
- declare function setPaletteColor(index: number, color: string, write: (data: string) => void): void;
541
- declare function parsePaletteResponse(input: string): {
542
- index: number;
543
- color: string;
544
- } | null;
545
- //#endregion
546
- //#region packages/ansi/src/osc-colors.d.ts
547
- /**
548
- * OSC 10/11/12 Terminal Color Queries — pure ANSI protocol.
549
- */
550
- declare function queryForegroundColor(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<string | null>;
551
- declare function queryBackgroundColor(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<string | null>;
552
- declare function queryCursorColor(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<string | null>;
553
- declare function setForegroundColor(write: (data: string) => void, color: string): void;
554
- declare function setBackgroundColor(write: (data: string) => void, color: string): void;
555
- declare function setCursorColor(write: (data: string) => void, color: string): void;
556
- declare function resetForegroundColor(write: (data: string) => void): void;
557
- declare function resetBackgroundColor(write: (data: string) => void): void;
558
- declare function resetCursorColor(write: (data: string) => void): void;
559
- declare function detectColorScheme(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<"light" | "dark" | null>;
560
- //#endregion
561
- //#region packages/ansi/src/theme/generate.d.ts
638
+ //#region packages/ansi/src/profile.d.ts
562
639
  /**
563
- * Generate a complete ANSI 16 theme from a primary color + dark/light preference.
564
- *
565
- * All token values are ANSI color names (e.g. "yellow", "blueBright").
640
+ * Which rung of the precedence chain resolved the profile's color tier.
641
+ *
642
+ * Scoped specifically to **color tier** not whole-profile provenance. Other
643
+ * caps fields (unicode, kittyKeyboard, …) come from `detectTerminalProfileFromEnv`
644
+ * or a caller-supplied caps object; their provenance is not tracked here.
645
+ *
646
+ * - `"env"` — `NO_COLOR` or `FORCE_COLOR` env var won.
647
+ * - `"override"` — caller-supplied `colorLevel` won.
648
+ * - `"caller-caps"` — `options.caps.colorLevel` fallback won. Note this
649
+ * conflates "pre-detected real caps the Term committed to" with
650
+ * "synthetically forced caps from a test fixture / user config"; callers
651
+ * that need to tell those apart pass `colorLevel` explicitly instead.
652
+ * - `"auto"` — env-based auto-detection (TERM/COLORTERM/TERM_PROGRAM) won.
653
+ *
654
+ * Consumers that only need "was the tier forced?" should read
655
+ * {@link TerminalCaps.colorForced} instead of comparing against this enum.
656
+ * Phase 5 of `km-silvery.terminal-profile-plateau` (per /pro review 2026-04-23):
657
+ * the flat `source` field was retired because it read like whole-profile
658
+ * provenance but only described color tier.
566
659
  */
567
- declare function generateTheme$1(primary: AnsiPrimary, dark: boolean): Theme$1;
568
- //#endregion
569
- //#region packages/theme/src/generate.d.ts
660
+ type ColorProvenance = "env" | "override" | "caller-caps" | "auto";
570
661
  /**
571
- * Generate a complete ANSI 16 theme from a primary color + dark/light preference.
572
- *
573
- * All token values are hex strings (e.g. "#808000" for yellow).
574
- * Terminal rendering quantizes these to 4-bit ANSI codes at paint time
575
- * when colorLevel === "basic".
662
+ * A fully-resolved view of the current terminal.
663
+ *
664
+ * Bundled intentionally callers shouldn't mix and match detection sources.
665
+ * `colorLevel` mirrors `caps.colorLevel`; it's exposed as a top-level field so
666
+ * callers that only need the tier (e.g. `createStyle({ level })`) don't have
667
+ * to reach into the caps object.
668
+ *
669
+ * **Immutability**: profiles are snapshot values — the whole plateau depends
670
+ * on `colorLevel === caps.colorLevel` never drifting. Every field is
671
+ * `readonly` at the type level, and `createTerminalProfile` freezes the
672
+ * returned object (and its nested `caps`) in dev builds so accidental
673
+ * mutation crashes loudly. Production builds skip the freeze to keep the
674
+ * allocation cheap; the type-level `readonly` already blocks TS writers.
675
+ *
676
+ * Post km-silvery.plateau-naming-polish (2026-04-23): 2-layer shape — `emulator`
677
+ * (what terminal IS this) and `caps` (what can it do, including `maybe*`
678
+ * heuristics). The original Phase 7 3-layer shape collapsed because the
679
+ * 3-field heuristics namespace was pulling its weight.
680
+ *
681
+ * @see createTerminalProfile
576
682
  */
577
- declare function generateTheme(primary: AnsiPrimary, dark: boolean): Theme$1;
578
- //#endregion
579
- //#region packages/theme/src/generators.d.ts
580
- /** Find which hue slot the primary color best matches by OKLCH hue angle proximity. */
581
- declare function assignPrimaryToSlot(primary: string): HueName;
683
+ interface TerminalProfile {
684
+ /** Environment identity — what terminal IS this (program, version, TERM). */
685
+ readonly emulator: TerminalEmulator;
686
+ /** Protocol-capability flags + low-confidence `maybe*` heuristics. Also
687
+ * carries `colorLevel` / `colorForced` / `colorProvenance`. */
688
+ readonly caps: TerminalCaps;
689
+ /** Convenience alias for `caps.colorLevel`. Exposed as a top-level field
690
+ * because callers that only need the tier (e.g. `createStyle({ level })`)
691
+ * shouldn't have to reach into the caps object. */
692
+ readonly colorLevel: ColorLevel;
693
+ /**
694
+ * OSC-detected terminal theme, populated only when the profile was built via
695
+ * {@link probeTerminalProfile}. Pre-quantized to {@link colorLevel} when the
696
+ * tier was {@link TerminalCaps.colorForced} so token hex values match what
697
+ * the pipeline will actually emit.
698
+ *
699
+ * Absent on sync {@link createTerminalProfile} — theme detection is an async
700
+ * OSC probe and can't run inside a sync call. Entry points that need a
701
+ * theme (run, createApp) should use `probeTerminalProfile` instead.
702
+ *
703
+ * Post km-silvery.plateau-profile-theme (H2 of the /big review 2026-04-23).
704
+ */
705
+ readonly theme?: Theme;
706
+ }
582
707
  /**
583
- * Generate a ColorScheme from a Base16 YAML scheme.
708
+ * Minimal stdout shape needed for detection.
584
709
  *
585
- * Maps base00–base0F to ANSI palette colors, derives special colors.
710
+ * Using a structural type (not `NodeJS.WriteStream`) keeps `@silvery/ansi`
711
+ * browser-safe — the canvas/DOM backends can pass `{ isTTY: false }` without
712
+ * pulling in Node's tty types.
586
713
  */
587
- declare function fromBase16(yamlOrJson: string): ColorScheme;
588
- interface FromColorsOptions {
589
- /** Background color (infers dark/light). */
590
- background?: string;
591
- /** Foreground/text color. Generated if omitted. */
592
- foreground?: string;
593
- /** Primary accent color. Generated if omitted. */
594
- primary?: string;
595
- /** Force dark mode. */
596
- dark?: boolean;
597
- /** Theme name. */
598
- name?: string;
714
+ interface TerminalProfileStdout {
715
+ isTTY?: boolean;
716
+ columns?: number;
717
+ rows?: number;
599
718
  }
600
719
  /**
601
- * Generate a full ColorScheme from 1-3 hex colors.
720
+ * Minimal stdin shape needed for input capability detection.
602
721
  *
603
- * At minimum, provide `background` or `primary`. Missing colors are
604
- * generated via surface ramp (from bg) and hue rotation (from primary).
722
+ * Structural like {@link TerminalProfileStdout} browser/canvas backends
723
+ * that have no stdin pass `undefined` and `caps.input` resolves to `false`
724
+ * via the default. Absorbed from the retired `detectInput(stdin)` helper
725
+ * in unicode-plateau Phase 4.
605
726
  */
606
- declare function fromColors(opts: FromColorsOptions): ColorScheme;
727
+ interface TerminalProfileStdin {
728
+ isTTY?: boolean;
729
+ setRawMode?: (mode: boolean) => unknown;
730
+ }
607
731
  /**
608
- * Look up a built-in palette by name.
609
- *
610
- * @returns The ColorScheme, or undefined if not found.
732
+ * Options for {@link createTerminalProfile}.
611
733
  */
612
- declare function fromPreset(name: string): ColorScheme | undefined;
613
- //#endregion
614
- //#region packages/theme/src/builder.d.ts
615
- interface ThemeBuilder {
616
- /** Set background color. */
617
- bg(color: string): ThemeBuilder;
618
- /** Set foreground color. */
619
- fg(color: string): ThemeBuilder;
620
- /** Set primary accent color. */
621
- primary(color: string): ThemeBuilder;
622
- /** Alias for `.primary()`. */
623
- accent(color: string): ThemeBuilder;
624
- /** Force dark mode. */
625
- dark(): ThemeBuilder;
626
- /** Force light mode. */
627
- light(): ThemeBuilder;
628
- /** Set any palette color by name. */
629
- color(name: keyof Omit<ColorScheme, "name" | "dark">, value: string): ThemeBuilder;
630
- /** Set full palette at once. */
631
- palette(p: ColorScheme): ThemeBuilder;
632
- /** Load a built-in palette by name. */
633
- preset(name: string): ThemeBuilder;
634
- /** Derive the final Theme from accumulated state. */
635
- build(): Theme$1;
734
+ interface CreateTerminalProfileOptions {
735
+ /** Environment (default: `process.env`). */
736
+ env?: Record<string, string | undefined>;
737
+ /** Output stream (default: `process.stdout`). */
738
+ stdout?: TerminalProfileStdout;
739
+ /**
740
+ * Input stream (default: `process.stdin`). Used to derive `caps.input` —
741
+ * whether the host can read raw keystrokes. Pass `undefined` explicitly
742
+ * (or omit on non-Node targets) to force `caps.input = false`.
743
+ */
744
+ stdin?: TerminalProfileStdin;
745
+ /**
746
+ * Explicit color tier override. Wins over `caps.colorLevel` but NOT over
747
+ * NO_COLOR / FORCE_COLOR env vars. `null` is accepted as an alias for
748
+ * `"mono"` (pre-plateau no-color spelling).
749
+ */
750
+ colorLevel?: ColorLevel | null;
751
+ /**
752
+ * Base capabilities. When provided, skips the env-based caps detection —
753
+ * the profile uses these as the starting point. `caps.colorLevel` acts as
754
+ * the fallback tier (used only if env+override both decline to set one).
755
+ *
756
+ * Typical uses:
757
+ * - Term constructors already computed full caps → pass them here to avoid
758
+ * a redundant detection pass.
759
+ * - Tests want a known-good caps fixture → pass a fully-populated object.
760
+ */
761
+ caps?: Partial<TerminalCaps>;
762
+ /**
763
+ * Base emulator identity. When provided, skips identity detection and uses
764
+ * these values. Typical use: Term constructors that already resolved
765
+ * TERM_PROGRAM from their stdin/stdout context.
766
+ */
767
+ emulator?: Partial<TerminalEmulator>;
636
768
  }
637
- /** Create a chainable theme builder. */
638
- declare function createTheme(): ThemeBuilder;
639
769
  /**
640
- * Quick theme from a primary color or color name.
770
+ * Build a {@link TerminalProfile} from the current environment.
641
771
  *
642
- * @example
643
- * ```typescript
644
- * quickTheme('#EBCB8B', 'dark') // yellow primary, dark mode
645
- * quickTheme('blue') // blue primary, default dark
646
- * ```
647
- */
648
- declare function quickTheme(primaryOrHex: string, mode?: "dark" | "light"): Theme$1;
649
- /**
650
- * Create a theme from a built-in preset name.
772
+ * Priority for the final `colorLevel` (highest wins):
773
+ * 1. `NO_COLOR` env var → `"mono"`
774
+ * 2. `FORCE_COLOR` env var → `0/false → mono, 1 ansi16, 2 → 256, 3 → truecolor`
775
+ * 3. `options.colorLevel` (caller-supplied explicit tier)
776
+ * 4. `options.caps.colorLevel` (base caps' pre-detected tier)
777
+ * 5. Auto-detected tier from env (TERM, COLORTERM, TERM_PROGRAM, …)
651
778
  *
652
- * @example
653
- * ```typescript
654
- * presetTheme('catppuccin-mocha')
655
- * presetTheme('nord')
656
- * ```
657
- */
658
- declare function presetTheme(name: string): Theme$1;
659
- //#endregion
660
- //#region packages/theme/src/auto-generate.d.ts
661
- /**
662
- * Generate a complete Theme from a single primary color.
779
+ * The env-var precedence (1 & 2) matches the existing `detectColor()` semantics
780
+ * and is observed on every silvery entry point — tests pass with explicit
781
+ * env vars even when a caller forces a tier via `colorLevel`.
663
782
  *
664
- * Derives a full ColorScheme using OKLCH color manipulation:
665
- * - Background/foreground from lightness endpoints using the primary's hue
666
- * - Complementary and analogous accent colors from hue rotation
667
- * - Surface ramp from bg lightness offsets
668
- * - Status colors (error, warning, success, info) from standard hue positions
783
+ * When `options.caps` is provided, the profile treats those as the base
784
+ * capabilities and skips the env-based caps detection only the color tier
785
+ * is resolved through the precedence chain above. When `options.caps` is
786
+ * absent, the full `detectTerminalProfileFromEnv` pass runs.
669
787
  *
670
- * @param primaryColor - A hex color string (e.g. "#5E81AC")
671
- * @param mode - "dark" or "light" theme mode
672
- * @returns A complete Theme with all 33 semantic tokens
788
+ * No I/O beyond whatever `detectTerminalCaps()` already does (a `defaults read`
789
+ * call on macOS for Apple Terminal dark-mode heuristics cached).
673
790
  *
674
791
  * @example
675
- * ```typescript
676
- * const theme = autoGenerateTheme("#5E81AC", "dark")
677
- * // Generates a full dark theme with blue as the primary accent
678
- *
679
- * const light = autoGenerateTheme("#E06C75", "light")
680
- * // Generates a full light theme with red/rose as the primary accent
681
- * ```
682
- */
683
- declare function autoGenerateTheme(primaryColor: string, mode: "dark" | "light"): Theme$1;
684
- //#endregion
685
- //#region packages/theme/src/validate.d.ts
686
- /** Validation result from validateColorScheme(). */
687
- interface ValidationResult {
688
- valid: boolean;
689
- errors: string[];
690
- warnings: string[];
691
- }
692
- /**
693
- * Validate a ColorScheme.
694
- *
695
- * Checks:
696
- * - All 22 color fields are present and non-empty hex strings
697
- * - Warns on low-contrast foreground/background combinations
698
- */
699
- declare function validateColorScheme(p: ColorScheme): ValidationResult;
700
- //#endregion
701
- //#region packages/theme/src/validate-theme.d.ts
702
- /**
703
- * Theme validation — checks that all required semantic tokens are present.
792
+ * ```ts
793
+ * // Auto-detect from process.env + process.stdout
794
+ * const profile = createTerminalProfile()
795
+ * console.log(profile.colorLevel) // "truecolor" on Ghostty
704
796
  *
705
- * Complements validateColorScheme() which validates the lower-level
706
- * ColorScheme. This validates the derived Theme object.
707
- */
708
- /** All 33 required semantic token keys on Theme (excludes `name` and `palette`). */
709
- declare const THEME_TOKEN_KEYS: readonly string[];
710
- /** Result of theme validation. */
711
- interface ThemeValidationResult {
712
- /** Whether the theme has all required tokens. */
713
- valid: boolean;
714
- /** Token keys that are required but missing or empty. */
715
- missing: string[];
716
- /** Token keys that exist on the object but are not recognized theme tokens. */
717
- extra: string[];
718
- }
719
- /**
720
- * Validate a Theme object — check that all required tokens are present.
797
+ * // Force a tier (still honors NO_COLOR / FORCE_COLOR env precedence)
798
+ * const forced = createTerminalProfile({ colorLevel: "256" })
721
799
  *
722
- * @param theme - The theme object to validate
723
- * @returns Validation result with missing and extra token lists
800
+ * // Term path base caps already detected, just resolve color tier.
801
+ * const termProfile = createTerminalProfile({
802
+ * colorLevel: userColorLevel,
803
+ * caps: term.caps,
804
+ * })
724
805
  *
725
- * @example
726
- * ```typescript
727
- * const result = validateTheme(myTheme)
728
- * if (!result.valid) {
729
- * console.log("Missing tokens:", result.missing)
730
- * }
806
+ * // Headless/test fixture — zero env influence
807
+ * const fake = createTerminalProfile({
808
+ * env: {},
809
+ * stdout: { isTTY: true },
810
+ * colorLevel: "truecolor",
811
+ * })
731
812
  * ```
732
813
  */
733
- declare function validateTheme(theme: Record<string, unknown>): ThemeValidationResult;
734
- //#endregion
735
- //#region packages/theme/src/alias.d.ts
814
+ declare function createTerminalProfile(options?: CreateTerminalProfileOptions): TerminalProfile;
736
815
  /**
737
- * Resolve all token aliases in a theme.
738
- *
739
- * Token values that start with `$` are treated as references to other tokens.
740
- * Alias chains are followed until a concrete (non-$) value is reached.
741
- * Circular references are detected via a depth limit and left unresolved.
742
- *
743
- * @param theme - A theme-like object where values may reference other tokens via `$name`
744
- * @returns A new object with all aliases resolved to concrete values
745
- *
746
- * @example
747
- * ```typescript
748
- * const themed = resolveAliases({
749
- * ...baseTheme,
750
- * button: "$primary", // resolves to the value of 'primary'
751
- * buttonHover: "$button", // chain: buttonHover -> button -> primary -> hex
752
- * })
753
- * ```
816
+ * Options for {@link probeTerminalProfile}. Extends the sync factory options
817
+ * with the async-only fields a theme probe needs.
754
818
  */
755
- declare function resolveAliases(theme: Record<string, string>): Record<string, string>;
819
+ interface ProbeTerminalProfileOptions extends CreateTerminalProfileOptions {
820
+ /**
821
+ * Probe the terminal's theme via OSC 10/11/4 and bundle the result as
822
+ * `profile.theme`. Default `true` — the whole point of using the async
823
+ * variant is to get the theme alongside caps. Set `false` to skip the
824
+ * probe (no OSC writes) while still resolving a {@link TerminalProfile}
825
+ * identical to the sync path.
826
+ */
827
+ probeTheme?: boolean;
828
+ /**
829
+ * Fallback scheme when the OSC probe returns partial / no data. Matches
830
+ * {@link DetectThemeOptions.fallbackDark}.
831
+ */
832
+ fallbackDark?: DetectThemeOptions["fallbackDark"];
833
+ /** Fallback for light terminals (overrides `fallbackDark`). */
834
+ fallbackLight?: DetectThemeOptions["fallbackLight"];
835
+ /** Per-OSC-query timeout in ms (default 150 — matches `detectTheme`). */
836
+ timeoutMs?: number;
837
+ /**
838
+ * Optional {@link ProbeInputOwner} (the structural type `detectTheme`
839
+ * accepts). When provided, the probe routes OSC queries through the
840
+ * owner's `probe()` method instead of touching `process.stdin` directly —
841
+ * required inside a running TUI session. Callers in `@silvery/ag-term`
842
+ * construct a transient `InputOwner` around this call; standalone callers
843
+ * can omit it.
844
+ */
845
+ input?: ProbeInputOwner;
846
+ }
756
847
  /**
757
- * Resolve a single alias value against a Theme.
848
+ * Build a {@link TerminalProfile} with an OSC-detected `theme` bundled in.
758
849
  *
759
- * Useful for resolving individual values without processing the entire theme.
850
+ * Async because the theme probe writes OSC queries to stdout and waits for
851
+ * responses on stdin. This is the Phase-H2 variant of
852
+ * {@link createTerminalProfile} — everything the sync factory does, plus:
760
853
  *
761
- * @param value - The value to resolve (may be "$tokenName" or a concrete value)
762
- * @param theme - The theme to resolve against
763
- * @returns The resolved concrete value
764
- */
765
- declare function resolveTokenAlias(value: string, theme: Theme$1): string;
766
- //#endregion
767
- //#region packages/theme/src/css.d.ts
768
- /**
769
- * Convert a Theme to CSS custom properties.
854
+ * 1. Run `detectTheme` (OSC 4/10/11 probe with fallback) once.
855
+ * 2. Pre-quantize the resulting theme via {@link pickColorLevel} when the
856
+ * tier was forced ({@link TerminalCaps.colorForced} is `true`) so
857
+ * token hex values match what the pipeline will actually emit.
858
+ * 3. Return the profile with `theme` populated — one detection, one profile
859
+ * flowing end-to-end through run() / createApp().
770
860
  *
771
- * Token names mirror Sterling's flat grammar with a `--` prefix:
772
- * - `bg-surface-default` `--bg-surface-default`
773
- * - `fg-accent` `--fg-accent`
774
- * - `border-focus` `--border-focus`
775
- * - Palette entries: `--color0` through `--color15`
861
+ * Call sites previously ran `createTerminalProfile(...)` + `detectTheme(...)`
862
+ * + `pickColorLevel(...)` as three separate steps on both the Term-path and
863
+ * options-path branches. Collapsing that into one function removes the
864
+ * duplication and the possibility of the three views disagreeing about
865
+ * what was forced.
776
866
  *
777
- * @param theme - The theme to convert (Sterling flat tokens must be populated)
778
- * @returns A record mapping CSS custom property names to color values
867
+ * When `probeTheme` is `false`, behaves like the sync {@link createTerminalProfile}
868
+ * but wrapped in a Promise useful for call sites that want uniform async
869
+ * treatment regardless of whether a probe is needed.
779
870
  *
780
871
  * @example
781
- * ```typescript
782
- * const vars = themeToCSSVars(myTheme)
783
- * // { "--bg-surface-default": "#1E1E2E", "--fg-accent": "#F9E2AF", ... }
784
- *
785
- * // Apply to an element:
786
- * Object.assign(element.style, vars)
872
+ * ```ts
873
+ * // Node entry point with TUI-safe probing.
874
+ * const profile = await probeTerminalProfile({
875
+ * colorLevel: options.colorLevel,
876
+ * caps: term.profile.caps,
877
+ * fallbackDark: nord,
878
+ * fallbackLight: catppuccinLatte,
879
+ * input: probeOwner, // structural InputOwner from @silvery/ag-term
880
+ * })
881
+ * // profile.caps, profile.colorLevel, profile.caps.colorForced, profile.theme
787
882
  * ```
883
+ *
884
+ * @see createTerminalProfile — sync variant, no theme probe
885
+ * @see DetectThemeOptions — the underlying probe options this wraps
788
886
  */
789
- declare function themeToCSSVars(theme: Theme$1): Record<string, string>;
887
+ declare function probeTerminalProfile(options?: ProbeTerminalProfileOptions): Promise<TerminalProfile>;
790
888
  //#endregion
791
- //#region packages/theme/src/import/types.d.ts
889
+ //#region packages/ansi/src/caps.d.ts
792
890
  /**
793
- * Base16 scheme type the 16-color format used by hundreds of community themes.
794
- *
795
- * @see https://github.com/chriskempson/base16
891
+ * Pure protocol capability flags plus low-confidence environment heuristics
892
+ * what the terminal *can* do at the wire level, plus what the system guesses
893
+ * about theme/font/emoji rendering. Used by renderers / measurer for
894
+ * pre-flight branching.
895
+ *
896
+ * Post km-silvery.plateau-naming-polish (2026-04-23):
897
+ * - `TerminalHeuristics` was absorbed into this type. Guesses live alongside
898
+ * hard facts but carry a `maybe` prefix so the uncertainty is loud at every
899
+ * read site (`caps.maybeDarkBackground` vs `caps.cursor`).
900
+ *
901
+ * Post km-silvery.caps-restructure (Phase 7, 2026-04-23): the original flat
902
+ * 22-field shape was split into {@link TerminalCaps} (this type) and
903
+ * {@link TerminalEmulator} (environment identity — program/version/TERM).
904
+ * Both live on `profile.{caps,emulator}`.
905
+ *
906
+ * Renames from the old flat shape:
907
+ * - `textSizingSupported` → `textSizing` (drops the verbose suffix)
908
+ * - `underlineStyles: boolean` → `underlineStyles: readonly UnderlineStyle[]`
909
+ * so a terminal that supports curly but not dotted can report that precisely
910
+ * - `colorForced` + `colorProvenance` moved INTO caps (they describe color
911
+ * resolution, which is caps-adjacent)
912
+ *
913
+ * Phase 7 briefly renamed `colorLevel` → `colorTier` on caps, then reverted
914
+ * in plateau-naming-polish (2026-04-23) because `level` was already the
915
+ * canonical vocabulary across the stack (Style.level, createStyle({ level }),
916
+ * pickColorLevel, Pipeline.ColorLevel, run({ colorLevel })). Alignment won.
796
917
  */
797
- /** A parsed Base16 color scheme. All hex values are WITHOUT `#` prefix. */
798
- interface Base16Scheme {
799
- scheme: string;
800
- author: string;
801
- base00: string;
802
- base01: string;
803
- base02: string;
804
- base03: string;
805
- base04: string;
806
- base05: string;
807
- base06: string;
808
- base07: string;
809
- base08: string;
810
- base09: string;
811
- base0A: string;
812
- base0B: string;
813
- base0C: string;
814
- base0D: string;
815
- base0E: string;
816
- base0F: string;
918
+ interface TerminalCaps {
919
+ /** Can the host reposition the cursor? True when the output stream is a
920
+ * TTY and `TERM` is not `"dumb"`. Absorbed from the standalone
921
+ * `detectCursor()` helper in unicode-plateau Phase 3. */
922
+ readonly cursor: boolean;
923
+ /** Can the host read raw keystrokes? True when the input stream is a TTY
924
+ * and supports `setRawMode`. Absorbed from the standalone
925
+ * `detectInput()` helper in unicode-plateau Phase 4. */
926
+ readonly input: boolean;
927
+ /** Color support level. See {@link ColorLevel}. */
928
+ readonly colorLevel: ColorLevel;
929
+ /**
930
+ * Was the color tier forced by env vars (NO_COLOR / FORCE_COLOR) or a
931
+ * caller-supplied `colorLevel`? Equivalent to
932
+ * `colorProvenance === "env" || colorProvenance === "override"` — exposed
933
+ * as a precomputed boolean because that's the question every pre-quantize
934
+ * gate in run.tsx / create-app.tsx actually asks.
935
+ *
936
+ * Moved from {@link ./profile#TerminalProfile} into caps in Phase 7 — it
937
+ * describes *color* resolution, which is caps-adjacent, so grouping it here
938
+ * means all color-tier metadata travels as one unit.
939
+ */
940
+ readonly colorForced: boolean;
941
+ /**
942
+ * Which rung of the precedence chain resolved {@link colorLevel}. Use
943
+ * {@link colorForced} for the common "was the tier forced?" check; use this
944
+ * enum only when the specific rung matters (e.g. diagnostics, theme
945
+ * detection, debug output).
946
+ */
947
+ readonly colorProvenance: ColorProvenance;
948
+ /** Unicode/emoji support */
949
+ readonly unicode: boolean;
950
+ /**
951
+ * Extended SGR 4:x underline styles this terminal advertises. Empty array
952
+ * means "only the standard SGR 4 single underline is known to work" and
953
+ * consumers should fall back accordingly.
954
+ *
955
+ * Phase 7 upgrade: was a single `boolean` (all-or-nothing). With the array
956
+ * a terminal that supports curly but not dotted can report that precisely;
957
+ * style.ts now checks `caps.underlineStyles.includes("curly")` per style.
958
+ */
959
+ readonly underlineStyles: readonly UnderlineStyle[];
960
+ /** SGR 58 underline color */
961
+ readonly underlineColor: boolean;
962
+ /**
963
+ * SGR 53/55 overline support. SGR 53 draws a line ABOVE the character cell,
964
+ * complementing the underline (SGR 4) below. Most modern terminals support
965
+ * it (Ghostty, iTerm2, xterm with extended attrs); the output phase skips
966
+ * emit when this is false so older terminals don't render the literal
967
+ * escape as text. See {@link BoxProps#overline} for the UI-facing prop.
968
+ */
969
+ readonly overline: boolean;
970
+ /** OSC 66 text sizing protocol likely supported (Kitty 0.40+, Ghostty).
971
+ * Phase 7 rename: dropped the verbose `Supported` suffix. */
972
+ readonly textSizing: boolean;
973
+ /** Kitty keyboard protocol supported */
974
+ readonly kittyKeyboard: boolean;
975
+ /** Bracketed paste mode */
976
+ readonly bracketedPaste: boolean;
977
+ /** SGR mouse tracking */
978
+ readonly mouse: boolean;
979
+ /** Kitty graphics protocol (inline images) */
980
+ readonly kittyGraphics: boolean;
981
+ /** Sixel graphics supported */
982
+ readonly sixel: boolean;
983
+ /** OSC 52 clipboard */
984
+ readonly osc52: boolean;
985
+ /** OSC 8 hyperlinks */
986
+ readonly hyperlinks: boolean;
987
+ /** OSC 9/99 notifications */
988
+ readonly notifications: boolean;
989
+ /** Synchronized output (DEC 2026) */
990
+ readonly syncOutput: boolean;
991
+ /** Heuristic: likely dark background (for theme selection). Use
992
+ * {@link probeTerminalProfile} with OSC 11 to resolve definitively. */
993
+ readonly maybeDarkBackground: boolean;
994
+ /** Heuristic: likely has Nerd Font installed (for icon selection).
995
+ * Sniffed from TERM / LC_TERMINAL / known-modern terminal programs. */
996
+ readonly maybeNerdFont: boolean;
997
+ /** Heuristic: text-presentation emoji (`⚠` `☑` `⭐` — `Extended_Pictographic`
998
+ * without default `Emoji_Presentation`) rendered as 2 cells. Modern terminals
999
+ * (Ghostty, iTerm, Kitty) render these at emoji width (2 cells); Terminal.app
1000
+ * renders them at text width (1 cell). Affects measurer + layout. */
1001
+ readonly maybeWideEmojis: boolean;
817
1002
  }
818
- //#endregion
819
- //#region packages/theme/src/import/base16.d.ts
820
1003
  /**
821
- * Import a Base16 YAML (or JSON) scheme into a ColorScheme.
822
- *
823
- * Mapping:
824
- * base00 → background, base01 → brightBlack, base02 → selectionBackground,
825
- * base03 → white (muted fg), base05 → foreground/brightWhite,
826
- * base08 → red, base09 → brightRed, base0A → yellow,
827
- * base0B → green, base0C → cyan, base0D → blue, base0E → magenta,
828
- * base0F → brightMagenta.
829
- *
830
- * Bright color variants are derived by brightening normals.
831
- * `dark` is inferred from base00 luminance.
1004
+ * Default capabilities modern-terminal-ish defaults for headless / emulator /
1005
+ * unknown contexts. Heuristic fields (`maybe*`) bake in "probably dark, no
1006
+ * nerd font, wide emojis like Ghostty/iTerm" — callers override via
1007
+ * `createTerminalProfile({caps})`.
832
1008
  */
833
- declare function importBase16(yamlOrJson: string): ColorScheme;
1009
+ declare function defaultCaps(): TerminalCaps;
834
1010
  //#endregion
835
- //#region packages/theme/src/export/base16.d.ts
1011
+ //#region packages/ansi/src/types.d.ts
836
1012
  /**
837
- * Export a ColorScheme to Base16 YAML format.
838
- *
839
- * Mapping:
840
- * background → base00, brightBlack → base01, selectionBackground → base02,
841
- * white → base03, (interpolated) → base04, foreground → base05,
842
- * (interpolated) → base06, (interpolated) → base07,
843
- * red → base08, brightRed → base09, yellow → base0A, green → base0B,
844
- * cyan → base0C, blue → base0D, magenta → base0E, brightMagenta → base0F.
1013
+ * Type definitions for @silvery/ansi
845
1014
  */
846
- declare function exportBase16(palette: ColorScheme): string;
847
- //#endregion
848
- //#region packages/theme/src/schemes/catppuccin.d.ts
849
- /** Catppuccin Mocha — the classic dark variant. */
850
- declare const catppuccinMocha: ColorScheme;
851
- /** Catppuccin Frappe — muted dark variant. */
852
- declare const catppuccinFrappe: ColorScheme;
853
- /** Catppuccin Macchiato — warm dark variant. */
854
- declare const catppuccinMacchiato: ColorScheme;
855
- /** Catppuccin Latte — the light variant. */
856
- declare const catppuccinLatte: ColorScheme;
857
- //#endregion
858
- //#region packages/theme/src/schemes/nord.d.ts
859
- /** Nord — the classic dark arctic theme. */
860
- declare const nord: ColorScheme;
861
- //#endregion
862
- //#region packages/theme/src/schemes/dracula.d.ts
863
- /** Dracula — vibrant dark theme. */
864
- declare const dracula: ColorScheme;
865
- //#endregion
866
- //#region packages/theme/src/schemes/solarized.d.ts
867
- /** Solarized Dark — Ethan Schoonover's classic dark variant. */
868
- declare const solarizedDark: ColorScheme;
869
- /** Solarized Light — Ethan Schoonover's classic light variant. */
870
- declare const solarizedLight: ColorScheme;
871
- //#endregion
872
- //#region packages/theme/src/schemes/tokyo-night.d.ts
873
- /** Tokyo Night — the default dark variant. */
874
- declare const tokyoNight: ColorScheme;
875
- /** Tokyo Night Storm — slightly lighter background. */
876
- declare const tokyoNightStorm: ColorScheme;
877
- /** Tokyo Night Day — the light variant. */
878
- declare const tokyoNightDay: ColorScheme;
879
- //#endregion
880
- //#region packages/theme/src/schemes/one-dark.d.ts
881
- /** One Dark — the classic Atom editor theme. */
882
- declare const oneDark: ColorScheme;
883
- //#endregion
884
- //#region packages/theme/src/schemes/gruvbox.d.ts
885
- /** Gruvbox Dark — warm retro dark theme. */
886
- declare const gruvboxDark: ColorScheme;
887
- /** Gruvbox Light — warm retro light theme. */
888
- declare const gruvboxLight: ColorScheme;
889
- //#endregion
890
- //#region packages/theme/src/schemes/rose-pine.d.ts
891
- /** Rosé Pine — the main dark variant. */
892
- declare const rosePine: ColorScheme;
893
- /** Rosé Pine Moon — slightly lighter dark variant. */
894
- declare const rosePineMoon: ColorScheme;
895
- /** Rosé Pine Dawn — the light variant. */
896
- declare const rosePineDawn: ColorScheme;
897
- //#endregion
898
- //#region packages/theme/src/schemes/kanagawa.d.ts
899
- /** Kanagawa Wave — the default dark variant, inspired by "The Great Wave off Kanagawa". */
900
- declare const kanagawaWave: ColorScheme;
901
- /** Kanagawa Dragon — a muted, earthy dark variant. */
902
- declare const kanagawaDragon: ColorScheme;
903
- /** Kanagawa Lotus — the light variant, inspired by lotus flowers. */
904
- declare const kanagawaLotus: ColorScheme;
905
- //#endregion
906
- //#region packages/theme/src/schemes/everforest.d.ts
907
- /** Everforest Dark — warm green-based dark theme (medium background). */
908
- declare const everforestDark: ColorScheme;
909
- /** Everforest Light — warm green-based light theme (medium background). */
910
- declare const everforestLight: ColorScheme;
911
- //#endregion
912
- //#region packages/theme/src/schemes/monokai.d.ts
913
- /** Monokai Classic — the original Sublime Text Monokai colors. */
914
- declare const monokai: ColorScheme;
915
- /** Monokai Pro — the modern, refined Monokai with balanced colors. */
916
- declare const monokaiPro: ColorScheme;
917
- //#endregion
918
- //#region packages/theme/src/schemes/snazzy.d.ts
919
- /** Snazzy — clean dark theme by Sindre Sorhus. */
920
- declare const snazzy: ColorScheme;
921
- //#endregion
922
- //#region packages/theme/src/schemes/material.d.ts
923
- /** Material Darker — the deep dark Material variant. */
924
- declare const materialDark: ColorScheme;
925
- /** Material Lighter — the light Material variant. */
926
- declare const materialLight: ColorScheme;
927
- //#endregion
928
- //#region packages/theme/src/schemes/palenight.d.ts
929
- /** Palenight — the soft, purple-tinted Material dark variant. */
930
- declare const palenight: ColorScheme;
931
- //#endregion
932
- //#region packages/theme/src/schemes/ayu.d.ts
933
- /** Ayu Dark — deep dark variant with warm accents. */
934
- declare const ayuDark: ColorScheme;
935
- /** Ayu Mirage — balanced dark variant with softer contrast. */
936
- declare const ayuMirage: ColorScheme;
937
- /** Ayu Light — clean light variant. */
938
- declare const ayuLight: ColorScheme;
939
- //#endregion
940
- //#region packages/theme/src/schemes/nightfox.d.ts
941
- /** Nightfox — dark blue-toned variant. */
942
- declare const nightfox: ColorScheme;
943
- /** Dawnfox — warm light variant inspired by Rose Pine Dawn. */
944
- declare const dawnfox: ColorScheme;
945
- //#endregion
946
- //#region packages/theme/src/schemes/horizon.d.ts
947
- /** Horizon — warm dark variant with vivid accents. */
948
- declare const horizon: ColorScheme;
949
- //#endregion
950
- //#region packages/theme/src/schemes/moonfly.d.ts
951
- /** Moonfly — dark charcoal theme. */
952
- declare const moonfly: ColorScheme;
953
- //#endregion
954
- //#region packages/theme/src/schemes/nightfly.d.ts
955
- /** Nightfly — midnight-blue dark theme. */
956
- declare const nightfly: ColorScheme;
957
- //#endregion
958
- //#region packages/theme/src/schemes/oxocarbon.d.ts
959
- /** Oxocarbon Dark — IBM Carbon-inspired dark variant. */
960
- declare const oxocarbonDark: ColorScheme;
961
- /** Oxocarbon Light — IBM Carbon-inspired light variant. */
962
- declare const oxocarbonLight: ColorScheme;
963
- //#endregion
964
- //#region packages/theme/src/schemes/sonokai.d.ts
965
- /** Sonokai — vivid dark theme with Monokai-inspired accents. */
966
- declare const sonokai: ColorScheme;
967
- //#endregion
968
- //#region packages/theme/src/schemes/edge.d.ts
969
- /** Edge Dark — clean dark variant with balanced accents. */
970
- declare const edgeDark: ColorScheme;
971
- /** Edge Light — clean, readable light variant. */
972
- declare const edgeLight: ColorScheme;
973
- //#endregion
974
- //#region packages/theme/src/schemes/modus.d.ts
975
- /** Modus Vivendi — elegant dark theme with maximum legibility. */
976
- declare const modusVivendi: ColorScheme;
977
- /** Modus Operandi — elegant light theme with maximum legibility. */
978
- declare const modusOperandi: ColorScheme;
979
- //#endregion
980
- //#region packages/theme/src/schemes/index.d.ts
981
1015
  /**
982
- * Dark ANSI 16 theme — hex-valued, derived from the default dark scheme.
983
- * All token values are hex strings (no ANSI slot names).
984
- * Terminal rendering quantizes hex to 4-bit ANSI codes when colorLevel === "basic".
1016
+ * The canonical 4-state color tier supported by a terminal.
985
1017
  *
986
- * Sterling flat tokens (`bg-surface-subtle`, `fg-on-accent`, `border-focus`, …)
987
- * are baked in at construction consumers can read either legacy fields or
988
- * Sterling flat keys off the same Theme object.
1018
+ * One enum, one spelling used everywhere a color capability is described
1019
+ * (caps, style level, chalk compat, tier quantization, etc.).
1020
+ *
1021
+ * - `"mono"` — no color (OSC queries disabled, monochrome attribute fallback).
1022
+ * - `"ansi16"` — 16-slot palette (SGR 30-37, 90-97 / 40-47, 100-107).
1023
+ * - `"256"` — xterm-256 palette (SGR 38;5;n).
1024
+ * - `"truecolor"` — 24-bit RGB (SGR 38;2;r;g;b).
1025
+ *
1026
+ * Prior to km-silvery.terminal-profile-plateau this type went by three
1027
+ * different names with three different spellings for the no-color case
1028
+ * (`null`, `"none"`, `"mono"`). Canonicalized to `ColorLevel` + `"mono"`.
989
1029
  */
990
- declare const ansi16DarkTheme: Theme$1;
1030
+ type ColorLevel = "mono" | "ansi16" | "256" | "truecolor";
991
1031
  /**
992
- * Light ANSI 16 theme hex-valued, derived from the default light scheme.
993
- * All token values are hex strings (no ANSI slot names).
994
- * Terminal rendering quantizes hex to 4-bit ANSI codes when colorLevel === "basic".
995
- *
996
- * Sterling flat tokens baked in at construction.
1032
+ * RGB color tuple for underline color.
1033
+ * Each component is 0-255.
997
1034
  */
998
- declare const ansi16LightTheme: Theme$1;
999
- /** Dark truecolor theme — derived from Nord. Sterling flat tokens baked in. */
1000
- declare const defaultDarkTheme: Theme$1;
1001
- /** Light truecolor theme — derived from Catppuccin Latte. Sterling flat tokens baked in. */
1002
- declare const defaultLightTheme: Theme$1;
1003
- /** All built-in ColorScheme definitions (70+ palettes). */
1004
- declare const builtinPalettes: Record<string, ColorScheme>;
1005
- /** All built-in themes, indexed by name (includes backward-compat aliases). */
1006
- declare const builtinThemes: Record<string, Theme$1>;
1007
- /** Resolve a theme by name. Defaults to dark-ansi16. */
1008
- declare function getThemeByName(name?: string): Theme$1;
1009
- /** Resolve a palette by name. Returns undefined if not found. */
1010
- declare function getSchemeByName(name: string): ColorScheme | undefined;
1011
- //#endregion
1012
- //#region packages/theme/src/detect.d.ts
1035
+ type RGB = [r: number, g: number, b: number];
1013
1036
  /**
1014
- * Detect the terminal's palette and return a Sterling-aware Theme.
1037
+ * Extended underline styles supported by modern terminals.
1015
1038
  *
1016
- * Identical to `@silvery/ansi`'s `detectTheme` but every returned theme has
1017
- * Sterling flat tokens baked in via `inlineSterlingTokens`.
1039
+ * - `single`: Standard underline (SGR 4:1)
1040
+ * - `double`: Two parallel lines (SGR 4:2)
1041
+ * - `curly`: Wavy/squiggly line (SGR 4:3) - commonly used for spell check
1042
+ * - `dotted`: Dotted line (SGR 4:4)
1043
+ * - `dashed`: Dashed line (SGR 4:5)
1018
1044
  */
1019
- declare function detectTheme(opts?: DetectThemeOptions): Promise<Theme$1>;
1045
+ type UnderlineStyle = "single" | "double" | "curly" | "dotted" | "dashed";
1020
1046
  //#endregion
1021
- //#region packages/theme/src/sterling/types.d.ts
1047
+ //#region packages/ansi/src/color-maps.d.ts
1022
1048
  /**
1023
- * Surface-only state pair: only `bg` varies by state. Used by the status
1024
- * roles (`info`, `success`, `warning`, `error`) where state variants are
1025
- * meaningful only for surfaces (filled bg), never for text.
1049
+ * Hex-in / hex-out quantization for previews.
1026
1050
  *
1027
- * Text tokens on status roles don't hover `fg-error` is a status color,
1028
- * not an interactive link. Keeping `fg.hover` / `fg.active` on those roles
1029
- * invited algorithmic over-generation that produced illegible results
1030
- * (e.g. catppuccin-frappe `warning.active.fg` collapsing to `#FFFFFF`).
1031
- */
1032
- interface BgStatePair {
1033
- readonly bg: string;
1034
- }
1035
- /**
1036
- * Interactive (link-like) state pair: both `fg` and `bg` vary by state.
1037
- * Used by `accent` — the canonical interactive-text role.
1038
- */
1039
- interface StatePair {
1040
- readonly fg: string;
1041
- readonly bg: string;
1042
- }
1043
- /**
1044
- * A status role — fg, bg, and `fgOn` (text color to draw when rendering ON
1045
- * a filled bg of this role). State variants apply to SURFACE (bg) only;
1046
- * text-color state variants are reserved for link-like roles (`accent`).
1047
- */
1048
- interface InteractiveRole {
1049
- /** Foreground hex — use for text/icon in this role. */
1050
- readonly fg: string;
1051
- /** Background hex — use as fill for emphasis. */
1052
- readonly bg: string;
1053
- /** Foreground to use when drawing ON `bg` (contrast-picked). */
1054
- readonly fgOn: string;
1055
- /** Hover state — surface only (adaptive ±L shift on bg). */
1056
- readonly hover: BgStatePair;
1057
- /** Active (pressed) state — surface only (adaptive ±L shift on bg). */
1058
- readonly active: BgStatePair;
1059
- }
1060
- /**
1061
- * Accent — the canonical link-like interactive-text role. Has everything
1062
- * `InteractiveRole` does PLUS a focus-ring border AND `fg.hover` /
1063
- * `fg.active` text-color state variants (link hover treatments).
1064
- */
1065
- interface AccentRole {
1066
- /** Foreground hex — use for text/icon in accent. */
1067
- readonly fg: string;
1068
- /** Background hex — use as fill for emphasis. */
1069
- readonly bg: string;
1070
- /** Foreground to use when drawing ON `bg` (contrast-picked). */
1071
- readonly fgOn: string;
1072
- /** Border color for focus rings using this accent. */
1073
- readonly border: string;
1074
- /** Hover state — both fg (link hover) and bg (surface hover). */
1075
- readonly hover: StatePair;
1076
- /** Active (pressed) state — both fg and bg. */
1077
- readonly active: StatePair;
1078
- }
1079
- /** Surface hierarchy — `default` is the canvas, subtle/raised/overlay stack upward. */
1080
- interface SurfaceRole {
1081
- readonly default: string;
1082
- readonly subtle: string;
1083
- readonly raised: string;
1084
- readonly overlay: string;
1085
- readonly hover: string;
1086
- }
1087
- /** Border roles — `focus` is the focus-ring color; `default` is normal rule line. */
1088
- interface BorderRole {
1089
- readonly default: string;
1090
- readonly focus: string;
1091
- readonly muted: string;
1092
- }
1093
- /** Cursor colors. */
1094
- interface CursorRole {
1095
- readonly fg: string;
1096
- readonly bg: string;
1097
- }
1098
- /** Muted role — lower-emphasis text/bg for deemphasized content. */
1099
- interface MutedRole {
1100
- readonly fg: string;
1101
- readonly bg: string;
1102
- }
1103
- /**
1104
- * The nested, programmatic form of a Theme. All leaf values are hex strings.
1105
- * Reached via `theme.accent.bg`, `theme.surface.raised`, etc.
1106
- */
1107
- interface Roles {
1108
- readonly accent: AccentRole;
1109
- readonly info: InteractiveRole;
1110
- readonly success: InteractiveRole;
1111
- readonly warning: InteractiveRole;
1112
- readonly error: InteractiveRole;
1113
- readonly muted: MutedRole;
1114
- readonly surface: SurfaceRole;
1115
- readonly border: BorderRole;
1116
- readonly cursor: CursorRole;
1117
- }
1118
- /**
1119
- * Every flat hyphen-key that Sterling emits. String-literal union so that
1120
- * `theme["bg-accent"]` is type-checked and typos fail the compile.
1051
+ * Takes any hex color and returns the hex a real terminal at that tier would
1052
+ * actually emit. Used by the Sterling storybook to make the `1/2/3/4` tier
1053
+ * toggle visibly different in-process the output phase already does this
1054
+ * when writing to a real TTY, but preview surfaces (theme swatches, rendered
1055
+ * components inside a storybook app) bypass output-phase quantization. Apply
1056
+ * `quantizeHex` at render time to mimic tier-specific terminal output.
1121
1057
  *
1122
- * Grammar: `prefix-role[-state]` or `prefix-on-role` or `prefix-role-kind[-state]`.
1123
- * (See design-system.md §"Flattening rule".)
1058
+ * - `truecolor`: returns the input unchanged (normalized to `#rrggbb`).
1059
+ * - `256`: snaps to the nearest xterm-256 slot, then returns that slot's hex.
1060
+ * - `ansi16`: snaps to one of the 16 standard slots (canonical xterm RGB).
1061
+ * - `mono`: luminance threshold (>= 0.5 → `#ffffff`, else `#000000`).
1062
+ *
1063
+ * Returns the input unchanged if it cannot be parsed as a hex color.
1124
1064
  */
1125
- type FlatToken = "bg-surface-default" | "bg-surface-subtle" | "bg-surface-raised" | "bg-surface-overlay" | "bg-surface-hover" | "border-default" | "border-focus" | "border-muted" | "fg-cursor" | "bg-cursor" | "fg-muted" | "bg-muted" | "fg-accent" | "bg-accent" | "fg-on-accent" | "fg-accent-hover" | "bg-accent-hover" | "fg-accent-active" | "bg-accent-active" | "border-accent" | "fg-info" | "bg-info" | "fg-on-info" | "bg-info-hover" | "bg-info-active" | "fg-success" | "bg-success" | "fg-on-success" | "bg-success-hover" | "bg-success-active" | "fg-warning" | "bg-warning" | "fg-on-warning" | "bg-warning-hover" | "bg-warning-active" | "fg-error" | "bg-error" | "fg-on-error" | "bg-error-hover" | "bg-error-active";
1126
- /** The flat projection — every FlatToken maps to a hex string. */
1127
- type FlatTokens = { readonly [K in FlatToken]: string };
1065
+ declare function quantizeHex(hex: string, tier: ColorLevel): string;
1128
1066
  /**
1129
- * Per-token record of HOW a token was derived. Populated only when the
1130
- * derivation is called with `{ trace: true }`. Used by the Sterling
1131
- * storybook to visualize derivation rules.
1067
+ * Pre-quantize every hex leaf in a Theme (or any object tree) to the
1068
+ * requested color tier.
1069
+ *
1070
+ * Walks the input recursively — each string leaf matching `#rgb` / `#rrggbb`
1071
+ * is passed through {@link quantizeHex}; all other values (numbers, booleans,
1072
+ * non-hex strings like `"Nord"`, null/undefined, arrays of non-hex values)
1073
+ * pass through unchanged. Arrays and nested objects are rebuilt with
1074
+ * quantized leaves.
1075
+ *
1076
+ * Works on both the legacy ANSI Theme (flat hex tokens + `palette` array)
1077
+ * and the Sterling Theme (nested roles + flat tokens) — the structural rule
1078
+ * "any leaf that looks like a hex is a color value" holds for both.
1079
+ *
1080
+ * @example Pre-cache tier variants
1081
+ * ```ts
1082
+ * import { pickColorLevel } from "silvery"
1083
+ *
1084
+ * const themes = {
1085
+ * truecolor: theme,
1086
+ * ansi16: pickColorLevel(theme, "ansi16"),
1087
+ * mono: pickColorLevel(theme, "mono"),
1088
+ * }
1089
+ * ```
1090
+ *
1091
+ * @example Storybook — show multiple tiers simultaneously
1092
+ * ```tsx
1093
+ * <ThemeProvider theme={pickColorLevel(theme, "ansi16")}>
1094
+ * <AlertPreview />
1095
+ * </ThemeProvider>
1096
+ * ```
1097
+ *
1098
+ * Notes:
1099
+ * - `truecolor` is a no-op — returns the input unchanged (identity).
1100
+ * - The result is structurally identical to the input (same keys, same
1101
+ * nesting); only hex leaves are remapped.
1102
+ * - Idempotent per tier: `pickColorLevel(pickColorLevel(t, "ansi16"), "ansi16")`
1103
+ * yields the same hex values as `pickColorLevel(t, "ansi16")`.
1104
+ * - Does not freeze the returned object. Callers that want immutability
1105
+ * should `Object.freeze()` (or deep-freeze) the result themselves.
1132
1106
  */
1133
- interface DerivationStep {
1134
- /** Token path (e.g. `"accent.hover.bg"` or flat `"bg-accent-hover"`). */
1135
- readonly token: string;
1136
- /** Human-readable rule name (e.g. `"OKLCH +0.04L on accent.bg"`). */
1137
- readonly rule: string;
1138
- /** Input hex(es) the rule operated on. */
1139
- readonly inputs: readonly string[];
1140
- /** Output hex. */
1141
- readonly output: string;
1142
- /** If auto-lift adjusted this token, the original value before adjustment. */
1143
- readonly liftedFrom?: string;
1144
- /** If pinned by scheme author, true. */
1145
- readonly pinned?: boolean;
1146
- }
1147
- type DerivationTrace = readonly DerivationStep[];
1107
+ declare function pickColorLevel<T>(theme: T, tier: ColorLevel): T;
1108
+ //#endregion
1109
+ //#region packages/ansi/src/terminal-control.d.ts
1148
1110
  /**
1149
- * Categorical color ring 8 harmonious hues for tagging, chart series,
1150
- * calendar categories, priority levels — any CATEGORICAL color that isn't
1151
- * stateful. ensureContrast-adjusted against bg at derivation time. Consumers
1152
- * access these via `$red`, `$orange`, …, `$pink` or direct field access.
1111
+ * Enable mouse tracking with full hover support.
1153
1112
  *
1154
- * Distinguish from:
1155
- * - `$color0..$color15` — raw terminal ANSI (user's theme verbatim)
1156
- * - `$error/$warning/$success` — semantic state (communicates meaning)
1157
- * - `$brand` — app identity anchor (one color)
1113
+ * Uses two modes:
1114
+ * - **1003** (any-event tracking): Reports ALL mouse motion — clicks, drags, AND hover.
1115
+ * This is what makes onMouseEnter/onMouseLeave work. Without it, only clicks are reported.
1116
+ * - **1006** (SGR encoding): Decimal coordinates with no 223-column limit.
1117
+ * - **1016** (SGR-Pixels): Optional pixel coordinates in the same SGR shape.
1118
+ *
1119
+ * WARNING: Do NOT replace 1003 with 1000+1002. The xterm mouse modes form a hierarchy:
1120
+ * 1000 = clicks only
1121
+ * 1002 = clicks + drag (motion while button held)
1122
+ * 1003 = clicks + drag + hover (ALL motion, even without button)
1123
+ * Mode 1003 supersedes 1000 and 1002. Using 1000+1002 instead of 1003 silently
1124
+ * disables hover — onMouseEnter/onMouseLeave stop firing with no error.
1158
1125
  */
1159
- interface CategoricalHues {
1160
- readonly red: string;
1161
- readonly orange: string;
1162
- readonly yellow: string;
1163
- readonly green: string;
1164
- readonly teal: string;
1165
- readonly blue: string;
1166
- readonly purple: string;
1167
- readonly pink: string;
1126
+ interface MouseModeOptions {
1127
+ /** Enable xterm SGR-Pixels mode 1016 in addition to 1003/1006. */
1128
+ pixels?: boolean;
1168
1129
  }
1130
+ declare function enableMouse(options?: MouseModeOptions): string;
1169
1131
  /**
1170
- * The canonical Sterling Theme Sterling flat tokens + nested roles on the
1171
- * same object, plus a small surface of non-token metadata and runtime
1172
- * convenience fields the framework depends on:
1132
+ * Disable mouse tracking. Disables in reverse order of enabling.
1133
+ */
1134
+ declare function disableMouse(): string;
1135
+ /**
1136
+ * Enable the Kitty keyboard protocol (push mode).
1173
1137
  *
1174
- * Two access paths for every hex leaf:
1175
- * - Nested: `theme.accent.hover.bg`
1176
- * - Flat: `theme["bg-accent-hover"]`
1177
- * Both paths reference the same string (not copies). The object is frozen
1178
- * after derivation (see `flatten.ts`).
1138
+ * Sends CSI > flags u to opt into the specified modes.
1139
+ * Supported by: Ghostty, Kitty, WezTerm, foot. Ignored by unsupported terminals.
1179
1140
  *
1180
- * Non-token metadata:
1181
- * - `name` — scheme display name (if derived from a named scheme)
1182
- * - `mode` — light/dark
1183
- * - `derivationTrace` — optional; present only when `{ trace: true }` was passed
1184
- * - `variants` — typography preset bundles (h1, body, code, …) resolved by
1185
- * `<Text variant="…">`
1186
- * - `palette` — 16-slot ANSI catalog used by `$color0` … `$color15`
1187
- * - categorical hues (`red`, `orange`, `yellow`, `green`, `teal`, `blue`,
1188
- * `purple`, `pink`) — hex strings for categorical UI
1141
+ * Flags are a bitfield:
1189
1142
  *
1190
- * The nested roles (`accent`, `muted`, `surface`, `border`, `cursor`, plus
1191
- * the status roles `info`/`success`/`warning`/`error`) are authoritative for
1192
- * stateful tokens. Legacy flat hex aliases for these roles (`theme.primary`,
1193
- * `theme.muted`, `theme.accent` as strings) are emitted as runtime
1194
- * conveniences via the scheme-builder but are not part of this type — they
1195
- * were deleted in silvery 0.19.0.
1143
+ * | Flag | Bit | Description |
1144
+ * | ---- | --- | ----------------------------------------- |
1145
+ * | 1 | 0 | Disambiguate escape codes |
1146
+ * | 2 | 1 | Report event types (press/repeat/release) |
1147
+ * | 4 | 2 | Report alternate keys |
1148
+ * | 8 | 3 | Report all keys as escape codes |
1149
+ * | 16 | 4 | Report associated text |
1150
+ *
1151
+ * @param flags Bitfield of Kitty keyboard flags
1196
1152
  */
1197
- type Theme = FlatTokens & Roles & {
1198
- readonly name?: string;
1199
- readonly mode: "light" | "dark";
1200
- readonly derivationTrace?: DerivationTrace;
1201
- readonly variants: Record<string, Variant>;
1202
- readonly palette: readonly string[];
1203
- } & CategoricalHues;
1153
+ declare function enableKittyKeyboard(flags?: number): string;
1204
1154
  /**
1205
- * A typography variant a named bundle of visual properties applied to a
1206
- * Text component via `variant="h1"`. The variant acts as a *default*: caller
1207
- * props always win over variant values.
1208
- *
1209
- * Color values follow the same syntax as `TextColor` — `$token` strings, hex
1210
- * values, ANSI names, or any string accepted by the color system.
1155
+ * Disable the Kitty keyboard protocol (pop mode stack).
1156
+ * Sends CSI < u to restore the previous keyboard mode.
1211
1157
  */
1212
- interface Variant {
1213
- readonly color?: string;
1214
- readonly backgroundColor?: string;
1215
- readonly bold?: boolean;
1216
- readonly italic?: boolean;
1217
- readonly dim?: boolean;
1218
- readonly underlineStyle?: "single" | "double" | "curly" | "dotted" | "dashed";
1219
- }
1158
+ declare function disableKittyKeyboard(): string;
1159
+ //#endregion
1160
+ //#region packages/ansi/src/style/style.d.ts
1220
1161
  /**
1221
- * Metadata describing a DesignSystem's Theme shapefor tooling (docs,
1222
- * storybook, CSS export). Plain data, no functions.
1162
+ * Resolve a color value against a theme the canonical token resolver.
1163
+ *
1164
+ * If the color starts with `$`, looks up the token in the theme.
1165
+ * Supports `$primary`, `$surface-bg` (hyphens stripped), `$color0`–`$color15` (palette).
1166
+ * Non-`$` strings pass through unchanged. Returns undefined if no theme or unknown token.
1167
+ *
1168
+ * Compatible with @silvery/theme's Theme type (or any object with string properties).
1223
1169
  */
1224
- interface ThemeShape {
1225
- /** The list of FlatTokens this system emits. */
1226
- readonly flatTokens: readonly string[];
1227
- /** The list of role-object keys this system emits (e.g. `["accent", "info", ...]`). */
1228
- readonly roles: readonly string[];
1229
- /** The list of state variants used on interactive roles (e.g. `["hover", "active"]`). */
1230
- readonly states: readonly string[];
1231
- }
1232
- /** Contrast enforcement mode for derivation. See D3 in sterling-preflight.md. */
1233
- type ContrastMode = /** Throw on WCAG AA failure on core role pairs. Used by catalog tests. */"strict" /** Auto-lift failing tokens via OKLCH L shifts. Used for user schemes. */ | "auto-lift";
1234
- /** Options accepted by all derivation entry points. */
1235
- interface DeriveOptions {
1236
- /** Default: `"auto-lift"`. */
1237
- readonly contrast?: ContrastMode;
1238
- /** If true, attach `derivationTrace` to the returned Theme. Default: false. */
1239
- readonly trace?: boolean;
1240
- /**
1241
- * Per-role token pins. A scheme author can pin specific tokens (e.g.
1242
- * `{ "error.fg": "#bf616a" }`) to skip auto-adjustment. The path syntax is
1243
- * nested-style: `"accent.hover.bg"`, `"error.fg"`. Flat-form pins are
1244
- * also accepted: `{ "bg-accent": "#...", "fg-on-error": "#..." }`.
1245
- */
1246
- readonly pins?: Readonly<Record<string, string>>;
1247
- /**
1248
- * Force light/dark inference. By default inferred from
1249
- * `scheme.dark` or WCAG luminance of `scheme.background`.
1250
- */
1251
- readonly mode?: "light" | "dark";
1170
+ declare function resolveThemeColor(name: string | undefined, theme: object | undefined): string | undefined;
1171
+ //#endregion
1172
+ //#region packages/ansi/src/theme/derive.d.ts
1173
+ interface ThemeAdjustment {
1174
+ token: string;
1175
+ from: string;
1176
+ to: string;
1177
+ against: string;
1178
+ target: number;
1179
+ ratioBefore: number;
1180
+ ratioAfter: number;
1252
1181
  }
1253
1182
  /**
1254
- * The `DesignSystem` contract. Sterling is the default implementation; other
1255
- * packages (e.g. `@silvery/design-material`) publish alternatives matching
1256
- * this shape.
1183
+ * Derive a Theme from a ColorScheme, with Sterling flat tokens baked in.
1184
+ *
1185
+ * Every Theme `@silvery/ansi` produces passes through `inlineSterlingTokens`
1186
+ * so consumers can read `$bg-accent`, `$bg-surface-overlay`, `$border-default`,
1187
+ * `$fg-muted`, etc. directly off the returned object. This is the one
1188
+ * canonical Theme shape in silvery — there is no separate "partial" Theme.
1257
1189
  */
1258
- interface DesignSystem {
1259
- /** Display name for tooling (e.g. `"sterling"`). */
1260
- readonly name: string;
1261
- /** Metadata about this system's Theme shape. */
1262
- readonly shape: ThemeShape;
1190
+ declare function deriveTheme(palette: ColorScheme, mode?: "ansi16" | "truecolor", adjustments?: ThemeAdjustment[]): Theme;
1191
+ //#endregion
1192
+ //#region packages/ansi/src/theme/orchestrator.d.ts
1193
+ /** How the final scheme was decided. */
1194
+ type DetectSource = "override" | "fingerprint" | "probed" | "bg-mode" | "fallback";
1195
+ /** Where each slot's value came from. */
1196
+ type SlotSource = "probed" | "catalog" | "derived" | "fallback";
1197
+ interface DetectSchemeResult {
1198
+ /** The resolved 22-slot color scheme. */
1199
+ scheme: ColorScheme;
1200
+ /** The derived, validated Theme (via loadTheme). */
1201
+ theme: Theme;
1202
+ /** How the scheme was determined overall. */
1203
+ source: DetectSource;
1204
+ /** 0–1 confidence heuristic (exact override = 1, fingerprint = match score, fallback = 0). */
1205
+ confidence: number;
1206
+ /** Per-slot provenance. Keys are ColorScheme field names. */
1207
+ slotSources: Partial<Record<keyof ColorScheme, SlotSource>>;
1208
+ /** If fingerprint matched, the catalog scheme name. */
1209
+ matchedName?: string;
1210
+ }
1211
+ interface DetectSchemeOptions {
1212
+ /** Explicit override — if provided, skips all probing. */
1213
+ override?: ColorScheme;
1214
+ /** Catalog to fingerprint against. If empty or undefined, skip fingerprinting. */
1215
+ catalog?: readonly ColorScheme[];
1216
+ /** OSC probe timeout (ms). Default 150. */
1217
+ timeoutMs?: number;
1218
+ /** Force dark/light inference when no bg is probed. */
1219
+ darkFallback?: boolean;
1263
1220
  /**
1264
- * Whether the framework should auto-apply `bakeFlat` to each derivation's
1265
- * output projecting hex leaves onto flat hyphen-keys on the same object.
1266
- *
1267
- * - `true` — use {@link defaultFlattenRule} (channel-role-state, Sterling style)
1268
- * - `FlattenRule` — system-specific rule (e.g. Material `onPrimary`)
1269
- * - `false` or omitted — no auto-flatten (system is responsible, or
1270
- * consumer only uses nested form)
1271
- *
1272
- * Sterling and anything modelled on it should set `flatten: true` —
1273
- * flat-projection-on-same-object is a universal feature of nested
1274
- * hex-leaf POJOs and Sterling users expect `theme["bg-accent"]` access.
1221
+ * Apply strict invariant validation to the loaded Theme. Default `lenient`.
1222
+ * See `loadTheme`'s `enforce` parameter.
1275
1223
  */
1276
- readonly flatten?: boolean | FlattenRule;
1277
- /** Return a raw default Theme, no input required. */
1278
- defaults(mode?: "light" | "dark"): Theme;
1224
+ enforce?: "strict" | "lenient" | "off";
1225
+ /** Add WCAG contrast check to the invariant validation. Default `false`. */
1226
+ wcag?: boolean;
1279
1227
  /**
1280
- * Fill partial theme values with defaults. Useful for hand-curated themes
1281
- * that override a few roles.
1228
+ * Optional InputOwner (from `@silvery/ag-term/runtime`). When provided,
1229
+ * OSC queries route through it instead of touching process.stdin directly.
1230
+ * See `probeColors` for the ownership rationale.
1282
1231
  */
1283
- theme(partial?: DeepPartial<Theme>, opts?: DeriveOptions): Theme;
1284
- /** Derive from a 22-color terminal scheme — Sterling's primary path. */
1285
- deriveFromScheme(scheme: ColorScheme, opts?: DeriveOptions): Theme;
1286
- /** Derive from a single seed color — Material-style. */
1287
- deriveFromColor(color: string, opts?: DeriveOptions & {
1288
- mode?: "light" | "dark";
1289
- }): Theme;
1290
- /** Derive from a light/dark scheme pair. */
1291
- deriveFromPair(light: ColorScheme, dark: ColorScheme, opts?: DeriveOptions): {
1292
- light: Theme;
1293
- dark: Theme;
1294
- };
1295
- /** Derive from a scheme plus a brand-color overlay (F — brand discipline). */
1296
- deriveFromSchemeWithBrand(scheme: ColorScheme, brand: string, opts?: DeriveOptions): Theme;
1232
+ input?: ProbeInputOwner;
1297
1233
  }
1298
- /** Utility: recursive `Partial` for nested Theme overrides. */
1299
- type DeepPartial<T> = T extends object ? T extends readonly unknown[] ? T : { [K in keyof T]?: DeepPartial<T[K]> } : T;
1300
- //#endregion
1301
- //#region packages/theme/src/sterling/sterling.d.ts
1302
1234
  /**
1303
- * Sterling the user-facing DesignSystem. `defineDesignSystem` wraps
1304
- * `rawSterling` with auto-`bakeFlat` (per `flatten: true`), so every
1305
- * returned Theme has both nested roles AND flat hyphen keys populated.
1235
+ * Detect the terminal's color scheme + derive a theme in one call.
1236
+ *
1237
+ * Runs the 4-layer detection cascade (override probe fingerprint
1238
+ * fallback) and returns a fully-resolved Theme along with provenance metadata
1239
+ * so callers can log how the scheme was determined.
1240
+ *
1241
+ * This is the recommended entry point for apps — it handles all the gotchas
1242
+ * (non-TTY environments, failed probes, partial OSC responses, catalog matches,
1243
+ * bg-mode inference) and returns something you can hand to `ThemeProvider`.
1244
+ *
1245
+ * @example
1246
+ * ```ts
1247
+ * import { detectScheme } from "@silvery/ansi"
1248
+ * import { builtinPalettes } from "@silvery/theme/schemes"
1249
+ *
1250
+ * const { scheme, theme, source, matchedName, confidence } = await detectScheme({
1251
+ * catalog: Object.values(builtinPalettes),
1252
+ * enforce: "lenient",
1253
+ * })
1254
+ * console.log(`${source === "fingerprint" ? `detected ${matchedName}` : source} (${(confidence * 100).toFixed(0)}%)`)
1255
+ * ```
1306
1256
  */
1307
- declare const sterling: DesignSystem;
1308
- //#endregion
1309
- //#region packages/theme/src/sterling/define.d.ts
1257
+ declare function detectScheme(opts?: DetectSchemeOptions): Promise<DetectSchemeResult>;
1310
1258
  /**
1311
- * Wrap a DesignSystem so every derivation method auto-applies `bakeFlat`
1312
- * per the `flatten` flag. Pass your raw system (one that returns nested
1313
- * themes) and this returns a user-facing system whose outputs have flat
1314
- * keys populated.
1259
+ * Shortcut: detect scheme + return the Theme only. For apps that don't care
1260
+ * about provenance. Same defaults as `detectScheme`.
1261
+ *
1262
+ * @example
1263
+ * ```ts
1264
+ * const theme = await detectSchemeTheme({ catalog: Object.values(builtinPalettes) })
1265
+ * render(<ThemeProvider theme={theme}>…</ThemeProvider>)
1266
+ * ```
1315
1267
  */
1316
- declare function defineDesignSystem(def: DesignSystem): DesignSystem;
1268
+ declare function detectSchemeTheme(opts?: DetectSchemeOptions): Promise<Theme>;
1317
1269
  //#endregion
1318
- //#region packages/theme/src/sterling/contrast.d.ts
1319
- /**
1320
- * Sterling contrast guardrails — D3 from sterling-preflight.md.
1321
- *
1322
- * Two modes:
1323
- * - `strict` — throw when a core role pair fails WCAG AA 4.5:1.
1324
- * Used by the catalog test (all 84 shipped schemes must pass).
1325
- * - `auto-lift` — adjust OKLCH lightness until AA passes (±0.04L increments
1326
- * up to ~0.20L). Logs at debug; silent by default. Used for user schemes
1327
- * at runtime.
1328
- *
1329
- * Pinned tokens (per-role overrides supplied by scheme authors) are excluded
1330
- * from auto-lift and from strict-mode enforcement — the author accepts the
1331
- * contrast consequence of pinning.
1332
- */
1333
- /** WCAG AA threshold for normal text. */
1334
- declare const WCAG_AA = 4.5;
1335
- interface ContrastViolation {
1336
- readonly token: string;
1337
- readonly fg: string;
1338
- readonly bg: string;
1339
- readonly ratio: number;
1340
- readonly target: number;
1341
- }
1342
- declare class ContrastError extends Error {
1343
- readonly violations: readonly ContrastViolation[];
1344
- constructor(violations: readonly ContrastViolation[]);
1345
- }
1270
+ //#region packages/ansi/src/theme/tokens.d.ts
1346
1271
  /**
1347
- * Verify `fg` on `bg` meets `target` ratio. Returns `null` when already
1348
- * passing; otherwise returns a ContrastViolation.
1272
+ * Built-in variant names the standard typography presets shipped by silvery.
1273
+ * These are the default keys in `Theme.variants`.
1349
1274
  */
1350
- declare function checkAA(token: string, fg: string, bg: string, target?: number): ContrastViolation | null;
1275
+ type VariantName = "h1" | "h2" | "h3" | "body" | "body-muted" | "fine-print" | "strong" | "em" | "link" | "key" | "code" | "kbd";
1351
1276
  /**
1352
- * Auto-lift `fg` against `bg` until the `target` contrast ratio is met,
1353
- * via OKLCH L shifts (hue + chroma preserved). Light bg → darken;
1354
- * dark bg lighten.
1355
- *
1356
- * Implementation note: binary-searches the minimum L shift achieving the
1357
- * target. Falls back to a best-effort value if the target is unreachable
1358
- * (e.g., yellow against white can never hit 4.5:1 at any lightness while
1359
- * preserving yellow hue; the result is the darkest in-gamut yellow).
1277
+ * Any variant name — built-in or app-defined. The `(string & {})` tail is the
1278
+ * Tailwind trick: preserves IDE autocomplete for the literal union while still
1279
+ * accepting any runtime string value.
1360
1280
  */
1361
- declare function autoLift(fg: string, bg: string, target?: number): {
1362
- value: string;
1363
- lifted: boolean;
1364
- };
1281
+ type KnownVariant = VariantName | (string & {});
1365
1282
  //#endregion
1366
- //#region packages/theme/src/sterling/derive.d.ts
1283
+ //#region packages/ansi/src/osc-palette.d.ts
1367
1284
  /**
1368
- * Derive a Theme's nested roles from a ColorScheme. Guardrails applied.
1285
+ * OSC 4 Terminal Color Palette Query/Set pure ANSI protocol.
1369
1286
  */
1370
- declare function deriveRoles(scheme: ColorScheme, opts: DeriveOptions): {
1371
- roles: Roles;
1372
- mode: "light" | "dark";
1373
- trace: DerivationStep[];
1374
- violations: ContrastViolation[];
1375
- };
1287
+ declare function queryPaletteColor(index: number, write: (data: string) => void): void;
1288
+ declare function queryMultiplePaletteColors(indices: number[], write: (data: string) => void): void;
1289
+ declare function setPaletteColor(index: number, color: string, write: (data: string) => void): void;
1290
+ declare function parsePaletteResponse(input: string): {
1291
+ index: number;
1292
+ color: string;
1293
+ } | null;
1294
+ //#endregion
1295
+ //#region packages/ansi/src/osc-colors.d.ts
1296
+ declare function queryForegroundColor(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<string | null>;
1297
+ declare function queryBackgroundColor(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<string | null>;
1298
+ declare function queryCursorColor(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<string | null>;
1299
+ declare function setForegroundColor(write: (data: string) => void, color: string): void;
1300
+ declare function setBackgroundColor(write: (data: string) => void, color: string): void;
1301
+ declare function setCursorColor(write: (data: string) => void, color: string): void;
1302
+ declare function resetForegroundColor(write: (data: string) => void): void;
1303
+ declare function resetBackgroundColor(write: (data: string) => void): void;
1304
+ declare function resetCursorColor(write: (data: string) => void): void;
1305
+ declare function detectColorScheme(write: (data: string) => void, read: (timeoutMs: number) => Promise<string | null>, timeoutMs?: number): Promise<"light" | "dark" | null>;
1306
+ //#endregion
1307
+ //#region packages/ansi/src/theme/generate.d.ts
1376
1308
  /**
1377
- * Derive a full Theme (pre-flatten) from a ColorScheme. Throws `ContrastError`
1378
- * in strict mode if any role pair fails WCAG AA. Callers typically wrap this
1379
- * with `flatten()` (from `flatten.ts`) to get the user-facing Theme.
1309
+ * Generate a complete ANSI 16 theme from a primary color + dark/light preference.
1380
1310
  *
1381
- * Returned Theme is NOT frozen and DOES NOT contain flat keys yet.
1311
+ * All token values are ANSI color names (e.g. "yellow", "blueBright").
1382
1312
  */
1383
- declare function deriveTheme(scheme: ColorScheme, opts?: DeriveOptions): Omit<Theme, keyof FlatTokens>;
1384
- //#endregion
1385
- //#region packages/theme/src/sterling/flat-tokens.d.ts
1386
- declare const STERLING_FLAT_TOKENS: readonly FlatToken[];
1387
- //#endregion
1388
- //#region packages/theme/src/sterling/defaults.d.ts
1389
- declare function defaultScheme(mode?: "light" | "dark"): ColorScheme;
1313
+ declare function generateTheme(primary: AnsiPrimary, dark: boolean): Theme;
1390
1314
  //#endregion
1391
- export { ayuMirage as $, resetBackgroundColor as $t, detectTheme as A, pickColorLevel as An, Base16Scheme as At, modusVivendi as B, createTheme as Bt, InteractiveRole as C, disableMouse as Cn, nord as Ct, SurfaceRole as D, bakeFlat as Dn, catppuccinMocha as Dt, StatePair as E, FlattenRule as En, catppuccinMacchiato as Et, defaultDarkTheme as F, detectTerminalCaps as Fn, ThemeValidationResult as Ft, oxocarbonLight as G, fromColors as Gt, edgeLight as H, quickTheme as Ht, defaultLightTheme as I, validateTheme as It, horizon as J, generateTheme$1 as Jt, nightfly as K, fromPreset as Kt, getSchemeByName as L, ValidationResult as Lt, ansi16LightTheme as M, ColorLevel as Mn, resolveAliases as Mt, builtinPalettes as N, TerminalCaps as Nn, resolveTokenAlias as Nt, Theme as O, defaultFlattenRule as On, exportBase16 as Ot, builtinThemes as P, defaultCaps as Pn, THEME_TOKEN_KEYS as Pt, ayuLight as Q, queryForegroundColor as Qt, getThemeByName as R, validateColorScheme as Rt, FlatTokens as S, disableKittyKeyboard as Sn, dracula as St, Roles as T, enableMouse as Tn, catppuccinLatte as Tt, sonokai as U, assignPrimaryToSlot as Ut, edgeDark as V, presetTheme as Vt, oxocarbonDark as W, fromBase16 as Wt, nightfox as X, queryBackgroundColor as Xt, dawnfox as Y, detectColorScheme as Yt, ayuDark as Z, queryCursorColor as Zt, DerivationStep as _, AnsiPrimary as _n, tokyoNight as _t, ContrastError as a, parsePaletteResponse as an, monokaiPro as at, DesignSystem as b, Theme$1 as bn, solarizedDark as bt, autoLift as c, setPaletteColor as cn, kanagawaDragon as ct, sterling as d, detectTerminalScheme as dn, rosePine as dt, resetCursorColor as en, palenight as et, AccentRole as f, KnownVariant as fn, rosePineDawn as ft, DeepPartial as g, ActiveScheme as gn, oneDark as gt, CursorRole as h, deriveTheme$1 as hn, gruvboxLight as ht, deriveTheme as i, setForegroundColor as in, monokai as it, ansi16DarkTheme as j, quantizeHex as jn, themeToCSSVars as jt, ThemeShape as k, ColorTier as kn, importBase16 as kt, checkAA as l, DetectThemeOptions as ln, kanagawaLotus as lt, ContrastMode as m, DetectSchemeResult as mn, gruvboxDark as mt, STERLING_FLAT_TOKENS as n, setBackgroundColor as nn, materialLight as nt, ContrastViolation as o, queryMultiplePaletteColors as on, everforestDark as ot, BorderRole as p, DetectSchemeOptions as pn, rosePineMoon as pt, moonfly as q, generateTheme as qt, deriveRoles as r, setCursorColor as rn, snazzy as rt, WCAG_AA as s, queryPaletteColor as sn, everforestLight as st, defaultScheme as t, resetForegroundColor as tn, materialDark as tt, defineDesignSystem as u, DetectedScheme as un, kanagawaWave as ut, DerivationTrace as v, COLOR_SCHEME_FIELDS as vn, tokyoNightDay as vt, MutedRole as w, enableKittyKeyboard as wn, catppuccinFrappe as wt, FlatToken as x, resolveThemeColor as xn, solarizedLight as xt, DeriveOptions as y, ColorScheme as yn, tokyoNightStorm as yt, modusOperandi as z, autoGenerateTheme as zt };
1392
- //# sourceMappingURL=index-D3saHouR.d.mts.map
1315
+ export { BorderRole as $, quantizeHex as A, createTerminalProfile as B, deriveTheme as C, enableKittyKeyboard as D, disableMouse as E, defaultCaps as F, detectTheme as G, DetectThemeOptions as H, ColorProvenance as I, AnsiPrimary as J, probeColors as K, CreateTerminalProfileOptions as L, RGB as M, UnderlineStyle as N, enableMouse as O, TerminalCaps as P, AccentRole as Q, ProbeTerminalProfileOptions as R, detectSchemeTheme as S, disableKittyKeyboard as T, DetectedScheme as U, probeTerminalProfile as V, detectTerminalScheme as W, ColorScheme as X, COLOR_SCHEME_FIELDS as Y, HueName as Z, DetectSchemeOptions as _, bakeFlat as _t, queryForegroundColor as a, DeriveOptions as at, SlotSource as b, resetForegroundColor as c, FlatTokens as ct, setForegroundColor as d, Roles as dt, ContrastMode as et, parsePaletteResponse as f, StatePair as ft, KnownVariant as g, FlattenRule as gt, setPaletteColor as h, ThemeShape as ht, queryCursorColor as i, DerivationTrace as it, ColorLevel as j, pickColorLevel as k, setBackgroundColor as l, InteractiveRole as lt, queryPaletteColor as m, Theme as mt, detectColorScheme as n, DeepPartial as nt, resetBackgroundColor as o, DesignSystem as ot, queryMultiplePaletteColors as p, SurfaceRole as pt, ActiveScheme as q, queryBackgroundColor as r, DerivationStep as rt, resetCursorColor as s, FlatToken as st, generateTheme as t, CursorRole as tt, setCursorColor as u, MutedRole as ut, DetectSchemeResult as v, defaultFlattenRule as vt, resolveThemeColor as w, detectScheme as x, DetectSource as y, TerminalEmulator as yt, TerminalProfile as z };
1316
+ //# sourceMappingURL=index-CSQf13CI.d.mts.map