@higinio/design-mcp 0.1.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,992 @@
1
+ /* ============================================================================
2
+ NOCTURNA ELÉCTRICA — Framework CSS v2.0
3
+ Sistema de diseño dark-first de Higinio Sosa.
4
+ Fuente de verdad: DESIGN-nocturna-electrica.md
5
+ Uso: enlazar este archivo antes de cualquier estilo propio.
6
+ Tema: dark por defecto; <html data-theme="light"> activa la variante clara.
7
+ Los componentes consumen SOLO aliases semánticos — nunca hex directos.
8
+ ========================================================================== */
9
+
10
+ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Manrope:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
11
+
12
+ /* ============================================================
13
+ 1. TOKENS — primitivos + aliases (dark por defecto)
14
+ ============================================================ */
15
+ :root {
16
+ /* -- Primitivos: acento -- */
17
+ --accent-100: #d9f0fb; --accent-200: #a8ddf6; --accent-300: #7dccf1;
18
+ --accent-400: #52baed; --accent-500: #2fa3dd; --accent-600: #1f87bb; --accent-700: #186a94;
19
+
20
+ /* -- Primitivos: índigo -- */
21
+ --indigo-300: #7a83c4; --indigo-400: #565fa3; --indigo-500: #353d7c;
22
+ --indigo-600: #2b3264; --indigo-700: #22284f; --indigo-800: #1a1e3b;
23
+
24
+ /* -- Primitivos: escala nocturna -- */
25
+ --night-950: #010203; --night-900: #0b0d12; --night-800: #14171f;
26
+ --night-700: #1e222d; --night-600: #2a2f3d; --night-500: #3d4354;
27
+ --night-400: #6b7183; --night-300: #9aa0b0; --night-200: #c5c9d4;
28
+ --night-100: #e8eaef; --night-50: #f6f7f9;
29
+
30
+ /* -- Primitivos: semánticos -- */
31
+ --success-400: #4ade80; --success-bg: #0a2617;
32
+ --warning-400: #fbbf24; --warning-bg: #2a2005;
33
+ --danger-400: #f87171; --danger-bg: #2c0f0f;
34
+ --info-400: #52baed; --info-bg: #0d1f2c;
35
+
36
+ /* -- Aliases semánticos (los componentes consumen SOLO esto) -- */
37
+ --bg: var(--night-950);
38
+ --surface-1: var(--night-900);
39
+ --surface-2: var(--night-800);
40
+ --surface-3: var(--night-700);
41
+ --border: var(--night-500);
42
+ --border-strong: var(--night-600);
43
+ --text-primary: var(--night-100);
44
+ --text-secondary: var(--night-200);
45
+ --text-muted: var(--night-300);
46
+ --text-disabled: var(--night-400);
47
+ --text-heading: var(--night-50);
48
+ --text-on-accent: var(--night-950);
49
+ --success: var(--success-400);
50
+ --warning: var(--warning-400);
51
+ --danger: var(--danger-400);
52
+ --info: var(--info-400);
53
+ --accent-ghost-hover: rgba(82,186,237,.08);
54
+ --accent-ghost-active: rgba(82,186,237,.14);
55
+ --accent-selected: rgba(82,186,237,.12);
56
+ --overlay: rgba(1,2,3,.7);
57
+
58
+ /* -- Aliases de componentes (derivados; cambian con el tema) -- */
59
+ --link: var(--accent-400);
60
+ --link-hover: var(--accent-200);
61
+ --focus-color: var(--accent-400);
62
+ --border-hover: var(--night-400);
63
+ --outline-hover-bg: var(--surface-2);
64
+ --outline-active-bg: var(--surface-3);
65
+ --text-on-danger: var(--night-950);
66
+ --data-color: var(--accent-400); /* cifras/datos clave */
67
+ --elevated-border: var(--night-600); /* borde de toasts, modales, menús */
68
+ --card-border: var(--night-600);
69
+ --code-color: var(--accent-300);
70
+ --code-border: var(--night-700);
71
+ --table-header-bg: var(--night-900);
72
+ --row-border: var(--night-800);
73
+ --row-hover: var(--night-700);
74
+ --navbar-bg: rgba(1,2,3,.8);
75
+ --nav-active: var(--accent-400);
76
+ --sidebar-bg: var(--night-900);
77
+ --sidebar-active-bg: var(--indigo-800);
78
+ --sidebar-active-text: var(--night-50);
79
+ --sidebar-active-icon: var(--accent-400);
80
+ --switch-off: var(--night-600);
81
+ --tooltip-bg: var(--night-700);
82
+ --tooltip-border: var(--night-600);
83
+ --tooltip-text: var(--night-100);
84
+ --skeleton-base: var(--night-800);
85
+ --skeleton-sheen: var(--night-700);
86
+ --empty-icon: var(--indigo-400);
87
+
88
+ /* -- Tipografía -- */
89
+ --font-display: "Space Grotesk", system-ui, sans-serif;
90
+ --font-body: "Manrope", system-ui, sans-serif;
91
+ --font-mono: "JetBrains Mono", monospace;
92
+ --text-xs: .75rem; --text-sm: .875rem; --text-base: 1rem; --text-lg: 1.125rem;
93
+ --text-xl: 1.25rem; --text-2xl: 1.5625rem; --text-3xl: 1.9375rem;
94
+ --text-4xl: 2.4375rem; --text-5xl: 3.0625rem;
95
+ --leading-tight: 1.05; --leading-heading: 1.15; --leading-h2: 1.2;
96
+ --leading-h3: 1.3; --leading-h4: 1.4; --leading-snug: 1.5; --leading-body: 1.6;
97
+ --tracking-display: -0.02em; --tracking-overline: 0.08em;
98
+ --measure: 65ch;
99
+
100
+ /* -- Espaciado -- */
101
+ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
102
+ --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
103
+ --space-12: 48px; --space-16: 64px; --space-20: 80px; --space-24: 96px;
104
+ --card-padding: 24px; --card-padding-mobile: 16px;
105
+ --section-gap: 64px; --form-gap: 20px;
106
+ --button-padding: 12px 20px; --touch-target: 44px;
107
+ --grid-gutter: 24px; --grid-gutter-mobile: 16px;
108
+
109
+ /* -- Radios y bordes -- */
110
+ --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px;
111
+ --radius-xl: 24px; --radius-full: 9999px;
112
+ --border-default: 1px solid var(--night-500);
113
+ --border-emphasis: 1px solid var(--night-600);
114
+ --focus-ring: 2px solid var(--accent-400);
115
+ --focus-ring-offset: 2px;
116
+
117
+ /* -- Elevación -- */
118
+ --shadow-1: 0 1px 2px rgba(0,0,0,.4);
119
+ --shadow-2: 0 4px 12px rgba(0,0,0,.5);
120
+ --shadow-3: 0 12px 32px rgba(0,0,0,.6);
121
+ --glow-accent: 0 0 0 1px rgba(82,186,237,.35), 0 4px 20px rgba(82,186,237,.18);
122
+ --ring: 0 0 0 3px rgba(82,186,237,.2);
123
+ --ring-danger: 0 0 0 3px rgba(248,113,113,.2);
124
+
125
+ /* -- Motion -- */
126
+ --duration-instant: 100ms; --duration-fast: 150ms; --duration-base: 220ms;
127
+ --duration-slow: 250ms; --duration-page: 350ms;
128
+ --ease-out: cubic-bezier(0.2, 0, 0, 1);
129
+ --ease-in: cubic-bezier(0.4, 0, 1, 1);
130
+ --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* moverse de A a B en pantalla */
131
+ --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
132
+
133
+ color-scheme: dark;
134
+ }
135
+
136
+ /* ============================================================
137
+ 2. VARIANTE LIGHT — <html data-theme="light">
138
+ El CTA primario NO cambia (fondo #52baed, texto #010203).
139
+ ============================================================ */
140
+ [data-theme="light"] {
141
+ --bg: #f5f8fb;
142
+ --surface-1: #ffffff;
143
+ --surface-2: #ffffff;
144
+ --surface-3: #eaf1f7;
145
+ --border: #d8dfe8;
146
+ --border-strong: #b9c3d1;
147
+ --text-primary: #14171f;
148
+ --text-secondary: #3d4354;
149
+ --text-muted: #6b7183;
150
+ --text-disabled: #9aa0b0;
151
+ --text-heading: #0b0d12;
152
+ --text-on-accent: #010203; /* el CTA no cambia */
153
+ --success: #15803d; --success-bg: #e3f5ea;
154
+ --warning: #a16207; --warning-bg: #fbf3dd;
155
+ --danger: #c03535; --danger-bg: #fbe7e7;
156
+ --info: #1f87bb; --info-bg: #e3f2fb;
157
+ --accent-ghost-hover: rgba(31,135,187,.08);
158
+ --accent-ghost-active: rgba(31,135,187,.14);
159
+ --accent-selected: rgba(82,186,237,.12);
160
+ --overlay: rgba(20,23,31,.45);
161
+
162
+ --link: #1f87bb;
163
+ --link-hover: #186a94;
164
+ --focus-color: #1f87bb;
165
+ --border-hover: #b9c3d1;
166
+ --outline-hover-bg: #eaf1f7;
167
+ --outline-active-bg: #d8dfe8;
168
+ --text-on-danger: #ffffff;
169
+ --data-color: #1f87bb;
170
+ --elevated-border: #d8dfe8;
171
+ --card-border: #d8dfe8;
172
+ --code-color: #186a94;
173
+ --code-border: #d8dfe8;
174
+ --table-header-bg: #eaf1f7;
175
+ --row-border: #eaf1f7;
176
+ --row-hover: #f5f8fb;
177
+ --navbar-bg: rgba(255,255,255,.8);
178
+ --nav-active: #186a94;
179
+ --sidebar-bg: #ffffff;
180
+ --sidebar-active-bg: #e3f2fb;
181
+ --sidebar-active-text: #14171f;
182
+ --sidebar-active-icon: #1f87bb;
183
+ --switch-off: #b9c3d1;
184
+ --tooltip-bg: #14171f;
185
+ --tooltip-border: #14171f;
186
+ --tooltip-text: #f6f7f9;
187
+ --skeleton-base: #eaf1f7;
188
+ --skeleton-sheen: #f5f8fb;
189
+
190
+ --ring: 0 0 0 3px rgba(31,135,187,.25);
191
+ --ring-danger: 0 0 0 3px rgba(192,53,53,.2);
192
+ --shadow-1: 0 1px 3px rgba(53,61,124,.08);
193
+ --shadow-2: 0 4px 10px rgba(53,61,124,.10);
194
+ --shadow-3: 0 12px 28px rgba(53,61,124,.14);
195
+ --glow-accent: 0 0 0 1px rgba(82,186,237,.4), 0 4px 16px rgba(82,186,237,.25);
196
+
197
+ color-scheme: light;
198
+ }
199
+
200
+ /* ============================================================
201
+ 3. ACCESIBILIDAD DEL MOVIMIENTO
202
+ ============================================================ */
203
+ @media (prefers-reduced-motion: reduce) {
204
+ *, *::before, *::after {
205
+ animation-duration: 0.01ms !important;
206
+ animation-iteration-count: 1 !important;
207
+ transition-duration: 0.01ms !important;
208
+ scroll-behavior: auto !important;
209
+ }
210
+ }
211
+
212
+ /* ============================================================
213
+ 4. BASE
214
+ ============================================================ */
215
+ *, *::before, *::after { box-sizing: border-box; }
216
+
217
+ body {
218
+ margin: 0;
219
+ background: var(--bg);
220
+ color: var(--text-primary);
221
+ font-family: var(--font-body);
222
+ font-size: var(--text-base);
223
+ line-height: var(--leading-body);
224
+ -webkit-font-smoothing: antialiased;
225
+ text-rendering: optimizeLegibility;
226
+ }
227
+
228
+ /* h1–h3 en display; h4 en adelante usa body */
229
+ h1, h2, h3 {
230
+ font-family: var(--font-display);
231
+ color: var(--text-heading);
232
+ letter-spacing: var(--tracking-display);
233
+ margin: 0 0 var(--space-4);
234
+ }
235
+ h1 { font-size: var(--text-4xl); line-height: var(--leading-heading); font-weight: 700; }
236
+ h2 { font-size: var(--text-3xl); line-height: var(--leading-h2); font-weight: 700; }
237
+ h3 { font-size: var(--text-2xl); line-height: var(--leading-h3); font-weight: 600; }
238
+ h4 { font-family: var(--font-body); font-size: var(--text-xl); line-height: var(--leading-h4); font-weight: 600; color: var(--text-heading); margin: 0 0 var(--space-3); }
239
+
240
+ p { max-width: var(--measure); margin: 0 0 var(--space-4); }
241
+
242
+ a { color: var(--link); text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
243
+ a:hover { color: var(--link-hover); }
244
+
245
+ ::placeholder { color: var(--text-disabled); }
246
+ ::selection { background: rgba(82,186,237,.3); }
247
+
248
+ :focus-visible {
249
+ outline: 2px solid var(--focus-color);
250
+ outline-offset: var(--focus-ring-offset);
251
+ }
252
+
253
+ /* ============================================================
254
+ 5. LAYOUT — contenedor y grid de 12 columnas
255
+ Breakpoints: sm 640 · md 768 · lg 1024 · xl 1280
256
+ ============================================================ */
257
+ .container { width: 100%; margin-inline: auto; padding-inline: var(--space-4); }
258
+ @media (min-width: 640px) { .container { max-width: calc(100% - 32px); } }
259
+ @media (min-width: 768px) { .container { max-width: 720px; } }
260
+ @media (min-width: 1024px) { .container { max-width: 960px; } }
261
+ @media (min-width: 1280px) { .container { max-width: 1200px; } }
262
+
263
+ .grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--grid-gutter-mobile); }
264
+ @media (min-width: 768px) { .grid { gap: var(--grid-gutter); } }
265
+ [class*="col-"] { grid-column: span 12; }
266
+ @media (min-width: 768px) {
267
+ .col-1{grid-column:span 1}.col-2{grid-column:span 2}.col-3{grid-column:span 3}
268
+ .col-4{grid-column:span 4}.col-5{grid-column:span 5}.col-6{grid-column:span 6}
269
+ .col-7{grid-column:span 7}.col-8{grid-column:span 8}.col-9{grid-column:span 9}
270
+ .col-10{grid-column:span 10}.col-11{grid-column:span 11}.col-12{grid-column:span 12}
271
+ }
272
+
273
+ /* ============================================================
274
+ 6. BOTONES — .btn
275
+ ============================================================ */
276
+ .btn {
277
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
278
+ height: 44px; padding: var(--button-padding); min-width: 44px;
279
+ border: 1px solid transparent; border-radius: var(--radius-md);
280
+ font-family: var(--font-body); font-size: var(--text-base); font-weight: 600;
281
+ line-height: 1; cursor: pointer; white-space: nowrap; text-decoration: none;
282
+ transition: background-color var(--duration-fast) var(--ease-out),
283
+ border-color var(--duration-fast) var(--ease-out),
284
+ color var(--duration-fast) var(--ease-out),
285
+ box-shadow var(--duration-base) var(--ease-out),
286
+ transform var(--duration-instant) var(--ease-out);
287
+ }
288
+ .btn:active:not(:disabled) { transform: scale(.98); }
289
+ .btn:disabled { cursor: not-allowed; }
290
+ .btn svg { width: 20px; height: 20px; flex: none; }
291
+
292
+ .btn--sm { height: 36px; padding: 8px 14px; font-size: var(--text-sm); }
293
+ .btn--lg { height: 52px; padding: 14px 24px; font-size: var(--text-lg); }
294
+
295
+ /* Primario — texto oscuro sobre acento, nunca blanco */
296
+ /* Gating de hover (§11.5): los hover que mueven/elevan (transform, box-shadow, glow)
297
+ van dentro de @media (hover: hover) and (pointer: fine) — en touch el tap dispara
298
+ hovers falsos que se quedan pegados. Los hover de solo color/fondo quedan fuera. */
299
+ .btn--primary { background: var(--accent-400); color: var(--text-on-accent); }
300
+ .btn--primary:hover:not(:disabled) { background: var(--accent-500); }
301
+ @media (hover: hover) and (pointer: fine) {
302
+ .btn--primary:hover:not(:disabled) { box-shadow: var(--glow-accent); }
303
+ }
304
+ .btn--primary:active:not(:disabled) { background: var(--accent-600); box-shadow: none; }
305
+ .btn--primary:disabled { background: var(--surface-3); color: var(--text-disabled); }
306
+
307
+ /* Secundario — índigo (idéntico en ambos temas) */
308
+ .btn--secondary { background: var(--indigo-500); color: var(--night-50); }
309
+ .btn--secondary:hover:not(:disabled) { background: var(--indigo-600); }
310
+ .btn--secondary:active:not(:disabled) { background: var(--indigo-700); }
311
+ .btn--secondary:disabled { opacity: .5; }
312
+
313
+ /* Outline */
314
+ .btn--outline { background: transparent; border-color: var(--border); color: var(--text-primary); }
315
+ .btn--outline:hover:not(:disabled) { background: var(--outline-hover-bg); border-color: var(--border-hover); }
316
+ .btn--outline:active:not(:disabled) { background: var(--outline-active-bg); }
317
+ .btn--outline:disabled { opacity: .5; }
318
+
319
+ /* Ghost */
320
+ .btn--ghost { background: transparent; color: var(--link); }
321
+ .btn--ghost:hover:not(:disabled) { background: var(--accent-ghost-hover); }
322
+ .btn--ghost:active:not(:disabled) { background: var(--accent-ghost-active); }
323
+ .btn--ghost:disabled { color: var(--text-disabled); }
324
+
325
+ /* Destructivo */
326
+ .btn--danger { background: var(--danger); color: var(--text-on-danger); }
327
+ .btn--danger:hover:not(:disabled) { filter: brightness(.92); }
328
+ .btn--danger:active:not(:disabled) { filter: brightness(.86); }
329
+ .btn--danger:disabled { opacity: .5; filter: none; }
330
+
331
+ /* ============================================================
332
+ 7. ICON BUTTON — .icon-btn (siempre con aria-label)
333
+ ============================================================ */
334
+ .icon-btn {
335
+ display: inline-flex; align-items: center; justify-content: center;
336
+ width: 44px; height: 44px; padding: 0; flex: none;
337
+ border: 1px solid transparent; border-radius: var(--radius-md);
338
+ background: transparent; cursor: pointer;
339
+ transition: background-color var(--duration-fast) var(--ease-out),
340
+ border-color var(--duration-fast) var(--ease-out),
341
+ color var(--duration-fast) var(--ease-out),
342
+ transform var(--duration-instant) var(--ease-out);
343
+ }
344
+ .icon-btn:active:not(:disabled) { transform: scale(.98); }
345
+ .icon-btn:disabled { opacity: .5; cursor: not-allowed; }
346
+ .icon-btn svg { width: 20px; height: 20px; }
347
+ .icon-btn--sm { width: 36px; height: 36px; } .icon-btn--sm svg { width: 18px; height: 18px; }
348
+ .icon-btn--lg { width: 52px; height: 52px; }
349
+
350
+ .icon-btn--outline { border-color: var(--border); color: var(--text-secondary); }
351
+ .icon-btn--outline:hover:not(:disabled) { background: var(--outline-hover-bg); border-color: var(--border-hover); }
352
+ .icon-btn--outline:active:not(:disabled) { background: var(--outline-active-bg); }
353
+
354
+ .icon-btn--ghost { color: var(--text-muted); }
355
+ .icon-btn--ghost:hover:not(:disabled) { background: var(--outline-hover-bg); color: var(--text-primary); }
356
+ .icon-btn--ghost:active:not(:disabled) { background: var(--outline-active-bg); }
357
+
358
+ .icon-btn--accent { color: var(--link); }
359
+ .icon-btn--accent:hover:not(:disabled) { background: var(--accent-ghost-hover); }
360
+ .icon-btn--accent:active:not(:disabled) { background: var(--accent-ghost-active); }
361
+
362
+ /* ============================================================
363
+ 8. SPINNER — .spinner
364
+ ============================================================ */
365
+ .spinner {
366
+ display: inline-block; width: 16px; height: 16px; flex: none;
367
+ border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
368
+ border-top-color: currentColor; border-radius: var(--radius-full);
369
+ color: var(--accent-400);
370
+ animation: ne-spin .8s linear infinite;
371
+ }
372
+ @keyframes ne-spin { to { transform: rotate(360deg); } }
373
+
374
+ /* ============================================================
375
+ 9. FORMULARIOS — .field, .input, .textarea, .select
376
+ ============================================================ */
377
+ .field { display: flex; flex-direction: column; margin-bottom: var(--form-gap); }
378
+ .field__label { font-size: var(--text-sm); font-weight: 500; color: var(--text-secondary); margin-bottom: 6px; }
379
+ .field__help { font-size: var(--text-sm); color: var(--text-muted); margin-top: 6px; }
380
+ .field__error {
381
+ display: inline-flex; align-items: center; gap: 6px;
382
+ font-size: var(--text-sm); color: var(--danger); margin-top: 6px;
383
+ }
384
+ .field__error svg { width: 14px; height: 14px; flex: none; }
385
+
386
+ .input, .textarea, .select {
387
+ width: 100%; background: var(--surface-2);
388
+ border: 1px solid var(--border); border-radius: var(--radius-sm);
389
+ color: var(--text-primary); font-family: var(--font-body); font-size: var(--text-base);
390
+ transition: border-color var(--duration-fast) var(--ease-out),
391
+ box-shadow var(--duration-fast) var(--ease-out);
392
+ }
393
+ .input, .select { height: 44px; padding: 0 14px; }
394
+ .input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
395
+ .input:focus, .textarea:focus, .select:focus {
396
+ outline: none; border-color: var(--focus-color); box-shadow: var(--ring);
397
+ }
398
+ .input:disabled, .textarea:disabled {
399
+ background: var(--surface-1); color: var(--text-disabled); cursor: not-allowed;
400
+ }
401
+ .input--error, .input--error:hover { border-color: var(--danger); }
402
+ .input--error:focus { border-color: var(--danger); box-shadow: var(--ring-danger); }
403
+ .input--success { border-color: var(--success); }
404
+
405
+ /* Input con icono leading */
406
+ .input-wrap { position: relative; }
407
+ .input-wrap > svg {
408
+ position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
409
+ width: 18px; height: 18px; color: var(--text-disabled); pointer-events: none;
410
+ }
411
+ .input-wrap .input { padding-left: 40px; }
412
+
413
+ .textarea { min-height: 96px; padding: 12px 14px; resize: vertical; line-height: var(--leading-body); }
414
+ .field__count { font-size: var(--text-xs); color: var(--text-disabled); text-align: right; margin-top: 4px; }
415
+
416
+ /* Select nativo estilizado (el menú custom usa .menu) */
417
+ .select-wrap { position: relative; }
418
+ .select { appearance: none; padding-right: 40px; cursor: pointer; }
419
+ .select-wrap::after {
420
+ content: ""; position: absolute; right: 14px; top: 50%;
421
+ width: 8px; height: 8px; pointer-events: none;
422
+ border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted);
423
+ transform: translateY(-70%) rotate(45deg);
424
+ transition: transform var(--duration-base) var(--ease-out);
425
+ }
426
+
427
+ /* Menú desplegable (dropdown/select custom) */
428
+ .menu {
429
+ min-width: 190px; padding: 6px; max-height: 320px; overflow: auto;
430
+ background: var(--surface-2); border: 1px solid var(--elevated-border);
431
+ border-radius: var(--radius-md); box-shadow: var(--shadow-3);
432
+ }
433
+ .menu__item {
434
+ display: flex; align-items: center; gap: 10px; width: 100%;
435
+ padding: 10px 12px; border: 0; border-radius: var(--radius-sm);
436
+ background: transparent; color: var(--text-primary);
437
+ font-family: var(--font-body); font-size: var(--text-sm); text-align: left; cursor: pointer;
438
+ transition: background-color var(--duration-fast) var(--ease-out);
439
+ }
440
+ .menu__item:hover { background: var(--surface-3); }
441
+ .menu__item.is-selected { background: var(--accent-selected); color: var(--accent-300); }
442
+ [data-theme="light"] .menu__item.is-selected { color: var(--link); }
443
+ .menu__item svg { width: 16px; height: 16px; color: var(--text-muted); flex: none; }
444
+
445
+ /* SegmentedControl */
446
+ .segmented {
447
+ display: inline-flex; align-items: stretch;
448
+ background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 3px;
449
+ height: 44px;
450
+ }
451
+ .segmented--sm { height: 36px; }
452
+ .segmented input { position: absolute; opacity: 0; pointer-events: none; }
453
+ .segmented label {
454
+ display: inline-flex; align-items: center; padding: 0 16px;
455
+ border-radius: calc(var(--radius-md) - 3px);
456
+ font-size: var(--text-sm); font-weight: 500; color: var(--text-secondary);
457
+ cursor: pointer; user-select: none; white-space: nowrap;
458
+ transition: background-color var(--duration-base) var(--ease-out),
459
+ color var(--duration-fast) var(--ease-out),
460
+ box-shadow var(--duration-base) var(--ease-out);
461
+ }
462
+ .segmented--sm label { padding: 0 12px; font-size: var(--text-xs); }
463
+ .segmented input:checked + label {
464
+ background: var(--surface-3); color: var(--accent-300);
465
+ font-weight: 600; box-shadow: var(--shadow-1);
466
+ }
467
+ .segmented input:focus-visible + label { outline: var(--focus-ring); outline-offset: 2px; }
468
+
469
+ /* Slider */
470
+ .slider-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; }
471
+ .slider-row .slider-label { font-size: var(--text-sm); color: var(--text-secondary); }
472
+ .slider-row .slider-value { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); font-variant-numeric: tabular-nums; }
473
+ .slider {
474
+ appearance: none; -webkit-appearance: none;
475
+ width: 100%; height: 6px; border-radius: var(--radius-full);
476
+ background: linear-gradient(to right, var(--accent-400) var(--slider-fill, 50%), var(--surface-3) var(--slider-fill, 50%));
477
+ cursor: pointer;
478
+ }
479
+ .slider:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
480
+ .slider:disabled { opacity: .5; cursor: not-allowed; }
481
+ .slider::-webkit-slider-thumb {
482
+ -webkit-appearance: none; width: 18px; height: 18px; border-radius: var(--radius-full);
483
+ background: var(--night-50); border: 2px solid var(--accent-400); box-shadow: var(--shadow-1);
484
+ transition: transform var(--duration-instant) var(--ease-out);
485
+ }
486
+ .slider:active::-webkit-slider-thumb { transform: scale(1.15); }
487
+ .slider::-moz-range-thumb {
488
+ width: 14px; height: 14px; border-radius: var(--radius-full); border: 2px solid var(--accent-400);
489
+ background: var(--night-50); box-shadow: var(--shadow-1);
490
+ transition: transform var(--duration-instant) var(--ease-out);
491
+ }
492
+ .slider:active::-moz-range-thumb { transform: scale(1.15); }
493
+ @media (prefers-reduced-motion: reduce) {
494
+ .slider::-webkit-slider-thumb { transition-duration: 0.01ms !important; }
495
+ .slider::-moz-range-thumb { transition-duration: 0.01ms !important; }
496
+ }
497
+
498
+ /* ============================================================
499
+ 10. SELECCIÓN — .checkbox, .radio, .switch
500
+ ============================================================ */
501
+ .check-row { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: var(--text-base); }
502
+
503
+ .checkbox, .radio {
504
+ appearance: none; width: 20px; height: 20px; margin: 0; flex: none;
505
+ background: transparent; border: 2px solid var(--border); cursor: pointer;
506
+ display: inline-grid; place-content: center;
507
+ transition: background-color var(--duration-base) var(--ease-out),
508
+ border-color var(--duration-fast) var(--ease-out);
509
+ }
510
+ .checkbox { border-radius: 4px; }
511
+ .radio { border-radius: var(--radius-full); }
512
+ .checkbox:hover, .radio:hover { border-color: var(--accent-300); }
513
+ .checkbox:checked, .radio:checked { background: var(--accent-400); border-color: var(--accent-400); }
514
+ .checkbox::after {
515
+ content: ""; width: 10px; height: 6px;
516
+ border-left: 2px solid var(--text-on-accent); border-bottom: 2px solid var(--text-on-accent);
517
+ transform: rotate(-45deg) scale(0); transform-origin: center;
518
+ transition: transform var(--duration-base) var(--ease-spring);
519
+ margin-top: -2px;
520
+ }
521
+ .checkbox:checked::after { transform: rotate(-45deg) scale(1); }
522
+ .radio::after {
523
+ content: ""; width: 8px; height: 8px; border-radius: var(--radius-full);
524
+ background: var(--text-on-accent); transform: scale(0);
525
+ transition: transform var(--duration-base) var(--ease-spring);
526
+ }
527
+ .radio:checked::after { transform: scale(1); }
528
+
529
+ /* Switch 44×24 */
530
+ .switch {
531
+ appearance: none; width: 44px; height: 24px; margin: 0; flex: none;
532
+ background: var(--switch-off); border: 0; border-radius: var(--radius-full);
533
+ position: relative; cursor: pointer;
534
+ transition: background-color var(--duration-base) var(--ease-out);
535
+ }
536
+ .switch::after {
537
+ content: ""; position: absolute; top: 2px; left: 2px;
538
+ width: 20px; height: 20px; border-radius: var(--radius-full);
539
+ background: var(--night-50); box-shadow: var(--shadow-1);
540
+ transition: transform var(--duration-base) var(--ease-spring);
541
+ }
542
+ .switch:checked { background: var(--accent-400); }
543
+ .switch:checked::after { transform: translateX(20px); }
544
+
545
+ /* ============================================================
546
+ 11. BADGES Y TAGS
547
+ ============================================================ */
548
+ .badge {
549
+ display: inline-flex; align-items: center; gap: 4px;
550
+ padding: 2px 8px; border-radius: var(--radius-full);
551
+ font-size: var(--text-xs); font-weight: 500; line-height: var(--leading-snug);
552
+ }
553
+ .badge--success { background: var(--success-bg); color: var(--success); border: 1px solid color-mix(in srgb, var(--success) 30%, transparent); }
554
+ .badge--warning { background: var(--warning-bg); color: var(--warning); border: 1px solid color-mix(in srgb, var(--warning) 30%, transparent); }
555
+ .badge--danger { background: var(--danger-bg); color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent); }
556
+ .badge--info { background: var(--info-bg); color: var(--info); border: 1px solid color-mix(in srgb, var(--info) 30%, transparent); }
557
+
558
+ .tag {
559
+ display: inline-flex; align-items: center; gap: 6px;
560
+ padding: 4px 10px; border-radius: var(--radius-full);
561
+ background: var(--surface-2); border: 1px solid var(--border);
562
+ color: var(--text-secondary); font-size: var(--text-xs); font-weight: 500;
563
+ }
564
+ .tag__x {
565
+ display: inline-grid; place-content: center; width: 14px; height: 14px; padding: 0;
566
+ border: 0; border-radius: var(--radius-full); background: transparent;
567
+ color: inherit; cursor: pointer; font-size: 12px; line-height: 1;
568
+ transition: background-color var(--duration-fast) var(--ease-out);
569
+ }
570
+ .tag__x:hover { background: var(--surface-3); }
571
+
572
+ /* ============================================================
573
+ 12. AVATAR — .avatar (xs 24 · sm 32 · md 40 · lg 48 · xl 64)
574
+ ============================================================ */
575
+ .avatar {
576
+ --avatar-size: 40px; --avatar-font: 15px;
577
+ position: relative; display: inline-flex; align-items: center; justify-content: center;
578
+ width: var(--avatar-size); height: var(--avatar-size); flex: none;
579
+ border-radius: var(--radius-full);
580
+ background: var(--indigo-700); border: 1px solid var(--indigo-600);
581
+ color: var(--night-50); font-family: var(--font-display); font-weight: 600;
582
+ font-size: var(--avatar-font); letter-spacing: var(--tracking-display);
583
+ text-transform: uppercase; user-select: none;
584
+ }
585
+ .avatar--xs { --avatar-size: 24px; --avatar-font: 10px; }
586
+ .avatar--sm { --avatar-size: 32px; --avatar-font: 12px; }
587
+ .avatar--lg { --avatar-size: 48px; --avatar-font: 18px; }
588
+ .avatar--xl { --avatar-size: 64px; --avatar-font: 24px; }
589
+ .avatar img {
590
+ width: 100%; height: 100%; object-fit: cover;
591
+ border-radius: inherit;
592
+ }
593
+ .avatar__dot {
594
+ position: absolute; right: 0; bottom: 0;
595
+ width: max(28%, 8px); height: max(28%, 8px);
596
+ border-radius: var(--radius-full); border: 2px solid var(--bg);
597
+ }
598
+ .avatar__dot--online { background: var(--success); }
599
+ .avatar__dot--busy { background: var(--danger); }
600
+ .avatar__dot--away { background: var(--warning); }
601
+ .avatar__dot--offline { background: var(--border); }
602
+
603
+ /* ============================================================
604
+ 12B. DIVIDER — .divider (hairline), .divider--label, .divider--vertical
605
+ ============================================================ */
606
+ .divider { border: 0; border-top: 1px solid var(--border); margin: var(--space-4) 0; }
607
+ .divider--label {
608
+ display: flex; align-items: center; gap: 12px; border: 0; margin: var(--space-4) 0;
609
+ color: var(--text-muted); font-size: var(--text-xs); font-weight: 500;
610
+ text-transform: uppercase; letter-spacing: var(--tracking-overline);
611
+ }
612
+ .divider--label::before, .divider--label::after {
613
+ content: ""; flex: 1; border-top: 1px solid var(--border);
614
+ }
615
+ .divider--vertical {
616
+ display: inline-block; align-self: stretch; width: 1px;
617
+ background: var(--border); border: 0; margin: 0 var(--space-3);
618
+ }
619
+
620
+ /* ============================================================
621
+ 13. STAT — cifra de dashboard con count-up (JS opcional)
622
+ ============================================================ */
623
+ .stat { display: flex; flex-direction: column; gap: 6px; }
624
+ .stat__label {
625
+ font-size: var(--text-xs); font-weight: 500; text-transform: uppercase;
626
+ letter-spacing: var(--tracking-overline); color: var(--text-muted);
627
+ }
628
+ .stat__value {
629
+ font-family: var(--font-mono); font-size: var(--text-5xl); font-weight: 500;
630
+ line-height: var(--leading-tight); color: var(--data-color);
631
+ font-variant-numeric: tabular-nums; white-space: nowrap;
632
+ }
633
+ .stat__delta { font-family: var(--font-mono); font-size: var(--text-sm); display: inline-flex; align-items: center; gap: 4px; }
634
+ .stat__delta--up { color: var(--success); }
635
+ .stat__delta--down { color: var(--danger); }
636
+ .stat__delta--neutral { color: var(--text-muted); }
637
+
638
+ /* ============================================================
639
+ 13B. PAGINATION — .pagination (activa: fondo acento + peso, no solo color)
640
+ ============================================================ */
641
+ .pagination { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
642
+ .pagination__btn {
643
+ display: inline-grid; place-items: center;
644
+ min-width: 36px; height: 36px; padding: 0 8px;
645
+ border: 0; border-radius: var(--radius-sm); background: transparent;
646
+ font-family: var(--font-body); font-size: var(--text-sm); font-weight: 500;
647
+ color: var(--text-secondary); cursor: pointer;
648
+ transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
649
+ }
650
+ .pagination__btn:hover:not(:disabled):not(.is-active) { background: var(--surface-2); color: var(--text-primary); }
651
+ .pagination__btn:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }
652
+ .pagination__btn.is-active {
653
+ background: var(--accent-400); color: var(--text-on-accent); font-weight: 700;
654
+ }
655
+ .pagination__btn:disabled { color: var(--text-disabled); cursor: not-allowed; }
656
+ .pagination__btn svg { width: 16px; height: 16px; }
657
+ .pagination__ellipsis { color: var(--text-disabled); padding: 0 4px; user-select: none; }
658
+
659
+ /* ============================================================
660
+ 14. CARD — elevación nivel 1; interactiva sube de nivel
661
+ ============================================================ */
662
+ .card {
663
+ background: var(--surface-1);
664
+ border: 1px solid var(--card-border);
665
+ border-radius: var(--radius-lg);
666
+ padding: var(--card-padding);
667
+ box-shadow: var(--shadow-1);
668
+ }
669
+ @media (max-width: 639px) { .card { padding: var(--card-padding-mobile); } }
670
+ .card--interactive {
671
+ cursor: pointer;
672
+ transition: transform var(--duration-base) var(--ease-out),
673
+ background-color var(--duration-base) var(--ease-out),
674
+ box-shadow var(--duration-base) var(--ease-out);
675
+ }
676
+ .card--interactive:hover { background: var(--surface-2); }
677
+ @media (hover: hover) and (pointer: fine) {
678
+ .card--interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
679
+ }
680
+ /* Glow de marca: MÁXIMO UNO POR PANTALLA (solo el elemento hero/CTA) */
681
+ .card--glow { box-shadow: var(--glow-accent); }
682
+
683
+ /* ============================================================
684
+ 15. TOOLTIP — .has-tooltip > .tooltip (delay 400ms)
685
+ ============================================================ */
686
+ .has-tooltip { position: relative; display: inline-flex; }
687
+ .tooltip {
688
+ position: absolute; bottom: calc(100% + 8px); left: 50%;
689
+ transform: translate(-50%, 4px);
690
+ background: var(--tooltip-bg); border: 1px solid var(--tooltip-border);
691
+ color: var(--tooltip-text); font-size: var(--text-xs); line-height: var(--leading-snug);
692
+ padding: 6px 10px; border-radius: var(--radius-sm); white-space: nowrap;
693
+ opacity: 0; pointer-events: none;
694
+ transition: opacity var(--duration-fast) var(--ease-out) 0ms,
695
+ transform var(--duration-fast) var(--ease-out) 0ms;
696
+ }
697
+ .has-tooltip:focus-visible .tooltip {
698
+ opacity: 1; transform: translate(-50%, 0);
699
+ transition-delay: 400ms, 400ms;
700
+ }
701
+ /* Tooltip por hover solo con puntero real — en touch quedaría pegado tras el tap */
702
+ @media (hover: hover) and (pointer: fine) {
703
+ .has-tooltip:hover .tooltip {
704
+ opacity: 1; transform: translate(-50%, 0);
705
+ transition-delay: 400ms, 400ms;
706
+ }
707
+ }
708
+
709
+ /* ============================================================
710
+ ALERT — .alert (banner inline persistente; vs Toast, transitorio)
711
+ Estado por icono + texto + color — nunca solo color.
712
+ ============================================================ */
713
+ .alert {
714
+ display: flex; gap: 12px; align-items: flex-start;
715
+ padding: 14px 16px; border-radius: var(--radius-md); border: 1px solid;
716
+ font-size: var(--text-sm);
717
+ }
718
+ .alert > svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }
719
+ .alert__title { font-weight: 600; margin: 0 0 2px; color: inherit; }
720
+ .alert__body { margin: 0; color: inherit; opacity: .88; }
721
+ .alert__close {
722
+ margin-left: auto; flex: none; display: grid; place-items: center;
723
+ width: 36px; height: 36px; border: 0; border-radius: var(--radius-sm);
724
+ background: transparent; color: inherit; cursor: pointer; opacity: .75;
725
+ transition: opacity var(--duration-fast) var(--ease-out), background-color var(--duration-fast) var(--ease-out);
726
+ }
727
+ .alert__close:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }
728
+ .alert__close svg { width: 18px; height: 18px; }
729
+ .alert--info { background: var(--info-bg); color: var(--info); border-color: color-mix(in srgb, var(--info) 30%, transparent); }
730
+ .alert--success { background: var(--success-bg); color: var(--success); border-color: color-mix(in srgb, var(--success) 30%, transparent); }
731
+ .alert--warning { background: var(--warning-bg); color: var(--warning); border-color: color-mix(in srgb, var(--warning) 30%, transparent); }
732
+ .alert--danger { background: var(--danger-bg); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
733
+ .alert.is-leaving { animation: ne-alert-out 200ms var(--ease-in) forwards; }
734
+ @keyframes ne-alert-out { to { opacity: 0; transform: scale(.98); } }
735
+
736
+ /* ============================================================
737
+ 16. TOAST — .toast-stack (fixed) + .toast
738
+ ============================================================ */
739
+ .toast-stack {
740
+ position: fixed; top: var(--space-4); right: var(--space-4); z-index: 90;
741
+ display: flex; flex-direction: column; gap: 12px; width: 360px; max-width: calc(100vw - 32px);
742
+ }
743
+ @media (max-width: 639px) { .toast-stack { right: 50%; transform: translateX(50%); } }
744
+ .toast {
745
+ display: flex; gap: 10px; align-items: flex-start;
746
+ background: var(--surface-2); border: 1px solid var(--elevated-border);
747
+ border-left-width: 3px; border-radius: var(--radius-md);
748
+ padding: 14px 16px; box-shadow: var(--shadow-3);
749
+ /* Entrada interrumpible (§11.2): transition + @starting-style, no @keyframes —
750
+ un keyframe no puede invertirse si el toast se apila o se descarta a mitad. */
751
+ opacity: 1; transform: none;
752
+ transition: opacity var(--duration-slow) var(--ease-out),
753
+ transform var(--duration-slow) var(--ease-out);
754
+ }
755
+ @starting-style {
756
+ .toast { opacity: 0; transform: translateX(24px); }
757
+ }
758
+ .toast--success { border-left-color: var(--success); } .toast--success > svg { color: var(--success); }
759
+ .toast--warning { border-left-color: var(--warning); } .toast--warning > svg { color: var(--warning); }
760
+ .toast--danger { border-left-color: var(--danger); } .toast--danger > svg { color: var(--danger); }
761
+ .toast--info { border-left-color: var(--info); } .toast--info > svg { color: var(--info); }
762
+ .toast > svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }
763
+ .toast__title { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); }
764
+ .toast__body { font-size: var(--text-sm); color: var(--text-muted); }
765
+ .toast.is-leaving { animation: ne-toast-out 200ms var(--ease-in) forwards; }
766
+ @keyframes ne-toast-out { to { opacity: 0; transform: translateX(24px); } }
767
+
768
+ /* ============================================================
769
+ 17. MODAL — .modal-overlay + .modal
770
+ ============================================================ */
771
+ .modal-overlay {
772
+ position: fixed; inset: 0; z-index: 100;
773
+ display: grid; place-items: center; padding: var(--space-4);
774
+ background: var(--overlay); backdrop-filter: blur(4px);
775
+ animation: ne-fade var(--duration-base) var(--ease-out);
776
+ }
777
+ .modal-overlay[hidden] { display: none; }
778
+ .modal {
779
+ width: 100%; max-width: 480px;
780
+ background: var(--surface-2); border: 1px solid var(--elevated-border);
781
+ border-radius: var(--radius-lg); box-shadow: var(--shadow-3);
782
+ padding: var(--card-padding);
783
+ animation: ne-modal-in var(--duration-slow) var(--ease-out);
784
+ }
785
+ .modal--lg { max-width: 640px; }
786
+ .modal__header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-4); }
787
+ .modal__title { font-family: var(--font-body); font-size: var(--text-xl); font-weight: 600; color: var(--text-heading); margin: 0; }
788
+ .modal__footer { display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: var(--space-6); }
789
+ @keyframes ne-fade { from { opacity: 0; } }
790
+ @keyframes ne-modal-in { from { opacity: 0; transform: scale(.96); } }
791
+
792
+ /* ============================================================
793
+ 18. TABLA — .table
794
+ ============================================================ */
795
+ .table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
796
+ .table th {
797
+ background: var(--table-header-bg);
798
+ font-size: var(--text-xs); font-weight: 500; text-transform: uppercase;
799
+ letter-spacing: var(--tracking-overline); color: var(--text-muted);
800
+ text-align: left; padding: 12px 16px;
801
+ border-bottom: 1px solid var(--border-strong);
802
+ }
803
+ .table td {
804
+ height: 52px; padding: 8px 16px;
805
+ border-bottom: 1px solid var(--row-border);
806
+ color: var(--text-secondary);
807
+ }
808
+ .table tbody tr { transition: background-color var(--duration-fast) var(--ease-out); }
809
+ .table tbody tr:hover { background: var(--row-hover); }
810
+ .table tbody tr.is-selected { background: var(--accent-selected); box-shadow: inset 2px 0 0 var(--accent-400); }
811
+ .table .num, .table td.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
812
+
813
+ /* ============================================================
814
+ 19. NAVEGACIÓN — .navbar, .sidebar, .tabs, .breadcrumbs
815
+ ============================================================ */
816
+ .navbar {
817
+ position: sticky; top: 0; z-index: 50;
818
+ display: flex; align-items: center; gap: var(--space-6);
819
+ height: 64px; padding: 0 var(--space-6);
820
+ background: var(--navbar-bg); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
821
+ border-bottom: 1px solid var(--elevated-border);
822
+ }
823
+ .navbar__links { display: flex; gap: var(--space-2); align-items: center; height: 100%; }
824
+ .navbar__link {
825
+ position: relative; display: inline-flex; align-items: center; height: 100%;
826
+ padding: 0 var(--space-3); color: var(--text-secondary); font-size: var(--text-sm); font-weight: 500;
827
+ transition: color var(--duration-fast) var(--ease-out);
828
+ }
829
+ .navbar__link:hover { color: var(--text-primary); }
830
+ .navbar__link.is-active { color: var(--nav-active); }
831
+ .navbar__link.is-active::after {
832
+ content: ""; position: absolute; left: var(--space-3); right: var(--space-3); bottom: 0;
833
+ height: 2px; background: var(--accent-400);
834
+ }
835
+
836
+ .sidebar {
837
+ width: 260px; padding: var(--space-3);
838
+ background: var(--sidebar-bg); border-right: 1px solid var(--row-border);
839
+ display: flex; flex-direction: column; gap: 2px;
840
+ }
841
+ .sidebar__item {
842
+ display: flex; align-items: center; gap: 10px;
843
+ padding: 10px 12px; border-radius: var(--radius-md);
844
+ color: var(--text-secondary); font-size: var(--text-sm); font-weight: 500;
845
+ transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
846
+ }
847
+ .sidebar__item:hover { background: var(--surface-2); color: var(--text-primary); }
848
+ .sidebar__item.is-active { background: var(--sidebar-active-bg); color: var(--sidebar-active-text); }
849
+ .sidebar__item svg { width: 18px; height: 18px; color: var(--text-muted); flex: none; }
850
+ .sidebar__item.is-active svg { color: var(--sidebar-active-icon); }
851
+
852
+ .tabs { position: relative; display: flex; gap: var(--space-2); border-bottom: 1px solid var(--border-strong); }
853
+ .tabs__btn {
854
+ padding: 10px 14px; border: 0; background: transparent; cursor: pointer;
855
+ color: var(--text-secondary); font-family: var(--font-body); font-size: var(--text-sm); font-weight: 500;
856
+ transition: color var(--duration-fast) var(--ease-out);
857
+ }
858
+ .tabs__btn:hover { color: var(--text-primary); }
859
+ .tabs__btn.is-active { color: var(--text-primary); }
860
+ .tabs__indicator {
861
+ position: absolute; bottom: -1px; left: 0; height: 2px; width: 0;
862
+ background: var(--accent-400);
863
+ /* Se mueve de A a B en pantalla → --ease-in-out (§11.2) */
864
+ transition: transform var(--duration-slow) var(--ease-in-out), width var(--duration-slow) var(--ease-in-out);
865
+ }
866
+
867
+ .breadcrumbs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); list-style: none; margin: 0; padding: 0; font-size: var(--text-sm); }
868
+ .breadcrumbs li { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--text-muted); }
869
+ .breadcrumbs li + li::before { content: "/"; color: var(--text-disabled); }
870
+ .breadcrumbs a { color: var(--text-muted); } .breadcrumbs a:hover { color: var(--text-primary); }
871
+ .breadcrumbs li:last-child { color: var(--text-primary); }
872
+
873
+ /* ============================================================
874
+ 20. ACCORDION — .accordion (animación grid-template-rows)
875
+ ============================================================ */
876
+ .accordion { border: 1px solid var(--elevated-border); border-radius: var(--radius-lg); overflow: hidden; }
877
+ .accordion__item { background: var(--surface-1); }
878
+ .accordion__item + .accordion__item { border-top: 1px solid var(--row-border); }
879
+ .accordion__header {
880
+ display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
881
+ width: 100%; padding: 16px 20px; border: 0; background: transparent; cursor: pointer;
882
+ color: var(--text-primary); font-family: var(--font-body); font-size: var(--text-base); font-weight: 500; text-align: left;
883
+ transition: background-color var(--duration-fast) var(--ease-out);
884
+ }
885
+ .accordion__header:hover { background: var(--surface-2); }
886
+ .accordion__header svg {
887
+ width: 18px; height: 18px; color: var(--text-muted); flex: none;
888
+ transition: transform var(--duration-slow) var(--ease-out);
889
+ }
890
+ .accordion__header[aria-expanded="true"] svg { transform: rotate(180deg); }
891
+ .accordion__panel {
892
+ display: grid; grid-template-rows: 0fr;
893
+ transition: grid-template-rows var(--duration-slow) var(--ease-out);
894
+ }
895
+ .accordion__header[aria-expanded="true"] + .accordion__panel { grid-template-rows: 1fr; }
896
+ .accordion__inner { overflow: hidden; }
897
+ .accordion__content {
898
+ padding: 0 20px 18px; font-size: 15px; line-height: var(--leading-body); color: var(--text-muted);
899
+ opacity: 0; transition: opacity var(--duration-slow) var(--ease-out);
900
+ }
901
+ .accordion__header[aria-expanded="true"] + .accordion__panel .accordion__content { opacity: 1; }
902
+
903
+ /* ============================================================
904
+ 21. PROGRESS BAR — .progress (con glow de acento)
905
+ ============================================================ */
906
+ .progress__head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
907
+ .progress__label { font-size: var(--text-sm); color: var(--text-secondary); }
908
+ .progress__value { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--data-color); font-variant-numeric: tabular-nums; }
909
+ .progress {
910
+ height: 6px; background: var(--surface-3); border-radius: var(--radius-full); overflow: hidden;
911
+ }
912
+ .progress__bar {
913
+ height: 100%; width: 0; background: var(--accent-400); border-radius: inherit;
914
+ box-shadow: 0 0 12px rgba(82,186,237,.5);
915
+ transition: width 300ms var(--ease-out);
916
+ }
917
+ .progress--no-glow .progress__bar { box-shadow: none; }
918
+ .progress--indeterminate .progress__bar { width: 40%; animation: ne-sweep 1.2s var(--ease-out) infinite; }
919
+ @keyframes ne-sweep { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
920
+
921
+ .progress-ring { display: inline-grid; place-items: center; position: relative; }
922
+ .progress-ring svg { transform: rotate(-90deg); }
923
+ .progress-ring__track { fill: none; stroke: var(--surface-3); }
924
+ .progress-ring__bar {
925
+ fill: none; stroke: var(--accent-400); stroke-linecap: round;
926
+ transition: stroke-dashoffset var(--duration-slow) var(--ease-out);
927
+ }
928
+ .progress-ring__value {
929
+ position: absolute; font-family: var(--font-mono); font-size: var(--text-sm);
930
+ font-weight: 600; color: var(--data-color); font-variant-numeric: tabular-nums;
931
+ }
932
+ @media (prefers-reduced-motion: reduce) {
933
+ .progress-ring__bar { transition-duration: 0.01ms !important; }
934
+ }
935
+
936
+ /* ============================================================
937
+ 22. LINK Y CODE — .link (subrayado animado), .code (inline)
938
+ ============================================================ */
939
+ .link { position: relative; display: inline-flex; align-items: center; gap: 4px; color: var(--link); }
940
+ .link::after {
941
+ content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
942
+ background: currentColor; transform: scaleX(0); transform-origin: left;
943
+ transition: transform 200ms var(--ease-out);
944
+ }
945
+ .link:hover { color: var(--link-hover); }
946
+ .link:hover::after { transform: scaleX(1); }
947
+ .link svg { width: 12px; height: 12px; }
948
+
949
+ .code {
950
+ font-family: var(--font-mono); font-size: .9em;
951
+ color: var(--code-color); background: var(--surface-2);
952
+ border: 1px solid var(--code-border); border-radius: 6px; padding: 1px 6px;
953
+ }
954
+
955
+ /* ============================================================
956
+ 23. SKELETON Y EMPTY STATE
957
+ ============================================================ */
958
+ .skeleton {
959
+ position: relative; overflow: hidden;
960
+ background: var(--skeleton-base); border-radius: var(--radius-sm);
961
+ }
962
+ .skeleton--circle { border-radius: var(--radius-full); }
963
+ .skeleton::after {
964
+ content: ""; position: absolute; inset: 0;
965
+ background: linear-gradient(90deg, transparent, var(--skeleton-sheen), transparent);
966
+ transform: translateX(-100%);
967
+ animation: ne-shimmer 1.4s infinite;
968
+ }
969
+ @keyframes ne-shimmer { to { transform: translateX(100%); } }
970
+
971
+ .empty-state {
972
+ display: flex; flex-direction: column; align-items: center; text-align: center;
973
+ gap: var(--space-2); padding: var(--space-10) var(--space-6);
974
+ }
975
+ .empty-state svg { width: 40px; height: 40px; color: var(--empty-icon); margin-bottom: var(--space-2); }
976
+ .empty-state__title { font-size: var(--text-lg); font-weight: 600; color: var(--text-primary); }
977
+ .empty-state__desc { font-size: var(--text-sm); color: var(--text-muted); max-width: 36ch; }
978
+ .empty-state .btn { margin-top: var(--space-3); }
979
+
980
+ /* ============================================================
981
+ 24. UTILIDADES MÍNIMAS
982
+ ============================================================ */
983
+ .overline {
984
+ font-size: var(--text-xs); font-weight: 500; text-transform: uppercase;
985
+ letter-spacing: var(--tracking-overline); color: var(--text-muted);
986
+ }
987
+ .text-muted { color: var(--text-muted); }
988
+ .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
989
+ .visually-hidden {
990
+ position: absolute; width: 1px; height: 1px; margin: -1px;
991
+ clip-path: inset(50%); overflow: hidden; white-space: nowrap;
992
+ }