@agent-native/core 0.148.0 → 0.149.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 (165) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/changelog/2026-08-10-wide-tables-in-analytics-chat-now-scroll-horizontally-within.md +6 -0
  3. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +13 -53
  4. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -70
  5. package/corpus/templates/calendar/app/lib/event-layout.ts +122 -0
  6. package/corpus/templates/calendar/app/routes/_app.availability.tsx +1 -1
  7. package/corpus/templates/calendar/changelog/2026-08-10-opening-availability-settings-from-the-agent-lands-on-the-av.md +6 -0
  8. package/corpus/templates/calendar/vitest.config.ts +6 -1
  9. package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +3 -1
  10. package/corpus/templates/clips/app/components/player/video-player.tsx +44 -4
  11. package/corpus/templates/clips/changelog/2026-08-10-fixed-transcription-failures-for-recordings-without-captured.md +6 -0
  12. package/corpus/templates/clips/changelog/2026-08-10-mobile-clips-can-now-enter-fullscreen-on-iphone-safari.md +6 -0
  13. package/corpus/templates/content/actions/_property-utils.ts +11 -1
  14. package/corpus/templates/content/actions/view-screen.ts +62 -12
  15. package/corpus/templates/content/server/plugins/agent-chat.ts +2 -0
  16. package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +22 -0
  17. package/corpus/templates/design/AGENTS.md +3 -0
  18. package/corpus/templates/design/actions/create-design-from-template.ts +19 -0
  19. package/corpus/templates/design/actions/get-design-snapshot.ts +18 -0
  20. package/corpus/templates/design/actions/get-design-template.ts +178 -0
  21. package/corpus/templates/design/actions/list-designs.ts +3 -1
  22. package/corpus/templates/design/actions/view-screen.ts +31 -0
  23. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +225 -214
  24. package/corpus/templates/design/app/components/design/multi-screen/types.ts +3 -0
  25. package/corpus/templates/design/app/i18n-data.ts +78 -0
  26. package/corpus/templates/design/app/lib/design-authors.ts +64 -0
  27. package/corpus/templates/design/app/pages/Index.tsx +114 -4
  28. package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +1 -0
  29. package/corpus/templates/design/changelog/2026-08-07-alt-dragging-an-element-to-copy-it-now-keeps-the-copy-visibl.md +6 -0
  30. package/corpus/templates/design/changelog/2026-08-07-design-cards-now-show-who-created-each-design-with-a-filter-.md +6 -0
  31. package/corpus/templates/design/changelog/2026-08-07-drawing-a-shape-on-the-overview-canvas-now-keeps-the-shape-s.md +6 -0
  32. package/corpus/templates/design/changelog/2026-08-07-hold-option-alt-while-dragging-a-frame-on-the-overview-canva.md +6 -0
  33. package/corpus/templates/design/server/lib/design-template-data.ts +143 -0
  34. package/corpus/templates/design/server/plugins/agent-chat.ts +1 -0
  35. package/corpus/templates/forms/AGENTS.md +2 -2
  36. package/corpus/templates/forms/actions/create-form.ts +1 -1
  37. package/corpus/templates/forms/actions/update-form.ts +5 -5
  38. package/corpus/templates/forms/changelog/2026-08-10-forms-now-keep-agent-applied-field-changes-visible-after-an-.md +6 -0
  39. package/corpus/templates/forms/changelog/2026-08-10-published-form-links-always-use-the-working-public-form-url.md +6 -0
  40. package/corpus/templates/forms/server/plugins/agent-chat.ts +2 -2
  41. package/corpus/templates/slides/AGENTS.md +4 -3
  42. package/corpus/templates/slides/actions/import-google-slides-reference.ts +56 -10
  43. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +12 -74
  44. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +5 -1
  45. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +15 -4
  46. package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +116 -55
  47. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1 -0
  48. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +143 -18
  49. package/corpus/templates/slides/app/i18n/en-US.ts +6 -0
  50. package/corpus/templates/slides/app/lib/generation-state.ts +7 -1
  51. package/corpus/templates/slides/app/pages/DeckEditor.tsx +32 -14
  52. package/corpus/templates/slides/app/pages/Index.tsx +110 -128
  53. package/corpus/templates/slides/changelog/2026-08-10-imported-reference-decks-now-show-clear-success-and-stay-sel.md +6 -0
  54. package/corpus/templates/slides/changelog/2026-08-10-pasted-google-slides-links-import-after-reconnecting-google-.md +6 -0
  55. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +4 -0
  56. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +13 -0
  57. package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
  58. package/dist/agent/engine/registry.d.ts +8 -2
  59. package/dist/agent/engine/registry.js +63 -29
  60. package/dist/agent/production-agent.js +7 -0
  61. package/dist/agent/run-manager.d.ts +5 -4
  62. package/dist/agent/run-manager.js +6 -5
  63. package/dist/cli/claude-code-participant.d.ts +2 -1
  64. package/dist/cli/claude-code-participant.js +19 -0
  65. package/dist/cli/code-agent-executor.js +223 -0
  66. package/dist/cli/create-workspace.js +3 -3
  67. package/dist/cli/create.d.ts +3 -2
  68. package/dist/cli/create.js +20 -24
  69. package/dist/client/AgentPanel.js +8 -4
  70. package/dist/client/AssistantChat.js +34 -1
  71. package/dist/client/agent-chat-adapter.d.ts +1 -0
  72. package/dist/client/agent-chat-adapter.js +10 -2
  73. package/dist/client/blocks/library/diagram.js +1 -1
  74. package/dist/client/blocks/library/sanitize-html.js +66 -2
  75. package/dist/client/blocks/library/wireframe-kit.js +69 -0
  76. package/dist/client/chat/markdown-renderer.d.ts +1 -0
  77. package/dist/client/chat/markdown-renderer.js +4 -0
  78. package/dist/client/chat/message-components.d.ts +1 -0
  79. package/dist/client/chat/message-components.js +9 -1
  80. package/dist/client/chat/tool-call-display.d.ts +8 -0
  81. package/dist/client/chat/tool-call-display.js +30 -21
  82. package/dist/client/chat-first/app-pane.js +1 -1
  83. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  84. package/dist/client/chat-first/apps-rail.js +12 -12
  85. package/dist/client/chat-first/chat-history.d.ts +1 -1
  86. package/dist/client/chat-first/chat-history.js +2 -0
  87. package/dist/client/chat-first/copy.js +1 -0
  88. package/dist/client/chat-first/primary-nav.js +1 -1
  89. package/dist/client/chat-first/types.d.ts +1 -0
  90. package/dist/client/resources/McpConnectionSuggestion.js +2 -2
  91. package/dist/client/settings/SettingsTabsPage.d.ts +3 -1
  92. package/dist/client/settings/SettingsTabsPage.js +2 -2
  93. package/dist/client/sse-event-processor.d.ts +8 -0
  94. package/dist/client/sse-event-processor.js +13 -6
  95. package/dist/collab/struct-routes.d.ts +1 -1
  96. package/dist/deploy/build.d.ts +5 -7
  97. package/dist/deploy/build.js +19 -12
  98. package/dist/localization/default-messages.js +1 -1
  99. package/dist/observability/routes.d.ts +3 -3
  100. package/dist/provider-api/actions/provider-api.d.ts +2 -2
  101. package/dist/scripts/call-agent.js +3 -3
  102. package/dist/scripts/describe-workspace-apps.js +1 -1
  103. package/dist/secrets/routes.d.ts +6 -6
  104. package/dist/server/agent-capabilities.js +0 -0
  105. package/dist/server/agent-chat/context-tools.js +1 -1
  106. package/dist/server/agent-chat/prompt-resources.js +1 -1
  107. package/dist/server/agent-chat-plugin.js +1 -1
  108. package/dist/server/auth.js +190 -42
  109. package/dist/server/better-auth-migrations.js +53 -0
  110. package/dist/server/http-response-telemetry.js +7 -1
  111. package/dist/server/onboarding-html.js +119 -33
  112. package/dist/server/transcribe-voice.d.ts +1 -1
  113. package/dist/shared/password-policy.d.ts +2 -1
  114. package/dist/shared/password-policy.js +2 -1
  115. package/dist/styles/agent-conversation.css +20 -3
  116. package/dist/styles/agent-native.css +14 -2
  117. package/dist/styles/blocks.css +132 -0
  118. package/dist/templates/default/app/i18n/ar-SA.ts +1 -1
  119. package/dist/templates/default/app/i18n/de-DE.ts +1 -1
  120. package/dist/templates/default/app/i18n/en-US.ts +1 -1
  121. package/dist/templates/default/app/i18n/es-ES.ts +1 -1
  122. package/dist/templates/default/app/i18n/fr-FR.ts +1 -1
  123. package/dist/templates/default/app/i18n/hi-IN.ts +1 -1
  124. package/dist/templates/default/app/i18n/ja-JP.ts +1 -1
  125. package/dist/templates/default/app/i18n/ko-KR.ts +1 -1
  126. package/dist/templates/default/app/i18n/pt-BR.ts +1 -1
  127. package/dist/templates/default/app/i18n/zh-CN.ts +1 -1
  128. package/dist/templates/default/app/i18n/zh-TW.ts +1 -1
  129. package/dist/templates/default/pnpm-workspace.yaml +1 -0
  130. package/dist/templates/workspace-root/pnpm-workspace.yaml +2 -0
  131. package/docs/content/actions.mdx +4 -1
  132. package/docs/content/agent-surfaces.mdx +8 -6
  133. package/docs/content/automations.mdx +1 -1
  134. package/docs/content/cloneable-saas.mdx +6 -6
  135. package/docs/content/database.mdx +6 -1
  136. package/docs/content/deployment.mdx +10 -8
  137. package/docs/content/docs-components.mdx +22 -14
  138. package/docs/content/drop-in-agent.mdx +1 -1
  139. package/docs/content/environment-variables.mdx +4 -3
  140. package/docs/content/getting-started-actions.mdx +5 -4
  141. package/docs/content/getting-started-pages.mdx +7 -6
  142. package/docs/content/getting-started.mdx +4 -3
  143. package/docs/content/notifications.mdx +6 -6
  144. package/docs/content/progress.mdx +5 -5
  145. package/docs/content/routing.mdx +3 -1
  146. package/docs/content/server-database.mdx +13 -4
  147. package/docs/content/server-overview.mdx +9 -9
  148. package/docs/content/server-plugins.mdx +10 -4
  149. package/docs/content/server-routes.mdx +7 -2
  150. package/docs/content/tracking.mdx +4 -4
  151. package/docs/content/what-is-agent-native.mdx +4 -4
  152. package/package.json +2 -2
  153. package/src/templates/default/app/i18n/ar-SA.ts +1 -1
  154. package/src/templates/default/app/i18n/de-DE.ts +1 -1
  155. package/src/templates/default/app/i18n/en-US.ts +1 -1
  156. package/src/templates/default/app/i18n/es-ES.ts +1 -1
  157. package/src/templates/default/app/i18n/fr-FR.ts +1 -1
  158. package/src/templates/default/app/i18n/hi-IN.ts +1 -1
  159. package/src/templates/default/app/i18n/ja-JP.ts +1 -1
  160. package/src/templates/default/app/i18n/ko-KR.ts +1 -1
  161. package/src/templates/default/app/i18n/pt-BR.ts +1 -1
  162. package/src/templates/default/app/i18n/zh-CN.ts +1 -1
  163. package/src/templates/default/app/i18n/zh-TW.ts +1 -1
  164. package/src/templates/default/pnpm-workspace.yaml +1 -0
  165. package/src/templates/workspace-root/pnpm-workspace.yaml +2 -0
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { getLocaleInitScript } from "../localization/server.js";
10
10
  import { DEFAULT_LOCALE, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, } from "../localization/shared.js";
11
- import { PASSWORD_MIN_LENGTH } from "../shared/password-policy.js";
11
+ import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, } from "../shared/password-policy.js";
12
12
  import { signInJourneyInlineScript } from "../shared/sign-in-journey.js";
13
13
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
14
14
  import { normalizeAppBasePath } from "./app-base-path.js";
@@ -89,7 +89,7 @@ const EN_AUTH_COPY = {
89
89
  sendMagicLink: "Continue",
90
90
  magicLinkSent: "Check your email",
91
91
  magicLinkSentCopy: "We sent a secure sign-in link to",
92
- magicLinkFailed: "Could not send sign-in link.",
92
+ magicLinkFailed: "We couldn't send a sign-in link. Check your email and try again.",
93
93
  usePasswordInstead: "Use a password instead",
94
94
  backToMagicLink: "Use a sign-in link instead",
95
95
  signupProgress: "Signup progress",
@@ -129,31 +129,32 @@ const EN_AUTH_COPY = {
129
129
  legalSuffix: ".",
130
130
  invalidEmail: "Enter a valid email address, like you@example.com.",
131
131
  signInToContinue: "Sign in to continue.",
132
- finishSignInFailed: "Could not finish sign-in automatically.",
132
+ finishSignInFailed: "We couldn't finish signing you in. Please sign in manually.",
133
133
  enterPasswordAfterVerification: "Enter your password after verifying your email.",
134
- finishSignInManually: "We could not finish sign-in automatically. Sign in to continue.",
134
+ finishSignInManually: "We couldn't finish signing you in automatically. Sign in to continue.",
135
135
  stillWaitingVerification: "Still waiting on verification. Click the link in your email, then try Continue again.",
136
- checkVerificationFailed: "Could not check verification. Please try again.",
136
+ checkVerificationFailed: "We couldn't check your verification status. Please try again.",
137
+ verificationLinkInvalid: "This verification link is invalid or expired. Request a new one.",
137
138
  checking: "Checking...",
138
139
  checkingVerification: "Checking your verification...",
139
140
  sending: "Sending...",
140
141
  sent: "Sent",
141
142
  sentVerification: "Sent a fresh verification link.",
142
- resendVerificationFailed: "Could not resend the verification email.",
143
- networkErrorRetry: "Network error. Please try again.",
144
- networkErrorDashRetry: "Network error — please try again",
145
- passwordsMismatch: "Passwords do not match",
143
+ resendVerificationFailed: "We couldn't resend the verification email. Please try again.",
144
+ networkErrorRetry: "We couldn't reach the server. Check your connection and try again.",
145
+ networkErrorDashRetry: "We couldn't reach the server. Check your connection and try again.",
146
+ passwordsMismatch: "Passwords do not match.",
146
147
  creatingAccount: "Creating account…",
147
- registrationFailed: "Registration failed",
148
+ registrationFailed: "We couldn't create your account. Please try again.",
148
149
  accountCreatedSigningIn: "Account created — signing you in…",
149
150
  emailVerifiedFinishing: "Email verified. Finishing sign-in...",
150
151
  emailVerifiedSignIn: "Email verified. Sign in to continue.",
151
152
  resetEmailSent: "If that email exists, a reset link is on its way.",
152
- resetEmailFailed: "Could not send reset email.",
153
+ resetEmailFailed: "We couldn't send a password reset email. Check your email and try again.",
153
154
  signingIn: "Signing in…",
154
- invalidLogin: "Invalid email or password",
155
- googleNotConfigured: "Google OAuth is not configured.",
156
- failedToConnect: "Failed to connect. Please try again.",
155
+ invalidLogin: "The email or password is incorrect.",
156
+ googleNotConfigured: "Google sign-in is not available right now.",
157
+ failedToConnect: "We couldn't connect. Please try again.",
157
158
  migrateLocalFallback: "Continue signing in to migrate local data.",
158
159
  googlePopupHelp: "Allow popups for this site and try again",
159
160
  googleNeverFinished: "Google sign-in did not finish. Check the Google OAuth redirect URI and server logs for [agent-native][google-oauth].",
@@ -236,6 +237,7 @@ const AUTH_LOCALE_COPY = {
236
237
  finishSignInManually: "无法自动完成登录。请登录以继续。",
237
238
  stillWaitingVerification: "仍在等待验证。请点击邮件中的链接,然后再次点击继续。",
238
239
  checkVerificationFailed: "无法检查验证状态。请重试。",
240
+ verificationLinkInvalid: "此验证链接无效或已过期。请重新请求一个。",
239
241
  checking: "正在检查...",
240
242
  checkingVerification: "正在检查验证状态...",
241
243
  sending: "正在发送...",
@@ -336,6 +338,7 @@ const AUTH_LOCALE_COPY = {
336
338
  finishSignInManually: "無法自動完成登入。請登入以繼續。",
337
339
  stillWaitingVerification: "仍在等待驗證。請點擊郵件中的連結,然後再次點擊繼續。",
338
340
  checkVerificationFailed: "無法檢查驗證狀態。請重試。",
341
+ verificationLinkInvalid: "此驗證連結無效或已過期。請重新索取。",
339
342
  checking: "正在檢查...",
340
343
  checkingVerification: "正在檢查驗證狀態...",
341
344
  sending: "正在寄送...",
@@ -436,6 +439,7 @@ const AUTH_LOCALE_COPY = {
436
439
  finishSignInManually: "No se pudo completar el inicio automáticamente. Inicia sesión para continuar.",
437
440
  stillWaitingVerification: "Aún esperamos la verificación. Haz clic en el enlace del email y luego prueba Continuar de nuevo.",
438
441
  checkVerificationFailed: "No se pudo comprobar la verificación. Inténtalo de nuevo.",
442
+ verificationLinkInvalid: "Este enlace de verificación no es válido o ha caducado. Solicita uno nuevo.",
439
443
  checking: "Comprobando...",
440
444
  checkingVerification: "Comprobando tu verificación...",
441
445
  sending: "Enviando...",
@@ -536,6 +540,7 @@ const AUTH_LOCALE_COPY = {
536
540
  finishSignInManually: "Impossible de terminer la connexion automatiquement. Connectez-vous pour continuer.",
537
541
  stillWaitingVerification: "La vérification est toujours en attente. Cliquez sur le lien dans votre e-mail, puis réessayez Continuer.",
538
542
  checkVerificationFailed: "Impossible de vérifier l'état. Veuillez réessayer.",
543
+ verificationLinkInvalid: "Ce lien de vérification est invalide ou expiré. Demandez-en un nouveau.",
539
544
  checking: "Vérification...",
540
545
  checkingVerification: "Vérification en cours...",
541
546
  sending: "Envoi...",
@@ -636,6 +641,7 @@ const AUTH_LOCALE_COPY = {
636
641
  finishSignInManually: "Die Anmeldung konnte nicht automatisch abgeschlossen werden. Melde dich an, um fortzufahren.",
637
642
  stillWaitingVerification: "Die Bestätigung steht noch aus. Klicke auf den Link in deiner E-Mail und versuche Weiter erneut.",
638
643
  checkVerificationFailed: "Bestätigung konnte nicht geprüft werden. Bitte erneut versuchen.",
644
+ verificationLinkInvalid: "Dieser Bestätigungslink ist ungültig oder abgelaufen. Fordere einen neuen an.",
639
645
  checking: "Prüfen...",
640
646
  checkingVerification: "Bestätigung wird geprüft...",
641
647
  sending: "Senden...",
@@ -736,6 +742,7 @@ const AUTH_LOCALE_COPY = {
736
742
  finishSignInManually: "サインインを自動で完了できませんでした。続行するにはサインインしてください。",
737
743
  stillWaitingVerification: "まだ確認待ちです。メール内のリンクをクリックしてから、もう一度続行してください。",
738
744
  checkVerificationFailed: "確認状態をチェックできませんでした。もう一度お試しください。",
745
+ verificationLinkInvalid: "この確認リンクは無効か期限切れです。新しいリンクをリクエストしてください。",
739
746
  checking: "確認中...",
740
747
  checkingVerification: "確認状態をチェック中...",
741
748
  sending: "送信中...",
@@ -836,6 +843,7 @@ const AUTH_LOCALE_COPY = {
836
843
  finishSignInManually: "자동으로 로그인을 완료할 수 없습니다. 계속하려면 로그인하세요.",
837
844
  stillWaitingVerification: "아직 확인을 기다리고 있습니다. 이메일의 링크를 클릭한 뒤 계속을 다시 눌러주세요.",
838
845
  checkVerificationFailed: "확인 상태를 확인할 수 없습니다. 다시 시도하세요.",
846
+ verificationLinkInvalid: "이 인증 링크가 유효하지 않거나 만료되었습니다. 새 링크를 요청하세요.",
839
847
  checking: "확인 중...",
840
848
  checkingVerification: "확인 상태 확인 중...",
841
849
  sending: "보내는 중...",
@@ -936,6 +944,7 @@ const AUTH_LOCALE_COPY = {
936
944
  finishSignInManually: "Não foi possível concluir o login automaticamente. Entre para continuar.",
937
945
  stillWaitingVerification: "Ainda estamos aguardando a verificação. Clique no link do email e tente Continuar novamente.",
938
946
  checkVerificationFailed: "Não foi possível verificar. Tente novamente.",
947
+ verificationLinkInvalid: "Este link de verificação é inválido ou expirou. Solicite um novo.",
939
948
  checking: "Verificando...",
940
949
  checkingVerification: "Verificando sua confirmação...",
941
950
  sending: "Enviando...",
@@ -1036,6 +1045,7 @@ const AUTH_LOCALE_COPY = {
1036
1045
  finishSignInManually: "साइन इन अपने आप पूरा नहीं हो सका। जारी रखने के लिए साइन इन करें।",
1037
1046
  stillWaitingVerification: "सत्यापन का इंतजार है। ईमेल में लिंक खोलें, फिर Continue दोबारा दबाएं।",
1038
1047
  checkVerificationFailed: "सत्यापन जांच नहीं हो सकी। कृपया फिर कोशिश करें।",
1048
+ verificationLinkInvalid: "यह सत्यापन लिंक अमान्य या समाप्त हो गया है। नया लिंक मांगें।",
1039
1049
  checking: "जांच हो रही है...",
1040
1050
  checkingVerification: "आपका सत्यापन जांच रहे हैं...",
1041
1051
  sending: "भेजा जा रहा है...",
@@ -1136,6 +1146,7 @@ const AUTH_LOCALE_COPY = {
1136
1146
  finishSignInManually: "تعذر إكمال تسجيل الدخول تلقائيًا. سجّل الدخول للمتابعة.",
1137
1147
  stillWaitingVerification: "ما زلنا ننتظر التحقق. افتح الرابط في بريدك الإلكتروني ثم جرّب متابعة مرة أخرى.",
1138
1148
  checkVerificationFailed: "تعذر التحقق من الحالة. حاول مرة أخرى.",
1149
+ verificationLinkInvalid: "رابط التحقق هذا غير صالح أو منتهي الصلاحية. اطلب رابطًا جديدًا.",
1139
1150
  checking: "جارٍ التحقق...",
1140
1151
  checkingVerification: "جارٍ التحقق من حالتك...",
1141
1152
  sending: "جارٍ الإرسال...",
@@ -2572,9 +2583,9 @@ ${googleOnly
2572
2583
  <label for="s-email"${i18nAttr("email")}>${esc(t("email"))}</label>
2573
2584
  <input id="s-email" type="email" autocomplete="email" autofocus placeholder="you@example.com" required />
2574
2585
  <label for="s-pass"${i18nAttr("password")}>${esc(t("password"))}</label>
2575
- <input id="s-pass" type="password" autocomplete="new-password" placeholder="${esc(t("passwordMinPlaceholder"))}"${i18nPlaceholderAttr("passwordMinPlaceholder")} required minlength="${PASSWORD_MIN_LENGTH}" />
2586
+ <input id="s-pass" type="password" autocomplete="new-password" placeholder="${esc(t("passwordMinPlaceholder"))}"${i18nPlaceholderAttr("passwordMinPlaceholder")} required minlength="${PASSWORD_MIN_LENGTH}" maxlength="${PASSWORD_MAX_LENGTH}" />
2576
2587
  <label for="s-pass2"${i18nAttr("confirmPassword")}>${esc(t("confirmPassword"))}</label>
2577
- <input id="s-pass2" type="password" autocomplete="new-password" placeholder="${esc(t("confirmPasswordPlaceholder"))}"${i18nPlaceholderAttr("confirmPasswordPlaceholder")} required minlength="${PASSWORD_MIN_LENGTH}" />
2588
+ <input id="s-pass2" type="password" autocomplete="new-password" placeholder="${esc(t("confirmPasswordPlaceholder"))}"${i18nPlaceholderAttr("confirmPasswordPlaceholder")} required minlength="${PASSWORD_MIN_LENGTH}" maxlength="${PASSWORD_MAX_LENGTH}" />
2578
2589
  <button type="submit"${i18nAttr("createAccount")}>${esc(t("createAccount"))}</button>
2579
2590
  ${signupLegalNoteHtml}
2580
2591
  ${signupLocalModeNoteHtml}
@@ -2721,6 +2732,28 @@ ${signInJourneyInlineScript()}
2721
2732
  var fallback = __AN_AUTH_LOCALES[__AN_AUTH_DEFAULT_LOCALE] || {};
2722
2733
  return localized[key] || fallback[key] || key;
2723
2734
  }
2735
+ function __anAuthErrorText(data, fallback) {
2736
+ var candidate = data && (data.error || data.message);
2737
+ if (typeof candidate !== 'string' || !candidate.trim()) return fallback;
2738
+ var message = candidate.trim();
2739
+ if (/failed query|\bselect\b.*\bfrom\b|\binsert\b.*\binto\b|\bupdate\b.*\bset\b|\bdelete\b.*\bfrom\b|\bsql\b|database|relation .* does not exist|column .* does not exist|syntax error|constraint|connection refused|econn|timeout/i.test(message)) {
2740
+ return fallback;
2741
+ }
2742
+ return message;
2743
+ }
2744
+ function __anBindPasswordValidation(input) {
2745
+ if (!input) return;
2746
+ input.addEventListener('invalid', function() {
2747
+ if (input.validity && input.validity.tooShort) {
2748
+ input.setCustomValidity(__anT('passwordMinPlaceholder'));
2749
+ } else if (input.validity && input.validity.tooLong) {
2750
+ input.setCustomValidity('Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.');
2751
+ }
2752
+ });
2753
+ input.addEventListener('input', function() {
2754
+ input.setCustomValidity('');
2755
+ });
2756
+ }
2724
2757
  function __anSetAuthI18nKey(node, key) {
2725
2758
  if (!node || !key) return;
2726
2759
  node.setAttribute('data-i18n', key);
@@ -3275,7 +3308,7 @@ ${identitySsoScript}
3275
3308
  try {
3276
3309
  __anOpenOAuthUrl(__anGoogleAuthUrlPath() + '?' + params.toString());
3277
3310
  } catch(e) {
3278
- __anShowOAuthError(err, btn, 'Could not start Google sign-in redirect' + (flowId ? ' for flow ' + __anFlowDebugId(flowId) : '') + ': ' + (e && e.message ? e.message : 'unknown error'));
3311
+ __anShowOAuthError(err, btn, __anT('failedToConnect'));
3279
3312
  }
3280
3313
  }
3281
3314
  function __anWaitForOAuthExchange(flowId, ret, btn, err) {
@@ -3295,7 +3328,7 @@ ${identitySsoScript}
3295
3328
  }
3296
3329
  if (data && data.error) {
3297
3330
  __anSetOAuthDebug('OAuth exchange returned an error: ' + (data.message || data.error), flowId);
3298
- __anShowOAuthError(err, btn, data.message || data.error);
3331
+ __anShowOAuthError(err, btn, __anAuthErrorText(data, __anT('googleNotConfigured')));
3299
3332
  return;
3300
3333
  }
3301
3334
  if (data && data.pending && (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0)) {
@@ -3538,6 +3571,16 @@ ${googleOnly
3538
3571
  return false;
3539
3572
  }
3540
3573
  }
3574
+ function __anVerificationRedirectError() {
3575
+ try {
3576
+ var params = new URLSearchParams(location.search);
3577
+ return params.get('error') === 'verification_link_invalid'
3578
+ ? __anT('verificationLinkInvalid')
3579
+ : '';
3580
+ } catch (e) { // coercion-ok: malformed query has no verification error to render
3581
+ return '';
3582
+ }
3583
+ }
3541
3584
  function __anShowEmailValidationError(input, msg) {
3542
3585
  if (msg) {
3543
3586
  msg.textContent = __anT('invalidEmail');
@@ -3579,7 +3622,7 @@ ${googleOnly
3579
3622
  console.warn('[auth] Could not parse sign-in response', error);
3580
3623
  return null;
3581
3624
  });
3582
- var error = (data && (data.error || data.message)) || __anT('finishSignInFailed');
3625
+ var error = __anAuthErrorText(data, __anT('finishSignInFailed'));
3583
3626
  return {
3584
3627
  ok: false,
3585
3628
  error: error,
@@ -3702,7 +3745,7 @@ ${googleOnly
3702
3745
  }
3703
3746
  var data = await res.json().catch(function() { return {}; });
3704
3747
  if (msg) {
3705
- msg.textContent = (data && (data.message || data.error)) || __anT('resendVerificationFailed');
3748
+ msg.textContent = __anAuthErrorText(data, __anT('resendVerificationFailed'));
3706
3749
  msg.classList.add('show', 'error');
3707
3750
  }
3708
3751
  if (btn) {
@@ -3722,6 +3765,7 @@ ${googleOnly
3722
3765
  }
3723
3766
  (function initActiveTab() {
3724
3767
  var initial = __AN_AUTH_MODE === 'magic-link' ? 'magicLink' : 'signup';
3768
+ var verificationError = __anVerificationRedirectError();
3725
3769
  try {
3726
3770
  var params = new URLSearchParams(location.search);
3727
3771
  var qp = params.get('tab');
@@ -3731,6 +3775,8 @@ ${googleOnly
3731
3775
  initial = qp;
3732
3776
  } else if (__anIsVerifiedRedirectSuccess()) {
3733
3777
  initial = 'login';
3778
+ } else if (verificationError) {
3779
+ initial = 'login';
3734
3780
  } else if (path === '/login' || path.endsWith('/login')) {
3735
3781
  initial = 'login';
3736
3782
  } else if (path === '/signup' || path.endsWith('/signup')) {
@@ -3742,6 +3788,13 @@ ${googleOnly
3742
3788
  } catch (e) {}
3743
3789
  if (initial === 'magicLink') showMagicLinkForm();
3744
3790
  else setActiveTab(initial, { persist: false });
3791
+ if (verificationError) {
3792
+ var verificationMsg = document.getElementById('l-msg');
3793
+ if (verificationMsg) {
3794
+ verificationMsg.textContent = verificationError;
3795
+ verificationMsg.classList.add('show', 'error');
3796
+ }
3797
+ }
3745
3798
  try {
3746
3799
  if (__anIsVerifiedRedirectSuccess()) {
3747
3800
  var rememberedEmail = readRememberedPendingSignupEmail();
@@ -3784,6 +3837,8 @@ ${googleOnly
3784
3837
  });
3785
3838
 
3786
3839
  var magicLinkForm = document.getElementById('magic-link-form');
3840
+ __anBindPasswordValidation(document.getElementById('s-pass'));
3841
+ __anBindPasswordValidation(document.getElementById('s-pass2'));
3787
3842
  var magicLinkEmail = document.getElementById('m-email');
3788
3843
  if (magicLinkEmail) {
3789
3844
  magicLinkEmail.addEventListener('input', updateMagicLinkSubmitState);
@@ -3820,7 +3875,7 @@ ${googleOnly
3820
3875
  showMagicLinkSuccess(email);
3821
3876
  return;
3822
3877
  }
3823
- msg.textContent = (data && (data.error || data.message)) || __anT('magicLinkFailed');
3878
+ msg.textContent = __anAuthErrorText(data, __anT('magicLinkFailed'));
3824
3879
  msg.classList.add('show', 'error');
3825
3880
  btn.disabled = false;
3826
3881
  btn.textContent = originalLabel;
@@ -3887,7 +3942,7 @@ ${googleOnly
3887
3942
  showVerificationStep(email, pass);
3888
3943
  return;
3889
3944
  }
3890
- msg.textContent = data.error || __anT('registrationFailed');
3945
+ msg.textContent = __anAuthErrorText(data, __anT('registrationFailed'));
3891
3946
  msg.classList.add('show', 'error');
3892
3947
  btn.disabled = false;
3893
3948
  btn.textContent = originalLabel;
@@ -3971,7 +4026,7 @@ ${googleOnly
3971
4026
  return;
3972
4027
  }
3973
4028
  var data = await res.json().catch(function() { return {}; });
3974
- msg.textContent = (data && (data.message || data.error)) || __anT('resetEmailFailed');
4029
+ msg.textContent = __anAuthErrorText(data, __anT('resetEmailFailed'));
3975
4030
  msg.classList.add('show', 'error');
3976
4031
  btn.disabled = false;
3977
4032
  btn.textContent = original;
@@ -4016,7 +4071,7 @@ ${googleOnly
4016
4071
  return;
4017
4072
  }
4018
4073
  var data = await res.json().catch(function() { return {}; });
4019
- msg.textContent = data.error || __anT('invalidLogin');
4074
+ msg.textContent = __anAuthErrorText(data, __anT('invalidLogin'));
4020
4075
  msg.classList.add('show');
4021
4076
  btn.disabled = false;
4022
4077
  btn.textContent = originalLabel;
@@ -4065,7 +4120,7 @@ ${renderGoogleButton
4065
4120
  if (data.url) {
4066
4121
  __anOpenOAuthUrl(data.url);
4067
4122
  } else {
4068
- err.textContent = data.message || __anT('googleNotConfigured');
4123
+ err.textContent = __anAuthErrorText(data, __anT('googleNotConfigured'));
4069
4124
  err.classList.add('show');
4070
4125
  btn.disabled = false;
4071
4126
  __anGoogleSignInInFlight = false;
@@ -4228,9 +4283,9 @@ export function getResetPasswordHtml() {
4228
4283
  <p class="subtitle">Set a new password for your account.</p>
4229
4284
  <form id="reset-form">
4230
4285
  <label for="p1">New password</label>
4231
- <input id="p1" type="password" autocomplete="new-password" autofocus placeholder="At least ${PASSWORD_MIN_LENGTH} characters" required minlength="${PASSWORD_MIN_LENGTH}" />
4286
+ <input id="p1" type="password" autocomplete="new-password" autofocus placeholder="At least ${PASSWORD_MIN_LENGTH} characters" required minlength="${PASSWORD_MIN_LENGTH}" maxlength="${PASSWORD_MAX_LENGTH}" />
4232
4287
  <label for="p2">Confirm password</label>
4233
- <input id="p2" type="password" autocomplete="new-password" placeholder="Confirm password" required minlength="${PASSWORD_MIN_LENGTH}" />
4288
+ <input id="p2" type="password" autocomplete="new-password" placeholder="Confirm password" required minlength="${PASSWORD_MIN_LENGTH}" maxlength="${PASSWORD_MAX_LENGTH}" />
4234
4289
  <button type="submit">Save new password</button>
4235
4290
  <p class="msg" id="msg"></p>
4236
4291
  </form>
@@ -4250,20 +4305,51 @@ export function getResetPasswordHtml() {
4250
4305
  var params = new URLSearchParams(location.search);
4251
4306
  var token = params.get('token') || '';
4252
4307
  var msg = document.getElementById('msg');
4308
+ var resetForm = document.getElementById('reset-form');
4309
+ function resetErrorText(data, fallback) {
4310
+ var candidate = data && (data.error || data.message);
4311
+ if (typeof candidate !== 'string' || !candidate.trim()) return fallback;
4312
+ var message = candidate.trim();
4313
+ if (/failed query|\bselect\b.*\bfrom\b|\binsert\b.*\binto\b|\bupdate\b.*\bset\b|\bdelete\b.*\bfrom\b|\bsql\b|database|relation .* does not exist|column .* does not exist|syntax error|constraint|connection refused|econn|timeout/i.test(message)) {
4314
+ return fallback;
4315
+ }
4316
+ if (/password.*(?:at least|minimum|min(?:imum)?|too short)/i.test(message)) {
4317
+ return 'Choose a password with at least ${PASSWORD_MIN_LENGTH} characters.';
4318
+ }
4319
+ if (/password.*(?:at most|maximum|max(?:imum)?|too long)/i.test(message)) {
4320
+ return 'Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.';
4321
+ }
4322
+ return message;
4323
+ }
4324
+ function bindPasswordValidation(input) {
4325
+ if (!input) return;
4326
+ input.addEventListener('invalid', function() {
4327
+ if (input.validity && input.validity.tooShort) {
4328
+ input.setCustomValidity('Choose a password with at least ${PASSWORD_MIN_LENGTH} characters.');
4329
+ } else if (input.validity && input.validity.tooLong) {
4330
+ input.setCustomValidity('Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.');
4331
+ }
4332
+ });
4333
+ input.addEventListener('input', function() {
4334
+ input.setCustomValidity('');
4335
+ });
4336
+ }
4337
+ bindPasswordValidation(document.getElementById('p1'));
4338
+ bindPasswordValidation(document.getElementById('p2'));
4253
4339
  if (!token) {
4254
- msg.textContent = 'Missing or invalid reset token. Request a new reset link.';
4340
+ msg.textContent = 'This password reset link is missing or invalid. Request a new one.';
4255
4341
  msg.classList.add('show', 'error');
4256
- document.getElementById('reset-form').style.display = 'none';
4342
+ resetForm.style.display = 'none';
4257
4343
  return;
4258
4344
  }
4259
- document.getElementById('reset-form').addEventListener('submit', async function(e) {
4345
+ resetForm.addEventListener('submit', async function(e) {
4260
4346
  e.preventDefault();
4261
4347
  var btn = e.currentTarget.querySelector('button[type="submit"]');
4262
4348
  var p1 = document.getElementById('p1').value;
4263
4349
  var p2 = document.getElementById('p2').value;
4264
4350
  msg.classList.remove('show', 'error', 'success');
4265
4351
  if (p1 !== p2) {
4266
- msg.textContent = 'Passwords do not match';
4352
+ msg.textContent = 'Passwords do not match.';
4267
4353
  msg.classList.add('show', 'error');
4268
4354
  return;
4269
4355
  }
@@ -4283,12 +4369,12 @@ export function getResetPasswordHtml() {
4283
4369
  return;
4284
4370
  }
4285
4371
  var data = await res.json().catch(function() { return {}; });
4286
- msg.textContent = (data && (data.message || data.error)) || 'Reset failed. The link may have expired — request a new one.';
4372
+ msg.textContent = resetErrorText(data, "We couldn't update your password. The link may have expired; request a new one.");
4287
4373
  msg.classList.add('show', 'error');
4288
4374
  btn.disabled = false;
4289
4375
  btn.textContent = original;
4290
4376
  } catch (err) {
4291
- msg.textContent = 'Network error — please try again';
4377
+ msg.textContent = "We couldn't reach the server. Check your connection and try again.";
4292
4378
  msg.classList.add('show', 'error');
4293
4379
  btn.disabled = false;
4294
4380
  btn.textContent = original;
@@ -20,6 +20,6 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- error?: undefined;
24
23
  text: string;
24
+ error?: undefined;
25
25
  }>>;
@@ -1,3 +1,4 @@
1
1
  export declare const PASSWORD_MIN_LENGTH = 12;
2
2
  export declare const PASSWORD_MAX_LENGTH = 128;
3
- export declare const PASSWORD_MIN_LENGTH_MESSAGE = "Password must be at least 12 characters";
3
+ export declare const PASSWORD_MIN_LENGTH_MESSAGE = "Choose a password with at least 12 characters.";
4
+ export declare const PASSWORD_MAX_LENGTH_MESSAGE = "Choose a password with no more than 128 characters.";
@@ -1,3 +1,4 @@
1
1
  export const PASSWORD_MIN_LENGTH = 12;
2
2
  export const PASSWORD_MAX_LENGTH = 128;
3
- export const PASSWORD_MIN_LENGTH_MESSAGE = `Password must be at least ${PASSWORD_MIN_LENGTH} characters`;
3
+ export const PASSWORD_MIN_LENGTH_MESSAGE = `Choose a password with at least ${PASSWORD_MIN_LENGTH} characters.`;
4
+ export const PASSWORD_MAX_LENGTH_MESSAGE = `Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.`;
@@ -43,10 +43,16 @@
43
43
  border-radius: 999px;
44
44
  background: hsl(var(--popover));
45
45
  color: hsl(var(--foreground));
46
- box-shadow: 0 10px 30px hsl(var(--background) / 0.28);
46
+ --agent-shadow: 0 0% 0%;
47
+ --agent-shadow-o: 0.14;
48
+ box-shadow: 0 10px 30px hsl(var(--agent-shadow) / var(--agent-shadow-o));
47
49
  cursor: pointer;
48
50
  }
49
51
 
52
+ .dark .agent-conversation__scroll-bottom {
53
+ --agent-shadow-o: 0.08;
54
+ }
55
+
50
56
  .agent-conversation-message {
51
57
  display: flex;
52
58
  width: 100%;
@@ -638,6 +644,17 @@
638
644
  font-size: 0.875em;
639
645
  }
640
646
 
647
+ .agent-markdown-table-wrap {
648
+ max-width: 100%;
649
+ overflow-x: auto;
650
+ overscroll-behavior-inline: contain;
651
+ }
652
+
653
+ .agent-markdown-table-wrap > table {
654
+ min-width: 100%;
655
+ width: max-content;
656
+ }
657
+
641
658
  .agent-markdown th,
642
659
  .agent-markdown td {
643
660
  border: 1px solid hsl(var(--border, 0 0% 20%));
@@ -653,7 +670,7 @@
653
670
 
654
671
  /* Streaming caret appended after last non-code paragraph while text is live. */
655
672
  .agent-markdown[data-streaming="true"]
656
- > :last-child:not(pre):not(table)::after {
673
+ > :last-child:not(pre):not(table):not(.agent-markdown-table-wrap)::after {
657
674
  content: "";
658
675
  display: inline-block;
659
676
  width: 0.42em;
@@ -678,7 +695,7 @@
678
695
 
679
696
  @media (prefers-reduced-motion: reduce) {
680
697
  .agent-markdown[data-streaming="true"]
681
- > :last-child:not(pre):not(table)::after {
698
+ > :last-child:not(pre):not(table):not(.agent-markdown-table-wrap)::after {
682
699
  animation: none;
683
700
  opacity: 0.28;
684
701
  }
@@ -309,7 +309,9 @@
309
309
  .agent-sidebar-panel[data-agent-sidebar-animation="drawer"] {
310
310
  overflow: clip;
311
311
  will-change: transform;
312
- box-shadow: -12px 0 30px hsl(var(--foreground) / 0.08);
312
+ --agent-shadow: 0 0% 0%;
313
+ --agent-shadow-o: 0.14;
314
+ box-shadow: -12px 0 30px hsl(var(--agent-shadow) / var(--agent-shadow-o));
313
315
  transition:
314
316
  transform 260ms var(--ease-drawer),
315
317
  width 260ms var(--ease-drawer);
@@ -329,14 +331,22 @@
329
331
  }
330
332
 
331
333
  .agent-sidebar-panel[data-agent-sidebar-animation="mobile"] {
334
+ --agent-shadow: 0 0% 0%;
335
+ --agent-shadow-o: 0.14;
332
336
  transform: var(
333
337
  --agent-sidebar-closed-transform,
334
338
  translateX(calc(100% + 1px))
335
339
  );
336
340
  will-change: transform;
341
+ box-shadow: 0 18px 40px hsl(var(--agent-shadow) / var(--agent-shadow-o));
337
342
  transition: transform 260ms var(--ease-drawer);
338
343
  }
339
344
 
345
+ .dark .agent-sidebar-panel[data-agent-sidebar-animation="drawer"],
346
+ .dark .agent-sidebar-panel[data-agent-sidebar-animation="mobile"] {
347
+ --agent-shadow-o: 0.08;
348
+ }
349
+
340
350
  .agent-sidebar-panel[data-agent-sidebar-animation="mobile"][data-agent-sidebar-state="open"] {
341
351
  transform: translateX(0);
342
352
  }
@@ -1079,7 +1089,9 @@
1079
1089
  }
1080
1090
 
1081
1091
  ::view-transition-old(agent-native-chat),
1082
- ::view-transition-new(agent-native-chat) {
1092
+ ::view-transition-new(agent-native-chat),
1093
+ ::view-transition-old(agent-native-sidebar-drawer),
1094
+ ::view-transition-new(agent-native-sidebar-drawer) {
1083
1095
  /* The default `block-size: auto` scales each snapshot by width, so as the
1084
1096
  panel narrows (896 -> 380) its captured height shrinks and the
1085
1097
  bottom-pinned chat field gets dragged upward (the "rises to half-page"
@@ -1333,6 +1333,138 @@
1333
1333
  direction: inherit;
1334
1334
  }
1335
1335
 
1336
+ /* Diagram arrows are geometry, not text glyphs. The clean path draws these
1337
+ shapes with CSS; sketchy mode replaces them with the rough.js paths below. */
1338
+ .plan-diagram-frame :is(.diagram-arrow[data-arrow]) {
1339
+ position: relative;
1340
+ display: inline-block;
1341
+ flex: 0 0 28px;
1342
+ width: 28px;
1343
+ height: 24px;
1344
+ min-width: 28px;
1345
+ font-size: 0 !important;
1346
+ line-height: 1;
1347
+ }
1348
+
1349
+ .plan-diagram-frame .diagram-arrow[data-arrow]::before,
1350
+ .plan-diagram-frame .diagram-arrow[data-arrow]::after {
1351
+ position: absolute;
1352
+ display: block;
1353
+ content: "";
1354
+ pointer-events: none;
1355
+ }
1356
+
1357
+ .plan-diagram-frame
1358
+ :is(
1359
+ .diagram-arrow[data-arrow="right"],
1360
+ .diagram-arrow[data-arrow="left"]
1361
+ )::before {
1362
+ top: calc(50% - 0.75px);
1363
+ left: 3px;
1364
+ width: 22px;
1365
+ height: 1.5px;
1366
+ background: currentColor;
1367
+ }
1368
+
1369
+ .plan-diagram-frame
1370
+ :is(
1371
+ .diagram-arrow[data-arrow="up"],
1372
+ .diagram-arrow[data-arrow="down"]
1373
+ )::before {
1374
+ top: 2px;
1375
+ left: calc(50% - 0.75px);
1376
+ width: 1.5px;
1377
+ height: 20px;
1378
+ background: currentColor;
1379
+ }
1380
+
1381
+ .plan-diagram-frame .diagram-arrow[data-arrow="right"]::after,
1382
+ .plan-diagram-frame .diagram-arrow[data-arrow="left"]::after,
1383
+ .plan-diagram-frame .diagram-arrow[data-arrow="up"]::after,
1384
+ .plan-diagram-frame .diagram-arrow[data-arrow="down"]::after {
1385
+ width: 7px;
1386
+ height: 7px;
1387
+ border-top: 1.5px solid currentColor;
1388
+ border-right: 1.5px solid currentColor;
1389
+ }
1390
+
1391
+ .plan-diagram-frame .diagram-arrow[data-arrow="right"]::after {
1392
+ top: calc(50% - 4px);
1393
+ right: 2px;
1394
+ transform: rotate(45deg);
1395
+ }
1396
+
1397
+ .plan-diagram-frame .diagram-arrow[data-arrow="left"]::after {
1398
+ top: calc(50% - 4px);
1399
+ left: 2px;
1400
+ transform: rotate(225deg);
1401
+ }
1402
+
1403
+ .plan-diagram-frame .diagram-arrow[data-arrow="up"]::after {
1404
+ top: 0;
1405
+ left: calc(50% - 4px);
1406
+ transform: rotate(-45deg);
1407
+ }
1408
+
1409
+ .plan-diagram-frame .diagram-arrow[data-arrow="down"]::after {
1410
+ bottom: 0;
1411
+ left: calc(50% - 4px);
1412
+ transform: rotate(135deg);
1413
+ }
1414
+
1415
+ .plan-diagram-frame .diagram-arrow[data-arrow="both"]::before {
1416
+ top: calc(50% - 0.75px);
1417
+ left: 3px;
1418
+ width: 22px;
1419
+ height: 1.5px;
1420
+ background: currentColor;
1421
+ }
1422
+
1423
+ .plan-diagram-frame .diagram-arrow[data-arrow="both"]::after {
1424
+ inset: 3px;
1425
+ background: currentColor;
1426
+ clip-path: polygon(
1427
+ 0 50%,
1428
+ 22% 0,
1429
+ 22% 38%,
1430
+ 78% 38%,
1431
+ 78% 0,
1432
+ 100% 50%,
1433
+ 78% 100%,
1434
+ 78% 62%,
1435
+ 22% 62%,
1436
+ 22% 100%
1437
+ );
1438
+ }
1439
+
1440
+ .plan-diagram-frame .diagram-arrow[data-arrow="refresh"]::before {
1441
+ top: 3px;
1442
+ left: 5px;
1443
+ width: 16px;
1444
+ height: 16px;
1445
+ border: 1.5px solid currentColor;
1446
+ border-left-color: transparent;
1447
+ border-radius: 50%;
1448
+ }
1449
+
1450
+ .plan-diagram-frame .diagram-arrow[data-arrow="refresh"]::after {
1451
+ top: 1px;
1452
+ right: 2px;
1453
+ width: 0;
1454
+ height: 0;
1455
+ border-right: 4px solid transparent;
1456
+ border-bottom: 7px solid currentColor;
1457
+ border-left: 4px solid transparent;
1458
+ transform: rotate(35deg);
1459
+ }
1460
+
1461
+ .plan-diagram-frame[data-style="sketchy"][data-rough-ready]
1462
+ .diagram-arrow[data-arrow]::before,
1463
+ .plan-diagram-frame[data-style="sketchy"][data-rough-ready]
1464
+ .diagram-arrow[data-arrow]::after {
1465
+ opacity: 0;
1466
+ }
1467
+
1336
1468
  .plan-diagram-frame[data-frame="show"] .plan-diagram-frame-content {
1337
1469
  padding: 0;
1338
1470
  }