@krizaka/ui 2.5.0 → 2.6.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 (222) hide show
  1. package/README.md +44 -1
  2. package/dist/action-bar.d.ts +38 -0
  3. package/dist/action-bar.js +52 -0
  4. package/dist/action-bar.js.map +1 -0
  5. package/dist/argument-card.d.ts +67 -0
  6. package/dist/argument-card.js +69 -0
  7. package/dist/argument-card.js.map +1 -0
  8. package/dist/audio-player.js +1 -1
  9. package/dist/block-link-BAg4eoZk.d.ts +12 -0
  10. package/dist/blocks.css +529 -0
  11. package/dist/button.js +5 -94
  12. package/dist/button.js.map +1 -1
  13. package/dist/card-grid.d.ts +42 -0
  14. package/dist/card-grid.js +47 -0
  15. package/dist/card-grid.js.map +1 -0
  16. package/dist/chunk-2AGSO3WH.js +20 -0
  17. package/dist/chunk-2AGSO3WH.js.map +1 -0
  18. package/dist/chunk-AB5D3KBG.js +37 -0
  19. package/dist/chunk-AB5D3KBG.js.map +1 -0
  20. package/dist/{chunk-YX6CNVJA.js → chunk-CPA5CF35.js} +1 -1
  21. package/dist/chunk-CPA5CF35.js.map +1 -0
  22. package/dist/chunk-K3SWZXYT.js +92 -0
  23. package/dist/chunk-K3SWZXYT.js.map +1 -0
  24. package/dist/{chunk-XUMJA5ZI.js → chunk-X6TW3X6Y.js} +2 -2
  25. package/dist/chunk-XCBVFMNV.js +41 -0
  26. package/dist/{chunk-YX6CNVJA.js.map → chunk-XCBVFMNV.js.map} +1 -1
  27. package/dist/chunk-XVLWVTQA.js +28 -0
  28. package/dist/chunk-XVLWVTQA.js.map +1 -0
  29. package/dist/chunk-Z6FUPB3Q.js +102 -0
  30. package/dist/chunk-Z6FUPB3Q.js.map +1 -0
  31. package/dist/code-block.d.ts +42 -0
  32. package/dist/code-block.js +202 -0
  33. package/dist/code-block.js.map +1 -0
  34. package/dist/combobox.js +2 -2
  35. package/dist/cta-panel.d.ts +23 -0
  36. package/dist/cta-panel.js +20 -0
  37. package/dist/cta-panel.js.map +1 -0
  38. package/dist/data-table.js +1 -1
  39. package/dist/date-picker.js +1 -1
  40. package/dist/decision-list.d.ts +34 -0
  41. package/dist/decision-list.js +67 -0
  42. package/dist/decision-list.js.map +1 -0
  43. package/dist/file-upload.js +1 -1
  44. package/dist/filter-bar.js +1 -1
  45. package/dist/link-card.d.ts +35 -0
  46. package/dist/link-card.js +46 -0
  47. package/dist/link-card.js.map +1 -0
  48. package/dist/mascot-quote.d.ts +42 -0
  49. package/dist/mascot-quote.js +267 -0
  50. package/dist/mascot-quote.js.map +1 -0
  51. package/dist/media-capture.js +1 -1
  52. package/dist/motion.css +25 -1
  53. package/dist/page-hero.d.ts +44 -0
  54. package/dist/page-hero.js +41 -0
  55. package/dist/page-hero.js.map +1 -0
  56. package/dist/page.d.ts +116 -0
  57. package/dist/page.js +17 -0
  58. package/dist/page.js.map +1 -0
  59. package/dist/pagination.js +25 -44
  60. package/dist/pagination.js.map +1 -1
  61. package/dist/pointer-light.d.ts +20 -0
  62. package/dist/pointer-light.js +12 -0
  63. package/dist/pointer-light.js.map +1 -0
  64. package/dist/search-field.js +1 -1
  65. package/dist/section-backdrop.js +4 -22
  66. package/dist/section-backdrop.js.map +1 -1
  67. package/dist/tag-input.js +2 -2
  68. package/dist/terminal-replay.d.ts +68 -0
  69. package/dist/terminal-replay.js +231 -0
  70. package/dist/terminal-replay.js.map +1 -0
  71. package/dist/toc.d.ts +23 -0
  72. package/dist/toc.js +39 -0
  73. package/dist/toc.js.map +1 -0
  74. package/dist/video-player.js +1 -1
  75. package/package.json +192 -7
  76. package/registry/action-bar.json +205 -0
  77. package/registry/alert.json +1 -1
  78. package/registry/argument-card.json +327 -0
  79. package/registry/audio-player.json +2 -2
  80. package/registry/avatar.json +1 -1
  81. package/registry/badge.json +1 -1
  82. package/registry/button.json +5 -5
  83. package/registry/card-grid.json +221 -0
  84. package/registry/card.json +3 -3
  85. package/registry/checkbox.json +1 -1
  86. package/registry/chip-link.json +1 -1
  87. package/registry/chip.json +1 -1
  88. package/registry/code-block.json +262 -0
  89. package/registry/combobox.json +2 -2
  90. package/registry/command.json +1 -1
  91. package/registry/confirm-button.json +3 -3
  92. package/registry/countdown.json +1 -1
  93. package/registry/cta-panel.json +154 -0
  94. package/registry/data-table.json +2 -2
  95. package/registry/date-picker.json +2 -2
  96. package/registry/decision-list.json +144 -0
  97. package/registry/dialog.json +1 -1
  98. package/registry/dropdown-menu.json +1 -1
  99. package/registry/empty-state.json +1 -1
  100. package/registry/examples/action-bar/buttons.d.ts +4 -0
  101. package/registry/examples/action-bar/buttons.js +22 -0
  102. package/registry/examples/action-bar/buttons.tsx +17 -0
  103. package/registry/examples/action-bar/icons.d.ts +4 -0
  104. package/registry/examples/action-bar/icons.js +24 -0
  105. package/registry/examples/action-bar/icons.tsx +23 -0
  106. package/registry/examples/argument-card/building-block.d.ts +4 -0
  107. package/registry/examples/argument-card/building-block.js +29 -0
  108. package/registry/examples/argument-card/building-block.tsx +29 -0
  109. package/registry/examples/argument-card/grid.d.ts +4 -0
  110. package/registry/examples/argument-card/grid.js +17 -0
  111. package/registry/examples/argument-card/grid.tsx +19 -0
  112. package/registry/examples/argument-card/unfold.d.ts +4 -0
  113. package/registry/examples/argument-card/unfold.js +26 -0
  114. package/registry/examples/argument-card/unfold.tsx +21 -0
  115. package/registry/examples/card-grid/products.d.ts +4 -0
  116. package/registry/examples/card-grid/products.js +16 -0
  117. package/registry/examples/card-grid/products.tsx +13 -0
  118. package/registry/examples/card-grid/reveal.d.ts +4 -0
  119. package/registry/examples/card-grid/reveal.js +13 -0
  120. package/registry/examples/card-grid/reveal.tsx +16 -0
  121. package/registry/examples/code-block/build-tools.d.ts +4 -0
  122. package/registry/examples/code-block/build-tools.js +30 -0
  123. package/registry/examples/code-block/build-tools.tsx +25 -0
  124. package/registry/examples/code-block/file.d.ts +4 -0
  125. package/registry/examples/code-block/file.js +17 -0
  126. package/registry/examples/code-block/file.tsx +13 -0
  127. package/registry/examples/cta-panel/discuss.d.ts +4 -0
  128. package/registry/examples/cta-panel/discuss.js +31 -0
  129. package/registry/examples/cta-panel/discuss.tsx +23 -0
  130. package/registry/examples/decision-list/product.d.ts +4 -0
  131. package/registry/examples/decision-list/product.js +35 -0
  132. package/registry/examples/decision-list/product.tsx +30 -0
  133. package/registry/examples/link-card/docs-hub.d.ts +4 -0
  134. package/registry/examples/link-card/docs-hub.js +18 -0
  135. package/registry/examples/link-card/docs-hub.tsx +20 -0
  136. package/registry/examples/link-card/external.d.ts +4 -0
  137. package/registry/examples/link-card/external.js +22 -0
  138. package/registry/examples/link-card/external.tsx +16 -0
  139. package/registry/examples/link-card/stack.d.ts +4 -0
  140. package/registry/examples/link-card/stack.js +26 -0
  141. package/registry/examples/link-card/stack.tsx +21 -0
  142. package/registry/examples/mascot-quote/callout.d.ts +4 -0
  143. package/registry/examples/mascot-quote/callout.js +11 -0
  144. package/registry/examples/mascot-quote/callout.tsx +10 -0
  145. package/registry/examples/mascot-quote/inline.d.ts +4 -0
  146. package/registry/examples/mascot-quote/inline.js +11 -0
  147. package/registry/examples/mascot-quote/inline.tsx +10 -0
  148. package/registry/examples/page/backdrop.d.ts +4 -0
  149. package/registry/examples/page/backdrop.js +23 -0
  150. package/registry/examples/page/backdrop.tsx +18 -0
  151. package/registry/examples/page/facts.d.ts +4 -0
  152. package/registry/examples/page/facts.js +24 -0
  153. package/registry/examples/page/facts.tsx +21 -0
  154. package/registry/examples/page/frame.d.ts +4 -0
  155. package/registry/examples/page/frame.js +15 -0
  156. package/registry/examples/page/frame.tsx +17 -0
  157. package/registry/examples/page/sections.d.ts +4 -0
  158. package/registry/examples/page/sections.js +14 -0
  159. package/registry/examples/page/sections.tsx +15 -0
  160. package/registry/examples/page-hero/building-block.d.ts +4 -0
  161. package/registry/examples/page-hero/building-block.js +24 -0
  162. package/registry/examples/page-hero/building-block.tsx +20 -0
  163. package/registry/examples/page-hero/hub.d.ts +4 -0
  164. package/registry/examples/page-hero/hub.js +21 -0
  165. package/registry/examples/page-hero/hub.tsx +15 -0
  166. package/registry/examples/pointer-light/list.d.ts +4 -0
  167. package/registry/examples/pointer-light/list.js +16 -0
  168. package/registry/examples/pointer-light/list.tsx +14 -0
  169. package/registry/examples/terminal-replay/at-rest.d.ts +4 -0
  170. package/registry/examples/terminal-replay/at-rest.js +32 -0
  171. package/registry/examples/terminal-replay/at-rest.tsx +26 -0
  172. package/registry/examples/terminal-replay/session.d.ts +4 -0
  173. package/registry/examples/terminal-replay/session.js +34 -0
  174. package/registry/examples/terminal-replay/session.tsx +28 -0
  175. package/registry/examples/toc/reading-page.d.ts +4 -0
  176. package/registry/examples/toc/reading-page.js +21 -0
  177. package/registry/examples/toc/reading-page.tsx +21 -0
  178. package/registry/field.json +1 -1
  179. package/registry/file-upload.json +2 -2
  180. package/registry/filter-bar.json +2 -2
  181. package/registry/glow-card.json +1 -1
  182. package/registry/image-cropper.json +1 -1
  183. package/registry/index.json +241 -1
  184. package/registry/iso.json +1 -1
  185. package/registry/kbd.json +1 -1
  186. package/registry/link-card.json +279 -0
  187. package/registry/loader.json +1 -1
  188. package/registry/marquee.json +1 -1
  189. package/registry/mascot-quote.json +191 -0
  190. package/registry/mascots.json +1 -1
  191. package/registry/media-capture.json +4 -4
  192. package/registry/meter.json +1 -1
  193. package/registry/nav-bar.json +1 -1
  194. package/registry/number-ticker.json +1 -1
  195. package/registry/page-header.json +1 -1
  196. package/registry/page-hero.json +254 -0
  197. package/registry/page.json +497 -0
  198. package/registry/pagination.json +2 -2
  199. package/registry/pointer-light.json +119 -0
  200. package/registry/popover.json +1 -1
  201. package/registry/progress.json +1 -1
  202. package/registry/radio-group.json +1 -1
  203. package/registry/search-field.json +2 -2
  204. package/registry/section-backdrop.json +1 -1
  205. package/registry/separator.json +1 -1
  206. package/registry/skeleton.json +3 -3
  207. package/registry/slider.json +1 -1
  208. package/registry/slot.json +1 -1
  209. package/registry/spinner.json +1 -1
  210. package/registry/stat.json +1 -1
  211. package/registry/stepper.json +1 -1
  212. package/registry/switch.json +1 -1
  213. package/registry/tabs.json +1 -1
  214. package/registry/tag-input.json +1 -1
  215. package/registry/terminal-replay.json +317 -0
  216. package/registry/theme.json +1 -1
  217. package/registry/toast.json +1 -1
  218. package/registry/toc.json +157 -0
  219. package/registry/tooltip.json +1 -1
  220. package/registry/video-player.json +4 -4
  221. package/registry/video-trimmer.json +3 -3
  222. /package/dist/{chunk-XUMJA5ZI.js.map → chunk-X6TW3X6Y.js.map} +0 -0
@@ -0,0 +1,529 @@
1
+ /* @krizaka/ui — the page blocks (Page, Section, PageHero, CardGrid, LinkCard, ArgumentCard, MascotQuote, DecisionList,
2
+ CodeBlock, ActionBar, CtaPanel, Toc, PointerLight). The app imports it once, from its root layout or its global
3
+ stylesheet by package path: `import "@krizaka/ui/blocks.css"` — never through a relative @import of another file. Plain CSS on the --kz-* tokens: dark and light alike, every brand (`.brand-<id>`)
4
+ through --kz-accent. Nothing here loops: the pointer lights, lifts and wakes; under reduced motion everything is still.
5
+
6
+ Two contracts a page can set on any ancestor:
7
+ - the frame: --kz-page-max (the width of the content, 72rem) and --kz-page-gutter (the side margin, 16 → 32 px);
8
+ - the hue of a subject: --kz-hue (rails, icon tiles, lights — decorative, ≥ 3:1), --kz-hue-2 (the end of its rail),
9
+ --kz-hue-text (small text, ≥ 4.5:1). Unset, every block falls back to the brand accent. */
10
+
11
+ /* ─── Page: one frame for every page — the width, the gutters, the vertical rhythm ─── */
12
+ .kz-frame {
13
+ --kz-gutter: var(--kz-page-gutter, clamp(16px, 3.2vw, 32px));
14
+ box-sizing: border-box;
15
+ width: 100%;
16
+ max-width: calc(var(--kz-page-max, 72rem) + 2 * var(--kz-gutter));
17
+ margin-inline: auto;
18
+ padding-inline: var(--kz-gutter);
19
+ }
20
+ .kz-frame[data-size="narrow"] { --kz-page-max: 48rem; }
21
+ .kz-frame[data-size="wide"] { --kz-page-max: 88rem; }
22
+ .kz-frame[data-size="full"] { max-width: none; }
23
+ /* A frame inside a frame (a Section in a TocLayout, a Page in a card) adds no second pair of gutters. */
24
+ .kz-frame .kz-frame { --kz-gutter: 0px; }
25
+
26
+ /* Section: the content in the frame, a space above and below; `divider` draws the hairline between two sections (the
27
+ transition), inside the gutters. */
28
+ .kz-section { --kz-section-space: clamp(48px, 7vw, 88px); position: relative; }
29
+ .kz-section[data-spacing="sm"] { --kz-section-space: clamp(28px, 4vw, 40px); }
30
+ .kz-section[data-spacing="lg"] { --kz-section-space: clamp(64px, 10vw, 128px); }
31
+ .kz-section > .kz-frame { position: relative; padding-block: var(--kz-section-space); }
32
+ .kz-section[data-divider] > .kz-frame {
33
+ background: linear-gradient(var(--kz-border-subtle), var(--kz-border-subtle)) top center / calc(100% - 2 * var(--kz-gutter)) 1px no-repeat;
34
+ }
35
+ .kz-section :is(h2, h3)[id] { scroll-margin-top: var(--kz-anchor-offset, 96px); }
36
+
37
+ .kz-eyebrow {
38
+ margin: 0;
39
+ display: inline-flex;
40
+ align-items: center;
41
+ gap: 10px;
42
+ font-family: var(--kz-font-mono);
43
+ font-size: 11px;
44
+ font-weight: 600;
45
+ letter-spacing: 0.18em;
46
+ text-transform: uppercase;
47
+ color: var(--kz-hue-text, var(--kz-accent-text));
48
+ }
49
+ .kz-label {
50
+ margin: 0;
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 6px;
54
+ font-family: var(--kz-font-mono);
55
+ font-size: 10.5px;
56
+ font-weight: 600;
57
+ letter-spacing: 0.14em;
58
+ text-transform: uppercase;
59
+ color: var(--kz-text-secondary);
60
+ }
61
+ .kz-heading { margin-bottom: clamp(24px, 3vw, 36px); display: grid; gap: 12px; }
62
+ .kz-heading[data-align="center"] { justify-items: center; text-align: center; }
63
+ .kz-heading[data-actions] { grid-template-columns: minmax(0, 1fr) auto; align-items: end; column-gap: 24px; }
64
+ .kz-heading[data-actions] > :not(.kz-heading-actions) { grid-column: 1; }
65
+ .kz-heading-actions { grid-column: 2; grid-row: 1 / span 3; display: flex; flex-wrap: wrap; gap: 8px; }
66
+ .kz-heading-title {
67
+ margin: 0;
68
+ max-width: 24ch;
69
+ font-family: var(--kz-font-display);
70
+ font-size: clamp(1.6rem, 3.6vw, 2.3rem);
71
+ font-weight: 800;
72
+ letter-spacing: -0.028em;
73
+ line-height: 1.15;
74
+ color: var(--kz-text-primary);
75
+ text-wrap: balance;
76
+ }
77
+ .kz-heading[data-size="sm"] .kz-heading-title { font-size: clamp(1.25rem, 2.6vw, 1.6rem); letter-spacing: -0.02em; max-width: none; }
78
+ .kz-heading-lead { margin: 0; max-width: 680px; font-size: 15.5px; line-height: 1.7; color: var(--kz-text-secondary); }
79
+ @media (max-width: 640px) {
80
+ .kz-heading[data-actions] { grid-template-columns: minmax(0, 1fr); }
81
+ .kz-heading-actions { grid-column: 1; grid-row: auto; }
82
+ }
83
+
84
+ /* Ticks: a word between backticks in a sentence reads as code. */
85
+ .kz-ic {
86
+ padding: 0.08em 0.38em;
87
+ border-radius: 6px;
88
+ font-family: var(--kz-font-mono);
89
+ font-size: 0.86em;
90
+ font-weight: 500;
91
+ overflow-wrap: anywhere;
92
+ color: var(--kz-text-primary);
93
+ background: var(--kz-surface-2);
94
+ border: 1px solid var(--kz-border-subtle);
95
+ }
96
+
97
+ /* Facts: a few mono words on one line (registry and version, a status said honestly). */
98
+ .kz-facts { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
99
+ .kz-fact {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ gap: 7px;
103
+ min-height: 26px;
104
+ padding: 0 10px;
105
+ border-radius: 999px;
106
+ white-space: nowrap;
107
+ font-family: var(--kz-font-mono);
108
+ font-size: 11.5px;
109
+ font-weight: 600;
110
+ text-decoration: none;
111
+ color: var(--kz-text-primary);
112
+ background: var(--kz-surface-2);
113
+ border: 1px solid var(--kz-border-subtle);
114
+ transition: border-color 0.2s var(--kz-ease, ease);
115
+ }
116
+ a.kz-fact:hover { border-color: var(--kz-border-strong); }
117
+ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
118
+ .kz-fact-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: var(--kz-text-secondary); }
119
+ .kz-fact[data-tone="ok"] .kz-fact-dot { background: var(--kz-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--kz-success) 22%, transparent); }
120
+ .kz-fact[data-tone="wip"] {
121
+ color: var(--kz-warning-text);
122
+ background: color-mix(in srgb, var(--kz-warning) 10%, var(--kz-surface-1));
123
+ border-color: color-mix(in srgb, var(--kz-warning) 30%, transparent);
124
+ }
125
+ .kz-fact[data-tone="wip"] .kz-fact-dot { width: 8px; height: 8px; background: transparent; border: 2px solid var(--kz-warning); border-right-color: transparent; transform: rotate(45deg); }
126
+
127
+ /* ─── PageHero: the first screen of a page — painted at once, never revealed ─── */
128
+ .kz-hero > .kz-frame {
129
+ position: relative;
130
+ padding-top: var(--kz-hero-top, clamp(112px, 14vw, 156px));
131
+ padding-bottom: var(--kz-hero-bottom, 32px);
132
+ display: grid;
133
+ grid-template-columns: minmax(0, 1fr) auto;
134
+ gap: 24px;
135
+ align-items: end;
136
+ }
137
+ .kz-hero[data-align="center"] > .kz-frame { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; }
138
+ .kz-hero[data-align="center"] .kz-hero-lead { margin-inline: auto; }
139
+ .kz-hero-text { min-width: 0; }
140
+ .kz-hero-back {
141
+ display: flex;
142
+ width: fit-content;
143
+ align-items: center;
144
+ gap: 6px;
145
+ min-height: 32px;
146
+ margin-bottom: 14px;
147
+ font-size: 13px;
148
+ font-weight: 600;
149
+ text-decoration: none;
150
+ color: var(--kz-text-secondary);
151
+ border-radius: 8px;
152
+ }
153
+ .kz-hero-back:hover { color: var(--kz-text-primary); }
154
+ .kz-hero-back:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
155
+ .kz-hero-title {
156
+ margin: 10px 0 0;
157
+ font-family: var(--kz-font-display);
158
+ font-size: clamp(2rem, 5.4vw, 3.1rem);
159
+ font-weight: 800;
160
+ letter-spacing: -0.035em;
161
+ line-height: 1.08;
162
+ color: var(--kz-text-primary);
163
+ text-wrap: balance;
164
+ }
165
+ .kz-hero-lead { margin: 16px 0 0; max-width: 680px; font-size: clamp(15px, 1.9vw, 17.5px); line-height: 1.7; color: var(--kz-text-secondary); }
166
+ .kz-hero-extra { margin-top: 18px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
167
+ .kz-hero-aside { display: flex; justify-content: flex-end; }
168
+ @media (max-width: 720px) {
169
+ .kz-hero > .kz-frame { grid-template-columns: minmax(0, 1fr); }
170
+ .kz-hero-aside { order: -1; justify-content: flex-start; }
171
+ }
172
+
173
+ /* ─── CardGrid: one column on a phone, cells of a row share their height ─── */
174
+ .kz-cards { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--kz-cards-gap, 16px);
175
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--kz-cards-min, 300px)), 1fr)); }
176
+ .kz-cards[data-fit] { grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--kz-cards-min, 300px)), 1fr)); }
177
+ .kz-cards[data-align="start"] { align-items: start; }
178
+ .kz-cards-cell { display: grid; min-width: 0; }
179
+
180
+ /* The shared surface of the cards: a rail of the hue along the top, the light that follows the pointer (PointerLight
181
+ writes --kz-pointer-x/y), a lift and a lit border under the pointer or the focus. */
182
+ .kz-block-card {
183
+ position: relative;
184
+ isolation: isolate;
185
+ overflow: hidden;
186
+ border-radius: 18px;
187
+ background: var(--kz-surface-1);
188
+ border: 1px solid var(--kz-border-default);
189
+ transition: transform 0.3s var(--kz-ease, ease), border-color 0.3s var(--kz-ease, ease), box-shadow 0.3s var(--kz-ease, ease);
190
+ }
191
+ .kz-block-card::before {
192
+ content: "";
193
+ position: absolute;
194
+ inset: 0 0 auto;
195
+ height: 2px;
196
+ z-index: 1;
197
+ background: linear-gradient(90deg, var(--kz-hue, var(--kz-accent)), var(--kz-hue-2, var(--kz-accent-2, var(--kz-accent))) 45%, transparent);
198
+ opacity: 0.85;
199
+ }
200
+ .kz-block-card::after {
201
+ content: "";
202
+ position: absolute;
203
+ inset: 0;
204
+ z-index: -1;
205
+ pointer-events: none;
206
+ opacity: 0;
207
+ background: radial-gradient(360px circle at var(--kz-pointer-x, 18%) var(--kz-pointer-y, 0%), color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 13%, transparent), transparent 62%);
208
+ transition: opacity 0.3s var(--kz-ease, ease);
209
+ }
210
+ .kz-block-card:focus-within,
211
+ .kz-block-card:focus-visible { border-color: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 50%, var(--kz-border-default)); }
212
+ .kz-block-card:is(:hover, :focus-within, :focus-visible)::after { opacity: 1; }
213
+ @media (hover: hover) {
214
+ .kz-block-card:hover {
215
+ transform: translateY(-3px);
216
+ border-color: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 45%, var(--kz-border-default));
217
+ box-shadow: 0 24px 48px -30px color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 70%, transparent);
218
+ }
219
+ }
220
+ /* The icon tile of a card: the hue around it; the node of a signature icon lights under the pointer. */
221
+ .kz-block-icon {
222
+ display: inline-flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ flex-shrink: 0;
226
+ width: 42px;
227
+ height: 42px;
228
+ border-radius: 12px;
229
+ color: var(--kz-text-primary);
230
+ background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 14%, var(--kz-surface-1));
231
+ border: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 30%, transparent);
232
+ transition: transform 0.3s var(--kz-ease, ease), box-shadow 0.3s var(--kz-ease, ease);
233
+ }
234
+ .kz-block-card :is(.kz-block-icon) svg [data-node] { transition: transform 0.3s var(--kz-ease, ease), filter 0.3s; transform-box: fill-box; transform-origin: center; }
235
+ .kz-block-card:is(:hover, :focus-within, :focus-visible) .kz-block-icon svg [data-node] { transform: scale(1.5); filter: drop-shadow(0 0 3px var(--kz-hue, var(--kz-accent))); }
236
+ @media (hover: hover) {
237
+ .kz-block-card:hover .kz-block-icon { transform: translateY(-2px) rotate(-3deg); box-shadow: 0 10px 22px -12px var(--kz-hue, var(--kz-accent)); }
238
+ }
239
+
240
+ /* ─── LinkCard: the whole card is the link — icon, title, one sentence, the way in ─── */
241
+ .kz-link-card {
242
+ display: grid;
243
+ grid-template-columns: auto minmax(0, 1fr);
244
+ align-items: start;
245
+ gap: 4px 14px;
246
+ padding: 18px 20px;
247
+ text-decoration: none;
248
+ color: var(--kz-text-primary);
249
+ }
250
+ .kz-link-card[data-layout="stack"] { grid-template-columns: minmax(0, 1fr); gap: 12px; }
251
+ .kz-link-card:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
252
+ .kz-link-card > .kz-block-icon { grid-row: span 3; }
253
+ .kz-link-card[data-layout="stack"] > .kz-block-icon { grid-row: auto; }
254
+ .kz-link-card-body { display: grid; gap: 5px; min-width: 0; }
255
+ .kz-link-card-meta { margin: 0; font-family: var(--kz-font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--kz-hue-text, var(--kz-accent-text)); }
256
+ .kz-link-card-title { margin: 0; font-family: var(--kz-font-display); font-size: 16.5px; font-weight: 750; letter-spacing: -0.012em; line-height: 1.3; color: var(--kz-text-primary); }
257
+ .kz-link-card-text { margin: 0; font-size: 14px; line-height: 1.55; color: var(--kz-text-secondary); }
258
+ .kz-link-card-extra { margin-top: 6px; }
259
+ .kz-link-card-cta {
260
+ display: inline-flex;
261
+ align-items: center;
262
+ gap: 6px;
263
+ margin-top: 8px;
264
+ width: fit-content;
265
+ font-size: 13.5px;
266
+ font-weight: 650;
267
+ color: var(--kz-hue-text, var(--kz-accent-text));
268
+ }
269
+ .kz-link-card-cta svg { transition: transform 0.25s var(--kz-ease, ease); }
270
+ .kz-link-card:is(:hover, :focus-visible) .kz-link-card-cta svg { transform: translateX(3px); }
271
+
272
+ /* ─── ArgumentCard, compact: icon · name · the bird in the corner → the trap in one line → facts → one short action ───
273
+ The long version is never on the face: on a detail page, or unfolded in place (a native <details>). A grid with
274
+ folds aligns its cards at the top, so opening one never stretches its neighbours. */
275
+ .kz-arg { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px 14px; }
276
+ .kz-arg .kz-block-icon { width: 40px; height: 40px; }
277
+ .kz-arg-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
278
+ .kz-arg-id { min-width: 0; }
279
+ .kz-arg-title { margin: 0; font-family: var(--kz-font-display); font-size: 17px; font-weight: 800; letter-spacing: -0.015em; line-height: 1.2; color: var(--kz-text-primary); }
280
+ .kz-arg-meta { margin: 3px 0 0; font-family: var(--kz-font-mono); font-size: 12px; color: var(--kz-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
281
+ .kz-arg-mark { margin-left: auto; align-self: flex-start; margin-top: -6px; margin-right: -4px; flex-shrink: 0; --kz-accent: var(--kz-hue, var(--kz-accent)); }
282
+ .kz-arg-line { margin: 0; font-size: 15px; font-weight: 500; line-height: 1.55; color: var(--kz-text-primary); text-wrap: pretty; }
283
+ .kz-arg .kz-fact { min-height: 24px; padding: 0 9px; font-size: 11px; }
284
+ .kz-arg-panel { margin-top: 2px; border-top: 1px solid var(--kz-border-subtle); }
285
+ .kz-arg-panel > summary {
286
+ display: inline-flex;
287
+ align-items: center;
288
+ gap: 6px;
289
+ min-height: 36px;
290
+ padding-top: 10px;
291
+ cursor: pointer;
292
+ list-style: none;
293
+ font-size: 13.5px;
294
+ font-weight: 650;
295
+ color: var(--kz-hue-text, var(--kz-accent-text));
296
+ border-radius: 6px;
297
+ }
298
+ .kz-arg-panel > summary::-webkit-details-marker { display: none; }
299
+ .kz-arg-panel > summary:hover { text-decoration: underline; text-underline-offset: 3px; }
300
+ .kz-arg-panel > summary:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
301
+ .kz-arg-panel > summary svg { transition: transform 0.25s var(--kz-ease, ease); }
302
+ .kz-arg-panel[open] > summary svg { transform: rotate(180deg); }
303
+ .kz-arg-panel-body { display: grid; gap: 16px; padding: 10px 0 4px; }
304
+ .kz-arg-panel dl { margin: 0; display: grid; gap: 10px; }
305
+ .kz-arg-panel dd { margin: 4px 0 0; font-size: 14px; line-height: 1.6; color: var(--kz-text-secondary); }
306
+ .kz-arg-panel .kz-list { margin-top: 8px; }
307
+ .kz-cards:has(.kz-arg-panel) { align-items: start; }
308
+ .kz-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
309
+ .kz-list li { position: relative; padding-left: 18px; font-size: 14px; line-height: 1.55; color: var(--kz-text-secondary); }
310
+ .kz-list li::before { content: ""; position: absolute; left: 2px; top: 0.6em; width: 7px; height: 7px; border-radius: 2px; background: var(--kz-hue, var(--kz-accent)); }
311
+ .kz-arg-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--kz-border-subtle); }
312
+ .kz-arg-more {
313
+ display: inline-flex;
314
+ align-items: center;
315
+ gap: 8px;
316
+ min-height: 32px;
317
+ padding: 4px 12px;
318
+ border-radius: 10px;
319
+ corner-shape: bevel; /* the Krizaka chamfer, like Button shape="cut" */
320
+ font-size: 13px;
321
+ font-weight: 650;
322
+ line-height: 1.25;
323
+ text-decoration: none;
324
+ color: var(--kz-text-primary);
325
+ background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 14%, var(--kz-surface-1));
326
+ border: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 38%, transparent);
327
+ transition: background-color 0.2s, border-color 0.2s;
328
+ }
329
+ .kz-arg-more:hover { background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 24%, var(--kz-surface-1)); border-color: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 55%, transparent); }
330
+ .kz-arg-more:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
331
+ .kz-arg-more svg { transition: transform 0.25s var(--kz-ease, ease); }
332
+ .kz-arg-more:hover svg { transform: translateX(3px); }
333
+ .kz-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
334
+
335
+ /* ─── MascotQuote: a sentence in a speech bubble, the bird under its tail ─── */
336
+ .kz-quote { margin: 0; display: grid; gap: 4px; }
337
+ .kz-quote blockquote {
338
+ position: relative;
339
+ margin: 0;
340
+ padding: 14px 16px 14px 44px;
341
+ border-radius: 16px 16px 16px 6px;
342
+ background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 9%, var(--kz-surface-0));
343
+ border: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 30%, transparent);
344
+ }
345
+ .kz-quote blockquote::before {
346
+ content: "\201C";
347
+ position: absolute;
348
+ left: 12px;
349
+ top: 6px;
350
+ font-family: var(--kz-font-display), Georgia, serif;
351
+ font-size: 44px;
352
+ font-weight: 800;
353
+ line-height: 1;
354
+ color: var(--kz-hue, var(--kz-accent));
355
+ }
356
+ .kz-quote blockquote::after {
357
+ content: "";
358
+ position: absolute;
359
+ left: 22px;
360
+ bottom: -7px;
361
+ width: 12px;
362
+ height: 12px;
363
+ transform: rotate(45deg);
364
+ background: inherit;
365
+ border-right: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 30%, transparent);
366
+ border-bottom: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 30%, transparent);
367
+ }
368
+ .kz-quote blockquote p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--kz-text-primary); }
369
+ .kz-quote figcaption {
370
+ display: flex;
371
+ align-items: center;
372
+ gap: 8px;
373
+ padding-left: 4px;
374
+ font-family: var(--kz-font-mono);
375
+ font-size: 10.5px;
376
+ font-weight: 700;
377
+ letter-spacing: 0.14em;
378
+ text-transform: uppercase;
379
+ color: var(--kz-hue-text, var(--kz-accent-text));
380
+ }
381
+ .kz-quote-bird { flex-shrink: 0; --kz-accent: var(--kz-hue, var(--kz-accent)); }
382
+ .kz-quote[data-variant="callout"] blockquote { padding: 24px 26px 24px 68px; border-radius: 22px 22px 22px 8px; }
383
+ .kz-quote[data-variant="callout"] blockquote::before { left: 18px; top: 12px; font-size: 72px; }
384
+ .kz-quote[data-variant="callout"] blockquote::after { left: 36px; bottom: -8px; width: 14px; height: 14px; }
385
+ .kz-quote[data-variant="callout"] blockquote p { font-family: var(--kz-font-display); font-size: clamp(16px, 2vw, 19px); font-weight: 600; line-height: 1.55; letter-spacing: -0.005em; }
386
+ .kz-quote[data-variant="callout"] figcaption { gap: 12px; padding-left: 14px; font-size: 11px; }
387
+ @media (max-width: 480px) {
388
+ .kz-quote[data-variant="callout"] blockquote { padding: 50px 20px 20px; }
389
+ .kz-quote[data-variant="callout"] blockquote::before { top: 6px; left: 16px; font-size: 58px; }
390
+ }
391
+ /* The bird answers the pointer once: a small hop toward the reader. */
392
+ @keyframes kz-quote-hop { 0%, 100% { transform: translateY(0) rotate(0); } 35% { transform: translateY(-6px) rotate(-5deg); } 70% { transform: translateY(0) rotate(2deg); } }
393
+ @media (hover: hover) and (prefers-reduced-motion: no-preference) {
394
+ :is(.kz-block-card, .kz-quote):hover .kz-quote-bird { animation: kz-quote-hop 0.7s var(--kz-ease, ease) 1; }
395
+ }
396
+
397
+ /* ─── DecisionList: one card per decision — what was chosen, large; refused · because · what it costs, side by side ─── */
398
+ .kz-decisions { margin: 0; padding: 0; list-style: none; display: grid; gap: 14px; }
399
+ .kz-decision { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 18px; padding: 20px 22px; border-radius: 18px; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
400
+ .kz-decision-n { font-family: var(--kz-font-display); font-size: 28px; font-weight: 800; line-height: 1; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; color: var(--kz-hue-text, var(--kz-accent-text)); }
401
+ .kz-decision-body { display: grid; gap: 14px; min-width: 0; }
402
+ .kz-decision-part p:not(.kz-label) { margin: 6px 0 0; font-size: 14px; line-height: 1.6; color: var(--kz-text-secondary); }
403
+ .kz-decision-part[data-part="chose"] .kz-label { color: var(--kz-success-text); }
404
+ .kz-decision-part[data-part="chose"] p:not(.kz-label) { font-size: 16px; font-weight: 600; line-height: 1.5; color: var(--kz-text-primary); }
405
+ .kz-decision-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
406
+ .kz-decision-grid > .kz-decision-part { min-width: 0; padding: 12px 14px; border-radius: 12px; background: var(--kz-surface-0); border: 1px solid var(--kz-border-subtle); border-top: 2px solid var(--kz-border-strong); }
407
+ .kz-decision-part[data-part="refused"] { border-top-color: var(--kz-danger); }
408
+ .kz-decision-part[data-part="refused"] .kz-label { color: var(--kz-danger-text); }
409
+ .kz-decision-part[data-part="because"] { border-top-color: var(--kz-hue, var(--kz-accent)); }
410
+ .kz-decision-part[data-part="because"] .kz-label { color: var(--kz-hue-text, var(--kz-accent-text)); }
411
+ .kz-decision-part[data-part="cost"] { border-top-color: var(--kz-warning); background: color-mix(in srgb, var(--kz-warning) 6%, var(--kz-surface-0)); }
412
+ .kz-decision-part[data-part="cost"] .kz-label { color: var(--kz-warning-text); }
413
+ @media (max-width: 900px) { .kz-decision-grid { grid-template-columns: minmax(0, 1fr); } }
414
+ @media (max-width: 560px) { .kz-decision { grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 18px; } .kz-decision-n { font-size: 22px; } }
415
+
416
+ /* ─── CodeBlock · CodeTabs: a file name, code that scrolls sideways (never shrinks), a copy button ─── */
417
+ .kz-code { margin: 0; min-width: 0; overflow: hidden; border-radius: 14px; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); box-shadow: inset 3px 0 0 var(--kz-hue, var(--kz-accent)); }
418
+ .kz-code-bar {
419
+ display: flex;
420
+ align-items: center;
421
+ justify-content: space-between;
422
+ gap: 12px;
423
+ min-height: 40px;
424
+ padding: 5px 6px 5px 16px;
425
+ font-family: var(--kz-font-mono);
426
+ font-size: 11.5px;
427
+ color: var(--kz-text-secondary);
428
+ background: var(--kz-surface-2);
429
+ border-bottom: 1px solid var(--kz-border-subtle);
430
+ }
431
+ .kz-code-file { display: inline-flex; align-items: center; gap: 10px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
432
+ .kz-code-lang { padding: 2px 7px; border-radius: 6px; font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--kz-text-primary); background: var(--kz-surface-3); }
433
+ .kz-code pre { margin: 0; padding: 16px 18px; overflow-x: auto; font-family: var(--kz-font-mono); font-size: 12.5px; line-height: 1.7; color: var(--kz-text-primary); tab-size: 2; }
434
+ .kz-code pre:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: -2px; }
435
+ .kz-tk-comment { color: var(--kz-text-secondary); font-style: italic; }
436
+ .kz-tk-string { color: var(--kz-success-text); }
437
+ .kz-tk-annotation { color: var(--kz-warning-text); }
438
+ .kz-tk-keyword, .kz-tk-tag { color: var(--kz-accent-text); font-weight: 600; }
439
+ .kz-code-copy {
440
+ display: inline-flex;
441
+ align-items: center;
442
+ gap: 5px;
443
+ min-height: 30px;
444
+ padding: 0 10px;
445
+ border-radius: 8px;
446
+ cursor: pointer;
447
+ font: 600 11.5px var(--kz-font-mono);
448
+ color: var(--kz-text-secondary);
449
+ background: var(--kz-surface-1);
450
+ border: 1px solid var(--kz-border-default);
451
+ }
452
+ .kz-code-copy:hover { color: var(--kz-text-primary); border-color: var(--kz-border-strong); }
453
+ .kz-code-copy:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
454
+ .kz-code-copy[data-copied] { color: var(--kz-success-text); }
455
+ .kz-code-tabs { display: grid; gap: 10px; min-width: 0; }
456
+ .kz-code-tabs [role="tablist"] { justify-self: start; width: auto; }
457
+
458
+ /* ─── ActionBar · CtaPanel ─── */
459
+ .kz-actions { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
460
+ .kz-actions[data-variant="icons"] { gap: 2px; }
461
+ .kz-actions a > svg:first-child { color: var(--kz-hue-text, var(--kz-accent-text)); }
462
+ /* The words of an icon action, as a tooltip on hover and focus (no script, no portal): the accessible name says them too. */
463
+ .kz-actions [data-tip] { position: relative; }
464
+ .kz-actions [data-tip]::after {
465
+ content: attr(data-tip);
466
+ position: absolute;
467
+ bottom: calc(100% + 6px);
468
+ left: 50%;
469
+ z-index: 10;
470
+ padding: 4px 8px;
471
+ border-radius: 6px;
472
+ white-space: nowrap;
473
+ pointer-events: none;
474
+ font: 600 12px/1.4 var(--kz-font-sans);
475
+ color: var(--kz-text-primary);
476
+ background: var(--kz-surface-3);
477
+ border: 1px solid var(--kz-border-default);
478
+ box-shadow: var(--kz-shadow-md);
479
+ opacity: 0;
480
+ transform: translate(-50%, 4px);
481
+ transition: opacity 0.15s, transform 0.15s var(--kz-ease, ease);
482
+ }
483
+ .kz-actions [data-tip]:is(:hover, :focus-visible)::after { opacity: 1; transform: translate(-50%, 0); }
484
+ .kz-actions li:last-child [data-tip]::after { left: auto; right: 0; transform: translateY(4px); }
485
+ .kz-actions li:last-child [data-tip]:is(:hover, :focus-visible)::after { transform: none; }
486
+
487
+ .kz-cta {
488
+ position: relative;
489
+ overflow: hidden;
490
+ display: flex;
491
+ flex-wrap: wrap;
492
+ align-items: center;
493
+ justify-content: space-between;
494
+ gap: 20px;
495
+ padding: 24px 26px;
496
+ border-radius: 20px;
497
+ background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 8%, var(--kz-surface-1));
498
+ border: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 30%, var(--kz-border-default));
499
+ }
500
+ .kz-cta-text { min-width: 0; flex: 1 1 320px; }
501
+ .kz-cta-title { margin: 0 0 6px; font-family: var(--kz-font-display); font-size: 21px; font-weight: 800; letter-spacing: -0.015em; color: var(--kz-text-primary); scroll-margin-top: var(--kz-anchor-offset, 96px); }
502
+ .kz-cta-body { margin: 0; max-width: 640px; font-size: 14.5px; line-height: 1.65; color: var(--kz-text-secondary); }
503
+ .kz-cta-actions { display: flex; flex-wrap: wrap; gap: 10px; }
504
+
505
+ /* ─── Toc: sticky beside the content on a wide screen, a row of chips on a phone ─── */
506
+ .kz-toc-layout { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 48px; align-items: start; }
507
+ .kz-toc-aside { position: sticky; top: var(--kz-anchor-offset, 96px); padding-top: 4px; }
508
+ .kz-toc ol { margin: 10px 0 0; padding: 0; list-style: none; display: grid; gap: 2px; border-left: 1px solid var(--kz-border-default); }
509
+ .kz-toc a { position: relative; display: flex; align-items: center; min-height: 34px; padding: 4px 0 4px 14px; font-size: 13.5px; font-weight: 600; text-decoration: none; color: var(--kz-text-secondary); transition: color 0.2s; }
510
+ .kz-toc a:hover, .kz-toc a[aria-current] { color: var(--kz-text-primary); }
511
+ .kz-toc a[aria-current]::before { content: ""; position: absolute; left: -1px; top: 6px; bottom: 6px; width: 2px; border-radius: 2px; background: var(--kz-hue, var(--kz-accent)); }
512
+ .kz-toc a:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
513
+ .kz-toc-main { min-width: 0; }
514
+ @media (max-width: 1023px) {
515
+ .kz-toc-layout { grid-template-columns: minmax(0, 1fr); gap: 8px; }
516
+ .kz-toc-aside { position: static; padding-top: 0; margin-inline: calc(-1 * var(--kz-gutter, 16px)); }
517
+ .kz-toc { padding: 0 var(--kz-gutter, 16px) 4px; overflow-x: auto; scrollbar-width: none; }
518
+ .kz-toc .kz-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
519
+ .kz-toc ol { margin: 0; display: flex; gap: 8px; width: max-content; border: 0; }
520
+ .kz-toc a { min-height: 36px; padding: 0 14px; border-radius: 999px; white-space: nowrap; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
521
+ .kz-toc a[aria-current] { border-color: var(--kz-hue, var(--kz-accent)); }
522
+ .kz-toc a[aria-current]::before { display: none; }
523
+ }
524
+
525
+ @media (prefers-reduced-motion: reduce) {
526
+ .kz-block-card, .kz-block-card::after, .kz-block-icon, .kz-block-icon svg [data-node], .kz-link-card-cta svg, .kz-arg-more svg, .kz-arg-panel > summary svg, .kz-actions [data-tip]::after { transition: none !important; }
527
+ .kz-block-card:hover, .kz-block-card:hover .kz-block-icon, .kz-link-card:hover .kz-link-card-cta svg, .kz-arg-more:hover svg { transform: none !important; }
528
+ .kz-quote-bird { animation: none !important; }
529
+ }
package/dist/button.js CHANGED
@@ -1,98 +1,9 @@
1
1
  import {
2
- LoaderGlyph
3
- } from "./chunk-43PTCDTL.js";
4
-
5
- // src/button/button.tsx
6
- import { Slot } from "radix-ui";
7
- import { tv } from "tailwind-variants";
8
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
- var buttonVariants = tv({
10
- base: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] [&[data-loading]]:opacity-100",
11
- variants: {
12
- variant: {
13
- primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover",
14
- // The brand's signature: accent → accent-2 (on-accent reads on both stops, tested in @krizaka/tokens).
15
- gradient: "bg-linear-to-r from-accent to-accent-2 text-on-accent shadow-sm hover:brightness-110",
16
- secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3",
17
- outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-fg-accent",
18
- ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg",
19
- // The border and the tint carry the danger; the label stays the primary text role, legible on the tint at rest
20
- // and hovered over every surface (`text-fg-danger` is for text set directly on a surface).
21
- danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20"
22
- },
23
- size: { sm: "h-8 px-3 text-xs", md: "h-10 px-4 text-sm", lg: "h-12 px-6 text-sm", icon: "h-10 w-10" },
24
- // `cut`: the Krizaka chamfer — 45° corners (CSS corner-shape, where supported; rounded elsewhere). The border, the
25
- // focus ring and the hover follow the cut, unlike a clip-path.
26
- shape: { rounded: "rounded-lg", pill: "rounded-full", cut: "rounded-[10px] [corner-shape:bevel]" }
27
- },
28
- defaultVariants: { variant: "secondary", size: "md", shape: "rounded" }
29
- });
30
- var STATUS_TEXT = { success: "text-fg-success", error: "text-fg-danger" };
31
- function Button({
32
- asChild,
33
- loading,
34
- progress,
35
- status,
36
- announce,
37
- indicator = true,
38
- shimmer,
39
- magnetic,
40
- variant,
41
- size,
42
- shape,
43
- className,
44
- disabled,
45
- children,
46
- ...props
47
- }) {
48
- const Comp = asChild ? Slot.Root : "button";
49
- const known = loading && typeof progress === "number" && Number.isFinite(progress);
50
- const ratio = known ? Math.min(1, Math.max(0, progress)) : 0;
51
- const glyph = indicator && !asChild && (loading || status) ? status ?? "loading" : null;
52
- const filled = variant === "primary" || variant === "gradient";
53
- const button = /* @__PURE__ */ jsx(
54
- Comp,
55
- {
56
- type: asChild ? void 0 : "button",
57
- "aria-busy": loading || void 0,
58
- "data-loading": loading ? "" : void 0,
59
- "data-variant": variant ?? "secondary",
60
- "data-kz-status": status ?? void 0,
61
- "data-kz-magnetic": magnetic ? "" : void 0,
62
- disabled: asChild ? void 0 : disabled || loading,
63
- "aria-disabled": asChild && (disabled || loading) ? true : void 0,
64
- className: buttonVariants({
65
- variant,
66
- size,
67
- shape,
68
- className: [known && "relative isolate overflow-hidden", shimmer && "kz-sheen", className].filter(Boolean).join(" ") || void 0
69
- }),
70
- ...props,
71
- children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
72
- known && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 -z-10 bg-current opacity-15 transition-[width] duration-500", style: { width: `${ratio * 100}%` } }),
73
- glyph && /* @__PURE__ */ jsx(
74
- "span",
75
- {
76
- "aria-hidden": true,
77
- "data-slot": "indicator",
78
- className: "-my-1 grid grid-cols-[1fr] transition-[grid-template-columns,margin,opacity] duration-300 starting:-mr-2 starting:grid-cols-[0fr] starting:opacity-0",
79
- children: /* @__PURE__ */ jsx("span", { className: "overflow-hidden", children: /* @__PURE__ */ jsx(LoaderGlyph, { state: glyph, value: known ? ratio : null, className: ["h-4 w-4", glyph !== "loading" && !filled && STATUS_TEXT[glyph]].filter(Boolean).join(" ") }) })
80
- }
81
- ),
82
- children
83
- ] })
84
- }
85
- );
86
- if (announce === void 0 || asChild) return button;
87
- return /* @__PURE__ */ jsxs(Fragment, { children: [
88
- button,
89
- /* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: announce })
90
- ] });
91
- }
92
- function IconButton({ label, size = "icon", children, ...props }) {
93
- const swap = props.indicator !== false && !props.asChild && (props.loading || props.status);
94
- return /* @__PURE__ */ jsx(Button, { "aria-label": label, title: label, size, ...props, children: swap ? null : children });
95
- }
2
+ Button,
3
+ IconButton,
4
+ buttonVariants
5
+ } from "./chunk-Z6FUPB3Q.js";
6
+ import "./chunk-43PTCDTL.js";
96
7
  export {
97
8
  Button,
98
9
  IconButton,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/button/button.tsx"],"sourcesContent":["// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { LoaderGlyph } from \"../spinner/glyph\";\n\nexport const buttonVariants = tv({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] \" +\n // Busy is not unavailable: a loading button keeps its colour (it is disabled only so it is not pressed twice).\n \"[&[data-loading]]:opacity-100\",\n variants: {\n variant: {\n primary: \"bg-accent text-on-accent shadow-sm hover:bg-accent-hover\",\n // The brand's signature: accent → accent-2 (on-accent reads on both stops, tested in @krizaka/tokens).\n gradient: \"bg-linear-to-r from-accent to-accent-2 text-on-accent shadow-sm hover:brightness-110\",\n secondary: \"border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3\",\n outline: \"border border-border-default bg-transparent text-fg hover:border-accent hover:text-fg-accent\",\n ghost: \"text-fg-secondary hover:bg-surface-2 hover:text-fg\",\n // The border and the tint carry the danger; the label stays the primary text role, legible on the tint at rest\n // and hovered over every surface (`text-fg-danger` is for text set directly on a surface).\n danger: \"border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20\",\n },\n size: { sm: \"h-8 px-3 text-xs\", md: \"h-10 px-4 text-sm\", lg: \"h-12 px-6 text-sm\", icon: \"h-10 w-10\" },\n // `cut`: the Krizaka chamfer — 45° corners (CSS corner-shape, where supported; rounded elsewhere). The border, the\n // focus ring and the hover follow the cut, unlike a clip-path.\n shape: { rounded: \"rounded-lg\", pill: \"rounded-full\", cut: \"rounded-[10px] [corner-shape:bevel]\" },\n },\n defaultVariants: { variant: \"secondary\", size: \"md\", shape: \"rounded\" },\n});\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /**\n * The look: `primary` (the accent), `gradient` (accent → accent-2), `secondary` (a raised surface), `outline`,\n * `ghost`, `danger`.\n * @default \"secondary\"\n */\n variant?: ButtonVariants[\"variant\"];\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"md\"\n */\n size?: ButtonVariants[\"size\"];\n /**\n * rounded · pill · cut (45° corners, the Krizaka chamfer).\n * @default \"rounded\"\n */\n shape?: ButtonVariants[\"shape\"];\n /** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */\n asChild?: boolean;\n /**\n * Disables and signals the wait (aria-busy, data-loading) and shows the Krizaka loader glyph before the label; the\n * button keeps its colour.\n */\n loading?: boolean;\n /**\n * Between 0 and 1, while `loading`: the glyph's trace and a light fill across the button grow to the value (an\n * upload, an export).\n */\n progress?: number | null;\n /**\n * How the action ended: `success` draws a check, `error` a cross (and the button shakes its head once); a ring of\n * the status colour opens around it. Clear it to return to rest.\n */\n status?: \"success\" | \"error\" | null;\n /** A message announced politely by assistive technology when it changes (“Saved”, “Upload failed”) — passed translated. */\n announce?: string;\n /**\n * Shows the glyph while `loading` / with a `status`. `false`: you draw your own.\n * @default true\n */\n indicator?: boolean;\n /** A sheen of light crosses the button on hover — for the one action a page is about. */\n shimmer?: boolean;\n /** The button leans a few pixels toward a fine pointer (driven by `MotionObserver`; never under reduced motion or on touch). */\n magnetic?: boolean;\n };\n\nconst STATUS_TEXT = { success: \"text-fg-success\", error: \"text-fg-danger\" } as const;\n\nexport function Button({\n asChild,\n loading,\n progress,\n status,\n announce,\n indicator = true,\n shimmer,\n magnetic,\n variant,\n size,\n shape,\n className,\n disabled,\n children,\n ...props\n}: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n const known = loading && typeof progress === \"number\" && Number.isFinite(progress);\n const ratio = known ? Math.min(1, Math.max(0, progress)) : 0;\n const glyph = indicator && !asChild && (loading || status) ? (status ?? \"loading\") : null;\n // On a filled variant the glyph stays in the label's colour; on the others it takes the status colour.\n const filled = variant === \"primary\" || variant === \"gradient\";\n const button = (\n <Comp\n type={asChild ? undefined : \"button\"}\n aria-busy={loading || undefined}\n data-loading={loading ? \"\" : undefined}\n data-variant={variant ?? \"secondary\"}\n data-kz-status={status ?? undefined}\n data-kz-magnetic={magnetic ? \"\" : undefined}\n disabled={asChild ? undefined : disabled || loading}\n aria-disabled={asChild && (disabled || loading) ? true : undefined}\n className={buttonVariants({\n variant,\n size,\n shape,\n className: [known && \"relative isolate overflow-hidden\", shimmer && \"kz-sheen\", className].filter(Boolean).join(\" \") || undefined,\n })}\n {...props}\n >\n {asChild ? (\n children\n ) : (\n <>\n {known && (\n <span aria-hidden className=\"absolute inset-y-0 left-0 -z-10 bg-current opacity-15 transition-[width] duration-500\" style={{ width: `${ratio * 100}%` }} />\n )}\n {glyph && (\n <span\n aria-hidden\n data-slot=\"indicator\"\n className=\"-my-1 grid grid-cols-[1fr] transition-[grid-template-columns,margin,opacity] duration-300 starting:-mr-2 starting:grid-cols-[0fr] starting:opacity-0\"\n >\n <span className=\"overflow-hidden\">\n <LoaderGlyph state={glyph} value={known ? ratio : null} className={[\"h-4 w-4\", glyph !== \"loading\" && !filled && STATUS_TEXT[glyph]].filter(Boolean).join(\" \")} />\n </span>\n </span>\n )}\n {children}\n </>\n )}\n </Comp>\n );\n if (announce === undefined || asChild) return button;\n return (\n <>\n {button}\n <span role=\"status\" className=\"sr-only\">\n {announce}\n </span>\n </>\n );\n}\n\nexport type IconButtonProps = Omit<ButtonProps, \"size\"> & {\n /** The accessible name (and tooltip) of the button — required, passed translated. */\n label: string;\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"icon\"\n */\n size?: ButtonProps[\"size\"];\n};\n\n/** An icon-only button: `label` is required, it is its accessible name. Loading or with a status, the glyph takes the icon's place. */\nexport function IconButton({ label, size = \"icon\", children, ...props }: IconButtonProps) {\n const swap = props.indicator !== false && !props.asChild && (props.loading || props.status);\n return (\n <Button aria-label={label} title={label} size={size} {...props}>\n {swap ? null : children}\n </Button>\n );\n}\n"],"mappings":";;;;;AACA,SAAS,YAAY;AAErB,SAAS,UAA6B;AA+H9B,mBAEI,KAFJ;AA3HD,IAAM,iBAAiB,GAAG;AAAA,EAC/B,MACE;AAAA,EAKF,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA;AAAA,MAET,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA;AAAA;AAAA,MAGP,QAAQ;AAAA,IACV;AAAA,IACA,MAAM,EAAE,IAAI,oBAAoB,IAAI,qBAAqB,IAAI,qBAAqB,MAAM,YAAY;AAAA;AAAA;AAAA,IAGpG,OAAO,EAAE,SAAS,cAAc,MAAM,gBAAgB,KAAK,sCAAsC;AAAA,EACnG;AAAA,EACA,iBAAiB,EAAE,SAAS,aAAa,MAAM,MAAM,OAAO,UAAU;AACxE,CAAC;AAoDD,IAAM,cAAc,EAAE,SAAS,mBAAmB,OAAO,iBAAiB;AAEnE,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAgB;AACd,QAAM,OAAO,UAAU,KAAK,OAAO;AACnC,QAAM,QAAQ,WAAW,OAAO,aAAa,YAAY,OAAO,SAAS,QAAQ;AACjF,QAAM,QAAQ,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC,IAAI;AAC3D,QAAM,QAAQ,aAAa,CAAC,YAAY,WAAW,UAAW,UAAU,YAAa;AAErF,QAAM,SAAS,YAAY,aAAa,YAAY;AACpD,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,UAAU,SAAY;AAAA,MAC5B,aAAW,WAAW;AAAA,MACtB,gBAAc,UAAU,KAAK;AAAA,MAC7B,gBAAc,WAAW;AAAA,MACzB,kBAAgB,UAAU;AAAA,MAC1B,oBAAkB,WAAW,KAAK;AAAA,MAClC,UAAU,UAAU,SAAY,YAAY;AAAA,MAC5C,iBAAe,YAAY,YAAY,WAAW,OAAO;AAAA,MACzD,WAAW,eAAe;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,CAAC,SAAS,oCAAoC,WAAW,YAAY,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK;AAAA,MAC1H,CAAC;AAAA,MACA,GAAG;AAAA,MAEH,oBACC,WAEA,iCACG;AAAA,iBACC,oBAAC,UAAK,eAAW,MAAC,WAAU,yFAAwF,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG;AAAA,QAE1J,SACC;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,aAAU;AAAA,YACV,WAAU;AAAA,YAEV,8BAAC,UAAK,WAAU,mBACd,8BAAC,eAAY,OAAO,OAAO,OAAO,QAAQ,QAAQ,MAAM,WAAW,CAAC,WAAW,UAAU,aAAa,CAAC,UAAU,YAAY,KAAK,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAG,GAClK;AAAA;AAAA,QACF;AAAA,QAED;AAAA,SACH;AAAA;AAAA,EAEJ;AAEF,MAAI,aAAa,UAAa,QAAS,QAAO;AAC9C,SACE,iCACG;AAAA;AAAA,IACD,oBAAC,UAAK,MAAK,UAAS,WAAU,WAC3B,oBACH;AAAA,KACF;AAEJ;AAaO,SAAS,WAAW,EAAE,OAAO,OAAO,QAAQ,UAAU,GAAG,MAAM,GAAoB;AACxF,QAAM,OAAO,MAAM,cAAc,SAAS,CAAC,MAAM,YAAY,MAAM,WAAW,MAAM;AACpF,SACE,oBAAC,UAAO,cAAY,OAAO,OAAO,OAAO,MAAa,GAAG,OACtD,iBAAO,OAAO,UACjB;AAEJ;","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}