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