@khipu/design-system 0.3.5-alpha.3 → 0.3.5-alpha.30

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.
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
17
17
  * Source: design-system/src/tokens/tokens.json
18
- * Generated: 2026-08-13T16:19:44.738Z
18
+ * Generated: 2026-10-06T20:11:26.407Z
19
19
  *
20
20
  * To regenerate:
21
21
  * cd design-system && npm run tokens:generate
@@ -399,13 +399,13 @@
399
399
  /* ============================================================================
400
400
  DARK MODE COLOR TOKENS
401
401
  Override only color variables; everything else inherits from :root.
402
- Activated via [data-theme="dark"] on <html>, <body>, or a wrapper —
403
- or via the BeerCSS-style body.dark class. Both selectors are emitted so
404
- a body.dark app gets the FULL dark theme (core + extended tokens); a
405
- single source flipping only partially is how mixed light/dark bugs arise.
402
+ Activated ONLY via [data-theme="dark"] on <html>, <body>, or a wrapper.
403
+ body.dark is deliberately NOT a trigger: BeerCSS adds that class on its
404
+ own when the OS reports a dark preference, so honouring it turns dark on
405
+ for consumers that never opted in. Dark stays opt-in until an app sets
406
+ data-theme explicitly.
406
407
  ============================================================================ */
407
408
 
408
- .kds-theme-root.dark,
409
409
  .kds-theme-root [data-theme="dark"] {
410
410
 
411
411
  /* Primary palette - Khipu brand */
@@ -881,11 +881,10 @@
881
881
  values so selected states / rows / hovers adapt. Additive: the light
882
882
  :root / body.light values above are unchanged. Tokens already defined as
883
883
  var() refs (warning-soft, danger-soft) adapt on their own and are omitted.
884
- body.dark is included on purpose: the light group above also matches
885
- body.dark (specificity 0,1,1), so a bare [data-theme] override (0,1,0)
886
- would lose on a body that carries the transitional dark class.
884
+ body.dark is deliberately NOT a trigger: BeerCSS adds that class on its own
885
+ when the OS reports a dark preference, so honouring it turns dark on for
886
+ consumers that never opted in. Dark stays opt-in via data-theme.
887
887
  ======================================== */
888
- .kds-theme-root.dark,
889
888
  .kds-theme-root [data-theme="dark"] {
890
889
  --kds-color-primary-faint: #1E1030; /* dark brand-tinted subtle surface (selected rows/cards) */
891
890
  --kds-color-info-soft: var(--kds-alert-info-bg); /* dark translucent blue */
@@ -919,7 +918,7 @@
919
918
  opt-out for Chrome/WebView "Auto Dark Theme" on Android: without it, an
920
919
  OS-dark device heuristically darkens SOME elements of a light page (mixed
921
920
  light/dark rendering in production apps). Dark is reached only by an
922
- explicit [data-theme="dark"] / body.dark opt-in. */
921
+ explicit [data-theme="dark"] opt-in. */
923
922
  .kds-theme-root,
924
923
  .kds-theme-root,
925
924
  .kds-theme-root {
@@ -938,8 +937,7 @@
938
937
  }
939
938
 
940
939
  /* Explicit dark theme: let native UI (form controls, scrollbars) render dark. */
941
- .kds-theme-root [data-theme="dark"],
942
- .kds-theme-root.dark {
940
+ .kds-theme-root [data-theme="dark"] {
943
941
  color-scheme: dark;
944
942
  }
945
943
 
@@ -1001,6 +999,20 @@
1001
999
  background-color: transparent !important;
1002
1000
  }
1003
1001
 
1002
+ /* Familia base del arbol del DS.
1003
+ BeerCSS la pone en `body { font-family: var(--font) }`, y `--font` es un alias
1004
+ declarado en :root. Una custom property se sustituye en el elemento que la declara,
1005
+ asi que ese alias se congela con la familia de :root: una marca que define
1006
+ --kds-font-family-primary mas abajo en el arbol no lo mueve, y el texto que solo
1007
+ hereda de body se queda con la familia por defecto.
1008
+
1009
+ Resolviendo el token aca, en la raiz del arbol del DS, hereda todo lo de adentro con
1010
+ la familia vigente en ese punto. Sin marca definida el valor es el mismo de siempre,
1011
+ asi que no cambia nada para quien no la configura. */
1012
+ .kds-theme-root .kds-theme-root {
1013
+ font-family: var(--kds-font-family-primary);
1014
+ }
1015
+
1004
1016
  /* ========================================
1005
1017
  TEXT UTILITIES OVERRIDE
1006
1018
  Fix BeerCSS classes that use wrong color tokens
@@ -1212,6 +1224,29 @@
1212
1224
  opacity: 0.9;
1213
1225
  }
1214
1226
 
1227
+ /* Outlined success — compone con .kds-btn-outlined, igual que .kds-btn-outlined-white:
1228
+ solo cambia superficie y color, la caja la aporta la variante base. */
1229
+ .kds-theme-root button.kds-btn-outlined-success,
1230
+ .kds-theme-root a.kds-btn-outlined-success {
1231
+ background: transparent;
1232
+ color: var(--kds-color-success-main);
1233
+ border-color: var(--kds-color-success-main);
1234
+ }
1235
+
1236
+ .kds-theme-root button.kds-btn-outlined-success:hover:not(:disabled),
1237
+ .kds-theme-root a.kds-btn-outlined-success:hover:not(:disabled) {
1238
+ background: var(--kds-color-success-soft);
1239
+ border-color: var(--kds-color-success-dark);
1240
+ color: var(--kds-color-success-dark);
1241
+ }
1242
+
1243
+ .kds-theme-root button.kds-btn-outlined-success:disabled,
1244
+ .kds-theme-root a.kds-btn-outlined-success:disabled {
1245
+ background: transparent;
1246
+ color: var(--kds-color-action-disabled);
1247
+ border-color: var(--kds-color-action-disabled);
1248
+ }
1249
+
1215
1250
  /* Text button — mismo tamaño que el resto de variantes (hereda min-height/padding
1216
1251
  del base): solo cambia la superficie, no la caja. */
1217
1252
  .kds-theme-root button.kds-btn-text,
@@ -1903,6 +1938,9 @@
1903
1938
  .kds-theme-root .kds-mt-4 { margin-top: var(--kds-spacing-4); }
1904
1939
  .kds-theme-root .kds-mt-6 { margin-top: var(--kds-spacing-6); }
1905
1940
  .kds-theme-root .kds-mt-8 { margin-top: var(--kds-spacing-8); }
1941
+ /* Absorbe el espacio libre de un contenedor flex-column: ancla el elemento al fondo
1942
+ (p.ej. las acciones de un form dentro de .kds-card-elevated--action). */
1943
+ .kds-theme-root .kds-mt-auto { margin-top: auto; }
1906
1944
 
1907
1945
  .kds-theme-root .kds-mb-0 { margin-bottom: 0; }
1908
1946
  .kds-theme-root .kds-mb-0-5 { margin-bottom: var(--kds-spacing-0-5); }
@@ -2356,28 +2394,35 @@
2356
2394
  }
2357
2395
 
2358
2396
  /* ========================================
2359
- Google Sign-In Button
2360
- Per Google Identity branding guidelines:
2397
+ SSO Button (federated sign-in: Google, Microsoft, ...)
2398
+ Neutral white button shared by every identity provider, styled per
2399
+ Google Identity branding guidelines, which Microsoft's also satisfy:
2361
2400
  https://developers.google.com/identity/branding-guidelines
2401
+ `.kds-btn-google` / `.kds-google-icon` are kept as aliases for
2402
+ consumers pinned to earlier versions.
2403
+ Colors go through --kds-btn-sso-* so the dark theme swaps all of them
2404
+ together (background alone flipping left the label unreadable).
2362
2405
  ======================================== */
2363
2406
 
2407
+ .kds-theme-root button.kds-btn-sso,
2408
+ .kds-theme-root a.kds-btn-sso,
2364
2409
  .kds-theme-root button.kds-btn-google,
2365
2410
  .kds-theme-root a.kds-btn-google {
2366
2411
  display: inline-flex;
2367
2412
  align-items: center;
2368
2413
  justify-content: center;
2369
- gap: var(--kds-spacing-1-5);
2414
+ gap: var(--kds-spacing-1-25);
2370
2415
  width: 100%;
2371
- background: var(--kds-color-background-paper);
2372
- color: #1F1F1F;
2373
- border: 1px solid #747775;
2416
+ background: var(--kds-btn-sso-bg, #FFFFFF);
2417
+ color: var(--kds-btn-sso-color, #1F1F1F);
2418
+ border: 1px solid var(--kds-btn-sso-border, #747775);
2374
2419
  border-radius: var(--kds-radius-button);
2375
2420
  padding: var(--kds-spacing-1) var(--kds-spacing-1-5);
2376
2421
  min-height: var(--kds-spacing-button-min-height);
2377
- font-family: "Roboto", var(--kds-font-family-secondary);
2422
+ font-family: var(--kds-font-family-secondary);
2378
2423
  font-weight: var(--kds-font-weight-medium);
2379
2424
  font-size: var(--kds-font-size-sm);
2380
- line-height: var(--kds-line-height-normal);
2425
+ line-height: 20px; /* Google 14/20; no line-height token matches */
2381
2426
  letter-spacing: var(--kds-letter-spacing-normal);
2382
2427
  text-transform: none;
2383
2428
  cursor: pointer;
@@ -2387,17 +2432,34 @@
2387
2432
  box-shadow: none;
2388
2433
  }
2389
2434
 
2435
+ .kds-theme-root button.kds-btn-sso:hover,
2436
+ .kds-theme-root a.kds-btn-sso:hover,
2390
2437
  .kds-theme-root button.kds-btn-google:hover,
2391
2438
  .kds-theme-root a.kds-btn-google:hover {
2392
- background: #F2F2F2;
2439
+ background: var(--kds-btn-sso-bg-hover, #F2F2F2);
2393
2440
  box-shadow: var(--kds-shadow-1);
2394
2441
  }
2395
2442
 
2443
+ .kds-theme-root button.kds-btn-sso:active,
2444
+ .kds-theme-root a.kds-btn-sso:active,
2396
2445
  .kds-theme-root button.kds-btn-google:active,
2397
2446
  .kds-theme-root a.kds-btn-google:active {
2398
- background: #E8E8E8;
2447
+ background: var(--kds-btn-sso-bg-active, #E8E8E8);
2448
+ }
2449
+
2450
+ /* Dark theme per Google Identity guidelines; hover/active are 8% / 12%
2451
+ state layers of the label color over the fill. */
2452
+ .kds-theme-root [data-theme="dark"] .kds-btn-sso,
2453
+ .kds-theme-root [data-theme="dark"] .kds-btn-google {
2454
+ --kds-btn-sso-bg: #131314;
2455
+ --kds-btn-sso-color: #E3E3E3;
2456
+ --kds-btn-sso-border: #8E918F;
2457
+ --kds-btn-sso-bg-hover: #242425;
2458
+ --kds-btn-sso-bg-active: #2C2C2D;
2399
2459
  }
2400
2460
 
2461
+ .kds-theme-root button.kds-btn-sso:disabled,
2462
+ .kds-theme-root a.kds-btn-sso:disabled,
2401
2463
  .kds-theme-root button.kds-btn-google:disabled,
2402
2464
  .kds-theme-root a.kds-btn-google:disabled {
2403
2465
  background: var(--kds-color-action-disabled-bg);
@@ -2407,7 +2469,8 @@
2407
2469
  box-shadow: none;
2408
2470
  }
2409
2471
 
2410
- /* Google G icon container - white background per guidelines */
2472
+ /* Provider logo container */
2473
+ .kds-theme-root .kds-btn-sso .kds-sso-icon,
2411
2474
  .kds-theme-root .kds-btn-google .kds-google-icon {
2412
2475
  display: flex;
2413
2476
  align-items: center;
@@ -2415,6 +2478,7 @@
2415
2478
  flex-shrink: 0;
2416
2479
  }
2417
2480
 
2481
+ .kds-theme-root .kds-btn-sso .kds-sso-icon svg,
2418
2482
  .kds-theme-root .kds-btn-google .kds-google-icon svg {
2419
2483
  width: var(--kds-spacing-button-icon-size);
2420
2484
  height: var(--kds-spacing-button-icon-size);
@@ -2458,12 +2522,21 @@
2458
2522
  /* Llena y centra dentro de contenedores flex (pantalla de carga); en flujo
2459
2523
  normal (contenedor no-flex) se reduce a su contenido. */
2460
2524
  flex: 1 1 auto;
2461
- /* Alto propio: el loader es contenido minimo por definicion, asi que sin esto la
2462
- card queda del alto del spinner y se lee como un recorte. Ocupa el body completo
2463
- de un telefono para que la pantalla de carga se lea como una pantalla y no como
2464
- una franja. Va aca y no en la card para que el minimo aplique solo a la carga:
2465
- el resto de las pantallas crece con su contenido. */
2466
- min-height: 36rem;
2525
+ /* Alto propio: el loader es contenido minimo por definicion, asi que sin esto la card
2526
+ queda del alto del spinner y se lee como un recorte. Va aca y no en la card para que
2527
+ el minimo aplique solo a la carga: el resto de las pantallas crece con su contenido.
2528
+ El valor de escritorio es moderado a proposito: el minimo de telefono (36rem) dejaba
2529
+ la card de la carga mucho mas alta que cualquier otra pantalla, y al entrar y salir
2530
+ del loader el widget crecia y volvia a encoger. */
2531
+ min-height: 18rem;
2532
+ }
2533
+
2534
+ /* En telefono la carga si ocupa el alto util de la pantalla: ahi la card va a ancho
2535
+ completo y un loader corto se lee como una franja perdida en el medio. */
2536
+ @media (max-width: 767px) {
2537
+ .kds-theme-root .kds-secure-loader {
2538
+ min-height: 36rem;
2539
+ }
2467
2540
  }
2468
2541
 
2469
2542
  .kds-theme-root .kds-secure-loader-text {
@@ -3273,12 +3346,32 @@
3273
3346
  cursor: pointer;
3274
3347
  }
3275
3348
 
3276
- /* Checked state */
3349
+ /* Checked state.
3350
+ accent-color aplica al input nativo, que BeerCSS deja con opacity 0: no se ve.
3351
+ Se mantiene igual por si algun consumidor no usa el markup de BeerCSS. */
3277
3352
  .kds-theme-root label.checkbox input[type="checkbox"]:checked,
3278
3353
  .kds-theme-root label.radio input[type="radio"]:checked {
3279
3354
  accent-color: var(--kds-color-accent, var(--primary));
3280
3355
  }
3281
3356
 
3357
+ /* El control que SI se ve lo dibuja BeerCSS como una ligadura de Material Symbols en
3358
+ `> span::before`, coloreada con var(--primary). Estas dos reglas reproducen sus
3359
+ selectores para que ese pseudo-elemento siga al rol accent.
3360
+
3361
+ Misma especificidad que el original y sin !important: este archivo va ultimo en el
3362
+ bundle, asi que gana por orden. El fallback deja el valor anterior intacto cuando la
3363
+ marca no define accent, que es el caso de todo consumidor actual.
3364
+
3365
+ No se toca `.switch`: es un control de encendido/apagado, no de seleccion, y el
3366
+ contrato de marca no lo incluye. */
3367
+ .kds-theme-root :is(.checkbox, .radio) > span::before {
3368
+ color: var(--kds-color-accent, var(--primary));
3369
+ }
3370
+
3371
+ .kds-theme-root :is(.checkbox, .radio) > input:checked + span::before, .kds-theme-root :is(.checkbox, .radio).icon > input:checked + span > i {
3372
+ color: var(--kds-color-accent, var(--primary));
3373
+ }
3374
+
3282
3375
  /* Disabled state */
3283
3376
  .kds-theme-root label.checkbox input[type="checkbox"]:disabled,
3284
3377
  .kds-theme-root label.radio input[type="radio"]:disabled {
@@ -4332,14 +4425,16 @@
4332
4425
 
4333
4426
  /* Code block for displaying code snippets */
4334
4427
  .kds-theme-root .kds-code-block {
4335
- background: var(--kds-color-background-elevated);
4336
- padding: var(--kds-spacing-4);
4428
+ background: var(--kds-color-background-muted);
4429
+ border: 1px solid var(--kds-color-divider);
4430
+ padding: var(--kds-spacing-2);
4337
4431
  border-radius: var(--kds-radius-md);
4338
4432
  overflow-x: auto;
4339
- font-family: 'Courier New', monospace;
4433
+ font-family: var(--kds-font-family-mono);
4340
4434
  font-size: var(--kds-font-size-sm);
4341
4435
  line-height: var(--kds-line-height-relaxed);
4342
4436
  color: var(--kds-color-text-primary);
4437
+ tab-size: 4;
4343
4438
  }
4344
4439
 
4345
4440
  /* ============================================
@@ -6280,13 +6375,39 @@
6280
6375
  alto que el mark de Khipu. Sirve para <img> o un elemento con .kds-psp-mark. */
6281
6376
  .kds-theme-root .kds-secure-footer img,
6282
6377
  .kds-theme-root .kds-secure-footer .kds-psp-mark {
6283
- height: 11px;
6284
6378
  width: auto;
6285
6379
  flex: 0 0 auto;
6286
6380
  display: block;
6287
6381
  object-fit: contain;
6288
6382
  }
6289
6383
 
6384
+ /* Logo del PSP: dos perillas, las dos calibradas contra el asset real que sube un PSP
6385
+ hoy (klap.png, 60x30, con 2px de aire transparente arriba y abajo).
6386
+
6387
+ Se nivela por LINEA DE BASE, no por caja ni por borde inferior de la tinta: los dos
6388
+ wordmarks tienen descendente -la "p" de Khipu baja un 20% de su caja- asi que igualar
6389
+ los bordes de abajo deja al logo del PSP flotando sobre la linea de Khipu.
6390
+
6391
+ - --kds-psp-mark-height: el alto de la caja. El ojo lee la tinta, no la caja, y el
6392
+ aire del PNG se come parte del alto: a 11px la tinta de klap medía 9.5px contra los
6393
+ 11px de Khipu y se veia mas chico. A 15px la tinta llega a 13px y se leen iguales.
6394
+ - --kds-psp-mark-top: cuanto baja para que su linea de base calce con la de Khipu.
6395
+ Va como valor y no como formula a proposito: depende del aire y de la anatomia del
6396
+ asset de cada PSP, y se termina de ajustar mirando la pantalla. */
6397
+ .kds-theme-root .kds-secure-footer {
6398
+ --kds-psp-mark-height: 15px;
6399
+ --kds-psp-mark-top: 1px;
6400
+ }
6401
+
6402
+ .kds-theme-root .kds-secure-footer img,
6403
+ .kds-theme-root .kds-secure-footer .kds-psp-mark {
6404
+ height: var(--kds-psp-mark-height);
6405
+ position: relative;
6406
+ top: var(--kds-psp-mark-top);
6407
+ }
6408
+
6409
+
6410
+
6290
6411
  .kds-theme-root .kds-secure-footer-code {
6291
6412
  color: var(--kds-color-text-hint);
6292
6413
  }
@@ -6542,14 +6663,37 @@
6542
6663
  color: var(--kds-color-success-main);
6543
6664
  }
6544
6665
 
6545
- /* Variant: pending (animated blue spinner, sin icono interno) */
6666
+ /* Variant: pending (animated spinner, sin icono interno).
6667
+ El acento sale de --kds-status-pending-accent, con el azul de info como
6668
+ fallback: el valor por defecto no cambia, y una pantalla puede pedir otro
6669
+ acento sin redefinir la regla ni recurrir a estilos inline. */
6546
6670
  .kds-theme-root .kds-status-block[data-status="pending"] .kds-status-block-icon {
6547
6671
  background: transparent;
6548
6672
  border: 3px solid var(--kds-color-divider);
6549
- border-top-color: var(--kds-color-info-main);
6673
+ border-top-color: var(--kds-status-pending-accent, var(--kds-color-info-main));
6550
6674
  animation: kds-spin 1s linear infinite;
6551
6675
  }
6552
6676
 
6677
+ /* Spinner neutro, para esperas que acompañan al contenido sin reclamar
6678
+ atención: el azul de info lee como un aviso y compite con la información
6679
+ de la pantalla. */
6680
+ .kds-theme-root .kds-status-block.kds-accent-neutral {
6681
+ --kds-status-pending-accent: var(--kds-color-text-primary);
6682
+ }
6683
+
6684
+ /* Spinner fino, para bandas de una línea donde el trazo de 3px pesa demasiado.
6685
+ El tamaño se pide por token y no por regla sobre el icono: así no compite en
6686
+ especificidad con `.kds-status-block.inline .kds-status-block-icon`, que
6687
+ marca igual y viene después. */
6688
+ .kds-theme-root .kds-status-block.kds-spinner-sm {
6689
+ --kds-status-icon-size: var(--kds-spacing-3);
6690
+ --kds-status-icon-size-sm: var(--kds-spacing-3);
6691
+ }
6692
+
6693
+ .kds-theme-root .kds-status-block.kds-spinner-sm .kds-status-block-icon {
6694
+ border-width: 2px;
6695
+ }
6696
+
6553
6697
  /* Variant: warn */
6554
6698
  .kds-theme-root .kds-status-block[data-status="warn"] .kds-status-block-icon {
6555
6699
  background: var(--kds-color-warning-soft);
@@ -6593,6 +6737,60 @@
6593
6737
  font-size: var(--kds-font-size-xl);
6594
6738
  }
6595
6739
 
6740
+ /* Inline without description: the title is the only thing next to the icon. Its
6741
+ margin-bottom (spacing-1, which separates it from the description in the centered
6742
+ variant) made the column taller, so align-items:center left the text ~4px above the
6743
+ icon's center. */
6744
+ .kds-theme-root .kds-status-block.inline .kds-status-block-title:last-child {
6745
+ margin-bottom: 0;
6746
+ --kds-typography-h2-margin-block-end: 0;
6747
+ }
6748
+
6749
+ /* Inline with description (KdsStatusBlock inline + description): the description is a
6750
+ full-width paragraph below the icon+title row, spacing-1 under it. The block drops its
6751
+ bottom padding and owns the gap to what follows (spacing-2), so consumers never add
6752
+ margins around the description. kds-btn-stack and kds-share-card already carry that
6753
+ top margin themselves. */
6754
+ .kds-theme-root .kds-status-block.inline.kds-status-block--described {
6755
+ flex-wrap: wrap;
6756
+ row-gap: var(--kds-spacing-1);
6757
+ padding-bottom: 0;
6758
+ }
6759
+
6760
+ .kds-theme-root .kds-status-block--described > .kds-status-block-description {
6761
+ flex-basis: 100%;
6762
+ }
6763
+
6764
+ .kds-theme-root .kds-status-block--described + .kds-alert,
6765
+ .kds-theme-root .kds-status-block--described + .kds-copy-row {
6766
+ margin-top: var(--kds-spacing-2);
6767
+ }
6768
+
6769
+ /* Banda: el bloque de estado sobre una superficie sutil, para cuando acompaña
6770
+ al contenido en lugar de encabezar la pantalla. Va después de `.inline`
6771
+ porque marca igual en especificidad y necesita ganarle el padding. */
6772
+ .kds-theme-root .kds-status-block.kds-banded {
6773
+ /* 0.75rem = 12px, el valor que --kds-font-size-xs toma desde tablet. Va plano y no
6774
+ sigue la escala responsiva a proposito: a 11px el mensaje de espera se parte en dos
6775
+ lineas y el diseno lo quiere en una. Como custom property de la variante, siguiendo
6776
+ el patron de kds-spinner-sm con --kds-status-icon-size. */
6777
+ --kds-status-band-font-size: 0.75rem;
6778
+ background: var(--kds-color-background-muted);
6779
+ border-radius: var(--kds-radius-md);
6780
+ padding: var(--kds-spacing-1-5) var(--kds-spacing-2);
6781
+ }
6782
+
6783
+ /* La banda de espera lleva su propia tipografia, por spec de Figma: 11px en bold.
6784
+ Va scopeada a la variante y no a .kds-status-block-description, que la comparten
6785
+ los bloques de resultado, donde 11px seria ilegible. El color se deja en el token
6786
+ heredado: un #000 fijo se volveria invisible bajo modo oscuro, donde text-primary
6787
+ pasa a blanco. */
6788
+ .kds-theme-root .kds-status-block.kds-banded .kds-status-block-description {
6789
+ font-size: var(--kds-status-band-font-size);
6790
+ font-weight: var(--kds-font-weight-bold);
6791
+ line-height: normal;
6792
+ }
6793
+
6596
6794
  @keyframes kds-spin {
6597
6795
  to { transform: rotate(360deg); }
6598
6796
  }
@@ -6679,6 +6877,48 @@
6679
6877
  min-height: 0;
6680
6878
  }
6681
6879
 
6880
+ /* Variante alta (size="full"): contenido largo (documentos, textos legales) usa todo el alto
6881
+ máximo del sheet y el body se estira para que un hijo lo llene. Los .kds-theme-root son
6882
+ envoltorios transparentes que el consumidor puede meter entre el body y el contenido (p. ej.
6883
+ un KdsRoot dentro de un div display:contents), así que se estiran a cualquier profundidad. */
6884
+ .kds-theme-root .kds-bottom-sheet-full {
6885
+ height: 90vh;
6886
+ height: 90dvh;
6887
+ }
6888
+
6889
+ .kds-theme-root .kds-bottom-sheet-full .kds-bottom-sheet-body,
6890
+ .kds-theme-root .kds-bottom-sheet-full .kds-bottom-sheet-body .kds-theme-root {
6891
+ display: flex;
6892
+ flex: 1;
6893
+ flex-direction: column;
6894
+ }
6895
+
6896
+ /* ========================================
6897
+ DOCUMENT FRAME (.kds-document-frame)
6898
+ Documento embebido (iframe) que llena su contenedor. --kds-document-frame-scale achica
6899
+ documentos pensados para un viewport de escritorio: el iframe se arma más ancho y se
6900
+ escala, así letra, títulos y márgenes bajan juntos.
6901
+ ======================================== */
6902
+
6903
+ .kds-theme-root .kds-document-frame {
6904
+ --kds-document-frame-scale: 1;
6905
+ position: relative;
6906
+ flex: 1;
6907
+ min-height: var(--kds-document-frame-min-height, 12rem);
6908
+ overflow: hidden;
6909
+ }
6910
+
6911
+ .kds-theme-root .kds-document-frame > iframe {
6912
+ position: absolute;
6913
+ top: 0;
6914
+ left: 0;
6915
+ width: calc(100% / var(--kds-document-frame-scale));
6916
+ height: calc(100% / var(--kds-document-frame-scale));
6917
+ border: 0;
6918
+ transform: scale(var(--kds-document-frame-scale));
6919
+ transform-origin: 0 0;
6920
+ }
6921
+
6682
6922
  .kds-theme-root .kds-bottom-sheet-icon {
6683
6923
  font-size: var(--kds-font-size-4xl);
6684
6924
  }
@@ -6714,6 +6954,14 @@
6714
6954
  color: var(--kds-color-primary-contrast);
6715
6955
  }
6716
6956
 
6957
+ /* El reset `.kds-bottom-sheet-actions button { border: 0 }` borra la caja de las
6958
+ variantes outlined. Se restituye solo grosor y estilo: el color queda en
6959
+ currentColor, que ya es el de cada variante (primary, success, etc.). */
6960
+ .kds-theme-root .kds-bottom-sheet-actions button.kds-btn-outlined {
6961
+ border-style: solid;
6962
+ border-width: var(--kds-border-width-sm, 1px);
6963
+ }
6964
+
6717
6965
  .kds-theme-root .kds-bottom-sheet-actions .kds-btn-ghost {
6718
6966
  background: transparent;
6719
6967
  color: var(--kds-color-text-secondary);
@@ -6834,6 +7082,15 @@
6834
7082
  }
6835
7083
 
6836
7084
  /* Auto-managed tab panels: hidden attribute must win over any display rule */
7085
+ /* `hidden` es semantica de plataforma: si el atributo esta, el elemento no se
7086
+ renderiza. El UA lo aplica con display:none, pero cualquier regla de autor con
7087
+ display lo pisa — .kds-btn y .kds-btn-stack son flex, asi que un boton con
7088
+ hidden seguia ocupando lugar. El !important es deliberado: ninguna regla de
7089
+ componente deberia poder anular el atributo. */
7090
+ .kds-theme-root [hidden] {
7091
+ display: none !important;
7092
+ }
7093
+
6837
7094
  .kds-theme-root [data-kds-tab-panel][hidden] {
6838
7095
  display: none;
6839
7096
  }
@@ -7224,6 +7481,48 @@
7224
7481
  padding: var(--kds-spacing-0-5);
7225
7482
  }
7226
7483
 
7484
+ /* -- Skeleton (KTUF-388) --
7485
+ Gris pulsante que reserva el lugar de un contenido que aún no llega. La base solo pinta:
7486
+ sobre un elemento que ya tiene tamaño (p.ej. .kds-invoice-merchant) conserva sus medidas,
7487
+ radio y colapso, y solo cambia el fondo. */
7488
+ .kds-theme-root .kds-skeleton {
7489
+ background: var(--kds-color-gray-200);
7490
+ animation: kds-skeleton-pulse 1.4s ease-in-out infinite;
7491
+ }
7492
+
7493
+ /* Línea de texto: inline-block de 1em puesto DENTRO del elemento real (p.kds-invoice-amount,
7494
+ dd, ...), hereda su font-size y line-height, así la caja mide lo mismo que con texto y el
7495
+ reemplazo no desplaza el layout. */
7496
+ .kds-theme-root .kds-skeleton--text {
7497
+ display: inline-block;
7498
+ width: 100%;
7499
+ height: 1em;
7500
+ vertical-align: middle;
7501
+ border-radius: var(--kds-radius-sm);
7502
+ }
7503
+
7504
+ .kds-theme-root [data-theme="dark"] .kds-skeleton {
7505
+ background: var(--kds-color-gray-700);
7506
+ }
7507
+
7508
+ @keyframes kds-skeleton-pulse {
7509
+ 0%, 100% { opacity: 1; }
7510
+ 50% { opacity: 0.45; }
7511
+ }
7512
+
7513
+ @media (prefers-reduced-motion: reduce) {
7514
+ .kds-theme-root .kds-skeleton {
7515
+ animation: none;
7516
+ }
7517
+ }
7518
+
7519
+ /* Header de la factura mientras carga (KdsInvoiceHeaderSkeleton): mismo markup que el
7520
+ header real, con anchos fijos por slot. */
7521
+ .kds-theme-root .kds-invoice-skeleton .kds-invoice-amount .kds-skeleton--text { width: 7.5em; }
7522
+ .kds-theme-root .kds-invoice-skeleton .kds-invoice-code .kds-skeleton--text { width: 13em; }
7523
+ .kds-theme-root .kds-invoice-skeleton .kds-kv dt .kds-skeleton--text { width: 4.5em; }
7524
+ .kds-theme-root .kds-invoice-skeleton .kds-kv dd .kds-skeleton--text { width: 65%; }
7525
+
7227
7526
  /* Titulo del body de la card: alineado a la izquierda, sin importar que el consumidor
7228
7527
  traiga .kds-text-center. Va con especificidad de contexto (screen + card) a proposito:
7229
7528
  el centrado se venia pidiendo app por app y el resultado era inconsistente entre
@@ -7908,6 +8207,25 @@
7908
8207
  border-radius: var(--kds-radius-card);
7909
8208
  }
7910
8209
 
8210
+ /* Body card con acción (opt-in, KTUF-388): alto mínimo acotado para que el card no salte de
8211
+ alto entre pasos y la acción (submit) quede anclada al fondo con `.kds-mt-auto`. No cambia
8212
+ el default de arriba: lo pide cada app.
8213
+ - Valor fijo, sin vh/dvh: en un iframe (KTUF-239) el viewport es el propio iframe, cuyo
8214
+ alto lo da el RESIZE del contenido; un mínimo relativo al viewport se realimenta.
8215
+ - 21rem = alto del card de carga en desktop (loader 18rem + padding spacing-3 x2), así el
8216
+ paso loader -> formulario no cambia de alto. Ajustable con el token.
8217
+ - El contenido directo (form) crece para que la acción baje dentro de él y no compita
8218
+ con el `margin-top: auto` de .kds-card-version. */
8219
+ .kds-theme-root .kds-screen > .kds-card-elevated.kds-card-elevated--action {
8220
+ min-height: var(--kds-card-action-min-height, 21rem);
8221
+ }
8222
+
8223
+ .kds-theme-root .kds-card-elevated--action > form {
8224
+ flex-grow: 1;
8225
+ display: flex;
8226
+ flex-direction: column;
8227
+ }
8228
+
7911
8229
  /* Variante sin radio superior: pantallas de resultado (éxito/fallo/timeout) que van
7912
8230
  SIN header arriba — la body card va sola y su tope queda plano (flush) en vez de
7913
8231
  con esquinas redondeadas sueltas. El padding del card sigue manejando el inset. */
@@ -7924,13 +8242,20 @@
7924
8242
 
7925
8243
  /* Payment stage — full-viewport centered wrapper.
7926
8244
  Fondo muted (gris) para que las cards blancas (header + body) y el gap entre
7927
- ellas se distingan; sin esto, card blanca sobre fondo blanco se funden. */
8245
+ ellas se distingan; sin esto, card blanca sobre fondo blanco se funden.
8246
+
8247
+ --kds-color-background-body es el fondo de la pantalla, y es lo que un comercio
8248
+ cambia con su backgroundColor. Se resuelve aca, con muted como fallback, y no
8249
+ como alias en :root: un alias se evalua en :root y queda con el valor de :root,
8250
+ asi que la variable que el widget setea en body nunca llegaria a la etapa. Los
8251
+ otros usos de muted (tabs, bloque de codigo, hover del FAB) no se tocan: son
8252
+ superficies de componentes, no el fondo de la pantalla. */
7928
8253
  .kds-theme-root .kds-payment-stage {
7929
8254
  min-height: 100vh;
7930
8255
  display: flex;
7931
8256
  justify-content: center;
7932
8257
  padding: var(--kds-spacing-2-5) var(--kds-spacing-2) var(--kds-spacing-8);
7933
- background: var(--kds-color-background-muted);
8258
+ background: var(--kds-color-background-body, var(--kds-color-background-muted));
7934
8259
  }
7935
8260
 
7936
8261
  /* Payment flow — narrow column */
@@ -7999,6 +8324,18 @@
7999
8324
  @media (hover: hover) and (pointer: fine) {
8000
8325
  .kds-theme-root .kds-card-elevated.kds-invoice-sticky {
8001
8326
  border-radius: var(--kds-radius-card);
8327
+ /* El clip-path del colapso recorta con `round 0 0 R R` y eso PISA al
8328
+ border-radius: aunque la card declare las cuatro esquinas, el recorte las
8329
+ deja rectas arriba. Hay que redondearlas también acá o el fix no se ve. */
8330
+ clip-path: inset(
8331
+ 0 0
8332
+ calc(
8333
+ var(--collapse-collapsible-h) * var(--collapse-progress)
8334
+ + var(--kds-spacing-1) * var(--collapse-progress)
8335
+ )
8336
+ 0
8337
+ round var(--kds-radius-card)
8338
+ );
8002
8339
  }
8003
8340
 
8004
8341
  .kds-theme-root .kds-screen > .kds-card-elevated.kds-card-elevated--flush-top,
@@ -8337,8 +8674,11 @@
8337
8674
  background: var(--kds-color-action-hover);
8338
8675
  }
8339
8676
 
8340
- /* Search field reutilizable (standalone o dentro del KdsBankModal). */
8341
- .kds-theme-root .kds-search-field {
8677
+ /* Search field reutilizable (standalone o dentro del KdsBankModal).
8678
+ El selector de descendiente se mantiene por compatibilidad con los consumidores
8679
+ que renderizan el input sin clase (payment lo arma a mano en GSP). */
8680
+ .kds-theme-root .kds-search-field,
8681
+ .kds-theme-root .kds-bank-modal-search input {
8342
8682
  width: 100%;
8343
8683
  padding: var(--kds-spacing-1-25) var(--kds-spacing-1-5);
8344
8684
  border: 1px solid var(--kds-color-divider);
@@ -8350,11 +8690,13 @@
8350
8690
  background: var(--kds-color-surface);
8351
8691
  }
8352
8692
 
8353
- .kds-theme-root .kds-search-field::placeholder {
8693
+ .kds-theme-root .kds-search-field::placeholder,
8694
+ .kds-theme-root .kds-bank-modal-search input::placeholder {
8354
8695
  color: var(--kds-color-text-hint);
8355
8696
  }
8356
8697
 
8357
- .kds-theme-root .kds-search-field:focus {
8698
+ .kds-theme-root .kds-search-field:focus,
8699
+ .kds-theme-root .kds-bank-modal-search input:focus {
8358
8700
  border-color: var(--kds-color-primary-main);
8359
8701
  box-shadow: 0 0 0 2px var(--kds-color-primary-faint);
8360
8702
  }