@wix/himalaya-cli 0.1539.0 → 0.1541.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.
Binary file
@@ -205,7 +205,7 @@
205
205
  ]
206
206
  }
207
207
  ],
208
- "propsSource": "export interface TextFieldProps {\n placeholder?: string;\n /** LITERAL initial text. Renderers paint it verbatim — a `$service:` sentinel\n * here shows the raw token to the user. Bind `valuePath` instead. */\n value?: string;\n /** `$service:`/`$item.` binding → live text from the worker (overrides `value`).\n * Adopted while the field is NOT focused; an empty worker value (a draft reset\n * after send/post/submit) is adopted even mid-focus, so a cleared draft empties\n * the field without the worker ever fighting the caret. */\n valuePath?: string;\n onChange?: Action;\n /** Text input enrichments. */\n keyboard?: Keyboard;\n secure?: boolean;\n multilineMaxLines?: number;\n maxLength?: number;\n autoCapitalization?: AutoCapitalization;\n onSubmit?: Action;\n /** Keyboard control. `suggestions: \"off\"` kills autocorrect + the suggestion\n * strip. `submitLabel` paints the return key and, with `onSubmit`, fires it —\n * submitting dismisses the keyboard except for `\"next\"`, which keeps it up so\n * a worker can move focus on. */\n suggestions?: Suggestions;\n submitLabel?: SubmitLabel;\n /** `$service:` binding → a TOKEN the worker changes to focus this field. Focus\n * is requested whenever the resolved value becomes a new NON-EMPTY value\n * (the first seed included, so a non-empty init focuses on open). Use a\n * monotonic nonce — `String(Date.now())` — since a latched boolean cannot\n * re-fire. Blur is the keyboard-dismiss capability, not a token here. */\n focusPath?: string;\n /** Accessory & state enrichments. */\n leadingIcon?: IconRef;\n trailingIcon?: IconRef;\n clearButton?: boolean;\n helperText?: string;\n error?: boolean;\n prefix?: string;\n suffix?: string;\n /** Drop the default rounded-border chrome so a caller background shows (composer pill). */\n borderless?: boolean;\n /** Declarative syntactic rules the RENDERER evaluates, so they hold with no\n * worker running (Tier 0-4) and with no bridge round-trip. Before this,\n * validation was reachable only by wrapping the field in `Form` -> `FormField`\n * - the shape the design guide steers you away from for hero flows. */\n validation?: Validation;\n /** `$service:`/`$item.` binding -> a worker-computed error string. Non-empty =\n * invalid. This is how SEMANTIC and CROSS-FIELD errors (\"passwords don't\n * match\", \"email taken\") reach the same error slot, with the same styling and\n * a11y wiring, as the declarative ones. Wins over `validation.message`. */\n errorPath?: string;\n /** LITERAL error string for a server-rendered screen with no worker to bind.\n * Lower precedence than `errorPath`, higher than the rules. */\n errorText?: string;\n /** Opt-in accessible show/hide button. Only applies to secure fields; initially masked. */\n visibilityToggle?: boolean;\n}"
208
+ "propsSource": "export interface TextFieldProps {\n placeholder?: string;\n /** LITERAL initial text. Renderers paint it verbatim — a `$service:` sentinel\n * here shows the raw token to the user. Bind `valuePath` instead. */\n value?: string;\n /** `$service:`/`$item.` binding → live text from the worker (overrides `value`).\n * Adopted while the field is NOT focused; an empty worker value (a draft reset\n * after send/post/submit) is adopted even mid-focus, so a cleared draft empties\n * the field without the worker ever fighting the caret. */\n valuePath?: string;\n onChange?: Action;\n /** Text input enrichments. */\n keyboard?: Keyboard;\n secure?: boolean;\n multilineMaxLines?: number;\n maxLength?: number;\n autoCapitalization?: AutoCapitalization;\n onSubmit?: Action;\n /** Keyboard control. `suggestions: \"off\"` kills autocorrect + the suggestion\n * strip. `submitLabel` paints the return key and, with `onSubmit`, fires it —\n * submitting dismisses the keyboard except for `\"next\"`, which keeps it up so\n * a worker can move focus on. */\n suggestions?: Suggestions;\n submitLabel?: SubmitLabel;\n /** `$service:` binding → a TOKEN the worker changes to focus this field. Focus\n * is requested whenever the resolved value becomes a new NON-EMPTY value\n * (the first seed included, so a non-empty init focuses on open). Use a\n * monotonic nonce — `String(Date.now())` — since a latched boolean cannot\n * re-fire. Blur is the keyboard-dismiss capability, not a token here. */\n focusPath?: string;\n /** Accessory & state enrichments. */\n leadingIcon?: IconRef;\n trailingIcon?: IconRef;\n clearButton?: boolean;\n helperText?: string;\n error?: boolean;\n prefix?: string;\n suffix?: string;\n /** Drop the default rounded-border chrome so a caller background shows (composer pill). */\n borderless?: boolean;\n /** Declarative syntactic rules the RENDERER evaluates, so they hold with no\n * worker running (Tier 0-4) and with no bridge round-trip. Before this,\n * validation was reachable only by wrapping the field in `Form` -> `FormField`\n * - the shape the design guide steers you away from for hero flows. */\n validation?: Validation;\n /** `$service:`/`$item.` binding -> a worker-computed error string. Non-empty =\n * invalid. This is how SEMANTIC and CROSS-FIELD errors (\"passwords don't\n * match\", \"email taken\") reach the same error slot, with the same styling and\n * a11y wiring, as the declarative ones. Wins over `validation.message`. */\n errorPath?: string;\n /** LITERAL error string for a server-rendered screen with no worker to bind.\n * Lower precedence than `errorPath`, higher than the rules. */\n errorText?: string;\n /** Opt-in accessible show/hide button. Only applies to secure fields; initially masked. */\n visibilityToggle?: boolean;\n /** `onChange` fires after this many ms of idle typing. 0 or unset = every change.\n * A submit fires a pending debounced `onChange` first. */\n debounceMs?: number;\n}"
209
209
  },
210
210
  {
211
211
  "name": "Toggle",
@@ -422,7 +422,9 @@
422
422
  "name": "SearchField",
423
423
  "category": "Search & filter",
424
424
  "propsType": "SearchFieldProps",
425
- "bindings": [],
425
+ "bindings": [
426
+ "focusPath"
427
+ ],
426
428
  "dispatches": [
427
429
  {
428
430
  "callback": "onChange",
@@ -437,7 +439,7 @@
437
439
  "note": "These two rows share a control and key, so they are NOT independently gated: a payload observation cannot say which callback produced it, and a helper-mediated dispatch does not name the callback at the write site at all. The gate proves the callback is still referenced in the component that dispatches, not that this callback carries the payload."
438
440
  }
439
441
  ],
440
- "propsSource": "export interface SearchFieldProps {\n placeholder?: string;\n value?: string;\n onChange?: Action;\n onSubmit?: Action;\n debounceMs?: number;\n}"
442
+ "propsSource": "export interface SearchFieldProps {\n placeholder?: string;\n value?: string;\n onChange?: Action;\n onSubmit?: Action;\n /** `onChange` fires after this many ms of idle typing; 0 or less (or unset) = 250 ms.\n * A submit fires a pending debounced `onChange` first. */\n debounceMs?: number;\n /** `$service:` binding → a focus TOKEN; `TextFieldProps.focusPath` semantics. */\n focusPath?: string;\n}"
441
443
  },
442
444
  {
443
445
  "name": "FilterChips",
@@ -58,7 +58,7 @@ See also **[Modifiers](#modifiers)** (the `modifiers` block) and **[Actions](#ac
58
58
  | `Skeleton` | State envelopes | — |
59
59
  | `FragmentSlot` | Descriptor-shipped dynamic structure | `casePath` |
60
60
  | `WorkerSubtree` | Bounded worker-authored component tree | `treeJsonPath` |
61
- | `SearchField` | Search & filter | — |
61
+ | `SearchField` | Search & filter | `focusPath` |
62
62
  | `FilterChips` | Search & filter | `optionsPath`, `selectedIds` |
63
63
  | `Tabs` | Navigation primitives | `optionsPath`, `activeColorPath`, `selectedId` |
64
64
  | `SegmentedControl` | Navigation primitives | `optionsPath`, `selectedId` |
@@ -620,6 +620,9 @@ export interface TextFieldProps {
620
620
  errorText?: string;
621
621
  /** Opt-in accessible show/hide button. Only applies to secure fields; initially masked. */
622
622
  visibilityToggle?: boolean;
623
+ /** `onChange` fires after this many ms of idle typing. 0 or unset = every change.
624
+ * A submit fires a pending debounced `onChange` first. */
625
+ debounceMs?: number;
623
626
  }
624
627
  ```
625
628
 
@@ -960,7 +963,11 @@ export interface SearchFieldProps {
960
963
  value?: string;
961
964
  onChange?: Action;
962
965
  onSubmit?: Action;
966
+ /** `onChange` fires after this many ms of idle typing; 0 or less (or unset) = 250 ms.
967
+ * A submit fires a pending debounced `onChange` first. */
963
968
  debounceMs?: number;
969
+ /** `$service:` binding → a focus TOKEN; `TextFieldProps.focusPath` semantics. */
970
+ focusPath?: string;
964
971
  }
965
972
  ```
966
973
 
@@ -80,6 +80,13 @@ The `ux_evidence_*` codes map to the existing typed `uxEvidence.state`; a succes
80
80
  `recorded` state has no refusal code. Successful pushes and warnings do not gain
81
81
  failure codes. A forced push still follows the existing override rules.
82
82
 
83
+ After a full `himi push --live`, push reads the app's rollout rings (`GET /v1/releases`). A ring
84
+ pinned to another release keeps serving that release to its devices, so the success envelope
85
+ then carries a `ring_pinned` entry in `warnings` (also printed to stderr) and
86
+ `ringPins: [{ ring, releaseId, promote }]`, where `promote` is the `himi promote … --ring <ring>`
87
+ that moves the ring to the new release. When the push passed `--control-url`, `promote` repeats it. It stays `ok: true`. When the rings cannot be read, push
88
+ prints neither.
89
+
83
90
  ## `himi cms seed` codes
84
91
 
85
92
  | Code | Meaning |
@@ -280,6 +287,16 @@ unresolved migration finding.
280
287
  - `topbar_coverage_failed`: a source top-bar control has no matching action
281
288
  with a non-empty `onTap.actionId` (exit 1).
282
289
 
290
+ ## `himi one-app validate-design` codes
291
+
292
+ - `invalid_usage`: required options are missing or incompatible (exit 2).
293
+ - `evidence_invalid`: the collected source evidence is missing or invalid (exit 1).
294
+ - `tokens_unreadable`: the token file cannot be read, or `--fix` cannot safely write it (exit 1).
295
+ - `design_mismatch`: a source value differs from the drawn target value (exit 1).
296
+ - `design_unresolved`: `--record` was requested while a design value still needs an
297
+ adapted ledger row; no evidence is written (exit 1).
298
+ - `record_failed`: `--record` could not safely write its private evidence files (exit 1).
299
+
283
300
  ## `himi one-app coverage` codes
284
301
 
285
302
  - `invalid_usage`: the mode or required paths are missing (exit 2).
@@ -151,6 +151,23 @@ Apply these interpretation rules:
151
151
  a feature to account for; they do not alone prove visibility or access for every
152
152
  visitor or member. Resolve those rules separately. This check is specific to this
153
153
  migration workflow; it does not change the behavior of `himi validate`.
154
+ - Before publishing, run the migration-only design check:
155
+ `himi one-app validate-design --evidence-dir .himi/one-app --content .`.
156
+ It resolves the effective source theme with the reader the source app instance
157
+ actually uses, then compares the resolved primary, background and content colors
158
+ and each button's `borderRadius` and `outlineWidth` against the app's `tokens.json`.
159
+ Hex case and shorthand are normalized; an absent button token is compared with the
160
+ value the renderer draws (an outline only on `secondary`; a radius of `radius.pill`,
161
+ else 24), not called a difference. A variant without its own radius must draw the
162
+ source radius at every Button size. A descriptor's per-button `cornerRadius` overrides
163
+ the tokens and is not checked. `--fix` writes the mismatching source values into
164
+ `tokens.json` and pins the dark and high-contrast schemes to what they drew before,
165
+ because a missing scheme falls back to the light value. Rebuild after `--fix`.
166
+ The report names every theme pointer the check did not compare, including typography
167
+ kits and any button `uppercase`, which Himi tokens cannot carry; resolve those
168
+ explicitly rather than treating a pass as full design parity. A deliberate difference
169
+ is waived only by a `design` coverage row with status `adapted` that cites the user's
170
+ instruction and explains the change. This check compares values, not rendered screens.
154
171
  - For each configured Detailed header, import and call the shared
155
172
  `detailedHeader` builder from `@wix/himalaya/screens`. Do not recreate its
156
173
  component tree in the app. Resolve the source fallback and visibility rules
@@ -254,15 +271,17 @@ Run `himi one-app coverage init --evidence-dir .himi/one-app --content .` to
254
271
  create `ONE-APP-COVERAGE.json` from the verified source graph. After edits or a
255
272
  CLI upgrade, run `coverage sync` and review new rows; `coverage check` fails when
256
273
  the file is absent or source requirements have appeared, disappeared or changed.
257
- Rows cover source graph warnings as well as routes and controls. This is an
258
- inventory of migration obligations, not proof that their target actions work.
274
+ Rows cover source graph warnings and app-wide design values as well as routes and
275
+ controls. This is an inventory of migration obligations, not proof that their target
276
+ actions work.
259
277
 
260
278
  Map each row to a target screen and, for interactions or top-bar controls, a
261
- target control. Set its `status` to `supported`, `adapted`, `conditional`, or
279
+ target control. A `design` row is app-wide, so it needs no screen or control: it is
280
+ satisfied by the design check instead. Set its `status` to `supported`, `adapted`, `conditional`, or
262
281
  `unresolved`. For an adaptation, cite the user's instruction and explain the
263
282
  change. Each resolved row needs a `verification` record using the required check
264
283
  ID for its kind (`route-walkthrough`, `visual-comparison`, `behavior-crawl`,
265
- `topbar-control`, `access-state`, or `source-resolution`), a safe relative path to
284
+ `topbar-control`, `access-state`, `design-token`, or `source-resolution`), a safe relative path to
266
285
  a JSON check record, and the exact release payload SHA-256 in `releaseHash`.
267
286
  The JSON file's `checks[]` must contain a passed record with that requirement ID,
268
287
  check ID, release hash, target mapping, and a relative `artifact` path to the
@@ -270,6 +289,25 @@ actual screenshot, test output, or walkthrough record. Multiple rows may share
270
289
  one file, but each needs its own passed check record. Keep private evidence under
271
290
  `.himi/` so it is excluded from the app source archive.
272
291
 
292
+ `design-token` evidence is the one kind nobody writes by hand. Run
293
+ `himi one-app validate-design --evidence-dir .himi/one-app --content . --record
294
+ --release-hash <64-hex-sha256>` after the release is built: it writes
295
+ `.himi/one-app/design-report.json` and `.himi/one-app/design-checks.json`, with one
296
+ passed record per matched or adapted design row, and refuses to write either file when
297
+ the check does not pass or any design row remains unresolved. Point each `design` row's
298
+ `verification` at the checks file. `--fix` writes only to a regular token file inside the
299
+ content directory; read-only validation can inspect an external token path.
300
+ The check also compares each idiom overlay selected by the app's statically readable policy
301
+ against the source value. An active overlay
302
+ that changes it needs a deliberate edit or an adapted ledger row that lists the overlay name in
303
+ `adaptation.idioms` (for example, `["ios"]`); a base-token adaptation alone does not waive it.
304
+ `--fix` repairs base tokens only.
305
+ A row the check cannot compare — an `unresolved` one, such as a button `uppercase` —
306
+ gets a record only once it is resolved as `adapted`, with the user's instruction and an
307
+ explanation. An adaptation counts only while the ledger's `sourceHashes` match the
308
+ collected evidence; after recollection, run `coverage sync` and decide again. `--record`
309
+ refuses `--fix` in the same run: the release hash names the tokens as built.
310
+
273
311
  For example, one entry in the referenced JSON file is:
274
312
 
275
313
  ```json
@@ -32,11 +32,12 @@ The dedicated flow has two renderers for one search model:
32
32
  new non-empty token when the screen opens; that focuses the field and opens
33
33
  the keyboard. If the screen has no worker, seed the token through local state.
34
34
  - **Debounce.** Let `onChange` update the query and start the search after the
35
- user pauses. The proposed native slot uses 250 ms when `debounceMs` is zero
36
- or unset; a pending change flushes before `onSubmit`, so the submitted query
37
- is current.
38
- For the existing inline `SearchField`, set `debounceMs` explicitly (150–300 ms
39
- for local filtering; 300–400 ms for a network search).
35
+ user pauses. `SearchField` (and the proposed native slot) uses 250 ms when
36
+ `debounceMs` is zero or unset, on every renderer; a pending change flushes
37
+ before `onSubmit`, so the submitted query is current. Set `debounceMs`
38
+ explicitly to tune it (150–300 ms for local filtering; 300–400 ms for a
39
+ network search). A `TextField` used as a search box debounces only when
40
+ `debounceMs` is set — unset, it sends every change.
40
41
  - **Clear.** Clear sets the query to `""`, runs `onChange` with the empty value,
41
42
  and returns to the initial state. It is not cancellation and must not invoke
42
43
  `onCancel`.
@@ -151,8 +152,9 @@ first; this recipe only adds the query layer.
151
152
  }
152
153
  ```
153
154
 
154
- - `debounceMs` batches keystrokes — 150–300ms is the sweet spot; without it every
155
- character dispatches a worker action.
155
+ - `debounceMs` batches keystrokes — 150–300ms is the sweet spot. Unset (or 0), a
156
+ `SearchField` waits 250 ms after the last keystroke; emptying the field sends `""`
157
+ at once.
156
158
  - `onSubmit` (keyboard search key) is optional when `onChange` already filters live.
157
159
  - For category/facet filtering alongside text search, add `FilterChips` with
158
160
  `optionsPath: "$service:posts.categories"` and a `selectCategory` action — same
@@ -16,6 +16,13 @@ areas, always in the same order, so you can skim for the one you care about.
16
16
 
17
17
  ## 2026-11-02
18
18
 
19
+ ### Getting started & the CLI
20
+
21
+ - The `restaurant`, `podcast-creator` and `podcast-creator-owner` starter templates no longer paint
22
+ their cream text on a light grey search field, segmented control and chips. Their `dark-luxe` kit
23
+ had no `surfaceTertiary`, so the base app's light value showed through at 1.04:1. The kit now
24
+ ships a dark `surfaceTertiary`. (#4999)
25
+
19
26
  ### Validate & test
20
27
 
21
28
  - **`himi validate` now judges `textPrimary` on card surfaces.** Body text was judged only against
@@ -25,6 +32,16 @@ areas, always in the same order, so you can skim for the one you care about.
25
32
  with an error (also for `textPrimary` on the page); below WCAG AA 4.5:1 it is a warning. The
26
33
  finding says when the page and the card sit on opposite sides of mid-grey, so no single text
27
34
  colour can serve both. (#4999)
35
+ - **`himi validate` now judges `textSecondary` too, and on every surface that text sits on.** Both
36
+ body text colours are judged against `surfaceSecondary` and `surfaceElevated` (cards, sheets, list
37
+ rows), `surfaceTertiary` (search fields, segmented controls, chips, badges) and `surfaceSubtle`
38
+ (Android's Material low containers). Below 1.5:1 validate fails with an error, on the page too;
39
+ below 4.5:1 it is a warning. (#4999)
40
+
41
+ ### Branded Lite & Owner Lite
42
+
43
+ - Branded Lite's dark-theme secondary text is now `#8B949E`. It clears 4.5:1 on the app's cards and
44
+ its search field; before, it was 4.31:1 on the search field. (#4999)
28
45
 
29
46
  ## 2026-11-01
30
47
 
@@ -143,6 +143,25 @@ preview — the `clientId` **is** the site binding (no separate MSID field). Pla
143
143
  `YOUR_WIX_CLIENT_ID` are not a real backend. Monorepo / native binary path:
144
144
  [branded-lite-site-binding.md](branded-lite-site-binding.md).
145
145
 
146
+ ### Keep the copied `_shared` helpers current
147
+
148
+ `init` copies the platform helpers under `tier5-src/_shared/` once, and nothing updates them. An old
149
+ copy keeps compiling against a newer platform and can break a feature without an error (an old
150
+ `iap-presentation.ts` left a Buy button disabled). So every build compares each copy with the ones
151
+ the running CLI ships. `himi build` lists a mismatch under `warnings`; `validate`, `push` and `pack`
152
+ report it as one issue (`pass: "stale-shared"`, `ruleCode: "shared-file-differs"`, `files: [{path,
153
+ shipped, alsoCopy}]`) with severity `warning`, which `--strict` does not promote. (`push --only`
154
+ lists it under `warnings`; `template publish` runs the same lint but prints issues only when it
155
+ refuses.) The message names each file and prints
156
+ the command that refreshes it, plus any `_shared` file the shipped copy imports that your package
157
+ lacks. A copy that matches any template's variant counts as current; the refresh takes the variant of
158
+ the template `init` recorded in `.himi/init-source.json`, or else the one closest to your copy. Files
159
+ the CLI does not ship are yours and are not checked.
160
+
161
+ When you changed a helper on purpose, add a `// himi:forked` line to it and the check skips that
162
+ file; `himi template sweep` adds that line to any `_shared` file it rewrites. Nothing else records
163
+ which files you edited after `init`, so an unmarked edit and an old copy look the same.
164
+
146
165
  ## Publish your own
147
166
 
148
167
  Any himi app can *become* a template. Add a `himalaya.template.json` next to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1539.0",
3
+ "version": "0.1541.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -71,5 +71,5 @@
71
71
  "artifactId": "himalaya-cli"
72
72
  }
73
73
  },
74
- "falconPackageHash": "cf2aec518d6f8738d5ae5bc0969628fe4258bf6977f4621442bbd5d4"
74
+ "falconPackageHash": "77f49a0fa384b30d68adfb678fda491e11084dd3f66b62764b113aaf"
75
75
  }
@@ -32,6 +32,10 @@
32
32
  "light": "#101319",
33
33
  "dark": "#101319"
34
34
  },
35
+ "surfaceTertiary": {
36
+ "light": "#232834",
37
+ "dark": "#232834"
38
+ },
35
39
  "textPrimary": {
36
40
  "light": "#F1E9D2",
37
41
  "dark": "#F1E9D2"
@@ -6,7 +6,7 @@
6
6
  "surfaceSubtle": { "light": "#F8FAF9", "dark": "#121821", "highContrast": "#111111" },
7
7
  "surfaceTertiary": { "light": "#E9EEF0", "dark": "#232A32", "highContrast": "#1A1A1A" },
8
8
  "textPrimary": { "light": "#1F2328", "dark": "#E6EDF3", "highContrast": "#FFFFFF" },
9
- "textSecondary": { "light": "#59636E", "dark": "#848D98", "highContrast": "#CCCCCC" },
9
+ "textSecondary": { "light": "#59636E", "dark": "#8B949E", "highContrast": "#CCCCCC" },
10
10
  "textTertiary": { "light": "#7D8791", "dark": "#6E7681", "highContrast": "#CCCCCC" },
11
11
  "textOnAccent": { "light": "#FFFFFF", "dark": "#FFFFFF", "highContrast": "#000000" },
12
12
  "accentPrimary": { "light": "#0A66C2", "dark": "#1E72C7", "highContrast": "#58A6FF" },
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "textSecondary": {
34
34
  "light": "#59636E",
35
- "dark": "#848D98",
35
+ "dark": "#8B949E",
36
36
  "highContrast": "#CCCCCC"
37
37
  },
38
38
  "textTertiary": {
@@ -21,8 +21,8 @@
21
21
  "highContrast": "#111111"
22
22
  },
23
23
  "surfaceTertiary": {
24
- "light": "#E9EEF0",
25
- "dark": "#232A32",
24
+ "light": "#232834",
25
+ "dark": "#232834",
26
26
  "highContrast": "#1A1A1A"
27
27
  },
28
28
  "textPrimary": {
@@ -96,8 +96,8 @@
96
96
  "highContrast": "#FFFFFF"
97
97
  },
98
98
  "accentText": {
99
- "light": "#8B6FFF",
100
- "dark": "#957CFF",
99
+ "light": "#947AFF",
100
+ "dark": "#947AFF",
101
101
  "highContrast": "#AE9AFF"
102
102
  }
103
103
  },
@@ -11,8 +11,8 @@
11
11
  "highContrast": "#111111"
12
12
  },
13
13
  "surfaceTertiary": {
14
- "light": "#E4E4E7",
15
- "dark": "#27272A",
14
+ "light": "#232834",
15
+ "dark": "#232834",
16
16
  "highContrast": "#111111"
17
17
  },
18
18
  "surfaceElevated": {
@@ -92,8 +92,8 @@
92
92
  "dark": "#221214"
93
93
  },
94
94
  "accentText": {
95
- "light": "#9474E1",
96
- "dark": "#9A7CE2",
95
+ "light": "#9B7DE3",
96
+ "dark": "#9B7DE3",
97
97
  "highContrast": "#B49DEA"
98
98
  }
99
99
  },
@@ -21,8 +21,8 @@
21
21
  "highContrast": "#111111"
22
22
  },
23
23
  "surfaceTertiary": {
24
- "light": "#E9EEF0",
25
- "dark": "#232A32",
24
+ "light": "#232834",
25
+ "dark": "#232834",
26
26
  "highContrast": "#1A1A1A"
27
27
  },
28
28
  "textPrimary": {
@@ -96,8 +96,8 @@
96
96
  "highContrast": "#FFFFFF"
97
97
  },
98
98
  "accentText": {
99
- "light": "#C36E65",
100
- "dark": "#C87B74",
99
+ "light": "#C87A72",
100
+ "dark": "#C87A72",
101
101
  "highContrast": "#D49892"
102
102
  }
103
103
  },