/* ADS Premium — design system */

:root {
  /* TEMA PADRAO DO SISTEMA: Dasho (Phoenixcoded, Bootstrap 5)
     https://html.phoenixcoded.net/dasho/bootstrap/default/
     Paleta oficial do template: primary #2196f3 (azul), success #4caf50,
     danger #f44336, warning #ff9800, info #00acc1, secondary #7e858e,
     dark #263238 (grafite azulado material). Bootstrap 5.3.8 vendorado em
     static/vendor/bootstrap e carregado antes deste arquivo no base.html --
     este arquivo e a camada de tema Dasho por cima do Bootstrap. */
  --bg: #f4f7fa;
  --bg-alt: #f8fafc;
  --surface: #ffffff;
  --surface-solid: #ffffff;
  --border: #e3e8ee;
  --border-strong: #cfd8dc;

  --brand: #2196f3;
  --brand-dark: #1976d2;
  --brand-soft: #e3f2fd;
  --brand-glow: rgba(33, 150, 243, 0.25);

  /* Neutro/secundario (botoes de cancelar e acoes de apoio). */
  --neutral: #7e858e;
  --neutral-dark: #6c757d;
  --neutral-soft: #eceff1;

  /* Danger (excluir/sair/confirmacoes destrutivas). */
  --danger: #f44336;
  --danger-dark: #d32f2f;

  --ink: #263238;
  /* Menu lateral: grafite escuro azulado (dark oficial do Dasho). */
  --dark: #263238;
  --dark-alt: #2f3e46;
  --dark-soft: #455a64;
  /* Fundo do menu lateral, tokens PROPRIOS -- nao reaproveita --dark/--dark-alt
     de proposito (2026-08-11, "quero as cores do fundo da barra de menu
     lateral mais nitida mais viva, hj esta muito opaca e acinzentada").
     --dark/--dark-alt tem saturacao baixa (~19-20%, cinza-azulado quase sem
     cor) e --dark e' usado em 11 outros lugares do sistema (tooltip, alguns
     badges) -- mudar o token global arriscaria descolorir esses tambem, sem
     necessidade. Os tokens novos sobem a saturacao pra ~58-62% (navy vivido
     na mesma familia de matiz do --brand) mantendo luminosidade parecida --
     contraste contra o texto do menu (#e9ecef) medido e confirmado bem acima
     do minimo AA (10-13:1, era 9-11:1 antes). */
  --sidebar-bg-alt: #183859;
  --sidebar-bg: #0f253e;

  --text: #37474f;
  --text-muted: #78909c;
  --text-faint: #b0bec5;

  --success-bg: #e8f5e9;
  --success-text: #2e7d32;
  --error-bg: #fdecea;
  --error-text: #c62828;
  --info-bg: #e0f7fa;
  --info-text: #00838f;
  --warning-bg: #fff3e0;
  --warning-text: #ef6c00;

  --radius-lg: 12px;
  --radius-md: 8px;
  --radius-sm: 6px;
  --shadow-sm: 0 1px 2px rgba(33, 37, 41, 0.06);
  --shadow-md: 0 4px 16px rgba(33, 37, 41, 0.07);
  --shadow-lg: 0 12px 32px rgba(33, 37, 41, 0.16);

  /* Tokens de movimento -- toda transicao/animacao do sistema usa essas
     curvas/duracoes pra manter o mesmo "sentimento" de movimento em todas
     as telas (consistencia de primeira qualidade). */
  --ease-out: cubic-bezier(0.22, 0.9, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.44, 1);
  --dur-fast: 0.14s;
  --dur-base: 0.22s;
  --dur-slow: 0.38s;

  /* Altura padrao unica de controle (input/select/button) usada em todo o
     sistema -- qualquer input e qualquer botao devem ter exatamente essa
     altura sempre que estiverem lado a lado, pra nunca ficar um maior que
     o outro. Nao aplicada a textarea (altura variavel por design/rows). */
  --field-h: 2.35rem;
}

/* Tema escuro (pedido do usuario, 2026-07-27: "se possivel tbm um dark
   theme, onde tema e idioma pode ser escolhido no header") -- ativado via
   [data-theme="dark"] no <html>, alternado pelo botao no topbar
   (toggleTheme() em base.html) e persistido em localStorage (mesmo padrao
   ja usado pro menu lateral recolhido/expandido). Sobrescreve so os
   TOKENS (variaveis) -- nenhuma regra de componente precisa mudar, ja que
   o sistema inteiro usa var(--...) em vez de cor solta. */
:root[data-theme="dark"] {
  --bg: #121820;
  --bg-alt: #1a222c;
  --surface: #1e2733;
  --surface-solid: #1e2733;
  --border: #2c3947;
  --border-strong: #3a4a5a;

  --brand: #42a5f5;
  --brand-dark: #64b5f6;
  --brand-soft: rgba(66, 165, 245, 0.16);
  --brand-glow: rgba(66, 165, 245, 0.35);

  --neutral: #9aa5b1;
  --neutral-dark: #b0bec5;
  --neutral-soft: rgba(158, 167, 178, 0.16);

  --danger: #ef5350;
  --danger-dark: #ff8a80;

  --ink: #eceff1;
  --dark: #0d1117;
  --dark-alt: #161d24;
  --dark-soft: #26333f;
  /* Mesma logica do bloco claro acima -- navy vivido proprio do menu, so'
     um pouco mais escuro pra combinar com o resto do tema escuro. */
  --sidebar-bg-alt: #11243b;
  --sidebar-bg: #091525;

  --text: #e3e8ee;
  --text-muted: #94a3b3;
  --text-faint: #64758a;

  --success-bg: rgba(76, 175, 80, 0.16);
  --success-text: #81c784;
  --error-bg: rgba(244, 67, 54, 0.16);
  --error-text: #ef9a9a;
  --info-bg: rgba(0, 172, 193, 0.16);
  --info-text: #4dd0e1;
  --warning-bg: rgba(255, 152, 0, 0.16);
  --warning-text: #ffb74d;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);
}

* {
  box-sizing: border-box;
}

html {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body {
  margin: 0;
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.55;
}

::selection {
  background: var(--brand-soft);
  color: var(--brand-dark);
}

/* Scrollbar tematizada (WebKit) -- detalhe de acabamento premium. */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(33, 37, 41, 0.18);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: rgba(33, 37, 41, 0.32); }

/* Entrada suave dos blocos principais ao carregar a pagina -- movimento
   curto e discreto (nao atrapalha o uso), mesmo easing em tudo. */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Acessibilidade: quem prefere menos movimento nao ve nenhuma animacao. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

h1, h2, h3, h4 {
  font-family: "Plus Jakarta Sans", "Inter", "Segoe UI", sans-serif;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0 0 0.35rem;
}

h2 { font-size: 1.4rem; font-weight: 700; }
h3 { font-size: 1.08rem; font-weight: 700; }
h4 { font-size: 0.95rem; font-weight: 700; }

p { color: var(--text-muted); margin: 0 0 0.6rem; }

a {
  color: var(--brand);
  text-decoration: none;
  font-weight: 600;
}

a:hover { color: var(--brand-dark); }

hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1.25rem 0;
}

/* Buttons */

button,
input,
textarea,
select {
  font: inherit;
}

/* Hierarquia de botoes estilo Bootstrap:
   - padrao (sem classe) = PRIMARIO verde solido (confirmar/acao principal)
   - .secondary-dark     = NEUTRO cinza solido (cancelar/acoes de apoio)
   - .button-danger      = DANGER vermelho solido (excluir/sair/destrutivo)
   Todos flat (sem gradiente), borda 1px na propria cor, mesmo raio e mesma
   altura --field-h. */
button,
.button-link {
  border: 1px solid var(--brand);
  border-radius: var(--radius-sm);
  /* Altura padrao do sistema (--field-h) -- so padding horizontal aqui, a
     vertical fica por conta da altura fixa, garantindo que todo botao meca
     exatamente o mesmo que um input ao lado dele. */
  height: var(--field-h);
  padding: 0 1.2rem;
  background: var(--brand);
  color: white;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.92rem;
  letter-spacing: 0.01em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  box-shadow: var(--shadow-sm);
  transition: background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

button:hover,
.button-link:hover {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: white;
}

button:active,
.button-link:active {
  transform: scale(0.98);
}

button:focus-visible,
.button-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-glow);
}

button.secondary {
  background: transparent;
  color: #eef3ee;
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: none;
}

button.secondary:hover {
  background: rgba(255, 255, 255, 0.08);
  box-shadow: none;
}

/* Botao NEUTRO (cinza Bootstrap #6c757d) -- cancelar, fechar, acoes de
   apoio. O nome .secondary-dark e historico (era um botao escuro), mantido
   pra nao tocar em todos os templates. */
.secondary-dark {
  background: var(--neutral);
  border-color: var(--neutral);
  color: #fff;
  box-shadow: var(--shadow-sm);
}

.secondary-dark:hover {
  background: var(--neutral-dark);
  border-color: var(--neutral-dark);
}

.secondary-dark:focus-visible {
  box-shadow: 0 0 0 3px rgba(108, 117, 125, 0.3);
}

.button-row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 1.1rem;
}

/* Layout */

.layout {
  display: grid;
  grid-template-columns: 268px 1fr;
  min-height: 100vh;
  transition: grid-template-columns var(--dur-base) var(--ease-out);
}

.layout.no-sidebar {
  grid-template-columns: 1fr;
}

.sidebar {
  /* Fundo mais nitido/profissional (2026-08-10, pedido do usuario) -- os 2
     halos radiais eram grandes e difusos (`transparent 45%`/`55%`, cobrindo
     quase o painel inteiro) e a diagonal em 200deg com stop em 68% misturava
     as 2 cores numa faixa larga, lendo como "borrado" em vez de definido.
     Halos agora concentrados/menores (leem como luz vinda de um canto, nao
     neblina cobrindo tudo) e a diagonal fica mais perto do vertical (165deg,
     mais "painel elevado" que "faixa diagonal"), com transicao mais curta
     (55% em vez de 68%) pra um corte mais definido entre os 2 tons. As
     orbs animadas (.sidebar-glow-1/2/3, ja existentes) continuam intactas
     por cima -- sao o toque "premium com movimento", isto aqui e' so a
     base parada por baixo delas. */
  background:
    radial-gradient(circle at 100% 0%, rgba(33, 150, 243, 0.20), transparent 34%),
    radial-gradient(circle at 4% 100%, rgba(255, 255, 255, 0.05), transparent 30%),
    linear-gradient(165deg, var(--sidebar-bg-alt) 0%, var(--sidebar-bg) 55%);
  color: #e9ecef;
  padding: 1.75rem 1.35rem;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  transition: padding var(--dur-base) var(--ease-out);
  /* Separacao/profundidade da coluna de conteudo (2026-08-02) -- uma linha
     de 1px bem sutil na borda direita + uma sombra rasa jogada pra direita,
     em vez de nenhuma fronteira visivel entre o menu escuro e o conteudo.
     Somado (2026-08-10) um traco fino de luz no TOPO (`inset`, blur 0 --
     nunca borrado) pra dar uma borda definida de "painel de vidro elevado"
     em vez do fundo se dissolver direto na topbar. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    1px 0 0 rgba(255, 255, 255, 0.05),
    6px 0 24px rgba(0, 0, 0, 0.10);
  /* BUG REAL corrigido (2026-08-06, reportado pelo usuario): o menu suspenso
     (flyout do sidebar recolhido, `body.sidebar-collapsed .nav-group-items`,
     z-index:60) escapa da caixa do menu via `position:absolute; left:100%`
     pra sobrepor a coluna de conteudo -- mas SEM z-index proprio aqui,
     `.sidebar` (position:sticky, sem z-index) cai no balde de pintura
     "z-index:auto, ordem do documento" do CSS (spec CSS2.1 apendice E,
     camada 5). `.dash-chart-box` (os cards de grafico do Dashboard, mais
     abaixo no arquivo) e' `position:relative` -- SEM z-index tambem -- ou
     seja, cai NO MESMO balde, e por vir DEPOIS no HTML (dentro do
     `.content`, que fica depois do `.sidebar` no layout), pinta POR CIMA
     do sidebar inteiro, inclusive do que escapa dele (o z-index:60 do
     flyout so' vale DENTRO do proprio contexto de empilhamento do sidebar,
     nao contra um irmao de fora). A versao MOBILE do `.sidebar` (mais
     abaixo, dentro do media query) ja' tinha `z-index: 50` -- documentado
     la' como "acima da topbar (40), abaixo dos modais (60)" -- so' faltava
     aplicar o MESMO valor aqui, na regra padrao/desktop. */
  z-index: 50;
}

/* Regiao ROLAVEL do menu (2026-08-16, "a altura esta ficando errada e
   cortada") -- envolve so' `<nav>` + `.sidebar-footer` (ver comentario em
   base.html). `.sidebar` continua height:100vh sem overflow proprio (o
   `.sidebar-collapse-btn`, position:absolute com metade pra FORA da borda
   direita, precisa que `.sidebar` nunca corte conteudo que escapa dela) --
   quem absorve o excesso de altura e' este wrapper, com min-height:0
   (obrigatorio: filho flex sem isso nunca encolhe abaixo do proprio
   conteudo, e o overflow-y:auto nunca entraria em acao). */
.sidebar-scroll {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Scrollbar clara -- a sidebar e' SEMPRE a superficie escura do sistema
   (tema claro ou escuro, ver comentario perto de `.nav-link.active`), e a
   scrollbar global (linha ~166) e' um polegar ESCURO pensado pra superficie
   clara: nela ficaria practicamente invisivel. */
.sidebar-scroll::-webkit-scrollbar { width: 6px; }
.sidebar-scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.18);
  background-clip: content-box;
}
.sidebar-scroll::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.32); }
.sidebar-scroll { scrollbar-color: rgba(255, 255, 255, 0.22) transparent; scrollbar-width: thin; }

/* Efeito de "luzes" animadas de fundo (2026-08-02, pedido do usuario) -- 3
   orbs desfocados (radial-gradient + blur) que derivam devagar e mudam de
   opacidade em loop infinito, dando profundidade "viva" ao fundo escuro do
   menu (mesmo espirito dos efeitos "aurora"/gradiente animado ja comuns em
   dashboards atuais). Sempre em tons de azul/ciano da MARCA -- nunca cor
   nova fora da paleta ja usada no resto do menu (regra do projeto: cor so
   muda pra reforcar hierarquia ja estabelecida). Wrapper com overflow:hidden
   PROPRIO (ver comentario no base.html) e z-index:-1 -- fica atras de
   brand/nav/footer sem precisar mexer em mais nada. pointer-events:none em
   tudo: nunca deve capturar clique que deveria ir pro menu de verdade.
   Anima so `transform`/`opacity` (nunca position/background-position), que
   sao as duas unicas propriedades compositaveis via GPU sem forcar reflow a
   cada frame -- mesma disciplina de performance ja usada nas animacoes do
   sistema (ver bloco "Animacoes do sistema" mais adiante no arquivo). */
.sidebar-glow-wrap {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: -1;
}

.sidebar-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  will-change: transform, opacity;
}

.sidebar-glow-1 {
  width: 260px;
  height: 260px;
  top: -70px;
  left: -90px;
  background: radial-gradient(circle, rgba(33, 150, 243, 0.55), transparent 70%);
  animation: sidebarGlowFloat1 18s var(--ease-out) infinite;
}

.sidebar-glow-2 {
  width: 230px;
  height: 230px;
  bottom: 8%;
  right: -100px;
  background: radial-gradient(circle, rgba(100, 181, 246, 0.42), transparent 70%);
  animation: sidebarGlowFloat2 23s var(--ease-out) infinite;
  animation-delay: -7s;
}

.sidebar-glow-3 {
  width: 190px;
  height: 190px;
  top: 42%;
  left: 25%;
  background: radial-gradient(circle, rgba(0, 172, 193, 0.32), transparent 70%);
  animation: sidebarGlowFloat3 27s var(--ease-out) infinite;
  animation-delay: -13s;
}

@keyframes sidebarGlowFloat1 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.5; }
  50% { transform: translate(45px, 65px) scale(1.15); opacity: 0.75; }
}

@keyframes sidebarGlowFloat2 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.35; }
  50% { transform: translate(-55px, -45px) scale(1.1); opacity: 0.6; }
}

@keyframes sidebarGlowFloat3 {
  0%, 100% { transform: translate(0, 0) scale(0.9); opacity: 0.22; }
  50% { transform: translate(30px, -55px) scale(1.2); opacity: 0.45; }
}

/* Mesma convencao ja usada em toda animacao do sistema (ver bloco
   "Animacoes do sistema" mais adiante) -- desliga por completo quando o
   usuario pede menos movimento. */
@media (prefers-reduced-motion: reduce) {
  .sidebar-glow {
    animation: none;
  }
}

/* Menu lateral recolhido (pedido do usuario, 2026-07-19): classe fica no
   <body> (aplicada por JS antes da pintura, ver base.html) -- reduz a
   coluna do grid, encolhe o padding do sidebar, empilha icone+rotulo dos
   nav-link na vertical com fonte menor, e gira a setinha do botao. */
body.sidebar-collapsed .layout {
  /* Pedido do usuario (2026-07-19): 84px deixava o botao de recolher
     parecendo descentralizado (coluna estreita demais pra folga em volta
     do circulo de 26px) -- aumentado pra dar mais respiro. */
  grid-template-columns: 108px 1fr;
}

body.sidebar-collapsed .sidebar {
  padding: 1.75rem 0.65rem;
}

/* Logo (2026-08-11): `.brand` voltou a ser so a logo, em linha simples --
   o botao de recolher saiu daqui de vez (agora e' filho direto de
   `.sidebar`, position:absolute, flutuando por cima -- ver
   `.sidebar-collapse-btn` mais abaixo e o comentario em base.html sobre
   PORQUE precisa ficar fora do fluxo de `.brand`). */
.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding-bottom: 1.5rem;
  margin-bottom: 1.4rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
}

body.sidebar-collapsed .brand {
  justify-content: center;
}

body.sidebar-collapsed .brand-logo {
  display: none;
}

.brand-logo-mark {
  display: none;
  height: 30px;
  width: auto;
}

body.sidebar-collapsed .brand-logo-mark {
  display: block;
}

/* Botao de recolher (2026-08-11, redesign a pedido do usuario -- reverte a
   versao "sem fundo" do dia anterior: "fundo branco com efeito hover
   proffisional", cantos "levemente arredondados" (quadrado com raio pequeno,
   nao mais circulo) e "barras grossas" -- a espessura maior vem do proprio
   SVG, `stroke-width="2.6"` na marcacao em base.html, aqui so' o tamanho).
   Posicao: filho direto de `.sidebar` (position:absolute relativo a ela,
   que e' position:sticky;top:0;height:100vh -- sempre colada no topo da
   viewport, mesma origem Y=0 da topbar, tambem sticky/top:0). `top` e'
   calculado via JS a partir da altura REAL da topbar
   (`positionSidebarCollapseButton()`, base.html) -- o valor abaixo e' so' um
   chute razoavel pro instante entre o primeiro paint e o JS rodar.
   `right:-15px` (metade do botao de 30px pra fora) gruda na borda direita
   REAL de `.sidebar`, que muda de largura ao recolher/expandir
   (grid-template-columns anima em `.layout`) -- o botao "acompanha" esse
   movimento de graca, sem nenhuma regra propria pro estado
   `body.sidebar-collapsed` (ponto explicito do pedido: "qnd recolhido ele
   acompanha a regra"). Cores reaproveitam os MESMOS tokens que `.icon-btn`
   ja usa em hover em todo o resto do app (`--brand-soft`/`--brand-dark`),
   pra ficar consistente com o resto do sistema em vez de inventar uma
   paleta so' pra este botao. */
.sidebar-collapse-btn {
  position: absolute;
  top: 17px;
  right: -15px;
  width: 30px;
  height: 30px;
  /* BUG REAL corrigido (2026-08-11, achado medindo `getBoundingClientRect`
     no navegador, nao so' lendo CSS): sem isto o botao renderizava 40px de
     largura, nao 30px. `button` global (linha ~216) da' `padding: 0 1.2rem`
     (19.2px de cada lado) a TODO `<button>`, e com `box-sizing:border-box`
     em vigor a caixa nao consegue encolher abaixo do proprio padding+borda
     -- o `width:30px` daqui vencia no cascade, mas ficava sem efeito porque
     30px e' menor que 19.2+19.2+1+1=40.4px de padding+borda sozinhos.
     Mesma classe de armadilha ja documentada varias vezes neste arquivo
     (".icon-btn" e outros -- global `button` "vence" numa propriedade que a
     classe especifica nao redeclara). */
  padding: 0;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(15, 23, 32, 0.08);
  background: #fff;
  color: var(--dark);
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 55;
  box-shadow: 0 2px 10px rgba(15, 23, 32, 0.26), 0 0 0 1px rgba(15, 23, 32, 0.04);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.sidebar-collapse-btn:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  box-shadow: 0 4px 16px rgba(33, 150, 243, 0.3), 0 0 0 1px rgba(33, 150, 243, 0.28);
  transform: translateY(-1px);
}

.sidebar-collapse-btn:active {
  transform: translateY(0) scale(0.92);
}

.sidebar-collapse-btn svg {
  width: 17px;
  height: 17px;
}

.brand-mark {
  width: 38px;
  height: 38px;
  border-radius: 8px;
  background: var(--brand);
  display: grid;
  place-items: center;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 800;
  font-size: 1.05rem;
  color: white;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  flex-shrink: 0;
}

.brand-text strong {
  display: block;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 1.02rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
}

.brand-text span {
  font-size: 0.72rem;
  color: rgba(233, 236, 239, 0.55);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.brand-logo {
  display: block;
  width: 100%;
  max-width: 190px;
  height: auto;
}

.sidebar nav {
  display: grid;
  /* UMA coluna (2026-08-03). O layout de duas colunas tentado em 2026-08-02
     nao cabia: com a sidebar em 268px cada celula ficava com 110px e os
     CINCO itens de topo saiam truncados -- medido, faltava 11px ate' no
     "Dashboard" (a palavra mais curta) e 97px no "Banco de Conhecimento".
     O resultado era metade do menu legivel (os grupos, que ocupam a linha
     inteira) e metade em reticencias. Menu lateral com rotulo ilegivel nao
     cumpre a funcao dele, entao o ganho de altura nao compensa. */
  grid-template-columns: 1fr;
  gap: 0.25rem;
  margin-bottom: auto;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.68rem 0.75rem;
  /* Cantos mais arredondados (2026-08-02, "modernizar") -- 10px em vez dos
     6px de --radius-sm, que e' o valor generico usado no resto do sistema
     (cards/botoes). Valor fixo aqui de proposito, nao criei variavel nova:
     e' um ajuste so' do menu lateral, mudar --radius-sm afetaria o app
     inteiro. */
  border-radius: 10px;
  color: rgba(233, 236, 239, 0.72);
  font-weight: 600;
  font-size: 0.9rem;
  position: relative;
  overflow: hidden;
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

.nav-link svg {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  opacity: 0.85;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}

/* Itens SOLTOS de topo (Dashboard, Banco de Conhecimento, Organizacoes,
   Configuracoes, Conformidade): com uma coluna o nome inteiro cabe, entao
   ficam na MESMA fonte dos itens dentro de grupo -- nada de fonte reduzida
   nem reticencias, que era o remendo da versao de duas colunas. O ellipsis
   fica so' como rede de seguranca pra um rotulo futuro muito longo (com
   min-width:0, obrigatorio: filho flex com texto tem min-width:auto e sem
   isso nao encolhe nem trunca). Nunca deixar quebrar em 2 linhas dentro de
   um link flex -- o icone fica alinhado so' com a 1a linha e desalinha. */
.sidebar nav > a.nav-link .nav-link-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Hover (2026-08-02, refinado -- NAO reintroduz a "faixa preenchendo da
   esquerda pra direita" que o usuario rejeitou em 2026-07-27: continua so'
   fundo + cor mudando, sem deslocamento nem faixa animada, so' que agora com
   um tom azulado (on-brand) em vez de branco/cinza generico, e' a mesma
   filosofia "hover simples" só com mais personalidade. Mesma linguagem
   visual pro menu inteiro (.nav-link e .nav-group-header). */
.nav-link:hover,
.nav-group-header:hover {
  background: rgba(100, 181, 246, 0.12);
  color: #fff;
}

/* Icone "acorda" um pouco no hover -- sutil (8%), nao e' a faixa rejeitada,
   e' so o icone crescendo de leve, padrao comum em nav moderno. */
.nav-link:hover svg,
.nav-group-header:hover svg:not(.nav-group-chevron) {
  transform: scale(1.08);
  opacity: 1;
}

/* Item ativo (modernizado, 2026-08-02, pedido do usuario "modernizar menu
   lateral, cores efeitos") -- trocado o preenchimento solido/chapado por um
   card translucido (glassmorphism) + indicador lateral, que e' o padrao
   mais atual de navegacao em dashboards (Linear/Vercel/Notion): fundo sutil
   na cor da marca em vez de um retangulo azul cheio, com uma barra fina na
   borda esquerda marcando "voce esta aqui". Texto continua branco solido
   (contraste garantido nos dois temas -- a sidebar e' sempre a superficie
   escura do sistema, nao muda de cor com o tema claro/escuro, ver :root vs
   :root[data-theme=dark] em nenhum dos dois tem override proprio pra
   .sidebar/.nav-link).
   ARMADILHA EVITADA: usar `border` aqui faria o item ativo CRESCER 2px em
   relacao aos demais (box model muda com borda) -- por isso o contorno usa
   `box-shadow: inset`, que fica "por dentro" sem alterar dimensao (mesma
   classe de erro ja documentada no projeto pra outros componentes).
   BUG REAL corrigido (2026-08-06, reportado pelo usuario com print -- uma
   mancha escura sobrando em cima do item seguinte do menu): a sombra externa
   `0 4px 14px` tem alcance visual de ~18px (offset + blur), mas o gap real
   entre itens do <nav> e' so' 4px (`gap: 0.25rem` em `.sidebar nav`) --
   medido no navegador, a sombra sempre invadia ~14px do item de baixo.
   Removida a sombra externa; ficam so' as DUAS internas (borda + brilho no
   topo), que ja bastam pra separar o card do fundo sem vazar pra fora da
   propria caixa -- mesmo criterio que `.nav-group-items .nav-link.active"
   (item ativo dentro de grupo) ja usava, ver mais abaixo. */
.nav-link.active {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, rgba(66, 165, 245, 0.22) 0%, rgba(33, 150, 243, 0.09) 100%);
  color: #fff;
  box-shadow:
    inset 0 0 0 1px rgba(100, 181, 246, 0.30),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* Barra indicadora lateral (substitui o "glass diagonal" antigo) -- mesmo
   papel visual, mais legivel: uma linha fina com leve brilho, no lugar de um
   verniz cobrindo o botao inteiro. Cabe dentro do padding existente do link
   (0.75rem = 12px, a barra tem 3px + 0.4rem de recuo), nunca empurra o
   texto/icone. */
.nav-link.active::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.35rem;
  bottom: 0.35rem;
  width: 3px;
  border-radius: 999px;
  background: linear-gradient(180deg, #90caf9, var(--brand));
  box-shadow: 0 0 8px rgba(66, 165, 245, 0.65);
}

.nav-link.active:hover { transform: none; }

/* Nav-link no modo recolhido: icone em cima, rotulo embaixo, fonte menor --
   pedido explicito ("deixando fonte abaixo do icone e reduzida"). */
body.sidebar-collapsed .nav-link {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  padding: 0.55rem 0.25rem;
  font-size: 0.6rem;
  line-height: 1.1;
  text-align: center;
  white-space: normal;
}

/* ARMADILHA DE ESPECIFICIDADE evitada (2026-08-02): `.sidebar nav > a.nav-link`
   (a regra de font-size dos itens de topo no grid de 2 colunas, acima) tem
   MAIS classes/elementos que `body.sidebar-collapsed .nav-link`, entao
   venceria por engano tambem no modo recolhido sem este override -- aqui o
   font-size correto continua sendo o do modo colapsado (0.6rem), nunca o
   0.82rem do modo expandido. O mesmo vale pro texto: no modo colapsado o
   rotulo tem espaco de sobra pra quebrar em ate 2 linhas (ver o proprio
   `white-space: normal` do bloco acima) -- nunca deve truncar com
   reticencias so' porque o modo expandido trunca. */
body.sidebar-collapsed .sidebar nav > a.nav-link {
  font-size: 0.6rem;
}

body.sidebar-collapsed .sidebar nav > a.nav-link .nav-link-text {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}

body.sidebar-collapsed .nav-link:hover {
  transform: none;
}

body.sidebar-collapsed .nav-link svg {
  width: 15px;
  height: 15px;
}

/* Sem barra indicadora no modo recolhido (2026-08-02) -- o layout aqui e'
   centralizado (icone em cima, rotulo embaixo) e a barra na borda esquerda
   ficaria descentrada em relacao a eles; o fundo/box-shadow do .active ja
   destaca o item sozinho. */
body.sidebar-collapsed .nav-link.active::before {
  display: none;
}

body.sidebar-collapsed .nav-count-badge {
  margin-left: 0;
}

/* Contagem de perguntas sem resposta no menu lateral: 0 fica discreto (mesma
   cor apagada do texto do sidebar), >0 ganha .highlight (pill de destaque). */
.nav-count-badge {
  margin-left: auto;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 0.7rem;
  font-weight: 700;
  background: rgba(255, 255, 255, 0.08);
  color: rgba(233, 236, 239, 0.6);
}

.nav-count-badge.highlight {
  background: var(--warning, #ff9800);
  color: #fff;
}

/* Grupos do menu lateral (Cadastros/Anuncios/Perguntas/Vendas, 2026-07-27) --
   cabecalho clicavel (mesma cara visual do .nav-link, so' com um chevron que
   gira) + lista de itens recolhivel embaixo. Fechado por padrao (altura 0,
   sem exigir JS pra medir alturas reais); .nav-group-open (aplicado no
   grupo que contem a pagina ativa, ou pelo toggle manual) revela. */
.nav-group {
  display: grid;
  /* Ocupa a linha inteira. Redundante com o grid de 1 coluna de hoje, mas
     mantido de proposito: se alguem voltar a experimentar mais de uma
     coluna no <nav>, um grupo com dropdown nunca pode dividir largura --
     precisa do espaco todo pro texto/chevron e pro submenu recolhivel. */
  grid-column: 1 / -1;
}

.nav-group-header {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  padding: 0.68rem 0.75rem;
  border-radius: 10px; /* mesmo ajuste de .nav-link, 2026-08-02 */
  color: rgba(233, 236, 239, 0.72);
  font-weight: 600;
  font-size: 0.9rem;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

.nav-group-header svg:not(.nav-group-chevron) {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  opacity: 0.85;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}

.nav-group-header span:first-of-type {
  flex: 1;
}

.nav-group-chevron {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  opacity: 0.6;
  transition: transform var(--dur-fast) var(--ease-out);
}

.nav-group-open > .nav-group-header .nav-group-chevron {
  transform: rotate(180deg);
}

.nav-group-items {
  display: grid;
  gap: 0.15rem;
  /* Recuo reduzido (pedido do usuario, 2026-07-27: "o espaço da esqueda no
     submenu deve diminuir") -- só o suficiente pra guia vertical (::before)
     caber sem colar no texto. */
  padding-left: 1.1rem;
  margin-left: 0.65rem;
  position: relative;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  /* Efeito de deslizar (pedido do usuario, 2026-07-27: "abrir mais opcoes
     um efeito de deslizar") -- max-height anima o "abrir pra baixo", opacity
     evita o conteudo aparecer de golpe antes da altura terminar de crescer.
     Mesmos tokens de movimento do resto do sistema (--dur-base/--ease-out). */
  transition: max-height var(--dur-base) var(--ease-out),
    opacity var(--dur-base) var(--ease-out),
    padding var(--dur-base) var(--ease-out);
}

/* Guia vertical conectando os itens ao cabecalho do grupo -- deixa claro
   (pedido do usuario: "diferente de menu apra saber o que faz parte") que
   essa coluna de links pertence aquele grupo especifico, nao ao menu
   principal solto. So aparece com o grupo aberto (senao ficaria um traco
   solto de 0px de altura). */
.nav-group-open > .nav-group-items::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15rem;
  bottom: 0.3rem;
  width: 2px;
  border-radius: 999px;
  /* Gradiente sutil em vez de cor solida flat (2026-08-02) -- mesma cor de
     marca da barra indicadora do item ativo, dando continuidade visual entre
     "isto e' um grupo" (guia) e "isto esta selecionado" (barra do .active). */
  background: linear-gradient(180deg, rgba(100, 181, 246, 0.45), rgba(255, 255, 255, 0.08));
}

.nav-group-open > .nav-group-items {
  max-height: 400px;
  opacity: 1;
  padding-top: 0.15rem;
  padding-bottom: 0.3rem;
}

.nav-group-items .nav-link {
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
  font-weight: 500;
  /* Sem fundo em repouso (pedido do usuario, 2026-07-27) -- so' ganha fundo
     no hover ou quando ativo (regras logo abaixo); a guia vertical do grupo
     ja' e' o suficiente pra indicar que esses itens pertencem ao grupo pai. */
  background: none;
}

/* Hover ja' vem do .nav-link:hover compartilhado (acima) -- sem regra
   propria aqui de proposito. */

.nav-group-items .nav-link.active {
  /* Item ativo dentro do grupo usa uma versao mais discreta do mesmo card
     translucido do nav-link principal (2026-08-02) -- o grupo inteiro ja
     ficou marcado como "aberto/atual" pelo cabecalho, entao o item dentro
     nao precisa da mesma intensidade, so' precisa se destacar dos irmaos. */
  background: linear-gradient(135deg, rgba(66, 165, 245, 0.18) 0%, rgba(33, 150, 243, 0.07) 100%);
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(100, 181, 246, 0.22);
}

/* Sem barra indicadora aqui -- colidiria com a guia vertical do grupo, que
   ja' cumpre esse papel (ambas ficariam grudadas na borda esquerda). */
.nav-group-items .nav-link.active::before {
  display: none;
}

/* Item "em breve" (grupo Vendas) -- mesma cara de .nav-link mas sem link
   real nenhum (span, nao <a>), cursor default, badge discreto. */
.nav-link-soon {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  color: rgba(233, 236, 239, 0.35);
  cursor: default;
}

.nav-soon-badge {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  color: rgba(233, 236, 239, 0.45);
  white-space: nowrap;
}

/* Menu recolhido (icone-so'): cabecalho do grupo vira icone empilhado, mesma
   cara dos demais .nav-link recolhidos. Os itens internos NAO ficam
   acessiveis aqui (ver bloco `.nav-group-items` mais abaixo, 2026-08-11) --
   clicar no cabecalho e' o unico jeito de chegar neles, e isso ja' descolapsa
   a barra pro modo normal antes de abrir (toggleNavGroup, base.html). */
body.sidebar-collapsed .nav-group-header {
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.55rem 0.25rem;
  font-size: 0.6rem;
  text-align: center;
}

body.sidebar-collapsed .nav-group-header svg:not(.nav-group-chevron) {
  width: 15px;
  height: 15px;
}

/* Sem espaco pra mostrar/girar a seta nesse modo -- nao ha' o que girar,
   o submenu nunca aparece com a barra recolhida (ver bloco abaixo). */
body.sidebar-collapsed .nav-group-chevron {
  display: none;
}

/* Flyout no hover REMOVIDO por completo (2026-08-11, pedido do usuario apos
   reportar que o hover fechava o submenu antes de conseguir clicar num item
   dele: "nao faz mais hover e mostrar dropdown qnd recolhido"). Nao existe
   mais nenhum jeito de VER o submenu com a barra recolhida -- essa regra
   forca `.nav-group-items` fechado sempre nesse modo, MESMO quando o grupo
   ja' nasce `.nav-group-open` pelo servidor (grupo da pagina atual) ou por
   preferencia salva de uma sessao anterior em que a barra nao estava
   recolhida. `body.sidebar-collapsed .nav-group-items` (0,2,1) vence
   `.nav-group-open > .nav-group-items` (0,2,0) pela cascata normal, sem
   precisar de `!important`. A UNICA forma de abrir um submenu aqui e'
   clicar no cabecalho do grupo, que primeiro tira a barra do modo recolhido
   (toggleNavGroup, base.html) -- a' sim a regra normal (nao-recolhida) do
   accordion assume, com o submenu no lugar de sempre. */
body.sidebar-collapsed .nav-group-items {
  max-height: 0 !important;
  opacity: 0 !important;
  overflow: hidden;
  pointer-events: none;
}

.sidebar-footer {
  padding-top: 1.25rem;
  margin-top: 1.25rem;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}

.user-chip {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.6rem;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.06);
  margin-bottom: 0.75rem;
  text-decoration: none;
  transition: background 0.15s ease;
}

.user-chip:hover {
  background: rgba(255, 255, 255, 0.12);
}

.user-chip .avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 0.78rem;
  flex-shrink: 0;
}

.user-chip .email {
  font-size: 0.78rem;
  color: rgba(233, 236, 239, 0.85);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-footer form button {
  width: 100%;
}

.content {
  /* Padding de baixo normal desde 2026-08-18: a faixa legal deixou de ser
     `position: fixed` (virou rodape no fim da pagina, ver .legal-footer-bar
     no fim do arquivo), entao nao ha' mais nada sobreposto pra compensar --
     antes eram 5.25rem reservados em TODA tela por causa dela. O respiro
     extra que sobrou aqui e' so' pra barra de salvar (.form-savebar) das
     telas de cadastro nao encostar no rodape. */
  padding: 2rem 2.25rem 2.5rem;
  min-width: 0;
}

.content.full {
  display: grid;
  place-items: center;
  padding: 0;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  padding: 0.9rem 0;
  margin: -2rem -2.25rem 1.5rem;
  padding-left: 2.25rem;
  padding-right: 2.25rem;
  border-bottom: 1px solid var(--border);
}

/* Topbar usa uma rgba fixa (nao var(--bg)) de proposito -- precisa manter
   a translucidez/blur mesmo com --bg mudando. Tema escuro ganha o mesmo
   tratamento com o tom escuro correspondente (documentado desde a intro
   do blur: "se mudar --bg, atualizar esse rgba junto"). */
:root[data-theme="dark"] .topbar {
  background: rgba(18, 24, 32, 0.86);
}

/* Navegacao inferior do celular (barra horizontal fixa no rodape, estilo
   app) e o fundo escuro do menu completo: existem so no celular/tablet --
   no desktop a barra lateral e' fixa e sempre visivel, entao os dois ficam
   fora de cena (a media query de 980px e' quem os liga). */
.mobile-bottom-nav,
.mobile-nav-backdrop,
.mobile-nav-close {
  display: none;
}

.mobile-bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* z-index 45: acima do conteudo e da topbar (40), abaixo dos modais (60)
     e dos toasts/flash (80) -- nunca cobre um alerta ou popup. */
  z-index: 45;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -2px 12px rgba(33, 37, 41, 0.08);
  /* Area segura do iPhone (barra de gestos) -- sem isso os rotulos ficam
     por baixo da faixa preta inferior. */
  padding-bottom: env(safe-area-inset-bottom, 0);
}

.mobile-nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  position: relative;
  padding: 0.5rem 0.25rem 0.45rem;
  min-height: 3.4rem;
  font-size: 0.62rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}

.mobile-nav-item svg {
  width: 19px;
  height: 19px;
}

.mobile-nav-item:hover {
  background: transparent;
  box-shadow: none;
  transform: none;
  color: var(--brand-dark);
}

.mobile-nav-item.active {
  color: var(--brand);
}

/* Botao central: circulo destacado, o unico item colorido em repouso. */
.mobile-nav-more-circle {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin-top: -1.1rem;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  box-shadow: 0 4px 12px var(--brand-glow);
  transition: transform var(--dur-fast) var(--ease-out);
}

.mobile-nav-more:hover .mobile-nav-more-circle,
body.mobile-nav-open .mobile-nav-more-circle {
  transform: scale(1.06);
}

.mobile-nav-more-circle svg {
  width: 19px;
  height: 19px;
}

/* Contador de perguntas sem resposta (mesma ideia do badge da barra lateral). */
.mobile-nav-badge {
  position: absolute;
  top: 0.3rem;
  left: 50%;
  margin-left: 0.25rem;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--warning-text);
  color: #fff;
  font-size: 0.58rem;
  font-style: normal;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

.topbar-title {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--text);
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.meli-status-pill {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.4rem 0.75rem;
  border-radius: 999px;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

.meli-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
  flex-shrink: 0;
}

.meli-status-pill.connected {
  color: var(--success-text);
  border-color: rgba(30, 107, 49, 0.2);
  background: var(--success-bg);
}

.meli-status-pill.connected .meli-status-dot {
  background: var(--success-text);
  box-shadow: 0 0 0 rgba(30, 107, 49, 0.5);
  animation: meli-pulse 1.8s infinite;
}

.meli-status-pill.disconnected {
  color: var(--error-text);
  border-color: rgba(163, 49, 42, 0.2);
  background: var(--error-bg);
}

@keyframes meli-pulse {
  0% { box-shadow: 0 0 0 0 rgba(30, 107, 49, 0.45); }
  70% { box-shadow: 0 0 0 6px rgba(30, 107, 49, 0); }
  100% { box-shadow: 0 0 0 0 rgba(30, 107, 49, 0); }
}

/* Card seletor de empresa no topbar (substitui o pill do ML quando ha empresa
   cadastrada) -- filtro visual dos anuncios; a bolinha segue mostrando o
   status da conexao (classes connected/disconnected direto no dot, ja que
   aqui nao existe o pill pai). Botao custom: precisa neutralizar o estilo do
   button global (fundo brand, sombra, lift no hover). */
.company-menu { position: relative; }

.company-card-btn {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.7rem;
  height: auto;
  border-radius: 999px;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text);
  font-weight: 600;
  font-size: 0.8rem;
  cursor: pointer;
  box-shadow: none;
}

.company-card-btn:hover {
  background: var(--bg);
  color: var(--text);
  transform: none;
  box-shadow: none;
}

.company-card-name {
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meli-status-dot.connected {
  background: var(--success-text);
  animation: meli-pulse 1.8s infinite;
}

.meli-status-dot.disconnected { background: var(--error-text); }

.company-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  min-width: 230px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
  padding: 0.4rem;
}

.company-dropdown.open { display: block; }

.company-dropdown form { margin: 0; }

.company-dropdown .company-option {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text);
  font-size: 0.83rem;
  font-weight: 600;
  padding: 0.5rem 0.6rem;
  height: auto;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.company-dropdown .company-option:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}

.company-dropdown .company-option.current {
  background: var(--brand-soft);
  color: var(--brand-dark);
}

.company-dropdown-hint {
  margin: 0.35rem 0.6rem 0.25rem;
  font-size: 0.72rem;
}

/* Popup "Acessar catalogo" (rodape da barra lateral) -- lista de empresas com
   catalogo publico ativo pra escolher qual visualizar. */
.catalog-picker-item {
  display: block;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
}

.catalog-picker-item:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-color: var(--brand);
}

/* Notificacoes */

.notif-menu { position: relative; }

.notif-btn { position: relative; }

.notif-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  background: var(--brand);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  border-radius: 999px;
  min-width: 16px;
  height: 16px;
  display: grid;
  place-items: center;
  padding: 0 3px;
}

.notif-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  width: 320px;
  max-height: 380px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
}

.notif-dropdown.open { display: block; }

/* Cabecalho "Notificacoes" do painel do sino.
   BUG REAL (reportado 2026-08-04: "esta com um texto Notificacoes (...) esta
   todo desalinhado"): o <div class="notif-dropdown-head"> existe no HTML
   desde que o painel foi criado, mas NUNCA teve regra CSS nenhuma. Sem ela
   ficava com padding 0 (colado na borda do painel), fonte herdada de 15px e
   peso normal -- enquanto os itens da lista logo abaixo tem recuo proprio,
   o que deixava o titulo 54px fora de alinhamento com todo o resto e sem
   cara de cabecalho. O recuo de 1rem alinha o texto exatamente com o inicio
   do conteudo dos itens (o icone de cada notificacao).
   `sticky` porque o painel rola (max-height 380px): sem isso o titulo some
   ao rolar a lista e o usuario perde a referencia do que esta vendo. */
.notif-dropdown-head {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 0.75rem 1rem 0.6rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Rodape do sino (2026-08-11): link fixo pro historico completo. `sticky` no
   bottom pelo mesmo motivo do cabecalho -- o painel rola, e este e' o unico
   caminho pras notificacoes que o filtro de tipos escondeu da lista. */
.notif-dropdown-foot {
  position: sticky;
  bottom: 0;
  z-index: 1;
  padding: 0.55rem 1rem;
  background: var(--surface);
  border-top: 1px solid var(--border);
  text-align: center;
}

.notif-dropdown-foot a {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--brand);
  text-decoration: none;
}

.notif-dropdown-foot a:hover { text-decoration: underline; }

/* Icone de tipo reaproveitado fora do sino (tabela do historico e caixinhas
   das preferencias) -- so' encolhe e alinha com o texto ao lado.
   SELETOR DUPLO de proposito: `.notif-icone` (width 30px) e' declarada mais
   ABAIXO neste arquivo, e com a mesma especificidade venceria por ordem. */
.notif-icone.notif-icone-inline {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  margin-right: 0.35rem;
}

.notif-icone.notif-icone-inline svg { width: 13px; height: 13px; }

.notif-kind-cell {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

/* Ja lida no historico: mesma distincao visual do sino, sem esconder nada. */
.notif-history-msg.is-read { color: var(--text-muted); }

/* Seletor de idioma no topbar (2026-07-27, pedido do usuario) -- mesmo
   padrao visual do menu de notificacoes. */
.lang-menu { position: relative; }

.lang-menu-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  width: auto;
  padding: 0 0.55rem;
}

.lang-menu-current {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.lang-menu-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  min-width: 140px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
  overflow: hidden;
}

.lang-menu-dropdown.open { display: block; }

.lang-menu-dropdown a {
  display: block;
  padding: 0.55rem 0.9rem;
  font-size: 0.85rem;
  color: var(--text);
  text-decoration: none;
}

.lang-menu-dropdown a:hover { background: var(--brand-soft); color: var(--brand-dark); }
.lang-menu-dropdown a.active { color: var(--brand-dark); font-weight: 700; background: var(--brand-soft); }

/* --- Ajuda contextual + tour guiado (2026-08-16) -------------------------
   Icone "?" no topbar, mesmo padrao visual/estrutural do sino de
   notificacoes (.notif-menu/.notif-dropdown) -- ver toggleHelpMenu em
   app_tour.js. O painel lista os topicos cadastrados pela tela atual
   (AdsPremiumTour.register); clicar num topico "espia" o elemento (rola ate
   ele e pisca um contorno), sem precisar entrar no passo a passo guiado. */
.help-menu { position: relative; }

.help-btn { position: relative; }

.help-badge-dot {
  position: absolute;
  top: -2px;
  right: -2px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--brand);
  border: 2px solid var(--surface);
  animation: help-badge-pulse 1.8s ease-in-out infinite;
}

@keyframes help-badge-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.25); opacity: 0.7; }
}

.help-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  width: 360px;
  max-height: 440px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
}

.help-dropdown.open { display: block; }

.help-dropdown-start {
  display: block;
  width: calc(100% - 1.5rem);
  margin: 0.75rem auto 0.25rem;
}

.help-topic {
  padding: 0.65rem 1rem;
  border-bottom: 1px solid var(--border);
}

.help-topic:last-child { border-bottom: none; }

.help-topic-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.15rem;
}

.help-topic-text {
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.45;
}

.help-topic-example {
  margin-top: 0.35rem;
  font-size: 0.76rem;
  color: var(--brand-dark);
  background: var(--brand-soft);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.5rem;
}

.help-topic-clickable {
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}

.help-topic-clickable:hover { background: var(--bg-alt); }

/* --- Sugestao automatica do tour (2026-08-16) ------------------------------
   Pedido do usuario: o badge-dot sozinho (ja pulsava, mas era pequeno demais
   pra chamar atencao de verdade) nao bastava -- "o icone devera ficar
   piscando e com um tooltip sugestivo, sempre aberto". Duas pecas: um anel
   pulsando ao REDOR do botao (mais chamativo que o pontinho) e um balao que
   abre SOZINHO (sem precisar clicar), convidando a conhecer o tour. */
@keyframes help-btn-pulse-ring {
  0% { box-shadow: 0 0 0 0 var(--brand-glow); }
  70% { box-shadow: 0 0 0 8px rgba(33, 150, 243, 0); }
  100% { box-shadow: 0 0 0 0 rgba(33, 150, 243, 0); }
}

.help-btn.help-btn-pulse {
  animation: help-btn-pulse-ring 2s ease-out infinite;
  border-color: var(--brand);
  color: var(--brand);
}

.help-suggest-bubble {
  display: none;
  position: absolute;
  right: -10px;
  top: calc(100% + 16px);
  width: 264px;
  background: var(--surface);
  border: 1px solid var(--brand);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 0.9rem 1.05rem 1rem;
  /* Acima do .help-dropdown normal (z-index 50, ver acima) -- os dois nunca
     ficam abertos ao mesmo tempo (abrir um fecha o outro, ver app_tour.js),
     mas se algum dia coincidirem o convite nao pode ficar escondido atras
     do menu. Abaixo dos modais do sistema (60+). */
  z-index: 52;
}

.help-suggest-bubble.open {
  display: block;
  animation: help-suggest-in var(--dur-slow) var(--ease-spring);
}

@keyframes help-suggest-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.95); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Setinha apontando pro icone -- mesmo truque do quadrado rotacionado 45deg
   usado em tooltips nativos do sistema, so' com fundo/borda do balao. */
.help-suggest-bubble::before {
  content: "";
  position: absolute;
  top: -7px;
  right: 22px;
  width: 13px;
  height: 13px;
  background: var(--surface);
  border-left: 1px solid var(--brand);
  border-top: 1px solid var(--brand);
  transform: rotate(45deg);
}

.help-suggest-close {
  position: absolute;
  top: 0.35rem;
  right: 0.45rem;
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border: none;
  box-shadow: none;
  color: var(--text-faint);
  font-size: 1.05rem;
  line-height: 1;
}

.help-suggest-close:hover { background: var(--neutral-soft); color: var(--text); border-color: transparent; }

.help-suggest-title {
  font-weight: 800;
  font-size: 0.86rem;
  color: var(--text);
  margin: 0 1.2rem 0.3rem 0;
}

.help-suggest-text {
  font-size: 0.78rem;
  color: var(--text-muted);
  line-height: 1.45;
  margin-bottom: 0.75rem;
}

.help-suggest-cta {
  display: block;
  width: 100%;
  height: auto;
  padding: 0.5rem 0.8rem;
  font-size: 0.8rem;
}

/* Breve destaque no elemento "espiado" a partir do painel de ajuda -- so'
   contorno/sombra (nunca opacity/transform que faca o elemento sumir se a
   animacao nao rodar, mesma regra ja usada no resto do projeto). */
.adsp-tour-peek {
  outline: 3px solid var(--brand) !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--brand-glow) !important;
  border-radius: var(--radius-sm);
  transition: outline-color var(--dur-fast) var(--ease-out);
}

/* --- Passo a passo guiado (spotlight + tooltip) --------------------------- */
.adsp-tour-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9000;
}

.adsp-tour-overlay.open { display: block; }

.adsp-tour-spotlight {
  position: fixed;
  border-radius: 10px;
  box-shadow: 0 0 0 9999px rgba(15, 23, 32, 0.62);
  transition: top 0.25s ease, left 0.25s ease, width 0.25s ease, height 0.25s ease;
  pointer-events: none;
  z-index: 9001;
}

.adsp-tour-card {
  position: fixed;
  width: 320px;
  max-width: calc(100vw - 2rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 1.1rem 1.2rem 1rem;
  z-index: 9002;
  transition: top 0.25s ease, left 0.25s ease;
}

.adsp-tour-close {
  position: absolute;
  top: 0.5rem;
  right: 0.65rem;
  background: none;
  border: none;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.2rem;
}

.adsp-tour-close:hover { color: var(--text); }

.adsp-tour-progress {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 0.35rem;
}

.adsp-tour-title {
  margin: 0 0 0.4rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  padding-right: 1.2rem;
}

.adsp-tour-text {
  margin: 0;
  font-size: 0.87rem;
  line-height: 1.55;
  color: var(--text-muted);
  white-space: pre-line;
}

.adsp-tour-example {
  margin-top: 0.6rem;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--brand-dark);
  background: var(--brand-soft);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.65rem;
}

.adsp-tour-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1rem;
}

.adsp-tour-skip {
  font-size: 0.78rem;
  padding: 0;
}

.adsp-tour-nav {
  display: flex;
  gap: 0.5rem;
}

.notif-empty {
  padding: 0.9rem;
  margin: 0;
}

.notif-list {
  list-style: none;
  margin: 0;
  padding: 0.35rem;
}

.notif-list li { margin: 0; }

/* Item da notificacao (redesenhado em 2026-07-31, pedido do usuario:
   "melhorar visualizacao (...) para saber o que e' cada notificacao").
   Era um bloco de texto puro, onde so' dava pra saber do que se tratava
   lendo a frase inteira. Agora e' uma grade de 3 partes:
     [icone do tipo]  [mensagem + badges + horario]
   O icone da a categoria de relance; o badge diz o canal (ML/Shopee). */
.notif-list a {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.6rem;
  align-items: start;
  padding: 0.65rem;
  border-radius: var(--radius-sm);
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--text);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-out);
}

.notif-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  flex: 0 0 auto;
}

.notif-icone svg { width: 15px; height: 15px; }

/* Cor por tipo -- reaproveita os tokens de estado que ja existem no tema,
   entao o modo escuro vem de graca. */
.notif-icone-success { background: var(--success-bg); color: var(--success-text); }
.notif-icone-info    { background: var(--info-bg);    color: var(--info-text); }
.notif-icone-warning { background: var(--warning-bg); color: var(--warning-text); }
.notif-icone-error   { background: var(--error-bg);   color: var(--error-text); }
.notif-icone-neutral { background: var(--neutral-soft); color: var(--text-muted); }

.notif-corpo { min-width: 0; }   /* deixa o texto truncar dentro da grade */

.notif-mensagem {
  display: block;
  overflow-wrap: anywhere;
}

.notif-meta {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
  margin-top: 0.3rem;
  font-size: 0.68rem;
  color: var(--text-faint);
}

.notif-tipo-tag {
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-size: 0.62rem;
}

.notif-meta .platform-tag { font-size: 0.6rem; }

/* Bolinha da marca marca o que ainda nao foi lido. */
.notif-list-item:not(.is-read) > a { position: relative; }

.notif-list-item:not(.is-read) .notif-mensagem { font-weight: 600; }

.notif-list-item:not(.is-read) > a::after {
  content: "";
  position: absolute;
  right: 0.55rem;
  top: 0.95rem;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--brand);
}

.notif-list a:hover {
  background: var(--brand-soft);
}

/* Notificacao ja lida (pedido do usuario, 2026-07-24): NUNCA some da
   lista, so' fica esmaecida -- marcar como lida agora e' automatico (abrir
   o sino), sem mais botao manual por item nem "marcar todas". */
.notif-list-item.is-read a { opacity: 0.62; }

/* Item que ACABOU de chegar pelo tempo real: um realce curto chama a
   atencao sem exigir que o usuario compare a lista com o que lembrava.
   Desligado para quem pediu menos movimento no sistema. */
@keyframes notif-chegou {
  from { background: var(--brand-soft); }
  to   { background: transparent; }
}

.notif-list-item.notif-nova > a {
  animation: notif-chegou 2s var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .notif-list-item.notif-nova > a { animation: none; }
}

/* "Carregar mais" e' uma acao secundaria dentro do painel -- herdava o
   botao azul solido de `.button-link` (fundo, borda e altura de botao
   principal), o que competia com as proprias notificacoes. Aqui vira um
   link discreto, so texto, sublinhado no hover. */
.notif-load-more {
  display: block;
  width: 100%;
  height: auto;
  padding: 0.6rem 0 0.7rem;
  background: none;
  border: none;
  border-top: 1px solid var(--border);
  border-radius: 0;
  box-shadow: none;
  color: var(--text-muted);
  font-size: 0.76rem;
  font-weight: 600;
  text-align: center;
  transition: color var(--dur-fast) var(--ease-out);
}

.notif-load-more:hover {
  background: none;
  border-color: var(--border);
  color: var(--brand-dark);
  text-decoration: underline;
  box-shadow: none;
  transform: none;
}

/* Card do usuario + dropdown no header */

.user-menu { position: relative; }

/* O card da conta fica ao lado de 3 .icon-btn (tema, idioma, notificações), que
   usam --radius-sm. Ele era uma pílula (999px) de 38px de altura no meio de
   botões quadrados de 30px -- destoava da barra inteira (2026-08-05: "é para
   ajustar o fundo ou tirar esse arredondamento, está tudo amador"). Agora segue
   o mesmo raio e a mesma altura dos vizinhos; só o avatar continua redondo. */
.user-card-btn {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: 30px;
  padding: 0 0.6rem 0 0.25rem;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text);
  font-weight: 600;
  font-size: 0.82rem;
  cursor: pointer;
}

/* BUG REAL corrigido (2026-08-06, reportado pelo usuario): no hover, o texto
   ficava BRANCO mas o fundo continuava claro (quase ilegivel). Causa: esta
   regra so' redeclarava `background`/`border-color`, nunca `color` -- e o
   `color: white` generico de `button:hover` (mais abaixo, elemento+pseudo)
   entrava por baixo, ja' que nada aqui competia com ele. `.user-card-btn:hover`
   tem MAIS peso de especificidade que `button:hover` (classe+pseudo >
   elemento+pseudo), entao vencia em `background`/`border-color` sozinho --
   so' faltava declarar `color` tambem, pra nao depender de heranca de uma
   regra alheia. Aproveitado pra declarar as TRES propriedades juntas e usar
   o MESMO azul que `button:hover` ja' usa no resto do sistema (--brand-dark),
   em vez do cinza claro que so' piorava o contraste com o texto branco.

   `.user-card-btn.open` cobre o pedido "qnd o menu suspenso estiver aberto
   ele fica azul, qnd some volta ao normal". ARMADILHA EVITADA: a primeira
   versao disto usava `.user-menu:has(#user-dropdown.open) .user-card-btn`
   (sem JS nenhum, so' lendo o estado real do dropdown) -- mas medido ao
   vivo, esse `:has()` combinado num seletor dinamico (classe trocada via
   `classList.add/remove` depois do primeiro paint) NUNCA disparava
   recalculo de `background-color`/`border-color` neste navegador (so'
   `color` atualizava -- reproduzido isolado, num elemento novo, ate' com
   `!important`, sem nenhuma relacao com o resto do CSS do projeto -- e'
   bug conhecido de invalidacao de `:has()` dinamico em algumas versoes de
   Chromium, nao coisa desta regra). Trocado pelo padrao classico e' 100%
   confiavel do projeto inteiro: JS poe/tira `.open` no proprio botao
   (toggleUserMenu/closeUserMenu em base.html), CSS so' reage a classe. */
.user-card-btn:hover,
.user-card-btn.open {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: #fff;
}

.user-card-btn .avatar {
  /* 22px pra caber nos 30px do card (que agora tem a altura dos .icon-btn
     vizinhos) sem encostar na borda. Redondo de propósito -- é avatar. */
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 0.7rem;
  flex-shrink: 0;
}

.user-card-btn img.avatar.avatar-photo {
  object-fit: cover;
  background: var(--bg-alt);
}

/* Foto de perfil no popup "Meu perfil" (pedido do usuário, 2026-07-19):
   círculo grande clicável com badge de lápis no canto -- clique abre o
   input file escondido. */
.profile-photo-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: 0.5rem;
}

.profile-photo-btn {
  position: relative;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  padding: 0;
  border: 1px solid var(--border);
  background: var(--bg-alt);
  overflow: visible;
  cursor: pointer;
  box-shadow: none;
}

.profile-photo-btn:hover {
  transform: none;
  box-shadow: none;
}

.profile-photo-btn img,
.profile-photo-btn .profile-photo-initials {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  object-fit: cover;
  display: grid;
  place-items: center;
  background: var(--brand);
  color: #fff;
  font-weight: 700;
  font-size: 1.35rem;
}

.profile-photo-edit-badge {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: grid;
  place-items: center;
  border: 2px solid var(--surface);
}

/* Wrapper so' pra posicionar o badge de remover FORA do <button> da foto
   (um <button> dentro de <button> e' HTML invalido -- mesma armadilha ja
   documentada no projeto pra menus de linha clicavel). */
.profile-photo-wrap {
  position: relative;
  width: 76px;
  height: 76px;
  flex: 0 0 auto;
}

.profile-photo-remove-badge {
  position: absolute;
  left: -2px;
  top: -2px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--error-bg, #fdecea);
  color: var(--error-text, #d32f2f);
  display: grid;
  place-items: center;
  border: 2px solid var(--surface);
  padding: 0;
  box-shadow: none;
  cursor: pointer;
  z-index: 1;
}

.profile-photo-remove-badge:hover {
  background: var(--error-text, #d32f2f);
  color: #fff;
  transform: none;
  box-shadow: none;
}

.user-card-name {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  min-width: 190px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
  padding: 0.4rem;
}

.user-dropdown.open { display: block; }

.user-dropdown button {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.55rem;
  width: 100%;
  background: none;
  border: none;
  color: var(--text);
  font-weight: 600;
  font-size: 0.82rem;
  padding: 0.55rem 0.6rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
}

.user-dropdown button:hover {
  background: var(--bg-alt);
}

.user-dropdown-danger {
  color: var(--error-text) !important;
}

.button-danger {
  background: var(--danger);
  border: 1px solid var(--danger);
  color: #fff;
  border-radius: var(--radius-sm);
  height: var(--field-h);
  padding: 0 1.2rem;
  font-weight: 600;
  cursor: pointer;
}

.button-danger:hover {
  background: var(--danger-dark);
  border-color: var(--danger-dark);
  filter: none;
}

.button-danger:focus-visible {
  box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.3);
}

@media (max-width: 900px) {
  .topbar {
    margin: -1.25rem -1.1rem 1.25rem;
    padding-left: 1.1rem;
    padding-right: 1.1rem;
  }
  .user-card-name { display: none; }
}

.topbar h1 {
  font-size: 1.55rem;
  font-weight: 800;
}

.topbar .eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--brand);
  margin-bottom: 0.25rem;
}

/* Surfaces */

.hero,
.panel,
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  /* fill "backwards" (nunca "both/forwards"): o transform some quando a
     animacao termina -- transform residual criaria stacking context
     permanente no painel e dropdowns internos ficariam por baixo dos
     paineis seguintes. */
  animation: rise-in var(--dur-slow) var(--ease-out) backwards;
}

/* Entrada escalonada dos cards de estatistica -- um atras do outro, efeito
   de sistema vivo sem atrasar o uso (delays curtos). */
.stats .card:nth-child(1) { animation-delay: 0.03s; }
.stats .card:nth-child(2) { animation-delay: 0.09s; }
.stats .card:nth-child(3) { animation-delay: 0.15s; }
.stats .card:nth-child(4) { animation-delay: 0.21s; }

.card {
  transition: transform var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: rgba(33, 150, 243, 0.4);
}

.hero,
.panel {
  padding: 1.6rem 1.75rem;
  margin-bottom: 1.5rem;
}

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.panel-head p {
  margin: 0;
}

/* Sincronização (Configurações > Configurações gerais) -- pedido do
   usuário 2026-07-13: seção unificada (sync automática + escopo por grupo
   + pós-venda + revalidação), separadores discretos entre os 3 blocos e
   lista do popup de histórico. */
.sync-panel-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1.25rem 0;
}

.sync-subsection-title {
  margin: 0 0 0.15rem;
  font-size: 0.95rem;
  color: var(--text);
}

.sync-history-list {
  max-height: 60vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 0.75rem;
}

.sync-history-row {
  border: 1px solid var(--border);
  border-left: 3px solid var(--neutral);
  border-radius: 8px;
  padding: 0.6rem 0.75rem;
  background: var(--bg-alt);
}

.sync-history-row.is-success { border-left-color: var(--brand); }
.sync-history-row.is-error { border-left-color: var(--danger); }
/* --warning-text, NAO --warning: essa variavel nunca existiu no :root (ver o
   aviso longo perto de .badge-nova-venda). Com var() indefinida a propriedade
   INTEIRA e' descartada em silencio, entao a linha "pulada" ficava com o
   border-left: 3px solid var(--neutral) da regra base -- visualmente igual a
   uma linha sem estado nenhum. Corrigido em 2026-08-16. */
.sync-history-row.is-skip { border-left-color: var(--warning-text); }

.sync-history-row-top {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.78rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.sync-history-target {
  margin-top: 0.25rem;
  font-weight: 600;
  color: var(--text);
}

.sync-history-message {
  margin-top: 0.15rem;
  font-size: 0.88rem;
  color: var(--text-muted);
}

/* Sincronização centralizada POR EMPRESA (Cadastro de Empresa > aba
   Sincronização, 2026-08-01) -- pedido do usuário: "o que estavindo
   informação de fora e atualizando o app... temq ser distinto" do "qnd for
   o app atualizando". Dois cartões visualmente diferentes por plataforma:
   OUTBOUND (app -> plataforma, cor da marca) e INBOUND (plataforma -> app
   via webhook, cor info/ciano com fundo tingido) -- nunca a mesma aparência,
   pra nunca confundir as duas direções. */
.sync-direction-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1rem 1.1rem;
  margin-top: 1.1rem;
  background: var(--bg-alt);
}

.sync-direction-card.sync-direction-outbound {
  border-left: 3px solid var(--brand);
}

.sync-direction-card.sync-direction-inbound {
  border-left: 3px solid var(--info-text);
  background: var(--info-bg);
}

.sync-direction-head {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  margin-bottom: 0.75rem;
}

.sync-direction-icon {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border);
}

.sync-direction-icon svg {
  width: 14px;
  height: 14px;
}

.sync-direction-outbound .sync-direction-icon {
  color: var(--brand);
  border-color: var(--brand);
}

.sync-direction-inbound .sync-direction-icon {
  color: var(--info-text);
  border-color: var(--info-text);
}

.sync-direction-eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text);
}

.sync-direction-inbound .sync-direction-eyebrow {
  color: var(--info-text);
}

.company-sync-platform-pane {
  margin-top: 0.25rem;
}

/* Sub-cabecalho de secao dentro de uma aba do Cadastro de Empresa (2026-08-01,
   modernizacao pedida pelo usuario) -- mesma tipografia eyebrow ja usada em
   .sync-direction-eyebrow, reaproveitada aqui pra padronizar as demais abas
   (antes cada uma tinha um <span style="font-size:0.85rem;..."> inline
   diferente). Sempre combinado com .label-row (rotulo + tooltip) no mesmo
   elemento -- por isso o seletor combinado (2 classes), NUNCA so
   ".company-section-title": medido ao vivo que ".label-row" (1 classe,
   mesma especificidade de ".company-section-title" sozinho) vem DEPOIS no
   arquivo e venceria o "display:flex" na cascata, deixando o elemento
   "inline-flex" (largura do conteudo) -- a borda inferior, pensada pra
   atravessar a linha toda, ficaria so' embaixo do texto+icone. */
.label-row.company-section-title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  padding-bottom: 0.55rem;
  margin-bottom: 0.3rem;
  border-bottom: 1px solid var(--border);
}

.panel > h2:first-child,
.panel > h3:first-child,
.panel-head:first-child {
  margin-top: 0;
}

.narrow {
  max-width: 520px;
}

.pill-count {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  padding: 0.28rem 0.65rem;
  border-radius: 999px;
}

.hero {
  background:
    linear-gradient(120deg, rgba(38, 50, 56, 0.97), rgba(55, 71, 79, 0.92)),
    radial-gradient(600px 260px at 100% 0%, rgba(33, 150, 243, 0.4), transparent 60%);
  color: #e9ecef;
  border: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.hero h2 { color: #fff; }
.hero p { color: rgba(233, 236, 239, 0.78); max-width: 46ch; }

.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.18);
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  color: #e9ecef;
  white-space: nowrap;
}

.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.card {
  padding: 1.3rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.card .card-icon {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--brand-soft);
  color: var(--brand-dark);
  display: grid;
  place-items: center;
  margin-bottom: 0.6rem;
}

.card .card-icon svg { width: 17px; height: 17px; }

.card strong {
  display: block;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 1.85rem;
  font-weight: 800;
  color: var(--ink);
}

.card span {
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 600;
}

/* Forms */

.form-grid {
  display: grid;
  gap: 1.05rem;
}

label {
  display: grid;
  gap: 0.4rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text);
  /* ARMADILHA DE ALINHAMENTO (corrigida 2026-07-31, reportada varias vezes):
     o <label> e' um grid item da grade de campos e, por padrao, ESTICA pra
     altura da linha inteira -- que e' definida pela celula MAIS ALTA da
     linha. Sem `align-content: start` a sobra de altura e' distribuida entre
     as linhas internas do proprio label, inchando o rotulo (medido: 19px ->
     41px) e empurrando o input pra baixo, desalinhado dos vizinhos. Com
     `start`, as linhas internas ficam no tamanho natural e a sobra vai toda
     pro fim -- os inputs de uma mesma linha sempre comecam na mesma altura. */
  align-content: start;
}

input,
textarea,
select {
  width: 100%;
  padding: 0.78rem 0.9rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-alt);
  color: var(--text);
  font-weight: 500;
  transition: border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

/* input/select (nao textarea, que tem altura variavel por design) seguem a
   mesma altura padrao dos botoes (--field-h) -- padding vertical vira 0,
   so horizontal, pra centralizar o texto dentro da altura fixa. Mesmo
   principio usado em .form-grid.compact-3col mais abaixo. */
input:not([type="file"]),
select {
  height: var(--field-h);
  padding-top: 0;
  padding-bottom: 0;
}

input:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--brand);
  background: var(--surface-solid);
  box-shadow: 0 0 0 3px var(--brand-glow);
}

input[type="file"] {
  padding: 0.6rem 0.7rem;
  cursor: pointer;
}

.field-hint {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-faint);
}

/* Estado vazio padrao das listas (2026-08-16) -- ver macro empty_state() em
   _macros.html. Funciona tanto solto num painel quanto dentro de uma
   <td colspan> de tabela (flex column, sem largura fixa). A animacao reusa
   o keyframe global "rise-in" (ja respeita prefers-reduced-motion). */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 2.75rem 1.5rem;
  text-align: center;
  animation: rise-in var(--dur-slow) var(--ease-out);
}

.empty-state-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 0.3rem;
  border-radius: 50%;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text-faint);
}

.empty-state-title {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text);
}

.empty-state-hint {
  margin: 0;
  max-width: 30rem;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--text-muted);
}

/* Tooltip tematizado (bolha com o visual do app, nao o title nativo do
   navegador) -- usado no icone "i" ao lado do texto do label, tanto pros
   atributos de categoria (.attr-tooltip) quanto pras descricoes de campo
   dos dados comerciais (.field-tooltip). Ambos usam data-tooltip em vez de
   title, e essa mesma regra generica cuida da bolha/seta/posicionamento. */
[data-tooltip] { position: relative; }

[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--dark);
  color: #fff;
  padding: 0.5rem 0.7rem;
  border-radius: var(--radius-sm);
  font-size: 0.74rem;
  font-weight: 500;
  line-height: 1.4;
  white-space: normal;
  width: max-content;
  max-width: 240px;
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease, transform 0.14s ease;
  z-index: 60;
}

[data-tooltip]::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 3px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  border: 5px solid transparent;
  border-top-color: var(--dark);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease, transform 0.14s ease;
  z-index: 60;
}

[data-tooltip]:hover::after, [data-tooltip]:focus::after,
[data-tooltip]:hover::before, [data-tooltip]:focus::before {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.field-tooltip {
  display: inline-flex;
  color: var(--text-faint);
  cursor: help;
  vertical-align: middle;
}

.field-tooltip svg { width: 13px; height: 13px; }

.field-tooltip:hover, .field-tooltip:focus { color: var(--brand-dark); outline: none; }

.label-row {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

/* Linha de resultado dinamico (liquido estimado, aviso de frete, resultado
   de consulta) fora da grade de 3 colunas -- assim nao desalinha as outras
   celulas quando aparece/some ou muda de tamanho. */
.form-row-banner {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-faint);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.85rem;
  margin-top: -0.35rem;
}

.form-row-banner.field-hint-warning {
  background: var(--warning-bg);
  color: var(--warning-text);
  border-color: transparent;
}

.form-row-banner:empty { display: none; }

.diag-log {
  margin: 0.75rem 0 1.25rem;
  font-size: 0.78rem;
  color: var(--text-faint);
}

.diag-log summary {
  cursor: pointer;
  font-weight: 500;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.diag-log summary::-webkit-details-marker {
  display: none;
}

.diag-log-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--error-text, #c0392b);
  display: inline-block;
  flex: none;
}

.diag-log-error {
  margin: 0.5rem 0 0;
  color: var(--error-text, #c0392b);
}

.diag-log-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.photo-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}

.photo-slot {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.1rem;
  background: var(--bg-alt);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.upload-box {
  min-height: 120px;
  border: 1.5px dashed #90caf9;
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  color: var(--brand-dark);
  background: var(--brand-soft);
  margin: 0.5rem 0;
  text-align: center;
  padding: 1rem;
  font-weight: 600;
  font-size: 0.85rem;
}

/* Dashboard charts */

.charts-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin-bottom: 1.5rem;
}

.chart-card {
  margin-bottom: 0;
}

.chart-card canvas {
  max-height: 260px;
  padding: 0.5rem 1.75rem 1.5rem;
  box-sizing: border-box;
}

@media (max-width: 900px) {
  .charts-row { grid-template-columns: 1fr; }
}

/* Tables */

/* PADRAO DE LISTAGEM (regra permanente, 2026-07-20): toda tela de lista nova
   (produtos, anuncios, grupos, categorias ML, marcas, etc.) deve reusar
   exatamente este conjunto de classes -- .products-toolbar (busca +
   .toolbar-actions-right com botao Filtrar/menu "...") + opcional .bulk-bar
   + .table-card > .panel-head (h3 + .pill-count) > .table-scroll table
   (thead/tbody, tr.row-clickable, td.row-actions > div.row-actions-inner
   com os .icon-btn) + macro pagination() de _macros.html. Mudar essas
   classes aqui vale pra TODAS as listas do sistema de uma vez -- nunca
   criar uma classe nova de lista paralela (ex. .ai-model-list era usado
   pra grupos e foi trocado por essa mesma tabela em 2026-07-20). */

.table-card {
  background: var(--surface);
  border: 1px solid var(--border);
  /* Canto menos arredondado que os paineis (8px no lugar de 12px): lista de
     dados pede aparencia mais "seca"/tecnica, e o raio grande brigava com os
     cantos retos das celulas na primeira e ultima linha. */
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  margin-bottom: 1.5rem;
  /* fill "backwards" (nunca "both/forwards"): o transform some quando a
     animacao termina -- transform residual criaria stacking context
     permanente no painel e dropdowns internos ficariam por baixo dos
     paineis seguintes. */
  animation: rise-in var(--dur-slow) var(--ease-out) backwards;
}

.table-card .panel-head {
  padding: 1.5rem 1.75rem 0.75rem;
  margin-bottom: 0;
}

.table-scroll {
  overflow-x: auto;
  /* overflow-x sem overflow-y pareado promove o eixo Y pra auto sozinho
     (regra da spec CSS Overflow) -- ver comentario completo em .ad-tab-bar. */
  overflow-y: hidden;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

thead th {
  text-align: left;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  font-weight: 700;
  padding: 0.9rem 1.2rem;
  background: var(--bg-alt);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.table-card table thead th:first-child { padding-left: 1.75rem; }
.table-card table thead th:last-child { padding-right: 1.75rem; }
.table-card table tbody td:first-child { padding-left: 1.75rem; }
.table-card table tbody td:last-child { padding-right: 1.75rem; }

/* Coluna "Categoria" da lista de categorias do ML (meli_categories.html) --
   breadcrumb completo (ex. "Autopeças > Elétrica > Alternadores") ficava
   espremido/quebrando em várias linhas nas demais colunas mais estreitas
   (pedido do usuário, 2026-07-20). */
.category-name-col { min-width: 340px; max-width: 480px; white-space: normal; }

td,
tbody th {
  padding: 0.95rem 1.2rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  color: var(--text);
  text-align: left;
  font-weight: 600;
}

tbody th { font-weight: 700; white-space: nowrap; }
tbody td { font-weight: 500; }

tbody tr:last-child td { border-bottom: none; }

tbody tr {
  transition: background var(--dur-fast) var(--ease-out);
}

/* --- Padrao unico das listas (zebrado + acabamento) ------------------------
   Escopado em `.table-card` de proposito: pega as 11 listas do sistema
   (produtos, anuncios, perguntas, marcas, veiculos, grupos, categorias,
   organizacoes, conhecimento, usuarios, dashboard) sem tocar nas tabelas
   internas de outra natureza -- compatibilidade, aplicacao e variacoes tem
   fundo/estado proprios e ficariam com listras concorrentes. */
/* Tom azulado bem leve em vez de `--bg-alt` (#f8fafc): aquele valor e' quase
   branco puro e o zebrado praticamente nao aparecia contra o fundo do card.
   Este puxa levemente pra cor da marca, entao a alternancia se le de relance
   sem virar listra chamativa. */
.table-card tbody tr:nth-child(even) {
  /* Mais destaque (pedido do usuario, 2026-08-04: "dar mais destaque para
     o efeito zebrado") -- era quase imperceptivel (0.035), aumentado sem
     virar listra chamativa. */
  background: rgba(33, 150, 243, 0.06);
}

/* O hover precisa vir DEPOIS do zebrado e ser mais forte que ele, senao a
   linha par nao acende ao passar o mouse (as duas regras disputam o mesmo
   `background` e a de maior peso/ordem vence). Exclui .ad-quality-row (a
   linha injetada com o painel de Qualidade/detalhe de venda expandido,
   qualquer plataforma -- Mercado Livre/Shopee/futura -- e' a MESMA classe
   compartilhada) -- pedido do usuario, 2026-07-30: "nao deve ter ação
   hover" -- essa linha nunca e' clicavel, so' mostra conteudo, entao nao
   deve parecer interativa ao passar o mouse. */
.table-card tbody tr:hover:not(.ad-quality-row),
.table-card tbody tr:nth-child(even):hover:not(.ad-quality-row) {
  background: var(--brand-soft);
}

/* Cabecalho mais firme: a borda de 1px se perdia contra o zebrado. */
.table-card thead th {
  border-bottom: 2px solid var(--border-strong);
}

/* Linha divisoria mais discreta -- com o zebrado marcando a alternancia, a
   borda cheia em toda linha vira ruido visual. */
.table-card tbody td {
  border-bottom-color: rgba(227, 232, 238, 0.7);
}

tbody tr:hover:not(.ad-quality-row) {
  background: rgba(33, 150, 243, 0.05);
}

td.empty-cell {
  text-align: center;
  color: var(--text-faint);
  padding: 2.75rem 1rem;
  font-weight: 500;
}

/* Status icons (products / ads lists) */

.ad-status-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
}

.ad-status-icon svg { width: 15px; height: 15px; }

.ad-status-icon.done { background: var(--success-bg); color: var(--success-text); }
.ad-status-icon.pending { background: var(--warning-bg); color: var(--warning-text); }
.ad-status-icon.none { background: var(--neutral-soft); color: var(--text-faint); }

/* Status do produto no catálogo (lista de produtos, coluna "Status") --
   pedido do usuario 2026-07-19: clique abre popup de atalho pra habilitar
   /desabilitar por empresa. Botao em vez de badge estatico pra deixar claro
   que e' clicavel, mesma altura --field-h do resto do sistema. */
.catalog-status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  height: auto;
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  border: 1px solid transparent;
  box-shadow: none;
  /* Uma linha so': "No catálogo (1)" quebrava em duas/tres linhas dentro da
     celula estreita e o pill ficava com cara de bloco de texto. */
  white-space: nowrap;
}

/* A coluna acompanha o pill em vez de espremer o texto dentro dele. Como o
   pill deixou de quebrar, ele passou a exigir a largura toda de uma vez --
   por isso o texto fica um tico menor aqui, pra nao roubar espaco da coluna
   de aplicacao (a mais importante da lista). */
.table-card td:has(> .catalog-status-badge) {
  white-space: nowrap;
  width: 1%;
}

.table-card .catalog-status-badge {
  font-size: 0.72rem;
  padding: 0.28rem 0.55rem;
  gap: 0.28rem;
}

.table-card .catalog-status-badge svg {
  width: 12px;
  height: 12px;
}

.catalog-status-badge svg {
  flex: 0 0 auto;
}
.catalog-status-badge svg { width: 13px; height: 13px; flex: 0 0 auto; }
.catalog-status-badge.visible { background: var(--success-bg); color: var(--success-text); border-color: var(--success-bg); }
.catalog-status-badge.linked { background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning-bg); }
.catalog-status-badge.none { background: var(--neutral-soft); color: var(--text-faint); border-color: var(--neutral-soft); }
.catalog-status-badge:hover { transform: none; box-shadow: none; filter: brightness(0.96); }

.photo-count-icon {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--warning-text);
}

.photo-count-icon svg { width: 15px; height: 15px; }
.photo-count-icon.ready { color: var(--success-text); }

/* Status badges */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 700;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge-success { background: var(--success-bg); color: var(--success-text); }
.badge-info { background: var(--info-bg); color: var(--info-text); }
.badge-warning { background: var(--warning-bg); color: var(--warning-text); }
.badge-error { background: var(--error-bg); color: var(--error-text); }
.badge-neutral { background: var(--neutral-soft); color: var(--text-muted); }

/* ---- Cores por etapa da venda (Vendas) ----------------------------------
   Pedido do usuario 2026-07-30: "definir cores diferentes para os status".
   Antes READY_TO_SHIP, PROCESSED, SHIPPED e TO_CONFIRM_RECEIVE eram TODOS
   badge-info -- 4 etapas bem diferentes com a mesma cor. Aqui cada etapa da
   jornada tem a sua, na ordem em que a venda anda (ambar -> roxo -> azul ->
   indigo -> ciano -> verde-agua -> verde), com 3 cores de excecao (alerta,
   cancelando, cancelado). Status que significam a MESMA etapa compartilham
   a cor de proposito -- e' o que faz a lista ser lida de relance.
   As mesmas classes valem pro stepper do detalhe (ORDER_STAGES), pra nao
   mostrar duas cores diferentes pra mesma venda. */
.badge-order-pending { background: #fff3e0; color: #b26a00; }
.badge-order-paid { background: #ede7f6; color: #5e35b1; }
.badge-order-ready { background: #e3f2fd; color: #1565c0; }
.badge-order-collect { background: #e8eaf6; color: #3949ab; }
.badge-order-shipped { background: #e0f7fa; color: #00838f; }
.badge-order-delivered { background: #e0f2f1; color: #00695c; }
.badge-order-done { background: #e8f5e9; color: #2e7d32; }
.badge-order-alert { background: #fbe9e7; color: #d84315; }
.badge-order-cancelling { background: #fce4ec; color: #ad1457; }
.badge-order-cancelled { background: #fdecea; color: #c62828; }

/* Tema escuro: fundo translucido da propria cor (mesma tecnica dos tokens
   --success-bg/--info-bg no dark) + texto claro, pra manter contraste. */
:root[data-theme="dark"] .badge-order-pending { background: rgba(255, 152, 0, 0.18); color: #ffb74d; }
:root[data-theme="dark"] .badge-order-paid { background: rgba(149, 117, 205, 0.18); color: #b39ddb; }
:root[data-theme="dark"] .badge-order-ready { background: rgba(33, 150, 243, 0.18); color: #64b5f6; }
:root[data-theme="dark"] .badge-order-collect { background: rgba(92, 107, 192, 0.20); color: #9fa8da; }
:root[data-theme="dark"] .badge-order-shipped { background: rgba(0, 172, 193, 0.18); color: #4dd0e1; }
:root[data-theme="dark"] .badge-order-delivered { background: rgba(0, 150, 136, 0.20); color: #4db6ac; }
:root[data-theme="dark"] .badge-order-done { background: rgba(76, 175, 80, 0.18); color: #81c784; }
:root[data-theme="dark"] .badge-order-alert { background: rgba(255, 87, 34, 0.20); color: #ff8a65; }
:root[data-theme="dark"] .badge-order-cancelling { background: rgba(233, 30, 99, 0.20); color: #f06292; }
:root[data-theme="dark"] .badge-order-cancelled { background: rgba(244, 67, 54, 0.18); color: #e57373; }

/* Tipo de anuncio (lista de anuncios): Premium vs Classico com cor/fundo
   proprios, distintos dos badges de status -- pedido explicito do usuario
   ("deixar a cara do tipo de anuncio com uma cor e fundo diferentes"). */
.listing-type-badge.premium { background: var(--brand-soft); color: var(--brand-dark); }
.listing-type-badge.classico { background: var(--neutral-soft); color: var(--text-muted); }
/* "Padrao": plataformas sem tipo de anuncio (Shopee/TikTok/eBay). Roxo pra
   nao competir com o azul do Premium nem com o cinza do Classico. */
.listing-type-badge.padrao { background: #ede4fb; color: #5b2ca8; }

/* Botao/link da direita da toolbar nao pode quebrar em duas linhas
   (ex.: "Nova categoria") -- bug visual reportado em 2026-07-28. */
.toolbar-actions-right .button-link,
.toolbar-actions-right button { white-space: nowrap; }
/* O <select> ao lado PODE encolher -- travar tudo com flex-shrink:0 fazia o
   grupo estourar pra fora da tela em telas menores (regressao de 2026-07-28). */
.toolbar-actions-right select { min-width: 0; }

/* Tag de plataforma de anuncio (2026-07-24, macro platform_badge em
   _macros.html) -- cor propria por plataforma, sempre visivel mesmo sem
   espaco (sigla abreviada: MLB/SHPP/TKTK/AMZN). Cores fixas das marcas, nao
   usam os tokens de tema (o "amarelo Mercado Livre" nao muda com o tema do
   sistema). */
.platform-tag,
.card .platform-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.14rem 0.45rem;
  border-radius: 5px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.4;
  white-space: nowrap;
  text-transform: uppercase;
}
/* Variante com o nome inteiro (card de plataforma do dashboard). Mantem
   EXATAMENTE a mesma linguagem visual da tag compacta -- mesmo raio, mesma
   caixa alta, mesmo espacamento de letra -- so' com respiro maior porque o
   texto e' mais longo. Antes ela virava uma pilula arredondada em caixa
   baixa, destoando de todas as outras tags do sistema (bug visual real,
   reportado 3x pelo usuario). */
.platform-tag.platform-tag-full { padding: 0.2rem 0.6rem; font-size: 0.68rem; font-weight: 700; }
/* REGRA PERMANENTE (usuario, 2026-07-29): a tag de plataforma SEMPRE usa a
   cor de fundo E a cor de fonte dela, em qualquer lugar do sistema.
   Seletor duplo (.platform-tag.platform-tag-X = 0,2,0) de proposito: dentro
   de um card existe `.card span { color: var(--text-muted) }` (0,1,1), que
   vencia as regras de uma classe so' e apagava a cor da fonte da tag --
   era esse o "fora do padrao" reportado 3x (a cor de fundo estava certa, a
   da FONTE virava cinza). Mesma armadilha ja documentada em
   `.currency-input input`; aqui resolvida por especificidade, sem
   !important. Tag nova segue o mesmo formato de seletor. */
.platform-tag.platform-tag-mlb { background: #FFE600; color: #2b2200; }
.platform-tag.platform-tag-shpp { background: #EE4D2D; color: #ffffff; }
.platform-tag.platform-tag-tktk { background: #010101; color: #25F4EE; box-shadow: inset 0 0 0 1px #FE2C55; }
.platform-tag.platform-tag-amzn { background: #232F3E; color: #FF9900; }
/* Loja Integrada -- roxo da marca deles; nao e' marketplace, e' plataforma
   de loja propria (ver comentario em AD_PLATFORMS, app.py). */
.platform-tag.platform-tag-lint { background: #6D3AC7; color: #ffffff; }
/* eBay -- fundo claro com as 4 cores da marca seria ilegivel numa tag
   pequena, entao usa o azul principal deles sobre branco. */
.platform-tag.platform-tag-ebay { background: #ffffff; color: #0064D2; box-shadow: inset 0 0 0 1px #E53238; }
.ad-cell-platform { margin-bottom: 0.3rem; }

/* Faixa do atalho de atencao, agora fora da linha de busca/filtro (que so
   pode ter busca + botao Filtrar + menu "..." -- pedido explicito do
   usuario) -- vira uma segunda linha discreta abaixo da toolbar. */
/* Banner de atencao (pedido 2026-07-20: mover pra dentro do cabecalho da
   lista, ao lado do titulo "Anuncios", em vez de ficar solto acima da
   toolbar) -- margin-bottom removido, agora e' um item inline num flex row
   junto do <h2>. */
.ads-attention-banner { display: inline-flex; }
.ads-panel-title-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.ads-panel-title-row h2 { margin: 0; }

/* Flash messages */

.flash-list {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 80;
  display: flex;
  flex-direction: column-reverse;
  gap: 0.6rem;
  width: 320px;
  max-width: calc(100vw - 2rem);
  pointer-events: none;
}

/* .flash e' reaproveitada em DOIS contextos diferentes: a pilha de avisos
   do canto inferior direito (#flash-list, em base.html -- cartao
   estruturado com cabecalho/corpo/rodape) e a mensagem simples embutida no
   card de login/cadastro (login.html/_signup_card_fields.html -- so' texto
   corrido, sem sub-elementos). A regra base cobre o fallback do segundo
   caso; o cartao estruturado do primeiro entra logo abaixo, escopado a
   `#flash-list .flash` para nao vazar pro login. */
.flash {
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  background: var(--surface-solid);
  box-shadow: var(--shadow-lg);
  animation: flash-in 0.2s ease-out;
  padding: 0.85rem 1rem;
  font-weight: 600;
  font-size: 0.85rem;
  white-space: pre-line;
  overflow-wrap: break-word;
}

.flash.flash-out { animation: flash-out 0.25s ease-in forwards; }

/* Cartao estruturado da PILHA (cabecalho com icone + titulo + fechar, corpo
   da mensagem rolavel com altura maxima -- e' isso que impede uma mensagem
   longa de publicacao de "estourar" pra fora do topo da tela -- e, so'
   quando ha' link de "Reportar problema", um rodape proprio embaixo de TODO
   o texto, nunca flutuando do lado da primeira linha) (2026-08-16). */
#flash-list .flash {
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  max-height: min(60vh, 420px);
  overflow: hidden;
  padding: 0;
  white-space: normal;
}

@keyframes flash-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes flash-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(8px); }
}

.flash.success { background: var(--success-bg); color: var(--success-text); border-color: rgba(30, 107, 49, 0.15); }
.flash.error { background: var(--error-bg); color: var(--error-text); border-color: rgba(163, 49, 42, 0.15); }
/* Aviso (nao e' falha): usado, por exemplo, quando o acesso e' negado por
   permissao -- some sozinho e nao oferece "Reportar problema", que so faz
   sentido pra erro de codigo. */
.flash.warning { background: var(--warning-bg); color: var(--warning-text); border-color: rgba(176, 106, 0, 0.15); }

.flash-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 0.85rem 0.4rem;
}

.flash-icon {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  display: flex;
}

.flash-icon svg { width: 100%; height: 100%; }

.flash-title {
  flex: 1 1 auto;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  opacity: 0.82;
  /* Titulo de uma linha so' -- se um dia ganhar texto mais longo, encolhe
     com reticencias em vez de empurrar o botao de fechar pra fora. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.flash-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 0.85rem 0.8rem;
  font-weight: 600;
  font-size: 0.85rem;
  line-height: 1.48;
  /* Mensagem de erro de publicacao vem em varias linhas (um problema por
     linha, com a explicacao embaixo) -- sem pre-line as quebras viravam
     espaco e tudo saia num paragrafo unico ilegivel. */
  white-space: pre-line;
  overflow-wrap: break-word;
}

.flash-footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  padding: 0.55rem 0.85rem 0.75rem;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
}

.flash-close {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.08);
  color: inherit;
  box-shadow: none;
  padding: 0;
  font-size: 0.6rem;
  line-height: 1;
}

.flash-close:hover { background: rgba(0, 0, 0, 0.16); transform: none; box-shadow: none; }

.flash-body::-webkit-scrollbar { width: 6px; }

@media (max-width: 620px) {
  .flash-list { left: 1rem; right: 1rem; width: auto; bottom: 1rem; }
  #flash-list .flash { max-height: min(55vh, 360px); }
}

pre {
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  padding: 1.1rem 1.25rem;
  border-radius: var(--radius-md);
  font-size: 0.82rem;
  color: var(--text-muted);
  max-height: 360px;
  overflow-y: auto;
}

.description-preview {
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  padding: 0.9rem 1.1rem;
  border-radius: var(--radius-md);
  font-size: 0.88rem;
  line-height: 1.55;
}

/* Telas de acesso (login, cadastro, redefinicao de senha, retorno do
   Google) -- repaginadas em 2026-08-18 no MESMO tema claro premium da
   landing page (pedido do usuario: "de acordo com o que foi pedido pra
   landing page vamos agora no mesmo tema com a mesma ideia ajustar a tela
   de login e cadastro, repaginação completa"). Mesma identidade do
   landing.html: fundo claro com nevoas de luz que derivam devagar (sem
   grade e sem particulas -- a landing aboliu o quadriculado a pedido
   explicito e a porta de entrada acompanha), tipografia Sora (titulos) +
   IBM Plex Sans (corpo), azul gradiente #1565c0 -> #1e88e5 -> #00acc1,
   cartao branco com sombra suave e CTA em pilula.

   Continua intencionalmente independente de --theme/data-theme (agora
   sempre CLARO, mesmo com o app em tema escuro): o toggle de tema nem
   aparece pra quem nao esta logado, e quem chega aqui vem da landing --
   trocar de paleta no meio do caminho quebraria a continuidade.

   Os tokens ficam numa regra propria (.auth-shell E .signup-popup-frame)
   porque o popup de cadastro renderiza o MESMO .auth-card dentro de um
   iframe SEM .auth-shell por volta -- token definido so' no shell sumiria
   la' e o cartao ficaria sem fundo/sombra em silencio. */

.auth-shell,
.signup-popup-frame {
  /* Espelho dos --lp-* da landing (landing.html e' standalone e nao
     compartilha CSS com o app -- duplicar os valores aqui e' o que mantem
     a paleta unica sem carregar os 444KB do styles.css la'). Mudou la',
     muda aqui junto. */
  --auth-ink: #0e1c2e;
  --auth-muted: #55677f;
  --auth-faint: #8b99ad;
  --auth-line: #e4eaf3;
  --auth-line-strong: #d2dcea;
  --auth-surface: #ffffff;
  --auth-accent: #1e88e5;
  --auth-accent-dark: #1565c0;
  --auth-grad: linear-gradient(96deg, #1565c0, #1e88e5 55%, #00acc1);
  --auth-sh-sm: 0 1px 2px rgba(14, 28, 46, 0.05), 0 4px 14px rgba(14, 28, 46, 0.05);
  --auth-sh-lg: 0 24px 70px rgba(21, 101, 192, 0.16), 0 6px 18px rgba(14, 28, 46, 0.08);
  --auth-disp: 'Sora', 'Plus Jakarta Sans', 'Segoe UI', system-ui, sans-serif;
  --auth-body: 'IBM Plex Sans', 'Inter', 'Segoe UI', system-ui, sans-serif;
}

.auth-shell {
  position: relative;
  width: 100%;
  min-height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #fbfdff 0%, #f6f8fc 55%, #eef3fa 100%);
  color: var(--auth-ink);
  font-family: var(--auth-body);
}

/* Rede de seguranca por ALTURA (nao so' largura) -- notebook comum com barra
   de tarefas + abas do navegador costuma sobrar so' ~650-700px de altura
   util mesmo numa tela 1366x768. `overflow:hidden` no .auth-shell cortaria
   (esconderia) conteudo de verdade se a coluna esquerda nao coubesse -- pior
   que deixar rolar. So' entra em jogo quando a altura realmente aperta;
   nas resolucoes desktop comuns (>=820px de altura util) nunca aparece
   scrollbar nenhuma, exatamente o pedido do usuario. */
@media (max-height: 900px) {
  .auth-shell {
    overflow-y: auto;
  }
}

.auth-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Nevoas de luz drifting -- MESMO fundo da landing (.lp-blob-1/2/3 de
   landing.html, cores e ritmos identicos): tres borroes de luz azul/ciano
   que derivam devagar. So' animam `transform`, GPU-only, mesma disciplina
   de sempre nas animacoes de fundo. */
.auth-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  will-change: transform;
}

.auth-blob-1 {
  width: 640px;
  height: 640px;
  top: -16%;
  right: -8%;
  background: radial-gradient(circle at 40% 40%, rgba(30, 136, 229, 0.34), rgba(30, 136, 229, 0) 70%);
  animation: auth-blob-drift-1 26s ease-in-out infinite;
}

.auth-blob-2 {
  width: 520px;
  height: 520px;
  top: 26%;
  left: -12%;
  background: radial-gradient(circle at 60% 40%, rgba(0, 172, 193, 0.26), rgba(0, 172, 193, 0) 70%);
  animation: auth-blob-drift-2 32s ease-in-out infinite;
}

.auth-blob-3 {
  width: 460px;
  height: 460px;
  bottom: -14%;
  right: 18%;
  background: radial-gradient(circle at 50% 50%, rgba(100, 181, 246, 0.30), rgba(100, 181, 246, 0) 70%);
  animation: auth-blob-drift-3 38s ease-in-out infinite;
}

@keyframes auth-blob-drift-1 { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-90px, 70px) scale(1.12); } }
@keyframes auth-blob-drift-2 { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(110px, -60px) scale(1.08); } }
@keyframes auth-blob-drift-3 { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-70px, -80px) scale(1.15); } }

/* Feixe fino de luz cruzando o topo (mesmo .lp-bg::after da landing).
   Escopado ao .auth-shell de proposito: o .auth-bg tambem e' reusado pelo
   legal_standalone.html (fundo escuro proprio), que nao deve ganhar o
   feixe claro por tabela. */
.auth-shell .auth-bg::after {
  content: "";
  position: absolute;
  top: 0;
  left: -40%;
  width: 60%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(30, 136, 229, 0.55), transparent);
  animation: auth-beam 8s ease-in-out infinite;
}

@keyframes auth-beam {
  0%, 100% { transform: translateX(0); opacity: 0; }
  50% { transform: translateX(200%); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .auth-blob,
  .auth-shell .auth-bg::after {
    animation: none;
  }
}

/* ---- Camadas ESCURAS antigas do fundo futurista (grade + glows +
   canvas de particulas) -- as telas de auth NAO as usam mais desde a
   repaginacao clara de 2026-08-18, mas legal_standalone.html (politica de
   privacidade/termos de uso, pagina standalone de fundo escuro proprio)
   continua montando o fundo dele com elas. Remover quebraria aquelas
   paginas em silencio. ---- */
.auth-bg-grid {
  position: absolute;
  inset: -10%;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
  background-size: 46px 46px;
  mask-image: radial-gradient(ellipse 70% 55% at 50% 32%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 70% 55% at 50% 32%, #000 0%, transparent 78%);
}

/* Bolhas de luz que derivam e pulsam devagar -- o "efeito de luzes
   animado" pedido. 3 tons (azul da marca, ciano, violeta) pra ficar rico
   sem sair da paleta do sistema (--brand/--info-text sao a mesma familia
   de azul/ciano ja usada em todo o resto do app). */
.auth-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  will-change: transform, opacity;
}

.auth-glow-1 {
  width: 640px;
  height: 640px;
  left: -14%;
  top: -16%;
  background: radial-gradient(circle, rgba(33, 150, 243, 0.55), transparent 70%);
  animation: auth-glow-drift-1 22s ease-in-out infinite;
}

.auth-glow-2 {
  width: 560px;
  height: 560px;
  right: -12%;
  top: 6%;
  background: radial-gradient(circle, rgba(0, 172, 193, 0.42), transparent 70%);
  animation: auth-glow-drift-2 27s ease-in-out infinite;
}

.auth-glow-3 {
  width: 520px;
  height: 520px;
  left: 28%;
  bottom: -20%;
  background: radial-gradient(circle, rgba(124, 77, 255, 0.32), transparent 70%);
  animation: auth-glow-drift-3 31s ease-in-out infinite;
}

@keyframes auth-glow-drift-1 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.5; }
  50% { transform: translate(60px, 45px) scale(1.12); opacity: 0.72; }
}

@keyframes auth-glow-drift-2 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.42; }
  50% { transform: translate(-55px, 55px) scale(1.08); opacity: 0.62; }
}

@keyframes auth-glow-drift-3 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.32; }
  50% { transform: translate(35px, -35px) scale(1.15); opacity: 0.52; }
}

/* Canvas de particulas conectadas (login.html, #auth-particles) -- fica por
   cima dos brilhos/grade (ordem no HTML dentro de .auth-bg) mas atras de
   TODO o conteudo real (.auth-center, fora de .auth-bg, sempre por cima
   por ordem de documento). Nunca intercepta clique/scroll. */
.auth-particles-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Duas colunas lado a lado (2026-08-03, pedido do usuario: "duas coluna era
   apra deixar o login") -- marca/proposta/integracoes/features a esquerda
   (.auth-col-brand), card de acesso a direita (.auth-col-card). Motivo real,
   nao so estetico: o conteudo empilhado numa coluna so (versao anterior)
   estourava 100vh em qualquer monitor com altura <= ~900px, forcando scroll
   vertical que o usuario explicitamente nao quer ("login ta ficando com
   scrooll e nao quero isso"). Lado a lado, a altura da secao vira a MAIOR
   das duas colunas (a esquerda, mais alta) em vez da SOMA das duas -- cabe
   confortavel em qualquer resolucao desktop comum sem precisar de
   `overflow:hidden` forcado (que cortaria conteudo de verdade em telas muito
   baixas, pior que so' deixar rolar). Abaixo de 980px de largura (ver
   media query) colapsa pra 1 coluna com scroll permitido -- normal em
   mobile, nao da pra caber tudo sem rolar numa tela estreita. */
.auth-center {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1180px;
  padding: 1.5rem 2.5rem;
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: 3.5rem;
  align-items: center;
}

.auth-col-brand {
  text-align: left;
}

.auth-col-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* Login enxuto, uma coluna so' (2026-08-06, "deixar essa tela de login com
   menos informação ja que agora temos landingpage") -- proposta de valor
   inteira (h1/lead/integrações/features) saiu do login e vive na landing;
   aqui sobra so' logo + eyebrow + card. Classe explicita no template (em vez
   de detectar via :has()) -- .auth-center ganha largura menor e volta a
   centralizar (era grid de 2 colunas alinhado a esquerda). */
.auth-center.auth-center-single {
  grid-template-columns: 1fr;
  max-width: 540px;
  justify-items: center;
  text-align: center;
}

/* `justify-items: center` encolhe o item de grade pro max-content (a coluna
   ficava com a largura da linha do rodape, ~400px, e o cartao encolhia
   junto) -- estica a coluna de volta; quem centraliza os filhos e' o
   proprio .auth-col-card (flex column + align-items center). */
.auth-center.auth-center-single .auth-col-card {
  width: 100%;
}

/* Logo clicavel -> landing (pedido: "logo ADS deixar maior, e se clicar ele
   manda para landinpage"). Desfaz o visual padrao de link (sem sublinhado/
   cor de link) -- e' so' a imagem que deve parecer clicavel, via cursor. */
.auth-hero-brand {
  display: inline-block;
  text-decoration: none;
  border: none;
  background: none;
  padding: 0;
  margin: 0 0 1rem;
  line-height: 0;
}

.auth-hero-logo {
  max-width: 220px;
  margin-bottom: 0;
  transition: opacity var(--dur-fast, 0.15s) var(--ease-out, ease);
}

.auth-hero-brand:hover .auth-hero-logo,
.auth-hero-brand:focus-visible .auth-hero-logo {
  opacity: 0.86;
}

/* Eyebrow logo ABAIXO da logo (pedido explicito) -- mesmo desenho do
   .lp-eyebrow da landing: caixa alta espacada com um traco gradiente na
   frente, sem pilula. */
.auth-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--auth-accent-dark);
  font-family: var(--auth-disp);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: 1.4rem;
}

.auth-eyebrow::before {
  content: "";
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--auth-grad);
}

.auth-center h1 {
  color: var(--auth-ink);
  font-family: var(--auth-disp);
  font-size: 2.1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.14;
  margin: 0 0 0.75rem;
  max-width: 20ch;
  text-wrap: balance;
}

.auth-lead {
  color: var(--auth-muted);
  font-size: 0.95rem;
  max-width: 46ch;
  margin: 0 0 1.6rem;
}

.auth-integrations {
  margin-bottom: 1.75rem;
}

.auth-integrations-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--auth-faint);
  margin-bottom: 0.6rem;
}

.auth-integrations-row {
  display: flex;
  align-items: center;
  /* Alinhado a esquerda (coluna da marca deixou de ser centralizada no
     layout de 2 colunas) -- so' fica centralizado no fallback mobile de
     1 coluna, ver @media (max-width: 980px). */
  justify-content: flex-start;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.55rem;
  border-radius: 999px;
  background: var(--auth-surface);
  border: 1px solid var(--auth-line);
  box-shadow: var(--auth-sh-sm);
  width: fit-content;
}

.auth-features {
  width: 100%;
  max-width: 440px;
  display: grid;
  gap: 0.65rem;
  list-style: none;
  padding: 0;
  margin: 0;
  text-align: left;
}

.auth-features li {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  color: var(--auth-muted);
  font-size: 0.86rem;
  font-weight: 500;
}

.auth-features .feature-icon {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: rgba(30, 136, 229, 0.1);
  color: var(--auth-accent-dark);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  margin-top: 0.05rem;
}

.auth-features svg { width: 14px; height: 14px; }

/* Cartao de acesso claro (mesma receita dos cartoes da landing): superficie
   branca, borda suave, sombra azulada grande e um filete gradiente FIXO no
   topo (o equivalente calmo da antiga borda de luz girando -- num tema
   claro corporativo, luz correndo em volta do card viraria ruido).
   overflow:hidden pro filete respeitar o raio do cartao. */
.auth-card {
  position: relative;
  width: 100%;
  max-width: 440px;
  background: var(--auth-surface);
  border: 1px solid var(--auth-line);
  border-radius: 18px;
  box-shadow: var(--auth-sh-lg);
  padding: 2rem 2.2rem 1.9rem;
  text-align: left;
  overflow: hidden;
}

/* Formulario um pouco mais compacto que o .form-grid padrao -- junto com os
   demais aportes verticais, e' o que faz a tela caber sem scroll num
   desktop comum (pedido antigo e reafirmado: login sem scroll). */
.auth-card .form-grid {
  gap: 0.85rem;
}

.auth-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--auth-grad);
  pointer-events: none;
}

.auth-card h2 {
  color: var(--auth-ink);
  font-family: var(--auth-disp);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin-bottom: 0.3rem;
}

.auth-card > p {
  color: var(--auth-muted);
  margin-bottom: 1.1rem;
  font-size: 0.88rem;
}

/* Campos com cores fixas do tema claro (nunca var(--bg-alt)/var(--text) do
   app: um data-theme=dark deixado no navegador por uma sessao anterior
   pintaria os campos escuros dentro do cartao branco). */
.auth-card label { color: #3c5069; }

/* Rotulo pequeno e firme acima do campo (padrao de formulario profissional)
   -- so' os rotulos diretos da grade, nunca o da verificacao humana (que
   tem tipografia propria). */
.auth-card .form-grid > label {
  font-size: 0.8rem;
  font-weight: 600;
}

.auth-card input {
  background: #f4f7fc;
  border-color: var(--auth-line);
  color: var(--auth-ink);
}

/* Campo alto e confortavel (46px) -- :not([type="checkbox"]) porque o
   "manter conectado" tambem e' um input dentro do cartao e 46px de altura
   deformaria a caixinha. */
.auth-card input:not([type="checkbox"]) {
  min-height: 46px;
  border-radius: 10px;
  padding: 0.6rem 0.95rem;
  font-size: 0.95rem;
}

.auth-card input::placeholder { color: var(--auth-faint); }

.auth-card input:focus {
  border-color: var(--auth-accent);
  background: #ffffff;
  box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.18);
}

/* Linha "Manter conectado | Esqueci minha senha" (login) -- os dois nas
   pontas, mesma altura de texto. */
.auth-form-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: -0.2rem;
}

.auth-form-meta .auth-remember-row {
  margin-top: 0;
  font-size: 0.83rem;
}

.auth-form-meta .auth-forgot-link,
.auth-form-meta .auth-forgot-link:hover,
.auth-form-meta .auth-forgot-link:focus-visible {
  display: inline;
  width: auto;
  height: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  font-size: 0.83rem;
  font-weight: 600;
  text-align: right;
}

.auth-form-meta .auth-forgot-link { color: var(--auth-accent-dark); }
.auth-form-meta .auth-forgot-link:hover { text-decoration: underline; color: var(--auth-accent-dark); }

/* Conteudo de apoio dentro do cartao claro tambem com cor FIXA -- flash,
   checklist de senha e .field-hint usam tokens do data-theme, e um tema
   ESCURO lembrado no navegador (localStorage de uma sessao logada
   anterior) os pintaria claros demais sobre o cartao branco. */
.auth-card .field-hint { color: #55677f; }

.auth-card .flash.success { background: rgba(14, 159, 110, 0.12); color: #0b7d57; border-color: rgba(14, 159, 110, 0.25); }
.auth-card .flash.error { background: rgba(201, 80, 58, 0.12); color: #b23e2a; border-color: rgba(201, 80, 58, 0.25); }
.auth-card .flash.warning { background: rgba(240, 165, 0, 0.14); color: #8a5a00; border-color: rgba(240, 165, 0, 0.3); }

.auth-card .password-strength-item { color: #55677f; }

.auth-card .password-strength-mark {
  background: #f4f7fc;
  border-color: #d2dcea;
  color: #8b99ad;
}

.auth-card .password-strength-item.ok .password-strength-mark {
  background: rgba(14, 159, 110, 0.14);
  border-color: transparent;
  color: #0e9f6e;
}

.auth-card .password-strength-item.erro .password-strength-mark {
  background: rgba(201, 80, 58, 0.14);
  border-color: transparent;
  color: #c9503a;
}

.auth-card .password-strength-confirm-hint {
  background: rgba(201, 80, 58, 0.14);
  color: #b23e2a;
}

.auth-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.65rem 0.85rem;
  border-radius: var(--radius-sm);
  margin-bottom: 1.4rem;
}

/* Cor fixa (nao var(--success-bg)/var(--error-bg), que seguem data-theme) --
   mesmo motivo do resto do card: esta tela e' sempre clara, um data-theme
   escuro deixado no navegador desalinharia os tokens do tema. Verde/coral
   da propria landing (--lp-success/--lp-dor). */
.auth-status.ok { background: rgba(14, 159, 110, 0.12); color: #0e9f6e; }
.auth-status.down { background: rgba(201, 80, 58, 0.12); color: #c9503a; }

.auth-status::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.auth-status.ok::before { box-shadow: 0 0 6px 1px currentColor; }

.auth-remember-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--auth-muted);
  cursor: pointer;
  margin-top: -0.3rem;
}

.auth-remember-row input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--auth-accent);
  cursor: pointer;
}

/* CTA de login (pedido do usuario: deixar o "cta" mais forte/chamativo) --
   nao esta ao lado de nenhum input, pode ficar mais alto que o padrao
   --field-h dos botoes de linha/tabela sem quebrar a regra de "botao ao
   lado de input tem que ter a mesma altura" (aqui nao ha input ao lado).
   height:auto opta pra fora da altura fixa global. Pilula gradiente = o
   MESMO .lp-btn-primary da landing (borda 999px, gradiente da marca,
   sombra azul, sobe 2px no hover) -- unico lugar do app onde isso e'
   proposital, pra porta de entrada casar com de onde a pessoa veio. */
.auth-card button[type="submit"] {
  width: 100%;
  height: auto;
  padding: 0.85rem 1.1rem;
  margin-top: 0.3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  background: var(--auth-grad);
  color: #ffffff;
  border: none;
  border-radius: 999px;
  box-shadow: 0 6px 20px rgba(30, 136, 229, 0.35);
  font-family: var(--auth-disp);
  font-weight: 600;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}

.auth-card button[type="submit"]:hover {
  background: var(--auth-grad);
  box-shadow: 0 10px 28px rgba(30, 136, 229, 0.45);
  transform: translateY(-2px);
}

.auth-card button[type="submit"] svg {
  transition: transform var(--dur-fast) var(--ease-out);
}

.auth-card button[type="submit"]:hover svg {
  transform: translateX(3px);
}

/* (A cor do "Esqueci minha senha" vive nas regras .auth-form-meta acima --
   desde 2026-08-18 o link so' existe na linha ao lado de "Manter
   conectado", nunca mais solto embaixo do botao.) */

.auth-foot {
  margin-top: 1.1rem;
  font-size: 0.76rem;
  color: var(--auth-faint);
}

.auth-foot a {
  color: inherit;
  text-decoration: underline;
}

.auth-foot a:hover { color: var(--auth-accent-dark); }

/* Photo drag zone */

.photo-dragzone {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin-bottom: 1rem;
}

.photo-square-wrap {
  cursor: grab;
  position: relative;
}

.photo-square-wrap:active { cursor: grabbing; }

.photo-square-wrap form { margin: 0; }

.photo-square {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  aspect-ratio: 1 / 1;
  border: 2px dashed #90caf9;
  border-radius: var(--radius-md);
  background-color: var(--brand-soft);
  background-size: cover;
  background-position: center;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color 0.12s ease, transform 0.12s ease;
}

.photo-square:hover { border-color: var(--brand); }

.photo-square.filled {
  border-style: solid;
  border-color: var(--border-strong);
}

.photo-square-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  color: var(--brand-dark);
  font-weight: 600;
  font-size: 0.8rem;
  text-align: center;
  padding: 0.5rem;
}

.photo-square-empty svg { width: 26px; height: 26px; }

.drag-handle {
  position: absolute;
  top: 0.4rem;
  left: 0.5rem;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(33, 37, 41, 0.55);
  border-radius: 999px;
  padding: 0.1rem 0.4rem;
  letter-spacing: 0.1em;
}

/* Lupa/zoom nas fotos do anuncio (mesma ideia do lightbox ja usado nas
   listas de produtos/anuncios, so que aqui ao lado do drag-handle). */
.photo-zoom-btn {
  position: absolute;
  top: 0.4rem;
  right: 0.5rem;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(33, 37, 41, 0.55);
  color: #fff;
  border: none;
  cursor: pointer;
  padding: 0;
}

.photo-zoom-btn svg { width: 12px; height: 12px; }

.photo-zoom-btn:hover { background: rgba(33, 37, 41, 0.8); }

.photo-square-wrap:not(:first-child) .photo-square-primary-badge {
  display: none;
}

.photo-square-primary-badge {
  position: absolute;
  bottom: 0.5rem;
  left: 50%;
  transform: translateX(-50%);
  background: var(--dark);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  white-space: nowrap;
}

/* Checkbox de selecionar foto pra usar no popup "Melhorar com IA" -- fica
   no canto inferior direito do quadrado (o inferior-centro ja e ocupado
   pelo badge "Principal", o superior ja tem drag-handle + lupa). */
.photo-square-select {
  position: absolute;
  bottom: 0.4rem;
  right: 0.5rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: rgba(33, 37, 41, 0.55);
  cursor: pointer;
}

.photo-square-select input[type="checkbox"] {
  width: 16px;
  height: 16px;
  min-width: 16px;
  margin: 0;
  accent-color: var(--brand);
  cursor: pointer;
}

/* Varinha magica de remover fundo com IA (@imgly/background-removal,
   2026-07-13) -- canto inferior esquerdo do quadrado (unico canto livre:
   superior tem drag-handle+lupa, inferior-direito tem o checkbox de selecao,
   inferior-centro tem o badge "Principal" na primeira foto). */
.photo-wand-btn {
  position: absolute;
  bottom: 0.4rem;
  left: 0.5rem;
  z-index: 2;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(33, 37, 41, 0.55);
  color: #fff;
  border: none;
  cursor: pointer;
  padding: 0;
}

.photo-wand-btn svg { width: 12px; height: 12px; }

.photo-wand-btn:hover { background: rgba(33, 37, 41, 0.8); }

/* Popup "Melhorar fotos com IA" (ad_detail.html) -- barra de modo (fotos
   selecionadas / gerar novas), lista de resultados com comparacao
   antes/depois empilhada (a foto original menor em cima, o resultado da IA
   maior embaixo, como pedido) e checkbox por card pra escolher o que
   aplicar. */
.photo-ai-mode-bar {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
}

.photo-ai-mode-btn {
  background: none;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.85rem;
  padding: 0.55rem 0.9rem;
  height: auto;
  cursor: pointer;
  box-shadow: none;
  transition: background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.photo-ai-mode-btn:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-color: var(--brand);
  transform: none;
  box-shadow: none;
}

.photo-ai-mode-btn.active {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}

#photo-ai-generate-options {
  margin-bottom: 0.75rem;
}

.photo-ai-results {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 1rem;
  max-height: 420px;
  overflow-y: auto;
}

.photo-ai-result-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.9rem;
}

.photo-ai-before-after {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.7rem;
}

.photo-ai-before,
.photo-ai-after {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}

.photo-ai-before img {
  width: 90px;
  height: 90px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  opacity: 0.8;
}

.photo-ai-after img {
  width: 240px;
  height: 240px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
}

@media (max-width: 620px) {
  .photo-ai-after img { width: 100%; height: auto; max-width: 240px; }
}

.photo-remove-btn {
  width: 100%;
  margin-top: 0.5rem;
  padding: 0.5rem 0.7rem;
  font-size: 0.8rem;
}

.error-hint {
  color: var(--error-text);
  font-weight: 600;
  margin-top: 0.4rem;
}

/* Compatibility rows */

.compat-rows {
  display: grid;
  gap: 0.6rem;
  margin-bottom: 1rem;
}

.compat-row {
  display: grid;
  grid-template-columns: 1.2fr 1.2fr 1.2fr 0.8fr 0.8fr 0.7fr auto;
  gap: 0.5rem;
  align-items: center;
}

.compat-row input {
  padding: 0.6rem 0.7rem;
  font-size: 0.85rem;
}

.compat-remove {
  background: var(--error-bg);
  color: var(--error-text);
  border: none;
  border-radius: var(--radius-sm);
  width: 34px;
  height: 34px;
  padding: 0;
  box-shadow: none;
  font-weight: 700;
}

.compat-remove:hover {
  filter: none;
  transform: none;
  background: var(--error-bg);
}

/* Attributes grid */

.attributes-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem 1.25rem;
}

.attr-tag {
  margin-left: 0.4rem;
  vertical-align: middle;
  font-size: 0.65rem;
  padding: 0.15rem 0.5rem;
}

/* Compact table variant */

.table-compact td,
.table-compact tbody th,
.table-compact thead th {
  padding: 0.6rem 1.1rem;
}

.preview-cell {
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-muted);
  font-size: 0.82rem;
  font-weight: 500;
}

/* Checklist */

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.checklist li {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
}

.checklist-icon {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.checklist-icon svg { width: 13px; height: 13px; }

.checklist li.ok .checklist-icon {
  background: var(--success-bg);
  color: var(--success-text);
}

.checklist li.pending .checklist-icon {
  background: var(--warning-bg);
  color: var(--warning-text);
}

.checklist li.pending { color: var(--text-muted); }

/* Category search */

.inline-form {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 0.75rem;
}

.category-results {
  display: grid;
  gap: 0.6rem;
  margin-top: 1.1rem;
}

.category-dropdown {
  max-height: 360px;
  overflow-y: auto;
}

.category-dropdown:empty {
  margin-top: 0;
}

/* Popup de categoria do anuncio: quando o produto ja tem categorias usadas
   no grupo (.category-group-results, lista de "Usar esta categoria" logo
   no topo do popup), faltava respiro antes da caixa de busca -- ela colava
   direto embaixo dos botoes "Usar esta categoria", bagunçando o popup (bug
   reportado 2026-07-24). Mesmo respiro do .category-results acima (1.1rem),
   pra ficar simetrico nos dois sentidos. */
.category-search-box {
  margin-top: 1.1rem;
}

.category-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
}

.category-result strong {
  display: block;
  font-size: 0.9rem;
}

.category-result button {
  padding: 0.55rem 0.9rem;
  font-size: 0.82rem;
  flex-shrink: 0;
}

.current-category {
  margin-top: 1.1rem;
  padding: 0.8rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.85rem;
}

/* Responsive */

@media (max-width: 980px) {
  .layout {
    grid-template-columns: 1fr;
  }

  .sidebar {
    position: relative;
    height: auto;
  }

  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .photo-grid {
    grid-template-columns: 1fr;
  }

  /* Abaixo de 980px: duas colunas nao cabem legiveis (ver .auth-center no
     bloco de cima) -- volta a empilhar em 1 coluna, re-centralizado (era
     text-align:left/justify-content:flex-start no layout de 2 colunas).
     Scroll passa a ser permitido aqui de proposito -- normal em tela
     estreita, diferente do desktop onde o pedido explicito era "nao quero
     scroll". */
  .auth-shell {
    overflow-y: auto;
  }

  .auth-center {
    grid-template-columns: 1fr;
    gap: 0;
    padding: 2.5rem 1.25rem 2.25rem;
    max-width: 520px;
  }

  .auth-col-brand {
    text-align: center;
  }

  .auth-integrations-row {
    justify-content: center;
    margin: 0 auto;
  }

  .auth-features {
    margin: 0 auto;
  }

  .auth-center h1 { max-width: none; font-size: 2rem; }
}

@media (max-width: 620px) {
  .content { padding: 1.25rem 1.1rem 2rem; }
  .hero, .panel { padding: 1.25rem; }
  .stats { grid-template-columns: 1fr; }
  .inline-form { grid-template-columns: 1fr; }
  .category-result { flex-direction: column; align-items: flex-start; }
  .compat-row { grid-template-columns: 1fr 1fr; }
  .attributes-grid { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .photo-dragzone { grid-template-columns: 1fr; }
}

/* Products toolbar (search + filter + upload) */

.products-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.1rem;
}

.toolbar-search {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.toolbar-search input[type="text"] {
  width: 260px;
  max-width: 60vw;
}

/* Lista de anuncios (pedido do usuario, 2026-07-12): botao de busca so com
   icone (reusa .icon-btn, mesmo quadrado var(--field-h) dos demais icones
   do sistema) + input de busca um pouco mais largo -- escopado por id pra
   nao afetar o toolbar-search de products.html, que compartilha as mesmas
   classes base. Os botoes "Filtrar"/"Limpar filtros"/menu "..." agrupados
   em .toolbar-actions-right, empurrados pro canto direito pelo
   justify-content: space-between de .products-toolbar (2 filhos diretos:
   o form de busca e este wrapper). */
#ads-search-form input[type="text"] {
  width: 320px;
}

.toolbar-actions-right {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* Botao de filtro "precisa de atencao" (lista de anuncios) -- pedido do
   usuario (2026-07-12) de conseguir filtrar quem exige atencao e o porque.
   Usa a paleta de warning (nao error) porque nem todo ponto de atencao e
   bloqueante -- so o badge por linha diferencia error/warning de verdade. */
.attention-filter-toggle {
  background: var(--warning-bg);
  border-color: rgba(239, 108, 0, 0.35);
  color: var(--warning-text);
}
.attention-filter-toggle:hover {
  background: var(--warning-bg);
  filter: brightness(0.96);
}
.attention-filter-toggle.active {
  background: var(--warning-text);
  border-color: var(--warning-text);
  color: white;
}

.attention-cell {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  max-width: 220px;
}
.attention-badge-list {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  width: fit-content;
}
.attention-badge-list.severity-error { background: var(--error-bg); color: var(--error-text); }
.attention-badge-list.severity-warning { background: var(--warning-bg); color: var(--warning-text); }
.attention-badge-list.severity-ok { background: var(--success-bg); color: var(--success-text); }

/* Aba de Perguntas e Respostas (ad_detail.html, pedido do usuario 2026-07-12) */
.tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 0.35rem;
  margin-left: 0.35rem;
  border-radius: 999px;
  background: var(--error-bg);
  color: var(--error-text);
  font-size: 0.7rem;
  font-weight: 700;
}
.question-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem 1rem;
  margin-bottom: 0.75rem;
}
.question-text {
  font-weight: 600;
  margin: 0 0 0.2rem;
}
.question-answer {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--border);
}
.question-answer p {
  margin: 0.3rem 0 0;
}
.question-answer-form {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  margin-top: 0.5rem;
}
.question-answer-form textarea {
  flex: 1;
  resize: vertical;
}

/* Características do produto (Cadastro de Produto, ad_detail.html, pedido
   do usuario 2026-07-12) -- lista dinamica de pares label/valor. */
.characteristics-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.4rem;
}
.characteristic-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.characteristic-row input {
  height: var(--field-h);
}
.characteristic-label-input {
  flex: 0 0 220px;
}
.characteristic-value-input {
  flex: 1;
}
.characteristic-row .icon-btn {
  flex: 0 0 auto;
}

/* Preços de atacado (PxQ, 2026-07-31) -- mesma estrutura de linha de
   .characteristics-list/.characteristic-row (lista vertical de linhas com
   2 campos + botão de remover), classes próprias por clareza semântica
   (quantidade/preço, não "label"/"value"). */
.wholesale-tiers-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.6rem;
}
.wholesale-tier-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.wholesale-tier-row.wholesale-tier-head {
  color: var(--text-muted);
  font-size: 0.8rem;
  font-weight: 600;
}
.wholesale-qty-input {
  flex: 0 0 200px;
}
.wholesale-price-input {
  flex: 1;
}
.wholesale-tier-row .icon-btn {
  flex: 0 0 auto;
}
.wholesale-tier-row-spacer {
  flex: 0 0 auto;
  width: var(--field-h);
}

/* Variacoes do produto (tamanho/cor/voltagem...) -- uma linha por
   combinacao, todos os campos LADO A LADO, com cabecalho de coluna acima
   da lista (pedido do usuario, 2026-07-31: "os inputs tem q ficar em linha
   um ao lado do outro, melhor layout deixar mais profissional").

   REESCRITO: o bloco antigo aqui era de uma feature diferente ("Variacao
   personalizada", 2026-07-24) que empilhava os campos em coluna
   (flex-direction: column) com tira de fotos por variacao. Essa marcacao
   nao existe mais em template nenhum (confirmado por grep:
   .variation-photos-strip/.variation-photo-thumb/.is-principal/
   .variation-field* sem nenhuma ocorrencia) -- mas a regra continuava
   valendo pela classe .variation-row, que a lista atual tambem usa, e era
   ela que empilhava os inputs verticalmente. Removido junto.

   Grid (nao flex) de proposito: as colunas do cabecalho e as das linhas
   usam o MESMO grid-template-columns, entao titulo e campo ficam sempre
   alinhados, sem depender de largura fixa em cada input. */
.variations-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr 1.1fr 90px 110px var(--field-h);
  gap: 0.5rem;
  align-items: center;
}

.variations-head {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding-bottom: 0.15rem;
}

.variation-row {
  border: 0;
  padding: 0;
  background: none;
}

.variation-row input {
  height: var(--field-h);
  width: 100%;
  max-width: none;
  min-width: 0;
}

/* O X e' 30px e os inputs --field-h (~38px) -- sem alinhar pelo TOPO ele
   fica centralizado na celula e sobra ~3px mais baixo que a linha. */
.variation-row .icon-btn {
  flex: 0 0 auto;
  align-self: start;
  height: var(--field-h);
  width: var(--field-h);
}

/* Em tela estreita a grade de 8 colunas nao cabe -- vira 2 colunas e o
   cabecalho some (cada campo se identifica pelo placeholder). */
@media (max-width: 900px) {
  .variations-grid {
    grid-template-columns: 1fr 1fr;
  }
  .variations-head { display: none; }
}

/* Tipos de variacao (2026-08-04) -- pedido do usuario: "podemos ter mais de
   um valor pra essa variação... fotos para cara variação primaria, estoque
   indiviual, preço, e sku". Um TIPO (ex. "Voltagem") vira um card com nome +
   lista de valores; o PRIMEIRO tipo cadastrado ganha um quadrado de foto por
   valor (regra fixa: foto so' na variacao primaria, nunca nos demais tipos).
   As COMBINACOES (produto cartesiano dos valores) sao geradas pelo servidor
   e mostradas embaixo, numa tabela separada -- ver .variation-combo-grid. */
/* CABECALHO da secao: titulo a esquerda, acao no extremo direito (pedido do
   usuario, 2026-08-04: "na mesam linha de variação (titulo,) deixar no lado
   direito extremo o bota de adicionar"). */
.variation-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.variation-panel-head .panel-head-title-group {
  margin: 0;
}
.variation-add-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.variation-types-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 0.75rem;
}

/* Estado vazio -- sem ele a secao aparecia como um bloco em branco, sem
   dizer o que fazer. */
.variation-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 1.6rem 1rem;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  color: var(--text-faint);
  text-align: center;
}
.variation-empty p {
  margin: 0;
  font-weight: 600;
  color: var(--text-muted);
}
.variation-empty .field-hint {
  margin: 0;
}

/* Card do TIPO -- somente leitura: nome + chips dos valores. A edicao toda
   acontece no popup (.variation-type-modal), o que tirou da tela os dezenas
   de inputs/botoes soltos que existiam aqui antes. */
.variation-type-card {
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-md);
  padding: 0.7rem 0.85rem;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.variation-type-card:hover {
  box-shadow: var(--shadow-md);
}
.variation-type-card:not(:first-child) {
  border-left-color: var(--border-strong);
}
.variation-type-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.55rem;
}
.variation-type-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  min-width: 0;
}
.variation-type-title strong {
  font-size: 0.95rem;
  color: var(--text);
}
.variation-type-count {
  font-size: 0.75rem;
  color: var(--text-faint);
}
.variation-type-actions {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex: 0 0 auto;
}
.variation-type-primary-badge {
  flex: 0 0 auto;
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--brand-dark);
  background: var(--brand-soft);
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.45rem;
  white-space: nowrap;
}

/* Chips dos valores -- leitura rapida do que existe naquele tipo, com a
   miniatura da foto quando e' a variacao principal. */
.variation-value-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.variation-value-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.22rem 0.55rem 0.22rem 0.28rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  font-size: 0.8rem;
  color: var(--text);
  max-width: 100%;
}
.variation-value-chip > span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.variation-chip-photo {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  border: 1px dashed var(--border-strong);
  background-color: var(--surface);
  background-size: cover;
  background-position: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
}
.variation-chip-photo.has-photo {
  border-style: solid;
  border-color: var(--border);
}

/* Popup de criar/editar um tipo. */
.variation-modal-name {
  display: block;
  margin-bottom: 0.2rem;
}
.variation-modal-hint {
  margin: 0.75rem 0 0.45rem;
}
.variation-modal-values {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  max-height: 40vh;
  overflow-y: auto;
}
.variation-modal-value-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.variation-modal-value-input {
  flex: 1;
  min-width: 0;
  height: var(--field-h);
}
/* O input de arquivo fica no DOM como irmao do botao (nunca dentro dele --
   ver o comentario em renderModalValores), so' que invisivel. */
.variation-modal-file {
  display: none;
}
.variation-modal-value-row .icon-btn {
  flex: 0 0 auto;
  width: var(--field-h);
  height: var(--field-h);
}
.variation-modal-add-value {
  margin-top: 0.55rem;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.variation-modal-aviso:empty {
  display: none;
}
.variation-modal-actions {
  margin-top: 1rem;
  justify-content: flex-end;
}

/* Quadrado de foto por valor (dentro do popup) -- preview via
   background-image; sem foto, so' o icone de camera tracejado (mesma
   linguagem visual do "+ Adicionar" de fotos do produto/anuncio). */
.variation-value-photo-btn {
  flex: 0 0 auto;
  width: var(--field-h);
  height: var(--field-h);
  border-radius: var(--radius-sm);
  border: 1px dashed var(--border-strong);
  background-color: var(--bg);
  background-size: cover;
  background-position: center;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  padding: 0;
}
.variation-value-photo-btn:hover {
  border-color: var(--brand);
  color: var(--brand-dark);
}
.variation-value-photo-btn.has-photo {
  border-style: solid;
  border-color: var(--border);
}

/* Tabela de COMBINACOES geradas (produto cartesiano dos tipos acima) --
   mesma altura/alinhamento de .variations-grid, mas a 1a coluna e' so'
   texto (a combinacao ja' vem pronta do servidor, nao e' mais digitada
   livre) e ganha 4 colunas extras de dimensao quando o toggle "peso e
   dimensões diferentes por variação" esta ligado (variante .with-dimensions,
   trocada via JS -- grid-template-columns muda, nunca esconde filho dentro
   do mesmo grid pra nao desalinhar cabecalho x linha). */
.variation-combo-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 90px 1fr 70px var(--field-h);
  gap: 0.5rem;
  align-items: center;
}
.variation-combo-grid.with-dimensions {
  grid-template-columns: 1.4fr 0.9fr 80px 0.9fr 75px 75px 75px 75px 70px var(--field-h);
}
/* Canal que nao aceita preco por variacao (Mercado Livre -- exige o mesmo
   preco em todas): a coluna de preco nem e' criada no DOM, entao a grade
   precisa ter uma coluna a menos. Ver mostrarPreco em variation_editor.js. */
.variation-combo-grid.sem-preco {
  grid-template-columns: 1.5fr 1fr 90px 70px var(--field-h);
}
.variation-combo-grid.sem-preco.with-dimensions {
  grid-template-columns: 1.4fr 0.9fr 80px 75px 75px 75px 75px 70px var(--field-h);
}
.variation-combo-name {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: break-word;
  min-width: 0;
}
.variation-combo-grid input[type="text"],
.variation-combo-grid input[type="number"] {
  height: var(--field-h);
  width: 100%;
  min-width: 0;
}
.variation-combo-grid > * {
  min-width: 0;
}
.variation-combo-active-toggle {
  text-align: center;
}
.variation-combo-active-toggle input[type="checkbox"] {
  width: 16px;
  height: 16px;
}
.variation-combo-grid .icon-btn {
  flex: 0 0 auto;
  height: var(--field-h);
  width: var(--field-h);
}
/* Salvamento de variacao e' sempre explicito (nunca autosave por blur -- ver
   o cabecalho de variation_editor.js). Esta linha e' a acao + o status. */
.variation-save-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.85rem;
  flex-wrap: wrap;
}
.variation-save-row .field-hint {
  margin: 0;
}
/* Enquanto houver alteracao nao salva, o botao pulsa de leve pra o usuario
   nao sair da tela achando que ja' salvou. */
.variation-save-row button.tem-pendencia {
  animation: variation-save-pulse 1.6s var(--ease-out) infinite;
}
@keyframes variation-save-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(33, 150, 243, 0.45); }
  50% { box-shadow: 0 0 0 5px rgba(33, 150, 243, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .variation-save-row button.tem-pendencia { animation: none; }
}
@media (max-width: 980px) {
  .variation-combo-grid,
  .variation-combo-grid.with-dimensions {
    grid-template-columns: 1fr 1fr;
  }
  .variation-combo-grid.variations-head { display: none; }
}

/* Produtos semelhantes (Cadastro de Produto, ad_detail.html, pedido do
   usuario 2026-07-13) -- lista de produtos casados por OEM/codigo, mais
   entradas manuais. Reusa .characteristic-row como base de layout (mesma
   altura/alinhamento), so acrescenta o wrapper de info + badges. */
.similar-products-panel-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.4rem;
}

.similar-product-panel-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1.1rem 0 0.75rem;
}
.similar-product-panel-row {
  align-items: center;
}
.similar-product-group-heading {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  margin: 0.6rem 0 0.1rem;
}
.similar-product-group-heading:first-child {
  margin-top: 0;
}
.similar-product-panel-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}
.similar-product-panel-title {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}
.similar-product-panel-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.1rem;
}
.similar-product-reason-badge {
  background: var(--brand-soft);
  color: var(--brand-dark);
}
.similar-product-reason-badge.manual {
  background: var(--neutral-soft);
  color: var(--text-muted);
}
.attention-flag-line {
  font-size: 0.74rem;
  color: var(--text-muted);
  line-height: 1.3;
}

/* Lista de anuncios reorganizada (pedido do usuario, 2026-07-20): titulo +
   codigo/ID ML/loja numa celula so, metricas de visitas/vendidos, valor de
   venda x valor liquido recebido do ML com percentual vs. o valor do
   produto (cadastro), tipo de anuncio + comissao numa celula so. */
.ad-cell-title {
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
}
/* Icone de "tem variacao" na lista de anuncios (pedido do usuario,
   2026-08-04: "qunado o produto possuir variação mostrar algum icone na
   lista de anucios apa sinalizar isso") -- inline com o titulo, nunca
   <button> (so' informativo, sem acao de clique), entao nao precisa da
   redeclaracao de hover/foco que os icones clicaveis do sistema exigem. */
.ad-variation-icon {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 0.35rem;
  color: var(--brand);
  cursor: help;
}
.ad-cell-subline {
  font-size: 0.78rem;
  color: var(--text-faint);
  line-height: 1.3;
  margin-top: 0.15rem;
  font-weight: 400;
}
.ad-cell-subline.muted {
  font-size: 0.76rem;
  opacity: 0.85;
}
.ad-cell-metric {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.5;
}
.ad-cell-metric svg { flex: 0 0 auto; color: var(--text-faint); }
.ad-cell-value {
  font-weight: 600;
  color: var(--text);
}
.text-danger { color: var(--danger); }
.text-success { color: var(--success-text); }
.text-warning { color: var(--warning-text); }

/* Painel de qualidade INLINE na lista de anuncios (menu "..." > Qualidade,
   2026-07-27) -- replica o painel "Qualidade da publicacao" do Mercado
   Livre, expandido dentro da propria linha da tabela com efeito de
   deslizar (mesmos tokens de movimento do resto do sistema). */
.ad-quality-row td {
  padding: 0;
  border-top: none;
}

.quality-panel-wrap {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}

.quality-row-open .quality-panel-wrap {
  max-height: 900px;
  opacity: 1;
}

.quality-panel {
  padding: 1.1rem 1.4rem;
  background: var(--bg-alt);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.quality-panel-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.9rem;
}

.quality-panel-head strong {
  font-size: 0.92rem;
}

/* Detalhe de venda inline (Vendas, 2026-07-30) -- cabecalho com numero do
   pedido + badges de plataforma/status lado a lado, e um traco sutil
   separando cada secao (Loja e data / Valores / Anuncio / Itens / Envio /
   Comprador) -- pedido explicito do usuario: "separa melhor as
   informações apra um melhor entendimenteo esta tudo estranho e
   bagunçaando". Reaproveita .category-details-subhead/.category-details-grid
   ja existentes (popup de categoria), so escopado a .order-detail-panel. */
.order-detail-panel .order-detail-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.3rem;
}

.order-detail-panel .order-detail-head strong {
  font-size: 1rem;
}

.order-detail-panel .category-details-subhead {
  margin-top: 1.1rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
}

.order-detail-panel .category-details-subhead:first-of-type {
  margin-top: 0.8rem;
}

/* ===== Detalhe de venda, versao visual 2 (2026-07-31) =====================
   Pedido do usuario: "nos detalhes de vendas, deixar mais bonito e organizado
   visualmente, organizar melhor os botoes, deixar toda parte de vendas
   moderno e profissional".
   Estrutura: HERO (numero + badges + valor) -> ETAPA -> ACOES -> CARDS.
   Cada bloco vira um cartao proprio em vez de linhas separadas por um traco. */
/* O painel do detalhe de venda tem respiro proprio (mais folgado que o
   .quality-panel base, que serve pro painel curto de Qualidade em Anuncios)
   -- pedido do usuario em 2026-08-01: "esta precisando melhorar o
   espacamento, o conteudo esta otimo". */
/* Fundo levemente acinzentado (herdado de .quality-panel) com os cartoes
   brancos por cima -- e' o que separa o painel aberto da linha da tabela. */
.order-detail-panel { padding: 1.4rem 1.5rem; }
@media (max-width: 700px) {
  .order-detail-panel { padding: 1rem 0.9rem; }
}

.order-hero {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
  padding: 1.15rem 1.35rem;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--brand-soft) 0%, var(--surface-solid) 78%);
  border: 1px solid var(--border);
}
.order-hero-main { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.order-hero-numero {
  font-size: 1.12rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
}
.order-hero-badges { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.order-hero-valor { text-align: right; display: flex; flex-direction: column; gap: 0.1rem; }
.order-hero-valor strong { font-size: 1.32rem; font-weight: 700; color: var(--text); letter-spacing: -0.02em; }
.order-hero-valor span { font-size: 0.72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600; }

/* Grade de cartoes: 2 colunas em tela larga, 1 no estreito. */
.order-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1rem;
  margin-top: 1rem;
}
/* O cartao em si vira um `.form-section` (padrao de cadastro, parte 217) --
   fundo, borda, raio, sombra e o padding do cabecalho/corpo passaram a vir de
   la'. Aqui fica so' o que e' proprio da GRADE: nao encolher e nao carregar o
   padding antigo, que somaria ao do `.form-section` e afundaria o conteudo.
   Ver o bloco "VENDAS NO MOLDE DO CADASTRO" no fim deste arquivo. */
.order-card { min-width: 0; }
/* Cartao que ocupa a largura toda (itens, acoes). */
.order-card.span-all { grid-column: 1 / -1; }

/* Par rotulo/valor dentro do cartao -- empilhado, mais legivel que grade. */
.order-linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.45rem 0;
  border-bottom: 1px dashed var(--border);
}
.order-linha:last-child { border-bottom: 0; padding-bottom: 0; }
.order-linha > span { font-size: 0.78rem; color: var(--text-muted); flex: 0 0 auto; }
.order-linha > strong {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--text);
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* Valor de destaque dentro do cartao (ex.: "Você recebe"). */
.order-linha.destaque > strong { color: var(--success-text); font-size: 0.95rem; font-weight: 700; }

/* Itens da venda. */
.order-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--border);
}
.order-item:last-child { border-bottom: 0; padding-bottom: 0; }
.order-item-info { min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.order-item-info strong { font-size: 0.87rem; font-weight: 600; }
.order-item-info small { font-size: 0.73rem; color: var(--text-muted); }
.order-item-valor { text-align: right; white-space: nowrap; font-weight: 700; font-size: 0.88rem; }
.order-item-valor small { display: block; font-weight: 500; font-size: 0.72rem; color: var(--text-muted); }

/* Stepper das etapas da venda (2026-07-30) -- escada canonica padronizada
   (ORDER_STAGES no app.py), a mesma pra qualquer canal. Etapa concluida fica
   na cor da marca, a atual em destaque cheio, as futuras apagadas. */
.order-stepper {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.6rem;
}

/* Conector entre as etapas (2026-07-31) -- deixa claro que e' uma escada, e
   nao uma coleçao de pills soltas. Fica na cor da marca no trecho ja
   percorrido. So no stepper dentro do cartao (.order-stepper-linha), pra nao
   mexer em nenhum outro uso. */
.order-stepper-linha { gap: 0; }
.order-stepper-linha .order-step { position: relative; z-index: 1; }
.order-stepper-linha .order-step + .order-step { margin-left: 0.42rem; }
.order-stepper-linha .order-step + .order-step::before {
  content: "";
  position: absolute;
  left: -0.42rem;
  top: 50%;
  width: 0.42rem;
  height: 2px;
  background: var(--border);
  transform: translateY(-50%);
}
.order-stepper-linha .order-step.is-done + .order-step::before,
.order-stepper-linha .order-step.is-current::before { background: var(--brand); }

.order-step {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 0.3rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-alt);
  color: var(--text-faint);
  white-space: nowrap;
}

.order-step.is-done {
  border-color: var(--brand-soft);
  background: var(--brand-soft);
  color: var(--brand-dark);
}

.order-step.is-current {
  border-color: var(--brand);
  background: var(--brand);
  color: #fff;
}

.order-step.is-cancelled {
  border-color: var(--error-text);
  background: var(--error-bg);
  color: var(--error-text);
}

/* Linha de botoes de acao da venda. */
.order-actions-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.6rem;
}

.quality-total-score {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--brand-dark);
  background: var(--brand-soft);
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
}

/* Duas colunas (pedido explicito: "sendo duas colunas dados do produto e
   condicao de venda") -- empilha em telas estreitas. */
.quality-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
}

@media (max-width: 760px) {
  .quality-cols { grid-template-columns: 1fr; }
}

.quality-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--text);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.5rem;
}

.quality-score {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--brand-dark);
}

.quality-goal-list {
  display: grid;
  gap: 0.5rem;
}

.quality-goal {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.82rem;
  line-height: 1.4;
}

.quality-goal-icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  margin-top: 0.05rem;
}

/* Core de certo/atencao (pedido explicito: "cada top com icone com core, de
   certo ou erraro apra atencao oua certo"). */
.quality-goal.is-done .quality-goal-icon { color: var(--success-text); }
.quality-goal.is-pending .quality-goal-icon { color: var(--warning-text, #b45309); }
.quality-goal.is-done .quality-goal-text { color: var(--text-muted); }
.quality-goal.is-pending .quality-goal-text { color: var(--text); font-weight: 500; }

.quality-goal-text { flex: 1; }

.quality-goal-action {
  flex: 0 0 auto;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--brand-dark);
  white-space: nowrap;
}
.quality-goal-action:hover { text-decoration: underline; }

.toolbar-search select {
  width: auto;
}

.toolbar-search button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* Paginacao das listagens (produtos/anuncios) */

.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.9rem 1.75rem;
  border-top: 1px solid var(--border);
}

.pagination-info {
  font-size: 0.82rem;
  color: var(--text-muted);
}

.pagination-links {
  display: flex;
  gap: 0.5rem;
}

.page-btn {
  display: inline-flex;
  align-items: center;
  padding: 0.45rem 0.9rem;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--text);
  border: 1px solid var(--border);
  font-size: 0.82rem;
  font-weight: 600;
}

.page-btn:hover { background: var(--brand-soft); color: var(--brand-dark); }

.page-btn.disabled {
  opacity: 0.45;
  pointer-events: none;
  cursor: default;
}

.page-btn.current {
  background: var(--brand);
  color: var(--brand-contrast, #fff);
  border-color: var(--brand);
  cursor: default;
}

.page-btn.ellipsis {
  border: none;
  background: none;
  padding: 0.45rem 0.2rem;
  color: var(--text-faint);
  font-weight: 400;
}

/* Bulk selection bar */

/* Barra de selecao em massa. Pedido do usuario (2026-07-30): "box de itens
   selecionado com cor mais suave e deve ter uma altura menor" -- era um bloco
   grafite escuro (var(--dark)) de ~50px; virou uma faixa clara/suave na cor
   da marca, bem mais baixa. O botao dentro dela volta a ser o botao normal do
   sistema (fundo claro agora, o overlay branco translucido de antes ficaria
   invisivel). */
.bulk-bar {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: var(--brand-soft);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 0.4rem 0.85rem;
  border-radius: var(--radius-md);
  margin-bottom: 0.85rem;
  flex-wrap: wrap;
  font-size: 0.85rem;
  box-shadow: none;
}

.bulk-bar.visible { display: flex; }

/* Grupo de acoes da barra de selecao alinhado a direita (pedido do usuario,
   2026-07-30) -- com os botoes soltos, o space-between da .bulk-bar deixava um
   deles no meio da faixa. margin-left:auto garante o encosto a direita mesmo
   se um botao a mais entrar aqui depois. */
.bulk-bar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-left: auto;
}


.bulk-bar .button-row { margin: 0; }

/* Botao mais baixo que o padrao do sistema pra a faixa nao voltar a crescer
   de altura (o --field-h global deixaria a barra na altura de antes). */
.bulk-bar button {
  height: auto;
  min-height: 0;
  padding: 0.32rem 0.7rem;
  font-size: 0.8rem;
}

.bulk-bar .secondary-dark {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
}

.bulk-bar .secondary-dark:hover { background: var(--bg-alt); }

/* Agrupa "Editar em massa" + "Opções" num unico bloco alinhado a direita
   (pedido do usuario, 2026-07-30: "deixar agrupado a direita ambos ficam
   alinhado a direita") -- antes os dois eram filhos diretos do
   justify-content:space-between de .bulk-bar, entao "Editar em massa"
   ficava sozinho no meio da barra em vez de colado no "Opções". */
.bulk-bar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Canal dos selecionados / aviso de "canais diferentes" ao lado do contador. */
.bulk-platform-hint {
  color: var(--text-muted);
  font-weight: 500;
}

/* Quantos itens selecionados NAO estao na busca atual (selection_keeper.js).
   Cor de aviso porque e' exatamente o que o usuario nao esta vendo na tela e
   ainda assim entra na acao em massa. */
.selecao-fora-aviso {
  margin-left: 0.4rem;
  padding: 0.08rem 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--warning-bg);
  color: var(--warning-text);
  font-size: 0.74rem;
  font-weight: 700;
}

/* "Limpar seleção" e' um <button class="button-link"> dentro da faixa clara:
   sem redeclarar, o `button:hover` global (elemento + pseudo-classe vence uma
   classe so') pintaria o fundo de azul solido -- mesma armadilha de
   especificidade ja corrigida em .ad-tab-btn/.copy-icon-btn/.stat-cell. */
.bulk-bar .button-link {
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text-muted);
  text-decoration: underline;
  padding: 0.32rem 0.35rem;
}

.bulk-bar .button-link:hover,
.bulk-bar .button-link:focus,
.bulk-bar .button-link:focus-visible {
  background: none;
  border: none;
  box-shadow: none;
  outline: none;
  color: var(--brand-dark);
}

/* Row icon actions -- IMPORTANTE: display:flex nunca vai direto no <td>.
   Um <td> com display:flex deixa de se comportar como celula de tabela de
   verdade (perde a participacao no algoritmo de layout da tabela), entao a
   altura da linha calculada pelo navegador nao bate mais com a dos outros
   <td> da mesma <tr> -- era a causa raiz do "botao desalinhado com a
   linha"/"linha de botoes em desencontro" reportado nas listas de produtos
   e anuncios. O flex fica num <div class="row-actions-inner"> DENTRO do
   <td>, que continua um table-cell normal (vertical-align:middle herdado
   de `td`, mesma altura de linha que as outras colunas). */
.row-actions {
  white-space: nowrap;
}

.row-actions-inner {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.3rem;
}

/* Checkbox das listas (selecionar linha / selecionar tudo) no tema do
   sistema, em vez do checkbox padrao (cinza) do navegador. */
table input[type="checkbox"] {
  width: 18px;
  height: 18px;
  min-width: 18px;
  padding: 0;
  accent-color: var(--brand);
  cursor: pointer;
  border-radius: 4px;
}

.table-card table thead th:first-child,
.table-card table tbody td:first-child {
  width: 40px;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--text-muted);
  border: 1px solid var(--border);
  box-shadow: none;
  padding: 0;
}

.icon-btn svg { width: 15px; height: 15px; }

.icon-btn:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}

.icon-btn.danger:hover {
  background: var(--error-bg);
  color: var(--error-text);
}

/* Pausar/ativar na lista de anuncios (2026-07-12): cor permanente (nao so
   no hover) pra diferenciar de cara os dois botoes, que antes eram
   identicos ao resto dos icones cinza da linha. */
.icon-btn.warn {
  background: var(--warning-bg);
  color: var(--warning-text);
  border-color: var(--warning-bg);
}
.icon-btn.warn:hover {
  background: var(--warning-text);
  color: #fff;
}
.icon-btn.success {
  background: var(--success-bg);
  color: var(--success-text);
  border-color: var(--success-bg);
}
.icon-btn.success:hover {
  background: var(--success-text);
  color: #fff;
}

/* Aba de metricas de desempenho (ad_detail.html, 2026-07-12) -- grafico de
   barras simples em CSS puro (sem lib de charts nova, so pra 30 pontos de
   visitas/dia). */
.metrics-bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 140px;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
}
.metrics-bar-col {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  min-width: 6px;
}
.metrics-bar {
  width: 100%;
  background: var(--brand);
  border-radius: 2px 2px 0 0;
  min-height: 2px;
}
.metrics-bar-label {
  font-size: 0.6rem;
  color: var(--text-muted);
  margin-top: 0.2rem;
  writing-mode: vertical-rl;
}

.icon-btn.disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.icon-btn.disabled:hover {
  background: var(--bg-alt);
  color: var(--text-muted);
}

.icon-btn.icon-btn-busy svg { animation: icon-btn-spin 0.8s linear infinite; }

@keyframes icon-btn-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.ad-nav-arrows {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
}

.ad-jump-list {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-top: 0.9rem;
  max-height: 55vh;
  overflow-y: auto;
}

.ad-jump-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.75rem;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: inherit;
  text-decoration: none;
}

.ad-jump-row:hover {
  background: var(--brand-soft);
}

.ad-jump-row.current {
  border: 1px solid var(--brand-dark);
}

.ad-jump-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.ad-jump-title {
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ad-jump-subline {
  font-size: 0.78rem;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ad-jump-price {
  flex-shrink: 0;
  font-weight: 600;
  font-size: 0.85rem;
  min-width: 88px;
  text-align: right;
}

#ad-jump-search {
  width: 100%;
}

/* Miniatura de foto principal nas listagens de produtos/anúncios */

.row-thumb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text-faint);
  flex-shrink: 0;
}

.row-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.row-thumb.empty svg {
  width: 18px;
  height: 18px;
}

/* Codigo do produto ACIMA do titulo na lista de anuncios (pedido do usuario,
   2026-08-05: "um pouco menor que a fonte do titulo, e cor um pouco
   discreta"). Fica entre o titulo (600/--text) e a subline (0.78rem/
   --text-faint): menor que o titulo, mas ainda legivel e menos apagado que a
   linha de empresa/integracao logo abaixo. */
.ad-cell-codigo {
  font-size: 0.74rem;
  font-weight: 500;
  color: var(--text-muted);
  line-height: 1.2;
  margin-bottom: 0.1rem;
}

/* Foto um pouco maior na lista de Produtos (pedido do usuario, 2026-08-04)
   -- modificador em vez de mudar .row-thumb global, que afetaria todas as
   outras listas (Anuncios/Perguntas/etc) fora do escopo deste pedido. */
.row-thumb.lg {
  width: 46px;
  height: 46px;
}

/* Colunas "Catálogo"/"Anúncios"/"Estoque" -- ícone + número com painel
   suspenso ao passar o mouse (pedido do usuario, 2026-08-04: "hover tem q
   ser um estilo menu suspenso... bem moderno, pra somente informar"). Mesmo
   visual base do .header-menu-dropdown (fundo/borda/sombra/raio), so' que
   ativado por :hover/:focus-within (teclado) OU pela classe .open (clique,
   cobre touch/mobile onde nao existe hover de verdade) -- é sempre
   informativo, nunca substitui uma ação real (o clique em "Catálogo"
   continua abrindo o popup de gerenciar visibilidade que já existia). */
.stat-cell {
  /* ARMADILHA DE ESPECIFICIDADE (2x nesta classe, documentada aqui pra nao
     repetir): (1) a coluna Catálogo usa <button>, e o `button` global do
     sistema trava `height: var(--field-h)` -- height/align-items/
     justify-content precisam ser redeclarados aqui explicitamente, senao o
     badge (conteudo curto: icone+numero) fica com a altura de um campo de
     formulario inteiro, desproporcional; (2) `button:hover`/`button:focus-
     visible` (elemento + pseudo-classe = especificidade 0,1,1) tem MAIS
     peso que `.stat-cell` sozinho (1 classe = 0,1,0) -- sem redeclarar hover/
     focus/active abaixo, passar o mouse no botão de Catálogo pintava o fundo
     de azul solido (bug real reportado pelo usuario, 2026-08-04: "melhorar
     esses icone nao tem ter fundo nem contorno"). Os outros dois (Anúncios é
     <a>, Estoque é <span>) nunca sofriam disso, so' o <button>. */
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  height: auto;
  gap: 0.35rem;
  padding: 0.3rem 0.35rem;
  border-radius: var(--radius-sm);
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text-faint);
  font-weight: 700;
  font-size: 0.82rem;
  cursor: default;
}

.stat-cell svg {
  width: 15px;
  height: 15px;
  color: var(--text-faint);
  flex-shrink: 0;
}

.stat-cell.clickable {
  cursor: pointer;
}

.stat-cell:hover,
.stat-cell:focus,
.stat-cell:focus-visible,
.stat-cell:active {
  background: none;
  border: none;
  box-shadow: none;
  outline: none;
}

.stat-cell.clickable:hover,
.stat-cell.clickable:focus-visible {
  color: var(--brand-dark);
}

.stat-cell.clickable:hover svg,
.stat-cell.clickable:focus-visible svg {
  color: var(--brand-dark);
}

.stat-cell.stat-empty {
  color: var(--text-faint);
  font-weight: 600;
  opacity: 0.55;
}

/* BUG REAL corrigido (2026-08-10, print do usuario): o popover era
   position:absolute dentro da celula, e `.table-card { overflow: hidden }`
   (necessario pro border-radius da 1a/ultima linha) clipava qualquer
   popover que ultrapassasse a borda do card -- ficava cortado no meio,
   exatamente como no print. Agora o JS (statPopoverOpen, ver
   products.html) SACA o popover aberto do lugar e reanexa direto no
   <body> com position:fixed, top/left calculados pelo getBoundingClientRect
   do gatilho -- mesmo padrao ja usado no menu "..." da linha
   (.row-click-menu). Por isso aqui e' so' `position: fixed` com top/left
   dinamicos (JS seta inline) -- os valores estaticos antigos (top:100%
   etc) nao servem mais pra nada. */
.stat-popover {
  display: none;
  position: fixed;
  min-width: 220px;
  max-width: 320px;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 55;
  padding: 0.5rem;
  text-align: left;
  cursor: default;
}

/* So' exibe via classe -- nunca mais via :hover/:focus-within (o popover
   deixa de ser descendente de .stat-cell assim que e' movido pro <body>,
   entao um seletor descendente pararia de bater; quem liga/desliga agora
   e' 100% o JS, no hover E no clique, pelas mesmas funcoes). */
.stat-popover.stat-popover-open {
  display: block;
  animation: dropdown-in var(--dur-base) var(--ease-spring);
}

.stat-popover-title {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-faint);
  padding: 0.15rem 0.35rem 0.4rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.3rem;
}

.stat-popover-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.3rem 0.35rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
  border-radius: var(--radius-sm);
}

.stat-popover-row span:last-child {
  color: var(--text-muted);
  font-weight: 700;
  white-space: nowrap;
  margin-left: 0.5rem;
}

.stat-popover-empty {
  padding: 0.4rem 0.35rem;
  font-size: 0.82rem;
  color: var(--text-faint);
}

/* Coluna "Produto" unificada -- codigo + aplicacao + marca numa celula so'
   (pedido do usuario, 2026-08-04: "unificando codigo, aplicação e marca").
   Linha principal = descricao resumida (o que mais ajuda a reconhecer o
   produto de relance); linha discreta abaixo = codigo + marca. */
.product-cell-main {
  display: block;
  font-weight: 700;
  color: var(--text);
  line-height: 1.3;
}

.product-cell-sub {
  display: block;
  font-size: 0.78rem;
  color: var(--text-faint);
  margin-top: 0.15rem;
}

/* Modals (delete confirmation, upload) */

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(33, 37, 41, 0.55);
  z-index: 60;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.modal-overlay.open { display: flex; }

.modal-box {
  background: var(--surface-solid);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  max-width: 460px;
  width: 100%;
  padding: 1.75rem;
  /* Bug real corrigido 2026-07-19: mensagem longa (ex. lista de causas do
     Mercado Livre ao publicar) nao tinha limite de altura nem rolagem --
     o popup "estourava" pra fora da tela sem jeito de ler o resto nem de
     fechar o botao OK, que ficava empurrado alem do viewport. Agora todo
     modal-box (inclusive as variantes .wide/.xwide/.editor-box, que ja
     tinham max-height proprio e continuam valendo por especificidade)
     tem um teto de altura com rolagem interna. */
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
}

/* Mensagem do popup de aviso (window.AdsPremiumModal.alert) e do popup de
   confirmacao (window.AdsPremiumModal.confirm) podem ter varias linhas
   (ex.: lista de pendencias do checklist, ou causas do Mercado Livre
   separadas uma por linha) -- preserva as quebras de linha do texto e
   quebra palavra longa em vez de estourar a largura do popup. */
#app-confirm-message,
#app-alert-message {
  white-space: pre-line;
  overflow-wrap: break-word;
}

.modal-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
  gap: 1rem;
}

.modal-head h3 { margin: 0; }

.modal-close {
  background: transparent;
  border: none;
  box-shadow: none;
  color: var(--text-muted);
  padding: 0.3rem 0.6rem;
  width: auto;
}

.modal-close:hover {
  background: var(--bg-alt);
  transform: none;
  box-shadow: none;
}

.upload-dropcard {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  border: 2px dashed #90caf9;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  padding: 2rem 1rem;
  cursor: pointer;
  text-align: center;
  color: var(--brand-dark);
  font-weight: 600;
  font-size: 0.88rem;
  margin-bottom: 1.1rem;
}

.upload-dropcard input[type="file"] { display: none; }

.upload-file-info { margin-top: 0.3rem; }
.upload-file-info strong { display: block; color: var(--text); }

@media (max-width: 620px) {
  .products-toolbar { flex-direction: column; align-items: stretch; }
  /* `flex: 1` no lugar de `width: 100%`: com 100% o campo tomava a linha
     inteira e jogava o botao de buscar (lupa) sozinho pra linha de baixo,
     gastando uma faixa vertical inteira do celular a toa. Assim os dois
     dividem a mesma linha. */
  .toolbar-search { flex-wrap: nowrap; }
  .toolbar-search input[type="text"] { flex: 1; width: auto; min-width: 0; max-width: none; }
  #ads-search-form { display: flex; gap: 0.6rem; }
  #ads-search-form input[type="text"] { flex: 1; width: auto; min-width: 0; }
  .toolbar-actions-right { justify-content: flex-end; }
}

/* Checklist do anuncio (ad_detail) -- 2026-07-27: deixou de ser um painel
   flutuante toggleavel (ficava fixo no canto, escondido/mostrado por um
   icone no header) e virou uma secao normal (.panel) no fluxo da coluna
   esquerda, logo abaixo de "Caracteristicas do produto base" -- sempre
   visivel, sem posicionamento/JS especial. Sem margin-top proprio de
   proposito: .ad-left-column ja e' flex com gap:1.5rem entre os filhos
   (mesmo espacamento de todas as demais secoes dessa coluna) -- um
   margin-top aqui SOMARIA ao gap e dobraria o respiro so' antes desta
   secao (bug real corrigido: 48px em vez dos 24px padrao). */

/* Cabecalho do anuncio: fixo/flutuante (sticky) logo abaixo da topbar global,
   pra manter o menu de acoes (salvar/validar/concluir/preencher com IA)
   sempre acessivel mesmo com a pagina rolada bem pra baixo. */
/* Cabecalho do anuncio (2026-07-24): deixou de ser um card branco fixo. O
   titulo/navegacao foi pra topbar (ad-topbar-head); o que sobra aqui (status,
   botoes de acao, SKU, metricas) flui na propria pagina, sem fundo de card,
   sem fixacao -- integrado ao fundo. */
/* Cabecalho + abas do anuncio fixos ao rolar (pedido do usuario, 2026-07-31:
   "disso aqui apra cima ficar fixo em tela qnd fizer scroll para baixo",
   selecionando a .ad-tab-bar) -- fica logo abaixo da .topbar global (que ja
   e' sticky). O `top` de cada um e' calculado em JS (positionAdStickyHeader,
   perto do fim do <script> principal) porque a altura da topbar E deste
   proprio painel variam (setas de navegacao, linha de SKU opcional, banner
   de atencao) -- nunca um valor fixo, mesma logica ja documentada pro
   checklist flutuante numa rodada anterior. Precisa de fundo OPACO (nao mais
   transparent) porque agora fica por cima do conteudo rolando por baixo. */
.ad-header-panel {
  background: var(--bg);
  border: none;
  box-shadow: none;
  padding: 0;
  margin-bottom: 1.25rem;
  position: sticky;
  z-index: 30;
}

/* Linha unica do header do anuncio: info (SKU/Loja/ID) a esquerda; a direita o
   grupo de acoes (icones + Salvar + Publicar/Sincronizar). So' quebra pra
   segunda linha quando nao couber mesmo. */
.ad-header-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin-bottom: 0.6rem;
}

.ad-header-sku {
  margin: 0;
  flex: 1;
  min-width: 12rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* Grupo de acoes empurrado pra direita, tudo na mesma linha do SKU. */
.ad-header-actions-group {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
  flex: 0 0 auto;
}

.ad-header-icons {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

/* Botoes principais do header um pouco mais compactos pra caber na linha. */
.ad-header-actions-group > button:not(.icon-btn) {
  padding: 0 0.9rem;
  font-size: 0.85rem;
}

/* Badge de status do anuncio na linha de metricas, na altura dos chips. */
.ad-metrics-row .badge {
  padding: 0.3rem 0.7rem;
  font-size: 0.8rem;
}

/* --- Cabecalho do anuncio na topbar --- */
.ad-topbar-head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  width: 100%;
}

.ad-topbar-title-group {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  gap: 0.05rem;
}

.ad-topbar-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* Codigo do produto abaixo do titulo (pedido do usuario, 2026-07-27) --
   fonte bem menor/discreta, so referencia rapida. */
.ad-topbar-codigo {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-muted);
  min-width: 0;
}

.ad-topbar-codigo-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Icone pequeno "copiar" -- sem contorno/fundo por padrao (pedido explicito
   do usuario: "sem contorno"), usado ao lado de codigos curtos (codigo do
   produto no header do anuncio, OEM na secao de caracteristicas). Feedback
   de clique troca o icone padrao por um check por 1,2s (ver copyToClipboard
   em ad_detail.html) -- nunca depende de toast/popup a mais. */
.copy-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  border: none;
  background: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
  color: var(--text-faint);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease-out);
}

.copy-icon-btn svg { width: 13px; height: 13px; }

.copy-icon-btn:hover {
  /* button:hover global do sistema (mais generico, so' 1 classe de
     especificidade) seta background/border-color/color -- sem sobrescrever
     os 3 aqui, o hover ficaria com fundo solido mesmo com "sem contorno"
     pedido explicitamente pelo usuario. */
  background: none;
  border-color: transparent;
  color: var(--brand);
  transform: none;
  box-shadow: none;
}

.copy-icon-btn .copy-icon-check { display: none; }

.copy-icon-btn.copied {
  color: var(--success-text);
}

.copy-icon-btn.copied .copy-icon-default { display: none; }
.copy-icon-btn.copied .copy-icon-check { display: inline-flex; }

/* A topbar-title generica limita a largura -- no anuncio o head precisa da
   linha toda pra caber nav + titulo + acoes. */
.topbar-title:has(.ad-topbar-head) {
  flex: 1;
  min-width: 0;
}

/* Menu suspenso "mais acoes" no header do anuncio -- mesmo padrao visual do
   user-dropdown (sem shadow nos botoes individuais, lista limpa estilo
   Google, so o painel em si tem borda/sombra sutil). */
.header-menu {
  position: relative;
}

.header-menu-divider {
  height: 1px;
  background: var(--border);
  margin: 0.3rem 0.2rem;
}

.header-menu-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  min-width: 210px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
  padding: 0.35rem;
  /* Considera o espaco disponivel na tela (pedido do usuario, 2026-07-30:
     "considerar a peça apra mostrar menu suspenso") -- o menu de acoes em
     massa passou a ter ~18 itens e estourava a altura da janela, deixando os
     ultimos inalcancaveis. --menu-max-h e' calculado em JS (distancia real do
     botao ate a borda de baixo); o valor aqui e' o fallback pra quando o JS
     nao rodou ainda. */
  max-height: var(--menu-max-h, 70vh);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Abre pra CIMA quando nao ha espaco suficiente embaixo do botao. */
.header-menu-dropdown.drop-up {
  top: auto;
  bottom: calc(100% + 0.5rem);
}

.header-menu-dropdown.open { display: block; }

/* Menu de clique-na-linha (products.html) -- mesmo visual do
   .header-menu-dropdown, mas fixed no ponto do clique do mouse em vez de
   absolute relativo a um botao pai. */
.row-click-menu {
  position: fixed;
  right: auto;
  top: auto;
  min-width: 240px;
}

/* Forca o mesmo visual em TODOS os itens do menu, nao importa a classe extra
   que cada botao carregue (fill-missing-btn, ou nenhuma) nem o estado
   (hover/disabled) -- padroniza icone, fonte, alinhamento e espaçamento. */
/* Regra permanente do sistema (2026-07-19): ícone + texto de QUALQUER item
   de menu suspenso sempre alinhados à ESQUERDA -- nunca space-between/
   center/flex-end, que empurraria o texto pra longe do ícone. Declarado
   explicitamente aqui (mesmo já sendo o default de flex-direction:row) pra
   nenhuma regra futura sobrescrever sem querer. */
.header-menu-dropdown button {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.55rem;
  width: 100%;
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text);
  font-family: inherit;
  font-weight: 600;
  font-size: 0.82rem;
  line-height: 1.3;
  padding: 0.6rem 0.65rem;
  margin: 0;
  border-radius: var(--radius-sm);
  text-align: left;
  letter-spacing: normal;
}

.header-menu-dropdown button svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

.header-menu-dropdown button:hover {
  background: var(--bg-alt);
  filter: none;
  transform: none;
  box-shadow: none;
  color: var(--text);
}

.header-menu-dropdown button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.header-menu-dropdown button.danger { color: var(--error-text); }
.header-menu-dropdown button.danger:hover { background: var(--error-bg); color: var(--error-text); }

/* Layout lado a lado: fotos (coluna menor) + dados comerciais (coluna maior) */

.ad-tab-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.25rem;
  margin: 1rem 0 1.5rem;
  border-bottom: 1px solid var(--border-strong);
  position: sticky;
  z-index: 29;
  background: var(--bg);
  padding-top: 0.35rem;
  /* Com muitas abas (Configuracoes ja' tem 10, ~1570px de conteudo numa
     coluna de ~1100px) a barra passava da largura da tela. A correcao
     anterior deixava rolar por dentro (overflow-x: auto) -- funcionava mas
     escondia aba atras de scroll horizontal (reportado como "abas ficando
     com scroll"). Agora quebra em mais de uma linha em vez de rolar --
     `flex: 0 0 auto` no botao (regra logo abaixo) garante que cada aba
     mantem o tamanho natural do texto, nunca encolhe nem quebra letra a
     letra, so' pula pra proxima linha quando nao cabe mais. `overflow-x:auto`
     fica so' como rede de seguranca (nunca aparece com o wrap funcionando --
     so' entraria em cena se uma aba sozinha for mais larga que o container
     inteiro, caso que wrap nenhum resolve). No mobile (media query no fim do
     arquivo) isso e' sobrescrito de proposito: label longo numa tela estreita
     quebraria em 3 linhas dentro do proprio botao, entao la' continua sendo
     faixa rolavel horizontal, nunca wrap. */
  overflow-x: auto;
  /* BUG REAL (2026-08-11, reportado mais de uma vez sem nunca ter sido
     achado): so' declarar `overflow-x: auto` faz o navegador PROMOVER
     `overflow-y` (nunca declarado aqui) pra `auto` tambem -- e' a regra da
     propria especificacao CSS Overflow ("se um eixo nao e' visible e o
     outro e', o outro vira auto"). Com `flex-wrap: wrap` + a borda de 2px
     dos botoes + `margin-bottom: -1px`, a barra sempre acaba com ~1px de
     overflow vertical por arredondamento -- e como o eixo Y virou `auto`
     por causa disso, esse 1px basta pra desenhar uma barra de scroll
     vertical fina (`scrollbar-width: thin` so' deixa mais discreta, nao
     evita) em TODA tela que usa `.ad-tab-bar` (anuncio, produto, empresa,
     configuracoes, metricas, reputacao...). Medido: scrollHeight 43 x
     clientHeight 42. `overflow-y: hidden` fixa o eixo Y explicitamente e
     tira o navegador dessa promocao automatica -- nunca corta nada de
     verdade (o unico "excesso" e' esse pixel de arredondamento). */
  overflow-y: hidden;
  scrollbar-width: thin;
}

.ad-tab-bar > * { flex: 0 0 auto; }

.ad-tab-btn {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.92rem;
  padding: 0.7rem 1rem;
  margin-bottom: -1px;
  cursor: pointer;
  box-shadow: none;
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

/* IMPORTANTE: precisa declarar `background` explicitamente aqui (nao so
   `color`) -- senao o hover herda `background: var(--brand-dark)` do
   `button:hover` global (a base do sistema), deixando o texto escuro
   (var(--text)) sobre um fundo verde escuro tambem, quase ilegivel. Usa o
   mesmo par claro/escuro do hover dos .icon-btn (--brand-soft de fundo +
   --brand-dark no texto) pra manter contraste bom e consistencia visual. */
.ad-tab-btn:hover {
  background: var(--brand-soft);
  border-color: transparent;
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}

.ad-tab-btn.active {
  background: none;
  color: var(--brand-dark);
  border-bottom-color: var(--brand);
}

.ad-tab-btn.active:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-bottom-color: var(--brand);
}

.ad-main-layout {
  display: grid;
  grid-template-columns: minmax(300px, 380px) 1fr;
  gap: 1.5rem;
  align-items: start;
  margin-bottom: 1.5rem;
}

/* Tela do anuncio em UMA COLUNA (pedido do usuario, 2026-07-31: "toda tela
   de anuncio agora ficara 1 coluna"). Vira um fluxo vertical simples: cada
   painel ocupa a largura toda, com o mesmo respiro entre eles que as demais
   telas do sistema usam. */
.ad-main-layout.ad-single-column {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  /* OBRIGATORIO: a regra base .ad-main-layout tem `align-items: start`, que
     no GRID original significava "alinha ao topo" (eixo vertical). Ao virar
     flex-column o eixo TRANSVERSAL passa a ser o HORIZONTAL, entao esse
     mesmo `start` vira "nao estique na largura" -- cada painel encolhia pro
     tamanho do proprio conteudo em vez de ocupar a linha toda. Era a causa
     real do painel de Fotos aparecer estreito mesmo com a tela em 1 coluna
     (reportado 4x). `stretch` e' o padrao do flex, mas precisa ser
     reafirmado aqui pra sobrescrever o `start` herdado. */
  align-items: stretch;
}

/* No fluxo de coluna unica o espaco entre paineis vem SO do `gap` do flex.
   Qualquer margin-top/bottom proprio de painel (varios tem margin-top:1.5rem
   herdado do layout antigo de 2 colunas) SOMARIA ao gap e dobraria o respiro
   -- foi exatamente o bug reportado ("espacamento desproporcional acima de
   Dimensoes/Categoria/Valores"). Zera os dois lados aqui, sem precisar
   caçar cada painel individualmente: o gap cuida de todo o espacamento. */
.ad-main-layout.ad-single-column > *,
.ad-main-layout.ad-single-column .ad-tab-content-wrap > * {
  margin-top: 0;
  margin-bottom: 0;
}

.ad-main-layout.ad-single-column .ad-tab-content-wrap {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.ad-photos-panel, .ad-commercial-panel, .ad-product-panel { margin-bottom: 0; }

/* Coluna esquerda (fotos + referencia visual de caracteristicas do
   produto base) -- pedido do usuario, 2026-07-24: NAO fica mais fixa
   (sticky) durante o scroll, mostra a altura completa do conteudo (sem
   cortar/scroll interno). Fluxo normal dentro do grid de 2 colunas
   (.ad-main-layout), so' um flex vertical simples. */
.ad-left-column {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.ad-product-reference-panel { margin-bottom: 0; }
.product-reference-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 0.85rem;
}
.product-reference-list li {
  padding: 0.35rem 0.6rem;
  background: var(--bg-alt);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}
.product-reference-list li strong { color: var(--text); }

/* Painel "Valores do anuncio" (secao separada abaixo de Dados comerciais,
   dentro da mesma coluna de abas) -- respiro entre os dois paineis, ja que
   .ad-commercial-panel zera o margin-bottom. */
.ad-values-panel {
  margin-top: 1.5rem;
  margin-bottom: 0;
}

.ad-values-panel > h3 { margin-bottom: 0.9rem; }

/* Secoes novas do anuncio (2026-07-14): Categoria / Produto de catalogo /
   Dimensoes -- mesmo tratamento visual/largura do painel de Valores (que
   zera o margin-bottom), entao cada uma abre com margin-top proprio e a
   ultima (Dimensoes) volta pro margin-bottom padrao de .panel pra dar
   respiro antes das Caracteristicas da categoria logo abaixo.
   Variacao personalizada / Loja Oficial / Disponibilidade entram na mesma
   cadeia (vem logo apos o painel de Valores, que zera o proprio
   margin-bottom) -- sem isso faltava respiro entre "Valores do anuncio" e
   "Variacao personalizada" (bug reportado 2026-07-24). */
.ad-custom-variation-panel,
.ad-official-store-panel,
.ad-availability-panel,
.ad-category-panel,
.ad-catalog-panel,
.ad-dimensions-panel { margin-top: 1.5rem; margin-bottom: 0; }
.ad-dimensions-panel { margin-bottom: 1.5rem; }
.ad-custom-variation-panel > h3,
.ad-official-store-panel > h3,
.ad-availability-panel > h3,
.ad-category-panel > h3,
.ad-catalog-panel > h3,
.ad-dimensions-panel > h3 { margin-bottom: 0.9rem; }

.ad-commercial-panel > h3,
.ad-product-panel .panel-head { margin-bottom: 0.9rem; }

/* Cadastro de Produto pediu margem lateral um pouco maior que o padrao de
   painel do sistema (1.75rem) -- respiro extra pros campos nao ficarem
   colados na borda do card. */
.ad-product-panel {
  padding-left: 2.3rem;
  padding-right: 2.3rem;
}

/* Pedido do usuario (2026-07-19, item 8): a secao "Caracteristicas do
   produto" deve ter a MESMA largura visual da secao "Dados comerciais do
   anuncio" (.ad-commercial-panel, dentro do padding padrao de .panel,
   1.75rem) -- mas ela vive dentro de .ad-product-panel, que tem padding
   lateral MAIOR (2.3rem, pedido de rodada anterior). Compensa a diferenca
   (0.55rem de cada lado) com margem negativa so nesse bloco, sem mexer no
   padding do painel inteiro (que continua valendo pros demais campos do
   Cadastro de Produto). */
.characteristics-panel-inset {
  margin-left: -0.55rem;
  margin-right: -0.55rem;
  width: calc(100% + 1.1rem);
}

.ai-field-toggle {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
}

.ai-field-toggle input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--brand);
  cursor: pointer;
}

/* Variante pra quando o texto do toggle e uma frase longa (ex.: aviso no
   popup de importar planilha) em vez de um rotulo curto -- a regra base
   usa white-space:nowrap de proposito (rotulos curtos tipo "Preco
   personalizado" ficam melhor numa linha so), mas isso cortava/nao
   quebrava frases longas. */
.ai-field-toggle.wrap {
  white-space: normal;
  align-items: flex-start;
}

.ai-field-toggle.wrap input[type="checkbox"] {
  flex: 0 0 auto;
  margin-top: 0.15rem;
}

/* Codigo original duplicado (ja usado em outro produto) */
.field-duplicate {
  border-color: var(--warning-text) !important;
  background: var(--warning-bg) !important;
  color: var(--warning-text);
}

@media (max-width: 980px) {
  .ad-main-layout { grid-template-columns: 1fr; }
}

/* Compact photo gallery (ad_detail) */

/* Tela do anuncio/produto virou 1 coluna (2026-07-31) -- o grid de fotos
   agora ocupa a largura inteira do painel, com quantas miniaturas couberem
   por linha. Tile um pouco maior que os 96px antigos (que faziam sentido na
   coluna estreita de antes e ficavam minusculos espalhados numa linha
   larga). As variantes .two-col-photos foram removidas junto com a coluna
   estreita -- nao ha' mais nenhum template usando essa classe. */
.photo-dragzone.compact {
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 0.7rem;
}

.photo-dragzone.compact .photo-square {
  border-radius: var(--radius-sm);
}

.photo-add-tile { cursor: pointer; }

.photo-add-tile .photo-square {
  background: var(--brand-soft);
  border-style: dashed;
  color: var(--brand-dark);
  font-size: 0.72rem;
  font-weight: 700;
  gap: 0.3rem;
}

.photo-add-tile .photo-square svg { width: 20px; height: 20px; }

/* Pedido do usuario (2026-07-19, item 6): botao de adicionar foto mais
   resumido -- icone/texto menores dentro do quadrado tracejado. Reescopado
   em 2026-07-31 de .two-col-photos (classe removida com o fim da coluna
   estreita) pra .photo-dragzone.compact, que e' a grade usada nas duas
   telas agora. */
.photo-dragzone.compact .photo-add-tile .photo-square svg { width: 16px; height: 16px; }
.photo-dragzone.compact .photo-add-tile .photo-square { font-size: 0.65rem; gap: 0.2rem; }

.photo-remove-x {
  position: absolute;
  top: -7px;
  right: -7px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--dark);
  color: #fff;
  border: 2px solid var(--surface-solid);
  box-shadow: var(--shadow-sm);
  padding: 0;
  font-size: 0.7rem;
  line-height: 1;
  z-index: 2;
}

.photo-remove-x:hover { background: var(--error-text); transform: none; box-shadow: var(--shadow-sm); }

.photo-url-list {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem;
  font-size: 0.72rem;
  color: var(--text-faint);
  word-break: break-all;
  margin-top: 0.6rem;
}

.photo-url-list .copy-icon-btn {
  align-self: center;
}

/* Compact 2-column ad form */

.form-grid.two-col {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem 1.25rem;
}

.form-grid.two-col .span-2 { grid-column: 1 / -1; }

/* Grid compacta de 3 colunas usada nos dados comerciais do anuncio (titulo,
   preco, categoria, sku etc.) -- deixa mais campos visiveis por linha e
   reduz o espacamento vertical entre eles. */
.form-grid.compact-3col {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.65rem 1rem;
}

.form-grid.compact-3col .span-2 { grid-column: span 2; }
.form-grid.compact-3col .span-3 { grid-column: 1 / -1; }

/* Par de campos lado a lado dentro da MESMA celula do grid (2026-08-11,
   pedido do usuario: "preço minimo e preço maximo, deixar na mesma linha
   ... data de publicação de e ate deixar na mesma linha"). Cada
   .field-pair e' UM item de grid so' (normalmente span-2) com
   display:flex por dentro -- isso garante os dois campos sempre colados,
   independente de quantos itens soltos vem antes dele no formulario (o
   auto-flow do CSS Grid deposita cada <label> onde sobrar espaco na
   linha, o que e' imprevisivel quando um campo condicional -- ex.
   Plataforma, so' aparece com mais de 1 canal liberado -- muda a
   contagem de itens antes dele). */
.form-grid .field-pair {
  display: flex;
  gap: 1rem;
}
.form-grid .field-pair > label {
  flex: 1;
  min-width: 0;
}

.form-grid.compact-3col label {
  gap: 0.3rem;
  font-size: 0.78rem;
}

.form-grid.compact-3col input,
.form-grid.compact-3col select {
  /* So padding horizontal -- a altura vem de --field-h (regra global de
     input/select), nunca da padding vertical, senao volta a ficar maior
     que os botoes ao lado (mesmo problema de especificidade documentado
     acima pro overlap do R$: uma regra mais especifica redefinindo
     padding-vertical destrava a altura fixa por baixo). */
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 0.7rem;
  padding-right: 0.7rem;
  font-size: 0.85rem;
}

.form-grid.compact-3col textarea {
  font-size: 0.88rem;
}

/* Variante de 4 colunas (pedido do usuario, 2026-07-31: "Preço de venda,
   comissao, frete, imposto -- deixar tudo na mesma linha"). Herda TODO o
   comportamento de .compact-3col (altura de campo, padding, span-*) e só
   troca a contagem de colunas -- por isso o seletor duplo nas regras de
   herança abaixo, em vez de duplicar o bloco inteiro. */
.form-grid.compact-4col {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.65rem 1rem;
}

.form-grid.compact-4col .span-2 { grid-column: span 2; }
.form-grid.compact-4col .span-3 { grid-column: 1 / -1; }

.form-grid.compact-4col label {
  gap: 0.3rem;
  font-size: 0.78rem;
}

.form-grid.compact-4col input,
.form-grid.compact-4col select {
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 0.7rem;
  padding-right: 0.7rem;
  font-size: 0.85rem;
}

/* Popup de detalhes completos da categoria (ad_detail) */

.category-details-body { line-height: 1.4; }

.category-details-header {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: 0.6rem;
}

.category-details-header h4 { margin: 0 0 0.15rem; }

.category-details-picture {
  width: 56px;
  height: 56px;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  padding: 0.3rem;
}

.category-details-breadcrumb { margin: 0 0 1rem; }

.category-details-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.9rem 1.2rem;
  margin-bottom: 1rem;
}

.category-details-grid strong {
  display: block;
  font-size: 1rem;
  color: var(--ink);
}

.category-details-grid span {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.category-details-subhead {
  margin: 0.4rem 0 0.5rem;
  font-size: 0.85rem;
}

.category-details-children {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
}

@media (max-width: 620px) {
  .category-details-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Popup "produtos parecidos no Mercado Livre" (ao lado do Preço de venda) --
   reusa .category-details-body/.category-details-subhead do popup de
   detalhes de categoria, só a lista de resultados é nova. */
.similar-products-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 380px;
  overflow-y: auto;
}

.similar-product-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.similar-product-row:hover {
  border-color: var(--brand);
  background: rgba(0, 0, 0, 0.02);
}

.similar-product-thumb {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 8px;
  flex: 0 0 auto;
}

.similar-product-info {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1 1 auto;
}

.similar-product-title {
  font-size: 0.85rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.similar-product-price {
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
  flex: 0 0 auto;
}

.input-with-action {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.input-with-action input { flex: 1; }

/* Botao de acao (lupa etc.) ao lado de um input -- trava em --field-h nos
   dois eixos (mesma altura E largura do input/botao padrao do sistema),
   nunca "auto"/stretch: isso e o que deixava o botao maior/desproporcional
   quando o input ao lado ficava mais alto por qualquer motivo. Com os dois
   fixos no mesmo valor, o botao nunca passa da altura do input. */
.input-with-action .icon-btn {
  width: var(--field-h);
  height: var(--field-h);
  flex: 0 0 auto;
}

/* Input monetario (R$) / percentual (%) -- prefixo/sufixo fixo dentro do
   proprio campo, em vez de deixar "(R$)" solto no texto do label (que
   nao escala com o valor digitado e fica desalinhado entre campos). */
.currency-input, .percent-input, .unit-input {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1;
  min-width: 0;
  height: var(--field-h);
}

.currency-input .currency-affix, .percent-input .currency-affix, .unit-input .currency-affix {
  position: absolute;
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.78rem;
  pointer-events: none;
}

.currency-input .currency-affix { left: 0.75rem; }

/* CAUSA REAL do overlap do "R$" que persistiu mesmo depois de aumentar o
   padding: ".form-grid.compact-3col input" (2 classes + elemento) tem
   especificidade MAIOR que ".currency-input input" (1 classe + elemento) --
   o navegador ignorava esse padding-left inteiro e usava o padding generico
   do grid por baixo, nao importa o valor que a gente colocasse aqui.
   Especificidade de CSS nao depende da ordem no arquivo. !important aqui e
   intencional: e um ajuste estreito e sempre correto (espaco reservado pro
   prefixo/sufixo nunca deve perder pra um padding de grid generico). Valor
   reduzido pra 2.3rem (era 3rem) -- espaco justo pro "R$" sem sobrar
   demais, a pedido do usuario. */
.currency-input input { padding-left: 2.3rem !important; }

/* .percent-input (%) e .unit-input (kg/cm) colocam o sufixo do lado
   direito -- por padrao o navegador desenha as setinhas de incremento de
   input[type=number] bem nesse canto, o que fazia o sufixo aparecer
   espremido/sobreposto em cima delas. As regras abaixo removem essas
   setinhas nativas (nao fazem falta aqui, ninguem usa pra digitar preco/
   peso) e dao espaco reservado suficiente pro sufixo nunca encostar no
   numero digitado. Mesmo !important acima, e pelo mesmo motivo. Valor
   reduzido pra 1.9rem (era 2.4rem). */
.percent-input .currency-affix, .unit-input .currency-affix { right: 0.65rem; }
.percent-input input, .unit-input input { padding-right: 1.9rem !important; }

.currency-input input[type="number"],
.percent-input input[type="number"],
.unit-input input[type="number"] {
  -moz-appearance: textfield;
}

.currency-input input[type="number"]::-webkit-outer-spin-button,
.currency-input input[type="number"]::-webkit-inner-spin-button,
.percent-input input[type="number"]::-webkit-outer-spin-button,
.percent-input input[type="number"]::-webkit-inner-spin-button,
.unit-input input[type="number"]::-webkit-outer-spin-button,
.unit-input input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Peso/dimensoes do pacote -- linha compacta de 4 campos pequenos usada
   so pra consultar o frete real (nao sao atributos do Mercado Livre em
   si, ficam junto do campo de frete). */
.package-dims-row {
  display: flex;
  gap: 0.5rem;
  align-items: stretch;
  flex-wrap: wrap;
}

.package-dims-row .package-dim-field {
  /* Nao usa flex:1 -- campo pequeno (peso/cm) nao precisa esticar pra
     preencher a largura toda da linha, fica proporcional ao conteudo. */
  flex: 0 1 120px;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.package-dims-row .package-dim-field span {
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.shipping-cost-controls {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.shipping-cost-controls .currency-input { flex: 1; min-width: 0; }

.shipping-cost-controls .icon-btn {
  width: var(--field-h);
  height: var(--field-h);
  flex: 0 0 auto;
}

/* Grupo de dois campos lado a lado (ex.: comissao %/R$, margem %/R$) --
   substitui um input unico dentro de .input-with-action/.pricing-field sem
   quebrar o alinhamento com o botao de lupa ao lado. */
.pricing-dual-group {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1;
  min-width: 0;
}

.pricing-dual-group .currency-input,
.pricing-dual-group .percent-input {
  flex: 1;
  min-width: 0;
}

/* Select de unidade (%/R$) dentro de um pricing-dual-group (ex.: Encargos)
   -- mesma altura padrao do sistema, nunca maior/menor que os inputs
   vizinhos no mesmo grupo. */
.pricing-dual-group select {
  flex: 0 0 auto;
  width: 62px;
  height: var(--field-h);
  padding: 0 0.4rem;
}

/* Linha da formula de precificacao no Cadastro de Produto (custo -> valor
   do produto) e "Total do anuncio e lucro" no anuncio -- mesmo padrao
   visual de .package-dims-row. Todos os campos ficam na mesma linha
   horizontal (nowrap) dentro do painel; so quebra em telas realmente
   estreitas (ver media query mais abaixo), nunca no meio de uma coluna do
   grid por causa de um campo largo demais. */
.pricing-formula-row {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
  flex-wrap: wrap;
}

.pricing-formula-row .pricing-field {
  /* Nao usa flex:1 -- cada campo fica do tamanho do conteudo (numero +
     prefixo/sufixo), nao esticado pra preencher a linha toda. Campos com
     um unico input (Custo, Imposto) ficam mais estreitos; campos com
     .pricing-dual-group (Margem, Encargos -- 2 inputs lado a lado) usam
     .pricing-field-wide, que reserva espaco suficiente pros dois sem
     cortar o valor digitado. */
  flex: 0 1 145px;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.pricing-formula-row .pricing-field span {
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* Campo que carrega um .pricing-dual-group (2 inputs lado a lado, ex.:
   Margem %/R$, Encargos %/R$/select) precisa de mais largura que um campo
   de input unico -- sem isso os 2 subcampos ficavam espremidos demais e
   cortavam o valor digitado. */
.pricing-formula-row .pricing-field.pricing-field-wide {
  flex-basis: 235px;
}

/* Botao de acao dentro de uma pricing-formula-row (ex.: "Usar esse valor
   no preco") nao deve ser espremido pela largura fixa dos campos vizinhos
   -- fica do tamanho do proprio texto/padding, nunca cortado/quebrado. */
.pricing-formula-row .pricing-field.pricing-field-action {
  flex: 0 0 auto;
  justify-content: flex-end;
}

.pricing-formula-row .pricing-field.pricing-field-action button {
  white-space: nowrap;
}

/* Campos de RESULTADO (calculados, nunca digitados) da linha "Total do
   anúncio e lucro" -- pedido do usuário (2026-07-31) foi que ficassem
   "desabilitados". Usam `readonly`, NÃO `disabled`: `venda_total`/`lucro`
   são colunas reais de marketplace_ads e campo disabled não viaja no POST
   (armadilha já documentada no projeto). Este bloco dá a APARÊNCIA de
   desabilitado sem tirar o valor do formulário. */
.pricing-formula-row .pricing-field input[readonly] {
  background: var(--bg-alt);
  color: var(--text-muted);
  cursor: default;
}

.pricing-formula-row .pricing-field input[readonly]:focus {
  outline: none;
  border-color: var(--border);
  box-shadow: none;
}

/* Campo estreito dentro da grade compacta (ex.: NF %) -- a celula do grid
   de 3 colunas reserva 1/3 do painel, mas o conteudo (percentual de 2-3
   digitos) nao precisa de tudo isso; trava a largura maxima no tamanho do
   conteudo em vez de esticar (o grid item por padrao tenta preencher a
   coluna toda -- max-width sem justify-self:stretch alterado ja resolve,
   o proprio grid posiciona o item encolhido no inicio da celula). */
.field-narrow { max-width: 150px; }

#venda-sugerida-hint,
#valor-produto-hint {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

/* Switch/toggle deslizante (ex.: "Preco personalizado") -- usado ao lado
   de um input, nunca como checkbox solto abaixo dele. Sibling selector
   (input ~ .switch-slider) troca a aparencia via :checked, sem JS extra
   alem do onchange que ja disparava no checkbox antigo. */
.switch-toggle {
  --switch-w: 34px;
  --switch-h: 18px;
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  width: var(--switch-w);
  height: var(--switch-h);
  cursor: pointer;
}

.switch-toggle input[type="checkbox"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}

.switch-toggle .switch-slider {
  position: absolute;
  inset: 0;
  background: var(--border-strong);
  border-radius: 999px;
  transition: background 0.15s ease;
  pointer-events: none;
}

.switch-toggle .switch-slider::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: calc(var(--switch-h) - 4px);
  height: calc(var(--switch-h) - 4px);
  background: #fff;
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease;
}

.switch-toggle input:checked ~ .switch-slider {
  background: var(--brand);
}

.switch-toggle input:checked ~ .switch-slider::before {
  transform: translateX(calc(var(--switch-w) - var(--switch-h)));
}

.switch-toggle input:focus-visible ~ .switch-slider {
  box-shadow: 0 0 0 3px var(--brand-glow);
}

.modal-box.wide { max-width: 640px; }

/* Popup de categoria (pedido do usuario, 2026-07-19, repetido varias vezes
   -- 2026-08-10: "em todos popup de categoria deixar mais largo... uma aba
   profissional... um de busca e um de explorador de categoria, sendo
   pesquisado em cascata"). Usado nos 3 popups de categoria do sistema
   (anuncio individual, alteracao em massa, planilha de edicao) -- a MESMA
   classe, pra largura ficar identica nos tres. `min(..., vw)` em vez de um
   numero fixo (mesmo padrao ja adotado no popup de compatibilidade,
   #compat-manual-modal): usa a tela disponivel de verdade em vez de
   adivinhar mais um numero que talvez nao seja largo o bastante numa
   proxima rodada -- 1080px cabe confortavelmente 4 colunas do Explorador
   (~220px cada) + os botoes de acao do rodape sem quebrar linha. */
.modal-box.category-modal-box {
  max-width: min(1080px, 92vw);
  max-height: 90vh;
}

/* Abas "Buscar" / "Explorador" dentro do popup de categoria -- mesma
   linguagem visual das abas de pagina (.ad-tab-bar/.ad-tab-btn: borda
   inferior na cor da marca quando ativa, fundo brand-soft no hover), mas
   SEM position:sticky/margem grande (aquelas foram desenhadas pra muitas
   abas de pagina inteira; aqui sao so' 2, sempre cabem numa linha dentro de
   um popup compacto). Regra ja documentada varias vezes no projeto: nao
   reusar a classe de pagina direto, replicar so' a linguagem visual. */
.picker-tabs {
  display: flex;
  gap: 0.2rem;
  border-bottom: 1px solid var(--border-strong);
  margin: 0.9rem 0 1.1rem;
}

.picker-tab-btn {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.88rem;
  padding: 0.55rem 0.95rem;
  margin-bottom: -1px;
  cursor: pointer;
  box-shadow: none;
  height: auto;
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

/* IMPORTANTE: precisa redeclarar `background` explicitamente aqui -- senao
   o hover herda `background: var(--brand-dark)` do `button:hover` global,
   deixando o texto escuro sobre fundo escuro tambem (mesma armadilha ja
   documentada em .ad-tab-btn/.copy-icon-btn/.stat-cell/.multi-select-trigger). */
.picker-tab-btn:hover,
.picker-tab-btn:focus,
.picker-tab-btn:focus-visible {
  background: var(--brand-soft);
  border-color: transparent;
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
  outline: none;
}

.picker-tab-btn.active {
  background: none;
  color: var(--brand-dark);
  border-bottom-color: var(--brand);
}

.picker-tab-btn.active:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-bottom-color: var(--brand);
}

.picker-tab-panel[hidden] { display: none; }

/* Explorador de categoria -- navegacao em colunas em cascata (marca->modelo
   equivalente pra categoria: raiz->subcategoria->...), alternativa a busca
   por texto. Ver static/js/category_explorer.js. */
.category-explorer {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.category-explorer-columns {
  display: flex;
  gap: 0;
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  min-height: 280px;
  max-height: 380px;
}

.category-explorer-col {
  flex: 0 0 220px;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem;
  border-right: 1px solid var(--border);
  overflow-y: auto;
}

.category-explorer-col:last-child { border-right: none; }

/* Item de coluna: e' um <button>, entao precisa redeclarar hover/focus (mesma
   armadilha do .picker-tab-btn acima) -- e reduzir a caixa alta/centralizada
   que o `button` global aplica por padrao (aqui e' uma linha de lista, texto
   alinhado a esquerda, nao um botao de acao). */
.category-explorer-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  width: 100%;
  text-align: left;
  padding: 0.5rem 0.6rem;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  box-shadow: none;
  height: auto;
  transform: none;
}

.category-explorer-item span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.category-explorer-item svg { flex: 0 0 auto; color: var(--text-faint); }

.category-explorer-item:hover,
.category-explorer-item:focus,
.category-explorer-item:focus-visible {
  background: var(--brand-soft);
  color: var(--brand-dark);
  box-shadow: none;
  transform: none;
  outline: none;
}
.category-explorer-item:hover svg { color: var(--brand-dark); }

.category-explorer-item.active {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
}
.category-explorer-item.active svg,
.category-explorer-item.active:hover svg { color: #fff; }
.category-explorer-item.active:hover {
  background: var(--brand-dark);
  color: #fff;
}

.category-explorer-loading {
  padding: 0.6rem;
  font-size: 0.8rem;
  color: var(--text-faint);
  margin: 0;
}

.category-explorer-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  font-size: 0.84rem;
}

.category-explorer-breadcrumb {
  color: var(--brand-dark);
  font-weight: 600;
  min-width: 0;
  overflow-wrap: break-word;
}

.category-explorer-actions {
  display: flex;
  gap: 0.5rem;
  flex: 0 0 auto;
}

@media (max-width: 620px) {
  .category-explorer-col { flex-basis: 170px; }
  .category-explorer-footer { flex-direction: column; align-items: stretch; }
  .category-explorer-actions { justify-content: flex-end; }
}

/* Popup "Sincronizar" (#sync-modal, ads.html -- ja usa .xwide, o maior
   tier padrao, mas o usuario pediu maior AINDA em altura e largura, 2026-
   08-06: "popup de sincronizar, deixar maior tanto altura e largura").
   Escopado so pra este modal (nao mexe em .xwide global, que outros popups
   tambem usam, ex. o de compatibilidade de veiculo) -- especificidade de
   id vence a classe sem precisar de !important. O modal-overlay ja tem
   padding proprio (1.5rem) que garante folga lateral em qualquer largura
   de tela, entao um max-width maior nunca estoura o viewport, so' usa mais
   espaco quando ha' espaco de sobra. */
#sync-modal .modal-box {
  max-width: 1200px;
  max-height: 92vh;
}

.category-locked-banner {
  background: var(--warning-bg, rgba(255, 152, 0, 0.12));
  color: var(--warning-text, #b25e00);
  border: 1px solid var(--warning, #ff9800);
  border-radius: 8px;
  padding: 0.6rem 0.9rem;
  margin: -0.2rem 0 0.9rem;
}

/* Campo "Categoria no Mercado Livre" agora se comporta como um dropdown de
   verdade -- readonly mas clicavel (abre o popup), com cursor/hover
   deixando isso claro visualmente. */
.category-dropdown-trigger {
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%), linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: calc(100% - 12px) calc(1.1em + 1px), calc(100% - 7px) calc(1.1em + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.category-dropdown-trigger:hover {
  border-color: var(--brand);
}

/* Popup "Adicionar veiculos compativeis" (2026-07-14): pedido explicito de
   aumentar altura/largura do popup atual -- bem maior que .wide, com teto de
   altura + scroll proprio pra nunca estourar a tela em resolucao menor. */
.modal-box.xwide {
  max-width: 960px;
  max-height: 88vh;
  overflow-y: auto;
}

/* Lupa/zoom de foto (listas de produtos/anuncios) -- so a imagem, sem
   cabecalho de texto, com um X flutuante no canto pra fechar. */
.modal-box.lightbox-box {
  max-width: 90vw;
  width: auto;
  padding: 0.75rem;
  background: var(--dark);
  position: relative;
}
.modal-box.lightbox-box .modal-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  background: rgba(0, 0, 0, 0.4);
  color: #fff;
  z-index: 1;
}
.modal-box.lightbox-box img {
  display: block;
  max-width: 100%;
  max-height: 82vh;
  border-radius: var(--radius-sm);
  margin: 0 auto;
}

/* Linhas de tabela clicaveis (produtos/anuncios): clicar na linha abre a
   edicao; clicar na miniatura da foto abre a lupa (stopPropagation evita
   que os dois cliques disparem juntos); clicar em checkbox/botoes tambem
   nao deve navegar (marcado via .no-row-click). */
.table-card table tbody tr.row-clickable {
  cursor: pointer;
}
.table-card table tbody tr.row-clickable:hover td {
  background: var(--bg-alt);
}
.row-thumb.clickable { cursor: zoom-in; }

.ai-model-current {
  font-weight: 600;
  margin-right: 0.75rem;
}

.ai-model-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  max-height: 60vh;
  overflow-y: auto;
  margin-top: 0.5rem;
}

.ai-model-card {
  border: 1px solid var(--border, #e2ddd0);
  border-radius: 12px;
  padding: 0.75rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.ai-model-card.current {
  border-color: var(--brand);
  background: rgba(33, 150, 243, 0.06);
}

.ai-model-card-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.ai-model-card p {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.88rem;
}

/* Aba "Usuários" de Configurações (pedido do usuário, 2026-07-19). */
.user-row-avatar,
.user-row-avatar-initials {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  display: grid;
  place-items: center;
  background: var(--brand);
  color: #fff;
  font-weight: 700;
  font-size: 0.68rem;
  flex-shrink: 0;
}

.user-log-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 320px;
  overflow-y: auto;
}

.user-log-row {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.85rem;
}

.user-log-date {
  font-size: 0.75rem;
  color: var(--text-muted);
}

/* Aba "IA" de Configuracoes: lista de pontos de uso da IA (titulo,
   descricao, fotos, etc.), cada linha com toggle + seletor de conexao +
   icone de ver prompt. Layout em wrapper interno (nao direto no td, essa
   linha nao e uma tabela mesmo, mas mantem o mesmo espirito de nunca
   depender de display:flex desalinhar algo -- aqui e so um <div>). */
.settings-touchpoint-section-title {
  margin: 1rem 0 0.4rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.settings-touchpoint-section-title:first-of-type { margin-top: 0.25rem; }

.touchpoint-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 0.75rem;
}

.touchpoint-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
}

.touchpoint-label {
  flex: 1 1 auto;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text);
}

.touchpoint-connection-select {
  flex: 0 0 auto;
  width: auto;
  min-width: 170px;
  max-width: 220px;
}

@media (max-width: 700px) {
  .touchpoint-row { flex-wrap: wrap; }
  .touchpoint-connection-select { max-width: none; flex: 1 1 100%; order: 3; }
}

@media (max-width: 900px) {
  .form-grid.compact-3col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-grid.compact-3col .span-2 { grid-column: 1 / -1; }
  .form-grid.compact-4col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-grid.compact-4col .span-2 { grid-column: 1 / -1; }
}

@media (max-width: 700px) {
  .form-grid.two-col { grid-template-columns: 1fr; }
  .form-grid.compact-3col { grid-template-columns: 1fr; }
  .form-grid.compact-3col .span-2,
  .form-grid.compact-3col .span-3 { grid-column: 1 / -1; }
  .form-grid.compact-4col { grid-template-columns: 1fr; }
  .form-grid.compact-4col .span-2,
  .form-grid.compact-4col .span-3 { grid-column: 1 / -1; }
}

/* Global loading overlay (uploads, geracao de anuncios, etc.) */

/* Carregamento padronizado no canto inferior direito (mesmo estilo do
   #save-toast/#corner-toast) -- era um overlay de tela cheia bloqueante,
   trocado por um card pequeno e nao-bloqueante pra todas as acoes com
   carregamento do sistema (regra do CLAUDE.md: sempre canto inferior
   direito, com barra de progresso). Mantem os mesmos ids/estrutura HTML
   (global-loading-label/bar-track/bar-fill/percent) usados por
   AdsPremiumLoading -- so muda a apresentacao visual. */
.loading-overlay {
  display: none;
  position: fixed;
  inset: auto;
  bottom: 1.5rem;
  right: 1.5rem;
  background: transparent;
  z-index: 90;
  padding: 0;
  pointer-events: none;
}

.loading-overlay.open { display: block; }

.loading-overlay-box {
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  width: 300px;
  max-width: calc(100vw - 2rem);
  max-height: min(60vh, 360px);
  overflow-y: auto;
  padding: 1rem 1.1rem;
  text-align: left;
  pointer-events: auto;
}

.loading-overlay-spinner {
  width: 20px;
  height: 20px;
  margin: 0 0 0.6rem;
  border-radius: 50%;
  border: 3px solid var(--brand-soft);
  border-top-color: var(--brand);
  animation: loading-spin 0.8s linear infinite;
}

@keyframes loading-spin {
  to { transform: rotate(360deg); }
}

.loading-overlay-label {
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--dark);
  margin-bottom: 0.7rem;
}

@media (max-width: 620px) {
  .loading-overlay { left: 1rem; right: 1rem; bottom: 1rem; }
  .loading-overlay-box { width: auto; }
}

.loading-overlay-bar-track {
  width: 100%;
  height: 10px;
  border-radius: 999px;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  overflow: hidden;
  margin-bottom: 0.5rem;
  position: relative;
}

.loading-overlay-bar-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand-dark) 100%);
  transition: width 0.2s ease;
}

.loading-overlay-bar-track.indeterminate .loading-overlay-bar-fill {
  width: 40% !important;
  transition: none;
  animation: loading-indeterminate 1.1s ease-in-out infinite;
}

@keyframes loading-indeterminate {
  0% { margin-left: -40%; }
  100% { margin-left: 100%; }
}

#global-loading-percent {
  margin: 0;
  font-weight: 600;
}

/* Validar/concluir anuncio no Mercado Livre */

.checklist-validate-btn {
  width: 100%;
  padding: 0.65rem 0.8rem;
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
}

.checklist-actions {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.9rem;
}

.checklist-actions form { width: 100%; }

.checklist-actions .secondary-dark {
  width: 100%;
  padding: 0.65rem 0.8rem;
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
}

.panel-head-title {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Cabecalho do anuncio: title row + acoes alinhados no centro (sem o
   desalinhamento do button-row padrao, que tem margin-top pensado pra
   ficar embaixo de labels de formulario) e a linha de SKU/tipo/marca mais
   discreta, separada por uma linha sutil. */
.ad-header-panel .panel-head {
  align-items: center;
}

.ad-header-panel .panel-head .button-row {
  margin-top: 0;
  align-items: center;
}

/* Botoes primarios (Salvar/Publicar/Republicar/Sincronizar) do header do
   anuncio -- pedido do usuario, 2026-07-12: tirar do menu "..." e deixar
   sempre visiveis, alinhados a esquerda (abaixo do titulo/badges), em vez
   de escondidos dentro do dropdown de "mais acoes". */
.ad-header-panel .ad-header-actions {
  margin-top: 0.85rem;
  margin-bottom: 0;
}

.ad-header-panel > p {
  margin: 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
  font-size: 0.85rem;
}

.validation-ok {
  border: 1px solid rgba(30, 107, 49, 0.35);
  background: var(--success-bg);
}

.validation-ok h3 { color: var(--success-text); }

/* Resumo de "pontos de atencao" do anuncio (compute_ad_attention_flags) --
   pedido do usuario (2026-07-12): sinalizar sempre que o anuncio precisa de
   melhora, com o motivo. So aparece quando ha algum flag salvo (calculado na
   validacao). */
.attention-summary-panel {
  border: 1px solid rgba(239, 108, 0, 0.35);
  background: var(--warning-bg);
}
.attention-summary-panel .panel-head { margin-bottom: 0.6rem; }
.attention-summary-panel h3 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--warning-text);
}
.attention-summary-list {
  list-style: none;
  margin: 0 0 0.6rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.attention-summary-item {
  background: var(--surface-solid);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.8rem;
  border-left: 3px solid var(--warning-text);
}
.attention-summary-item.severity-error { border-left-color: var(--error-text); }
/* `info` = estado normal/transitorio que o vendedor so' precisa SABER (ex.:
   anuncio em auditoria no TikTok Shop) -- nao e' pendencia, entao nao pode
   herdar o laranja de aviso do padrao. */
.attention-summary-item.severity-info { border-left-color: var(--info-text); }
.attention-summary-label {
  display: block;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text);
}
.attention-summary-hint {
  display: block;
  font-size: 0.82rem;
  color: var(--text-muted);
  margin-top: 0.15rem;
}

/* Metricas do anuncio (visitas/vendidos/status real no ML) -- pedido do
   usuario (2026-07-12), mostradas como chips logo abaixo do SKU no
   cabecalho do anuncio, so quando ja existe meli_item_id. */
.ad-metrics-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.ad-metric-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  background: var(--neutral-soft);
  color: var(--text-muted);
  text-decoration: none;
}
a.ad-metric-chip:hover { filter: brightness(0.96); }
.ad-metric-chip.severity-ok { background: var(--success-bg); color: var(--success-text); }
.ad-metric-chip.severity-error { background: var(--error-bg); color: var(--error-text); }

/* Loja (conta do Mercado Livre) dona do anuncio, na linha de SKU do
   cabecalho -- pedido do usuario, 2026-07-12: "mostrar no header qual loja
   esse anuncio pertence" (multiplas contas ML cadastradas). Mesmo espirito
   visual dos badges de tipo de anuncio (.listing-type-badge), pill pequena
   com a cor da marca pra se destacar sem competir com o resto da linha. */
.store-owner-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-weight: 600;
  font-size: 0.82rem;
}

.ml-item-id-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--neutral-soft, #eef1f4);
  color: var(--text);
  font-weight: 600;
  font-size: 0.82rem;
  font-family: monospace;
  letter-spacing: 0.01em;
}

.ml-item-id-chip-empty {
  font-family: inherit;
  font-weight: 500;
  color: var(--text-muted);
}

.ml-item-id-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: transparent;
  color: inherit;
  box-shadow: none;
  cursor: pointer;
}

.ml-item-id-copy:hover {
  color: var(--brand-dark);
  background: transparent;
  box-shadow: none;
  transform: none;
}

/* Resumo de valores do anuncio (pedido do usuario, 2026-07-12) -- painel
   full-width acima da secao de fotos, espelho somente-leitura de tudo que ja
   e calculado nas duas abas (custo/margem/encargos/imposto/valor do produto
   no Cadastro de Produto; preco/comissao/frete/NF/venda total/lucro no
   Anuncio). Grid de cards pequenos, mesmo espirito visual dos .stats do
   dashboard -- .value-summary-highlight destaca os 3 totais (valor do
   produto, venda total, lucro) com fundo levemente tintado de --brand;
   lucro tambem ganha severity-error (vermelho) quando fica negativo, via JS
   (syncValueSummaryPanel). */
.value-summary-panel .panel-head { margin-bottom: 0.6rem; }
.value-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.6rem;
}
.value-summary-item {
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.7rem;
}
.value-summary-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 0.15rem;
}
.value-summary-value {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}
.value-summary-item.value-summary-highlight {
  background: var(--brand-soft);
  border-color: var(--brand);
}
.value-summary-item.value-summary-highlight .value-summary-value { color: var(--brand-dark); }
.value-summary-item.severity-error { background: var(--error-bg); border-color: var(--error-text); }
.value-summary-item.severity-error .value-summary-value { color: var(--error-text); }
.value-summary-item.severity-ok.value-summary-highlight { background: var(--success-bg); border-color: var(--success-text); }
.value-summary-item.severity-ok.value-summary-highlight .value-summary-value { color: var(--success-text); }

/* Versao compacta do resumo de valores -- pedido do usuario pra ficar DENTRO
   do card de fotos (antes da grade de fotos), so com lucro/valor de
   venda/comissao/frete, em vez do painel full-width com os 11 campos de
   antes. Reusa .value-summary-item/label/value/highlight/severity-* (mesmo
   componente visual), só troca o grid pai por 2 colunas estreitas pra caber
   na largura da coluna de fotos (260-320px). */
.value-summary-compact {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin-bottom: 0.9rem;
}
.value-summary-compact .value-summary-item { padding: 0.4rem 0.55rem; }
.value-summary-compact .value-summary-value { font-size: 0.88rem; }

/* Qualidade do anuncio -- gauges em semicirculo (pedido do usuario,
   2026-07-21: replicar o indicador "Qualidade do anuncio"/"Experiencia de
   compra" que o proprio Mercado Livre mostra pro vendedor, ao lado do
   "Produto base deste anuncio"). .ad-base-product-row vira o banner do
   produto base + o widget de qualidade lado a lado; em telas estreitas
   empilha (media query no fim do arquivo). */
.ad-base-product-row {
  display: flex;
  align-items: stretch;
  gap: 0.85rem;
  margin: 0 0 0.85rem;
  flex-wrap: wrap;
}
.ad-base-product-banner {
  flex: 1 1 260px;
  margin: 0 !important;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

/* Campo com dropdown de busca (2026-07-31) -- usado no "Produto base", que
   deixou de ser um banner solto e virou campo padrao ao lado do titulo. O
   menu e' absoluto pra nao empurrar as celulas vizinhas da grade quando
   abre (regra permanente do projeto: nada que mude altura dentro de uma
   celula de .form-grid.compact-3col). */
.searchable-select {
  position: relative;
  width: 100%;
}

.searchable-select > input {
  width: 100%;
}

.searchable-select-menu {
  display: none;
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface-solid);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}

.searchable-select-menu.open { display: block; }

.searchable-select-option {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  width: 100%;
  min-height: 0;
  padding: 0.45rem 0.7rem;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  text-align: left;
  color: var(--text);
  font-weight: 500;
  cursor: pointer;
}

.searchable-select-option:hover {
  background: var(--brand-soft);
  border-color: transparent;
  color: var(--text);
  transform: none;
  box-shadow: none;
}

.searchable-select-option-title {
  font-size: 0.85rem;
  font-weight: 600;
}

.searchable-select-option-sub {
  font-size: 0.75rem;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.ad-quality-widget {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.5rem 0.9rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.quality-gauge-group { display: flex; gap: 0.75rem; }
.quality-gauge {
  position: relative;
  width: 108px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.quality-gauge-svg { width: 108px; height: 62px; overflow: visible; }
.quality-gauge-track {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 9;
  stroke-linecap: round;
}
.quality-gauge-fill {
  fill: none;
  stroke: var(--brand);
  stroke-width: 9;
  stroke-linecap: round;
  stroke-dasharray: 157.08;
  stroke-dashoffset: 157.08;
  transition: stroke-dashoffset var(--dur-slow) var(--ease-out);
}
.quality-gauge-fill-experience { stroke: var(--info-text); }
.quality-gauge-value {
  position: absolute;
  top: 30px;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
}
.quality-gauge-value strong { font-size: 1.15rem; color: var(--text); }
.quality-gauge-value span { font-size: 0.68rem; color: var(--text-muted); font-weight: 600; }
.quality-gauge-label { font-size: 0.7rem; color: var(--text-muted); margin-top: 0.15rem; text-align: center; }
.quality-gauge-hint { font-size: 0.62rem; color: var(--text-muted); text-align: center; }
.ad-quality-widget > .button-link { font-size: 0.78rem; margin-top: 0.1rem; }
@media (max-width: 720px) {
  .ad-quality-widget { width: 100%; }
}

.validation-error {
  border: 1px solid rgba(163, 49, 42, 0.3);
  background: var(--error-bg);
}

.validation-error h3 { color: var(--error-text); }

.validation-issues {
  margin: 0.8rem 0 0;
  padding-left: 0;
  list-style: none;
  display: grid;
  gap: 0.6rem;
  font-size: 0.85rem;
  color: var(--text);
}

.validation-issues li {
  display: grid;
  gap: 0.2rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--error-text);
  background: rgba(163, 49, 42, 0.06);
}

.validation-issues li.validation-issue-info {
  border-left-color: var(--text-faint);
  background: var(--bg-alt);
}

.validation-issue-badge {
  display: inline-block;
  width: fit-content;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  background: var(--error-text);
  color: #fff;
}

.validation-issue-info .validation-issue-badge {
  background: var(--text-faint);
}

.validation-issue-message {
  font-weight: 600;
  color: var(--text);
}

.validation-issue-hint {
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* Popup de validacao (pontos de correcao persistentes) e o icone/badge no
   header que sinaliza pendencia. */

.icon-btn.has-badge, .secondary-dark.has-badge { position: relative; }

.icon-btn-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--error-text);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

.validation-corrections-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.7rem;
  max-height: 55vh;
  overflow-y: auto;
}

.ad-change-log-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.6rem;
  max-height: 55vh;
  overflow-y: auto;
}
.ad-change-log-item {
  padding: 0.6rem 0.85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  background: var(--bg-alt);
}
.ad-change-log-item.ad-change-log-status-error {
  border-left-color: var(--error-text);
}
.ad-change-log-item.ad-change-log-status-skip {
  border-left-color: var(--text-faint);
}
.ad-change-log-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.ad-change-log-field {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text);
}
.ad-change-log-diff {
  margin: 0.3rem 0 0;
  font-size: 0.82rem;
  color: var(--text-muted);
  word-break: break-word;
}
.ad-change-log-old {
  text-decoration: line-through;
  color: var(--text-faint);
}
.ad-change-log-new {
  color: var(--brand-dark);
  font-weight: 600;
}

.validation-correction-item {
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--error-text);
  background: rgba(163, 49, 42, 0.06);
}

.validation-correction-item.severity-info {
  border-left-color: var(--text-faint);
  background: var(--bg-alt);
}

.validation-correction-item.status-corrigido {
  border-left-color: var(--success-text);
  background: var(--success-bg);
  opacity: 0.85;
}

.validation-correction-head {
  display: grid;
  gap: 0.25rem;
  margin-bottom: 0.35rem;
}

.validation-correction-toggle {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-muted);
  margin-top: 0.5rem;
  cursor: pointer;
}

.validation-correction-toggle input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--brand);
  cursor: pointer;
}

.validation-error details {
  margin-top: 0.9rem;
}

.validation-error summary {
  cursor: pointer;
  font-weight: 600;
}

.validation-error pre {
  margin-top: 0.6rem;
}

/* Compatibilidade em cascata (catalogo Mercado Livre) */

.compat-builder-selects {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.9rem;
}

.compat-builder-select {
  padding: 0.6rem 0.7rem;
  font-size: 0.85rem;
  min-width: 160px;
  flex: 1 1 160px;
}

/* Linha "+" de adicionar veiculo agora e uma <tr> real, com uma <td> por
   coluna do dominio (marca/modelo/ano/...) alinhada ao cabecalho da tabela
   -- cada select nasce vazio na sua celula e so aparece quando a coluna
   anterior ja foi escolhida (dependencia em cascata visualmente clara). */
.compat-builder-cell {
  padding: 0.4rem 0.5rem;
  vertical-align: middle;
  background: var(--bg-alt);
}

.compat-builder-cell .compat-builder-select {
  width: 100%;
  min-width: 0;
}

.compat-chip-list {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.compat-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.5rem 0.45rem 0.9rem;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-size: 0.82rem;
  font-weight: 600;
}

.compat-chip form { margin: 0; }

.compat-chip .compat-remove {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 0.6rem;
}

/* Compatibilidade em formato de tabela (visual tipo planilha) */

/* Cabecalho da secao (2026-07-13): titulo a esquerda, os 3 botoes de acao
   (IA / colunas / salvar) agrupados a direita junto com a seta de
   expandir/recolher -- os botoes de acao (nao a seta) so aparecem quando a
   secao esta aberta, via a regra :not([open]) abaixo. Removido o resumo
   "aplicacao cadastrada" (pedido explicito do usuario, virou redundante com
   a propria tabela). */
.panel-head-right {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.compat-head-actions {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.collapsible-panel:not([open]) .compat-head-actions {
  display: none;
}

#compat-save-status {
  margin: 0 0 0.6rem;
}

#compat-save-status:empty {
  display: none;
}

/* Header/corpo/builder da tabela de compatibilidade agora SEMPRE usam a
   MESMA lista de colunas (dominio completo do veiculo, ver
   sort_vehicle_domain_attributes em app.py) -- antes o header/corpo usavam
   so as colunas "com dado" e o builder do "+" usava o dominio completo,
   podendo ter contagens diferentes e desalinhar o builder por baixo do
   cabecalho errado. Colunas "principais" (marca/modelo/ano/versao,
   .compat-col-core) ficam sempre visiveis; as demais (.compat-col-extra)
   ficam escondidas por padrao -- JS (applyCompatColumnVisibility, no fim do
   <script> do template) revela as que ja tem dado cadastrado ou que o
   usuario escolheu no seletor "Colunas" (preferencia salva em localStorage
   por anuncio). Scroll horizontal em vez de deixar a tabela espremer o
   layout quando muitas colunas estao visiveis. */
.compat-table-scroll {
  overflow-x: auto;
  margin-top: 0.75rem;
  /* Pedido do usuario, 2026-07-19: limitar a altura da lista de veiculos
     compativeis e usar scroll vertical alem do horizontal ja existente
     (mesmo container, os dois scrolls convivem sem conflito). */
  max-height: 560px;
  overflow-y: auto;
}

.compat-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 0.6rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.compat-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
}

.compat-table thead th {
  text-align: left;
  padding: 0.5rem 0.75rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  border-bottom: 1px solid var(--border);
}

.compat-table tbody td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--border);
}

.compat-table tbody tr:last-child td { border-bottom: none; }

/* Bug real corrigido 2026-07-12 ("dropdown muito espremido"): as celulas de
   atributo de veiculo nao tinham piso de largura nenhum, e o select dentro
   delas usava min-width:0 -- com table-layout:auto e muitas colunas, o
   navegador dividia a largura do painel igualzinho entre todas, sobrando
   pouquissimo espaco por coluna. Um min-width por celula de atributo forca
   o navegador a dar espaco de verdade (e a estourar pro scroll horizontal
   do .compat-table-scroll quando nao cabe, em vez de espremer). Nao aplica
   na coluna de acoes (sem data-attr-id), que continua estreita de proposito. */
.compat-table td[data-attr-id],
.compat-table th[data-attr-id] {
  min-width: 160px;
}

.compat-col-extra {
  display: none;
}

/* Bug real corrigido 2026-07-27 ("botoes de editar/excluir saindo da
   lista"): a largura fixa de 70px do <td> nao dava espaco de verdade pros
   dois botoes (26px + gap + 34px + padding da celula > 70px) -- o
   navegador desenhava os botoes por cima/fora da borda da tabela em vez de
   redimensionar a celula. Tirado o width fixo (a celula agora cresce
   naturalmente pro conteudo, via white-space:nowrap) e os botoes viraram
   um wrapper flex proprio (.compat-actions-inner, nunca display:flex
   direto no <td> -- mesma regra ja documentada nas listas de
   produtos/anuncios, evita perder a sincronia de altura entre colunas). */
.compat-table-actions { text-align: right; white-space: nowrap; }
.compat-table-actions form { margin: 0; display: inline-flex; }
.compat-actions-inner {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.compat-actions-inner .compat-edit.icon-btn {
  width: 26px;
  height: 26px;
}

/* Popup "Editar veiculo compativel" (2026-07-20) -- cascata sequencial de
   selects, um por coluna do dominio (marca -> modelo -> ano -> ...),
   carregados um de cada vez conforme o anterior e escolhido. */
.compat-edit-selects {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0.75rem 0;
}
.compat-edit-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.compat-edit-row label {
  flex: 0 0 110px;
  font-weight: 600;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.compat-edit-row select {
  flex: 1;
}

/* "..." no cabecalho da ultima coluna da tabela (2026-07-14, pedido
   explicito) -- mesmo lugar onde ja fica o botao de remover linha por
   linha, so o CABECALHO ganha esse botao pra abrir o popup de colunas sem
   precisar do icone separado no cabecalho do painel (que continua existindo
   tambem, redundante de proposito -- fica acessivel mesmo com a tabela
   rolada bem pra direita). */
.compat-col-configure-btn {
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text-muted);
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 0.2rem 0.5rem;
  height: auto;
}
.compat-col-configure-btn:hover { color: var(--brand-dark); background: var(--brand-soft); }

/* Popup de escolher colunas (2026-07-13): virou modal do sistema
   (#compat-columns-modal, mesmo .modal-overlay/.modal-box de todo o resto)
   em vez do dropdown posicionado a mao que existia antes -- so falta o
   estilo da lista de checkboxes em si. */
.compat-columns-modal-list {
  max-height: 320px;
  overflow-y: auto;
  display: grid;
  gap: 0.15rem;
  margin: 0.75rem 0 1rem;
}

.compat-columns-modal-list .ai-field-toggle { padding: 0.3rem 0; }

/* Checkboxes de menu_permissions/allowed_company_ids nos popups de usuario
   (settings.html e organizations.html, 2026-07-24) -- mesmo padrao de lista
   de checkboxes ja usado no popup de colunas de compatibilidade acima, so em
   grid responsivo (2 colunas em telas largas) por ter mais itens. Classe
   generica (.checkbox-grid) ja referenciada em organizations.html sem CSS
   proprio -- definida aqui pra valer nos dois lugares. */
.checkbox-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.15rem;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  margin-top: 0.35rem;
}
.checkbox-grid .ai-field-toggle { padding: 0.25rem 0; }
/* "Menus visiveis" do popup de usuario: as caixinhas sao agrupadas igual ao
   menu lateral, entao a moldura/rolagem tem que ficar no container de fora --
   cada .checkbox-grid com a sua daria 6 caixas rolaveis empilhadas. */
.menu-permission-groups {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.35rem 0.75rem 0.6rem;
  margin-top: 0.35rem;
}
.checkbox-grid.checkbox-grid-plain {
  max-height: none;
  overflow: visible;
  border: none;
  border-radius: 0;
  padding: 0;
  margin-top: 0;
}
.menu-permission-group-title {
  margin: 0.55rem 0 0.1rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.menu-permission-groups > .menu-permission-group-title:first-child { margin-top: 0.15rem; }

/* Dropdown de multi-selecao por checkbox (Marca/Grupo dos filtros de
   Anuncios e Produtos, pedido do usuario 2026-08-03: "manter como input de
   dropdown, mas permitir selecionar mais de um") -- o gatilho continua com a
   MESMA altura/borda/fundo de um <select> normal (nunca muda a cara de
   "input" que ja existia); so' o painel que abre no clique tem checkbox em
   vez de opcao unica. Ver toggleMultiSelectDropdown()/
   updateMultiSelectTriggerLabel() em base.html. */
.multi-select-dropdown {
  position: relative;
}
.multi-select-trigger {
  width: 100%;
  height: var(--field-h);
  padding: 0 0.9rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-alt);
  color: var(--text);
  font-weight: 500;
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  cursor: pointer;
  text-align: left;
  transition: border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}
.multi-select-dropdown.open .multi-select-trigger {
  border-color: var(--brand);
  background: var(--surface-solid);
  box-shadow: 0 0 0 3px var(--brand-glow);
}
.multi-select-trigger-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.multi-select-trigger svg {
  flex: 0 0 auto;
  color: var(--text-faint);
  transition: transform var(--dur-fast) var(--ease-out);
}
.multi-select-dropdown.open .multi-select-trigger svg { transform: rotate(180deg); }
.multi-select-panel {
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 0.4rem);
  min-width: 100%;
  max-height: 260px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 50;
  padding: 0.4rem 0.6rem;
}
/* O gatilho e' um <button>, entao a regra global `button:hover` (que pinta de
   var(--brand-dark) com texto branco) vencia por especificidade tudo que
   .multi-select-trigger declara sem repetir no hover -- ele ficava AZUL ao
   passar o mouse, destoando dos <select> vizinhos. Mesma armadilha ja
   corrigida em .ad-tab-btn/.copy-icon-btn/.stat-cell: estado que a regra
   global toca precisa ser redeclarado aqui. */
.multi-select-trigger:hover,
.multi-select-trigger:focus,
.multi-select-trigger:focus-visible {
  background: var(--surface-solid);
  border-color: var(--brand);
  color: var(--text);
  outline: none;
}
.multi-select-dropdown.open .multi-select-panel { display: grid; gap: 0.15rem; }
.multi-select-panel .ai-field-toggle { padding: 0.25rem 0; white-space: normal; }
.multi-select-panel-empty {
  font-size: 0.8rem;
  color: var(--text-faint);
  padding: 0.3rem 0;
}
/* Cabecalho de grupo dentro do painel (equivale ao <optgroup> do <select> que
   o componente substituiu -- filtro de status em Vendas separa Mercado Livre
   dos demais canais). */
.multi-select-panel-group {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  padding: 0.45rem 0 0.15rem;
  border-top: 1px solid var(--border);
  margin-top: 0.2rem;
}
.multi-select-panel-group:first-child { border-top: none; margin-top: 0; padding-top: 0.1rem; }
/* Na toolbar o dropdown fica solto num flex (nao numa celula de form-grid como
   nos popups de filtro), entao sem largura minima ele ENCOLHERIA/CRESCERIA
   conforme o rotulo ("Todas as plataformas" -> "2 selecionadas"), empurrando
   os botoes ao lado a cada clique. */
.toolbar-multi-select { min-width: 190px; }
@media (max-width: 620px) {
  .toolbar-multi-select { min-width: 0; flex: 1 1 100%; }
}

/* Lista de Vendas: numero do pedido em cima, tag da plataforma (menor) + data
   embaixo -- pedido do usuario, 2026-08-05. A tag herda .platform-tag; aqui so
   encolhe, sem tocar nas cores da marca (regra permanente: tag de plataforma
   sempre com as cores dela). */
.venda-pedido-num { font-weight: 600; white-space: nowrap; }
.venda-pedido-sub {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.2rem;
  font-size: 0.72rem;
  color: var(--text-faint);
  white-space: nowrap;
}
.venda-pedido-sub .platform-tag {
  padding: 0.08rem 0.3rem;
  font-size: 0.58rem;
  border-radius: 4px;
}
/* Valor da venda: reusa .stat-cell/.stat-popover (colunas de estatistica da
   lista de Produtos) so' pra ganhar o popover de hover -- aqui o conteudo e'
   texto normal, nao um badge de contagem, entao cor/peso voltam ao padrao. */
.venda-valor-cell { padding: 0; }
.venda-valor-total { color: var(--text); font-weight: 600; font-size: 0.85rem; }
.venda-lucro {
  margin-top: 0.15rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--success-text);
  white-space: nowrap;
}
.venda-lucro.negativo { color: var(--error-text); }
.venda-lucro.sem-dado { color: var(--text-faint); font-weight: 500; }

/* Caminho oficial do ML pra "veiculo nao existe no catalogo" (excecao de
   compatibilidade) -- caixa discreta abaixo da tabela, so expande o form
   quando o vendedor clica (ou quando o builder detecta um passo sem
   opcoes). */
.compat-exception-box {
  margin-top: 0.75rem;
}

.compat-exception-box #compat-exception-form {
  margin-top: 0.5rem;
  padding: 0.75rem 0.9rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.compat-exception-box textarea {
  width: 100%;
  resize: vertical;
}

/* Popup "Adicionar veiculos compativeis" (reescrito 2026-07-13): tabela com
   cabecalho clicavel por coluna -- clicar abre um popover com checkboxes de
   multi-selecao (paginado de 20 em 20, com busca) -- ver openCompatManualModal
   / openCompatManualFilter no <script>. */
.compat-manual-table-scroll {
  max-height: 680px;
  overflow: auto;
  margin: 0.75rem 0 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* Pedido do usuario (2026-08-10, repetido 2x -- "deixar mais largo tbm"
   depois de ja ter ido pra 1200px/92vh, o maior tier fixo que existia no
   sistema ate aqui, #sync-modal): 1200px ainda nao era largo o bastante.
   Trocado de valor FIXO pra `min(..., vw)` -- usa a tela disponivel de
   verdade em vez de tentar adivinhar mais um numero fixo que talvez ainda
   nao seja "largo o suficiente" numa proxima rodada. `min(1600px, 95vw)`:
   nunca encosta na borda da tela (5vw de folga, some com o padding proprio
   de 1.5rem do .modal-overlay) e trava em 1600px pra nao esticar de forma
   ridicula numa tela ultrawide/4K. O max-height da tabela por dentro (acima)
   ja tinha subido junto na rodada anterior -- continua valendo. */
#compat-manual-modal .modal-box {
  max-width: min(1600px, 95vw);
  max-height: 92vh;
}

/* Pedido do usuario (2026-08-10): o "Recomeçar" (limpa filtro de coluna)
   saiu de dentro do cabecalho da tabela e passou a viver aqui, junto de
   Cancelar/Salvar -- os 3 agrupados e alinhados a direita, mesmo padrao ja
   usado em .plan-form-footer .button-row (escopado por seletor, nunca
   mexendo no .button-row global -- outros popups continuam left-aligned). */
#compat-manual-modal .button-row { justify-content: flex-end; }

.compat-manual-table-scroll table.compat-table { margin: 0; }

.compat-manual-th-cell { padding: 0.3rem; white-space: nowrap; }

.compat-manual-th-btn {
  background: none;
  border: 1px dashed var(--border);
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.35rem 0.55rem;
  border-radius: var(--radius-sm);
  box-shadow: none;
  height: auto;
  white-space: nowrap;
}

.compat-manual-th-btn.applied {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-color: var(--brand-soft);
}

.compat-manual-th-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Popup do filtro por coluna (Marca/Modelo/Ano...) -- overlay proprio por
   cima do popup de adicionar veiculo (z-index maior), fecha/aplica e "volta"
   sozinho pro popup de baixo sem nunca empurrar o layout dele. Largura/
   altura aumentadas junto com o popup de baixo (pedido do usuario,
   2026-08-10) -- 460px era o tier PADRAO (o menor do sistema), e uma lista
   de ~100 marcas com busca+checkbox pedia mais espaco de sobra; a grade
   por dentro (.compat-manual-filter-options) cresceu junto, senao so' o
   contorno do popup ficaria maior sem nenhuma linha a mais visivel. */
#compat-manual-filter-modal.modal-overlay { z-index: 65; }
#compat-manual-filter-modal .modal-box { max-width: 720px; max-height: 88vh; }
#compat-manual-filter-modal input[type="text"] { margin-bottom: 0.5rem; }

.compat-manual-filter-options {
  max-height: 480px;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.1rem 0.6rem;
  margin: 0.5rem 0;
}

.compat-manual-filter-options .ai-field-toggle { padding: 0.25rem 0; }

.compat-manual-filter-pager {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* Diferente do filtro por coluna (mostra tudo de uma vez, so busca) -- a
   lista de veiculos gerada e' que pagina de 20 em 20 quando passa disso
   (pedido explicito, 2026-07-13). */
.compat-manual-results-pager {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: -0.5rem 0 1rem;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.compat-add-plus {
  background: none;
  border: 1px dashed var(--border);
  color: var(--text-muted);
  width: 100%;
  text-align: left;
  padding: 0.55rem 0.75rem;
  border-radius: var(--radius-sm);
  font-weight: 600;
  box-shadow: none;
}

.compat-add-plus:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-color: var(--brand-soft);
  transform: none;
  box-shadow: none;
}

/* Compatibilidade -- aba "Cascata" (reescrita em 2026-08-14): explorador em
   COLUNAS, o mesmo desenho do explorador de categoria (.category-explorer),
   com uma diferenca que a categoria nao tem -- cada coluna aqui e'
   MULTISSELECAO (marca -> varios modelos -> varios anos -> ...). Alternativa
   ao builder em grade (.compat-manual-* acima), que continua existindo sem
   nenhuma mudanca de comportamento.
   As regras de tela pequena deste bloco ficam no FIM do arquivo (junto das
   demais responsivas) -- regra de mobile no meio do arquivo perde por
   cascata, sem erro nenhum. */
.compat-cascade-explorer {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  margin: 0.6rem 0 0.9rem;
}

.compat-cascade-columns {
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  min-height: 320px;
  max-height: 400px;
  box-shadow: inset 0 1px 2px rgba(33, 37, 41, 0.04);
}

.compat-cascade-col {
  flex: 0 0 236px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--border);
}
.compat-cascade-col:last-child { border-right: none; }

.compat-cascade-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  padding: 0.5rem 0.65rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.compat-cascade-col-title {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compat-cascade-col-count {
  flex: 0 0 auto;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--text-faint);
  background: var(--neutral-soft);
  border-radius: 999px;
  padding: 0.1rem 0.42rem;
}
.compat-cascade-col-count.is-on {
  background: var(--brand);
  color: #fff;
}

/* width:auto e' obrigatorio aqui: o `input` global do sistema e' width:100%,
   que resolve contra a largura da COLUNA -- somado a margem lateral, o campo
   estourava a coluna em 16px (medido a 414px). Com auto + o stretch do flex
   da coluna, ele ocupa exatamente a largura menos as margens. */
/* flex: 0 0 auto e' obrigatorio: a coluna e' um flex container e a lista de
   itens transborda, entao o campo (flex item com shrink 1 por padrao) era
   ESPREMIDO -- a altura declarada aqui nunca valia de verdade (medido: 30.8px
   com height: 2.25rem). */
.compat-cascade-col-search {
  width: auto;
  flex: 0 0 auto;
  margin: 0.5rem 0.5rem 0.15rem;
  height: 2.25rem;
  font-size: 0.85rem;
  padding: 0 0.6rem;
}

.compat-cascade-col-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.35rem;
}

.compat-cascade-col-msg {
  padding: 0.6rem;
  margin: 0;
  font-size: 0.8rem;
  color: var(--text-faint);
}

/* Item de coluna: e' um <button>, entao precisa redeclarar caixa/altura/
   hover/focus -- o `button` global venceria por especificidade de elemento
   (mesma armadilha ja documentada em .category-explorer-item). */
.compat-cascade-item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  text-align: left;
  padding: 0.45rem 0.55rem;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  box-shadow: none;
  height: auto;
  justify-content: flex-start;
  transform: none;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.compat-cascade-item-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compat-cascade-chevron { flex: 0 0 auto; color: var(--text-faint); }

/* Quadradinho de multissselecao: clicar NELE soma/tira da selecao da coluna;
   clicar no resto da linha troca a selecao e abre o proximo nivel. */
.compat-cascade-check {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border: 1.5px solid var(--border-strong);
  border-radius: 5px;
  background: var(--surface);
  color: transparent;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.compat-cascade-check svg { width: 11px; height: 11px; }

.compat-cascade-item:hover,
.compat-cascade-item:focus,
.compat-cascade-item:focus-visible {
  background: var(--brand-soft);
  color: var(--brand-dark);
  box-shadow: none;
  transform: none;
  outline: none;
}
.compat-cascade-item:focus-visible { box-shadow: 0 0 0 3px var(--brand-glow); }
.compat-cascade-item:hover .compat-cascade-chevron { color: var(--brand-dark); }
.compat-cascade-item:hover .compat-cascade-check { border-color: var(--brand); }

.compat-cascade-item.active {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
}
.compat-cascade-item.active:hover { background: var(--brand-dark); color: #fff; }
.compat-cascade-item.active .compat-cascade-chevron,
.compat-cascade-item.active:hover .compat-cascade-chevron { color: #fff; }
.compat-cascade-item.active .compat-cascade-check {
  background: #fff;
  border-color: #fff;
  color: var(--brand);
}

/* Barra de resumo: caminho escolhido a esquerda, acoes agrupadas a direita
   (padrao de rodape do sistema -- nunca botao solto no meio do texto). */
.compat-cascade-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.65rem 0.9rem;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
}

.compat-cascade-bar-info {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  min-width: 0;
}

.compat-cascade-breadcrumb {
  color: var(--brand-dark);
  font-size: 0.84rem;
  font-weight: 600;
  min-width: 0;
  overflow-wrap: break-word;
}

.compat-cascade-combo-badge {
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 700;
  color: #fff;
  background: var(--brand);
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
}

.compat-cascade-bar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 0 0 auto;
}

.compat-cascade-pending-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin: 0.2rem 0 0.5rem;
}

.compat-cascade-pending-title {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
}

.compat-cascade-pending-status {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.78rem;
  color: var(--success-text);
}

.compat-cascade-pending-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 0.7rem;
  max-height: 168px;
  overflow-y: auto;
}

.compat-cascade-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  max-width: 100%;
  padding: 0.3rem 0.4rem 0.3rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 0.8rem;
  box-shadow: var(--shadow-sm);
}

.compat-cascade-chip-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compat-cascade-chip-remove {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--neutral-soft);
  color: var(--text-muted);
  font-size: 0.68rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: none;
  transform: none;
}
.compat-cascade-chip-remove:hover {
  background: var(--danger);
  color: #fff;
  box-shadow: none;
  transform: none;
}

.compat-cascade-pending-empty {
  flex: 1 1 100%;
  padding: 0.9rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  text-align: center;
  color: var(--text-faint);
  font-size: 0.82rem;
  margin: 0;
}

/* Atributos: subtitulos e tooltip */

.attributes-subhead {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  margin: 1.1rem 0 0.7rem;
}

.attributes-subhead:first-child { margin-top: 0; }

.attributes-group-label {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--brand-dark);
  background: var(--brand-soft);
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  margin: 0.6rem 0 0.5rem;
}

.attr-label-row {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.attr-tooltip {
  display: inline-flex;
  color: var(--text-faint);
  cursor: help;
}

.attr-tooltip svg { width: 13px; height: 13px; }

.attr-tooltip:hover, .attr-tooltip:focus { color: var(--brand-dark); outline: none; }

.attr-input-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.attr-input-row input[type="text"] { flex: 1; min-width: 0; }
.attr-input-row input[type="text"]:disabled { opacity: 0.45; background: var(--bg-alt); }

.attr-na-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
}

.attr-na-toggle input[type="checkbox"] { width: 14px; height: 14px; margin: 0; }

/* Secoes colapsaveis (caracteristicas da categoria, compatibilidade) --
   carregam fechadas por padrao; clique no cabecalho abre/fecha. */
.collapsible-panel > summary.panel-head {
  cursor: pointer;
  list-style: none;
  margin-bottom: 0;
}

.collapsible-panel > summary.panel-head::-webkit-details-marker { display: none; }
.collapsible-panel > summary.panel-head::marker { content: ""; }

.collapse-chevron {
  flex: none;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}

.collapsible-panel[open] > summary .collapse-chevron { transform: rotate(90deg); }

.collapsible-body { margin-top: 1rem; }

/* Campo com botao de acao (descricao + IA) */

.field-with-button {
  display: grid;
  gap: 0.4rem;
  /* Sem isso a celula ESTICA pra altura da linha do grid (definida pela
     celula mais alta) e a sobra vai toda pro cabecalho, que incha e empurra
     o input pra baixo -- desalinhando os inputs vizinhos. Ver a mesma regra
     em .form-grid label logo abaixo. */
  align-content: start;
}

/* Cabecalho de celula com a MESMA altura, tenha ou nao botao de acao: com o
   botao ele mede 30px (altura do .icon-btn), sem o botao mediria ~19px (so'
   o texto) -- e duas celulas vizinhas com cabecalho de altura diferente
   deixam os inputs em alturas diferentes. Travar aqui resolve pra qualquer
   combinacao de celulas na mesma linha, sem precisar ajustar caso a caso.
   REGRA: campo novo com botao de IA/acao usa .field-with-button; campo
   simples usa <label> -- os dois agora alinham entre si. */
.field-with-button-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  min-height: 30px;
}

.field-with-button-head label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}

.compat-domain-form {
  max-width: 260px;
  margin-bottom: 1rem;
}

/* Toast flutuante nao-bloqueante (fila de geracao com IA) */

.corner-toast {
  display: none;
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  width: 300px;
  max-height: min(60vh, 380px);
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 70;
  flex-direction: column;
  overflow: hidden;
}

/* `flex` (nao `block`): o cabecalho fica sempre visivel e so' o corpo
   rola quando o conteudo cresce -- e' o que impede o toast de "estourar"
   pra cima do topo da tela em telas baixas (2026-08-16). */
.corner-toast.open { display: flex; }

.corner-toast-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--dark);
  padding: 0.85rem 0.95rem 0.6rem;
}

.corner-toast.done .corner-toast-head { color: var(--success-text); }
.corner-toast.error .corner-toast-head { color: var(--error-text); }
.corner-toast.done.error .corner-toast-head { color: var(--warning-text); }

/* Icone de estado: spinner enquanto roda, marca de sucesso ao concluir,
   alerta quando ha' falha (total ou parcial) -- troca sozinho junto com as
   classes que o JS ja' alternava (open/done/error), sem logica nova. */
.corner-toast-icon {
  position: relative;
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.corner-toast-spinner {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid var(--brand-soft);
  border-top-color: var(--brand);
  animation: loading-spin 0.8s linear infinite;
}

.corner-toast-icon-done,
.corner-toast-icon-error {
  display: none;
  width: 17px;
  height: 17px;
}

.corner-toast.done .corner-toast-spinner,
.corner-toast.error .corner-toast-spinner { display: none; }

.corner-toast.done:not(.error) .corner-toast-icon-done { display: block; color: var(--success-text); }
.corner-toast.error .corner-toast-icon-error { display: block; color: var(--error-text); }
.corner-toast.done.error .corner-toast-icon-error { color: var(--warning-text); }

.corner-toast-title {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.corner-toast-close {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  background: var(--bg-alt);
  color: var(--text-muted);
  box-shadow: none;
  padding: 0;
  font-size: 0.65rem;
  line-height: 1;
}

.corner-toast-close:hover { background: var(--brand-soft); color: var(--brand-dark); transform: none; box-shadow: none; }

.corner-toast-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 0.95rem 0.9rem;
}

.corner-toast-status {
  margin: 0.5rem 0 0;
  font-size: 0.78rem;
  color: var(--text-muted);
  overflow-wrap: break-word;
}

/* Rodape do "Reportar problema" -- sempre ABAIXO de toda a mensagem/status,
   nunca flutuando ao lado (mesmo padrao do card de flash). */
.corner-toast-footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  padding: 0.55rem 0.95rem 0.8rem;
  border-top: 1px solid var(--border);
}

.corner-toast-body::-webkit-scrollbar { width: 6px; }

@media (max-width: 620px) {
  /* bottom acompanha a barra de navegacao inferior (mesma conta da media
     query de 980px) -- se voltar pro 1rem antigo o toast fica escondido
     atras da barra. */
  .corner-toast {
    left: 1rem;
    right: 1rem;
    width: auto;
    max-height: min(55vh, 320px);
    bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px));
  }
}

/* #save-toast usa a mesma cara do #corner-toast (fila de IA), so que um
   pouco mais alto -- assim os dois nao se sobrepoem se acontecerem juntos. */
#save-toast { bottom: 7rem; }
@media (max-width: 980px) {
  #save-toast { bottom: calc(9.5rem + env(safe-area-inset-bottom, 0px)); }
}

.warranty-input-row {
  display: flex;
  gap: 0.5rem;
}
.warranty-input-row select { flex: 1; }

.field-hint-warning {
  color: var(--warning-text);
}

/* Mesma dica, mas quando o usuario JA' passou do limite -- o aviso deixa de
   ser informativo e vira erro. Criada junto do warning pra as duas variantes
   nascerem com a mesma forma (so' a cor muda). */
.field-hint-error {
  font-size: 0.78rem;
  color: var(--error-text);
  font-weight: 600;
}

/* ============================================================
   Animações do sistema (tema verde premium)
   Todo elemento que abre/fecha (dropdown, popup, toast, secao
   colapsavel) entra com o mesmo movimento suave -- consistencia
   visual em todas as telas. Como esses elementos alternam
   display none/block, a animacao reinicia sozinha a cada
   abertura (nao precisa de JS novo).
   ============================================================ */

@keyframes dropdown-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes overlay-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes pop-in {
  from { opacity: 0; transform: translateY(14px) scale(0.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes toast-in {
  from { opacity: 0; transform: translateX(18px); }
  to { opacity: 1; transform: translateX(0); }
}

.notif-dropdown.open,
.user-dropdown.open,
.header-menu-dropdown.open {
  animation: dropdown-in var(--dur-base) var(--ease-spring);
  transform-origin: top right;
}

.modal-overlay.open {
  animation: overlay-in var(--dur-base) var(--ease-out);
}

.modal-overlay.open .modal-box {
  animation: pop-in var(--dur-slow) var(--ease-spring);
}

.corner-toast.open,
.loading-overlay.open .loading-overlay-box,
.flash {
  animation: toast-in var(--dur-slow) var(--ease-spring);
}

/* Conteudo de secao colapsavel (<details>) desliza ao abrir. */
.collapsible-panel[open] > .collapsible-body {
  animation: rise-in var(--dur-base) var(--ease-out);
}

/* Troca de aba (Anuncio / Cadastro de Produto) com fade suave --
   switchAdTab() so alterna display, a animacao reinicia sozinha a cada
   troca (ids reais usados em ad_detail.html). Os dois paineis ja recebem
   rise-in por serem .panel; aqui so garante que a animacao reinicie na
   troca de display tambem. */
#tab-content-ad,
#tab-content-product {
  animation: rise-in var(--dur-base) var(--ease-out);
}

/* Miniaturas e fotos respondem ao toque (zoom sutil na miniatura). */
.row-thumb img {
  transition: transform var(--dur-base) var(--ease-out);
}

.row-thumb.clickable:hover img {
  transform: scale(1.12);
}

.photo-square {
  transition: border-color var(--dur-fast) var(--ease-out),
    transform var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}

.photo-square:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}

/* Linhas de tabela clicaveis com transicao mais rica no hover. */
.table-card table tbody tr.row-clickable td {
  transition: background var(--dur-fast) var(--ease-out);
}

/* Icones de acao ganham leve "lift" no hover, mantendo a altura fixa. */
.icon-btn {
  transition: background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.icon-btn:hover {
  border-color: rgba(33, 150, 243, 0.4);
}

/* Barra de progresso com brilho animado (carregamentos longos parecem
   vivos, nao travados). */
.loading-overlay-bar-fill {
  position: relative;
  overflow: hidden;
}

.loading-overlay-bar-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  animation: bar-shine 1.4s var(--ease-out) infinite;
}

@keyframes bar-shine {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}

/* Menu suspenso de autocomplete de placeholder ({ dentro de textarea de
   prompt de IA) -- pedido do usuario 2026-07-13: digitar "{" abre lista dos
   placeholders disponiveis (nome + descricao em fonte menor), filtra
   conforme digita, Enter/clique insere "{nome}". Posicionado via
   position:fixed com coordenadas calculadas em JS (tecnica de mirror-div
   pra achar o pixel do cursor dentro do textarea). */
.placeholder-suggest-dropdown {
  position: fixed;
  z-index: 200;
  min-width: 260px;
  max-width: 360px;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 0.3rem;
  animation: dropdown-in var(--dur-fast) var(--ease-out);
}

.placeholder-suggest-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  cursor: pointer;
  color: var(--text);
  height: auto;
  box-shadow: none;
  transform: none;
}

.placeholder-suggest-item:hover,
.placeholder-suggest-item.active {
  background: var(--brand-soft);
  color: var(--brand-dark);
  box-shadow: none;
  transform: none;
}

.placeholder-suggest-item-name {
  display: block;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.82rem;
  font-weight: 600;
}

.placeholder-suggest-item-desc {
  display: block;
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-top: 0.1rem;
  white-space: normal;
}

.placeholder-suggest-item.active .placeholder-suggest-item-desc {
  color: var(--brand-dark);
  opacity: 0.85;
}

.placeholder-suggest-empty {
  padding: 0.5rem 0.6rem;
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* Editor de fotos completo (TOAST UI Image Editor, headless -- 2026-07-14):
   menu de contexto (clique direito na foto) + popup do editor com toolbar
   100% custom nos moldes do sistema (a lib nao carrega o skin dela, so o
   motor -- ver static/js/photo_editor.js). */
.icon-btn.active {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}
.icon-btn.active:hover {
  background: var(--brand-dark);
  color: #fff;
}

.modal-box.editor-box {
  max-width: 960px;
  width: 96vw;
}

.photo-editor-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem;
  margin-bottom: 0.75rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.photo-editor-toolbar-sep {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 0 0.2rem;
}

.photo-editor-toolbar label.field-inline-label {
  font-size: 0.72rem;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
}

.photo-editor-toolbar input[type="color"] {
  width: var(--field-h);
  height: var(--field-h);
  padding: 2px;
  cursor: pointer;
}

.photo-editor-toolbar input[type="range"] {
  width: 90px;
  height: var(--field-h);
}

.photo-editor-toolbar select {
  width: auto;
  min-width: 110px;
}

.photo-editor-canvas-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 420px;
  max-height: 62vh;
  background: repeating-conic-gradient(#f1f3f5 0% 25%, #ffffff 0% 50%) 50% / 20px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: auto;
}

.photo-editor-tui-container {
  position: relative;
}

.photo-editor-overlay-canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
  cursor: crosshair;
}

.photo-editor-overlay-canvas.active {
  pointer-events: auto;
}

.photo-editor-hint {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 0.5rem 0 0;
}

.photo-editor-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.85);
  font-size: 0.85rem;
  color: var(--text-muted);
  z-index: 5;
}

/* ============================================================================
   RESPONSIVIDADE -- CELULAR E TABLET
   ============================================================================
   Este bloco fica NO FIM do arquivo de proposito. Varias regras base de
   componente sao declaradas mais abaixo do que as media queries antigas do
   projeto (ex.: `.ad-metrics-row` na casa da linha 4800) -- uma regra mobile
   escrita no meio do arquivo perde por ordem de cascata mesmo tendo a mesma
   especificidade, e o ajuste simplesmente nao aplica. Mantendo tudo aqui no
   fim, toda regra deste bloco vence sem precisar de !important.

   Breakpoints: 980px (tablet/celular -- some a barra lateral fixa e entra a
   navegacao inferior) e 620px (celular estreito).
   ==========================================================================*/

@media (max-width: 980px) {
  /* --- Estrutura: barra lateral vira menu off-canvas ---------------------
     Antes a `.sidebar` virava `position: relative; height: auto`, o que
     empilhava a barra inteira (marca + ~10 links + rodape) ACIMA do
     conteudo: toda tela abria com um menu gigante na frente. Agora ela sai
     da tela e entra deslizando pelo botao central da navegacao inferior.

     `body.sidebar-collapsed .layout` precisa aparecer junto: sem ele a
     regra do modo recolhido do desktop (especificidade 0,2,0) vence e
     mantem uma coluna de 108px reservada pra uma barra que ja e' fixed --
     o conteudo fica espremido nesse resto de tela. */
  .layout,
  body.sidebar-collapsed .layout {
    grid-template-columns: 1fr;
  }

  /* z-index 50: acima da topbar (40), abaixo dos modais (60) e dos
     toasts/flash (80) -- nunca cobre um alerta ou popup. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: min(268px, 82vw);
    height: 100vh;
    height: 100dvh;
    z-index: 50;
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform var(--dur-base) var(--ease-out);
    /* Area segura do notch/dynamic island (iPhone) -- sem isso a logo e o
       botao de fechar nasciam colados no topo fisico da tela, por baixo do
       recorte da camera em alguns aparelhos. Mesmo padding lateral/base de
       sempre, so' o topo ganha a folga extra. */
    padding-top: calc(1.75rem + env(safe-area-inset-top, 0px));
  }

  body.mobile-nav-open .sidebar {
    transform: translateX(0);
  }

  /* O modo "recolhido" e' uma preferencia de desktop -- no celular a barra
     e' o menu completo, entao a preferencia salva e' ignorada aqui. */
  body.sidebar-collapsed .sidebar {
    width: min(268px, 82vw);
    padding: 1.75rem 1.35rem;
    padding-top: calc(1.75rem + env(safe-area-inset-top, 0px));
  }

  body.sidebar-collapsed .brand-logo { display: block; }
  body.sidebar-collapsed .brand-logo-mark { display: none; }

  body.sidebar-collapsed .nav-link {
    flex-direction: row;
    /* `justify-content`/`text-align` voltam ao normal junto: sem eles os
       itens herdam a centralizacao do modo recolhido e os rotulos ficam no
       meio da coluna, desalinhados entre si. */
    justify-content: flex-start;
    align-items: center;
    text-align: left;
    font-size: 0.9rem;
    gap: 0.7rem;
    padding: 0.68rem 0.75rem;
    line-height: 1.55;
  }

  body.sidebar-collapsed .nav-link svg {
    width: 17px;
    height: 17px;
  }

  /* Recolher/expandir e' conceito de desktop. No celular o menu ja fecha ao
     escolher um item, tocar fora ou apertar Esc -- o botao nao aparece. */
  .sidebar-collapse-btn {
    display: none;
  }

  /* Fechar o menu -- unico sinal visual de que da' pra fechar sem escolher
     um item (antes so' existia tocar fora/Esc, sem nenhuma pista na tela).
     `position: absolute` relativo a `.sidebar` (fixed = ancestor
     posicionado mais proximo), fora de `.sidebar-scroll` de proposito --
     igual `.brand`, fica sempre visivel no topo, nunca rola junto com a
     lista de itens. */
  .mobile-nav-close {
    display: grid;
    place-items: center;
    position: absolute;
    top: calc(1.1rem + env(safe-area-inset-top, 0px));
    right: 1.1rem;
    width: 34px;
    height: 34px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(233, 236, 239, 0.85);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-out),
      color var(--dur-fast) var(--ease-out);
  }

  .mobile-nav-close svg {
    width: 18px;
    height: 18px;
  }

  .mobile-nav-close:hover,
  .mobile-nav-close:active {
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
  }

  /* Cabecalhos de grupo (Cadastros/Anuncios/Perguntas/Vendas/Sistema) sao
     <button>, que herdam a `height: var(--field-h)` do reset global de
     botao (mesma armadilha ja documentada varias vezes neste arquivo) --
     ficavam ~6px mais baixos que os links soltos ao lado deles (38px x
     44px), um alvo de toque menor e um ritmo vertical inconsistente na
     lista inteira. Alinhado ao `.nav-link` mobile. */
  .nav-group-header {
    min-height: 44px;
  }

  .mobile-nav-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(33, 37, 41, 0.5);
    z-index: 49;
  }

  body.mobile-nav-open .mobile-nav-backdrop {
    display: block;
    animation: overlay-in var(--dur-base) var(--ease-out);
  }

  /* --- Navegacao inferior ----------------------------------------------- */
  .mobile-bottom-nav {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
  }

  /* Espaco no fim do conteudo pra barra de navegacao inferior (fixa, 4.5rem)
     nunca cobrir o ultimo bloco da pagina -- botao de salvar, paginacao,
     rodape de tabela. Desde 2026-08-18 conta SO' com ela: a faixa legal virou
     rodape no fluxo e nao fica mais por cima de nada (ela mesma reserva o
     respiro dela, ver .legal-footer-bar no fim do arquivo). */
  .content {
    padding-bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px));
  }

  #save-toast {
    bottom: calc(9.5rem + env(safe-area-inset-bottom, 0px));
  }

  /* --- Tabelas das listas -----------------------------------------------
     O `overflow: hidden` do card (que existe pra manter o canto arredondado)
     cortava as colunas da direita sem deixar rolar -- na lista de produtos
     eram ~650px de conteudo inacessivel no celular. */
  .table-card {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* overflow-x sem overflow-y pareado promove o eixo Y pra auto sozinho --
       ver comentario completo em .ad-tab-bar. */
    overflow-y: hidden;
  }

  /* Sem largura minima o navegador espreme as colunas ate o texto quebrar
     letra a letra, em vez de acionar o scroll. */
  .table-card table {
    min-width: 640px;
  }

  /* --- Tela do anuncio --------------------------------------------------
     Abas (Anuncio / Cadastro de Produto / Aplicacao / Metricas / Perguntas):
     em flex com wrap elas eram espremidas ate o rotulo quebrar em tres
     linhas, e a ultima ficava cortada na borda. Viram faixa rolavel. */
  .ad-tab-bar {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* overflow-x sem overflow-y pareado promove o eixo Y pra auto sozinho --
       defensivo aqui tambem, mesmo a regra desktop ja cobrindo por cascata. */
    overflow-y: hidden;
    /* Barra de rolagem escondida: a fileira de abas ja sinaliza que ha mais
       conteudo, e a barra dobraria a altura do componente. */
    scrollbar-width: none;
  }

  .ad-tab-bar::-webkit-scrollbar { display: none; }

  .ad-tab-btn {
    flex: 0 0 auto;
    white-space: nowrap;
    padding: 0.7rem 0.8rem;
    font-size: 0.85rem;
  }

  /* Cabecalho do anuncio: somava ~500px dos 812px da tela antes de chegar no
     conteudo. Compactado sem esconder nenhuma informacao. */
  .ad-header-panel .panel-head h2 {
    font-size: 1.15rem;
    line-height: 1.3;
  }

  /* Salvar e Sincronizar lado a lado, metade da largura cada. */
  .ad-header-panel .ad-header-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.5rem;
    margin-top: 0.7rem;
  }

  .ad-header-panel .ad-header-actions > button,
  .ad-header-panel .ad-header-actions > a {
    width: 100%;
    padding: 0 0.6rem;
    font-size: 0.82rem;
    line-height: 1.15;
    height: auto;
    min-height: var(--field-h);
  }

  /* Chips de metrica em faixa rolavel: com wrap ocupavam 3 linhas. */
  .ad-header-panel .ad-metrics-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    /* overflow-x sem overflow-y pareado promove o eixo Y pra auto sozinho --
       ver comentario completo em .ad-tab-bar. */
    overflow-y: hidden;
    scrollbar-width: none;
  }

  .ad-header-panel .ad-metrics-row::-webkit-scrollbar { display: none; }

  .ad-header-panel .ad-metric-chip {
    flex: 0 0 auto;
    white-space: nowrap;
  }
}

@media (max-width: 780px) {
  /* --- Login ------------------------------------------------------------
     O conteudo de marketing (eyebrow, titulo, descricao, integracoes,
     features, rodape) empurraria o formulario pra baixo da dobra num
     celular -- quem abrisse veria so propaganda e precisaria rolar pra
     achar onde entrar. Mesmo principio ja estabelecido antes da
     reestruturacao "fundo completo e login centralizado" (2026-08-03):
     aqui vira so' logo compacta + card, o fundo animado continua rolando
     por baixo em tela cheia. */
  .auth-shell {
    min-height: 100vh;
    min-height: 100dvh; /* desconta a barra de endereco do navegador movel */
  }

  .auth-center {
    padding: 1.5rem 1.25rem 2.5rem;
  }

  .auth-hero-logo {
    max-width: 170px;
    margin-bottom: 1.25rem;
  }

  .auth-eyebrow,
  .auth-center h1,
  .auth-lead,
  .auth-integrations,
  .auth-features,
  .auth-foot {
    display: none;
  }

  .auth-card {
    padding: 1.75rem 1.4rem;
  }
}

@media (max-width: 620px) {
  /* --- Painel de notificacoes -------------------------------------------
     Tinha largura fixa de 320px ancorada no botao (que fica na ponta
     direita da topbar): o calculo jogava ~55px pra fora da tela pela
     esquerda e a caixa aparecia cortada. Agora flutua presa a viewport,
     com a mesma folga dos dois lados.

     O `top` real e' calculado em JS ao abrir (toggleNotifMenu), medindo o
     botao -- a topbar quebra em duas linhas quando a tela e' estreita,
     entao um valor fixo aqui acabaria cobrindo os botoes do cabecalho.
     O valor abaixo e' so o ponto de partida caso o JS nao rode. */
  .notif-dropdown {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    top: 7.25rem;
    width: auto;
    max-height: min(420px, calc(100vh - 11rem));
  }

  /* --- Barra de busca das listas ----------------------------------------
     Com `width: 100%` o campo tomava a linha inteira e jogava o botao de
     buscar (lupa) sozinho pra linha de baixo, gastando uma faixa vertical
     inteira do celular a toa. Com `flex: 1` os dois dividem a mesma linha. */
  .toolbar-search { flex-wrap: nowrap; }

  .toolbar-search input[type="text"] {
    flex: 1;
    width: auto;
    min-width: 0;
    max-width: none;
  }

  #ads-search-form { display: flex; gap: 0.6rem; }

  #ads-search-form input[type="text"] {
    flex: 1;
    width: auto;
    min-width: 0;
  }
}

@media (max-width: 620px) {
  /* --- Topbar ------------------------------------------------------------
     O seletor de empresa ocupava 206px do cabecalho e empurrava o avatar do
     usuario pra uma TERCEIRA linha (topbar com 161px de altura no celular).
     Encolhendo o nome da empresa com reticencias, titulo + empresa + sino +
     avatar cabem na mesma faixa. O nome completo continua no `title` do
     botao e dentro do proprio menu suspenso. */
  .topbar {
    gap: 0.5rem;
    padding-left: 1.1rem;
    padding-right: 1.1rem;
    margin-left: -1.1rem;
    margin-right: -1.1rem;
  }

  .topbar-actions {
    gap: 0.4rem;
  }

  .company-card-name {
    display: inline-block;
    max-width: 6.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
  }

  .company-card-btn {
    padding: 0.4rem 0.55rem;
    gap: 0.35rem;
  }
}

@media (max-width: 620px) {
  /* --- Cabecalho do anuncio: titulo em largura total ---------------------
     `.panel-head` e `.panel-head-title` sao flex em linha unica: com as
     setas de navegacao e os dois botoes de icone disputando espaco, sobravam
     ~119px pro titulo, que quebrava em cinco linhas. No celular a linha de
     navegacao/acoes vai pra cima e o titulo fica com a largura toda. */
  .ad-header-panel .panel-head {
    flex-direction: column;
    align-items: stretch;
    gap: 0.6rem;
  }

  .ad-header-panel .panel-head-title {
    flex-wrap: wrap;
    gap: 0.4rem;
  }

  .ad-header-panel .panel-head-title h2 {
    flex: 1 0 100%;
    order: 2;
    margin: 0;
  }

  /* Setas e icones ficam na primeira linha, o titulo logo abaixo. */
  .ad-header-panel .panel-head-title > .icon-btn,
  .ad-header-panel .panel-head-title > .ad-nav-arrows {
    order: 1;
  }

  /* "Sincronizar com o Mercado Livre" quebrava em quatro linhas dentro do
     botao -- fonte um pouco menor resolve sem cortar o texto. */
  .ad-header-panel .ad-header-actions > button,
  .ad-header-panel .ad-header-actions > a {
    font-size: 0.76rem;
    padding: 0.4rem 0.5rem;
  }
}

@media (max-width: 620px) {
  /* --- Margens laterais no celular --------------------------------------
     A soma das folgas comia largura util demais: 17.6px do `.content` mais
     20px do painel davam ~38px de cada lado, sobrando ~300px de 375px pro
     conteudo de verdade. Reduzido pra ~12px + ~14px (26px), devolvendo
     cerca de 24px de largura em toda tela do sistema. */
  .content {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  .topbar {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
    margin-left: -0.75rem;
    margin-right: -0.75rem;
  }

  .hero,
  .panel {
    padding: 0.9rem;
  }

  /* Painel do anuncio e o de cadastro de produto tinham folga propria maior
     (2.3rem no cadastro) -- alinhados com o resto no celular. */
  .ad-product-panel,
  .ad-values-panel,
  .ad-commercial-panel,
  .ad-header-panel {
    padding-left: 0.9rem;
    padding-right: 0.9rem;
  }
}

/* ============================================================================
   LISTAS -- DISTRIBUICAO DE COLUNAS
   ============================================================================
   Numa tabela `table-layout: auto` o navegador reparte a largura pelo
   conteudo de cada coluna, sem saber o que e' importante: na lista de
   produtos isso dava 22% da tabela pra caixa de selecao + botoes de acao
   (que nao precisam de quase nada) e so 18% pra "Aplicacao", justamente a
   coluna com o texto mais longo -- resultado: codigo "C-7076.1" quebrando em
   duas linhas e a tabela estourando ~47px pra fora do card.

   O truque abaixo e' o classico `width: 1%` + `nowrap`: encolhe a coluna ate
   o minimo que o conteudo exige e devolve toda a sobra pras colunas de texto.

   `:has()` e' usado pra pegar as colunas de controle em TODAS as listas sem
   precisar marcar 11 templates a mao. Em navegador que nao suporte (Chrome
   <105 / Safari <15.4), as regras sao simplesmente ignoradas e as listas
   voltam a se comportar como antes -- nada quebra.
   ==========================================================================*/

/* Caixa de selecao (primeira coluna das listas com selecao em massa). */
.table-card th:has(> input[type="checkbox"]),
.table-card td:has(> input[type="checkbox"]),
.table-card td:has(> .row-select) {
  width: 1%;
  white-space: nowrap;
}

/* Miniatura da foto. */
.table-card td:has(> .row-thumb),
.table-card td:has(> .row-thumb-placeholder) {
  width: 1%;
}

/* Coluna de acoes (ja tinha classe propria em products/ads/knowledge). */
.table-card .row-actions {
  width: 1%;
  white-space: nowrap;
}

/* Codigo, preco e datas nunca devem quebrar no meio -- sao valores curtos e
   ilegiveis partidos ("C-" numa linha, "7076.1" na outra). */
.table-card .col-nowrap,
.table-card .col-code,
.table-card .col-price {
  white-space: nowrap;
  width: 1%;
}

/* Coluna de texto principal: fica com a sobra e e' a unica que quebra em
   varias linhas de proposito. Sem `min-width` -- fixar um piso aqui empurrava
   a soma das colunas pra fora do card em vez de deixar a tabela se acomodar. */
.table-card .col-main {
  white-space: normal;
}

/* Reforco de largura pra colunas .col-main especificas (pedido do usuario,
   2026-07-27: "aumentar largura" das colunas Empresa/Integração/Usuário em
   Configuracoes) -- .col-main sozinho so' garante que ela NAO quebra palavra
   por palavra, mas quando ha mais de uma coluna sem width:1% ao lado (ex.:
   "Catálogo público"), o espaco livre da tabela se divide entre as duas.
   .col-wide da um empurrao explicito só onde foi pedido, sem mexer no
   .col-main generico (usado em varias outras listas do sistema). */
.table-card .col-wide {
  /* !important necessario nos dois -- min-width e' o que de fato funciona
     de forma confiavel em table-layout:auto (testado ao vivo: "width: 38%"
     sozinho e' so' uma DICA pro algoritmo de auto-layout, que o navegador
     ignora quando min-width/conteudo das outras colunas ja "satisfazem" o
     espaco -- min-width e' o mecanismo que .col-org-name/.col-integration-name
     ja usavam de verdade). !important necessario porque quando a coluna
     larga e' a PRIMEIRA da tabela (Empresa/Integração/Usuário/Nome em
     Organizações), ".table-card table thead th:first-child" (pensada pra
     coluna de checkbox, width:40px) e ".col-org-name"/".col-integration-name"
     (min-width:200px, alguns com ID no seletor) vencem por especificidade
     sem isso -- mesma classe de conflito ja documentada e resolvida assim
     uma vez neste arquivo (ver .currency-input input). */
  min-width: 320px !important;
  width: 38% !important;
}

/* Coluna "Anúncio" da aba "Anúncios deste produto" (Cadastro de Produto) --
   pedido 2026-08-05: "na coluna anuncio tem q ser maior". Classe PROPRIA em
   vez de .col-wide (compartilhada com Configuracoes) porque o min-width dela
   precisa ser menor aqui: esta tabela tem 9 colunas e, MEDIDO ao vivo, os
   320px da .col-wide passavam a forcar scroll horizontal em janela de 1280px,
   onde antes nao havia -- 260px e' o maior valor que ainda cabe.
   Em 1440px o width:38% assume e a coluna vai a 423px (era 172px).
   !important pelo mesmo motivo da .col-wide: ".table-card table thead
   th:first-child" (pensada pra coluna de checkbox) vence por especificidade
   quando a coluna larga e' a primeira da tabela. */
.table-card .col-ad-title {
  min-width: 260px !important;
  width: 38% !important;
}

/* Coluna "Empresa" da tabela de Integrações (pedido 2026-07-27: "deixar um
   pouco mais larga") -- ela e' .col-nowrap, entao nome de empresa comprido
   ficava espremido/cortado. min-width pelo mesmo motivo explicado acima:
   em table-layout:auto, width percentual sozinho e' so' uma dica. */
.table-card .col-company {
  min-width: 190px;
}

/* Respiro horizontal das celulas: 1.2rem de cada lado somava ~345px so' de
   padding numa lista de 9 colunas (mais que 1/3 da largura do card) e era a
   causa real da tabela estourar. 0.85rem mantem a leitura confortavel e
   devolve ~115px pro conteudo -- de quebra deixa a lista mais densa e
   "tecnica", que e' a cara que o sistema pede. */
.table-card th,
.table-card td {
  padding-left: 0.85rem;
  padding-right: 0.85rem;
}

.table-card table thead th:first-child,
.table-card table tbody td:first-child {
  padding-left: 1.15rem;
}

.table-card table thead th:last-child,
.table-card table tbody td:last-child {
  padding-right: 1.15rem;
}

/* ============================================================================
   BOTOES -- PADRAO DO SISTEMA
   ============================================================================
   Regra do projeto: botao sem classe = primario (azul da marca), `.secondary-dark`
   = neutro, `.button-danger` = destrutivo, todos na altura `--field-h`.
   Menus suspensos (`.header-menu-dropdown`, `.user-dropdown`, `.notif-dropdown`,
   `.company-dropdown`) e o menu lateral (`.nav-link`, `.sidebar-collapse-btn`)
   ficam DE FORA de proposito -- ali o padrao e' lista limpa, sem botao
   desenhado, e aplicar a altura/cor do sistema quebraria o visual de menu.
   ==========================================================================*/

/* --- Botao de busca ------------------------------------------------------
   Usava `.icon-btn` (quadrado de 30px, fundo cinza claro, texto apagado): ao
   lado de um campo de 2.35rem ficava menor que o input e com cara de acao
   secundaria, quando buscar e' justamente a acao principal da barra. Agora
   acompanha a altura do campo e usa a cor da marca. */
.toolbar-search button[type="submit"],
#ads-search-form button[type="submit"],
.category-search-box button[type="submit"] {
  width: var(--field-h);
  height: var(--field-h);
  flex: 0 0 auto;
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
  box-shadow: var(--shadow-sm);
}

.toolbar-search button[type="submit"]:hover,
#ads-search-form button[type="submit"]:hover,
.category-search-box button[type="submit"]:hover {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: #fff;
}

.toolbar-search button[type="submit"] svg,
#ads-search-form button[type="submit"] svg,
.category-search-box button[type="submit"] svg {
  width: 16px;
  height: 16px;
}

/* --- Altura uniforme -----------------------------------------------------
   Qualquer botao solto que tenha ganhado padding vertical proprio ao longo do
   tempo volta pra altura padrao quando esta ao lado de um campo. Fora de
   menus suspensos e do menu lateral, conforme a regra acima. */
/* Os botoes do seletor de empresa (chip "x" e "+ Empresa") sao compactos de
   proposito -- excluidos aqui pra nao serem esticados pra --field-h. */
.products-toolbar button:not(.icon-btn):not(.company-chip-x):not(.company-add-btn),
.toolbar-actions-right button:not(.icon-btn),
.panel-head > button,
.panel-head .button-row > button {
  min-height: var(--field-h);
}

/* Nome do grupo: eram 22rem fixas (32% da tabela) enquanto as colunas de
   texto se espremiam. Encolhe ao conteudo real em vez de um valor fixo --
   com largura fixa apertada os nomes de duas palavras ("Motor de partida",
   "Regulador de voltagem") quebravam em duas linhas e desalinhavam a altura
   das linhas da lista. */
.table-card .col-group-name {
  width: 1%;
  white-space: nowrap;
}

/* Coluna principal da lista de ANUNCIOS: o titulo do anuncio e' o dado que a
   pessoa le pra se localizar e estava quebrando em 5 linhas numa coluna
   estreita. Aqui ele ganha um piso de largura -- as colunas vizinhas
   (categoria, valores) sao curtas e cedem espaco sem prejuizo. */
#ads-table-fragment .table-card .col-main,
.table-card .ad-cell-title {
  min-width: 260px;
}

/* ============================================================================
   PERGUNTAS -- LISTA + COLUNA DE CONTEXTO
   ============================================================================
   Pedido do usuario (2026-07-24): ao clicar numa pergunta o contexto abre
   numa coluna a direita da lista, nao mais em popup. Antes eram DOIS popups
   empilhados (responder + "ver dados do produto"), o que obrigava a fechar um
   pra consultar o outro justamente enquanto se escrevia a resposta.
   ==========================================================================*/

.questions-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  align-items: start;
}

/* A coluna so' existe depois que uma pergunta e' escolhida -- sem isso a
   lista ficaria estreitada a toa mostrando um painel vazio. */
.questions-layout.side-open {
  grid-template-columns: minmax(0, 1fr) minmax(340px, 420px);
}

.questions-side-panel {
  display: none;
  position: sticky;
  /* Abaixo da topbar (que e' sticky em 0) -- o painel acompanha a rolagem da
     lista, que costuma ser longa. */
  top: 5.5rem;
  max-height: calc(100vh - 7rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  flex-direction: column;
}

.questions-layout.side-open .questions-side-panel {
  display: flex;
  animation: rise-in var(--dur-base) var(--ease-out);
}

.questions-side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-alt);
}

.questions-side-head h3 {
  margin: 0;
  font-size: 1rem;
}

.questions-side-body {
  padding: 1rem;
  overflow-y: auto;
}

/* Linha escolhida na lista fica marcada enquanto o painel esta aberto, pra
   nao perder a referencia de qual pergunta esta sendo respondida. */
.table-card tbody tr.is-selected,
.table-card tbody tr.is-selected:hover,
.table-card tbody tr:nth-child(even).is-selected {
  background: var(--brand-soft);
  box-shadow: inset 3px 0 0 var(--brand);
}

.questions-context {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

/* "Inserir link" e' uma conveniencia, nao uma acao principal da tela -- como
   botao solido competia com "Responder no Mercado Livre" logo acima. Vira um
   link de texto discreto, no mesmo espirito do "Carregar mais" das
   notificacoes. */
.qa-link-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.9rem;
}

.qa-link-row .field-hint {
  margin: 0;
}

.qa-link-insert {
  height: auto;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  color: var(--brand-dark);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.qa-link-insert:hover {
  background: none;
  border: none;
  box-shadow: none;
  transform: none;
  color: var(--brand);
}

/* Link discreto generico (texto sublinhado, sem cara de botao solido) --
   mesmo padrao ja usado em .qa-link-insert, extraido pra classe reaproveitavel
   em qualquer tela (ex.: "Esqueci minha senha" no login). */
.text-link-btn {
  height: auto;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  color: var(--brand-dark);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.text-link-btn:hover {
  background: none;
  border: none;
  box-shadow: none;
  transform: none;
  color: var(--brand);
}

/* ===========================================================================
   Planilha de edicao em massa -- ajustes de 2026-08-02
   =========================================================================== */

/* (1) A tabela ocupa melhor a tela: o .content tem 2.25rem de padding lateral
   que sobrava como moldura. A margem negativa devolve esse espaco SO' nesta
   tela (o padding continua valendo pro resto do app). O max-height sobe de
   250px pra 190px de desconto -- a toolbar e o rodape encolheram junto. */
.sheet-page {
  margin-left: -2.25rem;
  margin-right: -2.25rem;
  padding-left: 1rem;
  padding-right: 1rem;
}

.sheet-page .sheet-wrap { max-height: calc(100vh - 190px); }
.sheet-page .sheet-toolbar { margin-bottom: 0.55rem; }
.sheet-page .sheet-footer { margin-top: 0.45rem; }

@media (max-width: 900px) {
  /* No mobile o .content tem padding menor -- devolver 2.25rem cortaria a tela. */
  .sheet-page { margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }
}

/* (2) Linhas um pouco mais altas (pedido do usuario) + espaco pra miniatura.
   Mesma classe que a planilha de produtos ja usa; aqui e' aplicada na tabela
   de anuncios tambem. */
table.sheet.sheet-tall td.sheet-cell,
table.sheet.sheet-tall td.sheet-fixed {
  padding-top: 0.62rem;
  padding-bottom: 0.62rem;
}

/* (3) Contador de caracteres do canal, dentro da celula em edicao. */
.sheet-char-count {
  position: absolute;
  right: 4px;
  bottom: 2px;
  z-index: 3;
  font-size: 0.62rem;
  line-height: 1;
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--surface);
  color: var(--text-faint);
  border: 1px solid var(--border);
  pointer-events: none;
}

.sheet-char-count.no-limite {
  color: var(--warning-text);
  border-color: var(--warning-text);
  font-weight: 700;
}

/* ---------------------------------------------------------------------------
   Caixa "dados do produto base"
   Fica FORA da tabela (dentro dela o overflow do .sheet-wrap cortaria) e e'
   posicionada por JS: `top` na linha clicada, `left` na ultima coluna fixada.
   Por isso acompanha o scroll horizontal sem truque de CSS.
   --------------------------------------------------------------------------- */
.produto-card {
  position: absolute;
  z-index: 30;
  min-width: 420px;
  /* Coluna flex: o cabecalho fica parado e SO' o corpo rola. A altura real e'
     calculada por JS (espaco livre acima/abaixo da linha); este max-height e'
     so' a rede de seguranca pro instante antes do primeiro calculo. */
  display: flex;
  flex-direction: column;
  max-height: 70vh;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 42px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.08);
  overflow: hidden;
  /* VISIVEL por padrao, de proposito. O estado base NUNCA pode ser
     opacity:0 esperando uma transicao pra aparecer: transition/animation
     dependem do relogio de animacao, que nao avanca em aba de segundo plano
     nem com o compositor ocupado -- a caixa ficaria INVISIVEL, nao apenas
     "sem animacao". Bug real pego em teste nesta rodada; mesma licao ja
     documentada nas barras de dado (parte 131) e no PWA.
     A animacao e' so' enfeite: se nao rodar, abre/fecha instantaneo. */
  opacity: 1;
}

.produto-card.aberto { animation: produto-card-in var(--dur-base) var(--ease-out); }
.produto-card.fechando { animation: produto-card-out 160ms var(--ease-out) forwards; }

/* A animacao de ENTRADA mexe SO' em transform, nunca em opacity: enquanto uma
   animacao esta ativa o valor dela vence o do elemento, e se o relogio de
   animacao nao avancar (aba em segundo plano, compositor ocupado) ela congela
   no primeiro frame -- com `opacity: 0` ali a caixa simplesmente nao aparece.
   Congelada em translateY(-8px) ela aparece igual, so' sem o movimento.
   Na SAIDA opacity pode entrar: se nao animar, a caixa some na hora (o
   `hidden` vem logo depois de qualquer jeito), que e' o resultado esperado. */
@keyframes produto-card-in {
  from { transform: translateY(-8px) scale(0.985); }
  to   { transform: translateY(0) scale(1); }
}

@keyframes produto-card-out {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to   { opacity: 0; transform: translateY(-4px) scale(0.99); }
}

/* Quando nao cabe abaixo da linha, a caixa abre PRA CIMA -- entao o movimento
   e a sombra tambem viram, senao pareceria estar caindo de um lugar errado. */
.produto-card.acima-da-linha.aberto { animation-name: produto-card-in-cima; }
.produto-card.acima-da-linha {
  box-shadow: 0 -18px 42px rgba(0, 0, 0, 0.18), 0 -2px 8px rgba(0, 0, 0, 0.08);
}

@keyframes produto-card-in-cima {
  from { transform: translateY(8px) scale(0.985); }
  to   { transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .produto-card.aberto,
  .produto-card.fechando { animation: none; }
}

.produto-card-head {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 0.85rem;
  background: linear-gradient(135deg, rgba(33, 150, 243, 0.10), rgba(33, 150, 243, 0.02));
  border-bottom: 1px solid var(--border);
}

.produto-card-title { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }

.produto-card-eyebrow {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-dark);
}

.produto-card-title strong {
  font-size: 0.9rem;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 46ch;
}

.produto-card-head-actions { display: flex; align-items: center; gap: 0.3rem; }

.produto-card-body {
  padding: 0.85rem;
  /* Sem max-height proprio: quem limita a altura e' o card (calculada pelo
     espaco real da tela). Um teto aqui brigaria com aquele e o `overflow:
     hidden` do card cortaria o conteudo em vez de deixar rolar. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.produto-card-fotos {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  /* overflow-x sem overflow-y pareado promove o eixo Y pra auto sozinho --
     ver comentario completo em .ad-tab-bar. */
  overflow-y: hidden;
  padding-bottom: 0.35rem;
  margin-bottom: 0.7rem;
}

.produto-card-foto {
  flex: 0 0 auto;
  width: 74px;
  height: 74px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-alt);
  cursor: zoom-in;
  height: 74px;
}

.produto-card-foto:hover { border-color: var(--brand); background: var(--bg-alt); }
.produto-card-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }

.produto-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-bottom: 0.8rem;
}

/* Canto discreto, nunca pilula: o chip de OEM costuma quebrar em varias
   linhas (lista longa de codigos) e um raio de 999px vira uma bolha
   deformada. `align-items: flex-start` mantem o rotulo colado no topo
   quando o valor ocupa mais de uma linha. */
.produto-card-chip {
  display: inline-flex;
  align-items: flex-start;
  gap: 0.3rem;
  font-size: 0.72rem;
  padding: 0.25rem 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text);
}

.produto-card-chip-k {
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  flex: 0 0 auto;
  line-height: 1.5;
  white-space: nowrap;
}

.produto-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.85rem;
}

.produto-card-bloco { min-width: 0; }

.produto-card-bloco h4 {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.4rem;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  padding-bottom: 0.25rem;
  border-bottom: 1px solid var(--border);
}

.produto-card-badge {
  font-size: 0.6rem;
  font-weight: 700;
  padding: 0.05rem 0.35rem;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  color: var(--brand-dark);
  letter-spacing: 0;
}

.produto-card-dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem 0.6rem;
  margin: 0;
  font-size: 0.75rem;
}

.produto-card-dl dt { color: var(--text-muted); }
.produto-card-dl dd { margin: 0; color: var(--text); word-break: break-word; }

.produto-card-lista {
  margin: 0;
  padding-left: 1rem;
  font-size: 0.75rem;
  color: var(--text);
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.produto-card-texto {
  margin: 0;
  font-size: 0.75rem;
  color: var(--text);
  white-space: pre-line;
  max-height: 9rem;
  overflow-y: auto;
}

.produto-card-empty {
  margin: 0;
  font-size: 0.73rem;
  color: var(--text-faint);
}

/* Estoque abaixo do minimo que o canal exige pra anunciar (2026-08-02).
   A Shopee recusa publicar com menos de 2 -- o valor vem da API real dela
   (ad_platform_min_stock), nunca chumbado aqui. Usado na coluna Estoque da
   lista de anuncios e no campo Estoque de cada variacao. */
.estoque-cell {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.estoque-cell.estoque-abaixo-minimo {
  color: var(--warning-text);
  font-weight: 700;
}

.estoque-alerta {
  display: inline-flex;
  color: var(--warning-text);
  cursor: help;
}

.estoque-alerta svg { width: 15px; height: 15px; }

/* Estoque real do cadastro (product_companies) divergindo do que ja esta
   publicado (marketplace_ads.available_quantity) -- aparece so' quando os
   dois sao diferentes, nunca escondendo o valor publicado (pedido do
   usuario, 2026-08-04: "fiz alteração de estoque mas nao aparece o real
   estoque na lista" -- o publicado so' reflete o cadastro DEPOIS que a
   sincronizacao automatica empurrar). */
.estoque-pendente-sync {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.15rem;
  font-size: 0.72rem;
  color: var(--info-text);
  cursor: help;
  white-space: nowrap;
}

.estoque-pendente-sync svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

/* Mesmo aviso no input de estoque da variacao: borda/fundo de atencao, sem
   bloquear a digitacao (o usuario pode estar no meio de preencher). */
input.estoque-abaixo-minimo {
  border-color: var(--warning-text) !important;
  background: var(--warning-bg);
}

/* (O link "Instalar no computador" saiu da tela de login em 2026-08-18 --
   tela minima -- e o CSS .auth-install-link foi removido junto. O botao da
   topbar #btn-instalar-app continua; mostrarBotoesInstalar() em base.html
   ja' ignora id ausente.) */

.auth-forgot-link {
  display: block;
  margin: 1rem auto 0;
  text-align: center;
}

.qa-similar-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
}

.qa-similar-list li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.82rem;
}


/* ==========================================================================
   Planilha de edicao em massa de anuncios (2026-07-30)
   Estilo Excel: cabecalho fixo no topo, colunas de numero da linha e ID fixas
   na esquerda, celula selecionada com contorno, feedback curto de salvamento
   por celula (verde/vermelho) em vez de toast. Prefixo .sheet- em tudo pra
   nunca colidir com as tabelas normais do sistema (.table-card table).
   ========================================================================== */
.sheet-topbar-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.sheet-toolbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.85rem;
}

.sheet-toolbar-info {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  max-width: 900px;
}

.sheet-toolbar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.sheet-wrap {
  overflow: auto;
  max-height: calc(100vh - 250px);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

table.sheet {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.78rem;
  /* table-layout FIXED de proposito (2026-07-30): com `auto`, a largura da
     coluna e recalculada a partir do conteudo -- entrar em edicao troca o
     texto da celula por um <input> e a coluna PULAVA de largura. Com fixed +
     largura explicita em cada <th> (ver sheetRenderHead), o conteudo nunca
     mexe na largura, o redimensionamento manual passa a ser so trocar esse
     valor, e a tabela de 40+ colunas ainda renderiza mais rapido. */
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
}

table.sheet th,
table.sheet td {
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 0;
  vertical-align: middle;
  background: var(--surface);
}

/* --- Cabecalho (2 linhas: faixa de grupo + nome da coluna), sempre fixo --- */
table.sheet thead th {
  position: sticky;
  z-index: 4;
  background: var(--bg-alt);
  color: var(--text);
  font-weight: 700;
  text-align: left;
  white-space: nowrap;
  padding: 0.4rem 0.55rem;
  font-size: 0.72rem;
}

table.sheet thead tr.sheet-band-row th { top: 0; }
table.sheet thead tr.sheet-head-row th { top: 26px; }

table.sheet thead th.sheet-band {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.62rem;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-strong);
  text-align: center;
  background: var(--bg);
}

table.sheet thead th.sheet-attr-head {
  font-weight: 600;
  color: var(--text-muted);
}

table.sheet thead th.sheet-attr-head.required {
  color: var(--text);
  font-weight: 700;
}

/* --- Colunas fixas (numero da linha + ID) -------------------------------- */
.sheet-rownum { width: 44px; min-width: 44px; left: 0; }
.sheet-idcol { width: 72px; min-width: 72px; left: 44px; }

table.sheet td.sheet-fixed {
  position: sticky;
  z-index: 2;
  background: var(--bg-alt);
  color: var(--text-muted);
  text-align: center;
  padding: 0.5rem 0.4rem;
  font-variant-numeric: tabular-nums;
  border-right: 1px solid var(--border-strong);
}

table.sheet td.sheet-idcol a {
  color: var(--brand);
  font-weight: 700;
  text-decoration: none;
}

table.sheet td.sheet-idcol a:hover { text-decoration: underline; }

/* Cantos do cabecalho: precisam vencer tanto o thead sticky quanto as
   colunas fixas do corpo, senao a celula do canto "passa por baixo". */
table.sheet thead th.sheet-corner {
  position: sticky;
  z-index: 6;
  background: var(--bg);
  border-right: 1px solid var(--border-strong);
}

/* --- Linha de grupo (plataforma + raiz completa da categoria) ------------- */
tr.sheet-group-row td {
  background: var(--brand-soft);
  border-bottom: 1px solid var(--border-strong);
  border-top: 1px solid var(--border-strong);
  padding: 0;
}

.sheet-group-inner {
  position: sticky;
  left: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0.6rem;
  max-width: calc(100vw - 340px);
}

.sheet-group-label {
  font-weight: 700;
  color: var(--brand-dark);
  font-size: 0.78rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sheet-group-count {
  font-size: 0.68rem;
  color: var(--text-muted);
  white-space: nowrap;
}

/* --- Celulas editaveis --------------------------------------------------- */
table.sheet td.sheet-cell {
  /* Altura da linha vem daqui (pedido do usuario: linhas um pouco mais
     altas). max-width saiu: com table-layout fixed a largura e' a declarada
     no <th>, e um max-width menor brigaria com coluna redimensionada. */
  padding: 0.5rem 0.5rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: cell;
  color: var(--text);
}

/* Hover de linha um pouco mais escuro (pedido do usuario, 2026-07-30):
   --border em vez de --bg-alt. Os :not() sao necessarios por ESPECIFICIDADE:
   este seletor tem 3 classes (.sheet + :hover + .sheet-cell) e venceria as
   regras de estado da celula, que tem 3 tambem mas perdem no empate por vir
   antes -- sem eles, passar o mouse numa linha apagava o realce de selecao
   (.range/.active) e o verde/vermelho do salvamento. Nao usa --neutral-soft
   de proposito: e' a cor de "Nao aplica" (.na), ficaria ambiguo. */
table.sheet tbody tr:hover td.sheet-cell:not(.range):not(.active):not(.locked):not(.na):not(.saved):not(.failed):not(.busy) {
  background: var(--border);
}

table.sheet td.sheet-cell.active {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  background: var(--surface);
  position: relative;
  z-index: 1;
}

table.sheet td.sheet-cell.locked {
  background: repeating-linear-gradient(
    135deg,
    var(--bg-alt) 0 6px,
    var(--bg) 6px 12px
  );
  color: var(--text-faint);
  cursor: not-allowed;
}

table.sheet td.sheet-cell.absent { color: transparent; }

table.sheet td.sheet-cell.na {
  color: var(--text-faint);
  font-style: italic;
  background: var(--neutral-soft);
}

table.sheet td.sheet-cell.saved {
  background: var(--success-bg);
  transition: background var(--dur-slow) var(--ease-out);
}

table.sheet td.sheet-cell.failed {
  background: var(--error-bg);
  color: var(--error-text);
  font-weight: 600;
}

table.sheet td.sheet-cell.busy {
  background: linear-gradient(90deg, var(--bg-alt) 25%, var(--brand-soft) 50%, var(--bg-alt) 75%);
  background-size: 200% 100%;
  animation: sheet-busy 1.1s linear infinite;
}

@keyframes sheet-busy {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

table.sheet td.sheet-cell.editing {
  padding: 0;
  overflow: visible;
  position: relative;
  z-index: 5;
}

/* Editor: um por vez, montado dentro da celula ativa. Sobrescreve a altura
   padrao de input/select do sistema (--field-h) de proposito -- numa planilha
   a linha e' compacta; sem isso a linha "salta" ao entrar em edicao. */
.sheet-editor {
  /* width 100% do content-box da celula -- com table-layout fixed isso nunca
     empurra a coluna. box-sizing garante que borda/padding do editor caibam
     dentro da largura da celula em vez de somar. */
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  height: auto !important;
  min-height: 26px;
  border: 2px solid var(--brand) !important;
  border-radius: 0 !important;
  padding: 0.22rem 0.4rem !important;
  font-size: 0.78rem;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  /* sem box-shadow de proposito: a sombra dava aparencia de uma segunda caixa
     flutuando por cima da celula. So o textarea (que realmente sobrepoe as
     celulas vizinhas) ganha sombra, mais abaixo. */
  box-shadow: none;
  outline: none;
}

/* Editor ocupa 100% da ALTURA da celula (pedido do usuario, 2026-07-30): com
   as linhas mais altas da planilha de produto, o editor de altura fixa deixava
   uma faixa vazia dentro da celula. `height: 100%` num filho de <td> NAO
   resolve (a altura da celula vem do layout da linha, nao e' um valor definido
   pro filho) -- medido: celula 57px, editor 26px. E display:flex no <td> esta
   proibido no projeto (quebra a sincronia de altura/borda entre colunas da
   mesma linha, ver regra de 2026-07-11). A saida e' posicionar o editor pra
   cobrir a celula: td.editing ja e' position:relative/sticky, entao inset: 0
   preenche exatamente a area util. */
.sheet-editor:not(.sheet-editor-area) {
  position: absolute;
  inset: 0;
  width: 100%;
}

.sheet-editor-area {
  position: absolute;
  top: 0;
  left: 0;
  width: 360px;
  min-width: 360px;
  /* o textarea flutua sobre as celulas vizinhas -- altura propria, nao 100% */
  height: auto !important;
  z-index: 6;
  resize: vertical;
  white-space: pre-wrap;
  box-shadow: var(--shadow-md);
}


/* Colunas fixadas pelo usuario (botao direito no cabecalho, ate 3): grudam
   logo a direita do ID. O `left` de cada uma e calculado em JS
   (sheetApplyPinnedOffsets) porque depende da largura REAL das colunas
   anteriores -- aqui fica so o comportamento sticky, o realce e o z-index. */
table.sheet th.sheet-pinned,
table.sheet td.sheet-pinned {
  position: sticky;
  background: var(--bg-alt);
  border-right: 1px solid var(--border-strong);
}

table.sheet td.sheet-pinned { z-index: 2; }
table.sheet th.sheet-pinned { z-index: 6; }

/* Celula selecionada/em edicao precisa vencer as colunas fixadas (senao o
   contorno e o editor ficam por baixo delas) E, quando ela MESMA e de uma
   coluna fixada, precisa reafirmar `position: sticky`: as regras .active e
   .editing setam `position: relative` (pra poder empilhar com z-index) e,
   por terem 2 classes + elemento, venceriam o `sticky` de td.sheet-pinned --
   resultado: clicar numa celula de coluna fixada fazia a coluna "soltar" e
   rolar junto com o resto (bug real, pego em teste). 3 classes + elemento
   aqui garantem que o sticky volte a valer. */
table.sheet td.sheet-cell.sheet-pinned.active { position: sticky; z-index: 3; }
table.sheet td.sheet-cell.editing.sheet-pinned { position: sticky; z-index: 7; }

table.sheet thead th.sheet-band.sheet-pinned-band {
  background: var(--brand-soft);
  color: var(--brand-dark);
}

.sheet-pin-mark {
  margin-left: 0.3rem;
  font-size: 0.6rem;
  opacity: 0.75;
}

/* Cabecalho de coluna: o cursor avisa que ali tem menu (fixar/desfixar). */
table.sheet thead th[data-key] { cursor: context-menu; }


/* Selecao de VARIAS celulas (arraste / Shift / Ctrl+clique): a celula ATIVA
   mantem o contorno forte; as outras do conjunto ganham um preenchimento
   suave. Fundo (nao outline) de proposito -- outline em dezenas de celulas
   vizinhas viraria uma grade de linhas duplas. */
table.sheet td.sheet-cell.range {
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px var(--brand);
}

/* Selecionada + travada: mostra que faz parte do conjunto mas nao vai receber
   valor (o "clonar"/"limpar" pula ela). */
table.sheet td.sheet-cell.range.locked {
  background: var(--bg-alt);
  box-shadow: inset 0 0 0 1px var(--border-strong);
}

/* --- Um contorno por celula, nunca dois (relato do usuario 2026-07-30:
   "qnd selecionado esta ficando dois quadrado") ---------------------------
   A celula ATIVA ja tem o contorno de 2px do .active; como selecionar uma
   celula tambem a coloca no conjunto, o anel de 1px do .range vinha somado e
   apareciam DOIS quadrados. E em edicao havia um terceiro: a borda do proprio
   editor. Regra: o anel de intervalo nao vale na celula ativa, e em edicao
   quem desenha o contorno e' SO o editor.
   Especificidade: .range.active/.range.editing tem 3 classes, o que e'
   necessario pra vencer .range (2) -- e o outline: none em .editing vence o
   .active por vir depois com a mesma especificidade. */
table.sheet td.sheet-cell.range.active { box-shadow: none; }
table.sheet td.sheet-cell.editing { outline: none; }
table.sheet td.sheet-cell.range.editing { box-shadow: none; }

/* Enquanto arrasta, nao deixa o navegador selecionar o TEXTO das celulas
   (senao o gesto de selecionar celulas pinta texto azul por cima). */
table.sheet tbody { user-select: none; }
table.sheet td.sheet-cell .sheet-editor { user-select: text; }

.sheet-footer-selection {
  margin-left: auto;
  font-weight: 700;
  color: var(--brand-dark);
}


/* Alca de redimensionar coluna (pedido do usuario, 2026-07-30): fica na
   divisa direita do cabecalho da coluna. So aparece o cursor de resize --
   nenhuma borda visivel extra, pra nao poluir a grade. Depende do <th> ser
   posicionado (thead th e' sticky, o que ja serve de bloco de contencao). */
.sheet-col-resizer {
  position: absolute;
  top: 0;
  right: -3px;
  width: 7px;
  height: 100%;
  cursor: col-resize;
  z-index: 8;
  user-select: none;
}

.sheet-col-resizer:hover,
.sheet-col-resizer.dragging {
  background: var(--brand);
  opacity: 0.55;
}

/* Enquanto arrasta a divisa, o cursor de resize vale na tela toda (senao ele
   volta pro normal assim que o ponteiro sai dos 7px da alca). */
body.sheet-resizing,
body.sheet-resizing * {
  cursor: col-resize !important;
}


/* Texto de ajuda da planilha dentro do popup (o paragrafo longo saiu da
   toolbar e virou icone de informacao ao lado do contador, 2026-07-30). */
.sheet-help-list {
  display: grid;
  gap: 0.55rem;
  margin: 0.2rem 0 1rem;
  font-size: 0.82rem;
  color: var(--text-muted);
  line-height: 1.45;
}

.sheet-help-list p { margin: 0; }
.sheet-help-list strong { color: var(--text); }


/* --- Planilha do cadastro de produto ------------------------------------- */
/* Linhas mais altas que na planilha de anuncios (pedido do usuario) -- a
   primeira coluna e' de fotos, entao a linha precisa caber miniatura. */
table.sheet.sheet-tall td.sheet-cell,
table.sheet.sheet-tall td.sheet-fixed {
  padding-top: 0.7rem;
  padding-bottom: 0.7rem;
}

table.sheet.sheet-tall td.sheet-photos-cell {
  padding: 0.35rem 0.4rem;
  overflow: visible;
  white-space: normal;
  cursor: default;
}

.sheet-photos {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex-wrap: nowrap;
  overflow-x: auto;
  /* mesma causa raiz do scroll vertical de .ad-tab-bar (ver comentario la):
     overflow-x sem overflow-y pareado promove o eixo Y pra auto sozinho. */
  overflow-y: hidden;
}

.sheet-photo {
  width: 46px;
  height: 46px;
  flex: 0 0 auto;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
  cursor: grab;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sheet-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;   /* o alvo do drag/menu e' sempre o quadrado */
}

.sheet-photo.dragging { opacity: 0.45; }

.sheet-photo-add {
  width: 46px;
  height: 46px;
  min-height: 0;
  flex: 0 0 auto;
  padding: 0;
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1;
  border: 1px dashed var(--border-strong) !important;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--text-muted);
  box-shadow: none;
}

.sheet-photo-add:hover {
  border-color: var(--brand) !important;
  background: var(--brand-soft);
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}


/* Coluna de acao no fim das caracteristicas: so' o "+" no cabecalho, celulas
   inertes (pedido do usuario 2026-07-30 -- criar caracteristica nova dali). */
table.sheet thead th.sheet-add-col-head {
  text-align: center;
  padding: 0.2rem;
}

.sheet-add-carac-btn {
  width: 24px;
  height: 24px;
  min-height: 0;
  padding: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
  border-radius: 50%;
  border: 1px dashed var(--border-strong) !important;
  background: var(--surface);
  color: var(--text-muted);
  box-shadow: none;
}

.sheet-add-carac-btn:hover {
  border-color: var(--brand) !important;
  background: var(--brand-soft);
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}

table.sheet td.sheet-add-col-cell {
  background: var(--bg-alt);
  cursor: default;
}

/* --- Rodape com o contador de anuncios ---------------------------------- */
.sheet-footer {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.7rem;
  padding: 0.5rem 0.85rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.sheet-footer-sep { color: var(--border-strong); }

/* Em tela estreita nao ha espaco pras duas colunas: o painel passa a ocupar a
   largura toda, logo acima da lista (o contexto e' o que interessa no
   momento em que se esta respondendo). */
@media (max-width: 1100px) {
  .questions-layout.side-open {
    grid-template-columns: 1fr;
  }

  .questions-side-panel {
    position: static;
    max-height: none;
    order: -1;
  }
}

/* ============================================================================
   POPUPS -- CABECALHO E BOTAO DE FECHAR
   ==========================================================================*/

/* Titulo de popup nao quebra mais em duas linhas: como o cabecalho e' flex
   com gap, titulos mais longos ("Preencher planilha do Mercado Livre com IA",
   42 caracteres) eram comprimidos pelo botao de fechar e partiam no meio.
   O titulo agora pode crescer (flex) e o botao nunca encolhe. */
.modal-head {
  align-items: flex-start;
  gap: 0.75rem;
}

.modal-head h3 {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 1.05rem;
  line-height: 1.35;
}

/* Fechar em vermelho (pedido do usuario, 2026-07-24): era `--text-muted`,
   que ficava apagado contra o fundo branco do popup e passava batido.
   Vale pra TODO botao de fechar popup do sistema. */
.modal-close,
.questions-side-head .icon-btn {
  flex: 0 0 auto;
  background: transparent;
  border: none;
  box-shadow: none;
  color: var(--danger);
  font-size: 1.05rem;
  line-height: 1;
  transition: background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}

.modal-close:hover,
.questions-side-head .icon-btn:hover {
  background: var(--error-bg);
  border: none;
  box-shadow: none;
  transform: none;
  color: var(--danger-dark);
}

/* ============================================================================
   PERGUNTAS -- DISTRIBUICAO DOS DADOS NO PAINEL LATERAL
   ==========================================================================*/

/* O grid de detalhes e' de 3 colunas (pensado pra popup largo). Dentro da
   coluna lateral (~420px) isso dava ~120px por celula: rotulo e valor
   quebravam em varias linhas e os campos desalinhavam entre si. Duas colunas
   acomodam bem, e campos de conteudo longo (OEM com varios codigos, titulo)
   ocupam a linha inteira. */
.questions-side-panel .category-details-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem 0.9rem;
  margin-bottom: 0.9rem;
}

/* Os itens sao `div > strong + span` montados em JS (qpItem), sem classe
   propria -- por isso o seletor pega o filho direto do grid. */
.questions-side-panel .category-details-grid > div {
  min-width: 0;
}

/* Valor quebra por caractere quando e' um codigo unico gigante (OEM com
   varias referencias), em vez de estourar a largura da celula. */
.questions-side-panel .category-details-grid > div > strong {
  overflow-wrap: anywhere;
}

/* Celula "Usuario" das listas de Configuracoes: avatar + nome/permissoes na
   mesma linha, alinhados pelo topo (a linha de permissoes pode ter duas
   linhas de texto e nao deve puxar o avatar pro meio). */
.user-cell {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  min-width: 0;
}

.user-cell > div {
  min-width: 0;
}

.user-cell .field-hint {
  display: block;
  margin: 0.15rem 0 0;
}

/* Mensagem do teste de conexao/integracao dentro da celula. */
.table-card .connection-test-message {
  display: block;
  margin: 0.15rem 0 0;
}

/* ============================================================================
   BASE DE CONHECIMENTO -- MATERIAL + GARIMPO DE PRODUTOS
   ============================================================================
   Pedido do usuario (2026-07-24): ao abrir um material, uma coluna a direita
   onde a IA garimpa o texto atras de produtos ja cadastrados e sugere o
   cadastro dos novos. Mesma logica visual da coluna de contexto das
   Perguntas: a coluna so' aparece quando acionada, e a esquerda encolhe.
   ==========================================================================*/

.knowledge-edit-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  align-items: start;
}

.knowledge-edit-layout.prospect-open {
  grid-template-columns: minmax(0, 1fr) minmax(340px, 440px);
}

.knowledge-prospect-panel {
  display: none;
  position: sticky;
  top: 5.5rem;
  max-height: calc(100vh - 7rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  flex-direction: column;
}

.knowledge-edit-layout.prospect-open .knowledge-prospect-panel {
  display: flex;
  animation: rise-in var(--dur-base) var(--ease-out);
}

.knowledge-prospect-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-alt);
}

.knowledge-prospect-head h3 { margin: 0; font-size: 1rem; }

.knowledge-prospect-body {
  padding: 1rem;
  overflow-y: auto;
}

.prospect-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.prospect-item {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

/* Ja cadastrado fica mais apagado -- nao e' acao, e' so referencia. */
.prospect-item.is-existing {
  background: var(--bg-alt);
  opacity: 0.85;
}

.prospect-check {
  margin-top: 0.15rem;
  accent-color: var(--brand);
  flex: 0 0 auto;
  /* Sem isto o checkbox herda o `width: 100%` global de formulario e come a
     largura toda da linha, esmagando o texto do produto pra 0px. */
  width: 16px;
  height: 16px;
}

.prospect-info {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
  flex: 1;
  font-size: 0.82rem;
}

.prospect-info strong { overflow-wrap: anywhere; }

.prospect-item .badge { flex: 0 0 auto; }

@media (max-width: 1100px) {
  .knowledge-edit-layout.prospect-open {
    grid-template-columns: 1fr;
  }

  .knowledge-prospect-panel {
    position: static;
    max-height: none;
    order: -1;
  }
}

/* ============================================================================
   PILHA DE AVISOS DO CANTO INFERIOR DIREITO
   ============================================================================
   Pedido do usuario (2026-07-24): flash, loading, fila de IA e toast de
   salvar ficavam cada um com um `bottom` fixo hardcoded, o que ja tinha
   causado sobreposicao (e exigido remendo no mobile). Agora todos vivem
   nesta pilha flex: ancorada embaixo/direita, cresce pra cima conforme os
   avisos aparecem, com espaco entre eles -- nunca se cobrem.
   Os quatro elementos sao movidos pra ca por JS (appendChild) em base.html.
   ==========================================================================*/

.toast-stack {
  /* --stack-bottom centraliza o deslocamento inferior (nav mobile, banner
     de cookies, etc.) numa unica variavel -- e' o que permite calcular a
     altura maxima disponivel de verdade, em vez de um numero fixo que nao
     bate quando a pilha esta' deslocada pra cima (2026-08-16). Os overrides
     abaixo (mobile/cookie banner) mudam so' a variavel, nunca `bottom`
     direto, senao a conta da altura fica errada. */
  --stack-bottom: 1.5rem;
  position: fixed;
  right: 1.5rem;
  bottom: var(--stack-bottom);
  /* z-index no topo dos avisos (flash ja usava 80, loading 90) -- a pilha
     inteira sobe pra 90, abaixo so' dos modais de confirmacao (nenhum passa
     de 200) quando eles precisam bloquear. */
  z-index: 90;
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-end;
  gap: 0.75rem;
  /* Rede de seguranca da altura: cada aviso ja limita a propria altura
     (.flash/.corner-toast/.loading-overlay-box), mas com varios avisos
     abertos ao mesmo tempo a PILHA inteira tambem nao pode passar do topo
     da tela -- acima disso ela rola em vez de estourar. */
  max-height: calc(100vh - var(--stack-bottom) - 1rem);
  overflow-y: auto;
  overflow-x: hidden;
  /* A pilha em si nao intercepta clique -- so' os avisos dentro dela (a
     rolagem por scroll continua funcionando: o evento comeca num filho com
     pointer-events:auto e sobe ate' o ancestral rolavel normalmente). */
  pointer-events: none;
  max-width: min(340px, calc(100vw - 2rem));
}

.toast-stack::-webkit-scrollbar { width: 6px; }

/* Cada aviso perde o posicionamento fixo proprio e passa a fluir na pilha.
   `!important` porque as regras originais (.flash-list/.corner-toast/etc) e
   os overrides antigos de mobile setam position/bottom/right com peso maior
   -- aqui a pilha e' a unica fonte de verdade da posicao. */
.toast-stack > * {
  position: static !important;
  right: auto !important;
  bottom: auto !important;
  left: auto !important;
  top: auto !important;
  margin: 0 !important;
  pointer-events: auto;
  width: 300px;
  max-width: 100%;
}

/* O flash-list e' um pouco mais largo por design (cards de mensagem). */
.toast-stack > #flash-list {
  width: 320px;
}

/* Override mobile da pilha de avisos -- fica no FIM do arquivo, DEPOIS da
   definicao base de .toast-stack, senao a base (declarada mais abaixo que a
   media query antiga) venceria por ordem de cascata e a pilha ficaria por
   baixo da barra de navegacao inferior. */
@media (max-width: 980px) {
  .toast-stack {
    --stack-bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px));
    right: 0.75rem;
  }
}

/* Coluna "Nome" da lista de Planos (Organizacoes): tinha so ~99px porque o
   cabecalho de "Limites" (col-nowrap, texto longo numa linha) devorava a
   largura. Piso generoso aqui garante espaco pro nome + descricao do plano. */
.table-card #plan-table .col-plan-name {
  min-width: 220px;
  white-space: normal;
}

/* Coluna "Modulos" da lista de Planos: tinha .col-nowrap (width:1%), que
   espremia os 3 badges (IA/Catalogo/Perguntas) + badges de plataforma numa
   coluna minima. Piso generoso pra caber tudo numa leitura confortavel. */
.table-card #plan-table .col-plan-modules {
  min-width: 260px;
  white-space: normal;
}

/* Coluna "Nome" da lista de Organizacoes: nome + badge "Principal" ficavam
   espremidos contra a coluna "Tag" vizinha. */
.table-card #org-table .col-org-name {
  min-width: 200px;
  white-space: normal;
}

/* Coluna "Integracao" (Configuracoes > Integracoes): piso generoso pra
   nome + tag de plataforma (MLB/SHPP/TKTK/AMZN) + linhas extra de
   Usuario ML/Shop ID, sem ficar espremida contra "Empresa". A tag de
   plataforma fica ABAIXO do nome (div propria no template), nao mais do
   lado -- .col-integration-name empilha tudo em coluna. */
.table-card #integrations-table .col-integration-name {
  min-width: 200px;
  white-space: normal;
}
.table-card #integrations-table .col-integration-name > div {
  margin-top: 0.25rem;
}

/* Escopos da autorizacao (2026-07-30): a lista pode ser longa (o ML manda
   "offline_access read write", o TikTok manda varios escopos separados) --
   trunca em 2 linhas com o texto completo no tooltip, pra nao esticar a
   coluna nem empurrar as demais. */
.integration-scopes-value {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
  color: var(--text-muted);
}

/* Botao "inserir link" dentro de cada produto semelhante (Perguntas): mesma
   cara discreta do link de inserir do produto principal, so' que na linha da
   lista de semelhantes. */
.qa-similar-list li {
  flex-wrap: wrap;
}

.qa-similar-insert {
  margin-left: auto;
}

/* Select de status das Perguntas: sem isso ele herda o `width: 100%` global
   de formulario, estica pra largura toda da area de acoes e empurra o botao
   "Atualizar" pra uma segunda linha. Largura automatica mantem select +
   botao na mesma linha, alinhados a direita. */
#questions-status-select {
  width: auto;
  min-width: 8.5rem;
  flex: 0 0 auto;
}

/* Area de acoes da toolbar nao quebra em duas linhas no desktop -- so' cede
   pra empilhar no celular (onde a toolbar inteira ja vira coluna e um botao
   de texto longo tipo "Importar marcas dos produtos" precisaria quebrar). */
@media (min-width: 621px) {
  .toolbar-actions-right {
    flex-wrap: nowrap;
  }
}

/* Barra de progresso do garimpo em tempo real (Base de conhecimento). */
.prospect-progress {
  margin: 0.75rem 0;
}

.prospect-progress-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--bg-alt);
  overflow: hidden;
  margin-bottom: 0.35rem;
}

.prospect-progress-fill {
  height: 100%;
  width: 0;
  background: var(--brand);
  border-radius: 999px;
  transition: width var(--dur-base) var(--ease-out);
}

/* Item da lista de garimpo ja "usado" (aproveitado/cadastrado): fica
   esmaecido, como referencia -- nao e' mais uma acao pendente. */
.prospect-item.is-used {
  opacity: 0.6;
}

.prospect-item-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.25rem;
  flex: 0 0 auto;
}

/* Botao discreto de alternar usado/nao usado, no espirito dos links de acao
   secundaria do sistema (sem cara de botao solido). */
.prospect-used-toggle {
  height: auto;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text-muted);
  font-size: 0.7rem;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.prospect-used-toggle:hover {
  background: none;
  border: none;
  box-shadow: none;
  transform: none;
  color: var(--brand-dark);
}

/* ============================================================================
   SELETOR MULTI-EMPRESA POR CHIPS (Anuncios e Perguntas)
   ============================================================================
   Substitui o menu de empresa do topbar (2026-07-24): fica ao lado da busca,
   permite escolher varias empresas (cada uma um chip com "x"); nenhuma =
   todas. */
.company-chip-filter {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.company-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  height: 1.7rem;
  padding: 0 0.2rem 0 0.55rem;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand-dark);
  border: 1px solid var(--brand);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}

.company-chip-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Circulo bem menor que o chip (27px) pra nunca estourar: 16px, centralizado
     pelo align-items:center do proprio chip. */
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--danger);
  font-size: 0.8rem;
  line-height: 1;
  box-shadow: none;
}

.company-chip-x:hover {
  background: var(--danger);
  color: #fff;
  transform: none;
  box-shadow: none;
}

.company-chip-all {
  font-size: 0.82rem;
}

.company-add {
  position: relative;
  display: inline-flex;
}

.company-add-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  height: 1.7rem;
  padding: 0 0.6rem;
  border-radius: 999px;
  background: transparent;
  border: 1px dashed var(--border-strong);
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 600;
  box-shadow: none;
}

.company-add-btn svg { width: 12px; height: 12px; }

.company-add-btn:hover {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}

.company-add-menu {
  display: none;
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  z-index: 50;
  min-width: 12rem;
  max-height: 16rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 0.35rem;
}

.company-add-menu.open {
  display: block;
  animation: dropdown-in var(--dur-base) var(--ease-spring);
  transform-origin: top left;
}

.company-add-option {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.5rem 0.6rem;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font-size: 0.82rem;
  font-weight: 500;
  box-shadow: none;
}

.company-add-option:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
  transform: none;
  box-shadow: none;
}

/* ============================================================================
   TOOLTIP TEMATIZADO GLOBAL
   ============================================================================
   Substitui o balao nativo do navegador (atributo title) por um no tema do
   sistema, pra qualquer elemento com title (2026-07-24). Fundo grafite do
   menu, mesma cara dos demais tooltips do app. */
.app-tooltip {
  position: fixed;
  z-index: 200;
  max-width: 18rem;
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--dark);
  color: #fff;
  font-size: 0.76rem;
  font-weight: 500;
  line-height: 1.35;
  box-shadow: var(--shadow-md);
  pointer-events: none;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

.app-tooltip.open {
  opacity: 1;
  transform: translateY(0);
}

/* Banner de descricao/dicas no topo do Banco de Conhecimento (pedido do
   usuario, 2026-07-27: "qnd aberto dele ter uma descricao ao top... dicas
   para ser usado da melhor maneira"). */
.knowledge-intro-banner {
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  background: var(--brand-soft);
  border: 1px solid rgba(33, 150, 243, 0.28);
  border-radius: var(--radius-md);
  padding: 1rem 1.2rem;
  margin-bottom: 1.25rem;
}
.knowledge-intro-icon {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-solid);
  color: var(--brand-dark);
}
.knowledge-intro-body h3 {
  margin: 0 0 0.35rem;
  color: var(--brand-dark);
  font-size: 0.98rem;
}
.knowledge-intro-body p {
  margin: 0 0 0.5rem;
  color: var(--text);
  font-size: 0.87rem;
  line-height: 1.55;
}
.knowledge-intro-tips-label {
  font-weight: 600;
  color: var(--brand-dark);
  margin-bottom: 0.3rem !important;
}
.knowledge-intro-tips {
  margin: 0;
  padding-left: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.knowledge-intro-tips li {
  color: var(--text-muted);
  font-size: 0.85rem;
  line-height: 1.5;
}
@media (max-width: 620px) {
  .knowledge-intro-banner { flex-direction: column; }
}

/* Grafico de atividade de anuncios por dia (pedido do usuario,
   2026-07-27), acima da lista em ads.html. */
.activity-chart-panel { margin-bottom: 1.25rem; }
.activity-chart-panel .panel-head { margin-bottom: 0.75rem; }
.activity-chart-range-select {
  width: auto;
  min-width: 160px;
  height: var(--field-h);
}
.activity-chart-canvas-wrap {
  position: relative;
  height: 260px;
  width: 100%;
}

/* Icone "i" com tooltip ao lado de um titulo de painel (pedido do usuario,
   2026-07-27: trocar texto de ajuda solto por icone+tooltip, ex. "Fotos do
   produto"). Reusa o tooltip tematico global (title -> #app-tooltip). */
.panel-head-title-group {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.panel-head-info-btn {
  width: 22px;
  height: 22px;
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  color: var(--text-muted);
}
.panel-head-info-btn svg { width: 14px; height: 14px; }

/* Resumo por plataforma no dashboard (pedido do usuario, 2026-07-27) -- so
   aparece com mais de uma plataforma em uso; largura livre em vez dos 4
   fixos de .stats, ja que o numero de cartoes varia. */
.dashboard-platform-stats {
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.dashboard-platform-card { gap: 0.5rem; }
.dashboard-platform-card .platform-tag {
  align-self: flex-start;
  /* Mesmo ritmo vertical do icone-padrao dos cards vizinhos (.card-icon,
     34x34px + margin-bottom: 0.6rem) -- a tag de plataforma substitui o
     icone nesse card, mas sem essa margem ela ficava colada no numero
     logo abaixo, destoando do espacamento dos demais cards da mesma
     secao (pedido do usuario, 2026-07-30: "ajustar a tag pro padrao
     correto"). */
  margin-bottom: 0.6rem;
}

/* ============================================================================
   ACOES EM MASSA NA LISTA DE PRODUTOS -- FOTOS E ESTOQUE
   Pedido do usuario (2026-07-28): popup grande listando os selecionados, com
   uma faixa de miniaturas arrastaveis por produto e um tile "+" no fim.
   ==========================================================================*/

.bulk-photos-list {
  display: grid;
  gap: 0.75rem;
  max-height: 60vh;
  overflow-y: auto;
  margin: 0.5rem 0 1rem;
}

.bulk-photo-row {
  display: grid;
  grid-template-columns: minmax(140px, 220px) minmax(0, 1fr);
  gap: 1rem;
  align-items: center;
  padding: 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
}

.bulk-photo-info {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.bulk-photo-info strong {
  font-size: 0.85rem;
}

.bulk-photo-info .field-hint {
  margin: 0;
  font-size: 0.75rem;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.bulk-photo-strip {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-wrap: wrap;
  min-width: 0;
}

.bulk-photo-tile {
  position: relative;
  width: 64px;
  height: 64px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #fff;
  cursor: grab;
  flex: 0 0 auto;
}

.bulk-photo-tile.dragging {
  opacity: 0.5;
}

.bulk-photo-tile img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  pointer-events: none;
}

.bulk-photo-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.7rem;
  line-height: 1;
  box-shadow: none;
}

.bulk-photo-remove:hover {
  background: var(--danger);
  border: none;
  box-shadow: none;
  transform: none;
}

.bulk-photo-add {
  width: 64px;
  height: 64px;
  min-height: 0;
  padding: 0;
  flex: 0 0 auto;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  font-size: 1.3rem;
  line-height: 1;
  box-shadow: none;
}

.bulk-photo-add:hover {
  background: var(--brand-soft);
  border: 1px dashed var(--brand);
  box-shadow: none;
  transform: none;
  color: var(--brand-dark);
}

/* Estoque em massa: um campo por produto, rotulo a esquerda. */
.bulk-estoque-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bulk-estoque-input {
  flex: 0 0 140px;
}

@media (max-width: 720px) {
  .bulk-photo-row {
    grid-template-columns: 1fr;
  }
}

/* Contador de caracteres dos campos com limite por canal (titulo/descricao).
   O limite vem da plataforma do anuncio -- Shopee consulta a API real da
   loja, entao o numero nunca e' fixo no CSS/HTML. */
.text-limit-counter {
  display: block;
  margin-top: 0.3rem;
  font-variant-numeric: tabular-nums;
}
.text-limit-counter.over-limit {
  color: var(--error-text);
  font-weight: 600;
}

/* Chip de loja do anuncio, clicavel pra trocar de loja (2026-07-29).
   Aparece mesmo sem loja definida -- anuncio sem jeito de corrigir a loja
   travava a publicacao. */
.store-owner-chip-pick {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  transition: background var(--dur-fast) var(--ease-out);
}
.store-owner-chip-pick:hover {
  background: var(--brand-soft);
  color: var(--brand-dark);
}
.store-owner-chip-warn {
  background: var(--warning-bg);
  color: var(--warning-text);
}
.ad-store-menu { min-width: 210px; }
.ad-store-menu.open { display: flex; flex-direction: column; }

/* Qualidade na lista: barra simples pro score GERAL e arco tipo conta-giros
   por bloco (pedido do usuario, 2026-07-29). O arco reusa o mesmo desenho
   dos gauges da aba de metricas -- semicirculo raio 50. */
.quality-total-bar {
  height: 8px;
  border-radius: 99px;
  background: var(--neutral-soft);
  overflow: hidden;
  margin: 0.1rem 0 0.9rem;
}
.quality-total-bar span {
  display: block;
  height: 100%;
  border-radius: 99px;
  transition: width var(--dur-slow) var(--ease-out);
}
.quality-total-bar span.tone-ok { background: var(--success-text); }
.quality-total-bar span.tone-warn { background: var(--warning-text); }
.quality-total-bar span.tone-bad { background: var(--error-text); }

.quality-gauge-inline {
  position: relative;
  width: 110px;
  margin: 0.2rem 0 0.6rem;
}
.quality-gauge-inline .quality-gauge-svg { width: 100%; height: auto; display: block; }
.quality-gauge-inline .quality-gauge-value {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  text-align: center;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
}
.quality-gauge-fill.tone-ok { stroke: var(--success-text); }
.quality-gauge-fill.tone-warn { stroke: var(--warning-text); }
.quality-gauge-fill.tone-bad { stroke: var(--error-text); }

/* Planilha de edicao em massa em tela estreita: o scroll horizontal e'
   inerente (dezenas de colunas), so damos mais altura util e escondemos o
   texto de ajuda longo da toolbar. Fica no FIM do arquivo de proposito --
   regra do projeto: media query no meio do styles.css perde por cascata. */
@media (max-width: 980px) {
  .sheet-wrap { max-height: calc(100vh - 200px); }
  .sheet-toolbar-info .field-hint { display: none; }
  .sheet-editor-area { width: 260px; min-width: 260px; }
  .sheet-group-inner { max-width: calc(100vw - 60px); }
}

/* Chat de vendas em 3 areas (pedido do usuario, 2026-07-29: "duas colunas,
   uma com o chat e outra com dados do produto e da venda" -- a lista de
   conversas fica numa faixa propria a esquerda). */
.msg-layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr) 300px;
  gap: 1rem;
  align-items: start;
}
/* Cabecalho da sidebar ("Conversas" + contador) fica FIXO, so' a lista de
   itens rola -- antes .msg-sidebar inteira (cabecalho junto) tinha o
   overflow, entao o titulo sumia rolando junto com as conversas. Mesmo
   principio ja usado em qualquer .table-card do sistema (.table-scroll so'
   envolve o <table>, nunca o .panel-head). */
.msg-sidebar { display: flex; flex-direction: column; max-height: calc(100vh - 220px); }
.msg-lista { overflow-y: auto; flex: 1; }
.msg-lista-vazia { padding: 0 1.2rem 1rem; }
.msg-item-loja { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-item {
  /* .msg-item e' um <button> -- o global "button { height: var(--field-h);
     align-items:center; justify-content:center; }" (regra por elemento) so'
     perde pra classe em specificidade nas propriedades que ESTA regra
     redeclara explicitamente; qualquer propriedade omitida aqui (height,
     align-items, justify-content) cai de volta pro valor do global, travando
     o botao em ~38px de altura fixa e centralizando tudo -- foi exatamente
     isso que esmagava a previa ("Venda XXXX") a 0px de altura e centralizava
     o titulo. Mesma armadilha ja documentada varias vezes neste arquivo
     (hover de .ad-tab-btn, fundo de .copy-icon-btn) -- SEMPRE redeclarar
     height/align-items/justify-content num <button> customizado com layout
     proprio de coluna. */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  height: auto;
  gap: 0.2rem;
  width: 100%;
  text-align: left;
  padding: 0.7rem 1.2rem;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  min-height: 0;
  cursor: pointer;
  color: var(--text);
}
.msg-item:hover { background: var(--bg-alt); box-shadow: none; transform: none; }
.msg-item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.msg-item.ativo { background: var(--brand-soft); }
.msg-item-topo { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
/* Badge de nao-lida + botao "..." de arquivar/excluir agrupados no canto
   direito da linha (pedido do usuario, 2026-08-01: "opção de arquivas no app
   e de excluir") -- mesmo tamanho compacto ja usado em .copy-icon-btn pra
   nao competir visualmente com o titulo da conversa. */
.msg-item-topo-right { display: flex; align-items: center; gap: 0.35rem; flex-shrink: 0; }
.msg-item-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  border: none;
  background: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
  color: var(--text-faint);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.msg-item-menu-btn svg { width: 13px; height: 13px; }
.msg-item-menu-btn:hover { background: var(--border); color: var(--text); transform: none; box-shadow: none; }
.msg-item-previa {
  font-size: 0.8rem;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msg-item-rodape { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.2rem; }

.msg-conversa { display: flex; flex-direction: column; min-height: 420px; }
.msg-balloes {
  flex: 1;
  overflow-y: auto;
  max-height: calc(100vh - 340px);
  padding: 0.5rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.msg-balao {
  max-width: 72%;
  align-self: flex-start;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.55rem 0.75rem;
}
.msg-balao.meu { align-self: flex-end; background: var(--brand-soft); border-color: var(--brand-soft); }
.msg-balao p { margin: 0; font-size: 0.88rem; white-space: pre-wrap; }
.msg-balao-hora { display: block; margin-top: 0.25rem; font-size: 0.7rem; color: var(--text-muted); }

.msg-envio {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
  padding: 0.8rem 1.2rem 1rem;
  border-top: 1px solid var(--border);
}
.msg-envio textarea { flex: 1; height: auto; min-height: 2.6rem; }

.msg-contexto-corpo { display: grid; gap: 0.4rem; padding: 0 1.2rem 1.2rem; }
.msg-contexto-foto {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.msg-contexto-titulo { font-size: 0.9rem; line-height: 1.35; }

@media (max-width: 1100px) {
  .msg-layout { grid-template-columns: 1fr; }
  .msg-sidebar, .msg-balloes { max-height: 340px; }
}

/* Acoes do pedido (Vendas) -- hierarquia: a acao sugerida pra etapa atual
   vira um cartao destacado com icone e explicacao; as demais viram botoes
   compactos com icone; a destrutiva fica separada a direita. */
.order-actions { display: grid; gap: 0.7rem; margin-top: 0.9rem; }

.order-action-primary {
  display: flex;
  align-items: center;
  /* O button global centraliza o conteudo -- aqui o cartao tem icone +
     titulo + explicacao, entao alinha tudo a esquerda. */
  justify-content: flex-start;
  gap: 0.7rem;
  width: 100%;
  text-align: left;
  padding: 0.7rem 0.9rem;
  height: auto;
  border-radius: var(--radius-md);
}
.order-action-primary svg { width: 22px; height: 22px; flex: 0 0 auto; }
.order-action-primary span { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.order-action-primary strong { font-size: 0.92rem; font-weight: 700; }
.order-action-primary small { font-size: 0.75rem; opacity: 0.85; font-weight: 500; }

.order-actions-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.order-action-btn { display: inline-flex; align-items: center; gap: 0.4rem; }
.order-action-btn svg { width: 15px; height: 15px; flex: 0 0 auto; }
/* Empurra a acao destrutiva pro fim da linha -- longe das demais.
   IMPORTANTE: so' a PRIMEIRA da dupla leva o margin-left:auto. Com o auto nas
   duas (Cancelar + Excluir), cada uma empurrava a outra e elas ficavam
   separadas por um vao enorme -- reportado pelo usuario em 2026-08-01
   ("estao muito espacados um do outro, certo ficar alinhados a direita
   juntos e com espacamento padrao"). A segunda cola na primeira com o gap
   normal da linha. */
.order-action-danger { margin-left: auto; }
.order-action-danger ~ .order-action-danger { margin-left: 0; }

/* Reorganizacao dos botoes (2026-07-31, "organizar melhor os botoes"): as
   secundarias ficam separadas da destrutiva por um traco vertical, pra ficar
   obvio que "Excluir/Cancelar" nao sao do mesmo grupo das operacoes do dia a
   dia. Em tela estreita o traco some (a linha ja quebra). */
.order-actions-row .order-action-danger { position: relative; }
.order-actions-row .order-action-danger::before {
  content: "";
  position: absolute;
  left: -0.55rem;
  top: 15%;
  height: 70%;
  width: 1px;
  background: var(--border-strong);
}
/* O divisor separa o GRUPO destrutivo do resto -- entre Cancelar e Excluir
   nao deve ter traco nenhum (elas sao do mesmo grupo). */
.order-actions-row .order-action-danger ~ .order-action-danger::before { display: none; }
@media (max-width: 700px) {
  .order-action-danger { margin-left: 0; }
  .order-actions-row .order-action-danger::before { display: none; }
}

/* Venda ainda nao aberta na lista (2026-07-31) -- some sozinha quando o
   detalhe e' aberto (mark_order_viewed). Uma barra na lateral da linha + um
   badge no numero do pedido: da' pra bater o olho e ver o que chegou. */
.badge-nova-venda {
  background: var(--warning-bg);
  color: var(--warning-text);
  font-weight: 700;
}
/* ATENCAO: usar --warning-text/--warning-bg (existem no :root). Nao existe
   nenhuma variavel chamada so' "--warning" -- var() indefinida invalida a
   propriedade INTEIRA em silencio, e a regra simplesmente nao aplica (foi o
   que aconteceu na primeira versao desta linha). */
tbody tr.venda-nao-vista > td:first-child { box-shadow: inset 3px 0 0 var(--warning-text); }
tbody tr.venda-nao-vista > td { background: var(--warning-bg); }

/* Realce discreto quando uma venda muda/entra em tempo real -- so' a LINHA
   pisca, nunca a tela toda (ver aplicarFragmentoVendas em vendas.html). */
@keyframes linha-destaque {
  from { background: var(--brand-soft); }
  to { background: transparent; }
}
.linha-atualizada > td,
.linha-nova > td {
  animation: linha-destaque 1.6s var(--ease-out);
}
@media (prefers-reduced-motion: reduce) {
  .linha-atualizada > td, .linha-nova > td { animation: none; }
}

/* Campo de envio do chat com contador embaixo (limite por canal). */
.msg-envio-campo { flex: 1; display: flex; flex-direction: column; gap: 0.2rem; }
.msg-envio-campo textarea { width: 100%; height: auto; min-height: 2.6rem; }

/* Badge de novidades no CABECALHO de um grupo do menu (hoje: Vendas).
   Laranja de propósito -- aparece mesmo com o grupo recolhido, pra sinalizar
   novidade sem o usuario precisar abrir o menu. */
.nav-group-badge {
  margin-left: auto;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 0.7rem;
  font-weight: 700;
  background: var(--warning, #ff9800);
  color: #fff;
}
/* Com o menu recolhido o cabecalho vira so' icone -- o badge encolhe pra
   uma bolinha, senao estoura a largura da faixa. */
body.sidebar-collapsed .nav-group-badge {
  position: absolute;
  top: 4px;
  right: 6px;
  min-width: 8px;
  height: 8px;
  padding: 0;
  font-size: 0;
}
body.sidebar-collapsed .nav-group-header { position: relative; }

/* ---------------------------------------------------------------------------
   Tela de Categorias -- lista (2026-08-01)
   Reportado: "a coluna grupo tudo pequena demais a largura". A causa era usar
   `.col-nowrap` nela, que tem `width: 1%` de proposito (encolhe ao maximo,
   pensado pra codigo/data/preco). Coluna com <select> precisa do oposto: um
   piso de largura, senao o navegador espreme o campo ate o nome do grupo
   ficar ilegivel.
--------------------------------------------------------------------------- */
.table-card .col-category-group {
  width: 1%;
  min-width: 190px;
  white-space: nowrap;
}
.table-card .col-category-group .category-group-select {
  width: 100%;
  min-width: 175px;
  height: 2rem;              /* menor que --field-h: cabe melhor na linha */
  padding: 0 1.6rem 0 0.55rem;
  font-size: 0.8rem;
}
/* Sem grupo definido, o select fica discreto -- so' ganha a cor da marca
   quando de fato ha' um vinculo, pra a lista mostrar de relance o que ja
   foi organizado. */
.table-card .category-group-select:not(.tem-grupo) {
  color: var(--text-muted);
  border-style: dashed;
}
.table-card .category-group-select.tem-grupo {
  border-color: var(--brand);
  color: var(--brand-dark);
  font-weight: 600;
}

/* Numero alinhado a' direita: coluna de contagem fica muito mais legivel
   quando as casas decimais se alinham verticalmente. */
.table-card .col-align-right { text-align: right; }
.table-card thead th.col-align-right { text-align: right; }

/* Peso/dimensoes como chips: dois valores curtos e independentes na mesma
   celula ficam ilegiveis soltos ("1.200 kg 20×15×10 cm" vira uma frase). */
.shipping-chip {
  display: inline-block;
  padding: 0.12rem 0.45rem;
  margin: 0.1rem 0.2rem 0.1rem 0;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  font-size: 0.72rem;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Celula vazia: "--" apagado comunica "sem dado" sem competir com o
   conteudo real da linha. */
.cell-empty { color: var(--text-faint); }

/* ---------------------------------------------------------------------------
   Cadastro de Grupo -- categorias por plataforma (2026-08-01)
   Refeito: a busca usava `.inline-form`, que e' um grid de DUAS colunas
   (1fr auto). Com o seletor de plataforma virando um terceiro elemento, o
   botao "Buscar" era empurrado pra linha de baixo e esticado na largura
   inteira. Aqui o grid tem as 3 colunas certas, na ordem de uso:
   plataforma -> termo -> acao.
--------------------------------------------------------------------------- */
.group-category-search {
  display: grid;
  grid-template-columns: minmax(150px, 190px) 1fr auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.9rem;
}
@media (max-width: 720px) {
  .group-category-search { grid-template-columns: 1fr; }
}

.group-category-list-label {
  margin: 1.2rem 0 0.5rem;
  font-weight: 600;
  color: var(--text);
}

.group-category-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* Card compacto: a versao anterior usava `.category-result` (pensado pra
   RESULTADO de busca, com padding grande e botao de acao) e empilhava nome,
   id e caminho em <p> soltos -- cada item ocupava ~130px de altura pra
   mostrar tres linhas curtas de texto. */
.group-category-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.group-category-item:hover { border-color: var(--border-strong); }

.group-category-info { min-width: 0; }  /* deixa o texto truncar de verdade */

.group-category-head {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  min-width: 0;
}
.group-category-head strong {
  font-size: 0.86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.group-category-id {
  font-size: 0.72rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.group-category-path {
  margin: 0.15rem 0 0;
  font-size: 0.72rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.group-category-empty {
  padding: 0.9rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  text-align: center;
  margin: 0;
}

/* ---------------------------------------------------------------------------
   Cadastro de Grupo -- Subgrupos e Características (2026-08-01)
   Padronizadas com a seção de Categorias: a AÇÃO de adicionar vem antes da
   lista (é ela que traz conteúdo), a lista tem itens de altura uniforme e
   estado vazio explícito em vez de sumir sem explicação.
--------------------------------------------------------------------------- */
.group-add-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.9rem;
}
/* Quando só há o botão (Características), ele não deve esticar na largura
   toda -- é a mesma armadilha que deixou o "Buscar" gigante em Categorias. */
.group-add-row-single { grid-template-columns: auto; justify-content: start; }
@media (max-width: 720px) {
  .group-add-row { grid-template-columns: 1fr; }
  .group-add-row-single { grid-template-columns: 1fr; }
}

.group-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.group-list-item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.group-list-item:hover { border-color: var(--border-strong); }

/* Numero da ordem: deixa claro que a sequência das características é a que
   vai aparecer no produto. */
.group-list-index {
  flex: 0 0 auto;
  width: 1.35rem;
  height: 1.35rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--bg-alt);
  color: var(--text-muted);
  font-size: 0.7rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.group-list-icon {
  flex: 0 0 auto;
  display: inline-flex;
  color: var(--text-faint);
}
.group-list-icon svg { width: 15px; height: 15px; }

.group-list-nome {
  flex: 1;
  min-width: 0;
  font-size: 0.86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Input dentro do item: sem borda própria -- a borda do item já delimita, e
   duas bordas aninhadas é o que deixava a lista com cara de formulário cru. */
.group-list-input {
  flex: 1;
  min-width: 0;
  height: 2rem;
  border: none;
  background: transparent;
  padding: 0 0.2rem;
  font-size: 0.86rem;
}
.group-list-input:focus {
  outline: none;
  box-shadow: none;
  border-bottom: 1px solid var(--brand);
  border-radius: 0;
}

.group-list-empty {
  padding: 0.9rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  text-align: center;
  margin: 0;
}

/* Rodapé do form de Grupo: ações alinhadas à direita, com a primária por
   último -- mesmo sentido de leitura das outras telas de edição. */
.group-form-actions {
  margin-top: 1rem;
  justify-content: flex-end;
}

/* Popup "Categoria do grupo" (tela do anúncio): reusa o card compacto do
   Cadastro de Grupo (.group-category-item) pra as duas telas falarem a mesma
   língua. A lista já chega filtrada pelo canal do anúncio. */
.category-group-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.6rem;
}
.category-group-label {
  margin: 0 0 0.2rem;
  font-weight: 600;
  color: var(--text);
}
.category-group-pick button { flex: 0 0 auto; }

/* Popup de plano (Organizações > Planos) -- reorganizado em SEÇÕES em
   2026-08-02 ("deixar moderno e padronizado"). Antes era uma única grade
   corrida com nome/limites/preço/módulos/plataformas/ativo misturados, sem
   hierarquia nenhuma. Cada seção tem seu próprio .form-grid, então o
   alinhamento de cada linha é resolvido dentro dela (regra permanente do
   projeto: célula de grade nunca carrega texto solto, e campo de uma seção
   nunca "vaza" pra próxima). */
.plan-form-section { margin-bottom: 1.1rem; }
.plan-form-section:last-of-type { margin-bottom: 0.9rem; }

.plan-form-section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.55rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.plan-form-section-hint {
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-faint);
}

/* Cada plataforma aparece com a MESMA tag colorida usada na lista de planos
   e no resto do sistema (regra permanente: tag de plataforma sempre com as
   cores dela) -- em vez de só o nome em texto puro. */
.plan-platform-label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.plan-platform-label .field-hint { font-size: 0.68rem; }

/* Rodapé: "Plano ativo" à esquerda (é um estado do plano, não uma ação) e os
   botões à direita, separados do corpo por uma linha -- mesmo padrão de
   rodapé já usado no Cadastro de Grupo (.group-form-actions). */
.plan-form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
}
.plan-form-footer .button-row { margin: 0; }

@media (max-width: 620px) {
  .plan-form-footer { align-items: stretch; }
  .plan-form-footer .button-row { justify-content: flex-end; }
}

/* Cabeçalho de "Menus visíveis"/"Empresas visíveis": contador + botão de
   marcar todos empurrados pro canto direito, sem depender de um
   `margin-left:auto` inline em cada botão (era assim antes). Usado tanto no
   popup de usuário de Configurações quanto no de Organizações. */
.menu-permission-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-left: auto;
}

/* ==========================================================================
   Dashboard (reescrito 2026-08-03)
   As cores de serie/estado sao custom properties definidas no <style> do
   proprio dashboard.html (--serie-N, --st-*), validadas com o validador de
   acessibilidade -- aqui so' se CONSOME por papel, nunca hex solto.
   ========================================================================== */

.dash-hero {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.4rem;
}
.dash-hero-text h2 { margin: 0 0 0.15rem; font-size: 1.5rem; letter-spacing: -0.02em; }
.dash-hero-text .field-hint { margin: 0; }

/* Seletor de periodo: pilulas segmentadas */
.dash-period {
  display: inline-flex; gap: 0.15rem; padding: 0.22rem;
  background: var(--bg-alt); border: 1px solid var(--border); border-radius: 999px;
}
.dash-period-btn {
  display: inline-flex; align-items: center; padding: 0.35rem 0.85rem;
  font-size: 0.78rem; font-weight: 600; color: var(--text-muted);
  border-radius: 999px; text-decoration: none;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.dash-period-btn:hover { color: var(--text); background: var(--surface); }
.dash-period-btn.active {
  background: var(--surface); color: var(--brand-dark);
  box-shadow: var(--shadow-sm);
}

/* --- KPIs --------------------------------------------------------------- */
.kpi-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 1rem; margin-bottom: 1.4rem;
}
.kpi-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 0.28rem;
  padding: 1.15rem 1.25rem 1rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  animation: rise-in var(--dur-base) var(--ease-out) backwards;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.kpi-row .kpi-card:nth-child(2) { animation-delay: 60ms; }
.kpi-row .kpi-card:nth-child(3) { animation-delay: 120ms; }
.kpi-row .kpi-card:nth-child(4) { animation-delay: 180ms; }
.kpi-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
/* Faixa de acento no topo: identifica o card sem colorir texto nenhum */
.kpi-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--kpi-cor, var(--serie-1));
}
.kpi-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.kpi-label {
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted);
}
.kpi-delta {
  display: inline-flex; align-items: center; gap: 0.15rem;
  padding: 0.12rem 0.4rem 0.12rem 0.28rem; border-radius: 999px;
  font-size: 0.7rem; font-weight: 700; white-space: nowrap;
}
.kpi-delta svg { width: 12px; height: 12px; }
.kpi-delta.up { background: var(--success-bg); color: var(--success-text); }
.kpi-delta.down { background: var(--warning-bg); color: var(--danger-dark); }
.kpi-value {
  font-size: 1.9rem; font-weight: 700; line-height: 1.1; color: var(--text);
  letter-spacing: -0.02em;
}
/* Hero figure: o unico numero grande da tela, sempre na mesma familia sans
   do resto -- nunca uma face de display. */
.kpi-hero .kpi-value { font-size: 2.6rem; }
.kpi-currency { font-size: 0.62em; font-weight: 600; color: var(--text-muted); margin-right: 0.18rem; }
.kpi-detalhe { font-size: 0.76rem; color: var(--text-muted); }
.kpi-spark { margin-top: 0.5rem; height: 28px; }
.kpi-spark svg { width: 100%; height: 28px; display: block; overflow: visible; }
.spark-line { fill: none; stroke: var(--kpi-cor, var(--serie-1)); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.spark-area { fill: var(--kpi-cor, var(--serie-1)); opacity: 0.1; }
.spark-dot { fill: var(--kpi-cor, var(--serie-1)); }

/* --- Grades e paineis --------------------------------------------------- */
.dash-grid-2 {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 1.1rem; margin-bottom: 1.1rem;
}
/* Divisoria entre as secoes do Dashboard completo do Painel Admin
   (Cobranca/Suporte, 2026-08-14) -- .list-title nao tem margin-top, e sem
   ele as secoes coladas ficavam dificeis de separar visualmente. */
.admin-dash-section-title {
  margin: 1.6rem 0 0.9rem; font-size: 1.1rem; font-weight: 700;
  letter-spacing: -0.01em; color: var(--text);
}
.dash-panel { padding-bottom: 1.15rem; }
.dash-revenue { margin-bottom: 1.1rem; }
.dash-empty {
  margin: 0; padding: 2rem 1.75rem; text-align: center;
  color: var(--text-muted); font-size: 0.86rem;
}
.dash-money { font-variant-numeric: tabular-nums; font-weight: 600; }

/* Totais do faturamento no cabecalho do painel */
.dash-revenue-totais { display: flex; flex-wrap: wrap; gap: 0.35rem 1.1rem; align-items: baseline; }
.dash-revenue-total { display: inline-flex; flex-direction: column; line-height: 1.25; }
.dash-revenue-total em {
  font-style: normal; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--text-faint);
}
.dash-revenue-total b { font-size: 0.92rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.dash-revenue-total.is-geral b { font-size: 1.05rem; color: var(--text); }

/* --- Barras horizontais (funil de vendas) ------------------------------- */
.dash-bars { list-style: none; margin: 0; padding: 0 1.75rem 0.25rem; display: grid; gap: 0.6rem; }
.dash-bar-row {
  display: grid; grid-template-columns: minmax(120px, 1.1fr) 3fr auto;
  align-items: center; gap: 0.75rem;
}
.dash-bar-label { font-size: 0.8rem; color: var(--text-muted); }
.dash-bar-track { height: 9px; border-radius: 999px; background: var(--bg-alt); overflow: hidden; }
.dash-bar-fill {
  display: block; height: 100%; border-radius: 999px;
  background: var(--bar-cor, var(--st-info));
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.06);
}
.dash-bar-value {
  font-size: 0.86rem; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; min-width: 1.8rem; text-align: right;
}
/* Brilho suave no preenchimento: da' profundidade sem depender de tempo,
   entao a barra esta sempre visivel com a largura real. */
.dash-bar-fill, .dash-step-fill, .dash-quality-fill {
  background-image: linear-gradient(90deg, rgba(255,255,255,0.22), rgba(255,255,255,0) 60%);
}
.dash-bar-track, .dash-step-track, .dash-quality-track {
  box-shadow: inset 0 1px 2px rgba(15, 23, 32, 0.06);
}

/* --- Etapas do anuncio -------------------------------------------------- */
.dash-steps { list-style: none; margin: 0; padding: 0 1.75rem; display: grid; gap: 0.7rem; }
.dash-step { display: grid; gap: 0.22rem; }
.dash-step-top { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.dash-step-label { font-size: 0.78rem; font-weight: 600; color: var(--text-muted); }
.dash-step-pct { font-size: 0.72rem; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.dash-step-value { font-size: 1.15rem; font-weight: 700; color: var(--text); line-height: 1.1; }
.dash-step-track { height: 6px; border-radius: 999px; background: var(--bg-alt); overflow: hidden; }
.dash-step-fill {
  display: block; height: 100%; border-radius: 999px;
  background: var(--step-cor, var(--st-info));
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.06);
}
.dash-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.9rem 1.75rem 0; }
.dash-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.25rem 0.55rem; border-radius: 8px;
  background: var(--bg-alt); border: 1px solid var(--border);
  font-size: 0.78rem; color: var(--text-muted);
}
.dash-chip b { color: var(--text); font-variant-numeric: tabular-nums; }

/* --- Medidor de qualidade (ISO 8000) ------------------------------------ */
.dash-quality {
  display: grid; grid-template-columns: auto 1fr; gap: 1.4rem;
  align-items: start; padding: 0.3rem 1.75rem 0;
}
.dash-gauge { position: relative; width: 132px; text-align: center; }
.dash-gauge svg { width: 132px; height: 82px; display: block; }
.dash-gauge-track { stroke: var(--bg-alt); }
.dash-gauge-fill {
  stroke: var(--gauge-cor, var(--st-good));
  transition: stroke-dashoffset 900ms var(--ease-out);
}
.dash-gauge-num {
  position: absolute; left: 0; right: 0; top: 38px;
  font-size: 1.65rem; font-weight: 700; color: var(--text); line-height: 1;
}
.dash-gauge-num em { font-style: normal; font-size: 0.5em; color: var(--text-muted); margin-left: 1px; }
.dash-gauge-cap {
  display: block; margin-top: 0.1rem; font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-faint);
}
.dash-quality-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.dash-quality-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--text-faint);
}
.dash-quality-crit { text-transform: none; letter-spacing: 0; font-weight: 500; }
.dash-quality-crit b { color: var(--text-muted); }
.dash-quality-item {
  display: grid; grid-template-columns: minmax(110px, 1.2fr) 2fr auto;
  align-items: center; gap: 0.6rem;
}
.dash-quality-rot { font-size: 0.78rem; color: var(--text-muted); }
.dash-quality-track { height: 6px; border-radius: 999px; background: var(--bg-alt); overflow: hidden; }
.dash-quality-fill {
  display: block; height: 100%; border-radius: 999px; background: var(--q-cor, var(--st-good));
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.06);
}
.dash-quality-pct {
  font-size: 0.78rem; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; min-width: 2.4rem; text-align: right;
}

/* --- Integracoes -------------------------------------------------------- */
.dash-integrations { list-style: none; margin: 0; padding: 0 1.75rem; display: grid; gap: 0.5rem; }
.dash-integration {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 0.7rem;
  padding: 0.6rem 0.75rem; border-radius: var(--radius-md);
  background: var(--bg-alt); border: 1px solid var(--border);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.dash-integration:hover { border-color: var(--border-strong); }
.dash-integration-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--int-cor, var(--st-neutral));
}
.dash-integration-main { display: grid; gap: 0.15rem; min-width: 0; }
.dash-integration-nome {
  font-size: 0.85rem; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dash-integration-sub {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.73rem; color: var(--text-muted);
}
.dash-integration-estado {
  font-size: 0.72rem; font-weight: 700; color: var(--int-cor, var(--st-neutral));
  white-space: nowrap;
}

/* --- Status dos anuncios (anel + legenda em lista) ---------------------- */
.dash-status-wrap {
  display: grid; grid-template-columns: minmax(160px, 1fr) minmax(160px, 1.1fr);
  gap: 1.2rem; align-items: center; padding: 0.3rem 1.75rem 0;
}
.dash-status-legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.42rem; }
.dash-status-legend li {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 0.5rem;
}
.dash-legend-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--leg-cor, var(--st-neutral));
}
.dash-legend-rot {
  font-size: 0.79rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dash-legend-val {
  font-size: 0.82rem; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.dash-legend-val em {
  font-style: normal; font-weight: 500; font-size: 0.72rem;
  color: var(--text-faint); margin-left: 0.35rem;
}

@media (max-width: 760px) {
  .dash-hero { align-items: flex-start; }
  .dash-quality { grid-template-columns: 1fr; justify-items: center; }
  .dash-quality-list { width: 100%; }
  .dash-status-wrap { grid-template-columns: 1fr; }
  .dash-bar-row { grid-template-columns: minmax(90px, 1fr) 2fr auto; }
}

/* Caixa do grafico: a altura e o padding ficam AQUI, nunca no <canvas>.
   A regra antiga `.chart-card canvas` aplica padding no proprio canvas e,
   com box-sizing:border-box, o Chart.js calcula largura ZERO (bug real
   medido em 2026-08-03: canvas.width = 0 com o pai em 930px). */
.dash-chart-box {
  position: relative; height: 268px;
  padding: 0.4rem 1.75rem 1.2rem; box-sizing: border-box;
}
.dash-chart-box.is-anel { height: 232px; padding: 0.4rem 0 0.6rem; }
.dash-chart-box canvas { padding: 0 !important; max-height: none !important; }

/* --- Padrao unico das toolbars de lista (2026-08-03) --------------------
   Auditoria achou 4 variantes diferentes de classe pro MESMO botao "Novo X"
   (primario sem classe, secondary-dark, button-link, secondary-dark
   button-link). Agora a acao que a tela existe pra oferecer usa sempre
   .toolbar-primary; Filtrar/Importar/menu "..." ficam em .secondary-dark. */
.toolbar-primary {
  display: inline-flex; align-items: center; gap: 0.4rem;
  min-height: var(--field-h); text-decoration: none; white-space: nowrap;
}
a.button-link.toolbar-primary { padding: 0 0.95rem; }
.toolbar-primary svg { flex: 0 0 auto; }

/* Titulo/explicacao de lista ficam FORA da toolbar (knowledge e compliance
   colocavam <h2> dentro dela, o que mudava a altura da linha de acoes). */
.list-title { margin: 0 0 0.2rem; font-size: 1.25rem; letter-spacing: -0.01em; }
.list-subtitle { margin: 0 0 1rem; max-width: 76ch; }

/* "Limpar filtros" sempre no fim do form de busca, nunca solto entre as
   acoes da direita (estava nos dois lugares dependendo da tela). */
.toolbar-clear { white-space: nowrap; }

/* --- Visao geral das Configuracoes (2026-08-03) -------------------------
   Cartoes de entrada da tela: cada um resume uma area e leva pra aba dela.
   Sao <button>, entao precisam desfazer o visual do botao global (fundo
   azul, altura fixa, centralizacao) -- mesma armadilha ja documentada em
   .ad-tab-btn e .copy-icon-btn. */
.settings-hub-head { margin-bottom: 1.1rem; }
.settings-hub-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 1rem;
}
.settings-hub-card {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 0.9rem; width: 100%; height: auto; min-height: 0;
  padding: 1.05rem 1.1rem; text-align: left;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.settings-hub-card:hover {
  background: var(--surface); color: var(--text);
  transform: translateY(-2px); box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
}
.settings-hub-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: var(--radius-md);
  background: var(--bg-alt); color: var(--text-muted);
}
.settings-hub-icon svg { width: 20px; height: 20px; }
/* Cor do icone segue o ESTADO da area (verde ok / laranja atencao /
   vermelho pendencia), nunca uma cor decorativa por cartao. */
.settings-hub-card[data-papel="good"] .settings-hub-icon { background: var(--success-bg); color: var(--success-text); }
.settings-hub-card[data-papel="warning"] .settings-hub-icon { background: var(--warning-bg); color: var(--warning-text); }
.settings-hub-card[data-papel="critical"] .settings-hub-icon { background: var(--danger-soft, #ffebee); color: var(--danger-dark); }
.settings-hub-body { display: grid; gap: 0.12rem; min-width: 0; }
.settings-hub-title {
  font-size: 0.73rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted);
}
.settings-hub-value { display: flex; align-items: baseline; gap: 0.35rem; }
.settings-hub-value strong { font-size: 1.5rem; font-weight: 700; line-height: 1.1; }
.settings-hub-value em { font-style: normal; font-size: 0.78rem; color: var(--text-muted); }
.settings-hub-detail {
  font-size: 0.76rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.settings-hub-go { color: var(--text-faint); display: inline-flex; }
.settings-hub-go svg { width: 18px; height: 18px; }
.settings-hub-card:hover .settings-hub-go { color: var(--brand); }

/* --- Grupos de secao dentro de uma aba de Configuracoes ------------------
   A aba "Configuracoes gerais" tinha 8 paineis soltos misturando automacao,
   LGPD, registro e ferramenta pontual, sem nenhuma separacao. */
.settings-group { margin: 1.6rem 0 0.4rem; }
.settings-group:first-of-type { margin-top: 0.4rem; }
.settings-group-title {
  display: flex; align-items: center; gap: 0.6rem;
  margin: 0 0 0.2rem; font-size: 0.78rem; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted);
}
.settings-group-title::after {
  content: ''; flex: 1; height: 1px; background: var(--border);
}
.settings-group-hint { margin: 0 0 0.9rem; font-size: 0.8rem; color: var(--text-faint); max-width: 72ch; }

/* --- Popup "Alterar categoria dos selecionados" (2026-08-03) ------------- */
/* Busca: input e lupa na MESMA linha. */
.cat-search-row {
  display: flex; align-items: center; gap: 0.5rem; margin: 1rem 0 0.4rem;
}
.cat-search-row input[type="text"] { flex: 1 1 auto; min-width: 0; }
.cat-search-row .icon-btn { flex: 0 0 auto; width: var(--field-h); height: var(--field-h); }

.cat-grupo { margin-top: 1.1rem; }
.cat-grupo-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem; margin-bottom: 0.45rem; padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--border);
}
.cat-grupo-nome {
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted);
}
.cat-grupo-resumo { font-size: 0.76rem; color: var(--text-faint); white-space: nowrap; }

.cat-lista { display: grid; gap: 0.4rem; }
/* Cada categoria e' um <button> de largura total -- precisa desfazer o
   visual do botao global (fundo azul, altura fixa, centralizacao), mesma
   armadilha ja documentada em .ad-tab-btn/.settings-hub-card. */
.cat-item {
  display: flex; align-items: center; justify-content: space-between; gap: 0.9rem;
  width: 100%; height: auto; min-height: 0; text-align: left;
  padding: 0.65rem 0.8rem;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: none;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.cat-item:hover {
  background: var(--brand-soft); color: var(--text);
  border-color: var(--brand); box-shadow: none; transform: none;
}
.cat-item-info { display: grid; gap: 0.12rem; min-width: 0; }
.cat-item-nome {
  font-size: 0.86rem; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-item-caminho {
  font-size: 0.74rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-item-meta { font-size: 0.71rem; color: var(--text-faint); }
.cat-item-acao {
  flex: 0 0 auto; font-size: 0.76rem; font-weight: 700; color: var(--brand);
  white-space: nowrap;
}
/* Origem da sugestao: uma faixa fina a esquerda basta pra distinguir sem
   introduzir cor de texto nova. */
.cat-item[data-origem="cadastrada"] { border-left: 3px solid var(--success-text); }
.cat-item[data-origem="em_uso"] { border-left: 3px solid var(--brand); }
.cat-item[data-origem="sugerida"] { border-left: 3px solid var(--warning-text); }

/* Estado somente-leitura de uma configuracao que o usuario atual nao pode
   alterar (ex.: politicas de retencao, exclusivas do super usuario) -- mostra
   o valor vigente "para conhecimento", sem controle nenhum. */
.config-readonly {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.8rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
  color: var(--text);
}

.config-readonly .field-hint { margin: 0; }

/* ==========================================================================
   Reportar problema (2026-08-04)

   O link e' de proposito DISCRETO (pedido do usuario: "um botao discreto,
   como link") -- ele acompanha uma mensagem de erro, entao competir com ela
   visualmente seria ruim. Herda a cor do container (vermelho da flash,
   laranja do toast) em vez de ter cor propria.
   ========================================================================== */

.flash-report,
.toast-report,
.alert-report {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 0.75rem;
  font-weight: 600;
  color: inherit;
  opacity: 0.75;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
  cursor: pointer;
}

.flash-report:hover,
.toast-report:hover,
.alert-report:hover { opacity: 1; }

/* No alerta (modal centralizado, sem rodape proprio) o link fica numa
   linha propria, abaixo da mensagem. Na flash e no toast o link ja' mora
   dentro do proprio rodape (.flash-footer/.corner-toast-footer), que
   cuida do espacamento e do alinhamento -- por isso so' o alerta precisa
   do proprio margin aqui. */
.alert-report {
  display: inline-block;
  margin: 0.6rem 0 0;
  color: var(--error-text);
}

/* --- popup de report --- */
.report-erro-box {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.7rem 0.85rem;
  margin: 0.9rem 0;
  border-radius: var(--radius-sm);
  background: var(--error-bg);
  border: 1px solid rgba(163, 49, 42, 0.15);
}

.report-erro-msg {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--error-text);
  word-break: break-word;
}

.report-erro-codigo {
  font-size: 0.72rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-muted);
}

.report-trilha-wrap { margin: 0.9rem 0 0.2rem; }

.report-trilha-wrap > summary {
  cursor: pointer;
  font-size: 0.78rem;
  color: var(--text-muted);
  list-style: none;
}

.report-trilha-wrap > summary::-webkit-details-marker { display: none; }
.report-trilha-wrap > summary::before { content: "▸ "; }
.report-trilha-wrap[open] > summary::before { content: "▾ "; }

.report-trilha {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0.6rem 0.8rem;
  max-height: 190px;
  overflow-y: auto;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.report-trilha li {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  font-size: 0.78rem;
  color: var(--text);
  padding: 0.22rem 0;
  border-bottom: 1px dashed var(--border);
}

.report-trilha li:last-child { border-bottom: none; }

.report-trilha-hora {
  flex: 0 0 auto;
  font-size: 0.7rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-faint);
}

/* --- Central de suporte: diagnostico do problema (2026-08-04) ----------- */
.suporte-traceback { margin-top: 1rem; }

.suporte-traceback > summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--error-text);
}

.suporte-traceback pre {
  margin-top: 0.6rem;
  padding: 0.9rem 1rem;
  max-height: 340px;
  overflow: auto;
  font-size: 0.74rem;
  line-height: 1.5;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.suporte-report {
  padding: 1rem 1.1rem;
  margin-bottom: 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
}

.suporte-report:last-child { margin-bottom: 0; }

.suporte-report-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

.suporte-report-desc {
  margin: 0 0 0.6rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
}

/* Trilha: uma linha por passo, com a barra lateral colorida indicando o tipo
   (pagina aberta / acao clicada / erro que apareceu). */
.suporte-trilha {
  list-style: none;
  margin: 0.8rem 0 0;
  padding: 0;
  counter-reset: passo;
}

.suporte-trilha-item {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  padding: 0.3rem 0 0.3rem 0.7rem;
  font-size: 0.8rem;
  border-left: 3px solid var(--border);
}

.suporte-trilha-item.tipo-pagina { border-left-color: var(--brand); }
.suporte-trilha-item.tipo-acao { border-left-color: var(--border-strong); }
.suporte-trilha-item.tipo-erro { border-left-color: var(--error-text); color: var(--error-text); font-weight: 600; }

.suporte-trilha-hora {
  flex: 0 0 auto;
  font-size: 0.7rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-faint);
}

/* --- Cobertura de anúncios (produtos x loja) --- 2026-08-05 -------------- */
/* O "alvo" (empresa + canal) e os filtros ficam em duas linhas de campos que
   quebram sozinhas; a .products-toolbar padrão é uma linha só com
   space-between, que não comporta 8 campos. */
.cobertura-alvo { flex-direction: column; align-items: stretch; gap: 0.75rem; }
.cobertura-alvo-campos {
  display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: flex-end;
}
.cobertura-alvo-campos > label { display: flex; flex-direction: column; gap: 0.3rem; min-width: 170px; }
.cobertura-alvo-campos > label > select { min-width: 170px; }
.cobertura-alvo-campos .toolbar-search { flex: 1 1 280px; }
.cobertura-kpis { margin-bottom: 1rem; }
/* Quadrado de "sem foto": mesmo tamanho da miniatura, pra a coluna não pular */
.row-thumb-empty {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-alt); border: 1px dashed var(--border);
  color: var(--text-faint); font-size: 0.8rem;
}
@media (max-width: 720px) {
  .cobertura-alvo-campos > label,
  .cobertura-alvo-campos > label > select { min-width: 0; width: 100%; }
}

/* ---------------------------------------------------------------------------
   Popup "Meu perfil" (2026-08-05) -- modernizado a pedido do usuario:
   popup maior, campos em secao, e-mail desabilitado de verdade, telefone novo
   e TODAS as acoes numa linha so' no rodape.
   -------------------------------------------------------------------------- */

/* 460px (padrao) nao comporta 2 colunas de campo + 4 botoes numa linha. */
.modal-box.profile-box { max-width: 760px; }

/* Rotulo da foto: era um .field-hint igual ao texto de apoio logo abaixo, o
   que deixava os dois com o mesmo peso e sem hierarquia nenhuma. */
.profile-photo-title {
  margin: 0;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text);
}

/* E-mail desabilitado -- escopado no proprio formulario pra nao mexer no
   visual de campo desabilitado das outras telas (que tem regras proprias). */
#profile-form input:disabled {
  background: var(--bg-alt);
  color: var(--text-muted);
  border-color: var(--border);
  cursor: not-allowed;
}

/* Rodape: os botoes de dados (esquerda) e o salvar (direita) na MESMA linha.
   `min-width: 0` nos dois grupos permite que eles encolham antes de quebrar --
   sem isso o grupo da esquerda empurraria o salvar pra linha de baixo assim
   que a soma dos rotulos passasse da largura util. */
.profile-footer > .button-row {
  min-width: 0;
  flex-wrap: nowrap;
}
.profile-footer > .button-row > * { white-space: nowrap; }

/* Aviso de solicitacao de exclusao em aberto (ver profile_request_deletion) --
   tom de alerta, nunca de erro: a conta segue funcionando normalmente. */
.profile-deletion-banner {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  margin-bottom: 1rem;
  padding: 0.75rem 0.9rem;
  /* --warning-text, NAO --warning (que nao existe): com a var indefinida o
     `border` shorthand inteiro era descartado e o banner de exclusao de conta
     aparecia SEM borda nenhuma. Mesmo padrao do banner de erro (linha ~15434,
     `border: 1px solid var(--error-text)`). Corrigido em 2026-08-16. */
  border: 1px solid var(--warning-text);
  border-radius: var(--radius-sm);
  background: var(--warning-bg);
  color: var(--warning-text);
}
.profile-deletion-banner svg { flex: 0 0 auto; margin-top: 0.1rem; }
.profile-deletion-banner strong { display: block; font-size: 0.88rem; }
.profile-deletion-banner .field-hint { margin: 0.15rem 0 0; }

/* Popup "Como usamos e protegemos os seus dados" (#privacy-summary-modal). */
.privacy-summary-list {
  margin: 0;
  padding-left: 1.1rem;
  display: grid;
  gap: 0.35rem;
  font-size: 0.86rem;
  color: var(--text);
}
.privacy-summary-list li { line-height: 1.45; }

@media (max-width: 700px) {
  /* Em tela estreita a linha unica de botoes deixa de caber -- ai' sim cada
     grupo pode quebrar, e o salvar vai pro fim. */
  .profile-footer > .button-row { flex-wrap: wrap; }
}

/* ---------------------------------------------------------------------------
   Documentos juridicos dentro do app (politica de privacidade / termos de uso)
   -- ver legal_page.html.

   BUG REAL corrigido em 2026-08-05: os <p> herdavam a cor de paragrafo
   generica (--text-muted), o que dava 3.35:1 de contraste sobre o fundo do
   painel -- ABAIXO do minimo legivel (4.5:1). As <li> do mesmo documento
   ficavam em 9.65:1, entao o texto corrido aparecia visivelmente mais apagado
   que as listas logo abaixo dele. Documento juridico precisa ser legivel: a
   propria LGPD exige informacao clara e acessivel ao titular.
   -------------------------------------------------------------------------- */
.legal-doc p { color: var(--text); }
/* A data de atualizacao continua discreta de proposito -- e' metadado, nao
   parte do texto que precisa ser lido. */
.legal-doc .field-hint { color: var(--text-muted); }
.legal-doc h3 { margin-top: 1.7rem; }
/* O titulo dos documentos juridicos virou <h1> (SEO, 2026-08-20): sem
   isto ele cairia no tamanho padrao do navegador (2em) dentro do painel. */
.legal-doc h1 { font-size: 1.5rem; font-weight: 700; margin: 0 0 0.35rem; }
.legal-doc li { line-height: 1.6; }

/* ---------------------------------------------------------------------------
   Aviso de cookies/preferencias (2026-08-05) -- base da tela, largura total.
   Ver o bloco de consentimento no <head> do base.html pro que ele de fato
   liga/desliga.

   z-index 55: acima da topbar (40) e dos menus suspensos (50), abaixo dos
   modais (60) -- um popup aberto precisa cobrir o aviso, nunca o contrario.
   -------------------------------------------------------------------------- */
.cookie-banner {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 55;
  background: var(--surface-solid);
  border-top: 1px solid var(--border);
  box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.12);
  padding: 1rem 1.5rem calc(1rem + env(safe-area-inset-bottom, 0px));
  animation: rise-in var(--dur-base) var(--ease-out);
}
.cookie-banner[hidden] { display: none; }

.cookie-banner-inner {
  max-width: 1180px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.cookie-banner-texto { flex: 1 1 auto; min-width: 0; }
.cookie-banner-texto strong { display: block; font-size: 0.92rem; margin-bottom: 0.2rem; color: var(--text); }
.cookie-banner-texto p {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.5;
  /* --text, nao --text-muted: sobre o fundo claro o muted da' 3.35:1, abaixo
     do minimo legivel (4.5:1). Consentimento so' vale se for INFORMADO -- o
     usuario precisa conseguir ler o que esta' aceitando. Mesmo motivo da
     correcao feita nos documentos juridicos (.legal-doc p). */
  color: var(--text);
}
.cookie-banner-texto p strong { display: inline; font-size: inherit; margin: 0; color: var(--text); }
.cookie-estado {
  margin-top: 0.35rem !important;
  font-weight: 600;
  color: var(--brand-dark) !important;
}

/* Os dois botoes com a MESMA largura minima -- recusar precisa ter o mesmo
   peso visual de aceitar (consentimento livre; ver comentario no base.html). */
.cookie-banner-acoes {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.cookie-banner-acoes button { min-width: 116px; }
.cookie-banner-acoes a {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}
.cookie-banner-acoes a:hover { color: var(--brand); }

/* A pilha de avisos sobe enquanto o banner estiver na tela, senao os dois
   disputam o mesmo canto inferior. */
body.com-banner-cookies .toast-stack { --stack-bottom: 10.5rem; }

@media (max-width: 860px) {
  .cookie-banner { padding: 0.9rem 1rem calc(0.9rem + env(safe-area-inset-bottom, 0px)); }
  .cookie-banner-inner { flex-direction: column; align-items: stretch; gap: 0.8rem; }
  .cookie-banner-acoes { justify-content: flex-end; flex-wrap: wrap; }
  /* `1 1 0` (e nao `1 1 auto`): base zero faz os dois ficarem com a MESMA
     largura em vez de dividirem pelo tamanho do texto -- recusar nao pode
     parecer menor/menos importante que aceitar. */
  .cookie-banner-acoes button { flex: 1 1 0; }
  /* No mobile o banner e' mais alto (texto em varias linhas) e a pilha ja'
     sobe por causa da barra de navegacao inferior -- soma os dois. */
  body.com-banner-cookies .toast-stack { --stack-bottom: calc(14rem + env(safe-area-inset-bottom, 0px)); }
}

/* Popup "Sincronizar anúncios" (2026-08-05): prévia da plataforma com busca,
   filtros e seleção. Reaproveita .table-card/.table-compact/.multi-select-* e
   .badge do resto do sistema -- aqui só o que é específico do popup. */
.sync-resumo {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin: 0.35rem 0 0.6rem;
  font-size: 0.82rem;
  color: var(--text-muted);
}

/* A prévia pode ter centenas de linhas: rola por dentro do popup em vez de
   esticar o modal até estourar a tela. Pedido do usuário (2026-08-11):
   "aumenta altura dele" -- o SHELL do modal (#sync-modal .modal-box) já é
   92vh (o maior do sistema), mas a tabela em si ficava travada em 46vh,
   deixando boa parte dessa altura reservada sem uso (cabeçalho/toolbar/
   resumo/rodapé somam bem menos que os ~46vh de folga que sobravam).
   62vh usa esse espaço de sobra sem arriscar estourar viewport curta --
   .modal-box.xwide já tem overflow-y:auto próprio como rede de segurança
   caso a tela seja baixa demais até pra esse novo valor. */
.sync-table-card .table-scroll {
  max-height: 62vh;
  overflow-y: auto;
}

.sync-cell-ad {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.sync-cell-ad .row-thumb {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
}

/* Popup "Sincronizar anúncios": a linha de plataforma/loja/botão e a linha de
   busca+filtros logo abaixo ficavam colados (a .form-grid não tem margem
   inferior própria, e a toolbar só tem margin-bottom). */
.sync-form-topo {
  margin-bottom: 1.25rem;
}

/* A toolbar do popup vive dentro de um modal, não no topo de uma página --
   precisa de respiro acima dela, não só abaixo. */
#sync-toolbar {
  margin-top: 0.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

/* Menu "com qual IA gerar?" (2026-08-06) -- reaproveita todo o visual do
   .header-menu-dropdown.row-click-menu; aqui so' o titulo do menu e o selo
   "padrao" ao lado da conexao marcada como padrao da conta. */
.ai-picker-menu .ai-picker-title {
  padding: 0.55rem 0.9rem 0.4rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.25rem;
}

.ai-picker-badge {
  margin-left: auto;
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* --- Tarja de ambiente de teste (topo do conteudo) -----------------------
   Pedido do usuario (2026-08-06): "quando a organizacao for teste deixar uma
   tarja no topo avisando... essa tarja pode ser fechada... sera no topo
   abaixo do header e respeitar o menu lateral, nao sobre header e menu
   lateral, deixar cor informativo".

   NAO e' `position: fixed` (ao contrario da tarja de cobranca do rodape):
   fica no fluxo, DENTRO do <main class="content">, logo depois da topbar --
   por construcao nunca cobre o header nem o menu lateral, em nenhuma largura
   de tela.

   Sem margem negativa lateral de proposito: o padding do .content muda por
   breakpoint (2.25rem -> 1.1rem -> 0.75rem), entao sangrar com um valor fixo
   geraria scroll horizontal no celular. Assim ela acompanha a largura util
   do conteudo, alinhada com os paineis da pagina.

   Cor INFORMATIVA (--info-*), nao de alerta: estar em sandbox e' um estado
   normal de trabalho, nao um problema a corrigir. */
.ambiente-tarja {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--info-bg);
  color: var(--info-text);
  border: 1px solid color-mix(in srgb, var(--info-text) 22%, transparent);
  border-left: 3px solid var(--info-text);
  border-radius: var(--radius-md);
  padding: 0.65rem 0.9rem;
  margin: 0 0 1.25rem;
  font-size: 0.86rem;
  line-height: 1.35;
}

.ambiente-tarja-icone {
  display: inline-flex;
  flex: 0 0 auto;
}

.ambiente-tarja-icone svg {
  width: 17px;
  height: 17px;
}

.ambiente-tarja-texto {
  flex: 1 1 auto;
  min-width: 0;
}

/* Botao "X": o `button` global tem altura fixa (--field-h), fundo e borda
   proprios -- sem redeclarar aqui ele viraria um botao azul de formulario
   dentro da tarja (mesma armadilha ja documentada em .ad-tab-btn/.copy-icon-btn). */
.ambiente-tarja-fechar {
  flex: 0 0 auto;
  height: auto;
  min-height: 0;
  padding: 0.1rem 0.35rem;
  background: none;
  border: none;
  box-shadow: none;
  color: var(--info-text);
  opacity: 0.75;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}

.ambiente-tarja-fechar:hover,
.ambiente-tarja-fechar:focus,
.ambiente-tarja-fechar:focus-visible,
.ambiente-tarja-fechar:active {
  background: none;
  border: none;
  box-shadow: none;
  outline: none;
  opacity: 1;
}

/* Fechada nesta sessao do navegador (classe aplicada antes da pagina pintar,
   ver o script anti-flash do base.html). */
body.tarja-ambiente-fechada .ambiente-tarja {
  display: none;
}

/* --- Tarja de cobranca (rodape fixo) -------------------------------------
   Pedido do usuario (2026-08-06): "todas as pagina ficaram com uma faixa no
   rodape, em alerta, num estilo tarja sobrepondo e fixa bottom=0, com um
   texto link para ir a tela pagamentos".

   z-index 70: acima do conteudo e do #toast-stack (60), abaixo dos modais
   (que usam 100+) -- um popup de confirmacao precisa cobrir a tarja, senao o
   botao de confirmar fica escondido atras dela. */
.billing-tarja {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 1.4rem;
  font-size: 0.85rem;
  font-weight: 600;
  box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.16);
  /* Animacao PROPRIA, e nao a `toast-in` dos avisos do canto: aquela desliza
     18px na horizontal (translateX) e comeca em opacity 0.
     Numa faixa de largura total isso da' dois defeitos, os dois medidos:
     transborda a tela pela direita (right passava do viewport) e, se o
     relogio de animacao nao avancar -- aba em segundo plano, compositor
     ocupado --, a tarja fica INVISIVEL congelada no frame 0.
     Aqui e' justamente o aviso que explica por que nada salva: nunca pode
     sumir. Entao so' um deslocamento vertical minimo, sem opacity -- o pior
     caso congelado sao 6px cortados na base, com o texto legivel. */
  animation: billing-tarja-in var(--dur-base) var(--ease-out);
}

@keyframes billing-tarja-in {
  from { transform: translateY(6px); }
  to { transform: translateY(0); }
}

.billing-tarja-bloqueado {
  background: var(--error-bg);
  color: var(--error-text);
  border-top: 2px solid var(--error-text);
}

.billing-tarja-aviso {
  background: var(--warning-bg);
  color: var(--warning-text);
  border-top: 2px solid var(--warning-text);
}

.billing-tarja-icone {
  display: inline-flex;
  flex: 0 0 auto;
}

.billing-tarja-icone svg {
  width: 18px;
  height: 18px;
}

.billing-tarja-texto {
  flex: 1 1 auto;
  min-width: 0;
}

/* O link herda a cor da tarja (vermelha ou laranja) em vez de usar a cor da
   marca -- azul dentro de uma faixa de alerta some visualmente. */
.billing-tarja-link {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid currentColor;
  border-radius: var(--radius-sm);
  color: inherit;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out);
}

.billing-tarja-link:hover {
  background: rgba(0, 0, 0, 0.08);
  text-decoration: none;
}

.billing-tarja-link svg {
  width: 14px;
  height: 14px;
}

/* X de fechar do AVISO de vencimento (a tarja de bloqueio nao tem X).
   Redeclara fundo/borda/altura explicitos: o `button` global tem altura fixa
   de campo e fundo proprio que pintariam um botao azul dentro da faixa --
   mesma armadilha ja documentada em .copy-icon-btn/.stat-cell. */
.billing-tarja-fechar {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  min-height: 0;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  box-shadow: none;
  color: inherit;
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.billing-tarja-fechar:hover,
.billing-tarja-fechar:focus,
.billing-tarja-fechar:focus-visible,
.billing-tarja-fechar:active {
  background: rgba(0, 0, 0, 0.08);
  border: none;
  box-shadow: none;
  color: inherit;
  outline: none;
  transform: none;
}

/* A tarja cobre o rodape da pagina: sem isto, o ultimo item de uma lista
   longa fica escondido atras dela e o usuario nao consegue clicar. */
body.tem-billing-tarja .layout {
  padding-bottom: 58px;
}

@media (max-width: 620px) {
  .billing-tarja {
    flex-wrap: wrap;
    padding: 0.6rem 0.9rem;
    font-size: 0.78rem;
  }
  .billing-tarja-link {
    width: 100%;
    justify-content: center;
  }
  body.tem-billing-tarja .layout {
    padding-bottom: 96px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .billing-tarja {
    animation: none;
  }
}

/* --- Anuncios do Google/AdSense (rodape, lateral e flutuante) -------------
   2026-08-14, pedido do usuario. Rodape fica dentro de <main> (flui com o
   conteudo da pagina); lateral e flutuante sao POSICIONAMENTO FIXO --
   z-index abaixo da pilha de avisos (90) e da tarja de cobranca (70), pra
   nenhum dos dois ficar escondido atras de um anuncio. */
.google-ads-slot-tag {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.4rem;
}

.google-ads-unit {
  min-height: 90px;
}

.google-ads-slot-footer {
  position: relative;
  margin-top: 2rem;
  padding-top: 1.25rem;
  padding-right: 2rem;
  border-top: 1px solid var(--border);
  text-align: center;
}

/* O bloco saiu TAMANHO FIXO 600x160 na conta real (nao Responsivo) -- 600px
   nao cabe num celular, e a politica do AdSense proibe encolher anuncio por
   CSS (transform/scale muda a area clicavel real vs. a exibida). A saida e'
   deixar SO' este wrapper rolar na horizontal (nunca a pagina inteira). */
.google-ads-slot-footer-scroll {
  /* text-align (nao flex+justify-content:center): centralizar item flex
     que transborda corta o INICIO do conteudo ao rolar em alguns
     navegadores -- bug conhecido de flexbox. Com inline-block simples isso
     nao acontece. */
  overflow-x: auto;
  text-align: center;
}

/* 184px = 160px do anuncio (Skyscraper vertical fixo, ver base.html) + os
   0.75rem (12px) de padding de cada lado. */
.google-ads-rail {
  position: fixed;
  top: 50%;
  right: 1rem;
  transform: translateY(-50%);
  z-index: 55;
  width: 184px;
  max-width: calc(100vw - 2rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.75rem;
  box-shadow: var(--shadow-md);
}

.google-ads-floating {
  position: fixed;
  left: 1.25rem;
  bottom: 1.25rem;
  z-index: 55;
  width: 300px;
  max-width: calc(100vw - 2.5rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.75rem;
  box-shadow: var(--shadow-md);
  animation: billing-tarja-in var(--dur-base) var(--ease-out);
}

/* A tarja de cobranca ocupa a base inteira da tela quando existe -- a caixa
   flutuante sobe pra nao ficar atras dela (mesma altura reservada em
   body.tem-billing-tarja .layout, ver acima). */
body.tem-billing-tarja .google-ads-floating {
  bottom: calc(1.25rem + 58px);
}

/* Botao de fechar compartilhado pelos 3 blocos (rodape/lateral/flutuante) --
   pedido do usuario (2026-08-14): "x vermelho no canto direito superior".
   O pai precisa ser positioned (a lateral e a flutuante ja sao `fixed`; o
   rodape ganhou `position:relative` abaixo so' pra isto). */
.google-ads-close-btn {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  border-radius: 50%;
  font-size: 1rem;
  line-height: 1;
  font-weight: 700;
  color: var(--error-text);
  cursor: pointer;
}

.google-ads-close-btn:hover,
.google-ads-close-btn:focus-visible {
  background: var(--error-bg);
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .google-ads-floating {
    animation: none;
  }
}

/* --- Telas de cobranca (Pagamentos / Meu plano) --------------------------- */
.billing-hero {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding: 1.4rem 1.75rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  margin-bottom: 1.5rem;
}

/* A faixa lateral colorida carrega o estado -- e' o que o olho pega antes de
   ler o texto. */
.billing-hero-ok { border-left: 4px solid var(--success-text); }
.billing-hero-trial { border-left: 4px solid var(--warning-text); }
.billing-hero-bloqueado { border-left: 4px solid var(--error-text); }

.billing-hero-info { flex: 1 1 260px; min-width: 0; }

.billing-hero-eyebrow {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 0.25rem;
}

.billing-hero-status { font-size: 1.3rem; }
.billing-hero-msg { margin: 0.4rem 0 0; color: var(--text-muted); font-size: 0.88rem; }
.billing-hero-valor { flex: 0 0 auto; text-align: right; }
.billing-hero-valor strong { font-size: 1.35rem; color: var(--error-text); }
.billing-hero-acoes { flex: 0 0 auto; }

.billing-falta {
  display: block;
  font-size: 0.72rem;
  color: var(--warning-text);
  font-weight: 700;
}

.billing-pagamentos-row td { background: var(--bg-alt); }
.billing-pagamentos { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.billing-pagamentos-titulo {
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--text-muted);
}
.billing-pagamento-item {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.2rem 0.6rem; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border);
  font-size: 0.78rem; font-weight: 600;
}
.billing-pagamento-item em { font-style: normal; color: var(--text-muted); text-transform: capitalize; }
.billing-pagamento-item span { color: var(--text-faint); font-weight: 400; }

.billing-consumo-lista { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.75rem; }
.billing-consumo-item {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.55rem 0.8rem; border-radius: var(--radius-sm);
  background: var(--bg-alt); border: 1px solid var(--border);
}
.billing-consumo-item span { color: var(--text-muted); font-size: 0.85rem; }
.billing-consumo-item strong { font-size: 1rem; }

/* --- Meu plano ----------------------------------------------------------- */
.plano-atual-topo {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap; margin-bottom: 1.25rem;
}
.plano-atual-nome strong { font-size: 1.4rem; }
.plano-atual-nome p { margin: 0.3rem 0 0; color: var(--text-muted); font-size: 0.88rem; }
.plano-atual-preco { text-align: right; }
.plano-atual-preco strong { font-size: 1.6rem; color: var(--brand); }
.plano-atual-preco span { color: var(--text-muted); font-size: 0.85rem; }

.plano-secao-titulo {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-muted);
  margin: 1.5rem 0 0.75rem; padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
}

.plano-uso-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.plano-uso-item {
  padding: 0.85rem 1rem; border-radius: var(--radius-md);
  border: 1px solid var(--border); background: var(--bg-alt);
}
.plano-uso-cabecalho { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.plano-uso-cabecalho span { font-size: 0.8rem; color: var(--text-muted); }
.plano-uso-cabecalho strong { font-size: 1.05rem; }
.plano-uso-cabecalho em { font-style: normal; font-weight: 400; font-size: 0.78rem; color: var(--text-faint); }

.plano-uso-barra {
  height: 6px; border-radius: 3px; background: var(--border);
  margin-top: 0.6rem; overflow: hidden;
}
/* Barra sem animacao de largura de proposito: dado nunca depende do relogio
   de animacao pra aparecer (uma aba em segundo plano mostraria barra vazia). */
.plano-uso-barra span { display: block; height: 100%; background: var(--brand); }
.plano-uso-atencao .plano-uso-barra span { background: var(--warning-text); }
.plano-uso-critico .plano-uso-barra span { background: var(--error-text); }
.plano-uso-pct { font-size: 0.7rem; color: var(--text-faint); }

.plano-recursos { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.plano-recurso {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.35rem 0.75rem; border-radius: var(--radius-sm);
  font-size: 0.82rem; font-weight: 600; border: 1px solid var(--border);
}
.plano-recurso svg { width: 14px; height: 14px; }
.plano-recurso.ativo { background: var(--success-bg); color: var(--success-text); border-color: var(--success-text); }
.plano-recurso.inativo { background: var(--bg-alt); color: var(--text-faint); }

.plano-plataformas { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* Personalizacao por cliente (2026-08-12) -- observacao/isencao/limites
   extras, na tela /cobrancas/<id>. Card raso igual .plano-uso-item, 3 por
   linha quando cabe. */
.billing-custom-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.billing-custom-card {
  padding: 0.9rem 1rem; border-radius: var(--radius-md);
  border: 1px solid var(--border); background: var(--bg-alt);
  display: flex; flex-direction: column; gap: 0.5rem;
}
.billing-custom-card .plano-secao-titulo { margin: 0; }
.billing-custom-card > button,
.billing-custom-card form { margin-top: auto; }

.planos-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.plano-card {
  position: relative; padding: 1.25rem;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); display: flex; flex-direction: column; gap: 0.6rem;
}
.plano-card-atual { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.plano-card-tag {
  position: absolute; top: -0.6rem; left: 1rem;
  background: var(--brand); color: #fff; font-size: 0.65rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: 0.15rem 0.5rem; border-radius: var(--radius-sm);
}
.plano-card h4 { margin: 0; font-size: 1.05rem; }
.plano-card-preco strong { font-size: 1.35rem; color: var(--brand); }
.plano-card-preco span { color: var(--text-muted); font-size: 0.8rem; }
.plano-card-desc { margin: 0; font-size: 0.82rem; color: var(--text-muted); }
.plano-card-limites { list-style: none; padding: 0; margin: 0; font-size: 0.8rem; }
.plano-card-limites li { display: flex; justify-content: space-between; padding: 0.2rem 0; color: var(--text-muted); }
.plano-card-limites strong { color: var(--text); }
.plano-card .toolbar-primary { margin-top: auto; }

@media (max-width: 620px) {
  .billing-hero { flex-direction: column; align-items: stretch; }
  .billing-hero-valor { text-align: left; }
  .plano-atual-preco { text-align: left; }
}

/* Lista de faturas dentro do popup de cobranca do super admin */
.bl-fatura-item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  margin-bottom: 0.4rem;
  font-size: 0.82rem;
}
.bl-fatura-item strong { min-width: 4.5rem; }


/* ===========================================================================
   Verificacao "nao sou robo" (2026-08-06; repaginada clara em 2026-08-18)

   Usada no login e no autocadastro (tema claro fixo das telas de acesso) --
   cores fixas da mesma paleta da landing, nunca os tokens do data-theme, do
   mesmo jeito que .auth-remember-row / .auth-card ja' fazem nessas telas.
   =========================================================================== */

/* Honeypot: escondido de gente, visivel pro bot que le' o HTML. NUNCA usar
   `display:none` sozinho aqui -- bot esperto pula campo com display:none.
   Tirar da tela por posicao + tamanho zero e' mais convincente. */
.human-check-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* Caixa do desafio proprio: parecida com a de um CAPTCHA de verdade, pra a
   pessoa reconhecer o gesto na hora. */
.human-check-box {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid #d2dcea;
  border-radius: 10px;
  background: #f4f7fc;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}

.human-check-box:hover {
  border-color: rgba(30, 136, 229, 0.45);
  background: #eef4fb;
}

/* O <input> real fica fora da tela mas continua focavel pelo teclado (por
   isso `opacity:0` + tamanho zero, e nao `display:none`, que o tiraria da
   ordem de tabulacao e quebraria o acesso por teclado). */
.human-check-box input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
}

.human-check-mark {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border: 2px solid #b9c6d8;
  border-radius: 5px;
  background: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  color: transparent;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}

.human-check-mark svg { width: 14px; height: 14px; }

.human-check-box input[type="checkbox"]:checked ~ .human-check-mark {
  background: #0e9f6e;
  border-color: #0e9f6e;
  color: #fff;
}

/* Foco visivel: sem isso quem navega por teclado nao enxerga onde esta',
   ja' que o <input> de verdade esta' fora da tela. */
.human-check-box input[type="checkbox"]:focus-visible ~ .human-check-mark {
  outline: 2px solid #1e88e5;
  outline-offset: 2px;
}

.human-check-text {
  font-size: 0.85rem;
  font-weight: 500;
  color: #3c5069;
}

/* Widget de terceiro (Turnstile/reCAPTCHA): so' garante que ele nao estoure
   a largura do cartao -- o visual e' do provedor. */
.human-check-widget {
  display: flex;
  justify-content: center;
  max-width: 100%;
  overflow: hidden;
}

/* Rodape do cartao de acesso: "ja tem conta? entrar" / "nao tem conta?
   criar" -- os dois sentidos usam o mesmo bloco. */
.auth-alt-action {
  margin: 1rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid #eef2f8;
  text-align: center;
  font-size: 0.85rem;
  color: #55677f;
}

.auth-alt-action a {
  color: #1565c0;
  font-weight: 600;
  text-decoration: none;
}

.auth-alt-action a:hover { text-decoration: underline; }

/* (A demonstracao saiu da tela de login em 2026-08-18 -- "quero somente
   login senha e cadastro" -- e o CSS .auth-demo-* foi removido junto. A
   rota /demonstracao continua existindo; a landing e' quem aponta pra ela.) */

/* Dica de senha embaixo do campo, no cadastro. Aqui NAO vale a regra de
   "nada de texto solto dentro do rotulo" das grades de 3 colunas: este
   formulario e' de coluna unica (.auth-card .form-grid), entao a altura de
   um campo nao desalinha vizinho nenhum. */
.auth-password-hint {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.75rem;
  line-height: 1.35;
  color: #8b99ad;
}

/* Checklist de forca de senha, embaixo do campo (2026-08-06, static/js/
   password_strength.js) -- usado nos 5 formularios que definem/trocam senha
   (cadastro, redefinicao, perfil, novo usuario de organizacao, novo usuario
   da conta). Duas dessas telas (cadastro/redefinicao) vivem no fundo escuro
   FIXO do auth-shell, independente do tema claro/escuro do resto do app --
   por isso o icone de cada item usa o MESMO par "fundo tintado + texto" que
   .flash.success/.flash.error ja' usa (--success-bg/--success-text,
   --error-bg/--error-text): e' o fundo proprio do pill que garante contraste,
   nao a cor do texto sozinha (que ficaria ilegivel, verde/vermelho escuro
   sobre fundo quase preto). O texto da linha em si fica sempre neutro
   (--text-muted) -- so' o icone muda de cor, nunca so' a cor decide o estado. */
.password-strength-checklist {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.password-strength-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
  line-height: 1.3;
  color: var(--text-muted);
}
.password-strength-mark {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  font-size: 0.6rem;
  line-height: 1;
  color: var(--text-faint);
  transition: background var(--dur-fast, 0.15s) var(--ease-out, ease),
              color var(--dur-fast, 0.15s) var(--ease-out, ease),
              border-color var(--dur-fast, 0.15s) var(--ease-out, ease);
}
.password-strength-mark::before { content: "•"; }
.password-strength-item.ok .password-strength-mark {
  background: var(--success-bg);
  border-color: transparent;
  color: var(--success-text);
}
.password-strength-item.ok .password-strength-mark::before { content: "✓"; }
.password-strength-item.erro .password-strength-mark {
  background: var(--error-bg);
  border-color: transparent;
  color: var(--error-text);
}
.password-strength-item.erro .password-strength-mark::before { content: "✕"; font-size: 0.54rem; }

/* Dica de "as senhas nao coincidem" sob o campo de confirmar senha -- mesmo
   raciocinio de pill tintado acima (fundo proprio, nao so' cor de texto). */
.password-strength-confirm-hint {
  display: inline-block;
  margin: 0.35rem 0 0;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.76rem;
  line-height: 1.4;
  color: var(--error-text);
  background: var(--error-bg);
}

/* Inventario do popup "Excluir organizacao" (2026-08-06). Excluir apaga tudo
   (dado, arquivo e login -- LGPD art. 18), entao a confirmacao mostra o que
   sera' apagado antes de liberar o botao. Sem animacao de entrada de
   proposito: e' conteudo, e animacao congelada em opacity esconderia
   justamente a lista que o usuario precisa ler pra decidir. */
.org-delete-inventario {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0.6rem 0 0.9rem;
  max-height: 240px;
  overflow-y: auto;
  padding: 0.7rem 0.85rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.org-delete-linha {
  font-size: 0.85rem;
  color: var(--text);
  line-height: 1.4;
}

.org-delete-linha strong {
  color: var(--error-text);
  margin-right: 0.15rem;
}

/* Aviso de dados de demonstracao (2026-08-06) -- so' aparece enquanto a
   conta ainda tem os registros semeados. Cor de AVISO, nao de erro: nao ha'
   nada errado, e' um estado temporario da conta nova. */
.demo-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.2rem;
  padding: 0.9rem 1.2rem;
  border: 1px solid var(--warning-text);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--warning-bg);
}

.demo-banner-texto {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.demo-banner-texto strong {
  font-size: 0.9rem;
  color: var(--warning-text);
}

.demo-banner-texto span {
  font-size: 0.82rem;
  color: var(--text-muted);
}

/* "Entrar com Google" (2026-08-06) -- as diretrizes da marca pedem o logo
   colorido sobre FUNDO BRANCO, entao este botao foge de proposito do tema
   escuro das telas de acesso. E' o unico lugar do sistema assim. */
.auth-divider {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 0.8rem 0 0.75rem;
  color: #8b99ad;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #e4eaf3;
}

/* Pilula pra casar com o CTA gradiente logo acima -- fundo branco + cores
   oficiais do "G" continuam obrigatorios pelas diretrizes do Google. */
.google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  width: 100%;
  padding: 0.7rem 1rem;
  border: 1px solid #d2dcea;
  border-radius: 999px;
  background: #fff;
  color: #3c4043;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

.google-btn:hover {
  background: #f7f8f8;
  border-color: #b9c6d8;
  box-shadow: 0 2px 8px rgba(14, 28, 46, 0.12);
}

/* Popup de cadastro (2026-08-06) -- pedido: "popup com a mesma UI do login,
   sobrepondo com fundo desfocado, levando pra escolha de plano e pagamento
   pros planos pagos". `display:none`/`.open{display:flex}` de proposito
   (nunca opacity/transform em animacao de entrada -- ja documentado neste
   projeto que isso deixa o conteudo invisivel quando o relogio de animacao
   nao avanca). O conteudo em si e' um <iframe> pra /criar-conta -- a "mesma
   UI do login" ja vem de graca por ser literalmente a mesma pagina. */
.signup-popup-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 500;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: rgba(15, 23, 32, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.signup-popup-overlay.open { display: flex; }

body.signup-popup-travado { overflow: hidden; }

.signup-popup-box {
  position: relative;
  width: 100%;
  max-width: 520px;
  height: min(760px, 92vh);
  border-radius: var(--radius-lg);
  overflow: hidden;
  /* Placeholder CLARO (tema claro das telas de acesso, 2026-08-18) -- e' a
     cor que aparece um instante antes de o iframe carregar, e tem que casar
     com o fundo do .signup-popup-frame la' dentro. */
  background: #f6f8fc;
  box-shadow: 0 30px 80px rgba(14, 28, 46, 0.35);
}

.signup-popup-box iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: none;
}

/* Botao "x": redeclara fundo/borda/sombra em TODO estado -- o `button`
   global do sistema (height fixo, fundo solido no hover) venceria por
   especificidade de elemento se so' a regra base fosse declarada. */
.signup-popup-close {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 2;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(14, 28, 46, 0.08);
  color: #55677f;
  font-size: 1.3rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.signup-popup-close:hover,
.signup-popup-close:focus,
.signup-popup-close:focus-visible,
.signup-popup-close:active {
  background: rgba(14, 28, 46, 0.16);
  border: none;
  box-shadow: none;
  transform: none;
  color: #0e1c2e;
}

@media (max-width: 620px) {
  .signup-popup-box { height: min(760px, 100dvh); border-radius: var(--radius-md); }
  .signup-popup-overlay { padding: 0.5rem; }
}

/* Conteudo do popup de cadastro (2026-08-13) -- so' o cartao do formulario,
   SEM a moldura de pagina de login (hero/logo/fundo animado), pedido do
   usuario: "e um popup padrao do sistema nao a tela de login". O fundo
   claro aqui e' fixo (nao depende do tema claro/escuro do site) pra casar
   com a cor de placeholder do proprio .signup-popup-box, que fica visivel
   um instante antes do iframe carregar. Os tokens --auth-* chegam pela
   regra compartilhada com .auth-shell la' em cima -- e' o que mantem o
   .auth-card inteiro funcionando aqui dentro sem .auth-shell por volta.
   `overflow-y: auto` evita que o formulario (com o widget de verificacao
   humana em modo turnstile/recaptcha, mais alto que o modo local) estoure
   a caixa de 760px sem jeito de rolar ate' o botao "Criar conta". */
.signup-popup-frame {
  min-height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f6f8fc;
  color: var(--auth-ink);
  font-family: var(--auth-body);
  padding: 1.5rem;
  overflow-y: auto;
}

.signup-popup-card {
  margin: auto;
}

.google-btn svg { flex: 0 0 auto; }

/* Demonstrativo da troca de plano (2026-08-06) -- pedido: "mostrar um
   demonstrativo com datas de cobranca/historico antes de confirmar a troca
   de plano". <dl> simples de rotulo/valor dentro do popup de confirmacao
   ja existente (#troca-plano-modal) -- comeca com `hidden` (ver
   _my_plan_content.html) e so' aparece quando o fetch em
   /meu-plano/simular/<id> responde. */
.troca-plano-demonstrativo {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.35rem 0.75rem;
  margin: 0 0 1rem;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  font-size: 0.85rem;
}

.troca-plano-demonstrativo dt { color: var(--text-muted); margin: 0; }
.troca-plano-demonstrativo dd { margin: 0; font-weight: 600; text-align: right; }

/* Metricas/Reputacao por plataforma (2026-08-11) -- "em vendas, continuar
   com reputação, e metricas! separados po plataformas". Lista rotulo/valor
   simples (repasse do canal) -- mesma linguagem visual do
   .troca-plano-demonstrativo (grid 2 colunas, rotulo apagado, valor forte
   a direita), so' que via <ul>/<li> pra reaproveitar o padrao de lista ja
   usado nas demais secoes do Dashboard. */
.metrics-kv-list { list-style: none; margin: 0; padding: 0.25rem 1.75rem 0.5rem; display: grid; gap: 0.5rem; }
.metrics-kv-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem;
  font-size: 0.86rem; padding-bottom: 0.5rem; border-bottom: 1px dashed var(--border);
}
.metrics-kv-row:last-child { border-bottom: none; padding-bottom: 0; }
.metrics-kv-row span { color: var(--text-muted); }
.metrics-kv-row strong { color: var(--text); font-variant-numeric: tabular-nums; }
.metrics-kv-row.is-total { padding-top: 0.35rem; border-top: 1px solid var(--border-strong); border-bottom: none; }
.metrics-kv-row.is-total strong { color: var(--brand-dark); }

/* Reputacao -- badge de nivel (Mercado Livre) e cartao por loja/integracao,
   um cartao repetido dentro de cada aba de plataforma. */
.reputation-store-card { padding: 1.5rem 1.75rem; border-top: 1px solid var(--border); }
.reputation-store-card:first-child { border-top: none; }
.reputation-store-head {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: 0.5rem 1rem; margin-bottom: 1rem;
}
.reputation-store-name { font-weight: 700; font-size: 0.98rem; }
.reputation-store-company { color: var(--text-muted); font-size: 0.82rem; font-weight: 400; margin-left: 0.4rem; }
.reputation-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.25rem; }
.reputation-stat-label { font-size: 0.76rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.02em; margin: 0 0 0.35rem; }
.reputation-stat-value { font-size: 1.05rem; font-weight: 700; }

/* Pos-venda (2026-08-11) -- lista de casos (reclamacao/devolucao/cancelamento)
   dentro de cada .reputation-store-card, mesmo cartao por loja ja usado em
   /reputacao. Uma linha por caso, sem tabela (o conjunto de campos varia
   pouco e uma lista e' mais leve que criar outro componente de tabela). */
.postsale-case-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.65rem; }
.postsale-case-row {
  padding: 0.65rem 0.85rem; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--bg-alt);
}
.postsale-case-main { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.3rem; }
.postsale-case-type { font-weight: 600; font-size: 0.9rem; }
.postsale-case-meta {
  display: flex; align-items: center; gap: 0.5rem 0.9rem; flex-wrap: wrap;
  font-size: 0.8rem; color: var(--text-muted);
}
.postsale-case-reason { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }

/* Bloco recolhido de preferencias na tela /notificacoes (2026-08-11). O
   <summary> herda o cursor/afordancia padrao do <details>; so' precisa de
   respiro e de nao herdar o visual de titulo de painel. */
.notif-prefs-inline { margin-top: 1.25rem; }
.notif-prefs-inline > summary {
  cursor: pointer;
  font-size: 0.95rem;
  color: var(--text);
}

/* ---------------------------------------------------------------------------
   Aba "Características" do anúncio em 2 colunas (2026-08-11): esquerda = ficha
   da categoria (aberta), direita = o que o produto base já tem, como consulta.
   Colapsa em 1 coluna no mesmo breakpoint que o resto da tela do anúncio.    */
.ad-chars-2col {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}
.ad-chars-2col > .panel { margin: 0; }
.ad-chars-2col .ad-product-reference-panel { position: sticky; top: 8.5rem; }
@media (max-width: 980px) {
  .ad-chars-2col { grid-template-columns: 1fr; }
  .ad-chars-2col .ad-product-reference-panel { position: static; }
}

/* Ações no cabeçalho de um <details> (Salvar atributos / Preencher com IA na
   MESMA linha do título). O <summary> já é flex com espaço entre os lados --
   isto só agrupa os botões antes do chevron. `form` interno some do fluxo
   pra o botão dele encostar no vizinho, sem herdar espaçamento de bloco.    */
.panel-head-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.panel-head-actions form { display: contents; }

/* Aplicação do produto base dentro da Compatibilidade -- caixa clicável,
   fechada por padrão pra não empurrar a tabela.                             */
.compat-base-application {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  margin-bottom: 0.75rem;
}
.compat-base-application > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.8rem;
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-muted);
  list-style: none;
}
.compat-base-application > summary::-webkit-details-marker { display: none; }
.compat-base-application > summary:hover { color: var(--brand-dark); }
.compat-base-application > summary .collapse-chevron {
  margin-left: auto;
  transition: transform var(--dur-fast) var(--ease-out);
}
.compat-base-application[open] > summary .collapse-chevron { transform: rotate(90deg); }
.compat-base-application-text {
  margin: 0;
  padding: 0 0.8rem 0.7rem;
  max-height: 240px;
  overflow: auto;
  white-space: pre-wrap;
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--text);
}

/* ===========================================================================
   Telas de anúncio e de cadastro de produto -- repaginação visual (2026-08-11, pedido do usuário:
   "repaginar todo layout das telas de anúncios, moderna e rápida, com visual
   premium e profissional, com efeitos leves e bonitos").

   TUDO escopado em #ad-detail-root de propósito: `.ad-tab-bar`/`.ad-tab-btn`
   e `.panel` são compartilhados com Configurações, Produto, Empresa,
   Métricas e Reputação -- mexer neles sem escopo repaginaria o sistema
   inteiro, muito além do que foi pedido.

   Nenhum efeito de ENTRADA usa opacity/transform que possa esconder conteúdo:
   com o relógio de animação parado (aba em segundo plano, compositor
   ocupado) o frame 0 ficaria visível pra sempre. Só há transição em hover e
   em estado, onde o repouso já é o estado legível.                          */

/* Barra de abas: pílulas com fundo próprio e realce sólido na ativa. */
#ad-detail-root .ad-tab-bar,
#product-detail-root .ad-tab-bar{
  gap: 0.3rem;
  padding: 0.35rem 0.35rem 0;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--bg) 60%, transparent);
  backdrop-filter: blur(8px);
}
#ad-detail-root .ad-tab-btn,
#product-detail-root .ad-tab-btn{
  border-radius: var(--radius-sm);
  border-bottom: 2px solid transparent;
  padding: 0.6rem 0.95rem;
  letter-spacing: 0.01em;
}
#ad-detail-root .ad-tab-btn:hover,
#product-detail-root .ad-tab-btn:hover{
  background: var(--brand-soft);
  color: var(--brand-dark);
}
#ad-detail-root .ad-tab-btn.active,
#product-detail-root .ad-tab-btn.active{
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-bottom-color: var(--brand);
  box-shadow: inset 0 -2px 0 var(--brand);
}

/* Painéis: cantos e sombra um pouco mais suaves + elevação leve no hover.
   `transform` só no hover (nunca em repouso) pra não criar stacking context
   permanente -- armadilha já documentada no projeto com dropdowns internos. */
#ad-detail-root .panel,
#product-detail-root .panel{
  border-radius: var(--radius-lg);
  transition: box-shadow var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}
#ad-detail-root .panel:hover,
#product-detail-root .panel:hover{ box-shadow: var(--shadow-md); }
#ad-detail-root .panel > h3,
#product-detail-root .panel > h3,
#ad-detail-root .panel-head h3,
#product-detail-root .panel-head h3{
  letter-spacing: -0.01em;
}
/* Fio de destaque no topo do painel em foco -- pista visual discreta de
   "esta é a seção em que você está mexendo". */
#ad-detail-root .panel:focus-within,
#product-detail-root .panel:focus-within{
  border-color: var(--brand);
  box-shadow: var(--shadow-md);
}

/* Seções recolhíveis: cabeçalho ganha realce ao passar o mouse. */
#ad-detail-root .collapsible-panel > summary.panel-head,
#product-detail-root .collapsible-panel > summary.panel-head{
  border-radius: var(--radius-lg);
  transition: background var(--dur-fast) var(--ease-out);
}
#ad-detail-root .collapsible-panel > summary.panel-head:hover,
#product-detail-root .collapsible-panel > summary.panel-head:hover{
  background: var(--bg-alt);
}

/* Cabeçalho do Cadastro de Produto na MESMA linha das ações (2026-08-11) --
   .ad-header-actions nasceu como bloco separado (margin-top empurrava pra
   segunda linha); dentro da .ad-header-bar ela vira o grupo da direita.
   Escopado no header do produto pra não mexer no do anúncio, que já tem o
   arranjo próprio dele. */
#product-header-panel .ad-header-bar { justify-content: space-between; }
#product-header-panel .ad-header-bar .ad-header-actions {
  margin-top: 0;
  margin-left: auto;
}

/* =====================================================================
   Barra de progresso do anúncio (etapas) + realce dos obrigatórios
   Pedido do usuário (2026-08-12): "barra de progresso nos anuncios, no
   todo, como se fosse etapas de progresso" + "todos os requisito
   obrigatorio quando nao preenchido tem q ficar em focus e ter alertas".
   Fonte da verdade das etapas é o backend (build_ad_progress); aqui é só
   a apresentação. Cores por PAPEL (success/warning/error), nunca hex solto.
   ===================================================================== */

/* Painel mais enxuto que os demais: é uma faixa de leitura rápida no topo
   da tela, não um painel de conteúdo -- com o padding cheio do .panel
   (25.6px) ele empurrava demais o resto da página pra baixo. */
.ad-progress-panel {
  margin-bottom: 1rem;
  padding: 1rem 1.25rem 1.1rem;
}

.ad-progress-head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-bottom: 0.8rem;
}

.ad-progress-title {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
}

.ad-progress-title strong { font-size: 0.92rem; color: var(--text); line-height: 1.2; }

.ad-progress-pct {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--brand-dark);
  line-height: 1;
}

/* Resumo colado no título, não jogado no extremo direito: num painel de
   ~1090px o space-between abria um vão de ~670px entre duas informações
   que se leem juntas ("91%" / "1 obrigatório faltando"). */
.ad-progress-summary {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--neutral-soft);
}

.ad-progress-summary.tem-pendencia { color: var(--error-text); background: var(--error-bg); }
.ad-progress-summary.tudo-ok { color: var(--success-text); background: var(--success-bg); }

/* Faixa de etapas: uma coluna por etapa, cada uma com a própria barrinha.
   auto-fit + minmax faz as etapas caberem em qualquer largura sem estourar
   (canal com 6 etapas x canal com 4). */
.ad-progress-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 0.55rem 0.7rem;
}

/* É um <button> -- precisa desfazer o visual do botão global (fundo azul,
   altura fixa, centralização), mesma armadilha já documentada em
   .ad-tab-btn/.stat-cell/.copy-icon-btn. */
.ad-progress-step,
.ad-progress-step:hover,
.ad-progress-step:focus,
.ad-progress-step:focus-visible,
.ad-progress-step:active {
  background: none;
  border: none;
  box-shadow: none;
  height: auto;
  min-height: 0;
  padding: 0;
  margin: 0;
  text-align: left;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 0.35rem;
  cursor: pointer;
  color: var(--text-muted);
  transform: none;
  outline: none;
}

/* Anel de foco de volta para o teclado: a regra acima zera outline E
   box-shadow (precisa, pra matar o visual do botão global), e sem isto quem
   navega por Tab ficava SEM nenhum indicador -- medido na revisão. */
.ad-progress-step:focus-visible {
  box-shadow: 0 0 0 3px var(--brand-glow);
  border-radius: var(--radius-sm);
}

.ad-progress-step:hover .ad-progress-step-name,
.ad-progress-step:focus-visible .ad-progress-step-name { color: var(--brand-dark); }

.ad-progress-step-bar {
  display: block;
  height: 7px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}

.ad-progress-step-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--brand);
  transition: width var(--dur-base) var(--ease-out);
}

/* Estado da etapa: vazia (cinza), parcial (marca), com obrigatório faltando
   (vermelho -- é o que impede publicar) e concluída (verde).
   O TRILHO também muda de cor -- sem isso uma etapa em 0% fica com a barra
   inteira cinza e some justamente a informação mais importante: que ela
   está BLOQUEANDO a publicação (a faixa preenchida tem largura zero, então
   a cor do fill não aparece). Bug medido na revisão. */
.ad-progress-step.state-blocked .ad-progress-step-bar { background: var(--error-bg); }
.ad-progress-step.state-blocked .ad-progress-step-fill { background: var(--error-text); }
.ad-progress-step.state-partial .ad-progress-step-bar { background: var(--brand-soft); }
.ad-progress-step.state-done .ad-progress-step-fill { background: var(--success-text); }
.ad-progress-step.state-empty .ad-progress-step-fill { background: var(--border-strong); }

/* Rótulo SEMPRE em uma linha: o contador nunca some e o nome trunca com
   reticências (o nome completo fica no title da etapa). Antes o conjunto
   podia quebrar em 2-3 linhas e, como só alguns rótulos quebravam, a
   fileira ficava visivelmente irregular -- medido em 1280px (largura de
   notebook comum): "Informações básicas" com 33px de altura ao lado de
   "Fotos" com 14px. */
.ad-progress-step-label {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  min-width: 0;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.3;
}

.ad-progress-step-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ad-progress-step-count {
  flex: 0 0 auto;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.ad-progress-step.state-blocked .ad-progress-step-count { color: var(--error-text); }
.ad-progress-step.state-done .ad-progress-step-count { color: var(--success-text); }

/* Chips do que falta -- clicar leva até o campo. */
.ad-progress-pending {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.85rem;
}

.ad-progress-pending:empty { display: none; }

.ad-progress-chip,
.ad-progress-chip:hover,
.ad-progress-chip:focus,
.ad-progress-chip:focus-visible,
.ad-progress-chip:active {
  height: auto;
  min-height: 0;
  padding: 0.28rem 0.65rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  cursor: pointer;
  transform: none;
  box-shadow: none;
  outline: none;
}

.ad-progress-chip {
  background: var(--neutral-soft);
  color: var(--text-muted);
  border: 1px solid var(--border);
}

.ad-progress-chip:hover,
.ad-progress-chip:focus-visible {
  background: var(--brand-soft);
  color: var(--brand-dark);
  border-color: var(--brand);
}

.ad-progress-chip.obrigatorio {
  background: var(--error-bg);
  color: var(--error-text);
  border-color: var(--error-text);
}

.ad-progress-chip.obrigatorio:hover,
.ad-progress-chip.obrigatorio:focus-visible {
  background: var(--error-text);
  color: #fff;
  border-color: var(--error-text);
}

/* Mesmo motivo do anel de foco da etapa. */
.ad-progress-chip:focus-visible { box-shadow: 0 0 0 3px var(--brand-glow); }

.ad-progress-chip svg { width: 12px; height: 12px; flex-shrink: 0; }

/* --- Realce do campo pendente ---------------------------------------- */

/* Aplicado por JS no campo obrigatório vazio (input/select/textarea).
   Só a moldura muda -- nunca esconde nem desabilita nada. */
.campo-obrigatorio-pendente {
  border-color: var(--error-text) !important;
  background: var(--error-bg);
}

/* Pulso curto ao "ir até o campo" pelo chip/etapa. Só box-shadow: nada de
   opacity nem transform, pra o campo nunca sumir se a animação não rodar
   (aba em segundo plano). */
@keyframes campo-foco-pulso {
  0%   { box-shadow: 0 0 0 0 rgba(244, 67, 54, 0.45); }
  100% { box-shadow: 0 0 0 10px rgba(244, 67, 54, 0); }
}

.campo-foco-pulso { animation: campo-foco-pulso 1.1s var(--ease-out) 2; }

/* --- Características: gauge semicírculo + pendências ------------------ */

.attrs-progress {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

/* Gauge menor que o da qualidade (cabe no cabeçalho da seção, ao lado do
   título) -- reaproveita o desenho de .quality-gauge (arco de raio 50,
   comprimento 157.08), só encolhendo. */
.attrs-gauge { width: 58px; flex-shrink: 0; }
.attrs-gauge .quality-gauge-svg { width: 58px; height: 34px; }
.attrs-gauge .quality-gauge-value { font-size: 0.58rem; }
.attrs-gauge .quality-gauge-value strong { font-size: 0.7rem; }

.attrs-progress-text {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.attrs-progress-count { font-size: 0.78rem; font-weight: 800; color: var(--text); }
.attrs-progress-caption { font-size: 0.62rem; font-weight: 600; color: var(--text-muted); }

/* Aviso de obrigatórias faltando, no topo da seção. */
.attrs-alert {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 0.8rem;
  border-radius: var(--radius-sm);
  background: var(--error-bg);
  color: var(--error-text);
  font-size: 0.78rem;
  font-weight: 700;
  margin-bottom: 0.9rem;
}

.attrs-alert svg { width: 15px; height: 15px; flex-shrink: 0; }
.attrs-alert span { flex: 1 1 auto; min-width: 0; }

/* O .button-link global tem altura de campo (var(--field-h)) -- dentro do
   aviso isso jogava o botão pra uma segunda linha e deixava o bloco com
   86px de altura (medido). Aqui ele vira um botão compacto que cabe na
   mesma linha do texto. */
.attrs-alert .button-link,
.attrs-alert .button-link:hover,
.attrs-alert .button-link:focus,
.attrs-alert .button-link:active {
  flex: 0 0 auto;
  height: auto;
  min-height: 0;
  padding: 0.22rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 700;
  border-radius: 999px;
  background: var(--error-text);
  border: 1px solid var(--error-text);
  color: #fff;
  box-shadow: none;
  transform: none;
  white-space: nowrap;
}

.attrs-alert .button-link:hover { filter: brightness(1.12); }

/* Campo de atributo obrigatório vazio: moldura de alerta na célula inteira,
   pra achar de relance no meio de uma grade de 3 colunas. */
.attributes-grid > label.attr-pendente {
  border-left: 3px solid var(--error-text);
  padding-left: 0.6rem;
  margin-left: -0.6rem;
  border-radius: 2px;
}

.attributes-grid > label.attr-pendente .attr-label-row { color: var(--error-text); }

@media (max-width: 700px) {
  .ad-progress-steps { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
  .ad-progress-panel { padding: 0.9rem 1rem 1rem; }
  .ad-progress-head { gap: 0.5rem; }
  /* Em tela estreita o texto ocupa a linha e o botão desce -- aqui a quebra
     é aceitável (não há largura pra manter os dois lado a lado). */
  .attrs-alert { flex-wrap: wrap; }
  .attrs-alert .button-link { margin-left: auto; }
}


/* Guias de tamanho > Publicacao nos canais (2026-08-12): um cartao por
   destino, com o estado a esquerda e os botoes SEMPRE agrupados a direita
   (pedido do usuario: "os botoes sempre devem estar agrupados"). Antes eram
   dois .form-row-banner com o botao solto no meio do texto corrido.
   O cartao da imagem NAO usa a cor da marca na faixa: ela e' so' gerada aqui,
   nao e' uma publicacao de verdade nesses canais. */
.publish-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  padding: 0.9rem 1.1rem;
}
.publish-card + .publish-card { margin-top: 0.75rem; }
.publish-card-imagem { border-left-color: var(--neutral); }

.publish-card-info {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}
.publish-card-canais {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.publish-card-desc {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-faint);
}

/* estado + botoes viajam juntos no canto direito */
.publish-card-lado {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.publish-card-acoes { margin: 0; }

@media (max-width: 620px) {
  .publish-card { align-items: stretch; }
  .publish-card-lado { justify-content: flex-end; }
}

/* Listagem de guias: estado real de cada entrega, uma linha por destino. */
.size-chart-estado {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.size-chart-estado-linha {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}

/* Cabecalho de coluna da tabela de medidas: rotulo + "*" de obrigatorio +
   icone de ajuda, na mesma linha (mesma convencao da tela do Mercado Livre). */
.size-chart-col-head {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.size-chart-col-req {
  color: var(--error-text);
  font-weight: 700;
}
.size-chart-req-legend {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.6rem;
}

/* Bolha do tooltip abrindo PRA BAIXO. Necessario dentro de .table-scroll, que
   tem overflow-y: hidden -- acima do cabecalho a bolha seria cortada e o
   usuario nunca leria a explicacao da coluna. */
.field-tooltip.tooltip-below[data-tooltip]::after {
  bottom: auto;
  top: calc(100% + 9px);
}
.field-tooltip.tooltip-below[data-tooltip]::before {
  bottom: auto;
  top: calc(100% + 3px);
  border-top-color: transparent;
  border-bottom-color: var(--dark);
}


/* Guia de tamanhos no anuncio: campo PROPRIO, isolado das demais
   caracteristicas (pedido do usuario, 2026-08-12). Nao e' um texto como os
   outros -- e' a referencia a uma guia cadastrada, e sem ela o Mercado Livre
   recusa a publicacao inteira em moda. Por isso ganha destaque e o selo de
   obrigatorio, em vez de ficar perdido no meio da grade de atributos. */
.size-grid-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  padding: 0.9rem 1.1rem;
  margin-bottom: 1.1rem;
}
/* obrigatoria e ainda vazia: o mesmo tom de alerta dos demais pendentes */
.size-grid-field-pendente {
  border-left-color: var(--error-text);
  background: var(--error-bg);
}

.size-grid-field-info {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}
.size-grid-field-desc {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-faint);
}
.size-grid-field-controle {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.size-grid-field-controle select { min-width: 260px; }
.size-grid-field-acoes { margin: 0; }
/* ocupa a linha inteira embaixo dos dois lados */
.size-grid-field-aviso {
  flex: 1 0 100%;
  margin: 0;
  font-size: 0.78rem;
}

/* Genero + Tamanho no MESMO cartao da guia (2026-08-14). Linha inteira, como
   o aviso. auto-fit/minmax em vez de media query: os dois campos ficam lado a
   lado quando cabem e viram pilha sozinhos em tela estreita. */
.size-grid-field-casados {
  flex: 1 0 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0.7rem;
  padding-top: 0.2rem;
}
.size-grid-field-casado {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
  margin: 0;
}
.size-grid-field-casado-nome {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
}
/* select/input do projeto ja' e' width:100%; aqui o min-width:0 e' o que
   impede o campo de estourar a coluna do grid (conteudo intrinseco). */
.size-grid-field-casado select,
.size-grid-field-casado input { min-width: 0; width: 100%; }

@media (max-width: 620px) {
  .size-grid-field-controle { width: 100%; }
  .size-grid-field-controle select { min-width: 0; flex: 1; }
}

/* --- Observacao do CDC no popup de troca de plano (2026-08-12) ------------
   Pedido do usuario: "observacao ou icone de informacao com dado do codigo
   de defesa do consumidor pra clientes brasileiros". Cor INFORMATIVA
   (--info-*, mesma linguagem da tarja de ambiente de teste) -- e' orientacao
   legal, nao alerta de problema. */
.troca-plano-cdc {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  background: var(--info-bg);
  color: var(--info-text);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  margin: 0.6rem 0 0;
  font-size: 0.78rem;
  line-height: 1.45;
}
.troca-plano-cdc svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  margin-top: 0.15rem;
}

/* --- Aviso de moeda mista no painel de Valores (eBay, 2026-08-14) ---------
   E' um alerta de leitura, nao uma dica qualquer: sem destaque ele se
   perderia entre os campos e o vendedor leria o "Lucro" como se fosse real. */
.currency-mix-note {
  margin: 0.1rem 0 0.7rem;
  padding: 0.55rem 0.7rem;
  border-left: 3px solid var(--warning-text);
  border-radius: var(--radius-sm);
  background: var(--warning-bg);
  color: var(--text);
  line-height: 1.45;
}

/* --- Conferencia das fotos contra as exigencias do eBay (2026-08-14) ------
   Fica DENTRO do painel de Fotos, logo abaixo das miniaturas: e' sobre elas.
   Duas severidades no mesmo bloco -- "bloqueia" (o eBay recusa) e "atencao"
   (ele aceita, mas penaliza) --, cada linha com o selo antes do texto pra
   diferenca nao depender so' de cor. */
.ebay-photo-check {
  margin-top: 0.7rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--warning-text);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
}

.ebay-photo-check-title {
  margin: 0 0 0.45rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text);
}

.ebay-photo-check-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.ebay-photo-check-item {
  display: flex;
  align-items: flex-start;
  gap: 0.45rem;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text);
}

.ebay-photo-check-badge {
  flex: 0 0 auto;
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.12rem 0.4rem;
  border-radius: 999px;
  margin-top: 0.1rem;
}

.ebay-photo-check-item.is-error .ebay-photo-check-badge {
  background: var(--error-bg);
  color: var(--error-text);
}

.ebay-photo-check-item.is-warn .ebay-photo-check-badge {
  background: var(--warning-bg);
  color: var(--warning-text);
}

.ebay-photo-check-hint {
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  color: var(--text-faint);
}

/* --- Cadastro inline de politica/local do eBay (2026-08-12) ---------------
   Business Policies (envio/pagamento/devolucao) e local de estoque sao
   EXCLUSIVOS do eBay entre os canais deste app -- quando a conta ainda nao
   tem nenhuma, o vendedor precisa cadastrar sem sair da tela do anuncio.
   <details> nativo em vez de modal JS: nao precisa de markup de chevron
   proprio nem de listener de abrir/fechar. */
.ebay-policy-create {
  grid-column: 1 / -1;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.85rem;
  margin-top: 0.35rem;
}
.ebay-policy-create > summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--brand-dark);
  list-style: none;
}
.ebay-policy-create > summary::-webkit-details-marker { display: none; }
.ebay-policy-create > summary::before { content: "+ "; }
.ebay-policy-create[open] > summary::before { content: "\2212 "; }

/* --- Cascata de compatibilidade em telas pequenas (2026-08-14) ------------
   Fica aqui no fim, junto das demais regras responsivas: mobile no meio do
   arquivo perde por cascata, em silencio. Em telas estreitas as colunas
   viram uma pilha vertical (cada uma ocupa a largura toda e rola sozinha),
   em vez de exigir rolagem horizontal dentro do popup. */
@media (max-width: 720px) {
  .compat-cascade-columns {
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    max-height: 60vh;
  }
  .compat-cascade-col {
    flex: 0 0 auto;
    max-height: 210px;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  .compat-cascade-col:last-child { border-bottom: none; }
  .compat-cascade-bar { flex-direction: column; align-items: stretch; }
  .compat-cascade-bar-actions { justify-content: flex-end; }
}

/* --- Anuncios do Google em telas pequenas (2026-08-14) --------------------
   Fica aqui no fim, junto das demais regras responsivas: mobile no meio do
   arquivo perde por cascata, em silencio.

   A lateral (.google-ads-rail) SOME abaixo de 1360px -- nao ha' espaco pra
   uma faixa de 300px fixa sem cobrir o conteudo (a coluna de conteudo por si
   so' ja' fica apertada bem antes disso). A flutuante continua, so' sobe pra
   nao ficar atras da barra de navegacao inferior do celular (mesmo valor ja'
   usado pela pilha de avisos, calc(4.75rem + safe-area)). */
@media (max-width: 1360px) {
  .google-ads-rail {
    display: none;
  }
}

@media (max-width: 980px) {
  .google-ads-floating {
    left: 0.75rem;
    bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px));
  }
  body.tem-billing-tarja .google-ads-floating {
    bottom: calc(4.75rem + 96px + env(safe-area-inset-bottom, 0px));
  }
}

/* --- Ajuda contextual + tour guiado em celular (2026-08-16) --------------
   Mesma logica do painel de notificacoes: `position: fixed` colado nas
   bordas da viewport (o `top` real vem de JS, medindo o botao -- ver
   toggleHelpMenu em app_tour.js). O card do tour guiado tambem ganha teto
   de largura pra nunca estourar a tela em celular estreito. */
@media (max-width: 620px) {
  .help-dropdown {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    top: 7.25rem;
    width: auto;
    max-height: min(420px, calc(100vh - 11rem));
  }

  .adsp-tour-card {
    width: calc(100vw - 2rem);
  }
}

/* --- /documentacao -- organograma interativo do sistema (2026-08-16) -----
   Pedido do usuario: tela premium, animada e didatica, "tipo uma escola",
   organograma clicavel com instrucoes/requisitos/data/link por etapa.
   Reaproveita os MESMOS tokens de --brand/--surface/--border do resto do
   sistema (troca de tema clara/escura sozinha, nenhuma cor solta aqui) e a
   MESMA tecnica de borda animada por conic-gradient ja usada no auth-card
   da tela de login (2026-08-03) -- aqui so' no hero, nao em cada card (15
   cards animando ao mesmo tempo pesaria e ia contra o proposito didatico,
   que e' o usuario ler com calma, nao ficar com o olho puxado pra luz). */

.doc-page { display: flex; flex-direction: column; gap: 1.75rem; }

.doc-hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  padding: 2.4rem 2.1rem;
  background: linear-gradient(135deg, var(--sidebar-bg) 0%, var(--sidebar-bg-alt) 55%, var(--brand-dark) 145%);
  box-shadow: var(--shadow-lg);
}

.doc-hero-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.5;
  pointer-events: none;
  animation: doc-glow-pulse 9s ease-in-out infinite;
}

.doc-hero-glow-a { width: 340px; height: 340px; background: var(--brand); top: -140px; right: -80px; }
.doc-hero-glow-b { width: 260px; height: 260px; background: var(--info-text); bottom: -120px; left: 10%; animation-delay: -4.5s; }

@keyframes doc-glow-pulse {
  0%, 100% { transform: scale(1); opacity: 0.45; }
  50% { transform: scale(1.15); opacity: 0.65; }
}

.doc-hero-inner { position: relative; z-index: 1; max-width: 760px; }

.doc-hero-eyebrow {
  display: inline-block;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.72rem;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.72);
}

.doc-hero h1 {
  color: #fff;
  font-size: 1.85rem;
  margin: 0.4rem 0 0.65rem;
}

.doc-hero-inner p {
  color: rgba(226, 232, 240, 0.78);
  font-size: 0.95rem;
  margin: 0;
}

.doc-hero-stats { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 1.4rem; }

.doc-hero-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  padding: 0.4rem 0.95rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(6px);
}

.doc-hero-stat strong { font-size: 0.98rem; color: #fff; }

.doc-phase-nav { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.doc-phase-chip {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  border-radius: 999px;
  padding: 0.45rem 1rem;
  font-size: 0.78rem;
  font-weight: 700;
  transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}

.doc-phase-chip:hover, .doc-phase-chip.active {
  border-color: var(--brand);
  color: var(--brand-dark);
  background: var(--brand-soft);
}

.doc-click-hint { margin: -0.4rem 0 0; font-size: 0.78rem; color: var(--text-faint); }

.doc-map { position: relative; }

.doc-map::before {
  content: "";
  position: absolute;
  left: 27px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: linear-gradient(180deg, var(--brand) 0%, var(--info-text) 50%, var(--brand) 100%);
  background-size: 100% 220%;
  opacity: 0.3;
  animation: doc-spine-flow 7s linear infinite;
}

@keyframes doc-spine-flow {
  to { background-position: 0 220%; }
}

.doc-phase {
  position: relative;
  padding-left: 4rem;
  margin-bottom: 2.6rem;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

.doc-phase.in-view { opacity: 1; transform: none; }
.doc-phase:last-child { margin-bottom: 0; }

.doc-phase-node {
  position: absolute;
  left: 0;
  top: 0;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--brand);
  display: grid;
  place-items: center;
  font-family: "Plus Jakarta Sans", "Inter", sans-serif;
  font-weight: 800;
  font-size: 1.2rem;
  color: var(--brand-dark);
  box-shadow: var(--shadow-md);
  z-index: 1;
}

.doc-phase-head { margin-bottom: 1.1rem; padding-top: 0.55rem; }
.doc-phase-head h2 { margin: 0 0 0.2rem; font-size: 1.15rem; }
.doc-phase-head p { margin: 0; color: var(--text-muted); font-size: 0.85rem; }

.doc-stage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1rem;
}

.doc-stage-card {
  position: relative;
  text-align: left;
  background: var(--surface);
  /* `.doc-stage-card` e' um <button> -- sem `color` proprio aqui, ele herda
     o `color: white` do botao global do sistema (pensado pra botao SOLIDO
     azul, nao pra este card claro). Explicito pra nunca depender disso. */
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.05rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  height: 100%;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}

/* BUG REAL corrigido (2026-08-16, reportado pelo usuario -- "o hover ta
   ridiculo, ilegivel, primitivo"): sem `background`/`color` proprios aqui,
   o hover CAIA no `button:hover` global (fundo azul solido + texto branco,
   pensado pro botao de acao do sistema) -- e como os textos internos (h3/p/
   numero) tem cor propria ESCURA, o resultado era texto escuro em cima de
   azul solido, e o link "Ver detalhes" (mesma cor do fundo) sumia por
   completo. Corrigido fixando fundo/cor aqui, com um destaque de verdade
   (tingido suave + titulo e icone reagindo), nao so' "voltar ao normal". */
.doc-stage-card:hover, .doc-stage-card:focus-visible {
  transform: translateY(-3px);
  background: var(--brand-soft);
  color: var(--text);
  box-shadow: var(--shadow-md);
  border-color: var(--brand);
}

.doc-stage-card:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--brand-glow), var(--shadow-md); }

.doc-stage-card:hover h3 { color: var(--brand-dark); }

.doc-stage-top { display: flex; align-items: center; justify-content: space-between; }

.doc-stage-icon {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--brand-soft);
  color: var(--brand-dark);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

/* Fundo do card virou `--brand-soft` no hover -- o icone precisa de um tom
   com contraste PROPRIO nesse estado, senao os dois se fundem (mesma cor). */
.doc-stage-card:hover .doc-stage-icon {
  background: var(--brand);
  color: #fff;
  transform: scale(1.06);
}

.doc-stage-icon svg { width: 20px; height: 20px; }
.doc-stage-num { font-size: 0.68rem; font-weight: 800; color: var(--text-faint); letter-spacing: 0.04em; }

.doc-stage-card h3 { margin: 0; font-size: 0.98rem; transition: color var(--dur-base) var(--ease-out); }
.doc-stage-card > p { margin: 0; font-size: 0.8rem; color: var(--text-muted); flex: 1; }

.doc-stage-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.2rem;
}

.doc-admin-tag {
  font-size: 0.6rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--warning-text);
  background: var(--warning-bg);
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
  white-space: nowrap;
}

.doc-stage-view {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--brand-dark);
  margin-left: auto;
  opacity: 0.75;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.doc-stage-card:hover .doc-stage-view { opacity: 1; transform: translateX(2px); }

/* Drawer de detalhe (slide-over pela direita) -- mesma linguagem visual do
   painel de notificacoes/ajuda (fixed, sombra grande, transform pra animar
   entrada), mas overlay proprio porque este cobre a tela inteira, nao so'
   um dropdown ancorado num botao. */
.doc-drawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 21, 31, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out);
  z-index: 260;
}

.doc-drawer-overlay.open { opacity: 1; pointer-events: auto; }

.doc-drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100%;
  width: min(500px, 100vw);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  transform: translateX(100%);
  transition: transform var(--dur-slow) var(--ease-spring);
  z-index: 261;
  display: flex;
  flex-direction: column;
}

.doc-drawer.open { transform: none; }

.doc-drawer-head {
  position: relative;
  padding: 1.5rem 1.6rem 1.15rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-alt);
  flex-shrink: 0;
}

.doc-drawer-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 50%;
  background: var(--neutral-soft);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 1.1rem;
  line-height: 1;
  box-shadow: none;
}

.doc-drawer-close:hover { background: var(--danger); border-color: var(--danger); color: #fff; }

.doc-drawer-num {
  display: inline-block;
  font-family: "Plus Jakarta Sans", "Inter", sans-serif;
  font-weight: 800;
  font-size: 0.78rem;
  color: var(--brand-dark);
  background: var(--brand-soft);
  border-radius: 999px;
  padding: 0.15rem 0.65rem;
  margin-bottom: 0.5rem;
}

.doc-drawer-admin-tag {
  display: inline-block;
  margin: 0 0 0.5rem 0.4rem;
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--warning-text);
  background: var(--warning-bg);
  border-radius: 999px;
  padding: 0.18rem 0.55rem;
}

.doc-drawer-head h2 { margin: 0 0 0.4rem; font-size: 1.2rem; padding-right: 2rem; }
.doc-drawer-resumo { margin: 0 0 0.75rem; font-size: 0.86rem; color: var(--text-muted); }

.doc-updated-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.72rem;
  color: var(--text-faint);
}

.doc-drawer-body {
  padding: 1.3rem 1.6rem 2rem;
  overflow-y: auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
}

.doc-drawer-descricao { margin: 0; font-size: 0.88rem; color: var(--text); line-height: 1.6; }

.doc-section-title {
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-bottom: 0.6rem;
}

.doc-steps {
  margin: 0;
  padding-left: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  font-size: 0.86rem;
  color: var(--text);
}

.doc-steps li { padding-left: 0.15rem; }

.doc-reqs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }

.doc-reqs li {
  position: relative;
  padding: 0.5rem 0.7rem 0.5rem 2rem;
  font-size: 0.82rem;
  color: var(--text);
  background: var(--warning-bg);
  border-radius: var(--radius-sm);
  line-height: 1.5;
}

.doc-reqs li::before {
  content: "!";
  position: absolute;
  left: 0.7rem;
  top: 0.48rem;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--warning-text);
  color: #fff;
  font-size: 0.66rem;
  font-weight: 800;
  display: grid;
  place-items: center;
}

.doc-reqs-compact { margin-top: 0.2rem; }
.doc-reqs-compact li { padding: 0.4rem 0.6rem 0.4rem 1.75rem; font-size: 0.76rem; }
.doc-reqs-compact li::before { width: 13px; height: 13px; font-size: 0.6rem; left: 0.6rem; top: 0.42rem; }

.doc-platform-grid { display: flex; flex-direction: column; gap: 0.85rem; }

.doc-platform-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.9rem 1rem;
  background: var(--bg-alt);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.doc-platform-card h4 { margin: 0; font-size: 0.9rem; }
.doc-platform-auth { margin: 0; font-size: 0.76rem; color: var(--text-muted); }
.doc-platform-ref-label { font-size: 0.7rem; color: var(--text-faint); margin-top: 0.15rem; }

.doc-ref-links { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.doc-ref-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--brand-dark);
  background: var(--brand-soft);
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}

.doc-ref-link:hover { background: var(--brand); color: #fff; }
.doc-ref-link svg { flex-shrink: 0; }

.doc-drawer-cta { margin-top: 0.2rem; width: 100%; }

body.doc-drawer-locked { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .doc-hero-glow, .doc-map::before { animation: none; }
  .doc-phase { opacity: 1; transform: none; transition: none; }
}

/* --- /documentacao em celular (2026-08-16) -- regra de mobile no FIM do
   arquivo, senao perde por cascata (mesma armadilha ja documentada aqui
   varias vezes: regra no meio do arquivo simplesmente nao aplica). */
@media (max-width: 720px) {
  .doc-hero { padding: 1.8rem 1.3rem; }
  .doc-hero h1 { font-size: 1.45rem; }
  .doc-phase { padding-left: 3.1rem; }
  .doc-map::before { left: 20px; }
  .doc-phase-node { width: 42px; height: 42px; font-size: 0.95rem; }
  .doc-phase-head { padding-top: 0.3rem; }
  .doc-stage-grid { grid-template-columns: 1fr; }
  .doc-drawer { width: 100vw; }
}

/* --- Rodape legal, no FIM da pagina (2026-08-16, refeito em 2026-08-18) -----
   Links de privacidade/termos/instrucoes em toda tela (menos a landing, que
   nem estende base.html).

   ERA `position: fixed` grudado na tela. Pedido do usuario (2026-08-18):
   "deixar essa lindo sempre ao final da pagina e nao fixa em tela". Barra
   fixa custava uma faixa da altura da janela em TODA tela pra um link que
   quase nunca e' clicado, e obrigava a reservar espaco por baixo -- dai vinha
   o `padding-bottom: 5.25rem` do `.content` (e 7.1rem no celular), que
   empurrava o conteudo real pra cima a pagina inteira.

   Agora e' um rodape normal, no fluxo: aparece depois do conteudo, quando a
   pessoa chega no fim da pagina. Sem `position`, sem `z-index` e sem reserva
   de espaco -- por isso o `.content` voltou ao padding normal (ver `.content`
   la' em cima) e a compensacao de celular ficou so' com a barra de navegacao.

   Fica FORA de `.layout`, entao ocupa a largura toda (por baixo do menu
   lateral tambem) -- que e' o comportamento classico de rodape de site. */
.legal-footer-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.55rem;
  padding: 1.35rem 1.5rem;
  background: var(--bg-alt);
  border-top: 1px solid var(--border);
  font-size: 0.76rem;
}

.legal-footer-bar a {
  color: var(--text-muted);
  font-weight: 600;
  text-decoration: none;
  padding: 0.2rem 0.35rem;
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

.legal-footer-bar a:hover {
  color: var(--brand-dark);
  background: var(--brand-soft);
}

.legal-footer-sep { color: var(--text-faint); font-size: 0.7rem; }

@media (max-width: 980px) {
  /* A navegacao inferior do celular e' `position: fixed` e cobriria o rodape
     quando a pessoa chega no fim da pagina -- o respiro vai NO RODAPE (nao no
     .content) porque ele e' o ultimo elemento do documento. */
  .legal-footer-bar {
    padding-bottom: calc(1.35rem + 4.5rem + env(safe-area-inset-bottom, 0px));
  }
}

@media (max-width: 480px) {
  .legal-footer-bar {
    gap: 0.35rem;
    padding-left: 0.8rem;
    padding-right: 0.8rem;
    font-size: 0.72rem;
  }
}

/* --- Balao de sugestao do tour em celular (2026-08-16) -- mesma logica de
   sempre: regra de mobile no FIM do arquivo, senao perde por cascata pra
   `.help-suggest-bubble` la' em cima. Mesmo padrao ja usado por
   `.help-dropdown` (position:fixed colado nas bordas, ver acima) -- em tela
   estreita um balao ancorado no botao (`right:-10px`) estouraria a tela. */
@media (max-width: 620px) {
  .help-suggest-bubble {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    top: 7.25rem;
    width: auto;
  }

  .help-suggest-bubble::before {
    right: 28px;
  }
}

/* ===========================================================================
   PADRAO DE TELA DE CADASTRO (2026-08-18)

   Pedido do usuario: "repaginacao completa no layout, organizando tudo
   profissionalmente em cadastros ... melhores os titulos e o agrupamento de
   inputs". Antes cada tela de cadastro montava o proprio cabecalho e os
   proprios "titulos de secao" na mao, quase sempre com `style=` inline
   (`font-size:1.1rem; font-weight:700; color:var(--text)` repetido em 6+
   lugares so' no product_detail) -- resultado: nenhum cadastro parecia com o
   outro, e um campo novo nunca sabia em que "secao" entrar porque secao
   visual nao existia, era so' um <span> em negrito solto no meio do grid.

   Este bloco define o vocabulario unico dessas telas:
     .form-page-head   -- cabecalho (breadcrumb + titulo + metadados + acoes)
     .form-section     -- cartao de secao (icone + titulo + descricao + corpo)
     .form-grid.cols-12 -- grade de 12 colunas pro agrupamento fino dos inputs
     .form-savebar     -- barra de salvar grudada no rodape

   Tudo montado pelas macros de _macros.html (form_page_head/form_section/
   form_savebar) -- template nenhum deve reescrever essas classes na mao, senao
   volta a divergir. Fica no FIM do arquivo de proposito (regra permanente do
   projeto: regra no meio perde por cascata sem erro nenhum), e as media
   queries deste bloco ficam no fim DELE pelo mesmo motivo.
=========================================================================== */

/* --- Cabecalho da tela ---------------------------------------------------- */
.form-page-head {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 0.9rem 1.25rem;
  margin-bottom: 1rem;
}

/* Encostado na barra de abas quando ela vem logo abaixo (cadastro de produto
   e anuncio) -- os dois viram um bloco visual so', em vez de dois cartoes
   separados por um vao. */
.form-page-head.has-tabs {
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  margin-bottom: 0;
  padding-bottom: 0.85rem;
}

.form-page-breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.76rem;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
}

.form-page-breadcrumb a {
  color: var(--text-muted);
  text-decoration: none;
  font-weight: 600;
}

.form-page-breadcrumb a:hover { color: var(--brand-dark); }
.form-page-breadcrumb-sep { color: var(--text-faint); }

.form-page-head-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
}

.form-page-head-titles { min-width: 0; }

.form-page-head-titles h1,
.form-page-head-titles h2,
.form-page-head-titles h3 {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
}

.form-page-head-meta {
  margin: 0.1rem 0 0;
  font-size: 0.76rem;
  color: var(--text-muted);
}

.form-page-head-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* --- Cartao de secao ------------------------------------------------------ */
.form-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: 1rem;
  /* Mesma entrada dos .panel do sistema -- `backwards` (nunca forwards) pelo
     mesmo motivo ja documentado la' em cima: transform residual criaria
     stacking context e afundaria dropdown/tooltip dos campos de dentro. */
  animation: rise-in var(--dur-slow) var(--ease-out) backwards;
}

.form-section-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.25rem;
  border-bottom: 1px solid var(--border);
}

/* Secao recolhida nao mostra divisor -- senao fica uma linha solta pendurada
   embaixo do cabecalho, sem corpo nenhum depois dela. */
.form-section.is-collapsed > .form-section-head { border-bottom: none; }

.form-section-ico {
  width: 2.1rem;
  height: 2.1rem;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  color: var(--brand-dark);
  display: grid;
  place-items: center;
}

.form-section-ico svg { width: 17px; height: 17px; }

.form-section-titles { min-width: 0; }

.form-section-titles h3,
.form-section-titles h4 {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.form-section-desc {
  margin: 0.1rem 0 0;
  font-size: 0.76rem;
  color: var(--text-muted);
  line-height: 1.45;
}

.form-section-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Contador da secao ("8 itens", "2 tipos - 6 combinacoes") -- da' pra saber o
   que tem dentro sem precisar abrir a secao recolhida. */
.form-section-count {
  font-size: 0.68rem;
  font-weight: 700;
  background: var(--neutral-soft);
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  padding: 0.14rem 0.5rem;
  white-space: nowrap;
}

.form-section-body { padding: 1.1rem 1.25rem 1.25rem; }

/* Secao que ENVOLVE uma tabela (convertida de um `.table-card`, que mantem a
   classe via `extra_class` pra nao perder zebra/hover/paddings de celula):
   o corpo perde o padding proprio pra tabela encostar nas bordas do cartao
   como encostava antes. Sem isto a tabela ganha padding DUAS vezes -- o do
   corpo da secao e o de 1.75rem que `.table-card` ja da' na primeira/ultima
   celula -- e a lista fica visivelmente afundada dentro do cartao. */
.form-section.table-card > .form-section-body { padding: 0; }

/* Mesma ideia pro cabecalho: alinhado com a primeira celula da tabela. */
.form-section.table-card > .form-section-head { padding: 0.9rem 1.25rem; }

/* ...mas texto solto no corpo (uma dica antes da tabela) precisa do padding de
   volta, senao encosta na borda esquerda do cartao -- o `padding:0` acima e'
   pra TABELA encostar, nao pro paragrafo. Vale so' pros filhos diretos que
   nao sao a area rolavel da tabela. */
.form-section.table-card > .form-section-body > p,
.form-section.table-card > .form-section-body > .field-hint,
.form-section.table-card > .form-section-body > .form-subhead {
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.form-section.table-card > .form-section-body > p:first-child,
.form-section.table-card > .form-section-body > .field-hint:first-child {
  padding-top: 0.9rem;
}

/* Secao recolhivel: o cabecalho inteiro e' o alvo do clique (area grande,
   nao so' a setinha). */
.form-section.is-collapsible > .form-section-head { cursor: pointer; }
.form-section.is-collapsed > .form-section-body { display: none; }

.form-section-toggle {
  flex: none;
  color: var(--text-muted);
  transition: transform var(--dur-base) var(--ease-out);
}

.form-section.is-collapsed .form-section-toggle { transform: rotate(-90deg); }

/* Divisor interno, pra separar assuntos DENTRO de uma secao sem precisar
   criar um cartao novo (ex. "Endereco" dentro de Dados da empresa). */
.form-subhead {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.35rem 0 0;
}

.form-subhead > span {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

.form-subhead::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* --- Grade de 12 colunas -------------------------------------------------- */
/* Variante ADITIVA: .compact-3col/.compact-4col continuam existindo e
   intocadas. 12 colunas permitem 2/3/4/6 campos por linha e larguras
   desiguais (ex. 8+4) sem inventar uma classe nova por caso. */
.form-grid.cols-12 {
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 0.85rem 1rem;
}

.form-grid.cols-12 > .col-2 { grid-column: span 2; }
.form-grid.cols-12 > .col-3 { grid-column: span 3; }
.form-grid.cols-12 > .col-4 { grid-column: span 4; }
.form-grid.cols-12 > .col-5 { grid-column: span 5; }
.form-grid.cols-12 > .col-6 { grid-column: span 6; }
.form-grid.cols-12 > .col-7 { grid-column: span 7; }
.form-grid.cols-12 > .col-8 { grid-column: span 8; }
.form-grid.cols-12 > .col-9 { grid-column: span 9; }
.form-grid.cols-12 > .col-12 { grid-column: 1 / -1; }

/* COLISAO COM O BOOTSTRAP -- nao remover.
   O Bootstrap 5.3.8 (vendorado e carregado em TODA tela pelo base.html, antes
   deste arquivo) define `.col-2` ... `.col-9` com `flex:0 0 auto; width:N%`.
   Os nomes batem com os desta grade, e as duas regras se SOMAM: o item recebe
   a area certa do grid (`grid-column`) e, dentro dela, encolhe pro percentual
   do Bootstrap. Medido ao vivo: um `.col-4` de 285px renderizava com 95px
   (33,33% de 285) -- campo espremido em toda tela de cadastro, sem erro
   nenhum no console.
   `width:auto` devolve o comportamento normal de item de grid (preencher a
   celula). `max-width:none` entra junto porque versoes anteriores do
   Bootstrap tambem limitavam por max-width -- barato e evita a mesma
   armadilha se o vendor for atualizado. */
.form-grid.cols-12 > [class*="col-"] {
  width: auto;
  max-width: none;
}

/* Mesma tipografia/altura de campo das grades compactas ja existentes -- um
   cadastro nao pode ter input de tamanho diferente do outro. */
.form-grid.cols-12 label {
  gap: 0.3rem;
  font-size: 0.78rem;
}

.form-grid.cols-12 input,
.form-grid.cols-12 select {
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 0.7rem;
  padding-right: 0.7rem;
  font-size: 0.85rem;
}

.form-grid.cols-12 textarea { font-size: 0.88rem; }

/* Rotulo com acao a direita (botao de IA, "ver detalhes") -- antes cada
   ocorrencia repetia `style="justify-content:space-between; width:100%"` no
   proprio template. */
.form-field-label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
}

.form-field-label > .form-field-label-action { margin-left: auto; }

.form-field-required { color: var(--danger); font-weight: 700; }

.form-field-hint {
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--text-muted);
}

/* --- Barra de salvar ------------------------------------------------------ */
/* `sticky` (nao `fixed`): fica visivel enquanto se rola o formulario, mas
   PARA de flutuar quando chega na posicao natural dela, no fim do conteudo --
   por isso nunca cobre o rodape legal (.legal-footer-bar), que vem depois,
   ja' fora do `.content`. Com `fixed` ela ficaria pendurada por cima do
   rodape na hora que a pessoa chega no fim da pagina. */
.form-savebar {
  position: sticky;
  bottom: 0.75rem;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 0.7rem 1.25rem;
  margin-top: 1.2rem;
}

.form-savebar-status {
  font-size: 0.78rem;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.form-savebar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Bloco de logo (marca/empresa): preview a esquerda, acoes a direita, em vez
   do preview empilhado em cima do botao ocupando a coluna inteira. */
.brand-logo-row {
  display: flex;
  align-items: flex-start;
  gap: 1.1rem;
  flex-wrap: wrap;
}

.brand-logo-preview-img {
  width: 128px;
  height: 128px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  display: block;
}

.brand-logo-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

.brand-logo-actions .field-hint { margin: 0; }

/* --- Paineis do anuncio convertidos pro padrao (2026-08-18) ---------------
   As secoes da tela de anuncio guardaram as classes antigas (.ad-values-panel,
   .ad-commercial-panel, .ad-product-panel...) via `extra_class` da macro
   form_section, pra nao perder os ganchos de CSS/JS que ja' apontavam pra
   elas. Duas dessas regras antigas foram escritas pensando no `.panel`, onde o
   padding ficava no PROPRIO painel; no `.form-section` o padding mora no
   cabecalho e no corpo, entao herda-las aqui indentaria o cartao inteiro (o
   .ad-product-panel tinha 2.3rem lateral, e a regra de celular alcanca as
   tres). Zeradas explicitamente -- as classes continuam servindo de gancho,
   so' nao mandam mais no espacamento. */
.form-section.ad-product-panel,
.form-section.ad-values-panel,
.form-section.ad-commercial-panel {
  padding-left: 0;
  padding-right: 0;
}

/* A margem negativa de -0.55rem existia SO' pra compensar aquele padding de
   2.3rem (alinhar "Caracteristicas do produto" com os demais cartoes). Com o
   padding zerado acima ela passaria a puxar o bloco pra FORA do cartao. */
.form-section .characteristics-panel-inset {
  margin-left: 0;
  margin-right: 0;
  width: auto;
}

/* Planilha de edicao em massa DENTRO de um cartao do padrao (2026-08-18).
   `.sheet-wrap` limita a propria altura com um desconto fixo da viewport
   (`calc(100vh - 250px)`, e 190px na variante `.sheet-page`) -- numeros
   calibrados pra tela SEM cabecalho de pagina e SEM cartao de secao. Com a
   moldura nova (cabecalho + breadcrumb + cabecalho da secao + padding do
   corpo) entram ~150px a mais acima da grade, e a planilha passava a estourar
   a viewport, criando uma segunda barra de rolagem por fora da propria
   planilha. Os valores abaixo recuperam o "tela cheia" dessas duas telas.
   Se a moldura mudar de altura, e' aqui que se ajusta. */
.form-section .sheet-wrap { max-height: calc(100vh - 400px); }
.sheet-page .form-section .sheet-wrap { max-height: calc(100vh - 340px); }

/* --- Botoes de acao SEMPRE a direita (2026-08-18) --------------------------
   Pedido do usuario: "fazer tbm a padronizacao dos botoes sempre a direita em
   todas essas janelas". Ate' aqui `.button-row` era so' `display:flex` sem
   alinhamento, entao a linha de botoes encostava a ESQUERDA -- e cada tela
   resolvia (ou nao) na mao, com `margin-left:auto` avulso. Resultado: em
   alguns popups o "Salvar" ficava na esquerda, em outros na direita.

   O alinhamento a direita e' a convencao de formulario (a acao final fica no
   fim da leitura, junto da borda onde o olho termina) e ja' era o que
   `.form-savebar-actions` e `.form-page-head-actions` faziam -- isto so'
   estende a mesma regra pros dois lugares que faltavam.

   Escopado de proposito: `.button-row` tambem e' usada em barra de
   ferramentas de lista e em blocos de conteudo, onde a esquerda esta' certa.
   So' muda dentro de POPUP e dentro de SECAO de cadastro. */
.modal-box .button-row,
.form-section .button-row,
.form-section-body > .button-row {
  justify-content: flex-end;
}

/* Excecao: linha que tem um texto/aviso ANTES dos botoes (ex. "3 itens
   selecionados" + acoes) usa `space-between` -- o texto fica na esquerda e os
   botoes na direita, que e' o mesmo principio. */
.modal-box .button-row.with-info,
.form-section .button-row.with-info {
  justify-content: space-between;
}

/* --- Responsivo do padrao de cadastro (fim do bloco, ver nota do topo) ---- */
@media (max-width: 900px) {
  .form-grid.cols-12 > .col-2,
  .form-grid.cols-12 > .col-3,
  .form-grid.cols-12 > .col-4 { grid-column: span 6; }

  .form-grid.cols-12 > .col-5,
  .form-grid.cols-12 > .col-7,
  .form-grid.cols-12 > .col-8,
  .form-grid.cols-12 > .col-9 { grid-column: 1 / -1; }
}

@media (max-width: 620px) {
  .form-page-head,
  .form-section-head { padding-left: 1rem; padding-right: 1rem; }

  .form-section-body { padding: 0.95rem 1rem 1.1rem; }

  .form-page-head-actions,
  .form-savebar-actions { margin-left: 0; width: 100%; }

  .form-page-head-actions > *,
  .form-savebar-actions > * { flex: 1; justify-content: center; }

  /* Em tela estreita todo campo ocupa a linha inteira -- meia largura de 320px
     nao cabe rotulo nenhum sem quebrar em 3 linhas. */
  .form-grid.cols-12 > [class*="col-"] { grid-column: 1 / -1; }

  .form-section-desc { display: none; }
}

/* Mesma correcao de altura da planilha na faixa estreita (a regra de 980px
   la' em cima usa `calc(100vh - 200px)`, tambem sem contar a moldura nova).
   Depois do bloco de 620px de proposito: media query so' vence media query se
   vier depois, mesma armadilha de cascata ja documentada no projeto. */
@media (max-width: 980px) {
  .form-section .sheet-wrap { max-height: calc(100vh - 330px); }
}

/* ===========================================================================
   VENDAS NO MOLDE DO CADASTRO + NOTA FISCAL (2026-08-18)

   Pedido do usuario: "em vendas ... fazer a correta adequacao e a padronizacao
   visual no mesmo molde q eu pedi para os cadastros".

   O detalhe da venda tinha um vocabulario proprio (`.order-card` +
   `.order-card-title`, um rotulo minusculo em CAIXA ALTA sem chapa de icone e
   sem divisor) enquanto TODA tela de cadastro ja falava o vocabulario de
   `.form-section`. Em vez de reescrever o desenho aqui de novo -- que e'
   exatamente como as duas coisas divergem -- o `odCard()` do vendas.html
   passou a EMITIR a estrutura do `.form-section`, e este bloco so' ajusta a
   escala: o painel abre DENTRO de uma linha da tabela, entao respira um pouco
   menos que uma tela cheia de cadastro.

   Fica no fim do arquivo pela regra permanente do projeto (regra no meio perde
   por cascata sem erro nenhum) e depois do proprio bloco do padrao de
   cadastro, que e' quem estas regras afinam.
=========================================================================== */

/* A grade `.order-cards` ja separa os cartoes com `gap` -- a margem de baixo
   que todo `.form-section` tem somaria a ela e deixaria a coluna torta. */
.order-cards > .form-section { margin-bottom: 0; }

/* Escala reduzida: cabecalho e corpo mais justos que na tela de cadastro. */
.order-card > .form-section-head { padding: 0.7rem 0.95rem; }
.order-card > .form-section-body { padding: 0.8rem 0.95rem 0.95rem; }
.order-card .form-section-ico { width: 1.75rem; height: 1.75rem; }
.order-card .form-section-ico svg { width: 14px; height: 14px; }
.order-card .form-section-titles h3 { font-size: 0.85rem; }

/* A primeira/ultima linha do cartao nao precisa do respiro proprio: o corpo
   da secao ja da' o espaco (antes o padding vinha do cartao e a linha
   encostava nele de proposito). */
.order-card .form-section-body > .order-linha:first-child { padding-top: 0; }

/* O hero (numero da venda + valor) e' o "cabecalho de pagina" deste painel --
   mesmo raio e mesma sombra do `.form-page-head`, pra ele e os cartoes
   abaixo parecerem do mesmo sistema. */
.order-hero {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

/* --- Nota fiscal ---------------------------------------------------------- */
/* Bloco de situacao dentro do popup: mesmas linhas rotulo/valor do detalhe da
   venda, so' que emolduradas -- e' leitura, nao campo, e sem a moldura ficava
   colado nos inputs logo abaixo como se fosse parte do formulario. */
.nfe-situacao {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-solid);
  padding: 0.35rem 0.85rem;
}

.nfe-situacao .order-linha:first-child { padding-top: 0.35rem; }
.nfe-situacao .order-linha:last-child { padding-bottom: 0.35rem; }
.nfe-situacao .field-hint { line-height: 1.45; }

/* Campo de arquivo dentro da grade de 12 colunas. `.form-grid.cols-12 input`
   zera padding vertical (input de texto ganha a altura pelo `height` do tema),
   so' que campo de arquivo NAO tem altura fixa -- sem isto o "Escolher
   arquivo" fica espremido contra a borda. Especificidade maior que a regra
   generica de propósito. */
.form-grid.cols-12 input[type="file"] {
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  height: auto;
}

/* ===========================================================================
   PADRAO DE TELA DE LISTAGEM (2026-08-18)

   Pedido do usuario: "repaginacao visual completa em todas as paginas de
   listagem ... modelo premium e moderno ... os botoes devem ser agrupados a
   direita". Mesmo espirito do PADRAO DE TELA DE CADASTRO logo acima: um
   vocabulario unico, montado pela macro `list_page_head` de _macros.html --
   template nenhum reescreve essas classes na mao.

     .list-page-head  -- cartao de cabecalho da lista (chapa de icone +
                         titulo + contagem + descricao); a toolbar da tela
                         entra DENTRO dele como segunda linha (via {% call %})
     .products-toolbar / .toolbar-search / .toolbar-actions-right -- as
                         classes historicas das toolbars continuam as mesmas
                         (JS e tour guiado dependem delas); aqui elas so'
                         ganham o acabamento novo
     .table-card / .pagination-bar -- refinadas pro mesmo acabamento

   Fica no FIM do arquivo de proposito (regra permanente do projeto: regra no
   meio perde por cascata sem erro nenhum) e as media queries deste bloco
   ficam no fim DELE pelo mesmo motivo.
=========================================================================== */

/* --- Cartao de cabecalho da lista ----------------------------------------- */
.list-page-head {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
  /* `backwards` (nunca forwards) -- transform residual criaria stacking
     context e afundaria os dropdowns da toolbar de dentro (mesma nota dos
     .panel/.form-section). */
  animation: rise-in var(--dur-slow) var(--ease-out) backwards;
}

.list-page-head-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  min-width: 0;
}

.list-page-ico {
  width: 2.4rem;
  height: 2.4rem;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  color: var(--brand-dark);
  display: grid;
  place-items: center;
}

.list-page-ico svg { width: 19px; height: 19px; }

.list-page-titles { min-width: 0; }

.list-page-titles h1,
.list-page-titles h2,
.list-page-titles h3 {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
}

.list-page-count {
  font-size: 0.68rem;
  font-weight: 700;
  background: var(--neutral-soft);
  color: var(--text-muted);
  border-radius: 999px;
  padding: 0.16rem 0.6rem;
  white-space: nowrap;
}

.list-page-desc {
  margin: 0.15rem 0 0;
  font-size: 0.78rem;
  color: var(--text-muted);
  line-height: 1.45;
  max-width: 86ch;
}

/* Toolbar como segunda linha do cartao: divisor fino entre o titulo e a
   linha de busca/acoes, e a margem propria da toolbar zera porque quem
   respira agora e' o cartao. */
.list-page-head > .products-toolbar {
  margin: 0.85rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
}

/* --- Toolbar (acabamento premium, mesma estrutura de sempre) --------------- */
/* Acoes SEMPRE agrupadas a direita (pedido do usuario). O space-between da
   .products-toolbar ja fazia isso quando a busca existia; em tela SEM busca o
   unico filho ia parar na ESQUERDA -- o margin-left:auto garante o canto
   direito em qualquer composicao. */
.toolbar-actions-right { margin-left: auto; }

/* Busca em pilula: campo e lupa com canto cheio, fundo levemente rebaixado
   que acende ao focar -- todo por token, entao o tema escuro acompanha. */
.toolbar-search input[type="text"] {
  border-radius: 999px;
  padding-left: 1.05rem;
  padding-right: 1.05rem;
  background: var(--bg-alt);
}

.toolbar-search input[type="text"]:focus {
  background: var(--surface);
}

.toolbar-search .icon-btn,
.toolbar-search button[type="submit"] { border-radius: 999px; }

/* Hierarquia premium dos botoes de lista: UM botao de cor (a acao que a tela
   existe pra oferecer, .toolbar-primary) e o resto "quieto" -- superficie
   clara com borda, mesma receita que a .bulk-bar ja usa nos dela. O cinza
   solido em todos os botoes deixava a linha de acoes pesada e sem
   hierarquia nenhuma. Escopado na toolbar/cabecalho de lista de proposito:
   o .secondary-dark de popup e formulario continua como era. */
.products-toolbar .secondary-dark,
.list-page-head .secondary-dark {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

.products-toolbar .secondary-dark:hover,
.list-page-head .secondary-dark:hover {
  background: var(--bg-alt);
  border-color: var(--border-strong);
  color: var(--text);
}

/* A acao principal ganha um respiro de sombra pra "saltar" da linha. */
.products-toolbar .toolbar-primary,
.list-page-head .toolbar-primary {
  box-shadow: var(--shadow-sm);
}

/* Campo curto com rotulo na propria linha da toolbar (ex. "De"/"Ate" das
   faturas) -- antes era `style="display:flex; ..."` inline no template. */
.toolbar-inline-field {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.toolbar-inline-field input { width: auto; }

/* --- Cartao de tabela ------------------------------------------------------ */
/* Mesmo raio grande dos demais cartoes do sistema (cabecalho de lista,
   secao de cadastro) -- o raio menor "tecnico" destoava do resto. */
.table-card { border-radius: var(--radius-lg); }

/* Cabecalho de coluna mais leve: rotulo pequeno em caixa alta ja marca a
   linha; a borda dupla + fundo forte viravam peso desnecessario. */
.table-card thead th {
  font-size: 0.7rem;
  letter-spacing: 0.07em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-strong);
}

/* --- Paginacao ------------------------------------------------------------- */
/* Numeros em pilula "fantasma": so' a pagina atual tem cor cheia; as demais
   acendem no hover. Menos moldura, mesma area de clique. */
.page-btn {
  min-width: 2.2rem;
  justify-content: center;
  border-radius: 999px;
  border-color: transparent;
  background: transparent;
}

.page-btn:hover { background: var(--brand-soft); }

.page-btn.current {
  background: var(--brand);
  border-color: var(--brand);
}

.page-btn.ellipsis { min-width: 0; }

/* --- Responsivo do padrao de listagem (fim do bloco, ver nota do topo) ----- */
@media (max-width: 620px) {
  .list-page-head { padding: 0.85rem 1rem; }

  .list-page-desc { display: none; }

  /* Busca vira linha inteira; as acoes continuam agrupadas a direita na
     linha de baixo (mesma regra do pedido, tela estreita nao muda isso). */
  .toolbar-search { width: 100%; }

  .toolbar-search input[type="text"] {
    flex: 1;
    width: auto;
    max-width: none;
  }

  .toolbar-actions-right {
    width: 100%;
    margin-left: 0;
    justify-content: flex-end;
  }
}


/* ==========================================================================
   VERIFICACAO DE PROPRIEDADE DO SITE NO ADSENSE (Painel Admin > Publicidade)
   2026-08-20 -- a tela repete a escolha que o painel do Google oferece
   (snippet do AdSense / snippet do ads.txt / metatag) como cartoes de radio,
   mais o bloco que mostra o codigo que o site esta' publicando agora.
   Bloco no FIM do arquivo de proposito (regra do projeto: regra no meio
   perde por cascata sem erro nenhum).
   ========================================================================== */

.verify-method-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.6rem;
  margin-top: 0.35rem;
}

.verify-method {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 10px);
  background: var(--bg-alt);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}

.verify-method:hover { border-color: var(--brand); }

/* :has() cobre o cartao inteiro pintado quando o radio dentro dele esta'
   marcado -- sem isso so' a bolinha mudaria e o cartao escolhido ficaria
   visualmente igual aos outros. */
.verify-method:has(input:checked) {
  /* `--brand` (azul do sistema), NAO `--primary`: esse token nem existe no
     styles.css -- var() sem fallback pra variavel inexistente e' declaracao
     invalida, some em silencio (pego medindo o computed style no navegador).
     O anel interno + o fundo em `--surface` (contra o `--bg-alt` dos nao
     escolhidos) e' o que faz a escolha se ler de longe, nos dois temas. */
  border-color: var(--brand);
  box-shadow: inset 0 0 0 1px var(--brand);
  background: var(--surface);
}

.verify-method input[type="radio"] {
  margin: 0.15rem 0 0 0;
  flex: 0 0 auto;
  width: auto;
}

.verify-method-text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.verify-method-text strong { font-size: 0.9rem; font-weight: 600; }
.verify-method-text small { font-size: 0.78rem; color: var(--text-muted); line-height: 1.35; }

.verify-published-code {
  margin: 0.35rem 0 0.4rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 10px);
  background: var(--bg-alt);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  /* Codigo longo (o snippet do AdSense passa de 130 caracteres) rola dentro
     do proprio bloco -- sem isso a secao inteira estouraria a largura da
     tela no celular. */
  overflow-x: auto;
  white-space: pre;
}
