@tatchi-xyz/sdk 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/cjs/core/EmailRecovery/index.js +25 -0
  2. package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
  3. package/dist/cjs/core/TatchiPasskey/emailRecovery.js +80 -60
  4. package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
  5. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  6. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  7. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  8. package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  9. package/dist/cjs/core/WebAuthnManager/index.js +23 -0
  10. package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
  11. package/dist/cjs/core/types/emailRecovery.js +33 -0
  12. package/dist/cjs/core/types/emailRecovery.js.map +1 -0
  13. package/dist/cjs/index.js +4 -0
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BCrFe5p3.css} +1 -1
  16. package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
  17. package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
  18. package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
  19. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
  20. package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
  21. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
  22. package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
  23. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
  24. package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
  25. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
  26. package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  27. package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
  28. package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
  29. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +25 -0
  30. package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  31. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +80 -60
  32. package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  33. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  34. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  35. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  36. package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  37. package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js +23 -0
  38. package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
  39. package/dist/cjs/react/sdk/src/core/types/emailRecovery.js +33 -0
  40. package/dist/cjs/react/sdk/src/core/types/emailRecovery.js.map +1 -0
  41. package/dist/esm/core/EmailRecovery/index.js +25 -1
  42. package/dist/esm/core/EmailRecovery/index.js.map +1 -1
  43. package/dist/esm/core/TatchiPasskey/emailRecovery.js +81 -61
  44. package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
  45. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  46. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  47. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  48. package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  49. package/dist/esm/core/WebAuthnManager/index.js +23 -0
  50. package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
  51. package/dist/esm/core/types/emailRecovery.js +26 -0
  52. package/dist/esm/core/types/emailRecovery.js.map +1 -0
  53. package/dist/esm/index.js +3 -1
  54. package/dist/esm/index.js.map +1 -1
  55. package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BCrFe5p3.css} +1 -1
  56. package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
  57. package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
  58. package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
  59. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
  60. package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
  61. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
  62. package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
  63. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
  64. package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
  65. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
  66. package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
  67. package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
  68. package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
  69. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +25 -1
  70. package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
  71. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +81 -61
  72. package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
  73. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
  74. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
  75. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
  76. package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
  77. package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js +23 -0
  78. package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
  79. package/dist/esm/react/sdk/src/core/types/emailRecovery.js +26 -0
  80. package/dist/esm/react/sdk/src/core/types/emailRecovery.js.map +1 -0
  81. package/dist/esm/sdk/{createAdapters-qVGD6i0g.js → createAdapters-DIRR8_Z9.js} +1 -1
  82. package/dist/esm/sdk/{createAdapters-BumKM2ft.js → createAdapters-Yga6W0en.js} +2 -2
  83. package/dist/esm/sdk/{createAdapters-BumKM2ft.js.map → createAdapters-Yga6W0en.js.map} +1 -1
  84. package/dist/esm/sdk/{localOnly-pXMTqh1m.js → localOnly-BHScJasw.js} +2 -2
  85. package/dist/esm/sdk/{localOnly-Byi3AK7A.js → localOnly-VevCI7H0.js} +3 -3
  86. package/dist/esm/sdk/{localOnly-Byi3AK7A.js.map → localOnly-VevCI7H0.js.map} +1 -1
  87. package/dist/esm/sdk/offline-export-app.js +29 -6
  88. package/dist/esm/sdk/offline-export-app.js.map +1 -1
  89. package/dist/esm/sdk/{registration-CBiS4Ua_.js → registration-bKEg9Zr2.js} +2 -2
  90. package/dist/esm/sdk/{registration-CBiS4Ua_.js.map → registration-bKEg9Zr2.js.map} +1 -1
  91. package/dist/esm/sdk/{registration-DLPLsGCz.js → registration-lDD60Ytt.js} +1 -1
  92. package/dist/esm/sdk/{transactions-Bk-VavcV.js → transactions-BalIhtJ9.js} +1 -1
  93. package/dist/esm/sdk/{transactions-BIqKZeR0.js → transactions-bqaAwL4k.js} +2 -2
  94. package/dist/esm/sdk/{transactions-BIqKZeR0.js.map → transactions-bqaAwL4k.js.map} +1 -1
  95. package/dist/esm/sdk/wallet-iframe-host.js +150 -65
  96. package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
  97. package/dist/types/src/core/EmailRecovery/index.d.ts +8 -0
  98. package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
  99. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +7 -2
  100. package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
  101. package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.d.ts.map +1 -1
  102. package/dist/types/src/core/WebAuthnManager/index.d.ts +7 -0
  103. package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
  104. package/dist/types/src/core/types/emailRecovery.d.ts +10 -0
  105. package/dist/types/src/core/types/emailRecovery.d.ts.map +1 -0
  106. package/dist/types/src/core/types/index.d.ts +1 -0
  107. package/dist/types/src/core/types/index.d.ts.map +1 -1
  108. package/dist/types/src/index.d.ts +1 -0
  109. package/dist/types/src/index.d.ts.map +1 -1
  110. package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
  111. package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
  112. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Web3AuthProfileButton-DopOg7Xc.css","names":[],"sources":["../../../../../src/react/components/AccountMenuButton/Web3AuthProfileButton.css"],"sourcesContent":["* {\n box-sizing: border-box;\n}\n\n.w3a-profile-button-morphable {\n position: relative;\n background-color: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n box-shadow: var(--w3a-shadows-sm);\n font-size: 14px;\n font-weight: 500;\n color: var(--w3a-colors-textPrimary);\n cursor: pointer;\n outline: none;\n overflow: visible;\n width: fit-content;\n transition: none;\n}\n\n.w3a-profile-button-morphable:hover {\n border-color: var(--w3a-colors-borderHover);\n}\n\n.w3a-profile-button-icon {\n flex-shrink: 0;\n}\n\n.w3a-profile-button-icon svg {\n overflow: visible;\n}\n\n.w3a-profile-button-username {\n white-space: nowrap;\n overflow: hidden;\n display: inline-block;\n}\n\n.w3a-profile-button-icon {\n color: var(--w3a-colors-textSecondary);\n}\n\n.w3a-profile-button-username {\n display: block; color: var(--w3a-colors-textSecondary);\n}\n\n.w3a-profile-button-username.hidden {\n display: none;\n}\n\n.w3a-user-account--toggle-content {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: space-between;\n transition: opacity 0.15s ease-in-out;\n}\n\n.w3a-user-account--toggle-text {\n flex: 1;\n}\n\n.w3a-user-account--toggle-title {\n font-weight: 500;\n color: var(--w3a-colors-textPrimary);\n font-size: 14px;\n margin: 0;\n}\n\n.w3a-user-account--toggle-description {\n font-size: 14px;\n color: var(--w3a-colors-textMuted);\n margin: 0;\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA"}
1
+ {"version":3,"file":"Web3AuthProfileButton-DXFRw8ND.css","names":[],"sources":["../../../../../src/react/components/AccountMenuButton/Web3AuthProfileButton.css"],"sourcesContent":["* {\n box-sizing: border-box;\n}\n\n.w3a-profile-button-morphable {\n position: relative;\n background-color: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n box-shadow: var(--w3a-shadows-sm);\n font-size: 14px;\n font-weight: 500;\n color: var(--w3a-colors-textPrimary);\n cursor: pointer;\n outline: none;\n overflow: visible;\n width: fit-content;\n transition: none;\n}\n\n.w3a-profile-button-morphable:hover {\n border-color: var(--w3a-colors-borderHover);\n}\n\n.w3a-profile-button-icon {\n flex-shrink: 0;\n}\n\n.w3a-profile-button-icon svg {\n overflow: visible;\n}\n\n.w3a-profile-button-username {\n white-space: nowrap;\n overflow: hidden;\n display: inline-block;\n}\n\n.w3a-profile-button-icon {\n color: var(--w3a-colors-textSecondary);\n}\n\n.w3a-profile-button-username {\n display: block; color: var(--w3a-colors-textSecondary);\n}\n\n.w3a-profile-button-username.hidden {\n display: none;\n}\n\n.w3a-user-account--toggle-content {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: space-between;\n transition: opacity 0.15s ease-in-out;\n}\n\n.w3a-user-account--toggle-text {\n flex: 1;\n}\n\n.w3a-user-account--toggle-title {\n font-weight: 500;\n color: var(--w3a-colors-textPrimary);\n font-size: 14px;\n margin: 0;\n}\n\n.w3a-user-account--toggle-description {\n font-size: 14px;\n color: var(--w3a-colors-textMuted);\n margin: 0;\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA"}
@@ -38,4 +38,4 @@
38
38
  }
39
39
 
40
40
 
41
- /*# sourceMappingURL=TouchIcon-BQWentvJ.css.map*/
41
+ /*# sourceMappingURL=TouchIcon-DNgbAK_i.css.map*/
@@ -1 +1 @@
1
- {"version":3,"file":"TouchIcon-BQWentvJ.css","names":[],"sources":["../../../../../../src/react/components/AccountMenuButton/icons/TouchIcon.css"],"sourcesContent":["/* TouchIcon specific styles and animations */\n\n.w3a-fingerprint-icon {\n transition: transform 400ms ease;\n}\n\n.w3a-fingerprint-icon path {\n /* Normalize path length so dash animations are simple */\n stroke: currentColor;\n}\n\n.w3a-fingerprint-icon.open path {\n /* Draw the fingerprint when expanding/opening */\n stroke-dasharray: 1;\n stroke-dashoffset: 1;\n animation: w3a-fp-open 1.6s ease-out 0.1s both;\n}\n\n/* Animate when closing the menu */\n.w3a-fingerprint-icon.closed path {\n stroke-dasharray: 1;\n stroke-dashoffset: 1;\n animation: w3a-fp-close 1.6s ease-out 0.1s both;\n}\n\n@keyframes w3a-fp-open {\n from { stroke-dashoffset: 1; }\n to { stroke-dashoffset: 0; }\n}\n\n@keyframes w3a-fp-close {\n from { stroke-dashoffset: 1; }\n to { stroke-dashoffset: 0; }\n}\n\n.w3a-fingerprint-icon:hover {\n transform: rotate(180deg) scale(1.2);\n}\n"],"mappings":"AAAA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
1
+ {"version":3,"file":"TouchIcon-DNgbAK_i.css","names":[],"sources":["../../../../../../src/react/components/AccountMenuButton/icons/TouchIcon.css"],"sourcesContent":["/* TouchIcon specific styles and animations */\n\n.w3a-fingerprint-icon {\n transition: transform 400ms ease;\n}\n\n.w3a-fingerprint-icon path {\n /* Normalize path length so dash animations are simple */\n stroke: currentColor;\n}\n\n.w3a-fingerprint-icon.open path {\n /* Draw the fingerprint when expanding/opening */\n stroke-dasharray: 1;\n stroke-dashoffset: 1;\n animation: w3a-fp-open 1.6s ease-out 0.1s both;\n}\n\n/* Animate when closing the menu */\n.w3a-fingerprint-icon.closed path {\n stroke-dasharray: 1;\n stroke-dashoffset: 1;\n animation: w3a-fp-close 1.6s ease-out 0.1s both;\n}\n\n@keyframes w3a-fp-open {\n from { stroke-dashoffset: 1; }\n to { stroke-dashoffset: 0; }\n}\n\n@keyframes w3a-fp-close {\n from { stroke-dashoffset: 1; }\n to { stroke-dashoffset: 0; }\n}\n\n.w3a-fingerprint-icon:hover {\n transform: rotate(180deg) scale(1.2);\n}\n"],"mappings":"AAAA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
@@ -951,4 +951,4 @@
951
951
  }
952
952
 
953
953
 
954
- /*# sourceMappingURL=PasskeyAuthMenu-DwrzWMYx.css.map*/
954
+ /*# sourceMappingURL=PasskeyAuthMenu-DRwSoF8q.css.map*/
@@ -1 +1 @@
1
- {"version":3,"file":"PasskeyAuthMenu-DwrzWMYx.css","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/PasskeyAuthMenu.css"],"sourcesContent":["/* Root container */\n.w3a-signup-menu-root {\n position: relative; /* relative position to anchor back button */\n width: min(100dvw, 420px);\n max-width: 100dvw;\n min-width: 330px;\n min-height: 250px;\n color: var(--w3a-colors-textPrimary);\n background: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 3rem;\n box-shadow: var(--w3a-shadows-lg);\n padding: var(--w3a-spacing-lg);\n padding-top: calc(var(--w3a-spacing-lg) + 4px);\n position: relative;\n display: flex;\n flex-direction: column;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), min-height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height, min-height;\n}\n\n/* Back button */\n.w3a-back-button {\n position: absolute;\n top: 1rem;\n left: 1rem;\n width: 48px;\n height: 48px;\n padding: 0;\n aspect-ratio: 1 / 1;\n display: grid;\n place-items: center;\n line-height: 0;\n border-radius: 50%;\n color: var(--w3a-colors-textPrimary);\n background: transparent;\n cursor: pointer;\n border: none;\n z-index: 3;\n transition: transform 120ms ease, background-color 160ms ease, opacity 220ms ease;\n opacity: 0;\n pointer-events: none;\n filter: blur(0.2px);\n}\n.w3a-back-button.is-visible {\n opacity: 1;\n pointer-events: auto;\n filter: none;\n}\n.w3a-back-button:hover {\n transform: scale(1.02);\n background: var(--w3a-colors-surface);\n}\n.w3a-back-button:active {\n transform: scale(0.96);\n}\n\n/* Header */\n.w3a-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n opacity: 1;\n height: auto;\n overflow: hidden;\n transition: opacity 240ms ease-out, height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), padding 260ms cubic-bezier(0.2, 0.8, 0.2, 1), margin 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n pointer-events: auto;\n position: relative;\n will-change: height, opacity;\n}\n\n/* Hide header when waiting or scan device is active */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-header,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Hide header when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Adjust content area when header is hidden */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-content-area,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Adjust content area when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Specific height adjustments for different states */\n.w3a-signup-menu-root[data-waiting=\"true\"] {\n min-height: 200px;\n}\n\n.w3a-signup-menu-root[data-scan-device=\"true\"] {\n min-height: 300px;\n}\n\n.w3a-signup-menu-root[data-email-recovery=\"true\"] {\n min-height: 320px;\n}\n\n.w3a-title {\n font-size: 24px;\n font-weight: 700;\n margin: 0.5rem 0.75rem;\n}\n\n.w3a-subhead {\n font-size: 1rem;\n font-weight: 500;\n line-height: 1;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0;\n margin-bottom: 1rem;\n margin-left: 0.75rem;\n}\n\n/* Content switcher container */\n.w3a-content-switcher {\n display: flex;\n flex-direction: column;\n overflow: hidden; /* ensure smooth height animations without spillover */\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height;\n}\n\n/* Content area container */\n.w3a-content-area {\n position: relative;\n /* do not force-stretch; let content define intrinsic height */\n flex: 0 1 auto;\n display: flex;\n flex-direction: column;\n animation: fade-in 240ms ease-out;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Intrinsic sizer wrapper inside content area used for height measurement */\n.w3a-content-sizer {\n display: block;\n width: 100%;\n}\n\n/* Default content */\n.w3a-signin-menu {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0px;\n min-height: 250px;\n width: 100%;\n animation: content-enter 240ms ease-in-out;\n}\n\n@keyframes content-enter {\n from {\n opacity: 0;\n transform: scale(0.98) translateY(6px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n@keyframes fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Social providers row */\n.w3a-social-row {\n display: flex;\n gap: 8px;\n margin-bottom: var(--w3a-spacing-sm);\n}\n.w3a-social-btn {\n height: 48px;\n flex: 1 1 0;\n min-width: 0;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--w3a-colors-textSecondary, #64748b);\n overflow: hidden;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n border-radius: var(--w3a-border-radius-xl);\n /* no shadow requested */\n box-shadow: none;\n}\n.w3a-social-btn svg {\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n.w3a-social-btn:hover {\n background: var(--w3a-colors-surface2);\n box-shadow: var(--w3a-shadows-sm);\n}\n.w3a-social-btn:hover svg {\n color: var(--w3a-colors-textPrimary, #1e293b);\n}\n\n/* Passkey row */\n.w3a-passkey-row {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.w3a-input-pill {\n position: relative;\n display: flex;\n flex: 1;\n align-items: center;\n padding: 0rem 1rem;\n height: 54px;\n gap: 8px;\n border: none;\n background: var(--w3a-colors-surface);\n border-radius: 2rem 2rem 2rem 2rem;\n box-shadow: none;\n overflow-x: hidden;\n transition: border-radius 150ms ease-in-out;\n}\n.w3a-input-pill.is-enabled {\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n transition: border-radius 150ms ease-in-out;\n}\n\n.w3a-input-wrap {\n position: relative;\n flex: 1;\n height: 32px;\n display: flex;\n align-items: center;\n min-width: 0; /* allow input to shrink inside flex container without clipping */\n}\n.w3a-input {\n width: 100%;\n height: 32px;\n border: none;\n outline: none;\n background: transparent;\n color: var(--w3a-colors-textPrimary);\n font-size: 16px;\n padding: 0;\n min-width: 0; /* prevent overflow clipping in flex layouts */\n}\n\n/* Absolute status message anchored to bottom-right of the input area */\n.w3a-input::placeholder {\n /* Improve contrast for placeholders on dark */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n opacity: 0.95;\n}\n\n.w3a-postfix {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n color: var(--w3a-colors-textSecondary);\n font-size: 16px;\n white-space: nowrap;\n pointer-events: none;\n visibility: hidden; /* React enables once measured */\n will-change: left;\n transition: left 32ms ease;\n}\n.w3a-postfix.is-existing {\n color: var(--w3a-colors-success);\n}\n/* On focus, keep postfix subtle for readability */\n.w3a-input:focus ~ .w3a-postfix {\n color: var(--w3a-colors-textMuted);\n}\n\n.w3a-arrow-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0; /* hidden footprint by default */\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n color: #fff;\n line-height: 0;\n cursor: pointer;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n margin-left: -1rem;\n z-index: 1;\n border: 6px solid var(--w3a-colors-colorBackground, #fff);\n height: 64px;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.is-enabled {\n width: 100px; /* expand when enabled */\n /* Prefer themed primary; fall back to legacy then a sane default */\n background: var(--w3a-colors-primary, #2563eb);\n border-radius: 2rem;\n /* border-radius: 2rem; */\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.no-transition,\n.w3a-arrow-btn.no-transition.is-enabled {\n transition: none;\n}\n.w3a-arrow-btn .w3a-arrow-icon {\n color: #fff;\n}\n.w3a-arrow-btn.is-enabled:hover {\n /* transform: scale(1.02); */\n background: var(--w3a-colors-primaryHover, #1d4ed8);\n}\n.w3a-arrow-btn.is-enabled:active {\n transform: scale(0.96);\n}\n.w3a-arrow-btn:disabled {\n width: 0;\n cursor: not-allowed;\n opacity: 0.5;\n background: var(--w3a-colors-borderSecondary);\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn .w3a-arrow-label {\n margin-left: 8px;\n font-weight: 600;\n line-height: 1;\n}\n\n/* Animated arrow inside the continue button */\n.w3a-arrow-btn .stripe-arrow {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.w3a-arrow-btn .stripe-arrow > .HoverArrow {\n position: relative;\n margin-top: 0.1rem;\n margin-left: 8px;\n stroke-width: 2;\n fill: none;\n stroke: currentColor;\n}\n\n/* Horizontal line: fades in on hover of the button */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 0;\n transition: opacity 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n/* Chevron: nudges right and slightly scales on hover */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transition: transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__linePath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 1;\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__tipPath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transform: translateX(3px);\n}\n\n/* Segmented control */\n.w3a-seg {\n position: relative;\n min-height: 54px;\n overflow: hidden;\n padding: 5px;\n border: none;\n background: var(--w3a-colors-surface2);\n border-radius: var(--w3a-border-radius-xl);\n}\n.w3a-seg-active {\n position: absolute;\n top: 5px;\n bottom: 5px;\n left: 0;\n border-radius: var(--w3a-border-radius-xl);\n transition:\n transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1),\n width 220ms ease,\n opacity 150ms ease;\n will-change: transform, width;\n pointer-events: none;\n}\n.w3a-seg-grid {\n display: flex;\n gap: 4px;\n height: 100%;\n position: relative;\n z-index: 1;\n}\n.w3a-seg-btn {\n flex: 1 1 0;\n min-width: 0;\n min-height: 44px;\n border-radius: 12px;\n background: transparent;\n /* Make inactive tabs more legible and clearly tappable */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 45%);\n font-weight: 600;\n cursor: pointer;\n border: none;\n /* Immediate taps on mobile; opt-out of double-tap zoom heuristics */\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n transition: color 200ms ease, transform 120ms ease;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n white-space: normal;\n padding: 0 14px;\n font-size: clamp(13px, 3.6vw, 15px);\n}\n.w3a-seg-btn:hover {\n transform: scale(1.02);\n}\n.w3a-seg-btn:active {\n transform: scale(0.98);\n}\n.w3a-seg-btn.is-active {\n color: var(--w3a-colors-textPrimary);\n}\n.w3a-seg-btn:focus-visible {\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--w3a-colors-focus), transparent 60%);\n}\n\n@media (max-width: 420px) {\n .w3a-signup-menu-root {\n padding: 1rem;\n padding-top: calc(1rem + 4px);\n border-radius: 2rem;\n max-width: calc(100dvw - 0.25rem);\n }\n\n @supports (width: 1dvw) {\n .w3a-signup-menu-root { max-width: calc(100dvw - 0.25rem); }\n }\n\n .w3a-title {\n font-size: 20px;\n }\n\n .w3a-subhead {\n font-size: 0.9rem;\n margin-bottom: 0.75rem;\n }\n\n .w3a-input-pill {\n height: 48px;\n }\n\n .w3a-arrow-btn {\n height: 60px;\n }\n\n .w3a-arrow-btn.is-enabled {\n width: 60px;\n }\n\n .w3a-seg {\n min-height: 48px;\n padding: 4px;\n }\n\n .w3a-seg-grid {\n gap: 3px;\n }\n\n .w3a-seg-active {\n top: 4px;\n bottom: 4px;\n }\n\n .w3a-seg-btn {\n min-height: 42px;\n padding: 0 12px;\n font-size: clamp(12px, 3.4vw, 14px);\n }\n\n .w3a-back-button {\n top: -0.5rem;\n left: -0.5rem;\n }\n}\n\n/* Waiting state */\n.w3a-waiting {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 200px;\n /* Quick fade with configurable delay for smoother handoff */\n animation: content-enter 200ms ease-out;\n animation-delay: var(--w3a-waiting-delay, 0ms);\n animation-fill-mode: both;\n}\n.w3a-waiting-text { font-size: 18px; font-weight: 600; }\n.w3a-spinner {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 3px solid rgba(255,255,255,0.15);\n border-top-color: var(--w3a-colors-primary);\n animation: w3a-spin 0.9s linear infinite;\n}\n\n/* Scan device content wrapper */\n.w3a-scan-device-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 300px;\n width: 100%;\n overflow: hidden;\n animation: content-enter 240ms ease-out;\n}\n\n/* Ensure QR code content stays within bounds */\n.w3a-scan-device-content .qr-code-container,\n.w3a-scan-device-content .qr-modal-backdrop,\n.w3a-scan-device-content .qr-modal-content {\n max-width: 100%;\n max-height: 100%;\n overflow: hidden;\n}\n\n.w3a-scan-device-content .qr-code-display {\n max-width: 280px;\n width: 100%;\n}\n\n/* Status message row */\n.w3a-status-row {\n position: absolute;\n font-size: 0.75rem;\n bottom: -10px;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n}\n.w3a-status-message {\n font-size: 11px;\n font-weight: 500;\n}\n\n/* Section divider */\n.w3a-section-divider {\n display: flex;\n align-items: center;\n margin: var(--w3a-spacing-md) 0;\n position: relative;\n}\n\n.w3a-section-divider::before,\n.w3a-section-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--w3a-colors-borderSecondary);\n}\n\n.w3a-section-divider-text {\n padding: 0 var(--w3a-spacing-sm);\n font-size: 12px;\n color: var(--w3a-colors-textSecondary);\n font-weight: 500;\n background: var(--w3a-colors-colorBackground);\n}\n\n/* Labels and helper text */\n.w3a-field-label {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n margin: 6px 2px 6px;\n font-weight: 600;\n}\n.w3a-seg-help {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 25%);\n margin: 0;\n margin-left: 0.75rem;\n}\n.w3a-seg-help-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 8px;\n}\n/* Tooltip for account existence status */\n.w3a-input-wrap .w3a-tooltip {\n position: absolute;\n right: 0;\n padding: 4px 8px;\n border-radius: 1rem;\n font-size: 0.7rem;\n background: var(--w3a-colors-surface2);\n color: var(--w3a-colors-textPrimary);\n opacity: 0;\n transform: translateX(50px) scale(0.9);\n pointer-events: none;\n transition: opacity 180ms ease, transform 200ms ease;\n z-index: 2;\n}\n.w3a-input-wrap .w3a-tooltip.is-visible {\n opacity: 0.8;\n transform: translateX(0px) scale(1);\n}\n.w3a-input-wrap .w3a-tooltip.is-error {\n color: var(--w3a-colors-error);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-error), transparent 90%); */\n}\n.w3a-input-wrap .w3a-tooltip.is-success {\n color: var(--w3a-colors-blue400);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-blue400), transparent 90%); */\n}\n\n@keyframes w3a-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Pop/bounce-in animation (kept for legacy classes) */\n@keyframes w3a-input-msg-pop {\n 0% { opacity: 0; transform: translateY(8px) scale(0.98); }\n 60% { opacity: 1; transform: translateY(-2px) scale(1.02); }\n 100% { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .w3a-input-msg.is-error { animation: none; }\n}\n\n/* Button System */\n.w3a-scan-device-row {\n}\n\n.w3a-secondary-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.w3a-link-device-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n overflow: hidden;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n height: 48px;\n width: 100%;\n max-width: 100%;\n background: var(--w3a-colors-surface) !important;\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n cursor: pointer;\n color: var(--w3a-colors-textPrimary);\n font-family: var(--w3a-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n font-weight: 500;\n font-size: 0.875rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Hover/focus elevated state (theme-reactive via CSS vars) */\n.w3a-link-device-btn:hover:not(:disabled),\n.w3a-link-device-btn:focus-visible {\n background: var(--w3a-colors-surface2) !important;\n}\n\n.w3a-link-device-btn-primary {\n background: var(--w3a-colors-buttonBackground, var(--w3a-colors-primary, #3b82f6)) !important;\n border-color: transparent;\n border-radius: 2rem;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:hover:not(:disabled),\n.w3a-link-device-btn-primary:focus-visible {\n background: var(--w3a-colors-buttonHoverBackground, var(--w3a-colors-primaryHover, #2563eb)) !important;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Button-local spinner: match text size inside buttons */\n.w3a-link-device-btn .w3a-spinner {\n width: 1em;\n height: 1em;\n border-width: 2px;\n}\n\n.w3a-link-device-btn-primary .w3a-spinner {\n border-color: rgba(255, 255, 255, 0.35);\n border-top-color: #ffffff;\n}\n\n/* Email recovery slide */\n.w3a-email-recovery-content {\n width: 100%;\n padding-top: 1rem;\n}\n\n.w3a-email-recovery-slide {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 260px;\n animation: content-enter 240ms ease-out;\n}\n\n.w3a-email-recovery-title {\n font-size: 20px;\n font-weight: 700;\n margin: 0.5rem 0.5rem;\n display: flex;\n justify-content: center;\n}\n\n.w3a-email-recovery-help {\n font-size: 0.95rem;\n line-height: 1.2;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0 0.25rem;\n}\n\n.w3a-email-recovery-meta {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n padding: 0 0.25rem;\n font-size: 0.85rem;\n}\n\n.w3a-email-recovery-meta-label {\n opacity: 0.85;\n}\n\n.w3a-email-recovery-meta-value {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 0.85rem;\n opacity: 0.9;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 70%;\n text-align: right;\n}\n\n.w3a-email-recovery-input-pill {\n height: 54px;\n padding: 0 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n transition: box-shadow 160ms ease, border-color 160ms ease;\n}\n\n.w3a-email-recovery-input-pill:focus-within {\n border-color: var(--w3a-colors-primary, #3b82f6);\n}\n\n.w3a-email-recovery-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n.w3a-email-recovery-summary {\n font-size: 0.875rem;\n line-height: 1.2;\n padding: 0 0.25rem;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.w3a-email-recovery-warning {\n color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-textPrimary) 30%);\n}\n\n.w3a-email-recovery-link {\n font-size: 0.875rem;\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n padding: 0 0.25rem;\n}\n\n.w3a-email-recovery-link:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-status {\n font-size: 0.875rem;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n margin-bottom: 0.5rem;\n}\n\n.w3a-email-recovery-status.is-error {\n border-color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-borderPrimary) 60%);\n color: var(--w3a-colors-error);\n}\n\n.w3a-email-recovery-elapsed {\n margin-left: 6px;\n opacity: 0.75;\n}\n\n.w3a-email-recovery-saved-emails {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.w3a-email-recovery-email-chip {\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n padding: 6px 10px;\n border-radius: 999px;\n font-size: 0.85rem;\n cursor: pointer;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.w3a-email-recovery-email-chip:hover:not(:disabled) {\n background: var(--w3a-colors-surface2);\n}\n\n.w3a-email-recovery-email-chip:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.w3a-email-recovery-toast {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n font-size: 0.875rem;\n color: var(--w3a-colors-textPrimary);\n}\n\n.w3a-email-recovery-toast a {\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n}\n\n.w3a-email-recovery-toast a:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-toast-close {\n margin-left: auto;\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: none;\n background: transparent;\n color: var(--w3a-colors-textSecondary);\n cursor: pointer;\n display: grid;\n place-items: center;\n}\n\n.w3a-email-recovery-toast-close:hover {\n background: var(--w3a-colors-surface2);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
1
+ {"version":3,"file":"PasskeyAuthMenu-DRwSoF8q.css","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/PasskeyAuthMenu.css"],"sourcesContent":["/* Root container */\n.w3a-signup-menu-root {\n position: relative; /* relative position to anchor back button */\n width: min(100dvw, 420px);\n max-width: 100dvw;\n min-width: 330px;\n min-height: 250px;\n color: var(--w3a-colors-textPrimary);\n background: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 3rem;\n box-shadow: var(--w3a-shadows-lg);\n padding: var(--w3a-spacing-lg);\n padding-top: calc(var(--w3a-spacing-lg) + 4px);\n position: relative;\n display: flex;\n flex-direction: column;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), min-height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height, min-height;\n}\n\n/* Back button */\n.w3a-back-button {\n position: absolute;\n top: 1rem;\n left: 1rem;\n width: 48px;\n height: 48px;\n padding: 0;\n aspect-ratio: 1 / 1;\n display: grid;\n place-items: center;\n line-height: 0;\n border-radius: 50%;\n color: var(--w3a-colors-textPrimary);\n background: transparent;\n cursor: pointer;\n border: none;\n z-index: 3;\n transition: transform 120ms ease, background-color 160ms ease, opacity 220ms ease;\n opacity: 0;\n pointer-events: none;\n filter: blur(0.2px);\n}\n.w3a-back-button.is-visible {\n opacity: 1;\n pointer-events: auto;\n filter: none;\n}\n.w3a-back-button:hover {\n transform: scale(1.02);\n background: var(--w3a-colors-surface);\n}\n.w3a-back-button:active {\n transform: scale(0.96);\n}\n\n/* Header */\n.w3a-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n opacity: 1;\n height: auto;\n overflow: hidden;\n transition: opacity 240ms ease-out, height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), padding 260ms cubic-bezier(0.2, 0.8, 0.2, 1), margin 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n pointer-events: auto;\n position: relative;\n will-change: height, opacity;\n}\n\n/* Hide header when waiting or scan device is active */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-header,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Hide header when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Adjust content area when header is hidden */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-content-area,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Adjust content area when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Specific height adjustments for different states */\n.w3a-signup-menu-root[data-waiting=\"true\"] {\n min-height: 200px;\n}\n\n.w3a-signup-menu-root[data-scan-device=\"true\"] {\n min-height: 300px;\n}\n\n.w3a-signup-menu-root[data-email-recovery=\"true\"] {\n min-height: 320px;\n}\n\n.w3a-title {\n font-size: 24px;\n font-weight: 700;\n margin: 0.5rem 0.75rem;\n}\n\n.w3a-subhead {\n font-size: 1rem;\n font-weight: 500;\n line-height: 1;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0;\n margin-bottom: 1rem;\n margin-left: 0.75rem;\n}\n\n/* Content switcher container */\n.w3a-content-switcher {\n display: flex;\n flex-direction: column;\n overflow: hidden; /* ensure smooth height animations without spillover */\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height;\n}\n\n/* Content area container */\n.w3a-content-area {\n position: relative;\n /* do not force-stretch; let content define intrinsic height */\n flex: 0 1 auto;\n display: flex;\n flex-direction: column;\n animation: fade-in 240ms ease-out;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Intrinsic sizer wrapper inside content area used for height measurement */\n.w3a-content-sizer {\n display: block;\n width: 100%;\n}\n\n/* Default content */\n.w3a-signin-menu {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0px;\n min-height: 250px;\n width: 100%;\n animation: content-enter 240ms ease-in-out;\n}\n\n@keyframes content-enter {\n from {\n opacity: 0;\n transform: scale(0.98) translateY(6px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n@keyframes fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Social providers row */\n.w3a-social-row {\n display: flex;\n gap: 8px;\n margin-bottom: var(--w3a-spacing-sm);\n}\n.w3a-social-btn {\n height: 48px;\n flex: 1 1 0;\n min-width: 0;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--w3a-colors-textSecondary, #64748b);\n overflow: hidden;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n border-radius: var(--w3a-border-radius-xl);\n /* no shadow requested */\n box-shadow: none;\n}\n.w3a-social-btn svg {\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n.w3a-social-btn:hover {\n background: var(--w3a-colors-surface2);\n box-shadow: var(--w3a-shadows-sm);\n}\n.w3a-social-btn:hover svg {\n color: var(--w3a-colors-textPrimary, #1e293b);\n}\n\n/* Passkey row */\n.w3a-passkey-row {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.w3a-input-pill {\n position: relative;\n display: flex;\n flex: 1;\n align-items: center;\n padding: 0rem 1rem;\n height: 54px;\n gap: 8px;\n border: none;\n background: var(--w3a-colors-surface);\n border-radius: 2rem 2rem 2rem 2rem;\n box-shadow: none;\n overflow-x: hidden;\n transition: border-radius 150ms ease-in-out;\n}\n.w3a-input-pill.is-enabled {\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n transition: border-radius 150ms ease-in-out;\n}\n\n.w3a-input-wrap {\n position: relative;\n flex: 1;\n height: 32px;\n display: flex;\n align-items: center;\n min-width: 0; /* allow input to shrink inside flex container without clipping */\n}\n.w3a-input {\n width: 100%;\n height: 32px;\n border: none;\n outline: none;\n background: transparent;\n color: var(--w3a-colors-textPrimary);\n font-size: 16px;\n padding: 0;\n min-width: 0; /* prevent overflow clipping in flex layouts */\n}\n\n/* Absolute status message anchored to bottom-right of the input area */\n.w3a-input::placeholder {\n /* Improve contrast for placeholders on dark */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n opacity: 0.95;\n}\n\n.w3a-postfix {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n color: var(--w3a-colors-textSecondary);\n font-size: 16px;\n white-space: nowrap;\n pointer-events: none;\n visibility: hidden; /* React enables once measured */\n will-change: left;\n transition: left 32ms ease;\n}\n.w3a-postfix.is-existing {\n color: var(--w3a-colors-success);\n}\n/* On focus, keep postfix subtle for readability */\n.w3a-input:focus ~ .w3a-postfix {\n color: var(--w3a-colors-textMuted);\n}\n\n.w3a-arrow-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0; /* hidden footprint by default */\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n color: #fff;\n line-height: 0;\n cursor: pointer;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n margin-left: -1rem;\n z-index: 1;\n border: 6px solid var(--w3a-colors-colorBackground, #fff);\n height: 64px;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.is-enabled {\n width: 100px; /* expand when enabled */\n /* Prefer themed primary; fall back to legacy then a sane default */\n background: var(--w3a-colors-primary, #2563eb);\n border-radius: 2rem;\n /* border-radius: 2rem; */\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.no-transition,\n.w3a-arrow-btn.no-transition.is-enabled {\n transition: none;\n}\n.w3a-arrow-btn .w3a-arrow-icon {\n color: #fff;\n}\n.w3a-arrow-btn.is-enabled:hover {\n /* transform: scale(1.02); */\n background: var(--w3a-colors-primaryHover, #1d4ed8);\n}\n.w3a-arrow-btn.is-enabled:active {\n transform: scale(0.96);\n}\n.w3a-arrow-btn:disabled {\n width: 0;\n cursor: not-allowed;\n opacity: 0.5;\n background: var(--w3a-colors-borderSecondary);\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn .w3a-arrow-label {\n margin-left: 8px;\n font-weight: 600;\n line-height: 1;\n}\n\n/* Animated arrow inside the continue button */\n.w3a-arrow-btn .stripe-arrow {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.w3a-arrow-btn .stripe-arrow > .HoverArrow {\n position: relative;\n margin-top: 0.1rem;\n margin-left: 8px;\n stroke-width: 2;\n fill: none;\n stroke: currentColor;\n}\n\n/* Horizontal line: fades in on hover of the button */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 0;\n transition: opacity 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n/* Chevron: nudges right and slightly scales on hover */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transition: transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__linePath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 1;\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__tipPath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transform: translateX(3px);\n}\n\n/* Segmented control */\n.w3a-seg {\n position: relative;\n min-height: 54px;\n overflow: hidden;\n padding: 5px;\n border: none;\n background: var(--w3a-colors-surface2);\n border-radius: var(--w3a-border-radius-xl);\n}\n.w3a-seg-active {\n position: absolute;\n top: 5px;\n bottom: 5px;\n left: 0;\n border-radius: var(--w3a-border-radius-xl);\n transition:\n transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1),\n width 220ms ease,\n opacity 150ms ease;\n will-change: transform, width;\n pointer-events: none;\n}\n.w3a-seg-grid {\n display: flex;\n gap: 4px;\n height: 100%;\n position: relative;\n z-index: 1;\n}\n.w3a-seg-btn {\n flex: 1 1 0;\n min-width: 0;\n min-height: 44px;\n border-radius: 12px;\n background: transparent;\n /* Make inactive tabs more legible and clearly tappable */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 45%);\n font-weight: 600;\n cursor: pointer;\n border: none;\n /* Immediate taps on mobile; opt-out of double-tap zoom heuristics */\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n transition: color 200ms ease, transform 120ms ease;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n white-space: normal;\n padding: 0 14px;\n font-size: clamp(13px, 3.6vw, 15px);\n}\n.w3a-seg-btn:hover {\n transform: scale(1.02);\n}\n.w3a-seg-btn:active {\n transform: scale(0.98);\n}\n.w3a-seg-btn.is-active {\n color: var(--w3a-colors-textPrimary);\n}\n.w3a-seg-btn:focus-visible {\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--w3a-colors-focus), transparent 60%);\n}\n\n@media (max-width: 420px) {\n .w3a-signup-menu-root {\n padding: 1rem;\n padding-top: calc(1rem + 4px);\n border-radius: 2rem;\n max-width: calc(100dvw - 0.25rem);\n }\n\n @supports (width: 1dvw) {\n .w3a-signup-menu-root { max-width: calc(100dvw - 0.25rem); }\n }\n\n .w3a-title {\n font-size: 20px;\n }\n\n .w3a-subhead {\n font-size: 0.9rem;\n margin-bottom: 0.75rem;\n }\n\n .w3a-input-pill {\n height: 48px;\n }\n\n .w3a-arrow-btn {\n height: 60px;\n }\n\n .w3a-arrow-btn.is-enabled {\n width: 60px;\n }\n\n .w3a-seg {\n min-height: 48px;\n padding: 4px;\n }\n\n .w3a-seg-grid {\n gap: 3px;\n }\n\n .w3a-seg-active {\n top: 4px;\n bottom: 4px;\n }\n\n .w3a-seg-btn {\n min-height: 42px;\n padding: 0 12px;\n font-size: clamp(12px, 3.4vw, 14px);\n }\n\n .w3a-back-button {\n top: -0.5rem;\n left: -0.5rem;\n }\n}\n\n/* Waiting state */\n.w3a-waiting {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 200px;\n /* Quick fade with configurable delay for smoother handoff */\n animation: content-enter 200ms ease-out;\n animation-delay: var(--w3a-waiting-delay, 0ms);\n animation-fill-mode: both;\n}\n.w3a-waiting-text { font-size: 18px; font-weight: 600; }\n.w3a-spinner {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 3px solid rgba(255,255,255,0.15);\n border-top-color: var(--w3a-colors-primary);\n animation: w3a-spin 0.9s linear infinite;\n}\n\n/* Scan device content wrapper */\n.w3a-scan-device-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 300px;\n width: 100%;\n overflow: hidden;\n animation: content-enter 240ms ease-out;\n}\n\n/* Ensure QR code content stays within bounds */\n.w3a-scan-device-content .qr-code-container,\n.w3a-scan-device-content .qr-modal-backdrop,\n.w3a-scan-device-content .qr-modal-content {\n max-width: 100%;\n max-height: 100%;\n overflow: hidden;\n}\n\n.w3a-scan-device-content .qr-code-display {\n max-width: 280px;\n width: 100%;\n}\n\n/* Status message row */\n.w3a-status-row {\n position: absolute;\n font-size: 0.75rem;\n bottom: -10px;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n}\n.w3a-status-message {\n font-size: 11px;\n font-weight: 500;\n}\n\n/* Section divider */\n.w3a-section-divider {\n display: flex;\n align-items: center;\n margin: var(--w3a-spacing-md) 0;\n position: relative;\n}\n\n.w3a-section-divider::before,\n.w3a-section-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--w3a-colors-borderSecondary);\n}\n\n.w3a-section-divider-text {\n padding: 0 var(--w3a-spacing-sm);\n font-size: 12px;\n color: var(--w3a-colors-textSecondary);\n font-weight: 500;\n background: var(--w3a-colors-colorBackground);\n}\n\n/* Labels and helper text */\n.w3a-field-label {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n margin: 6px 2px 6px;\n font-weight: 600;\n}\n.w3a-seg-help {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 25%);\n margin: 0;\n margin-left: 0.75rem;\n}\n.w3a-seg-help-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 8px;\n}\n/* Tooltip for account existence status */\n.w3a-input-wrap .w3a-tooltip {\n position: absolute;\n right: 0;\n padding: 4px 8px;\n border-radius: 1rem;\n font-size: 0.7rem;\n background: var(--w3a-colors-surface2);\n color: var(--w3a-colors-textPrimary);\n opacity: 0;\n transform: translateX(50px) scale(0.9);\n pointer-events: none;\n transition: opacity 180ms ease, transform 200ms ease;\n z-index: 2;\n}\n.w3a-input-wrap .w3a-tooltip.is-visible {\n opacity: 0.8;\n transform: translateX(0px) scale(1);\n}\n.w3a-input-wrap .w3a-tooltip.is-error {\n color: var(--w3a-colors-error);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-error), transparent 90%); */\n}\n.w3a-input-wrap .w3a-tooltip.is-success {\n color: var(--w3a-colors-blue400);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-blue400), transparent 90%); */\n}\n\n@keyframes w3a-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Pop/bounce-in animation (kept for legacy classes) */\n@keyframes w3a-input-msg-pop {\n 0% { opacity: 0; transform: translateY(8px) scale(0.98); }\n 60% { opacity: 1; transform: translateY(-2px) scale(1.02); }\n 100% { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .w3a-input-msg.is-error { animation: none; }\n}\n\n/* Button System */\n.w3a-scan-device-row {\n}\n\n.w3a-secondary-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.w3a-link-device-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n overflow: hidden;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n height: 48px;\n width: 100%;\n max-width: 100%;\n background: var(--w3a-colors-surface) !important;\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n cursor: pointer;\n color: var(--w3a-colors-textPrimary);\n font-family: var(--w3a-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n font-weight: 500;\n font-size: 0.875rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Hover/focus elevated state (theme-reactive via CSS vars) */\n.w3a-link-device-btn:hover:not(:disabled),\n.w3a-link-device-btn:focus-visible {\n background: var(--w3a-colors-surface2) !important;\n}\n\n.w3a-link-device-btn-primary {\n background: var(--w3a-colors-buttonBackground, var(--w3a-colors-primary, #3b82f6)) !important;\n border-color: transparent;\n border-radius: 2rem;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:hover:not(:disabled),\n.w3a-link-device-btn-primary:focus-visible {\n background: var(--w3a-colors-buttonHoverBackground, var(--w3a-colors-primaryHover, #2563eb)) !important;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Button-local spinner: match text size inside buttons */\n.w3a-link-device-btn .w3a-spinner {\n width: 1em;\n height: 1em;\n border-width: 2px;\n}\n\n.w3a-link-device-btn-primary .w3a-spinner {\n border-color: rgba(255, 255, 255, 0.35);\n border-top-color: #ffffff;\n}\n\n/* Email recovery slide */\n.w3a-email-recovery-content {\n width: 100%;\n padding-top: 1rem;\n}\n\n.w3a-email-recovery-slide {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 260px;\n animation: content-enter 240ms ease-out;\n}\n\n.w3a-email-recovery-title {\n font-size: 20px;\n font-weight: 700;\n margin: 0.5rem 0.5rem;\n display: flex;\n justify-content: center;\n}\n\n.w3a-email-recovery-help {\n font-size: 0.95rem;\n line-height: 1.2;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0 0.25rem;\n}\n\n.w3a-email-recovery-meta {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n padding: 0 0.25rem;\n font-size: 0.85rem;\n}\n\n.w3a-email-recovery-meta-label {\n opacity: 0.85;\n}\n\n.w3a-email-recovery-meta-value {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 0.85rem;\n opacity: 0.9;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 70%;\n text-align: right;\n}\n\n.w3a-email-recovery-input-pill {\n height: 54px;\n padding: 0 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n transition: box-shadow 160ms ease, border-color 160ms ease;\n}\n\n.w3a-email-recovery-input-pill:focus-within {\n border-color: var(--w3a-colors-primary, #3b82f6);\n}\n\n.w3a-email-recovery-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n.w3a-email-recovery-summary {\n font-size: 0.875rem;\n line-height: 1.2;\n padding: 0 0.25rem;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.w3a-email-recovery-warning {\n color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-textPrimary) 30%);\n}\n\n.w3a-email-recovery-link {\n font-size: 0.875rem;\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n padding: 0 0.25rem;\n}\n\n.w3a-email-recovery-link:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-status {\n font-size: 0.875rem;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n margin-bottom: 0.5rem;\n}\n\n.w3a-email-recovery-status.is-error {\n border-color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-borderPrimary) 60%);\n color: var(--w3a-colors-error);\n}\n\n.w3a-email-recovery-elapsed {\n margin-left: 6px;\n opacity: 0.75;\n}\n\n.w3a-email-recovery-saved-emails {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.w3a-email-recovery-email-chip {\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n padding: 6px 10px;\n border-radius: 999px;\n font-size: 0.85rem;\n cursor: pointer;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.w3a-email-recovery-email-chip:hover:not(:disabled) {\n background: var(--w3a-colors-surface2);\n}\n\n.w3a-email-recovery-email-chip:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.w3a-email-recovery-toast {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n font-size: 0.875rem;\n color: var(--w3a-colors-textPrimary);\n}\n\n.w3a-email-recovery-toast a {\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n}\n\n.w3a-email-recovery-toast a:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-toast-close {\n margin-left: auto;\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: none;\n background: transparent;\n color: var(--w3a-colors-textSecondary);\n cursor: pointer;\n display: grid;\n place-items: center;\n}\n\n.w3a-email-recovery-toast-close:hover {\n background: var(--w3a-colors-surface2);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
@@ -1,11 +1,36 @@
1
1
  import { init_accountIds, toAccountId } from "../../../sdk/src/core/types/accountIds.js";
2
2
  import { IndexedDBManager, init_IndexedDBManager } from "../../../sdk/src/core/IndexedDBManager/index.js";
3
+ import { EmailRecoveryErrorCode, init_emailRecovery } from "../../../sdk/src/core/types/emailRecovery.js";
3
4
  import React from "react";
4
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
6
 
6
7
  //#region src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx
7
8
  init_IndexedDBManager();
8
9
  init_accountIds();
10
+ init_emailRecovery();
11
+ function getEmailRecoveryErrorCode(err) {
12
+ const code = err?.code;
13
+ if (typeof code !== "string") return null;
14
+ return Object.values(EmailRecoveryErrorCode).includes(code) ? code : null;
15
+ }
16
+ function getEmailRecoveryUiError(err) {
17
+ const fallback = err instanceof Error ? err.message : String(err || "");
18
+ const code = getEmailRecoveryErrorCode(err);
19
+ switch (code) {
20
+ case EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED: return {
21
+ message: fallback || "Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again.",
22
+ canRestart: true
23
+ };
24
+ case EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED: return {
25
+ message: fallback || "Registration did not verify on-chain. Please restart email recovery and try again.",
26
+ canRestart: true
27
+ };
28
+ default: return {
29
+ message: fallback || "Email recovery failed",
30
+ canRestart: false
31
+ };
32
+ }
33
+ }
9
34
  const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {
10
35
  const mountedRef = React.useRef(true);
11
36
  const mailtoAttemptTimerRef = React.useRef(null);
@@ -24,10 +49,12 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
24
49
  const [accountIdInput, setAccountIdInput] = React.useState("");
25
50
  const [recoveryEmailInput, setRecoveryEmailInput] = React.useState("");
26
51
  const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState(null);
52
+ const [pendingNearPublicKey, setPendingNearPublicKey] = React.useState(null);
27
53
  const [mailtoUiState, setMailtoUiState] = React.useState("ready");
28
54
  const [statusText, setStatusText] = React.useState(null);
29
55
  const [pollingElapsedMs, setPollingElapsedMs] = React.useState(null);
30
56
  const [errorText, setErrorText] = React.useState(null);
57
+ const [canRestart, setCanRestart] = React.useState(false);
31
58
  const [accountInfo, setAccountInfo] = React.useState(null);
32
59
  const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);
33
60
  const [accountInfoError, setAccountInfoError] = React.useState(null);
@@ -45,11 +72,13 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
45
72
  }, [accountId]);
46
73
  React.useEffect(() => {
47
74
  setPendingMailtoUrl(null);
75
+ setPendingNearPublicKey(null);
48
76
  setMailtoUiState("ready");
49
77
  cancelRequestedRef.current = false;
50
78
  setStatusText(null);
51
79
  setPollingElapsedMs(null);
52
80
  setErrorText(null);
81
+ setCanRestart(false);
53
82
  setAccountInfo(null);
54
83
  setAccountInfoError(null);
55
84
  setLocalRecoveryEmails([]);
@@ -66,10 +95,12 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
66
95
  };
67
96
  };
68
97
  const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);
98
+ const safeSetPendingNearPublicKey = React.useMemo(() => safeSet(setPendingNearPublicKey), []);
69
99
  const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);
70
100
  const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);
71
101
  const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);
72
102
  const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);
103
+ const safeSetCanRestart = React.useMemo(() => safeSet(setCanRestart), []);
73
104
  const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);
74
105
  const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);
75
106
  const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);
@@ -98,9 +129,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
98
129
  if (ev?.phase === "email-recovery-error" || ev?.status === "error") {
99
130
  const raw = ev?.error || ev?.message || "Email recovery failed";
100
131
  safeSetErrorText(String(raw));
132
+ safeSetCanRestart(false);
101
133
  }
102
134
  }, [
103
135
  emailRecoveryOptions,
136
+ safeSetCanRestart,
104
137
  safeSetErrorText,
105
138
  safeSetExplorerToast,
106
139
  safeSetPollingElapsedMs,
@@ -276,9 +309,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
276
309
  safeSetIsBusy(true);
277
310
  cancelRequestedRef.current = false;
278
311
  safeSetErrorText(null);
312
+ safeSetCanRestart(false);
279
313
  safeSetStatusText(null);
280
314
  safeSetPollingElapsedMs(null);
281
315
  safeSetPendingMailtoUrl(null);
316
+ safeSetPendingNearPublicKey(null);
282
317
  safeSetMailtoUiState("ready");
283
318
  let didForwardError = false;
284
319
  try {
@@ -297,6 +332,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
297
332
  }
298
333
  });
299
334
  safeSetPendingMailtoUrl(result.mailtoUrl);
335
+ safeSetPendingNearPublicKey(result.nearPublicKey);
300
336
  safeSetStatusText("Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…");
301
337
  attemptOpenMailtoAuto(result.mailtoUrl);
302
338
  const finalizePromise = tatchiPasskey.finalizeEmailRecovery({
@@ -306,7 +342,9 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
306
342
  onEvent,
307
343
  onError: (err) => {
308
344
  if (cancelRequestedRef.current) return;
309
- safeSetErrorText(err?.message || "Failed to finalize email recovery");
345
+ const uiError = getEmailRecoveryUiError(err);
346
+ safeSetErrorText(uiError.message || "Failed to finalize email recovery");
347
+ safeSetCanRestart(uiError.canRestart);
310
348
  didForwardError = true;
311
349
  emailRecoveryOptions?.onError?.(err);
312
350
  },
@@ -333,10 +371,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
333
371
  safeSetStatusText(null);
334
372
  safeSetPollingElapsedMs(null);
335
373
  safeSetPendingMailtoUrl(null);
374
+ safeSetPendingNearPublicKey(null);
336
375
  safeSetMailtoUiState("ready");
376
+ safeSetCanRestart(false);
337
377
  return;
338
378
  }
339
- safeSetErrorText(err?.message || "Failed to start email recovery");
379
+ const uiError = getEmailRecoveryUiError(err);
380
+ safeSetErrorText(uiError.message || "Failed to start email recovery");
381
+ safeSetCanRestart(uiError.canRestart);
340
382
  if (!didForwardError && err instanceof Error) emailRecoveryOptions?.onError?.(err);
341
383
  } finally {
342
384
  safeSetIsBusy(false);
@@ -357,6 +399,40 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
357
399
  attemptOpenMailtoAuto,
358
400
  tatchiPasskey
359
401
  ]);
402
+ const handleRestart = React.useCallback(async () => {
403
+ const normalizedAccountId = (accountIdInput || "").trim();
404
+ if (!normalizedAccountId) return;
405
+ safeSetIsBusy(true);
406
+ try {
407
+ cancelRequestedRef.current = true;
408
+ await tatchiPasskey.cancelEmailRecovery({
409
+ accountId: normalizedAccountId,
410
+ nearPublicKey: pendingNearPublicKey || void 0
411
+ }).catch(() => {});
412
+ safeSetErrorText(null);
413
+ safeSetStatusText(null);
414
+ safeSetPollingElapsedMs(null);
415
+ safeSetPendingMailtoUrl(null);
416
+ safeSetPendingNearPublicKey(null);
417
+ safeSetMailtoUiState("ready");
418
+ safeSetCanRestart(false);
419
+ } finally {
420
+ cancelRequestedRef.current = false;
421
+ safeSetIsBusy(false);
422
+ }
423
+ }, [
424
+ accountIdInput,
425
+ pendingNearPublicKey,
426
+ safeSetCanRestart,
427
+ safeSetErrorText,
428
+ safeSetIsBusy,
429
+ safeSetMailtoUiState,
430
+ safeSetPendingMailtoUrl,
431
+ safeSetPendingNearPublicKey,
432
+ safeSetPollingElapsedMs,
433
+ safeSetStatusText,
434
+ tatchiPasskey
435
+ ]);
360
436
  const summaryLine = accountInfoLoading ? "Checking if account has recovery emails configured..." : accountInfo && !accountInfoError ? `Recovery emails configured: ${accountInfo.emailsCount}` : "\xA0";
361
437
  const noRecoveryEmailsConfigured = !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;
362
438
  return /* @__PURE__ */ jsxs("div", {
@@ -368,7 +444,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
368
444
  }),
369
445
  /* @__PURE__ */ jsx("div", {
370
446
  className: "w3a-email-recovery-help",
371
- children: "Send a special recovery email from your recovery email address. Your account will be recovered with a new key once the email is verified."
447
+ children: "Send a recovery email from your registered email address. Your account will be recovered with a new key once the email is verified."
372
448
  }),
373
449
  /* @__PURE__ */ jsx("div", {
374
450
  className: "w3a-email-recovery-field",
@@ -438,22 +514,32 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
438
514
  }),
439
515
  /* @__PURE__ */ jsxs("div", {
440
516
  className: "w3a-email-recovery-actions",
441
- children: [(!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ jsx("button", {
442
- onClick: handleStart,
443
- className: "w3a-link-device-btn w3a-link-device-btn-primary",
444
- disabled: isBusy || noRecoveryEmailsConfigured,
445
- children: noRecoveryEmailsConfigured ? "No recovery emails configured" : isBusy ? "Working…" : "Start Email Recovery"
446
- }), pendingMailtoUrl && /* @__PURE__ */ jsxs("button", {
447
- type: "button",
448
- onClick: () => attemptOpenMailtoFromUserGesture(pendingMailtoUrl),
449
- className: "w3a-link-device-btn w3a-link-device-btn-primary",
450
- disabled: mailtoUiState === "opening",
451
- "aria-busy": mailtoUiState === "opening",
452
- children: [mailtoUiState === "opening" && /* @__PURE__ */ jsx("span", {
453
- className: "w3a-spinner",
454
- "aria-hidden": "true"
455
- }), mailtoUiState === "opening" ? "Opening email…" : "Open recovery email draft"]
456
- })]
517
+ children: [
518
+ (!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ jsx("button", {
519
+ onClick: handleStart,
520
+ className: "w3a-link-device-btn w3a-link-device-btn-primary",
521
+ disabled: isBusy || noRecoveryEmailsConfigured,
522
+ children: noRecoveryEmailsConfigured ? "No recovery emails configured" : isBusy ? "Working…" : "Start Email Recovery"
523
+ }),
524
+ pendingMailtoUrl && /* @__PURE__ */ jsxs("button", {
525
+ type: "button",
526
+ onClick: () => attemptOpenMailtoFromUserGesture(pendingMailtoUrl),
527
+ className: "w3a-link-device-btn w3a-link-device-btn-primary",
528
+ disabled: mailtoUiState === "opening",
529
+ "aria-busy": mailtoUiState === "opening",
530
+ children: [mailtoUiState === "opening" && /* @__PURE__ */ jsx("span", {
531
+ className: "w3a-spinner",
532
+ "aria-hidden": "true"
533
+ }), mailtoUiState === "opening" ? "Opening email…" : "Open recovery email draft"]
534
+ }),
535
+ errorText && canRestart && /* @__PURE__ */ jsx("button", {
536
+ type: "button",
537
+ onClick: handleRestart,
538
+ className: "w3a-link-device-btn",
539
+ disabled: isBusy,
540
+ children: "Restart email recovery"
541
+ })
542
+ ]
457
543
  }),
458
544
  (errorText || statusText || explorerToast) && /* @__PURE__ */ jsxs("div", {
459
545
  className: `w3a-email-recovery-status${errorText ? " is-error" : ""}`,
@@ -467,13 +553,13 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
467
553
  "s)."
468
554
  ]
469
555
  }),
470
- explorerToast && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("br", {}), /* @__PURE__ */ jsx("a", {
556
+ explorerToast && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("a", {
471
557
  className: "w3a-email-recovery-link",
472
558
  href: explorerToast.url,
473
559
  target: "_blank",
474
560
  rel: "noopener noreferrer",
475
561
  children: "View on explorer"
476
- })] })
562
+ }) })
477
563
  ]
478
564
  })
479
565
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"EmailRecoverySlide.js","names":["EmailRecoverySlide: React.FC<EmailRecoverySlideProps>","localEmails: string[]","info: EmailRecoveryAccountInfo | null","err: any"],"sources":["../../../../../../src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx"],"sourcesContent":["import React from 'react';\n\nimport type { EmailRecoverySSEEvent } from '@/core/types/sdkSentEvents';\nimport type { TatchiPasskey } from '@/core/TatchiPasskey';\nimport { IndexedDBManager } from '@/core/IndexedDBManager';\nimport { toAccountId } from '@/core/types/accountIds';\n\nexport interface EmailRecoverySlideProps {\n tatchiPasskey: TatchiPasskey;\n accountId: string;\n refreshLoginState?: (nearAccountId?: string) => Promise<void>;\n emailRecoveryOptions?: {\n onEvent?: (event: EmailRecoverySSEEvent) => void;\n onError?: (error: Error) => void;\n };\n}\n\ntype EmailRecoveryPolicy = {\n minRequiredEmails?: number;\n maxAgeMs?: number;\n};\n\ntype EmailRecoveryAccountInfo = {\n emailsCount: number;\n};\n\ntype MailtoUiState = 'ready' | 'opening';\n\nexport const EmailRecoverySlide: React.FC<EmailRecoverySlideProps> = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {\n const mountedRef = React.useRef(true);\n const mailtoAttemptTimerRef = React.useRef<number | null>(null);\n const cancelRequestedRef = React.useRef(false);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n }, []);\n\n const [isBusy, setIsBusy] = React.useState(false);\n const [accountIdInput, setAccountIdInput] = React.useState('');\n const [recoveryEmailInput, setRecoveryEmailInput] = React.useState('');\n const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState<string | null>(null);\n const [mailtoUiState, setMailtoUiState] = React.useState<MailtoUiState>('ready');\n const [statusText, setStatusText] = React.useState<string | null>(null);\n const [pollingElapsedMs, setPollingElapsedMs] = React.useState<number | null>(null);\n const [errorText, setErrorText] = React.useState<string | null>(null);\n const [accountInfo, setAccountInfo] = React.useState<EmailRecoveryAccountInfo | null>(null);\n const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);\n const [accountInfoError, setAccountInfoError] = React.useState<string | null>(null);\n const [localRecoveryEmails, setLocalRecoveryEmails] = React.useState<string[]>([]);\n const [explorerToast, setExplorerToast] = React.useState<{ url: string; accountId?: string; transactionHash?: string } | null>(null);\n\n const lastPrefilledAccountIdRef = React.useRef<string>('');\n const lastPrefilledRecoveryEmailRef = React.useRef<string>('');\n\n React.useEffect(() => {\n const next = (accountId || '').trim();\n if (!next) return;\n if (accountIdInput.trim() === '' || accountIdInput === lastPrefilledAccountIdRef.current) {\n lastPrefilledAccountIdRef.current = next;\n setAccountIdInput(next);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [accountId]);\n\n React.useEffect(() => {\n setPendingMailtoUrl(null);\n setMailtoUiState('ready');\n cancelRequestedRef.current = false;\n setStatusText(null);\n setPollingElapsedMs(null);\n setErrorText(null);\n setAccountInfo(null);\n setAccountInfoError(null);\n setLocalRecoveryEmails([]);\n setExplorerToast(null);\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n }, [accountId]);\n\n const safeSet = <T,>(setter: React.Dispatch<React.SetStateAction<T>>) => {\n return (value: React.SetStateAction<T>) => {\n if (!mountedRef.current) return;\n setter(value);\n };\n };\n\n const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);\n const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);\n const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);\n const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);\n const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);\n const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);\n const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);\n const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);\n const safeSetLocalRecoveryEmails = React.useMemo(() => safeSet(setLocalRecoveryEmails), []);\n const safeSetExplorerToast = React.useMemo(() => safeSet(setExplorerToast), []);\n const safeSetMailtoUiState = React.useMemo(() => safeSet(setMailtoUiState), []);\n\n const onEvent = React.useCallback(\n (ev: EmailRecoverySSEEvent) => {\n if (cancelRequestedRef.current) return;\n safeSetStatusText(ev?.message || null);\n emailRecoveryOptions?.onEvent?.(ev);\n\n const data = (ev as any)?.data || {};\n const rawTxHash = data?.transactionHash ?? data?.transaction_hash;\n const txHash = typeof rawTxHash === 'string' ? rawTxHash.trim() : '';\n if (txHash) {\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/txns/${txHash}`\n : `${base}/transactions/${txHash}`;\n safeSetExplorerToast({ url, transactionHash: txHash });\n }\n const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;\n if (elapsedRaw == null) safeSetPollingElapsedMs(null);\n const elapsed = elapsedRaw == null ? Number.NaN : Number(elapsedRaw);\n if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);\n\n if (ev?.phase === 'email-recovery-error' || (ev as any)?.status === 'error') {\n const raw = (ev as any)?.error || ev?.message || 'Email recovery failed';\n safeSetErrorText(String(raw));\n }\n },\n [emailRecoveryOptions, safeSetErrorText, safeSetExplorerToast, safeSetPollingElapsedMs, safeSetStatusText, tatchiPasskey],\n );\n\n const showExplorerToast = React.useCallback(\n (rawAccountId: string) => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) return;\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/address/${normalized}`\n : `${base}/accounts/${normalized}`;\n\n safeSetExplorerToast({ url, accountId: normalized });\n },\n [safeSetExplorerToast, tatchiPasskey],\n );\n\n const launchMailto = React.useCallback((rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n if (typeof window !== 'undefined') {\n try {\n window.location.href = url;\n } catch {}\n }\n }, []);\n\n const attemptOpenMailtoFromUserGesture = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n safeSetMailtoUiState('opening');\n\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n }\n\n // If the browser never blurs/hides (i.e. mailto blocked or cancelled), re-enable so users can retry.\n mailtoAttemptTimerRef.current = window.setTimeout(() => {\n safeSetMailtoUiState(prev => (prev === 'opening' ? 'ready' : prev));\n mailtoAttemptTimerRef.current = null;\n }, 2_000);\n\n launchMailto(url);\n },\n [launchMailto, safeSetMailtoUiState],\n );\n\n const attemptOpenMailtoAuto = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n // Best-effort only: do not change `mailtoUiState` so users can immediately click the CTA.\n launchMailto(url);\n },\n [launchMailto],\n );\n\n React.useEffect(() => {\n if (mailtoUiState !== 'opening') return;\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n // Heuristic signals that the mail client likely opened. Treat as a hint only:\n // re-enable immediately so the CTA remains retryable even if this is a false-positive.\n const markMaybeOpened = () => {\n safeSetMailtoUiState('ready');\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') markMaybeOpened();\n };\n\n window.addEventListener('blur', markMaybeOpened);\n window.addEventListener('pagehide', markMaybeOpened);\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n return () => {\n window.removeEventListener('blur', markMaybeOpened);\n window.removeEventListener('pagehide', markMaybeOpened);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }, [mailtoUiState, safeSetMailtoUiState]);\n\n const fetchLocalRecoveryEmailsFromIndexedDB = React.useCallback(\n async (rawAccountId: string): Promise<string[]> => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId');\n return [];\n }\n\n try {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB', { accountId: normalized });\n const records = await IndexedDBManager.getRecoveryEmails(toAccountId(normalized));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records', {\n accountId: normalized,\n count: Array.isArray(records) ? records.length : 0,\n records,\n });\n if (!Array.isArray(records) || records.length === 0) return [];\n\n const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));\n const emails = sorted\n .map(r => String(r?.email || '').trim().toLowerCase())\n .filter(e => !!e && e.includes('@'));\n\n const uniq = Array.from(new Set(emails));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails', {\n accountId: normalized,\n emails: uniq,\n });\n return uniq;\n } catch (err) {\n // best-effort; treat as no saved emails (e.g., IndexedDB unavailable)\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB', {\n accountId: normalized,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n },\n [],\n );\n\n const deriveEmailsFromRecoveryRecords = React.useCallback((records: unknown): string[] => {\n if (!Array.isArray(records) || records.length === 0) return [];\n const emails = records\n .map((r: any) => String(r?.email || '').trim().toLowerCase())\n .filter((e: string) => !!e && e.includes('@'));\n return Array.from(new Set(emails));\n }, []);\n\n React.useEffect(() => {\n const normalized = (accountIdInput || '').trim();\n if (!normalized) {\n setAccountInfo(null);\n setAccountInfoError(null);\n setAccountInfoLoading(false);\n safeSetLocalRecoveryEmails([]);\n return;\n }\n\n let cancelled = false;\n // Show loading state immediately (don't wait for debounce).\n safeSetAccountInfoLoading(true);\n safeSetAccountInfoError(null);\n const handle = window.setTimeout(() => {\n void (async () => {\n try {\n const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;\n\n // Legacy mode: suggest recovery emails from local IndexedDB mapping (best-effort).\n let localEmails: string[] = [];\n if (!isWalletIframeMode) {\n localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);\n if (!cancelled) {\n console.log('[EmailRecoverySlide] local saved emails (IndexedDB)', { accountId: normalized, localEmails });\n }\n }\n\n const records = await tatchiPasskey.getRecoveryEmails(normalized);\n const resolvedEmails = isWalletIframeMode\n ? deriveEmailsFromRecoveryRecords(records)\n : localEmails;\n\n if (!cancelled) {\n safeSetLocalRecoveryEmails(resolvedEmails);\n console.log('[EmailRecoverySlide] recovery email suggestions (state)', { accountId: normalized, emails: resolvedEmails });\n\n if (\n resolvedEmails.length === 1 &&\n (recoveryEmailInput.trim() === '' || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)\n ) {\n lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];\n setRecoveryEmailInput(resolvedEmails[0]);\n }\n }\n\n const info: EmailRecoveryAccountInfo | null = records\n ? { emailsCount: Array.isArray(records) ? records.length : 0 }\n : null;\n if (cancelled) return;\n safeSetAccountInfo(info);\n } catch (err: any) {\n if (cancelled) return;\n safeSetAccountInfo(null);\n safeSetAccountInfoError(err?.message || 'Failed to load email recovery settings for this account');\n } finally {\n if (!cancelled) safeSetAccountInfoLoading(false);\n }\n })();\n }, 350);\n\n return () => {\n cancelled = true;\n window.clearTimeout(handle);\n };\n }, [\n accountIdInput,\n deriveEmailsFromRecoveryRecords,\n fetchLocalRecoveryEmailsFromIndexedDB,\n recoveryEmailInput,\n safeSetAccountInfo,\n safeSetAccountInfoError,\n safeSetAccountInfoLoading,\n safeSetLocalRecoveryEmails,\n tatchiPasskey,\n ]);\n\n const handleStart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) {\n safeSetErrorText('Enter an account ID.');\n return;\n }\n\n const emailCandidate = (recoveryEmailInput || '').trim().toLowerCase();\n if (!emailCandidate) {\n safeSetErrorText('Enter the recovery email to send from.');\n return;\n }\n\n safeSetIsBusy(true);\n cancelRequestedRef.current = false;\n safeSetErrorText(null);\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n\n let didForwardError = false;\n try {\n const result = await tatchiPasskey.startEmailRecovery({\n accountId: normalizedAccountId,\n recoveryEmail: emailCandidate,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSetErrorText(err?.message || 'Failed to start email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n safeSetPendingMailtoUrl(result.mailtoUrl);\n safeSetStatusText('Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…');\n\n // Best-effort open. If blocked/cancelled, the CTA remains immediately clickable for a user-gesture retry.\n attemptOpenMailtoAuto(result.mailtoUrl);\n\n // Start polling immediately after attempting to open the email prompt.\n const finalizePromise = tatchiPasskey.finalizeEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: result.nearPublicKey,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSetErrorText(err?.message || 'Failed to finalize email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n showExplorerToast(normalizedAccountId);\n\n await finalizePromise;\n\n // Best-effort auto-login: the core flow attempts it, but if it couldn't (e.g. missing Shamir\n // auto-unlock and user cancelled TouchID), try once more here.\n let loginOk = false;\n const session = await tatchiPasskey.getLoginSession(normalizedAccountId).catch(() => null);\n if (session?.login?.isLoggedIn) {\n loginOk = true;\n } else {\n safeSetStatusText('Email recovery completed. Logging you in…');\n loginOk = await tatchiPasskey.loginAndCreateSession(normalizedAccountId)\n .then(() => true)\n .catch(() => false);\n }\n\n if (refreshLoginState) {\n await refreshLoginState(normalizedAccountId).catch(() => {});\n }\n\n safeSetStatusText(loginOk ? 'Email recovery completed on this device.' : 'Email recovery completed. Please log in on this device.');\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n safeSetPollingElapsedMs(null);\n } catch (err: any) {\n if (cancelRequestedRef.current) {\n safeSetErrorText('Email recovery cancelled. Please try again.');\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n return;\n }\n safeSetErrorText(err?.message || 'Failed to start email recovery');\n if (!didForwardError && err instanceof Error) {\n emailRecoveryOptions?.onError?.(err);\n }\n } finally {\n safeSetIsBusy(false);\n }\n }, [\n accountIdInput,\n emailRecoveryOptions,\n recoveryEmailInput,\n onEvent,\n refreshLoginState,\n showExplorerToast,\n safeSetErrorText,\n safeSetIsBusy,\n safeSetPendingMailtoUrl,\n safeSetPollingElapsedMs,\n safeSetStatusText,\n safeSetMailtoUiState,\n attemptOpenMailtoAuto,\n tatchiPasskey,\n ]);\n\n const summaryLine = accountInfoLoading\n ? 'Checking if account has recovery emails configured...'\n : accountInfo && !accountInfoError\n ? `Recovery emails configured: ${accountInfo.emailsCount}`\n : '\\u00A0';\n\n const noRecoveryEmailsConfigured =\n !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;\n\n return (\n <div className=\"w3a-email-recovery-slide\">\n <div className=\"w3a-email-recovery-title\">Recover Account with Email</div>\n <div className=\"w3a-email-recovery-help\">\n Send a special recovery email from your recovery email address.\n Your account will be recovered with a new key once the email is verified.\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"text\"\n value={accountIdInput}\n onChange={(e) => setAccountIdInput(e.target.value)}\n placeholder=\"NEAR account ID (e.g. alice.testnet)\"\n className=\"w3a-input\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"text\"\n disabled={isBusy}\n />\n </div>\n </div>\n </div>\n\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>{summaryLine}</div>\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"email\"\n value={recoveryEmailInput}\n onChange={(e) => setRecoveryEmailInput(e.target.value)}\n placeholder=\"Recovery email to send from\"\n className=\"w3a-input\"\n list={localRecoveryEmails.length > 0 ? 'w3a-email-recovery-saved-emails' : undefined}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"email\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n />\n </div>\n </div>\n </div>\n\n {localRecoveryEmails.length > 0 && (\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>Saved on this device:</div>\n <div className=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <button\n key={email}\n type=\"button\"\n className=\"w3a-email-recovery-email-chip\"\n onClick={() => setRecoveryEmailInput(email)}\n disabled={isBusy}\n >\n {email}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {localRecoveryEmails.length > 0 && (\n <datalist id=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <option key={email} value={email} />\n ))}\n </datalist>\n )}\n\n <div className=\"w3a-email-recovery-actions\">\n {(!pendingMailtoUrl || !isBusy) && (\n <button\n onClick={handleStart}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n >\n {noRecoveryEmailsConfigured ? 'No recovery emails configured' : (isBusy ? 'Working…' : 'Start Email Recovery')}\n </button>\n )}\n\n {pendingMailtoUrl && (\n <button\n type=\"button\"\n onClick={() => attemptOpenMailtoFromUserGesture(pendingMailtoUrl)}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={mailtoUiState === 'opening'}\n aria-busy={mailtoUiState === 'opening'}\n >\n {mailtoUiState === 'opening' && <span className=\"w3a-spinner\" aria-hidden=\"true\" />}\n {mailtoUiState === 'opening' ? 'Opening email…' : 'Open recovery email draft'}\n </button>\n )}\n </div>\n\n {(errorText || statusText || explorerToast) && (\n <div className={`w3a-email-recovery-status${errorText ? ' is-error' : ''}`}>\n {errorText ? errorText : statusText}\n {pollingElapsedMs != null && !Number.isNaN(pollingElapsedMs) && pollingElapsedMs > 0 && (\n <span className=\"w3a-email-recovery-elapsed\">\n (~{Math.round(pollingElapsedMs / 1000)}s).\n </span>\n )}\n {explorerToast && (\n <>\n <br />\n <a className=\"w3a-email-recovery-link\" href={explorerToast.url} target=\"_blank\" rel=\"noopener noreferrer\">\n View on explorer\n </a>\n </>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default EmailRecoverySlide;\n"],"mappings":"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"}
1
+ {"version":3,"file":"EmailRecoverySlide.js","names":["EmailRecoverySlide: React.FC<EmailRecoverySlideProps>","localEmails: string[]","info: EmailRecoveryAccountInfo | null","err: any"],"sources":["../../../../../../src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx"],"sourcesContent":["import React from 'react';\n\nimport type { EmailRecoverySSEEvent } from '@/core/types/sdkSentEvents';\nimport type { TatchiPasskey } from '@/core/TatchiPasskey';\nimport { IndexedDBManager } from '@/core/IndexedDBManager';\nimport { toAccountId } from '@/core/types/accountIds';\nimport { EmailRecoveryErrorCode } from '@/core/types/emailRecovery';\n\nexport interface EmailRecoverySlideProps {\n tatchiPasskey: TatchiPasskey;\n accountId: string;\n refreshLoginState?: (nearAccountId?: string) => Promise<void>;\n emailRecoveryOptions?: {\n onEvent?: (event: EmailRecoverySSEEvent) => void;\n onError?: (error: Error) => void;\n };\n}\n\ntype EmailRecoveryPolicy = {\n minRequiredEmails?: number;\n maxAgeMs?: number;\n};\n\ntype EmailRecoveryAccountInfo = {\n emailsCount: number;\n};\n\ntype MailtoUiState = 'ready' | 'opening';\n\nfunction getEmailRecoveryErrorCode(err: unknown): EmailRecoveryErrorCode | null {\n const code = (err as { code?: unknown } | null)?.code;\n if (typeof code !== 'string') return null;\n return Object.values(EmailRecoveryErrorCode).includes(code as EmailRecoveryErrorCode)\n ? (code as EmailRecoveryErrorCode)\n : null;\n}\n\nfunction getEmailRecoveryUiError(err: unknown): { message: string; canRestart: boolean } {\n const fallback = err instanceof Error ? err.message : String(err || '');\n const code = getEmailRecoveryErrorCode(err);\n switch (code) {\n case EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED:\n return {\n message: fallback || 'Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again.',\n canRestart: true,\n };\n case EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED:\n return {\n message: fallback || 'Registration did not verify on-chain. Please restart email recovery and try again.',\n canRestart: true,\n };\n default:\n return { message: fallback || 'Email recovery failed', canRestart: false };\n }\n}\n\nexport const EmailRecoverySlide: React.FC<EmailRecoverySlideProps> = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {\n const mountedRef = React.useRef(true);\n const mailtoAttemptTimerRef = React.useRef<number | null>(null);\n const cancelRequestedRef = React.useRef(false);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n }, []);\n\n const [isBusy, setIsBusy] = React.useState(false);\n const [accountIdInput, setAccountIdInput] = React.useState('');\n const [recoveryEmailInput, setRecoveryEmailInput] = React.useState('');\n const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState<string | null>(null);\n const [pendingNearPublicKey, setPendingNearPublicKey] = React.useState<string | null>(null);\n const [mailtoUiState, setMailtoUiState] = React.useState<MailtoUiState>('ready');\n const [statusText, setStatusText] = React.useState<string | null>(null);\n const [pollingElapsedMs, setPollingElapsedMs] = React.useState<number | null>(null);\n const [errorText, setErrorText] = React.useState<string | null>(null);\n const [canRestart, setCanRestart] = React.useState(false);\n const [accountInfo, setAccountInfo] = React.useState<EmailRecoveryAccountInfo | null>(null);\n const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);\n const [accountInfoError, setAccountInfoError] = React.useState<string | null>(null);\n const [localRecoveryEmails, setLocalRecoveryEmails] = React.useState<string[]>([]);\n const [explorerToast, setExplorerToast] = React.useState<{ url: string; accountId?: string; transactionHash?: string } | null>(null);\n\n const lastPrefilledAccountIdRef = React.useRef<string>('');\n const lastPrefilledRecoveryEmailRef = React.useRef<string>('');\n\n React.useEffect(() => {\n const next = (accountId || '').trim();\n if (!next) return;\n if (accountIdInput.trim() === '' || accountIdInput === lastPrefilledAccountIdRef.current) {\n lastPrefilledAccountIdRef.current = next;\n setAccountIdInput(next);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [accountId]);\n\n React.useEffect(() => {\n setPendingMailtoUrl(null);\n setPendingNearPublicKey(null);\n setMailtoUiState('ready');\n cancelRequestedRef.current = false;\n setStatusText(null);\n setPollingElapsedMs(null);\n setErrorText(null);\n setCanRestart(false);\n setAccountInfo(null);\n setAccountInfoError(null);\n setLocalRecoveryEmails([]);\n setExplorerToast(null);\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n }, [accountId]);\n\n const safeSet = <T,>(setter: React.Dispatch<React.SetStateAction<T>>) => {\n return (value: React.SetStateAction<T>) => {\n if (!mountedRef.current) return;\n setter(value);\n };\n };\n\n const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);\n const safeSetPendingNearPublicKey = React.useMemo(() => safeSet(setPendingNearPublicKey), []);\n const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);\n const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);\n const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);\n const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);\n const safeSetCanRestart = React.useMemo(() => safeSet(setCanRestart), []);\n const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);\n const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);\n const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);\n const safeSetLocalRecoveryEmails = React.useMemo(() => safeSet(setLocalRecoveryEmails), []);\n const safeSetExplorerToast = React.useMemo(() => safeSet(setExplorerToast), []);\n const safeSetMailtoUiState = React.useMemo(() => safeSet(setMailtoUiState), []);\n\n const onEvent = React.useCallback(\n (ev: EmailRecoverySSEEvent) => {\n if (cancelRequestedRef.current) return;\n safeSetStatusText(ev?.message || null);\n emailRecoveryOptions?.onEvent?.(ev);\n\n const data = (ev as any)?.data || {};\n const rawTxHash = data?.transactionHash ?? data?.transaction_hash;\n const txHash = typeof rawTxHash === 'string' ? rawTxHash.trim() : '';\n if (txHash) {\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/txns/${txHash}`\n : `${base}/transactions/${txHash}`;\n safeSetExplorerToast({ url, transactionHash: txHash });\n }\n const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;\n if (elapsedRaw == null) safeSetPollingElapsedMs(null);\n const elapsed = elapsedRaw == null ? Number.NaN : Number(elapsedRaw);\n if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);\n\n if (ev?.phase === 'email-recovery-error' || (ev as any)?.status === 'error') {\n const raw = (ev as any)?.error || ev?.message || 'Email recovery failed';\n safeSetErrorText(String(raw));\n safeSetCanRestart(false);\n }\n },\n [emailRecoveryOptions, safeSetCanRestart, safeSetErrorText, safeSetExplorerToast, safeSetPollingElapsedMs, safeSetStatusText, tatchiPasskey],\n );\n\n const showExplorerToast = React.useCallback(\n (rawAccountId: string) => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) return;\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/address/${normalized}`\n : `${base}/accounts/${normalized}`;\n\n safeSetExplorerToast({ url, accountId: normalized });\n },\n [safeSetExplorerToast, tatchiPasskey],\n );\n\n const launchMailto = React.useCallback((rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n if (typeof window !== 'undefined') {\n try {\n window.location.href = url;\n } catch {}\n }\n }, []);\n\n const attemptOpenMailtoFromUserGesture = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n safeSetMailtoUiState('opening');\n\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n }\n\n // If the browser never blurs/hides (i.e. mailto blocked or cancelled), re-enable so users can retry.\n mailtoAttemptTimerRef.current = window.setTimeout(() => {\n safeSetMailtoUiState(prev => (prev === 'opening' ? 'ready' : prev));\n mailtoAttemptTimerRef.current = null;\n }, 2_000);\n\n launchMailto(url);\n },\n [launchMailto, safeSetMailtoUiState],\n );\n\n const attemptOpenMailtoAuto = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n // Best-effort only: do not change `mailtoUiState` so users can immediately click the CTA.\n launchMailto(url);\n },\n [launchMailto],\n );\n\n React.useEffect(() => {\n if (mailtoUiState !== 'opening') return;\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n // Heuristic signals that the mail client likely opened. Treat as a hint only:\n // re-enable immediately so the CTA remains retryable even if this is a false-positive.\n const markMaybeOpened = () => {\n safeSetMailtoUiState('ready');\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') markMaybeOpened();\n };\n\n window.addEventListener('blur', markMaybeOpened);\n window.addEventListener('pagehide', markMaybeOpened);\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n return () => {\n window.removeEventListener('blur', markMaybeOpened);\n window.removeEventListener('pagehide', markMaybeOpened);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }, [mailtoUiState, safeSetMailtoUiState]);\n\n const fetchLocalRecoveryEmailsFromIndexedDB = React.useCallback(\n async (rawAccountId: string): Promise<string[]> => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId');\n return [];\n }\n\n try {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB', { accountId: normalized });\n const records = await IndexedDBManager.getRecoveryEmails(toAccountId(normalized));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records', {\n accountId: normalized,\n count: Array.isArray(records) ? records.length : 0,\n records,\n });\n if (!Array.isArray(records) || records.length === 0) return [];\n\n const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));\n const emails = sorted\n .map(r => String(r?.email || '').trim().toLowerCase())\n .filter(e => !!e && e.includes('@'));\n\n const uniq = Array.from(new Set(emails));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails', {\n accountId: normalized,\n emails: uniq,\n });\n return uniq;\n } catch (err) {\n // best-effort; treat as no saved emails (e.g., IndexedDB unavailable)\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB', {\n accountId: normalized,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n },\n [],\n );\n\n const deriveEmailsFromRecoveryRecords = React.useCallback((records: unknown): string[] => {\n if (!Array.isArray(records) || records.length === 0) return [];\n const emails = records\n .map((r: any) => String(r?.email || '').trim().toLowerCase())\n .filter((e: string) => !!e && e.includes('@'));\n return Array.from(new Set(emails));\n }, []);\n\n React.useEffect(() => {\n const normalized = (accountIdInput || '').trim();\n if (!normalized) {\n setAccountInfo(null);\n setAccountInfoError(null);\n setAccountInfoLoading(false);\n safeSetLocalRecoveryEmails([]);\n return;\n }\n\n let cancelled = false;\n // Show loading state immediately (don't wait for debounce).\n safeSetAccountInfoLoading(true);\n safeSetAccountInfoError(null);\n const handle = window.setTimeout(() => {\n void (async () => {\n try {\n const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;\n\n // Legacy mode: suggest recovery emails from local IndexedDB mapping (best-effort).\n let localEmails: string[] = [];\n if (!isWalletIframeMode) {\n localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);\n if (!cancelled) {\n console.log('[EmailRecoverySlide] local saved emails (IndexedDB)', { accountId: normalized, localEmails });\n }\n }\n\n const records = await tatchiPasskey.getRecoveryEmails(normalized);\n const resolvedEmails = isWalletIframeMode\n ? deriveEmailsFromRecoveryRecords(records)\n : localEmails;\n\n if (!cancelled) {\n safeSetLocalRecoveryEmails(resolvedEmails);\n console.log('[EmailRecoverySlide] recovery email suggestions (state)', { accountId: normalized, emails: resolvedEmails });\n\n if (\n resolvedEmails.length === 1 &&\n (recoveryEmailInput.trim() === '' || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)\n ) {\n lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];\n setRecoveryEmailInput(resolvedEmails[0]);\n }\n }\n\n const info: EmailRecoveryAccountInfo | null = records\n ? { emailsCount: Array.isArray(records) ? records.length : 0 }\n : null;\n if (cancelled) return;\n safeSetAccountInfo(info);\n } catch (err: any) {\n if (cancelled) return;\n safeSetAccountInfo(null);\n safeSetAccountInfoError(err?.message || 'Failed to load email recovery settings for this account');\n } finally {\n if (!cancelled) safeSetAccountInfoLoading(false);\n }\n })();\n }, 350);\n\n return () => {\n cancelled = true;\n window.clearTimeout(handle);\n };\n }, [\n accountIdInput,\n deriveEmailsFromRecoveryRecords,\n fetchLocalRecoveryEmailsFromIndexedDB,\n recoveryEmailInput,\n safeSetAccountInfo,\n safeSetAccountInfoError,\n safeSetAccountInfoLoading,\n safeSetLocalRecoveryEmails,\n tatchiPasskey,\n ]);\n\n const handleStart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) {\n safeSetErrorText('Enter an account ID.');\n return;\n }\n\n const emailCandidate = (recoveryEmailInput || '').trim().toLowerCase();\n if (!emailCandidate) {\n safeSetErrorText('Enter the recovery email to send from.');\n return;\n }\n\n safeSetIsBusy(true);\n cancelRequestedRef.current = false;\n safeSetErrorText(null);\n safeSetCanRestart(false);\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetPendingNearPublicKey(null);\n safeSetMailtoUiState('ready');\n\n let didForwardError = false;\n try {\n const result = await tatchiPasskey.startEmailRecovery({\n accountId: normalizedAccountId,\n recoveryEmail: emailCandidate,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSetErrorText(err?.message || 'Failed to start email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n safeSetPendingMailtoUrl(result.mailtoUrl);\n safeSetPendingNearPublicKey(result.nearPublicKey);\n safeSetStatusText('Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…');\n\n // Best-effort open. If blocked/cancelled, the CTA remains immediately clickable for a user-gesture retry.\n attemptOpenMailtoAuto(result.mailtoUrl);\n\n // Start polling immediately after attempting to open the email prompt.\n const finalizePromise = tatchiPasskey.finalizeEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: result.nearPublicKey,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n const uiError = getEmailRecoveryUiError(err);\n safeSetErrorText(uiError.message || 'Failed to finalize email recovery');\n safeSetCanRestart(uiError.canRestart);\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n showExplorerToast(normalizedAccountId);\n\n await finalizePromise;\n\n // Best-effort auto-login: the core flow attempts it, but if it couldn't (e.g. missing Shamir\n // auto-unlock and user cancelled TouchID), try once more here.\n let loginOk = false;\n const session = await tatchiPasskey.getLoginSession(normalizedAccountId).catch(() => null);\n if (session?.login?.isLoggedIn) {\n loginOk = true;\n } else {\n safeSetStatusText('Email recovery completed. Logging you in…');\n loginOk = await tatchiPasskey.loginAndCreateSession(normalizedAccountId)\n .then(() => true)\n .catch(() => false);\n }\n\n if (refreshLoginState) {\n await refreshLoginState(normalizedAccountId).catch(() => {});\n }\n\n safeSetStatusText(loginOk ? 'Email recovery completed on this device.' : 'Email recovery completed. Please log in on this device.');\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n safeSetPollingElapsedMs(null);\n } catch (err: any) {\n if (cancelRequestedRef.current) {\n safeSetErrorText('Email recovery cancelled. Please try again.');\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetPendingNearPublicKey(null);\n safeSetMailtoUiState('ready');\n safeSetCanRestart(false);\n return;\n }\n const uiError = getEmailRecoveryUiError(err);\n safeSetErrorText(uiError.message || 'Failed to start email recovery');\n safeSetCanRestart(uiError.canRestart);\n if (!didForwardError && err instanceof Error) {\n emailRecoveryOptions?.onError?.(err);\n }\n } finally {\n safeSetIsBusy(false);\n }\n }, [\n accountIdInput,\n emailRecoveryOptions,\n recoveryEmailInput,\n onEvent,\n refreshLoginState,\n showExplorerToast,\n safeSetErrorText,\n safeSetIsBusy,\n safeSetPendingMailtoUrl,\n safeSetPollingElapsedMs,\n safeSetStatusText,\n safeSetMailtoUiState,\n attemptOpenMailtoAuto,\n tatchiPasskey,\n ]);\n\n const handleRestart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) return;\n\n safeSetIsBusy(true);\n try {\n cancelRequestedRef.current = true;\n await tatchiPasskey.cancelEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: pendingNearPublicKey || undefined,\n }).catch(() => {});\n safeSetErrorText(null);\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetPendingNearPublicKey(null);\n safeSetMailtoUiState('ready');\n safeSetCanRestart(false);\n } finally {\n cancelRequestedRef.current = false;\n safeSetIsBusy(false);\n }\n }, [\n accountIdInput,\n pendingNearPublicKey,\n safeSetCanRestart,\n safeSetErrorText,\n safeSetIsBusy,\n safeSetMailtoUiState,\n safeSetPendingMailtoUrl,\n safeSetPendingNearPublicKey,\n safeSetPollingElapsedMs,\n safeSetStatusText,\n tatchiPasskey,\n ]);\n\n const summaryLine = accountInfoLoading\n ? 'Checking if account has recovery emails configured...'\n : accountInfo && !accountInfoError\n ? `Recovery emails configured: ${accountInfo.emailsCount}`\n : '\\u00A0';\n\n const noRecoveryEmailsConfigured =\n !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;\n\n return (\n <div className=\"w3a-email-recovery-slide\">\n <div className=\"w3a-email-recovery-title\">Recover Account with Email</div>\n <div className=\"w3a-email-recovery-help\">\n Send a recovery email from your registered email address.\n Your account will be recovered with a new key once the email is verified.\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"text\"\n value={accountIdInput}\n onChange={(e) => setAccountIdInput(e.target.value)}\n placeholder=\"NEAR account ID (e.g. alice.testnet)\"\n className=\"w3a-input\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"text\"\n disabled={isBusy}\n />\n </div>\n </div>\n </div>\n\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>{summaryLine}</div>\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"email\"\n value={recoveryEmailInput}\n onChange={(e) => setRecoveryEmailInput(e.target.value)}\n placeholder=\"Recovery email to send from\"\n className=\"w3a-input\"\n list={localRecoveryEmails.length > 0 ? 'w3a-email-recovery-saved-emails' : undefined}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"email\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n />\n </div>\n </div>\n </div>\n\n {localRecoveryEmails.length > 0 && (\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>Saved on this device:</div>\n <div className=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <button\n key={email}\n type=\"button\"\n className=\"w3a-email-recovery-email-chip\"\n onClick={() => setRecoveryEmailInput(email)}\n disabled={isBusy}\n >\n {email}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {localRecoveryEmails.length > 0 && (\n <datalist id=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <option key={email} value={email} />\n ))}\n </datalist>\n )}\n\n <div className=\"w3a-email-recovery-actions\">\n {(!pendingMailtoUrl || !isBusy) && (\n <button\n onClick={handleStart}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n >\n {noRecoveryEmailsConfigured ? 'No recovery emails configured' : (isBusy ? 'Working…' : 'Start Email Recovery')}\n </button>\n )}\n\n {pendingMailtoUrl && (\n <button\n type=\"button\"\n onClick={() => attemptOpenMailtoFromUserGesture(pendingMailtoUrl)}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={mailtoUiState === 'opening'}\n aria-busy={mailtoUiState === 'opening'}\n >\n {mailtoUiState === 'opening' && <span className=\"w3a-spinner\" aria-hidden=\"true\" />}\n {mailtoUiState === 'opening' ? 'Opening email…' : 'Open recovery email draft'}\n </button>\n )}\n\n {errorText && canRestart && (\n <button\n type=\"button\"\n onClick={handleRestart}\n className=\"w3a-link-device-btn\"\n disabled={isBusy}\n >\n Restart email recovery\n </button>\n )}\n </div>\n\n {(errorText || statusText || explorerToast) && (\n <div className={`w3a-email-recovery-status${errorText ? ' is-error' : ''}`}>\n {errorText ? errorText : statusText}\n {pollingElapsedMs != null && !Number.isNaN(pollingElapsedMs) && pollingElapsedMs > 0 && (\n <span className=\"w3a-email-recovery-elapsed\">\n (~{Math.round(pollingElapsedMs / 1000)}s).\n </span>\n )}\n {explorerToast && (\n <>\n <a className=\"w3a-email-recovery-link\" href={explorerToast.url} target=\"_blank\" rel=\"noopener noreferrer\">\n View on explorer\n </a>\n </>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default EmailRecoverySlide;\n"],"mappings":"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"}
@@ -110,4 +110,4 @@
110
110
  }
111
111
 
112
112
 
113
- /*# sourceMappingURL=ShowQRCode-CCN4h6Uv.css.map*/
113
+ /*# sourceMappingURL=ShowQRCode-CL4gsszN.css.map*/
@@ -1 +1 @@
1
- {"version":3,"file":"ShowQRCode-CCN4h6Uv.css","names":[],"sources":["../../../../src/react/components/ShowQRCode.css"],"sourcesContent":[".qr-code-container {\n padding-top: 1rem;\n}\n\n/* Modal Header */\n.qr-header {\n position: relative;\n display: grid;\n place-content: center;\n padding: 0rem;\n}\n\n.qr-title {\n font-size: 1.5rem;\n font-weight: 700;\n color: var(--w3a-colors-textPrimary, #1e293b);\n padding-top: 0rem;\n margin: 0;\n}\n\n.qr-body {\n padding: 0rem;\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.qr-code-section {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* QR Code Display */\n.qr-code-display {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0rem;\n padding: 1rem;\n border-radius: 1.5rem;\n width: 100%;\n max-width: 300px;\n}\n\n.qr-instruction, .qr-status {\n margin: 0;\n font-size: 1rem;\n font-weight: 500;\n line-height: 1.5;\n color: var(--w3a-colors-textSecondary, #1e293b);\n text-align: center;\n}\n\n.qr-status {\n margin-bottom: 0.5rem;\n}\n\n.animated-ellipsis {\n display: inline-block;\n width: 1.2em;\n text-align: left;\n}\n\n.animated-ellipsis::after {\n content: \"...\";\n animation: ellipsis 1.5s infinite;\n}\n\n@keyframes ellipsis {\n 0% { content: \"...\"; }\n 25% { content: \"\"; }\n 50% { content: \".\"; }\n 75% { content: \"..\"; }\n 100% { content: \"...\"; }\n}\n\n.qr-code-image {\n max-width: 200px;\n height: auto;\n border-radius: var(--w3a-border-radius-md, 0.5rem);\n}\n\n.qr-loading {\n text-align: center;\n padding: 2rem;\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .qr-modal-content {\n margin: 1rem;\n max-width: calc(100vw - 2rem);\n }\n\n @supports (width: 1dvw) {\n .qr-modal-content { max-width: calc(100dvw - 2rem); }\n }\n\n .qr-code-image {\n max-width: 200px;\n }\n\n .qr-code-display {\n padding: 1rem;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA"}
1
+ {"version":3,"file":"ShowQRCode-CL4gsszN.css","names":[],"sources":["../../../../src/react/components/ShowQRCode.css"],"sourcesContent":[".qr-code-container {\n padding-top: 1rem;\n}\n\n/* Modal Header */\n.qr-header {\n position: relative;\n display: grid;\n place-content: center;\n padding: 0rem;\n}\n\n.qr-title {\n font-size: 1.5rem;\n font-weight: 700;\n color: var(--w3a-colors-textPrimary, #1e293b);\n padding-top: 0rem;\n margin: 0;\n}\n\n.qr-body {\n padding: 0rem;\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.qr-code-section {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* QR Code Display */\n.qr-code-display {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0rem;\n padding: 1rem;\n border-radius: 1.5rem;\n width: 100%;\n max-width: 300px;\n}\n\n.qr-instruction, .qr-status {\n margin: 0;\n font-size: 1rem;\n font-weight: 500;\n line-height: 1.5;\n color: var(--w3a-colors-textSecondary, #1e293b);\n text-align: center;\n}\n\n.qr-status {\n margin-bottom: 0.5rem;\n}\n\n.animated-ellipsis {\n display: inline-block;\n width: 1.2em;\n text-align: left;\n}\n\n.animated-ellipsis::after {\n content: \"...\";\n animation: ellipsis 1.5s infinite;\n}\n\n@keyframes ellipsis {\n 0% { content: \"...\"; }\n 25% { content: \"\"; }\n 50% { content: \".\"; }\n 75% { content: \"..\"; }\n 100% { content: \"...\"; }\n}\n\n.qr-code-image {\n max-width: 200px;\n height: auto;\n border-radius: var(--w3a-border-radius-md, 0.5rem);\n}\n\n.qr-loading {\n text-align: center;\n padding: 2rem;\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .qr-modal-content {\n margin: 1rem;\n max-width: calc(100vw - 2rem);\n }\n\n @supports (width: 1dvw) {\n .qr-modal-content { max-width: calc(100dvw - 2rem); }\n }\n\n .qr-code-image {\n max-width: 200px;\n }\n\n .qr-code-display {\n padding: 1rem;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA"}