@higinio/design-mcp 0.1.1 → 0.2.1

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.
@@ -0,0 +1,1588 @@
1
+ /* ============================================================
2
+ Salvia Serena — Design Tokens v1.0
3
+ Sistema de diseño de Higinio Sosa · light-first
4
+ Fuente de verdad: DESIGN-salvia-serena.md
5
+ Uso: importar ANTES de cualquier estilo propio.
6
+ Los componentes consumen SOLO aliases semánticos, nunca hex.
7
+ ============================================================ */
8
+
9
+ @import url("https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,600;0,700;1,600&family=Nunito+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Source+Code+Pro:wght@400;500&display=swap");
10
+
11
+ :root {
12
+ /* == Primitivos: primario (Salvia) == */
13
+ --primary-50: #e2eadf; --primary-100: #d4e0d1; --primary-200: #b8cbb7;
14
+ --primary-300: #97b09e; --primary-400: #73907c; --primary-500: #4f6b58;
15
+ --primary-600: #435c4b; --primary-700: #384d3f; --primary-800: #304236;
16
+ --primary-900: #2c3630;
17
+
18
+ /* == Primitivos: neutrales (Lino) == */
19
+ --neutral-0: #fbfaf6; --neutral-50: #f3f2ec; --neutral-100: #eae9e1;
20
+ --neutral-200: #dfe0d6; --neutral-300: #b9beb4; --neutral-400: #858d84;
21
+ --neutral-500: #5c675f; --neutral-600: #47524b; --neutral-700: #38423b;
22
+ --neutral-800: #2c3630; --neutral-900: #1f2622;
23
+
24
+ /* == Primitivos: semánticos (ramp de 3: sólido / fondo / texto AA) ==
25
+ El éxito es verde azulado, lejos del acento salvia: el acento nunca comunica éxito. */
26
+ --success-500: #2f7d6a; --success-100: #dcefe8; --success-text: #22604f;
27
+ --warning-500: #b8862f; --warning-100: #f6ecd8; --warning-text: #7e5a17;
28
+ --danger-500: #b5523f; --danger-100: #f6e4df; --danger-text: #8a3a2b;
29
+ --info-500: #5b7891; --info-100: #e3eaf0; --info-text: #3f5a70;
30
+
31
+ /* == Aliases semánticos (los componentes consumen SOLO esto) == */
32
+ --bg: var(--neutral-50);
33
+ --surface: var(--neutral-0);
34
+ --surface-alt: var(--neutral-100);
35
+ --border: var(--neutral-200);
36
+ --border-strong: var(--neutral-400);
37
+ --text-primary: var(--neutral-800);
38
+ --text-secondary: var(--neutral-600);
39
+ --text-muted: var(--neutral-500);
40
+ --text-disabled: var(--neutral-400);
41
+ --text-on-primary: #ffffff;
42
+ --text-on-primary-solid: var(--primary-700);
43
+ --accent: var(--primary-500);
44
+ --accent-hover: var(--primary-600);
45
+ --accent-active: var(--primary-700);
46
+ --accent-soft: var(--primary-50);
47
+ --accent-soft-strong: var(--primary-100);
48
+ --link: var(--primary-600); /* AA 7.00:1 sobre --surface — texto de links y ghost */
49
+
50
+ /* == Tipografía == */
51
+ --font-display: "Lora", Georgia, serif;
52
+ --font-body: "Nunito Sans", system-ui, -apple-system, sans-serif;
53
+ --font-mono: "Source Code Pro", ui-monospace, monospace;
54
+ --text-xs: .75rem; --text-sm: .875rem; --text-base: 1rem; --text-lg: 1.125rem;
55
+ --text-xl: 1.25rem; --text-2xl: 1.5625rem; --text-3xl: 1.9375rem;
56
+ --text-4xl: 2.4375rem; --text-5xl: 3.0625rem;
57
+ --leading-xs: 1.5; --leading-sm: 1.5; --leading-base: 1.6; --leading-lg: 1.55;
58
+ --leading-xl: 1.4; --leading-2xl: 1.3; --leading-3xl: 1.25;
59
+ --leading-4xl: 1.15; --leading-5xl: 1.1;
60
+ --tracking-display: -0.02em; --tracking-body: 0; --tracking-label: 0.04em;
61
+ --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700;
62
+ --measure: 65ch;
63
+
64
+ /* == Espaciado (escala base 4px) == */
65
+ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
66
+ --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
67
+ --space-12: 48px; --space-16: 64px; --space-20: 80px; --space-24: 96px;
68
+ --card-padding: var(--space-6); --card-padding-mobile: var(--space-4);
69
+ --section-gap: var(--space-16); --form-gap: var(--space-5);
70
+ --button-padding-md: 12px 20px; --button-padding-sm: 8px 14px;
71
+ --control-height-sm: 36px; --control-height-md: 44px; --control-height-lg: 52px;
72
+ --gutter: 24px; --gutter-mobile: 16px;
73
+
74
+ /* == Radios, bordes y sombras (teñidas de tinta verde, nunca negro puro) == */
75
+ --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px;
76
+ --radius-xl: 24px; --radius-full: 9999px;
77
+ --border-width: 1px;
78
+ --shadow-xs: 0 1px 2px rgba(44,54,48,.06);
79
+ --shadow-sm: 0 1px 3px rgba(44,54,48,.08), 0 1px 2px rgba(44,54,48,.05);
80
+ --shadow-md: 0 4px 8px rgba(44,54,48,.09), 0 2px 4px rgba(44,54,48,.05);
81
+ --shadow-lg: 0 12px 24px rgba(44,54,48,.12), 0 4px 8px rgba(44,54,48,.06);
82
+ --shadow-xl: 0 24px 48px rgba(44,54,48,.16);
83
+
84
+ /* == Focus == */
85
+ --ring: 0 0 0 3px rgba(79,107,88,.25);
86
+ --ring-color: rgba(79,107,88,.25);
87
+
88
+ /* == Motion (pausado: nada urge) == */
89
+ --duration-instant: 100ms; --duration-fast: 150ms; --duration-base: 220ms;
90
+ --duration-slow: 280ms; --duration-page: 340ms;
91
+ --ease-out: cubic-bezier(0.2, 0, 0, 1);
92
+ --ease-in: cubic-bezier(0.4, 0, 1, 1);
93
+ --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* moverse de A a B en pantalla */
94
+ --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
95
+ --stagger-step: 30ms;
96
+
97
+ color-scheme: light;
98
+
99
+ --overlay: rgba(44, 54, 48, .5);
100
+ --tooltip-bg: var(--neutral-900);
101
+ --tooltip-text: var(--neutral-0);
102
+ --focus-color: var(--accent);
103
+ --text-on-danger: var(--neutral-0);
104
+ --border-hover: var(--neutral-500);
105
+ --ring-danger: 0 0 0 3px rgba(181,82,63,.22);
106
+
107
+ --action-bg: var(--accent);
108
+ --action-hover: var(--accent-hover);
109
+ --action-active: var(--accent-active);
110
+ --text-on-action: var(--text-on-primary);
111
+ --control-border: var(--border-strong);
112
+ --placeholder: var(--text-muted);
113
+ --selection-bg: var(--action-bg);
114
+ --selection-text: var(--text-on-action);
115
+ --font-ui-heading: var(--font-body);
116
+ --text-ui-title: 2rem;
117
+ --touch-target: 44px;
118
+ --text-display-fluid: clamp(2.5rem, 1.8rem + 2.4vw, 4.5rem);
119
+
120
+ /* Series categóricas: orden estable; acompañar con etiqueta o forma. */
121
+ --chart-1: #549864;
122
+ --chart-2: #8d4226;
123
+ --chart-3: #179a8e;
124
+ --chart-4: #81416d;
125
+ --chart-5: #8a8b39;
126
+ --chart-6: #195f91;
127
+ --chart-7: #996f18;
128
+ /* Ritmo de contenido y formularios. */
129
+ --field-gap: 6px;
130
+ --heading-gap: var(--space-2);
131
+ --content-gap: var(--space-4);
132
+ --card-content-gap: var(--space-4);
133
+ --card-group-gap: var(--space-8);
134
+
135
+ }
136
+
137
+ /* == Modo oscuro (variante) — alternar data-theme en <html> ==
138
+ Casi sin sombras: las capas se separan por superficie y borde, y solo
139
+ los overlays (lg/xl) conservan una sombra tenue. */
140
+ [data-theme="dark"] {
141
+ --bg: #151a17;
142
+ --surface: #1d231f;
143
+ --surface-alt: #252c27;
144
+ --border: #2d3530;
145
+ --border-strong: #6f7b72;
146
+ --text-primary: #e3e8e2;
147
+ --text-secondary: #c4ccc5;
148
+ --text-muted: #a6b0a8;
149
+ --text-disabled: #79837b;
150
+ --accent: #9fc2a8;
151
+ --accent-hover: #b5d2bc;
152
+ --accent-active: #8ab295;
153
+ --accent-soft: #26332b;
154
+ --accent-soft-strong: #2f4035;
155
+ --text-on-primary: #151a17;
156
+ --text-on-primary-solid: #b5d2bc;
157
+ --link: #b5d2bc;
158
+ --success-500: #6cc3ac; --success-100: #14271f; --success-text: #8ad3bf;
159
+ --warning-500: #d9a94f; --warning-100: #2a2213; --warning-text: #e6c17e;
160
+ --danger-500: #d9806d; --danger-100: #2c1814; --danger-text: #e9a597;
161
+ --info-500: #8fb0c9; --info-100: #18222b; --info-text: #a9c4d8;
162
+ --ring: 0 0 0 3px rgba(159,194,168,.3);
163
+ --ring-color: rgba(159,194,168,.3);
164
+ --shadow-xs: none;
165
+ --shadow-sm: none;
166
+ --shadow-md: none;
167
+ --shadow-lg: 0 8px 24px rgba(8,10,9,.3);
168
+ --shadow-xl: 0 16px 32px rgba(8,10,9,.35);
169
+ color-scheme: dark;
170
+
171
+ --overlay: rgba(0, 0, 0, .6);
172
+ --tooltip-bg: #e3e8e2;
173
+ --tooltip-text: #2c3630;
174
+ --focus-color: var(--accent);
175
+ --text-on-danger: #151a17;
176
+ --border-hover: #a6b0a8;
177
+ --ring-danger: 0 0 0 3px rgba(217,128,109,.25);
178
+
179
+ --selection-bg: var(--action-bg);
180
+ --selection-text: var(--text-on-action);
181
+
182
+ /* Series categóricas: orden estable; acompañar con etiqueta o forma. */
183
+ --chart-1: #60a46f;
184
+ --chart-2: #a85a3f;
185
+ --chart-3: #2da79b;
186
+ --chart-4: #9b5986;
187
+ --chart-5: #818230;
188
+ --chart-6: #3678ac;
189
+ --chart-7: #946b10;
190
+ }
191
+
192
+ /* == Accesibilidad del movimiento == */
193
+
194
+ @media (prefers-reduced-motion: reduce) {
195
+ :root {
196
+ --duration-instant: 0ms; --duration-fast: 0ms; --duration-base: 0ms;
197
+ --duration-slow: 0ms; --duration-page: 0ms; --stagger-step: 0ms;
198
+ }
199
+ }
200
+
201
+ *, *::before, *::after { box-sizing: border-box; }
202
+
203
+ /* Focus ring global de teclado — especificidad cero vía :where() */
204
+ :where(a, button, [role="button"], input, select, textarea, summary, [tabindex]):focus-visible {
205
+ outline: 2px solid var(--focus-color);
206
+ outline-offset: 2px;
207
+ border-radius: 2px;
208
+ }
209
+
210
+ .salvia-reset {
211
+ margin: 0;
212
+ background: var(--bg);
213
+ color: var(--text-primary);
214
+ font-family: var(--font-body);
215
+ font-size: var(--text-base);
216
+ line-height: var(--leading-base);
217
+ letter-spacing: var(--tracking-body);
218
+ -webkit-font-smoothing: antialiased;
219
+ text-rendering: optimizeLegibility;
220
+ }
221
+ .salvia-reset h1, .salvia-reset h2 {
222
+ font-family: var(--font-display);
223
+ font-weight: var(--weight-bold);
224
+ letter-spacing: var(--tracking-display);
225
+ color: var(--text-primary);
226
+ margin: 0 0 .5em;
227
+ }
228
+ .salvia-reset h1 { font-size: var(--text-4xl); line-height: var(--leading-4xl); }
229
+ .salvia-reset h2 { font-size: var(--text-3xl); line-height: var(--leading-3xl); font-weight: var(--weight-semibold); }
230
+ .salvia-reset h3, .salvia-reset h4, .salvia-reset h5, .salvia-reset h6 {
231
+ font-family: var(--font-body);
232
+ font-weight: var(--weight-semibold);
233
+ color: var(--text-primary);
234
+ margin: 0 0 .5em;
235
+ }
236
+ .salvia-reset h3 { font-size: var(--text-2xl); line-height: var(--leading-2xl); }
237
+ .salvia-reset h4 { font-size: var(--text-xl); line-height: var(--leading-xl); }
238
+ .salvia-reset h5 { font-size: var(--text-lg); line-height: var(--leading-lg); }
239
+ .salvia-reset h6 { font-size: var(--text-base); line-height: var(--leading-base); }
240
+ .salvia-reset p { max-width: var(--measure); margin: 0 0 1em; }
241
+ .salvia-reset table { font-variant-numeric: tabular-nums; }
242
+ .salvia-reset ::placeholder { color: var(--placeholder); }
243
+ .salvia-reset ::selection { background: var(--ring-color); }
244
+
245
+
246
+
247
+ /* --------------------------------------------------------------------------
248
+ 3. LAYOUT — contenedor, grid 12 col (§14)
249
+ -------------------------------------------------------------------------- */
250
+ .container { width: 100%; margin-inline: auto; padding-inline: var(--gutter-mobile); }
251
+ @media (min-width: 640px) { .container { padding-inline: var(--space-4); } }
252
+ @media (min-width: 768px) { .container { max-width: 720px; } }
253
+ @media (min-width: 1024px) { .container { max-width: 960px; } }
254
+ @media (min-width: 1280px) { .container { max-width: 1200px; } }
255
+
256
+ .grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--gutter-mobile); }
257
+ @media (min-width: 768px) { .grid { gap: var(--gutter); } }
258
+ .col-1{grid-column:span 1}.col-2{grid-column:span 2}.col-3{grid-column:span 3}
259
+ .col-4{grid-column:span 4}.col-5{grid-column:span 5}.col-6{grid-column:span 6}
260
+ .col-7{grid-column:span 7}.col-8{grid-column:span 8}.col-9{grid-column:span 9}
261
+ .col-10{grid-column:span 10}.col-11{grid-column:span 11}.col-12{grid-column:span 12}
262
+ @media (min-width: 768px) {
263
+ .col-md-3{grid-column:span 3}.col-md-4{grid-column:span 4}
264
+ .col-md-6{grid-column:span 6}.col-md-8{grid-column:span 8}.col-md-12{grid-column:span 12}
265
+ }
266
+ @media (min-width: 1024px) {
267
+ .col-lg-3{grid-column:span 3}.col-lg-4{grid-column:span 4}
268
+ .col-lg-6{grid-column:span 6}.col-lg-8{grid-column:span 8}.col-lg-12{grid-column:span 12}
269
+ }
270
+
271
+ /* --------------------------------------------------------------------------
272
+ 4. BOTONES (§10.1) · ICON BUTTON (§10.2) · SPINNER (§10.3)
273
+ -------------------------------------------------------------------------- */
274
+ .btn {
275
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
276
+ height: var(--control-height-md); padding: var(--button-padding-md);
277
+ border: var(--border-width) solid transparent; border-radius: var(--radius-md);
278
+ font-family: var(--font-body); font-size: var(--text-base); font-weight: var(--weight-semibold);
279
+ line-height: 1; color: var(--text-primary); background: transparent;
280
+ cursor: pointer; text-decoration: none; white-space: nowrap; user-select: none;
281
+ transition: background-color var(--duration-fast) var(--ease-out),
282
+ border-color var(--duration-fast) var(--ease-out),
283
+ box-shadow var(--duration-fast) var(--ease-out),
284
+ transform var(--duration-instant) var(--ease-out);
285
+ }
286
+ .btn:active:not(:disabled) { transform: scale(.98); }
287
+ .btn:disabled { cursor: not-allowed; }
288
+ .btn svg { width: 20px; height: 20px; flex: none; }
289
+
290
+ /* Gating de hover (§11.5): los hover que mueven/elevan (transform, box-shadow) van
291
+ dentro de @media (hover: hover) and (pointer: fine) — en touch el tap dispara
292
+ hovers falsos que se quedan pegados. Los hover de solo color/fondo quedan fuera. */
293
+ .btn--primary { background: var(--action-bg); color: var(--text-on-action); }
294
+ .btn--primary:hover:not(:disabled) { background: var(--action-hover); }
295
+ @media (hover: hover) and (pointer: fine) {
296
+ .btn--primary:hover:not(:disabled) { box-shadow: var(--shadow-sm); }
297
+ }
298
+ .btn--primary:active:not(:disabled) { background: var(--action-active); box-shadow: none; }
299
+ .btn--primary:disabled { background: var(--border); color: var(--text-disabled); box-shadow: none; }
300
+
301
+ .btn--secondary { background: var(--surface); border-color: var(--border-strong); color: var(--text-primary); }
302
+ .btn--secondary:hover:not(:disabled) { background: var(--bg); }
303
+ .btn--secondary:active:not(:disabled) { background: var(--surface-alt); }
304
+ .btn--secondary:disabled { opacity: .5; }
305
+
306
+ .btn--outline { background: transparent; border-color: var(--accent); color: var(--link); }
307
+ .btn--outline:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent-hover); }
308
+ .btn--outline:active:not(:disabled) { background: var(--accent-soft-strong); }
309
+ .btn--outline:disabled { opacity: .5; }
310
+
311
+ .btn--ghost { color: var(--link); }
312
+ .btn--ghost:hover:not(:disabled) { background: var(--accent-soft); }
313
+ .btn--ghost:active:not(:disabled) { background: var(--accent-soft-strong); }
314
+ .btn--ghost:disabled { background: var(--border); color: var(--text-disabled); }
315
+
316
+ .btn--danger { background: var(--danger-500); color: var(--text-on-danger); }
317
+ .btn--danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger-500) 92%, black); }
318
+ .btn--danger:active:not(:disabled) { background: color-mix(in srgb, var(--danger-500) 86%, black); }
319
+ .btn--danger:disabled { opacity: .5; }
320
+
321
+ .btn--sm { height: var(--control-height-sm); padding: var(--button-padding-sm); font-size: var(--text-sm); }
322
+ .btn--lg { height: var(--control-height-lg); padding: 14px 24px; font-size: var(--text-lg); }
323
+
324
+ /* IconButton — requiere aria-label */
325
+ .icon-btn {
326
+ display: inline-grid; place-items: center;
327
+ width: var(--control-height-md); height: var(--control-height-md); padding: 0; flex: none;
328
+ border: var(--border-width) solid transparent; border-radius: var(--radius-md);
329
+ background: transparent; color: var(--text-secondary); cursor: pointer;
330
+ transition: background-color var(--duration-fast) var(--ease-out),
331
+ border-color var(--duration-fast) var(--ease-out),
332
+ transform var(--duration-instant) var(--ease-out);
333
+ }
334
+ .icon-btn:active:not(:disabled) { transform: scale(.98); }
335
+ .icon-btn:disabled { opacity: .5; cursor: not-allowed; }
336
+ .icon-btn svg { width: 18px; height: 18px; }
337
+ .icon-btn--sm { width: 32px; height: 32px; } .icon-btn--sm svg { width: 16px; height: 16px; }
338
+ .icon-btn--lg { width: 48px; height: 48px; } .icon-btn--lg svg { width: 20px; height: 20px; }
339
+ .icon-btn--ghost:hover:not(:disabled) { background: var(--surface-alt); color: var(--text-primary); }
340
+ .icon-btn--primary { background: var(--accent); color: var(--text-on-primary); }
341
+ .icon-btn--primary:hover:not(:disabled) { background: var(--accent-hover); }
342
+ .icon-btn--secondary { background: var(--surface); border-color: var(--border-strong); }
343
+ .icon-btn--secondary:hover:not(:disabled) { background: var(--bg); }
344
+
345
+ /* Spinner */
346
+ .spinner { width: 16px; height: 16px; animation: ss-spin .8s linear infinite; color: var(--accent); }
347
+ .spinner circle { opacity: .25; }
348
+ .spinner path { opacity: 1; }
349
+ @keyframes ss-spin { to { transform: rotate(360deg); } }
350
+
351
+ /* --------------------------------------------------------------------------
352
+ 5. FORMULARIOS — field, input, textarea, select (§10.4–10.6)
353
+ -------------------------------------------------------------------------- */
354
+ .field { display: flex; flex-direction: column; gap: 6px; }
355
+ .field__label { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-secondary); }
356
+ .field__help { font-size: var(--text-sm); color: var(--text-muted); }
357
+ .field__error { font-size: var(--text-sm); color: var(--danger-text); display: inline-flex; align-items: center; gap: 6px; }
358
+ .field__error svg { width: 14px; height: 14px; flex: none; }
359
+ /* Campo obligatorio (§10.4): asterisco decorativo; el input lleva required/aria-required */
360
+ .field--required .field__label::after { content: " *"; color: var(--danger-text); }
361
+
362
+ .input, .textarea, .select {
363
+ width: 100%; font-family: var(--font-body); font-size: var(--text-base);
364
+ color: var(--text-primary); background: var(--surface);
365
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
366
+ transition: border-color var(--duration-fast) var(--ease-out),
367
+ box-shadow var(--duration-fast) var(--ease-out);
368
+ }
369
+ .input, .select { height: var(--control-height-md); padding: 0 14px; }
370
+ .input:hover:not(:disabled):not(:focus),
371
+ .textarea:hover:not(:disabled):not(:focus),
372
+ .select:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
373
+ .input:focus, .textarea:focus, .select:focus {
374
+ outline: none; border-color: var(--accent); box-shadow: var(--ring);
375
+ }
376
+ .input:disabled, .textarea:disabled, .select:disabled {
377
+ background: var(--surface-alt); color: var(--text-disabled); cursor: not-allowed;
378
+ }
379
+ .input--error, .input--error:focus, .textarea--error { border-color: var(--danger-500); box-shadow: var(--ring-danger); }
380
+ .input--success { border-color: var(--success-500); }
381
+
382
+ .input-icon { position: relative; }
383
+ .input-icon > svg {
384
+ position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
385
+ width: 18px; height: 18px; color: var(--text-disabled); pointer-events: none;
386
+ }
387
+ .input-icon .input { padding-left: 40px; }
388
+
389
+ .textarea { min-height: 96px; padding: 12px 14px; resize: vertical; line-height: var(--leading-base); }
390
+ .textarea-counter { font-size: var(--text-xs); color: var(--text-muted); text-align: right; }
391
+
392
+ .select-wrap { position: relative; }
393
+ .select { appearance: none; padding-right: 38px; cursor: pointer; }
394
+ .select-wrap::after {
395
+ content: ""; position: absolute; right: 14px; top: 50%;
396
+ width: 16px; height: 16px; transform: translateY(-50%);
397
+ background: currentColor; color: var(--text-muted); pointer-events: none;
398
+ -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>') center / contain no-repeat;
399
+ mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>') center / contain no-repeat;
400
+ transition: transform var(--duration-base) var(--ease-out);
401
+ }
402
+
403
+ /* --------------------------------------------------------------------------
404
+ 6. SEGMENTED CONTROL (§10.7) · SLIDER (§10.8)
405
+ -------------------------------------------------------------------------- */
406
+ .segmented {
407
+ display: inline-flex; align-items: stretch;
408
+ background: var(--surface-alt); border-radius: var(--radius-md); padding: 3px;
409
+ height: 40px;
410
+ }
411
+ .segmented--sm { height: 32px; }
412
+ .segmented input { position: absolute; opacity: 0; pointer-events: none; }
413
+ .segmented label {
414
+ display: inline-flex; align-items: center; padding: 0 16px;
415
+ border-radius: calc(var(--radius-md) - 3px);
416
+ font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-secondary);
417
+ cursor: pointer; user-select: none; white-space: nowrap;
418
+ transition: background-color var(--duration-base) var(--ease-out),
419
+ color var(--duration-fast) var(--ease-out),
420
+ box-shadow var(--duration-base) var(--ease-out);
421
+ }
422
+ .segmented input:checked + label {
423
+ background: var(--surface); color: var(--text-primary);
424
+ font-weight: var(--weight-semibold); box-shadow: var(--shadow-xs);
425
+ }
426
+ .segmented input:focus-visible + label { outline: 2px solid var(--focus-color); outline-offset: 2px; }
427
+
428
+ .slider-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; }
429
+ .slider-row .slider-label { font-size: var(--text-sm); color: var(--text-secondary); }
430
+ .slider-row .slider-value { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); }
431
+ .slider {
432
+ -webkit-appearance: none; appearance: none;
433
+ width: 100%; height: 6px; border-radius: var(--radius-full);
434
+ background: linear-gradient(to right, var(--accent) var(--slider-fill, 50%), var(--border) var(--slider-fill, 50%));
435
+ cursor: pointer;
436
+ }
437
+ .slider:disabled { opacity: .5; cursor: not-allowed; }
438
+ .slider::-webkit-slider-thumb {
439
+ -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%;
440
+ background: var(--surface); border: 2px solid var(--accent); box-shadow: var(--shadow-sm);
441
+ transition: transform var(--duration-instant) var(--ease-out);
442
+ }
443
+ .slider:active::-webkit-slider-thumb { transform: scale(1.15); }
444
+ .slider::-moz-range-thumb {
445
+ width: 14px; height: 14px; border-radius: 50%;
446
+ background: var(--surface); border: 2px solid var(--accent); box-shadow: var(--shadow-sm);
447
+ transition: transform var(--duration-instant) var(--ease-out);
448
+ }
449
+ .slider:active::-moz-range-thumb { transform: scale(1.15); }
450
+
451
+ /* --------------------------------------------------------------------------
452
+ 7. SELECCIÓN — checkbox, radio, switch (§10.9–10.10)
453
+ -------------------------------------------------------------------------- */
454
+ .checkbox, .radio {
455
+ display: inline-flex; align-items: center; gap: 10px;
456
+ font-size: var(--text-base); color: var(--text-primary); cursor: pointer; position: relative;
457
+ }
458
+ .checkbox input, .radio input, .switch input {
459
+ position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0;
460
+ }
461
+ .checkbox__box {
462
+ width: 20px; height: 20px; flex: none; display: grid; place-items: center;
463
+ background: var(--surface); border: 2px solid var(--control-border); border-radius: 4px;
464
+ transition: background-color var(--duration-fast) var(--ease-out),
465
+ border-color var(--duration-fast) var(--ease-out);
466
+ }
467
+ .checkbox__box svg {
468
+ width: 12px; height: 12px; fill: none; stroke: var(--text-on-primary);
469
+ stroke-width: 3; stroke-linecap: round; stroke-linejoin: round;
470
+ stroke-dasharray: 20; stroke-dashoffset: 20;
471
+ transition: stroke-dashoffset var(--duration-base) var(--ease-spring);
472
+ }
473
+ .checkbox:hover .checkbox__box { border-color: var(--focus-color); }
474
+ .checkbox input:checked ~ .checkbox__box { background: var(--accent); border-color: var(--accent); }
475
+ .checkbox input:checked ~ .checkbox__box svg { stroke-dashoffset: 0; }
476
+ .checkbox input:focus-visible ~ .checkbox__box { box-shadow: var(--ring); }
477
+ .checkbox input:disabled ~ * { opacity: .5; cursor: not-allowed; }
478
+ /* Estado indeterminate (§10.9): guion horizontal para "seleccionar todo" parcial */
479
+ .checkbox__box { position: relative; }
480
+ .checkbox input:indeterminate ~ .checkbox__box { background: var(--accent); border-color: var(--accent); }
481
+ .checkbox input:indeterminate ~ .checkbox__box svg { visibility: hidden; }
482
+ .checkbox input:indeterminate ~ .checkbox__box::after {
483
+ content: ""; position: absolute; top: 50%; left: 50%;
484
+ width: 10px; height: 2px;
485
+ background: var(--text-on-primary); transform: translate(-50%, -50%);
486
+ }
487
+
488
+ .radio__dot {
489
+ width: 20px; height: 20px; flex: none; display: grid; place-items: center;
490
+ background: var(--surface); border: 2px solid var(--control-border); border-radius: var(--radius-full);
491
+ transition: background-color var(--duration-fast) var(--ease-out),
492
+ border-color var(--duration-fast) var(--ease-out);
493
+ }
494
+ .radio__dot::after {
495
+ content: ""; width: 8px; height: 8px; border-radius: 50%;
496
+ background: var(--text-on-primary); transform: scale(0);
497
+ transition: transform var(--duration-base) var(--ease-spring);
498
+ }
499
+ .radio:hover .radio__dot { border-color: var(--focus-color); }
500
+ .radio input:checked ~ .radio__dot { background: var(--accent); border-color: var(--accent); }
501
+ .radio input:checked ~ .radio__dot::after { transform: scale(1); }
502
+ .radio input:focus-visible ~ .radio__dot { box-shadow: var(--ring); }
503
+
504
+ .switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; position: relative; font-size: var(--text-base); }
505
+ .switch__track {
506
+ width: 44px; height: 24px; flex: none; border-radius: var(--radius-full);
507
+ background: var(--border-strong); position: relative;
508
+ transition: background-color var(--duration-base) var(--ease-out);
509
+ }
510
+ .switch__track::after {
511
+ content: ""; position: absolute; top: 2px; left: 2px;
512
+ width: 20px; height: 20px; border-radius: 50%;
513
+ background: var(--neutral-0); box-shadow: var(--shadow-xs);
514
+ transition: transform var(--duration-base) var(--ease-spring);
515
+ }
516
+ .switch input:checked ~ .switch__track { background: var(--accent); }
517
+ .switch input:checked ~ .switch__track::after { transform: translateX(20px); }
518
+ .switch input:focus-visible ~ .switch__track { box-shadow: var(--ring); }
519
+ .switch input:disabled ~ * { opacity: .5; cursor: not-allowed; }
520
+
521
+ /* --------------------------------------------------------------------------
522
+ 8. SUPERFICIES — card, badge, tag, avatar, divider, accordion (§10.11–10.14)
523
+ -------------------------------------------------------------------------- */
524
+ .card {
525
+ background: var(--surface); border: var(--border-width) solid var(--border);
526
+ border-radius: var(--radius-lg); padding: var(--card-padding);
527
+ box-shadow: var(--shadow-sm);
528
+ }
529
+ @media (max-width: 639px) { .card { padding: var(--card-padding-mobile); } }
530
+ .card--interactive {
531
+ cursor: pointer;
532
+ transition: transform var(--duration-base) var(--ease-out),
533
+ box-shadow var(--duration-base) var(--ease-out);
534
+ }
535
+ @media (hover: hover) and (pointer: fine) {
536
+ .card--interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
537
+ }
538
+
539
+ .badge {
540
+ display: inline-flex; align-items: center; gap: 4px;
541
+ font-size: var(--text-xs); font-weight: var(--weight-medium);
542
+ padding: 2px 8px; border-radius: var(--radius-full);
543
+ background: var(--surface-alt); color: var(--text-secondary);
544
+ }
545
+ .badge svg { width: 12px; height: 12px; }
546
+ .badge--success { background: var(--success-100); color: var(--success-text); }
547
+ .badge--warning { background: var(--warning-100); color: var(--warning-text); }
548
+ .badge--danger { background: var(--danger-100); color: var(--danger-text); }
549
+ .badge--info { background: var(--info-100); color: var(--info-text); }
550
+
551
+ .tag {
552
+ display: inline-flex; align-items: center; gap: 6px;
553
+ font-size: var(--text-xs); font-weight: var(--weight-medium);
554
+ padding: 3px 6px 3px 10px; border-radius: var(--radius-full);
555
+ background: var(--surface-alt); color: var(--text-secondary);
556
+ border: var(--border-width) solid var(--border);
557
+ }
558
+ .tag__close {
559
+ position: relative; display: grid; place-items: center; width: 16px; height: 16px;
560
+ border: 0; border-radius: 50%; background: transparent; color: inherit; cursor: pointer;
561
+ transition: background-color var(--duration-fast) var(--ease-out);
562
+ }
563
+ .tag__close:hover { background: var(--border); }
564
+ .tag__close svg { width: 10px; height: 10px; }
565
+
566
+ .avatar {
567
+ position: relative; display: inline-flex; flex: none;
568
+ width: 36px; height: 36px; font-size: 14px;
569
+ }
570
+ .avatar--sm { width: 28px; height: 28px; font-size: 12px; }
571
+ .avatar--lg { width: 48px; height: 48px; font-size: 18px; }
572
+ .avatar--xl { width: 64px; height: 64px; font-size: 24px; }
573
+ .avatar__img, .avatar__initials {
574
+ width: 100%; height: 100%; border-radius: var(--radius-full);
575
+ }
576
+ .avatar__img { object-fit: cover; }
577
+ .avatar__initials {
578
+ display: grid; place-items: center;
579
+ background: var(--accent-soft-strong); color: var(--text-on-primary-solid);
580
+ font-weight: var(--weight-semibold); text-transform: uppercase;
581
+ }
582
+ .avatar__dot {
583
+ position: absolute; right: 0; bottom: 0;
584
+ width: 28%; height: 28%; min-width: 8px; min-height: 8px;
585
+ border-radius: 50%; box-shadow: 0 0 0 2px var(--surface);
586
+ background: var(--neutral-300);
587
+ }
588
+ .avatar__dot--online { background: var(--success-500); }
589
+ .avatar__dot--busy { background: var(--danger-500); }
590
+ .avatar__dot--away { background: var(--warning-500); }
591
+
592
+ /* AvatarGroup (§10.27): stack solapado con anillo de superficie */
593
+ .avatar-group { display: inline-flex; align-items: center; }
594
+ .avatar-group .avatar { border: 2px solid var(--surface); border-radius: var(--radius-full); }
595
+ .avatar-group .avatar + .avatar,
596
+ .avatar-group .avatar-group__more { margin-left: -8px; }
597
+ .avatar-group__more {
598
+ display: grid; place-items: center; flex: none;
599
+ width: 36px; height: 36px; border-radius: var(--radius-full);
600
+ border: 2px solid var(--surface);
601
+ background: var(--accent-soft-strong); color: var(--text-on-primary-solid);
602
+ font-family: var(--font-body); font-size: var(--text-xs); font-weight: var(--weight-semibold);
603
+ }
604
+
605
+ .divider { border: 0; border-top: var(--border-width) solid var(--border); margin: var(--space-4) 0; }
606
+ .divider--label {
607
+ display: flex; align-items: center; gap: 12px; border: 0; margin: var(--space-4) 0;
608
+ color: var(--text-muted); font-size: var(--text-xs); font-weight: var(--weight-medium);
609
+ text-transform: uppercase; letter-spacing: var(--tracking-label);
610
+ }
611
+ .divider--label::before, .divider--label::after {
612
+ content: ""; flex: 1; border-top: var(--border-width) solid var(--border);
613
+ }
614
+ .divider--vertical {
615
+ display: inline-block; align-self: stretch; width: var(--border-width);
616
+ background: var(--border); border: 0; margin: 0 var(--space-3);
617
+ }
618
+
619
+ .accordion {
620
+ border: var(--border-width) solid var(--border); border-radius: var(--radius-lg);
621
+ background: var(--surface); overflow: hidden;
622
+ }
623
+ .accordion__item + .accordion__item { border-top: var(--border-width) solid var(--border); }
624
+ .accordion__header {
625
+ display: flex; align-items: center; justify-content: space-between; gap: 12px;
626
+ width: 100%; padding: 16px 20px; border: 0; background: transparent;
627
+ font-family: var(--font-body); font-size: var(--text-base); font-weight: var(--weight-medium);
628
+ color: var(--text-primary); text-align: left; cursor: pointer;
629
+ transition: background-color var(--duration-fast) var(--ease-out);
630
+ }
631
+ .accordion__header:hover { background: var(--bg); }
632
+ .accordion__header svg {
633
+ width: 18px; height: 18px; flex: none; color: var(--text-muted);
634
+ transition: transform var(--duration-base) var(--ease-out);
635
+ }
636
+ .accordion__item.is-open .accordion__header svg { transform: rotate(180deg); }
637
+ .accordion__panel {
638
+ display: grid; grid-template-rows: 0fr;
639
+ transition: grid-template-rows var(--duration-slow) var(--ease-out);
640
+ }
641
+ .accordion__item.is-open .accordion__panel { grid-template-rows: 1fr; }
642
+ .accordion__panel > div { overflow: hidden; }
643
+ .accordion__content {
644
+ padding: 0 20px 16px; font-size: var(--text-sm); color: var(--text-secondary);
645
+ opacity: 0; transition: opacity var(--duration-slow) var(--ease-out);
646
+ }
647
+ .accordion__item.is-open .accordion__content { opacity: 1; }
648
+
649
+ /* --------------------------------------------------------------------------
650
+ 9. FEEDBACK — tooltip, alert, toast, progress, skeleton, empty state
651
+ (§10.15–10.18, §10.25)
652
+ -------------------------------------------------------------------------- */
653
+ [data-tooltip] { position: relative; }
654
+ [data-tooltip]::after {
655
+ content: attr(data-tooltip);
656
+ position: absolute; bottom: calc(100% + 8px); left: 50%;
657
+ transform: translate(-50%, 4px);
658
+ background: var(--tooltip-bg); color: var(--tooltip-text);
659
+ font-size: var(--text-xs); line-height: 1.4; white-space: nowrap;
660
+ padding: 6px 10px; border-radius: var(--radius-sm);
661
+ opacity: 0; pointer-events: none; z-index: 70;
662
+ transition: opacity var(--duration-fast) var(--ease-out) 0s,
663
+ transform var(--duration-fast) var(--ease-out) 0s;
664
+ }
665
+ [data-tooltip]::before {
666
+ content: ""; position: absolute; bottom: calc(100% + 2px); left: 50%;
667
+ transform: translate(-50%, 4px);
668
+ border: 6px solid transparent; border-top-color: var(--tooltip-bg); border-bottom: 0;
669
+ opacity: 0; pointer-events: none; z-index: 70;
670
+ transition: opacity var(--duration-fast) var(--ease-out) 0s,
671
+ transform var(--duration-fast) var(--ease-out) 0s;
672
+ }
673
+ [data-tooltip]:focus-visible::after, [data-tooltip]:focus-visible::before {
674
+ opacity: 1; transform: translate(-50%, 0); transition-delay: 400ms;
675
+ }
676
+ /* Tooltip por hover solo con puntero real — en touch quedaría pegado tras el tap */
677
+ @media (hover: hover) and (pointer: fine) {
678
+ [data-tooltip]:hover::after, [data-tooltip]:hover::before {
679
+ opacity: 1; transform: translate(-50%, 0); transition-delay: 400ms;
680
+ }
681
+ }
682
+
683
+ .alert {
684
+ display: flex; gap: 12px; align-items: flex-start;
685
+ padding: 14px 16px; border-radius: var(--radius-md); font-size: var(--text-sm);
686
+ }
687
+ .alert > svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }
688
+ .alert__title { font-weight: var(--weight-semibold); margin: 0 0 2px; }
689
+ .alert__body { margin: 0; }
690
+ .alert__close {
691
+ position: relative; margin-left: auto; flex: none; display: grid; place-items: center;
692
+ width: 24px; height: 24px; border: 0; border-radius: var(--radius-sm);
693
+ background: transparent; color: inherit; cursor: pointer; opacity: .7;
694
+ }
695
+ .alert__close:hover { opacity: 1; }
696
+ .alert__close svg { width: 16px; height: 16px; }
697
+ /* Botones de cierre de aspecto compacto: un ::before invisible centrado lleva
698
+ el área de toque a 44 px (§12) sin cambiar el tamaño visual. */
699
+ .alert__close::before, .search__clear::before, .file-upload__remove::before,
700
+ .tag__close::before {
701
+ content: ""; position: absolute; top: 50%; left: 50%;
702
+ width: var(--control-height-md); height: var(--control-height-md);
703
+ transform: translate(-50%, -50%);
704
+ }
705
+ .alert--info { background: var(--info-100); color: var(--info-text); }
706
+ .alert--info > svg { color: var(--info-500); }
707
+ .alert--success { background: var(--success-100); color: var(--success-text); }
708
+ .alert--success > svg { color: var(--success-500); }
709
+ .alert--warning { background: var(--warning-100); color: var(--warning-text); }
710
+ .alert--warning > svg { color: var(--warning-500); }
711
+ .alert--danger { background: var(--danger-100); color: var(--danger-text); }
712
+ .alert--danger > svg { color: var(--danger-500); }
713
+
714
+ .toast-stack {
715
+ position: fixed; top: 16px; right: 16px; z-index: 90;
716
+ display: flex; flex-direction: column; gap: 12px; align-items: flex-end;
717
+ }
718
+ @media (max-width: 639px) {
719
+ .toast-stack { right: 50%; transform: translateX(50%); align-items: center; }
720
+ }
721
+ .toast {
722
+ display: flex; gap: 12px; align-items: flex-start;
723
+ width: 360px; max-width: calc(100vw - 32px);
724
+ background: var(--surface); color: var(--text-primary);
725
+ border-left: 3px solid var(--info-500); border-radius: var(--radius-md);
726
+ box-shadow: var(--shadow-lg); padding: 14px 16px; font-size: var(--text-sm);
727
+ /* Entrada interrumpible (§11.2): transition + @starting-style, no @keyframes —
728
+ un keyframe no puede invertirse si el toast se apila o se descarta a mitad. */
729
+ opacity: 1; transform: none;
730
+ transition: opacity var(--duration-slow) var(--ease-out),
731
+ transform var(--duration-slow) var(--ease-out);
732
+ }
733
+ @starting-style {
734
+ .toast { opacity: 0; transform: translateX(24px); }
735
+ }
736
+ .toast.is-leaving { animation: ss-toast-out var(--duration-base) var(--ease-in) forwards; }
737
+ .toast > svg { width: 20px; height: 20px; flex: none; }
738
+ .toast--success { border-left-color: var(--success-500); } .toast--success > svg { color: var(--success-500); }
739
+ .toast--warning { border-left-color: var(--warning-500); } .toast--warning > svg { color: var(--warning-500); }
740
+ .toast--danger { border-left-color: var(--danger-500); } .toast--danger > svg { color: var(--danger-500); }
741
+ .toast--info { border-left-color: var(--info-500); } .toast--info > svg { color: var(--info-500); }
742
+ .toast__title { font-weight: var(--weight-semibold); margin: 0; }
743
+ .toast__body { color: var(--text-secondary); margin: 0; }
744
+ @keyframes ss-toast-out { to { opacity: 0; transform: translateX(24px); } }
745
+
746
+ .progress-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
747
+ .progress-row .progress-label { font-size: var(--text-sm); color: var(--text-secondary); }
748
+ .progress-row .progress-value { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); }
749
+ .progress {
750
+ height: 8px; border-radius: var(--radius-full);
751
+ background: var(--surface-alt); overflow: hidden;
752
+ }
753
+ .progress__bar {
754
+ height: 100%; width: 0; border-radius: var(--radius-full);
755
+ background: var(--accent);
756
+ transition: width var(--duration-slow) var(--ease-out);
757
+ }
758
+ .progress__bar--success { background: var(--success-500); }
759
+ .progress__bar--warning { background: var(--warning-500); }
760
+ .progress__bar--danger { background: var(--danger-500); }
761
+
762
+ .progress-ring { display: inline-grid; place-items: center; position: relative; }
763
+ .progress-ring svg { transform: rotate(-90deg); }
764
+ .progress-ring__track { fill: none; stroke: var(--surface-alt); }
765
+ .progress-ring__bar {
766
+ fill: none; stroke: var(--accent); stroke-linecap: round;
767
+ transition: stroke-dashoffset var(--duration-slow) var(--ease-out);
768
+ }
769
+ .progress-ring__value {
770
+ position: absolute; font-family: var(--font-mono); color: var(--text-primary);
771
+ font-weight: var(--weight-medium);
772
+ }
773
+
774
+ /* Pulso de opacidad, sin degradado: el bloque entero se atenúa y vuelve.
775
+ Con movimiento reducido, el reset global lo deja quieto y opaco. */
776
+ .skeleton {
777
+ background: var(--surface-alt); border-radius: var(--radius-sm);
778
+ min-height: 12px;
779
+ animation: ss-pulse calc(var(--duration-page) * 4) linear infinite alternate;
780
+ }
781
+ @keyframes ss-pulse { to { opacity: .5; } }
782
+ .skeleton--circle { border-radius: var(--radius-full); }
783
+
784
+ .empty-state {
785
+ display: flex; flex-direction: column; align-items: center; text-align: center;
786
+ gap: var(--space-3); padding: var(--space-10) var(--space-6);
787
+ }
788
+ .empty-state > svg { width: 40px; height: 40px; color: var(--primary-300); }
789
+ .empty-state__title { font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--text-primary); margin: 0; }
790
+ .empty-state__desc { font-size: var(--text-sm); color: var(--text-muted); max-width: 40ch; margin: 0; }
791
+
792
+ /* --------------------------------------------------------------------------
793
+ 10. OVERLAYS — modal, menu (§10.19–10.20)
794
+ -------------------------------------------------------------------------- */
795
+ .modal {
796
+ position: fixed; inset: 0; z-index: 100;
797
+ display: grid; place-items: center; padding: var(--space-4);
798
+ visibility: hidden;
799
+ }
800
+ .modal.is-open { visibility: visible; }
801
+ .modal__overlay {
802
+ position: absolute; inset: 0; background: var(--overlay);
803
+ opacity: 0; transition: opacity var(--duration-base) var(--ease-out);
804
+ }
805
+ .modal.is-open .modal__overlay { opacity: 1; }
806
+ .modal__panel {
807
+ position: relative; width: min(480px, 100%);
808
+ background: var(--surface); border-radius: var(--radius-lg);
809
+ box-shadow: var(--shadow-xl); padding: var(--card-padding);
810
+ opacity: 0; transform: scale(.96);
811
+ transition: opacity var(--duration-slow) var(--ease-out),
812
+ transform var(--duration-slow) var(--ease-out);
813
+ }
814
+ .modal.is-open .modal__panel { opacity: 1; transform: scale(1); }
815
+ .modal__panel--lg { width: min(640px, 100%); }
816
+ .modal__header {
817
+ display: flex; align-items: center; justify-content: space-between;
818
+ gap: var(--space-4); margin-bottom: var(--space-4);
819
+ }
820
+ .modal__title { font-size: var(--text-xl); font-weight: var(--weight-semibold); margin: 0; }
821
+ .modal__footer {
822
+ display: flex; justify-content: flex-end; gap: var(--space-3);
823
+ margin-top: var(--space-6);
824
+ }
825
+
826
+ .menu-wrap { position: relative; display: inline-block; }
827
+ .menu {
828
+ position: absolute; top: calc(100% + 6px); left: 0; z-index: 50;
829
+ min-width: 190px; padding: 6px;
830
+ background: var(--surface); border: var(--border-width) solid var(--border);
831
+ border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
832
+ opacity: 0; transform: translateY(-4px); pointer-events: none;
833
+ transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
834
+
835
+ visibility: hidden;
836
+
837
+ display: none;
838
+ }
839
+ .menu--right { left: auto; right: 0; }
840
+ .menu.is-open { opacity: 1; transform: none; pointer-events: auto; visibility: visible; display: block; }
841
+ .menu__item {
842
+ display: flex; align-items: center; gap: 10px; width: 100%;
843
+ padding: 9px 12px; border: 0; border-radius: var(--radius-sm);
844
+ background: transparent; font-family: var(--font-body); font-size: var(--text-sm);
845
+ color: var(--text-primary); text-align: left; cursor: pointer;
846
+ transition: background-color var(--duration-fast) var(--ease-out);
847
+ }
848
+ .menu__item:hover { background: var(--bg); }
849
+ .menu__item svg { width: 16px; height: 16px; color: var(--text-muted); flex: none; }
850
+ .menu__item--danger, .menu__item--danger svg { color: var(--danger-text); }
851
+ .menu__item--danger:hover { background: var(--danger-100); }
852
+ .menu__sep { height: var(--border-width); background: var(--border); margin: 6px 4px; }
853
+
854
+ /* --------------------------------------------------------------------------
855
+ 11. DATOS — tabla, stat, pagination (§10.21–10.23)
856
+ -------------------------------------------------------------------------- */
857
+ .table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
858
+ .table thead th {
859
+ height: 40px; padding: 0 16px; text-align: left;
860
+ background: var(--bg); color: var(--text-muted);
861
+ font-size: var(--text-xs); font-weight: var(--weight-medium);
862
+ text-transform: uppercase; letter-spacing: var(--tracking-label);
863
+ border-bottom: var(--border-width) solid var(--border);
864
+ }
865
+ .table tbody td {
866
+ height: 52px; padding: 0 16px; color: var(--text-primary);
867
+ border-bottom: var(--border-width) solid var(--surface-alt);
868
+ }
869
+ .table tbody tr { transition: background-color var(--duration-fast) var(--ease-out); }
870
+ .table tbody tr:hover { background: var(--bg); }
871
+ .table tbody tr.is-selected { background: var(--accent-soft); }
872
+ .table .num, .table td.num, .table th.num { text-align: right; font-family: var(--font-mono); }
873
+
874
+ /* Variantes de tabla (§10.21): zebra, sticky header, orden y selección */
875
+ .table--zebra tbody tr:nth-child(even) { background: var(--surface-alt); }
876
+ .table--zebra tbody tr:nth-child(even):hover { background: var(--bg); }
877
+ .table--sticky thead th { position: sticky; top: 0; z-index: 1; }
878
+ .table tbody tr.row--selected,
879
+ .table tbody tr.row--selected:hover { background: var(--accent-soft); }
880
+ .table .col-select { width: 44px; text-align: center; }
881
+ .table .col-select .checkbox { display: inline-flex; justify-content: center; gap: 0; }
882
+
883
+ .th-sort {
884
+ display: inline-flex; align-items: center; gap: 6px; width: 100%;
885
+ border: 0; background: transparent; cursor: pointer;
886
+ font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; text-align: left;
887
+ }
888
+ .th-sort--num { justify-content: flex-end; }
889
+ .th-sort .sort-icon {
890
+ width: 14px; height: 14px; flex: none; opacity: .35;
891
+ transition: opacity var(--duration-fast) var(--ease-out),
892
+ transform var(--duration-base) var(--ease-out);
893
+ }
894
+ .table th[aria-sort="ascending"] .sort-icon,
895
+ .table th[aria-sort="descending"] .sort-icon { opacity: 1; color: var(--accent); }
896
+ .table th[aria-sort="descending"] .sort-icon { transform: rotate(180deg); }
897
+
898
+ .stat__label {
899
+ display: inline-flex; align-items: center; gap: 8px; margin-bottom: 8px;
900
+ font-size: var(--text-sm); color: var(--text-muted);
901
+ }
902
+ .stat__label svg { width: 16px; height: 16px; }
903
+ .stat__row { display: flex; align-items: baseline; gap: 10px; }
904
+ .stat__value {
905
+ font-family: var(--font-mono); font-size: var(--text-3xl);
906
+ font-weight: var(--weight-semibold); color: var(--text-primary);
907
+ letter-spacing: -0.01em; line-height: 1;
908
+ }
909
+ /* El delta indica tendencia, no éxito: tono neutro por defecto. --up/--down tiñen
910
+ solo cuando el producto decide qué sentido es bueno (deltaTone). */
911
+ .stat__delta {
912
+ display: inline-flex; align-items: center; gap: 4px;
913
+ font-size: var(--text-sm); font-weight: var(--weight-semibold);
914
+ color: var(--text-secondary);
915
+ }
916
+ .stat__delta svg { width: 14px; height: 14px; }
917
+ .stat__delta--up { color: var(--success-text); }
918
+ .stat__delta--down { color: var(--danger-text); }
919
+
920
+ /* Chip de métrica (§10.22): rótulo y valor en una pastilla de una línea */
921
+ .metric-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
922
+ .metric-chip {
923
+ display: inline-flex; align-items: center; gap: var(--space-2);
924
+ padding: var(--space-1) var(--space-3);
925
+ border: var(--border-width) solid var(--border); border-radius: var(--radius-full);
926
+ background: var(--surface);
927
+ font-family: var(--font-body); font-size: var(--text-sm); line-height: 1.5;
928
+ color: var(--text-secondary); white-space: nowrap;
929
+ }
930
+ .metric-chip svg { width: 16px; height: 16px; flex: none; color: var(--text-muted); }
931
+ .metric-chip__value {
932
+ font-weight: var(--weight-semibold); color: var(--link);
933
+ font-variant-numeric: tabular-nums;
934
+ }
935
+ button.metric-chip {
936
+ min-height: var(--control-height-md); padding-inline: var(--space-4);
937
+ cursor: pointer; text-align: left;
938
+ transition: background-color var(--duration-fast) var(--ease-out),
939
+ border-color var(--duration-fast) var(--ease-out),
940
+ transform var(--duration-instant) var(--ease-out);
941
+ }
942
+ button.metric-chip:hover { background: var(--accent-soft); border-color: var(--accent); }
943
+ button.metric-chip:active { background: var(--accent-soft-strong); transform: scale(.98); }
944
+ button.metric-chip:focus-visible { outline: 2px solid var(--focus-color); outline-offset: 2px; }
945
+ /* Meta cumplida: el ✓ va en el tono de éxito, nunca en el salvia del valor */
946
+ .metric-chip--met svg { color: var(--success-500); }
947
+
948
+ .pagination { display: flex; align-items: center; gap: 4px; list-style: none; padding: 0; margin: 0; }
949
+ .pagination__btn {
950
+ display: inline-grid; place-items: center;
951
+ min-width: 36px; height: 36px; padding: 0 8px;
952
+ border: 0; border-radius: var(--radius-sm); background: transparent;
953
+ font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium);
954
+ color: var(--text-secondary); cursor: pointer;
955
+ transition: background-color var(--duration-fast) var(--ease-out);
956
+ }
957
+ .pagination__btn:hover:not(:disabled):not(.is-active) { background: var(--surface-alt); }
958
+ .pagination__btn.is-active {
959
+ background: var(--accent); color: var(--text-on-primary); font-weight: var(--weight-semibold);
960
+ }
961
+ .pagination__btn:disabled { color: var(--text-disabled); cursor: not-allowed; }
962
+ .pagination__btn svg { width: 16px; height: 16px; }
963
+ .pagination__ellipsis { color: var(--text-disabled); padding: 0 4px; user-select: none; }
964
+
965
+ /* --------------------------------------------------------------------------
966
+ 12. NAVEGACIÓN — navbar, sidebar, tabs, breadcrumbs (§10.24)
967
+ -------------------------------------------------------------------------- */
968
+ .navbar {
969
+ display: flex; align-items: center; gap: var(--space-8);
970
+ height: 64px; padding: 0 var(--space-6);
971
+ background: var(--surface); border-bottom: var(--border-width) solid var(--border);
972
+ }
973
+ .navbar__brand { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-lg); color: var(--text-primary); text-decoration: none; }
974
+ .navbar__nav { display: flex; align-items: stretch; gap: var(--space-6); height: 100%; }
975
+ .navbar__link {
976
+ position: relative; display: inline-flex; align-items: center;
977
+ font-size: var(--text-sm); font-weight: var(--weight-medium);
978
+ color: var(--text-secondary); text-decoration: none;
979
+ transition: color var(--duration-fast) var(--ease-out);
980
+ }
981
+ .navbar__link:hover { color: var(--text-primary); }
982
+ .navbar__link.is-active { color: var(--accent-active); }
983
+ .navbar__link.is-active::after {
984
+ content: ""; position: absolute; left: 0; right: 0; bottom: 0;
985
+ height: 2px; background: var(--accent);
986
+ }
987
+
988
+ .sidebar {
989
+ width: 260px; padding: var(--space-4);
990
+ background: var(--bg); border-right: var(--border-width) solid var(--border);
991
+ display: flex; flex-direction: column; gap: 2px;
992
+ }
993
+ .sidebar__item {
994
+ display: flex; align-items: center; gap: 10px;
995
+ padding: 10px 12px; border-radius: var(--radius-md);
996
+ font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium);
997
+ color: var(--text-secondary); text-decoration: none; border: 0; background: transparent;
998
+ cursor: pointer; text-align: left; width: 100%;
999
+ transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
1000
+ }
1001
+ .sidebar__item svg { width: 18px; height: 18px; flex: none; }
1002
+ .sidebar__item:hover { background: var(--surface-alt); color: var(--text-primary); }
1003
+ .sidebar__item.is-active { background: var(--accent-soft-strong); color: var(--link); }
1004
+ .sidebar__item.is-active svg { color: var(--accent); }
1005
+
1006
+ /* Grupos con rótulo dentro del sidebar */
1007
+ .sidebar__group { display: flex; flex-direction: column; gap: 2px; }
1008
+ .sidebar__group + .sidebar__group { margin-top: var(--space-4); }
1009
+ .sidebar__group-label {
1010
+ padding: 0 12px var(--space-1);
1011
+ font-size: var(--text-xs); font-weight: var(--weight-semibold);
1012
+ text-transform: uppercase; letter-spacing: var(--tracking-label);
1013
+ color: var(--text-muted); white-space: nowrap;
1014
+ }
1015
+ .sidebar__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1016
+
1017
+ /* Sidebar contraíble (§10.24): expandido 260 px, riel de iconos de 64 px.
1018
+ El ancho cambia sin transición; solo los rótulos se funden con opacity y transform. */
1019
+ .sidebar--collapsible .sidebar__label {
1020
+ transition: opacity var(--duration-fast) var(--ease-out),
1021
+ transform var(--duration-fast) var(--ease-out);
1022
+ }
1023
+ .sidebar__toggle { margin-top: auto; }
1024
+ .sidebar.is-collapsed { width: 64px; padding-inline: var(--space-3); }
1025
+ .sidebar.is-collapsed .sidebar__item { position: relative; justify-content: center; padding-inline: 0; }
1026
+ .sidebar.is-collapsed .sidebar__toggle svg { transform: rotate(180deg); }
1027
+ .sidebar.is-collapsed .sidebar__group + .sidebar__group { margin-top: var(--space-2); }
1028
+ /* En el riel, el rótulo de grupo es un separador de 1 px; su texto sigue en el árbol de accesibilidad */
1029
+ .sidebar.is-collapsed .sidebar__group-label {
1030
+ height: 1px; padding: 0; margin: 0 var(--space-2) var(--space-2);
1031
+ overflow: hidden; color: transparent; background: var(--border);
1032
+ }
1033
+ /* Oculto a la vista pero accesible (patrón de .u-visually-hidden) */
1034
+ .sidebar.is-collapsed .sidebar__label,
1035
+ .sidebar.is-collapsed .sidebar__group:first-child > .sidebar__group-label {
1036
+ position: absolute; width: 1px; height: 1px; margin: -1px;
1037
+ clip-path: inset(50%); overflow: hidden; white-space: nowrap;
1038
+ }
1039
+ .sidebar.is-collapsed .sidebar__label {
1040
+ border-radius: var(--radius-sm); background: var(--tooltip-bg); color: var(--tooltip-text);
1041
+ font-size: var(--text-xs); line-height: 16px;
1042
+ pointer-events: none; z-index: 70;
1043
+ opacity: 0; transform: translateX(-4px);
1044
+ }
1045
+ /* Tooltip del riel: el propio rótulo aparece a la derecha del ítem, también con teclado */
1046
+ .sidebar.is-collapsed .sidebar__item:focus-visible .sidebar__label {
1047
+ left: calc(100% + 8px); top: calc(50% - 14px); width: auto; height: auto;
1048
+ margin: 0; padding: 6px 10px; clip-path: none; overflow: visible;
1049
+ opacity: 1; transform: none; transition-delay: 400ms;
1050
+ }
1051
+ /* Por hover solo con puntero real — en touch quedaría pegado tras el tap */
1052
+ @media (hover: hover) and (pointer: fine) {
1053
+ .sidebar.is-collapsed .sidebar__item:hover .sidebar__label {
1054
+ left: calc(100% + 8px); top: calc(50% - 14px); width: auto; height: auto;
1055
+ margin: 0; padding: 6px 10px; clip-path: none; overflow: visible;
1056
+ opacity: 1; transform: none; transition-delay: 400ms;
1057
+ }
1058
+ }
1059
+ /* Por debajo de 768 px la navegación vive en un Drawer --left (§10.29), que abre el botón ☰
1060
+ .sidebar-trigger (combinado con .icon-btn); desde 768 px el sidebar es fijo y el botón sobra */
1061
+ @media (max-width: 767px) {
1062
+ .sidebar--collapsible { display: none; }
1063
+ }
1064
+ @media (min-width: 768px) {
1065
+ .sidebar-trigger { display: none; }
1066
+ }
1067
+
1068
+ .tabs { display: flex; gap: var(--space-6); border-bottom: var(--border-width) solid var(--border); }
1069
+ .tabs__tab {
1070
+ padding: 12px 4px; margin-bottom: -1px;
1071
+ border: 0; border-bottom: 2px solid transparent; background: transparent;
1072
+ font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium);
1073
+ color: var(--text-secondary); cursor: pointer;
1074
+ transition: color var(--duration-fast) var(--ease-out),
1075
+ border-color var(--duration-slow) var(--ease-out);
1076
+ }
1077
+ .tabs__tab:hover { color: var(--text-primary); }
1078
+ .tabs__tab.is-active { color: var(--accent-active); border-bottom-color: var(--accent); }
1079
+
1080
+ .breadcrumbs { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); }
1081
+ .breadcrumbs a { color: var(--text-muted); text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
1082
+ .breadcrumbs a:hover { color: var(--link); }
1083
+ .breadcrumbs__sep { user-select: none; }
1084
+ .breadcrumbs__current { color: var(--text-primary); }
1085
+
1086
+ /* --------------------------------------------------------------------------
1087
+ 13. TIPOGRÁFICOS — link, code
1088
+ -------------------------------------------------------------------------- */
1089
+ .link {
1090
+ color: var(--link); text-decoration: none;
1091
+ background-image: linear-gradient(currentColor, currentColor);
1092
+ background-size: 0% 1px; background-repeat: no-repeat; background-position: 0 100%;
1093
+ transition: color var(--duration-fast) var(--ease-out),
1094
+ background-size var(--duration-base) var(--ease-out);
1095
+ }
1096
+ .link:hover { background-size: 100% 1px; }
1097
+
1098
+ .code {
1099
+ font-family: var(--font-mono); font-size: .9em;
1100
+ background: var(--surface-alt); color: var(--text-primary);
1101
+ border: var(--border-width) solid var(--border);
1102
+ border-radius: var(--radius-sm); padding: 1px 6px;
1103
+ }
1104
+
1105
+ /* --------------------------------------------------------------------------
1106
+ 13b. COMBOBOX · BÚSQUEDA · DRAWER · POPOVER · BUTTONGROUP (§10.28–10.31)
1107
+ -------------------------------------------------------------------------- */
1108
+
1109
+ /* Combobox / Autocomplete (§10.28) */
1110
+ .combobox { position: relative; }
1111
+ .combobox__input {
1112
+ width: 100%; height: var(--control-height-md); padding: 0 14px;
1113
+ font-family: var(--font-body); font-size: var(--text-base);
1114
+ color: var(--text-primary); background: var(--surface);
1115
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
1116
+ transition: border-color var(--duration-fast) var(--ease-out),
1117
+ box-shadow var(--duration-fast) var(--ease-out);
1118
+ }
1119
+ .combobox__input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
1120
+ .combobox__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
1121
+ .combobox__input:disabled { background: var(--surface-alt); color: var(--text-disabled); cursor: not-allowed; }
1122
+ .combobox__list {
1123
+ position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 50;
1124
+ max-height: 264px; overflow-y: auto; margin: 0; padding: 6px; list-style: none;
1125
+ background: var(--surface); border: var(--border-width) solid var(--border);
1126
+ border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
1127
+ opacity: 0; transform: translateY(-4px); pointer-events: none;
1128
+ transition: opacity var(--duration-base) var(--ease-out),
1129
+ transform var(--duration-base) var(--ease-out);
1130
+ }
1131
+ .combobox.is-open .combobox__list { opacity: 1; transform: none; pointer-events: auto; }
1132
+ .combobox__option {
1133
+ display: flex; align-items: center; gap: 8px;
1134
+ padding: 10px 12px; border-radius: var(--radius-sm);
1135
+ font-size: var(--text-sm); color: var(--text-primary); cursor: pointer;
1136
+ transition: background-color var(--duration-fast) var(--ease-out);
1137
+ }
1138
+ .combobox__option .combobox__check {
1139
+ width: 16px; height: 16px; margin-left: auto; flex: none;
1140
+ color: var(--accent); opacity: 0;
1141
+ }
1142
+ .combobox__option.is-active { background: var(--accent-soft); }
1143
+ .combobox__option[aria-selected="true"] { color: var(--link); font-weight: var(--weight-medium); }
1144
+ .combobox__option[aria-selected="true"] .combobox__check { opacity: 1; }
1145
+ .combobox__empty { padding: 10px 12px; font-size: var(--text-sm); color: var(--text-muted); }
1146
+
1147
+ /* Búsqueda (§10.28) */
1148
+ .search { position: relative; display: flex; align-items: center; }
1149
+ .search__icon {
1150
+ position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
1151
+ width: 18px; height: 18px; color: var(--text-disabled); pointer-events: none;
1152
+ }
1153
+ .search__input {
1154
+ width: 100%; height: var(--control-height-md); padding: 0 40px;
1155
+ font-family: var(--font-body); font-size: var(--text-base);
1156
+ color: var(--text-primary); background: var(--surface);
1157
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
1158
+ transition: border-color var(--duration-fast) var(--ease-out),
1159
+ box-shadow var(--duration-fast) var(--ease-out);
1160
+ }
1161
+ .search__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
1162
+ .search__input:hover:not(:focus) { border-color: var(--border-hover); }
1163
+ .search__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
1164
+ .search__clear {
1165
+ position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
1166
+ display: none; width: 32px; height: 32px; align-items: center; justify-content: center;
1167
+ border: 0; border-radius: var(--radius-full); background: transparent;
1168
+ color: var(--text-muted); cursor: pointer;
1169
+ transition: background-color var(--duration-fast) var(--ease-out),
1170
+ color var(--duration-fast) var(--ease-out);
1171
+ }
1172
+ .search__clear:hover { background: var(--surface-alt); color: var(--text-primary); }
1173
+ .search__clear svg { width: 16px; height: 16px; }
1174
+ .search__input:not(:placeholder-shown) ~ .search__clear { display: inline-flex; }
1175
+
1176
+ /* Drawer / Sheet (§10.29) */
1177
+ .drawer {
1178
+ position: fixed; inset: 0; z-index: 100;
1179
+ visibility: hidden; pointer-events: none;
1180
+ transition: visibility 0s linear var(--duration-base);
1181
+ }
1182
+ .drawer.is-open { visibility: visible; pointer-events: auto; transition-delay: 0s; }
1183
+ .drawer__overlay {
1184
+ position: absolute; inset: 0; background: var(--overlay);
1185
+ opacity: 0; transition: opacity var(--duration-base) var(--ease-out);
1186
+ }
1187
+ .drawer.is-open .drawer__overlay { opacity: 1; }
1188
+ .drawer__panel {
1189
+ position: absolute; inset: 0 0 0 auto; width: min(400px, 100%);
1190
+ display: flex; flex-direction: column; gap: var(--space-5);
1191
+ padding: var(--card-padding); background: var(--surface);
1192
+ box-shadow: var(--shadow-xl); overflow-y: auto; overscroll-behavior: contain;
1193
+ transform: translateX(100%);
1194
+ transition: transform var(--duration-base) var(--ease-in);
1195
+ }
1196
+ .drawer.is-open .drawer__panel {
1197
+ transform: none;
1198
+ transition: transform var(--duration-slow) var(--ease-out);
1199
+ }
1200
+ .drawer--right .drawer__panel { inset: 0 0 0 auto; transform: translateX(100%); }
1201
+ .drawer--left .drawer__panel { inset: 0 auto 0 0; transform: translateX(-100%); }
1202
+ .drawer--bottom .drawer__panel {
1203
+ inset: auto 0 0 0; width: 100%; max-height: 85vh;
1204
+ border-radius: var(--radius-lg) var(--radius-lg) 0 0; transform: translateY(100%);
1205
+ }
1206
+ .drawer__header {
1207
+ display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
1208
+ }
1209
+ .drawer__title { font-size: var(--text-lg); font-weight: var(--weight-semibold); margin: 0; }
1210
+ .drawer__body { flex: 1; }
1211
+ .drawer__footer {
1212
+ display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: auto;
1213
+ }
1214
+
1215
+ /* Popover (§10.30) */
1216
+ .popover { position: relative; display: inline-block; }
1217
+ .popover__panel {
1218
+ position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
1219
+ width: max-content; max-width: 300px; padding: var(--space-4);
1220
+ background: var(--surface); border: var(--border-width) solid var(--border);
1221
+ border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
1222
+ transform-origin: top left; opacity: 0; transform: scale(.96); pointer-events: none;
1223
+ transition: opacity var(--duration-base) var(--ease-out),
1224
+ transform var(--duration-base) var(--ease-out);
1225
+
1226
+ visibility: hidden;
1227
+
1228
+ display: none;
1229
+ }
1230
+ .popover.is-open .popover__panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; display: block; }
1231
+ .popover--right .popover__panel { left: auto; right: 0; transform-origin: top right; }
1232
+
1233
+ /* ButtonGroup (§10.31) */
1234
+ .btn-group { display: inline-flex; }
1235
+ .btn-group .btn { border-radius: 0; }
1236
+ .btn-group .btn:first-child {
1237
+ border-top-left-radius: var(--radius-md); border-bottom-left-radius: var(--radius-md);
1238
+ }
1239
+ .btn-group .btn:last-child {
1240
+ border-top-right-radius: var(--radius-md); border-bottom-right-radius: var(--radius-md);
1241
+ }
1242
+ .btn-group .btn:not(:first-child) { margin-left: calc(var(--border-width) * -1); }
1243
+ .btn-group .btn:hover, .btn-group .btn:focus-visible { z-index: 1; }
1244
+
1245
+ /* --------------------------------------------------------------------------
1246
+ 13c. DATEPICKER · FILEUPLOAD · STEPPER · KBD (§10.32–10.35)
1247
+ -------------------------------------------------------------------------- */
1248
+
1249
+ /* DatePicker (§10.32) */
1250
+ .datepicker { position: relative; display: inline-block; }
1251
+ .datepicker__input {
1252
+ width: 100%; height: var(--control-height-md); padding: 0 40px 0 14px;
1253
+ font-family: var(--font-body); font-size: var(--text-base);
1254
+ color: var(--text-primary); background: var(--surface);
1255
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
1256
+ transition: border-color var(--duration-fast) var(--ease-out),
1257
+ box-shadow var(--duration-fast) var(--ease-out);
1258
+ }
1259
+ .datepicker__input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
1260
+ .datepicker__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
1261
+ .datepicker__input:disabled { background: var(--surface-alt); color: var(--text-disabled); cursor: not-allowed; }
1262
+ .datepicker__icon {
1263
+ position: absolute; right: 12px; top: calc(var(--control-height-md) / 2); transform: translateY(-50%);
1264
+ width: 18px; height: 18px; color: var(--text-muted); pointer-events: none;
1265
+ }
1266
+ .datepicker__calendar {
1267
+ position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
1268
+ width: max-content; padding: var(--space-4);
1269
+ background: var(--surface); border: var(--border-width) solid var(--border);
1270
+ border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
1271
+ transform-origin: top left; opacity: 0; transform: scale(.96); pointer-events: none;
1272
+ transition: opacity var(--duration-base) var(--ease-out),
1273
+ transform var(--duration-base) var(--ease-out);
1274
+
1275
+ visibility: hidden;
1276
+
1277
+ display: none;
1278
+ }
1279
+ .datepicker.is-open .datepicker__calendar { opacity: 1; transform: none; pointer-events: auto; visibility: visible; display: block; }
1280
+ .datepicker--right .datepicker__calendar { left: auto; right: 0; transform-origin: top right; }
1281
+
1282
+ .calendar { width: 15.75rem; }
1283
+ .calendar__header {
1284
+ display: flex; align-items: center; justify-content: space-between;
1285
+ gap: var(--space-2); margin-bottom: var(--space-3);
1286
+ }
1287
+ .calendar__title { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary); }
1288
+ .calendar__weekdays,
1289
+ .calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
1290
+ .calendar__weekdays { margin-bottom: 4px; }
1291
+ .calendar__week { display: contents; }
1292
+ .calendar__weekday {
1293
+ display: flex; align-items: center; justify-content: center; height: 28px;
1294
+ font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--text-muted);
1295
+ }
1296
+ .calendar__day {
1297
+ display: flex; align-items: center; justify-content: center;
1298
+ width: 34px; height: 34px; margin: 0 auto; padding: 0;
1299
+ border: 0; border-radius: var(--radius-sm); background: transparent;
1300
+ font-family: var(--font-body); font-size: var(--text-sm); color: var(--text-primary);
1301
+ cursor: pointer;
1302
+ transition: background-color var(--duration-fast) var(--ease-out),
1303
+ color var(--duration-fast) var(--ease-out);
1304
+ }
1305
+ .calendar__day:hover:not(:disabled):not(.calendar__day--selected) { background: var(--accent-soft); }
1306
+ .calendar__day--outside { color: var(--text-muted); }
1307
+ .calendar__day--today { font-weight: var(--weight-semibold); box-shadow: inset 0 0 0 1px var(--border-strong); }
1308
+ .calendar__day--selected { background: var(--accent); color: var(--text-on-primary); font-weight: var(--weight-semibold); }
1309
+ .calendar__day:disabled { color: var(--text-disabled); cursor: not-allowed; }
1310
+
1311
+ /* FileUpload (§10.33) */
1312
+ .file-upload {
1313
+ border: 2px dashed var(--border-strong); border-radius: var(--radius-lg);
1314
+ background: var(--surface);
1315
+ transition: border-color var(--duration-fast) var(--ease-out),
1316
+ background-color var(--duration-fast) var(--ease-out);
1317
+ }
1318
+ .file-upload.is-dragover { border-color: var(--accent); background: var(--accent-soft); }
1319
+ .file-upload__input {
1320
+ position: absolute; width: 1px; height: 1px; margin: -1px;
1321
+ clip-path: inset(50%); overflow: hidden; white-space: nowrap;
1322
+ }
1323
+ .file-upload__label {
1324
+ display: flex; flex-direction: column; align-items: center; text-align: center;
1325
+ gap: var(--space-2); padding: var(--space-8) var(--space-6); cursor: pointer;
1326
+ }
1327
+ .file-upload__label > svg { width: 32px; height: 32px; color: var(--text-muted); }
1328
+ .file-upload__title { font-size: var(--text-sm); color: var(--text-secondary); }
1329
+ .file-upload__hint { font-size: var(--text-xs); color: var(--text-muted); }
1330
+ .file-upload__button {
1331
+ display: inline-flex; align-items: center; justify-content: center;
1332
+ height: var(--control-height-sm); padding: 0 16px; margin-top: var(--space-1);
1333
+ border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-md);
1334
+ font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary);
1335
+ background: var(--surface);
1336
+ transition: background-color var(--duration-fast) var(--ease-out);
1337
+ }
1338
+ .file-upload__label:hover .file-upload__button { background: var(--bg); }
1339
+ .file-upload__list { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
1340
+ .file-upload__item {
1341
+ display: flex; align-items: center; gap: var(--space-3);
1342
+ padding: var(--space-3); border: var(--border-width) solid var(--border);
1343
+ border-radius: var(--radius-md); background: var(--surface);
1344
+ }
1345
+ .file-upload__icon { width: 20px; height: 20px; color: var(--text-muted); flex: none; }
1346
+ .file-upload__meta { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
1347
+ .file-upload__name {
1348
+ font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-primary);
1349
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
1350
+ }
1351
+ .file-upload__size { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--text-muted); }
1352
+ .file-upload__size svg { width: 12px; height: 12px; flex: none; }
1353
+ .file-upload__meta .progress { margin-top: 2px; }
1354
+ .file-upload__remove {
1355
+ position: relative; display: inline-flex; align-items: center; justify-content: center;
1356
+ width: 32px; height: 32px; flex: none; border: 0; border-radius: var(--radius-full);
1357
+ background: transparent; color: var(--text-muted); cursor: pointer;
1358
+ transition: background-color var(--duration-fast) var(--ease-out),
1359
+ color var(--duration-fast) var(--ease-out);
1360
+ }
1361
+ .file-upload__remove:hover { background: var(--surface-alt); color: var(--text-primary); }
1362
+ .file-upload__remove svg { width: 16px; height: 16px; }
1363
+ .file-upload__item--error { border-color: var(--danger-500); }
1364
+ .file-upload__item--error .file-upload__icon,
1365
+ .file-upload__item--error .file-upload__size { color: var(--danger-text); }
1366
+
1367
+ /* Stepper / Wizard (§10.34) */
1368
+ .stepper { display: flex; list-style: none; margin: 0; padding: 0; }
1369
+ .step {
1370
+ position: relative; flex: 1;
1371
+ display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-2);
1372
+ }
1373
+ .step__marker {
1374
+ position: relative; z-index: 1;
1375
+ display: inline-flex; align-items: center; justify-content: center;
1376
+ width: 32px; height: 32px; flex: none; border-radius: var(--radius-full);
1377
+ border: 2px solid var(--border-strong); background: var(--surface);
1378
+ font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-muted);
1379
+ }
1380
+ .step__marker svg { width: 16px; height: 16px; }
1381
+ .step__label { font-size: var(--text-sm); color: var(--text-secondary); }
1382
+ .step__connector {
1383
+ position: absolute; top: 16px; z-index: 0; left: 50%; right: -50%;
1384
+ height: 2px; margin: 0 20px; background: var(--border);
1385
+ }
1386
+ .step--complete .step__marker { background: var(--accent); border-color: var(--accent); color: var(--text-on-primary); }
1387
+ .step--complete .step__label { color: var(--text-primary); }
1388
+ .step--complete .step__connector { background: var(--accent); }
1389
+ .step--current .step__marker { border-color: var(--accent); color: var(--accent); }
1390
+ .step--current .step__label { color: var(--text-primary); font-weight: var(--weight-semibold); }
1391
+ .stepper--vertical { flex-direction: column; align-items: stretch; }
1392
+ .stepper--vertical .step {
1393
+ flex-direction: row; align-items: flex-start; text-align: left;
1394
+ gap: var(--space-3); padding-bottom: var(--space-6);
1395
+ }
1396
+ .stepper--vertical .step:last-child { padding-bottom: 0; }
1397
+ .stepper--vertical .step__connector {
1398
+ top: 36px; bottom: -4px; left: 15px; right: auto;
1399
+ width: 2px; height: auto; margin: 0;
1400
+ }
1401
+ .stepper--vertical .step__label { padding-top: 5px; }
1402
+
1403
+ /* Kbd (§10.35) */
1404
+ .kbd {
1405
+ display: inline-flex; align-items: center; justify-content: center;
1406
+ min-width: 20px; height: 20px; padding: 0 6px;
1407
+ font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1;
1408
+ color: var(--text-secondary); background: var(--surface);
1409
+ border: var(--border-width) solid var(--border-strong);
1410
+ border-radius: var(--radius-sm); box-shadow: var(--shadow-xs);
1411
+ }
1412
+ .kbd-combo { display: inline-flex; align-items: center; gap: 4px; color: var(--text-muted); font-size: var(--text-xs); }
1413
+
1414
+ /* --------------------------------------------------------------------------
1415
+ 14. UTILIDADES MÍNIMAS
1416
+ -------------------------------------------------------------------------- */
1417
+ .u-visually-hidden {
1418
+ position: absolute; width: 1px; height: 1px; margin: -1px;
1419
+ clip-path: inset(50%); overflow: hidden; white-space: nowrap;
1420
+ }
1421
+ .u-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
1422
+ .u-muted { color: var(--text-muted); }
1423
+ .u-measure { max-width: var(--measure); }
1424
+
1425
+ /* CONTRATOS COMPARTIDOS GENERADOS */
1426
+ /* Contratos comunes de interacción; la identidad y los valores viven en tokens.css. */
1427
+ .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
1428
+ .grid > *, .field, .card { min-inline-size: 0; }
1429
+ .stack, .card__content, .form-stack, .text-group { display: flex; flex-direction: column; align-items: stretch; }
1430
+ .stack, .card__content { gap: var(--content-gap); }
1431
+ .stack--tight, .text-group { gap: var(--heading-gap); }
1432
+ .stack--cards { gap: var(--card-group-gap); }
1433
+ .form-stack { gap: var(--form-gap); }
1434
+ .cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
1435
+ .card { display: flex; flex-direction: column; gap: var(--card-content-gap); }
1436
+ .field { gap: var(--field-gap); }
1437
+ .field__label, .field__help, .field__error, .field > :is(label, p, span, div) { margin-block: 0; }
1438
+ :where(.field + .field, .field + .btn, .field + .cluster) { margin-block-start: var(--form-gap); }
1439
+ :where(.card + .card) { margin-block-start: var(--card-group-gap); }
1440
+ .stack > *, .card__content > *, .form-stack > *, .text-group > *, .grid > .card,
1441
+ .card > :is(h1, h2, h3, h4, h5, h6, p), .text-group > :is(h1, h2, h3, h4, h5, h6, p),
1442
+ .stack > :is(h1, h2, h3, h4, h5, h6, p) { margin-block: 0; }
1443
+ .form-stack > .field { margin-block: 0; }
1444
+ .btn {
1445
+ block-size: auto;
1446
+ min-block-size: var(--control-height-md);
1447
+ max-inline-size: 100%;
1448
+ white-space: normal;
1449
+ line-height: 1.35;
1450
+ text-align: center;
1451
+ }
1452
+ .btn--sm { min-block-size: var(--control-height-sm, 36px); }
1453
+ .btn--lg { min-block-size: var(--control-height-lg, 52px); }
1454
+ .btn--primary, .icon-btn--primary, .calendar__day--selected, .pagination__btn.is-active {
1455
+ background: var(--action-bg);
1456
+ color: var(--text-on-action);
1457
+ }
1458
+ .btn--primary:hover:not(:disabled), .icon-btn--primary:hover:not(:disabled) { background: var(--action-hover); color: var(--text-on-action); }
1459
+ .btn--primary:active:not(:disabled), .icon-btn--primary:active:not(:disabled) { background: var(--action-active); color: var(--text-on-action); }
1460
+ .input, .textarea, .select, .combobox__input, .search__input, .datepicker__input {
1461
+ max-inline-size: 100%;
1462
+ caret-color: var(--focus-color);
1463
+ }
1464
+ .input, .select, .combobox__input, .search__input, .datepicker__input {
1465
+ block-size: auto; min-block-size: var(--control-height-md);
1466
+ padding-block: var(--space-2); line-height: 1.5;
1467
+ }
1468
+ :is(.input, .textarea, .select, .combobox__input, .search__input, .datepicker__input):not(.input--error, .input--success, .textarea--error, [aria-invalid="true"]) { border-color: var(--control-border); }
1469
+ .input:hover:not(:disabled):not(:focus):not(.input--error, .input--success, [aria-invalid="true"]), .textarea:hover:not(:disabled):not(:focus):not(.textarea--error, [aria-invalid="true"]),
1470
+ .select:hover:not(:disabled):not(:focus), .combobox__input:hover:not(:disabled):not(:focus),
1471
+ .search__input:hover:not(:focus), .datepicker__input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
1472
+ .input:focus-visible, .textarea:focus-visible, .select:focus-visible,
1473
+ .combobox__input:focus-visible, .search__input:focus-visible, .datepicker__input:focus-visible {
1474
+ outline: 2px solid var(--focus-color);
1475
+ outline-offset: 2px;
1476
+ }
1477
+ .input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--danger-text, var(--danger)); }
1478
+ .input.input--error, .textarea.textarea--error,
1479
+ .input.input--error:hover:not(:disabled):not(:focus), .textarea.textarea--error:hover:not(:disabled):not(:focus),
1480
+ :is(.input, .textarea, .select, .combobox__input, .search__input, .datepicker__input)[aria-invalid="true"]:hover:not(:disabled):not(:focus) {
1481
+ border-color: var(--danger-text, var(--danger));
1482
+ }
1483
+ .input.input--success, .input.input--success:hover:not(:disabled):not(:focus) { border-color: var(--success-text, var(--success)); }
1484
+ .pagination { max-inline-size: 100%; flex-wrap: wrap; row-gap: var(--space-2); }
1485
+ .pagination__ellipsis { color: var(--text-muted); }
1486
+ .step--current .step__marker { color: var(--link); border-color: var(--focus-color); }
1487
+ .checkbox input:focus-visible ~ .checkbox__box,
1488
+ .radio input:focus-visible ~ .radio__dot,
1489
+ .switch input:focus-visible ~ .switch__track {
1490
+ outline: 2px solid var(--focus-color);
1491
+ outline-offset: 2px;
1492
+ }
1493
+ input.checkbox, input.radio { border-color: var(--control-border); }
1494
+ input.checkbox:hover, input.radio:hover { border-color: var(--focus-color); }
1495
+ input.checkbox:checked, input.checkbox:indeterminate, input.radio:checked { border-color: var(--focus-color); }
1496
+ .switch__track { background: var(--control-border); }
1497
+ .tabs { max-inline-size: 100%; overflow-x: auto; }
1498
+ .tabs__tab { flex-shrink: 0; }
1499
+ .segmented { max-inline-size: 100%; block-size: auto; min-block-size: var(--control-height-md); overflow-x: auto; }
1500
+ .segmented label { padding-block: var(--space-2); }
1501
+ .stat__row, .breadcrumbs, .check-row { flex-wrap: wrap; row-gap: var(--space-2); }
1502
+ .progress-row, .slider-row { flex-wrap: wrap; gap: var(--space-2); }
1503
+ .stat__value { max-inline-size: 100%; white-space: normal; overflow-wrap: anywhere; }
1504
+ .file-upload, .file-upload__label { min-inline-size: 0; max-inline-size: 100%; }
1505
+ .file-upload__button { max-inline-size: 100%; white-space: normal; text-align: center; }
1506
+ .file-upload__hint { overflow-wrap: anywhere; }
1507
+ .table-scroll { max-inline-size: 100%; overflow-x: auto; overscroll-behavior-inline: contain; }
1508
+ .popover__panel, .datepicker__calendar, .combobox__list {
1509
+ max-inline-size: calc(100vw - 2rem);
1510
+ max-block-size: min(32rem, 70dvh);
1511
+ overflow: auto;
1512
+ }
1513
+ .file-upload__input:focus-visible + .file-upload__label { outline: 2px solid var(--focus-color); outline-offset: 2px; }
1514
+ .calendar { max-inline-size: calc(100vw - 2rem); }
1515
+ .ui-title, :is(h1, h2, h3, h4, h5, h6).ui-title, [data-mode="operate"] :is(h1, h2, h3) {
1516
+ font-family: var(--font-ui-heading);
1517
+ letter-spacing: 0;
1518
+ line-height: 1.3;
1519
+ font-weight: var(--weight-semibold);
1520
+ }
1521
+ .ui-title, :is(h1, h2, h3, h4, h5, h6).ui-title, [data-mode="operate"] h1 { font-size: var(--text-ui-title); }
1522
+ [data-mode="operate"] h2 { font-size: var(--text-xl); }
1523
+ [data-mode="operate"] h3 { font-size: var(--text-lg); }
1524
+ .display, .reading-title, :is(h1, h2, h3, h4, h5, h6):is(.display, .reading-title) {
1525
+ font-family: var(--font-display);
1526
+ font-size: var(--text-display-fluid);
1527
+ line-height: 1.08;
1528
+ letter-spacing: var(--tracking-display);
1529
+ text-wrap: balance;
1530
+ }
1531
+ :where(.celeste-reset, .salvia-reset, .bruma-reset, .nocturna-reset, body[data-system]) {
1532
+ scrollbar-color: var(--control-border) var(--bg);
1533
+ }
1534
+ ::selection,
1535
+ .celeste-reset ::selection, .salvia-reset ::selection, .bruma-reset ::selection {
1536
+ background: var(--selection-bg); color: var(--selection-text);
1537
+ }
1538
+ ::placeholder { color: var(--placeholder); opacity: 1; }
1539
+ :where(a) { text-underline-offset: .2em; text-decoration-thickness: .08em; }
1540
+ .skip-link {
1541
+ position: fixed; inset-block-start: var(--space-2); inset-inline-start: var(--space-2);
1542
+ z-index: 1000; padding: var(--space-3) var(--space-4);
1543
+ background: var(--action-bg); color: var(--text-on-action);
1544
+ border-radius: var(--radius-sm); transform: translateY(-180%);
1545
+ }
1546
+ .skip-link:focus { transform: none; outline: 2px solid var(--focus-color); outline-offset: 2px; }
1547
+ [data-tooltip]::before, [data-tooltip]::after { display: none; }
1548
+ [data-tooltip]:focus-visible::before, [data-tooltip]:focus-visible::after { display: block; }
1549
+ .has-tooltip .tooltip { display: none; }
1550
+ .has-tooltip:has(:focus-visible) .tooltip { display: block; opacity: 1; transform: translate(-50%, 0); }
1551
+ @media (hover: hover) and (pointer: fine) {
1552
+ [data-tooltip]:hover::before, [data-tooltip]:hover::after { display: block; }
1553
+ .has-tooltip:hover .tooltip { display: block; }
1554
+ }
1555
+ @media (pointer: coarse) {
1556
+ .btn, .icon-btn, .segmented label, .pagination button,
1557
+ .tag__close, .search__clear, .toast__close, .check-row,
1558
+ .checkbox:not(input), .radio:not(input), .switch:not(input) {
1559
+ min-block-size: var(--touch-target);
1560
+ min-inline-size: var(--touch-target);
1561
+ }
1562
+ }
1563
+ @media (max-width: 479px) {
1564
+ .btn-group { flex-wrap: wrap; }
1565
+ .modal { max-inline-size: calc(100vw - 2rem); }
1566
+ .stepper { flex-direction: column; align-items: stretch; gap: var(--space-4); }
1567
+ .step { flex-direction: row; align-items: center; gap: var(--space-3); text-align: start; min-inline-size: 0; }
1568
+ .step__label { overflow-wrap: anywhere; }
1569
+ .step__connector { display: none; }
1570
+ }
1571
+ @media (prefers-reduced-motion: reduce) {
1572
+ html, html:focus-within { scroll-behavior: auto; }
1573
+ .spinner, .skeleton, .skeleton::after,
1574
+ .progress--indeterminate .progress__bar, .alert.is-leaving, .toast.is-leaving { animation: none; }
1575
+ .progress--indeterminate .progress__bar { transform: none; }
1576
+ .btn, .icon-btn, .card--interactive, .slider::-webkit-slider-thumb { transform: none; }
1577
+ .btn:active:not(:disabled), .icon-btn:active:not(:disabled), .card--interactive:hover { transform: none; }
1578
+ .btn, .icon-btn { transition: background-color 80ms linear, color 80ms linear; }
1579
+ .menu, .popover__panel, .datepicker__calendar, .link::after { transition: none; }
1580
+ .progress__bar, .progress-ring__value, .accordion__content, .accordion__body { transition: none; }
1581
+ }
1582
+ @media (forced-colors: active) {
1583
+ input.switch, .switch__track { border: 1px solid CanvasText; background: Canvas; }
1584
+ input.switch::after, .switch__track::after { background: CanvasText; }
1585
+ input.switch:checked, .switch input:checked ~ .switch__track { border-color: Highlight; }
1586
+ input.switch:checked::after, .switch input:checked ~ .switch__track::after { background: Highlight; }
1587
+ .checkbox__box, .radio__dot { border-color: CanvasText; }
1588
+ }