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