@higinio/design-mcp 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,7 @@
16
16
  /* -- Primitivos: acento -- */
17
17
  --accent-100: #d9f0fb; --accent-200: #a8ddf6; --accent-300: #7dccf1;
18
18
  --accent-400: #52baed; --accent-500: #2fa3dd; --accent-600: #1f87bb; --accent-700: #186a94;
19
+ --accent-800: #12506f; /* solo light: texto de acción en hover */
19
20
 
20
21
  /* -- Primitivos: índigo -- */
21
22
  --indigo-300: #7a83c4; --indigo-400: #565fa3; --indigo-500: #353d7c;
@@ -24,6 +25,7 @@
24
25
  /* -- Primitivos: escala nocturna -- */
25
26
  --night-950: #010203; --night-900: #0b0d12; --night-800: #14171f;
26
27
  --night-700: #1e222d; --night-600: #2a2f3d; --night-500: #3d4354;
28
+ --night-450: #5f6575; /* texto atenuado en light */
27
29
  --night-400: #6b7183; --night-300: #9aa0b0; --night-200: #c5c9d4;
28
30
  --night-100: #e8eaef; --night-50: #f6f7f9;
29
31
 
@@ -146,27 +148,28 @@
146
148
  --border-strong: #b9c3d1;
147
149
  --text-primary: #14171f;
148
150
  --text-secondary: #3d4354;
149
- --text-muted: #6b7183;
151
+ --text-muted: #5f6575; /* night-400 caía a 4.27:1 sobre --surface-3 */
150
152
  --text-disabled: #9aa0b0;
151
153
  --text-heading: #0b0d12;
152
154
  --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;
155
+ /* Los semánticos son texto sobre su propio --*-bg tintado: se calibran contra ese fondo. */
156
+ --success: #166534; --success-bg: #e3f5ea;
157
+ --warning: #854d0e; --warning-bg: #fbf3dd;
158
+ --danger: #b02c2c; --danger-bg: #fbe7e7;
159
+ --info: #186a94; --info-bg: #e3f2fb;
157
160
  --accent-ghost-hover: rgba(31,135,187,.08);
158
161
  --accent-ghost-active: rgba(31,135,187,.14);
159
162
  --accent-selected: rgba(82,186,237,.12);
160
163
  --overlay: rgba(20,23,31,.45);
161
164
 
162
- --link: #1f87bb;
163
- --link-hover: #186a94;
164
- --focus-color: #1f87bb;
165
+ --link: #186a94; /* accent-700 · 5.95:1 — accent-600 solo daba 4.01:1 */
166
+ --link-hover: #12506f; /* accent-800 · en light el hover oscurece */
167
+ --focus-color: #1f87bb; /* accent-600 se queda: es UI (4.01 ≥ 3), no texto */
165
168
  --border-hover: #b9c3d1;
166
169
  --outline-hover-bg: #eaf1f7;
167
170
  --outline-active-bg: #d8dfe8;
168
171
  --text-on-danger: #ffffff;
169
- --data-color: #1f87bb;
172
+ --data-color: #186a94; /* pinta cifras y .progress__value: es TEXTO, necesita 4.5 */
170
173
  --elevated-border: #d8dfe8;
171
174
  --card-border: #d8dfe8;
172
175
  --code-color: #186a94;
@@ -376,6 +379,8 @@ a:hover { color: var(--link-hover); }
376
379
  ============================================================ */
377
380
  .field { display: flex; flex-direction: column; margin-bottom: var(--form-gap); }
378
381
  .field__label { font-size: var(--text-sm); font-weight: 500; color: var(--text-secondary); margin-bottom: 6px; }
382
+ /* Campo obligatorio: asterisco decorativo; la semántica va en required/aria-required del control */
383
+ .field--required > .field__label::after { content: "*"; margin-left: 2px; color: var(--danger); font-weight: 600; }
379
384
  .field__help { font-size: var(--text-sm); color: var(--text-muted); margin-top: 6px; }
380
385
  .field__error {
381
386
  display: inline-flex; align-items: center; gap: 6px;
@@ -519,6 +524,12 @@ a:hover { color: var(--link-hover); }
519
524
  margin-top: -2px;
520
525
  }
521
526
  .checkbox:checked::after { transform: rotate(-45deg) scale(1); }
527
+ /* Indeterminate: guion horizontal, no el check. Solo por JS (el.indeterminate = true) */
528
+ .checkbox:indeterminate { background: var(--accent-400); border-color: var(--accent-400); }
529
+ .checkbox:indeterminate::after {
530
+ content: ""; width: 10px; height: 2px; margin-top: 0;
531
+ border: 0; border-radius: var(--radius-full); background: var(--text-on-accent); transform: none;
532
+ }
522
533
  .radio::after {
523
534
  content: ""; width: 8px; height: 8px; border-radius: var(--radius-full);
524
535
  background: var(--text-on-accent); transform: scale(0);
@@ -600,6 +611,17 @@ a:hover { color: var(--link-hover); }
600
611
  .avatar__dot--away { background: var(--warning); }
601
612
  .avatar__dot--offline { background: var(--border); }
602
613
 
614
+ /* AvatarGroup — avatares solapados + chip +N.
615
+ Borde 2px del color del fondo (--surface-1 en tarjetas, --bg en el lienzo) para separar. */
616
+ .avatar-group { display: inline-flex; align-items: center; }
617
+ .avatar-group .avatar { border: 2px solid var(--surface-1); }
618
+ .avatar-group .avatar:not(:first-child) { margin-left: -8px; }
619
+ .avatar-group__more {
620
+ background: var(--surface-3); color: var(--text-secondary);
621
+ font-family: var(--font-body); font-weight: 600;
622
+ letter-spacing: 0; text-transform: none;
623
+ }
624
+
603
625
  /* ============================================================
604
626
  12B. DIVIDER — .divider (hairline), .divider--label, .divider--vertical
605
627
  ============================================================ */
@@ -807,9 +829,39 @@ a:hover { color: var(--link-hover); }
807
829
  }
808
830
  .table tbody tr { transition: background-color var(--duration-fast) var(--ease-out); }
809
831
  .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
832
  .table .num, .table td.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
812
833
 
834
+ /* Zebra — filas pares en surface-2; hover y selección mandan sobre la banda */
835
+ .table--zebra tbody tr:nth-child(even) { background: var(--surface-2); }
836
+ .table--zebra tbody tr:hover { background: var(--row-hover); }
837
+
838
+ /* Sticky header — dentro de un contenedor con overflow: auto y altura acotada */
839
+ .table--sticky thead th { position: sticky; top: 0; z-index: 1; }
840
+
841
+ /* Header ordenable — botón dentro del th + icono; el estado vive en aria-sort del th */
842
+ .th-sort {
843
+ display: inline-flex; align-items: center; gap: 6px;
844
+ margin: 0; padding: 0; border: 0; background: transparent;
845
+ font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
846
+ cursor: pointer;
847
+ }
848
+ .th-sort:hover { color: var(--text-secondary); }
849
+ .th-sort:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-sm); }
850
+ .sort-icon {
851
+ width: 14px; height: 14px; flex: none; opacity: .45;
852
+ transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
853
+ }
854
+ .table th[aria-sort="ascending"] .sort-icon,
855
+ .table th[aria-sort="descending"] .sort-icon { opacity: 1; color: var(--accent-400); }
856
+ .table th[aria-sort="descending"] .sort-icon { transform: rotate(180deg); }
857
+
858
+ /* Columna de selección (checkbox en th y en cada fila) */
859
+ .table .col-select { width: 44px; text-align: center; padding-left: var(--space-2); padding-right: var(--space-2); }
860
+
861
+ /* Fila seleccionada — .row--selected (contrato); .is-selected se mantiene como alias */
862
+ .table tbody tr.is-selected,
863
+ .table tbody tr.row--selected { background: var(--accent-selected); box-shadow: inset 2px 0 0 var(--accent-400); }
864
+
813
865
  /* ============================================================
814
866
  19. NAVEGACIÓN — .navbar, .sidebar, .tabs, .breadcrumbs
815
867
  ============================================================ */
@@ -990,3 +1042,270 @@ a:hover { color: var(--link-hover); }
990
1042
  position: absolute; width: 1px; height: 1px; margin: -1px;
991
1043
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
992
1044
  }
1045
+
1046
+ /* ============================================================
1047
+ 25. COMBOBOX / AUTOCOMPLETE — .combobox + SEARCH — .search
1048
+ El listado vive sobre --surface-2 (superficie de dropdowns).
1049
+ ============================================================ */
1050
+ .combobox { position: relative; }
1051
+ .combobox__input { width: 100%; } /* consume .input para el resto de estilos */
1052
+ .combobox__list {
1053
+ position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 40;
1054
+ margin: 0; padding: 6px; list-style: none; max-height: 264px; overflow: auto;
1055
+ background: var(--surface-2); border: 1px solid var(--elevated-border);
1056
+ border-radius: var(--radius-md); box-shadow: var(--shadow-3);
1057
+ }
1058
+ .combobox__list[hidden] { display: none; }
1059
+ .combobox__option {
1060
+ display: flex; align-items: center; gap: 10px; width: 100%;
1061
+ padding: 10px 12px; border-radius: var(--radius-sm);
1062
+ color: var(--text-primary); font-size: var(--text-sm); cursor: pointer;
1063
+ transition: background-color var(--duration-fast) var(--ease-out);
1064
+ }
1065
+ .combobox__option[hidden] { display: none; }
1066
+ /* .is-active = resaltado por teclado; [aria-selected] = la elegida (fondo + icono, no solo color) */
1067
+ .combobox__option.is-active { background: var(--surface-3); }
1068
+ .combobox__option[aria-selected="true"] { background: var(--accent-selected); color: var(--accent-300); }
1069
+ [data-theme="light"] .combobox__option[aria-selected="true"] { color: var(--link); }
1070
+ .combobox__check { display: none; margin-left: auto; width: 16px; height: 16px; color: var(--accent-400); flex: none; }
1071
+ .combobox__option[aria-selected="true"] .combobox__check { display: block; }
1072
+
1073
+ /* Search — wrapper con lupa (aria-hidden) + botón limpiar (×, aria-label="Limpiar") */
1074
+ .search { position: relative; display: flex; align-items: center; }
1075
+ .search__icon {
1076
+ position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
1077
+ width: 18px; height: 18px; color: var(--text-disabled); pointer-events: none;
1078
+ }
1079
+ .search__input { width: 100%; padding-left: 40px; padding-right: 40px; } /* consume .input */
1080
+ /* Oculta el clear nativo de WebKit para no duplicar el affordance del .search__clear */
1081
+ .search__input::-webkit-search-cancel-button,
1082
+ .search__input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
1083
+ .search__clear {
1084
+ position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
1085
+ display: inline-grid; place-content: center; width: 28px; height: 28px; padding: 0;
1086
+ border: 0; border-radius: var(--radius-full); background: transparent;
1087
+ color: var(--text-muted); cursor: pointer;
1088
+ transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
1089
+ }
1090
+ .search__clear:hover { background: var(--surface-3); color: var(--text-primary); }
1091
+ .search__clear svg { width: 16px; height: 16px; }
1092
+ .search__clear[hidden] { display: none; }
1093
+
1094
+ /* ============================================================
1095
+ 26. DRAWER / SHEET — .drawer + __overlay + __panel (focus-trap por JS)
1096
+ Motion: transform translate + fade del overlay (--duration-slow).
1097
+ El overlay reutiliza --overlay del modal; SIN blur nuevo.
1098
+ ============================================================ */
1099
+ .drawer { position: fixed; inset: 0; z-index: 100; }
1100
+ .drawer[hidden] { display: none; }
1101
+ .drawer__overlay {
1102
+ position: absolute; inset: 0; background: var(--overlay);
1103
+ opacity: 0; transition: opacity var(--duration-slow) var(--ease-out);
1104
+ }
1105
+ .drawer.is-open .drawer__overlay { opacity: 1; }
1106
+ .drawer__panel {
1107
+ position: absolute; top: 0; right: 0; bottom: 0;
1108
+ display: flex; flex-direction: column;
1109
+ width: min(400px, 100%); padding: var(--card-padding);
1110
+ background: var(--surface-2); border-left: 1px solid var(--elevated-border);
1111
+ box-shadow: var(--shadow-3);
1112
+ overflow-y: auto; overscroll-behavior: contain;
1113
+ transform: translateX(100%);
1114
+ transition: transform var(--duration-slow) var(--ease-out);
1115
+ }
1116
+ .drawer.is-open .drawer__panel { transform: none; }
1117
+ /* Variante izquierda */
1118
+ .drawer--left .drawer__panel {
1119
+ right: auto; left: 0; border-left: 0; border-right: 1px solid var(--elevated-border);
1120
+ transform: translateX(-100%);
1121
+ }
1122
+ .drawer--left.is-open .drawer__panel { transform: none; }
1123
+ /* Variante inferior (sheet) */
1124
+ .drawer--bottom .drawer__panel {
1125
+ top: auto; left: 0; right: 0; width: 100%; max-height: 80dvh;
1126
+ border-left: 0; border-top: 1px solid var(--elevated-border);
1127
+ border-radius: var(--radius-lg) var(--radius-lg) 0 0;
1128
+ transform: translateY(100%);
1129
+ }
1130
+ .drawer--bottom.is-open .drawer__panel { transform: none; }
1131
+ .drawer__header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-4); }
1132
+ .drawer__title { font-family: var(--font-body); font-size: var(--text-xl); font-weight: 600; letter-spacing: normal; color: var(--text-heading); margin: 0; }
1133
+ .drawer__body { flex: 1; }
1134
+ .drawer__footer { display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: var(--space-6); }
1135
+
1136
+ /* ============================================================
1137
+ 27. POPOVER — .popover + __trigger + __panel (abre por CLICK)
1138
+ Motion: fade + scale(0.96→1) desde el transform-origin del trigger.
1139
+ Panel sobre --surface-2. Se distingue del Tooltip: click, no hover.
1140
+ ============================================================ */
1141
+ .popover { position: relative; display: inline-flex; }
1142
+ .popover__panel {
1143
+ position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
1144
+ min-width: 240px; max-width: 320px; padding: var(--space-4);
1145
+ background: var(--surface-2); border: 1px solid var(--elevated-border);
1146
+ border-radius: var(--radius-md); box-shadow: var(--shadow-3);
1147
+ transform-origin: top left; /* origin-aware: crece desde el disparador */
1148
+ opacity: 0; transform: scale(.96); visibility: hidden;
1149
+ transition: opacity var(--duration-base) var(--ease-out),
1150
+ transform var(--duration-base) var(--ease-out),
1151
+ visibility 0s linear var(--duration-base);
1152
+ }
1153
+ .popover.is-open .popover__panel {
1154
+ opacity: 1; transform: none; visibility: visible;
1155
+ transition: opacity var(--duration-base) var(--ease-out),
1156
+ transform var(--duration-base) var(--ease-out),
1157
+ visibility 0s;
1158
+ }
1159
+ /* Alineado a la derecha del disparador */
1160
+ .popover--right .popover__panel { left: auto; right: 0; transform-origin: top right; }
1161
+
1162
+ /* ============================================================
1163
+ 28. BUTTON GROUP — .btn-group (bordes compartidos, radios en extremos)
1164
+ ============================================================ */
1165
+ .btn-group { display: inline-flex; }
1166
+ .btn-group > .btn { border-radius: 0; }
1167
+ .btn-group > .btn:not(:first-child) { margin-left: -1px; }
1168
+ .btn-group > .btn:first-child { border-top-left-radius: var(--radius-md); border-bottom-left-radius: var(--radius-md); }
1169
+ .btn-group > .btn:last-child { border-top-right-radius: var(--radius-md); border-bottom-right-radius: var(--radius-md); }
1170
+ /* El botón enfocado/hover sube de z-index para que su borde no lo tape el vecino */
1171
+ .btn-group > .btn:hover, .btn-group > .btn:focus-visible, .btn-group > .btn.is-active { z-index: 1; }
1172
+
1173
+ /* ============================================================
1174
+ 29. DATEPICKER — .datepicker + calendario en popover
1175
+ El panel reutiliza el look de .popover__panel sobre --surface-2.
1176
+ Grid role="grid"; días como <button role="gridcell">.
1177
+ ============================================================ */
1178
+ .datepicker { position: relative; }
1179
+ .datepicker__input { cursor: pointer; } /* consume .input; el icono va con .input-wrap */
1180
+ .datepicker__calendar {
1181
+ position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
1182
+ padding: var(--space-4);
1183
+ background: var(--surface-2); border: 1px solid var(--elevated-border);
1184
+ border-radius: var(--radius-md); box-shadow: var(--shadow-3);
1185
+ }
1186
+ .datepicker__calendar[hidden] { display: none; }
1187
+
1188
+ .calendar { width: 252px; }
1189
+ .calendar__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-3); }
1190
+ .calendar__title { font-size: var(--text-sm); font-weight: 600; color: var(--text-heading); } /* mes en minúscula (es) */
1191
+ .calendar__weekdays { display: grid; grid-template-columns: repeat(7, 1fr); margin-bottom: var(--space-1); }
1192
+ .calendar__weekdays span {
1193
+ display: grid; place-items: center; height: 28px;
1194
+ font-size: var(--text-xs); font-weight: 500; color: var(--text-muted);
1195
+ }
1196
+ .calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
1197
+ .calendar__week { display: contents; } /* fila semántica (role="row") sin romper el grid */
1198
+ .calendar__day {
1199
+ display: grid; place-items: center; width: 100%; height: 36px; padding: 0;
1200
+ border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent;
1201
+ color: var(--text-primary); font-family: var(--font-mono); font-size: var(--text-sm);
1202
+ font-variant-numeric: tabular-nums; cursor: pointer;
1203
+ transition: background-color var(--duration-fast) var(--ease-out),
1204
+ color var(--duration-fast) var(--ease-out);
1205
+ }
1206
+ .calendar__day:hover:not([disabled]):not(.calendar__day--selected) { background: var(--surface-3); }
1207
+ /* Hoy: aro de acento por borde (no glow) + texto de acento */
1208
+ .calendar__day--today { border-color: var(--accent-400); color: var(--accent-300); }
1209
+ /* Seleccionado: fondo de acento + texto oscuro + peso — no depende solo del color */
1210
+ .calendar__day--selected { background: var(--accent-400); border-color: var(--accent-400); color: var(--text-on-accent); font-weight: 600; }
1211
+ .calendar__day--outside { color: var(--text-disabled); }
1212
+ .calendar__day[disabled] { color: var(--text-disabled); opacity: .5; cursor: not-allowed; }
1213
+
1214
+ /* ============================================================
1215
+ 30. FILE UPLOAD — .file-upload (dropzone) + __list
1216
+ El input file real va oculto accesiblemente (.visually-hidden).
1217
+ ============================================================ */
1218
+ .file-upload { display: block; }
1219
+ .file-upload__label {
1220
+ display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
1221
+ padding: var(--space-8) var(--space-6); text-align: center;
1222
+ background: var(--surface-1); border: 1px dashed var(--border-strong);
1223
+ border-radius: var(--radius-lg); color: var(--text-muted); cursor: pointer;
1224
+ transition: border-color var(--duration-fast) var(--ease-out),
1225
+ background-color var(--duration-fast) var(--ease-out),
1226
+ color var(--duration-fast) var(--ease-out);
1227
+ }
1228
+ .file-upload__label > svg { width: 28px; height: 28px; color: var(--text-muted); }
1229
+ .file-upload__button { color: var(--link); font-weight: 600; }
1230
+ .file-upload__hint { font-size: var(--text-xs); color: var(--text-disabled); }
1231
+ @media (hover: hover) and (pointer: fine) {
1232
+ .file-upload__label:hover { border-color: var(--border-hover); background: var(--surface-2); color: var(--text-secondary); }
1233
+ }
1234
+ /* El ring se pinta sobre el label porque el input está oculto */
1235
+ .file-upload__input:focus-visible + .file-upload__label { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }
1236
+ /* Arrastrando encima: acento (icono + borde, no solo color) */
1237
+ .file-upload.is-dragover .file-upload__label { border-color: var(--accent-400); background: var(--accent-ghost-hover); color: var(--text-secondary); }
1238
+
1239
+ .file-upload__list { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
1240
+ .file-upload__item {
1241
+ display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-3);
1242
+ padding: var(--space-3); background: var(--surface-2);
1243
+ border: 1px solid var(--border); border-radius: var(--radius-md);
1244
+ }
1245
+ .file-upload__item > svg { width: 20px; height: 20px; color: var(--text-muted); flex: none; }
1246
+ .file-upload__item > div { min-width: 0; } /* permite truncar el nombre */
1247
+ .file-upload__item .progress { margin-top: var(--space-2); }
1248
+ .file-upload__name { display: block; font-size: var(--text-sm); color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1249
+ .file-upload__size { display: block; font-size: var(--text-xs); color: var(--text-muted); font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
1250
+ /* Error: borde + icono + texto en danger, nunca solo por color */
1251
+ .file-upload__item--error { border-color: color-mix(in srgb, var(--danger) 45%, transparent); background: var(--danger-bg); }
1252
+ .file-upload__item--error > svg { color: var(--danger); }
1253
+ .file-upload__item--error .file-upload__size { color: var(--danger); }
1254
+ .file-upload__remove {
1255
+ display: inline-grid; place-content: center; width: 28px; height: 28px; padding: 0; flex: none;
1256
+ border: 0; border-radius: var(--radius-full); background: transparent;
1257
+ color: var(--text-muted); cursor: pointer;
1258
+ transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
1259
+ }
1260
+ .file-upload__remove:hover { background: var(--surface-3); color: var(--text-primary); }
1261
+ .file-upload__remove svg { width: 16px; height: 16px; }
1262
+
1263
+ /* ============================================================
1264
+ 31. STEPPER / WIZARD — .stepper (<ol>) + .step
1265
+ Completo → check (no solo color); actual → acento.
1266
+ ============================================================ */
1267
+ .stepper { display: flex; list-style: none; margin: 0; padding: 0; }
1268
+ .step {
1269
+ position: relative; flex: 1; display: flex; flex-direction: column; align-items: center;
1270
+ gap: var(--space-2); text-align: center; min-width: 0;
1271
+ }
1272
+ .step__marker {
1273
+ position: relative; z-index: 1;
1274
+ display: grid; place-items: center; width: 32px; height: 32px; flex: none;
1275
+ border-radius: var(--radius-full); border: 2px solid var(--border);
1276
+ background: var(--surface-1); color: var(--text-muted);
1277
+ font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; font-variant-numeric: tabular-nums;
1278
+ }
1279
+ .step__marker svg { width: 16px; height: 16px; }
1280
+ .step__label { font-size: var(--text-sm); color: var(--text-muted); }
1281
+ .step__connector {
1282
+ position: absolute; top: 15px; left: 50%; z-index: 0;
1283
+ width: 100%; height: 2px; background: var(--border);
1284
+ }
1285
+ /* Completo */
1286
+ .step--complete .step__marker { background: var(--accent-400); border-color: var(--accent-400); color: var(--text-on-accent); }
1287
+ .step--complete .step__label { color: var(--text-secondary); }
1288
+ .step--complete .step__connector { background: var(--accent-400); }
1289
+ /* Actual */
1290
+ .step--current .step__marker { border-color: var(--accent-400); color: var(--accent-300); }
1291
+ .step--current .step__label { color: var(--text-primary); font-weight: 600; }
1292
+ /* Próximo = valores por defecto (atenuado) */
1293
+
1294
+ /* Variante vertical */
1295
+ .stepper--vertical { flex-direction: column; }
1296
+ .stepper--vertical .step { flex-direction: row; align-items: flex-start; gap: var(--space-3); text-align: left; padding-bottom: var(--space-6); }
1297
+ .stepper--vertical .step:last-child { padding-bottom: 0; }
1298
+ .stepper--vertical .step__label { padding-top: var(--space-1); }
1299
+ .stepper--vertical .step__connector { top: 34px; left: 15px; width: 2px; height: calc(100% - 34px); }
1300
+
1301
+ /* ============================================================
1302
+ 32. KBD — .kbd (tecla / atajo de teclado)
1303
+ Combos: varias .kbd con un "+" literal entre ellas.
1304
+ ============================================================ */
1305
+ .kbd {
1306
+ display: inline-flex; align-items: center; justify-content: center;
1307
+ min-width: 20px; height: 20px; padding: 0 6px;
1308
+ font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; line-height: 1;
1309
+ color: var(--text-secondary); background: var(--surface-2);
1310
+ border: 1px solid var(--border-strong); border-radius: 6px; box-shadow: var(--shadow-1);
1311
+ }