@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.
@@ -51,7 +51,10 @@
51
51
  --surface-2: var(--night-800);
52
52
  --surface-3: var(--night-700);
53
53
  --border: var(--night-500);
54
- --border-strong: var(--night-600);
54
+ /* night-400, no night-600: en dark, oscurecer un borde lo DEBILITA (principio 2:
55
+ la elevación se comunica aclarando). n600 daba 1.46:1 vs los 1.97:1 del borde
56
+ normal — el énfasis se veía más flojo. n400 = 3.99:1 sobre surface-1. */
57
+ --border-strong: var(--night-400);
55
58
  --text-primary: var(--night-100);
56
59
  --text-secondary: var(--night-200);
57
60
  --text-muted: var(--night-300);
@@ -122,7 +125,7 @@
122
125
  --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px;
123
126
  --radius-xl: 24px; --radius-full: 9999px;
124
127
  --border-default: 1px solid var(--night-500);
125
- --border-emphasis: 1px solid var(--night-600);
128
+ --border-emphasis: 1px solid var(--night-400); /* ver --border-strong */
126
129
  --focus-ring: 2px solid var(--accent-400);
127
130
  --focus-ring-offset: 2px;
128
131
 
@@ -155,7 +158,9 @@
155
158
  --surface-2: #ffffff;
156
159
  --surface-3: #eaf1f7;
157
160
  --border: #d8dfe8;
158
- --border-strong: #b9c3d1;
161
+ /* border-strong NO se redefine en claro: night-400 (:root) cumple 1.4.11 en
162
+ AMBOS temas (3.26-3.99:1 en dark, 4.27-4.87:1 en light). #b9c3d1 daba
163
+ 1.53-1.78:1, bajo el mínimo de 3:1 para UI. */
159
164
  --text-primary: #14171f;
160
165
  --text-secondary: #3d4354;
161
166
  --text-muted: #5f6575;
@@ -426,7 +431,7 @@ a:hover { color: var(--link-hover); }
426
431
  .input-wrap .input { padding-left: 40px; }
427
432
 
428
433
  .textarea { min-height: 96px; padding: 12px 14px; resize: vertical; line-height: var(--leading-body); }
429
- .field__count { font-size: var(--text-xs); color: var(--text-disabled); text-align: right; margin-top: 4px; }
434
+ .field__count { font-size: var(--text-xs); color: var(--text-muted); text-align: right; margin-top: 4px; }
430
435
 
431
436
  /* Select nativo estilizado (el menú custom usa .menu) */
432
437
  .select-wrap { position: relative; }
@@ -669,6 +674,32 @@ a:hover { color: var(--link-hover); }
669
674
  .stat__delta--down { color: var(--danger); }
670
675
  .stat__delta--neutral { color: var(--text-muted); }
671
676
 
677
+ /* Chip de métrica: rótulo y valor en una pastilla de una línea */
678
+ .metric-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
679
+ .metric-chip {
680
+ display: inline-flex; align-items: center; gap: var(--space-2);
681
+ padding: var(--space-1) var(--space-3);
682
+ border: 1px solid var(--border); border-radius: var(--radius-full);
683
+ background: var(--surface-1);
684
+ font-family: var(--font-body); font-size: var(--text-sm); line-height: var(--leading-snug);
685
+ color: var(--text-secondary); white-space: nowrap;
686
+ }
687
+ .metric-chip svg { width: 16px; height: 16px; flex: none; color: var(--text-muted); }
688
+ .metric-chip__value {
689
+ font-family: var(--font-mono); font-weight: 500; color: var(--link);
690
+ font-variant-numeric: tabular-nums;
691
+ }
692
+ button.metric-chip {
693
+ min-height: var(--touch-target); padding-inline: var(--space-4);
694
+ cursor: pointer; text-align: left;
695
+ transition: background-color var(--duration-fast) var(--ease-out),
696
+ border-color var(--duration-fast) var(--ease-out),
697
+ transform var(--duration-instant) var(--ease-out);
698
+ }
699
+ button.metric-chip:hover { background: var(--outline-hover-bg); border-color: var(--border-hover); }
700
+ button.metric-chip:active { background: var(--outline-active-bg); transform: scale(.98); }
701
+ button.metric-chip:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }
702
+
672
703
  /* ============================================================
673
704
  13B. PAGINATION — .pagination (activa: fondo acento + peso, no solo color)
674
705
  ============================================================ */
@@ -751,7 +782,7 @@ a:hover { color: var(--link-hover); }
751
782
  }
752
783
  .alert > svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }
753
784
  .alert__title { font-weight: 600; margin: 0 0 2px; color: inherit; }
754
- .alert__body { margin: 0; color: inherit; opacity: .88; }
785
+ .alert__body { margin: 0; color: inherit; }
755
786
  .alert__close {
756
787
  margin-left: auto; flex: none; display: grid; place-items: center;
757
788
  width: 36px; height: 36px; border: 0; border-radius: var(--radius-sm);
@@ -913,6 +944,70 @@ a:hover { color: var(--link-hover); }
913
944
  .sidebar__item svg { width: 18px; height: 18px; color: var(--text-muted); flex: none; }
914
945
  .sidebar__item.is-active svg { color: var(--sidebar-active-icon); }
915
946
 
947
+ /* Grupos con rótulo dentro del sidebar */
948
+ .sidebar__group { display: flex; flex-direction: column; gap: 2px; }
949
+ .sidebar__group + .sidebar__group { margin-top: var(--space-4); }
950
+ .sidebar__group-label {
951
+ padding: 0 12px var(--space-1);
952
+ font-size: var(--text-xs); font-weight: 500; text-transform: uppercase;
953
+ letter-spacing: var(--tracking-overline); color: var(--text-muted); white-space: nowrap;
954
+ }
955
+ .sidebar__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
956
+
957
+ /* Sidebar contraíble: expandido 260 px, riel de iconos de 64 px.
958
+ El ancho cambia sin transición; solo los rótulos se funden con opacity y transform. */
959
+ .sidebar--collapsible .sidebar__label {
960
+ transition: opacity var(--duration-fast) var(--ease-out),
961
+ transform var(--duration-fast) var(--ease-out);
962
+ }
963
+ .sidebar__toggle {
964
+ margin-top: auto; width: 100%; border: 0; background: transparent;
965
+ font-family: var(--font-body); text-align: left; cursor: pointer;
966
+ }
967
+ .sidebar.is-collapsed { width: 64px; }
968
+ .sidebar.is-collapsed .sidebar__item { position: relative; justify-content: center; padding-inline: 0; }
969
+ .sidebar.is-collapsed .sidebar__toggle svg { transform: rotate(180deg); }
970
+ .sidebar.is-collapsed .sidebar__group + .sidebar__group { margin-top: var(--space-2); }
971
+ /* En el riel, el rótulo de grupo es un separador de 1 px; su texto sigue en el árbol de accesibilidad */
972
+ .sidebar.is-collapsed .sidebar__group-label {
973
+ height: 1px; padding: 0; margin: 0 var(--space-2) var(--space-2);
974
+ overflow: hidden; color: transparent; background: var(--border);
975
+ }
976
+ /* Oculto a la vista pero accesible (patrón de .visually-hidden) */
977
+ .sidebar.is-collapsed .sidebar__label,
978
+ .sidebar.is-collapsed .sidebar__group:first-child > .sidebar__group-label {
979
+ position: absolute; width: 1px; height: 1px; margin: -1px;
980
+ clip-path: inset(50%); overflow: hidden; white-space: nowrap;
981
+ }
982
+ .sidebar.is-collapsed .sidebar__label {
983
+ background: var(--tooltip-bg); border: 1px solid var(--tooltip-border); border-radius: var(--radius-sm);
984
+ color: var(--tooltip-text); font-size: var(--text-xs); line-height: 16px;
985
+ pointer-events: none; z-index: 70;
986
+ opacity: 0; transform: translateX(-4px);
987
+ }
988
+ /* Tooltip del riel: el propio rótulo aparece a la derecha del ítem, también con teclado */
989
+ .sidebar.is-collapsed .sidebar__item:focus-visible .sidebar__label {
990
+ left: calc(100% + 8px); top: calc(50% - 15px); width: auto; height: auto;
991
+ margin: 0; padding: 6px 10px; clip-path: none; overflow: visible;
992
+ opacity: 1; transform: none; transition-delay: 400ms;
993
+ }
994
+ /* Por hover solo con puntero real — en touch quedaría pegado tras el tap */
995
+ @media (hover: hover) and (pointer: fine) {
996
+ .sidebar.is-collapsed .sidebar__item:hover .sidebar__label {
997
+ left: calc(100% + 8px); top: calc(50% - 15px); width: auto; height: auto;
998
+ margin: 0; padding: 6px 10px; clip-path: none; overflow: visible;
999
+ opacity: 1; transform: none; transition-delay: 400ms;
1000
+ }
1001
+ }
1002
+ /* Por debajo de 768 px la navegación vive en un Drawer --left, que abre el botón ☰
1003
+ .sidebar-trigger (combinado con .icon-btn); desde 768 px el sidebar es fijo y el botón sobra */
1004
+ @media (max-width: 767px) {
1005
+ .sidebar--collapsible { display: none; }
1006
+ }
1007
+ @media (min-width: 768px) {
1008
+ .sidebar-trigger { display: none; }
1009
+ }
1010
+
916
1011
  .tabs { position: relative; display: flex; gap: var(--space-2); border-bottom: 1px solid var(--border-strong); }
917
1012
  .tabs__btn {
918
1013
  padding: 10px 14px; border: 0; background: transparent; cursor: pointer;
@@ -1223,7 +1318,7 @@ a:hover { color: var(--link-hover); }
1223
1318
  .calendar__day--today { border-color: var(--accent-400); color: var(--accent-300); }
1224
1319
  /* Seleccionado: fondo de acento + texto oscuro + peso — no depende solo del color */
1225
1320
  .calendar__day--selected { background: var(--accent-400); border-color: var(--accent-400); color: var(--text-on-accent); font-weight: 600; }
1226
- .calendar__day--outside { color: var(--text-disabled); }
1321
+ .calendar__day--outside { color: var(--text-muted); }
1227
1322
  .calendar__day[disabled] { color: var(--text-disabled); opacity: .5; cursor: not-allowed; }
1228
1323
 
1229
1324
  /* ============================================================
@@ -1242,7 +1337,7 @@ a:hover { color: var(--link-hover); }
1242
1337
  }
1243
1338
  .file-upload__label > svg { width: 28px; height: 28px; color: var(--text-muted); }
1244
1339
  .file-upload__button { color: var(--link); font-weight: 600; }
1245
- .file-upload__hint { font-size: var(--text-xs); color: var(--text-disabled); }
1340
+ .file-upload__hint { font-size: var(--text-xs); color: var(--text-muted); }
1246
1341
  @media (hover: hover) and (pointer: fine) {
1247
1342
  .file-upload__label:hover { border-color: var(--border-hover); background: var(--surface-2); color: var(--text-secondary); }
1248
1343
  }
@@ -1389,10 +1484,23 @@ html { scroll-behavior: smooth; }
1389
1484
  .ds-demo--grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); align-items: start; }
1390
1485
  .ds-demo:has(table) { overflow-x: auto; }
1391
1486
 
1487
+ /* Demo del sidebar contraíble: rejilla auto 1fr, el contenido sigue al riel sin animar el ancho */
1488
+ .ds-app-demo { display: grid; grid-template-columns: auto 1fr; align-items: stretch; gap: 0; min-height: 400px; padding: 0; }
1489
+ .ds-app-demo > .sidebar { border-radius: var(--radius-lg) 0 0 var(--radius-lg); }
1490
+ .ds-app-demo__main { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); min-width: 0; padding: var(--space-6); }
1491
+ @media (max-width: 767px) {
1492
+ .ds-app-demo { grid-template-columns: 1fr; min-height: 0; }
1493
+ }
1494
+
1392
1495
  .ds-code { margin-top: var(--space-3); border: 1px solid var(--row-border); border-radius: var(--radius-md); overflow: hidden; }
1496
+ /* «Copiar» es hermano del details, no hijo del summary (un control no puede
1497
+ anidarse en otro), y se superpone al extremo derecho de la cabecera. */
1498
+ .ds-code-wrap { position: relative; margin-top: var(--space-3); }
1499
+ .ds-code-wrap > .ds-code { margin-top: 0; }
1500
+ .ds-code-wrap > .ds-copy { position: absolute; top: 11px; right: 17px; }
1393
1501
  .ds-code summary {
1394
1502
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
1395
- padding: 10px 16px; cursor: pointer; user-select: none;
1503
+ min-height: 45px; padding: 10px 96px 10px 16px; cursor: pointer; user-select: none;
1396
1504
  font-size: var(--text-sm); color: var(--text-muted); list-style: none;
1397
1505
  }
1398
1506
  .ds-code summary::-webkit-details-marker { display: none; }
@@ -1674,11 +1782,11 @@ html { scroll-behavior: smooth; }
1674
1782
  <div class="ds-elev-demo" style="background:var(--bg);border:1px dashed var(--border);">Nivel 0<br>night-950</div>
1675
1783
  <div class="ds-elev-demo" style="background:var(--surface-1);box-shadow:var(--shadow-1);border:1px solid var(--row-border);">Nivel 1<br>night-900 + shadow-1</div>
1676
1784
  <div class="ds-elev-demo" style="background:var(--surface-2);box-shadow:var(--shadow-2);border:1px solid var(--row-border);">Nivel 2<br>night-800 + shadow-2</div>
1677
- <div class="ds-elev-demo" style="background:var(--surface-2);box-shadow:var(--shadow-3);border:1px solid var(--border-strong);">Nivel 3<br>night-800 + borde night-600 + shadow-3</div>
1785
+ <div class="ds-elev-demo" style="background:var(--surface-2);box-shadow:var(--shadow-3);border:1px solid var(--border-strong);">Nivel 3<br>night-800 + borde night-400 + shadow-3</div>
1678
1786
  </div>
1679
1787
  <h3 style="margin-top:32px;">Glow de acento</h3>
1680
1788
  <div class="ds-demo">
1681
- <div class="ds-elev-demo" style="background:var(--surface-1);box-shadow:var(--glow-accent);max-width:280px;">glow-accent<br><span style="color:var(--text-disabled)">máximo uno por pantalla</span></div>
1789
+ <div class="ds-elev-demo" style="background:var(--surface-1);box-shadow:var(--glow-accent);max-width:280px;">glow-accent<br><span style="color:var(--text-muted)">máximo uno por pantalla</span></div>
1682
1790
  </div>
1683
1791
  </section>
1684
1792
 
@@ -1732,16 +1840,16 @@ html { scroll-behavior: smooth; }
1732
1840
  <button class="btn btn--primary">Mediano</button>
1733
1841
  <button class="btn btn--primary btn--lg">Grande</button>
1734
1842
  <button class="btn btn--outline"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m-7-7v14"/></svg>Con icono</button>
1735
- <button class="btn btn--primary" style="min-width:160px;"><span class="spinner" style="color:currentColor;"></span></button>
1843
+ <button class="btn btn--primary" style="min-width:160px;" aria-label="Cargando"><span class="spinner" style="color:currentColor;"></span></button>
1736
1844
  </div>
1737
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;button class="btn btn--primary"&gt;Guardar cambios&lt;/button&gt;
1845
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;button class="btn btn--primary"&gt;Guardar cambios&lt;/button&gt;
1738
1846
  &lt;button class="btn btn--secondary"&gt;Ver informe&lt;/button&gt;
1739
1847
  &lt;button class="btn btn--outline"&gt;Exportar&lt;/button&gt;
1740
1848
  &lt;button class="btn btn--ghost"&gt;Cancelar&lt;/button&gt;
1741
1849
  &lt;button class="btn btn--danger"&gt;Eliminar cuenta&lt;/button&gt;
1742
1850
 
1743
1851
  &lt;!-- Tamaños: .btn--sm (36px) · default (44px) · .btn--lg (52px) --&gt;
1744
- &lt;!-- Loading: fijar min-width y sustituir el texto por .spinner --&gt;</code></pre></details>
1852
+ &lt;!-- Loading: fijar min-width y sustituir el texto por .spinner --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1745
1853
  </section>
1746
1854
 
1747
1855
  <!-- ================= ICON BUTTON ================= -->
@@ -1755,10 +1863,10 @@ html { scroll-behavior: smooth; }
1755
1863
  <button class="icon-btn icon-btn--outline icon-btn--sm" aria-label="Copiar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="8" y="8" width="14" height="14" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button>
1756
1864
  <button class="icon-btn icon-btn--outline" disabled aria-label="Deshabilitado"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
1757
1865
  </div>
1758
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;button class="icon-btn icon-btn--outline" aria-label="Buscar"&gt;
1866
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;button class="icon-btn icon-btn--outline" aria-label="Buscar"&gt;
1759
1867
  &lt;svg&gt;…&lt;/svg&gt;
1760
1868
  &lt;/button&gt;
1761
- &lt;!-- Variantes: --outline · --ghost · --accent | Tamaños: --sm (36) · default (44) · --lg (52) --&gt;</code></pre></details>
1869
+ &lt;!-- Variantes: --outline · --ghost · --accent | Tamaños: --sm (36) · default (44) · --lg (52) --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1762
1870
  </section>
1763
1871
 
1764
1872
  <!-- ================= SPINNER ================= -->
@@ -1770,8 +1878,8 @@ html { scroll-behavior: smooth; }
1770
1878
  <span class="spinner" style="width:24px;height:24px;"></span>
1771
1879
  <span class="spinner" style="width:32px;height:32px;color:var(--text-muted);"></span>
1772
1880
  </div>
1773
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;span class="spinner"&gt;&lt;/span&gt;
1774
- &lt;!-- Hereda currentColor; default accent-400 --&gt;</code></pre></details>
1881
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;span class="spinner"&gt;&lt;/span&gt;
1882
+ &lt;!-- Hereda currentColor; default accent-400 --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1775
1883
  </section>
1776
1884
 
1777
1885
  <!-- ================= INPUT ================= -->
@@ -1806,7 +1914,7 @@ html { scroll-behavior: smooth; }
1806
1914
  <span class="field__help">El asterisco es decorativo; lo obligatorio lo marca <span class="code">required</span>.</span>
1807
1915
  </div>
1808
1916
  </div>
1809
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="field"&gt;
1917
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="field"&gt;
1810
1918
  &lt;label class="field__label" for="email"&gt;Correo&lt;/label&gt;
1811
1919
  &lt;input class="input" id="email" type="email" placeholder="tu@correo.com"&gt;
1812
1920
  &lt;span class="field__help"&gt;Texto de ayuda.&lt;/span&gt;
@@ -1818,7 +1926,7 @@ html { scroll-behavior: smooth; }
1818
1926
  &lt;input class="input" id="name" type="text" required aria-required="true"&gt;
1819
1927
  &lt;/div&gt;
1820
1928
  &lt;!-- Estados: .input--error (+ .field__error) · .input--success · disabled --&gt;
1821
- &lt;!-- Icono leading: envolver en .input-wrap con un svg antes del input --&gt;</code></pre></details>
1929
+ &lt;!-- Icono leading: envolver en .input-wrap con un svg antes del input --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1822
1930
  </section>
1823
1931
 
1824
1932
  <!-- ================= TEXTAREA ================= -->
@@ -1832,11 +1940,11 @@ html { scroll-behavior: smooth; }
1832
1940
  <span class="field__count">0 / 280</span>
1833
1941
  </div>
1834
1942
  </div>
1835
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="field"&gt;
1943
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="field"&gt;
1836
1944
  &lt;label class="field__label" for="desc"&gt;Descripción&lt;/label&gt;
1837
1945
  &lt;textarea class="textarea" id="desc" placeholder="Describe el proyecto…"&gt;&lt;/textarea&gt;
1838
1946
  &lt;span class="field__count"&gt;0 / 280&lt;/span&gt;
1839
- &lt;/div&gt;</code></pre></details>
1947
+ &lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1840
1948
  </section>
1841
1949
 
1842
1950
  <!-- ================= SELECT ================= -->
@@ -1854,9 +1962,9 @@ html { scroll-behavior: smooth; }
1854
1962
  </div>
1855
1963
  </div>
1856
1964
  </div>
1857
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="select-wrap"&gt;
1965
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="select-wrap"&gt;
1858
1966
  &lt;select class="select"&gt;&lt;option&gt;Opción&lt;/option&gt;&lt;/select&gt;
1859
- &lt;/div&gt;</code></pre></details>
1967
+ &lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1860
1968
  </section>
1861
1969
 
1862
1970
  <!-- ================= SEGMENTEDCONTROL ================= -->
@@ -1875,11 +1983,11 @@ html { scroll-behavior: smooth; }
1875
1983
  <input type="radio" name="seg-per" id="seg-12m"><label for="seg-12m">12 m</label>
1876
1984
  </div>
1877
1985
  </div>
1878
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="segmented" role="radiogroup" aria-label="Vista"&gt;
1986
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="segmented" role="radiogroup" aria-label="Vista"&gt;
1879
1987
  &lt;input type="radio" name="vista" id="lista" checked&gt;&lt;label for="lista"&gt;Lista&lt;/label&gt;
1880
1988
  &lt;input type="radio" name="vista" id="tablero"&gt;&lt;label for="tablero"&gt;Tablero&lt;/label&gt;
1881
1989
  &lt;/div&gt;
1882
- &lt;!-- Compacto: añadir segmented--sm --&gt;</code></pre></details>
1990
+ &lt;!-- Compacto: añadir segmented--sm --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1883
1991
  </section>
1884
1992
 
1885
1993
  <!-- ================= SLIDER ================= -->
@@ -1896,12 +2004,12 @@ html { scroll-behavior: smooth; }
1896
2004
  </div>
1897
2005
  <input class="slider js-slider" type="range" min="0" max="100" value="70" disabled aria-label="Slider deshabilitado">
1898
2006
  </div>
1899
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="slider-row"&gt;
2007
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="slider-row"&gt;
1900
2008
  &lt;span class="slider-label"&gt;Límite de gasto&lt;/span&gt;
1901
2009
  &lt;span class="slider-value"&gt;$ 350&lt;/span&gt;
1902
2010
  &lt;/div&gt;
1903
2011
  &lt;input class="slider" type="range" min="0" max="1000" value="350"&gt;
1904
- &lt;!-- JS: --slider-fill = ((v-min)/(max-min))*100 + '%' --&gt;</code></pre></details>
2012
+ &lt;!-- JS: --slider-fill = ((v-min)/(max-min))*100 + '%' --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1905
2013
  </section>
1906
2014
 
1907
2015
  <!-- ================= CHECKBOX Y RADIO ================= -->
@@ -1914,10 +2022,10 @@ html { scroll-behavior: smooth; }
1914
2022
  <label class="check-row"><input type="radio" name="r1" class="radio" checked> Mensual</label>
1915
2023
  <label class="check-row"><input type="radio" name="r1" class="radio"> Anual</label>
1916
2024
  </div>
1917
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;label class="check-row"&gt;&lt;input type="checkbox" class="checkbox"&gt; Etiqueta&lt;/label&gt;
2025
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;label class="check-row"&gt;&lt;input type="checkbox" class="checkbox"&gt; Etiqueta&lt;/label&gt;
1918
2026
  &lt;label class="check-row"&gt;&lt;input type="radio" name="g" class="radio"&gt; Opción&lt;/label&gt;
1919
2027
  &lt;!-- Indeterminate = tercer estado (guion horizontal). Solo por JS: --&gt;
1920
- &lt;!-- document.querySelector('.checkbox').indeterminate = true; --&gt;</code></pre></details>
2028
+ &lt;!-- document.querySelector('.checkbox').indeterminate = true; --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1921
2029
  </section>
1922
2030
 
1923
2031
  <!-- ================= SWITCH ================= -->
@@ -1926,7 +2034,7 @@ html { scroll-behavior: smooth; }
1926
2034
  <div class="ds-demo" style="gap:32px;">
1927
2035
  <label class="check-row"><input type="checkbox" class="switch" checked> Modo compacto</label>
1928
2036
  </div>
1929
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;label class="check-row"&gt;&lt;input type="checkbox" class="switch"&gt; Activar&lt;/label&gt;</code></pre></details>
2037
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;label class="check-row"&gt;&lt;input type="checkbox" class="switch"&gt; Activar&lt;/label&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1930
2038
  </section>
1931
2039
 
1932
2040
  <!-- ================= BADGES ================= -->
@@ -1940,8 +2048,8 @@ html { scroll-behavior: smooth; }
1940
2048
  <span class="tag">diseño <button class="tag__x" aria-label="Quitar etiqueta diseño">×</button></span>
1941
2049
  <span class="tag">frontend <button class="tag__x" aria-label="Quitar etiqueta frontend">×</button></span>
1942
2050
  </div>
1943
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;span class="badge badge--success"&gt;Activo&lt;/span&gt;
1944
- &lt;span class="tag"&gt;diseño &lt;button class="tag__x" aria-label="Quitar"&gt;×&lt;/button&gt;&lt;/span&gt;</code></pre></details>
2051
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;span class="badge badge--success"&gt;Activo&lt;/span&gt;
2052
+ &lt;span class="tag"&gt;diseño &lt;button class="tag__x" aria-label="Quitar"&gt;×&lt;/button&gt;&lt;/span&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1945
2053
  </section>
1946
2054
 
1947
2055
  <!-- ================= AVATAR ================= -->
@@ -1955,9 +2063,9 @@ html { scroll-behavior: smooth; }
1955
2063
  <span class="avatar avatar--lg">hs<span class="avatar__dot avatar__dot--busy"></span></span>
1956
2064
  <span class="avatar avatar--xl">hs<span class="avatar__dot avatar__dot--away"></span></span>
1957
2065
  </div>
1958
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;span class="avatar"&gt;HS&lt;span class="avatar__dot avatar__dot--online"&gt;&lt;/span&gt;&lt;/span&gt;
2066
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;span class="avatar"&gt;HS&lt;span class="avatar__dot avatar__dot--online"&gt;&lt;/span&gt;&lt;/span&gt;
1959
2067
  &lt;!-- Tamaños: --xs 24 · --sm 32 · default 40 · --lg 48 · --xl 64 --&gt;
1960
- &lt;!-- Con imagen: &lt;span class="avatar"&gt;&lt;img src="…" alt="Nombre"&gt;&lt;/span&gt; --&gt;</code></pre></details>
2068
+ &lt;!-- Con imagen: &lt;span class="avatar"&gt;&lt;img src="…" alt="Nombre"&gt;&lt;/span&gt; --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1961
2069
 
1962
2070
  <h3 style="margin-top:var(--space-8);">AvatarGroup</h3>
1963
2071
  <p>Avatares solapados 8px con borde <span class="code">2px</span> del color del fondo; el chip <span class="code">.avatar-group__more</span> resume los ocultos.</p>
@@ -1970,13 +2078,13 @@ html { scroll-behavior: smooth; }
1970
2078
  <span class="avatar avatar-group__more">+3</span>
1971
2079
  </div>
1972
2080
  </div>
1973
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="avatar-group" role="group" aria-label="Equipo del proyecto"&gt;
2081
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="avatar-group" role="group" aria-label="Equipo del proyecto"&gt;
1974
2082
  &lt;span class="avatar"&gt;HS&lt;/span&gt;
1975
2083
  &lt;span class="avatar"&gt;ML&lt;/span&gt;
1976
2084
  &lt;span class="avatar"&gt;AR&lt;/span&gt;
1977
2085
  &lt;span class="avatar avatar-group__more"&gt;+3&lt;/span&gt;
1978
2086
  &lt;/div&gt;
1979
- &lt;!-- Solapamiento -8px + borde del color del fondo (--surface-1 / --bg). --&gt;</code></pre></details>
2087
+ &lt;!-- Solapamiento -8px + borde del color del fondo (--surface-1 / --bg). --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1980
2088
  </section>
1981
2089
 
1982
2090
  <!-- ================= DIVIDER ================= -->
@@ -1990,9 +2098,9 @@ html { scroll-behavior: smooth; }
1990
2098
  <span>Filtros</span><span class="divider--vertical" role="separator"></span><span>Ordenar</span><span class="divider--vertical" role="separator"></span><span>Exportar</span>
1991
2099
  </div>
1992
2100
  </div>
1993
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;hr class="divider"&gt;
2101
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;hr class="divider"&gt;
1994
2102
  &lt;div class="divider--label" role="separator"&gt;o continúa con&lt;/div&gt;
1995
- &lt;span class="divider--vertical" role="separator"&gt;&lt;/span&gt;</code></pre></details>
2103
+ &lt;span class="divider--vertical" role="separator"&gt;&lt;/span&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
1996
2104
  </section>
1997
2105
 
1998
2106
  <!-- ================= ACCORDION ================= -->
@@ -2014,7 +2122,7 @@ html { scroll-behavior: smooth; }
2014
2122
  </div>
2015
2123
  </div>
2016
2124
  </div>
2017
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="accordion"&gt;
2125
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="accordion"&gt;
2018
2126
  &lt;div class="accordion__item"&gt;
2019
2127
  &lt;button class="accordion__header" aria-expanded="false"&gt;
2020
2128
  Pregunta &lt;svg&gt;chevron&lt;/svg&gt;
@@ -2024,7 +2132,7 @@ html { scroll-behavior: smooth; }
2024
2132
  &lt;/div&gt;&lt;/div&gt;
2025
2133
  &lt;/div&gt;
2026
2134
  &lt;/div&gt;
2027
- &lt;!-- JS: alternar aria-expanded en el header --&gt;</code></pre></details>
2135
+ &lt;!-- JS: alternar aria-expanded en el header --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2028
2136
  </section>
2029
2137
 
2030
2138
  <!-- ================= TOOLTIP ================= -->
@@ -2041,10 +2149,10 @@ html { scroll-behavior: smooth; }
2041
2149
  <span class="tooltip" role="tooltip">Ajustes</span>
2042
2150
  </span>
2043
2151
  </div>
2044
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;span class="has-tooltip"&gt;
2152
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;span class="has-tooltip"&gt;
2045
2153
  &lt;button class="btn btn--outline"&gt;Pasa el cursor&lt;/button&gt;
2046
2154
  &lt;span class="tooltip" role="tooltip"&gt;Exportar como CSV&lt;/span&gt;
2047
- &lt;/span&gt;</code></pre></details>
2155
+ &lt;/span&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2048
2156
  </section>
2049
2157
 
2050
2158
  <!-- ================= ALERT ================= -->
@@ -2085,7 +2193,7 @@ html { scroll-behavior: smooth; }
2085
2193
  <button class="alert__close js-alert-close" aria-label="Cerrar aviso"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
2086
2194
  </div>
2087
2195
  </div>
2088
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="alert alert--warning" role="status"&gt;
2196
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="alert alert--warning" role="status"&gt;
2089
2197
  &lt;svg&gt;…icono…&lt;/svg&gt;
2090
2198
  &lt;div&gt;
2091
2199
  &lt;p class="alert__title"&gt;Tu plan expira en 5 días&lt;/p&gt;
@@ -2093,7 +2201,7 @@ html { scroll-behavior: smooth; }
2093
2201
  &lt;/div&gt;
2094
2202
  &lt;button class="alert__close" aria-label="Cerrar aviso"&gt;…x…&lt;/button&gt;
2095
2203
  &lt;/div&gt;
2096
- &lt;!-- Variantes: --info · --success · --warning · --danger --&gt;</code></pre></details>
2204
+ &lt;!-- Variantes: --info · --success · --warning · --danger --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2097
2205
  </section>
2098
2206
 
2099
2207
  <!-- ================= TOAST ================= -->
@@ -2106,7 +2214,7 @@ html { scroll-behavior: smooth; }
2106
2214
  <button class="btn btn--outline" data-toast="warning">Toast de aviso</button>
2107
2215
  <button class="btn btn--outline" data-toast="danger">Toast de error</button>
2108
2216
  </div>
2109
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="toast-stack" role="status" aria-live="polite"&gt;
2217
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="toast-stack" role="status" aria-live="polite"&gt;
2110
2218
  &lt;div class="toast toast--success"&gt;
2111
2219
  &lt;svg&gt;…&lt;/svg&gt;
2112
2220
  &lt;div&gt;
@@ -2114,7 +2222,7 @@ html { scroll-behavior: smooth; }
2114
2222
  &lt;div class="toast__body"&gt;El proyecto se actualizó correctamente.&lt;/div&gt;
2115
2223
  &lt;/div&gt;
2116
2224
  &lt;/div&gt;
2117
- &lt;/div&gt;</code></pre></details>
2225
+ &lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2118
2226
  </section>
2119
2227
 
2120
2228
  <!-- ================= PROGRESS ================= -->
@@ -2124,14 +2232,14 @@ html { scroll-behavior: smooth; }
2124
2232
  <div class="ds-demo ds-demo--col" style="gap:24px;">
2125
2233
  <div>
2126
2234
  <div class="progress__head"><span class="progress__label">Subiendo archivos…</span><span class="progress__value" id="pgVal">64 %</span></div>
2127
- <div class="progress" role="progressbar" aria-valuenow="64" aria-valuemin="0" aria-valuemax="100"><div class="progress__bar" id="pgBar" style="width:64%;"></div></div>
2235
+ <div class="progress" role="progressbar" aria-label="Subiendo archivos" aria-valuenow="64" aria-valuemin="0" aria-valuemax="100"><div class="progress__bar" id="pgBar" style="width:64%;"></div></div>
2128
2236
  </div>
2129
2237
  <div>
2130
2238
  <div class="progress__head"><span class="progress__label">Indeterminado</span></div>
2131
- <div class="progress progress--indeterminate" role="progressbar"><div class="progress__bar"></div></div>
2239
+ <div class="progress progress--indeterminate" role="progressbar" aria-label="Indeterminado"><div class="progress__bar"></div></div>
2132
2240
  </div>
2133
2241
  <div style="display:flex;align-items:center;gap:24px;">
2134
- <div class="progress-ring" id="pgRing" data-value="64" role="progressbar" aria-valuenow="64" aria-valuemin="0" aria-valuemax="100">
2242
+ <div class="progress-ring" id="pgRing" data-value="64" role="progressbar" aria-label="Progreso circular" aria-valuenow="64" aria-valuemin="0" aria-valuemax="100">
2135
2243
  <svg width="56" height="56" viewBox="0 0 56 56" aria-hidden="true"><circle class="progress-ring__track" cx="28" cy="28" r="24" stroke-width="5"/><circle class="progress-ring__bar" id="pgRingBar" cx="28" cy="28" r="24" stroke-width="5"/></svg>
2136
2244
  <span class="progress-ring__value" id="pgRingVal">64%</span>
2137
2245
  </div>
@@ -2139,7 +2247,7 @@ html { scroll-behavior: smooth; }
2139
2247
  </div>
2140
2248
  <button class="btn btn--outline btn--sm" id="pgRandom" style="align-self:flex-start;">Cambiar progreso</button>
2141
2249
  </div>
2142
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="progress__head"&gt;
2250
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="progress__head"&gt;
2143
2251
  &lt;span class="progress__label"&gt;Subiendo…&lt;/span&gt;
2144
2252
  &lt;span class="progress__value"&gt;64 %&lt;/span&gt;
2145
2253
  &lt;/div&gt;
@@ -2155,7 +2263,7 @@ html { scroll-behavior: smooth; }
2155
2263
  &lt;/svg&gt;
2156
2264
  &lt;span class="progress-ring__value"&gt;64%&lt;/span&gt;
2157
2265
  &lt;/div&gt;
2158
- &lt;!-- JS: stroke-dasharray = 2πr; stroke-dashoffset = c * (1 - value/100) --&gt;</code></pre></details>
2266
+ &lt;!-- JS: stroke-dasharray = 2πr; stroke-dashoffset = c * (1 - value/100) --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2159
2267
  </section>
2160
2268
 
2161
2269
  <!-- ================= MODAL ================= -->
@@ -2166,7 +2274,7 @@ html { scroll-behavior: smooth; }
2166
2274
  <button class="btn btn--primary" id="openModal">Abrir modal</button>
2167
2275
  <button class="btn btn--outline" id="openModalLg">Abrir formulario</button>
2168
2276
  </div>
2169
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="modal-overlay"&gt;
2277
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="modal-overlay"&gt;
2170
2278
  &lt;!-- aria-modal, aria-labelledby (título) y aria-describedby (descripción, si la hay);
2171
2279
  tabindex="-1" permite mover el foco al panel al abrir --&gt;
2172
2280
  &lt;div class="modal" role="dialog" aria-modal="true"
@@ -2184,7 +2292,7 @@ html { scroll-behavior: smooth; }
2184
2292
  &lt;/div&gt;
2185
2293
  &lt;!-- JS: al abrir guarda document.activeElement y enfoca el panel; Tab cicla dentro
2186
2294
  (focus-trap); Esc / clic en overlay / data-close-modal cierran y devuelven el foco.
2187
- Destructivo: añade data-modal-persistent al .modal-overlay. --&gt;</code></pre></details>
2295
+ Destructivo: añade data-modal-persistent al .modal-overlay. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2188
2296
  </section>
2189
2297
 
2190
2298
  <!-- ================= MENU ================= -->
@@ -2201,10 +2309,10 @@ html { scroll-behavior: smooth; }
2201
2309
  </div>
2202
2310
  </div>
2203
2311
  </div>
2204
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="menu"&gt;
2312
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="menu"&gt;
2205
2313
  &lt;button class="menu__item"&gt;Duplicar&lt;/button&gt;
2206
2314
  &lt;button class="menu__item is-selected"&gt;Seleccionado&lt;/button&gt;
2207
- &lt;/div&gt;</code></pre></details>
2315
+ &lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2208
2316
  </section>
2209
2317
 
2210
2318
  <!-- ================= TABLA ================= -->
@@ -2261,7 +2369,7 @@ html { scroll-behavior: smooth; }
2261
2369
  </tbody>
2262
2370
  </table>
2263
2371
  </div>
2264
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;table class="table table--zebra table--sticky"&gt;
2372
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;table class="table table--zebra table--sticky"&gt;
2265
2373
  &lt;thead&gt;&lt;tr&gt;
2266
2374
  &lt;th scope="col" class="col-select"&gt;
2267
2375
  &lt;input type="checkbox" class="checkbox" aria-label="Seleccionar todas"&gt;&lt;/th&gt;
@@ -2276,7 +2384,7 @@ html { scroll-behavior: smooth; }
2276
2384
  &lt;tr class="row--selected"&gt;…&lt;/tr&gt;
2277
2385
  &lt;/tbody&gt;
2278
2386
  &lt;/table&gt;
2279
- &lt;!-- El icono se atenúa si aria-sort no está fijado; JS reordena y alterna aria-sort. --&gt;</code></pre></details>
2387
+ &lt;!-- El icono se atenúa si aria-sort no está fijado; JS reordena y alterna aria-sort. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2280
2388
  </section>
2281
2389
 
2282
2390
  <!-- ================= STAT ================= -->
@@ -2300,11 +2408,30 @@ html { scroll-behavior: smooth; }
2300
2408
  <span class="stat__delta stat__delta--neutral">— sin cambios</span>
2301
2409
  </div>
2302
2410
  </div>
2303
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="stat"&gt;
2411
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="stat"&gt;
2304
2412
  &lt;span class="stat__label"&gt;Ingresos del mes&lt;/span&gt;
2305
2413
  &lt;span class="stat__value"&gt;$128 450&lt;/span&gt;
2306
2414
  &lt;span class="stat__delta stat__delta--up"&gt;▲ +12,4 %&lt;/span&gt;
2307
- &lt;/div&gt;</code></pre></details>
2415
+ &lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2416
+ <h3 style="margin-top:32px;">Chip de métrica</h3>
2417
+ <p>Pastilla de una línea con rótulo y valor en <span class="code">--link</span> · fila con <span class="code">gap</span> que salta de línea en móvil · el chip interactivo es un <span class="code">&lt;button&gt;</span> de 44 px con nombre accesible completo.</p>
2418
+ <div class="ds-demo">
2419
+ <div class="metric-chips">
2420
+ <span class="metric-chip"><span class="metric-chip__label">Latencia</span> <span class="metric-chip__value">42 ms</span></span>
2421
+ <span class="metric-chip"><span class="metric-chip__label">Errores</span> <span class="metric-chip__value">0,3 %</span></span>
2422
+ <button class="metric-chip" type="button" id="dsWaterChip" aria-label="Agua: 3 de 8 vasos. Sumar un vaso"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg><span class="metric-chip__label">Agua</span> <span class="metric-chip__value">3 de 8</span></button>
2423
+ </div>
2424
+ </div>
2425
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="metric-chips"&gt;
2426
+ &lt;span class="metric-chip"&gt;
2427
+ &lt;span class="metric-chip__label"&gt;Latencia&lt;/span&gt; &lt;span class="metric-chip__value"&gt;42 ms&lt;/span&gt;
2428
+ &lt;/span&gt;
2429
+ &lt;button class="metric-chip" type="button" aria-label="Agua: 3 de 8 vasos. Sumar un vaso"&gt;
2430
+ &lt;svg aria-hidden="true"&gt;…plus…&lt;/svg&gt;
2431
+ &lt;span class="metric-chip__label"&gt;Agua&lt;/span&gt; &lt;span class="metric-chip__value"&gt;3 de 8&lt;/span&gt;
2432
+ &lt;/button&gt;
2433
+ &lt;/div&gt;
2434
+ &lt;!-- El aria-label se actualiza con el valor; empieza por el texto visible --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2308
2435
  </section>
2309
2436
 
2310
2437
  <!-- ================= PAGINATION ================= -->
@@ -2314,14 +2441,14 @@ html { scroll-behavior: smooth; }
2314
2441
  <div class="ds-demo">
2315
2442
  <ul class="pagination" id="paginationDemo" aria-label="Paginación"></ul>
2316
2443
  </div>
2317
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;ul class="pagination" aria-label="Paginación"&gt;
2444
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;ul class="pagination" aria-label="Paginación"&gt;
2318
2445
  &lt;li&gt;&lt;button class="pagination__btn" data-page="prev" aria-label="Página anterior"&gt;‹&lt;/button&gt;&lt;/li&gt;
2319
2446
  &lt;li&gt;&lt;button class="pagination__btn" data-page="1"&gt;1&lt;/button&gt;&lt;/li&gt;
2320
2447
  &lt;li&gt;&lt;span class="pagination__ellipsis"&gt;…&lt;/span&gt;&lt;/li&gt;
2321
2448
  &lt;li&gt;&lt;button class="pagination__btn is-active" data-page="5" aria-current="page"&gt;5&lt;/button&gt;&lt;/li&gt;
2322
2449
  &lt;li&gt;&lt;button class="pagination__btn" data-page="6"&gt;6&lt;/button&gt;&lt;/li&gt;
2323
2450
  &lt;li&gt;&lt;button class="pagination__btn" data-page="next" aria-label="Página siguiente"&gt;›&lt;/button&gt;&lt;/li&gt;
2324
- &lt;/ul&gt;</code></pre></details>
2451
+ &lt;/ul&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2325
2452
  </section>
2326
2453
 
2327
2454
  <!-- ================= NAVEGACIÓN ================= -->
@@ -2346,6 +2473,69 @@ html { scroll-behavior: smooth; }
2346
2473
  <a class="sidebar__item" href="#comp-navegacion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg>Proyectos</a>
2347
2474
  </div>
2348
2475
  </div>
2476
+ <h3 style="margin-top:32px;">Sidebar contraíble</h3>
2477
+ <p>Expandido 260 px · riel de iconos de 64 px con grupos separados por una línea · en el riel, el nombre aparece como tooltip al pasar el cursor o al enfocar con teclado · el ancho cambia sin transición y solo los rótulos se funden · por debajo de 768 px lo sustituye un Drawer <span class="code">--left</span>.</p>
2478
+ <div class="ds-demo ds-app-demo">
2479
+ <nav class="sidebar sidebar--collapsible" id="demoAppNav" aria-label="Navegación de ejemplo">
2480
+ <div class="sidebar__group" role="group" aria-labelledby="demoAppNavG1">
2481
+ <span class="sidebar__group-label" id="demoAppNavG1">Monitoreo</span>
2482
+ <a class="sidebar__item is-active" href="#comp-navegacion" aria-current="page"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 22V12h6v10"/></svg><span class="sidebar__label">Inicio</span></a>
2483
+ <a class="sidebar__item" href="#comp-navegacion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3v18h18"/><path d="M7 15v3m5-8v8m5-13v13"/></svg><span class="sidebar__label">Analítica</span></a>
2484
+ <a class="sidebar__item" href="#comp-navegacion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg><span class="sidebar__label">Actividad</span></a>
2485
+ </div>
2486
+ <div class="sidebar__group" role="group" aria-labelledby="demoAppNavG2">
2487
+ <span class="sidebar__group-label" id="demoAppNavG2">Gestión</span>
2488
+ <a class="sidebar__item" href="#comp-navegacion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg><span class="sidebar__label">Proyectos</span></a>
2489
+ <a class="sidebar__item" href="#comp-navegacion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg><span class="sidebar__label">Equipo</span></a>
2490
+ <a class="sidebar__item" href="#comp-navegacion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg><span class="sidebar__label">Alertas</span></a>
2491
+ </div>
2492
+ <button class="sidebar__item sidebar__toggle" type="button" aria-expanded="true" aria-controls="demoAppNav"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg><span class="sidebar__label">Contraer</span></button>
2493
+ </nav>
2494
+ <div class="ds-app-demo__main">
2495
+ <button class="icon-btn icon-btn--outline sidebar-trigger" type="button" id="openNavDrawer" aria-label="Abrir navegación" aria-expanded="false" aria-controls="demoNavDrawer"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/></svg></button>
2496
+ <h4 style="margin:0;">Inicio</h4>
2497
+ <p class="text-muted" style="margin:0;font-size:var(--text-sm);">El contenido ocupa el ancho que deja el sidebar: la rejilla <span class="code">auto 1fr</span> sigue al riel al instante, sin animar el ancho.</p>
2498
+ </div>
2499
+ </div>
2500
+ <div class="drawer drawer--left" id="demoNavDrawer" hidden>
2501
+ <div class="drawer__overlay" data-close-drawer></div>
2502
+ <aside class="drawer__panel" role="dialog" aria-modal="true" aria-labelledby="navDrawerTitle" tabindex="-1">
2503
+ <div class="drawer__header">
2504
+ <h3 class="drawer__title" id="navDrawerTitle">Navegación</h3>
2505
+ <button class="icon-btn icon-btn--ghost" data-close-drawer aria-label="Cerrar navegación"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
2506
+ </div>
2507
+ <nav class="drawer__body" aria-label="Navegación de ejemplo">
2508
+ <div class="sidebar__group" role="group" aria-labelledby="demoNavDrawerG1">
2509
+ <span class="sidebar__group-label" id="demoNavDrawerG1">Monitoreo</span>
2510
+ <a class="sidebar__item is-active" href="#comp-navegacion" aria-current="page" data-close-drawer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 22V12h6v10"/></svg><span class="sidebar__label">Inicio</span></a>
2511
+ <a class="sidebar__item" href="#comp-navegacion" data-close-drawer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3v18h18"/><path d="M7 15v3m5-8v8m5-13v13"/></svg><span class="sidebar__label">Analítica</span></a>
2512
+ <a class="sidebar__item" href="#comp-navegacion" data-close-drawer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg><span class="sidebar__label">Actividad</span></a>
2513
+ </div>
2514
+ <div class="sidebar__group" role="group" aria-labelledby="demoNavDrawerG2">
2515
+ <span class="sidebar__group-label" id="demoNavDrawerG2">Gestión</span>
2516
+ <a class="sidebar__item" href="#comp-navegacion" data-close-drawer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg><span class="sidebar__label">Proyectos</span></a>
2517
+ <a class="sidebar__item" href="#comp-navegacion" data-close-drawer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg><span class="sidebar__label">Equipo</span></a>
2518
+ <a class="sidebar__item" href="#comp-navegacion" data-close-drawer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg><span class="sidebar__label">Alertas</span></a>
2519
+ </div>
2520
+ </nav>
2521
+ </aside>
2522
+ </div>
2523
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;nav class="sidebar sidebar--collapsible" id="appNav" aria-label="Principal"&gt;
2524
+ &lt;div class="sidebar__group" role="group" aria-labelledby="navMonitor"&gt;
2525
+ &lt;span class="sidebar__group-label" id="navMonitor"&gt;Monitoreo&lt;/span&gt;
2526
+ &lt;a class="sidebar__item is-active" href="/" aria-current="page"&gt;
2527
+ &lt;svg aria-hidden="true"&gt;…&lt;/svg&gt;&lt;span class="sidebar__label"&gt;Inicio&lt;/span&gt;
2528
+ &lt;/a&gt;
2529
+ &lt;/div&gt;
2530
+ &lt;button class="sidebar__item sidebar__toggle" type="button"
2531
+ aria-expanded="true" aria-controls="appNav"&gt;
2532
+ &lt;svg aria-hidden="true"&gt;…chevron-left…&lt;/svg&gt;&lt;span class="sidebar__label"&gt;Contraer&lt;/span&gt;
2533
+ &lt;/button&gt;
2534
+ &lt;/nav&gt;
2535
+ &lt;!-- Contraído: .is-collapsed en el nav, aria-expanded="false" y texto «Expandir».
2536
+ Por debajo de 768 px: botón ☰ .sidebar-trigger que abre un .drawer.drawer--left con los mismos ítems. --&gt;
2537
+ &lt;button class="icon-btn sidebar-trigger" type="button" aria-label="Abrir navegación"
2538
+ aria-expanded="false" aria-controls="navDrawer"&gt;…menu…&lt;/button&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2349
2539
  <h3 style="margin-top:32px;">Tabs y Breadcrumbs</h3>
2350
2540
  <div class="ds-demo ds-demo--col">
2351
2541
  <div class="tabs" id="demoTabs">
@@ -2360,10 +2550,10 @@ html { scroll-behavior: smooth; }
2360
2550
  <li aria-current="page">Panel analítico</li>
2361
2551
  </ul>
2362
2552
  </div>
2363
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="navbar"&gt;…&lt;a class="navbar__link is-active"&gt;Resumen&lt;/a&gt;…&lt;/div&gt;
2553
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="navbar"&gt;…&lt;a class="navbar__link is-active"&gt;Resumen&lt;/a&gt;…&lt;/div&gt;
2364
2554
  &lt;div class="sidebar"&gt;&lt;a class="sidebar__item is-active"&gt;&lt;svg&gt;…&lt;/svg&gt;Inicio&lt;/a&gt;&lt;/div&gt;
2365
2555
  &lt;div class="tabs"&gt;&lt;button class="tabs__btn is-active"&gt;Resumen&lt;/button&gt;…&lt;span class="tabs__indicator"&gt;&lt;/span&gt;&lt;/div&gt;
2366
- &lt;ul class="breadcrumbs"&gt;&lt;li&gt;&lt;a&gt;Inicio&lt;/a&gt;&lt;/li&gt;&lt;li aria-current="page"&gt;Actual&lt;/li&gt;&lt;/ul&gt;</code></pre></details>
2556
+ &lt;ul class="breadcrumbs"&gt;&lt;li&gt;&lt;a&gt;Inicio&lt;/a&gt;&lt;/li&gt;&lt;li aria-current="page"&gt;Actual&lt;/li&gt;&lt;/ul&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2367
2557
  </section>
2368
2558
 
2369
2559
  <!-- ================= SKELETON ================= -->
@@ -2384,7 +2574,7 @@ html { scroll-behavior: smooth; }
2384
2574
  <button class="btn btn--primary btn--sm">Crear proyecto</button>
2385
2575
  </div>
2386
2576
  </div>
2387
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;span class="skeleton" style="height:12px;width:70%"&gt;&lt;/span&gt;
2577
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;span class="skeleton" style="height:12px;width:70%"&gt;&lt;/span&gt;
2388
2578
  &lt;span class="skeleton skeleton--circle" style="width:40px;height:40px"&gt;&lt;/span&gt;
2389
2579
 
2390
2580
  &lt;div class="empty-state"&gt;
@@ -2392,7 +2582,7 @@ html { scroll-behavior: smooth; }
2392
2582
  &lt;span class="empty-state__title"&gt;Aún no hay proyectos&lt;/span&gt;
2393
2583
  &lt;span class="empty-state__desc"&gt;Crea tu primer proyecto…&lt;/span&gt;
2394
2584
  &lt;button class="btn btn--primary btn--sm"&gt;Crear proyecto&lt;/button&gt;
2395
- &lt;/div&gt;</code></pre></details>
2585
+ &lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2396
2586
  </section>
2397
2587
 
2398
2588
  <!-- ================= CARD, LINK Y CODE ================= -->
@@ -2409,17 +2599,17 @@ html { scroll-behavior: smooth; }
2409
2599
  <p style="margin:0;font-size:var(--text-sm);color:var(--text-muted);">Al pasar el cursor sube de nivel: −2px + superficie más clara.</p>
2410
2600
  </div>
2411
2601
  </div>
2412
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="card"&gt;…&lt;/div&gt;
2602
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="card"&gt;…&lt;/div&gt;
2413
2603
  &lt;div class="card card--interactive"&gt;…&lt;/div&gt;
2414
- &lt;!-- .card--glow: firma de marca — MÁXIMO UNO POR PANTALLA --&gt;</code></pre></details>
2604
+ &lt;!-- .card--glow: firma de marca — MÁXIMO UNO POR PANTALLA --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2415
2605
  <h3 style="margin-top:32px;">Link y Code</h3>
2416
2606
  <div class="ds-demo" style="gap:32px;">
2417
2607
  <a class="link" href="#comp-card">Link con subrayado animado</a>
2418
2608
  <a class="link" href="https://lucide.dev" target="_blank" rel="noopener noreferrer">Link externo<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17 17 7M7 7h10v10"/></svg></a>
2419
2609
  <span>Acento con <span class="code">var(--accent-400)</span></span>
2420
2610
  </div>
2421
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;a class="link" href="…"&gt;Link con subrayado animado&lt;/a&gt;
2422
- &lt;span class="code"&gt;var(--accent-400)&lt;/span&gt;</code></pre></details>
2611
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;a class="link" href="…"&gt;Link con subrayado animado&lt;/a&gt;
2612
+ &lt;span class="code"&gt;var(--accent-400)&lt;/span&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2423
2613
  </section>
2424
2614
 
2425
2615
  <!-- ================= COMBOBOX / SEARCH ================= -->
@@ -2453,7 +2643,7 @@ html { scroll-behavior: smooth; }
2453
2643
  </div>
2454
2644
  </div>
2455
2645
  </div>
2456
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="combobox"&gt;
2646
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="combobox"&gt;
2457
2647
  &lt;input class="input combobox__input" role="combobox" aria-expanded="false"
2458
2648
  aria-controls="lista" aria-autocomplete="list" aria-activedescendant=""&gt;
2459
2649
  &lt;ul class="combobox__list" id="lista" role="listbox" aria-label="Frameworks" hidden&gt;
@@ -2467,7 +2657,7 @@ html { scroll-behavior: smooth; }
2467
2657
  &lt;input class="input search__input" type="search" aria-label="Buscar"&gt;
2468
2658
  &lt;button class="search__clear" aria-label="Limpiar" hidden&gt;×&lt;/button&gt;
2469
2659
  &lt;/div&gt;
2470
- &lt;!-- JS: filtra en vivo, ↑/↓/Enter/Esc; el clear vacía y devuelve el foco. --&gt;</code></pre></details>
2660
+ &lt;!-- JS: filtra en vivo, ↑/↓/Enter/Esc; el clear vacía y devuelve el foco. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2471
2661
  </section>
2472
2662
 
2473
2663
  <!-- ================= DRAWER ================= -->
@@ -2506,7 +2696,7 @@ html { scroll-behavior: smooth; }
2506
2696
  </div>
2507
2697
  </aside>
2508
2698
  </div>
2509
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="drawer drawer--right" hidden&gt;
2699
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="drawer drawer--right" hidden&gt;
2510
2700
  &lt;div class="drawer__overlay" data-close-drawer&gt;&lt;/div&gt;
2511
2701
  &lt;aside class="drawer__panel" role="dialog" aria-modal="true"
2512
2702
  aria-labelledby="dTitle" tabindex="-1"&gt;
@@ -2519,7 +2709,7 @@ html { scroll-behavior: smooth; }
2519
2709
  &lt;/aside&gt;
2520
2710
  &lt;/div&gt;
2521
2711
  &lt;!-- Variantes: --right (default) · --left · --bottom (sheet).
2522
- JS: .is-open dispara el slide; Esc / overlay cierran y devuelven el foco. --&gt;</code></pre></details>
2712
+ JS: .is-open dispara el slide; Esc / overlay cierran y devuelven el foco. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2523
2713
  </section>
2524
2714
 
2525
2715
  <!-- ================= POPOVER ================= -->
@@ -2543,7 +2733,7 @@ html { scroll-behavior: smooth; }
2543
2733
  </div>
2544
2734
  </div>
2545
2735
  </div>
2546
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="popover"&gt;
2736
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="popover"&gt;
2547
2737
  &lt;button class="btn btn--outline popover__trigger" type="button"
2548
2738
  aria-haspopup="dialog" aria-expanded="false" aria-controls="panel"&gt;Compartir&lt;/button&gt;
2549
2739
  &lt;div class="popover__panel" role="dialog" aria-label="Compartir proyecto" id="panel"&gt;
@@ -2552,7 +2742,7 @@ html { scroll-behavior: smooth; }
2552
2742
  &lt;a class="link" href="…"&gt;Ver permisos avanzados&lt;/a&gt;
2553
2743
  &lt;/div&gt;
2554
2744
  &lt;/div&gt;
2555
- &lt;!-- Abre por CLICK (no hover); el foco entra al panel; Esc / clic fuera cierran. --&gt;</code></pre></details>
2745
+ &lt;!-- Abre por CLICK (no hover); el foco entra al panel; Esc / clic fuera cierran. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2556
2746
  </section>
2557
2747
 
2558
2748
  <!-- ================= BUTTON GROUP ================= -->
@@ -2566,12 +2756,12 @@ html { scroll-behavior: smooth; }
2566
2756
  <button class="btn btn--outline" type="button">Derecha</button>
2567
2757
  </div>
2568
2758
  </div>
2569
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="btn-group" role="group" aria-label="Alineación del texto"&gt;
2759
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="btn-group" role="group" aria-label="Alineación del texto"&gt;
2570
2760
  &lt;button class="btn btn--outline"&gt;Izquierda&lt;/button&gt;
2571
2761
  &lt;button class="btn btn--outline"&gt;Centro&lt;/button&gt;
2572
2762
  &lt;button class="btn btn--outline"&gt;Derecha&lt;/button&gt;
2573
2763
  &lt;/div&gt;
2574
- &lt;!-- Radios solo en los extremos; bordes internos colapsados (margin-left:-1px). --&gt;</code></pre></details>
2764
+ &lt;!-- Radios solo en los extremos; bordes internos colapsados (margin-left:-1px). --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2575
2765
  </section>
2576
2766
 
2577
2767
  <!-- ================= DATEPICKER ================= -->
@@ -2584,7 +2774,7 @@ html { scroll-behavior: smooth; }
2584
2774
  <div class="input-wrap" style="max-width:220px;">
2585
2775
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>
2586
2776
  <input class="input datepicker__input" type="text" id="dpInput" readonly
2587
- aria-haspopup="dialog" aria-expanded="false" aria-controls="dpCalendar"
2777
+ aria-haspopup="dialog" aria-controls="dpCalendar"
2588
2778
  aria-labelledby="dpLabel" value="15 de julio de 2026">
2589
2779
  </div>
2590
2780
  <div class="datepicker__calendar" id="dpCalendar" role="dialog" aria-label="Elegir fecha" hidden>
@@ -2594,6 +2784,7 @@ html { scroll-behavior: smooth; }
2594
2784
  <span class="calendar__title" id="dpTitle" aria-live="polite">julio 2026</span>
2595
2785
  <button class="icon-btn icon-btn--ghost icon-btn--sm" type="button" id="dpNext" aria-label="Mes siguiente"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></button>
2596
2786
  </div>
2787
+ <div class="calendar__table" role="grid" aria-labelledby="dpTitle">
2597
2788
  <div class="calendar__weekdays" role="row">
2598
2789
  <span role="columnheader" aria-label="lunes">L</span>
2599
2790
  <span role="columnheader" aria-label="martes">M</span>
@@ -2603,16 +2794,17 @@ html { scroll-behavior: smooth; }
2603
2794
  <span role="columnheader" aria-label="sábado">S</span>
2604
2795
  <span role="columnheader" aria-label="domingo">D</span>
2605
2796
  </div>
2606
- <div class="calendar__grid" id="dpGrid" role="grid" aria-labelledby="dpTitle"></div>
2797
+ <div class="calendar__grid" id="dpGrid" role="rowgroup"></div>
2798
+ </div>
2607
2799
  </div>
2608
2800
  </div>
2609
2801
  </div>
2610
2802
  </div>
2611
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="datepicker"&gt;
2803
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="datepicker"&gt;
2612
2804
  &lt;div class="input-wrap"&gt;
2613
2805
  &lt;svg aria-hidden="true"&gt;…calendario…&lt;/svg&gt;
2614
2806
  &lt;input class="input datepicker__input" readonly aria-haspopup="dialog"
2615
- aria-expanded="false" aria-controls="cal" value="15 de julio de 2026"&gt;
2807
+ aria-controls="cal" value="15 de julio de 2026"&gt;
2616
2808
  &lt;/div&gt;
2617
2809
  &lt;div class="datepicker__calendar" id="cal" role="dialog" aria-label="Elegir fecha" hidden&gt;
2618
2810
  &lt;div class="calendar"&gt;
@@ -2621,19 +2813,21 @@ html { scroll-behavior: smooth; }
2621
2813
  &lt;span class="calendar__title" aria-live="polite"&gt;julio 2026&lt;/span&gt;
2622
2814
  &lt;button class="icon-btn icon-btn--ghost icon-btn--sm" aria-label="Mes siguiente"&gt;›&lt;/button&gt;
2623
2815
  &lt;/div&gt;
2816
+ &lt;div class="calendar__table" role="grid" aria-label="julio 2026"&gt;
2624
2817
  &lt;div class="calendar__weekdays" role="row"&gt;
2625
2818
  &lt;span role="columnheader" aria-label="lunes"&gt;L&lt;/span&gt; …
2626
2819
  &lt;/div&gt;
2627
- &lt;div class="calendar__grid" role="grid"&gt;
2820
+ &lt;div class="calendar__grid" role="rowgroup"&gt;
2628
2821
  &lt;div class="calendar__week" role="row"&gt;
2629
2822
  &lt;button class="calendar__day" role="gridcell"
2630
2823
  aria-label="15 de julio de 2026" aria-selected="true"&gt;15&lt;/button&gt; …
2631
2824
  &lt;/div&gt;
2632
2825
  &lt;/div&gt;
2826
+ &lt;/div&gt;
2633
2827
  &lt;/div&gt;
2634
2828
  &lt;/div&gt;
2635
2829
  &lt;/div&gt;
2636
- &lt;!-- JS: clic abre; flechas mueven el día (±1, ±7) cruzando meses; Enter elige; Esc cierra. --&gt;</code></pre></details>
2830
+ &lt;!-- JS: clic abre; flechas mueven el día (±1, ±7) cruzando meses; Enter elige; Esc cierra. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2637
2831
  </section>
2638
2832
 
2639
2833
  <!-- ================= FILE UPLOAD ================= -->
@@ -2677,7 +2871,7 @@ html { scroll-behavior: smooth; }
2677
2871
  </ul>
2678
2872
  </div>
2679
2873
  </div>
2680
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;div class="file-upload"&gt;
2874
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;div class="file-upload"&gt;
2681
2875
  &lt;input class="file-upload__input visually-hidden" type="file" id="f" multiple
2682
2876
  aria-describedby="hint"&gt;
2683
2877
  &lt;label class="file-upload__label" for="f"&gt;
@@ -2699,7 +2893,7 @@ html { scroll-behavior: smooth; }
2699
2893
  &lt;li class="file-upload__item file-upload__item--error"&gt;…icono + texto de error…&lt;/li&gt;
2700
2894
  &lt;/ul&gt;
2701
2895
  &lt;/div&gt;
2702
- &lt;!-- JS: dragover añade .is-dragover; el botón × quita el ítem. --&gt;</code></pre></details>
2896
+ &lt;!-- JS: dragover añade .is-dragover; el botón × quita el ítem. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2703
2897
  </section>
2704
2898
 
2705
2899
  <!-- ================= STEPPER ================= -->
@@ -2745,7 +2939,7 @@ html { scroll-behavior: smooth; }
2745
2939
  </li>
2746
2940
  </ol>
2747
2941
  </div>
2748
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;ol class="stepper" aria-label="Progreso de la configuración"&gt;
2942
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>&lt;ol class="stepper" aria-label="Progreso de la configuración"&gt;
2749
2943
  &lt;li class="step step--complete"&gt;
2750
2944
  &lt;span class="step__marker"&gt;&lt;svg aria-hidden="true"&gt;…check…&lt;/svg&gt;&lt;/span&gt;
2751
2945
  &lt;span class="step__label"&gt;Cuenta&lt;/span&gt;
@@ -2760,7 +2954,7 @@ html { scroll-behavior: smooth; }
2760
2954
  &lt;span class="step__marker"&gt;4&lt;/span&gt;&lt;span class="step__label"&gt;Confirmación&lt;/span&gt;
2761
2955
  &lt;/li&gt;
2762
2956
  &lt;/ol&gt;
2763
- &lt;!-- El último paso no lleva conector. Variante: .stepper--vertical. --&gt;</code></pre></details>
2957
+ &lt;!-- El último paso no lleva conector. Variante: .stepper--vertical. --&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2764
2958
  </section>
2765
2959
 
2766
2960
  <!-- ================= KBD ================= -->
@@ -2775,10 +2969,10 @@ html { scroll-behavior: smooth; }
2775
2969
  <span style="display:inline-flex;align-items:center;gap:6px;color:var(--text-muted);"><kbd class="kbd">Ctrl</kbd> + <kbd class="kbd">S</kbd></span>
2776
2970
  <span style="display:inline-flex;align-items:center;gap:6px;color:var(--text-muted);"><kbd class="kbd">Shift</kbd> + <kbd class="kbd">⇥</kbd></span>
2777
2971
  </div>
2778
- <details class="ds-code"><summary>Ver código<button class="ds-copy" type="button">Copiar</button></summary><pre><code>Pulsa &lt;kbd class="kbd"&gt;Esc&lt;/kbd&gt; para cerrar.
2972
+ <div class="ds-code-wrap"><details class="ds-code"><summary>Ver código</summary><pre><code>Pulsa &lt;kbd class="kbd"&gt;Esc&lt;/kbd&gt; para cerrar.
2779
2973
 
2780
2974
  Abre el buscador con &lt;kbd class="kbd"&gt;⌘&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;K&lt;/kbd&gt;.
2781
- Guarda con &lt;kbd class="kbd"&gt;Ctrl&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;S&lt;/kbd&gt;.</code></pre></details>
2975
+ Guarda con &lt;kbd class="kbd"&gt;Ctrl&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;S&lt;/kbd&gt;.</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2782
2976
  </section>
2783
2977
 
2784
2978
  <!-- ================= MOTION ================= -->
@@ -2844,11 +3038,11 @@ Guarda con &lt;kbd class="kbd"&gt;Ctrl&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;S&lt
2844
3038
  <p>El sistema se distribuye en <span class="code">dist/nocturna-electrica/</span>: <strong>nocturna-electrica.css</strong> (framework completo), <strong>tokens.css</strong> (solo variables), <strong>tailwind.css</strong> (bloque <span class="code">@theme</span> para Tailwind v4) y <strong>tokens.json</strong> (formato estándar W3C DTCG 2025.10, interoperable con Figma / Tokens Studio / Style Dictionary).</p>
2845
3039
 
2846
3040
  <h3>Variables CSS (núcleo)</h3>
2847
- <details class="ds-code" open><summary>tokens :root (aliases semánticos)<button class="ds-copy" type="button">Copiar</button></summary><pre><code>:root {
3041
+ <div class="ds-code-wrap"><details class="ds-code" open><summary>tokens :root (aliases semánticos)</summary><pre><code>:root {
2848
3042
  /* Superficies */
2849
3043
  --bg: #010203;
2850
3044
  --surface-1: #0b0d12; --surface-2: #14171f; --surface-3: #1e222d;
2851
- --border: #3d4354; --border-strong: #2a2f3d;
3045
+ --border: #3d4354; --border-strong: #6b7183;
2852
3046
 
2853
3047
  /* Texto */
2854
3048
  --text-primary: #e8eaef; --text-secondary: #c5c9d4;
@@ -2882,10 +3076,10 @@ Guarda con &lt;kbd class="kbd"&gt;Ctrl&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;S&lt
2882
3076
  --ease-out: cubic-bezier(0.2, 0, 0, 1);
2883
3077
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
2884
3078
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
2885
- }</code></pre></details>
3079
+ }</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2886
3080
 
2887
3081
  <h3 style="margin-top:32px;">Tailwind CSS v4 — <span class="code">@theme</span></h3>
2888
- <details class="ds-code"><summary>tailwind.css<button class="ds-copy" type="button">Copiar</button></summary><pre><code>@import "tailwindcss";
3082
+ <div class="ds-code-wrap"><details class="ds-code"><summary>tailwind.css</summary><pre><code>@import "tailwindcss";
2889
3083
 
2890
3084
  @theme {
2891
3085
  --color-night-950: #010203; --color-night-900: #0b0d12;
@@ -2919,7 +3113,7 @@ Guarda con &lt;kbd class="kbd"&gt;Ctrl&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;S&lt
2919
3113
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
2920
3114
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
2921
3115
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
2922
- }</code></pre></details>
3116
+ }</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2923
3117
 
2924
3118
  <div class="ds-callout ds-callout--info" style="margin-top:32px;">
2925
3119
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4m0-4h.01"/></svg>
@@ -2933,41 +3127,41 @@ Guarda con &lt;kbd class="kbd"&gt;Ctrl&lt;/kbd&gt; + &lt;kbd class="kbd"&gt;S&lt
2933
3127
  <p>El sistema se distribuye como paquete npm (<span class="code">@higinio/design-css</span>) y también como archivos sueltos en <span class="code">dist/nocturna-electrica/</span>. Instálalo o cópialos, y elige qué importar según tu stack (A/B/C/D). En todas: <strong>dark por defecto</strong>; <span class="code">&lt;html data-theme="light"&gt;</span> activa el modo claro, y los componentes consumen <strong>solo aliases semánticos</strong>, nunca hex.</p>
2934
3128
 
2935
3129
  <h3 style="margin-top:32px;">Instalar desde npm (recomendado)</h3>
2936
- <p>Un solo paquete con los dos sistemas en subrutas <span class="code">/celeste/</span> y <span class="code">/nocturna/</span>. Instálalo y usa las vías de abajo apuntando a la subruta, en vez de a un archivo copiado.</p>
2937
- <details class="ds-code" open><summary>terminal + CSS de entrada<button class="ds-copy" type="button">Copiar</button></summary><pre><code>npm i @higinio/design-css
3130
+ <p>Un solo paquete con todos los sistemas, cada uno en su subruta; Nocturna Eléctrica vive en <span class="code">/nocturna/</span>. Instálalo y usa las vías de abajo apuntando a la subruta, en vez de a un archivo copiado.</p>
3131
+ <div class="ds-code-wrap"><details class="ds-code" open><summary>terminal + CSS de entrada</summary><pre><code>npm i @higinio/design-css
2938
3132
 
2939
3133
  /* framework completo (vía A) */
2940
3134
  @import "@higinio/design-css/nocturna/framework.css";
2941
3135
  /* o solo tokens (vía B) */
2942
3136
  @import "@higinio/design-css/nocturna/tokens.css";
2943
3137
  /* o Tailwind v4 (vía C) */
2944
- @import "@higinio/design-css/nocturna/tailwind.css";</code></pre></details>
3138
+ @import "@higinio/design-css/nocturna/tailwind.css";</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2945
3139
 
2946
3140
  <h3 style="margin-top:32px;">A · CSS drop-in (framework completo)</h3>
2947
3141
  <p>Para cualquier proyecto — HTML plano o cualquier framework. Trae variables + clases de componentes listas (tipo Bootstrap) y ya importa las fuentes.</p>
2948
- <details class="ds-code" open><summary>index.html<button class="ds-copy" type="button">Copiar</button></summary><pre><code>&lt;link rel="stylesheet" href="/estilos/nocturna-electrica.css"&gt;
3142
+ <div class="ds-code-wrap"><details class="ds-code" open><summary>index.html</summary><pre><code>&lt;link rel="stylesheet" href="/estilos/nocturna-electrica.css"&gt;
2949
3143
  &lt;!-- luego usas las clases directo: --&gt;
2950
3144
  &lt;button class="btn btn--primary"&gt;Guardar&lt;/button&gt;
2951
- &lt;div class="card"&gt;…&lt;/div&gt;</code></pre></details>
3145
+ &lt;div class="card"&gt;…&lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2952
3146
 
2953
3147
  <h3 style="margin-top:32px;">B · Solo tokens</h3>
2954
3148
  <p>Si diseñas tus propios componentes: solo las variables, sin clases.</p>
2955
- <details class="ds-code"><summary>styles.css<button class="ds-copy" type="button">Copiar</button></summary><pre><code>@import "./tokens.css";
3149
+ <div class="ds-code-wrap"><details class="ds-code"><summary>styles.css</summary><pre><code>@import "./tokens.css";
2956
3150
 
2957
3151
  .mi-panel {
2958
3152
  background: var(--surface-1);
2959
3153
  color: var(--text-primary);
2960
3154
  border: 1px solid var(--border);
2961
- }</code></pre></details>
3155
+ }</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2962
3156
 
2963
3157
  <h3 style="margin-top:32px;">C · Tailwind v4</h3>
2964
3158
  <p>Tailwind v4 se configura por CSS. El <span class="code">tailwind.css</span> ya incluye <span class="code">@import "tailwindcss"</span>, los tokens y el bloque <span class="code">@theme</span> — úsalo como tu hoja de entrada (mantén <span class="code">tokens.css</span> a su lado, que es lo que importa).</p>
2965
- <details class="ds-code"><summary>terminal + CSS de entrada<button class="ds-copy" type="button">Copiar</button></summary><pre><code># 1) instala Tailwind v4
3159
+ <div class="ds-code-wrap"><details class="ds-code"><summary>terminal + CSS de entrada</summary><pre><code># 1) instala Tailwind v4
2966
3160
  npm i tailwindcss @tailwindcss/postcss
2967
3161
 
2968
3162
  # 2) copia tailwind.css + tokens.css a tu carpeta de CSS
2969
3163
  # y usa tailwind.css como entrada. Ya tienes utilidades:
2970
- &lt;div class="bg-night-900 text-accent-400"&gt;…&lt;/div&gt;</code></pre></details>
3164
+ &lt;div class="bg-night-900 text-accent-400"&gt;…&lt;/div&gt;</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
2971
3165
 
2972
3166
  <h3 style="margin-top:32px;">D · Pipelines de tokens</h3>
2973
3167
  <p>Para Figma, Tokens Studio o Style Dictionary: importa <span class="code">tokens.json</span> (formato estándar W3C DTCG 2025.10).</p>
@@ -2981,20 +3175,23 @@ npm i tailwindcss @tailwindcss/postcss
2981
3175
  <!-- ================= MCP ================= -->
2982
3176
  <section id="mcp">
2983
3177
  <h2>MCP</h2>
2984
- <p>El paquete <span class="code">@higinio/design-mcp</span> expone ambos sistemas de diseño — Celeste Clásica y Nocturna Eléctrica — a cualquier IDE o cliente compatible con Model Context Protocol: tokens, componentes, reglas duras y validación de código. Complementa a las skills de Claude, no las reemplaza: misma fuente de verdad, accesible también fuera del entorno de Claude.</p>
3178
+ <p>El paquete <span class="code">@higinio/design-mcp</span> expone los sistemas de diseño de Higinio Sosa, entre ellos Nocturna Eléctrica (<span class="code">system="nocturna"</span>), a cualquier IDE o cliente compatible con Model Context Protocol: tokens, componentes, reglas duras y validación de código. Complementa a las skills de Claude, no las reemplaza: misma fuente de verdad, accesible también fuera del entorno de Claude.</p>
2985
3179
 
2986
- <h3>Las 8 tools</h3>
3180
+ <h3>Las 11 tools</h3>
2987
3181
  <div class="ds-demo ds-demo--col" style="padding:0;overflow-x:auto;">
2988
3182
  <table class="table">
2989
3183
  <thead><tr><th>Tool</th><th>Qué hace</th></tr></thead>
2990
3184
  <tbody>
2991
3185
  <tr><td class="mono">list_design_systems</td><td>Lista los sistemas de diseño disponibles.</td></tr>
2992
- <tr><td class="mono">get_token</td><td>Devuelve el valor resuelto de un token o alias de un sistema.</td></tr>
3186
+ <tr><td class="mono">get_token</td><td>Resuelve un alias semántico o un token DTCG por path a su valor.</td></tr>
2993
3187
  <tr><td class="mono">search_tokens</td><td>Busca tokens por nombre, categoría o valor.</td></tr>
2994
3188
  <tr><td class="mono">list_components</td><td>Lista los componentes documentados de un sistema.</td></tr>
2995
3189
  <tr><td class="mono">get_component_spec</td><td>Devuelve la especificación completa de un componente: estados, medidas, variantes.</td></tr>
2996
3190
  <tr><td class="mono">get_rules</td><td>Devuelve las reglas duras (no negociables) del sistema.</td></tr>
2997
3191
  <tr><td class="mono">validate_code</td><td>Audita CSS/HTML contra las reglas del sistema — hex directos, contraste, aliases.</td></tr>
3192
+ <tr><td class="mono">validate_motion</td><td>Audita el motion contra las reglas del sistema: <span class="code">transition</span> sobre todas las propiedades, ease-in en entradas, propiedades de layout, duraciones por encima de <span class="code">--duration-page</span>.</td></tr>
3193
+ <tr><td class="mono">check_slop</td><td>Detecta clichés de diseño generado por IA: gradientes, glassmorphism, sombras de negro puro, fuentes genéricas y copy de marketing.</td></tr>
3194
+ <tr><td class="mono">checklist_preflight</td><td>Checklist estático de pre-producción sobre HTML/CSS: metadatos, headings, imágenes y accesibilidad de controles.</td></tr>
2998
3195
  <tr><td class="mono">generate_snippet</td><td>Genera un snippet de componente listo para usar, con los aliases correctos.</td></tr>
2999
3196
  </tbody>
3000
3197
  </table>
@@ -3002,7 +3199,7 @@ npm i tailwindcss @tailwindcss/postcss
3002
3199
 
3003
3200
  <h3 style="margin-top:32px;">Conectar (remoto)</h3>
3004
3201
  <p>Añade el servidor a tu <span class="code">.mcp.json</span>:</p>
3005
- <details class="ds-code" open><summary>.mcp.json<button class="ds-copy" type="button">Copiar</button></summary><pre><code>{
3202
+ <div class="ds-code-wrap"><details class="ds-code" open><summary>.mcp.json</summary><pre><code>{
3006
3203
  "mcpServers": {
3007
3204
  "design": {
3008
3205
  "type": "http",
@@ -3010,15 +3207,15 @@ npm i tailwindcss @tailwindcss/postcss
3010
3207
  "headers": { "Authorization": "Bearer &lt;tu-token&gt;" }
3011
3208
  }
3012
3209
  }
3013
- }</code></pre></details>
3210
+ }</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
3014
3211
 
3015
3212
  <h3 style="margin-top:32px;">Ejemplo</h3>
3016
3213
  <p>Consultar un token de este sistema:</p>
3017
- <details class="ds-code"><summary>get_token<button class="ds-copy" type="button">Copiar</button></summary><pre><code>get_token(system="nocturna", name="--accent")
3018
- → "#52baed"</code></pre></details>
3214
+ <div class="ds-code-wrap"><details class="ds-code"><summary>get_token</summary><pre><code>get_token(system="nocturna", name="--accent")
3215
+ → "#52baed"</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
3019
3216
  <p>Auditar código antes de integrarlo:</p>
3020
- <details class="ds-code"><summary>validate_code<button class="ds-copy" type="button">Copiar</button></summary><pre><code>validate_code(system="nocturna", code="…")
3021
- → { ok: false, issues: ["hex directo #52baed en línea 12 — usa var(--accent-400)"] }</code></pre></details>
3217
+ <div class="ds-code-wrap"><details class="ds-code"><summary>validate_code</summary><pre><code>validate_code(system="nocturna", code="…")
3218
+ → { ok: false, issues: ["hex directo #52baed en línea 12 — usa var(--accent-400)"] }</code></pre></details><button class="ds-copy" type="button">Copiar</button></div>
3022
3219
 
3023
3220
  <div class="ds-callout ds-callout--info" style="margin-top:32px;">
3024
3221
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4m0-4h.01"/></svg>
@@ -3209,10 +3406,9 @@ spaces.forEach(function(s){
3209
3406
 
3210
3407
  /* ---------- Copiar código ---------- */
3211
3408
  document.querySelectorAll('.ds-copy').forEach(function(btn){
3212
- btn.addEventListener('click', function(e){
3213
- e.preventDefault(); e.stopPropagation();
3214
- var details = btn.closest('details');
3215
- var code = details ? details.querySelector('code') : null;
3409
+ btn.addEventListener('click', function(){
3410
+ var box = btn.closest('.ds-code-wrap');
3411
+ var code = box ? box.querySelector('code') : null;
3216
3412
  if (code) {
3217
3413
  copyText(code.textContent, function(){
3218
3414
  btn.textContent = '¡Copiado!'; btn.classList.add('is-done');
@@ -3303,6 +3499,31 @@ tabs.querySelectorAll('.tabs__btn').forEach(function(b){
3303
3499
  });
3304
3500
  setTimeout(function(){ moveIndicator(tabs.querySelector('.is-active')); }, 100);
3305
3501
 
3502
+ /* ---------- Sidebar contraíble: riel de iconos ---------- */
3503
+ document.querySelectorAll('.sidebar__toggle').forEach(function(btn){
3504
+ var nav = document.getElementById(btn.getAttribute('aria-controls'));
3505
+ var label = btn.querySelector('.sidebar__label');
3506
+ if (!nav) return;
3507
+ btn.addEventListener('click', function(){
3508
+ var collapsed = nav.classList.toggle('is-collapsed');
3509
+ btn.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
3510
+ if (label) label.textContent = collapsed ? 'Expandir' : 'Contraer';
3511
+ });
3512
+ });
3513
+
3514
+ /* ---------- Chip de métrica: sumar un vaso ---------- */
3515
+ (function(){
3516
+ var chip = document.getElementById('dsWaterChip');
3517
+ if (!chip) return;
3518
+ var value = chip.querySelector('.metric-chip__value');
3519
+ var max = 8, n = 3;
3520
+ chip.addEventListener('click', function(){
3521
+ n = n >= max ? 0 : n + 1;
3522
+ value.textContent = n + ' de ' + max;
3523
+ chip.setAttribute('aria-label', 'Agua: ' + n + ' de ' + max + ' vasos. ' + (n < max ? 'Sumar un vaso' : 'Empezar de nuevo'));
3524
+ });
3525
+ })();
3526
+
3306
3527
  /* ---------- Alert ---------- */
3307
3528
  document.querySelectorAll('.js-alert-close').forEach(function(btn){
3308
3529
  btn.addEventListener('click', function(){
@@ -3414,6 +3635,7 @@ function wireDrawer(triggerId, drawerId){
3414
3635
  function open(){
3415
3636
  lastFocused = document.activeElement;
3416
3637
  drawer.hidden = false;
3638
+ if (trigger.hasAttribute('aria-expanded')) trigger.setAttribute('aria-expanded', 'true');
3417
3639
  /* dos pasos: pinta oculto y en el siguiente frame añade .is-open para que el transform anime */
3418
3640
  requestAnimationFrame(function(){ drawer.classList.add('is-open'); });
3419
3641
  if (panel) panel.focus(); /* tabindex="-1"; el lector anuncia el título */
@@ -3421,6 +3643,7 @@ function wireDrawer(triggerId, drawerId){
3421
3643
  function close(){
3422
3644
  if (drawer.hidden) return;
3423
3645
  drawer.classList.remove('is-open');
3646
+ if (trigger.hasAttribute('aria-expanded')) trigger.setAttribute('aria-expanded', 'false');
3424
3647
  var finish = function(){ drawer.hidden = true; if (lastFocused && typeof lastFocused.focus === 'function') lastFocused.focus(); };
3425
3648
  if (reduced) finish(); else setTimeout(finish, 250); /* espera el slide de salida (--duration-slow) */
3426
3649
  }
@@ -3440,6 +3663,7 @@ function wireDrawer(triggerId, drawerId){
3440
3663
  });
3441
3664
  }
3442
3665
  wireDrawer('openDrawer', 'demoDrawer');
3666
+ wireDrawer('openNavDrawer', 'demoNavDrawer');
3443
3667
 
3444
3668
  /* ---------- Popover (abre por CLICK; foco entra; Esc / clic fuera cierran) ---------- */
3445
3669
  (function(){
@@ -3798,11 +4022,10 @@ if (mReplayBtn) {
3798
4022
  }
3799
4023
  }
3800
4024
  function focusRoving(){ var f = grid.querySelector('.calendar__day[tabindex="0"]'); if (f) f.focus(); }
3801
- function open(){ render(); cal.hidden = false; input.setAttribute('aria-expanded', 'true'); focusRoving(); }
4025
+ function open(){ render(); cal.hidden = false; focusRoving(); }
3802
4026
  function close(returnFocus){
3803
4027
  if (cal.hidden) return;
3804
4028
  cal.hidden = true;
3805
- input.setAttribute('aria-expanded', 'false');
3806
4029
  if (returnFocus) input.focus();
3807
4030
  }
3808
4031
  function setView(y, m){ view = new Date(y, m, 1); render(); }