Pós-registro & Auth — fluxo regulatório e dedup de bursts
Novo hook useAfterRegisterFlow (app/hooks/useAfterRegisterFlow.ts) orquestra o pós-registro: abre o modal de depósito uma vez, logo após o cadastro, bypassando o throttle de 12h do useAutoDepositModal. Replica o handleOpenRegisterStrategy → openModal('deposit') do handleSuccessRegister legado em Vue. Suporta o ramo regulatório (espera o LimitsStep do ValidationBlockerOverlay resolver antes de abrir o depósito) e suprime quando há ?deposit=<campaign> na URL, conta restrita ou featuresConfig.autoDepositAfterRegister === false.
Store app/store/onboarding.ts (Zustand, não persistida) carrega o sinal justRegistered + lastPrudentialLimitActive entre o sucesso do RegisterModal e o próximo render do DefaultLayout. Reset automático no logout.
Forward de user_prudential_limit_active no payload de signup (/bff/register-simplified, /auth/register): sinaliza ao BFF qual botão regulatório o usuário clicou ("Quero definir meus limites agora" vs "Continuar sem limites"). Nova feature flag autoDepositAfterRegister propagada nos 13 overrides de brand.
Dedup cross-request de /auth/user-profile em app/services/auth.server.ts: cache token-scoped com TTL de 10s + cap de 100 entradas (chave = SHA-256 hex do token, evita expor token cru em dumps de memória). Resolve o burst pós-login onde POST /api/auth/login, useAuthProfileSync → GET /api/auth/profile e revalidator.revalidate() → _layout loader pegavam três Requests distintos com o mesmo token — o WeakMap<Request> antigo não conseguia deduplicar.
/api/auth/profile agora consome getAuthForRequest em vez de chamar createAuthFromClient direto, herdando automaticamente o cache acima. PRs touch-up em 20+ componentes (UserSummaryHeader, ValidationContextGate, GameIframe, payments, protection, validation steps) que liam useProfile() ad-hoc.
refreshProfile() após depósito (PR #674) — opt-in via flag refreshProfileAfterDeposit em 7k-bet-br, cassino-bet-br, vera-bet-br apenas. Faz refetch do profile assim que o depósito fecha pra que ftd_value/ftd_date saiam de 0 imediatamente após o FTD, destravando features gateadas (minigames diários, FTD cashback) sem reload. Disparo do tracking acontece antes do refresh pra preservar o sinal de FTD. Demais brands não recebem a flag (ruído removido dos overrides).
Botão "Já paguei" oculto no resultado Pix (PR #677) — feature flag hidePixAlreadyPaidButton ativa em 7k-bet-br, cassino-bet-br, vera-bet-br. Usuário fica preso no fluxo "aguardando confirmação real do BFF" em vez de poder forçar o onApproved manualmente.
Toggle de marketing sincronizado com store (PR #680) — MarketingSection agora deriva accepted direto de useAccountsStore (era useState local que só semeava no mount → mostrava valor stale ao navegar fora e voltar). Adiciona feedback de save via sonner toast e trata erro com extractApiError. Strings novas em pt-br/es/en no namespace user.
Cassino — banner regulamentado, promoções, layout do card
Side CTA de "Plataforma Regulamentada" agora rola até o footer em vez de navegar (PR #670). Novo type action: "scroll-to-footer" em HomeBannerSideCta — mutualmente exclusivo com link. SideCtaCard usa <button> em vez de <Link>, faz scrollIntoView({ behavior: "smooth" }) no <footer id="page-footer"> (fallback window.scrollTo(bottom)). Footer agora carrega o id="page-footer" em FooterDefault e FooterStacked. Aplicado em cassino-bet-br via override do home-banner.ts.
Cards de promoção sem crop em cassino-bet-br (PR #681) — novo override widgets/post-card.ts força thumbAspect: "ultrawide" (5:2), espelhando o precedente do 7k-bet-br. Banners promocionais saem em ~2.44:1 com logo + disclaimer "Aposta não é investimento" no lado direito; o default 16:9 cropava essa região.
Game card mais denso em mobile (PR #673) — GameCarousel ajusta largura compacta (w-[118px] em mobile) e regular; BalloonIcon reduz pra w-3.5 h-3.5 em mobile (mantém sm:w-5 sm:h-5 em desktop); chip de stat ganha gap-1 em mobile (sm:gap-1.5 em desktop).
PageDescription permite scroll (PR #682) — quando expandida, vira max-h-[80vh] overflow-y-auto (antes max-h-max sem clamp). Descrições SEO longas na home não estouram mais o viewport.
Vai sem sanitizeTrackingValue — lastclick é tratado como ID opaco do parceiro Clever, que pode usar formatos com strings da blocklist (document, appendChild, macros {macro}/__CLICKID__). Sanitizar mutilava IDs e quebrava atribuição.
Resolve por params.getAll("utm_source") pegando o último valor (handles ?utm_source=a&utm_source=b), em vez de params.get() que pega o primeiro.
Fallback usa último valor da primeira key (paridade com Object.values(searchParams)[0] + Array.isArray ? .last : . do legado).
Clever-02 — Set-Cookie cross-site + cookies legacy individuais (PR #685, follow-up do clever-01 de 25/04). captureTrackingFromRequest agora retorna setCookies: string[] (plural) com o cookie_tracking+ cookies individuais legacy (src, utm_source, utm_campaign, utm_content, utm_medium, gclid, fbclid, etc.) emitidos como Set-Cookie separados. Em HTTPS, todos viram SameSite=None; Secure pra que validators de afiliado/anúncio enxerguem o cookie em chains cross-site (HTTP local cai em SameSite=Lax porque o browser rejeita None sem Secure). Loaders app/root.tsx e app/routes/clever.ts propagam setCookies em vez de setCookie único.
AppsFlyer S2S restrito a mobile browser fora de TWA (PR #675). Antes disparava em qualquer App Mode (?app=true); agora exige (1) UA de phone + (2) NÃO estar em TWA. Razão: as APKs Android do 7k/cassino/vera já reportam lead/dep/rebill via SDK nativo (InAppEvents.logEvent) — disparar S2S no WebView por cima dobrava todo evento no dashboard AppsFlyer. Captura de appsflyer_id/advertising_id/app_version da URL roda incondicional pra cobrir o caso "usuário sai da APK pro browser mid-session".
Autoexclusão permanente: -1 (front) → 99 (BFF) (PR #671). Front novo adotou -1 como convenção interna pra "permanente" (alinhado com SELF_EXCLUSION_MONTHS_OPTIONS em @cactus-agents/accounts e isPermanentExclusion); BFF rejeita 0/negativos com "user exclusion deve ser pelo menos 1" e exige 99 (convenção do legado Vera). Boundary fica no proxy app/routes/api/user/self-exclusion.ts via toBffExclusionValue() — callers podem continuar passando -1 sem precisar lembrar da regra.
Privacy HTML legado pras brands ANA Gaming (PR #652) — 7k-bet-br, cassino-bet-br, vera-bet-br ganham overrides próprios de app/config/legal/pages.ts com versões terms=5.0, privacy=2.0, demais=4.0 (espelhando o versionText do Terms.vue legado). Brands não-ANA caem no fallback "1.0" do loader (pageConfig.version ?? "1.0"). Tabela de privacy renderiza responsiva em mobile (linhas empilham, sem scroll horizontal). Flag useStaticPrivacyTerm removida das 11 brands não-target (ruído).
Vera referral — copy persuasiva + CTA pra jogos elegíveis (PR #669). overrides/vera-bet-br/app/config/referral/v1.ts ganha minBetAmount: 200, providerName: "PG Soft", eligibleGamesPath: "/cassino/categoria/indique-amigos". Copy vinda do pt-br.json:608 legado ("girar o mínimo de R$200,00 em jogos selecionados da PG Soft").