@livenetworks/ashlar 2.0.7 → 2.0.8

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 (207) hide show
  1. package/LICENSE +641 -641
  2. package/components/COMPONENTS.md +1116 -1116
  3. package/components/index.js +81 -81
  4. package/components/ln-accordion/ln-accordion-dev.scss +8 -8
  5. package/components/ln-accordion/ln-accordion.js +1 -1
  6. package/components/ln-accordion/ln-accordion.schema.json +30 -30
  7. package/components/ln-ajax/ln-ajax-dev.scss +8 -8
  8. package/components/ln-ajax/ln-ajax.js +1 -1
  9. package/components/ln-ajax/ln-ajax.schema.json +30 -30
  10. package/components/ln-api-connector/ln-api-connector.js +1 -1
  11. package/components/ln-api-connector/ln-api-connector.schema.json +96 -96
  12. package/components/ln-api-connector/src/ln-api-connector.js +1 -0
  13. package/components/ln-api-queue/ln-api-queue.js +1 -1
  14. package/components/ln-api-queue/ln-api-queue.schema.json +34 -34
  15. package/components/ln-api-queue/src/ln-api-queue.js +3 -13
  16. package/components/ln-autoresize/ln-autoresize-dev.scss +8 -8
  17. package/components/ln-autoresize/ln-autoresize.js +1 -1
  18. package/components/ln-autoresize/ln-autoresize.schema.json +22 -22
  19. package/components/ln-autosave/ln-autosave-dev.scss +13 -13
  20. package/components/ln-autosave/ln-autosave.js +1 -1
  21. package/components/ln-autosave/ln-autosave.schema.json +48 -48
  22. package/components/ln-autosave/src/autosave-model.js +34 -34
  23. package/components/ln-chart/ln-chart.js +1 -1
  24. package/components/ln-chart/ln-chart.schema.json +146 -146
  25. package/components/ln-chart/src/chart-model.js +154 -154
  26. package/components/ln-circular-progress/ln-circular-progress.js +1 -1
  27. package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -42
  28. package/components/ln-confirm/ln-confirm-dev.scss +24 -24
  29. package/components/ln-confirm/ln-confirm.js +1 -1
  30. package/components/ln-confirm/ln-confirm.schema.json +66 -66
  31. package/components/ln-confirm/src/ln-confirm.js +178 -178
  32. package/components/ln-core/crypto.js +286 -265
  33. package/components/ln-core/dom.js +115 -115
  34. package/components/ln-core/form.js +136 -136
  35. package/components/ln-core/helpers.js +33 -33
  36. package/components/ln-core/http.js +48 -48
  37. package/components/ln-core/index.js +1 -1
  38. package/components/ln-core/ln-core.schema.json +109 -109
  39. package/components/ln-core/locale.js +55 -55
  40. package/components/ln-core/matching.js +78 -78
  41. package/components/ln-core/number.js +125 -125
  42. package/components/ln-core/template.js +206 -206
  43. package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  44. package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -50
  45. package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +1 -0
  46. package/components/ln-data-coordinator/README.md +9 -38
  47. package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -8
  48. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
  49. package/components/ln-data-coordinator/ln-data-coordinator.schema.json +16 -16
  50. package/components/ln-data-coordinator/src/data-read-policy.js +0 -7
  51. package/components/ln-data-coordinator/src/ln-data-coordinator.js +428 -1308
  52. package/components/ln-data-store/ln-data-store-dev.scss +13 -13
  53. package/components/ln-data-store/ln-data-store.js +1 -1
  54. package/components/ln-data-store/ln-data-store.schema.json +84 -84
  55. package/components/ln-data-store/src/data-store-model.js +184 -184
  56. package/components/ln-data-store/src/ln-data-store.js +1 -1
  57. package/components/ln-date/ln-date.js +1 -1
  58. package/components/ln-date/ln-date.schema.json +92 -92
  59. package/components/ln-date/src/date-model.js +186 -186
  60. package/components/ln-debug/ln-debug.js +1 -1
  61. package/components/ln-debug/ln-debug.schema.json +28 -28
  62. package/components/ln-debug/src/console-sink.js +19 -19
  63. package/components/ln-debug/src/gate.js +95 -95
  64. package/components/ln-debug/src/generated-attributes.js +2 -2
  65. package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
  66. package/components/ln-dropdown/ln-dropdown.js +1 -1
  67. package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
  68. package/components/ln-editor/ln-editor.js +1 -1
  69. package/components/ln-editor/ln-editor.schema.json +58 -58
  70. package/components/ln-external-links/ln-external-links.js +1 -1
  71. package/components/ln-external-links/ln-external-links.schema.json +18 -18
  72. package/components/ln-fill/ln-fill.js +1 -1
  73. package/components/ln-fill/ln-fill.schema.json +23 -23
  74. package/components/ln-filter/ln-filter.js +1 -1
  75. package/components/ln-filter/ln-filter.schema.json +153 -153
  76. package/components/ln-filter/src/filter-model.js +185 -185
  77. package/components/ln-form/ln-form-dev.scss +8 -8
  78. package/components/ln-form/ln-form.js +1 -1
  79. package/components/ln-form/ln-form.schema.json +45 -45
  80. package/components/ln-http/ln-http.js +1 -1
  81. package/components/ln-http/ln-http.schema.json +6 -6
  82. package/components/ln-icon/ln-icon.schema.json +6 -6
  83. package/components/ln-include/ln-include.js +1 -1
  84. package/components/ln-include/ln-include.schema.json +23 -23
  85. package/components/ln-key/ln-key-dev.scss +18 -18
  86. package/components/ln-key/ln-key.js +1 -1
  87. package/components/ln-key/ln-key.schema.json +56 -56
  88. package/components/ln-key/src/ln-key.js +10 -10
  89. package/components/ln-link/ln-link-dev.scss +8 -8
  90. package/components/ln-link/ln-link.js +1 -1
  91. package/components/ln-link/ln-link.schema.json +22 -22
  92. package/components/ln-list/README.md +152 -152
  93. package/components/ln-list/ln-list-dev.scss +8 -8
  94. package/components/ln-list/ln-list.js +1 -1
  95. package/components/ln-list/ln-list.schema.json +166 -166
  96. package/components/ln-modal/ln-modal.js +1 -1
  97. package/components/ln-modal/ln-modal.schema.json +65 -65
  98. package/components/ln-nav/ln-nav.js +1 -1
  99. package/components/ln-nav/ln-nav.schema.json +25 -25
  100. package/components/ln-number/ln-number.js +1 -1
  101. package/components/ln-number/ln-number.schema.json +63 -63
  102. package/components/ln-number/src/number-model.js +31 -31
  103. package/components/ln-obfuscator/README.md +60 -60
  104. package/components/ln-obfuscator/ln-obfuscator.js +1 -1
  105. package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
  106. package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
  107. package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
  108. package/components/ln-options/ln-options.js +1 -1
  109. package/components/ln-options/ln-options.schema.json +41 -41
  110. package/components/ln-persist/README.md +151 -151
  111. package/components/ln-persist/ln-persist.js +1 -1
  112. package/components/ln-persist/ln-persist.schema.json +28 -28
  113. package/components/ln-persist/src/ln-persist.js +83 -83
  114. package/components/ln-picklist/README.md +230 -230
  115. package/components/ln-picklist/ln-picklist-dev.scss +22 -22
  116. package/components/ln-picklist/ln-picklist.js +1 -1
  117. package/components/ln-picklist/ln-picklist.schema.json +49 -49
  118. package/components/ln-picklist/src/ln-picklist.js +228 -228
  119. package/components/ln-popover/ln-popover-dev.scss +13 -13
  120. package/components/ln-popover/ln-popover.js +1 -1
  121. package/components/ln-popover/ln-popover.schema.json +82 -82
  122. package/components/ln-progress/ln-progress-dev.scss +8 -8
  123. package/components/ln-progress/ln-progress.js +1 -1
  124. package/components/ln-progress/ln-progress.schema.json +40 -40
  125. package/components/ln-router/ln-router.js +1 -1
  126. package/components/ln-router/ln-router.schema.json +76 -76
  127. package/components/ln-scroll/README.md +45 -45
  128. package/components/ln-scroll/ln-scroll.js +1 -1
  129. package/components/ln-scroll/ln-scroll.schema.json +85 -85
  130. package/components/ln-scroll/src/ln-scroll.js +150 -150
  131. package/components/ln-search/README.md +188 -188
  132. package/components/ln-search/ln-search.js +1 -1
  133. package/components/ln-search/ln-search.schema.json +103 -103
  134. package/components/ln-slug/ln-slug.js +1 -1
  135. package/components/ln-slug/ln-slug.schema.json +23 -23
  136. package/components/ln-sort/ln-sort.js +1 -1
  137. package/components/ln-sort/ln-sort.schema.json +104 -104
  138. package/components/ln-sort/src/ln-sort.js +321 -321
  139. package/components/ln-sort/src/sort-model.js +117 -117
  140. package/components/ln-sortable/ln-sortable-dev.scss +13 -13
  141. package/components/ln-sortable/ln-sortable.js +1 -1
  142. package/components/ln-sortable/ln-sortable.schema.json +36 -36
  143. package/components/ln-stat/ln-stat-dev.scss +8 -8
  144. package/components/ln-stat/ln-stat.js +1 -1
  145. package/components/ln-stat/ln-stat.schema.json +32 -32
  146. package/components/ln-stat/src/stat-model.js +28 -28
  147. package/components/ln-table/ln-table.js +1 -1
  148. package/components/ln-table/ln-table.schema.json +211 -211
  149. package/components/ln-table/src/table-model.js +98 -98
  150. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  151. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
  152. package/components/ln-tabs/ln-tabs.js +1 -1
  153. package/components/ln-tabs/ln-tabs.schema.json +75 -75
  154. package/components/ln-tabs/src/ln-tabs.js +208 -208
  155. package/components/ln-tabs/src/tabs-model.js +82 -82
  156. package/components/ln-time/ln-time-dev.scss +13 -13
  157. package/components/ln-time/ln-time.js +1 -1
  158. package/components/ln-time/ln-time.schema.json +38 -38
  159. package/components/ln-toast/ln-toast.js +1 -1
  160. package/components/ln-toast/ln-toast.schema.json +65 -65
  161. package/components/ln-toggle/ln-toggle.js +1 -1
  162. package/components/ln-toggle/ln-toggle.schema.json +52 -52
  163. package/components/ln-tooltip/ln-tooltip.js +1 -1
  164. package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
  165. package/components/ln-translations/ln-translations.js +1 -1
  166. package/components/ln-translations/ln-translations.schema.json +120 -120
  167. package/components/ln-ui-coordinator/README.md +62 -62
  168. package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
  169. package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
  170. package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
  171. package/components/ln-upload/ln-upload.js +1 -1
  172. package/components/ln-upload/ln-upload.schema.json +193 -193
  173. package/components/ln-upload/src/upload-model.js +78 -78
  174. package/components/ln-validate/ln-validate.js +1 -1
  175. package/components/ln-validate/ln-validate.schema.json +50 -50
  176. package/components/ln-validate/src/validate-model.js +64 -64
  177. package/components/ln-websocket-connector/README.md +166 -166
  178. package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
  179. package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
  180. package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
  181. package/ln-ashlar.html-data.json +7 -8
  182. package/package.json +84 -84
  183. package/theme/brand.css +73 -73
  184. package/theme/components/_confirm.scss +6 -6
  185. package/theme/components/_picklist.scss +3 -3
  186. package/theme/config/_palette.scss +274 -274
  187. package/theme/config/_theme.scss +292 -292
  188. package/theme/config/_tokens.scss +285 -285
  189. package/theme/config/mixins/_index.scss +62 -62
  190. package/theme/config/mixins/_picklist.scss +66 -66
  191. package/theme/ln-ashlar-dev.scss +66 -66
  192. package/theme/ln-ashlar-landing.scss +56 -56
  193. package/theme/ln-ashlar-theme.scss +63 -63
  194. package/theme/presentation/_bento.scss +151 -151
  195. package/theme/presentation/_cta.scss +111 -111
  196. package/theme/presentation/_effects.scss +216 -216
  197. package/theme/presentation/_features.scss +108 -108
  198. package/theme/presentation/_footer.scss +129 -129
  199. package/theme/presentation/_hero.scss +158 -158
  200. package/theme/presentation/_layout.scss +170 -170
  201. package/theme/presentation/_navbar.scss +140 -140
  202. package/theme/presentation/_pricing.scss +262 -262
  203. package/theme/presentation/_stats.scss +87 -87
  204. package/theme/presentation/_testimonials.scss +124 -124
  205. package/theme/presentation/_tokens.scss +39 -39
  206. package/theme/presentation/_typography.scss +163 -163
  207. package/web-types.json +12 -12
@@ -1,274 +1,274 @@
1
- // ==========================================================================
2
- // Palette & Color Derivation Mixins — ln-ashlar
3
- // ==========================================================================
4
- // Value mixins + the derivation chain, plus two zero-specificity CSS blocks
5
- // at the bottom (brand, base defaults).
6
- // Defines theme values (light and dark) and the unified color derivation chain.
7
- // ==========================================================================
8
-
9
- @mixin ln-values-light {
10
- // Secondary tint layers
11
- --color-secondary-light: 160 84% 94%;
12
- --color-secondary-lighter: 160 84% 97%;
13
-
14
- // Status colors
15
- --color-success: 142 76% 36%;
16
- --color-success-light: 142 71% 94%;
17
- --color-success-lighter: 142 71% 97%;
18
-
19
- --color-error: 0 84% 48%;
20
- --color-error-light: 0 84% 94%;
21
- --color-error-lighter: 0 84% 97%;
22
-
23
- --color-warning: 32 95% 38%;
24
- --color-warning-light: 38 92% 94%;
25
- --color-warning-lighter: 38 92% 97%;
26
-
27
- --color-info: 200 95% 38%;
28
- --color-info-light: 199 89% 94%;
29
- --color-info-lighter: 199 89% 97%;
30
-
31
- // Neutral scale (canonical greys)
32
- --color-neutral-50: 210 20% 98%;
33
- --color-neutral-100: 220 14% 96%;
34
- --color-neutral-150: 220 13% 93%;
35
- --color-neutral-175: 220 13% 91%;
36
- --color-neutral-200: 220 13% 90%;
37
- --color-neutral-300: 216 12% 84%;
38
- --color-neutral-400: 218 11% 58%;
39
- --color-neutral-500: 220 10% 40%;
40
- --color-neutral-600: 215 14% 34%;
41
- --color-neutral-700: 217 19% 27%;
42
- --color-neutral-800: 215 28% 17%;
43
- --color-neutral-900: 222 47% 11%;
44
-
45
- // Base canvas background
46
- --color-white: 0 0% 100%;
47
-
48
- // Shadows — cool-tinted, dual-layer (ambient + key light)
49
- --shadow-none: none;
50
-
51
- --shadow-xs:
52
- 0 1px 2px 0 hsl(220 40% 10% / 0.05);
53
-
54
- --shadow-sm:
55
- 0 1px 3px 0 hsl(220 40% 10% / 0.07),
56
- 0 1px 2px -1px hsl(220 40% 10% / 0.05);
57
-
58
- --shadow-md:
59
- 0 4px 6px -1px hsl(220 40% 10% / 0.08),
60
- 0 2px 4px -2px hsl(220 40% 10% / 0.05);
61
-
62
- --shadow-lg:
63
- 0 10px 15px -3px hsl(220 40% 10% / 0.08),
64
- 0 4px 6px -4px hsl(220 40% 10% / 0.04);
65
-
66
- --shadow-xl:
67
- 0 20px 25px -5px hsl(220 40% 10% / 0.09),
68
- 0 8px 10px -6px hsl(220 40% 10% / 0.04);
69
-
70
- --shadow-2xl:
71
- 0 25px 50px -12px hsl(220 40% 10% / 0.18);
72
-
73
- --shadow-inner:
74
- inset 0 2px 4px 0 hsl(220 40% 15% / 0.06);
75
-
76
- // Surface highlight — subtle top-edge bevel/illumination for elevated surfaces
77
- --surface-highlight: inset 0 1px 0 0 hsl(0 0% 100% / 0.6);
78
-
79
- // Value vocabulary — what bg/fg/border/shadow values exist
80
- --bg-base: hsl(var(--color-white));
81
- --bg-elevated: var(--bg-base);
82
- --bg-sunken: hsl(var(--color-neutral-100));
83
- --bg-recessed: hsl(var(--color-neutral-50));
84
-
85
- --bg-hover: hsl(var(--color-neutral-100));
86
- --bg-active: hsl(var(--color-neutral-150));
87
-
88
- // Bound low on the ramp so every tier clears 7:1 against --bg-active,
89
- // the lightest surface any of them lands on (8.02 / 11.52 / 14.11).
90
- --fg-default: hsl(var(--color-neutral-900));
91
- --fg-muted: hsl(var(--color-neutral-800));
92
- --fg-subtle: hsl(var(--color-neutral-700));
93
-
94
- --border-subtle: hsl(var(--color-neutral-200));
95
- --border-strong: hsl(var(--color-neutral-300));
96
-
97
- // Interactive boundaries only (input/select/checkbox). 1.4.11 wants 3:1
98
- // for these; --border-subtle/-strong stay decorative and exempt.
99
- --border-ui: hsl(var(--color-neutral-400));
100
-
101
- --color-scrim: hsl(var(--color-neutral-900) / 0.5);
102
-
103
- // Per-polarity, not derived in the chain: the chain re-evaluates at
104
- // [data-mode], where neutral-900 inverts to near-white and the scrim would
105
- // lighten the page instead of dimming it.
106
- --app-scrim-bg: hsl(var(--color-neutral-900) / 0.4);
107
- }
108
-
109
- @mixin ln-values-dark {
110
- // Neutral scale — inverted
111
- --color-neutral-50: 220 20% 5%;
112
- --color-neutral-100: 220 16% 7%;
113
- --color-neutral-150: 220 14% 10%;
114
- --color-neutral-175: 220 13% 12%;
115
- --color-neutral-200: 220 13% 14%;
116
- --color-neutral-300: 220 13% 36%;
117
- --color-neutral-400: 218 11% 52%;
118
- --color-neutral-500: 220 10% 68%;
119
- --color-neutral-600: 220 11% 76%;
120
- --color-neutral-700: 220 14% 84%;
121
- --color-neutral-800: 220 20% 92%;
122
- --color-neutral-900: 221 30% 97%;
123
-
124
- // --color-white is deliberately not restated: :where(:root) still matches
125
- // <html data-mode="dark"> and supplies it, and --color-accent-fg needs real
126
- // white for text on a solid accent fill.
127
-
128
- // Vocabulary — bg. Elevated is DARKER than sunken here; that inversion
129
- // against light is intentional.
130
- --bg-base: hsl(var(--color-neutral-100));
131
- --bg-elevated: hsl(var(--color-neutral-150));
132
- --bg-sunken: hsl(var(--color-neutral-175));
133
- --bg-recessed: hsl(var(--color-neutral-50));
134
- --bg-hover: hsl(var(--color-neutral-175));
135
- --bg-active: hsl(var(--color-neutral-200));
136
-
137
- // Vocabulary — fg
138
- // Bound high on the ramp for the same reason as light: every tier clears
139
- // 7:1 against --bg-active (8.68 / 10.74 / 14.78).
140
- --fg-default: hsl(var(--color-neutral-900));
141
- --fg-muted: hsl(var(--color-neutral-700));
142
- --fg-subtle: hsl(var(--color-neutral-600));
143
-
144
- --border-subtle: hsl(var(--color-neutral-175));
145
- --border-strong: hsl(var(--color-neutral-300));
146
-
147
- --border-ui: hsl(var(--color-neutral-400));
148
-
149
- // Scrims — anchored to black, not the ramp: dark --color-neutral-900 is
150
- // near-white, so binding either to it would need an index flip.
151
- --color-scrim: hsl(0 0% 0% / 0.6);
152
- --app-scrim-bg: hsl(0 0% 0% / 0.4);
153
-
154
- // Status tint layers — re-tuned for dark surfaces
155
- --color-success-light: 142 50% 18%;
156
- --color-success-lighter: 142 40% 13%;
157
- --color-warning-light: 32 55% 20%;
158
- --color-warning-lighter: 32 45% 14%;
159
- --color-info-light: 217 55% 22%;
160
- --color-info-lighter: 217 45% 15%;
161
-
162
- --color-error: 0 84% 65%; // Lighter red for text contrast in dark mode
163
- --color-error-light: 0 50% 20%;
164
- --color-error-lighter: 0 40% 14%;
165
-
166
- // Secondary tint layers — re-tuned for dark surfaces
167
- --color-secondary-light: 160 55% 20%;
168
- --color-secondary-lighter: 160 45% 14%;
169
-
170
- // Shadows — solid black, boosted alpha, dual-layer
171
- --shadow-xs:
172
- 0 1px 2px 0 hsl(0 0% 0% / 0.35);
173
- --shadow-sm:
174
- 0 1px 3px 0 hsl(0 0% 0% / 0.40),
175
- 0 1px 2px -1px hsl(0 0% 0% / 0.25);
176
- --shadow-md:
177
- 0 4px 6px -1px hsl(0 0% 0% / 0.45),
178
- 0 2px 4px -2px hsl(0 0% 0% / 0.30);
179
- --shadow-lg:
180
- 0 10px 15px -3px hsl(0 0% 0% / 0.50),
181
- 0 4px 6px -4px hsl(0 0% 0% / 0.35);
182
- --shadow-xl:
183
- 0 20px 25px -5px hsl(0 0% 0% / 0.60),
184
- 0 8px 10px -6px hsl(0 0% 0% / 0.40);
185
- --shadow-2xl:
186
- 0 25px 50px -12px hsl(0 0% 0% / 0.70);
187
- --shadow-inner:
188
- inset 0 2px 4px 0 hsl(0 0% 0% / 0.32);
189
-
190
- // Surface highlight — crisp top-edge bevel on dark elevated surfaces
191
- --surface-highlight: inset 0 1px 0 0 hsl(0 0% 100% / 0.08);
192
- }
193
-
194
- @mixin ln-color-chain {
195
- // brand → semantic
196
- --color-primary: var(--brand-primary);
197
- --color-secondary: var(--brand-secondary);
198
-
199
- // colour-aware shadows
200
- --shadow-primary: 0 8px 24px -6px hsl(var(--color-primary) / 0.28);
201
- --shadow-success: 0 8px 24px -6px hsl(var(--color-success) / 0.28);
202
- --shadow-error: 0 8px 24px -6px hsl(var(--color-error) / 0.28);
203
- }
204
-
205
- // ---------------------------------------------------------------------------
206
- // Brand — :where(:root) ONLY. Deliberately not in ln-values-light /
207
- // ln-values-dark and deliberately not joined to the four-axis block below.
208
- //
209
- // Brand is a literal with no polarity opinion. Declared inside the value
210
- // mixins it would be re-declared on every nested [data-mode] island, and a
211
- // declaration beats inheritance at any specificity — so a light card inside
212
- // <section data-theme="sunset" data-mode="dark"> would snap back to default
213
- // blue. :root-only means no island re-declares it; [data-theme] at (0,1,0)
214
- // rebinds it normally; a consumer's brand.css at (0,1,0) still wins at any
215
- // stylesheet load order, which is brand.css's whole guarantee.
216
- // ---------------------------------------------------------------------------
217
- :where(:root) {
218
- --brand-primary: 221 83% 43%;
219
- --brand-secondary: 160 84% 36%;
220
- }
221
-
222
- // ---------------------------------------------------------------------------
223
- // Base Defaults — Lazy-evaluated primitives and surfaces.
224
- // These live in :where(:root) (0,0,0) so they can be overridden by [data-skin]
225
- // or [data-theme] (0,1,0) without being clobbered by nested [data-mode] islands.
226
- // ---------------------------------------------------------------------------
227
- :where(:root),
228
- :where([data-mode]),
229
- :where([data-theme]),
230
- :where([data-skin]) {
231
- // shadow roles
232
- --shadow-resting: var(--shadow-sm);
233
- --shadow-floating: var(--shadow-md);
234
- --shadow-overlay: var(--shadow-xl);
235
-
236
- // primitives — what mixin bodies read
237
- --color-bg: var(--bg-base);
238
- --color-fg: var(--fg-default);
239
- --color-border: var(--border-subtle);
240
- --shadow: var(--shadow-resting);
241
- --radius: var(--radius-md);
242
-
243
- // accent — tints computed against the LOCAL --bg-base, so one
244
- // formula serves both themes. The two override slots are
245
- // undeclared by default; a client declares them to win.
246
- --color-accent: hsl(var(--color-primary));
247
- --color-accent-fg: hsl(var(--color-white));
248
-
249
- // Dark foreground pole for fills too light to carry white at AAA.
250
- // A literal, never var(--color-neutral-900) — that inverts to near-white
251
- // in dark mode, which is exactly where the ink islands live. Mirrors
252
- // $_ln-contrast-ink in _contrast.scss; keep the two in step.
253
- --color-ink: 222 47% 11%;
254
-
255
- // Checkmark stroke is baked into the data URI, so it ships in both poles
256
- // and --check-mark selects one. An ink island must repoint this or its
257
- // checkmark stays white on a light fill, well under the 3:1 that 1.4.11
258
- // asks of a meaningful graphic.
259
- --check-mark-on-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
260
- --check-mark-on-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230f1729' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
261
- --check-mark: var(--check-mark-on-light);
262
- --color-accent-tint: var(--brand-primary-tint,
263
- color-mix(in srgb, hsl(var(--color-primary)) 8%, var(--bg-base)));
264
- --color-accent-tint-strong: var(--brand-primary-tint-strong,
265
- color-mix(in srgb, hsl(var(--color-primary)) 16%, var(--bg-base)));
266
-
267
- // button surface (neutral default)
268
- --btn-bg: var(--color-bg);
269
- --btn-fg: var(--color-fg);
270
- --btn-border: var(--border-strong);
271
- --btn-bg-hover: var(--bg-hover);
272
- --btn-fg-hover: var(--color-fg);
273
- --btn-border-hover: var(--border-strong);
274
- }
1
+ // ==========================================================================
2
+ // Palette & Color Derivation Mixins — ln-ashlar
3
+ // ==========================================================================
4
+ // Value mixins + the derivation chain, plus two zero-specificity CSS blocks
5
+ // at the bottom (brand, base defaults).
6
+ // Defines theme values (light and dark) and the unified color derivation chain.
7
+ // ==========================================================================
8
+
9
+ @mixin ln-values-light {
10
+ // Secondary tint layers
11
+ --color-secondary-light: 160 84% 94%;
12
+ --color-secondary-lighter: 160 84% 97%;
13
+
14
+ // Status colors
15
+ --color-success: 142 76% 36%;
16
+ --color-success-light: 142 71% 94%;
17
+ --color-success-lighter: 142 71% 97%;
18
+
19
+ --color-error: 0 84% 48%;
20
+ --color-error-light: 0 84% 94%;
21
+ --color-error-lighter: 0 84% 97%;
22
+
23
+ --color-warning: 32 95% 38%;
24
+ --color-warning-light: 38 92% 94%;
25
+ --color-warning-lighter: 38 92% 97%;
26
+
27
+ --color-info: 200 95% 38%;
28
+ --color-info-light: 199 89% 94%;
29
+ --color-info-lighter: 199 89% 97%;
30
+
31
+ // Neutral scale (canonical greys)
32
+ --color-neutral-50: 210 20% 98%;
33
+ --color-neutral-100: 220 14% 96%;
34
+ --color-neutral-150: 220 13% 93%;
35
+ --color-neutral-175: 220 13% 91%;
36
+ --color-neutral-200: 220 13% 90%;
37
+ --color-neutral-300: 216 12% 84%;
38
+ --color-neutral-400: 218 11% 58%;
39
+ --color-neutral-500: 220 10% 40%;
40
+ --color-neutral-600: 215 14% 34%;
41
+ --color-neutral-700: 217 19% 27%;
42
+ --color-neutral-800: 215 28% 17%;
43
+ --color-neutral-900: 222 47% 11%;
44
+
45
+ // Base canvas background
46
+ --color-white: 0 0% 100%;
47
+
48
+ // Shadows — cool-tinted, dual-layer (ambient + key light)
49
+ --shadow-none: none;
50
+
51
+ --shadow-xs:
52
+ 0 1px 2px 0 hsl(220 40% 10% / 0.05);
53
+
54
+ --shadow-sm:
55
+ 0 1px 3px 0 hsl(220 40% 10% / 0.07),
56
+ 0 1px 2px -1px hsl(220 40% 10% / 0.05);
57
+
58
+ --shadow-md:
59
+ 0 4px 6px -1px hsl(220 40% 10% / 0.08),
60
+ 0 2px 4px -2px hsl(220 40% 10% / 0.05);
61
+
62
+ --shadow-lg:
63
+ 0 10px 15px -3px hsl(220 40% 10% / 0.08),
64
+ 0 4px 6px -4px hsl(220 40% 10% / 0.04);
65
+
66
+ --shadow-xl:
67
+ 0 20px 25px -5px hsl(220 40% 10% / 0.09),
68
+ 0 8px 10px -6px hsl(220 40% 10% / 0.04);
69
+
70
+ --shadow-2xl:
71
+ 0 25px 50px -12px hsl(220 40% 10% / 0.18);
72
+
73
+ --shadow-inner:
74
+ inset 0 2px 4px 0 hsl(220 40% 15% / 0.06);
75
+
76
+ // Surface highlight — subtle top-edge bevel/illumination for elevated surfaces
77
+ --surface-highlight: inset 0 1px 0 0 hsl(0 0% 100% / 0.6);
78
+
79
+ // Value vocabulary — what bg/fg/border/shadow values exist
80
+ --bg-base: hsl(var(--color-white));
81
+ --bg-elevated: var(--bg-base);
82
+ --bg-sunken: hsl(var(--color-neutral-100));
83
+ --bg-recessed: hsl(var(--color-neutral-50));
84
+
85
+ --bg-hover: hsl(var(--color-neutral-100));
86
+ --bg-active: hsl(var(--color-neutral-150));
87
+
88
+ // Bound low on the ramp so every tier clears 7:1 against --bg-active,
89
+ // the lightest surface any of them lands on (8.02 / 11.52 / 14.11).
90
+ --fg-default: hsl(var(--color-neutral-900));
91
+ --fg-muted: hsl(var(--color-neutral-800));
92
+ --fg-subtle: hsl(var(--color-neutral-700));
93
+
94
+ --border-subtle: hsl(var(--color-neutral-200));
95
+ --border-strong: hsl(var(--color-neutral-300));
96
+
97
+ // Interactive boundaries only (input/select/checkbox). 1.4.11 wants 3:1
98
+ // for these; --border-subtle/-strong stay decorative and exempt.
99
+ --border-ui: hsl(var(--color-neutral-400));
100
+
101
+ --color-scrim: hsl(var(--color-neutral-900) / 0.5);
102
+
103
+ // Per-polarity, not derived in the chain: the chain re-evaluates at
104
+ // [data-mode], where neutral-900 inverts to near-white and the scrim would
105
+ // lighten the page instead of dimming it.
106
+ --app-scrim-bg: hsl(var(--color-neutral-900) / 0.4);
107
+ }
108
+
109
+ @mixin ln-values-dark {
110
+ // Neutral scale — inverted
111
+ --color-neutral-50: 220 20% 5%;
112
+ --color-neutral-100: 220 16% 7%;
113
+ --color-neutral-150: 220 14% 10%;
114
+ --color-neutral-175: 220 13% 12%;
115
+ --color-neutral-200: 220 13% 14%;
116
+ --color-neutral-300: 220 13% 36%;
117
+ --color-neutral-400: 218 11% 52%;
118
+ --color-neutral-500: 220 10% 68%;
119
+ --color-neutral-600: 220 11% 76%;
120
+ --color-neutral-700: 220 14% 84%;
121
+ --color-neutral-800: 220 20% 92%;
122
+ --color-neutral-900: 221 30% 97%;
123
+
124
+ // --color-white is deliberately not restated: :where(:root) still matches
125
+ // <html data-mode="dark"> and supplies it, and --color-accent-fg needs real
126
+ // white for text on a solid accent fill.
127
+
128
+ // Vocabulary — bg. Elevated is DARKER than sunken here; that inversion
129
+ // against light is intentional.
130
+ --bg-base: hsl(var(--color-neutral-100));
131
+ --bg-elevated: hsl(var(--color-neutral-150));
132
+ --bg-sunken: hsl(var(--color-neutral-175));
133
+ --bg-recessed: hsl(var(--color-neutral-50));
134
+ --bg-hover: hsl(var(--color-neutral-175));
135
+ --bg-active: hsl(var(--color-neutral-200));
136
+
137
+ // Vocabulary — fg
138
+ // Bound high on the ramp for the same reason as light: every tier clears
139
+ // 7:1 against --bg-active (8.68 / 10.74 / 14.78).
140
+ --fg-default: hsl(var(--color-neutral-900));
141
+ --fg-muted: hsl(var(--color-neutral-700));
142
+ --fg-subtle: hsl(var(--color-neutral-600));
143
+
144
+ --border-subtle: hsl(var(--color-neutral-175));
145
+ --border-strong: hsl(var(--color-neutral-300));
146
+
147
+ --border-ui: hsl(var(--color-neutral-400));
148
+
149
+ // Scrims — anchored to black, not the ramp: dark --color-neutral-900 is
150
+ // near-white, so binding either to it would need an index flip.
151
+ --color-scrim: hsl(0 0% 0% / 0.6);
152
+ --app-scrim-bg: hsl(0 0% 0% / 0.4);
153
+
154
+ // Status tint layers — re-tuned for dark surfaces
155
+ --color-success-light: 142 50% 18%;
156
+ --color-success-lighter: 142 40% 13%;
157
+ --color-warning-light: 32 55% 20%;
158
+ --color-warning-lighter: 32 45% 14%;
159
+ --color-info-light: 217 55% 22%;
160
+ --color-info-lighter: 217 45% 15%;
161
+
162
+ --color-error: 0 84% 65%; // Lighter red for text contrast in dark mode
163
+ --color-error-light: 0 50% 20%;
164
+ --color-error-lighter: 0 40% 14%;
165
+
166
+ // Secondary tint layers — re-tuned for dark surfaces
167
+ --color-secondary-light: 160 55% 20%;
168
+ --color-secondary-lighter: 160 45% 14%;
169
+
170
+ // Shadows — solid black, boosted alpha, dual-layer
171
+ --shadow-xs:
172
+ 0 1px 2px 0 hsl(0 0% 0% / 0.35);
173
+ --shadow-sm:
174
+ 0 1px 3px 0 hsl(0 0% 0% / 0.40),
175
+ 0 1px 2px -1px hsl(0 0% 0% / 0.25);
176
+ --shadow-md:
177
+ 0 4px 6px -1px hsl(0 0% 0% / 0.45),
178
+ 0 2px 4px -2px hsl(0 0% 0% / 0.30);
179
+ --shadow-lg:
180
+ 0 10px 15px -3px hsl(0 0% 0% / 0.50),
181
+ 0 4px 6px -4px hsl(0 0% 0% / 0.35);
182
+ --shadow-xl:
183
+ 0 20px 25px -5px hsl(0 0% 0% / 0.60),
184
+ 0 8px 10px -6px hsl(0 0% 0% / 0.40);
185
+ --shadow-2xl:
186
+ 0 25px 50px -12px hsl(0 0% 0% / 0.70);
187
+ --shadow-inner:
188
+ inset 0 2px 4px 0 hsl(0 0% 0% / 0.32);
189
+
190
+ // Surface highlight — crisp top-edge bevel on dark elevated surfaces
191
+ --surface-highlight: inset 0 1px 0 0 hsl(0 0% 100% / 0.08);
192
+ }
193
+
194
+ @mixin ln-color-chain {
195
+ // brand → semantic
196
+ --color-primary: var(--brand-primary);
197
+ --color-secondary: var(--brand-secondary);
198
+
199
+ // colour-aware shadows
200
+ --shadow-primary: 0 8px 24px -6px hsl(var(--color-primary) / 0.28);
201
+ --shadow-success: 0 8px 24px -6px hsl(var(--color-success) / 0.28);
202
+ --shadow-error: 0 8px 24px -6px hsl(var(--color-error) / 0.28);
203
+ }
204
+
205
+ // ---------------------------------------------------------------------------
206
+ // Brand — :where(:root) ONLY. Deliberately not in ln-values-light /
207
+ // ln-values-dark and deliberately not joined to the four-axis block below.
208
+ //
209
+ // Brand is a literal with no polarity opinion. Declared inside the value
210
+ // mixins it would be re-declared on every nested [data-mode] island, and a
211
+ // declaration beats inheritance at any specificity — so a light card inside
212
+ // <section data-theme="sunset" data-mode="dark"> would snap back to default
213
+ // blue. :root-only means no island re-declares it; [data-theme] at (0,1,0)
214
+ // rebinds it normally; a consumer's brand.css at (0,1,0) still wins at any
215
+ // stylesheet load order, which is brand.css's whole guarantee.
216
+ // ---------------------------------------------------------------------------
217
+ :where(:root) {
218
+ --brand-primary: 221 83% 43%;
219
+ --brand-secondary: 160 84% 36%;
220
+ }
221
+
222
+ // ---------------------------------------------------------------------------
223
+ // Base Defaults — Lazy-evaluated primitives and surfaces.
224
+ // These live in :where(:root) (0,0,0) so they can be overridden by [data-skin]
225
+ // or [data-theme] (0,1,0) without being clobbered by nested [data-mode] islands.
226
+ // ---------------------------------------------------------------------------
227
+ :where(:root),
228
+ :where([data-mode]),
229
+ :where([data-theme]),
230
+ :where([data-skin]) {
231
+ // shadow roles
232
+ --shadow-resting: var(--shadow-sm);
233
+ --shadow-floating: var(--shadow-md);
234
+ --shadow-overlay: var(--shadow-xl);
235
+
236
+ // primitives — what mixin bodies read
237
+ --color-bg: var(--bg-base);
238
+ --color-fg: var(--fg-default);
239
+ --color-border: var(--border-subtle);
240
+ --shadow: var(--shadow-resting);
241
+ --radius: var(--radius-md);
242
+
243
+ // accent — tints computed against the LOCAL --bg-base, so one
244
+ // formula serves both themes. The two override slots are
245
+ // undeclared by default; a client declares them to win.
246
+ --color-accent: hsl(var(--color-primary));
247
+ --color-accent-fg: hsl(var(--color-white));
248
+
249
+ // Dark foreground pole for fills too light to carry white at AAA.
250
+ // A literal, never var(--color-neutral-900) — that inverts to near-white
251
+ // in dark mode, which is exactly where the ink islands live. Mirrors
252
+ // $_ln-contrast-ink in _contrast.scss; keep the two in step.
253
+ --color-ink: 222 47% 11%;
254
+
255
+ // Checkmark stroke is baked into the data URI, so it ships in both poles
256
+ // and --check-mark selects one. An ink island must repoint this or its
257
+ // checkmark stays white on a light fill, well under the 3:1 that 1.4.11
258
+ // asks of a meaningful graphic.
259
+ --check-mark-on-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
260
+ --check-mark-on-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230f1729' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
261
+ --check-mark: var(--check-mark-on-light);
262
+ --color-accent-tint: var(--brand-primary-tint,
263
+ color-mix(in srgb, hsl(var(--color-primary)) 8%, var(--bg-base)));
264
+ --color-accent-tint-strong: var(--brand-primary-tint-strong,
265
+ color-mix(in srgb, hsl(var(--color-primary)) 16%, var(--bg-base)));
266
+
267
+ // button surface (neutral default)
268
+ --btn-bg: var(--color-bg);
269
+ --btn-fg: var(--color-fg);
270
+ --btn-border: var(--border-strong);
271
+ --btn-bg-hover: var(--bg-hover);
272
+ --btn-fg-hover: var(--color-fg);
273
+ --btn-border-hover: var(--border-strong);
274
+ }