@khipu/design-system 0.3.5-alpha.35 → 0.3.5-alpha.37

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.
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
15
15
  * Source: design-system/src/tokens/tokens.json
16
- * Generated: 2026-10-09T18:13:29.633Z
16
+ * Generated: 2026-10-27T18:34:57.467Z
17
17
  *
18
18
  * To regenerate:
19
19
  * cd design-system && npm run tokens:generate
@@ -1485,6 +1485,118 @@ a.kds-btn.kds-btn-md {
1485
1485
  line-height: var(--kds-line-height-normal);
1486
1486
  }
1487
1487
 
1488
+ /* Extra content under the description (e.g. a "Necesitarás" list). */
1489
+ .kds-card-selector-details {
1490
+ font-size: var(--kds-font-size-sm);
1491
+ color: var(--kds-color-text-primary);
1492
+ line-height: var(--kds-line-height-normal);
1493
+ }
1494
+
1495
+ /* !important on the top margin: BeerCSS adds 1rem to a list after a sibling with a higher
1496
+ specificity (same approach as .kds-card-plan ul). */
1497
+ .kds-card-selector-details :is(ul, ol) {
1498
+ margin: 0;
1499
+ margin-block-start: var(--kds-spacing-1) !important;
1500
+ padding-inline-start: var(--kds-spacing-2-5);
1501
+ }
1502
+
1503
+ /* Small section label inside the details, e.g. "Necesitarás". */
1504
+ .kds-card-selector-eyebrow {
1505
+ display: block;
1506
+ font-size: var(--kds-font-size-xs);
1507
+ font-weight: var(--kds-font-weight-bold);
1508
+ letter-spacing: var(--kds-letter-spacing-wide);
1509
+ text-transform: uppercase;
1510
+ color: var(--primary);
1511
+ }
1512
+
1513
+ /* Radio option (.kds-card-selector--radio): a <div> card with a native radio top-right
1514
+ and the title <label> stretched over the card, so any click selects it and cards
1515
+ sharing a `name` behave as one radio group (arrow keys, form submit) without JS.
1516
+ Same pattern as .kds-card-plan--selectable. */
1517
+ .kds-card-selector--radio {
1518
+ position: relative;
1519
+ padding: var(--kds-spacing-2-5);
1520
+ gap: var(--kds-spacing-1);
1521
+ }
1522
+
1523
+ /* Icon tile tinted from --primary (follows the merchant's brand; the base tile uses the
1524
+ fixed --kds-color-primary-focus). Base button-mode cards keep their tile. */
1525
+ .kds-card-selector--radio .kds-card-selector-icon {
1526
+ background: color-mix(in srgb, var(--primary) 12%, transparent);
1527
+ border-radius: var(--kds-radius-md);
1528
+ }
1529
+
1530
+ /* Selector group (KdsCardSelectorGroup): columns by the group's own width, like
1531
+ .kds-card-plan-group. */
1532
+ .kds-card-selector-group {
1533
+ display: grid;
1534
+ grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
1535
+ gap: var(--kds-spacing-2);
1536
+ align-items: stretch;
1537
+ }
1538
+
1539
+ .kds-card-selector-radio {
1540
+ position: absolute;
1541
+ top: var(--kds-spacing-2);
1542
+ right: var(--kds-spacing-2);
1543
+ z-index: 2;
1544
+ width: var(--kds-spacing-2-5);
1545
+ height: var(--kds-spacing-2-5);
1546
+ margin: 0;
1547
+ accent-color: var(--primary);
1548
+ cursor: pointer;
1549
+ }
1550
+
1551
+ /* BeerCSS positions and sizes bare <label>s; the title keeps its own type styles and
1552
+ must stay static so its ::after resolves against the card. */
1553
+ .kds-card-selector--radio label.kds-card-selector-title {
1554
+ position: static;
1555
+ padding-inline-end: var(--kds-spacing-4);
1556
+ cursor: pointer;
1557
+ }
1558
+
1559
+ .kds-card-selector--radio label.kds-card-selector-title::after {
1560
+ content: "";
1561
+ position: absolute;
1562
+ inset: 0;
1563
+ z-index: 1;
1564
+ border-radius: var(--kds-radius-md);
1565
+ }
1566
+
1567
+ /* Interactive content inside the card stays above the stretched label. */
1568
+ .kds-card-selector--radio :is(a, button, input:not(.kds-card-selector-radio), select, textarea, summary, [tabindex]) {
1569
+ position: relative;
1570
+ z-index: 2;
1571
+ }
1572
+
1573
+ /* Hover must not look like the checked state: neutral, darker border. Same specificity as
1574
+ the base `.kds-card-selector:hover:not(.selected)` (primary tint) and later, so it wins. */
1575
+ .kds-card-selector.kds-card-selector--radio:hover:not(.selected) {
1576
+ border-color: var(--kds-border-dark);
1577
+ background: var(--kds-color-background-paper);
1578
+ }
1579
+
1580
+ /* Checked and focus need :has. Without it the radio keeps its native look and focus
1581
+ ring, so the choice and the focus stay visible in older browsers. */
1582
+ @supports selector(:has(*)) {
1583
+ /* Same brand tint as the selected plan card (follows the merchant's --primary).
1584
+ Doubled class so it outranks the neutral hover above and stays selected on hover. */
1585
+ .kds-card-selector.kds-card-selector--radio:has(.kds-card-selector-radio:checked) {
1586
+ border-color: var(--primary);
1587
+ background: color-mix(in srgb, var(--primary) 5%, var(--kds-surface-base));
1588
+ }
1589
+
1590
+ .kds-card-selector--radio:has(.kds-card-selector-radio:focus-visible) {
1591
+ outline: 2px solid var(--primary);
1592
+ outline-offset: 2px;
1593
+ }
1594
+
1595
+ .kds-card-selector-radio:focus-visible {
1596
+ outline: none;
1597
+ }
1598
+ }
1599
+
1488
1600
  /* Selected state - visual feedback via border only */
1489
1601
 
1490
1602
  /* Pricing/Plan card */
@@ -1529,9 +1641,190 @@ a.kds-btn.kds-btn-md {
1529
1641
  box-shadow: var(--kds-shadow-elevation-4);
1530
1642
  }
1531
1643
 
1532
- /* Recommended Badge — inline dentro del card (no flotante).
1533
- Es el primer hijo del .kds-card-plan, así que aparece arriba de todo
1534
- el contenido, alineado a la izquierda. */
1644
+ /* Selectable plan (.kds-card-plan--selectable): a native radio sits top-right and the
1645
+ title <label> is stretched over the whole card, so any click selects it and cards
1646
+ sharing a `name` behave as one radio group (arrow keys, form submit) without JS. */
1647
+ .kds-card-plan-radio {
1648
+ position: absolute;
1649
+ top: var(--kds-spacing-2);
1650
+ right: var(--kds-spacing-2);
1651
+ z-index: 2;
1652
+ width: var(--kds-spacing-2-5);
1653
+ height: var(--kds-spacing-2-5);
1654
+ margin: 0;
1655
+ accent-color: var(--primary);
1656
+ cursor: pointer;
1657
+ }
1658
+
1659
+ .kds-card-plan--selectable .kds-card-plan-header {
1660
+ padding-inline-end: var(--kds-spacing-4);
1661
+ }
1662
+
1663
+ /* BeerCSS makes header, h3 and label `position: relative`; they must stay static so the
1664
+ label's ::after resolves against the card, not against the label itself. */
1665
+ .kds-card-plan--selectable :is(.kds-card-plan-header, .kds-card-plan-header h3, .kds-card-plan-header label) {
1666
+ position: static;
1667
+ }
1668
+
1669
+ /* BeerCSS sizes bare <label>s; the title label must look like the h3 it lives in. */
1670
+ .kds-card-plan--selectable .kds-card-plan-header label {
1671
+ font: inherit;
1672
+ color: inherit;
1673
+ cursor: pointer;
1674
+ }
1675
+
1676
+ /* Above the (BeerCSS-positioned) feature items, below the radio and actions. */
1677
+ .kds-card-plan--selectable .kds-card-plan-header label::after {
1678
+ content: "";
1679
+ position: absolute;
1680
+ inset: 0;
1681
+ z-index: 1;
1682
+ border-radius: var(--kds-radius-lg);
1683
+ }
1684
+
1685
+ /* Interactive content inside the card stays above the stretched label, so it remains
1686
+ clickable (features may come as raw HTML from the consumer). */
1687
+ .kds-card-plan--selectable :is(a, button, input:not(.kds-card-plan-radio), select, textarea, summary, [tabindex]) {
1688
+ position: relative;
1689
+ z-index: 2;
1690
+ }
1691
+
1692
+ /* Optional plan description (KdsCardPlan `description`) — a <div>, so BeerCSS's sibling
1693
+ margin on <p> does not apply. */
1694
+ .kds-card-plan-description {
1695
+ font-size: var(--kds-font-size-sm);
1696
+ line-height: var(--kds-line-height-normal);
1697
+ color: var(--kds-color-text-secondary);
1698
+ }
1699
+
1700
+ /* Optional check per feature (KdsCardPlan `checkFeatures`), in the brand color. */
1701
+ .kds-card-plan-features--check li {
1702
+ display: flex;
1703
+ align-items: flex-start;
1704
+ gap: var(--kds-spacing-1);
1705
+ }
1706
+
1707
+ .kds-card-plan-features--check li > i {
1708
+ flex: none;
1709
+ margin-top: 2px;
1710
+ font-size: var(--kds-font-size-base);
1711
+ color: var(--primary);
1712
+ }
1713
+
1714
+ /* Selectable plan cards (new, onboarding): compact like the plan screen — badge on top,
1715
+ smaller title and price, and the divider above the feature list instead of under a big
1716
+ price. Plain .kds-card-plan (marketing/billing) keeps its larger layout. */
1717
+ .kds-card-plan--selectable {
1718
+ gap: var(--kds-spacing-1);
1719
+ }
1720
+
1721
+ /* Badge as a soft tag (not the solid pill of marketing plan cards), so it doesn't compete
1722
+ with the selected border. */
1723
+ .kds-card-plan--selectable .kds-card-plan-badge {
1724
+ order: -1;
1725
+ padding: var(--kds-spacing-0-25) var(--kds-spacing-1);
1726
+ background: color-mix(in srgb, var(--primary) 12%, var(--kds-surface-base));
1727
+ color: var(--primary);
1728
+ font-weight: var(--kds-font-weight-medium);
1729
+ line-height: var(--kds-line-height-normal);
1730
+ border-radius: var(--kds-radius-sm);
1731
+ }
1732
+
1733
+ .kds-card-plan--selectable .kds-card-plan-header h3 {
1734
+ font-size: var(--kds-font-size-lg);
1735
+ }
1736
+
1737
+ .kds-card-plan--selectable .kds-card-plan-price {
1738
+ gap: var(--kds-spacing-0-5);
1739
+ border-bottom: 0;
1740
+ }
1741
+
1742
+ .kds-card-plan--selectable .kds-price {
1743
+ font-size: var(--kds-font-size-sm);
1744
+ font-weight: var(--kds-font-weight-medium);
1745
+ line-height: var(--kds-line-height-normal);
1746
+ }
1747
+
1748
+ .kds-card-plan--selectable .kds-price-period {
1749
+ font-size: var(--kds-font-size-sm);
1750
+ }
1751
+
1752
+ .kds-card-plan--selectable .kds-card-plan-features {
1753
+ gap: var(--kds-spacing-0-75);
1754
+ margin-top: var(--kds-spacing-0-5);
1755
+ padding-top: var(--kds-spacing-1-5);
1756
+ border-top: 1px solid var(--kds-border-light);
1757
+ font-size: var(--kds-font-size-sm);
1758
+ line-height: var(--kds-line-height-snug);
1759
+ }
1760
+
1761
+ .kds-card-plan--selectable .kds-card-plan-features--check li > i {
1762
+ font-size: var(--kds-font-size-sm);
1763
+ margin-top: 3px;
1764
+ }
1765
+
1766
+ /* Plan group (KdsCardPlanGroup): as many columns as fit in the group's own width, so it
1767
+ also works in a narrow card next to the panel sidebar (a viewport breakpoint would put
1768
+ two 260px cards in a 300px card and overflow). Inside the group the cards fill their
1769
+ column; min(…, 100%) keeps a single column from overflowing very narrow containers. */
1770
+ .kds-card-plan-group {
1771
+ display: grid;
1772
+ grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
1773
+ gap: var(--kds-spacing-2);
1774
+ align-items: stretch;
1775
+ }
1776
+
1777
+ .kds-card-plan-group > .kds-card-plan {
1778
+ min-width: 0;
1779
+ max-width: none;
1780
+ }
1781
+
1782
+ /* In a selection the border signals the choice, so `recommended` keeps only its badge. */
1783
+ .kds-card-plan--selectable.recommended {
1784
+ background: var(--kds-surface-base);
1785
+ box-shadow: none;
1786
+ }
1787
+
1788
+ /* Unselected border matches the sibling selector cards (border-light), lighter than the
1789
+ plain plan card's border-medium. Before the hover rule so hover still wins. */
1790
+ .kds-card-plan--selectable,
1791
+ .kds-card-plan--selectable.recommended {
1792
+ border-color: var(--kds-border-light);
1793
+ }
1794
+
1795
+ /* Hover must not look like the selected state (primary border): neutral, darker border.
1796
+ The selected card keeps its primary border on hover (the :checked rule outranks this). */
1797
+ .kds-card-plan--selectable:hover,
1798
+ .kds-card-plan--selectable.recommended:hover {
1799
+ border-color: var(--kds-border-dark);
1800
+ }
1801
+
1802
+ .kds-card-plan--selectable.recommended:hover {
1803
+ box-shadow: var(--kds-shadow-2);
1804
+ }
1805
+
1806
+ /* Selected and focus states need :has. Without it the radio keeps its native look and
1807
+ focus ring, so the choice and the focus stay visible in older browsers. */
1808
+ @supports selector(:has(*)) {
1809
+ .kds-card-plan--selectable:has(.kds-card-plan-radio:checked) {
1810
+ border-color: var(--primary);
1811
+ background: color-mix(in srgb, var(--primary) 5%, var(--kds-surface-base));
1812
+ }
1813
+
1814
+ /* Focus is shown on the whole card; the radio's own ring would draw a second one. */
1815
+ .kds-card-plan--selectable:has(.kds-card-plan-radio:focus-visible) {
1816
+ outline: 2px solid var(--primary);
1817
+ outline-offset: 2px;
1818
+ }
1819
+
1820
+ .kds-card-plan-radio:focus-visible {
1821
+ outline: none;
1822
+ }
1823
+ }
1824
+
1825
+ /* Recommended Badge — inline dentro del card (no flotante), alineado a la izquierda.
1826
+ KdsCardPlan lo renderiza después del precio; en las cards seleccionables
1827
+ (.kds-card-plan--selectable) `order: -1` lo sube arriba del título. */
1535
1828
  .kds-card-plan-badge {
1536
1829
  align-self: flex-start;
1537
1830
  padding: var(--kds-spacing-0-5) var(--kds-spacing-1-5);
@@ -2151,6 +2444,154 @@ a.kds-btn.kds-btn-md {
2151
2444
  }
2152
2445
  }
2153
2446
 
2447
+ /* Stepper modifiers (additive: the base markup above, e.g. payment's mat:stepper,
2448
+ renders exactly as before without them). */
2449
+
2450
+ /* --numbered: step number inside the indicator. Bold 20px is "large text", so the
2451
+ white number on the info indicator (3.8:1) still meets AA. Completed steps hide the
2452
+ number and keep the ::after check. */
2453
+ .kds-stepper--numbered .kds-step-indicator {
2454
+ font-size: var(--kds-font-size-2xl);
2455
+ font-weight: var(--kds-font-weight-bold);
2456
+ line-height: 1;
2457
+ }
2458
+
2459
+ .kds-stepper--numbered .kds-step.current .kds-step-indicator {
2460
+ color: var(--kds-color-info-contrast);
2461
+ }
2462
+
2463
+ /* --on-primary follows the merchant's brand (KdsThemeProvider computes it from --primary). */
2464
+ .kds-stepper--numbered.kds-stepper--primary .kds-step.current .kds-step-indicator {
2465
+ color: var(--on-primary);
2466
+ }
2467
+
2468
+ .kds-stepper--numbered .kds-step.completed .kds-step-indicator {
2469
+ font-size: 0;
2470
+ }
2471
+
2472
+ /* --primary: current step in the brand color instead of info. */
2473
+ .kds-stepper--primary .kds-step.current .kds-step-indicator {
2474
+ background: var(--primary);
2475
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 15%, transparent);
2476
+ }
2477
+
2478
+ /* --numbered: pending steps and the connector must be visible on a white card (the base
2479
+ background-elevated #fafafa is ~1.04:1 against white). */
2480
+ .kds-stepper--numbered::before {
2481
+ background: var(--kds-color-gray-300);
2482
+ }
2483
+
2484
+ .kds-stepper--numbered .kds-step:not(.completed):not(.current) .kds-step-indicator {
2485
+ background: var(--kds-color-gray-200);
2486
+ box-shadow: none;
2487
+ }
2488
+
2489
+ /* --numbered + --primary (onboarding): compact 28px dots, small bold number (white on the
2490
+ brand color is 6:1, so it does not need large text), small labels, and a progress line
2491
+ per segment: green up to the current step, grey after it. */
2492
+ .kds-stepper--numbered.kds-stepper--primary::before {
2493
+ display: none;
2494
+ }
2495
+
2496
+ .kds-stepper--numbered.kds-stepper--primary .kds-step-indicator {
2497
+ width: var(--kds-spacing-3-5);
2498
+ height: var(--kds-spacing-3-5);
2499
+ font-size: var(--kds-font-size-sm);
2500
+ }
2501
+
2502
+ .kds-stepper--numbered.kds-stepper--primary .kds-step.completed .kds-step-indicator {
2503
+ font-size: 0;
2504
+ }
2505
+
2506
+ .kds-stepper--numbered.kds-stepper--primary .kds-step.completed .kds-step-indicator::after {
2507
+ font-size: var(--kds-font-size-lg);
2508
+ }
2509
+
2510
+ .kds-stepper--numbered.kds-stepper--primary .kds-step:not(:first-child)::before {
2511
+ content: "";
2512
+ position: absolute;
2513
+ top: calc(var(--kds-spacing-3-5) / 2 - 1px);
2514
+ left: -50%;
2515
+ right: 50%;
2516
+ height: 2px;
2517
+ background: var(--kds-color-gray-300);
2518
+ z-index: 0;
2519
+ }
2520
+
2521
+ .kds-stepper--numbered.kds-stepper--primary .kds-step:is(.completed, .current)::before {
2522
+ background: var(--kds-color-success-main);
2523
+ }
2524
+
2525
+ .kds-stepper--numbered.kds-stepper--primary .kds-step-label {
2526
+ margin-top: var(--kds-spacing-0-75);
2527
+ font-size: var(--kds-font-size-xs);
2528
+ }
2529
+
2530
+ .kds-stepper--numbered.kds-stepper--primary .kds-step.current .kds-step-label {
2531
+ font-weight: var(--kds-font-weight-bold);
2532
+ }
2533
+
2534
+ /* --current-label: when the stepper itself is narrow (≤ 560px of available width, e.g. a
2535
+ card next to the panel sidebar, or a phone) only the current step keeps a visible label;
2536
+ the others are visually hidden but still read by screen readers. The first/last current
2537
+ label hugs its edge so it is not cut. It is a container query so it reacts to the space
2538
+ the stepper gets, not to the viewport; browsers without container queries fall back to
2539
+ the viewport width. */
2540
+ /* Size containment drops the intrinsic width: without an explicit width the stepper would
2541
+ collapse to 0px inside content-sized parents (centered flex columns, inline-block). */
2542
+ .kds-stepper--current-label {
2543
+ container-type: inline-size;
2544
+ inline-size: 100%;
2545
+ }
2546
+
2547
+ @container (max-width: 560px) {
2548
+ .kds-stepper--current-label .kds-step:not(.current) .kds-step-label {
2549
+ position: absolute;
2550
+ width: 1px;
2551
+ height: 1px;
2552
+ overflow: hidden;
2553
+ clip-path: inset(50%);
2554
+ white-space: nowrap;
2555
+ }
2556
+
2557
+ .kds-stepper--current-label .kds-step.current .kds-step-label {
2558
+ white-space: nowrap;
2559
+ }
2560
+
2561
+ .kds-stepper--current-label .kds-step.current:first-child .kds-step-label {
2562
+ align-self: flex-start;
2563
+ text-align: start;
2564
+ }
2565
+
2566
+ .kds-stepper--current-label .kds-step.current:last-child .kds-step-label {
2567
+ align-self: flex-end;
2568
+ text-align: end;
2569
+ }
2570
+ }
2571
+
2572
+ @supports not (container-type: inline-size) {
2573
+ @media (max-width: 560px) {
2574
+ .kds-stepper--current-label .kds-step:not(.current) .kds-step-label {
2575
+ position: absolute;
2576
+ width: 1px;
2577
+ height: 1px;
2578
+ overflow: hidden;
2579
+ clip-path: inset(50%);
2580
+ white-space: nowrap;
2581
+ }
2582
+
2583
+ .kds-stepper--current-label .kds-step.current .kds-step-label {
2584
+ white-space: nowrap;
2585
+ }
2586
+ }
2587
+ }
2588
+
2589
+ /* Safety net for any stepper in a narrow box: a long word breaks inside its column
2590
+ instead of overlapping the next label. No effect where the words already fit. */
2591
+ .kds-step-label {
2592
+ overflow-wrap: break-word;
2593
+ }
2594
+
2154
2595
  /* ========================================
2155
2596
  Snackbar Positioning & Styling
2156
2597
  ======================================== */
@@ -3345,6 +3786,14 @@ label.radio span {
3345
3786
  cursor: pointer;
3346
3787
  }
3347
3788
 
3789
+ /* BeerCSS sets white-space: nowrap on the label, so a label longer than its container ran
3790
+ past it (e.g. on phones). Let the text wrap; labels that fit render as before. */
3791
+ label.checkbox > span,
3792
+ label.radio > span {
3793
+ white-space: normal;
3794
+ min-width: 0;
3795
+ }
3796
+
3348
3797
  /* Checked state.
3349
3798
  accent-color aplica al input nativo, que BeerCSS deja con opacity 0: no se ve.
3350
3799
  Se mantiene igual por si algun consumidor no usa el markup de BeerCSS. */
@@ -4207,6 +4656,47 @@ footer > .kds-container-center {
4207
4656
  transform: translateY(0);
4208
4657
  }
4209
4658
 
4659
+ /* Menu toggle (KdsSidebar with a menu): a real <button> holding avatar, text and arrow,
4660
+ with the dropdown as its sibling — never links inside a button. It looks like the plain
4661
+ header content, so BeerCSS's button styles (fill, size, radius, ripple) are reset. The
4662
+ vanilla markup (sidebar.js) keeps the click handler on the header itself. */
4663
+ .kds-sidebar-header > .kds-sidebar-header-toggle {
4664
+ display: flex;
4665
+ flex: 1;
4666
+ min-width: 0;
4667
+ align-items: center;
4668
+ justify-content: flex-start;
4669
+ gap: var(--kds-spacing-3);
4670
+ block-size: auto;
4671
+ margin: 0;
4672
+ padding: 0;
4673
+ border: 0;
4674
+ border-radius: 0;
4675
+ background: transparent;
4676
+ box-shadow: none;
4677
+ color: inherit;
4678
+ font: inherit;
4679
+ letter-spacing: inherit;
4680
+ text-align: start;
4681
+ text-transform: none;
4682
+ cursor: pointer;
4683
+ }
4684
+
4685
+ /* Outranks BeerCSS's `:is(…, button):not([class*=ripple])::after` ripple (0,2,1), which
4686
+ would otherwise cover the whole header (the button is not positioned). */
4687
+ .kds-sidebar .kds-sidebar-header > .kds-sidebar-header-toggle::after {
4688
+ content: none;
4689
+ }
4690
+
4691
+ .kds-sidebar-header > .kds-sidebar-header-toggle:focus-visible {
4692
+ outline: 2px solid var(--primary);
4693
+ outline-offset: 2px;
4694
+ }
4695
+
4696
+ .kds-sidebar-header-toggle[aria-expanded="true"] .kds-sidebar-dropdown-icon {
4697
+ transform: rotate(180deg);
4698
+ }
4699
+
4210
4700
  /* Navigation */
4211
4701
  .kds-sidebar-nav {
4212
4702
  padding: var(--kds-spacing-2) 0;
@@ -4370,6 +4860,10 @@ footer > .kds-container-center {
4370
4860
  transition: transform var(--kds-transition-standard) var(--kds-easing-ease-out);
4371
4861
  z-index: var(--kds-z-index-drawer);
4372
4862
  border-radius: 0;
4863
+ /* Full-height fixed drawer: scroll instead of cutting off items below the fold
4864
+ (long menus, short screens in landscape). */
4865
+ overflow-y: auto;
4866
+ overscroll-behavior: contain;
4373
4867
  }
4374
4868
 
4375
4869
  /* Barra superior mobile visible */
@@ -4964,6 +5458,46 @@ dialog#surveyModal button.circle {
4964
5458
  overflow-y: auto;
4965
5459
  }
4966
5460
 
5461
+ /* Read-to-accept contract (.kds-contract): content + acceptance checkbox + hint. The
5462
+ checkbox stays disabled until the content is scrolled to the end (KdsContract, or
5463
+ [data-kds-contract] with Khipu.initContract in the BeerCSS bundle). */
5464
+ .kds-contract {
5465
+ display: flex;
5466
+ flex-direction: column;
5467
+ gap: var(--kds-spacing-2);
5468
+ }
5469
+
5470
+ /* Inside the read-to-accept block the box is denser and shorter than the standalone
5471
+ contract page (.kds-contract-content alone keeps its 48px padding / 400px height). */
5472
+ .kds-contract > .kds-contract-content {
5473
+ padding: var(--kds-spacing-2);
5474
+ max-height: 240px;
5475
+ }
5476
+
5477
+ /* Denser paragraphs in the read-to-accept box (BeerCSS gives <p> 0.5rem + 1rem siblings). */
5478
+ .kds-contract > .kds-contract-content p {
5479
+ margin: 0 0 var(--kds-spacing-1) !important;
5480
+ }
5481
+
5482
+ /* The content is focusable so it can be scrolled with the keyboard. */
5483
+ .kds-contract-content:focus-visible {
5484
+ outline: 2px solid var(--primary);
5485
+ outline-offset: 2px;
5486
+ }
5487
+
5488
+ /* BeerCSS pads label.checkbox; the gap of .kds-contract spaces the parts and the hint
5489
+ (a <div>: BeerCSS adds a 1rem top margin to a <p> after a sibling) sits close to the
5490
+ checkbox it explains. */
5491
+ .kds-contract > .kds-contract-accept {
5492
+ padding-block: 0;
5493
+ }
5494
+
5495
+ .kds-contract > .kds-contract-hint {
5496
+ margin: calc(var(--kds-spacing-1) * -1) 0 0;
5497
+ font-size: var(--kds-font-size-sm);
5498
+ color: var(--kds-color-text-secondary);
5499
+ }
5500
+
4967
5501
  .kds-contract-content details {
4968
5502
  margin-bottom: var(--kds-spacing-4);
4969
5503
  }
@@ -5887,7 +6421,9 @@ dialog#surveyModal button.circle {
5887
6421
 
5888
6422
  /* ========================================
5889
6423
  05 - LOCKED FIELD (.field.locked)
5890
- Read-only field with lock icon
6424
+ Read-only field with lock icon.
6425
+ Value and label use text-secondary (not text-disabled): unlike a disabled
6426
+ field, the user still has to read a locked value, so it must meet AA contrast.
5891
6427
  ======================================== */
5892
6428
 
5893
6429
  .field.locked {
@@ -5896,40 +6432,57 @@ dialog#surveyModal button.circle {
5896
6432
 
5897
6433
  .field.locked > input,
5898
6434
  .field.locked > textarea {
5899
- color: var(--kds-color-text-disabled);
6435
+ color: var(--kds-color-text-secondary);
5900
6436
  cursor: default;
5901
6437
  pointer-events: none;
5902
6438
  }
5903
6439
 
5904
6440
  .field.locked > label {
5905
- color: var(--kds-color-text-disabled);
6441
+ color: var(--kds-color-text-secondary);
6442
+ }
6443
+
6444
+ /* Locked: no editable hover. */
6445
+ .field.label.border:not(.fill).locked:hover:not(:focus-within) > label::after {
6446
+ border-block-start-color: var(--outline);
6447
+ }
6448
+ .field.label.border:not(.fill).locked:hover:not(:focus-within) > :is(input, textarea, select) {
6449
+ border-color: var(--outline);
6450
+ }
6451
+ .field.label.locked:hover:not(:focus-within) > label {
6452
+ color: var(--kds-color-text-secondary);
5906
6453
  }
5907
6454
 
5908
- /* Locked: suppress all hover/focus visual changes */
5909
- .field.label.border:not(.fill).locked:hover:not(:focus-within) > label::after,
6455
+ /* Locked focus: a locked field stays reachable with Tab, so it needs a visible focus
6456
+ indicator (WCAG 2.4.7), but not the primary-colored one of an editable field.
6457
+ BeerCSS's 2px focus border is kept (its padding already compensates it) in the
6458
+ neutral text-secondary color, and the label does not turn primary. */
5910
6459
  .field.label.border:not(.fill).locked:focus-within > label::after {
5911
- border-block-start-color: var(--outline);
6460
+ border-block-start-color: var(--kds-color-text-secondary);
5912
6461
  }
5913
- .field.label.border:not(.fill).locked:hover:not(:focus-within) > :is(input, textarea, select),
5914
6462
  .field.label.border:not(.fill).locked:focus-within > :is(input, textarea, select) {
5915
- border-color: var(--outline);
6463
+ border-color: var(--kds-color-text-secondary);
5916
6464
  }
5917
- .field.label.locked:hover:not(:focus-within) > label {
5918
- color: var(--kds-color-text-disabled);
6465
+ .field.label.locked > :focus + label {
6466
+ color: var(--kds-color-text-secondary);
5919
6467
  }
5920
6468
 
5921
- .field.locked > i {
6469
+ /* Lock icon only: a leading .prefix icon is the first child and keeps its place.
6470
+ text-secondary, not text-disabled: the lock is what tells locked from disabled,
6471
+ so as a meaningful graphic it needs 3:1 (WCAG 1.4.11). */
6472
+ .field.locked > i:not(:first-child) {
5922
6473
  position: absolute;
5923
6474
  right: var(--kds-spacing-1-5);
5924
- top: 50%;
6475
+ /* Center of the input (BeerCSS --_middle), not of the field: with helper text the
6476
+ field is taller than the input. Without it both are the same. */
6477
+ top: var(--_middle, 50%);
5925
6478
  transform: translateY(-50%);
5926
- color: var(--kds-color-text-disabled);
6479
+ color: var(--kds-color-text-secondary);
5927
6480
  pointer-events: none;
5928
6481
  font-size: 18px;
5929
6482
  }
5930
6483
 
5931
6484
  /* Verified variant (green check) */
5932
- .field.locked.verified > i {
6485
+ .field.locked.verified > i:not(:first-child) {
5933
6486
  color: var(--kds-color-success-main);
5934
6487
  }
5935
6488
 
@@ -6850,6 +7403,260 @@ button.kds-fab:active:not(:disabled) {
6850
7403
  }
6851
7404
  }
6852
7405
 
7406
+ /* ========================================
7407
+ PROGRESS CHECKLIST (.kds-progress-checklist)
7408
+ Steps that advance pending → active → done (or error), e.g. an automatic
7409
+ validation. The list is aria-live; each item carries its status as visually
7410
+ hidden text (.kds-progress-checklist-status). Status modifiers are BEM
7411
+ (--pending/--active/--done/--error): BeerCSS already has global .error/.active.
7412
+ ======================================== */
7413
+
7414
+ .kds-progress-checklist {
7415
+ list-style: none;
7416
+ margin: 0;
7417
+ padding: 0;
7418
+ display: flex;
7419
+ flex-direction: column;
7420
+ gap: var(--kds-spacing-0-75);
7421
+ text-align: start;
7422
+ }
7423
+
7424
+ .kds-progress-checklist-item {
7425
+ position: relative;
7426
+ display: flex;
7427
+ align-items: center;
7428
+ gap: var(--kds-spacing-1-25);
7429
+ margin: 0;
7430
+ font-size: var(--kds-font-size-base);
7431
+ color: var(--kds-color-text-primary);
7432
+ transition: color 0.25s ease;
7433
+ }
7434
+
7435
+ /* Inside a bottom sheet the list is a centered block, under the centered title. */
7436
+ .kds-bottom-sheet-body > .kds-progress-checklist {
7437
+ width: fit-content;
7438
+ margin-inline: auto;
7439
+ }
7440
+
7441
+ .kds-progress-checklist-item--pending {
7442
+ color: var(--kds-color-text-secondary);
7443
+ }
7444
+
7445
+ .kds-progress-checklist-mark {
7446
+ display: inline-flex;
7447
+ align-items: center;
7448
+ justify-content: center;
7449
+ flex: none;
7450
+ width: var(--kds-spacing-2-5);
7451
+ height: var(--kds-spacing-2-5);
7452
+ }
7453
+
7454
+ .kds-progress-checklist-mark > i {
7455
+ font-size: var(--kds-spacing-2-5);
7456
+ }
7457
+
7458
+ /* Smaller dots so the loader fits the 20px mark like the icons do. */
7459
+ .kds-progress-checklist-mark .kds-dots-loader > span {
7460
+ width: var(--kds-spacing-0-5);
7461
+ height: var(--kds-spacing-0-5);
7462
+ }
7463
+
7464
+ .kds-progress-checklist-item--done .kds-progress-checklist-mark {
7465
+ color: var(--kds-color-success-main);
7466
+ }
7467
+
7468
+ .kds-progress-checklist-item--error .kds-progress-checklist-mark {
7469
+ color: var(--kds-color-error-main);
7470
+ }
7471
+
7472
+ .kds-progress-checklist-item--active .kds-progress-checklist-mark {
7473
+ color: var(--kds-color-text-secondary);
7474
+ }
7475
+
7476
+ /* The pending dot is decorative (the status is in the hidden text), so it can be faint;
7477
+ the label keeps text-secondary for contrast. */
7478
+ .kds-progress-checklist-item--pending .kds-progress-checklist-mark {
7479
+ color: var(--kds-color-text-disabled);
7480
+ }
7481
+
7482
+ .kds-progress-checklist-dot {
7483
+ width: var(--kds-spacing-0-75);
7484
+ height: var(--kds-spacing-0-75);
7485
+ border-radius: var(--kds-radius-full);
7486
+ background: currentColor;
7487
+ }
7488
+
7489
+ .kds-progress-checklist-status {
7490
+ position: absolute;
7491
+ width: 1px;
7492
+ height: 1px;
7493
+ overflow: hidden;
7494
+ clip-path: inset(50%);
7495
+ white-space: nowrap;
7496
+ }
7497
+
7498
+ /* ========================================
7499
+ FEEDBACK CARD (.kds-feedback-card)
7500
+ Optional question (e.g. "¿Cómo nos conociste?") with an answer control and a
7501
+ submit button; turns into a thank-you note (--submitted) in the same aria-live
7502
+ region. Text blocks are <div>s: BeerCSS adds margins to a <p> after a sibling.
7503
+ ======================================== */
7504
+
7505
+ .kds-feedback-card {
7506
+ display: flex;
7507
+ align-items: flex-start;
7508
+ gap: var(--kds-spacing-2);
7509
+ padding: var(--kds-spacing-2);
7510
+ border: 1px solid var(--kds-border-light);
7511
+ border-radius: var(--kds-radius-lg);
7512
+ background: var(--kds-color-background-elevated);
7513
+ }
7514
+
7515
+ .kds-feedback-card-icon {
7516
+ display: grid;
7517
+ place-items: center;
7518
+ flex: none;
7519
+ width: var(--kds-spacing-5);
7520
+ height: var(--kds-spacing-5);
7521
+ border-radius: var(--kds-radius-md);
7522
+ background: var(--kds-color-primary-focus);
7523
+ color: var(--kds-color-primary-main);
7524
+ }
7525
+
7526
+ .kds-feedback-card-body {
7527
+ flex: 1;
7528
+ min-width: 0;
7529
+ display: flex;
7530
+ flex-direction: column;
7531
+ gap: var(--kds-spacing-2);
7532
+ }
7533
+
7534
+ .kds-feedback-card-title {
7535
+ font-size: var(--kds-font-size-base);
7536
+ font-weight: var(--kds-font-weight-bold);
7537
+ color: var(--kds-color-text-primary);
7538
+ }
7539
+
7540
+ /* BeerCSS adds 1rem above a .field after a sibling; the body gap already spaces it. */
7541
+ .kds-feedback-card-body > .field {
7542
+ margin-block-start: 0 !important;
7543
+ }
7544
+
7545
+ .kds-feedback-card-description {
7546
+ font-size: var(--kds-font-size-sm);
7547
+ line-height: var(--kds-line-height-normal);
7548
+ color: var(--kds-color-text-secondary);
7549
+ }
7550
+
7551
+ .kds-feedback-card--submitted {
7552
+ align-items: center;
7553
+ border-color: var(--kds-color-success-border-light);
7554
+ background: var(--kds-color-success-soft);
7555
+ }
7556
+
7557
+ .kds-feedback-card--submitted .kds-feedback-card-icon {
7558
+ background: var(--kds-color-background-paper);
7559
+ color: var(--kds-color-success-main);
7560
+ }
7561
+
7562
+ /* ========================================
7563
+ CONSENT CARD (.kds-consent-card)
7564
+ Access consent on a .kds-card-elevated: "<requester> solicita acceso a
7565
+ <resource>", sections (data requested, validity, purpose) and
7566
+ Authorize / Reject. Headings are div[role=heading] so BeerCSS heading
7567
+ margins do not apply. The secure footer goes outside the card.
7568
+ ======================================== */
7569
+
7570
+ .kds-consent-card {
7571
+ display: flex;
7572
+ flex-direction: column;
7573
+ gap: var(--kds-spacing-3);
7574
+ padding: var(--kds-spacing-3);
7575
+ }
7576
+
7577
+ .kds-consent-card-header {
7578
+ display: flex;
7579
+ flex-direction: column;
7580
+ align-items: center;
7581
+ gap: var(--kds-spacing-1);
7582
+ text-align: center;
7583
+ }
7584
+
7585
+ .kds-consent-card-title {
7586
+ font-size: var(--kds-font-size-xl);
7587
+ line-height: var(--kds-line-height-tight);
7588
+ color: var(--kds-color-text-primary);
7589
+ }
7590
+
7591
+ .kds-consent-card-title strong {
7592
+ color: var(--primary);
7593
+ font-weight: var(--kds-font-weight-semibold);
7594
+ }
7595
+
7596
+ .kds-consent-card-subtitle {
7597
+ font-size: var(--kds-font-size-sm);
7598
+ color: var(--kds-color-text-secondary);
7599
+ }
7600
+
7601
+ .kds-consent-card-body {
7602
+ display: flex;
7603
+ flex-direction: column;
7604
+ gap: var(--kds-spacing-2);
7605
+ }
7606
+
7607
+ .kds-consent-card-section {
7608
+ display: flex;
7609
+ flex-direction: column;
7610
+ gap: var(--kds-spacing-1);
7611
+ }
7612
+
7613
+ /* Dividers only between sections, not before the actions. */
7614
+ .kds-consent-card-section + .kds-consent-card-section {
7615
+ padding-block-start: var(--kds-spacing-2);
7616
+ border-block-start: 1px solid var(--kds-color-divider);
7617
+ }
7618
+
7619
+ .kds-consent-card-section-title {
7620
+ font-size: var(--kds-font-size-xs);
7621
+ font-weight: var(--kds-font-weight-semibold);
7622
+ letter-spacing: var(--kds-letter-spacing-wide);
7623
+ text-transform: uppercase;
7624
+ color: var(--kds-color-text-secondary);
7625
+ }
7626
+
7627
+ /* !important on the top margin: BeerCSS adds 1rem to a <ul> after a sibling with a
7628
+ higher specificity (same approach as .kds-card-elevated). */
7629
+ .kds-consent-card-items {
7630
+ list-style: none;
7631
+ margin: 0;
7632
+ margin-block-start: 0 !important;
7633
+ padding: 0;
7634
+ display: flex;
7635
+ flex-direction: column;
7636
+ gap: var(--kds-spacing-0-75);
7637
+ }
7638
+
7639
+ .kds-consent-card-item {
7640
+ display: flex;
7641
+ align-items: flex-start;
7642
+ gap: var(--kds-spacing-1-25);
7643
+ margin: 0;
7644
+ font-size: var(--kds-font-size-base);
7645
+ color: var(--kds-color-text-primary);
7646
+ }
7647
+
7648
+ .kds-consent-card-item > i {
7649
+ flex: none;
7650
+ font-size: var(--kds-spacing-2-5);
7651
+ color: var(--kds-color-text-secondary);
7652
+ }
7653
+
7654
+ .kds-consent-card-actions {
7655
+ display: flex;
7656
+ flex-direction: column;
7657
+ gap: var(--kds-spacing-1);
7658
+ }
7659
+
6853
7660
  /* ========================================
6854
7661
  14 - BOTTOM SHEET (.kds-bottom-sheet)
6855
7662
  Modal bottom sheet for mobile confirmations
@@ -6879,12 +7686,33 @@ button.kds-fab:active:not(:disabled) {
6879
7686
  background: var(--kds-color-background-paper);
6880
7687
  border-radius: var(--kds-radius-2xl) var(--kds-radius-2xl) 0 0;
6881
7688
  padding: var(--kds-spacing-3-5) var(--kds-spacing-3) var(--kds-spacing-3);
7689
+ /* iPhone home indicator: keep the actions clear of it on viewport-fit=cover pages. */
7690
+ padding-bottom: calc(var(--kds-spacing-3) + env(safe-area-inset-bottom, 0px));
6882
7691
  box-shadow: var(--kds-bottom-sheet-shadow);
6883
7692
  animation: kds-rise 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) both;
6884
7693
  text-align: center;
6885
7694
  position: relative;
6886
7695
  }
6887
7696
 
7697
+ /* The dialog container receives focus programmatically when it opens (Radix, tabindex=-1);
7698
+ the browser ring around the whole sheet is noise. Controls inside keep their own ring. */
7699
+ .kds-bottom-sheet:focus-visible {
7700
+ outline: none;
7701
+ }
7702
+
7703
+ /* As soon as the viewport is wider than the sheet (--kds-bottom-sheet-max-width = 420px;
7704
+ media queries cannot read tokens) the sheet no longer spans the screen, and glued to the
7705
+ bottom edge with square bottom corners it looks cut off. It stays anchored at the bottom
7706
+ (still a drawer) but floats: all corners rounded and a gap to the edge. The max-height
7707
+ also caps the full-height variant. */
7708
+ @media (min-width: 421px) {
7709
+ .kds-bottom-sheet {
7710
+ margin-bottom: var(--kds-spacing-3);
7711
+ border-radius: var(--kds-radius-2xl);
7712
+ max-height: calc(90dvh - var(--kds-spacing-3));
7713
+ }
7714
+ }
7715
+
6888
7716
  .kds-bottom-sheet-grabber {
6889
7717
  position: absolute;
6890
7718
  left: 50%;
@@ -6948,6 +7776,92 @@ button.kds-fab:active:not(:disabled) {
6948
7776
  flex-direction: column;
6949
7777
  }
6950
7778
 
7779
+ /* Dialog variant (KdsBottomSheet variant="dialog"): a regular modal for desktop flows, with
7780
+ left-aligned text. On phones it stays a bottom sheet (stacked actions, primary first, as
7781
+ the DOM order); from 521px it is centered on the screen with the actions side by side and
7782
+ the primary on the right (row-reverse keeps the primary first in the tab order). 520px is
7783
+ where two buttons stop fitting side by side. The scrim modifier centers it vertically. */
7784
+ .kds-bottom-sheet--dialog {
7785
+ text-align: left;
7786
+ }
7787
+
7788
+ .kds-bottom-sheet--dialog .kds-bottom-sheet-title {
7789
+ font-weight: var(--kds-font-weight-bold);
7790
+ }
7791
+
7792
+ .kds-bottom-sheet--dialog .kds-bottom-sheet-description {
7793
+ font-size: var(--kds-font-size-sm);
7794
+ line-height: var(--kds-line-height-normal);
7795
+ color: var(--kds-color-text-primary);
7796
+ }
7797
+
7798
+ /* Status dialog (align="center"), e.g. a validation in progress with a loader on top. */
7799
+ .kds-bottom-sheet--dialog.kds-bottom-sheet--center {
7800
+ text-align: center;
7801
+ }
7802
+
7803
+ /* Icon / loader slot above the title (KdsBottomSheet `icon`): a flex row so a block child
7804
+ (a spinner) follows the text alignment too. */
7805
+ div.kds-bottom-sheet-icon {
7806
+ display: flex;
7807
+ justify-content: center;
7808
+ margin-bottom: var(--kds-spacing-1);
7809
+ }
7810
+
7811
+ .kds-bottom-sheet--dialog:not(.kds-bottom-sheet--center) div.kds-bottom-sheet-icon {
7812
+ justify-content: flex-start;
7813
+ }
7814
+
7815
+ /* An icon in the slot matches the default KdsSpinner (BeerCSS circle, 2.5rem), so swapping
7816
+ the loader for a result icon does not shift the content. */
7817
+ div.kds-bottom-sheet-icon > i {
7818
+ font-size: 2.5rem;
7819
+ inline-size: 2.5rem;
7820
+ block-size: 2.5rem;
7821
+ min-inline-size: unset;
7822
+ min-block-size: unset;
7823
+ }
7824
+
7825
+ /* Short note above the actions (KdsBottomSheet `hint`), e.g. "No cierres esta ventana." */
7826
+ .kds-bottom-sheet-hint {
7827
+ margin: var(--kds-spacing-2) 0 0;
7828
+ font-size: var(--kds-font-size-xs);
7829
+ line-height: var(--kds-line-height-normal);
7830
+ color: var(--kds-color-text-secondary);
7831
+ }
7832
+
7833
+ @media (min-width: 521px) {
7834
+ .kds-bottom-sheet-scrim--dialog {
7835
+ align-items: center;
7836
+ padding: var(--kds-spacing-2);
7837
+ }
7838
+
7839
+ .kds-bottom-sheet--dialog {
7840
+ margin: 0;
7841
+ padding: var(--kds-spacing-3);
7842
+ border-radius: var(--kds-radius-lg);
7843
+ max-height: 90dvh;
7844
+ }
7845
+
7846
+ .kds-bottom-sheet--dialog .kds-bottom-sheet-grabber {
7847
+ display: none;
7848
+ }
7849
+
7850
+ .kds-bottom-sheet--dialog .kds-bottom-sheet-title {
7851
+ margin-top: 0;
7852
+ }
7853
+
7854
+ .kds-bottom-sheet--dialog .kds-bottom-sheet-actions {
7855
+ flex-direction: row-reverse;
7856
+ margin-top: var(--kds-spacing-2);
7857
+ }
7858
+
7859
+ .kds-bottom-sheet--dialog .kds-bottom-sheet-actions > * {
7860
+ flex: 1;
7861
+ min-width: 0;
7862
+ }
7863
+ }
7864
+
6951
7865
  /* ========================================
6952
7866
  DOCUMENT FRAME (.kds-document-frame)
6953
7867
  Documento embebido (iframe) que llena su contenedor. --kds-document-frame-scale achica
@@ -9286,6 +10200,22 @@ a.kds-copy-all-btn.copied:hover {
9286
10200
  .kds-section-note.kds-error { color: var(--kds-color-error-dark); }
9287
10201
  .kds-section-note.kds-error > i { color: var(--kds-color-error-dark); }
9288
10202
 
10203
+ /* Neutral tone: calm, non-alarming context (e.g. "Datos obtenidos de tu cuenta en…",
10204
+ "Khipu no almacena tus contraseñas"). Secondary text with the icon in the brand color. */
10205
+ .kds-section-note.kds-neutral { color: var(--kds-color-text-secondary); }
10206
+ .kds-section-note.kds-neutral > i { color: var(--primary); }
10207
+
10208
+ /* Neutral notes often wrap to two lines: icon pinned to the first line, with a gap. */
10209
+ .kds-section-note.kds-neutral {
10210
+ align-items: flex-start;
10211
+ gap: var(--kds-spacing-1);
10212
+ line-height: var(--kds-line-height-normal);
10213
+ }
10214
+
10215
+ .kds-section-note.kds-neutral > i {
10216
+ margin-top: 0.125em;
10217
+ }
10218
+
9289
10219
  /* Dark: the semantic *-dark shades are near-invisible on the dark page bg —
9290
10220
  use the alert *-text tokens (light shades in dark). Base note is warning. */
9291
10221
  [data-theme="dark"] .kds-section-note,
@@ -9296,6 +10226,8 @@ a.kds-copy-all-btn.copied:hover {
9296
10226
  [data-theme="dark"] .kds-section-note.kds-success > i { color: var(--kds-alert-success-text); }
9297
10227
  [data-theme="dark"] .kds-section-note.kds-error,
9298
10228
  [data-theme="dark"] .kds-section-note.kds-error > i { color: var(--kds-alert-error-text); }
10229
+ [data-theme="dark"] .kds-section-note.kds-neutral { color: var(--kds-color-text-secondary); }
10230
+ [data-theme="dark"] .kds-section-note.kds-neutral > i { color: var(--primary); }
9299
10231
 
9300
10232
  /* ========================================
9301
10233
  INFO TOOLTIP (.kds-info-tip)