/* ============================================================
   tryzen — componentes
   ============================================================ */

/* ---------- topbar ---------- */
.topbar {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  min-height: 34px;
  padding: 0 var(--pad);
  margin-bottom: var(--gap-lg);
}
.topbar__back {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: -6px;
  padding: 6px;
  min-height: 44px;          /* area de toque confortavel no celular */
  color: var(--text);
  font-size: var(--fs-body);
}
.topbar__back svg { width: 20px; height: 20px; }
.topbar__spacer { flex: 1; }
.topbar__right {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;      /* deixa o que estiver dentro poder encolher */
  color: var(--text-3);
}
.topbar__action { color: var(--accent-texto); font-weight: 600; }

/* ---------- link dentro de uma frase ----------
   O app quase nao tem link de texto: quase tudo clicavel e botao, linha
   ou cartao, e por isso `a { text-decoration: none }` vale globalmente
   em css/base.css. Onde o clicavel mora DENTRO de um paragrafo (os
   termos embaixo do cadastro, a politica na faixa de cookie), sublinhado
   e a unica marca que sobra: a cor sozinha nao serve, porque quem nao
   distingue cor fica sem saber onde tocar.

   `text-underline-offset` porque o sublinhado colado corta a perna do g
   e do p, e este texto e todo minusculo. */
.link-texto {
  color: var(--text-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.link-texto:active { opacity: .6; }
/* O link que mora SOZINHO ("Agora nao", "Tem um codigo?") ganha 48 px
   de toque por uma faixa invisivel, sem mexer no desenho nem no layout.
   O link no meio de uma frase fica como esta. */
:is(button, a).link-texto:not(p *) { position: relative; }
:is(button, a).link-texto:not(p *)::before {
  content: '';
  position: absolute;
  left: -4px; right: -4px;
  top: 50%;
  height: 48px;
  translate: 0 -50%;
}

/* acao textual pequena: mantem o visual, garante 44px de toque */
.tap {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
/* mesma ideia, mas sem empurrar o layout ao redor */
.tap--inline { padding: 6px 0; margin: -6px 0; }
/* qualquer acao no topo tem no minimo 44px de altura tocavel */
.topbar__right > *,
.topbar__action {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin: -8px;
  color: var(--text);
  position: relative;
}
.icon-btn svg { width: 24px; height: 24px; }
/* Um botao de icone tem 40px e ponto. Na topbar ele divide a linha com
   texto que pode ser longo, e sem isto o flex encolhe o QUADRADO em vez
   do texto — o alvo de toque desaparece antes da primeira reticencia. */
.topbar .icon-btn { flex: none; }
.icon-btn--dot::after {
  content: '';
  position: absolute;
  top: 7px; right: 7px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--bg);
}

/* ---------- botoes ---------- */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 58px;
  padding: 0 22px;
  border-radius: var(--r);
  font-size: var(--fs-lg);
  font-weight: 600;
  letter-spacing: -.01em;
  transition: transform .12s var(--ease), opacity .12s var(--ease);
}
.btn:active { transform: scale(.985); opacity: .9; }

.btn--primary   { background: var(--accent); color: var(--on-accent); }
.btn--secondary { background: var(--surface); color: var(--text); }
.btn--outline   { border: 1px solid var(--border); color: var(--text); }
.btn--ghost     { color: var(--text); min-height: 48px; }
.btn[disabled]  { opacity: .38; pointer-events: none; }

/* ---------- o botao especular ----------
   O SpecularButton do React Bits, so no detalhe (js/especular.js): a
   linha do contorno acende perto do cursor e um reflexo leve passa por
   dentro. O botao continua sendo o do app. Vai so nos botoes que fecham
   alguma coisa: Assinar, Gerar o Pix, Entrar, Cadastrar, Gerar link.

   `isolation` cria a pilha propria: o `::after` com z-index -1 fica
   ACIMA do fundo verde e ABAIXO da letra, que e onde reflexo mora. */
.btn--specular {
  --mx: 50%;
  --my: 50%;
  --brilho: 0;
  --especular-linha: rgba(255, 255, 255, .95);
  --especular-reflexo: rgba(255, 255, 255, .30);
  position: relative;
  isolation: isolate;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .20);
}
.btn--outline.btn--specular,
.btn--ghost.btn--specular {
  --especular-linha: var(--accent);
  --especular-reflexo: var(--accent-tint);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.btn--specular::before,
.btn--specular::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  transition: opacity .35s var(--ease);
}
/* a linha de luz: um anel de 1px, recortado pela mascara, com o brilho
   centrado no cursor */
.btn--specular::before {
  padding: 1px;
  background: radial-gradient(140px circle at var(--mx) var(--my), var(--especular-linha), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: var(--brilho);
}
/* o reflexo por dentro, mais fraco que a linha */
.btn--specular::after {
  z-index: -1;
  background: radial-gradient(120px circle at var(--mx) var(--my), var(--especular-reflexo), transparent 65%);
  opacity: calc(var(--brilho) * .8);
}
@media (hover: none) {
  .btn--specular:active::after { opacity: .9; }
}

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 20px;
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 600;
  border: 1px solid transparent;
  white-space: nowrap;
}
/* Dois botoes no pe de um cartao. Sem isto o flex espreme o QUE PODE
   ceder — o icone, que vira um risco de 3px, porque a letra e `nowrap`
   e nao encolhe.

   A base de cada um e o proprio conteudo (`1 1 auto`, e nao `flex:1`):
   eles crescem pra dividir a linha, mas nunca ficam menores do que a
   palavra que carregam. E quando a palavra nao cabe mais — 320px de
   tela — a linha quebra e cada um passa a ocupar a largura inteira, em
   vez de vazar por fora do cartao. */
.par {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-sm);
  width: 100%;
}
.par > .pill { flex: 1 1 auto; padding: 0 12px; }
/* A acao que ganha a linha inteira. E o terceiro botao do pe do
   cartao de hoje ("Registrar na mao"): sem a base de 100% ele
   dividiria a primeira linha com os outros dois e os tres ficariam
   com tres letras cada num celular estreito. */
.par > .pill--linha { flex-basis: 100%; }
.pill svg { flex: none; }

.pill--solid   { background: var(--accent); color: var(--on-accent); }
.pill--outline { border-color: var(--accent-texto); color: var(--accent-texto); }
.pill--muted   { border-color: var(--border); color: var(--text-2); }
.pill--lg      { min-height: 52px; font-size: var(--fs-body); flex: 1; }
.pill:active   { opacity: .82; }

/* ---------- o toque nos verdes (28/09/2026) ----------
   Ate aqui segurar um botao verde so baixava a opacidade: no escuro
   isso e quase nada, porque um verde a 82%% em cima de preto continua
   sendo um verde. Agora o verde APERTADO tem cor propria — o Positive
   Deep do dono —, e a letra sobe pro verde vivo pra nao sumir no meio
   do toque (5,0:1 no escuro, 4,6:1 no claro).

   O contorno enche em vez de afundar: ele nao tem corpo pra escurecer,
   entao o toque e o corpo aparecendo. */
.btn--primary:active,
.pill--solid:active {
  background: var(--accent-preso);
  color: var(--accent);
  opacity: 1;
}
.pill--outline:active { background: var(--certo-preso); opacity: 1; }

/* As mesmas duas familias que so existem quando alguem precisa agir. O
   fundo apertado e claro nos dois casos, entao a letra desce: --bg no
   amarelo (4,5:1) e --text no vermelho (6,4:1). */
.chip--acao[aria-pressed="true"]:active {
  background: var(--acao-preso);
  color: var(--bg);
}

/* ---------- campo com underline ---------- */
/* e um <label>: sem display:block o padding vertical nao entra no fluxo
   e os campos se sobrepoem, fazendo o rotulo encostar na linha de cima. */
.field {
  display: block;
  padding: 18px 0 15px;
  border-bottom: 1px solid var(--border);
}
.field__label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  margin-bottom: 10px;
}
.field__input {
  font-size: var(--fs-h3);
  line-height: 1.3;
  color: var(--text);
  padding: 2px 0;
}
/* O traco fica CINZA tambem no foco, so mais fechado. Ele era verde
   (--accent-texto), e um campo aceso de verde no meio de um formulario
   e cor gasta com uma informacao que o cursor piscando dentro do campo
   ja deu. Quem navega por teclado nao perde nada: o anel de foco e o
   `:focus-visible` do base.css, que continua verde e por cima.

   E o valor esta escrito a mao em vez de usar `--text-3` porque o
   --text-3 (#5E6167) tambem puxa pro azul, 9 pontos no canal B — ele e
   medido pra CONTRASTE de letra, nao pra ser cinza. Aqui e o mesmo
   cinza do traco solto, so mais fechado, pra que o campo ativo mude de
   peso sem mudar de cor. */
.field:focus-within { border-bottom-color: rgba(60, 60, 60, .72); }

/* campo de hora. O <input type=time> desenha o proprio relogio, e ele
   vem com a fonte e a cor do sistema: sem estas linhas o campo aparece
   menor que os outros e com o iconezinho azul do Chrome no meio de uma
   tela verde. A `color-scheme` da raiz (tokens.css) ja cuida do tema do
   seletor que abre. */
.campo-hora {
  font-family: var(--font-mono);
  font-size: var(--fs-h1);
  letter-spacing: var(--tr-mono);
  background: none;
  border: 0;
  width: 100%;
}
.campo-hora::-webkit-calendar-picker-indicator { filter: grayscale(1); opacity: .5; cursor: pointer; }
.campo-hora::-webkit-calendar-picker-indicator:hover { opacity: .85; }

/* ---------- campo de numero livre (quiz) ---------- */
/* A unidade fica dentro da linha do campo, nao no rotulo: quem digita
   "40" precisa ver "km / semana" ao lado do proprio numero pra saber o
   que acabou de responder. No rotulo, acima, ela ja saiu do campo de
   visao no momento em que o teclado sobe. */
.numero__linha {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.numero__input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-h1);
  letter-spacing: var(--tr-mono);
}
.numero__unidade {
  flex: none;
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}
/* ---------- o pedido e menor que a resposta ----------
   Dentro da caixa vazia fica uma INSTRUCAO ("Digite sua altura"), nunca
   um valor de exemplo — um "175" cinza e indistinguivel de um 175 ja
   digitado. Mas a caixa e dimensionada pro NUMERO: `--fs-h1` em mono,
   feito pra um "21,1" ocupar a linha. Uma frase nesse tamanho passa da
   largura do campo, encosta na unidade do lado direito e é cortada no
   meio da palavra.

   Entao o placeholder desce pro tamanho de texto corrido e sai do mono:
   ele deixa de competir com o numero e passa a parecer o que e, um
   pedido. E o mesmo par de vozes do resto do app — o dado em mono
   grande, a instrucao em texto pequeno.

   As duas regras estao separadas de proposito: um seletor que o
   navegador nao conhece invalida a declaracao inteira, e juntar os
   prefixos faria o Safari e o Firefox perderem a regra do Chrome. */
.field__input::placeholder,
.numero__input::placeholder {
  font-family: var(--font);
  font-size: var(--fs-body);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--text-3);
  /* O Firefox entrega o placeholder com 54% de opacidade por padrao, e
     em cima do --text-3 isso vira um cinza que some no fundo. */
  opacity: 1;
}

/* CTA desligado enquanto o numero nao serve. Fica visivel de proposito
   — some-lo faria a tela parecer quebrada; apagado com o motivo escrito
   logo acima diz o que falta. */
.btn.is-off {
  opacity: 0.4;
  pointer-events: none;
}

.or {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--text-3);
}
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* ---------- card de opcao (quiz) ---------- */
.opt {
  display: block;
  width: 100%;
  text-align: left;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: transparent;
  transition: border-color .16s var(--ease), background .16s var(--ease);
}
.opt + .opt { margin-top: 12px; }
.opt__kicker {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  margin-bottom: 6px;
}
.opt__text { font-size: var(--fs-body); line-height: 1.4; color: var(--text); }
.opt__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--text-3);
  margin-top: 4px;
}
.opt[aria-selected="true"] { border-color: var(--accent-texto); background: var(--accent-tint); }
.opt[aria-selected="true"] .opt__kicker { color: var(--accent-texto); }
.opt--warn[aria-selected="true"] { border-color: var(--warn); background: var(--warn-tint); }
.opt--warn[aria-selected="true"] .opt__title { color: var(--warn); }
.opt__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.opt__title { font-size: var(--fs-body); font-weight: 500; }
.opt__check { color: var(--warn); flex: none; }
/* O visto nasceu na pergunta de saude, onde marcar uma opcao e um
   alerta e o amarelo faz sentido. Fora dela (Editar Plano) marcar e
   so escolher, e um visto amarelo leria como aviso. */
.opt:not(.opt--warn)[aria-selected="true"] .opt__check { color: var(--accent-texto); }
.opt__check svg { width: 20px; height: 20px; }

/* ---------- linha de lista ---------- */
.list { border-top: 1px solid var(--border); }
.list--flush { border-top: 0; }

.row {
  display: flex;
  align-items: center;
  gap: var(--gap);
  width: 100%;
  text-align: left;
  min-height: 66px;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
  color: inherit;
}
.row__main  { flex: 1; min-width: 0; }
.row__title { font-size: var(--fs-body); line-height: 1.3; }
.row__sub {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--text-3);
  margin-top: 3px;
}
.row__value { font-size: var(--fs-body); color: var(--text-2); white-space: nowrap; }
/* etiqueta ao lado do nome (+5% pace, 4 em comum): nunca quebra no meio */
.row__tag { white-space: nowrap; font-size: 12px; }
.row__chev  { color: var(--text-3); flex: none; }
.row__chev svg { width: 18px; height: 18px; }
.row:active { opacity: .6; }

/* linha de lista com simbolo a esquerda: o icone nao ganha caixa nem
   fundo — ele e so mais um sinal cinza, senao a lista vira um mosaico */
.row--com-icone { gap: 15px; }
.row__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  color: var(--text-3);
}
.row__icon svg { width: 23px; height: 23px; }

/* ---------- linha de lista com PESSOA a esquerda ----------
   ⚠️ Avatar NAO e icone, e nao entra no `.row__icon`.

   O `.row__icon` e uma caixa fixa de 26px feita pra um traco cinza. O
   avatar tem 46px e `flex: none`: posto la dentro ele transborda 10px
   pra cada lado, encosta na margem da lista de um lado e no texto do
   outro, e a linha inteira sai torta. Foi o que aconteceu na lista de
   membros da equipe.

   Aqui o avatar e o proprio slot: ele entra como filho direto da linha
   e o `.row__link` so segura ele junto do texto, pra que tocar no nome
   ou na foto abra o perfil, enquanto o botao da direita continua sendo
   um alvo separado. */
.row__link {
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex: 1;
  min-width: 0;
  color: inherit;
}

/* ---------- estado vazio ----------
   Desenho, frase e (as vezes) uma saida, centralizados. O maior ganho
   aqui e o VAO: a ilustracao fica sozinha no meio da tela, com ar dos
   dois lados, em vez de um paragrafo cinza encostado na margem.      */
.vazio {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--gap-md) 0 var(--gap-lg);
}
.vazio p { max-width: 32ch; }
.vazio__acao { width: 100%; max-width: 300px; }

/* As ilustracoes vivem numa moldura de 160x96; o max-width segura elas
   num tamanho confortavel no celular e impede que estiquem no desktop. */
.arte {
  width: 100%;
  max-width: 208px;
  height: auto;
  color: var(--text-3);
}

.group-label {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  padding-bottom: 13px;
  border-bottom: 1px solid var(--border);
}

/* ---------- chips ---------- */
.chips { display: flex; gap: var(--gap-sm); flex-wrap: wrap; }
.chips--scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 calc(var(--pad) * -1);
  padding: 0 var(--pad);
}
.chips--scroll::-webkit-scrollbar { display: none; }
/* numa fila que rola, os chips mantem a largura do texto (nao encolhem) */
.chips--scroll > * { flex: none; }

/* ---------- o chip de escolher ----------
   Pedido do dono (19/09/2026), olhando o painel: "voce colocou um outline
   em elementos verdes, em vez de deixar so verde o objeto selecionado".
   O escolhido era verde CLARO com um ARO verde em volta, e o aro lia como
   um segundo elemento por cima do primeiro. Agora ha UMA pintura por
   estado, e nenhuma borda em nenhum dos dois:

     solto      o cinza de superficie, letra de apoio
     escolhido  o VERDE CHEIO do botao principal, com a letra dele (a
                escolha do dono entre "verde cheio" e "verde clarinho")

   Era o que o `.chip--solid` ja fazia na escolha Corrida/Caminhada, e
   virou a regra de todo chip. O `--solid` continua existindo so pra nao
   quebrar quem ainda escreve a classe.

   O desenho vem do JellyRadio (reactbits.dev/micro/jelly-radio): chip
   cheio sem traco, a escolha em cor chapada e a letra em 500. Quem da o
   movimento e o js/gelatina.js, pra toda fila marcada com `.gel`. */
.chip {
  display: grid;
  place-items: center;
  min-width: 46px;
  min-height: 46px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-2);
  font-size: var(--fs-body);
  font-weight: 500;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color .2s var(--ease),
    color .2s var(--ease),
    scale .16s cubic-bezier(.23, 1, .32, 1);
}
.chip[aria-pressed="true"],
.chip[aria-checked="true"],
.chip.is-active {
  background: var(--accent);
  color: var(--on-accent);
}
/* o toque: 3% pra dentro, como o `.btn:active` do app. Vai no `scale`
   e nao no `transform`, que e da gelatina: os dois se somam. */
.chip:active { scale: .97; }
.chip--pill  { border-radius: var(--r-pill); min-height: 44px; }
.chip--solid[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
/* a contagem miuda ao lado do nome (sub-abas do painel, galhos no
   celular): mono, e herda a cor do chip, escolhido ou nao */
.chip__nota {
  margin-left: 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  letter-spacing: var(--tr-mono);
  opacity: .72;
}

/* ---------- a gelatina ----------
   Ate 20/09/2026 a fila reservava uma folga dos lados pro chip inchado e
   pros vizinhos empurrados, e era essa folga que a tirava da linha do
   texto. Agora a escolhida so fica 5% maior, ninguem e empurrado, e os
   chips das pontas crescem pra dentro (js/gelatina.js): a fila comeca
   onde o titulo comeca. */
.gel {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.gel > * { transform-origin: 50% 50%; touch-action: manipulation; }
@media (prefers-reduced-motion: reduce) {
  .chip:active { scale: 1; }
}
.chip--sq { padding: 0; width: 46px; }

/* fila de 7 dias: divide a largura por igual pra nunca quebrar linha */
.chips--days { display: flex; gap: 8px; }
.chips--days .chip {
  flex: 1;
  min-width: 0;
  width: auto;
  padding: 0;
  aspect-ratio: 1;
}

/* ---------- escala: uma fila de opcoes que divide a largura ----------
   Serve pras tres perguntas da avaliacao pos-corrida (esforco 1-10,
   dificuldade 1-5, corpo em tres palavras) e pra qualquer outra fila
   onde as opcoes sao irmas e nenhuma pode ser mais larga que a outra.
   `flex: 1` + `min-width: 0` e o que impede a fila de quebrar linha
   num aparelho de 320px — sem o min-width o conteudo do chip vira o
   piso da largura e a ultima opcao cai pra baixo. */
.escala { display: flex; gap: 7px; }
.escala .chip {
  flex: 1;
  min-width: 0;
  padding: 0 4px;
  font-size: var(--fs-sm);
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- dez opcoes nao cabem numa fileira ----------
   A regua de esforco vai de 1 a 10, e dez chips lado a lado dao 22px
   de largura num aparelho de 320px — e 33px ate num de 430px. Alvo de
   toque tem piso de 44px, e aqui ele importa mais que em qualquer
   outro lugar do app: errar o chip corrompe justamente o dado que a
   tela inteira existe pra coletar.

   Duas fileiras de cinco resolvem em todo tamanho de tela (50px de
   largura ja no 320px) e ainda leem melhor — 1 a 5 em cima, 6 a 10
   embaixo. `flex-basis: 20%` menos a folga das quatro brechas e o que
   fixa cinco por linha; sem isso o `flex: 1` esticaria pra dez. */
.escala--dupla { flex-wrap: wrap; }
.escala--dupla .chip { flex: 1 1 calc(20% - 6px); }

/* ---------- os porques ----------
   A lista de motivos que sustentam uma recomendacao. Marcador em traco,
   nao em bolinha: sao razoes, nao itens de checklist — e bolinha puxa
   o olho pro marcador em vez de pro texto. */
.porques { list-style: none; padding: 0; margin: 0; }
.porques li { position: relative; padding-left: 18px; }
.porques li + li { margin-top: 6px; }
.porques li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .72em;
  width: 10px;
  height: 1px;
  background: var(--text-3);
}

/* A opcao que pede atencao — "dolorido" na pergunta do corpo. Amarelo,
   nao vermelho: o vermelho deste app e so pra acao destrutiva, e dizer
   que algo doeu nao e um estrago, e uma coisa que pede olhar. */
.chip--acao[aria-pressed="true"] {
  background: var(--acao-fundo);
  color: var(--acao-texto);
}

/* ============================================================
   O CARTAO — a peca que separa
   ------------------------------------------------------------
   ANATOMIA (a mesma em toda tela; se uma tela ganhar valores
   proprios, as telas se afastam e a grade nunca assenta):

     ┌─ .card — corpo na cor do ESTADO (--*-fundo) ─────────┐
     │  .card__head  titulo e selos, SEM fundo proprio      │
     │  ┌─ .bandeja — recuo em --bg, com halo de 4px ────┐  │
     │  │   .pastilha  linha de informacao               │  │
     │  └────────────────────────────────────────────────┘  │
     │  .card__foot  acoes                                  │
     └──────────────────────────────────────────────────────┘

   REGRAS
   1. UMA cor por cartao. Todas as pastilhas vestem o tom do corpo.
      Quem separa uma da outra e a BANDEJA por tras, nao mais cor.
   2. Nada de letra direto sobre a cor viva. Toda letra mora no
      cabecalho claro, na bandeja ou num botao.
   3. Sem sombra. O que separa o cartao da pagina e a diferenca de
      TOM. Sombra so no que flutua de verdade (modal, hover).
   ============================================================ */
.card {
  display: block;
  padding: 8px;
  border-radius: var(--r-card);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
}
.card + .card { margin-top: var(--gap); }

/* ---------- o texto miudo dentro de um corpo de cor (28/09/2026) ----------
   No escuro a superficie de estado ganhou corpo: o verde e o vivo a
   16,5% no preto quente, o amarelo e o vermelho sao cheios
   (css/tokens.css). O --text-3 — o cinza do rotulo, da data, do "km" —
   fecha 4,5:1 em cima dos cinzas do tema, mas so 4,2:1 em cima do
   verde: ele reprovaria em TODA legenda dentro de um cartao de estado.
   Falta pouco, e "falta pouco" tambem reprova.

   A correcao mora aqui e nao no token, porque o --text-3 global esta
   certo: o que muda e a superficie embaixo dele. Dentro de um corpo de
   cor ele sobe pro --text-2, que passa nos tres (6,6:1 no verde, 5,1:1
   no amarelo, 7,6:1 no vermelho). Perde-se um degrau de hierarquia
   nesses blocos; o degrau que sobra (--text contra --text-2) e o que
   separa o dado do rotulo, e ele continua inteiro.

   ⚠️ Estado novo com corpo solido entra nesta lista. */
:is(.card--certo, .card--acao, .card--risco,
    .bento__i--certo, .bento__i--acao, .bento__i--risco,
    .pbento__i--certo, .pbento__i--acao, .pbento__i--risco,
    .porque__decisao--certo, .porque__decisao--alerta) { --text-3: var(--text-2); }
/* A bandeja e um recuo em --bg DENTRO do cartao colorido: ali embaixo
   nao ha cor nenhuma, e o cinza volta a ser o cinza. Sem esta linha o
   degrau de hierarquia se perderia tambem nas pastilhas, que sao a
   maior parte do texto miudo do app. */
:is(.card--certo, .card--acao, .card--risco) .bandeja { --text-3: var(--text-3-base); }

/* o corpo veste o ESTADO. Uma classe por leitura, e so estas. */
.card--certo { background: var(--certo-fundo); }
.card--acao  { background: var(--acao-fundo); }
.card--feito { background: var(--feito-fundo); }
.card--risco { background: var(--risco-fundo); }
/* incompleto nao tem corpo: so o traco de onde a coisa vai ficar */
.card--vazio {
  background: var(--vazio-fundo);
  box-shadow: inset 0 0 0 1px var(--vazio);
}
.card--vazio .bandeja { background: var(--surface); }
/* Chip dentro da bandeja cinza: com o mesmo --surface dela, o botao
   sumia e so sobrava a palavra solta (Hoje, "Como voce se identifica?",
   20/09/2026). Fora da escolha ele usa o fundo da pagina. */
.bandeja .chip:not([aria-pressed="true"], [aria-checked="true"], .is-active) { background: var(--bg); }

.card__head {
  display: flex;
  align-items: baseline;
  gap: var(--gap-sm);
  padding: 10px 12px 12px;
}
.card__head > .grow { flex: 1; }
.card__kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-2);
}
.card__title { font-size: var(--fs-lg); font-weight: 600; line-height: 1.2; }
.card__foot {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  padding: 12px 12px 6px;
}

/* a bandeja: o recuo que separa as informacoes umas das outras.
   Vai em --bg (o fundo da pagina), nunca em branco puro no claro —
   com o cartao colorido, o branco puro virava um TERCEIRO tom. */
.bandeja {
  background: var(--bg);
  border-radius: var(--r-lg);
  padding: 4px;              /* o halo de 4px em volta das pastilhas */
}
.pastilha {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 44px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  line-height: 1.35;
}
.pastilha + .pastilha { box-shadow: 0 -1px 0 var(--border-soft); }
.pastilha__ic { flex: none; color: var(--text-3); display: flex; }
.pastilha__ic svg { width: 19px; height: 19px; }
.pastilha__label { color: var(--text-2); }
.pastilha__valor { margin-left: auto; font-weight: 500; white-space: nowrap; }
/* pastilha de recado: o valor e uma frase, entao quebra e alinha a
   esquerda. Sem isso o texto do coach vazava pra fora do cartao. */
.pastilha--texto { align-items: flex-start; }
.pastilha--texto .pastilha__valor {
  margin-left: 0;
  white-space: normal;
  font-weight: 400;
  color: var(--text-2);
  min-width: 0;
}
.pastilha--texto .pastilha__ic { margin-top: 1px; }

/* ============================================================
   O bento
   ------------------------------------------------------------
   Blocos de tamanhos diferentes numa grade so. O cartao mostra UMA
   coisa por vez; o bento mostra o panorama — os numeros que so dizem
   alguma coisa lado a lado.

   DUAS COLUNAS, e nao tres. O original e de tres porque nasceu numa
   pagina de largura de monitor; aqui a tela tem 430px no maximo, e a
   terceira coluna daria 110px por bloco: um numero de 30px com o rotulo
   quebrando embaixo. O `--largo` (a linha inteira) e quem faz o ritmo:
   sem ele a grade vira tabela de duas colunas.

   O bloco veste o mesmo ESTADO do cartao, e pelo mesmo motivo: dois
   vocabularios de cor na mesma tela obrigariam a decorar duas legendas.

   ANATOMIA (de cima pra baixo, e o de baixo encosta no pe):
     icone · rotulo mono · [o vao] · numero · nota · corpo · ir
   A nota e legenda do numero, entao vem colada nele; o corpo e o que
   sobra (o recado do coach, o relato de quem correu, um selo) e fica
   por ultimo, separado por um respiro.
   O vao e um `margin-top:auto` no numero: o rotulo fica no topo, e o
   numero desce ate encostar no que vem embaixo dele. Dois blocos
   vizinhos com o mesmo tanto de texto embaixo alinham os NUMEROS, que e
   o que se compara; um bloco com "ir" ao lado de um sem carrega uma
   linha a mais e o numero dele sobe. E o preco de o pe ser o pe.
   ============================================================ */
/* A UNIDADE de linha. E o `auto-rows-[22rem]` do original, na escala
   daqui: 58px e a altura de um dia de descanso (rotulo e uma palavra),
   e e a conta de que uma corrida cabe em duas unidades e uma corrida
   com recado do coach em tres. Quem distribui os blocos por essas
   unidades e o `empacotar()` do js/ui.js, que escreve o `grid-area` de
   cada um.

   `minmax(58px, auto)` e nao 58px cravado: o original corta o que passa
   (`overflow-hidden`) porque o texto dos cartoes dele e escrito a mao.
   Aqui o texto vem do banco e de um modelo, e um relato de quatro
   linhas cortado no meio e pior que uma fileira um pouco mais alta. */
.bento {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: minmax(58px, auto);
  gap: var(--gap-sm);
}
.bento__i {
  position: relative;
  display: flex;
  flex-direction: column;
  /* `min-content` e nao 0, e a razao e sutil: o `overflow: hidden` la
     embaixo zera a contribuicao minima do bloco pro calculo da fileira,
     e ai o `auto` do `grid-auto-rows` nunca cresce — a fileira fica nas
     58px da unidade e o `hidden` CORTA o que passar. Num celular de
     320px, onde "Corrida forte" quebra em duas linhas, isso comia o
     pace e o detalhe. Com `min-content` o bloco volta a dizer de quanto
     ele precisa, a fileira cresce, e o corte fica so pro que e
     realmente demais (o relato, que tem `line-clamp`). */
  min-height: min-content;
  padding: 13px 14px 12px;
  border-radius: var(--r-card);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
}
/* a linha inteira. E o que quebra o ritmo de tabela */
.bento__i--largo { grid-column: 1 / -1; }

/* o corpo veste o ESTADO — as mesmas cinco leituras do cartao */
.bento__i--certo { background: var(--certo-fundo); }
.bento__i--acao  { background: var(--acao-fundo); }
.bento__i--feito { background: var(--feito-fundo); }
.bento__i--risco { background: var(--risco-fundo); }
.bento__i--vazio {
  background: var(--vazio-fundo);
  box-shadow: inset 0 0 0 1px var(--vazio);
}
/* INCOMPLETO nao tem corpo, e o texto dele nao tem voz: um "Descanso"
   em preto e negrito gritava tanto quanto o longao de 18 km ao lado. */
.bento__i--vazio .bento__valor { color: var(--text-3); font-weight: 500; }

/* O icone e o rotulo na MESMA linha. Em linhas separadas, o bloco que
   tem icone empurrava o rotulo pra baixo e a data dele desalinhava da
   data do bloco vizinho — numa semana, duas datas em alturas
   diferentes lado a lado leem como erro. */
.bento__topo { display: flex; align-items: center; gap: 7px; min-height: 18px; }
.bento__ic { flex: none; color: var(--text-3); display: flex; }
.bento__ic svg { width: 17px; height: 17px; }
.bento__kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-2);
  min-width: 0;
}
/* ---------- o tamanho do bloco e o tamanho da letra ----------
   Num mosaico, bloco grande com letra de bloco pequeno nao le como
   hierarquia, le como bloco com sobra. Entao a letra acompanha as
   unidades que o bloco ocupa. A altura em si nao mora mais aqui: ela e
   o `grid-area` que o empacotador escreve.

   `--alto` sao tres unidades ou mais (o dia com recado do coach, o
   treino com relato gravado); `--destaque` e o hoje, que a tela pede
   por nome; `--raso` e uma unidade so, onde nao cabe letra grande. */
.bento__i--alto.bento__i--palavra .bento__valor,
.bento__i--destaque.bento__i--palavra .bento__valor { font-size: var(--fs-h3); }
.bento__i--destaque .bento__valor { font-size: var(--fs-h3); }
.bento__i--raso.bento__i--palavra .bento__valor { font-size: var(--fs-body); }
.bento__i--raso { padding: 10px 12px; }

/* pouco conteudo: o que tem fica no meio do bloco, nao no pe */
.bento__i--meio { justify-content: center; }
.bento__i--meio .bento__valor { margin-top: 10px; padding-top: 0; }
.bento__i--meio .bento__topo { flex: none; }
/* Pouco conteudo NA FILEIRA INTEIRA vira uma linha so, e baixa. Isso
   acontece quando um dia de descanso e promovido a largo pra fechar a
   fileira (ver `fecharFileiras` em ui.js): em pe, ele virava 140px de
   caixa vazia com uma palavra dentro — o maior bloco da semana sendo o
   dia em que nao acontece nada. */
.bento__i--largo.bento__i--meio {
  flex-direction: row;
  /* `justify-content: center` do `--meio` centrava no eixo principal, e
     em linha o eixo principal e o horizontal: a data ia parar no meio
     do bloco, longe da margem onde todas as outras datas comecam. */
  justify-content: flex-start;
  align-items: center;
  gap: 12px;
  min-height: 66px;
}
.bento__i--largo.bento__i--meio .bento__valor { margin-top: 0; }
.bento__valor {
  margin-top: auto;
  padding-top: 10px;
  font-size: var(--fs-stat);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -.02em;
}
.bento__unidade {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-2);
  margin-left: 4px;
  letter-spacing: 0;
}
/* o numero que e uma PALAVRA (o bloco, a rotina): 30px de palavra
   estoura a coluna de 188px, e quebrar no meio de "calibragem" e pior
   que uma letra menor */
.bento__i--palavra .bento__valor {
  font-size: var(--fs-lg);
  line-height: 1.2;
  letter-spacing: -.01em;
}
.bento__nota {
  margin-top: 5px;
  font-size: var(--fs-xs);
  line-height: 1.35;
  color: var(--text-2);
}
.bento__corpo { margin-top: 9px; }
/* Dois selos no mesmo bloco ("concluído" e "doeu") sao dois objetos, nao
   uma frase: sem o respiro eles encostam e leem como uma pastilha so.
   E quando o relato gravado vem logo abaixo deles, ele precisa da mesma
   distancia que o corpo tem do resto — colado, a fala parecia legenda
   do selo. */
.bento__corpo .selo + .selo { margin-left: 6px; }
.bento__corpo .selo + .bento__recado { margin-top: 8px; }

/* ---------- o fundo do bloco ----------
   No original (magicui.design) cada cartao tem um `background` proprio:
   um calendario, um globo, uma fila animada. E dali que vem a cara de
   bento — cada compartimento mostra uma COISA, e nenhum e igual ao
   vizinho. Sem isso a grade e so uma lista arrumada em duas colunas.

   Aqui esse lugar nao recebe enfeite: recebe o DADO daquele bloco. Numa
   corrida com GPS e o desenho do trajeto; numa sem, nao ha fundo.

   Ele sangra ate a borda do bloco (as margens negativas) e o
   `overflow: hidden` do bloco corta o que passar, que e o que faz a
   peca parecer parte do cartao e nao uma figura colada dentro dele. */
.bento__fundo {
  margin: 11px -14px -12px;
  border-radius: 0 0 var(--r-card) var(--r-card);
  overflow: hidden;
  line-height: 0;
}
/* O fio de cima nao e enfeite. O estilo `light-v11` do Mapbox e quase
   branco, e o cartao tambem (`--surface`): sem uma linha separando os
   dois, o trajeto aparece flutuando no nada e o bloco parece ter um
   pedaco em branco embaixo. */
.bento__fundo .mapa {
  border-radius: 0;
  box-shadow: inset 0 1px 0 var(--border-soft);
  background: var(--bg);
}
.bento__fundo .mapa img { opacity: .95; }
.bento__i--vazio .bento__fundo .mapa { background: none; }

/* ---------- a linha de comparacao saiu (27/09/2026) ----------
   Era a faixa de km no pe do bloco, um degrade da cor do estado ate
   `--ate`. O dono pediu as etiquetas "sem aquela faixa por baixo": a
   distancia ja esta escrita no bloco, e a etiqueta diz o estado. O
   fundo do bloco ficou so pro trajeto do GPS. */
/* O recado do coach e o relato de quem correu dentro de um bloco: e
   FALA, nao dado, e no app inteiro fala escrita por alguem vem em
   italico. Sem isto o "puxou no fim" do Zentry teria o mesmo peso dos
   8 km ali em cima. */
.bento__recado {
  font-size: var(--fs-sm);
  font-style: italic;
  line-height: 1.35;
  color: var(--text-2);
  /* ---------- sem corte ----------
     Havia um `line-clamp: 3` aqui, e ele cortava com "…" metade das
     frases do motor ("...o longo caberem na…"). Num bloco de bento nao
     ha "ver mais": o que foi cortado nao tem como ser lido em lugar
     nenhum, e uma explicacao pela metade e pior que explicacao nenhuma
     — ela parece um defeito.

     Quem cuida do tamanho agora e o `alturaDe()` do js/ui.js, que conta
     o texto e pede as unidades necessarias ANTES de desenhar. E se a
     conta dele errar pra menos, o `min-height: min-content` do
     `.bento__i` faz a fileira crescer: o texto aparece inteiro pelos
     dois caminhos. */
}
/* o "ir" e visivel desde sempre, e nao so no hover como no original:
   num celular nao existe hover, e um destino que so aparece pra quem
   tem mouse e um destino que ninguem daqui encontra */
.bento__cta {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}
.bento__cta svg { width: 13px; height: 13px; }
a.bento__i:active { opacity: .72; }
@media (hover: hover) {
  a.bento__i .bento__cta { transition: color .2s var(--ease); }
  a.bento__i:hover .bento__cta { color: var(--text); }
}
@media (prefers-reduced-motion: reduce) {
  a.bento__i .bento__cta { transition: none; }
}

/* ---------- o bloco que e link E tem botao dentro ----------
   Um `<button>` dentro de um `<a>` e marcacao invalida, e o toque no
   botao vira navegacao. Entao o bloco com acao deixa de SER o link: uma
   camada cobre ele inteiro e leva o toque pra tela do treino, e so a
   acao mora acima dela.

   O resto do topo (o icone, a data) fica DEBAIXO da camada de
   proposito: subir a linha inteira faria tocar na data nao abrir mais o
   dia, que e o contrario do que o cartao promete. */
.bento__cobre {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}
/* O retorno do toque era do `a.bento__i`, e agora o <a> nao e mais a
   caixa: sem isto o cartao inteiro deixaria de apagar no dedo. */
.bento__i:has(> .bento__cobre:active) { opacity: .72; }

.bento__acao {
  position: relative;
  z-index: 2;
  margin-left: auto;
  display: flex;
}
.bento__editar {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  /* A area de toque cresce pra fora sem empurrar a data do lado nem
     aumentar a altura do topo. */
  margin: -6px -6px -6px 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.bento__editar svg { width: 15px; height: 15px; }
/* O lapis continua com 30 px de desenho; o toque tem 48 (Fitts). A
   faixa invisivel cresce pra fora sem empurrar a data do lado. */
.bento__editar { position: relative; }
.bento__editar::before { content: ''; position: absolute; inset: -9px; border-radius: 999px; }
.bento__editar:active { color: var(--text); scale: .9; }
@media (prefers-reduced-motion: reduce) {
  .bento__editar:active { scale: 1; }
}

/* ---------- o vao entre a data e o titulo (dono, 21/09/2026) ----------
   `.bento__valor` nasce com `margin-top: auto`, que joga o miolo pro pe
   do bloco. Num painel de numeros isso e o certo: rotulo pequeno em
   cima, numero grande embaixo, e o vao no meio e o que da peso ao
   numero.

   Na semana do Plano nao e. A fileira estica todo bloco na altura do
   mais alto, entao o que aparecia entre "TER 23" e "Corrida forte" era
   um vao de quarenta pixels de nada — e as duas linhas se leem juntas.
   Aqui o miolo sobe e a sobra fica no pe.

   Vale SO na semana (`.semana-dias`), e nao no bento inteiro: o Hoje,
   as Provas e os paineis continuam com o numero no pe, que e onde ele
   deve ficar. E o `--meio` fica de fora porque ele ja resolve o mesmo
   problema do outro jeito, centrando o pouco que tem. */
.semana-dias .bento__i:not(.bento__i--meio) .bento__valor {
  margin-top: 0;
  padding-top: 6px;
}

/* selo: o que significa um ESTADO nao veste a cor do cartao (regra 2
   do doc) — ele tem a propria, senao "feito" e "atrasado" ficam iguais. */
.selo {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}
.selo--certo { background: var(--certo-fundo); color: var(--certo-texto); }
.selo--acao  { background: var(--acao-fundo);  color: var(--acao-texto); }
/* FEITO tem o fundo da propria superficie, entao dentro de um cartao ou
   de um bloco de bento que ja veste "feito" o selo ficaria invisivel: a
   pastilha teria exatamente a cor do que esta atras dela. O fio resolve
   sem inventar uma cor — e o mesmo contorno que o estado ja usa. */
.selo--feito {
  background: var(--feito-fundo);
  color: var(--feito-texto);
  box-shadow: inset 0 0 0 1px var(--feito-fio);
}
.selo--risco { background: var(--risco-fundo); color: var(--risco-texto); }

/* ---------- stats ---------- */
.stats { display: flex; gap: var(--gap-lg); }
.stats--grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-md) var(--gap); }
.stats--spread { justify-content: space-between; gap: var(--gap); }
/* fila de PRs: 4 lado a lado, mas vira 2x2 em telas estreitas */
.stats--prs { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-md) var(--gap-sm); }
@media (max-width: 379px) {
  .stats--prs { grid-template-columns: repeat(2, 1fr); }
}

.stat__label {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  margin-bottom: 4px;
}
.stat__value {
  font-size: var(--fs-stat);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -.02em;
  white-space: nowrap;
}
.stat__value--lg { font-size: var(--fs-stat-lg); }
.stat__unit { font-size: var(--fs-body); font-weight: 400; color: var(--text-3); margin-left: 3px; }
.stat__note {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--text-3);
  margin-top: 5px;
}

.bignum { display: flex; align-items: flex-end; gap: 10px; }
.bignum__n {
  font-size: clamp(96px, 34vw, 140px);
  font-weight: 600;
  line-height: .8;
  letter-spacing: -.05em;
  color: var(--accent-texto);
}
.bignum__side { padding-bottom: 10px; }

/* ---------- progresso ---------- */
.progress {
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--surface);
  overflow: hidden;
}
.progress__fill { height: 100%; background: var(--accent); border-radius: inherit; }

.progress-seg { display: flex; gap: 8px; }
.progress-seg span { flex: 1; height: 2px; background: var(--border); border-radius: 2px; }
.progress-seg span.is-on { background: var(--accent); }

.split-bar { display: flex; height: 8px; border-radius: var(--r-pill); overflow: hidden; }
.split-bar__a { background: var(--accent); }
.split-bar__b { background: var(--warn); }

/* ---------- segmented / tabs ---------- */
.segmented {
  display: flex;
  padding: 5px;
  background: var(--surface);
  border-radius: var(--r-pill);
}
.segmented button {
  flex: 1;
  min-height: 42px;
  border-radius: var(--r-pill);
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--text-2);
}
.segmented button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); font-weight: 600; }

.tabs {
  display: flex;
  gap: 28px;
  border-bottom: 1px solid var(--border);
  margin: 0 calc(var(--pad) * -1);
  padding: 0 var(--pad);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs button {
  position: relative;
  padding: 0 0 15px;
  font-size: var(--fs-h3);
  font-weight: 500;
  color: var(--text-3);
  white-space: nowrap;
}
.tabs button[aria-selected="true"] { color: var(--text); font-weight: 600; }
.tabs button[aria-selected="true"]::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--accent);
}

/* ---------- avatar ---------- */
.avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.avatar--me { background: var(--accent); color: var(--on-accent); }
.avatar--sm { width: 36px; height: 36px; font-size: var(--fs-xs); }
.avatar--lg { width: 74px; height: 74px; font-size: 26px; }
.avatar--xl { width: 88px; height: 88px; font-size: 30px; }

/* ---------- anel de score ---------- */
.ring { position: relative; flex: none; display: grid; place-items: center; }
.ring svg { transform: rotate(-90deg); }
.ring__track { stroke: var(--border); }
.ring__bar   { stroke: var(--accent); stroke-linecap: round; }
.ring__inner { position: absolute; display: grid; place-items: center; line-height: 1; }
.ring__n { font-size: 26px; font-weight: 600; color: var(--accent-texto); letter-spacing: -.02em; }
.ring__cap {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .08em;
  color: var(--text-3);
  margin-top: 3px;
}

/* ---------- grafico de barras da semana ---------- */
.weekbars { display: flex; align-items: flex-end; gap: 10px; height: 132px; }
.weekbars__col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  height: 100%;
  justify-content: flex-end;
}
/* A semana em cinco leituras, duas cores:
     hoje       verde CHEIO      — e o agora, e onde o olho para
     planejado  verde DILUIDO    — mesmo verde, menos voz
     feito      cinza cheio      — aconteceu, tem corpo, nao pede nada
     falta      contorno da acao — foi combinado e nao aconteceu
     vazio      cinza sem corpo  — traco: nao existe treino nesse dia
   Sem aro em volta do dia de hoje: a forca do verde ja diz qual e, e o
   aro so acrescentava um segundo contorno brigando com o raio da barra.

   A falta e CONTORNO e nao barra cheia (20/09/2026). Ela e o unico dia
   da fileira que nao tem corpo nenhum pra mostrar: nao foi feito e nao
   vai ser. Pintar ela cheia de amarelo faria o dia que ficou pra tras
   ser a coisa mais forte da semana, e a semana nao e sobre ele. */
.weekbars__bar { width: 100%; border-radius: 5px; background: var(--feito); }
.weekbars__bar--done    { background: var(--feito); }
.weekbars__bar--planned { background: var(--certo-fraco); }
.weekbars__bar--today   { background: var(--certo); }
.weekbars__bar--falta   { border: 1px dashed var(--acao); background: var(--acao-fundo); }
.weekbars__bar--empty   { border: 1px dashed var(--vazio); background: none; }
.weekbars__day { font-family: var(--font-mono); font-size: var(--fs-mono-sm); color: var(--text-3); }
.weekbars__col.is-today .weekbars__day { color: var(--certo-texto); font-weight: 600; }
/* O numero de km embaixo da barra. Existe porque barra sozinha diz
   PROPORCAO e nao quantidade: da pra ver que domingo e o maior dia da
   semana e nao da pra saber se sao 8 km ou 18. Menor que o dia da
   semana de proposito — quem procura a forma ve a forma, quem procura o
   numero acha o numero, e nenhum dos dois grita. */
.weekbars__km {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
  line-height: 1;
  margin-top: -6px;
}
.weekbars__col.is-today .weekbars__km { color: var(--certo-texto); }

/* ---------- citacao / card ---------- */
.quote {
  border-left: 2px solid var(--accent);
  padding-left: 18px;
  font-style: italic;
  color: var(--text-2);
  line-height: 1.5;
}
.quote--muted { border-left-color: var(--border); }
/* trecho em destaque dentro da citacao volta ao normal (igual ao mockup) */
.quote b { font-style: normal; color: var(--text); }

/* ---------- splits: cartao visual, nunca planilha ----------
   Era uma tabela de 4 colunas (n · alvo · real · delta) com o MESMO
   alvo repetido em toda linha. O alvo agora e dito UMA vez no topo e
   cada km vira uma barra que sai do centro: pra esquerda foi mais
   rapido, pra direita mais lento. O olho le o desenho; o numero fica
   so pro delta, que e o unico dado que a barra nao mede com precisao.
   -------------------------------------------------------------- */
.splits-v { display: flex; flex-direction: column; }
.splits-v__linha {
  display: grid;
  grid-template-columns: 34px 1fr 46px;
  align-items: center;
  gap: 10px;
  min-height: 34px;
}
.splits-v__km {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  color: var(--text-3);
}
/* a trilha tem um fio no meio: e o alvo. A barra nasce dele. */
.splits-v__trilha {
  position: relative;
  height: 12px;
  border-radius: 3px;
  background: var(--border-soft);
}
.splits-v__trilha::before {
  content: '';
  position: absolute;
  left: 50%;
  top: -2px;
  bottom: -2px;
  width: 1px;
  background: var(--border);
}
.splits-v__barra {
  position: absolute;
  top: 2px;
  bottom: 2px;
  border-radius: 2px;
  background: var(--certo);   /* dentro do combinado */
}
.splits-v__barra--lento { background: var(--acao); }
.splits-v__delta {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  text-align: right;
  color: var(--text-3);
}
.splits-v__delta--rapido { color: var(--certo-texto); }
.splits-v__delta--lento  { color: var(--acao-texto); }

/* ---------- chat ----------
   Cada fala mora numa CAIXA que se encosta num lado: o Zentry na
   esquerda, voce na direita. O lado ja diz de quem e antes de ler
   qualquer coisa, e a caixa fecha o limite de uma fala — que era o que
   faltava quando os turnos eram paragrafos soltos: numa conversa longa,
   onde a resposta acabava e a proxima pergunta comecava so se descobria
   voltando pro rotulo mono la em cima.

   A caixa nunca chega na largura toda (86%): a beirada que sobra do
   outro lado e o que faz o lado ser lido como lado, e nao como margem.  */
.chat__turn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.chat__turn--voce { align-items: flex-end; }
.chat__turn + .chat__turn { margin-top: var(--gap); }
.chat__who {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  margin-bottom: 6px;
  padding: 0 4px;
}
.chat__text {
  max-width: 86%;
  padding: 12px 16px;
  border-radius: var(--r-lg);
  background: var(--surface);
  font-size: var(--fs-body);
  line-height: 1.5;
}
/* ---------- os topicos do Zentry ----------
   Desde que ele responde por partes, a caixa dele tem mais de um
   bloco: paragrafo, lista, paragrafo. O espaco entre eles e o que
   separa a abertura dos itens; sem ele a resposta vira um paragrafo so
   com marcadores dentro, que e exatamente o que a lista veio resolver.

   O ponto e desenhado aqui, e nao no texto: o modelo escreve "-" num
   dia e "·" no outro, e na tela os dois tem que virar a mesma coisa.
   Verde do `--accent`, que e a cor de quem esta ativo no app: a lista
   do coach nao e um documento, e alguem apontando o que fazer. */
.chat__text > * + * { margin-top: 10px; }
.chat__itens { display: grid; gap: 6px; }
.chat__itens li { position: relative; padding-left: 15px; }
.chat__itens li::before {
  content: '';
  position: absolute;
  left: 3px;
  /* meia linha de altura menos meio ponto: centro da PRIMEIRA linha do
     item, nao do item inteiro. Item de duas linhas com o ponto no meio
     pareceria um tracinho perdido entre elas. */
  top: calc(.75em - 2px);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

/* O canto de baixo do lado de quem falou fica mais fechado: e o que
   ancora a caixa naquela margem em vez de deixa-la boiando. */
.chat__turn--coach .chat__text { border-bottom-left-radius: var(--r-sm); }
.chat__turn--voce  .chat__text {
  background: var(--accent-tint);
  border-bottom-right-radius: var(--r-sm);
}
.chat__text + .chat__text { margin-top: 6px; }

/* O coach pensando. Pulso lento e de baixa amplitude: a tela fica
   parada alguns segundos esperando a OpenAI, e uma animacao mais viva
   ai vira ansiedade. Quem pediu menos movimento nao ve pulso nenhum,
   so o texto apagado. */
.chat__pensando { color: var(--text-3); animation: chat-pulso 1.4s ease-in-out infinite; }
@keyframes chat-pulso { 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .chat__pensando { animation: none; } }

/* Falha do coach: e recado sobre o app, nao fala dele. Fica em risco
   pra nao ser lida como conselho de treino. */
.chat__erro { font-size: var(--fs-body); line-height: 1.5; color: var(--risco-texto); }

/* a Intelligence que executa (03/11/2026): a pergunta em botoes e o cartao do antes e depois */
/* contorno so no que agrupa (o cartao); o que se aperta tem fundo; cor so no traco do que confirma */
.chat__perguntas, .chat__proposta { margin-top: 12px; display: grid; gap: 12px; width: 100%; max-width: 380px; box-sizing: border-box; }
.chat__proposta { padding: 16px; border: 1px solid var(--border-soft, var(--border)); border-radius: 18px; background: var(--surface); }
.chat__perguntas-titulo { font-size: var(--fs-body); font-weight: 600; color: var(--text); }
.chat__escolhas { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.chat__escolha {
  display: grid; justify-items: center; gap: 8px; padding: 14px 6px 12px; border-radius: 14px;
  background: var(--preenche, var(--surface-2)); color: var(--text); font-size: var(--fs-small, 14px); font-weight: 500;
  cursor: pointer; transition: background .15s, transform .12s;
}
.chat__escolha:active { transform: scale(.97); }
.chat__escolha[aria-pressed="true"] { background: var(--accent-tint); color: var(--accent-texto); }
.chat__escolha[disabled]:not([aria-pressed="true"]) { opacity: .45; }
.chat__escolha-desenho { display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 50%;
  background: var(--bg); color: var(--accent-texto); }
.chat__proposta-topo { display: flex; align-items: center; gap: 10px; }
.chat__proposta-topo .chat__escolha-desenho { width: 32px; height: 32px; background: var(--preenche, var(--surface-2)); }

.chat__media { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border-radius: 14px; background: var(--preenche, var(--surface-2)); }
.chat__media-nome { font-size: var(--fs-small, 14px); color: var(--text-2); }
.chat__media-km { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-body); white-space: nowrap; }
.chat__media-km s { color: var(--text-3); text-decoration-thickness: 1px; }
.chat__media-km svg { width: 16px; height: 16px; color: var(--text-3); }
.chat__media-km b { font-weight: 600; color: var(--text); }

.chat__dias { list-style: none; margin: 0; padding: 0; display: grid; }
.chat__dia { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 10px 0; }
.chat__dia + .chat__dia { border-top: 1px solid var(--border-soft, var(--border)); }
.chat__dia-data { display: grid; justify-items: center; line-height: 1.1; padding: 6px 0; border-radius: 10px;
  background: var(--preenche, var(--surface-2)); font-size: 11px; color: var(--text-2); text-transform: capitalize; }
.chat__dia-data b { font-size: 16px; font-weight: 600; color: var(--text); }
.chat__dia-nome { display: grid; gap: 2px; font-size: var(--fs-small, 14px); color: var(--text); min-width: 0; }
.chat__dia-tom { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; color: var(--text-2); }
.chat__dia-tom svg { width: 14px; height: 14px; }
.chat__dia-km { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-small, 14px); white-space: nowrap; }
.chat__dia-km s { color: var(--text-3); text-decoration-thickness: 1px; }
.chat__dia-km svg { width: 14px; height: 14px; color: var(--text-3); }
.chat__dia-km b { font-weight: 600; color: var(--text); }

.chat__proposta-nota { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-2); }
.chat__proposta-nota svg { width: 16px; height: 16px; flex: none; }
.chat__acoes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.chat__acoes .btn { min-height: 46px; padding-inline: 12px; font-size: var(--fs-body); gap: 6px; white-space: nowrap; }
.chat__acoes .btn svg { width: 18px; height: 18px; }
.chat__acoes .btn--secondary { background: var(--preenche, var(--surface-2)); }

/* ---------- a fala do Zentry fora do chat ----------
   O rotulo mono em cima e o texto embaixo sao os mesmos do chat de
   proposito: e a mesma pessoa falando. A CAIXA e que nao vem junto —
   caixa e coisa de conversa, onde ha dois lados se revezando. No topo
   do plano nao ha revezamento nenhum: e uma voz so, comentando o que
   esta logo abaixo, e uma caixa ali separaria a leitura da semana
   justamente da semana que ela le. */
.zentry__quem {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  margin-bottom: 6px;
}
.zentry__texto { font-size: var(--fs-body); line-height: 1.5; }
/* No topo do plano ele e um paragrafo so, e esta regra nao faz nada.
   Na estreia (a primeira fala dele) o texto vem em partes, pelo mesmo
   `fala()` do chat: abertura, topicos, fecho. O espaco entre os blocos
   e o mesmo do `.chat__text`, senao a mesma resposta teria um respiro
   na conversa e outro aqui. */
.zentry__texto > * + * { margin-top: 10px; }

.chatbar {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  margin: 0 var(--pad);
  padding: 8px 8px 8px 20px;
  background: var(--surface);
  border-radius: var(--r-pill);
}
.chatbar input { font-size: var(--fs-body); }
.chatbar__enviar {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
}
.chatbar__enviar svg { width: 22px; height: 22px; }
/* O chat fica com o desenho de sempre (pedido do dono); so o toque do
   enviar cresce pra 48 px, por uma borda invisivel. */
.chatbar__enviar { position: relative; }
.chatbar__enviar::before { content: ''; position: absolute; inset: -1px; border-radius: 50%; }

/* ============================================================
   O BRILHO DA BORDA
   ------------------------------------------------------------
   O BorderGlow do reactbits.dev. Nao e de nenhuma tela: e uma
   classe que qualquer peca pode vestir, e quem acende e o
   js/brilho.js. Hoje quem veste sao duas, as duas no chat:

   · o campo de escrever, enquanto a conversa nao comecou. A luz
     da uma volta na abertura e a classe sai quando a conversa
     comeca (js/screens/chat.js).
   · cada fala que a pessoa manda, no instante em que ela nasce
     na tela. Uma volta so, e a classe sai no fim dela.

   Quem veste precisa dizer duas coisas — `--brilho-fundo` (a cor
   do fundo da propria peca) e `--brilho-raio` (a forma dela).
   Sao os dois lugares onde o desenho nao tem como se virar
   sozinho; ver os blocos no fim.

   ---------- como funciona ----------
   Sao tres camadas empilhadas, todas recortadas pelo MESMO cone,
   que aponta pra `--brilho-angulo`. Mover esse angulo e passar a
   luz pela borda; `--brilho-perto` e o quanto ela acende. As duas
   variaveis vem do js/brilho.js, e mais nada vem de la.

   · ::before  o fio de 1px na borda, pintado por um emaranhado de
               gradientes. O `padding-box` com `--brilho-fundo` por
               cima e o que deixa so o fio aparecendo.
   · ::after   o mesmo emaranhado por DENTRO, em soft-light e bem
               de leve, so perto da borda. E o que faz a luz
               parecer atravessar a peca em vez de contorna-la.
   · .brilho__halo  o halo de fora, um empilhado de sombras.

   ---------- o que mudou do original ----------
   · Ele e um CARTAO que embrulha um conteudo, com fundo, borda e
     raio proprios. Aqui nao ha embrulho: as tres camadas entram
     direto na peca, que ja tem fundo e forma. Um wrapper so
     traria um segundo fundo por cima do primeiro.
   · O raio e o da peca, e nao os 24px do exemplo: o brilho
     contorna o que ele decora. Um retangulo arredondado em volta
     de uma pilula nao seria um brilho, seria um erro de
     alinhamento.
   · As cores sao as do app. O exemplo vem roxo, rosa e azul sobre
     um fundo quase preto; o tryzen tem uma cor so, e ela e verde
     (a mesma lei do traco da rota no mapa, em js/config.js).   */
.brilho {
  --brilho-perto: 0;               /* 0 a 100: o quanto acende */
  --brilho-angulo: 45deg;          /* de que lado a luz esta */

  /* As duas que a peca tem que dizer. Os padroes sao os do
     `.surface` generico, pra que uma peca que esqueca de dizer
     ainda saia com uma cara plausivel em vez de um borrao. */
  --brilho-fundo: var(--surface);
  --brilho-raio: var(--r);

  /* Os numeros do exemplo. O `limiar` e o piso: abaixo dele nao
     acende nada, e e por isso que a conta de `opacity` la embaixo
     subtrai antes de dividir. O da COR e 20 acima do da luz, pra
     que o fio colorido chegue depois do halo branco e nao junto. */
  --brilho-limiar: 13;
  --brilho-limiar-cor: calc(var(--brilho-limiar) + 20);
  --brilho-halo: 40px;
  --brilho-cone: 25;
  --brilho-forca: 2.5;
  --brilho-preenche: .5;

  /* A unica medida que NAO veio do exemplo. A escada de sombras dele
     vai ate 50px de desfoque, o que num cartao de ~500px de altura e
     um fio de luz na beirada. As pecas daqui tem 60 e poucos pixels:
     a mesma escada enche a peca inteira de verde e o que passa nao
     parece luz correndo pela borda, parece uma mancha atravessando.
     Encolher a escada devolve a proporcao — a luz volta a ser borda. */
  --brilho-escala: .5;

  /* O verde da marca em HSL, que e o formato que o empilhado de
     sombras pede pra poder variar so a opacidade. */
  --brilho-hsl: 144deg 90% 43%;

  /* Os sete gradientes do emaranhado, nas mesmas posicoes do
     original. Ficam em variavel porque as duas camadas coloridas
     usam os mesmos sete, cada uma na sua caixa. */
  --bg-um:    radial-gradient(at 80% 55%, #0BD25C 0px, transparent 50%);
  --bg-dois:  radial-gradient(at 69% 34%, #34C759 0px, transparent 50%);
  --bg-tres:  radial-gradient(at 8% 6%,   #7BEFA6 0px, transparent 50%);
  --bg-qua:   radial-gradient(at 41% 38%, #0BD25C 0px, transparent 50%);
  --bg-cin:   radial-gradient(at 86% 85%, #34C759 0px, transparent 50%);
  --bg-seis:  radial-gradient(at 82% 18%, #7BEFA6 0px, transparent 50%);
  --bg-sete:  radial-gradient(at 51% 4%,  #34C759 0px, transparent 50%);
  --bg-base:  linear-gradient(#0BD25C 0 100%);

  position: relative;
  /* `isolate` prende o `z-index: -1` das camadas aqui dentro: sem
     ele elas iriam parar ATRAS do fundo da tela, e some tudo. */
  isolation: isolate;
}

.brilho::before,
.brilho::after,
.brilho > .brilho__halo {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: -1;
  pointer-events: none;
  transition: opacity .25s ease-out;
}

/* Parado, o campo e o campo: as tres camadas so existem durante a
   varredura ou com o ponteiro em cima. A saida e mais lenta que a
   entrada de proposito — acender e um aviso, apagar nao precisa
   chamar atencao pra si. */
.brilho:not(:hover):not(.is-varrendo)::before,
.brilho:not(:hover):not(.is-varrendo)::after,
.brilho:not(:hover):not(.is-varrendo) > .brilho__halo {
  opacity: 0;
  transition: opacity .75s ease-in-out;
}

/* ---------- o fio da borda ---------- */
.brilho::before {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--brilho-fundo) 0 100%) padding-box,
    var(--bg-um) border-box,
    var(--bg-dois) border-box,
    var(--bg-tres) border-box,
    var(--bg-qua) border-box,
    var(--bg-cin) border-box,
    var(--bg-seis) border-box,
    var(--bg-sete) border-box,
    var(--bg-base) border-box;

  opacity: calc((var(--brilho-perto) - var(--brilho-limiar-cor)) / (100 - var(--brilho-limiar-cor)));

  mask-image: conic-gradient(
    from var(--brilho-angulo) at center,
    #000 calc(var(--brilho-cone) * 1%),
    transparent calc((var(--brilho-cone) + 15) * 1%),
    transparent calc((100 - var(--brilho-cone) - 15) * 1%),
    #000 calc((100 - var(--brilho-cone)) * 1%)
  );
}

/* ---------- o vazamento pra dentro ---------- */
.brilho::after {
  background:
    var(--bg-um) padding-box,
    var(--bg-dois) padding-box,
    var(--bg-tres) padding-box,
    var(--bg-qua) padding-box,
    var(--bg-cin) padding-box,
    var(--bg-seis) padding-box,
    var(--bg-sete) padding-box,
    var(--bg-base) padding-box;

  /* A primeira mascara e inteira e as outras sao furos: o
     `subtract` tira do meio o que as elipses marcam, sobrando so
     a moldura de dentro. O cone recorta de novo pelo angulo. */
  mask-image:
    linear-gradient(to bottom, #000, #000),
    radial-gradient(ellipse at 50% 50%, #000 40%, transparent 65%),
    radial-gradient(ellipse at 66% 66%, #000 5%, transparent 40%),
    radial-gradient(ellipse at 33% 33%, #000 5%, transparent 40%),
    radial-gradient(ellipse at 66% 33%, #000 5%, transparent 40%),
    radial-gradient(ellipse at 33% 66%, #000 5%, transparent 40%),
    conic-gradient(from var(--brilho-angulo) at center, transparent 5%, #000 15%, #000 85%, transparent 95%);
  mask-composite: subtract, add, add, add, add, add;

  opacity: calc(var(--brilho-preenche) * (var(--brilho-perto) - var(--brilho-limiar-cor)) / (100 - var(--brilho-limiar-cor)));
  mix-blend-mode: soft-light;
}

/* ---------- o halo de fora ----------
   Ele e maior que o campo (`inset` negativo) pra que a sombra
   caiba; quem devolve o desenho pro lugar certo e o `::before`
   dele, empurrado de volta pelo mesmo tanto. */
.brilho > .brilho__halo {
  inset: calc(var(--brilho-halo) * -1);
  z-index: 1;
  border-radius: 0;
  mask-image: conic-gradient(
    from var(--brilho-angulo) at center, #000 2.5%, transparent 10%, transparent 90%, #000 97.5%
  );
  opacity: calc((var(--brilho-perto) - var(--brilho-limiar)) / (100 - var(--brilho-limiar)));
}

.brilho > .brilho__halo::before {
  content: "";
  position: absolute;
  inset: var(--brilho-halo);
  border-radius: var(--brilho-raio);
  /* A escada do original (1, 3, 6, 15, 25, 50px de desfoque, com a
     opacidade caindo na mesma medida), duas vezes: pra dentro e pra
     fora. O `--brilho-escala` encolhe os desfoques; o fio de 1px de
     cima fica de fora dela, porque ele e a linha e nao o halo. */
  box-shadow:
    inset 0 0 0 1px hsl(var(--brilho-hsl) / min(100%, calc(100% * var(--brilho-forca)))),
    inset 0 0 calc( 1px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(60% * var(--brilho-forca)))),
    inset 0 0 calc( 3px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(50% * var(--brilho-forca)))),
    inset 0 0 calc( 6px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(40% * var(--brilho-forca)))),
    inset 0 0 calc(15px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(30% * var(--brilho-forca)))),
    inset 0 0 calc(25px * var(--brilho-escala)) 1px hsl(var(--brilho-hsl) / min(100%, calc(20% * var(--brilho-forca)))),
    inset 0 0 calc(50px * var(--brilho-escala)) 1px hsl(var(--brilho-hsl) / min(100%, calc(10% * var(--brilho-forca)))),
          0 0 calc( 1px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(60% * var(--brilho-forca)))),
          0 0 calc( 3px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(50% * var(--brilho-forca)))),
          0 0 calc( 6px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(40% * var(--brilho-forca)))),
          0 0 calc(15px * var(--brilho-escala)) 0 hsl(var(--brilho-hsl) / min(100%, calc(30% * var(--brilho-forca)))),
          0 0 calc(25px * var(--brilho-escala)) 1px hsl(var(--brilho-hsl) / min(100%, calc(20% * var(--brilho-forca)))),
          0 0 calc(50px * var(--brilho-escala)) 1px hsl(var(--brilho-hsl) / min(100%, calc(10% * var(--brilho-forca))));
}

/* ---------- quem veste o brilho ---------- */

/* O campo de escrever. So o raio: o fundo dele ja e o `--surface`
   que o padrao supoe. */
.chatbar.brilho { --brilho-raio: var(--r-pill); }

/* A fala que acabou de aparecer, dos dois lados. As duas caixas nao
   sao iguais, e o brilho precisa saber as duas diferencas:

   1. O FUNDO. A do Zentry e `--surface`, que ja e o padrao la em
      cima. A de quem escreveu e `--accent-tint`, e essa nao pode ser
      usada crua: o tint e translucido, e a camada de baixo do brilho
      e pintada POR CIMA do fundo da propria caixa. Repintar um verde
      de 12% em cima de outro de 12% da 23% — a fala escureceria
      durante a volta pra clarear de novo no fim. O `color-mix` achata
      os dois num opaco so, que e o que a caixa ja parece.
      ⚠️ Os 12% sao os do `--accent-tint` do tema claro. O escuro usa
      10, e a diferenca de dois pontos nao chega a um ponto de cor
      sobre o fundo preto — mas se o tint mudar, esta linha muda.

   2. O CANTO FECHADO. Ele ancora a caixa na margem de quem falou, e
      por isso troca de lado: embaixo a direita na fala de quem
      escreveu, embaixo a esquerda na do Zentry. E o mesmo desenho do
      `.chat__text` la em cima, repetido aqui porque o brilho contorna
      a peca e precisa da forma dela — mexeu la, mexe aqui.        */
.chat__turn--voce .chat__text.brilho {
  --brilho-fundo: color-mix(in srgb, var(--accent) 12%, var(--bg));
  --brilho-raio: var(--r-lg) var(--r-lg) var(--r-sm) var(--r-lg);
}
.chat__turn--coach .chat__text.brilho {
  --brilho-raio: var(--r-lg) var(--r-lg) var(--r-lg) var(--r-sm);
}

.search {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 0 18px;
  background: var(--surface);
  border-radius: var(--r);
  color: var(--text-3);
}
.search svg { width: 21px; height: 21px; flex: none; }
.search input { font-size: var(--fs-body); }

.dashed {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 68px;
  padding: 0 18px;
  border: 1px dashed var(--border);
  border-radius: var(--r);
  color: var(--text-2);
  font-size: var(--fs-body);
  width: 100%;
}
.dashed svg { width: 20px; height: 20px; }

/* ---------- tab bar ---------- */
.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  display: flex;
  height: calc(var(--tabbar-h) + var(--safe-bottom));
  padding-bottom: var(--safe-bottom);
  /* Fundo do tema, OPACO (27/09/2026). Era translucido com
     `backdrop-filter: blur(18px)`, o efeito mais caro do app: a barra fica
     sempre na tela, e o navegador refazia o borrado a cada quadro de
     rolagem. O borrado nao dizia nada a quem usa; o lag, sim. */
  background: var(--bg);
  border-top: 1px solid var(--border-soft);
}

/* ---------- a faixa da barra do sistema ----------
   O app e edge-to-edge (`viewport-fit=cover` no index.html): o Android
   desenha a barra dele — voltar, home, recentes — POR CIMA dos nossos
   pixels, e quem pinta aquele pedaco e o app. E o `--safe-bottom` que a
   tab bar ja reserva acima.

   O problema e QUE COR fica ali. A tab bar e translucida de proposito
   (o borrado que deixa o conteudo passar por baixo dela), e embaixo dos
   botoes do sistema isso nao le como cor do app: le como um borrao que
   muda conforme o que esta rolando atras, e o sistema ainda escurece a
   faixa pra dar contraste aos proprios botoes. O resultado e uma barra
   preta num app claro.

   Entao a faixa do sistema — e SO ela, os ultimos `--safe-bottom` — e
   opaca e da cor do fundo do tema: os botoes do Android ficam sobre o
   `--bg` exato do tema escolhido, sem transparencia nenhuma. O resto da
   tab bar continua translucido como sempre foi.

   `z-index: -1` porque o `backdrop-filter` faz da tab bar um contexto de
   empilhamento: o negativo para NELA, cobrindo o fundo translucido dela
   naquele pedaco sem passar por cima dos icones. E onde nao ha barra do
   sistema pra reservar (`--safe-bottom` = 0), a faixa tem altura zero e
   nao existe. */
.tabbar::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--safe-bottom);
  background: var(--bg);
  z-index: -1;
}

.tabbar__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  color: var(--text-3);
  padding-top: 2px;
}
.tabbar__item svg { width: 25px; height: 25px; }
.tabbar__item span {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  letter-spacing: var(--tr-mono);
}
.tabbar__item.is-active { color: var(--accent-texto); }

/* ---------- com o teclado aberto ela sai de cena ----------
   Escolha do dono (22/09/2026), pra tela de conversa: enquanto se
   digita, a barra desce e o campo encosta direto no teclado. O motivo e
   espaco — com o teclado ocupando metade da tela, 58px de abas pra
   ninguem tocar agora sao 58px de conversa que nao se le.

   Ela nao "esconde": `fixed` no fim do layout viewport, com o teclado
   aberto, ela JA esta atras do teclado em toda tela do app (o teclado
   cobre o fim da pagina, ele nao encurta a pagina — ver js/teclado.js).
   O que estas linhas fazem e tirar ela de la de verdade, pra ninguem
   tocar no escuro e pro lugar dela poder ser usado.

   O `translate` (e nao `transform`) porque no desktop a barra ja tem um
   `transform: translateX(-50%)` que a centra na moldura de 430px
   (screens.css): as duas propriedades se somam, e assim nao ha uma
   segunda copia daquela regra aqui. O `--dur` cai pra 0.01ms com menos
   movimento pedido, e ai ela so sai.                                   */
.tabbar {
  transition: translate var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
body.com-teclado .tabbar {
  translate: 0 100%;
  opacity: 0;
  pointer-events: none;
}
/* (o `[hidden]` que vence este display:flex mora no base.css, valendo
   pra todo componente — nao so pra barra) */

/* ---------- ranking ---------- */
.rank {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 17px 0;
  border-bottom: 1px solid var(--border);
}
.rank--me {
  border: 1px solid var(--accent);
  border-radius: var(--r);
  background: var(--accent-tint);
  padding: 14px;
  margin: 8px 0;
}
.rank__pos {
  flex: none;
  width: 30px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--text-3);
  text-align: center;
}
.rank__pos--1 {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}
.rank__main  { flex: 1; min-width: 0; }
.rank__name  { font-size: var(--fs-body); font-weight: 500; }
.rank__sub   { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-3); margin-top: 2px; }
.rank__delta { font-family: var(--font-mono); font-size: var(--fs-mono); }
.rank__score { font-size: 24px; font-weight: 600; letter-spacing: -.02em; }
.rank__score small {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 400;
  color: var(--text-3);
}

/* ---------- notificacao ---------- */
.notif {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 19px 0;
  border-bottom: 1px solid var(--border);
  width: 100%;
  text-align: left;
}
.notif__dot {
  flex: none;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  margin-top: 19px;
}
.notif__dot--off { background: none; }
.notif__text { font-size: var(--fs-body); line-height: 1.42; color: var(--text-2); }
.notif__text b { color: var(--text); font-weight: 600; }
.notif__time { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-3); margin-top: 5px; }
.notif__ai {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid var(--accent);
}
.notif__ai::after { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }

/* O simbolo da conquista no sino: o mesmo disco cinza da lista de
   Desafios (docs/cores.md § 3 — ja aconteceu, tem corpo), no tamanho do
   avatar que ele substitui na linha. */
.notif__conquista {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--feito-fundo);
  color: var(--feito-texto);
}
.notif__conquista svg { width: 24px; height: 24px; }

/* Notificacao que leva a algum lugar e um <a>: some a cor de link e
   ganha o toque afundado das outras linhas. */
a.notif { color: inherit; align-items: center; }
a.notif:active { opacity: .6; }
a.notif .row__chev { align-self: center; }

/* ---------- feed ---------- */
.post { padding: var(--gap-lg) 0; border-bottom: 1px solid var(--border); }
.post__head { display: flex; align-items: center; gap: 14px; }
.post__name { font-size: var(--fs-lg); font-weight: 600; }
.post__meta { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-3); margin-top: 2px; }
.post__actions { display: flex; align-items: center; gap: 22px; color: var(--text-3); }
.post__action {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-body);
  /* cresce a area de toque pra 44px sem empurrar o layout */
  min-height: 44px;
  padding: 0 4px;
  margin: 0 -4px;
}
.post__action svg { width: 21px; height: 21px; }

.reps { display: flex; gap: var(--gap-sm); overflow-x: auto; scrollbar-width: none; }
.reps::-webkit-scrollbar { display: none; }
.rep { flex: 1; min-width: 78px; padding: 15px 16px; background: var(--surface); border-radius: var(--r-sm); }
.rep__label { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-3); }
.rep__value { font-size: 21px; font-weight: 600; color: var(--accent-texto); margin-top: 3px; letter-spacing: -.02em; }

/* ---------- linha do plano: SAIU na v1.69 ----------
   A semana era uma pilha de sete cartoes de largura inteira, e esta era
   a linha de dentro deles (data grande a esquerda, titulo no meio,
   visto a direita). Ela virou bloco de bento: a grade de duas colunas
   de `.bento` acima, montada em js/screens/plano.js -> blocoDoDia().
   O motivo esta la; em resumo, empilhado um domingo de descanso pesava
   o mesmo que o longao de 18 km. */

/* ---------- toast ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--tabbar-h) + var(--safe-bottom) + 18px);
  transform: translateX(-50%) translateY(12px);
  z-index: 90;
  max-width: calc(100vw - 40px);
  padding: 13px 20px;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--fs-sm);
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s var(--ease), transform .22s var(--ease);
}
.toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }

/* O recado tambem sobe. Ele mede a partir da tab bar, que com o teclado
   aberto nao esta mais la — e sem isto o aviso de "nao consegui mandar
   agora" nasceria atras do teclado, no unico momento em que ele
   importa: logo depois de alguem apertar enviar. */
body.com-teclado .toast { bottom: calc(var(--teclado) + 18px); }

/* ============================================================
   O MAPA — a mesma moldura em toda tela
   ------------------------------------------------------------
   Duas pecas, e nao mais que duas:

     .mapa         a moldura. Serve tanto pra <img> estatica (treino,
                   feed, prova, rotas) quanto pro mapa vivo do GL JS.
     .mapa--vivo   so na tela de correr: ocupa o corpo da tela em vez
                   de ter altura propria.

   Raio e o do cartao, e a borda e o mesmo fio de todo mundo: um mapa
   com raio proprio se afasta das outras pecas e a grade nao assenta
   (a mesma lei do `card()` — ver o bloco do CARTAO acima).

   Sem sombra: o que separa o mapa da pagina e a diferenca de tom, igual
   ao cartao.
   ============================================================ */
.mapa {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-card);
  background: var(--surface);   /* o tom que ocupa o lugar enquanto carrega */
  box-shadow: inset 0 0 0 1px var(--border-soft);
}
.mapa img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------- o mapa vivo (tela de correr) ---------- */
/* flex:1 e min-height:0 na area: e o mapa que absorve a sobra vertical da
   tela, e sao os numeros embaixo dele que tem tamanho fixo. Sem o
   min-height:0 o container de flex se recusa a encolher e empurra o
   rodape pra fora da dobra — que e justamente o botao de Pausar. */
.mapa-area {
  position: relative;
  display: flex;
  flex: 1;
  min-height: 0;
  margin: var(--gap) var(--pad) 0;
}
.mapa--vivo {
  flex: 1;
  min-height: 180px;
  border-radius: var(--r-lg);
}

/* Ponto de "estou aqui". Nao e um alfinete: alfinete aponta pra um lugar
   no mapa, e este ponto e a PESSOA — ela esta no meio dele, nao embaixo. */
.gps-ponto {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--certo);
  border: 3px solid var(--bg);
  box-shadow: 0 0 0 4px var(--certo-fundo);
}

/* O mapa da Mapbox nasce com a fonte e o tamanho dele. Estas tres regras
   trazem a atribuicao pro tipo do app — ela e obrigatoria por contrato,
   entao fica visivel; o que da pra fazer e nao deixar ela gritando. */
.mapboxgl-ctrl-attrib,
.mapboxgl-ctrl-attrib a {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
}
.mapboxgl-ctrl-bottom-right .mapboxgl-ctrl-attrib { background: var(--bg); }

/* ---------- botao de recentralizar ----------
   Aparece so depois que a pessoa arrasta o mapa: enquanto o mapa segue
   sozinho, um botao de "centralizar" nao tem o que fazer e so ocupa um
   canto. Flutua, entao aqui a sombra e legitima. */
/* No ALTO do mapa, nao no rodape: embaixo moram o logo e a atribuicao
   da Mapbox, que sao obrigatorios por contrato e nao podem ficar
   escondidos atras de um botao. */
.mapa__recentrar {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 14px;
  min-height: 40px;
  border-radius: var(--r-pill);
  background: var(--bg);
  color: var(--certo-texto);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .16), inset 0 0 0 1px var(--border-soft);
}
.mapa__recentrar svg { width: 16px; height: 16px; }

/* ---------- os numeros da corrida ---------- */
/* Tres, nunca seis: distancia, tempo e pace. Cadencia, calorias e
   altimetria sao numeros que o GPS de celular NAO mede bem — mostrar
   seria inventar precisao. */
.corrida-num {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: var(--gap);
  padding: var(--gap-md) var(--pad) 0;
}
.corrida-num .stat__value { white-space: nowrap; }
.corrida-dica {
  padding: var(--gap-xs) var(--pad) 0;
  min-height: 1.6em;      /* reserva a linha: sem isso a tela pula quando
                             o texto vai de vazio pra "gravando" */
}

/* Corrida ou caminhada, antes de comecar. Mora entre a dica e o rodape
   e some quando a captura arranca — nao ha o que escolher no meio de
   uma corrida, e um chip ali vira alvo de toque acidental. */
.corrida-modo { padding: var(--gap-sm) var(--pad) 0; }

/* ---------- a legenda do território (dominação) ----------
   Duas cores e duas palavras, na mesma linha que diz o estado do mapa.
   Não vira quadro nem cartão: uma legenda de dois itens que ocupa uma
   caixa própria pesa mais que a informação que ela carrega.

   As cores são as mesmas leituras de sempre (docs/cores.md § 2): verde
   é o que é seu, amarelo é o que está fora do combinado e pede uma
   volta lá. Nenhuma cor nova entrou por causa desta tela. */
.legenda { display: inline-flex; align-items: center; gap: 6px; }
.legenda + .legenda { margin-left: var(--gap); }
.legenda__cor {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 3px;
}
.legenda__cor--meu   { background: var(--certo); }
.legenda__cor--outro { background: var(--acao); }

/* Tela baixa: o mapa cede primeiro. O que nao pode sair da dobra e o
   botao do rodape. */
@media (max-height: 700px) {
  .corrida-num { padding-top: var(--gap); }
  .corrida-num .stat__value--lg { font-size: var(--fs-stat); }
  .mapa--vivo { min-height: 140px; }
}

/* ---------- busca de lugar (prova nova) ---------- */
/* Lista de resultado da geocodificacao. Nasce colada no campo: e a
   continuacao dele, nao um cartao a parte. */
.lugares {
  margin-top: 2px;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface);
}
.lugares__i {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 56px;
  padding: 10px 14px;
  text-align: left;
}
.lugares__i + .lugares__i { box-shadow: 0 -1px 0 var(--border-soft); }
.lugares__i:active { background: var(--surface-2); }
.lugares__ic { flex: none; color: var(--text-3); display: flex; }
.lugares__ic svg { width: 18px; height: 18px; }
.lugares__txt { min-width: 0; }
.lugares__nome {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lugares__end {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- transicao de rota ----------
   Feita com transition (nao animation) de proposito: o estado de REPOUSO
   e o estado correto. Se o JS falhar ou o navegador engasgar na animacao,
   a tela fica no lugar certo em vez de travar deslocada.               */
/* So opacidade, e curta (27/09/2026): o deslize de 0,26 s fazia cada toque
   parecer mais lento do que era. Um fade de 0,15 s ainda diz "a tela
   mudou" sem cobrar tempo de quem ja esta esperando a rede. */
.screen {
  transition: opacity .15s linear;
}
.screen.is-entering { opacity: 0; }

/* ---------- o esqueleto (js/router.js) ----------
   O formato da tela em cinza enquanto a rede responde. O brilho que
   passa e o unico movimento: diz "carregando" sem spinner no meio. */
.esqueleto { display: flex; flex-direction: column; gap: 16px; padding-top: 24px; }
.esqueleto__bloco {
  height: 16px;
  border-radius: 8px;
  background-color: var(--surface-2);
  background-image: linear-gradient(90deg, transparent, var(--surface), transparent);
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: esqueleto-brilho 1.2s linear infinite;
}
.esqueleto__bloco--titulo { height: 32px; width: 60%; }
.esqueleto__bloco--cartao { height: 180px; border-radius: 16px; }
.esqueleto__bloco--curto  { width: 40%; }
@keyframes esqueleto-brilho {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .screen, .screen.is-entering { transition: none; opacity: 1; transform: none; }
  .esqueleto__bloco { animation: none; }
}

/* ============================================================
   A GAVETA DAS CONVERSAS
   ------------------------------------------------------------
   A lista de assuntos do chat. Entra pela esquerda porque e de la que
   se volta: ela nao leva pra frente, leva pra uma conversa que ja
   existe. Mesma anatomia da folha de instalar (scrim + Esc + dialog),
   so que deitada.

   z-index 85: acima da tab bar (40) e da folha de instalar (80),
   abaixo do toast (90) — um "conversa apagada" ainda precisa ser lido
   por cima dela.

   A largura para em 300px e em 84% da tela: numa tela estreita, uma
   gaveta que cobre tudo nao e gaveta, e outra pagina — e a conversa
   por tras dela e o que diz de onde a pessoa esta saindo.
   ============================================================ */
.lateral {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: flex;
}
.lateral__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .32);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.lateral__folha {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(300px, 84%);
  padding: calc(var(--safe-top) + 16px) 14px calc(var(--gap-md) + var(--safe-bottom));
  background: var(--bg-elev);
  border-right: 1px solid var(--border-soft);
  /* a gaveta FLUTUA de verdade: aqui a sombra e informacao (o que esta
     por cima), a mesma excecao da folha de instalar */
  box-shadow: 10px 0 44px rgba(0, 0, 0, .16);
  transform: translateX(-100%);
  transition: transform var(--dur) var(--ease);
}
.lateral__folha:focus { outline: none; }
.lateral.is-on .lateral__scrim { opacity: 1; }
.lateral.is-on .lateral__folha { transform: translateX(0); }

.lateral__topo {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  margin-bottom: var(--gap-md);
}
.lateral__topo .pill { flex: 1; padding: 0 12px; }

/* So a lista rola. O botao de conversa nova fica onde esta: ele e a
   acao mais provavel de quem abriu a gaveta, e uma acao que sobe junto
   com a rolagem some justo em quem tem muitos assuntos. */
.lateral__rolagem {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.lateral__lista { margin-top: 6px; }
.lateral__linha {
  display: flex;
  align-items: center;
  border-radius: var(--r-sm);
}
.lateral__linha.is-ativa { background: var(--accent-tint); }
.lateral__item {
  flex: 1;
  min-width: 0;              /* sem isto o titulo longo estica a linha */
  display: block;
  padding: 10px;
  color: var(--text);
}
.lateral__titulo {
  display: block;
  font-size: var(--fs-body);
  /* Uma linha e reticencias: a lista e pra reconhecer o assunto de
     relance, e um titulo de tres linhas empurra os outros pra fora. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lateral__quando {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-mono-sm);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}
.lateral__linha.is-ativa .lateral__titulo { font-weight: 600; }

.lateral__apagar {
  display: grid;
  place-items: center;
  min-width: 40px;
  min-height: 40px;
  padding: 0 8px;
  border-radius: var(--r-pill);
  color: var(--text-3);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.lateral__apagar svg { width: 19px; height: 19px; }
/* O segundo toque e o que apaga, e ate ele o botao diz isso em
   vermelho: uma lixeira que ja mudou de forma pergunta melhor do que
   uma que continua igual. */
.lateral__apagar.is-perguntando { color: var(--risco-texto); }

/* O nome do assunto aberto, na topbar. Ele e o unico que CEDE ali: o
   titulo e contexto, e os dois botoes ao lado dele sao acao. Sem o
   `flex: 0 1 auto` e o `min-width: 0` do pai, um titulo longo empurrava
   o botao da gaveta ate 0px de largura — ele continuava no DOM, sem
   nada pra tocar. */
/* O seletor e longo porque precisa vencer o `.topbar__right > *`, que
   deixa todo filho da direita `inline-flex`. Reticencia nao existe em
   caixa flex: o texto ficava cortado no meio da letra, sem o "…" que
   diz que ha mais titulo. */
.topbar__right > .chat__nome {
  display: block;
  /* O `min-height: 44px` da regra acima existe pra garantir alvo de
     toque em ACAO. Este nao e um: e o nome do assunto, e ninguem toca
     nele. Com os 44px e sem o `align-items` que o `inline-flex` trazia,
     o texto encostava no topo da linha, acima dos dois icones. */
  min-height: 0;
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================================================
   INSTALAR NA TELA DE INICIO
   ------------------------------------------------------------
   Uma folha que sobe do rodape, nao um banner colado no topo. O
   banner competiria com a marca do splash e ficaria por cima do
   conteudo de toda tela; a folha aparece uma vez, pede uma decisao
   e sai. Ela e um dialogo de verdade (role="dialog"): tem scrim,
   fecha no Esc e devolve o foco pro corpo dela.

   z-index 80: acima da tab bar (40), abaixo do toast (90) — um
   aviso de "salvo" ainda precisa ser lido por cima dela.

   O max-width e o mesmo do #app no desktop (430px), senao a folha
   atravessaria a moldura do "celular" que o screens.css desenha.
   ============================================================ */
.instalar {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.instalar__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .32);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.instalar__folha {
  position: relative;
  width: 100%;
  max-width: 430px;
  padding: var(--gap-md) var(--pad) calc(var(--gap-md) + var(--safe-bottom));
  border-radius: var(--r-card) var(--r-card) 0 0;
  background: var(--bg-elev);
  /* a folha FLUTUA de verdade: aqui a sombra e informacao (o que esta
     por cima), nao enfeite — a mesma excecao do modal citada no topo
     deste arquivo */
  box-shadow: 0 -10px 44px rgba(0, 0, 0, .16);
  border-top: 1px solid var(--border-soft);
  transform: translateY(100%);
  transition: transform var(--dur) var(--ease);
}
.instalar__folha:focus { outline: none; }
.instalar.is-on .instalar__scrim { opacity: 1; }
.instalar.is-on .instalar__folha { transform: translateY(0); }

/* o corredor da marca, no verde da marca — igual ao splash */
.instalar__marca {
  color: var(--marca);
  margin-bottom: var(--gap);
}

/* os dois passos do iPhone. Numero em pastilha porque a ordem AQUI e
   informacao: fazer o Compartilhar depois do Adicionar nao existe. */
.instalar__passos {
  list-style: none;
  /* o respiro mora AQUI, nao numa classe .mt-* no HTML: as duas teriam
     a mesma especificidade e este arquivo carrega depois do base.css,
     entao o `margin: 0` da lista venceria a utilitaria e os passos
     colariam no paragrafo */
  margin: var(--gap-md) 0 0;
  padding: 0;
  counter-reset: passo;
}
.instalar__passos li {
  counter-increment: passo;
  position: relative;
  padding-left: 34px;
  min-height: 24px;
  font-size: var(--fs-body);
  line-height: 1.45;
  color: var(--text-2);
}
.instalar__passos li + li { margin-top: var(--gap-sm); }
.instalar__passos li::before {
  content: counter(passo);
  position: absolute;
  left: 0;
  top: 1px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--certo-fundo);
  color: var(--certo-texto);
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}
.instalar__passos b { color: var(--text); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .instalar__folha { transition: none; }
}

/* ============================================================
   o cartao do Tryzen Pro (30/09/2026)
   ------------------------------------------------------------
   O cartao do desenho do dono: o filme da trilha ocupando o cartao
   INTEIRO, o corredor da marca em branco no meio dele e um painel
   escuro encostado no pe. Quem monta e js/convite-pro.js, e ele e o
   UNICO modal do Pro: a Hoje o abre uma vez por dia, o chat o abre
   quando o portao barra uma pergunta. A folha que morava no chat saiu
   na mesma noite, quando o dono achou os dois.

   ---------- por que ele e centrado, e nao uma folha ----------
   Folha e a forma de quem responde a um toque: ela vem de baixo, de
   onde o polegar estava (e a de instalar, logo acima). Este cartao
   aparece na frente da tela, e centrado ele e uma coisa que CHEGOU, e
   nao a continuacao do que a pessoa estava fazendo. Serve pros dois
   momentos porque nos dois o app parou pra falar.

   ---------- por que o painel NAO segue o tema ----------
   Ele e legenda de foto: mora POR CIMA de um filme que e escuro nas
   sombras e claro no ceu. No tema claro um painel claro sumiria no
   ceu azul do filme e a letra iria junto. Entao o painel usa o cinza
   do escuro (#212121, o cinza neutro do dono) e a letra dele e a do
   tema escuro, nos dois temas. O verde do botao continua sendo o
   token: a pilula e a mesma do app inteiro.

   z-index 80: o mesmo da folha de instalar — acima da tab bar (40),
   abaixo do toast (90).
   ============================================================ */
.convite-pro {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: calc(var(--gap) + var(--safe-top)) var(--gap) calc(var(--gap) + var(--safe-bottom));
  /* a rede de seguranca da conta de altura do cartao: numa lingua que
     quebre a frase em tres linhas o painel passa dos 190px estimados, e
     sem isto o botao ficaria abaixo da tela num aparelho baixo */
  overflow-y: auto;
}
.convite-pro__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .45);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.convite-pro.is-on .convite-pro__scrim { opacity: 1; }

.convite-pro__cartao {
  position: relative;
  /* ---------- a largura sai da ALTURA que sobra (30/09/2026) ----------
     O filme tem a proporcao do arquivo e nao corta nada, entao a altura
     do cartao e "3/4 da largura + o painel". Num aparelho baixo isso
     estouraria a tela, e a saida NAO pode ser apertar o filme: o que se
     encolhe e o cartao inteiro, junto, mantendo o quadro igual (escolha
     do dono, 30/09).

     A conta inversa: se a altura disponivel e H e o painel come ~190px,
     a largura maxima e (H - 190) * 4/3. Os 390px sao a largura do #app
     no desktop (430) menos os dois vaos, e o `100%` e o celular comum.
     Quem vencer dos tres manda.

     O 190 e uma estimativa do painel (titulo, duas linhas de frase e a
     pilula). Numa lingua que quebre em tres linhas ele passa disso, e
     por isso a rolagem do `.convite-pro` la em cima fica de rede. */
  --convite-h: calc(100dvh - var(--safe-top) - var(--safe-bottom) - 2 * var(--gap));
  width: min(100%, 390px, (var(--convite-h) - 190px) * 4 / 3);
  border-radius: var(--r-card);
  /* o preto e o que aparece nos milissegundos antes do primeiro quadro
     e nas bordas, se o filme nao cobrir por arredondamento */
  background: #000;
  overflow: hidden;
  /* o cartao FLUTUA de verdade: aqui a sombra e informacao (o que esta
     por cima), nao enfeite */
  box-shadow: 0 18px 60px rgba(0, 0, 0, .34);
  opacity: 0;
  transform: translateY(14px) scale(.96);
  /* a mola das folhas e modais do beui (SPRING_PANEL): sobreamortecida,
     ela nao balanca — um cartao que pede dinheiro nao pode parecer
     brinquedo */
  transition:
    opacity var(--dur) var(--ease),
    transform var(--mola-folha-dur) var(--mola-folha);
}
.convite-pro__cartao:focus { outline: none; }
.convite-pro.is-on .convite-pro__cartao {
  opacity: 1;
  transform: none;
}

/* ---------- o filme ----------
   ⚠️ A caixa tem a PROPORCAO DO ARQUIVO (4/3, os 720x540 de
   assets/pro/convite.mp4). Trocou o mp4, troque este numero junto.

   Ate a primeira versao desta tela o filme era `inset: 0`, esticado
   sobre o cartao INTEIRO, e o painel tapava os 54% de baixo. A conta
   disso e que so a FATIA DE CIMA do quadro aparecia — e a corredora
   mora no meio e no pe dele: na cena da trilha (a 67% da altura) ela
   sumia atras do painel, e o corte lateral de 11% ainda cortava o pe
   dela no close das pedras. O dono viu e mandou consertar: "cortou a
   pessoa correndo, mesmo que ocupe um espaco maior para cima"
   (30/09/2026).

   Agora a caixa E o quadro: nada e cortado, nem em cima nem dos lados,
   e o cartao cresce pra caber. O painel encosta nela por baixo e sobe
   so o proprio raio (ver `.convite-pro__base`), que e o que faz ele
   parecer apoiado na foto sem comer nada que importe.

   A FOTO e o fundo desta caixa, e nao o `poster` do <video>: quem pediu
   menos movimento nao ganha <video> nenhum (js/convite-pro.js) e mesmo
   assim ve o quadro. E o primeiro quadro do proprio filme. */
.convite-pro__filme {
  position: relative;
  aspect-ratio: 4 / 3;
  background: #0A0E0A url('../assets/pro/convite.jpg') center / cover no-repeat;
}
.convite-pro__filme video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* `cover` numa caixa que ja tem a proporcao do arquivo nao corta nada;
     ele so garante que meio pixel de arredondamento nao deixe uma
     listra do fundo aparecendo na borda. */
  object-fit: cover;
  display: block;
}
/* ---------- o corredor da marca, em branco ----------
   A altura e 13,2% da LARGURA do cartao, medida no video do dono: la o
   cartao tem 1053px e o corredor 139. Como a razao do desenho e
   0,7125 (406,76 / 570,86), a largura sai em 9,4% — e assim ele cresce
   junto com o cartao em vez de ficar num tamanho fixo que so acerta
   num aparelho.

   Sem sombra, sem contorno: o desenho do dono nao tem nenhum, e branco
   cheio aguenta tanto o ceu azul quanto o pedregulho da segunda cena.
   O `%` precisa de uma largura pra resolver, e quem a da e o span; o
   svg dentro dele so preenche. */
.convite-pro__marca {
  position: absolute;
  /* no centro do QUADRO, como no desenho do dono (resposta dele,
     30/09/2026: "exatamente como no video que mostrei") */
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  display: block;
  width: 9.4%;
  color: #fff;
}
.convite-pro__marca svg {
  display: block;
  width: 100%;
  height: auto;
}
/* o X: unica saida desenhada. O circulo escuro existe pelo mesmo motivo
   da sombra da marca — o filme muda de cor debaixo dele. */
.convite-pro__x {
  position: absolute;
  top: 10px;
  right: 10px;
  /* 40px e o alvo de toque de sempre; o circulo pintado tem 32 */
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  color: #fff;
}
.convite-pro__x::before {
  content: '';
  position: absolute;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .38);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.convite-pro__x svg {
  position: relative;
  width: 18px;
  height: 18px;
}

/* ---------- o painel ----------
   Ele sobe sobre o filme o proprio raio (18px, o `--r-lg`), e nada
   alem disso. E o bastante pros cantos arredondados mostrarem o quadro
   atras deles, que e o que faz o painel parecer APOIADO na foto — o
   desenho do dono — e pouco o suficiente pra so tapar o chao: a
   corredora mais baixa do filme esta a 67% da altura, e 18px num
   quadro de 257 sao os ultimos 7%. */
.convite-pro__base {
  position: relative;
  margin-top: calc(var(--r-lg) * -1);
  background: #292927;
  /* o raio de cima e o da bandeja de dentro, sempre MENOR que o do
     cartao por fora; embaixo ele acompanha o cartao, senao sobraria um
     canto de filme no pe */
  border-radius: var(--r-lg) var(--r-lg) var(--r-card) var(--r-card);
  padding: var(--gap) var(--gap) var(--gap);
}
.convite-pro__titulo {
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -.02em;
  color: #F2F0E8;
}
.convite-pro__frase {
  margin-top: var(--gap-xs);
  font-size: var(--fs-sm);
  line-height: 1.4;
  color: #B2B1AE;
}
/* A pilula e a do app (.btn--primary), so que do tamanho do texto e
   encostada na direita, como no desenho: o cartao e um convite, e um
   botao de borda a borda soaria como uma tela pedindo decisao. */
.convite-pro__cta {
  /* `width: auto` nao bastaria: o .btn e um flex de nivel de bloco e
     esticaria do mesmo jeito, e ai o `margin-left: auto` nao teria
     sobra pra empurrar nada. */
  width: fit-content;
  min-height: 52px;
  margin-top: var(--gap);
  margin-left: auto;
  padding: 0 26px;
  border-radius: var(--r-pill);
  font-size: var(--fs-body);
}

@media (prefers-reduced-motion: reduce) {
  .convite-pro__cartao { transition: none; }
}
/* ---------- a faixa de cookie ----------
   Ela nasce no <body>, fora do #view: o router reescreve o innerHTML da
   view a cada troca de tela e levaria a faixa junto.

   Sobe de baixo porque e onde o polegar esta, e as duas saidas tem o
   MESMO tamanho de alvo: recusar nao pode ser mais dificil do que
   aceitar. So aparece antes do login (ver js/rastreio.js). */
.consent {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(12px + var(--safe-bottom));
  z-index: 95;
  padding: var(--gap) var(--gap) 14px;
  border-radius: var(--r-lg);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  box-shadow: 0 12px 34px rgba(0, 0, 0, .18);
  max-width: 520px;
  margin-inline: auto;
  transform: translateY(14px);
  opacity: 0;
  transition: transform .22s ease, opacity .22s ease;
}
.consent.is-open { transform: none; opacity: 1; }
.consent__texto { color: var(--text-2); }
/* O link da politica dentro da faixa: o texto ao redor ja e --text-2, e
   link da mesma cor do paragrafo se apoia so no sublinhado. Aqui ele
   sobe pro --text, que e o que o olho pega primeiro numa caixa de 3
   linhas com dois botoes embaixo. */
.consent__texto .link-texto { color: var(--text); }
.consent__acoes {
  display: flex;
  gap: var(--gap-sm);
  margin-top: var(--gap);
}
.consent__acoes .btn { flex: 1; min-height: 46px; font-size: var(--fs-sm); }

/* Enquanto a faixa esta na tela, a tela encurta. Sem isto a faixa cobre
   "Criar conta" na splash, que e o botao principal do produto.
   Encurtar e nao empurrar com padding: padding jogaria o rodape pra
   baixo da dobra e a pessoa teria que rolar pra achar o botao. */
body.tem-consent .screen {
  min-height: calc(100vh - 168px);
  min-height: calc(100dvh - 168px);
}

@media (prefers-reduced-motion: reduce) {
  .consent { transition: none; }
}

/* ---------- a rotina dentro do convite do lembrete ----------
   O convite da tela Hoje pergunta a rotina ANTES de mostrar os
   horarios, entao a bandeja do cartao guarda dois blocos: o que a
   pessoa escolhe e o que ela vai receber. Os 4px da bandeja sao o halo
   das pastilhas, curtos demais pra campo e chip: este bloco repoe a
   margem por dentro, sem mexer na bandeja das outras telas. */
.convite__rotina { padding: 10px 10px 14px; }

/* Aqui a fila de sete dias divide uma largura menor que a do quiz (esta
   dentro do cartao, nao da tela). Quadrado perfeito deixaria cada dia
   com ~36px de altura, abaixo do alvo de toque; a altura vira fixa e a
   largura fica com o que sobra. */
.convite__rotina .chips--days .chip { aspect-ratio: auto; min-height: 44px; }

.convite__titulo-avisos { padding: 2px 10px 8px; }

/* Os atalhos de hora do convite ficam em duas linhas: a palavra em cima
   e a hora embaixo. Numa linha so eles nao cabem na largura do cartao,
   e a fila quebrava com um atalho sozinho embaixo. O `.chip` ja e um
   grid centralizado, entao os dois filhos empilham sem regra nova. */
.convite__rotina .escala .chip { line-height: 1.25; }
.convite__rotina .chip__quando {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  color: var(--text-3);
}

/* ============================================================
   O texto que entra borrado
   ------------------------------------------------------------
   O desenho do `textoAnimado()` (js/texto-animado.js), que e o
   `blurIn` do TextAnimate do MagicUI escrito em CSS. Os numeros sao
   os de la: sai de `blur(10px)` com opacidade 0 e chega em `blur(0)`
   com opacidade 1, em 0.3s. A fila e o `--i` de cada pedaco vezes o
   passo, que o JS ja calculou.

   O `inline-block` nao e enfeite: `filter` nao pinta em caixa inline,
   e sem ele as palavras entrariam todas de uma vez, sem borrao
   nenhum. Ele traz junto a obrigacao do `white-space`: caixas
   inline-block lado a lado comem o espaco entre elas, entao o espaco
   que virou pedaco no JS precisa do `pre` pra continuar existindo, e
   o `pre-wrap` do pai e quem deixa a frase quebrar linha mesmo com os
   espacos preservados.

   A curva e a `--ease` do app, nao a do MagicUI: a de la e a padrao do
   motion, esta e a mesma de toda transicao daqui.
   ============================================================ */
.ta { white-space: pre-wrap; }

.ta__seg {
  display: inline-block;
  white-space: pre;
  opacity: 0;
  filter: blur(10px);
  animation: ta-borrao var(--ta-dur, .3s) var(--ease) forwards;
  animation-delay: calc(var(--ta-espera, 0ms) + var(--i) * var(--ta-passo, 50ms));
}

@keyframes ta-borrao {
  from { opacity: 0; filter: blur(10px); }
  to   { opacity: 1; filter: blur(0); }
}

/* Sem o `filter: none` a palavra ficaria nitida mas ainda numa camada
   propria de composicao, e o texto sai mais mole que o resto da tela. */
@media (prefers-reduced-motion: reduce) {
  .ta__seg { animation: none; opacity: 1; filter: none; }
}

/* ============================================================
   A lista que entra item a item
   ------------------------------------------------------------
   O AnimatedList do MagicUI escrito em CSS, do mesmo jeito que o
   `.ta` aqui em cima: de la vieram os NUMEROS, nao o codigo. Sao
   estes, letra por letra:

     · o estado de entrada: `scale: 0` com opacidade 0;
     · a chegada: `scale: 1`, opacidade 1;
     · o `originY: 0`, que aqui e o `transform-origin: top`: o cartao
       cresce PRA BAIXO, a partir da borda de cima, e nao inchando do
       meio. E o que faz a lista parecer que esta sendo servida de
       cima pra baixo em vez de piscar inteira;
     · a mola (stiffness 350, damping 40), que virou `--mola` e
       `--mola-dur` no css/tokens.css.

   ---------- o que NAO veio de la ----------
   O intervalo entre um item e o outro. La e 1000ms, porque o
   AnimatedList e uma caixa de notificacoes que chegam sozinhas ao
   vivo; aqui os itens ja estao todos na tela e sao a PERGUNTA que a
   pessoa veio responder. Um segundo por opcao deixaria alguem
   esperando cinco segundos pra poder tocar na ultima. O passo e 70ms:
   a lista inteira assenta antes do dedo chegar.

   ---------- por que nao ha JavaScript aqui ----------
   Pelo mesmo motivo do texto borrado: trocar de tela neste app e um
   `innerHTML` (js/router.js), e animacao de CSS em elemento novo
   comeca sozinha. Cada passo do quiz e outro `<button>`; ele ja nasce
   entrando.

   `scale` nao mexe em layout: a altura de cada opcao esta reservada
   desde o primeiro quadro, entao a lista nao empurra nada enquanto
   entra — e o que ja estava desenhado continua exatamente onde
   estava.
   ============================================================ */
.lista-anim > * {
  transform-origin: top center;
  opacity: 0;
  transform: scale(0);
  animation: lista-entra var(--mola-dur) var(--mola) forwards;
  animation-delay: calc(var(--i, 0) * var(--la-passo, 70ms));
}

@keyframes lista-entra {
  from { opacity: 0; transform: scale(0); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .lista-anim > * { animation: none; opacity: 1; transform: none; }
}

/* ============================================================
   Tryzen Pro
   ------------------------------------------------------------
   Pedido do dono (13/09/2026): a tela de assinar ganha brilho, e tudo
   que for acrescentado respeita o desenho do app. Por isso NADA aqui
   tem cor propria: o botao e o `.btn--primary` do app (verde da marca,
   letra escura), os fundos sao `--bg` e `--bg-elev`, e o verde do
   brilho e o `--accent`. Trocar entre claro e escuro troca tudo junto.

   A primeira versao cravava o verde neon sobre verde quase preto nos
   dois temas: no claro o hero e a festa ficavam pretos no meio de uma
   tela branca, e o botao escuro nao parecia botao do app.

     .btn--pro        o botao principal com a luz girando no contorno
     .brilho-borda    a borda que brilha em tudo que e do Pro
     .pro-hero        titulo com blur, a foto do app que abre ao rolar,
                      e duas fotos em parallax
     .pro-festa       a tela cheia "Agora voce e Tryzen Pro"
   ============================================================ */
@property --pro-giro {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}
@keyframes pro-gira { to { --pro-giro: 360deg; } }

/* ---------- o botao ----------
   O fundo e a letra sao os do `.btn--primary`. O que o SpecularButton
   traz e o CONTORNO se mexendo: uma luz que da a volta na borda sem
   parar (decisao do dono: "luz girando sempre"), e fica mais forte
   quando o cursor chega perto (o `--brilho` que js/especular.js escreve,
   proximidade 250px). No celular nao ha cursor, entao a volta ja nasce
   visivel sozinha. Raio 18px.

   Segunda rodada do dono (13/09/2026): "a animacao dos botoes mais
   aparente". A volta ficou mais rapida (2s), a luz mais longa e com
   2px, o halo quase inteiro desde o comeco, e o botao respira um
   brilho verde por fora. */
@keyframes pro-pulsa {
  0%, 100% { box-shadow: inset 0 0 0 1px var(--pro-contorno), 0 0 0 0 var(--accent-glow); }
  50%      { box-shadow: inset 0 0 0 1px var(--pro-contorno), 0 0 26px 2px var(--accent-glow); }
}
.btn--pro {
  --pro-contorno: rgba(255, 255, 255, .22);
  position: relative;
  isolation: isolate;
  border-radius: 18px;
  box-shadow: inset 0 0 0 1px var(--pro-contorno);
  animation: pro-pulsa 2.4s ease-in-out infinite;
}
.btn--pro.btn--specular::before,
.btn--pro.btn--specular::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: conic-gradient(from var(--pro-giro),
    transparent 0deg 150deg,
    rgba(255, 255, 255, .6) 220deg,
    #ffffff 280deg,
    rgba(255, 255, 255, .6) 320deg,
    transparent 360deg);
  animation: pro-gira 2s linear infinite;
}
/* a luz: um anel de 2px recortado pela mascara */
.btn--pro.btn--specular::before {
  padding: 2px;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: calc(.9 + var(--brilho) * .1);
}
/* o halo por fora, no verde da marca, que cresce com o cursor perto */
.btn--pro.btn--specular::after {
  z-index: -1;
  inset: -6px;
  background: conic-gradient(from var(--pro-giro),
    transparent 0deg 150deg, var(--accent) 270deg, transparent 360deg);
  filter: blur(12px);
  opacity: calc(.75 + var(--brilho) * .25);
}
/* ---------- a borda que brilha ---------- */
.brilho-borda {
  position: relative;
  isolation: isolate;
  border-radius: var(--r-card);
  padding: 1.5px;
  background: var(--accent-line);
}
.brilho-borda::before,
.brilho-borda::after,
.card--gira::before,
.card--gira::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(from var(--pro-giro),
    transparent 0deg 140deg, var(--accent) 220deg, var(--accent-texto) 250deg,
    var(--accent) 280deg, transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  animation: pro-gira 4.5s linear infinite;
  pointer-events: none;
}
.brilho-borda::after,
.card--gira::after {
  z-index: -1;
  inset: -2px;
  padding: 5px;
  filter: blur(12px);
  opacity: .8;
}

/* ---------- a mesma borda, num cartao comum ----------
   Os dois cartoes de pagar usavam a luz do campo do chat (js/brilho.js),
   que da UMA volta a cada 5s e acende forte na passagem. O dono achou
   forte demais e pediu a borda do cartao do preco: esta, que gira sem
   parar e sem picos (14/09/2026).

   Aqui o anel e o mesmo, mas o corpo do cartao NAO muda: o `.brilho-borda`
   e um embrulho com fundo proprio e respiro proprio, e trocar por ele
   deixaria os cartoes de pagar identicos ao do preco. O `.card--gira` so
   desenha o anel por cima da borda que o `.card` ja tem, entao o fundo, a
   bandeja e o respiro continuam os de antes.

   Sem `padding` nem `background` proprios de proposito: quem pinta o
   fundo continua sendo o `.card`. O que vem de la e so o `isolate`, pra
   segurar o `z-index: -1` do halo dentro do cartao. */
.card--gira {
  position: relative;
  isolation: isolate;
}
.brilho-borda__dentro {
  position: relative;
  border-radius: calc(var(--r-card) - 1.5px);
  background: var(--bg-elev);
  padding: var(--gap-md) var(--gap);
}
.brilho-borda.is-acende { animation: brilho-acende 1.1s var(--ease) both; }
@keyframes brilho-acende {
  from { box-shadow: 0 0 0 0 transparent; transform: scale(.97); opacity: 0; }
  60%  { box-shadow: 0 0 40px 4px var(--accent-glow); opacity: 1; }
  to   { box-shadow: 0 0 20px 0 var(--accent-tint); transform: none; opacity: 1; }
}

/* o selo do plano: o selo "certo" do app com o anel do Pro */
.selo--pro {
  background: var(--certo-fundo);
  color: var(--certo-texto);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}

/* ---------- o que o Pro libera ---------- */
.pro-funcoes { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }
.pro-funcao { display: grid; grid-template-columns: 38px 1fr; gap: 14px; align-items: start; }
.pro-funcao__ic {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: var(--certo-fundo);
  color: var(--certo-texto);
}
.pro-funcao__ic svg { width: 19px; height: 19px; }
.pro-funcao__titulo { font-weight: 600; font-size: var(--fs-body); line-height: 1.3; color: var(--text); }
.pro-funcao__texto { margin-top: 4px; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-2); }
.pro-funcoes--festa { gap: 10px; margin-top: var(--gap-md); }
/* 27/09/2026: a lista virou so titulos (3 a 5 palavras), entao o icone
   centraliza com a linha. A folha do chat usa a mesma lista, mais junta. */
.pro-funcao { align-items: center; }
.pro-codigo { text-align: center; }
.pro-por-mes { margin-left: .35em; }
.pro-codigo #codigo-campo { text-align: left; }
/* ---------- o cupom do embaixador, no app (10/10/2026) ----------
   Campo e botao na mesma linha; o preco cheio riscado em cima do
   preco da oferta; e um pulso curto no cartao quando o numero troca. */
.cupom-campo { display: flex; align-items: flex-end; gap: var(--gap-sm); text-align: left; }
.cupom-campo[hidden], .cupom-aplicado[hidden] { display: none; }
.cupom-campo__entrada { flex: 1 1 auto; min-width: 0; }
.cupom-campo__botao { flex: 0 0 auto; width: auto; }
.cupom-aplicado { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.cupom-cheio s { text-decoration-thickness: 1px; }
.cupom-pulso #loja-cheio, .cupom-pulso #loja-linha,
.cupom-pulso #loja-economia, .cupom-pulso #loja-depois { animation: cupom-entra .42s ease-out both; }
.cupom-pulso #loja-economia { animation-delay: .06s; }
.cupom-pulso #loja-depois { animation-delay: .12s; }
@keyframes cupom-entra {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cupom-pulso #loja-cheio, .cupom-pulso #loja-linha,
  .cupom-pulso #loja-economia, .cupom-pulso #loja-depois { animation: none; }
}
.pro-funcoes--festa .pro-funcao { align-items: center; }
.pro-funcoes--festa .pro-funcao__texto { display: none; }
.pro-gratis { margin-top: var(--gap-md); padding-top: var(--gap); border-top: 1px solid var(--border-soft); }

/* ---------- a entrada ao rolar (whileInView: y 48 -> 0, 0.75s) ---------- */
[data-entra] {
  opacity: 0;
  transform: translateY(48px);
  transition: opacity .75s ease-in-out, transform .75s ease-in-out;
  transition-delay: calc(var(--i, 0) * 70ms);
}
[data-entra].is-dentro { opacity: 1; transform: none; }

/* ---------- o hero ----------
   Dois blocos em fila (segunda rodada do dono, 13/09/2026):

     1. a cabeca: o titulo e a frase entram com o blur do app
        (js/texto-animado.js), no fundo da propria tela
     2. o palco: a TRILHA NA FLORESTA fica presa no topo enquanto a
        pessoa rola, abrindo do recorte do meio ate a borda e tirando o
        zoom de 170% pra 100%, e as duas fotos sobem POR CIMA dela, mais
        rapido que a rolagem, ate passarem do topo. A floresta solta no
        mesmo quadro em que a ultima some, e a secao das funcoes vem logo
        depois. Eram quatro fotos ate 14/09/2026: o dono cortou duas pra
        encurtar o caminho ate o preco.
     3. a frase "Nos vamos te ajudar a achar o seu caminho", toda branca,
        entrando borrada no primeiro movimento pra baixo, numa camada
        propria POR CIMA das fotos e SEM recorte nenhum.

   O `padding-top` das fotos e o que faz a primeira chegar so depois que
   a floresta abriu: 560px sao 80% dos 700px do percurso (PERCURSO em
   js/pro.js). Mexeu num, mexe no outro. */
.pro-hero { position: relative; }
.pro-hero__cabeca .mono { color: var(--certo-texto); }
.pro-hero__cabeca .h1 { margin-top: var(--gap-sm); line-height: 1.08; }
.pro-hero__cabeca .body-t { margin-top: var(--gap); max-width: 32ch; color: var(--text-2); }
.pro-hero__rolar {
  margin-top: var(--gap-md);
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}
.pro-hero__palco {
  position: relative;
  margin: var(--gap-lg) calc(-1 * var(--pad)) 0;
}
/* O Backlight (dono, 20/09/2026): a propria floresta, borrada 40px e
   saturada 4x como no MagicUI, presa ATRAS da janela. Nasce do tamanho
   da janela (25% a 75% da tela) e o js/pro.js so muda a escala dela
   junto com o recorte. O borrao e desenhado uma vez: escalar e trabalho
   do compositor, e a foto continua abrindo lisa. Ocupa a altura da tela
   no fluxo, e a floresta volta essa altura com o margin-top negativo. */
.pro-hero__luz {
  position: sticky;
  top: 0;
  height: 100svh;
  pointer-events: none;
}
.pro-hero__luz-i {
  position: absolute;
  left: 25%;
  top: 25%;
  width: 50%;
  height: 50%;
  background: url(../assets/pro/floresta.jpg) 55% 56% / cover no-repeat;
  filter: blur(40px) saturate(4);
  opacity: .85;
  will-change: transform;
}
.pro-hero.is-parado .pro-hero__luz { display: none; }
.pro-hero__centro {
  margin-top: -100svh;
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--bg);
  clip-path: polygon(25% 25%, 75% 25%, 75% 75%, 25% 75%);
  will-change: clip-path;
}
/* A floresta e deitada e o palco e em pe: a altura manda e os lados
   saem. A trilha corre um pouco a direita do meio (55%), entao o
   recorte e o zoom miram ali, no ponto onde ela some entre as arvores. */
.pro-hero__app {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 55% 50%;
  transform: scale(1.7);
  transform-origin: 55% 56%;
  will-change: transform;
}
/* O veu que deixa a frase legivel no ceu claro. A foto e a mesma nos
   dois temas, entao o veu e a letra branca tambem sao. */
.pro-hero__centro::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .14) 50%, rgba(0, 0, 0, .3) 100%);
  pointer-events: none;
}
/* ---------- a frase ----------
   Camada PROPRIA, e so isso: presa no topo como a floresta, por baixo
   das fotos, e SEM recorte nenhum. As duas versoes anteriores puseram
   alguma coisa no caminho do recorte que o js/pro.js escreve por quadro
   — primeiro a frase numa camada com o MESMO recorte (13/09/2026),
   depois a frase DENTRO da floresta (14/09/2026) — e das duas vezes a
   foto abriu arrastada. Aqui dentro da floresta so ficou a foto, e ela
   volta a abrir como abria antes das duas.

   O `margin-top` negativo devolve a altura que esta camada ocupa: sem
   ele as fotos comecariam 100svh mais pra baixo.

   Fica no MEIO da tela, e nao mais em 16svh. La em cima ela nascia fora
   da janela de 25%/75% da floresta: o blur comeca no primeiro movimento
   pra baixo e acabava antes de a janela abrir ate ela, entao a frase
   aparecia pronta, sem borrao nenhum. */
.pro-hero__frase {
  position: sticky;
  top: 0;
  /* Por CIMA das fotos (elas sao z-index 1), e nao por baixo: a frase
     ficava escondida atras delas, com meia palavra aparecendo entre uma
     foto e outra (pedido do dono, 14/09/2026). Agora as fotos passam por
     baixo dela e nada da frase se perde. */
  z-index: 2;
  height: 100svh;
  margin-top: -100svh;
  display: grid;
  align-content: center;
  padding: 0 var(--pad);
  text-align: center;
  pointer-events: none;
}
/* O veu da frase. O veu da floresta (`.pro-hero__centro::after`) fica
   DENTRO do recorte, entao ele so cobre a janela: enquanto ela e
   estreita, as pontas das linhas caem no fundo da tela, e no tema claro
   letra branca em fundo branco some. Esta mancha anda com a frase, nos
   dois temas, e no meio da foto ela devolve o contraste que a frase
   tinha em 16svh (la o veu da floresta ja estava em 0.5; no meio ele
   vale 0.14). Parada: nao custa quadro nenhum. */
.pro-hero__frase::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(78% 24% at 50% 50%, rgba(0, 0, 0, .38), rgba(0, 0, 0, 0) 100%);
}
/* a frase e toda branca (pedido do dono, 13/09/2026): o verde que
   destacava "achar o seu caminho" saiu */
.pro-hero__frase .h1 {
  position: relative;
  color: #fff;
  line-height: 1.1;
  text-shadow: 0 2px 22px rgba(0, 0, 0, .35);
}
/* O `padding-bottom` nao e respiro: e a pista que as fotos precisam pra
   sumir ANTES de a floresta soltar. Com os 96px de antes, a ultima foto
   ainda estava no meio da tela quando o palco acabava, e ela saia
   rolando junto com o hero em vez de subir embora (pedido do dono,
   14/09/2026). Medido: a ultima foto passa do topo no mesmo quadro em que
   o palco encosta no pe da tela.

   Foi 50svh enquanto eram quatro fotos. Com duas (a lista mora em
   js/screens/assinatura.js) a ultima e a mais ALTA das duas, que sobe
   mais cedo, e 50svh deixava meia tela de floresta parada no fim: 40svh
   entrega o mesmo encontro e encurta o palco. Este numero anda junto com
   a lista de fotos e com o `sobe` delas: mexeu num, confere o outro. */
.pro-hero__fotos {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 72px;
  padding: 560px var(--pad) 40svh;
}
.pro-hero__foto { width: 64%; }
.pro-hero__foto:nth-child(2) { margin-left: auto; }
.pro-hero__foto img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-lg);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .35);
  will-change: transform;
}
/* menos movimento: a floresta ja aberta e sem zoom, a frase ja escrita.
   Ela continua presa e as fotos continuam passando por baixo dela: isso
   e rolagem, nao animacao. Sem o laco de quadros elas tambem nao sobem
   sozinhas, entao saem da tela no tempo da rolagem, e nao antes. */
.pro-hero.is-parado .pro-hero__centro { clip-path: none; }
.pro-hero.is-parado .pro-hero__app { transform: none; }
.pro-hero.is-parado .pro-hero__fotos { padding-top: 45svh; }

/* ---------- a celebracao ----------
   O fundo e o da tela (claro no claro, escuro no escuro) com um halo
   verde no meio; o cartao e o `--bg-elev` com a borda que brilha. */
.pro-festa {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: var(--pad);
  overflow: hidden;
}
.pro-festa__fundo {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(70% 45% at 50% 42%, var(--accent-tint), transparent 70%),
    color-mix(in srgb, var(--bg) 94%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0;
  transition: opacity .38s var(--ease);
}
.pro-festa__raios {
  position: absolute;
  width: 160vmax;
  height: 160vmax;
  left: 50%;
  top: 45%;
  translate: -50% -50%;
  background: repeating-conic-gradient(from 0deg, var(--accent-tint) 0deg 6deg, transparent 6deg 24deg);
  -webkit-mask: radial-gradient(circle, #000 0, transparent 55%);
  mask: radial-gradient(circle, #000 0, transparent 55%);
  opacity: 0;
  animation: festa-raios 22s linear infinite;
  transition: opacity .6s var(--ease);
  pointer-events: none;
}
@keyframes festa-raios { to { rotate: 360deg; } }
.pro-festa__cartao {
  width: 100%;
  max-width: 380px;
  opacity: 0;
  transform: translateY(24px) scale(.96);
  transition: opacity .45s var(--ease), transform .55s var(--mola, var(--ease));
}
.pro-festa__cartao:focus { outline: none; }
.pro-festa__cartao .brilho-borda__dentro { padding: var(--gap-lg) var(--gap-md) var(--gap-md); }
.pro-festa__kicker { color: var(--certo-texto); }
.pro-festa__titulo { margin-top: var(--gap-sm); line-height: 1.08; color: var(--text); }
.pro-festa__titulo span { color: var(--certo-titulo); text-shadow: 0 0 24px var(--accent-glow); }
.pro-festa__sub { margin-top: var(--gap); color: var(--text-2); }
.pro-festa.is-on .pro-festa__fundo,
.pro-festa.is-on .pro-festa__raios { opacity: 1; }
.pro-festa.is-on .pro-festa__cartao { opacity: 1; transform: none; }
.pro-festa.is-on .pro-festa__cartao.brilho-borda { animation: brilho-acende 1.1s var(--ease) both; }

@media (prefers-reduced-motion: reduce) {
  .btn--pro.btn--specular::before, .btn--pro.btn--specular::after,
  .brilho-borda::before, .brilho-borda::after, .pro-festa__raios,
  .card--gira::before, .card--gira::after,
  .brilho-borda.is-acende, .pro-festa.is-on .pro-festa__cartao.brilho-borda { animation: none; }
  [data-entra] { opacity: 1; transform: none; transition: none; }
  .pro-festa__cartao, .pro-festa__fundo { transition: none; }
}

/* ---------- a logo do Zentry (js/ui.js -> zentryLogo) ----------
   Do tamanho da letra de onde ela mora, no verde da marca, antes do
   nome. Nos rotulos em mono (o nome em cima da fala) ela alinha pela
   linha do texto, sem empurrar a altura da linha.

   Desde 26/09/2026 o desenho e o CORREDOR da Tryzen, e nao o glifo
   quadrado do Zentry: por isso toda regra aqui manda na ALTURA e deixa a
   largura pro `aspect-ratio` do desenho. Cravar as duas achataria o
   corredor. */
.zentry-logo {
  display: inline-block;
  height: 1.15em;
  width: auto;
  aspect-ratio: 406.76 / 570.86;
  margin-right: .4em;
  vertical-align: -.2em;
  color: var(--accent);
  flex: none;
}
.chat__who .zentry-logo,
.zentry__quem .zentry-logo { height: 1.25em; width: auto; }
.pro-funcao__ic .zentry-logo { height: 20px; width: auto; margin: 0; vertical-align: 0; color: currentColor; }

/* ---------- a logo do Zentry no chat ----------
   Pedido do dono (13/09/2026): o icone do Zentry tambem no chat. No topo
   ela diz com quem e a conversa. No convite ela NAO entra (pedido do
   dono, 13/09/2026): la ficam so os aneis e a frase. */
/* O `margin-right: auto` separa a marca do nome do assunto SO enquanto
   sobra espaco na barra; sem sobra ele vale 0. Com "Zentry" sempre
   sobrava. Desde 26/09/2026 a marca e "Tryzen Intelligence", que come a
   sobra num celular estreito, e os dois textos passaram a se encostar. O
   `padding-right` nao depende de sobra: e o minimo garantido. */
.chat__marca { display: inline-flex; align-items: center; gap: 2px; margin-right: auto; padding-right: 10px; color: var(--text); }
.chat__marca .zentry-logo { height: 22px; width: auto; margin-right: 6px; vertical-align: 0; }
.chat__marca .mono { color: var(--text); font-weight: 600; }

/* ---------- o blur que espera ----------
   O texto com blur (js/texto-animado.js) comecava a animar no instante em
   que o HTML nascia, ainda durante a entrada da tela, e acabava antes de
   a pessoa olhar. Dentro de [data-blur-espera] ele fica parado e
   invisivel ate o js/pro.js marcar .is-dentro: logo depois que a tela
   assentou, pro titulo, e quando a secao aparece, pro resto. */
[data-blur-espera] .ta__seg,
[data-blur-rolagem] .ta__seg { animation-play-state: paused; }
[data-blur-espera].is-dentro .ta__seg,
[data-blur-rolagem].is-dentro .ta__seg { animation-play-state: running; }
/* [data-blur-rolagem] e o mesmo desenho com outro gatilho: a frase em
   cima da floresta acende no primeiro movimento de rolagem pra baixo
   (js/pro.js), e nao quando entra na tela.

   E `is-pronta` apaga o filtro quando o ultimo pedaco chega: `blur(0)`
   ainda e um filtro, e filtro parado guarda uma camada de composicao
   por palavra ate o fim da rolagem. O borrao ja passou, sobra o texto.
   Quem pediu menos movimento nem chega aqui: o media query la em cima
   ja deixou tudo escrito e sem filtro. */
[data-blur-rolagem].is-pronta .ta__seg { animation: none; opacity: 1; filter: none; }

/* ---------- a secao "o que o tryzen pro libera" ----------
   Ajuste do dono (13/09/2026): o titulo estava colado nas funcoes. O
   respiro e entre o TITULO e a LISTA (e acima da secao), nao entre as
   fotos, que ficam como estao. */
.pro-secao { margin-top: var(--gap-lg); }
.pro-secao__titulo { margin-top: var(--gap-sm); line-height: 1.15; }
.pro-secao__lista { margin-top: var(--gap-xl); }


@media (prefers-reduced-motion: reduce) {
  .btn--pro { animation: none; }
}

/* ============================================================
   A roda de tempo (js/roda.js + js/tempo.js)
   ------------------------------------------------------------
   O campo de hora e de duracao virou tambor. O desenho e o do beui:
   uma janela com desbotamento em cima e embaixo, as linhas curvando
   pra dentro do cilindro e a linha do meio nitida dentro de uma faixa.

   A faixa e a MESMA lista, clipada numa linha e desenhada com a cor
   forte: por isso ela nunca sai do lugar em relacao ao que esta atras.
   ============================================================ */

.tempo {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-xs);
  margin-top: var(--gap-xs);
}
.tempo__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}
/* Os dois pontos ficam na altura da faixa do meio, nao no topo da
   coluna: e ali que esta o numero que eles separam. */
.tempo__sep {
  flex: none;
  align-self: flex-start;
  margin-top: calc(var(--roda-alt, 176px) / 2 - 0.6em);
  font-family: var(--font-mono);
  font-size: var(--fs-h2, 24px);
  color: var(--text-3);
  line-height: 1;
}
.tempo__unid {
  text-align: center;
  font-size: var(--fs-xs);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}

/* O campo que virou roda perde o fio de baixo: a faixa do meio ja e a
   linha que diz onde esta a resposta, e duas linhas competiam. */
.field--roda { border-bottom-color: transparent; }
.field--roda:focus-within { border-bottom-color: transparent; }

.roda {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--surface);
  outline: none;
  cursor: grab;
  /* O tambor e dono do gesto inteiro: sem isto o dedo rola a pagina e
     o iOS ainda abre a lupa de selecao por cima. */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
}
.roda.is-drag { cursor: grabbing; }
.roda:focus-visible { box-shadow: inset 0 0 0 2px var(--accent-line); }
.roda.is-off { opacity: .5; pointer-events: none; }

.roda__tambor {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  margin: 0;
  padding: 0;
  height: 0;
  list-style: none;
  backface-visibility: hidden;
  transform-style: preserve-3d;
  will-change: transform;
}
.roda__tambor li {
  position: absolute;
  left: 0; right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 500;
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}

/* A linha do meio: mesma lista, cor forte, recortada numa linha so. */
.roda__faixa {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  z-index: 1;
  transform: translateY(-50%);
  overflow: hidden;
  border-radius: var(--r-sm);
  background: var(--accent-tint);
  pointer-events: none;
}
.roda__faixa .roda__tambor li { color: var(--text); font-weight: 600; }

/* ---------- menos movimento ----------
   Sem tambor e sem fisica: uma lista que rola com encaixe nativo. O
   original faz igual, e aqui vale o mesmo motivo do resto do app. */
.roda--lista .roda__rolagem {
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scroll-behavior: smooth;
  -ms-overflow-style: none;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
}
.roda--lista .roda__rolagem::-webkit-scrollbar { display: none; }
.roda--lista li { scroll-snap-align: center; }
.roda--lista button {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 500;
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
}
.roda--lista button.is-on { color: var(--text); font-weight: 600; }

/* ============================================================
   A FOLHA DO @ DO EMBAIXADOR (js/embaixador.js)
   ------------------------------------------------------------
   Mesma anatomia da folha de instalar — scrim, folha que sobe do
   rodape, dialogo de verdade — com UMA diferenca que e a razao de ela
   existir: ela nao fecha. Nao tem X, o scrim nao e clicavel e o Esc nao
   sai. E o unico dialogo do app assim.

   O motivo e pratico e nao de design: o @ e por onde a divulgacao e
   conferida e por onde o socio fala com o embaixador. Uma ficha sem @
   e trabalho pra alguem depois.

   z-index 86: acima da lateral (85) e da folha de instalar (80), abaixo
   do toast (90) — um "salvo" ainda precisa ser lido por cima dela.

   Ela sobe com a mola de painel do beui (--mola-folha), e nao com a
   duracao curta do resto: uma folha que PEDE alguma coisa merece o
   tempo de ser vista chegando.
   ============================================================ */
/* ---------- a folha que sobe ----------
   Tres usam o mesmo desenho: a do @ do embaixador (js/embaixador.js),
   a da escolha de volume (js/escolha-volume.js, 16/09/2026) e a do
   modelo de divulgar (js/folha-modelo.js, 18/09/2026). Os
   seletores andam juntos em vez de o segundo copiar os valores do
   primeiro — duas listas iguais divergem na primeira vez que alguem
   ajusta uma delas.

   A diferenca entre as duas esta no COMPORTAMENTO, nao aqui: a do @ nao
   fecha sem resposta; a do volume fecha no scrim e no Esc, porque nao
   responder ali tem um significado proprio (fica como esta). */
.apagar,
.arroba,
.denuncia,
.editar-dia,
.escolha,
.falta,
.modelo-folha,
.zentry-folha {
  position: fixed;
  inset: 0;
  z-index: 86;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.apagar__scrim,
.arroba__scrim,
.denuncia__scrim,
.editar-dia__scrim,
.escolha__scrim,
.falta__scrim,
.modelo-folha__scrim,
.zentry-folha__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .42);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.apagar__folha,
.arroba__folha,
.denuncia__folha,
.editar-dia__folha,
.escolha__folha,
.falta__folha,
.modelo-folha__folha,
.zentry-folha__folha {
  position: relative;
  width: 100%;
  max-width: 430px;
  padding: var(--gap-md) var(--pad) calc(var(--gap-md) + var(--safe-bottom));
  border-radius: var(--r-card) var(--r-card) 0 0;
  background: var(--bg-elev);
  box-shadow: 0 -10px 44px rgba(0, 0, 0, .18);
  border-top: 1px solid var(--border-soft);
  transform: translateY(100%);
  transition: transform var(--mola-folha-dur) var(--mola-folha);
}
/* ---------- a folha do dia rola por dentro ----------
   Ela e a mais alta das cinco (tres cartoes de opcao, a roda e dois
   botoes): medida em 1007px, ela passava da tela de 932 e o titulo
   ficava ACIMA da borda de cima, fora de alcance. As outras quatro sao
   curtas e nao precisam disto, entao a regra e so dela: dar rolagem a
   uma folha que cabe seria abrir a porta pra folhas que nao cabem. */
.editar-dia__folha {
  max-height: 92vh;      /* fallback: iOS < 15.4 */
  max-height: 92svh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.apagar__folha:focus,
.arroba__folha:focus,
.denuncia__folha:focus,
.editar-dia__folha:focus,
.escolha__folha:focus,
.falta__folha:focus,
.modelo-folha__folha:focus,
.zentry-folha__folha:focus { outline: none; }
/* o X de fechar, no canto de cima da folha (12/10/2026: todo "Fechar" virou X) */
.folha-x { position: absolute; top: 12px; right: 14px; margin: 0; width: 36px; height: 36px; color: var(--text-2); }
.apagar.is-on .apagar__scrim,
.arroba.is-on .arroba__scrim,
.denuncia.is-on .denuncia__scrim,
.editar-dia.is-on .editar-dia__scrim,
.escolha.is-on .escolha__scrim,
.falta.is-on .falta__scrim,
.modelo-folha.is-on .modelo-folha__scrim,
.zentry-folha.is-on .zentry-folha__scrim { opacity: 1; }
.apagar.is-on .apagar__folha,
.arroba.is-on .arroba__folha,
.denuncia.is-on .denuncia__folha,
.editar-dia.is-on .editar-dia__folha,
.escolha.is-on .escolha__folha,
.falta.is-on .falta__folha,
.modelo-folha.is-on .modelo-folha__folha,
.zentry-folha.is-on .zentry-folha__folha { transform: translateY(0); }

/* ---------- com o teclado aberto, a folha sobe com ele ----------
   A folha encosta no PE da tela (`align-items: flex-end`), e com o
   teclado aberto o pe da tela esta atras do teclado — o campo de
   escrever ficaria coberto pelo teclado que o abriu. O `--teclado` e a
   medida de quanto esta coberto (js/teclado.js); vale pras cinco
   folhas porque, com uma delas aberta, o foco esta dentro dela.

   E o teto de altura desce junto: sem isto a folha que rola por dentro
   continuaria medindo a tela inteira e o topo dela sairia por cima. */
body.com-teclado .apagar,
body.com-teclado .arroba,
body.com-teclado .denuncia,
body.com-teclado .editar-dia,
body.com-teclado .escolha,
body.com-teclado .falta,
body.com-teclado .modelo-folha { bottom: var(--teclado); }
body.com-teclado .editar-dia__folha,
body.com-teclado .modelo-folha__folha {
  max-height: calc(100svh - var(--teclado) - 12px);
}

/* ---------- apagar a conta (js/apagar-conta.js) ----------
   O vermelho so aparece aqui e so no que apaga: o texto do botao e a
   frase de quando nao deu. Sem a palavra digitada o botao fica no
   `.btn[disabled]` de todo botao do app, apagado e sem toque. */
.apagar__botao { color: var(--risco-texto); border-color: currentColor; }
/* O toque no botao que destroi: ele ENCHE de vermelho (Negative Deep)
   em vez de piscar. E a unica familia em que o toque merece peso — e o
   ultimo aviso antes de uma coisa que nao volta. */
.apagar__botao:active,
.denuncia__botao:active { background: var(--risco-preso); color: var(--text); opacity: 1; }
.apagar__erro { color: var(--risco-texto); }

/* ---------- denunciar e bloquear (js/denunciar.js) ----------
   Ela rola por dentro pelo mesmo motivo da folha do dia: o passo do
   motivo tem SETE cartoes de opcao, mais o campo de detalhe e dois
   botoes, e isso passa de qualquer tela de celular. A diferenca e que
   aqui a altura muda de passo pra passo (o menu tem duas linhas), entao
   e `max-height` e nao altura: a folha do menu continua baixa, e so a
   do motivo encosta no teto.

   O vermelho e do bloquear e da frase de quando nao deu, e nao do
   denunciar: denunciar nao apaga nada de ninguem. */
.denuncia__folha {
  max-height: 92vh;      /* fallback: iOS < 15.4 */
  max-height: 92svh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
body.com-teclado .denuncia__folha {
  max-height: calc(100svh - var(--teclado) - 12px);
}
.denuncia__botao { color: var(--risco-texto); border-color: currentColor; }
.denuncia__erro { color: var(--risco-texto); }

@media (prefers-reduced-motion: reduce) {
  .apagar__folha,
  .arroba__folha,
  .denuncia__folha,
  .editar-dia__folha,
  .escolha__folha,
  .falta__folha,
  .modelo-folha__folha,
  .zentry-folha__folha { transition: none; }
}

/* ============================================================
   A FAIXA NO NOME (js/faixa.js)
   ------------------------------------------------------------
   O DiaTextReveal. Quem pinta a faixa e o JS, quadro a quadro; aqui so
   mora o que vale fora da animacao: o nome nao quebra no meio ("Tryzen"
   numa linha e "Intelligence" na outra dividiria a faixa em duas).
   ============================================================ */
.faixa { white-space: nowrap; }

/* ============================================================
   O ZENTRY PENSANDO (js/pensando.js)
   ------------------------------------------------------------
   O ThoughtLine do React Bits, na letra do app. Na conversa e nas
   leituras ele E o cabecalho da fala ("Zentry" em mono, em cima da
   caixa), entao herda o mono de 13px do `.chat__who`: quando a resposta
   chega, a linha fica no lugar do rotulo e nada pula.
   ============================================================ */
.pensa {
  --pensa-sopro: 1.6s;
  --pensa-assenta: 350ms;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 100%;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  line-height: 1.2;
  color: var(--text-3);
}
.pensa__cabeca {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .35em;
  padding: 0 4px;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  white-space: nowrap;
  cursor: default;
  -webkit-tap-highlight-color: transparent;
}
.pensa__cabeca[data-abre] { cursor: pointer; }
.pensa__cabeca:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; border-radius: 6px; }

/* o simbolo respira enquanto trabalha e assenta apagado no fim */
.pensa__glifo {
  display: inline-flex;
  flex: none;
  width: 1.25em;
  height: 1.25em;
  color: var(--accent);
  opacity: .55;
  transition: opacity var(--pensa-assenta) cubic-bezier(.23, 1, .32, 1);
}
.pensa__glifo svg { display: block; width: 100%; height: 100%; margin: 0; }
.pensa[data-trabalhando] .pensa__glifo {
  animation: pensa-respira var(--pensa-sopro) cubic-bezier(.77, 0, .175, 1) infinite;
}
@keyframes pensa-respira {
  0%, 100% { opacity: .55; }
  50%      { opacity: 1; }
}
.pensa__nome { color: var(--text-3); }

/* as duas frases moram na mesma celula e trocam com borrao */
.pensa__rotulo { display: inline-grid; }
.pensa__texto {
  grid-area: 1 / 1;
  width: max-content;
  opacity: 0;
  filter: blur(2px);
  transition:
    opacity var(--pensa-assenta) cubic-bezier(.23, 1, .32, 1),
    filter var(--pensa-assenta) cubic-bezier(.23, 1, .32, 1);
}
.pensa__texto[data-ativo] { opacity: 1; filter: blur(0); }
.pensa__texto--feito[data-ativo] { opacity: .85; }

/* ---------- o brilho passando, em verde ----------
   O original clareia a propria letra. Aqui o miolo do degrade e o verde
   do app: e o Zentry trabalhando, e o verde e a cor de quem esta ativo. */
.pensa__sopro { display: inline-block; }
.pensa[data-trabalhando] .pensa__sopro {
  background: linear-gradient(
    100deg,
    var(--text-3) 30%,
    var(--accent-texto) 50%,
    var(--text-3) 70%
  );
  background-size: 250% 100%;
  background-position: 125% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: pensa-brilho 1.8s linear infinite;
}
@keyframes pensa-brilho { to { background-position: -125% 0; } }

.pensa__relogio {
  font-variant-numeric: tabular-nums;
  opacity: .6;
  transition:
    opacity var(--pensa-assenta) ease,
    transform var(--pensa-assenta) cubic-bezier(.77, 0, .175, 1);
}
.pensa__relogio[data-feito] { opacity: .85; }

.pensa__seta {
  display: inline-flex;
  opacity: 0;
  transition:
    opacity .2s ease,
    transform var(--pensa-assenta) cubic-bezier(.23, 1, .32, 1);
}
.pensa__seta[data-on] { opacity: .6; }
.pensa[data-trabalhando] .pensa__seta { opacity: 0; }

.pensa__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- os passos ---------- */
.pensa__rastro {
  display: grid;
  grid-template-rows: 0fr;
  width: 0;
  min-width: 100%;
  transition: grid-template-rows var(--pensa-assenta) cubic-bezier(.23, 1, .32, 1);
}
.pensa__rastro[data-aberto]:not([data-vazio]) { grid-template-rows: 1fr; }
.pensa__dobra { min-height: 0; overflow-x: visible; overflow-y: clip; }
.pensa__passos {
  display: flex;
  flex-direction: column;
  gap: .5em;
  width: max-content;
  max-width: 100%;
  padding: .7em 0 .3em 1.9em;
  font-family: var(--font);
  font-size: var(--fs-xs);
  letter-spacing: 0;
  white-space: normal;
}
.pensa__passo {
  display: flex;
  align-items: center;
  gap: .55em;
  color: var(--text-2);
  transition: opacity .2s cubic-bezier(.23, 1, .32, 1), transform .2s cubic-bezier(.23, 1, .32, 1);
}
@starting-style {
  .pensa__passo { opacity: 0; transform: translateY(-4px); }
}
.pensa__marca {
  display: inline-grid;
  flex: none;
  place-items: center;
  width: 1em;
  height: 1em;
  color: var(--accent-texto);
}
.pensa__pulso {
  display: block;
  width: .45em;
  height: .45em;
  border-radius: 50%;
  background: var(--accent);
  animation: pensa-pulsa 1.6s cubic-bezier(.77, 0, .175, 1) infinite;
}
@keyframes pensa-pulsa {
  0%, 100% { opacity: .55; }
  50%      { opacity: 1; }
}
.pensa__passo[data-feito] .pensa__passo-texto { opacity: .6; }

@media (prefers-reduced-motion: reduce) {
  .pensa__texto { filter: none !important; transition: opacity var(--pensa-assenta) ease; }
  .pensa__relogio { transition: opacity var(--pensa-assenta) ease; }
  .pensa__passo { transform: none !important; transition: opacity .2s ease; }
  .pensa[data-trabalhando] .pensa__glifo { animation-duration: 2.4s; }
  .pensa__pulso { animation-duration: 2.4s; }
  .pensa[data-trabalhando] .pensa__sopro { animation: none; }
  .pensa__rastro { transition: none; }
}

/* ============================================================
   A BARRA DO ZENTRY (js/barra-zentry.js)
   ------------------------------------------------------------
   O PromptBar do React Bits na letra e na cor do app: o campo e o
   cinza de superficie, o menu sobe por cima dele na cor da folha, o
   verde e do enviar e das faiscas. Os tempos sao os do original.
   ============================================================ */
.pbar {
  --pbar-fundo: var(--surface);
  --pbar-menu: var(--bg-elev);
  --pbar-faisca: var(--accent);
  --pbar-sai: cubic-bezier(.23, 1, .32, 1);
  --pbar-apoio: var(--text-3);
  --pbar-realce: color-mix(in srgb, var(--text) 7%, transparent);

  position: relative;
  margin: 0 var(--pad);
  color: var(--text);
}

/* ---------- o menu que sobe ---------- */
.pbar__menu {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 8px);
  z-index: 5;
  padding: 5px;
  border-radius: var(--r-lg);
  background: var(--pbar-menu);
  border: 1px solid var(--border-soft);
  box-shadow: 0 14px 34px -12px rgba(0, 0, 0, .28), 0 1px 2px rgba(0, 0, 0, .06);
  transform-origin: bottom center;
  animation: pbar-sobe 180ms var(--pbar-sai) both;
}
.pbar__menu[hidden] { display: none; }
.pbar__menu[data-tipo="tom"] { right: auto; width: min(300px, 100%); transform-origin: bottom left; }
.pbar__menu[data-tipo="tamanho"] { right: auto; width: min(300px, 100%); padding: 14px 16px 12px; transform-origin: bottom left; }
@keyframes pbar-sobe {
  from { opacity: 0; transform: translateY(4px) scale(.98); }
}

.pbar__luz {
  position: absolute;
  left: 5px;
  right: 5px;
  border-radius: var(--r-sm);
  background: var(--pbar-realce);
  opacity: 0;
  pointer-events: none;
  transition: top 220ms var(--pbar-sai), height 220ms var(--pbar-sai), opacity 150ms ease;
}
.pbar__linha {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 46px;
  padding: 0 10px;
  border-radius: var(--r-sm);
  text-align: left;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.pbar__linha-ic { display: inline-flex; flex: none; width: 20px; justify-content: center; color: var(--pbar-apoio); }
.pbar__linha-ic svg { width: 19px; height: 19px; }
.pbar__linha-nome { flex: none; font-size: var(--fs-sm); font-weight: 500; }
/* quebra de linha em vez de reticencias: o dono le qualquer corte
   como defeito (a regra "nada sai cortado") */
.pbar__linha-desc,
.pbar__linha-tag {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-xs);
  line-height: 1.3;
  color: var(--pbar-apoio);
}
.pbar__linha-tag { text-align: right; }
.pbar__linha-visto { display: inline-flex; flex: none; width: 16px; justify-content: center; color: var(--accent-texto); opacity: 0; }
.pbar__linha-visto[data-on] { opacity: 1; }

/* ---------- a regua do tamanho ---------- */
.pbar__regua-topo { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); }
.pbar__regua-titulo { color: var(--pbar-apoio); }
.pbar__regua-nivel { font-weight: 600; }
.pbar__regua-pontas {
  display: flex;
  justify-content: space-between;
  margin-top: 12px;
  font-size: var(--fs-xs);
  color: var(--pbar-apoio);
}
.pbar__regua {
  position: relative;
  height: 22px;
  margin-top: 8px;
  border-radius: 11px;
  background: var(--surface);
  cursor: pointer;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
.pbar__regua:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 3px; }
.pbar__regua-cheio {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--pbar-cheio);
  border-radius: 11px;
  background: color-mix(in srgb, var(--text) 16%, transparent);
  transition: width 220ms var(--pbar-sai), background-color 300ms ease;
}
.pbar__regua-ponto {
  position: absolute;
  top: 50%;
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--text) 30%, transparent);
}
.pbar__regua-pino {
  position: absolute;
  top: -3px;
  left: var(--pbar-x);
  width: 14px;
  height: 28px;
  margin-left: -7px;
  border-radius: 7px;
  background: var(--text);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .25);
  transition: left 220ms var(--pbar-sai), background-color 300ms ease;
}
.pbar[data-max] .pbar__regua-cheio { background: color-mix(in srgb, var(--pbar-faisca) 38%, transparent); }
.pbar[data-max] .pbar__regua-pino { background: var(--pbar-faisca); }
.pbar__regua-nota { margin-top: 10px; font-size: var(--fs-xs); line-height: 1.35; color: var(--pbar-apoio); }

/* ---------- o campo ---------- */
.pbar__campo {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 12px 10px 16px;
  border-radius: var(--r-card);
  background: var(--pbar-fundo);
  cursor: text;
}
.pbar__campo.brilho { --brilho-raio: var(--r-card); --brilho-fundo: var(--pbar-fundo); }
.pbar__aura {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(140% 120% at 0% 100%, color-mix(in srgb, var(--pbar-faisca) 24%, transparent), transparent 62%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 500ms ease;
}
.pbar__campo[data-max] .pbar__aura { opacity: 1; }
.pbar__faiscas {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  pointer-events: none;
}

.pbar__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pbar__chips[hidden] { display: none; }
.pbar__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 4px 0 9px;
  border-radius: var(--r-sm);
  background: var(--certo-fundo);
  color: var(--certo-texto);
  font-size: var(--fs-xs);
  font-weight: 500;
  animation: pbar-sobe 200ms var(--pbar-sai) both;
}
.pbar__chip-ic { display: inline-flex; }
.pbar__chip-ic svg { width: 15px; height: 15px; }
.pbar__chip-x {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  color: inherit;
  opacity: .7;
}
.pbar__chip-x:active { opacity: 1; scale: .94; }

.pbar__entrada {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--fs-body);
  line-height: 24px;
  resize: none;
  outline: none;
  overflow-wrap: anywhere;
}
.pbar__entrada::placeholder { color: var(--text-3); }

.pbar__barra { display: flex; align-items: center; gap: 4px; margin-left: -6px; }
.pbar__vao { flex: 1 1 auto; }
.pbar__ferramenta,
.pbar__escolha,
.pbar__enviar {
  flex: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.pbar__ferramenta {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  transition: background-color 150ms ease, color 150ms ease, scale 160ms var(--pbar-sai);
}
.pbar__ferramenta:active { scale: .94; }
.pbar__escolha {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 9px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-2);
  transition: background-color 150ms ease, color 150ms ease;
}
.pbar__escolha svg { width: 14px; height: 14px; }
.pbar__ferramenta[data-on],
.pbar__escolha[data-on] { background: var(--pbar-realce); color: var(--text); }
.pbar__escolha[data-max] { color: var(--accent-texto); }

.pbar__enviar {
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--text) 10%, var(--pbar-fundo));
  color: color-mix(in srgb, var(--text) 45%, var(--pbar-fundo));
  transition: background-color 200ms ease, color 200ms ease, scale 160ms var(--pbar-sai);
}
.pbar__enviar[data-armado] { background: var(--accent); color: var(--on-accent); }
.pbar__enviar:disabled { cursor: default; }
.pbar__enviar[data-armado]:active { scale: .96; }
.pbar__glifo { display: block; width: 17px; height: 17px; transform-origin: 50% 50%; }

@media (prefers-reduced-motion: reduce) {
  .pbar__menu, .pbar__chip { animation: none; }
  .pbar__luz { transition: opacity 150ms ease; }
  .pbar__regua-cheio, .pbar__regua-pino { transition: background-color 300ms ease; }
  .pbar__ferramenta:active, .pbar__enviar[data-armado]:active { scale: 1; }
}

/* A linha no lugar do rotulo "Zentry": o recuo e o dela, e nao o do
   rotulo, senao o nome anda 4px quando a resposta chega. */
.chat__who--pensa { padding: 0; }
.zentry__quem--pensa .pensa__cabeca { padding: 0; }

/* A semana no Plano entrava com o AnimatedList (.lista-anim--semana)
   ate 20/09/2026; agora entra com o BlurFade (.bf, js/blur-fade.js). */

/* ---------- o Historico ----------
   A entrada e a do Masonry (js/masonry.js -> entrarDeBaixo); o toque
   tambem: o bloco encolhe pra 95%, o `hoverScale` do original virado
   em `:active`, porque o app nao tem hover. */
.s-log .bento__i { transition: scale .18s cubic-bezier(.23, 1, .32, 1); }
.s-log a.bento__i:active { scale: .95; }
@media (prefers-reduced-motion: reduce) {
  .s-log a.bento__i:active { scale: 1; }
}

/* ---------- a Tryzen Intelligence montando o plano (#/gerando) ----------
   A mesma linha do Zentry, em letra de tela e nao de rotulo: aqui ela e
   o assunto da tela inteira, e o rastro dos passos e o que se le. */
.gerando__pensa .pensa { font-size: var(--fs-sm); }
.gerando__pensa .pensa__glifo { width: 1.1em; height: 1.4em; }
.gerando__pensa .pensa__glifo .marca { width: 100%; height: 100%; color: var(--marca); }
.gerando__pensa .pensa__passos { font-size: var(--fs-body); gap: .7em; padding-left: 1.6em; }

/* ---------- o ponto da aba "voce" (a resposta do Suporte) ---------- */
.tabbar__item { position: relative; }
.tabbar__item--dot::after {
  content: '';
  position: absolute;
  top: 7px;
  left: calc(50% + 8px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--bg);
}

/* ---------- o Suporte (js/screens/suporte.js) ----------
   As caixas sao as do chat com o Zentry. O rotulo da equipe leva o
   corredor da marca (quem responde e gente, nao a IA), e a hora vai
   miuda ao lado do nome, que e onde a conversa longa precisa dela. */
.suporte__marca { display: inline-flex; margin-right: 6px; vertical-align: -2px; color: var(--marca); }
.suporte__marca .marca { width: auto; height: 14px; }
.suporte__hora { color: var(--text-3); opacity: .8; }
.pbar--simples .pbar__barra { margin-left: 0; }
.pbar--simples .pbar__campo { padding-top: 13px; }
.row__ponto {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 1px;
}

/* o aviso do Suporte no sino: o corredor da marca num disco de superficie */
.notif__suporte {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--surface);
  color: var(--marca);
}
.notif__suporte .marca { width: auto; height: 20px; }

/* ---------- o BlurFade (js/blur-fade.js) ----------
   A semana no Plano (dono, 20/09/2026). Nasce 6px acima, borrada e
   apagada, e desce pro lugar em 0,4 s. `translate`, e nao `transform`:
   o cartao ainda pode encolher no toque sem uma apagar a outra. A classe
   sai quando a entrada acaba, pra o atraso nao valer pro toque. */
.bf {
  opacity: 0;
  translate: 0 -6px;
  filter: blur(6px);
  transition: opacity .4s ease-out, translate .4s ease-out, filter .4s ease-out;
  transition-delay: var(--bf-atraso, 0s);
}
.bf.is-dentro { opacity: 1; translate: none; filter: none; }
@media (prefers-reduced-motion: reduce) {
  .bf { opacity: 1; translate: none; filter: none; transition: none; }
}

/* ---------- a TypingAnimation (js/digitar.js) ----------
   O texto inteiro fica no lugar, transparente: e ele que segura o
   tamanho da caixa e e ele que o leitor de tela le. A parte escrita e
   uma camada por cima, na mesma fonte e na mesma largura, entao a
   quebra de linha e a mesma e nada empurra o cartao de baixo. */
.digita { position: relative; }
.digita__fantasma { color: transparent; }
.digita__vivo {
  position: absolute;
  inset: 0;
  /* o padding-top do .bento__valor empurra o texto pra baixo: a camada
     comeca no mesmo lugar que o texto de verdade */
  padding: inherit;
}
.digita__cursor {
  display: inline-block;
  margin-left: 1px;
  color: var(--accent);
  font-weight: 400;
  animation: digita-pisca 1.2s step-end infinite;
}
@keyframes digita-pisca {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ---------- o Stepper (js/stepper.js) ----------
   O do React Bits nas cores do app: a caixa de borda fina e canto de
   28px, as bolinhas de 2rem (cinza parada, verde cheio no passo atual e
   nos feitos), o traco que enche de verde e o "Continuar" em pilula.
   Sem hover; o retorno e o :active. */
.stepper {
  border: 1px solid var(--border-soft);
  border-radius: 28px;
  background: var(--bg);
}
.stepper__linha { display: flex; align-items: center; padding: 22px 20px; }
.stepper__ponto {
  flex: none;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-3);
  font-size: .875rem;
  font-weight: 600;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .3s ease, color .3s ease, scale .16s cubic-bezier(.23, 1, .32, 1);
}
.stepper__ponto[data-estado="ativo"],
.stepper__ponto[data-estado="feito"] { background: var(--accent); color: var(--on-accent); }
.stepper__ponto:disabled { cursor: default; }
/* O ponto tem 32 px de desenho e 48 de toque (Fitts, 27/09/2026). */
.stepper__ponto { position: relative; }
.stepper__ponto::before { content: ''; position: absolute; inset: -8px; border-radius: 50%; }
.stepper__ponto:not(:disabled):active { scale: .92; }
.stepper__ponto-dentro { width: .75rem; height: .75rem; border-radius: 50%; background: var(--on-accent); }
.stepper__visto { width: 1rem; height: 1rem; }
.stepper__visto path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: stepper-visto .3s ease-out .1s forwards;
}
@keyframes stepper-visto { to { stroke-dashoffset: 0; } }
.stepper__elo {
  position: relative;
  flex: 1;
  height: 2px;
  margin: 0 .5rem;
  border-radius: 2px;
  overflow: hidden;
  background: color-mix(in srgb, var(--text) 14%, transparent);
}
.stepper__elo-cheio {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--accent);
  transition: width .4s ease;
}
.stepper__elo.is-cheio .stepper__elo-cheio { width: 100%; }
/* A caixa do conteudo esconde o que sobra dos lados enquanto um passo
   sai e o outro entra, e acompanha a altura do passo novo. */
.stepper__conteudo {
  position: relative;
  overflow: hidden;
  transition: height .4s cubic-bezier(.22, 1, .36, 1);
}
.stepper__passo { position: absolute; top: 0; left: 0; right: 0; padding: 0 20px 4px; }
.stepper__pe {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 28px 20px 20px;
}
.stepper__pe--so-seguir { justify-content: flex-end; }
.stepper__voltar {
  padding: 10px 6px;
  color: var(--text-3);
  font-weight: 500;
  -webkit-tap-highlight-color: transparent;
}
.stepper__voltar:active { color: var(--text); }
.stepper__seguir {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 22px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  letter-spacing: -.01em;
  -webkit-tap-highlight-color: transparent;
  transition: scale .16s cubic-bezier(.23, 1, .32, 1), opacity .2s ease;
}
.stepper__seguir:active { scale: .97; }
.stepper__seguir:disabled { opacity: .5; }
@media (prefers-reduced-motion: reduce) {
  .stepper__conteudo, .stepper__elo-cheio, .stepper__ponto { transition: none; }
  .stepper__visto path { animation: none; stroke-dashoffset: 0; }
}
/* o passo de Recalibrar: pergunta, explicacao e a resposta */
.recal-passo__titulo { font-size: var(--fs-h3); font-weight: 600; line-height: 1.2; }
.recal-add { display: flex; flex-direction: column; }
.recal-texto {
  width: 100%;
  min-height: 84px;
  resize: none;
  font: inherit;
  font-size: var(--fs-body);
  line-height: 1.45;
  color: var(--text);
  background: none;
  border: 0;
  padding: 2px 0;
}

/* ============================================================
   A APRESENTACAO DO ZENTRY (js/tour.js)
   ------------------------------------------------------------
   O tour de nove passos. Duas pecas, e a primeira e a que faz a coisa
   toda funcionar:

   · `.tour__foco` e um retangulo VAZIO com uma sombra de 100vmax. O
     escuro da tela e a SOMBRA dele; o buraco e a caixa. Isso evita ter
     que levantar o elemento real com z-index, coisa que nao funciona
     pra quem esta dentro de um contexto de empilhamento (o `.card` tem
     `isolation`, a `.pbar` e fixa). O elemento fica onde estava, com o
     CSS dele intacto, e aparece pelo buraco.

     O escuro e .62 e nao os .42 do scrim das folhas: uma folha so
     precisa separar duas camadas, e aqui o contraste entre o que esta
     aceso e o resto E a mensagem.

     As transicoes de left/top/width/height sao o que faz o buraco
     DESLIZAR de um elemento pro outro. Com `prefers-reduced-motion` o
     `--dur` do tokens.css ja vale .01ms e ele pula direto, sem regra a
     mais aqui.

   · `.tour__cartao` e a fala. Centralizado por left/right/auto, e nao
     por `translateX(-50%)`, pra deixar o `transform` livre pra entrada.
     Quem manda no `top` e o JS, que mede onde sobra espaco.

   z-index 84: acima da tab bar (40) e da folha de instalar (80), abaixo
   da lateral (85), do @ do embaixador (86) e do toast (90) — um "salvo"
   ainda precisa ser lido por cima de tudo.
   ============================================================ */
.tour {
  position: fixed;
  inset: 0;
  z-index: 84;
}

/* A camada que come o toque. Sem ela, o dedo cairia no botao real que
   esta aceso no buraco e a pessoa sairia do tour no meio do passo. Ela
   tambem e o "toque em qualquer lugar pra seguir". */
.tour__toque { position: absolute; inset: 0; }

.tour__foco {
  position: fixed;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  border: 1.5px solid var(--accent);
  border-radius: 14px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .62);
  opacity: 0;
  pointer-events: none;
  transition:
    left var(--dur) var(--ease),
    top var(--dur) var(--ease),
    width var(--dur) var(--ease),
    height var(--dur) var(--ease),
    opacity var(--dur) var(--ease);
}

.tour__cartao {
  position: fixed;
  top: 50%;
  left: 12px;
  right: 12px;
  margin: 0 auto;
  max-width: 430px;
  padding: var(--gap-md);
  border-radius: var(--r-card);
  border: 1px solid var(--border-soft);
  background: var(--bg-elev);
  box-shadow: 0 14px 44px rgba(0, 0, 0, .28);
  opacity: 0;
  transform: translateY(8px);
  transition:
    top var(--dur) var(--ease),
    opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}
.tour__cartao:focus { outline: none; }

.tour__pe {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  margin-top: var(--gap-md);
}
/* A contagem empurra os dois botoes pra direita, que e onde o polegar
   esta. Ela e a unica coisa do cartao que nao e fala. */
.tour__conta { margin-right: auto; }

.tour.is-on .tour__foco,
.tour.is-on .tour__cartao { opacity: 1; }
.tour.is-on .tour__cartao { transform: none; }

/* Trocando de passo: as duas pecas somem juntas e voltam ja no lugar
   certo. Sem isto, o buraco atravessaria a tela apontando pro nada
   enquanto a tela de destino ainda esta pintando. */
.tour--indo .tour__foco { opacity: 0; }
.tour--indo .tour__cartao { opacity: 0; transform: translateY(8px); }

/* Passo sem alvo (o ultimo, e qualquer um cujo elemento nao exista
   naquele dia): o buraco vira um ponto no meio da tela, a sombra dele
   continua cobrindo tudo e a borda some — senao sobraria um pontinho
   verde no vazio. */
.tour--sem-foco .tour__foco { border-color: transparent; }

/* ---------- a tabela que so o leitor de tela ve ----------
   `overflow: hidden` com 1px de altura nao corta TABELA: ali altura e
   minimo e overflow nao vale. Por isso a marcacao poe uma DIV com esta
   classe POR FORA da tabela (js/paineis/graficos.js e js/saldo.js): a div corta de
   verdade. Se algum dia a classe voltar pro <table>, a pagina cresce
   centenas de pixels de vazio sem nada aparecer na tela. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* ============================================================
   O cartao do numero e da linha que se arrasta (js/saldo.js)
   ------------------------------------------------------------
   Mora aqui, e nao no css/paineis.css, porque o cartao e do APP e dos
   PAINEIS: ele abre a Hoje (os sete dias da semana) e as telas de
   Crescimento e Runway do /admin. O app nao carrega o paineis.css.

   Duas partes: o numero com a variacao, e a linha que se arrasta.

   Em 22/09/2026 saiu daqui a faixa de cima com as cinco gotas de goma
   que se juntavam ao puxar: o dono pediu a atualizacao automatica, e
   sem a puxada a goma nao tinha o que comunicar. Junto foram o
   `padding-top` que abria a faixa, o filtro `feGaussianBlur` e o giro.
   ============================================================ */

/* ---------- o cartao ---------- */
.bal-cartao {
  /* a mesma superficie do `.gcard` e do bento: e um cartao do painel,
     e nao uma peca com cara propria */
  background: var(--surface);
  border-radius: var(--r-card);
  padding: var(--gap) var(--gap) 12px;
}
.bal-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
/* ---------- o botao ----------
   Desenhado AQUI, e nao com o `.btn` do app nem com o `.xs-btn` do
   painel: no app o `.btn` e um bloco de largura cheia, e o cartao (que
   agora abre a Hoje) ficava com o texto espremido numa coluna de 90px
   ao lado de um botao gigante. Componente que mora em dois lugares nao
   pode depender de como cada lugar desenha botao. Sem hover, como tudo
   no projeto: o retorno e o :active. */
.bal-btn {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: none;
  color: var(--text-2);
  font: inherit;
  font-size: var(--fs-xs);
  line-height: 1;
  cursor: pointer;
}
.bal-btn:active { background: var(--surface-2); }
.bal-btn:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }

/* o texto do cartao fica com a largura toda que sobra: sem o `min-width`
   o flex nunca deixa ele encolher abaixo do conteudo e o numero grande
   quebra letra a letra */
.bal-lendo { min-width: 0; flex: 1 1 auto; }

.bal-kicker {
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--text-3);
  letter-spacing: .01em;
}
.bal-valor {
  margin: 2px 0 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-stat-lg);
  line-height: var(--lh-tight);
  font-weight: 600;
  color: var(--text);
}
.bal-var {
  margin: 4px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--text-3);
}
.bal-var b { color: var(--certo-texto); font-weight: 600; }
/* ---------- a cor do que desceu ----------
   No painel, cair e dinheiro: vale a `--serie-alerta`, o amarelo que o
   dono reservou pro que SAI do caixa. No app o amarelo nao pode
   aparecer aqui — um dia de descanso com menos km que a segunda nao e
   um aviso —, e como a `--serie-alerta` so existe no css/paineis.css,
   a Hoje cai sozinha no cinza do texto. */
.bal-var.is-cai b { color: var(--serie-alerta, var(--text-2)); }
/* o ponto que esta sendo lido fica na PROPRIA linha: ele nao e parte da
   variacao, e sim a resposta de "isto aqui e qual?". Na mesma linha, o
   painel lia "+563,4% desde março  setembro", com dois meses colados
   dizendo coisas diferentes. */
.bal-var__mes { flex: 1 0 100%; color: var(--text-2); }

/* ---------- a linha ---------- */
.bal-plot {
  margin-top: 10px;
  /* arrastar pela linha e horizontal: a pagina nao rouba o gesto */
  touch-action: none;
  cursor: ew-resize;
  border-radius: 10px;
}
.bal-plot:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }
.bal-svg { display: block; width: 100%; height: auto; }
/* ---------- de quem e o verde ----------
   Nos paineis vale a `--serie-1`, a cor de serie validada no dataviz
   contra a superficie de grafico. Ela mora no css/paineis.css, que o
   APP nao carrega: na Hoje o mesmo cartao cai no `--accent`, o verde do
   app. Uma variavel que nao existe nao e erro aqui, e o segundo valor. */
.bal-linha { fill: none; stroke: var(--serie-1, var(--accent)); stroke-width: 2; stroke-linecap: round; }
/* o mes em curso e medida de um mes que ainda nao acabou */
.bal-linha--fim { stroke-dasharray: 4 4; opacity: .7; }
.bal-mira { stroke: var(--border); stroke-width: 1; }
.bal-ponto { fill: var(--serie-1, var(--accent)); stroke: var(--surface); stroke-width: 2; }
/* ---------- o eixo ----------
   Um rotulo por ponto, na largura que a linha usa: a primeira e a
   ultima marca ficam nas bordas do desenho, e nao no meio de uma
   coluna que nao existe (aqui nao ha coluna, ha ponto). O que esta
   sendo lido acende, junto com o numero grande. */
.bal-eixo {
  display: flex;
  justify-content: space-between;
  margin: 2px 10px 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.bal-eixo__i { flex: 1 1 0; text-align: center; }
.bal-eixo__i:first-child { text-align: left; }
.bal-eixo__i:last-child { text-align: right; }
.bal-eixo__i.is-lido { color: var(--certo-texto); font-weight: 600; }

.bal-pe { margin: 10px 0 0; }

@keyframes bal-area { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .bal-area { animation: none !important; }
  .bal-linha { transition: none !important; stroke-dasharray: none !important; stroke-dashoffset: 0 !important; }
}

/* ============================================================
   O cartao que empurra (0077, js/cartao-do-dia.js)
   ------------------------------------------------------------
   Um cartao comum de acao, com tres ajustes:
   · o cabecalho alinha pelo TOPO, e nao pela linha de base: com o x
     de 40px do lado, `baseline` subia o titulo (o mesmo defeito do
     botao do painel, 21/09/2026);
   · a logo do Zentry veste a cor do botao: a padrao e o verde do
     acento, e no botao cheio ela sumiria no proprio fundo;
   · a saida e so opacidade, na mesma --dur do resto do app.
   ============================================================ */
.cartao-dia { transition: opacity var(--dur) var(--ease); }
.cartao-dia--sai { opacity: 0; }
.cartao-dia .card__head { align-items: flex-start; }
.cartao-dia__fechar { flex: none; margin: -6px -8px -8px 0; color: var(--text-2); }
.cartao-dia__fechar svg { width: 20px; height: 20px; }
.cartao-dia__texto { padding: 10px 12px; }
.cartao-dia__zentry .zentry-logo { color: currentColor; margin-right: .35em; vertical-align: -.18em; }

@media (prefers-reduced-motion: reduce) {
  .cartao-dia { transition: none; }
}

/* ---------- o cartao citado na assinatura ----------
   Quem veio do "Entender com o Zentry" ve, antes do hero, a pergunta
   que ficou esperando. */
.pro-citado { margin-bottom: var(--gap); }
.pro-citado .card__title::before { content: '\201C'; }
.pro-citado .card__title::after  { content: '\201D'; }

/* ---------- a pergunta do Zentry (0078) ----------
   O mesmo lugar do cartao que empurra, sem cor de estado: ela pergunta,
   nao avisa. `hidden` precisa ser dito aqui porque `.par` e flex, e
   display de autor ganha do [hidden] do navegador; sem a segunda regra
   o pe vazio deixaria 18px de nada embaixo das opcoes. */
.cartao-dia__quem { display: inline-flex; align-items: center; color: var(--text-2); }
.cartao-dia__quem .zentry-logo { height: 1.1em; width: auto; margin-right: .35em; vertical-align: 0; }
.cartao-dia__opcoes { padding: 8px 8px 10px; }
/* A replica do cartao usa o MESMO fio verde da replica do componente
   (js/pergunta.js): e o mesmo gesto — a IA respondendo no quadro do
   toque —, e gesto igual com desenho diferente e o que faz ninguem
   reconhecer nenhum dos dois. A estrutura dos dois blocos continua
   diferente de proposito: aqui o titulo e o fechar moram no `card__head`,
   porque este cartao pode ser dispensado e o da tela do porque nao. */
.cartao-dia__replica {
  padding: 2px 12px 10px;
  margin-left: 12px;
  border-left: 2px solid var(--accent-line);
}
.cartao-dia__leve[hidden] { display: none; }
.cartao-dia--pergunta .card__foot:has(> .cartao-dia__leve[hidden]) { display: none; }


/* ---------- aprendi algo novo (0079) ----------
   O pe tem duas linhas: as respostas e o link pra tela inteira. As
   respostas somem depois do toque (a replica fica no lugar), e `.par`
   e flex, entao o [hidden] precisa de regra propria. */
.cartao-dia__memoria-pe { display: grid; gap: 10px; width: 100%; }
.cartao-dia__respostas[hidden] { display: none; }
.cartao-dia__tudo { justify-self: start; }

/* ---------- O que o Zentry sabe sobre voce (0079) ---------- */
.memoria__lista { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gap); }
.memoria__item {
  padding: 14px 16px;
  border-radius: var(--r-card);
  background: var(--surface);
  transition: opacity var(--dur) var(--ease);
}
.memoria__item--saindo { opacity: .4; }
.memoria__item--corrigida { background: transparent; box-shadow: inset 0 0 0 1px var(--border); }
.memoria__novo { margin-bottom: 4px; }
.memoria__detalhe { margin-top: 6px; }
.memoria__acoes { display: flex; flex-wrap: wrap; gap: var(--gap-sm); margin-top: 12px; }
.memoria__acoes .pill { min-height: 36px; padding: 0 14px; }
.memoria__porque .zentry-logo { color: currentColor; margin-right: .35em; vertical-align: -.18em; }
.memoria__opcoes { margin-top: 10px; }
.memoria__opcoes[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .memoria__item { transition: none; }
}

/* ============================================================
   O Zentry ao vivo na corrida (23/09/2026)
   ------------------------------------------------------------
   A faixa: a ultima coisa que ele disse ou viu, fixa em cima do mapa.
   Flutua sobre o mapa, entao a sombra e legitima (a mesma do botao de
   recentralizar). Duas linhas no maximo: e leitura de relance, de quem
   esta correndo, e a frase inteira ja foi falada.
   ============================================================ */
.corrida-zentry {
  position: absolute;
  left: 12px;
  right: 12px;
  top: 12px;
  z-index: 3;
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 10px 14px;
  border-radius: var(--r-lg);
  background: var(--bg);
  color: var(--text);
  font-size: var(--fs-sm);
  line-height: 1.35;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .16), inset 0 0 0 1px var(--border-soft);
}
.corrida-zentry[hidden] { display: none; }
/* ---------- o treino guiado na faixa (11/10/2026) ----------
   A faixa ganhou andares: o bloco de agora em cima ("Correr · 0:42" e
   "3 de 8"), a ultima fala embaixo, e no maximo um botao. Cada andar
   some sozinho quando nao tem o que dizer, entao o treino sem guia ve a
   mesma faixa de uma linha de antes. */
.corrida-zentry__fala { display: flex; align-items: flex-start; gap: 8px; }
.corrida-zentry__fala[hidden],
.corrida-bloco[hidden],
.corrida-zentry__acao[hidden] { display: none; }
.corrida-bloco {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
/* O que fazer agora e a maior coisa da faixa: e leitura de relance, de
   quem esta correndo. Algarismos de largura fixa, pra contagem nao
   empurrar a palavra a cada segundo. */
.corrida-bloco__agora {
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.corrida-bloco__n { flex: none; color: var(--text-3); }
.corrida-zentry__acao { justify-self: start; min-height: 36px; padding: 0 14px; }
/* "Por que?" e "Falar", lado a lado. A fileira some quando os dois somem,
   pra faixa nao guardar um andar vazio. */
.corrida-zentry__acoes { display: flex; flex-wrap: wrap; gap: 8px; }
.corrida-zentry__acoes:not(:has(.corrida-zentry__acao:not([hidden]))) { display: none; }
/* O microfone aberto: o botao acende na cor da marca enquanto ouve, e
   e esse o aviso de que ha escuta (junto do indicador do sistema). */
.corrida-zentry__acao.e-ouvindo { border-color: var(--accent-texto); color: var(--accent-texto); }
.corrida-zentry__acao:disabled { opacity: .6; }
/* O porque e uma explicacao, e nao um aviso: ele cabe inteiro. */
#zentry-vivo-texto.e-longa { -webkit-line-clamp: 6; }
.corrida-zentry__logo { flex: none; line-height: 0; padding-top: 1px; }
.corrida-zentry__logo .zentry-logo { height: 16px; width: auto; margin: 0; }
#zentry-vivo-texto {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Com a faixa no alto, o "Centralizar" desce pra baixo dela: os dois no
   mesmo canto se tapariam. */
.mapa-area:has(.corrida-zentry:not([hidden])) .mapa__recentrar { top: 72px; }
/* A faixa do treino guiado e mais alta: cada andar a mais empurra o
   botao o tanto que ele ocupa (31px do bloco, 44px do botao). */
.mapa-area:has(.corrida-bloco:not([hidden])) .mapa__recentrar { top: 104px; }
.mapa-area:has(.corrida-zentry__acao:not([hidden])) .mapa__recentrar { top: 116px; }
.mapa-area:has(.corrida-bloco:not([hidden])):has(.corrida-zentry__acao:not([hidden])) .mapa__recentrar { top: 148px; }
.mapa-area:has(#zentry-vivo-texto.e-longa) .mapa__recentrar { top: 188px; }

/* O mudo, no topo. Mesmo alvo de 40px de todo icon-btn do app. */
.corrida-voz { flex: none; margin-right: 6px; color: var(--text-2); }
.corrida-voz[aria-pressed="true"] { color: var(--text-3); }

.corrida-aviso { padding: var(--gap-xs) var(--pad) 0; }
.corrida-aviso[hidden] { display: none; }

/* O anel onde o circuito fecha: o destino, e nao a pessoa. Vazado e na
   cor de acento, pra nao ser confundido com o ponto cheio de "estou
   aqui"; os metros ficam embaixo, numa pastilha. */
.gps-fecho { display: grid; justify-items: center; gap: 4px; pointer-events: none; }
.gps-fecho__anel {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.gps-fecho__m {
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--bg);
  color: var(--text);
  font-size: 11px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .16);
  white-space: nowrap;
}

/* ---------- a pergunta da Tryzen Intelligence (js/pergunta.js) ----------
   O microformato de 2 toques, pedido do dono em 26/09/2026: a mesma cara
   onde quer que a IA pergunte. A moldura e a marca mais o nome em mono,
   igual a toda fala dela no app — e e ela que faz o gesto ser
   reconhecido antes de a frase ser lida.

   Sem fundo, sem borda e sem sombra de proposito: este bloco mora DENTRO
   de um cartao (a Hoje) ou de uma secao (a tela do porque), e cada um
   deles ja tem o seu. Uma caixa aqui viraria caixa dentro de caixa. */
.pergunta__quem {
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tr-mono);
  color: var(--text-3);
  margin-bottom: 6px;
}
.pergunta__titulo {
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.25;
  color: var(--text);
}
.pergunta__texto { margin-top: var(--gap-sm); }
.pergunta__opcoes { margin-top: var(--gap-md); }
.pergunta__opcoes[hidden] { display: none; }
/* A replica entra no lugar dos chips, no mesmo quadro do toque. O fio a
   esquerda diz que ela e RESPOSTA ao que acabou de ser tocado, e nao
   mais um paragrafo da tela. */
.pergunta__replica {
  margin-top: var(--gap-md);
  padding-left: 12px;
  border-left: 2px solid var(--accent-line);
}

/* ---------- escolher o idioma (js/escolher-idioma.js) ----------
   O `<select>` nativo fica INVISIVEL por cima do desenho: quem toca
   abre o seletor do proprio sistema. 16px no select porque o iPhone
   amplia a tela ao focar campo com letra menor que isso. */
.idioma-select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  font-size: 16px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}
.idioma-linha { position: relative; }
.idioma-pilula {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: 999px;
  font-size: var(--fs-sm);
  line-height: 1;
}
.idioma-pilula .ic { width: 18px; height: 18px; flex: none; }
/* o anel de foco do teclado aparece na pilula, ja que o select e invisivel */
.idioma-pilula:focus-within,
.idioma-linha:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
/* rotulo da aba em outro idioma: centrado e sem estourar a coluna
   ("Aujourd’hui", "マイページ") */
.tabbar__item span { text-align: center; max-width: 100%; padding: 0 2px; line-height: 1.15; }

/* ---------- a etiqueta de estado (js/ui.js · etiqueta) ----------
   Uma palavra curta com o estado do dia (Feito, Pulou, Hoje, Descanso,
   Doeu), no lugar de uma frase: le-se sem parar pra ler. Sem contorno
   (28/09/2026): o app separa as coisas pelo tom, nao por traco. */
.etiqueta {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 2px 10px;
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .01em;
  white-space: nowrap;
}
.etiqueta--feito    { background: var(--certo); color: var(--on-accent); }
.etiqueta--pulou    { background: var(--warn);  color: #3D2C00; }
.etiqueta--hoje     { background: var(--text);  color: var(--bg); }
.etiqueta--descanso { background: var(--surface-2); color: var(--text-2); }
.etiqueta--doeu     { background: #C4271C; color: #FFFFFF; }
.etiqueta + .etiqueta { margin-left: 6px; }

/* ---------- o botao que sobe (js/acao-sobe.js) ----------
   Preso na borda de baixo, acima da tab bar (40) e abaixo das folhas
   (80). Fora da vista ate existir resposta; sobe em .2s. */
.acao-sobe {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  padding: 12px var(--pad) calc(12px + var(--safe-bottom));
  background: var(--bg);
  box-shadow: 0 -1px 0 var(--border-soft);
  transform: translateY(110%);
  transition: transform .2s cubic-bezier(.2, .8, .3, 1);
}
.acao-sobe.is-on { transform: none; }
.acao-sobe__btn { width: 100%; min-height: 56px; font-size: var(--fs-lg); }
.acao-sobe__sec { display: block; margin: 8px auto 0; min-height: 44px; }
/* a tela que tem o botao reserva o espaco dele no fim, senao a ultima
   resposta fica embaixo do botao quando ele sobe */
.screen:has([data-acao-sobe]) { padding-bottom: calc(112px + var(--safe-bottom)); }
@media (prefers-reduced-motion: reduce) { .acao-sobe { transition: none; } }

/* ---------- o teclado nao pode esconder o botao de seguir (19/10/2026) ----------
   Relato do dono: no iPhone, digitando e-mail e senha (e no quiz), o
   teclado cobria o Entrar e o Continuar e nao havia como passar de
   etapa. O app sobe com o teclado em `resize: none`: a tela NAO encolhe,
   o teclado cobre os ultimos `--teclado` pixels dela (js/teclado.js), e
   como a tela tem a altura exata da janela nao sobrava rolagem pra
   chegar no botao.
   Duas respostas: o botao que sobe passa a morar logo acima do teclado,
   e toda tela (menos a conversa, que tem a conta dela em screens.css)
   ganha embaixo a altura do teclado, pra rolar ate o fim do formulario.
   Quem rola sozinho ate o botao, no foco, e o revelarFoco do teclado.js. */
body.com-teclado .acao-sobe { bottom: var(--teclado); padding-bottom: 12px; }
body.com-teclado .screen:not(.screen--travada) { padding-bottom: calc(var(--teclado) + 24px); }
body.com-teclado .screen:not(.screen--travada):has([data-acao-sobe]) { padding-bottom: calc(var(--teclado) + 112px); }

/* Erro de campo em VERMELHO (27/09/2026). Era o cinza de apoio: a pessoa
   lia "precisa de pelo menos um dia" como nota, nao como o motivo de o
   botao nao andar (Nielsen: erro claro, dizendo como resolver). */
#q-num-erro:not(:empty), #erro-campo:not(:empty) { color: var(--risco-texto); font-weight: 600; }
/* a data e a etiqueta dividem a linha de cima do bloco; se o idioma nao
   couber (alemao, frances), a etiqueta desce pra linha de baixo */
.bento__topo { flex-wrap: wrap; row-gap: 4px; }
.bento__acao .etiqueta + .etiqueta { margin-left: 4px; }

/* ---------- o <details> sem triangulo (02/10/2026) ----------
   Pedido do dono. Fechado: tres pontos. Aberto: um traco. O marcador
   nativo sai pelos dois caminhos que os navegadores conhecem, porque um
   so nao cobre todos. */
.sumario { display: flex; align-items: center; gap: 10px; min-height: 44px; cursor: pointer; font-weight: 600; }
.sumario, .sumario::-webkit-details-marker { list-style: none; }
.sumario::-webkit-details-marker { display: none; }
.sumario__sinal { display: flex; flex: none; color: var(--text-3); }
.sumario__sinal .sinal-traco { display: none; }
details[open] > .sumario .sinal-pontos { display: none; }
details[open] > .sumario .sinal-traco { display: block; }
/* quem fala e a Tryzen: o corredor na altura da palavra ao lado, igual
   ao kicker do cartao da Hoje */
.sumario__marca { display: inline-flex; align-items: center; flex: none; color: var(--text-2); }
.sumario__marca .zentry-logo { height: 1.1em; width: auto; margin: 0; vertical-align: 0; }

/* ---------- Meu treinador (0094) ----------
   O que o treinador vai ver, numa lista curta antes do Aceitar. */
.treinador__lista { margin: 8px 0 0; padding-left: 1.1em; display: grid; gap: 6px; list-style: disc; }
/* a foto do treinador (0147): a que ele pos no painel, ou as iniciais */
.treinador__quem { display: flex; align-items: center; gap: 14px; min-width: 0; }
.treinador__quem .h2 { min-width: 0; overflow-wrap: anywhere; }
.treinador__foto { flex: none; width: 56px; height: 56px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--surface-2); color: var(--text); font-weight: 600; font-size: 18px; }
.treinador__foto img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- Seja treinador (0096) ---------- */
.seja__codigo-valor { font-size: 40px; line-height: 1.1; letter-spacing: .14em; margin-top: 4px; }
.seja__acoes { display: grid; gap: 10px; }
/* o plano do Tryzen Coach comprado no app (16/10/2026): o mesmo cartao
   suave dos planos do painel, o preco escrito pela loja */
.seja-coach__planos { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-top: 8px; }
.seja-coach__plano { all: unset; box-sizing: border-box; display: grid; gap: 2px; padding: 14px 16px; border-radius: 14px; cursor: pointer;
  background: color-mix(in srgb, var(--text) 4.5%, transparent); }
.seja-coach__plano:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.seja-coach__plano[disabled] { cursor: default; opacity: .6; }
.seja-coach__plano.is-atual { opacity: 1; box-shadow: inset 0 0 0 1.5px var(--accent); }
.seja-coach__nome { font-weight: 600; color: var(--text); }
.seja-coach__preco { margin-top: 6px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }

/* ============================================================
   O mapa da semana (0104, 08/10/2026)
   ------------------------------------------------------------
   O raciocinio do motor desenhado (js/mapa-mental.js). Os nos sao o
   recuo da bandeja, em --bg; o SVG e so o que liga um no ao outro, com
   o traco da casa (1,6, ponta redonda) que nao engrossa quando o
   desenho estica. Verde so no que lidera e no que acontece.
   ============================================================ */
.mapa { display: grid; padding: 6px; }
.mapa__no {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px 12px;
  border-radius: var(--r-sm);
  background: var(--bg);
}
.mapa__no.is-lider { background: var(--certo-fundo); }
.mapa__no-corpo { min-width: 0; flex: 1; }
.mapa__ic { flex: none; display: flex; color: var(--text-3); }
.mapa__ic svg { width: 19px; height: 19px; }
.is-lider > .mapa__ic { color: var(--certo-texto); }
.mapa__rot {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-sm);
  letter-spacing: var(--tr-mono);
  color: var(--text-2);
}
.mapa__val { margin-top: 2px; font-size: var(--fs-sm); font-weight: 600; }
.mapa__nota { margin: 4px 0 0; font-size: var(--fs-sm); line-height: 1.35; color: var(--text-2); }
.mapa__sinais { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 4px; font-size: var(--fs-sm); line-height: 1.35; color: var(--text-2); }

/* os fios: o ramo que abre e fecha nas tres hipoteses, e o fio reto */
.mapa__ramo { display: block; width: 100%; height: 26px; overflow: visible; }
.mapa__fio { display: block; width: 10px; height: 22px; margin: 0 auto; overflow: visible; }
.mapa__ramo path, .mapa__fio path {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.6;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.mapa__ramo path.is-lider, .mapa__fio path.is-lider { stroke: var(--accent); stroke-width: 2; }

/* as tres hipoteses de carga, lado a lado */
.mapa__tres { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.mapa__hip {
  display: grid;
  justify-items: center;
  gap: 4px;
  padding: 10px 10px 12px;
  border-radius: var(--r-sm);
  background: var(--bg);
  text-align: center;
}
.mapa__hip.is-lider { background: var(--certo-fundo); }
.mapa__hip-rot { font-size: var(--fs-xs); line-height: 1.2; color: var(--text-2); }
.mapa__hip-pct { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }
.mapa__hip.is-lider .mapa__hip-pct { color: var(--certo-texto); }

/* a barra: uma linha grossa de ponta redonda, que estica sem deformar */
.mapa__barra { display: block; width: 100%; height: 8px; overflow: visible; }
.mapa__barra line { stroke-width: 6; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.mapa__trilho { stroke: var(--surface-2); fill: none; }
.mapa__cheio { stroke: var(--feito); fill: none; }
.is-lider .mapa__cheio, .mapa__cheio.is-lider { stroke: var(--accent); }
.mapa__hip .mapa__barra { width: calc(100% - 6px); margin-top: 4px; }

/* barras: as tres hipoteses em linha, e o anel do que falta medir */
.mapa--barras { gap: 4px; }
.mapa__linha {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 11px;
  row-gap: 8px;
  padding: 11px 15px 13px 12px;
  border-radius: var(--r-sm);
  background: var(--bg);
}
.mapa__linha .mapa__barra { grid-column: 2 / 4; }
.mapa__linha-rot { font-size: var(--fs-sm); color: var(--text-2); }
.mapa__linha-pct { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
.mapa__linha.is-lider .mapa__linha-rot { color: var(--text); font-weight: 600; }
.mapa__linha.is-lider .mapa__linha-pct { color: var(--certo-texto); }
.mapa__falta {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: var(--bg);
}
.mapa__anel { flex: none; width: 46px; height: 46px; }
.mapa__anel circle { fill: none; stroke-width: 4; }
.mapa__anel .mapa__cheio { stroke: var(--accent); stroke-linecap: round; }
.mapa__anel text { font-family: var(--font-mono); font-size: 11px; font-weight: 600; fill: var(--text); }

/* cascata: o nivel recente, o que cada razao puxou, e a previsao */
.mapa--cascata { padding: 4px; }
/* rotulo e valor na linha de cima, a barra de ponta a ponta embaixo:
   todas as barras na mesma regua, que e o que faz a cascata ler como
   cascata (cada degrau comeca onde o anterior parou) */
.mapa__cas {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: 10px;
  row-gap: 7px;
  padding: 10px 15px 11px 12px;
  background: var(--bg);
}
.mapa__cas > .mapa__barra, .mapa__cas-barra { grid-row: 2; grid-column: 1 / -1; }
.mapa__cas-val { grid-row: 1; grid-column: 2; }
.mapa__cas:first-child { border-radius: var(--r-sm) var(--r-sm) 0 0; }
.mapa__cas + .mapa__cas { box-shadow: 0 -1px 0 var(--border-soft); }
.mapa__cas--fim { border-radius: 0 0 var(--r-sm) var(--r-sm); }
.mapa__cas-rot { font-size: var(--fs-sm); line-height: 1.25; color: var(--text-2); }
.mapa__cas-val { min-width: 4.6em; text-align: right; white-space: nowrap; font-size: var(--fs-sm); font-weight: 500; font-variant-numeric: tabular-nums; }
.mapa__cas--fim .mapa__cas-rot { color: var(--text); font-weight: 600; font-size: var(--fs-sm); }
.mapa__cas--fim .mapa__cas-val { font-weight: 700; color: var(--certo-texto); }
.mapa__barra--cascata .mapa__trilho { stroke: var(--surface); }
.mapa__cheio.is-base { stroke: var(--feito); }
.mapa__cheio.is-sobe { stroke: var(--certo-fraco); }
.mapa__cheio.is-desce { stroke: var(--text-3); }
.mapa__cas-barra { position: relative; display: block; }
.mapa__marca {
  position: absolute;
  top: -6px;
  bottom: -6px;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--text);
}
.mapa__marca-mini { display: inline-block; width: 2px; height: 12px; margin-right: 8px; vertical-align: -1px; border-radius: 1px; background: var(--text); }
.mapa__legenda { margin: 0; padding: 10px 12px 4px; }
/* 0106: as familias na Hoje, sem as barras */
.mapa--curta { padding: 0; margin-bottom: 8px; }
.mapa--curta .mapa__cas { padding: 7px 12px; }

/* faixa e regua: onde a semana deve cair, e onde o plano cai */
.mapa--faixa { padding: 10px 12px 6px; background: var(--bg); border-radius: var(--r-sm); margin: 4px; }
.mapa--faixa .mapa__legenda { padding: 8px 0 0; }
.mapa__regua { display: block; width: 100%; height: auto; overflow: visible; }
.mapa__eixo { fill: none; stroke: var(--border); stroke-width: 1.6; stroke-linecap: round; }
.mapa__banda { fill: var(--certo-fundo); stroke: var(--certo-fio); stroke-width: 1.2; }
.mapa__centro { fill: var(--accent); }
.mapa__origem { fill: var(--bg); stroke: var(--text-3); stroke-width: 1.6; }
.mapa__trajeto { fill: none; stroke: var(--text-3); stroke-width: 1.6; stroke-linecap: round; stroke-dasharray: 2 4; }
.mapa__plano { fill: none; stroke: var(--text); stroke-width: 2; stroke-linecap: round; }
.mapa__plano-seta { fill: var(--text); }
.mapa__regua text { font-family: var(--font-mono); font-size: 14px; fill: var(--text-2); }
.mapa__regua text.is-lider { fill: var(--certo-texto); font-weight: 600; }
.mapa__regua--mini { padding: 6px 8px 2px; }

/* o placar: os dois motores, o erro de cada um e quem fala */
.mapa-cartao .card__foot { padding-top: 10px; }
/* o mapa limpo do Plano (09/10/2026): sem o contorno de fora, e o cartao
   encosta na borda da dobra que ja o contem */
.mapa-cartao--limpo, .mapa-cartao--limpo .mapa { box-shadow: none; }
.mapa-cartao--limpo { padding-left: 0; padding-right: 0; }
.mapa-cartao--limpo .mapa__hip { padding: 12px 8px; }
.mapa-cartao--limpo .mapa__fio { height: 18px; }
.mapa__placar { display: grid; gap: 8px; width: 100%; }
.mapa__motores { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.mapa__motor {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 8px;
  row-gap: 1px;
  min-height: 44px;
  padding: 8px 12px;
  border-radius: var(--r-sm);
  background: var(--bg);
  font-size: var(--fs-sm);
}
.mapa__motor.is-lider { background: var(--certo-fundo); font-weight: 600; }
.mapa__ponto { width: 7px; height: 7px; border-radius: 50%; background: var(--feito); }
.mapa__motor.is-lider .mapa__ponto { background: var(--accent); }
.mapa__erro { grid-column: 2; font-family: var(--font-mono); font-size: var(--fs-mono-sm); font-weight: 400; color: var(--text-3); }
.mapa__regra { margin: 0; font-size: var(--fs-xs); line-height: 1.35; color: var(--text-3); }

/* a pilha das tres hipoteses (a faixa da Hoje e a pergunta) */
.mapa__pilha { padding: 10px 12px 8px; }
.mapa__pilha-trilho { height: 10px; border-radius: 5px; overflow: hidden; }
.mapa__pilha-trilho svg { display: block; width: 100%; height: 100%; }
.mapa__seg { fill: var(--feito); transition: x .55s var(--mola-pilula), width .55s var(--mola-pilula), fill var(--dur) var(--ease); }
.mapa__seg.is-lider { fill: var(--accent); }
.mapa__pilha-legenda { display: flex; justify-content: space-between; gap: 8px; margin-top: 8px; font-size: var(--fs-xs); color: var(--text-2); }
.mapa__pilha-legenda b { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.mapa__pilha-legenda .is-lider, .mapa__pilha-legenda .is-lider b { color: var(--certo-texto); }
.mapa__pilha--pergunta { padding: 4px 12px 4px; }
.mapa__pilha.is-andou .mapa__pilha-legenda b { display: inline-block; animation: mapa-pulo var(--mola-pulo-dur) var(--mola-pulo); }

/* a faixa da Hoje e um cartao inteiro que leva pro mapa */
.mapa-hoje .card__head { align-items: center; }
.mapa-hoje__seta { flex: none; display: flex; color: var(--text-3); }
.mapa-hoje__seta svg { width: 18px; height: 18px; }
.mapa-hoje { transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease); }
.mapa-hoje:active { transform: scale(.985); opacity: .9; }

/* ---------- o traco se desenhando (resposta ao toque) ---------- */
.mapa-cartao.is-vivo .mapa__no,
.mapa-cartao.is-vivo .mapa__hip,
.mapa-cartao.is-vivo .mapa__linha,
.mapa-cartao.is-vivo .mapa__falta,
.mapa-cartao.is-vivo .mapa__cas { animation: mapa-no .42s var(--ease) both; }
.mapa-cartao.is-vivo .mapa__ramo path,
.mapa-cartao.is-vivo .mapa__fio path,
.mapa-cartao.is-vivo .mapa__eixo {
  stroke-dasharray: 1;
  animation: mapa-traco .6s var(--ease) .12s both;
}
.mapa-cartao.is-vivo .mapa__ramo + .mapa__tres .mapa__hip,
.mapa-cartao.is-vivo .mapa__ramo + .mapa__no,
.mapa-cartao.is-vivo .mapa__fio + .mapa__no { animation-delay: .32s; }
.mapa-cartao.is-vivo .mapa__barra .mapa__cheio {
  transform-box: fill-box;
  transform-origin: left center;
  animation: mapa-encher .9s var(--mola-trilho) .3s both;
}
.mapa-cartao.is-vivo .mapa__anel .mapa__cheio { animation: mapa-anel .9s var(--mola-trilho) .3s both; }
.mapa-cartao.is-vivo .mapa__centro { transform-box: fill-box; transform-origin: center; animation: mapa-pulo var(--mola-pulo-dur) var(--mola-pulo) .4s both; }
@keyframes mapa-no { from { opacity: 0; transform: translateY(6px); } }
@keyframes mapa-traco { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes mapa-encher { from { transform: scaleX(0); } }
@keyframes mapa-anel { from { stroke-dasharray: 0 1; } }
@keyframes mapa-pulo { from { transform: scale(.6); } }
@media (prefers-reduced-motion: reduce) {
  .mapa-cartao.is-vivo *, .mapa__pilha.is-andou * { animation: none !important; }
  .mapa__seg, .mapa-hoje { transition: none; }
}

/* De onde saiu o tamanho da semana (0104): cadastro, medido e a base,
   tres nos ligados por seta. O que ainda nao existe e so o contorno. */
.origem { display: grid; grid-template-columns: minmax(0, 1fr) 18px minmax(0, 1fr) 18px minmax(0, 1fr); align-items: center; padding: 6px; }
.origem__no {
  display: grid;
  gap: 3px;
  padding: 10px 10px 11px;
  border-radius: var(--r-sm);
  background: var(--bg);
  text-align: center;
  min-height: 70px;
  align-content: center;
}
.origem__no.is-vazio { background: transparent; box-shadow: inset 0 0 0 1px var(--border); }
.origem__no.is-lider { background: var(--certo-fundo); }
.origem__rot { font-size: var(--fs-xs); line-height: 1.2; color: var(--text-2); }
.origem__val { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }
.origem__no.is-vazio .origem__val { color: var(--text-3); }
.origem__no.is-lider .origem__val { color: var(--certo-texto); }
.origem__seta { width: 18px; height: 18px; color: var(--border); }
.origem__seta path { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.origem__frase { margin: 0; padding: 6px 10px 8px; font-size: var(--fs-sm); line-height: 1.4; }
.origem__frase + .origem__frase { padding-top: 0; }
.cartao-dia__motor { margin-left: .35em; color: var(--text-3); }
.mapa__mudou { margin: 0; padding: 0 12px 6px; font-family: var(--font-mono); font-size: var(--fs-mono-sm); font-weight: 600; color: var(--certo-texto); }
.mapa__mudou[hidden] { display: none; }

/* ---------- o futuro (0105, 08/10/2026) ----------
   No lugar do nome do motor: o km que a semana deve fechar e o ritmo
   leve de hoje ate daqui a 4 a 8 semanas, dois nos ligados por seta. */
.futuro { display: grid; gap: 6px; width: 100%; }
.futuro__linha {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 44px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  background: var(--bg);
  font-size: var(--fs-sm);
}
.futuro__rot { display: flex; align-items: center; gap: 11px; color: var(--text-2); font-size: var(--fs-sm); }
.futuro__val { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--certo-texto); white-space: nowrap; }
.futuro__ritmo { display: grid; gap: 8px; padding: 10px 12px; border-radius: var(--r-sm); background: var(--bg); }
.futuro__pontes { display: grid; grid-template-columns: minmax(0, 1fr) 18px minmax(0, 1fr); align-items: center; gap: 6px; }
.futuro__no { display: grid; gap: 2px; padding: 8px 10px; border-radius: var(--r-sm); background: var(--surface); text-align: center; }
.futuro__no small { font-size: var(--fs-xs); color: var(--text-2); }
.futuro__no b { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }
.futuro__no.is-lider { background: var(--certo-fundo); }
.futuro__no.is-lider b { color: var(--certo-texto); }
.futuro__seta { width: 18px; height: 18px; color: var(--border); }
.futuro__seta path { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.futuro__nota { margin: 0; font-size: var(--fs-xs); color: var(--text-3); }
/* dentro da bandeja cinza (a pergunta e a faixa da Hoje) o no do meio vai em --surface-2 */
.bandeja .futuro { padding: 4px 0 2px; }
.bandeja .futuro__no:not(.is-lider) { background: var(--surface); }
.mapa-cartao .card__foot .futuro { padding-top: 2px; }

/* o bloco da decisao no Plano, em mapa (0105) */
.decisao-mapa .mapa { padding: 0; }
.decisao-mapa__data { margin: 0 0 8px; font-size: var(--fs-xs); color: var(--text-3); }

/* ---------- o perfil de treino (0116, 10/10/2026) ----------
   A etiqueta "Recomendado pela Tryzen" e discreta: ela informa, quem
   marca e a pessoa. O resto da tela e feito das pecas de sempre. */
.perfil__tag { margin-top: 8px; min-height: 26px; padding: 0 10px; font-size: var(--fs-xs, 12px); }
.perfil__porque > summary { list-style: none; cursor: pointer; display: inline-flex; }
.perfil__porque > summary::-webkit-details-marker { display: none; }
.perfil-card .pastilha__valor { font-weight: 600; }

/* ---------- o campo de numero, do tamanho do numero (11/10/2026) ----------
   Pedido do dono: a caixa ia de ponta a ponta da tela, com a unidade
   ("kg", "anos", "km") la no canto direito, longe do que se digita, e o
   pedido ("Digite seu peso") saia miudo dentro dela. Agora a caixa tem
   o tamanho de um numero, a unidade anda colada nele e o pedido cresce.
   Vale no questionario do cadastro e no Editar Plano, que usam a mesma
   peca. */
.numero__linha {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  max-width: 100%;
  padding: 10px 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.numero__linha:focus-within { border-color: var(--accent); }
.numero__linha .numero__input {
  flex: 0 1 auto;
  /* a caixa acompanha o que esta escrito: o pedido quando vazia, o
     numero quando preenchida, e a unidade anda colada. Navegador que
     nao conhece `field-sizing` fica na largura fixa. */
  width: 170px;
  field-sizing: content;
  min-width: 3ch;
  max-width: 100%;
  padding: 4px 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.numero__linha .numero__input:focus { outline: 0; box-shadow: none; }
.numero__linha .numero__unidade { font-size: var(--fs-body); color: var(--text-2); }
.numero__linha .numero__input::placeholder { font-size: var(--fs-lg); font-weight: 500; color: var(--text-2); }
.numero__linha .numero__input::-moz-placeholder { font-size: var(--fs-lg); font-weight: 500; color: var(--text-2); opacity: 1; }

/* a linha de baixo do campo antigo nao faz mais sentido: a caixa ja fecha o campo */
.field:has(> .numero__linha) { border-bottom: 0; }

/* ---------- a conversa com o treinador, em Meu treinador (0120) ---------- */
/* ---------- o plano na assessoria (0121, 11/10/2026) ---------- */
.plano-ass { padding: 16px; }
.plano-ass__lista { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; }
.plano-ass__lista li { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-sm); }
.plano-ass__sit { flex: none; padding: 3px 10px; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 700; background: var(--surface-2); color: var(--text-2); }
.plano-ass__sit--paga { background: var(--certo); color: var(--on-accent); }
.plano-ass__sit--vencida { background: #C4271C; color: #FFFFFF; }
.plano-modal { position: fixed; inset: 0; z-index: 90; display: flex; align-items: flex-end; justify-content: center;
  padding: 12px 12px calc(12px + var(--safe-bottom, 0px)); background: color-mix(in srgb, #000 55%, transparent); }
.plano-modal__cartao { width: min(460px, 100%); max-height: 88dvh; overflow-y: auto; padding: 20px; border-radius: var(--r-card);
  background: var(--bg); border: 1px solid var(--border-soft); display: flex; flex-direction: column; }
.plano-modal__cartao .btn { width: 100%; }
@media (min-width: 700px) { .plano-modal { align-items: center; } }

.tchat__lista { display: grid; gap: 8px; max-height: 46vh; overflow-y: auto; }
.tchat__msg { padding: 10px 14px; border-radius: 16px; max-width: 86%; line-height: 1.4; overflow-wrap: anywhere; }
.tchat__msg--eu { justify-self: end; background: var(--accent); color: var(--on-accent); }
.tchat__msg--ele { justify-self: start; background: var(--surface-2); color: var(--text); }
/* o lembrete de mensalidade do treinador (0129): a mesma bolha, com o rotulo em cima */
.tchat__rotulo { display: block; margin-bottom: 4px; font-size: 12.5px; font-weight: 600; letter-spacing: .02em; color: var(--text-2); }
/* a caixa de escrever: fundo proprio, contorno sempre, campo e botao na
   mesma caixa, e baixa (pedido do dono, 11/10/2026) */
.tchat__form { display: flex; gap: 8px; align-items: flex-end; margin: 12px; padding: 6px 6px 6px 14px;
  border: 1px solid color-mix(in srgb, var(--text) 24%, transparent); border-radius: 18px;
  background: color-mix(in srgb, var(--text) 7%, var(--surface)); }
.tchat__form:focus-within { border-color: color-mix(in srgb, var(--text) 45%, transparent); }
.tchat__form textarea { flex: 1; min-width: 0; min-height: 0; max-height: 108px; resize: none; padding: 8px 0;
  border: 0; border-radius: 0; background: none; box-shadow: none; line-height: 1.4; field-sizing: content; }
.tchat__form textarea:focus { outline: 0; box-shadow: none; }
.tchat__form .btn { width: auto; flex: none; min-height: 38px; padding: 0 16px; }

/* ============================================================
   Os desenhos do app (js/desenhos-app.js, 12/10/2026)
   ------------------------------------------------------------
   Linha fina e geometria limpa, no padrao da pagina /faq/planos/: o
   traco do painel do treinador ficou "HQ e cartoonesco" dentro do app
   (dono, 12/10). So a cor do texto; o que esta longe fica mais claro.
   O modal resumido: desenho, titulo curto, ate tres linhas com icone,
   e o texto inteiro de antes no "Saber mais" recolhido.
   ============================================================ */
.desenho-caixa { margin: 6px 0 10px; }
.desenho-fino { display: block; width: 72px; height: 72px; color: var(--text); stroke-width: 1.15; overflow: visible; }
.desenho-caixa--lado .desenho-fino { width: 52px; height: 52px; }
/* o rebranding (31/10): o molde do passo do briefing (.palco--icone e .hist__corpo
   em screens.css). Icone de 48 centrado, traco que se desenha uma vez, e o rotulo,
   o titulo e a primeira frase no mesmo eixo, entrando em cascata. */
.desenho-caixa--serio { display: grid; place-items: center; margin: 8px 0 14px; }
.desenho-fino--serio, .desenho-caixa--lado .desenho-fino--serio, .tour__cartao .desenho-fino--serio { width: 48px; height: 48px; color: color-mix(in srgb, var(--text) 78%, var(--bg)); }
.desenho-fino--serio * { stroke-width: 1.1; }
.desenho-caixa--serio + .mono { display: block; text-align: center; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); }
.desenho-caixa--serio + .mono + h2, .desenho-caixa--serio + .mono + h2 + p, .desenho-caixa--serio + .resumo__titulo { text-align: center; }
@media (prefers-reduced-motion: no-preference) {
  .desenho-fino--serio .ic-t { stroke-dasharray: 1; stroke-dashoffset: 1; animation: serio-desenha .55s cubic-bezier(.25, 1, .5, 1) forwards; animation-delay: calc(.08s + var(--i, 0) * .07s); }
  .desenho-caixa--serio, .desenho-caixa--serio ~ * { animation: serio-entra .34s var(--ease) both; }
  .desenho-caixa--serio + * { animation-delay: 60ms; }
  .desenho-caixa--serio + * + * { animation-delay: 120ms; }
  .desenho-caixa--serio + * + * ~ * { animation-delay: 180ms; }
}
@keyframes serio-desenha { to { stroke-dashoffset: 0; } }
@keyframes serio-entra { from { opacity: 0; transform: translateY(6px); filter: blur(4px); } }
.desenho-fino .meio { opacity: .62; }
.desenho-fino .leve { opacity: .38; }
.desenho-fino .fundo { fill: var(--desenho-fundo, var(--bg-elev)); }
.desenho-fino .r-rastro { animation: desenho-rastro 1.6s ease-in-out infinite; }
.desenho-fino .r-onda { animation: desenho-onda 2.4s ease-in-out infinite; }
@keyframes desenho-rastro { 50% { transform: translateX(-2px); opacity: .12; } }
@keyframes desenho-onda { 50% { opacity: .08; } }
/* o visto do treino que chegou: entra uma vez, com a mola da folha */
.desenho-fino .r-chega { transform-box: fill-box; transform-origin: center; animation: desenho-chega var(--mola-folha-dur) var(--mola-folha) .28s both; }
@keyframes desenho-chega { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .desenho-fino .r-rastro, .desenho-fino .r-onda, .desenho-fino .r-chega { animation: none; } }

.resumo__titulo { font-size: var(--fs-lg); font-weight: 600; line-height: 1.25; color: var(--text); }
.resumo__linhas { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 12px; }
.resumo__linha { display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: start;
  font-size: var(--fs-body); line-height: 1.4; color: var(--text); }
.resumo__ic svg, .resumo__ic .zentry-logo { display: block; width: 20px; height: 20px; margin: 1px 0 0; color: var(--text-2); }
.resumo__mais { margin-top: 14px; }
.resumo__mais summary { list-style: none; display: inline-flex; align-items: center; gap: 8px;
  font-size: var(--fs-sm); color: var(--text-2); cursor: pointer; }
.resumo__mais summary::-webkit-details-marker { display: none; }
.resumo__mais summary::after { content: ''; width: 6px; height: 6px; margin-top: -3px;
  border-right: 1.4px solid currentColor; border-bottom: 1.4px solid currentColor;
  transform: rotate(45deg); transition: transform .2s ease; }
.resumo__mais[open] summary::after { margin-top: 3px; transform: rotate(-135deg); }
.resumo__mais p { margin: 10px 0 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-2); }

/* o tour: o desenho entre a marca e o titulo */
.tour__cartao .desenho-caixa { margin: 10px 0 8px; }
.tour__cartao .desenho-fino { width: 64px; height: 64px; }

/* ---------- o Tryzen Pro no padrao da pagina de Planos ----------
   Medalha fina, etiqueta em pilula e passos 01/02/03 com o primeiro
   aceso e um desenho fino em cada (resposta do dono, 12/10/2026). */
.pro-selo { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--gap-md); }
.medalha-pro { display: block; width: 34px; height: 42px; color: var(--text); }
.pro-etiqueta { border: 1px solid var(--border); border-radius: 999px; padding: 5px 12px;
  font-size: 12.5px; line-height: 1.3; color: var(--text-2); }
.pro-funcoes.pro-passos { gap: 4px; }
.pro-passos .pro-funcao { grid-template-columns: 28px 1fr 52px; gap: 10px; padding: 12px 14px; border-radius: 16px; }
.pro-passos .pro-funcao:first-child { background: var(--accent-tint);
  --desenho-fundo: color-mix(in srgb, var(--accent) 12%, var(--bg)); }
.pro-funcao__n { font-size: var(--fs-sm); color: var(--text-3); font-variant-numeric: tabular-nums; }
.pro-passos .pro-funcao:first-child .pro-funcao__n { color: var(--accent-texto, var(--accent)); }
.pro-passos .desenho-caixa { margin: 0; }

/* ============================================================
   A PRESENCA INTELIGENTE (js/presenca.js, 0137)
   ------------------------------------------------------------
   O mesmo modal do "Resolver tudo" do Tryzen Coach (o dono mandou o
   print, 14/10/2026: "exatamente esse"): o cartao encostado embaixo no
   celular e no meio no computador, o selo redondo com o icone do
   assunto, o titulo grande a esquerda, o rotulo com a dica, o cartao
   com o visto verde e os numeros, e o pe com a linha em cima, "Agora
   nao" cinza a esquerda e o botao cheio a direita. Cores dos tokens do
   tema: o claro e o escuro vem juntos.
   ============================================================ */
.presenca {
  position: fixed;
  inset: 0;
  z-index: 86;
  display: grid;
  place-items: end center;
  padding: 8px 8px calc(8px + var(--safe-bottom, 0px));
}
@media (min-width: 600px) { .presenca { place-items: center; padding: 20px; } }
.presenca__scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, #000 52%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.presenca__caixa {
  position: relative;
  width: min(460px, 100%);
  max-height: calc(100svh - 20px);
  overflow-y: auto;
  padding: 24px 22px 0;
  border-radius: 22px;
  background: var(--bg-elev);
  color: var(--text);
  border: 1px solid var(--border-soft);
  box-shadow: 0 24px 64px rgba(0, 0, 0, .28);
  text-align: left;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .25s var(--ease), transform .45s cubic-bezier(.22, 1, .36, 1);
}
.presenca__caixa:focus { outline: none; }
.presenca.is-on .presenca__scrim { opacity: 1; }
.presenca.is-on .presenca__caixa { opacity: 1; transform: none; }
.presenca__de { display: flex; align-items: center; gap: 7px; margin: 0; font-size: 13.5px; color: var(--text-3); }
.presenca__ponto { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.presenca__selo {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin: 18px auto 14px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--text) 5%, transparent);
  color: var(--text-2);
}
.presenca__selo--semana,
.presenca__selo--evolucao { color: var(--certo-texto); }
.presenca__selo--consistencia { color: var(--acao-texto); }
.presenca__selo--recuperacao { color: var(--risco-texto); }
.presenca__selo--persona { color: var(--certo-texto); }
.presenca__titulo { margin: 0; font-size: 22px; line-height: 1.3; font-weight: 600; letter-spacing: -.01em; }
.presenca__texto { margin: 8px 0 0; font-size: 15px; line-height: 1.5; color: var(--text-2); }
.presenca__rotulo { margin: 18px 0 8px; font-size: 15px; font-weight: 600; color: var(--text); }
.presenca__rotulo span { display: block; font-size: 13.5px; font-weight: 500; color: var(--text-3); }
.presenca__visto {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--text) 16%, transparent);
  background: color-mix(in srgb, var(--text) 3%, var(--bg-elev));
}
.presenca__visto i {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent, #0b2a14);
}
.presenca__visto span { display: grid; gap: 1px; min-width: 0; }
.presenca__visto b { font-size: 16px; font-weight: 600; color: var(--text); }
.presenca__visto small { font-size: 13.5px; line-height: 1.4; color: var(--text-2); }
.presenca__trocar { all: unset; display: inline-block; margin-top: 10px; font-size: 14px; color: var(--text-2); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.presenca__trocar:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.presenca__pe {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 20px -22px 0;
  padding: 14px 16px 16px;
  background: var(--bg-elev);
  border-top: 1px solid color-mix(in srgb, var(--text) 10%, transparent);
}
.presenca__pe { gap: 8px; }
.presenca__pe .btn { width: auto; min-height: 46px; padding-inline: 16px; font-size: 15.5px; white-space: nowrap; }
.presenca__pe .btn--primary { flex: 1; min-width: 0; margin-left: auto; padding-inline: 10px; letter-spacing: -.01em; white-space: normal; text-wrap: balance; line-height: 1.2; }
@media (max-width: 370px) { .presenca__pe .btn { font-size: 14.5px; padding-inline: 13px; } .presenca__pe .btn--primary { padding-inline: 8px; } }
.presenca__nao { flex: none; border: 0; background: color-mix(in srgb, var(--text) 7%, transparent); color: var(--text); }
@media (prefers-reduced-motion: reduce) {
  .presenca__scrim, .presenca__caixa { transition: none; }
}

/* ============================================================
   O desenho de estado e a Tryzen apontando, no app (20/10/2026)
   ------------------------------------------------------------
   js/estado-app.js. A mesma logica do painel do Coach, no traco do app:
   o desenho diz o estado pela forma, e a cor mora SO no traco (escolha
   do dono): amarelo forte = pede atencao, verde = tudo certo, cinza =
   mudou pouco. Nada de pilula nem fundo colorido.
   ============================================================ */
.est { --est-pede: var(--acao-preso, #B86700); display: inline-grid; place-items: center; flex: none; vertical-align: -4px; }
.est svg { width: 20px; height: 20px; }
.est--problema { color: var(--est-pede); }
.est--ok { color: var(--accent); }
.est--estavel { color: var(--text-3); }
@media (prefers-color-scheme: dark) { :root:not([data-tema="claro"]) .est { --est-pede: var(--warn); } }
:root[data-tema="escuro"] .est { --est-pede: var(--warn); }
.pastilha__valor .est { margin-left: 6px; }

/* o balao da Tryzen: a primeira linha do que ela aponta */
.tz-fala-app { position: relative; display: flex; align-items: flex-start; gap: 10px; margin: 0 0 14px; padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--text) 10%, transparent); border-radius: 16px; background: var(--surface); }
.tz-fala-app::after { content: ''; position: absolute; left: 24px; bottom: -7px; width: 12px; height: 12px; background: inherit;
  border-right: inherit; border-bottom: inherit; transform: rotate(45deg); }
.tz-fala-app--problema { border-color: color-mix(in srgb, var(--acao-preso, #B86700) 45%, transparent); }
.tz-fala-app__marca { flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: #fff; }
.tz-fala-app p { flex: 1; min-width: 0; margin: 2px 0 0; font-size: 15px; line-height: 1.45; color: var(--text); }
.tz-fala-app b { font-weight: 600; margin-right: 4px; }
/* o X so existe com o holofote aceso; apagado, a frase fica como a primeira linha */
.tz-fala-app__x { display: none; flex: none; place-items: center; width: 36px; height: 36px; margin: -6px -6px -6px 0; border: 0; border-radius: 50%;
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }
.holofote-app .tz-fala-app__x { display: grid; }
.tz-fala-app__x:active { transform: scale(.94); opacity: .85; }

/* o holofote: tudo em volta escurece e so a parte da vez fica acesa */
.holofote-app { position: relative; z-index: 60; border-radius: 20px; background: var(--bg);
  box-shadow: 0 0 0 6px var(--bg), 0 0 0 200vmax rgba(0, 0, 0, .52); }
@media (prefers-reduced-motion: no-preference) {
  .holofote-app { transition: box-shadow .35s ease; }
  .holofote-app .tz-fala-app { animation: tz-fala-entra .35s cubic-bezier(.3, .8, .25, 1) both; }
}
@keyframes tz-fala-entra { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---------- o WhatsApp com a equipe (0169, 24/10/2026) ----------
   O pedido de quem da equipe vira um cartao de contorno, com o desenho
   do WhatsApp, a pergunta e Sim ou Agora nao lado a lado. */
.zap-pedido { border: 1px solid var(--border); background: transparent; }
.zap-pedido__ic { display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 12px;
  border: 1px solid var(--border); color: var(--accent-texto); }
.zap-pedido__pe { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.zap-pedido__pe .btn { width: 100%; white-space: nowrap; }

/* o print na caixa do chat (02/11/2026): a miniatura no lugar do icone */
.pbar__chip--print { padding-left: 4px; }
.pbar__chip-foto {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  object-fit: cover;
}
.chat__print {
  display: block;
  max-width: min(220px, 70%);
  margin: 0 0 6px auto;
  border-radius: var(--r-md);
}

/* o paywall (02/11/2026): a tela inteira de quem ainda nao tem o Pro */
.paywall__corpo { display: flex; flex-direction: column; padding-top: 40px; padding-bottom: 40px; }
.paywall__titulo { text-wrap: balance; }
.paywall__aviso { text-align: center; min-height: 1.4em; }
.paywall__rodape { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 8px; }
