orbital-ds 0.7.0 → 0.9.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 (109) hide show
  1. package/AGENTS.md +145 -80
  2. package/README.md +87 -73
  3. package/components.manifest.json +1326 -1267
  4. package/contract.json +226 -168
  5. package/dist/hooks/use-ds-messages.d.ts +36 -0
  6. package/dist/hooks/use-ds-messages.js +12 -0
  7. package/dist/hooks/use-ds-motion.d.ts +17 -0
  8. package/dist/hooks/use-ds-motion.js +50 -0
  9. package/dist/lib/i18n.d.ts +46 -0
  10. package/dist/lib/i18n.js +109 -0
  11. package/dist/lib/motion.d.ts +74 -0
  12. package/dist/lib/motion.js +97 -0
  13. package/dist/styles.css +876 -528
  14. package/dist/themes/friendly.css +362 -318
  15. package/dist/themes/friendly.meta.json +75 -14
  16. package/dist/themes/friendly.scoped.css +362 -318
  17. package/dist/themes/qratia.meta.json +42 -12
  18. package/dist/themes/tactile.css +575 -429
  19. package/dist/themes/tactile.fonts.css +3 -2
  20. package/dist/themes/tactile.guide.md +82 -49
  21. package/dist/themes/tactile.meta.json +175 -16
  22. package/dist/themes/tactile.scoped.css +575 -429
  23. package/dist/themes/twitter.css +354 -298
  24. package/dist/themes/twitter.meta.json +83 -61
  25. package/dist/themes/twitter.scoped.css +354 -298
  26. package/dist/themes/zyro.css +443 -389
  27. package/dist/themes/zyro.meta.json +67 -14
  28. package/dist/themes/zyro.scoped.css +443 -389
  29. package/dist/ui/accordion.js +5 -5
  30. package/dist/ui/alert-dialog.js +3 -3
  31. package/dist/ui/alert.d.ts +1 -1
  32. package/dist/ui/alert.js +9 -3
  33. package/dist/ui/attachment.d.ts +1 -1
  34. package/dist/ui/attachment.js +4 -4
  35. package/dist/ui/avatar.js +6 -6
  36. package/dist/ui/ayuda.js +3 -2
  37. package/dist/ui/badge.d.ts +1 -1
  38. package/dist/ui/badge.js +9 -3
  39. package/dist/ui/banner.d.ts +14 -0
  40. package/dist/ui/banner.js +88 -0
  41. package/dist/ui/breadcrumb.js +7 -3
  42. package/dist/ui/bubble.js +6 -6
  43. package/dist/ui/button-group.js +4 -4
  44. package/dist/ui/button.d.ts +1 -1
  45. package/dist/ui/button.js +5 -5
  46. package/dist/ui/calendar.js +33 -6
  47. package/dist/ui/card.js +4 -4
  48. package/dist/ui/carousel.js +15 -8
  49. package/dist/ui/chart.js +7 -3
  50. package/dist/ui/checkbox.js +1 -1
  51. package/dist/ui/combobox.js +7 -7
  52. package/dist/ui/command.js +13 -11
  53. package/dist/ui/context-menu.js +8 -8
  54. package/dist/ui/dialog.js +10 -6
  55. package/dist/ui/drawer.js +9 -9
  56. package/dist/ui/dropdown-menu.js +8 -8
  57. package/dist/ui/empty.js +3 -3
  58. package/dist/ui/field.js +2 -2
  59. package/dist/ui/hover-card.js +1 -1
  60. package/dist/ui/i18n-provider.d.ts +11 -0
  61. package/dist/ui/i18n-provider.js +18 -0
  62. package/dist/ui/icon-tile.d.ts +1 -1
  63. package/dist/ui/input-group.d.ts +1 -1
  64. package/dist/ui/input-group.js +11 -9
  65. package/dist/ui/input-otp.js +3 -3
  66. package/dist/ui/input.js +1 -1
  67. package/dist/ui/item.d.ts +1 -1
  68. package/dist/ui/item.js +3 -3
  69. package/dist/ui/kbd.js +1 -1
  70. package/dist/ui/label.js +1 -1
  71. package/dist/ui/marker.d.ts +1 -1
  72. package/dist/ui/marker.js +2 -2
  73. package/dist/ui/menubar.js +9 -9
  74. package/dist/ui/message-scroller.js +5 -2
  75. package/dist/ui/message.js +2 -2
  76. package/dist/ui/motion-provider.d.ts +11 -0
  77. package/dist/ui/motion-provider.js +16 -0
  78. package/dist/ui/native-select.js +4 -4
  79. package/dist/ui/navigation-menu.js +7 -6
  80. package/dist/ui/pagination.js +19 -11
  81. package/dist/ui/popover.js +2 -2
  82. package/dist/ui/progress.js +2 -2
  83. package/dist/ui/questionnaire.js +20 -15
  84. package/dist/ui/radio-group.js +2 -2
  85. package/dist/ui/resizable.js +2 -2
  86. package/dist/ui/scroll-area.js +3 -3
  87. package/dist/ui/select.js +6 -6
  88. package/dist/ui/separator.js +1 -1
  89. package/dist/ui/sheet.js +6 -4
  90. package/dist/ui/sidebar.js +42 -30
  91. package/dist/ui/skeleton.js +1 -1
  92. package/dist/ui/slider.js +6 -6
  93. package/dist/ui/sonner.js +25 -8
  94. package/dist/ui/spinner.js +4 -1
  95. package/dist/ui/switch.js +2 -2
  96. package/dist/ui/table.js +3 -3
  97. package/dist/ui/tabs.js +5 -5
  98. package/dist/ui/textarea.js +1 -1
  99. package/dist/ui/toast.js +15 -12
  100. package/dist/ui/toggle-group.js +2 -2
  101. package/dist/ui/toggle.js +6 -4
  102. package/dist/ui/tooltip.js +2 -2
  103. package/docs/CONTRACT.md +183 -153
  104. package/package.json +160 -142
  105. package/scripts/brand-core.mjs +153 -0
  106. package/scripts/doctor.mjs +128 -7
  107. package/scripts/i18n.mjs +111 -0
  108. package/scripts/init.mjs +294 -57
  109. package/scripts/setup.mjs +99 -0
@@ -1,429 +1,575 @@
1
- /*
2
- * TEMA tactile — interfaz táctil de papel y tinta, con rotulador.
3
- *
4
- * Dirección ORIGINAL (no copia ninguna referencia: toma un principio de cada una).
5
- * - Lo que se pulsa lleva TINTA: contorno de 2px y una arista inferior de 5px que
6
- * baja al pulsar, como una tecla. Las superficies llevan filete suave.
7
- * - Un ROTULADOR mostaza translúcido bajo los títulos.
8
- * - Papel cálido y tinta berenjena casi negra (nunca #000). Un acento vivo
9
- * (mostaza, con texto de tinta: contraste 10:1) y uno pequeño (pino).
10
- * - Formas: 8 · 12 · 14 · 16. Sin sombras difusas: la profundidad la dan las aristas.
11
- * - Titulares en Fraunces (serifa suave) y cuerpo en Figtree.
12
- *
13
- * Importar DESPUÉS de la estructura. Variables `--zw-*`: privadas de este tema.
14
- * Fuentes: `tactile.fonts.css`, lo primero del CSS de la app.
15
- */
16
-
17
- /* ── VARIABLES · PIEL CLARA («papel») ────────────────────────────────────── */
18
- :root:where([data-theme='tactile']) {
19
- --radius: 16px;
20
-
21
- --ds-font-sans: 'Figtree', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
22
- --ds-font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
23
- --ds-font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
24
-
25
- /* Lateral: iconos, raíl, logo y separadores (cada tema fija su forma y tamaño) */
26
- --ds-sidebar-icon: 1.5rem;
27
- --ds-sidebar-icon-stroke: 2.1;
28
- --ds-sidebar-rail-w: 5rem;
29
- --ds-sidebar-rail-item: 3rem;
30
- --ds-sidebar-logo: 2.5rem;
31
- --ds-sidebar-sep-inset: -0.5rem;
32
- --ds-heading-tracking: -0.01em;
33
-
34
- --background: #f6f0e3;
35
- --foreground: #2a2233;
36
-
37
- --card: #fffcf4;
38
- --card-foreground: #2a2233;
39
- --popover: #fffcf4;
40
- --popover-foreground: #2a2233;
41
-
42
- --primary: #f2b33d;
43
- --primary-foreground: #2a2233;
44
- --secondary: #ede3cd;
45
- --secondary-foreground: #2a2233;
46
- --muted: #ede3cd;
47
- --muted-foreground: rgba(42, 34, 51, 0.7);
48
- --accent: color-mix(in srgb, var(--primary) 30%, transparent);
49
- --accent-foreground: #2a2233;
50
- --destructive: #b53a22;
51
- --destructive-foreground: #fffcf4;
52
-
53
- --border: rgba(42, 34, 51, 0.14);
54
- --input: #2a2233;
55
- --ring: #17624f;
56
-
57
- --chart-1: #f2b33d;
58
- --chart-2: #17624f;
59
- --chart-3: #2f6fb0;
60
- --chart-4: #b53a22;
61
- --chart-5: #8b5a9e;
62
-
63
- --sidebar: #ede3cd;
64
- --sidebar-foreground: #2a2233;
65
- --sidebar-primary: #f2b33d;
66
- --sidebar-primary-foreground: #2a2233;
67
- --sidebar-accent: #fffcf4;
68
- --sidebar-accent-foreground: #2a2233;
69
- --sidebar-border: rgba(42, 34, 51, 0.26);
70
- --sidebar-ring: #17624f;
71
-
72
- --danger: #ae3821;
73
- --danger-soft: rgba(214, 69, 43, 0.13);
74
- --warning: #7a5200;
75
- --warning-soft: rgba(242, 179, 61, 0.3);
76
- --success: #17624f;
77
- --success-soft: rgba(23, 98, 79, 0.12);
78
- --info: #2a649e;
79
- --info-soft: rgba(47, 111, 176, 0.12);
80
- --neutral: rgba(42, 34, 51, 0.72);
81
- --neutral-soft: rgba(42, 34, 51, 0.08);
82
-
83
- --link: #17624f;
84
- --link-hover: #0f4538;
85
- --inset: #ede3cd;
86
- --inset-foreground: #2a2233;
87
- --brand: #f2b33d;
88
- --brand-bright: #f7c566;
89
-
90
- /* Formas */
91
- --ds-radius-sm: 8px;
92
- --ds-radius-md: 12px;
93
- --ds-radius-lg: 14px;
94
- --ds-radius-xl: 16px;
95
- --ds-radius-2xl: 20px;
96
- --ds-radius-control: 12px;
97
- --ds-radius-overlay: 18px;
98
-
99
- /* Sin sombras difusas: la profundidad la dan las aristas (ver la personalidad) */
100
- --ds-shadow-card: 0 0 #0000;
101
- --ds-shadow-card-hover: 0 0 #0000;
102
- --ds-shadow-control: 0 0 #0000;
103
- --ds-shadow-raised: 0 0 #0000;
104
- --ds-shadow-overlay: 0 8px 0 rgba(42, 34, 51, 0.12);
105
- --ds-shadow-popover: 0 6px 0 rgba(42, 34, 51, 0.12);
106
-
107
- /* Medidas: teclas generosas */
108
- --ds-control-h-sm: 2.25rem;
109
- --ds-control-h-md: 2.75rem;
110
- --ds-control-h-lg: 3.25rem;
111
- --ds-button-px-sm: 0.875rem;
112
- --ds-button-px-md: 1.125rem;
113
- --ds-button-px-lg: 1.5rem;
114
- --ds-field-px: 0.875rem;
115
- --ds-card-spacing: 1.25rem;
116
- --ds-card-spacing-sm: 1rem;
117
-
118
- /* Materiales: ninguno */
119
- --ds-card-backdrop: none;
120
- --ds-overlay-backdrop: none;
121
- --ds-field-backdrop: none;
122
- --ds-sidebar-backdrop: none;
123
- --ds-page-backdrop: none;
124
-
125
- /* Sidebar a ras de borde, papel más hondo, filas como teclas */
126
- --ds-sidebar-pad: 0px;
127
- --ds-sidebar-radius: 0px;
128
- --ds-sidebar-shadow: 0 0 #0000;
129
- --ds-sidebar-ring: 0px;
130
- --ds-sidebar-edge: 2px solid var(--sidebar-border);
131
- --ds-sidebar-item-radius: 14px;
132
- --ds-sidebar-item-h: 3rem;
133
-
134
- /* Baldosas de icono: grandes, tintadas y con relleno duotono suave */
135
- --ds-icon-tile-sm: 2.25rem;
136
- --ds-icon-tile-md: 3.5rem;
137
- --ds-icon-tile-lg: 4.5rem;
138
- --ds-icon-tile-radius: var(--ds-radius-xl);
139
- --ds-icon-tile-fill: 0.2;
140
-
141
- /* Privadas de tactile */
142
- --zw-outline: #2a2233;
143
- --zw-edge: rgba(42, 34, 51, 0.26);
144
- --zw-mark: color-mix(in srgb, var(--primary) 62%, transparent);
145
- }
146
-
147
- /* ── VARIABLES · PIEL OSCURA («noche») ───────────────────────────────────── */
148
- :where(:root[data-theme='tactile']).dark {
149
- --background: #1d1824;
150
- --foreground: #f4ebda;
151
-
152
- --card: #2c2636;
153
- --card-foreground: #f4ebda;
154
- --popover: #2c2636;
155
- --popover-foreground: #f4ebda;
156
-
157
- --primary: #f2b33d;
158
- --primary-foreground: #1d1824;
159
- --secondary: #25202e;
160
- --secondary-foreground: #f4ebda;
161
- --muted: #25202e;
162
- --muted-foreground: rgba(244, 235, 218, 0.72);
163
- --accent: color-mix(in srgb, var(--primary) 18%, transparent);
164
- --accent-foreground: #f7c566;
165
- --destructive: #ff8266;
166
- --destructive-foreground: #1d1824;
167
-
168
- --border: rgba(244, 235, 218, 0.14);
169
- --input: rgba(244, 235, 218, 0.92);
170
- --ring: #5cc9a8;
171
-
172
- --chart-1: #f2b33d;
173
- --chart-2: #5cc9a8;
174
- --chart-3: #7db3f0;
175
- --chart-4: #ff8266;
176
- --chart-5: #c79ad8;
177
-
178
- --sidebar: #25202e;
179
- --sidebar-foreground: #f4ebda;
180
- --sidebar-primary: #f2b33d;
181
- --sidebar-primary-foreground: #1d1824;
182
- --sidebar-accent: #2c2636;
183
- --sidebar-accent-foreground: #f4ebda;
184
- --sidebar-border: rgba(244, 235, 218, 0.26);
185
- --sidebar-ring: #5cc9a8;
186
-
187
- --danger: #ff8266;
188
- --danger-soft: rgba(255, 130, 102, 0.16);
189
- --warning: #f2b33d;
190
- --warning-soft: rgba(242, 179, 61, 0.18);
191
- --success: #5cc9a8;
192
- --success-soft: rgba(92, 201, 168, 0.16);
193
- --info: #7db3f0;
194
- --info-soft: rgba(125, 179, 240, 0.16);
195
- --neutral: rgba(244, 235, 218, 0.72);
196
- --neutral-soft: rgba(244, 235, 218, 0.1);
197
-
198
- --link: #5cc9a8;
199
- --link-hover: #8ee0c4;
200
- --inset: #25202e;
201
- --inset-foreground: #f4ebda;
202
- --brand: #f2b33d;
203
- --brand-bright: #f7c566;
204
-
205
- --ds-shadow-overlay: 0 8px 0 rgba(0, 0, 0, 0.4);
206
- --ds-shadow-popover: 0 6px 0 rgba(0, 0, 0, 0.4);
207
-
208
- --zw-outline: rgba(244, 235, 218, 0.92);
209
- --zw-edge: rgba(244, 235, 218, 0.26);
210
- --zw-mark: color-mix(in srgb, var(--primary) 45%, transparent);
211
- }
212
-
213
- /* ── PERSONALIDAD ────────────────────────────────────────────────────────────
214
- * Sin capa: gana a las utilidades de los componentes. Solo variables. No usa
215
- * box-shadow en los controles, así el anillo de foco sigue funcionando.
216
- */
217
- :root:where([data-theme='tactile']) {
218
- /* Teclas: contorno de tinta y arista inferior; al pulsar, se hunden */
219
- [data-slot='button'] {
220
- border: 2px solid var(--zw-outline);
221
- border-bottom-width: 5px;
222
- border-radius: 14px;
223
- font-weight: 700;
224
- transition:
225
- transform var(--ds-motion-fast) ease,
226
- border-bottom-width var(--ds-motion-fast) ease,
227
- background-color var(--ds-motion-base) ease;
228
- }
229
- [data-slot='button']:active:not(:disabled) {
230
- transform: translateY(3px);
231
- border-bottom-width: 2px;
232
- }
233
- [data-slot='button']:disabled {
234
- opacity: 0.45;
235
- }
236
- [data-slot='button'][data-variant='default']:hover:not(:disabled) {
237
- background-color: color-mix(in oklch, var(--primary) 78%, var(--card));
238
- }
239
- [data-slot='button'][data-variant='secondary'],
240
- [data-slot='button'][data-variant='outline'] {
241
- background: var(--card);
242
- color: var(--foreground);
243
- }
244
- [data-slot='button'][data-variant='outline'] {
245
- background: transparent;
246
- }
247
- [data-slot='button'][data-variant='secondary']:hover:not(:disabled),
248
- [data-slot='button'][data-variant='outline']:hover:not(:disabled) {
249
- background: var(--secondary);
250
- }
251
- [data-slot='button'][data-variant='ghost'] {
252
- border-color: transparent;
253
- border-bottom-width: 2px;
254
- }
255
- [data-slot='button'][data-variant='ghost']:hover:not(:disabled) {
256
- background: var(--secondary);
257
- }
258
- [data-slot='button'][data-variant='destructive'] {
259
- background: var(--destructive);
260
- color: var(--destructive-foreground);
261
- }
262
- [data-slot='button'][data-variant='link'] {
263
- border: 0;
264
- font-weight: 700;
265
- }
266
- [data-slot='button'][data-variant='link']:active:not(:disabled) {
267
- transform: none;
268
- }
269
-
270
- /* Superficies: filete suave y una arista inferior más marcada */
271
- [data-slot='card'] {
272
- border: 2px solid var(--border);
273
- border-bottom: 5px solid var(--zw-edge);
274
- box-shadow: none;
275
- }
276
-
277
- /* Campos: contorno de tinta */
278
- [data-slot='input'],
279
- [data-slot='textarea'],
280
- [data-slot='select-trigger'] {
281
- background: var(--card);
282
- border: 2px solid var(--input);
283
- }
284
-
285
- /* Etiquetas: esquina de 8px, no píldora */
286
- [data-slot='badge'] {
287
- border-radius: 8px;
288
- font-weight: 700;
289
- }
290
-
291
- /* Pestañas: teclas pequeñas; la activa, en mostaza */
292
- [data-slot='tabs-list'] {
293
- background: transparent;
294
- gap: 8px;
295
- }
296
- [data-slot='tabs-trigger'] {
297
- border: 2px solid var(--border);
298
- border-bottom-width: 4px;
299
- border-radius: 12px;
300
- font-weight: 700;
301
- background: transparent;
302
- }
303
- [data-slot='tabs-trigger'][data-active] {
304
- background: var(--primary);
305
- color: var(--primary-foreground);
306
- border-color: var(--zw-outline);
307
- }
308
-
309
- /* Interruptor, casilla y progreso, con tinta */
310
- [data-slot='switch'] {
311
- border: 2px solid var(--zw-outline);
312
- border-bottom-width: 4px;
313
- border-radius: 12px;
314
- }
315
- [data-slot='switch'][data-checked] {
316
- background: var(--primary);
317
- }
318
- [data-slot='switch-thumb'] {
319
- border-radius: 7px;
320
- background: var(--zw-outline);
321
- }
322
- [data-slot='checkbox'] {
323
- border: 2px solid var(--zw-outline);
324
- border-radius: 8px;
325
- }
326
- [data-slot='checkbox'][data-checked] {
327
- background: var(--primary);
328
- color: var(--primary-foreground);
329
- }
330
- [data-slot='progress'] {
331
- border: 2px solid var(--zw-outline);
332
- border-radius: 8px;
333
- background: var(--background);
334
- }
335
- [data-slot='progress-indicator'] {
336
- background: var(--primary);
337
- }
338
-
339
- /* Capas flotantes: contorno de tinta y arista inferior */
340
- [data-slot='dialog-content'],
341
- [data-slot='sheet-content'] {
342
- border: 2px solid var(--zw-outline);
343
- border-bottom-width: 6px;
344
- }
345
- [data-slot='popover-content'],
346
- [data-slot='dropdown-menu-content'],
347
- [data-slot='select-content'] {
348
- border: 2px solid var(--zw-outline);
349
- border-bottom-width: 4px;
350
- }
351
-
352
- /* Avisos con tinta */
353
- [data-slot='alert'] {
354
- border: 2px solid var(--zw-outline);
355
- border-radius: 14px;
356
- }
357
-
358
- /* Tablas: filetes de 2px */
359
- [data-slot='table-row'] {
360
- border-top: 2px solid var(--border);
361
- }
362
- [data-slot='table-head'] {
363
- text-transform: uppercase;
364
- font-size: 0.75rem;
365
- letter-spacing: 0.08em;
366
- font-weight: 700;
367
- color: var(--muted-foreground);
368
- }
369
-
370
- /* Teclas del teclado */
371
- [data-slot='kbd'] {
372
- border: 2px solid var(--zw-outline);
373
- border-bottom-width: 4px;
374
- border-radius: 8px;
375
- background: var(--card);
376
- font-weight: 700;
377
- }
378
-
379
- /* ROTULADOR: franja translúcida bajo el título (la mitad inferior de la letra) */
380
- [data-slot='card-title'],
381
- [data-slot='dialog-title'],
382
- [data-slot='sheet-title'],
383
- header h1 {
384
- width: fit-content;
385
- max-width: 100%;
386
- background: linear-gradient(transparent 56%, var(--zw-mark) 56%);
387
- padding-inline: 0.14em;
388
- margin-inline: -0.14em;
389
- -webkit-box-decoration-break: clone;
390
- box-decoration-break: clone;
391
- }
392
-
393
- /* Sidebar: filas como teclas */
394
- [data-sidebar='menu-button'] {
395
- border: 2px solid transparent;
396
- border-radius: 14px;
397
- font-weight: 600;
398
- font-size: 1rem;
399
- }
400
- /* Señalada: la tecla se asoma (papel de tarjeta, contorno de tinta y arista); pulsada, se hunde */
401
- [data-sidebar='menu-button']:hover:not([data-active='true']) {
402
- background: var(--card);
403
- border-color: var(--zw-outline);
404
- border-bottom-width: 4px;
405
- }
406
- [data-sidebar='menu-button']:active:not([data-active='true']) {
407
- border-bottom-width: 2px;
408
- transform: translateY(2px);
409
- }
410
- /* Activa: la tecla pulsada y rellena con el color principal */
411
- [data-sidebar='menu-button'][data-active='true'] {
412
- background: var(--primary);
413
- color: var(--primary-foreground);
414
- border-color: var(--zw-outline);
415
- border-bottom-width: 5px;
416
- }
417
- /* Tooltips: etiqueta de tinta con arista inferior, como una tecla invertida */
418
- [data-slot='tooltip-content'] {
419
- background: var(--foreground);
420
- color: var(--background);
421
- border-radius: 12px;
422
- border-bottom: 4px solid var(--zw-edge);
423
- font-weight: 700;
424
- }
425
- /* Sin flecha: un rombo de tinta tapaba la primera letra de la etiqueta */
426
- [data-slot='tooltip-arrow'] {
427
- display: none;
428
- }
429
- }
1
+ /*
2
+ * TEMA tactile — interfaz táctil de papel y tinta, con rotulador.
3
+ *
4
+ * Dirección ORIGINAL (no copia ninguna referencia: toma un principio de cada una).
5
+ * - Lo que se pulsa lleva TINTA: contorno y una arista inferior que baja al pulsar,
6
+ * como una tecla. Las superficies llevan filete suave.
7
+ * - Un ROTULADOR translúcido (del color principal) bajo los títulos.
8
+ * - Papel cálido y tinta berenjena casi negra (nunca #000). Un acento vivo
9
+ * (mostaza, con texto de tinta: contraste 10:1) y uno pequeño (pino: foco y enlace).
10
+ * - Formas: 8 · 12 · 14 · 16. Sin sombras difusas: la profundidad la dan las aristas.
11
+ * - Titulares en Fraunces (serifa suave, ejes SOFT y WONK) y cuerpo en Figtree.
12
+ *
13
+ * TODO es variable: la personalidad no escribe ni una medida, color, peso ni opacidad
14
+ * (lo exige `pnpm check:ds`: este tema es `conformance: strict`). Para ajustarlo desde
15
+ * una app, cambia las variables en su brand.css: `--ds-key-*`, `--ds-marker*`,
16
+ * `--ds-rule-w`, `--ds-title-weight`, `--ds-display-variation`…
17
+ *
18
+ * Marca: lateral, `--brand` y la primera serie de gráficas DERIVAN de `--primary`.
19
+ * El foco (`--ring`) y el enlace son pino a propósito: un foco mostaza sobre papel no
20
+ * llega a 3:1. Si cambias `--primary`, revisa `--primary-foreground`, `--ring` y `--link`
21
+ * (o usa `pnpm exec orbital-ds-init`).
22
+ *
23
+ * Importar DESPUÉS de la estructura. Fuentes: `tactile.fonts.css`, lo primero del CSS.
24
+ * Las antiguas `--zw-outline|edge|mark` siguen funcionando como alternativa, pero están
25
+ * obsoletas: usa `--ds-key-outline`, `--ds-key-edge` y `--ds-marker`.
26
+ */
27
+
28
+ /* ── VARIABLES · PIEL CLARA («papel») ────────────────────────────────────── */
29
+ :root:where([data-theme='tactile']) {
30
+ --radius: 16px;
31
+
32
+ /* Tipografía: Fraunces suave y con sus letras «wonky» en titulares; Figtree en el cuerpo */
33
+ --ds-font-sans: 'Figtree', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
34
+ --ds-font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
35
+ --ds-font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
36
+ --ds-display-variation: 'SOFT' 50, 'WONK' 1;
37
+ --ds-heading-tracking: -0.01em;
38
+ --ds-heading-weight: 700;
39
+ --ds-title-weight: 650;
40
+ --ds-title-leading: 1.25;
41
+ --ds-label-tracking: 0.08em;
42
+ --ds-strong-weight: 700;
43
+ --ds-nav-weight: 600;
44
+
45
+ /* Escala: cuerpo de 15px para teclas de 44px (la de 14px quedaba pequeña) */
46
+ --ds-text-xs: 0.8125rem;
47
+ --ds-leading-xs: 1.3846;
48
+ --ds-text-sm: 0.9375rem;
49
+ --ds-leading-sm: 1.4667;
50
+
51
+ /* Lateral: iconos, raíl, logo y separadores (cada tema fija su forma y tamaño) */
52
+ --ds-sidebar-icon: 1.5rem;
53
+ --ds-sidebar-icon-stroke: 2.1;
54
+ --ds-sidebar-rail-w: 5rem;
55
+ --ds-sidebar-rail-item: 3rem;
56
+ --ds-sidebar-logo: 2.5rem;
57
+ --ds-sidebar-sep-inset: -0.5rem;
58
+
59
+ --background: #f6f0e3;
60
+ --foreground: #2a2233;
61
+
62
+ --card: #fffcf4;
63
+ --card-foreground: var(--foreground);
64
+ --popover: var(--card);
65
+ --popover-foreground: var(--foreground);
66
+
67
+ --primary: #f2b33d;
68
+ --primary-foreground: #2a2233;
69
+ --secondary: #ede3cd;
70
+ --secondary-foreground: var(--foreground);
71
+ --muted: var(--secondary);
72
+ --muted-foreground: rgba(42, 34, 51, 0.7);
73
+ --accent: color-mix(in srgb, var(--primary) 30%, transparent);
74
+ --accent-foreground: var(--foreground);
75
+ --destructive: #b53a22;
76
+ --destructive-foreground: var(--card);
77
+
78
+ --border: rgba(42, 34, 51, 0.14);
79
+ --input: var(--foreground);
80
+ --ring: #17624f;
81
+
82
+ --chart-1: var(--primary);
83
+ --chart-2: #17624f;
84
+ --chart-3: #2f6fb0;
85
+ --chart-4: #b53a22;
86
+ --chart-5: #8b5a9e;
87
+
88
+ --sidebar: var(--secondary);
89
+ --sidebar-foreground: var(--foreground);
90
+ --sidebar-primary: var(--primary);
91
+ --sidebar-primary-foreground: var(--primary-foreground);
92
+ --sidebar-accent: var(--card);
93
+ --sidebar-accent-foreground: var(--foreground);
94
+ --sidebar-border: rgba(42, 34, 51, 0.26);
95
+ --sidebar-ring: var(--ring);
96
+
97
+ --danger: #ae3821;
98
+ --danger-soft: rgba(214, 69, 43, 0.13);
99
+ --warning: #7a5200;
100
+ --warning-soft: rgba(242, 179, 61, 0.3);
101
+ --success: #17624f;
102
+ --success-soft: rgba(23, 98, 79, 0.12);
103
+ --info: #2a649e;
104
+ --info-soft: rgba(47, 111, 176, 0.12);
105
+ --neutral: rgba(42, 34, 51, 0.72);
106
+ --neutral-soft: rgba(42, 34, 51, 0.08);
107
+
108
+ --link: #17624f;
109
+ --link-hover: #0f4538;
110
+ --inset: var(--secondary);
111
+ --inset-foreground: var(--foreground);
112
+ --brand: var(--primary);
113
+ --brand-bright: color-mix(in oklch, var(--primary), white 25%);
114
+
115
+ /* Formas */
116
+ --ds-radius-sm: 8px;
117
+ --ds-radius-md: 12px;
118
+ --ds-radius-lg: 14px;
119
+ --ds-radius-xl: 16px;
120
+ --ds-radius-2xl: 20px;
121
+ --ds-radius-control: 12px;
122
+ --ds-radius-overlay: 18px;
123
+
124
+ /* Sin sombras difusas: la profundidad la dan las aristas (ver la personalidad) */
125
+ --ds-shadow-card: 0 0 #0000;
126
+ --ds-shadow-card-hover: 0 0 #0000;
127
+ --ds-shadow-control: 0 0 #0000;
128
+ --ds-shadow-raised: 0 0 #0000;
129
+ --ds-shadow-overlay: 0 8px 0 rgba(42, 34, 51, 0.12);
130
+ --ds-shadow-popover: 0 6px 0 rgba(42, 34, 51, 0.12);
131
+
132
+ /* Medidas: teclas generosas */
133
+ --ds-control-h-sm: 2.25rem;
134
+ --ds-control-h-md: 2.75rem;
135
+ --ds-control-h-lg: 3.25rem;
136
+ --ds-button-px-sm: 0.875rem;
137
+ --ds-button-px-md: 1.125rem;
138
+ --ds-button-px-lg: 1.5rem;
139
+ --ds-field-px: 0.875rem;
140
+ --ds-card-spacing: 1.25rem;
141
+ --ds-card-spacing-sm: 1rem;
142
+ --ds-tabs-gap: 0.5rem;
143
+
144
+ /* Movimiento: seco y rápido, como una tecla; las piezas que aparecen rebotan un poco */
145
+ --ds-motion-fast: 80ms;
146
+ --ds-motion-base: 160ms;
147
+ --ds-motion-slow: 240ms;
148
+ --ds-ease-standard: cubic-bezier(0.2, 0, 0, 1);
149
+ --ds-ease-enter: cubic-bezier(0.34, 1.4, 0.64, 1);
150
+ --ds-ease-exit: cubic-bezier(0.4, 0, 1, 1);
151
+ --ds-motion-distance: 4px;
152
+ --ds-motion-scale: 0.98;
153
+ --ds-motion-blur: 0px;
154
+ --ds-spring-bounce: 0.25;
155
+ --ds-motion-stagger: 30ms;
156
+ --ds-motion-press-scale: 1;
157
+
158
+ /* Materiales: ninguno */
159
+ --ds-card-backdrop: none;
160
+ --ds-overlay-backdrop: none;
161
+ --ds-field-backdrop: none;
162
+ --ds-sidebar-backdrop: none;
163
+ --ds-page-backdrop: none;
164
+
165
+ /* Sidebar a ras de borde, papel más hondo, filas como teclas */
166
+ --ds-sidebar-pad: 0px;
167
+ --ds-sidebar-radius: 0px;
168
+ --ds-sidebar-shadow: 0 0 #0000;
169
+ --ds-sidebar-ring: 0px;
170
+ --ds-sidebar-edge: var(--ds-rule-w) solid var(--sidebar-border);
171
+ --ds-sidebar-item-radius: var(--ds-key-radius);
172
+ --ds-sidebar-item-h: 3rem;
173
+
174
+ /* Baldosas de icono: grandes, tintadas y con relleno duotono suave */
175
+ --ds-icon-tile-sm: 2.25rem;
176
+ --ds-icon-tile-md: 3.5rem;
177
+ --ds-icon-tile-lg: 4.5rem;
178
+ --ds-icon-tile-radius: var(--ds-radius-xl);
179
+ --ds-icon-tile-fill: 0.2;
180
+
181
+ /* GESTO · tecla (todo lo pulsable) y rotulador (títulos). Apaga el rotulador con
182
+ * --ds-marker: transparent; aplana las teclas con --ds-key-edge-w: var(--ds-key-border). */
183
+ --ds-key-outline: var(--zw-outline, var(--foreground)); /* contorno (--zw-outline, obsoleta) */
184
+ --ds-key-edge: var(--zw-edge, rgba(42, 34, 51, 0.26)); /* arista de superficies (--zw-edge, obsoleta) */
185
+ --ds-key-border: 2px;
186
+ --ds-key-edge-w: 5px;
187
+ --ds-key-edge-w-sm: 4px;
188
+ --ds-key-edge-w-pressed: 2px;
189
+ --ds-key-press: 3px;
190
+ --ds-key-press-sm: 2px;
191
+ --ds-key-radius: var(--ds-radius-lg);
192
+ --ds-key-radius-sm: var(--ds-radius-control);
193
+ --ds-key-weight: 700;
194
+ --ds-key-disabled-opacity: 0.45;
195
+ --ds-rule-w: 2px;
196
+ --ds-overlay-edge-w: 6px;
197
+ --ds-marker: var(--zw-mark, color-mix(in srgb, var(--primary) 62%, transparent)); /* (--zw-mark, obsoleta) */
198
+ --ds-marker-thickness: 0.45em;
199
+ --ds-marker-offset: -0.32em;
200
+ }
201
+
202
+ /* ── VARIABLES · PIEL OSCURA («noche») ───────────────────────────────────────
203
+ * Las derivadas (`var(--primary)`…) se repiten aquí: una variable se resuelve donde
204
+ * se declara, y si `.dark` va en un descendiente heredaría el valor claro.
205
+ */
206
+ :where(:root[data-theme='tactile']).dark {
207
+ --background: #1d1824;
208
+ --foreground: #f4ebda;
209
+
210
+ --card: #2c2636;
211
+ --card-foreground: var(--foreground);
212
+ --popover: var(--card);
213
+ --popover-foreground: var(--foreground);
214
+
215
+ --primary: #f2b33d;
216
+ --primary-foreground: #1d1824;
217
+ --secondary: #25202e;
218
+ --secondary-foreground: var(--foreground);
219
+ --muted: var(--secondary);
220
+ --muted-foreground: rgba(244, 235, 218, 0.72);
221
+ --accent: color-mix(in srgb, var(--primary) 18%, transparent);
222
+ --accent-foreground: var(--brand-bright);
223
+ --destructive: #ff8266;
224
+ --destructive-foreground: var(--background);
225
+
226
+ --border: rgba(244, 235, 218, 0.14);
227
+ --input: rgba(244, 235, 218, 0.92);
228
+ --ring: #5cc9a8;
229
+
230
+ --chart-1: var(--primary);
231
+ --chart-2: #5cc9a8;
232
+ --chart-3: #7db3f0;
233
+ --chart-4: #ff8266;
234
+ --chart-5: #c79ad8;
235
+
236
+ --sidebar: var(--secondary);
237
+ --sidebar-foreground: var(--foreground);
238
+ --sidebar-primary: var(--primary);
239
+ --sidebar-primary-foreground: var(--primary-foreground);
240
+ --sidebar-accent: var(--card);
241
+ --sidebar-accent-foreground: var(--foreground);
242
+ --sidebar-border: rgba(244, 235, 218, 0.26);
243
+ --sidebar-ring: var(--ring);
244
+
245
+ --danger: #ff8266;
246
+ --danger-soft: rgba(255, 130, 102, 0.16);
247
+ --warning: #f2b33d;
248
+ --warning-soft: rgba(242, 179, 61, 0.18);
249
+ --success: #5cc9a8;
250
+ --success-soft: rgba(92, 201, 168, 0.16);
251
+ --info: #7db3f0;
252
+ --info-soft: rgba(125, 179, 240, 0.16);
253
+ --neutral: rgba(244, 235, 218, 0.72);
254
+ --neutral-soft: rgba(244, 235, 218, 0.1);
255
+
256
+ --link: #5cc9a8;
257
+ --link-hover: #8ee0c4;
258
+ --inset: var(--secondary);
259
+ --inset-foreground: var(--foreground);
260
+ --brand: var(--primary);
261
+ --brand-bright: color-mix(in oklch, var(--primary), white 25%);
262
+
263
+ --ds-shadow-overlay: 0 8px 0 rgba(0, 0, 0, 0.4);
264
+ --ds-shadow-popover: 0 6px 0 rgba(0, 0, 0, 0.4);
265
+
266
+ --ds-key-outline: var(--zw-outline, var(--input));
267
+ --ds-key-edge: var(--zw-edge, rgba(244, 235, 218, 0.26));
268
+ --ds-marker: var(--zw-mark, color-mix(in srgb, var(--primary) 45%, transparent));
269
+ }
270
+
271
+ /* ── PERSONALIDAD ────────────────────────────────────────────────────────────
272
+ * Sin capa: gana a las utilidades de los componentes. SOLO variables (lo comprueba
273
+ * el doctor). No usa box-shadow en los controles, así el anillo de foco sigue
274
+ * funcionando. Familias completas: si una pieza lleva el gesto, sus hermanas también.
275
+ */
276
+ :root:where([data-theme='tactile']) {
277
+ /* ── TECLAS: contorno de tinta y arista inferior; al pulsar, se hunden ── */
278
+ [data-slot='button'] {
279
+ border: var(--ds-key-border) solid var(--ds-key-outline);
280
+ border-bottom-width: var(--ds-key-edge-w);
281
+ border-radius: var(--ds-key-radius);
282
+ font-weight: var(--ds-key-weight);
283
+ transition:
284
+ transform var(--ds-motion-fast) ease,
285
+ border-bottom-width var(--ds-motion-fast) ease,
286
+ background-color var(--ds-motion-base) ease;
287
+ }
288
+ [data-slot='button']:active:not(:disabled) {
289
+ transform: translateY(var(--ds-key-press));
290
+ border-bottom-width: var(--ds-key-edge-w-pressed);
291
+ }
292
+ [data-slot='button']:disabled {
293
+ opacity: var(--ds-key-disabled-opacity);
294
+ }
295
+ /* Teclas pequeñas, y las que viven dentro de piezas densas: arista menor */
296
+ [data-slot='button']:is([data-size='xs'], [data-size='sm'], [data-size='icon-xs'], [data-size='icon-sm']),
297
+ :is([data-slot='calendar'], [data-slot='pagination'], [data-slot='input-group'], [data-slot='button-group'])
298
+ [data-slot='button'] {
299
+ border-bottom-width: var(--ds-key-edge-w-sm);
300
+ }
301
+ [data-slot='button']:is([data-size='xs'], [data-size='sm'], [data-size='icon-xs'], [data-size='icon-sm']):active:not(:disabled),
302
+ :is([data-slot='calendar'], [data-slot='pagination'], [data-slot='input-group'], [data-slot='button-group'])
303
+ [data-slot='button']:active:not(:disabled) {
304
+ transform: translateY(var(--ds-key-press-sm));
305
+ border-bottom-width: var(--ds-key-edge-w-pressed);
306
+ }
307
+ [data-slot='button'][data-variant='default']:hover:not(:disabled) {
308
+ background-color: color-mix(in oklch, var(--primary) 78%, var(--card));
309
+ }
310
+ [data-slot='button'][data-variant='secondary'],
311
+ [data-slot='button'][data-variant='outline'] {
312
+ background: var(--card);
313
+ color: var(--foreground);
314
+ }
315
+ [data-slot='button'][data-variant='outline'] {
316
+ background: transparent;
317
+ }
318
+ [data-slot='button'][data-variant='secondary']:hover:not(:disabled),
319
+ [data-slot='button'][data-variant='outline']:hover:not(:disabled) {
320
+ background: var(--secondary);
321
+ }
322
+ [data-slot='button'][data-variant='ghost'] {
323
+ border-color: transparent;
324
+ border-bottom-width: var(--ds-key-edge-w-pressed);
325
+ }
326
+ [data-slot='button'][data-variant='ghost']:hover:not(:disabled) {
327
+ background: var(--secondary);
328
+ }
329
+ [data-slot='button'][data-variant='destructive'] {
330
+ background: var(--destructive);
331
+ color: var(--destructive-foreground);
332
+ }
333
+ [data-slot='button'][data-variant='link'] {
334
+ border: 0;
335
+ font-weight: var(--ds-key-weight);
336
+ }
337
+ [data-slot='button'][data-variant='link']:active:not(:disabled) {
338
+ transform: none;
339
+ }
340
+
341
+ /* ── SUPERFICIES: filete suave y una arista inferior más marcada ── */
342
+ [data-slot='card'] {
343
+ border: var(--ds-rule-w) solid var(--border);
344
+ border-bottom: var(--ds-key-edge-w) solid var(--ds-key-edge);
345
+ box-shadow: none;
346
+ }
347
+
348
+ /* ── CAMPOS (familia «field»): contorno de tinta y papel de tarjeta ── */
349
+ [data-slot='input'],
350
+ [data-slot='textarea'],
351
+ [data-slot='select-trigger'],
352
+ [data-slot='native-select'],
353
+ [data-slot='input-group'] {
354
+ background: var(--card);
355
+ border: var(--ds-key-border) solid var(--input);
356
+ }
357
+ /* El OTP es una fila de casillas pegadas: grosor de tinta en sus bordes, sin duplicarlos */
358
+ [data-slot='input-otp-slot'] {
359
+ background: var(--card);
360
+ border-color: var(--input);
361
+ border-top-width: var(--ds-key-border);
362
+ border-bottom-width: var(--ds-key-border);
363
+ border-right-width: var(--ds-key-border);
364
+ }
365
+ [data-slot='input-otp-slot']:first-child {
366
+ border-left-width: var(--ds-key-border);
367
+ }
368
+
369
+ /* ── ELECCIÓN (familia «choice»): casilla y radio con tinta; marcados, en mostaza ── */
370
+ [data-slot='checkbox'],
371
+ [data-slot='radio-group-item'] {
372
+ border: var(--ds-key-border) solid var(--ds-key-outline);
373
+ }
374
+ [data-slot='checkbox'] {
375
+ border-radius: var(--ds-radius-sm);
376
+ }
377
+ [data-slot='checkbox'][data-checked],
378
+ [data-slot='radio-group-item'][data-checked] {
379
+ background: var(--primary);
380
+ color: var(--primary-foreground);
381
+ }
382
+
383
+ /* Etiquetas: esquina pequeña, no píldora */
384
+ [data-slot='badge'] {
385
+ border-radius: var(--ds-radius-sm);
386
+ font-weight: var(--ds-key-weight);
387
+ }
388
+
389
+ /* ── CONMUTADORES (familia «toggle»): teclas pequeñas; la activa, en mostaza ── */
390
+ [data-slot='tabs-list'] {
391
+ background: transparent;
392
+ gap: var(--ds-tabs-gap);
393
+ }
394
+ [data-slot='tabs-trigger'],
395
+ [data-slot='toggle'],
396
+ [data-slot='toggle-group-item'] {
397
+ border: var(--ds-key-border) solid var(--border);
398
+ border-bottom-width: var(--ds-key-edge-w-sm);
399
+ border-radius: var(--ds-key-radius-sm);
400
+ font-weight: var(--ds-key-weight);
401
+ background: transparent;
402
+ }
403
+ [data-slot='toggle']:active,
404
+ [data-slot='toggle-group-item']:active {
405
+ transform: translateY(var(--ds-key-press-sm));
406
+ border-bottom-width: var(--ds-key-edge-w-pressed);
407
+ }
408
+ [data-slot='tabs-trigger'][data-active],
409
+ [data-slot='toggle'][aria-pressed='true'],
410
+ [data-slot='toggle-group-item'][aria-pressed='true'] {
411
+ background: var(--primary);
412
+ color: var(--primary-foreground);
413
+ border-color: var(--ds-key-outline);
414
+ }
415
+
416
+ /* Interruptor, con tinta */
417
+ [data-slot='switch'] {
418
+ border: var(--ds-key-border) solid var(--ds-key-outline);
419
+ border-bottom-width: var(--ds-key-edge-w-sm);
420
+ border-radius: var(--ds-key-radius-sm);
421
+ }
422
+ [data-slot='switch'][data-checked] {
423
+ background: var(--primary);
424
+ }
425
+ [data-slot='switch-thumb'] {
426
+ border-radius: var(--ds-radius-sm);
427
+ background: var(--ds-key-outline);
428
+ }
429
+
430
+ /* ── PISTAS (familia «track»): progreso y deslizador, con tinta ── */
431
+ [data-slot='progress'],
432
+ [data-slot='slider-track'] {
433
+ border: var(--ds-key-border) solid var(--ds-key-outline);
434
+ border-radius: var(--ds-radius-sm);
435
+ background: var(--background);
436
+ }
437
+ [data-slot='progress-indicator'],
438
+ [data-slot='slider-range'] {
439
+ background: var(--primary);
440
+ }
441
+ [data-slot='slider-thumb'] {
442
+ border: var(--ds-key-border) solid var(--ds-key-outline);
443
+ border-bottom-width: var(--ds-key-edge-w-sm);
444
+ border-radius: var(--ds-radius-sm);
445
+ background: var(--card);
446
+ box-shadow: none;
447
+ }
448
+
449
+ /* ── CAPAS: contorno de tinta y arista inferior ── */
450
+ [data-slot='dialog-content'],
451
+ [data-slot='sheet-content'],
452
+ [data-slot='alert-dialog-content'],
453
+ [data-slot='drawer-popup'] {
454
+ border: var(--ds-key-border) solid var(--ds-key-outline);
455
+ border-bottom-width: var(--ds-overlay-edge-w);
456
+ }
457
+ [data-slot='popover-content'],
458
+ [data-slot='dropdown-menu-content'],
459
+ [data-slot='dropdown-menu-sub-content'],
460
+ [data-slot='select-content'],
461
+ [data-slot='context-menu-content'],
462
+ [data-slot='context-menu-sub-content'],
463
+ [data-slot='menubar-content'],
464
+ [data-slot='menubar-sub-content'],
465
+ [data-slot='hover-card-content'],
466
+ [data-slot='combobox-content'],
467
+ [data-slot='navigation-menu-popup'] {
468
+ border: var(--ds-key-border) solid var(--ds-key-outline);
469
+ border-bottom-width: var(--ds-key-edge-w-sm);
470
+ }
471
+
472
+ /* ── AVISOS (familia «notice»): con tinta. El banner va a lo ancho: solo filete inferior ── */
473
+ [data-slot='alert'],
474
+ [data-slot='toast'] {
475
+ border: var(--ds-key-border) solid var(--ds-key-outline);
476
+ border-radius: var(--ds-key-radius);
477
+ }
478
+ [data-slot='toast'],
479
+ [data-sonner-toast] {
480
+ border-bottom-width: var(--ds-key-edge-w-sm);
481
+ }
482
+ [data-sonner-toast] {
483
+ border: var(--ds-key-border) solid var(--ds-key-outline);
484
+ border-bottom-width: var(--ds-key-edge-w-sm);
485
+ }
486
+ [data-slot='banner'] {
487
+ border-bottom: var(--ds-rule-w) solid var(--ds-key-outline);
488
+ font-weight: var(--ds-nav-weight);
489
+ }
490
+
491
+ /* Acordeón: filetes de papel entre secciones */
492
+ [data-slot='accordion-item'] {
493
+ border-bottom: var(--ds-rule-w) solid var(--border);
494
+ }
495
+ [data-slot='accordion-trigger'] {
496
+ font-weight: var(--ds-key-weight);
497
+ }
498
+
499
+ /* Tablas: filetes y cabecera en versalitas */
500
+ [data-slot='table-row'] {
501
+ border-top: var(--ds-rule-w) solid var(--border);
502
+ }
503
+ [data-slot='table-head'] {
504
+ text-transform: uppercase;
505
+ font-size: var(--ds-text-xs);
506
+ letter-spacing: var(--ds-label-tracking);
507
+ font-weight: var(--ds-key-weight);
508
+ color: var(--muted-foreground);
509
+ }
510
+
511
+ /* Teclas del teclado */
512
+ [data-slot='kbd'] {
513
+ border: var(--ds-key-border) solid var(--ds-key-outline);
514
+ border-bottom-width: var(--ds-key-edge-w-sm);
515
+ border-radius: var(--ds-radius-sm);
516
+ background: var(--card);
517
+ font-weight: var(--ds-key-weight);
518
+ }
519
+
520
+ /* ── TÍTULOS (familia «title»): peso, interlineado y tracking propios del tema ── */
521
+ h1,
522
+ h2,
523
+ h3 {
524
+ font-weight: var(--ds-heading-weight);
525
+ }
526
+ [data-slot='card-title'],
527
+ [data-slot='dialog-title'],
528
+ [data-slot='sheet-title'],
529
+ [data-slot='alert-dialog-title'],
530
+ [data-slot='drawer-title'],
531
+ [data-slot='empty-title'] {
532
+ font-weight: var(--ds-title-weight);
533
+ line-height: var(--ds-title-leading);
534
+ letter-spacing: var(--ds-heading-tracking);
535
+ }
536
+
537
+ /* El ROTULADOR lo dibuja la estructura (gesto común): aquí solo se le da color arriba. */
538
+
539
+ /* ── LATERAL: filas como teclas ── */
540
+ [data-sidebar='menu-button'] {
541
+ border: var(--ds-key-border) solid transparent;
542
+ border-radius: var(--ds-sidebar-item-radius);
543
+ font-weight: var(--ds-nav-weight);
544
+ font-size: var(--ds-text-base);
545
+ }
546
+ /* Señalada: la tecla se asoma (papel de tarjeta, contorno de tinta y arista); pulsada, se hunde */
547
+ [data-sidebar='menu-button']:hover:not([data-active='true']) {
548
+ background: var(--card);
549
+ border-color: var(--ds-key-outline);
550
+ border-bottom-width: var(--ds-key-edge-w-sm);
551
+ }
552
+ [data-sidebar='menu-button']:active:not([data-active='true']) {
553
+ border-bottom-width: var(--ds-key-edge-w-pressed);
554
+ transform: translateY(var(--ds-key-press-sm));
555
+ }
556
+ /* Activa: la tecla pulsada y rellena con el color principal */
557
+ [data-sidebar='menu-button'][data-active='true'] {
558
+ background: var(--primary);
559
+ color: var(--primary-foreground);
560
+ border-color: var(--ds-key-outline);
561
+ border-bottom-width: var(--ds-key-edge-w);
562
+ }
563
+ /* Tooltips: etiqueta de tinta con arista inferior, como una tecla invertida */
564
+ [data-slot='tooltip-content'] {
565
+ background: var(--foreground);
566
+ color: var(--background);
567
+ border-radius: var(--ds-key-radius-sm);
568
+ border-bottom: var(--ds-key-edge-w-sm) solid var(--ds-key-edge);
569
+ font-weight: var(--ds-key-weight);
570
+ }
571
+ /* Sin flecha: un rombo de tinta tapaba la primera letra de la etiqueta */
572
+ [data-slot='tooltip-arrow'] {
573
+ display: none;
574
+ }
575
+ }