Novo evento Mixpanel Deposit Requested (useAnalytics.trackDepositRequested) disparado quando /wallet/add-credit retorna 200 OK. Espelha o legado DefaultLayout.vue das brands 7k/cassino/vera (props Amount em unidades inteiras + DepositMethod). Continua complementar ao evento de funil já existente (pix_generated no GTM e PixGenerated no Facebook).
Bugfix crítico nos eventos S2S do AppsFlyer (sendRegister, sendFTD, sendRebill). Os três estavam dentro do guard if (!shouldLoadTrackers) return do useAnalytics, mas o gate é o inverso do gate do AppsFlyer (shouldLoadTrackers = !isAppMode && !isBot, useAppsFlyer.ready = enabled && isAppMode) — resultado: nenhuma das chamadas server-to-server disparava nem na web (gate externo bloqueia) nem dentro do APK (early return do gate externo cortava o caminho). Agora as três chamadas são disparadas antes do guard e o S2S funciona em produção. Coberto por useAppsFlyer.test.ts (202 linhas) e useAppMode.test.ts (72 linhas).
useAppMode agora reconhece ?is_twa=true além de ?app=true. Os APKs em produção da família 7k/cassino/vera (publicados antes do rename do query param) continuam injetando o legado em cada landing — sem isso isAppMode ficava false pra users do app e desativava todo o pipeline de tracking S2S silenciosamente.
Valor do deposit GTM corrigido pra unidades inteiras (amountCents / 100) ao invés de cents puros — paridade com o legado e com a expectativa dos dashboards de BI.
Sitemap monolítico fatiado em sub-sitemaps temáticos (feat/sitemap-split-and-index): sitemap.xml virou índice e aponta pra sitemap-static.xml, sitemap-games.xml, sitemap-categories.xml, sitemap-providers.xml, sitemap-promotions.xml, sitemap-blog.xml e sitemap-faq.xml. Sub-sitemaps só aparecem no índice quando a brand tem conteúdo correspondente — evita Googlebot descobrir filhos vazios. Sharding automático em sitemap-games.xml quando passa de 45k URLs (computeShardCount).
Origem do <loc> agora vem do request.url ao invés de ORIGIN_DOMAIN (fix/sitemap-origin-from-request-host). A env aponta pro domínio canônico da brand (compartilhado entre prod e stage), então o sitemap de stage estava listando URLs de produção e ficava inútil pra QA. Agora prod aponta pra https://7k.bet.br, stage pra https://stage.7k.bet.br, dev pra http://localhost:5173. Fallback pra ORIGIN_DOMAIN apenas quando request.url falha — caso patológico em workers Cloudflare.
robots.txt bloqueia indexação em hosts não-prod — stage e dev disparam Disallow: / enquanto o domínio canônico fica liberado.
Stylesheet XSL (public/sitemap.xsl, 391 linhas) adicionada pra renderizar o sitemap legível em browser.
Listing de categoria/provider agora é híbrido (perf/games-listing-infinite-scroll-search-ux): catálogos com total <= 120 jogos (90%+ dos casos) seguem 100% client-side com filter reativo sub-segundo; categorias maiores recebem só a primeira batch via SSR e completam por infinite-scroll usando os novos endpoints /api/games/category/:slug e /api/games/provider/:slug (offset/limit, default 48). Cutoff e batch size centralizados em useHybridGamesList (329 linhas, 287 linhas de teste).
Hook useStatsBatchHydration + endpoint /api/games/stats-batch alimenta o store reativo de stats sem bloquear a primeira pintura.
Search com debounce de 250ms server-side quando em modo paginado; folding de diacríticos via foldForSearch do core mantém paridade entre filter local e server.
NavigationLoader/ProgressBar/Spinner ajustados pra refletir corretamente navegações dentro do mesmo route (filter, infinite-scroll) via novo hook useIsRouteNavigation.
Página /cassino/categoria/all ganha PageDescription específico via override casino.category:todos-os-jogos (fix/all-games-landing-seo-and-canonical-slug). Antes a SEO copy era pulada (pageDescription = null) só pra "all", deixando a landing órfã. Agora o resolver usa o slug canônico todos-os-jogos como chave do override, valendo tanto pro alias legado /cassino/categoria/all quanto pra URL canônica /cassino/categoria/todos-os-jogos.
Helpers CANONICAL_ALL_GAMES_SLUG, isAllGamesSlug e resolveCategorySlug centralizados em app/utils/casino-categories.ts — qualquer caller que precise resolver "all games" passa a usar o mesmo trio (filter bar, breadcrumbs, SEO) e os dois slugs (all e todos-os-jogos) ficam cobertos.
Item "Regras de Apostas" na seção esportes da sidebar (feat/sidebar-betting-rules-7k-cassino-vera). Aparece somente quando showSidebarBettingRules: true, o user está em rota /sports e o provider ativo é first (CactusSportsbook). Click dispara o evento cactus:show-betting-rules que o SportsIframeFirst escuta e reescreve o src do iframe com #betting-rules — espelha o legado CactusSportsbook.showBettingRules. Ativado em 7k-bet-br, cassino-bet-br e vera-bet-br; flag adicionada (default false) em todas as 14 brands com override pra evitar drift do file-replacement.
Sidebar variants ganham suporte a actionKey em SidebarMenuItem — quando preenchido, o item renderiza como botão com side-effect handler ao invés de link de navegação. Primeiro consumer é o betting-rules acima.
Footer com row opcional de links extras (feat/footer-extra-legal-links-7k-cassino-vera): novo tipo ExtraLegalLinksConfig com 3 posições (footer-stacked-bottom-bar, footer-default-after-seals, footer-default-after-legal). 7k, cassino e vera ganham os links Denúncias / Privacidade / Ouvidoria; demais brands continuam com null.
Métodos pixtopay-global e pixtopay-global-webpay (Payku/CHL) suportados no checkout (feat/chl-pixtopay-global-methods). Render via iframe (altura 750px, mesmo padrão do bank-transfer/khipu). Bump do @cactus-agents/payments na lockfile.
Valor pre-preenchido do depósito agora é clamped pro mínimo da brand (fix/clamp-prefilled-deposit-min). Antes, ?value=500 num site com mínimo R$ 10 (1000 cents) abria o form com R$ 5 e bloqueava o submit; agora Math.max(initialAmount, minAmount) garante que o form nunca abre abaixo do threshold.
"Dados Pessoais" virou read-only (fix/readonly-personal-data). Nome, sobrenome, data de nascimento e gênero vêm da validação de documento (CPF/RUT/CURP) no registro e o BFF rejeita updates com VUD001 — manter os inputs editáveis dava falsa impressão de poder editar. Exceção: BirthdateForm ainda aparece quando birth_date é nulo ou 0000-00-00 (raro pra BR, possível pra outros países). Mesma lógica do legado Document.vue.
Tournament/Mission/MiniGames cards e wins-carousel ganham key props faltantes + miscelâneas de lint (chore/biome-lint-warnings-cleanup, 74 warnings biome saneados em ~35 arquivos sem mudança funcional).
Race condition no anti-tamper do ValidationBlockerOverlay corrigida (fix/kyc-blocker-logout-anti-tamper-race). Quando o user clicava "Sair" no blocker, o MutationObserver e o setInterval que protegem o overlay disparavam window.location.reload() no momento em que o React desmontava o componente em resposta ao logout — causava reload espúrio. Novo isLoggingOutRef desarma os dois antes de o overlay sumir e o cleanup do effect reseta armed pra evitar re-armar em strict-mode.
Sheet de Favoritos hidrata o store no reload (fix/favorites-hydration-on-reload). O gate de fetch era isFavoritesSynced(userId) — flag em sessionStorage que sobrevive ao F5 enquanto o store Zustand não. Resultado: depois de reload o sheet abria vazio porque a flag dizia "já sincronizado" mas o store estava frio. Novo gate é _isFavoritesHydrated (em-memory, morre com o store). markFavoritesSynced permanece exportado pra observabilidade. Cobertura nova em useFavoritesSync.test.ts (149 linhas).
Carousel ganha arrowStyle="outside" (fix/carousel-outside-arrows-payment-method) — setas como flex siblings do track (não overlay), self-stretch na altura da linha, theme tokens (bg-bg-secondary, border-texts/10). Disabled nos edges mantém espaço (não pula). Nova prop hideArrowsOnMobile esconde abaixo de sm. Aplicado no MethodSelector (depósito/saque) e na GamesFilterBar — nas duas, as setas pequenas competiam por espaço com o conteúdo.
Modal de Oferta Relâmpago FTD desativado nas brands 7k-bet-br, cassino-bet-br e vera-bet-br (hotfix/disable-ftd-offer-modal-vera-cassino-7k). ftdOffer.enabled = false faz o FtdOfferProvider virar pass-through (não monta hook, modal central, widget flutuante nem story thumb). Config preservada pra reativação rápida quando marketing pedir.
cassino-bet-br mostra logo compacto (símbolo apenas) no header mobile autenticado (fix/cassino-logo-responsive). Reaproveita o gate showCompactMobileLogo (hydrated && isAuthenticated) que vera-bet-br já usa. Novo asset logo-icon.png (32×32) declarado em theme/sizes.ts via logo.mobile.compactSrc.
7k-bet-br, cassino-bet-br, vera-bet-br — ftdOffer.enabled = false (hotfix), showSidebarBettingRules: true, novo extra-legal-links.ts com Denúncias/Privacidade/Ouvidoria.
cassino-bet-br — theme/sizes.ts ganha logo.mobile.compactSrc apontando pro novo public/assets/brand/logo-icon.png. SEO casino.category:todos-os-jogos adicionado em page-descriptions.server.ts.
7k-bet-br, cassino-bet-br, vera-bet-br, state77-com, pt-state77-com, ph-state77-com, fi-7k-bet, ng-7k-bet, pb-bet, rj-bet, betpontobet-bet-br, casateste-com, x2b-bet — flag showSidebarBettingRules adicionada em todas (default false exceto nas três acima) pra acompanhar o file-replacement do features.ts e evitar undefined silencioso. SEO override casino.category:todos-os-jogos propagado em todos os 13 overrides de page-descriptions.server.ts.
@cactus-agents/i18n — chave nova gender em user.json nos 4 locales ativos (pt-br, pt, es, en) — alimenta o display read-only do gênero no novo InfosSection.
@cactus-agents/api-client e @cactus-agents/platform-cache — 16 warnings pré-existentes do biome saneados (packages/api-client/src/server.ts, packages/platform-cache/src/engine.ts) + ajustes em biome.json. Sem mudança funcional.
platform-cache — gameListPage adicionado à configuração de cache pra suportar as listagens paginadas do hook híbrido novo (useHybridGamesList consome /api/games/{category,provider}/:slug).
sitemap cache policy atualizada no front-ops pra acompanhar o split de sub-sitemaps.
Performance defaults Chile ajustados como configuração padrão da stage.