@khipu/design-system 0.2.0-alpha.6 → 0.2.0-alpha.61

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.
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
13
13
  * Source: design-system/src/tokens/tokens.json
14
- * Generated: 2026-05-14T21:45:40.100Z
14
+ * Generated: 2026-06-19T16:33:44.315Z
15
15
  *
16
16
  * To regenerate:
17
17
  * cd design-system && npm run tokens:generate
@@ -48,15 +48,21 @@
48
48
  --kds-color-success-main: #2E7D32;
49
49
  --kds-color-success-light: #4CAF50;
50
50
  --kds-color-success-dark: #1B5E20;
51
+ --kds-color-success-contrast: #FFFFFF;
51
52
  --kds-color-warning-main: #EF6C00;
52
53
  --kds-color-warning-light: #FF9800;
53
54
  --kds-color-warning-dark: #E65100;
55
+ --kds-color-warning-contrast: #FFFFFF;
56
+ --kds-color-warning-warm: #8A6D1A;
54
57
  --kds-color-error-main: #D32F2F;
55
58
  --kds-color-error-light: #EF5350;
56
59
  --kds-color-error-dark: #C62828;
60
+ --kds-color-error-contrast: #FFFFFF;
57
61
  --kds-color-info-main: #0288D1;
58
62
  --kds-color-info-light: #03A9F4;
59
63
  --kds-color-info-dark: #01579B;
64
+ --kds-color-info-contrast: #FFFFFF;
65
+ --kds-color-info-blue: #5A5FE0;
60
66
 
61
67
  /* Text colors */
62
68
  --kds-color-text-primary: #333333;
@@ -134,6 +140,8 @@
134
140
  --kds-font-weight-bold: 700;
135
141
 
136
142
  /* Font sizes (base scale xs–4xl: see responsive section below) */
143
+ --kds-font-size-decimal-sup: 0.5em;
144
+
137
145
  /* Line heights */
138
146
  --kds-line-height-tight: 1.2;
139
147
  --kds-line-height-snug: 1.375;
@@ -846,7 +854,10 @@ a.kds-btn {
846
854
 
847
855
  /* Interaction */
848
856
  cursor: pointer;
849
- transition: background .15s, box-shadow .15s, transform .05s;
857
+ transition: background-color var(--kds-transition-shorter) var(--kds-easing-standard),
858
+ color var(--kds-transition-shorter) var(--kds-easing-standard),
859
+ box-shadow var(--kds-transition-shorter) var(--kds-easing-standard),
860
+ transform var(--kds-transition-shortest) var(--kds-easing-standard);
850
861
  box-sizing: border-box;
851
862
  vertical-align: middle;
852
863
  }
@@ -978,7 +989,7 @@ a.kds-btn-text {
978
989
 
979
990
  button.kds-btn-text:hover:not(:disabled),
980
991
  a.kds-btn-text:hover:not(:disabled) {
981
- background: var(--kds-color-primary-hover); /* rgba(131, 71, 173, 0.04) */
992
+ color: var(--kds-color-primary-dark);
982
993
  }
983
994
 
984
995
  button.kds-btn-text:disabled,
@@ -988,6 +999,30 @@ a.kds-btn-text:disabled {
988
999
  box-shadow: none;
989
1000
  }
990
1001
 
1002
+ /* Error text (destructive, ghost) — red text, no fill/border. Para acciones
1003
+ destructivas secundarias que no deben competir con el CTA primario. */
1004
+ button.kds-btn-error-text,
1005
+ a.kds-btn-error-text {
1006
+ background: transparent;
1007
+ color: var(--kds-color-error-main);
1008
+ border: none;
1009
+ padding: 6px var(--kds-spacing-2);
1010
+ min-height: 32px;
1011
+ box-shadow: none;
1012
+ }
1013
+
1014
+ button.kds-btn-error-text:hover:not(:disabled),
1015
+ a.kds-btn-error-text:hover:not(:disabled) {
1016
+ color: var(--kds-color-error-dark);
1017
+ }
1018
+
1019
+ button.kds-btn-error-text:disabled,
1020
+ a.kds-btn-error-text:disabled {
1021
+ background: transparent;
1022
+ color: var(--kds-color-action-disabled);
1023
+ box-shadow: none;
1024
+ }
1025
+
991
1026
  /* Icon wrapper - control size via span container */
992
1027
  button.kds-btn > .kds-icon,
993
1028
  a.kds-btn > .kds-icon {
@@ -1050,6 +1085,7 @@ a.kds-btn.kds-btn-md {
1050
1085
  padding: var(--kds-spacing-2);
1051
1086
  box-shadow: var(--kds-shadow-card);
1052
1087
  transition: box-shadow 0.3s ease;
1088
+ margin-block-start: 0 !important;
1053
1089
  }
1054
1090
 
1055
1091
  .kds-card-elevated:hover,
@@ -1072,63 +1108,90 @@ a.kds-btn.kds-btn-md {
1072
1108
  }
1073
1109
  }
1074
1110
 
1075
- /* Selection card */
1111
+ /* Selection card.
1112
+ IMPORTANTE: este componente se renderiza como `<button>`. BeerCSS aplica al
1113
+ `button` base: `display: inline-flex; align-items: center; justify-content: center;
1114
+ block-size: 2.5rem; padding: 0 1rem; background: var(--primary); color: on-primary`.
1115
+ Todas esas reglas hay que sobreescribirlas para que el card-selector funcione como
1116
+ un contenedor flex column de altura variable y alineado a la izquierda.
1117
+
1118
+ Convención del DS: spacing entre hijos via `gap` del flex padre + padding.
1119
+ Los elementos internos (.kds-card-selector-icon/-title/-description) NO usan margin. */
1076
1120
  .kds-card-selector {
1121
+ /* Reset BeerCSS button */
1122
+ display: flex;
1123
+ flex-direction: column;
1124
+ align-items: stretch;
1125
+ justify-content: flex-start;
1126
+ block-size: auto;
1127
+ inline-size: 100%;
1128
+ text-align: left;
1129
+ line-height: 1.5;
1130
+ color: var(--kds-color-text-primary);
1131
+ /* Estilos propios del card-selector */
1077
1132
  padding: var(--kds-spacing-3);
1133
+ gap: var(--kds-spacing-1-5);
1078
1134
  border-radius: var(--kds-radius-md);
1079
- border: 2px solid var(--kds-border-light);
1135
+ border: var(--kds-border-width-md) solid var(--kds-border-light);
1080
1136
  background: var(--kds-color-background-paper);
1081
1137
  transition: all 0.3s ease;
1082
- text-align: left;
1083
1138
  cursor: pointer;
1084
- display: flex;
1085
- flex-direction: column;
1086
1139
  }
1087
1140
 
1088
- .kds-card-selector:hover {
1089
- border-color: #D1D5DB; /* gray-300 */
1141
+ .kds-card-selector:hover:not(.selected) {
1142
+ border-color: var(--kds-color-primary-light);
1143
+ background: var(--kds-color-primary-hover);
1144
+ }
1145
+
1146
+ /* Override del ripple/overlay default de BeerCSS:
1147
+ `:is(.wave,.chip,.button,button,nav.tabbed>a,...):not([class*=ripple])::after`
1148
+ tiene specificity (0,2,4) según DevTools (Chrome cuenta cada selector dentro
1149
+ de :is() individualmente para algunos motores). Usamos !important — consistente
1150
+ con cómo se overridean otros estilos de BeerCSS en este archivo (67 usos previos).
1151
+ Antes pintaba negro porque `currentColor` resolvía a text-primary del card. */
1152
+ .kds-card-selector::after {
1153
+ background-image: radial-gradient(circle, var(--kds-color-primary-main) 1%, transparent 1%) !important;
1090
1154
  }
1091
1155
 
1092
1156
  .kds-card-selector.selected {
1093
- border-color: #3B82F6; /* blue-600 */
1094
- background: #EFF6FF; /* blue-50 */
1157
+ border-color: var(--kds-color-primary-main);
1158
+ background: var(--kds-color-primary-faint);
1095
1159
  box-shadow: var(--kds-shadow-md);
1096
1160
  }
1097
1161
 
1098
- /* Icon container */
1162
+ /* Icon container — spacing manejado por gap del padre, no margin */
1099
1163
  .kds-card-selector-icon {
1100
- width: 48px;
1101
- height: 48px;
1102
- background: #DBEAFE; /* blue-100 */
1103
- border-radius: 8px;
1164
+ width: var(--kds-spacing-6);
1165
+ height: var(--kds-spacing-6);
1166
+ background: var(--kds-color-primary-focus);
1167
+ border-radius: var(--kds-radius-sm);
1104
1168
  display: flex;
1105
1169
  align-items: center;
1106
1170
  justify-content: center;
1107
- margin-bottom: 16px;
1108
1171
  }
1109
1172
 
1110
1173
  .kds-card-selector-icon i,
1111
1174
  .kds-card-selector-icon svg {
1112
- width: 24px;
1113
- height: 24px;
1114
- min-width: 24px;
1115
- min-height: 24px;
1116
- color: #3B82F6; /* blue-600 */
1175
+ width: var(--kds-spacing-3);
1176
+ height: var(--kds-spacing-3);
1177
+ min-width: var(--kds-spacing-3);
1178
+ min-height: var(--kds-spacing-3);
1179
+ font-size: var(--kds-spacing-3);
1180
+ color: var(--kds-color-primary-main);
1117
1181
  }
1118
1182
 
1119
- /* Title */
1183
+ /* Title — spacing manejado por gap del padre, no margin */
1120
1184
  .kds-card-selector-title {
1121
- font-weight: 600;
1185
+ font-weight: var(--kds-font-weight-semibold);
1122
1186
  color: var(--kds-color-text-primary);
1123
- margin-bottom: 8px;
1124
- font-size: 16px;
1187
+ font-size: var(--kds-font-size-lg);
1125
1188
  }
1126
1189
 
1127
1190
  /* Description */
1128
1191
  .kds-card-selector-description {
1129
- font-size: 14px;
1130
- color: #4B5563; /* gray-600 */
1131
- line-height: 1.5;
1192
+ font-size: var(--kds-font-size-sm);
1193
+ color: var(--kds-color-text-secondary);
1194
+ line-height: var(--kds-line-height-normal);
1132
1195
  }
1133
1196
 
1134
1197
  /* Selected state - visual feedback via border only */
@@ -1140,14 +1203,22 @@ a.kds-btn.kds-btn-md {
1140
1203
  display: flex;
1141
1204
  flex-direction: column;
1142
1205
  gap: var(--kds-spacing-2);
1143
- padding: var(--kds-spacing-4);
1206
+ padding: var(--kds-spacing-2);
1144
1207
  border-radius: var(--kds-radius-lg);
1145
1208
  border: 2px solid var(--kds-border-medium);
1146
- max-width: 400px; /* Increased from 365px for better text spacing */
1209
+ /* Ancho mínimo aplicado a TODOS los planes así un plan sin badge en una
1210
+ grilla con un plan recomendado mantiene la misma anchura, y el badge nunca
1211
+ se superpone al título por estrechez del card. */
1212
+ min-width: 260px;
1213
+ max-width: 400px;
1147
1214
  background: var(--kds-surface-base);
1148
1215
  transition: all 0.3s ease;
1149
1216
  cursor: pointer;
1150
- height: 100%; /* Ensure cards fill grid height */
1217
+ /* Alto fijo: el card se estira al alto de su row del grid (align-items stretch
1218
+ es el default) — todas las cards de la misma fila quedan a la misma altura
1219
+ sin importar el contenido. `align-self: stretch` lo hace explícito. */
1220
+ height: 100%;
1221
+ align-self: stretch;
1151
1222
  }
1152
1223
 
1153
1224
  .kds-card-plan:hover {
@@ -1167,18 +1238,19 @@ a.kds-btn.kds-btn-md {
1167
1238
  box-shadow: var(--kds-shadow-elevation-4);
1168
1239
  }
1169
1240
 
1170
- /* Recommended Badge */
1241
+ /* Recommended Badge — inline dentro del card (no flotante).
1242
+ Es el primer hijo del .kds-card-plan, así que aparece arriba de todo
1243
+ el contenido, alineado a la izquierda. */
1171
1244
  .kds-card-plan-badge {
1172
- position: absolute;
1173
- top: -12px;
1174
- right: var(--kds-spacing-6);
1175
- padding: var(--kds-spacing-1) var(--kds-spacing-4);
1245
+ align-self: flex-start;
1246
+ padding: var(--kds-spacing-0-5) var(--kds-spacing-1-5);
1176
1247
  background: var(--primary);
1177
1248
  color: white;
1178
- font-size: var(--kds-font-size-sm);
1249
+ font-size: var(--kds-font-size-xs);
1179
1250
  font-weight: var(--kds-font-weight-semibold);
1251
+ line-height: 1;
1180
1252
  border-radius: var(--kds-radius-full);
1181
- box-shadow: var(--kds-shadow-elevation-1);
1253
+ white-space: nowrap;
1182
1254
  }
1183
1255
 
1184
1256
  /* Plan Header */
@@ -1206,13 +1278,11 @@ a.kds-btn.kds-btn-md {
1206
1278
  display: flex;
1207
1279
  align-items: baseline;
1208
1280
  gap: var(--kds-spacing-2);
1209
- padding: var(--kds-spacing-4) 0;
1210
1281
  border-bottom: 1px solid var(--kds-border-light);
1211
- min-height: 88px; /* Standardize price area height */
1212
1282
  }
1213
1283
 
1214
1284
  .kds-price {
1215
- font-size: 42px;
1285
+ font-size: var(--kds-font-size-4xl);
1216
1286
  font-weight: var(--kds-font-weight-bold);
1217
1287
  color: var(--primary);
1218
1288
  line-height: 1.1;
@@ -1726,53 +1796,108 @@ a.kds-btn.kds-btn-md {
1726
1796
  }
1727
1797
 
1728
1798
  /* ========================================
1729
- Snackbar Positioning
1799
+ Snackbar Positioning & Styling
1730
1800
  ======================================== */
1731
1801
 
1732
1802
  .snackbar {
1733
1803
  position: fixed;
1734
- bottom: var(--kds-spacing-3);
1735
- left: 50%;
1736
- transform: translateX(-50%);
1737
1804
  z-index: var(--kds-z-index-snackbar);
1738
1805
  min-width: 344px;
1739
1806
  max-width: var(--kds-snackbar-max-width);
1740
1807
  box-shadow: var(--kds-shadow-8);
1808
+ border-radius: var(--kds-radius-md);
1809
+ padding: var(--kds-spacing-1-5) var(--kds-spacing-2);
1810
+ gap: var(--kds-spacing-1);
1811
+ font-family: var(--kds-font-family-primary);
1812
+ font-size: var(--kds-font-size-body2);
1813
+ font-weight: var(--kds-font-weight-medium);
1814
+ line-height: var(--kds-line-height-normal);
1815
+ letter-spacing: var(--kds-letter-spacing-normal);
1816
+ overflow: hidden;
1741
1817
  }
1742
1818
 
1743
1819
  /* Snackbar active state - ensure visibility when toggled via JS */
1744
1820
  .snackbar.active {
1745
1821
  visibility: visible !important;
1746
1822
  opacity: 1 !important;
1747
- transform: translateX(-50%) !important;
1748
1823
  }
1749
1824
 
1750
- /* Snackbar semantic variants - background + text/icon color */
1825
+ /* Snackbar semantic variants
1826
+ All use white text (--kds-color-primary-contrast) on solid semantic backgrounds */
1751
1827
  .snackbar.error {
1752
1828
  background-color: var(--kds-color-error-main) !important;
1753
- color: var(--on-error, var(--kds-color-primary-contrast)) !important;
1829
+ color: var(--kds-color-primary-contrast) !important;
1754
1830
  }
1755
1831
 
1756
1832
  .snackbar.error i {
1757
- color: var(--on-error, var(--kds-color-primary-contrast)) !important;
1833
+ color: var(--kds-color-primary-contrast) !important;
1758
1834
  }
1759
1835
 
1760
1836
  .snackbar.info {
1761
1837
  background-color: var(--kds-color-info-main) !important;
1762
- color: var(--on-info, var(--kds-color-primary-contrast)) !important;
1838
+ color: var(--kds-color-primary-contrast) !important;
1763
1839
  }
1764
1840
 
1765
1841
  .snackbar.info i {
1766
- color: var(--on-info, var(--kds-color-primary-contrast)) !important;
1842
+ color: var(--kds-color-primary-contrast) !important;
1767
1843
  }
1768
1844
 
1769
1845
  .snackbar.success {
1770
1846
  background-color: var(--kds-color-success-main) !important;
1771
- color: var(--on-success, var(--kds-color-primary-contrast)) !important;
1847
+ color: var(--kds-color-primary-contrast) !important;
1772
1848
  }
1773
1849
 
1774
1850
  .snackbar.success i {
1775
- color: var(--on-success, var(--kds-color-primary-contrast)) !important;
1851
+ color: var(--kds-color-primary-contrast) !important;
1852
+ }
1853
+
1854
+ /* Snackbar progress bar — animated timer for auto-dismiss */
1855
+ .snackbar[data-auto-dismiss]::after {
1856
+ content: '';
1857
+ position: absolute;
1858
+ bottom: 0;
1859
+ left: 0;
1860
+ height: 3px;
1861
+ width: 100%;
1862
+ background: rgba(255, 255, 255, 0.35);
1863
+ border-radius: 0 0 var(--kds-radius-md) var(--kds-radius-md);
1864
+ animation: kds-snackbar-timer var(--kds-snackbar-duration, 5s) linear forwards;
1865
+ }
1866
+
1867
+ @keyframes kds-snackbar-timer {
1868
+ from { width: 100%; }
1869
+ to { width: 0; }
1870
+ }
1871
+
1872
+ /* Snackbar close button */
1873
+ .kds-snackbar-close {
1874
+ background: none !important;
1875
+ border: none !important;
1876
+ color: var(--kds-color-primary-contrast) !important;
1877
+ cursor: pointer;
1878
+ padding: var(--kds-spacing-0-5) !important;
1879
+ margin: calc(-1 * var(--kds-spacing-0-5)) !important;
1880
+ margin-left: 0 !important;
1881
+ border-radius: var(--kds-radius-full) !important;
1882
+ display: flex;
1883
+ align-items: center;
1884
+ justify-content: center;
1885
+ flex-shrink: 0;
1886
+ opacity: 0.7;
1887
+ transition: opacity 150ms;
1888
+ min-width: auto !important;
1889
+ width: auto !important;
1890
+ height: auto !important;
1891
+ }
1892
+
1893
+ .kds-snackbar-close:hover {
1894
+ opacity: 1;
1895
+ background: rgba(255, 255, 255, 0.15) !important;
1896
+ }
1897
+
1898
+ .kds-snackbar-close i {
1899
+ font-size: 18px !important;
1900
+ color: var(--kds-color-primary-contrast) !important;
1776
1901
  }
1777
1902
 
1778
1903
  /* ========================================
@@ -1973,6 +2098,210 @@ a.kds-btn-google:disabled {
1973
2098
  height: var(--kds-spacing-button-icon-size);
1974
2099
  }
1975
2100
 
2101
+ /* ========================================
2102
+ KDS LINEAR PROGRESS
2103
+ Native <progress> (KdsLinearProgress). Additive over BeerCSS `progress`,
2104
+ scoped to .kds-progress so other consumers are unaffected.
2105
+ ======================================== */
2106
+
2107
+ /* `progress` is inline-block by default → leaves a baseline (descender) gap
2108
+ below the bar. Block removes that gap so it sits flush with siblings. */
2109
+ .kds-progress {
2110
+ display: block;
2111
+ }
2112
+
2113
+ /* Animate the filled value when it changes (e.g. advancing a step). BeerCSS
2114
+ sets the value background but no transition, so the width jumps abruptly. */
2115
+ .kds-progress::-webkit-progress-value {
2116
+ transition: width var(--kds-transition-standard) var(--kds-easing-standard);
2117
+ }
2118
+
2119
+ .kds-progress::-moz-progress-bar {
2120
+ transition: width var(--kds-transition-standard) var(--kds-easing-standard);
2121
+ }
2122
+
2123
+ /* ========================================
2124
+ KDS SECURE LOADER
2125
+ Loader de espera: anillo circular + candado centrado + frases opcionales.
2126
+ El anillo reutiliza el spinner circular de BeerCSS, escalado.
2127
+ ======================================== */
2128
+
2129
+ .kds-secure-loader {
2130
+ display: flex;
2131
+ flex-direction: column;
2132
+ align-items: center;
2133
+ justify-content: center;
2134
+ gap: var(--kds-spacing-4);
2135
+ text-align: center;
2136
+ /* Llena y centra dentro de contenedores flex (pantalla de carga); en flujo
2137
+ normal (contenedor no-flex) se reduce a su contenido. */
2138
+ flex: 1 1 auto;
2139
+ }
2140
+
2141
+ .kds-secure-loader-text {
2142
+ display: flex;
2143
+ flex-direction: column;
2144
+ gap: var(--kds-spacing-0-25);
2145
+ }
2146
+
2147
+ .kds-secure-loader-title {
2148
+ margin: 0;
2149
+ font-family: var(--kds-font-family-primary);
2150
+ font-size: var(--kds-font-size-h6);
2151
+ font-weight: var(--kds-font-weight-semibold);
2152
+ line-height: var(--kds-line-height-snug);
2153
+ color: var(--kds-color-text-primary);
2154
+ }
2155
+
2156
+ .kds-secure-loader-message {
2157
+ margin: 0;
2158
+ font-family: var(--kds-font-family-secondary);
2159
+ font-size: var(--kds-font-size-body1);
2160
+ line-height: var(--kds-line-height-normal);
2161
+ color: var(--kds-color-primary-main);
2162
+ }
2163
+
2164
+ /* Caja del spinner con tamaño fijo: la animación no altera el layout.
2165
+ 6.25rem (100px) = tamaño del loader original (CircularProgress size=100). */
2166
+ .kds-secure-loader-spinner {
2167
+ position: relative;
2168
+ display: inline-grid;
2169
+ place-items: center;
2170
+ inline-size: var(--kds-secure-loader-size, 6.25rem);
2171
+ block-size: var(--kds-secure-loader-size, 6.25rem);
2172
+ }
2173
+
2174
+ /* Anillo: SVG nativo con arco vía stroke-dasharray, rotando. Replica el
2175
+ CircularProgress original (viewBox 44u, thickness 2, arco ~63%, disableShrink). */
2176
+ .kds-secure-loader-ring {
2177
+ inline-size: var(--kds-secure-loader-size, 6.25rem);
2178
+ block-size: var(--kds-secure-loader-size, 6.25rem);
2179
+ animation: kds-secure-loader-spin 1.2s linear infinite;
2180
+ }
2181
+
2182
+ .kds-secure-loader-ring circle {
2183
+ fill: none;
2184
+ stroke: var(--kds-color-primary-main);
2185
+ stroke-width: 2;
2186
+ stroke-linecap: round;
2187
+ /* circunferencia ≈ 2π·20.2 ≈ 127; arco visible ≈ 80 (~63%) */
2188
+ stroke-dasharray: 80 127;
2189
+ }
2190
+
2191
+ @keyframes kds-secure-loader-spin {
2192
+ to {
2193
+ transform: rotate(360deg);
2194
+ }
2195
+ }
2196
+
2197
+ /* Candado centrado sobre el anillo (~0.3 del diámetro). Centrado explícito
2198
+ (top/left 50% + translate) para que no dependa del grid ni se recorte. */
2199
+ .kds-secure-loader-lock {
2200
+ position: absolute;
2201
+ top: 50%;
2202
+ left: 50%;
2203
+ transform: translate(-50%, -50%);
2204
+ color: var(--kds-color-text-secondary);
2205
+ font-size: calc(var(--kds-secure-loader-size, 6.25rem) * 0.3);
2206
+ line-height: 1;
2207
+ pointer-events: none;
2208
+ }
2209
+
2210
+ /* ========================================
2211
+ KDS COPY BUTTON
2212
+ Chip compacto que muestra un valor + icono copy y lo copia al click.
2213
+ Acción inline (distinto de KdsCopyRow). Look del copy button de khenshin.
2214
+ ======================================== */
2215
+
2216
+ .kds-copy-button {
2217
+ display: inline-flex;
2218
+ align-items: center;
2219
+ gap: var(--kds-spacing-1);
2220
+ padding: var(--kds-spacing-0-25) var(--kds-spacing-1-5);
2221
+ border: none;
2222
+ border-radius: var(--kds-radius-button);
2223
+ background: var(--kds-alert-info-bg);
2224
+ color: var(--kds-color-info-dark);
2225
+ font-family: var(--kds-font-family-secondary);
2226
+ font-size: var(--kds-font-size-sm);
2227
+ font-weight: var(--kds-font-weight-medium);
2228
+ line-height: var(--kds-line-height-normal);
2229
+ cursor: pointer;
2230
+ transition: background-color var(--kds-transition-shorter) var(--kds-easing-standard),
2231
+ color var(--kds-transition-shorter) var(--kds-easing-standard);
2232
+ }
2233
+
2234
+ /* value y copiedText se apilan en la MISMA celda de grid: la celda toma el
2235
+ ancho del texto más largo, por lo que el botón conserva su ancho al alternar
2236
+ entre "valor" y "copiado" (sin reflow). */
2237
+ .kds-copy-button-label {
2238
+ display: inline-grid;
2239
+ }
2240
+
2241
+ .kds-copy-button-value,
2242
+ .kds-copy-button-copied {
2243
+ grid-area: 1 / 1;
2244
+ white-space: nowrap;
2245
+ }
2246
+
2247
+ /* Estado por defecto: visible el valor, oculto (pero ocupando espacio) el copiado */
2248
+ .kds-copy-button-copied {
2249
+ visibility: hidden;
2250
+ }
2251
+
2252
+ /* Al copiar se invierte la visibilidad; el ancho no cambia */
2253
+ .kds-copy-button.copied .kds-copy-button-value {
2254
+ visibility: hidden;
2255
+ }
2256
+
2257
+ .kds-copy-button.copied .kds-copy-button-copied {
2258
+ visibility: visible;
2259
+ }
2260
+
2261
+ .kds-copy-button .material-symbols-outlined {
2262
+ font-size: 1rem;
2263
+ color: var(--kds-color-info-main);
2264
+ flex-shrink: 0;
2265
+ }
2266
+
2267
+ .kds-copy-button.copied {
2268
+ background: var(--kds-alert-success-bg);
2269
+ color: var(--kds-alert-success-text);
2270
+ animation: kds-copy-button-pulse var(--kds-transition-short) var(--kds-easing-standard);
2271
+ }
2272
+
2273
+ .kds-copy-button.copied .material-symbols-outlined {
2274
+ color: var(--kds-color-success-main);
2275
+ /* el check entra con un pop al copiar */
2276
+ animation: kds-copy-button-pop var(--kds-transition-short) var(--kds-easing-standard);
2277
+ }
2278
+
2279
+ @keyframes kds-copy-button-pulse {
2280
+ 0% {
2281
+ transform: scale(1);
2282
+ }
2283
+ 50% {
2284
+ transform: scale(1.04);
2285
+ }
2286
+ 100% {
2287
+ transform: scale(1);
2288
+ }
2289
+ }
2290
+
2291
+ @keyframes kds-copy-button-pop {
2292
+ 0% {
2293
+ transform: scale(0.3);
2294
+ opacity: 0;
2295
+ }
2296
+ 60% {
2297
+ transform: scale(1.25);
2298
+ opacity: 1;
2299
+ }
2300
+ 100% {
2301
+ transform: scale(1);
2302
+ }
2303
+ }
2304
+
1976
2305
  /* ========================================
1977
2306
  Link Styles
1978
2307
  ======================================== */
@@ -2105,6 +2434,17 @@ body.dark {
2105
2434
  transition: border-color 0.2s, box-shadow 0.2s, outline-color 0.2s;
2106
2435
  }
2107
2436
 
2437
+ /* === TEXTAREA FIX === */
2438
+ /* BeerCSS base sets minimal block padding; add breathing room for textarea */
2439
+ .field > textarea {
2440
+ padding-block: 0.75rem;
2441
+ resize: vertical;
2442
+ }
2443
+
2444
+ .field.label > textarea {
2445
+ padding-block-start: 1.5rem;
2446
+ }
2447
+
2108
2448
  /* ==========================================
2109
2449
  NOTCH VISIBILITY (opacity)
2110
2450
  ========================================== */
@@ -2192,12 +2532,16 @@ body.dark {
2192
2532
  Asegurar que el dropdown arrow sea visible
2193
2533
  ========================================== */
2194
2534
 
2195
- /* Select: mantener appearance nativa para mostrar el dropdown arrow */
2535
+ /* Select: reset nativo + arrow custom via SVG (iOS Safari ignora estilos con appearance:auto) */
2196
2536
  .field select {
2197
- /* BeerCSS puede estar ocultando el arrow, aseguramos que sea visible */
2198
- appearance: auto;
2199
- -webkit-appearance: auto;
2200
- -moz-appearance: auto;
2537
+ -webkit-appearance: none;
2538
+ -moz-appearance: none;
2539
+ appearance: none;
2540
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23333' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
2541
+ background-repeat: no-repeat;
2542
+ background-position: right var(--kds-spacing-1) center;
2543
+ background-size: 20px;
2544
+ padding-right: var(--kds-spacing-4) !important;
2201
2545
  }
2202
2546
 
2203
2547
  /* ==========================================
@@ -2222,6 +2566,23 @@ body.dark {
2222
2566
  color: var(--error); /* Rojo error */
2223
2567
  }
2224
2568
 
2569
+ /* ==========================================
2570
+ PASSWORD REVEAL TOGGLE (KdsTextField `revealable`)
2571
+ El <a role="button"> reusa el posicionamiento de icono de BeerCSS
2572
+ (.field > a, pointer-events: all). Aquí solo: color del icono
2573
+ (on-surface-variant) y un focus ring accesible para el toggle
2574
+ navegable por teclado (BeerCSS hace `outline: inherit` en <a>).
2575
+ ========================================== */
2576
+ .field > a.kds-field-reveal {
2577
+ color: var(--on-surface-variant);
2578
+ }
2579
+
2580
+ .field > a.kds-field-reveal:focus-visible {
2581
+ outline: 2px solid var(--primary);
2582
+ outline-offset: 2px;
2583
+ border-radius: 50%;
2584
+ }
2585
+
2225
2586
  /* ==========================================
2226
2587
  LABEL COLOR
2227
2588
  Mantener sincronizado con border
@@ -2330,25 +2691,90 @@ body.dark {
2330
2691
  }
2331
2692
 
2332
2693
  /* ========================================
2333
- Material Symbols Icon Sizing
2694
+ Radix Tooltip (.kds-tooltip)
2695
+ Espejo de `.tooltip` pero para popovers de Radix:
2696
+ bg oscuro, texto blanco, sombra + animación fade/slide direccional.
2334
2697
  ======================================== */
2335
2698
 
2336
- .material-symbols-outlined {
2337
- font-variation-settings:
2338
- 'FILL' 0,
2339
- 'wght' 400,
2340
- 'GRAD' 0,
2341
- 'opsz' 24;
2342
- min-width: 30px;
2343
- min-height: 30px;
2344
- display: inline-flex;
2345
- align-items: center;
2346
- justify-content: center;
2699
+ .kds-tooltip {
2700
+ background-color: var(--kds-color-text-primary);
2701
+ color: var(--kds-color-background-paper);
2702
+ font-family: var(--kds-font-family-primary);
2703
+ font-size: var(--kds-font-size-xs);
2704
+ font-weight: var(--kds-font-weight-medium);
2705
+ line-height: var(--kds-line-height-normal);
2706
+ border-radius: var(--kds-radius-sm);
2707
+ padding: var(--kds-spacing-0-75) var(--kds-spacing-1-5);
2708
+ box-shadow: var(--kds-shadow-4);
2709
+ max-width: 280px;
2710
+ z-index: var(--kds-z-index-tooltip, 1500);
2711
+ user-select: none;
2712
+ /* Animación direccional según Radix data-side — coordinada con copy-row
2713
+ (cubic-bezier 0.2, 0.8, 0.2, 1) para un feel consistente del DS. */
2714
+ animation-duration: 240ms;
2715
+ animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
2716
+ will-change: transform, opacity;
2347
2717
  }
2348
2718
 
2349
- /* Filled icons for specific contexts */
2350
- .icon-filled {
2351
- font-variation-settings:
2719
+ .kds-tooltip[data-state='closed'] {
2720
+ animation-duration: 140ms;
2721
+ animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
2722
+ }
2723
+
2724
+ /* Direccional según data-side (Radix añade el attr en runtime).
2725
+ Cada lado entra desde su dirección con ~8px de offset (más visible que 4px). */
2726
+ .kds-tooltip[data-side='top'][data-state='delayed-open'],
2727
+ .kds-tooltip[data-side='top'][data-state='instant-open'] { animation-name: kds-tooltip-in-top; }
2728
+ .kds-tooltip[data-side='bottom'][data-state='delayed-open'],
2729
+ .kds-tooltip[data-side='bottom'][data-state='instant-open'] { animation-name: kds-tooltip-in-bottom; }
2730
+ .kds-tooltip[data-side='left'][data-state='delayed-open'],
2731
+ .kds-tooltip[data-side='left'][data-state='instant-open'] { animation-name: kds-tooltip-in-left; }
2732
+ .kds-tooltip[data-side='right'][data-state='delayed-open'],
2733
+ .kds-tooltip[data-side='right'][data-state='instant-open'] { animation-name: kds-tooltip-in-right; }
2734
+
2735
+ /* Fallback cuando no hay data-side resuelto aún */
2736
+ .kds-tooltip[data-state='delayed-open']:not([data-side]),
2737
+ .kds-tooltip[data-state='instant-open']:not([data-side]) {
2738
+ animation-name: kds-tooltip-in-top;
2739
+ }
2740
+
2741
+ .kds-tooltip[data-state='closed'] { animation-name: kds-tooltip-out; }
2742
+
2743
+ @keyframes kds-tooltip-in-top { from { opacity: 0; transform: translateY(8px) scale(0.96); } to { opacity: 1; transform: none; } }
2744
+ @keyframes kds-tooltip-in-bottom { from { opacity: 0; transform: translateY(-8px) scale(0.96); } to { opacity: 1; transform: none; } }
2745
+ @keyframes kds-tooltip-in-left { from { opacity: 0; transform: translateX(8px) scale(0.96); } to { opacity: 1; transform: none; } }
2746
+ @keyframes kds-tooltip-in-right { from { opacity: 0; transform: translateX(-8px) scale(0.96); } to { opacity: 1; transform: none; } }
2747
+
2748
+ @keyframes kds-tooltip-out {
2749
+ from { opacity: 1; transform: none; }
2750
+ to { opacity: 0; transform: scale(0.96); }
2751
+ }
2752
+
2753
+ /* Arrow (SVG path generado por Radix) */
2754
+ .kds-tooltip-arrow {
2755
+ fill: var(--kds-color-text-primary);
2756
+ }
2757
+
2758
+ /* ========================================
2759
+ Material Symbols Icon Sizing
2760
+ ======================================== */
2761
+
2762
+ .material-symbols-outlined {
2763
+ font-variation-settings:
2764
+ 'FILL' 0,
2765
+ 'wght' 400,
2766
+ 'GRAD' 0,
2767
+ 'opsz' 24;
2768
+ min-width: 30px;
2769
+ min-height: 30px;
2770
+ display: inline-flex;
2771
+ align-items: center;
2772
+ justify-content: center;
2773
+ }
2774
+
2775
+ /* Filled icons for specific contexts */
2776
+ .icon-filled {
2777
+ font-variation-settings:
2352
2778
  'FILL' 1,
2353
2779
  'wght' 400,
2354
2780
  'GRAD' 0,
@@ -2363,6 +2789,16 @@ body.dark {
2363
2789
  width: 100%;
2364
2790
  }
2365
2791
 
2792
+ /* Truncado en una línea con ellipsis. Incluye min-width:0 para que funcione
2793
+ dentro de contenedores flex/grid (el ítem puede encogerse por debajo de su
2794
+ contenido). Útil para nombres/asuntos largos en headers y filas. */
2795
+ .kds-truncate {
2796
+ min-width: 0;
2797
+ overflow: hidden;
2798
+ text-overflow: ellipsis;
2799
+ white-space: nowrap;
2800
+ }
2801
+
2366
2802
  .kds-max-w-sm {
2367
2803
  max-width: 400px;
2368
2804
  }
@@ -2406,6 +2842,11 @@ body.dark {
2406
2842
  display: flex;
2407
2843
  flex-direction: column;
2408
2844
  gap: var(--kds-spacing-3);
2845
+ /* Reset del fieldset nativo: sin borde/padding/margin por defecto del navegador. */
2846
+ margin: 0;
2847
+ padding: 0;
2848
+ border: 0;
2849
+ min-inline-size: 0;
2409
2850
  }
2410
2851
 
2411
2852
  /* Checkbox Label - BeerCSS override */
@@ -2455,6 +2896,42 @@ label.radio:has(input:disabled) {
2455
2896
  opacity: 0.6;
2456
2897
  }
2457
2898
 
2899
+ /* ========================================
2900
+ RADIO GROUP — variante card (.kds-radio-group--card)
2901
+ Cada opción como fila con borde (estilo selección de banco/cuenta),
2902
+ manteniendo el control radio. Hover + opción seleccionada resaltada.
2903
+ ======================================== */
2904
+ .kds-radio-group--card {
2905
+ gap: var(--kds-spacing-2);
2906
+ }
2907
+
2908
+ .kds-radio-group--card label.radio {
2909
+ gap: var(--kds-spacing-1-5);
2910
+ /* Vertical con un poco más de aire; horizontal reducido para pegar el radio a la izquierda. */
2911
+ padding: var(--kds-spacing-2) var(--kds-spacing-1-5);
2912
+ /* Bordes con los valores del bank selector. */
2913
+ border: 1px solid var(--kds-color-border-subtle);
2914
+ border-radius: var(--kds-radius-card);
2915
+ background: var(--kds-color-surface);
2916
+ transition: border-color 0.2s, background 0.2s;
2917
+ }
2918
+
2919
+ /* Leve separación extra entre el radio y el texto de la opción. */
2920
+ .kds-radio-group--card label.radio span {
2921
+ margin-left: var(--kds-spacing-0-5);
2922
+ }
2923
+
2924
+ .kds-radio-group--card label.radio:hover {
2925
+ border-color: var(--kds-color-border-default);
2926
+ }
2927
+
2928
+ /* Seleccionada: poco color primario — solo un fondo faint sutil + borde gris
2929
+ (el punto del radio ya comunica la selección). */
2930
+ .kds-radio-group--card label.radio:has(input:checked) {
2931
+ border-color: var(--kds-color-border-default);
2932
+ background: var(--kds-color-primary-faint);
2933
+ }
2934
+
2458
2935
  /* ========================================
2459
2936
  ONBOARDING COMPONENTS
2460
2937
  Multi-stage onboarding flow with form validation
@@ -2745,7 +3222,8 @@ dialog.modal .field.border:focus-within {
2745
3222
  padding: var(--kds-spacing-2);
2746
3223
  }
2747
3224
 
2748
- .snackbar {
3225
+ .snackbar,
3226
+ .snackbar.active {
2749
3227
  min-width: calc(100% - 32px);
2750
3228
  left: 16px;
2751
3229
  right: 16px;
@@ -3044,6 +3522,32 @@ footer > .kds-container-center {
3044
3522
  color: var(--kds-color-error-dark);
3045
3523
  }
3046
3524
 
3525
+ /* Close button — icon-only, discreto, no usa kds-btn para no romper el flex layout del alert */
3526
+ .kds-alert-close {
3527
+ flex-shrink: 0;
3528
+ display: inline-flex;
3529
+ align-items: center;
3530
+ justify-content: center;
3531
+ width: 28px;
3532
+ height: 28px;
3533
+ padding: 0;
3534
+ background: transparent;
3535
+ border: 0;
3536
+ border-radius: 50%;
3537
+ color: inherit;
3538
+ cursor: pointer;
3539
+ transition: background-color 0.15s ease;
3540
+ }
3541
+
3542
+ .kds-alert-close:hover {
3543
+ background: rgba(0, 0, 0, 0.06);
3544
+ }
3545
+
3546
+ .kds-alert-close i {
3547
+ font-size: 18px;
3548
+ line-height: 1;
3549
+ }
3550
+
3047
3551
  /* Lists inside alerts */
3048
3552
  .kds-alert ul {
3049
3553
  padding-left: var(--kds-spacing-2);
@@ -4040,6 +4544,14 @@ dialog#surveyModal button.circle {
4040
4544
  text-align: center;
4041
4545
  }
4042
4546
 
4547
+ .kds-text-left {
4548
+ text-align: left;
4549
+ }
4550
+
4551
+ .kds-text-right {
4552
+ text-align: right;
4553
+ }
4554
+
4043
4555
  .kds-text-underline {
4044
4556
  text-decoration: underline;
4045
4557
  }
@@ -4056,6 +4568,54 @@ dialog#surveyModal button.circle {
4056
4568
  font-size: var(--kds-font-size-sm);
4057
4569
  }
4058
4570
 
4571
+ /* ── Font-size scale utilities (additive — opt-in companions to .kds-text-sm) ── */
4572
+ .kds-text-base {
4573
+ font-size: var(--kds-font-size-base);
4574
+ }
4575
+
4576
+ .kds-text-lg {
4577
+ font-size: var(--kds-font-size-lg);
4578
+ }
4579
+
4580
+ .kds-text-xl {
4581
+ font-size: var(--kds-font-size-xl);
4582
+ }
4583
+
4584
+ .kds-text-2xl {
4585
+ font-size: var(--kds-font-size-2xl);
4586
+ }
4587
+
4588
+ /* ── Font-weight utilities ── */
4589
+ .kds-fw-regular {
4590
+ font-weight: var(--kds-font-weight-regular);
4591
+ }
4592
+
4593
+ .kds-fw-medium {
4594
+ font-weight: var(--kds-font-weight-medium);
4595
+ }
4596
+
4597
+ .kds-fw-semibold {
4598
+ font-weight: var(--kds-font-weight-semibold);
4599
+ }
4600
+
4601
+ .kds-fw-bold {
4602
+ font-weight: var(--kds-font-weight-bold);
4603
+ }
4604
+
4605
+ /* ── Text-transform utilities ── */
4606
+ .kds-text-transform-none {
4607
+ text-transform: none;
4608
+ }
4609
+
4610
+ /* ── Soft background utilities (semantic muted backgrounds for callouts) ── */
4611
+ .kds-bg-warning-soft {
4612
+ background-color: var(--kds-color-warning-soft);
4613
+ }
4614
+
4615
+ .kds-bg-info-soft {
4616
+ background-color: var(--kds-color-info-soft);
4617
+ }
4618
+
4059
4619
  /* ── Typography variants ── */
4060
4620
  .kds-text-display1 {
4061
4621
  font-family: var(--kds-font-family-primary, 'Public Sans', sans-serif);
@@ -4146,6 +4706,12 @@ dialog#surveyModal button.circle {
4146
4706
  color: var(--kds-color-primary-dark, #5B3179);
4147
4707
  }
4148
4708
 
4709
+ /* Inline emphasis: bold weight only, inherits size/color/family from context so it
4710
+ works as a highlighted fragment inside any other variant (body, heading, etc.). */
4711
+ .kds-text-strong {
4712
+ font-weight: var(--kds-font-weight-bold, 700);
4713
+ }
4714
+
4149
4715
  /* Display utilities */
4150
4716
  .kds-hidden {
4151
4717
  display: none;
@@ -4266,7 +4832,9 @@ dialog#surveyModal button.circle {
4266
4832
  ======================================== */
4267
4833
 
4268
4834
  .kds-badge {
4269
- display: inline-block;
4835
+ display: inline-flex;
4836
+ align-items: center;
4837
+ gap: 4px;
4270
4838
  padding: 2px 8px;
4271
4839
  border-radius: var(--kds-radius-sm);
4272
4840
  font-size: var(--kds-font-size-xs);
@@ -4274,6 +4842,40 @@ dialog#surveyModal button.circle {
4274
4842
  line-height: 1.5;
4275
4843
  }
4276
4844
 
4845
+ /* Icon prefix inside chip — small inline icon */
4846
+ .kds-badge > i.material-symbols-outlined {
4847
+ font-size: 14px;
4848
+ line-height: 1;
4849
+ }
4850
+
4851
+ /* Deletable chip close button — discreto, sin kds-btn (eso lo agrandaba ridículo) */
4852
+ .kds-badge-close {
4853
+ display: inline-flex;
4854
+ align-items: center;
4855
+ justify-content: center;
4856
+ width: 16px;
4857
+ height: 16px;
4858
+ margin-right: -2px;
4859
+ padding: 0;
4860
+ background: transparent;
4861
+ border: 0;
4862
+ border-radius: 50%;
4863
+ color: inherit;
4864
+ cursor: pointer;
4865
+ opacity: 0.7;
4866
+ transition: opacity 0.15s, background-color 0.15s;
4867
+ }
4868
+
4869
+ .kds-badge-close:hover {
4870
+ opacity: 1;
4871
+ background: rgba(0, 0, 0, 0.1);
4872
+ }
4873
+
4874
+ .kds-badge-close i {
4875
+ font-size: 14px;
4876
+ line-height: 1;
4877
+ }
4878
+
4277
4879
  .kds-badge.success {
4278
4880
  background-color: var(--kds-color-success-container);
4279
4881
  color: var(--kds-color-success-dark);
@@ -4552,6 +5154,11 @@ dialog#surveyModal button.circle {
4552
5154
  color: var(--kds-color-text-primary);
4553
5155
  }
4554
5156
 
5157
+ /* Opt-in color modifier — switches the value to the LigoPay/khipu-blue tone */
5158
+ .kds-amount-value--info {
5159
+ color: var(--kds-color-info-blue); /* #5A5FE0 */
5160
+ }
5161
+
4555
5162
  .kds-amount-value small {
4556
5163
  font-size: 18px;
4557
5164
  font-weight: 500;
@@ -4909,7 +5516,7 @@ dialog#surveyModal button.circle {
4909
5516
  display: flex;
4910
5517
  align-items: center;
4911
5518
  justify-content: center;
4912
- gap: var(--kds-spacing-1);
5519
+ gap: var(--kds-spacing-0-5);
4913
5520
  color: var(--kds-color-gray-400);
4914
5521
  font-size: var(--kds-font-size-xs);
4915
5522
  letter-spacing: var(--kds-letter-spacing-wide);
@@ -4921,6 +5528,10 @@ dialog#surveyModal button.circle {
4921
5528
  display: none;
4922
5529
  }
4923
5530
 
5531
+ .kds-screen > form {
5532
+ margin-block-start: 0 !important;
5533
+ }
5534
+
4924
5535
  @media (max-width: 767px) {
4925
5536
  .kds-card-elevated > .kds-secure-footer {
4926
5537
  display: flex;
@@ -4970,14 +5581,20 @@ dialog#surveyModal button.circle {
4970
5581
  cursor: pointer;
4971
5582
  display: inline-flex;
4972
5583
  align-items: center;
4973
- gap: var(--kds-spacing-0-75);
5584
+ gap: 0;
4974
5585
  }
4975
5586
 
4976
- .kds-expand-toggle:hover {
5587
+ .kds-expand-toggle:hover,
5588
+ .kds-expand-toggle:focus,
5589
+ .kds-expand-toggle:active {
4977
5590
  background: transparent;
5591
+ outline: none;
5592
+ box-shadow: none;
4978
5593
  }
4979
5594
 
4980
- .kds-expand-toggle:hover span {
5595
+ .kds-expand-toggle:hover span,
5596
+ .kds-expand-toggle:focus span,
5597
+ .kds-expand-toggle:active span {
4981
5598
  text-decoration: underline;
4982
5599
  }
4983
5600
 
@@ -5157,11 +5774,11 @@ dialog#surveyModal button.circle {
5157
5774
  color: var(--kds-color-success-main);
5158
5775
  }
5159
5776
 
5160
- /* Variant: pending (animated spinner) */
5777
+ /* Variant: pending (animated blue spinner, sin icono interno) */
5161
5778
  .kds-status-block[data-status="pending"] .kds-status-block-icon {
5162
5779
  background: transparent;
5163
5780
  border: 3px solid var(--kds-color-divider);
5164
- border-top-color: var(--kds-color-primary-main);
5781
+ border-top-color: var(--kds-color-info-main);
5165
5782
  animation: kds-spin 1s linear infinite;
5166
5783
  }
5167
5784
 
@@ -5179,12 +5796,21 @@ dialog#surveyModal button.circle {
5179
5796
  color: var(--kds-color-error-main);
5180
5797
  }
5181
5798
 
5799
+ /* Variant: info — usar SIEMPRE con icon "info_i" (i minúscula sin glyph circular)
5800
+ para que solo se vea nuestro círculo decorativo. Iconos como "info" tienen
5801
+ su propio círculo built-in → causarían doble círculo. */
5802
+ .kds-status-block[data-status="info"] .kds-status-block-icon {
5803
+ background: var(--kds-color-info-soft);
5804
+ border: var(--kds-border-width-md) solid var(--kds-color-info-main);
5805
+ color: var(--kds-color-info-main);
5806
+ }
5807
+
5182
5808
  /* Inline variant: icon left + text right */
5183
5809
  .kds-status-block.inline {
5184
5810
  text-align: left;
5185
5811
  display: flex;
5186
5812
  align-items: center;
5187
- gap: var(--kds-spacing-3);
5813
+ gap: var(--kds-spacing-2);
5188
5814
  padding: var(--kds-spacing-1) 0;
5189
5815
  }
5190
5816
 
@@ -5246,6 +5872,40 @@ dialog#surveyModal button.circle {
5246
5872
  background: var(--kds-color-divider);
5247
5873
  }
5248
5874
 
5875
+ /* Close button — top-right discreto, NO usa kds-btn (rompía el flex layout) */
5876
+ .kds-bottom-sheet-close {
5877
+ position: absolute;
5878
+ top: var(--kds-spacing-1);
5879
+ right: var(--kds-spacing-1);
5880
+ width: 32px;
5881
+ height: 32px;
5882
+ display: inline-flex;
5883
+ align-items: center;
5884
+ justify-content: center;
5885
+ padding: 0;
5886
+ background: transparent;
5887
+ border: 0;
5888
+ border-radius: 50%;
5889
+ color: var(--kds-color-text-secondary);
5890
+ cursor: pointer;
5891
+ transition: background-color 0.15s ease;
5892
+ }
5893
+
5894
+ .kds-bottom-sheet-close:hover {
5895
+ background: rgba(0, 0, 0, 0.06);
5896
+ }
5897
+
5898
+ .kds-bottom-sheet-close i {
5899
+ font-size: 20px;
5900
+ line-height: 1;
5901
+ }
5902
+
5903
+ /* Body container — separa el content del title/actions */
5904
+ .kds-bottom-sheet-body {
5905
+ text-align: left;
5906
+ margin-top: var(--kds-spacing-1);
5907
+ }
5908
+
5249
5909
  .kds-bottom-sheet-icon {
5250
5910
  font-size: var(--kds-font-size-4xl);
5251
5911
  }
@@ -5575,6 +6235,13 @@ div.kds-invoice-header,
5575
6235
  align-content: initial;
5576
6236
  }
5577
6237
 
6238
+ /* Mobile collapsed state: center-align so merchant tile aligns with the smaller amount */
6239
+ @media (max-width: 767px) {
6240
+ .kds-invoice-sticky.is-collapsed .kds-invoice-header {
6241
+ align-items: center;
6242
+ }
6243
+ }
6244
+
5578
6245
  /* Reset BeerCSS sibling margin on <p> inside invoice header — specificity (0,4,1) ties BeerCSS, wins by source order */
5579
6246
  .kds-card-elevated.kds-invoice-sticky .kds-invoice-header p.kds-invoice-amount,
5580
6247
  .kds-card-elevated.kds-invoice-sticky .kds-invoice-header p.kds-invoice-code {
@@ -5582,7 +6249,7 @@ div.kds-invoice-header,
5582
6249
  }
5583
6250
 
5584
6251
  .kds-invoice-amount {
5585
- font-weight: var(--kds-font-weight-bold);
6252
+ font-weight: var(--kds-font-weight-semibold);
5586
6253
  font-size: var(--kds-font-size-3xl);
5587
6254
  line-height: var(--kds-line-height-tight);
5588
6255
  letter-spacing: var(--kds-letter-spacing-wide);
@@ -5603,10 +6270,16 @@ div.kds-invoice-header,
5603
6270
  color: var(--kds-color-gray-400);
5604
6271
  text-transform: uppercase;
5605
6272
  margin: 0;
5606
- margin-top: var(--kds-spacing-1);
6273
+ margin-block: unset;
6274
+ display: flex;
6275
+ gap: var(--kds-spacing-1-5);
5607
6276
  }
5608
6277
 
5609
6278
  .kds-invoice-code-value {
6279
+ color: var(--kds-color-gray-400);
6280
+ }
6281
+
6282
+ .kds-invoice-code-value--lowercase {
5610
6283
  text-transform: lowercase;
5611
6284
  }
5612
6285
 
@@ -5619,6 +6292,9 @@ div.kds-invoice-header,
5619
6292
  place-items: center;
5620
6293
  color: #fff;
5621
6294
  flex-shrink: 0;
6295
+ /* Clip the slightly-oversized logo (see `.kds-invoice-merchant img`) to the
6296
+ rounded square so it can fully cover the deep-purple background. */
6297
+ overflow: hidden;
5622
6298
  }
5623
6299
 
5624
6300
  .kds-invoice-merchant i {
@@ -5638,15 +6314,18 @@ div.kds-invoice-header,
5638
6314
  }
5639
6315
 
5640
6316
  .kds-invoice-merchant img {
5641
- width: 100%;
5642
- height: 100%;
6317
+ /* Slightly larger than the container (+2px, centered by the grid) so the
6318
+ logo overflows under the parent's rounded clip and the deep-purple
6319
+ background never peeks through at the corners when the logo shrinks. */
6320
+ width: calc(100% + 2px);
6321
+ height: calc(100% + 2px);
5643
6322
  object-fit: cover;
5644
6323
  border-radius: var(--kds-radius-md);
5645
6324
  }
5646
6325
 
5647
6326
  /* -- Card Title -- */
5648
6327
  .kds-card-title {
5649
- font-weight: 700;
6328
+ font-weight: var(--kds-font-weight-semibold);
5650
6329
  font-size: var(--kds-font-size-base);
5651
6330
  line-height: 1.5;
5652
6331
  letter-spacing: -0.31px;
@@ -5654,12 +6333,22 @@ div.kds-invoice-header,
5654
6333
  margin-bottom: var(--kds-spacing-2) !important;
5655
6334
  }
5656
6335
 
6336
+ /* Opt-in size modifiers (additive — do NOT change default 16/600) */
6337
+ .kds-card-title--lg {
6338
+ font-size: var(--kds-font-size-xl); /* 20px */
6339
+ font-weight: var(--kds-font-weight-semibold);
6340
+ }
6341
+
6342
+ .kds-card-title--xl {
6343
+ font-size: var(--kds-font-size-2xl); /* 24px */
6344
+ font-weight: var(--kds-font-weight-semibold);
6345
+ }
6346
+
5657
6347
  /* -- Key-Value Grid -- */
5658
6348
  .kds-kv {
5659
6349
  display: grid;
5660
6350
  grid-template-columns: auto 1fr;
5661
- row-gap: var(--kds-spacing-1);
5662
- column-gap: var(--kds-spacing-1-5);
6351
+ column-gap: var(--kds-spacing-1);
5663
6352
  align-items: baseline;
5664
6353
  }
5665
6354
 
@@ -5676,7 +6365,7 @@ div.kds-invoice-header,
5676
6365
  margin: 0;
5677
6366
  font-size: var(--kds-font-size-sm);
5678
6367
  line-height: var(--kds-line-height-relaxed);
5679
- font-weight: var(--kds-font-weight-bold);
6368
+ font-weight: var(--kds-font-weight-semibold);
5680
6369
  letter-spacing: normal;
5681
6370
  color: var(--kds-color-gray-800);
5682
6371
  min-width: 0;
@@ -5706,7 +6395,13 @@ div.kds-invoice-header,
5706
6395
  flex-direction: column;
5707
6396
  gap: var(--kds-spacing-1-5);
5708
6397
  margin: 0;
5709
- padding: 0 0 var(--kds-spacing-1);
6398
+ padding: 0;
6399
+ }
6400
+
6401
+ @media (max-width: 767px) {
6402
+ .kds-detail-list {
6403
+ padding-bottom: var(--kds-spacing-2);
6404
+ }
5710
6405
  }
5711
6406
 
5712
6407
  .kds-detail-group {
@@ -5722,7 +6417,6 @@ div.kds-invoice-header,
5722
6417
  letter-spacing: var(--kds-letter-spacing-wide);
5723
6418
  color: var(--kds-color-text-hint);
5724
6419
  text-transform: uppercase;
5725
- margin: 0 0 var(--kds-spacing-0-5);
5726
6420
  }
5727
6421
 
5728
6422
  .kds-detail-group dd {
@@ -5791,16 +6485,16 @@ div.kds-invoice-header,
5791
6485
  font-size: var(--kds-font-size-sm);
5792
6486
  }
5793
6487
 
5794
- .kds-recap-list .k {
6488
+ .kds-recap-list .kds-key {
5795
6489
  color: var(--kds-color-text-secondary);
5796
6490
  }
5797
6491
 
5798
- .kds-recap-list .v {
6492
+ .kds-recap-list .kds-value {
5799
6493
  color: var(--kds-color-text-primary);
5800
6494
  font-weight: 500;
5801
6495
  }
5802
6496
 
5803
- .kds-recap-list .v.placeholder {
6497
+ .kds-recap-list .kds-value.placeholder {
5804
6498
  color: var(--kds-color-text-hint);
5805
6499
  }
5806
6500
 
@@ -5827,6 +6521,72 @@ a.kds-btn-success:disabled {
5827
6521
  box-shadow: none;
5828
6522
  }
5829
6523
 
6524
+ /* -- Button Warning (amber CTA) -- */
6525
+ button.kds-btn-warning,
6526
+ a.kds-btn-warning {
6527
+ background: var(--kds-color-warning-main);
6528
+ color: var(--kds-color-warning-contrast);
6529
+ border: none;
6530
+ }
6531
+
6532
+ button.kds-btn-warning:hover:not(:disabled),
6533
+ a.kds-btn-warning:hover:not(:disabled) {
6534
+ background: var(--kds-color-warning-dark);
6535
+ }
6536
+
6537
+ button.kds-btn-warning:active:not(:disabled),
6538
+ button.kds-btn-warning:focus-visible:not(:disabled),
6539
+ a.kds-btn-warning:active:not(:disabled),
6540
+ a.kds-btn-warning:focus-visible:not(:disabled) {
6541
+ background: var(--kds-color-warning-dark);
6542
+ outline: 2px solid var(--kds-color-warning-main);
6543
+ outline-offset: 2px;
6544
+ }
6545
+
6546
+ button.kds-btn-warning:disabled,
6547
+ a.kds-btn-warning:disabled {
6548
+ background-color: var(--kds-color-action-disabled-bg);
6549
+ color: var(--kds-color-action-disabled);
6550
+ box-shadow: none;
6551
+ }
6552
+
6553
+ button.kds-btn-warning::after {
6554
+ display: none;
6555
+ }
6556
+
6557
+ /* -- Button Error (red / destructive CTA) -- */
6558
+ button.kds-btn-error,
6559
+ a.kds-btn-error {
6560
+ background: var(--kds-color-error-main);
6561
+ color: var(--kds-color-error-contrast);
6562
+ border: none;
6563
+ }
6564
+
6565
+ button.kds-btn-error:hover:not(:disabled),
6566
+ a.kds-btn-error:hover:not(:disabled) {
6567
+ background: var(--kds-color-error-dark);
6568
+ }
6569
+
6570
+ button.kds-btn-error:active:not(:disabled),
6571
+ button.kds-btn-error:focus-visible:not(:disabled),
6572
+ a.kds-btn-error:active:not(:disabled),
6573
+ a.kds-btn-error:focus-visible:not(:disabled) {
6574
+ background: var(--kds-color-error-dark);
6575
+ outline: 2px solid var(--kds-color-error-main);
6576
+ outline-offset: 2px;
6577
+ }
6578
+
6579
+ button.kds-btn-error:disabled,
6580
+ a.kds-btn-error:disabled {
6581
+ background-color: var(--kds-color-action-disabled-bg);
6582
+ color: var(--kds-color-action-disabled);
6583
+ box-shadow: none;
6584
+ }
6585
+
6586
+ button.kds-btn-error::after {
6587
+ display: none;
6588
+ }
6589
+
5830
6590
  /* -- Field Helper Text -- */
5831
6591
  .kds-field-helper {
5832
6592
  font-size: var(--kds-font-size-xs);
@@ -5869,6 +6629,8 @@ button.kds-btn-success::after {
5869
6629
  /* -- Alert inline (borderless, used inside cards) -- */
5870
6630
  .kds-alert-inline {
5871
6631
  border: none;
6632
+ padding: var(--kds-spacing-1) var(--kds-spacing-1-5);
6633
+ margin-bottom: var(--kds-spacing-1-5);
5872
6634
  }
5873
6635
 
5874
6636
  /* -- Card dimmed (behind overlays) -- */
@@ -5970,17 +6732,42 @@ button.kds-btn-success::after {
5970
6732
  }
5971
6733
 
5972
6734
  .kds-bill-description-picture {
5973
- width: 120px;
5974
- height: 120px;
6735
+ max-width: 100px;
5975
6736
  object-fit: contain;
5976
6737
  background: var(--kds-color-background-paper);
5977
- padding: var(--kds-spacing-1-25);
5978
- border-radius: var(--kds-radius-md);
5979
- margin-top: var(--kds-spacing-1);
6738
+ margin-top: var(--kds-spacing-1-25);
5980
6739
  display: block;
5981
6740
  box-sizing: content-box;
5982
6741
  }
5983
6742
 
6743
+ /* -- Bill Attachments -- */
6744
+ .kds-bill-attachments {
6745
+ display: flex;
6746
+ flex-direction: column;
6747
+ gap: var(--kds-spacing-0-75);
6748
+ }
6749
+
6750
+ .kds-bill-attachment {
6751
+ display: inline-flex;
6752
+ align-items: center;
6753
+ justify-content: flex-start;
6754
+ width: fit-content;
6755
+ color: var(--kds-color-info-main);
6756
+ font-size: var(--kds-font-size-sm);
6757
+ font-weight: var(--kds-font-weight-medium);
6758
+ text-decoration: none;
6759
+ }
6760
+
6761
+ .kds-bill-attachment:hover span {
6762
+ text-decoration: underline;
6763
+ }
6764
+
6765
+ .kds-bill-attachment i {
6766
+ font-size: var(--kds-font-size-lg);
6767
+ min-width: unset;
6768
+ justify-content: flex-start;
6769
+ }
6770
+
5984
6771
  /* -- Share Card (mustContinue) -- */
5985
6772
  .kds-share-card {
5986
6773
  margin-top: var(--kds-spacing-2);
@@ -6150,10 +6937,17 @@ button.kds-btn-success::after {
6150
6937
  padding-bottom: var(--kds-spacing-2);
6151
6938
  }
6152
6939
 
6153
- /* Invoice sticky card: progressive padding-top (expanded 20px → collapsed 8px).
6154
- Overrides base rule at same specificity; source order wins here. */
6940
+ /* Invoice sticky card padding (mobile).
6941
+ Top: estático 12px. Bottom: progresivo 20px (expandido) 8px (colapsado).
6942
+ El padding-bottom animado da breathing room natural cuando expandido y se
6943
+ reduce convencionalmente al colapsar — sin depender de que el clip-path
6944
+ corte el padding abruptamente. */
6155
6945
  .kds-payment-flow .kds-card-elevated.kds-invoice-sticky {
6156
6946
  padding-top: var(--kds-spacing-1-5);
6947
+ padding-bottom: calc(
6948
+ var(--kds-spacing-2-5)
6949
+ - var(--kds-spacing-1-5) * var(--collapse-progress, 0)
6950
+ );
6157
6951
  }
6158
6952
 
6159
6953
 
@@ -6192,7 +6986,8 @@ button.kds-btn-success::after {
6192
6986
  }
6193
6987
  .kds-brand-inner svg,
6194
6988
  .kds-brand-inner img {
6195
- height: 22px;
6989
+ width: calc(50px - 16px * var(--collapse-progress, 0));
6990
+ height: auto;
6196
6991
  display: block;
6197
6992
  }
6198
6993
 
@@ -6411,7 +7206,7 @@ button.kds-btn-success::after {
6411
7206
  inset: 0;
6412
7207
  background: var(--kds-modal-backdrop);
6413
7208
  display: none;
6414
- align-items: center;
7209
+ align-items: flex-start;
6415
7210
  justify-content: center;
6416
7211
  z-index: var(--kds-z-index-modal, 50);
6417
7212
  animation: kds-fade 0.2s ease both;
@@ -6439,7 +7234,7 @@ button.kds-btn-success::after {
6439
7234
  display: flex;
6440
7235
  align-items: center;
6441
7236
  justify-content: space-between;
6442
- padding: var(--kds-spacing-2) var(--kds-spacing-2) var(--kds-spacing-1);
7237
+ padding: var(--kds-spacing-1) var(--kds-spacing-2) var(--kds-spacing-1);
6443
7238
  }
6444
7239
 
6445
7240
  .kds-bank-modal-header h3 {
@@ -6464,11 +7259,8 @@ button.kds-btn-success::after {
6464
7259
  display: none;
6465
7260
  }
6466
7261
 
6467
- .kds-bank-modal-search {
6468
- padding: 0 var(--kds-spacing-2) var(--kds-spacing-1-5);
6469
- }
6470
-
6471
- .kds-bank-modal-search input {
7262
+ /* Search field reutilizable (standalone o dentro del KdsBankModal). */
7263
+ .kds-search-field {
6472
7264
  width: 100%;
6473
7265
  padding: var(--kds-spacing-1-25) var(--kds-spacing-1-5);
6474
7266
  border: 1px solid var(--kds-color-divider);
@@ -6480,15 +7272,57 @@ button.kds-btn-success::after {
6480
7272
  background: var(--kds-color-surface);
6481
7273
  }
6482
7274
 
6483
- .kds-bank-modal-search input::placeholder {
7275
+ .kds-search-field::placeholder {
6484
7276
  color: var(--kds-color-text-hint);
6485
7277
  }
6486
7278
 
6487
- .kds-bank-modal-search input:focus {
7279
+ .kds-search-field:focus {
6488
7280
  border-color: var(--kds-color-primary-main);
6489
7281
  box-shadow: 0 0 0 2px var(--kds-color-primary-faint);
6490
7282
  }
6491
7283
 
7284
+ /* Variante con ícono (withIcon): lupa posicionada DENTRO del input, a la derecha. */
7285
+ .kds-search-field-wrapper {
7286
+ position: relative;
7287
+ width: 100%;
7288
+ }
7289
+
7290
+ .kds-search-field-icon {
7291
+ position: absolute;
7292
+ right: var(--kds-spacing-1-5);
7293
+ top: 50%;
7294
+ transform: translateY(-50%);
7295
+ font-size: 20px;
7296
+ color: var(--kds-color-text-hint);
7297
+ pointer-events: none;
7298
+ }
7299
+
7300
+ /* Espacio a la derecha del texto para no solaparse con la lupa. */
7301
+ .kds-search-field-wrapper .kds-search-field {
7302
+ padding-right: calc(var(--kds-spacing-1-5) + var(--kds-spacing-3));
7303
+ }
7304
+
7305
+ /* Variante angosta del field (prop `narrow` de KdsTextField): ancho reducido y texto
7306
+ centrado, para inputs de pocos caracteres dispuestos en fila (ej. segmentos de
7307
+ coordenadas o código). No crece ni se encoge dentro de un flex row. */
7308
+ .field.kds-field--narrow {
7309
+ width: 6rem;
7310
+ flex: 0 0 auto;
7311
+ /* En fila horizontal no aplica el margin vertical que BeerCSS da a fields
7312
+ hermanos (regla de "flow" `... + :is(.field,...)`, specificity ~0,3,1);
7313
+ sin el reset los siguientes quedan desalineados hacia abajo. `!important`
7314
+ para ganarle a esa regla de framework. */
7315
+ margin-block: 0 !important;
7316
+ }
7317
+
7318
+ .field.kds-field--narrow > input {
7319
+ text-align: center;
7320
+ }
7321
+
7322
+ .kds-bank-modal-search {
7323
+ padding: 0 var(--kds-spacing-2) var(--kds-spacing-1-5);
7324
+ }
7325
+
6492
7326
  .kds-bank-modal-body {
6493
7327
  flex: 1;
6494
7328
  overflow-y: auto;
@@ -6586,7 +7420,7 @@ button.kds-btn-success::after {
6586
7420
  min-width: 0;
6587
7421
  }
6588
7422
 
6589
- .kds-qr-text .title {
7423
+ .kds-qr-text .kds-qr-title {
6590
7424
  font-family: var(--kds-font-family-primary);
6591
7425
  font-weight: 600;
6592
7426
  font-size: var(--kds-font-size-sm);
@@ -6594,10 +7428,15 @@ button.kds-btn-success::after {
6594
7428
  color: var(--kds-color-text-primary);
6595
7429
  }
6596
7430
 
6597
- .kds-qr-text .sub {
7431
+ .kds-qr-text .kds-qr-subtitle {
6598
7432
  font-family: var(--kds-font-family-primary);
6599
7433
  font-size: var(--kds-font-size-caption);
6600
7434
  color: var(--kds-color-text-secondary);
7435
+ /* Trunca con ellipsis en lugar de wrap a 2 líneas — evita apretar el row
7436
+ cuando el contenedor es angosto (mobile o decorator constrained). */
7437
+ overflow: hidden;
7438
+ text-overflow: ellipsis;
7439
+ white-space: nowrap;
6601
7440
  }
6602
7441
 
6603
7442
  /* QR Badge - "Rápido" indicator */
@@ -6620,46 +7459,26 @@ button.kds-btn-success::after {
6620
7459
  font-size: 20px;
6621
7460
  }
6622
7461
 
6623
- /* Mobile responsive: Ajustes para pantallas pequeñas */
7462
+ /* Mobile responsive (≤480px): respira más mantenemos padding/gap/avatar igual
7463
+ que desktop y solo agregamos truncation al subtitle y `flex-shrink: 0` en los
7464
+ ítems que deben mantener su tamaño (avatar, badge, chevron). */
6624
7465
  @media (max-width: 480px) {
6625
- .kds-qr-row {
6626
- gap: var(--kds-spacing-1-5);
6627
- padding: var(--kds-spacing-1-5);
6628
- }
6629
-
6630
7466
  .kds-qr-avatar {
6631
- width: var(--kds-spacing-4-5);
6632
- height: var(--kds-spacing-4-5);
6633
7467
  flex-shrink: 0;
6634
7468
  }
6635
7469
 
6636
- .kds-qr-avatar .material-symbols-outlined,
6637
- .kds-qr-avatar .material-icons-round {
6638
- font-size: var(--kds-font-size-lg);
6639
- }
6640
-
6641
- .kds-qr-text .title {
6642
- font-size: var(--kds-font-size-xs);
6643
- line-height: var(--kds-line-height-tight);
6644
- }
6645
-
6646
7470
  .kds-qr-text .sub {
6647
- font-size: var(--kds-font-size-caption);
6648
- line-height: var(--kds-line-height-tight);
6649
7471
  overflow: hidden;
6650
7472
  text-overflow: ellipsis;
6651
7473
  white-space: nowrap;
6652
7474
  }
6653
7475
 
6654
7476
  .kds-qr-badge {
6655
- font-size: var(--kds-font-size-caption);
6656
- padding: var(--kds-spacing-0-25) var(--kds-spacing-0-75);
6657
7477
  flex-shrink: 0;
6658
7478
  }
6659
7479
 
6660
7480
  .kds-qr-row .material-symbols-outlined:last-child,
6661
7481
  .kds-qr-row .material-icons-round:last-child {
6662
- font-size: var(--kds-font-size-base);
6663
7482
  flex-shrink: 0;
6664
7483
  }
6665
7484
  }
@@ -6688,7 +7507,11 @@ button.kds-btn-success::after {
6688
7507
  border-radius: var(--kds-spacing-0-75);
6689
7508
  font-size: var(--kds-font-size-sm);
6690
7509
  cursor: pointer;
6691
- transition: background 0.12s ease;
7510
+ /* Transición más amplia y suave: bg + color + border ease-out */
7511
+ transition:
7512
+ background-color 280ms cubic-bezier(0.2, 0.8, 0.2, 1),
7513
+ color 280ms cubic-bezier(0.2, 0.8, 0.2, 1),
7514
+ border-top-color 280ms ease-out;
6692
7515
  position: relative;
6693
7516
  user-select: none;
6694
7517
  }
@@ -6697,19 +7520,21 @@ button.kds-btn-success::after {
6697
7520
  border-top: 0;
6698
7521
  }
6699
7522
 
6700
- .kds-copyable-table-row:hover {
7523
+ /* Hover NO aplica mientras la row esté en `.copied` o `.settling`
7524
+ (evita el flicker del hover state al desaparecer el verde de "copiado") */
7525
+ .kds-copyable-table-row:not(.copied):not(.settling):hover {
6701
7526
  background: var(--kds-color-primary-faint);
6702
7527
  }
6703
7528
 
6704
- .kds-copyable-table-row:hover + .kds-copyable-table-row {
7529
+ .kds-copyable-table-row:not(.copied):not(.settling):hover + .kds-copyable-table-row {
6705
7530
  border-top-color: transparent;
6706
7531
  }
6707
7532
 
6708
- .kds-copyable-table-row:active {
7533
+ .kds-copyable-table-row:not(.copied):not(.settling):active {
6709
7534
  background: var(--kds-color-primary-selected);
6710
7535
  }
6711
7536
 
6712
- .kds-copyable-table-row .k {
7537
+ .kds-copyable-table-row .kds-key {
6713
7538
  color: var(--kds-color-text-secondary);
6714
7539
  font-size: var(--kds-font-size-caption);
6715
7540
  letter-spacing: 0.3px;
@@ -6718,7 +7543,7 @@ button.kds-btn-success::after {
6718
7543
  flex: 0 0 auto;
6719
7544
  }
6720
7545
 
6721
- .kds-copyable-table-row .v {
7546
+ .kds-copyable-table-row .kds-value {
6722
7547
  color: var(--kds-color-text-primary);
6723
7548
  font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, Consolas, monospace;
6724
7549
  font-weight: var(--kds-font-weight-medium);
@@ -6734,17 +7559,18 @@ button.kds-btn-success::after {
6734
7559
  flex: 1 1 auto;
6735
7560
  }
6736
7561
 
6737
- .kds-copyable-table-row .v::after {
7562
+ .kds-copyable-table-row .kds-value::after {
6738
7563
  content: 'content_copy';
6739
7564
  font-family: 'Material Symbols Outlined';
6740
7565
  font-size: var(--kds-font-size-sm);
6741
7566
  color: var(--kds-color-primary-main);
6742
7567
  opacity: 0;
6743
- transition: opacity 0.12s ease;
7568
+ /* Transición coordinada con la row */
7569
+ transition: opacity 280ms cubic-bezier(0.2, 0.8, 0.2, 1);
6744
7570
  flex: 0 0 auto;
6745
7571
  }
6746
7572
 
6747
- .kds-copyable-table-row:hover .v::after {
7573
+ .kds-copyable-table-row:not(.copied):not(.settling):hover .kds-value::after {
6748
7574
  opacity: 0.7;
6749
7575
  }
6750
7576
 
@@ -6752,22 +7578,76 @@ button.kds-btn-success::after {
6752
7578
  background: var(--kds-color-success-soft);
6753
7579
  }
6754
7580
 
6755
- .kds-copyable-table-row.copied .v {
7581
+ .kds-copyable-table-row.copied .kds-value {
6756
7582
  color: var(--kds-color-success-dark);
6757
7583
  }
6758
7584
 
6759
- .kds-copyable-table-row.copied .v::after {
7585
+ .kds-copyable-table-row.copied .kds-value::after {
6760
7586
  content: 'check';
6761
7587
  font-family: 'Material Symbols Outlined';
6762
7588
  color: var(--kds-color-success-dark);
6763
7589
  opacity: 1;
6764
7590
  }
6765
7591
 
7592
+ /* `.settling`: estado de "recién copiado" — la row vuelve al normal sin
7593
+ activar hover. Dura lo mismo que la transición (~300ms) y se aplica
7594
+ desde React tras quitar `.copied`. */
7595
+ .kds-copyable-table-row.settling .kds-value::after {
7596
+ /* Mantén el check con opacity 0 mientras settling, fade out suave */
7597
+ opacity: 0;
7598
+ }
7599
+
6766
7600
  /* Disable BeerCSS ripple on copyable table rows */
6767
7601
  .kds-copyable-table-row::after {
6768
7602
  display: none;
6769
7603
  }
6770
7604
 
7605
+ /* ========================================
7606
+ GRID VARIANT (.kds-copyable-table--grid)
7607
+ Read-only grid of N text cells per row. No copy,
7608
+ no role=button, no "copy all". Cells share the row
7609
+ width equally. Used inside radio options, etc.
7610
+ ======================================== */
7611
+
7612
+ /* La grilla es solo columnas de texto (como el DataTable original): sin caja,
7613
+ borde, fondo ni sombra del contenedor copyable. */
7614
+ .kds-copyable-table--grid {
7615
+ border: 0;
7616
+ border-radius: 0;
7617
+ background: none;
7618
+ padding: 0;
7619
+ box-shadow: none;
7620
+ }
7621
+
7622
+ .kds-copyable-table-row--grid {
7623
+ display: flex;
7624
+ align-items: center;
7625
+ gap: var(--kds-spacing-1-5);
7626
+ padding: 0;
7627
+ /* Sin el divisor border-top que trae la fila base del copyable. */
7628
+ border-top: 0;
7629
+ cursor: default;
7630
+ user-select: text;
7631
+ }
7632
+
7633
+ /* Separación entre filas de la grilla (sin divisores). */
7634
+ .kds-copyable-table-row--grid + .kds-copyable-table-row--grid {
7635
+ margin-top: var(--kds-spacing-0-5);
7636
+ }
7637
+
7638
+ .kds-grid-cell {
7639
+ flex: 1 1 0;
7640
+ min-width: 0;
7641
+ font-size: var(--kds-font-size-sm);
7642
+ font-weight: var(--kds-font-weight-medium);
7643
+ color: var(--kds-color-text-primary);
7644
+ word-break: break-word;
7645
+ }
7646
+
7647
+ .kds-grid-cell--disabled {
7648
+ color: var(--kds-color-text-disabled);
7649
+ }
7650
+
6771
7651
  /* ========================================
6772
7652
  COPY-ALL BUTTON (.kds-copy-all-btn)
6773
7653
  Modifier for kds-btn kds-btn-outlined that adds
@@ -6825,6 +7705,14 @@ a.kds-copy-all-btn.copied:hover {
6825
7705
  min-height: unset;
6826
7706
  }
6827
7707
 
7708
+ /* Severity variants — default stays warning (backward-compatible) */
7709
+ .kds-section-note.kds-info { color: var(--kds-color-info-dark); }
7710
+ .kds-section-note.kds-info > i { color: var(--kds-color-info-dark); }
7711
+ .kds-section-note.kds-success { color: var(--kds-color-success-dark); }
7712
+ .kds-section-note.kds-success > i { color: var(--kds-color-success-dark); }
7713
+ .kds-section-note.kds-error { color: var(--kds-color-error-dark); }
7714
+ .kds-section-note.kds-error > i { color: var(--kds-color-error-dark); }
7715
+
6828
7716
  /* ========================================
6829
7717
  INFO TOOLTIP (.kds-info-tip)
6830
7718
  Inline info button with hover/click tooltip bubble.
@@ -6920,7 +7808,7 @@ a.kds-copy-all-btn.copied:hover {
6920
7808
  .kds-monto-row {
6921
7809
  display: flex;
6922
7810
  justify-content: space-between;
6923
- align-items: flex-end;
7811
+ align-items: flex-start;
6924
7812
  padding: var(--kds-spacing-1-75) 0 var(--kds-spacing-1);
6925
7813
  border-top: 1px dashed var(--kds-color-divider);
6926
7814
  margin-top: var(--kds-spacing-1-75);
@@ -6944,3 +7832,191 @@ a.kds-copy-all-btn.copied:hover {
6944
7832
  color: var(--kds-color-text-primary);
6945
7833
  }
6946
7834
 
7835
+ /* ========================================
7836
+ PAYMENT TOTAL (.kds-payment-total)
7837
+ Bloque "monto a pagar" para QR view y email templates.
7838
+ Portado desde paylink-ligopay → <kh:paymentTotal> + materialize-config.css.
7839
+ Variantes:
7840
+ - default: amount grande (3rem) en color primario Khipu.
7841
+ - email: amount compacto (1.5rem) en color texto primario.
7842
+ Responsive (default): mobile (≤ 1024px) centra y oculta titleMobile.
7843
+ ======================================== */
7844
+
7845
+ .kds-payment-total {
7846
+ /* Component-scoped tokens — overrideables sin tocar el CSS global. */
7847
+ --kds-payment-total-title-size: var(--kds-font-size-2xl); /* 24px */
7848
+ --kds-payment-total-label-size: var(--kds-font-size-xl); /* 20px */
7849
+ --kds-payment-amount-size: 3rem; /* 48px — destacado */
7850
+ --kds-payment-amount-line-height: var(--kds-line-height-snug);
7851
+ --kds-payment-amount-color: var(--kds-color-primary-main);
7852
+ --kds-payment-amount-weight: var(--kds-font-weight-medium);
7853
+
7854
+ text-align: left;
7855
+ }
7856
+
7857
+ .kds-payment-total-title,
7858
+ .kds-payment-total-title-mobile {
7859
+ font-size: var(--kds-payment-total-title-size);
7860
+ font-weight: var(--kds-font-weight-semibold);
7861
+ color: var(--kds-color-text-primary);
7862
+ margin-bottom: var(--kds-spacing-4);
7863
+ }
7864
+
7865
+ .kds-payment-total-title-mobile {
7866
+ display: none;
7867
+ }
7868
+
7869
+ .kds-payment-total .kds-payment-label {
7870
+ font-size: var(--kds-payment-total-label-size);
7871
+ font-weight: var(--kds-font-weight-semibold);
7872
+ color: var(--kds-color-text-primary);
7873
+ margin-bottom: var(--kds-spacing-1);
7874
+ padding-top: 0;
7875
+ }
7876
+
7877
+ .kds-payment-total .kds-payment-amount {
7878
+ font-size: var(--kds-payment-amount-size);
7879
+ font-weight: var(--kds-payment-amount-weight);
7880
+ line-height: var(--kds-payment-amount-line-height);
7881
+ color: var(--kds-payment-amount-color);
7882
+ margin-bottom: var(--kds-spacing-4);
7883
+ }
7884
+
7885
+ .kds-payment-total .kds-payment-amount .kds-payment-total-decimal-sup,
7886
+ .kds-invoice-amount .kds-payment-total-decimal-sup {
7887
+ font-size: var(--kds-font-size-decimal-sup);
7888
+ font-weight: var(--kds-font-weight-semibold);
7889
+ position: relative;
7890
+ top: 0;
7891
+ }
7892
+
7893
+ /* Variante email: amount compacto en color texto primario, alineación izquierda fija */
7894
+ .kds-payment-total--email {
7895
+ --kds-payment-amount-size: var(--kds-font-size-2xl); /* 24px */
7896
+ --kds-payment-amount-line-height: var(--kds-line-height-snug);
7897
+ --kds-payment-amount-color: var(--kds-color-text-primary);
7898
+ --kds-payment-amount-weight: var(--kds-font-weight-semibold);
7899
+ }
7900
+
7901
+ /* Tone modifier: swaps the amount color to the khipu-blue / LigoPay info blue.
7902
+ Combinable with --email or with the default variant. */
7903
+ .kds-payment-total--tone-info {
7904
+ --kds-payment-amount-color: var(--kds-color-info-blue); /* #5A5FE0 */
7905
+ }
7906
+
7907
+ /* Centered modifier: removes the asymmetric desktop padding (which exists for
7908
+ LigoPay QR view) and centers all internal text. Composable with --email and
7909
+ --tone-info. */
7910
+ .kds-payment-total--centered {
7911
+ padding-left: 0;
7912
+ padding-top: 0;
7913
+ text-align: center;
7914
+ }
7915
+ .kds-payment-total--centered .kds-payment-total-title,
7916
+ .kds-payment-total--centered .kds-payment-total-title-mobile,
7917
+ .kds-payment-total--centered .kds-payment-label,
7918
+ .kds-payment-total--centered .kds-payment-amount {
7919
+ text-align: center;
7920
+ }
7921
+
7922
+ /* Responsive: mobile ≤ 1024px — centra y conmuta los títulos (sólo variante default) */
7923
+ @media (max-width: 1024px) {
7924
+ .kds-payment-total {
7925
+ text-align: center;
7926
+ }
7927
+
7928
+ .kds-payment-total .kds-payment-total-title {
7929
+ display: none;
7930
+ }
7931
+
7932
+ .kds-payment-total .kds-payment-total-title-mobile {
7933
+ display: block;
7934
+ text-align: center;
7935
+ }
7936
+
7937
+ .kds-payment-total .kds-payment-label,
7938
+ .kds-payment-total .kds-payment-amount {
7939
+ text-align: center;
7940
+ }
7941
+
7942
+ /* Email mantiene alineación izquierda incluso en mobile (matchea email clients) */
7943
+ .kds-payment-total--email,
7944
+ .kds-payment-total--email .kds-payment-label,
7945
+ .kds-payment-total--email .kds-payment-amount {
7946
+ text-align: left;
7947
+ }
7948
+ }
7949
+
7950
+ /* ==========================================================================
7951
+ GRID UTILITIES — semantic aliases for BeerCSS .grid / .s* / .m* / .l*
7952
+
7953
+ Estas utilidades son ALIAS de las clases cortas de BeerCSS para que
7954
+ consumers (payment, LigoPay, Grails legacy) puedan escribir markup con
7955
+ nombres descriptivos sin renunciar al grid de 12 columnas de BeerCSS.
7956
+
7957
+ Convención (estilo Bootstrap responsive):
7958
+ - kds-grid → .grid (12-col CSS grid + 1rem gap)
7959
+ - kds-col-sm-{1..12} → .s{1..12} (mobile, siempre aplica)
7960
+ - kds-col-md-{1..12} → .m{1..12} (>=601px)
7961
+ - kds-col-lg-{1..12} → .l{1..12} (>=993px)
7962
+
7963
+ Las definiciones originales de BeerCSS NO se tocan; estas son aditivas.
7964
+ ========================================================================== */
7965
+
7966
+ .kds-grid {
7967
+ --_gap: 1rem;
7968
+ display: grid;
7969
+ grid-template-columns: repeat(12, 1fr);
7970
+ gap: var(--_gap);
7971
+ block-size: auto;
7972
+ }
7973
+
7974
+ .kds-grid.kds-grid-no-space { --_gap: 0rem; }
7975
+ .kds-grid.kds-grid-medium-space { --_gap: 1.5rem; }
7976
+ .kds-grid.kds-grid-large-space { --_gap: 2rem; }
7977
+
7978
+ .kds-grid > * { margin: 0; }
7979
+
7980
+ .kds-col-sm-1 { grid-area: auto/span 1; }
7981
+ .kds-col-sm-2 { grid-area: auto/span 2; }
7982
+ .kds-col-sm-3 { grid-area: auto/span 3; }
7983
+ .kds-col-sm-4 { grid-area: auto/span 4; }
7984
+ .kds-col-sm-5 { grid-area: auto/span 5; }
7985
+ .kds-col-sm-6 { grid-area: auto/span 6; }
7986
+ .kds-col-sm-7 { grid-area: auto/span 7; }
7987
+ .kds-col-sm-8 { grid-area: auto/span 8; }
7988
+ .kds-col-sm-9 { grid-area: auto/span 9; }
7989
+ .kds-col-sm-10 { grid-area: auto/span 10; }
7990
+ .kds-col-sm-11 { grid-area: auto/span 11; }
7991
+ .kds-col-sm-12 { grid-area: auto/span 12; }
7992
+
7993
+ @media only screen and (min-width: 601px) {
7994
+ .kds-col-md-1 { grid-area: auto/span 1; }
7995
+ .kds-col-md-2 { grid-area: auto/span 2; }
7996
+ .kds-col-md-3 { grid-area: auto/span 3; }
7997
+ .kds-col-md-4 { grid-area: auto/span 4; }
7998
+ .kds-col-md-5 { grid-area: auto/span 5; }
7999
+ .kds-col-md-6 { grid-area: auto/span 6; }
8000
+ .kds-col-md-7 { grid-area: auto/span 7; }
8001
+ .kds-col-md-8 { grid-area: auto/span 8; }
8002
+ .kds-col-md-9 { grid-area: auto/span 9; }
8003
+ .kds-col-md-10 { grid-area: auto/span 10; }
8004
+ .kds-col-md-11 { grid-area: auto/span 11; }
8005
+ .kds-col-md-12 { grid-area: auto/span 12; }
8006
+ }
8007
+
8008
+ @media only screen and (min-width: 993px) {
8009
+ .kds-col-lg-1 { grid-area: auto/span 1; }
8010
+ .kds-col-lg-2 { grid-area: auto/span 2; }
8011
+ .kds-col-lg-3 { grid-area: auto/span 3; }
8012
+ .kds-col-lg-4 { grid-area: auto/span 4; }
8013
+ .kds-col-lg-5 { grid-area: auto/span 5; }
8014
+ .kds-col-lg-6 { grid-area: auto/span 6; }
8015
+ .kds-col-lg-7 { grid-area: auto/span 7; }
8016
+ .kds-col-lg-8 { grid-area: auto/span 8; }
8017
+ .kds-col-lg-9 { grid-area: auto/span 9; }
8018
+ .kds-col-lg-10 { grid-area: auto/span 10; }
8019
+ .kds-col-lg-11 { grid-area: auto/span 11; }
8020
+ .kds-col-lg-12 { grid-area: auto/span 12; }
8021
+ }
8022
+