diff --git a/apps/widget-whatsapp/src/i18n/en.ts b/apps/widget-whatsapp/src/i18n/en.ts
index 14659f1b..af6f8a3f 100644
--- a/apps/widget-whatsapp/src/i18n/en.ts
+++ b/apps/widget-whatsapp/src/i18n/en.ts
@@ -20,21 +20,15 @@ export const EN: Record = {
'card.refresh.name': 'Refresh status',
'card.refresh.desc': 'Re-check whether WhatsApp is linked',
'card.refresh.in-flight': 'Checking…',
- 'card.warning.name': 'Read before linking',
- 'card.warning.desc': 'Important information about risks — tap to open',
- 'warning.title': 'Read before linking WhatsApp',
+ 'warning.title': 'Important before linking WhatsApp',
'warning.body-1':
'Mautrix-whatsapp connects to your account through the same linked-device mechanism as WhatsApp Web. Technically a standard API — but unlike other messengers, WhatsApp’s terms of service explicitly forbid connecting through third-party clients, and Meta may ban your account for it.',
'warning.body-2':
'WhatsApp bans are regular and unpredictable — Meta does not publish criteria. For some users the bridge works for years without issue; for others the account is banned within hours of linking.',
'warning.tos-label': 'WhatsApp terms of service:',
'warning.tos-url': 'https://www.whatsapp.com/legal/terms-of-service',
- 'warning.close': 'Got it',
- 'warning.aria-close': 'Close warning',
- 'warning.about-callout':
- '⚠ Before linking WhatsApp, read the “Read before linking” card on the bot’s main screen.',
'card.about.name': 'How the WhatsApp bot works',
- 'card.about.desc': 'Sign-in, safety, and source code',
+ 'card.about.desc': 'How it works and the risks — tap to read',
'about.title': 'About the WhatsApp bot',
'about.body-1':
'This bot connects WhatsApp to Vojo. After sign-in, your private chats and groups from WhatsApp will appear in Vojo’s chat list, and replies from the Vojo app will be sent to your contacts as normal WhatsApp messages.',
diff --git a/apps/widget-whatsapp/src/i18n/ru.ts b/apps/widget-whatsapp/src/i18n/ru.ts
index c8ef490a..04a2d54e 100644
--- a/apps/widget-whatsapp/src/i18n/ru.ts
+++ b/apps/widget-whatsapp/src/i18n/ru.ts
@@ -35,40 +35,27 @@ export const RU = {
'card.refresh.name': 'Обновить статус',
'card.refresh.desc': 'Перепроверить, привязан ли WhatsApp',
'card.refresh.in-flight': 'Проверяю…',
- // --- Warning card (WhatsApp-specific) ---------------------------------
- // Карточка-предупреждение ставится ТОЛЬКО для WhatsApp в каталоге
- // Vojo, потому что у WhatsApp ToS прямо запрещает подключение
- // через сторонние клиенты и Meta это активно энфорсит. Сравнения с
- // Telegram/Discord В ИНТЕРФЕЙСЕ намеренно НЕТ: Telegram user ToS
- // (telegram.org/tos) такого ограничения вообще не упоминает, а
- // Discord — отдельный кейс. Делать сравнение в копии = вводить
- // юзера в заблуждение, поэтому warning-модалка говорит ТОЛЬКО про
- // WhatsApp/Meta и ссылается ТОЛЬКО на Meta ToS.
+ // --- About panel -------------------------------------------------------
+ // WhatsApp-only Meta-ToS risk disclosure is folded into the About
+ // modal as an amber callout at the top of the body. The AboutCard
+ // itself carries `command-card warn` (amber border + amber name)
+ // and a triangle warning glyph in the lead slot — instead of the
+ // info-circle TG / Discord use — so the «риски» half of the hybrid
+ // description («о работе и рисках») is visible at a glance before
+ // the user opens the modal. TG / Discord get the plain «вход,
+ // безопасность, исходный код» variant because they don't carry an
+ // account-loss risk in the same way (Telegram user ToS doesn't
+ // forbid third-party clients; Discord's restriction on self-bots
+ // lives in developer policies, not user ToS proper). The amber
+ // block keeps the unique WhatsApp framing without claiming anything
+ // about TG / Discord by comparison.
//
- // ToS reference: https://www.whatsapp.com/legal/terms-of-service
- // секция «Harm To WhatsApp Or Our Users» запрещает «software or
- // APIs that function substantially the same as our Services» и
+ // ToS reference for the body: https://www.whatsapp.com/legal/terms-of-service
+ // section «Harm To WhatsApp Or Our Users» forbids «software or
+ // APIs that function substantially the same as our Services» and
// «accounts for our Services through unauthorized or automated
// means».
- // Triangle glyph lives in the icon slot to the LEFT — don't repeat
- // it in the title text or it doubles up («⚠ ⚠ Прочтите...»).
- 'card.warning.name': 'Прочтите перед подключением',
- // Two-line desc: hint + explicit «click here to read» so the user
- // doesn't stare at the card wondering if it's interactive (the
- // amber tone helps signal it's special, but doesn't tell you it's
- // a button).
- 'card.warning.desc': 'Важная информация о рисках — нажмите, чтобы открыть',
'warning.title': 'Важно знать до подключения WhatsApp',
- // Два информационных параграфа: что технически делает мост и
- // почему это под риском, и насколько риск реален. Сравнение
- // с другими мессенджерами оставлено НЕЯВНЫМ («в отличие от других
- // мессенджеров») — без явного перечисления TG/Discord, потому что
- // у Telegram user ToS (telegram.org/tos) запрета на сторонние
- // клиенты нет вообще, у Discord ToS тоже нет (запрет self-bot'ов
- // живёт у них в developer policies, не в ToS proper). Прямой
- // формальный запрет в ToS есть ТОЛЬКО у WhatsApp; общая фраза
- // «в отличие от других мессенджеров» подчёркивает уникальность
- // WhatsApp без неточностей в адрес конкретных сервисов.
'warning.body-1':
'Mautrix-whatsapp подключает ваш аккаунт через тот же механизм связанных устройств, что и WhatsApp Web. Технически это стандартный API — но в отличие от других мессенджеров, условия использования WhatsApp прямо запрещают подключение через сторонние клиенты, и Meta может заблокировать аккаунт за это.',
'warning.body-2':
@@ -79,17 +66,12 @@ export const RU = {
// src/app/features/bots/BotWidgetEmbed.ts).
'warning.tos-label': 'Условия использования WhatsApp:',
'warning.tos-url': 'https://www.whatsapp.com/legal/terms-of-service',
- 'warning.close': 'Понятно',
- 'warning.aria-close': 'Закрыть предупреждение',
- // Короткий callout в About-модале — пойнтер на отдельную карточку
- // с предупреждением. Объяснение «почему» живёт в самой модалке
- // warning'а; здесь — только указание куда смотреть, чтобы About
- // не дублировал warning по сути.
- 'warning.about-callout':
- '⚠ Перед подключением WhatsApp прочтите карточку «Прочтите перед подключением» на главном экране бота.',
- // --- About panel -------------------------------------------------------
'card.about.name': 'Как работает WhatsApp-бот',
- 'card.about.desc': 'Вход, безопасность и исходный код',
+ // Hybrid copy: tells the user the modal carries BOTH the «как
+ // работает» explainer AND the Meta-ToS risk disclosure. «нажмите,
+ // чтобы прочесть» reinforces interactivity — the amber border +
+ // warning triangle help but the explicit verb seals it.
+ 'card.about.desc': 'Информация о работе и рисках — нажмите, чтобы прочесть',
'about.title': 'О боте WhatsApp',
'about.body-1':
'Этот бот подключает WhatsApp к Vojo. После входа личные чаты и группы из WhatsApp появятся в списке чатов Vojo, а ответы из приложения Vojo будут отправляться собеседникам как обычные сообщения в WhatsApp.',
diff --git a/apps/widget-whatsapp/src/styles.css b/apps/widget-whatsapp/src/styles.css
index 3ae9c48c..591ce0fb 100644
--- a/apps/widget-whatsapp/src/styles.css
+++ b/apps/widget-whatsapp/src/styles.css
@@ -319,11 +319,14 @@ body {
display: block;
}
-/* Spin the chevron icon while the card is in its `refreshing` in-flight
- * state. Combined with `disabled` (which dims the card to opacity 0.5 and
- * gates :hover via :not(:disabled)), the spinner is the unambiguous «I'm
- * working» signal — no more guessing whether the click registered. */
-.command-card.refreshing .command-card-chevron svg {
+/* Spin the leading refresh icon while the card is in its `refreshing`
+ * in-flight state. Combined with `disabled` (which dims the card to
+ * opacity 0.5 and gates :hover via :not(:disabled)), the spinner is
+ * the unambiguous «I'm working» signal — no more guessing whether the
+ * click registered. The selector targets the leading icon slot since
+ * the refresh card moved its glyph from the chevron (right) to the
+ * lead slot (left) for parity with every other card. */
+.command-card.refreshing .command-card-lead-icon svg {
animation: command-card-spin 0.8s linear infinite;
}
@keyframes command-card-spin {
@@ -424,45 +427,45 @@ body {
border-color: var(--rose);
}
-/* Warning card — WhatsApp-specific Meta-ToS account-ban risk disclosure.
- * Sized like every other card in the grid (auto-fill column on
- * desktop, full-width on mobile) — visually distinguished from peers
- * by amber tint + border, NOT by spanning the full row. The earlier
- * full-width version was visually overweight on a wide desktop grid.
- * Amber tint on every layer of chrome (border, name, background)
- * without going as loud as `.danger` — this isn't destructive, it's
- * «read this before you act». */
+/* Generic leading-icon slot — every command-card carries one as a
+ * left-side semantic glyph (mirror of the right-side chevron). The
+ * SVG picks up `currentColor` so it tints with the card's modifier
+ * — muted by default, amber inside `.command-card.warn`, rose-ish
+ * inheritance left intentionally OFF for `.danger` (only the title
+ * goes rose; the lead icon stays muted to keep one accent per card). */
+.command-card-lead-icon {
+ flex-shrink: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--muted);
+}
+.command-card-lead-icon svg {
+ width: 20px;
+ height: 20px;
+ display: block;
+}
+
+/* Warn variant — WhatsApp-only, applied to the AboutCard so the amber
+ * border, amber-tinted name, and amber lead icon together signal that
+ * the modal behind this card carries a Meta-ToS risk disclosure (in
+ * addition to the «how it works» copy). The hybrid card description
+ * («о работе и рисках») depends on this visual cue to feel honest. */
.command-card.warn {
- /* Slight amber tint on the surface itself so the eye can't slide
- * past the card on a quick scan; the border underlines it. */
background: rgba(212, 184, 138, 0.06);
border-color: var(--amber);
}
.command-card.warn .command-card-name {
color: var(--amber);
}
+.command-card.warn .command-card-lead-icon {
+ color: var(--amber);
+}
:root[data-input='mouse'] .command-card.warn:hover:not(:disabled) {
background: rgba(212, 184, 138, 0.12);
border-color: var(--amber);
}
-/* Icon slot to the LEFT of the title block — distinct from the chevron
- * which is on the right. The triangle SVG picks up `currentColor` from
- * the parent's amber tint so it stays in palette without a separate
- * fill rule. */
-.command-card-warn-icon {
- flex-shrink: 0;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- color: var(--amber);
-}
-.command-card-warn-icon svg {
- width: 22px;
- height: 22px;
- display: block;
-}
-
/* Inline confirm-in-place body for the destructive logout card. The button
* group lives inside the same card frame — no modal, no layout shift. */
.command-card-confirm {
@@ -1061,43 +1064,48 @@ body {
border-top: 1px solid var(--divider);
}
-/* WhatsApp-only: Meta-ToS callout that prepends the About body. Same
- * tone as `.section-warn-banner` — amber tint + border, distinct
- * shape from the body paragraphs around it so it doesn't blend in.
+/* WhatsApp-only: Meta-ToS risk-disclosure callout at the top of the
+ * About modal body. Amber tint + border distinguish it from the plain
+ * paragraphs that follow — same visual language the dedicated warning
+ * card used to carry on the disconnected screen, now folded inline.
*
- * Selector specificity note: `.about-body p { color: var(--text) }`
- * (specificity 0,1,1) wins over a bare `.about-warn-callout` rule
- * (0,1,0), so the callout's amber `color` would silently lose. Pin
- * the callout selector inside `.about-body p.about-warn-callout`
- * (0,2,1) to outscore the descendant rule. Background and border
- * weren't affected because no competing rule sets them on `.about-body p`. */
-.about-body p.about-warn-callout {
- background: rgba(212, 184, 138, 0.10);
+ * Body text inside the callout still picks up the about-body's
+ * `.about-body p` rule (default text colour), which is intentional:
+ * only the title is amber-tinted, the paragraphs stay readable. */
+.about-warn-callout {
+ background: rgba(212, 184, 138, 0.08);
border: 1px solid var(--amber);
border-radius: 8px;
- padding: 10px 12px;
- color: var(--amber);
+ padding: 12px 14px;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
/* Keep the about-body's `gap: 12px` honoured (no extra margin). */
}
-/* Warning modal — same chrome as About modal but with an amber-tinted
- * header to make the dialog's purpose visible at a glance. The icon
- * sits to the left of the title; the close-X stays on the right. */
-.about-panel-warn {
- border-color: var(--amber);
+.about-warn-callout-head {
+ display: flex;
+ align-items: center;
+ gap: 10px;
}
-.about-header-warn {
- background: rgba(212, 184, 138, 0.08);
-}
-.about-header-icon {
+
+.about-warn-callout-icon {
flex-shrink: 0;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--amber);
}
-.about-header-icon svg {
- width: 22px;
- height: 22px;
+.about-warn-callout-icon svg {
+ width: 20px;
+ height: 20px;
display: block;
}
+
+.about-warn-callout-title {
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--amber);
+ margin: 0;
+ line-height: 1.3;
+}