/*
 * Hub — Copyright (c) 2026 Bernardo Garcia Ferrão.
 * Todos os direitos reservados.
 *
 * Software proprietário, protegido pela Lei 9.610/98 (Brasil) e pelos tratados
 * internacionais de direito autoral. A licença de uso é pessoal e intransferível.
 *
 * É PROIBIDO, sem autorização escrita do autor: copiar, redistribuir, revender,
 * publicar, modificar ou criar obra derivada deste código, no todo ou em parte.
 *
 * Este arquivo estar legível no pacote é consequência de o produto rodar no
 * navegador, não permissão de uso. A autoria está registrada com data no
 * histórico do repositório.
 *
 * Contato: suporte@suportehub.dev.br
 */

/*
 * app.css — Estilos do Hub.
 *
 * Zero recursos externos: o produto roda offline, então tudo vem do próprio
 * servidor. Fontes do sistema, ícones em SVG inline, gráficos desenhados à mão.
 *
 * Direção visual: sóbria e densa. Tipografia menor e mais precisa, paleta
 * contida (cinzas + um acento por perfil), cards discretos. A cor do perfil
 * entra por --accent e é usada com parcimônia — em destaque de estado e ação,
 * não como decoração.
 */

:root {
  /* O laranja do hub.ico, medido dele. É o valor de PARTIDA: assim que
     alguém entra, applyProfileTheme troca pela cor do perfil. Ele aparece
     nas telas anteriores ao login — ativação, boas-vindas, escolha de
     perfil —, que ficavam azuis num produto laranja: o cliente instalava um
     ícone laranja e a primeira tela do app era azul. */
  --accent: #ec6925;

  /* ESPACAMENTO
     A escala que o arquivo ja usava na pratica, agora escrita. Havia 39
     valores distintos entre padding, margin e gap, com passos de 0.05rem
     (0,8px) que ninguem escolheu e ninguem enxerga isolados -- mas que,
     somados, desalinham cards vizinhos e sao a causa da impressao de
     descuido. Os valores soltos foram encostados no degrau mais proximo.

     Regra para o codigo novo: use o token. Valor cru so quando houver
     motivo, e o motivo escrito ao lado. */
  --sp-1: .2rem;
  --sp-2: .3rem;
  --sp-3: .5rem;
  --sp-4: .7rem;
  --sp-5: 1rem;
  --sp-6: 1.4rem;
  --sp-7: 2rem;

  /* TIPOGRAFIA
     Eram ~30 tamanhos, sete deles espremidos entre .78 e .92rem -- degraus
     que ninguem distingue lado a lado, mas que impedem qualquer ritmo. Os
     valores soltos foram encostados no degrau mais proximo (deslocamento
     maximo de 0,8px), e os pesos 620 e 650 viraram 600.

     Regra para o codigo novo: use o token, e prefira mudar o PESO antes de
     inventar um tamanho intermediario. */
  --fs-xs: .72rem;    /* rotulo em caixa alta, nota de rodape */
  --fs-sm: .78rem;    /* rotulo de campo */
  --fs-md: .82rem;    /* texto de apoio, o mais usado do arquivo */
  --fs-base: .9rem;   /* corpo */
  --fs-lg: 1.05rem;   /* titulo de card */
  --fs-xl: 1.35rem;   /* numero de indicador */
  --fs-2xl: 2.6rem;   /* numero grande, tela de destaque */

  /* BREAKPOINTS
     Eram doze valores (380, 400, 480, 560, 640, 700, 720, 760, 859, 860,
     980), com 700/720/760 a menos de 60px um do outro dizendo a mesma coisa
     -- "tela estreita, empilha" -- e nenhum motivo escrito para a diferenca.
     Sinal de acumulo, nao de decisao. Agora sao:

       400px   telefone pequeno: o que ainda quebra em 360
       480px   telefone: grade de emoji e de capa
       560px   telefone deitado: formulario passa a caber em duas colunas
       640px   limite do celular: padding, titulo e a tabela da aba do
               Produto, que aperta antes por ter seis colunas
       760px   tablet em pe: as grades de duas colunas viram uma, e a lista
               do Caderno vira gaveta (o app.js confere a MESMA largura no
               matchMedia -- mudar aqui pede mudar la)
       859/860 a GRADE DA TELA INICIAL. O par existe porque um lado apaga o
               posicionamento e o outro o monta; nao mexer sem ler o bloco
               da .wgrid
       980px   as abas param de rolar e se espalham na barra
       1840px  monitor largo: sobra margem para a nota flutuante

     Nao invente valor novo sem antes ver se um destes serve. */

  /* O desenho da medalha, para o pseudo-elemento do avatar recortar. E o
     mesmo caminho do icone `medalha` no app.js; mudou um, muda o outro. */
  --medalha-svg: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M8.5 3 12 9.5 15.5 3M12 21a5 5 0 1 0 0-10 5 5 0 0 0 0 10Z"/></svg>');

  --r: 10px;
  --r-sm: 7px;
  --r-xs: 4px;
  /* Pílula: usado por barra de progresso, chip e trilho de controle. Antes
     conviviam 99px e 999px, que desenham a mesma forma -- um token evita a
     terceira variante. */
  --r-pill: 999px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace;

  --step: #d97706;
  --water: #2563eb;
  --sleep: #7c3aed;
  --heart: #dc2626;
  --weight: #0891b2;

  /* Patrimônio e Investido não seguem o tema: são os dois números que a
     pessoa procura primeiro, e mudavam de cor junto com o resto. Também não
     repetem o azul de "Entrou" nem o vermelho de "Saiu". */
  --patrimonio: #ea580c;
  --investido: #4f46e5;

  --ok: #059669;
  --warn: #d97706;
  --err: #dc2626;

  --shadow: 0 1px 2px rgb(0 0 0 / 4%);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

/*
 * `color-scheme` acompanha o tema, e não é decoração: é o que o navegador lê
 * para pintar o que ele desenha sozinho, e que nenhuma regra nossa alcança.
 * Sem isso, quem ligava o escuro com o celular no claro ficava com o menu do
 * <select>, o calendário do type="date" e a barra de seleção de texto ainda
 * em cores de tema claro, sobre o nosso fundo escuro.
 */

/*
 * `only` antes do nome: o Hub JÁ tem tema escuro próprio, e sem isso o
 * "Forçar modo escuro nos sites" do Chrome no Android reescrevia cor a cor
 * por cima do nosso. O efeito era pior que o problema que ele resolve: os
 * tons de cinza da cor do texto saíam todos parecidos E fora de ordem,
 * porque a inversão comprime a luminância e troca claro por escuro.
 *
 * Quem quer o Hub escuro tem o botão de tema; o navegador não precisa
 * adivinhar.
 */

/* Claro */

/* Claro escolhido a mao */
:root[data-theme="light"][data-temp="neutro"] {
  --bg: #fbfbfb; --surface: #ffffff; --surface-2: #f6f6f6;
  --border: #e7e7e7; --border-strong: #d7d7d7;
}
:root[data-theme="light"][data-temp="quente-leve"] {
  --bg: #fcfbfb; --surface: #ffffff; --surface-2: #f6f5f5;
  --border: #e8e7e6; --border-strong: #dad7d5;
}
:root[data-theme="light"][data-temp="quente-medio"] {
  --bg: #fcfbfb; --surface: #ffffff; --surface-2: #f7f5f4;
  --border: #ece6e2; --border-strong: #dfd5d0;
}
:root[data-theme="light"][data-temp="quente-forte"] {
  --bg: #fdfbfa; --surface: #ffffff; --surface-2: #f8f5f3;
  --border: #eee5e0; --border-strong: #e3d4cc;
}
:root[data-theme="light"][data-temp="frio-leve"] {
  --bg: #fbfbfc; --surface: #ffffff; --surface-2: #f5f5f6;
  --border: #e5e6e9; --border-strong: #d4d6db;
}
:root[data-theme="light"][data-temp="frio-medio"] {
  --bg: #fbfbfc; --surface: #ffffff; --surface-2: #f4f5f7;
  --border: #e2e6ec; --border-strong: #d0d5df;
}
:root[data-theme="light"][data-temp="frio-forte"] {
  --bg: #fafbfd; --surface: #ffffff; --surface-2: #f3f5f8;
  --border: #e0e5ee; --border-strong: #ccd4e3;
}

/* Claro automatico: sistema em claro e sem escolha gravada */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"])[data-temp="neutro"] {
    --bg: #fbfbfb; --surface: #ffffff; --surface-2: #f6f6f6;
    --border: #e7e7e7; --border-strong: #d7d7d7;
  }
  :root:not([data-theme="dark"])[data-temp="quente-leve"] {
    --bg: #fcfbfb; --surface: #ffffff; --surface-2: #f6f5f5;
    --border: #e8e7e6; --border-strong: #dad7d5;
  }
  :root:not([data-theme="dark"])[data-temp="quente-medio"] {
    --bg: #fcfbfb; --surface: #ffffff; --surface-2: #f7f5f4;
    --border: #ece6e2; --border-strong: #dfd5d0;
  }
  :root:not([data-theme="dark"])[data-temp="quente-forte"] {
    --bg: #fdfbfa; --surface: #ffffff; --surface-2: #f8f5f3;
    --border: #eee5e0; --border-strong: #e3d4cc;
  }
  :root:not([data-theme="dark"])[data-temp="frio-leve"] {
    --bg: #fbfbfc; --surface: #ffffff; --surface-2: #f5f5f6;
    --border: #e5e6e9; --border-strong: #d4d6db;
  }
  :root:not([data-theme="dark"])[data-temp="frio-medio"] {
    --bg: #fbfbfc; --surface: #ffffff; --surface-2: #f4f5f7;
    --border: #e2e6ec; --border-strong: #d0d5df;
  }
  :root:not([data-theme="dark"])[data-temp="frio-forte"] {
    --bg: #fafbfd; --surface: #ffffff; --surface-2: #f3f5f8;
    --border: #e0e5ee; --border-strong: #ccd4e3;
  }
}
:root, :root[data-theme="light"] {
  color-scheme: only light;
  /* Quente-medio, o mesmo degrau do tema escuro. O claro tinha ficado com
     cinzas AZULADOS (matiz 220) enquanto o escuro ja puxava para o quente:
     as duas metades do produto nao combinavam. */
  --bg: #fcfbfb;
  --surface: #ffffff;
  --surface-2: #f6f5f5;
  --border: #e9e6e5;
  --border-strong: #dbd6d4;
  --text: #1c1917;
  --text-dim: #6d625c;
  /* Medido contra --surface-2 (#f4f5f7), o pior fundo: #8b909b dava 2.93:1
     e reprovava em AA para texto normal. */
  --text-faint: #746c68;

  /* O laranja da marca CONTINUA #ec6925 em preenchimento e borda -- é a
     identidade. Como texto ele dava 2.91:1 sobre --surface-2, então a versão
     escrita ganha um token próprio, com o mesmo matiz. */
  --accent-text: #b8511c;
  --step-text: #7d5930;
  --patrimonio-text: #935738;
  --ok-text: #047f59;
  --err-text: #c81e1e;
  --water-text: #4360b2;
  --sleep-text: #7448b9;
  --investido-text: #5148ba;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: only dark;
    --bg: #0e0d0d;
    --surface: #161514;
    --surface-2: #1e1c1b;
    --border: #2a2725;
    --border-strong: #383533;
    --text: #edeae9;
    --text-dim: #aca19b;
    --text-faint: #938781;
    --accent-text: var(--accent);
    --step-text: #c29660;
    --patrimonio-text: #c78d6c;
    --ok-text: #0c996d;
    --err-text: #e45757;
    --water-text: #7590ca;
    --sleep-text: #a48ad2;
    --investido-text: #938fd4;
    --shadow: none;
  }
}

:root[data-theme="dark"] {
  color-scheme: only dark;
  --bg: #0e0d0d;
  --surface: #161514;
  --surface-2: #1e1c1b;
  --border: #2a2725;
  --border-strong: #383533;
  --text: #edeae9;
  --text-dim: #aca19b;
  --text-faint: #938781;
  --accent-text: var(--accent);
  --step-text: #c29660;
  --patrimonio-text: #c78d6c;
  --ok-text: #0c996d;
  --err-text: #e45757;
  --water-text: #7590ca;
  --sleep-text: #a48ad2;
  --investido-text: #938fd4;
  --shadow: none;
}

/* ---------------------------------------------------------------------------
   TEMPERATURA DAS SUPERFICIES

   O fundo do Hub nao e cinza puro: ele puxa para o quente, para nao brigar
   com o laranja da marca. Quanto ele puxa passa a ser escolha de quem usa,
   em Configuracoes -> Perfil -> Cor.

   Sao sete degraus: neutro no meio, tres para o quente e tres para o frio.
   Nao e um cursor continuo -- cada degrau tem valor calibrado, e o que muda
   e so o MATIZ e a SATURACAO. A luminancia de cada superficie fica onde
   esta, senao todo o contraste medido em AA deixaria de valer.

   O padrao (`quente-medio`) reproduz exatamente os valores de hoje, entao
   quem nunca abrir esta tela nao ve diferenca nenhuma.

   O atributo vive no <html> como `data-temp`, e o tema claro e o escuro tem
   valores proprios: clarear e escurecer o mesmo matiz nao da o mesmo
   resultado nas duas pontas da escala.
   --------------------------------------------------------------------------- */

/* Escuro */

/* Escuro escolhido a mao */
:root[data-theme="dark"][data-temp="neutro"] {
  --bg: #0e0e0e; --surface: #151515; --surface-2: #1c1c1c;
  --border: #282828; --border-strong: #363636;
}
:root[data-theme="dark"][data-temp="quente-medio"] {
  --bg: #0f0d0c; --surface: #171413; --surface-2: #1f1b19;
  --border: #2b2624; --border-strong: #3a3431;
}
:root[data-theme="dark"][data-temp="quente-forte"] {
  --bg: #100d0b; --surface: #181411; --surface-2: #211a17;
  --border: #2e2521; --border-strong: #3f332c;
}
:root[data-theme="dark"][data-temp="frio-leve"] {
  --bg: #0d0d0e; --surface: #141516; --surface-2: #1b1c1e;
  --border: #25272a; --border-strong: #333538;
}
:root[data-theme="dark"][data-temp="frio-medio"] {
  --bg: #0c0d0f; --surface: #131417; --surface-2: #191b1f;
  --border: #23262c; --border-strong: #30343b;
}
:root[data-theme="dark"][data-temp="frio-forte"] {
  --bg: #0b0d10; --surface: #111418; --surface-2: #171a21;
  --border: #21252e; --border-strong: #2c333f;
}

/* Escuro automatico: sistema em escuro e sem escolha gravada */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"])[data-temp="neutro"] {
    --bg: #0e0e0e; --surface: #151515; --surface-2: #1c1c1c;
    --border: #282828; --border-strong: #363636;
  }
  :root:not([data-theme="light"])[data-temp="quente-medio"] {
    --bg: #0f0d0c; --surface: #171413; --surface-2: #1f1b19;
    --border: #2b2624; --border-strong: #3a3431;
  }
  :root:not([data-theme="light"])[data-temp="quente-forte"] {
    --bg: #100d0b; --surface: #181411; --surface-2: #211a17;
    --border: #2e2521; --border-strong: #3f332c;
  }
  :root:not([data-theme="light"])[data-temp="frio-leve"] {
    --bg: #0d0d0e; --surface: #141516; --surface-2: #1b1c1e;
    --border: #25272a; --border-strong: #333538;
  }
  :root:not([data-theme="light"])[data-temp="frio-medio"] {
    --bg: #0c0d0f; --surface: #131417; --surface-2: #191b1f;
    --border: #23262c; --border-strong: #30343b;
  }
  :root:not([data-theme="light"])[data-temp="frio-forte"] {
    --bg: #0b0d10; --surface: #111418; --surface-2: #171a21;
    --border: #21252e; --border-strong: #2c333f;
  }
}

/* Claro */


* { box-sizing: border-box; margin: 0; padding: 0; }

/* Sem o ESTICAO no fim da rolagem.

   Chegando ao topo ou ao pe, o navegador do celular estica a pagina e
   solta, como um elastico. Um `position: fixed` acompanha esse estirao --
   ele desloca o viewport VISUAL, e nao o layout --, e a alca, que vive
   encostada na borda, passeava junto: era o movimento que sobrava depois
   de o `svh` acertar o salto da barra de endereco. Dois efeitos
   diferentes, o mesmo sintoma para quem olha.

   `contain` corta so o excesso nas pontas e mantem a rolagem normal. Nao e
   `none`, que desligaria tambem o "puxar para atualizar" do navegador. */
html {
  overscroll-behavior-y: contain;
}

body {
  overscroll-behavior-y: contain;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

h1, h2, h3 { line-height: 1.25; font-weight: 600; letter-spacing: -0.02em; }
h1 { font-size: 1.35rem; }
h2 { font-size: 1.05rem; }
h3 { font-size: .85rem; }

.ico { flex-shrink: 0; vertical-align: -.2em; }

/* --------------------------------------------------------------- controles */

button, .btn {
  font: inherit;
  font-size: .85rem;
  font-weight: 500;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  border-radius: var(--r-sm);
  padding: .5rem .8rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  transition: background .12s, border-color .12s, opacity .12s;
  min-height: 38px;
}
button:hover, .btn:hover { background: var(--surface-2); }
button:disabled { opacity: .45; cursor: not-allowed; }

:focus-visible { outline: none; box-shadow: var(--ring); }

.btn-primary {
  background: var(--accent);
  border-color: transparent;
  /* Acompanha o acento: com a cor de perfil branca, um #fff fixo deixava o
     botão inteiro branco sobre branco. O JS calcula pela luminância. */
  color: var(--sobre-accent, #fff);
}
.btn-primary:hover { background: var(--accent); filter: brightness(1.1); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }

.btn-lg { padding: .7rem 1.2rem; font-size: .95rem; min-height: 44px; }
.btn-block { width: 100%; }

/* Link com aparência de botão (usado para abrir os guias em nova aba). */
a.btn { text-decoration: none; color: var(--text); }
a.btn:visited { color: var(--text); }

.icon-only {
  width: 34px;
  padding: 0;
  color: var(--text-dim);
}
.icon-only:hover { color: var(--text); }

input, select, textarea {
  font: inherit;
  font-size: .85rem;
  width: 100%;
  padding: .5rem .7rem;
  min-height: 38px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  outline: none;
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: var(--ring);
}
input::placeholder { color: var(--text-faint); }
input[type="color"] { padding: .15rem; height: 38px; cursor: pointer; }

/* Os controles deslizantes das metas. Sem `accent-color` o navegador pinta
   a trilha preenchida e a bolinha do azul PADRÃO DELE — que não vem de
   `--accent` nem de nada nosso, então continuavam azuis mesmo com o resto
   do Hub laranja.

   A regra geral acima trata todo `input` como campo de texto: fundo, borda
   e altura mínima desenhavam uma caixa em volta da barra. Aqui isso é
   desfeito. */
input[type="range"] {
  accent-color: var(--accent);
  width: 100%;
  min-height: 0;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}
input[type="range"]:focus {
  box-shadow: none;
  border: none;
}
/* O anel de foco vai na bolinha, não na caixa: a barra não tem borda para
   receber o realce, e sem isto quem navega por teclado perde o controle de
   vista. */
input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: var(--ring); }
input[type="range"]:focus-visible::-moz-range-thumb { box-shadow: var(--ring); }

/* Sem as setinhas de incremento: em campos de passos ou água elas não servem
   (ninguém ajusta 8.432 de 1 em 1) e roubam espaço do número. */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

label {
  display: block;
  font-size: .78rem;
  font-weight: 500;
  color: var(--text-dim);
  margin-bottom: .3rem;
}

.field { margin-bottom: .9rem; }
.hint { font-size: .78rem; color: var(--text-faint); margin-top: .3rem; }

/* ------------------------------------------------------------------ layout */

/* Em monitores largos, 1080px deixava dois terços da tela vazios. 1320px
   aproveita o espaço sem esticar a linha de texto além do confortável. */
/* O padding de CIMA e menor que o dos lados: a barra de abas ja e uma
   separacao visual, e 1.2rem embaixo dela abria uma faixa vazia antes do
   primeiro card. Os lados continuam em 1.2rem, que e a margem da coluna. */
.wrap { max-width: 1320px; margin: 0 auto; padding: .5rem 1.2rem 1.2rem; }

/* Duas colunas a partir de tablet; empilhado no celular.
   As colunas são flex e o último card de cada uma cresce, para as duas
   terminarem na mesma altura — antes uma parava bem antes da outra e a tela
   ficava com um degrau visível. */
/* -------------------------------------------------- grade de widgets */

/* Celular: uma coluna, na ordem definida no desktop. Posicionamento livre
   não cabe em 390px — arrastar em duas dimensões ali seria pior que a
   ordem simples. */
.wgrid { display: flex; flex-direction: column; gap: 12px; }

/* O !important anula o grid-column inline de cada widget. Precisa ficar
   dentro do media query do celular: fora dele, apagava o posicionamento no
   desktop e todos os widgets viravam caixinhas de uma coluna. */
@media (max-width: 859px) {
  .wgrid .wcell { grid-column: auto !important; grid-row: auto !important; }
}

@media (min-width: 860px) {
  .wgrid {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    /* Linha de altura FIXA, não minmax(48px, auto).
       Com `auto` a linha crescia até caber o conteúdo, e a altura escolhida
       na alça virava apenas um mínimo: o widget de métricas resolvia para
       121px pedindo 48px, e o de notícias não descia de ~102px. Nenhum ajuste
       dentro da célula resolve isso — a célula obedece à linha. Com altura
       fixa o que sobra rola por dentro do card (regras abaixo). */
    grid-auto-rows: 48px;
    gap: 12px;
  }
}

.wcell { position: relative; min-width: 0; display: flex; flex-direction: column; }

/* O widget nunca corta o conteúdo: quando a altura escolhida não comporta,
   o card cresce e empurra a linha seguinte. Rolar por dentro escondia
   informação sem avisar, e o cabeçalho ficava preso enquanto o resto sumia. */
.wbody { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* A altura escolhida no modo organizar tem de valer. Sem isto o conteúdo
   empurrava a célula por baixo: o widget de notícias parava em ~102px e o de
   métricas em 242px, qualquer que fosse a altura pedida — o usuário arrastava
   a alça e nada acontecia. Cada nível da cadeia precisa poder encolher
   (min-height:0) e o último contém o excedente (overflow). */
.wbody > .card,
.wbody > .grid {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* O card é ele próprio uma coluna: assim o miolo cede espaço e o cabeçalho
   fica. Sem isso os filhos empilham na altura natural e nada encolhe. */
.wbody > .card {
  display: flex;
  flex-direction: column;
}

/* Cabeçalho não encolhe — é ele que diz de que widget se trata. */
.wbody > .card > .row-between { flex: none; }

/* ---------------------------------------------------------------------------
   O WIDGET BAIXO E O ESPACO QUE SOBRA

   `.wbody > .card` e uma coluna flex sem `justify-content`, entao o conteudo
   empilha no TOPO e toda a folga cai embaixo. Num widget alto isso nao
   aparece -- o conteudo enche a altura. Nos baixos, aparece muito: o Caderno
   com o atalho colado no titulo e um vao embaixo, o "O que ja preenchi hoje"
   com os botoes no alto, o Acompanhar com o botao Abrir espremido.

   Centrar distribui a folga em cima e embaixo, que e o que faz o card baixo
   parecer composto em vez de cortado. So nos baixos: no widget alto o
   conteudo ja ocupa a altura, e centrar nao mudaria nada.
   --------------------------------------------------------------------------- */
.wgrid .wcell[data-wh="2"] .wbody > .card,
.wgrid .wcell[data-wh="3"] .wbody > .card {
  /* `safe` e o que impede o corte. Centrar num container MENOR que o
     conteudo empurra para fora nas DUAS pontas, e o que sai pelo topo fica
     inalcancavel -- era o titulo "Acompanhar" aparecendo pela metade. Com
     `safe`, o navegador desiste de centrar quando ia cortar e volta a
     alinhar pelo inicio, que e o comportamento certo nesse caso. */
  justify-content: safe center;
}

/* MENOS quando o corpo do card e uma LISTA. Ali a altura muda com o
   conteudo, e centrar faz o texto pular: entrando no Hub, "Carregando..."
   e uma linha so e aparecia no meio do card; quando a lista chegava, ela
   subia para o topo. O salto lia como defeito.

   Com a lista alinhada ao topo o ponto de partida e o mesmo antes e depois,
   e nada se move quando o dado chega. Vale para o estado de carregamento
   (`> .muted`, o paragrafo solto) pelo mesmo motivo. */
.wgrid .wcell[data-wh="2"] .wbody > .card:has(> .list),
.wgrid .wcell[data-wh="3"] .wbody > .card:has(> .list),
.wgrid .wcell[data-wh="2"] .wbody > .card:has(> ul),
.wgrid .wcell[data-wh="3"] .wbody > .card:has(> ul),
.wgrid .wcell[data-wh="2"] .wbody > .card:has(> .muted),
.wgrid .wcell[data-wh="3"] .wbody > .card:has(> .muted) { justify-content: flex-start; }

/* O Caderno e a excecao da excecao: a lista dele tem altura FIXA (uma linha
   inteira, regra mais abaixo), entao nao muda quando o dado chega e nao ha
   salto nenhum a evitar. Centrar ali e o que tira o atalho de cima do
   titulo. */
.wgrid .wcell[data-wh="2"] .wbody > .card:has(.cad-atalhos) { justify-content: safe center; }

/* A lista que rola corta no fim de uma LINHA, nao no meio dela.

   `scroll-snap` alinha o corte a borda de um item: a lista para sempre com
   linhas inteiras a vista, e o que sobra fica inteiro embaixo em vez de
   aparecer pela metade. O degrade continua avisando que ha mais -- ele diz
   "continua", e o snap garante que o que se ve esta completo.

   Meia linha visivel le como defeito de renderizacao; linha inteira mais
   degrade le como lista que continua, que e a informacao certa. */
.wbody .card > .list,
.wbody .card > ul {
  scroll-snap-type: y proximity;
}
.wbody .card > .list > li,
.wbody .card > ul > li {
  scroll-snap-align: start;
}

/* O Caderno precisa caber uma pagina INTEIRA na altura minima. A linha do
   atalho mede 36px e a lista sobrava com 25 -- menos que uma linha, entao o
   unico atalho aparecia pela metade. Com o cabecalho podendo encolher e o
   padding menor, a linha inteira entra. */
.wgrid .wcell[data-wh="2"] .wbody > .card:has(.cad-atalhos) { padding: .6rem .8rem; }
.wgrid .wcell[data-wh="2"] .wbody > .card:has(.cad-atalhos) > .row-between {
  margin-bottom: .3rem !important;
}
.wgrid .wcell[data-wh="2"] .cad-atalhos li { padding: .2rem 0 !important; }

/* E a lista mostra um numero INTEIRO de atalhos. Com a altura livre ela
   parava no meio da segunda linha -- pior que mostrar so a primeira, porque
   meia linha lida como defeito e nao como "tem mais". A altura fixa em uma
   linha (28px) corta no lugar certo, e o resto rola. */
.wgrid .wcell[data-wh="2"] .wbody > .card:has(.cad-atalhos) > .cad-atalhos {
  max-height: 28px;
}

/* O botao "Abrir" do Acompanhar sai inteiro. Ele estava sendo espremido pela
   linha do parceiro; `flex: none` no botao e o alinhamento vertical dao a ele
   a altura que o texto pede. */
/* O botao ENCOLHE ate o que sobra, em vez de manter a largura natural.
   Com `flex: none` ele ficava com os 170px do texto mais o padding e passava
   20px da borda direita do card -- num card de 204px sobram ~135 depois do
   padding, do avatar e do vao entre os dois. `min-width: 0` e o que autoriza
   o encolhimento; sem ele o flex respeita a largura do conteudo e transborda
   do mesmo jeito. */
.wgrid .wcell[data-wh="2"] .linha-dupla .btn,
.wgrid .wcell[data-wh="2"] .linha-dupla .btn-primary,
.wgrid .wcell[data-wh="2"] .linha-dupla .btn-contorno {
  flex: 0 1 auto;
  min-width: 0;
  padding-inline: .5rem;
}
/* O `.row` que agrupa os botoes tambem precisa poder encolher: sem isto ele
   guarda a largura dos dois filhos somados e empurra tudo para fora do card
   -- e o caso do painel visitado, que tem "Recado" e "Voltar ao meu" lado a
   lado onde o normal tem so um botao. */
.wgrid .wcell[data-wh="2"] .linha-dupla > .row,
.wgrid .wcell[data-wh="3"] .linha-dupla > .row { min-width: 0; flex-shrink: 1; }
.wgrid .wcell[data-wh="2"] .linha-dupla .btn,
.wgrid .wcell[data-wh="2"] .linha-dupla .btn-primary {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* O total em kcal do widget de Alimentacao ficava 4px para fora do card na
   altura padrao (o conteudo pede 247px e o card tem 226), e o numero saia
   cortado pela metade. Sao 21px de excesso, tirados do espacamento -- a
   rosca continua do mesmo tamanho, que e o que a pessoa le de longe. */
.wgrid .wcell[data-wh="4"] .wbody > .card:has(.pizza-wrap),
.wgrid .wcell[data-wh="5"] .wbody > .card:has(.pizza-wrap) { padding: .7rem .8rem; }
.wgrid .wcell[data-wh="4"] .wbody > .card:has(.pizza-wrap) > div:first-child {
  margin-bottom: .3rem !important;
}
.wgrid .wcell[data-wh="4"] .pizza-wrap { gap: .6rem; }
.wgrid .wcell[data-wh="4"] .wbody > .card:has(.pizza-wrap) > .center {
  margin-top: .2rem !important;
}


/* Listas longas (notícias, tarefas) rolam só dentro da própria lista, com o
   título do card sempre visível. */
.wbody .card > .list,
.wbody .card > ul { overflow-y: auto; min-height: 0; flex: 1; }

/* A ultima linha visivel da lista saia cortada no meio da palavra, sem nada
   dizendo que havia mais embaixo -- parecia defeito de renderizacao, nao
   conteudo continuando. O mesmo degrade que a barra de abas ja usa na
   horizontal, agora na vertical: a linha cortada esmaece e o corte vira
   aviso.

   O `min-height` NAO e detalhe. Sem ele o degrade se aplicava a qualquer
   lista, inclusive as que ficam menores que o proprio degrade: o widget do
   Caderno na altura minima deixa a lista com 25px, o degrade de 1.6rem
   (25.6px) cobria ela inteira, e o unico atalho visivel aparecia cortado no
   meio e desbotado -- parecia defeito, que e justamente o que a regra veio
   evitar. Abaixo de 3rem nao ha o que esmaecer sem apagar o conteudo. */
.wbody .card > .list,
.wbody .card > ul {
  min-height: 0;
}
@supports (mask-image: linear-gradient(#000, #000)) {
  .wbody .card > .list:not(:empty),
  .wbody .card > ul:not(:empty) {
    -webkit-mask-image: linear-gradient(to top, transparent, #000 1.6rem);
    mask-image: linear-gradient(to top, transparent, #000 1.6rem);
  }
  /* Lista baixa demais para caber o degrade: sem mascara nenhuma. */
  .wgrid .wcell[data-wh="1"] .wbody .card > .list,
  .wgrid .wcell[data-wh="1"] .wbody .card > ul,
  .wgrid .wcell[data-wh="2"] .wbody .card > .list,
  .wgrid .wcell[data-wh="2"] .wbody .card > ul {
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* O QUE NÃO É LISTA também precisa caber ao encolher.
   O calendário, a rosca de macros, o formulário de saúde, a grade de vistos:
   nenhum deles é uma `<ul>`, então nenhum pegava a regra acima, e o
   excedente ficava atrás da borda do card -- inalcançável, porque
   `.wbody > .card` tem `overflow: hidden`.
   Com o card rolando, o widget encolhido mostra o começo e a pessoa desce,
   que é o pior caso aceitável. O alternativo era esconder conteúdo, e
   esconder é o que faz um widget pequeno deixar de servir. */
.wbody > .card { overflow-y: auto; }
/* O cabeçalho fica: é ele que diz de que widget se trata, e ele já não
   encolhe (`flex: none` acima). */
.wbody > .card > .row-between,
.wbody > .card > h3 { position: sticky; top: 0; z-index: 1;
                      background: var(--surface); }

/* Dentro de um widget as métricas ficam sempre numa linha só. O auto-fit
   embrulhava para 3+1 quando a largura apertava, dobrando a altura necessária
   e cortando os números pela metade. */
.wbody > .grid {
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  grid-auto-flow: column;
  grid-auto-rows: minmax(0, 1fr);
  margin-bottom: 0 !important;   /* a margem inline sobraria dentro da célula */
}
.wbody > .grid > * { min-height: 0; overflow: hidden; }

/* Espremido, o cartão preserva o essencial — que número é este e quanto vale.
   Meta e barra saem primeiro; o ícone colorido fica, senão sobrariam quatro
   números sem dizer qual é qual. */
.wbody .stat { padding: .6rem .7rem; justify-content: center; }
.wgrid .wcell[data-wh="1"] .stat {
  display: flex; flex-direction: row; align-items: center; gap: .4rem;
  padding: .35rem .6rem;
}
.wgrid .wcell[data-wh="1"] .stat .stat-head { margin: 0; }
.wgrid .wcell[data-wh="1"] .stat .stat-label,
.wgrid .wcell[data-wh="1"] .stat .stat-goal,
.wgrid .wcell[data-wh="1"] .stat .bar { display: none; }
.wgrid .wcell[data-wh="1"] .stat .stat-value { font-size: 1.05rem; }
.wgrid .wcell[data-wh="2"] .stat { padding: .45rem .7rem; }
.wgrid .wcell[data-wh="2"] .stat .stat-goal,
.wgrid .wcell[data-wh="2"] .stat .bar { display: none; }
.wgrid .wcell[data-wh="2"] .stat .stat-head { margin-bottom: .15rem; }
.wgrid .wcell[data-wh="2"] .stat .stat-value { font-size: 1.35rem; }
/* Sem a barra de meta o card fica com o número colado no topo e um vão
   embaixo, porque `.stat` é uma coluna flex e nada mais ocupa o espaço.
   Centrar distribui a sobra em cima e embaixo do número. */
.wgrid .wcell[data-wh="2"] .stat { justify-content: center; }

/* ESTREITO, e não baixo: a altura já tinha os degraus acima, mas a largura
   mínima era de duas colunas e os cards de indicador não encolhiam além de
   um sexto da tela. Agora vão a uma coluna, e aqui o conteúdo acompanha.

   Container query, e não media query: o que importa é a largura do CARD, e
   não a da janela — o mesmo widget pode estar largo numa tela pequena. */
/* `size`, e não `inline-size`: as duas dimensões. `inline-size` mede só a
   largura, e uma consulta por `min-height` nunca casa -- foi o que deixou os
   últimos lançamentos do Saldo do mês invisíveis mesmo num card alto.
   A célula já tem tamanho próprio dado pela grade, então declarar a altura
   como contenção não a deixa colapsar.

   MAS isso só vale no DESKTOP. `container-type: size` obriga o navegador a
   resolver a altura sem olhar para dentro, e no celular a altura vinha só do
   `grid-row`, que o media query acima apaga: sem grade e sem conteúdo para
   medir, toda célula resolvia para ZERO e a tela inicial virava uma pilha de
   contornos vazios sobrepostos. Valia para qualquer janela abaixo de 860px,
   não só para celular.

   Abaixo de 860px a contenção passa a ser só de largura: as consultas por
   `min-height` deixam de casar (o widget está empilhado e cresce com o
   conteúdo, então não há altura fixa para consultar), e a altura volta a
   sair do que está dentro. */
.wcell { container-type: size; }

@media (max-width: 859px) {
  .wcell { container-type: inline-size; }
}

@container (max-width: 92px) {
  /* O rótulo perde a palavra inteira antes de o número perder um dígito:
     "2.000" sem "Passos" ainda é legível ao lado do ícone colorido, que é
     quem diz o que aquilo mede.

     O limiar era 130px, e escondia rotulo que CABIA: medido num card de
     96px, "Passos" pede 67px do cabecalho e ha 72 disponiveis -- os quatro
     indicadores da fileira estreita ficavam sem nome a toa, e quem chegava
     na tela via quatro numeros sem legenda. A 92px o mais largo comeca a
     apertar de verdade. */
  .stat-head .stat-label { display: none; }
  /* CENTRADO, e não colado à esquerda. `.stat` é uma coluna flex alinhada
     ao início: com o rótulo fora, sobrava o ícone e o número num canto e um
     vão do tamanho do card à direita. Centrar distribui a sobra dos dois
     lados, que é o que faz um card estreito parecer um card e não um
     pedaço cortado de um maior. */
  .stat {
    padding: .4rem .45rem;
    align-items: center;
    justify-content: center;
    text-align: center;
  }
  .stat-head { margin-bottom: .2rem; justify-content: center; }
  .stat-value { font-size: 1.05rem; }
  .stat-goal, .stat .bar { display: none; }
  /* A unidade em cima do número, e não ao lado: "2.001 ml" não cabe numa
     linha de 130px, e cortar o número seria perder o dado. */
  .stat-unit { display: block; margin: 0; font-size: .72rem; }
  /* O humor é o único indicador cujo "valor" é um emoji com a palavra ao
     lado. Empilhar os dois é o que cabe. */
  .stat-value { display: flex; flex-direction: column; align-items: center;
                gap: .1rem; }
}

@container (max-width: 90px) {
  /* Uma coluna. Sobra o ícone e o número, que é o mínimo que ainda informa. */
  .stat { padding: .3rem .35rem; }
  .stat-value { font-size: .95rem; }
  .stat-extra { display: none; }
}

/* ------------------------------------------- saldo do mês

   Os últimos lançamentos, que preenchem o card quando ele é alto. Ficam
   ESCONDIDOS por padrão e aparecem só com altura: num widget baixo o saldo
   e os três totais é o que cabe, e espremer uma lista ali cortaria as duas
   coisas. */
.fin-ultimos { display: none; }
@container (min-height: 210px) {
  .fin-ultimos {
    display: block;
    margin-top: .7rem;
    border-top: 1px solid var(--border);
    padding-top: .2rem;
  }
  .fin-ultimos li {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem 0;
    font-size: .8rem;
  }
  .fin-dia { flex-shrink: 0; color: var(--text-faint); font-size: .72rem; }
  .fin-nome {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .fin-valor { flex-shrink: 0; font-weight: 500; }
  .fin-valor.entrou { color: var(--ok-text); }
  .fin-valor.saiu { color: var(--err-text); }
}

/* O widget do parceiro, estreito: sobra a FOTO e o BOTÃO.
   O nome sai porque a foto já diz de quem é, e a frase de apoio ("Ver como
   está o dia") descreve o que o botão faz -- num card de 200px ela gastava
   duas linhas para repetir a palavra que está no botão. O título "Acompanhar"
   fica: é ele que diz de que widget se trata. */
@container (max-width: 230px) {
  /* Estreito, o card do parceiro fica com a FOTO a esquerda e o botao a
     direita, na mesma linha -- e nao empilhado.

     Empilhado (avatar em cima, botao embaixo) o conteudo passava de 100px de
     altura, e num card de duas linhas de grade isso nao cabe: o titulo
     "Acompanhar" era empurrado para fora e aparecia cortado pela metade.
     Lado a lado a altura cai pela metade e sobra espaco para o titulo. */
  .card-parceiro .parceiro-quem { display: none; }
  .card-parceiro .row-between {
    flex-direction: row !important;
    align-items: center !important;
    gap: .5rem;
  }
  .card-parceiro .row { justify-content: flex-start; flex: none; }
  .card-parceiro .btn { flex: 1; min-width: 0; padding-inline: .4rem; }
}

/* Uma coluna so: nao ha largura para a foto E o botao lado a lado -- o
   botao era espremido a 25px e "Abrir" saia cortado. Aqui a foto sai e
   sobra o botao, que e a unica acao do card. O titulo diz de quem e. */
@container (max-width: 150px) {
  .card-parceiro .avatar { display: none; }
  .card-parceiro .row-between { flex-direction: column !important; }
  .card-parceiro .btn { width: 100%; flex: none; }
}

/* `row-between` num card estreito vira duas colunas de nada com um buraco
   no meio. Empilhar resolve — mas SÓ onde os dois lados são conteúdo de
   verdade, como no widget do parceiro (avatar + nome de um lado, botão do
   outro).

   O CABEÇALHO de um card não entra: ali o `row-between` é um título e um
   ícone de engrenagem, e empilhá-los gastava duas linhas para mostrar o
   mesmo — no widget do Caderno isso comia a altura que a LISTA precisava, e
   um widget de atalhos sem nenhum atalho visível é um widget que não serve.
   Por isso a regra pede `.linha-dupla`, marcada onde empilhar ajuda. */
/* O widget do parceiro, estreito: sobra a FOTO e o BOTÃO.
   O nome sai porque a foto já diz de quem é, e a frase de apoio ("Ver como
   está o dia") descreve o que o botão faz -- num card de 200px ela gastava
   duas linhas para repetir a palavra que está no botão. O título "Acompanhar"
   fica: é ele que diz de que widget se trata. */
@container (max-width: 230px) {
  .card-parceiro .parceiro-quem { display: none; }
  .card-parceiro .row-between { gap: .6rem; }
  .card-parceiro .row { justify-content: center; }
}

/* `row-between` num card estreito vira duas colunas de nada com um buraco
   no meio. Empilhar resolve — mas SÓ onde os dois lados são conteúdo de
   verdade, como no widget do parceiro (avatar + nome de um lado, botão do
   outro).

   O CABEÇALHO de um card não entra: ali o `row-between` é um título e um
   ícone de engrenagem, e empilhá-los gastava duas linhas para mostrar o
   mesmo — no widget do Caderno isso comia a altura que a LISTA precisava, e
   um widget de atalhos sem nenhum atalho visível é um widget que não serve.
   Por isso a regra pede `.linha-dupla`, marcada onde empilhar ajuda. */
/* ------------------------------------------- saldo do mês

   Os últimos lançamentos, que preenchem o card quando ele é alto. Ficam
   ESCONDIDOS por padrão e aparecem só com altura: num widget baixo o saldo
   e os três totais é o que cabe, e espremer uma lista ali cortaria as duas
   coisas. */
.fin-ultimos { display: none; }
@container (min-height: 210px) {
  .fin-ultimos {
    display: block;
    margin-top: .7rem;
    border-top: 1px solid var(--border);
    padding-top: .2rem;
  }
  .fin-ultimos li {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem 0;
    font-size: .8rem;
  }
  .fin-dia { flex-shrink: 0; color: var(--text-faint); font-size: .72rem; }
  .fin-nome {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .fin-valor { flex-shrink: 0; font-weight: 500; }
  .fin-valor.entrou { color: var(--ok-text); }
  .fin-valor.saiu { color: var(--err-text); }
}

/* O widget do parceiro, estreito: sobra a FOTO e o BOTÃO.
   O nome sai porque a foto já diz de quem é, e a frase de apoio ("Ver como
   está o dia") descreve o que o botão faz -- num card de 200px ela gastava
   duas linhas para repetir a palavra que está no botão. O título "Acompanhar"
   fica: é ele que diz de que widget se trata. */
@container (max-width: 230px) {
  .card-parceiro .parceiro-quem { display: none; }
  .card-parceiro .row-between { gap: .6rem; }
  .card-parceiro .row { justify-content: center; }
}

@container (max-width: 260px) {
  .wbody > .card > .row-between.linha-dupla {
    flex-direction: column;
    align-items: stretch;
    /* Mais folga que os .5rem de antes: empilhado num card estreito, o
       avatar ficava colado no titulo e o botao quase encostando na borda de
       baixo -- o card lia como apertado, nao como composto. */
    gap: .7rem;
    padding-block: .2rem;
  }
  .wbody > .card > .row-between.linha-dupla > .row { justify-content: center; }
  .wbody > .card > .row-between.linha-dupla .btn,
  .wbody > .card > .row-between.linha-dupla .btn-primary { width: 100%; }
}

/* Em alturas pequenas o padding de 1rem sozinho já consome metade da linha. */
.wgrid .wcell[data-wh="1"] .wbody > .card { padding: .5rem .8rem; }
.wgrid .wcell[data-wh="1"] .wbody > .card > .row-between { margin-bottom: .2rem; }
.wgrid .wcell[data-wh="1"] .wbody > .grid { gap: .35rem; }

/* Modo organizar */
.wgrid.editing {
  background-image:
    repeating-linear-gradient(to right,
      color-mix(in srgb, var(--accent) 6%, transparent) 0 1px,
      transparent 1px calc((100% - 132px) / 12 + 12px));
  border-radius: var(--r);
}
.wgrid.editing .wcell {
  outline: 1px dashed color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 2px;
  border-radius: var(--r);
}
.wgrid.editing .wbody { pointer-events: none; opacity: .75; }

/* A barra flutua sobre o widget em vez de empilhar acima dele: somada à
   altura, ela consumia os 48px inteiros de uma linha e o conteúdo do widget
   sumia no modo organizar — justo quando a pessoa precisa vê-lo para decidir
   o tamanho. Sobreposta, o que se arrasta é do tamanho do que se vê. */
.wbar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  display: flex; align-items: center; gap: .4rem;
  padding: .25rem .4rem;
  background: color-mix(in srgb, var(--surface-2) 92%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  font-size: .72rem;
}
.wname {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-dim);
  font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
}
.wgrip { cursor: grab; color: var(--text-faint); user-select: none; padding: 0 .1rem; }
.wgrip:active { cursor: grabbing; }

/* A alca de redimensionar: uma MARCA DE CANTO, nao um L laranja.
   Com 16px e traco de 2px ela era a coisa mais visivel de cada widget no
   modo Organizar -- num card pequeno tomava um sexto da borda, e num grande
   como o mini calendario continuava um gancho grosso no canto. Menor e mais
   fina, ela diz onde pegar sem competir com o conteudo.

   A AREA DE ARRASTO nao encolhe junto: o `::after` estende o alvo do
   ponteiro para 20px, que e o que a mao precisa acertar. Encolher o desenho
   e o alvo juntos tornaria o gesto dificil. */
.whandle {
  position: absolute;
  right: -1px; bottom: -1px;
  width: 10px; height: 10px;
  cursor: nwse-resize;
  border-right: 1.5px solid var(--accent);
  border-bottom: 1.5px solid var(--accent);
  border-bottom-right-radius: var(--r-sm);
  opacity: .55;
}
.whandle::after {
  content: '';
  position: absolute;
  right: -5px; bottom: -5px;
  width: 20px; height: 20px;
}
.whandle:hover { opacity: 1; }

.wmoving { z-index: 5; opacity: .85; }
.wmoving .wbody { box-shadow: 0 8px 24px rgb(0 0 0 / 18%); }

/* Sem arrastar no celular: não há espaço para posicionar em duas dimensões. */
@media (max-width: 859px) {
  .whandle { display: none; }
  .wgrip { cursor: default; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 1rem;
  box-shadow: var(--shadow);
}

.grid { display: grid; gap: .75rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

.row { display: flex; align-items: center; gap: .6rem; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.wrap-row { flex-wrap: wrap; }
.spacer { flex: 1; }

.stack > * + * { margin-top: .75rem; }
.muted { color: var(--text-dim); }
.small { font-size: .8rem; }
.center { text-align: center; }
.hidden { display: none !important; }

/* Rótulo de seção: caixa alta discreta, no lugar de título com emoji. */
.eyebrow {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Título de widget que leva para a aba de origem. Herda tudo do .eyebrow para
   parecer texto comum, e só o hover revela que é clicável. */
.eyebrow-link {
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.eyebrow-link:hover,
.eyebrow-link:focus-visible { color: var(--accent-text); }

/* ---------------------------------------------------------------- cabeçalho */

header.topbar {
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 30;
}
.topbar-inner {
  max-width: 1320px;
  margin: 0 auto;
  padding: .6rem 1.2rem;
  display: flex;
  align-items: center;
  gap: .6rem;
}
.topbar-text { min-width: 0; }
.hub-title,
.topbar-text .small {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hub-title { font-weight: 600; font-size: .9rem; letter-spacing: -0.01em; }

/* Quantos dias de teste restam, ao lado da saudação.

   Fica no cabeçalho e não num banner porque precisa estar sempre à vista sem
   ocupar espaço: quem está testando tem de saber quanto falta sem procurar, e
   um banner seria fechado no primeiro dia e nunca mais visto.

   Discreto enquanto sobra tempo, laranja nos dois últimos dias — a mesma
   fronteira do aviso em janela, para os dois falarem a mesma língua. */
.selo-teste {
  display: inline-block;
  margin-left: .4rem;
  padding: .1rem .4rem;
  border-radius: var(--r-pill);
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
  vertical-align: baseline;
}
/* O "ou" entre as duas saídas do fim de teste, com um fio de cada lado. */
.fim-ou {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin: 1.1rem 0 .8rem;
}
.fim-ou::before,
.fim-ou::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* `btn-ghost` é transparente e sem borda — bom para um "Cancelar", fraco
   demais para "Ativar", que continua sendo uma ação de verdade. A borda o
   devolve ao lugar certo: visível, sem competir com o botão cheio. */
.btn-contorno {
  border-color: var(--border);
  color: var(--text);
}
.btn-contorno:hover { border-color: var(--accent); color: var(--text); }

.selo-teste.acabando {
  color: var(--accent-text);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: .95rem;
  background: var(--surface-2);
  color: var(--accent-text);
  border: 1px solid var(--border-strong);
  flex-shrink: 0;
}
.avatar-sm { width: 26px; height: 26px; font-size: .8rem; }

/* Os três tamanhos que a pessoa escolhe. O médio é o padrão e não tem regra
   própria: é o `.avatar` acima, para quem já usa o Hub não ver o ícone mudar
   sozinho numa atualização. */
.avatar-s { width: 24px; height: 24px; font-size: .72rem; }
/* Na escolha de quem entra, o avatar é o assunto da tela. */
.avatar-login { width: 52px; height: 52px; font-size: 1.5rem; }
.avatar-g { width: 44px; height: 44px; font-size: 1.35rem; }

nav.tabs {
  display: flex;
  gap: .1rem;
  overflow-x: auto;
  /* Sem padding lateral, e a largura ja descontada das margens da coluna.
     A caixa que ROLA tem de ser a que RECORTA. Com `padding: 0 1.2rem` o
     padding empurrava as abas para dentro, mas seguia sendo area pintavel da
     propria caixa rolavel -- as abas passavam por cima dele ao rolar.
     Assim a borda da caixa cai exatamente sobre o limite dos widgets, e e
     nela que o `overflow-x` corta: medido, o ultimo pixel de aba fica em
     1180, 1340 e 1600 para colunas que terminam em 1181, 1341 e 1601. */
  max-width: min(calc(1320px - 2.4rem), calc(100vw - 2.4rem));
  margin: 0 auto;
  padding: 0;
  scrollbar-width: none;
  /* As abas CENTRADAS quando a barra rola (abaixo de 980px o espalhamento
     sai de cena, ver o `@media` mais abaixo). Encostadas a esquerda sobrava
     um vazio de um lado so.

     `safe center` e o que faz isso conviver com a rolagem: com `center`
     puro, quando as abas nao cabem, o navegador corta pelos DOIS lados e as
     primeiras ficam inalcancaveis - nem rolando. O `safe` desiste de centrar
     nesse caso e volta a alinhar pelo comeco, que e o que se pode rolar. */
  justify-content: safe center;
  /* Um esmaecido nas pontas quando há aba escondida. No celular o dedo
     arrasta e a pessoa descobre sozinha; no PC, com a barra de rolagem
     oculta, nada indicava que existiam mais três abas depois de "Vagas" —
     numa janela estreita elas simplesmente sumiam.

     `background-attachment: local` prende o degradê ao CONTEÚDO, então ele
     acompanha a rolagem e some sozinho ao chegar ao fim, sem JavaScript.

     Havia um segundo par, de sombras `radial-gradient` presas à moldura
     (`scroll`), para reforçar a borda. Elas apareciam SEMPRE — inclusive com
     todas as abas visíveis, que é o caso comum no desktop.

     E o esmaecido usava `--bg`, a cor da PÁGINA, sobre uma barra que é
     `--surface`: no escuro isso é #0b0d11 sobre #14171d, ou seja, uma mancha
     mais escura que o fundo dela. Os dois juntos eram a sombra visível nas
     pontas. Com `--surface` o degradê some quando não há o que esconder, que
     era a intenção desde o começo. */
  /* O esmaecido das pontas usa a MESMA mascara da barra de subabas, ligada
     por `marcaPontasDaBarra`: ela so aparece do lado que tem aba fora da
     vista e some quando a rolagem chega ao fim.

     Antes era um degrade pintado com `--surface`. Ali a cor ate acerta (esta
     barra fica sobre `--surface`), mas duas solucoes para o mesmo problema
     significam corrigir duas vezes - e foi na copia dela, nas subabas, que a
     cor errada virou brilho sobre a pagina. */
}
.tabs.fade-esq {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 2rem);
  mask-image: linear-gradient(to right, transparent, #000 2rem);
}
.tabs.fade-dir {
  -webkit-mask-image: linear-gradient(to left, transparent, #000 2rem);
  mask-image: linear-gradient(to left, transparent, #000 2rem);
}
.tabs.fade-esq.fade-dir {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 2rem,
                        #000 calc(100% - 2rem), transparent);
  mask-image: linear-gradient(to right, transparent, #000 2rem,
                #000 calc(100% - 2rem), transparent);
}
nav.tabs::-webkit-scrollbar { display: none; }

/* No desktop as abas ocupam a barra em vez de se amontoarem à esquerda,
   deixando quase 500px vazios à direita. No celular continuam compactas e
   roláveis, onde cada aba precisa do próprio tamanho.

   `flex: 1 1 0` dava a MESMA largura a todas: como os rótulos têm tamanhos
   diferentes, a última sobrava e parecia deslocada. Com `auto` a base é o
   conteúdo, e o espaço extra é dividido em proporção — todas ficam com o
   mesmo respiro em volta do texto. */
/* Espalhar as abas pela barra em vez de amontoá-las à esquerda só faz
   sentido quando elas CABEM. Com dez abas ligadas são 964px de conteúdo, e
   entre 860 e 963 o `space-between` espremia todas para caber, cortando
   rótulo. Abaixo de 860 a barra rolava, mas sem barra de rolagem visível e
   sem gesto de arrastar no PC: três abas sumiam sem nada indicar.

   O `min-width: 980px` cobre as duas faixas: acima disso as abas se
   espalham porque sobra espaço; abaixo, rolam com o degradê da borda
   avisando que há mais. E `overflow-x: auto` fica de pé em toda largura,
   então a roda do mouse e o arrasto funcionam. */
/* A sobra vira VAO entre as abas, e nao padding dentro delas.
   Com `flex: 1 1 auto` cada aba engordava em proporcao a propria largura, e
   o padding extra da PRIMEIRA e da ULTIMA so tinha vizinha de um lado: os
   vaos medidos ficavam 13, 2, 2, 2, 2, 2, 2, 2, 2, 13 px -- os das pontas
   seis vezes maiores, que e o espaco sobrando ao lado de "Produto".
   Repartindo pelo `gap`, todos os vaos saem iguais. */
@media (min-width: 980px) {
  /* `space-between` com as abas SEM crescer (`flex: 0 0 auto`): a sobra vira
     vao, e como nenhuma aba engorda os vaos saem todos iguais.

     Foi `flex: 1 1 auto` que os desigualava antes -- cada aba crescia em
     proporcao a propria largura, e os vaos mediam 13, 2, 2, 2, 2, 2, 2, 2,
     2, 13 px, os das pontas seis vezes maiores.

     E `space-between`, e nao `center`, porque as duas pontas precisam
     encostar na coluna de conteudo: centrado, com as onze abas cabendo, o
     "Produto" parava 75px antes da borda enquanto o "Inicio" alinhava. Como
     bonus ele nao tem o defeito do `center` puro, que quando o conteudo nao
     cabe corta pelos DOIS lados e deixa a primeira aba fora do alcance da
     rolagem: `space-between` se comporta como `flex-start` nesse caso.

     O `gap` e PISO, para os vaos nao sumirem de todo quando o espaco aperta
     -- a sobra, quando ha, e distribuida por cima dele. */
  /* O espalhamento agora e ESCOLHA, e nao regra fixa: `data-espaco` no
     `<html>` diz qual, e vale para as duas barras -- em cima e embaixo. */
  :root[data-espaco="espalhar"] nav.tabs {
    justify-content: space-between;
    gap: .55rem;
  }
  nav.tabs .tab { flex: 0 0 auto; }

  /* Com POUCAS abas elas se juntam no meio, em vez de se espalharem pela
     coluna inteira. `space-between` reparte a sobra pelos vaos: com cinco
     abas numa linha de 1300px isso da mais de 200px entre uma e outra, e a
     barra deixa de se ler como um grupo -- cada rotulo vira uma ilha, e o
     olho nao encontra o conjunto.

     O criterio nao e a CONTAGEM, e o VAO que sairia. Medido a 1400px de
     janela: seis abas dao 156px de vao, oito dao 85, dez dao 30. Cortar por
     numero de abas erra porque os rotulos tem larguras diferentes -- seis
     abas de nome curto sobram mais que oito de nome longo.

     `justify-content: center` com um `gap` grande faz as duas coisas de uma
     vez: quando o conteudo mais os vaos de 1.75rem cabem com folga, as abas
     ficam juntas no meio; quando nao cabem, o `space-between` do bloco acima
     e que vale. O `:has()` compara o quanto a barra esta cheia. */
  :root[data-espaco="espalhar"] nav.tabs:not(:has(.tab:nth-child(7))) {
    justify-content: center;
    gap: 1.75rem;
  }

  /* JUNTAR: as abas viram um bloco no centro, em qualquer quantidade. */
  :root[data-espaco="juntar"] nav.tabs {
    justify-content: safe center;
    gap: 1.4rem;
  }
}

/* Aba ativa marcada por sublinhado, não por pílula colorida — menos peso
   visual e mais próximo de ferramenta que de app de bem-estar. */
.tab {
  border: none;
  background: transparent;
  color: var(--text-dim);
  padding: .55rem .7rem;
  border-radius: 0;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  min-height: 38px;
  font-size: .85rem;
  gap: .4rem;
}
.tab:hover { background: transparent; color: var(--text); }
.tab.active {
  color: var(--text);
  border-bottom-color: var(--accent-text);
  font-weight: 500;
}
.tab .ico { opacity: .7; }
.tab.active .ico { opacity: 1; color: var(--accent-text); }

/* --------------------------------------------------------------- indicadores */

/* Coluna com o rodapé embaixo: cards sem barra de meta ficariam mais curtos e
   desalinhariam a fileira. */
.stat { padding: .9rem; display: flex; flex-direction: column; }
/* A fileira de indicadores do topo de Financas: os cinco cards tem a mesma
   ALTURA (125px), mas conteudo de 42 a 76px -- tres tem so rotulo e numero,
   e "Patrimonio" e "Investido" trazem uma ou duas linhas de apoio. Alinhados
   ao topo, a sobra caia toda embaixo e os cards curtos ficavam com um vao,
   o que lia como desalinho numa fileira que deveria ser regular.
   Centrado, a sobra se divide em cima e embaixo e os numeros se alinham
   entre si, que e o que o olho percorre. */
/* A fileira de indicadores alinha pelo TOPO, nao pelo centro.
   Centrado, um card sem barra de meta (o Peso) descia o numero 17px em
   relacao aos vizinhos, e a fileira perdia a linha de base -- o olho corre
   os valores na horizontal, e um fora do lugar chama mais atencao que o
   proprio dado. O que sobra vai para baixo, igual em todos. */
.grid-4 > .card.stat { justify-content: flex-start; }

/* O NUMERO do card, editavel: um campo que nao parece um campo ate ser
   tocado. Ele mostra o valor no mesmo tamanho e peso do numero que
   substituiu -- se parecesse uma caixa de formulario, a fileira de
   indicadores viraria um formulario de cinco campos. */
.stat-campo {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  font-variant-numeric: inherit;
  text-align: center;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-xs);
  padding: 0 .15rem;
  margin: 0;
  min-height: 0;
  /* A largura acompanha o CONTEUDO, e nao a caixa.
     Sem isto o campo tomava a linha inteira: a unidade era empurrada para
     baixo, caia em cima da meta e o card virava tres linhas sobrepostas.

     `field-sizing` faz isso nativamente; onde nao ha suporte, o `size=1` do
     HTML ja deixa o campo estreito e o `width: auto` impede que o
     `width: 100%` herdado dos inputs do Hub o estique. */
  field-sizing: content;
  width: auto;
  min-width: 2ch;
  max-width: 6ch;
}
.stat-campo:hover { border-color: var(--border); }
.stat-campo:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface-2);
}
/* As setinhas do campo numerico saem: elas apareceriam no lugar do numero
   ao passar o mouse, e ninguem ajusta passos de um em um. */
.stat-campo::-webkit-outer-spin-button,
.stat-campo::-webkit-inner-spin-button { appearance: none; margin: 0; }

/* "Anotar o dia" numa linha: rotulo, os campos que sobraram e o Salvar.
   Eram quatro campos altos empilhados em duas colunas e um Salvar de ponta
   a ponta -- cinco linhas de formulario para os mesmos quatro valores que
   os cards do topo ja mostram (e onde agora tambem se digita). */
.anotar-linha {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: .5rem .9rem;
}
.anotar-linha > .eyebrow { align-self: center; margin-right: .2rem; }
.anotar-campo {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  flex: 1 1 7rem;
  min-width: 0;
}
.anotar-campo > span {
  font-size: .72rem;
  color: var(--text-dim);
}
.anotar-campo > input { margin: 0; }
.anotar-linha > button { flex: none; }

/* O Google conectado numa linha, e nao num card: ver `viewHealthGoogle`. */
.google-linha {
  gap: .6rem;
  align-items: center;
  margin-top: 1rem;
  color: var(--text-dim);
}
.google-linha .ico { vertical-align: -2px; }

/* O CONTEUDO do card de indicador e CENTRADO na horizontal.
   Encostado a esquerda, "7 h" ficava num canto de um card de 250px, com
   dois tercos de vazio a direita -- e o rotulo, o valor e a meta formavam
   uma coluna estreita grudada na borda em vez de um bloco no meio do
   cartao. A barra de meta continua de ponta a ponta: ela e uma regua, e
   encolhe-la ao tamanho do texto tiraria a referencia de quanto falta. */
.grid-4 > .card.stat,
.wgrid .wcell .wbody > .card.stat { align-items: center; text-align: center; }
.grid-4 > .card.stat > .bar,
.wgrid .wcell .wbody > .card.stat > .bar { align-self: stretch; }
.stat .bar { margin-top: auto; }
.stat-goal { margin-top: .3rem; }
.stat-head {
  display: flex; align-items: center; gap: .4rem;
  /* O rotulo do indicador e SEMPRE neutro. A cor da metrica vive no
     `.stat-ico` ao lado, que e um ponto pequeno e nao disputa com o numero.
     Cinco cards lado a lado com cinco titulos coloridos era o que dava a
     faixa um ar de mosaico. */
  color: var(--text-dim);
  margin-bottom: .5rem;
}
/* O icone guarda a identidade da metrica -- agua azul, sono roxo -- que e o
   que se reconhece de relance. `flex: none` porque ele nao encolhe quando o
   rotulo e longo. */
.stat-ico { display: inline-flex; flex: none; }
.stat-label {
  font-size: .72rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
}
.stat-value {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  /* Numero e unidade compartilham UMA linha de base.
     Sem o flex, cada um ganhava a sua caixa de linha e a unidade, menor,
     era centrada na propria caixa -- ficava no meio da altura do numero em
     vez de assentada nele. */
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  /* ALTURA FIXA, para a linha de base cair no MESMO ponto nos cinco cards.
     Sem ela, cada valor tinha a altura do proprio conteudo: "300 passos" e
     "77,5 kg" desciam ate 103px por causa do "p" e do "g", "1.400 ml" e
     "0 h" paravam em 92, e o rosto do Humor comecava 4px mais alto. A caixa
     de cada um comecava no mesmo topo, mas a MANCHA -- que e o que o olho
     compara -- ficava em alturas diferentes.

     1.5rem de fonte com 1.05 de entrelinha da a caixa da linha; o resto e a
     folga da unidade, que assenta na base junto com o numero. */
  height: 1.75rem;
  align-content: baseline;
  overflow: visible;
}
/* A unidade fica ao lado de um numero de 1.5rem. Em --text-faint e peso 400
   ela quase sumia, e "1.400" sem o "ml" e um numero sem grandeza -- quem bate
   o olho no card precisa dos dois. Sobe para --text-dim e peso 500: continua
   claramente secundaria em relacao ao numero, mas passa a ser legivel. */
.stat-unit {
  font-size: .82rem;
  font-weight: 500;
  color: var(--text-dim);
  margin-left: .2rem;
  /* A linha de base e a UNICA ancora estavel entre os cards.
     Tentei antes centrar a unidade na altura do numero, e nao funciona: a
     caixa de "passos" e mais alta que a de "ml" porque o "p" tem
     descendente, entao centrar as duas as poe em alturas diferentes -- foi
     o que deixou "300 passos" e "54 ml" desencontrados. O numero tambem
     muda de largura e de casas ("0 h", "1.400 ml", "77,5 kg"), e nada
     disso mexe na base.

     Ancorada na base, a unidade cai sempre no mesmo lugar em relacao ao
     numero, seja qual for a palavra e sejam quantas forem as casas. */
  align-self: baseline;
}
/* O horario do sono ao lado do numero. Em bloco proprio ele nao cabia na
   altura do card, e esticar o widget desalinhava a fileira de indicadores. */
.stat-extra { font-size: .72rem; font-weight: 400; color: var(--text-faint);
              margin-left: .45rem; white-space: nowrap; }
.stat-goal {
  font-size: .72rem; color: var(--text-faint);
  margin-top: .3rem;
  font-variant-numeric: tabular-nums;
}

.bar {
  height: 4px;
  background: var(--surface-2);
  border-radius: var(--r-pill);
  overflow: hidden;
  margin-top: .6rem;
}
.bar > span {
  display: block; height: 100%;
  border-radius: var(--r-pill);
  background: var(--accent);
  transition: width .35s cubic-bezier(.4, 0, .2, 1);
}

.badge {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .72rem; font-weight: 500;
  padding: .15rem .45rem;
  border-radius: var(--r-xs);
  background: var(--surface-2);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.badge.ok { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok-text); }
.badge.warn { background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--warn); }
.badge.err { background: color-mix(in srgb, var(--err) 12%, transparent); color: var(--err-text); }
/* Quem lidera a competição: acompanha o tema, não o verde de "deu certo". */
.badge.lider { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent-text); }

/* --------------------------------------------------------------- onboarding */

.screen-center {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 1.2rem;
}

/* Modal (position:fixed): a altura é a da janela, então o conteúdo que passa
   disso precisa rolar. Sem isto o botão Fechar de um modal alto, como o
   diagnóstico, ficava fora da tela e a única saída era clicar no fundo.
   `min-height` não serve aqui: o container cresceria junto em vez de rolar. */
.screen-center[style*="fixed"] {
  min-height: 0;
  height: 100%;
  overflow-y: auto;
  /* Alinhado ao topo quando não cabe; centralizado quando cabe. */
  align-content: safe center;
}

/* Folga no fim da rolagem, por margem no próprio painel. O `padding-bottom`
   do container é ignorado pelo navegador ao calcular o limite do scroll, e um
   `::after` entraria DENTRO do painel, não depois dele: nos dois casos o
   último botão ficava colado na borda, parecendo cortado mesmo inteiro. */
.screen-center[style*="fixed"] > .panel { margin-bottom: 2rem; }

.panel { width: 100%; max-width: 420px; }
/* A escolha de perfil respira mais: com foto, 420px deixava o rosto do
   tamanho de um emoji e ninguém se reconhecia. */
#login .panel { max-width: 460px; }

.steps { display: flex; gap: .3rem; justify-content: center; margin-bottom: 1.2rem; }
.step-dot {
  width: 20px; height: 2px; border-radius: var(--r-pill);
  background: var(--border-strong);
  transition: background .2s;
}
.step-dot.done { background: var(--accent); }

.choice {
  display: block;
  width: 100%;
  text-align: left;
  padding: .8rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  background: var(--surface);
  margin-bottom: .5rem;
  min-height: auto;
}
.choice:hover { border-color: var(--text-faint); background: var(--surface); }
.choice.selected {
  border-color: var(--accent);
  box-shadow: var(--ring);
}
.choice-title {
  font-weight: 600; font-size: .9rem;
  display: flex; align-items: center; gap: .45rem;
}
.choice-desc { font-size: .8rem; color: var(--text-dim); margin-top: .2rem; line-height: 1.45; }

/* Linha informativa: usada onde não há decisão a tomar, só explicação. */
.info-row {
  display: flex; gap: .7rem;
  padding: .8rem 0;
  border-bottom: 1px solid var(--border);
}
.info-row:last-of-type { border-bottom: none; }
.info-row .ico { color: var(--accent-text); margin-top: .15rem; }
.info-title { font-weight: 600; font-size: .85rem; }
.info-desc { font-size: .8rem; color: var(--text-dim); margin-top: .15rem; line-height: 1.45; }

/* Grade fixa de 8 em vez de flex-wrap: são 16 avatares e o wrap livre quebrava
   9 + 7 conforme a largura do modal, o que fica torto. */
.emoji-picker {
  display: grid;
  grid-template-columns: repeat(8, 38px);
  gap: .3rem;
  justify-content: center;
}
.emoji-opt {
  width: 38px; height: 38px;
  font-size: 1.05rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  padding: 0;
  min-height: 38px;
}
.emoji-opt.selected { border-color: var(--accent); box-shadow: var(--ring); }

.color-picker { display: flex; flex-wrap: wrap; gap: .4rem; justify-content: center; }
.color-opt {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid transparent;
  outline: 1px solid var(--border);
  outline-offset: 1px;
  cursor: pointer;
  padding: 0;
  min-height: 28px;
}
.color-opt.selected { outline: 2px solid var(--text); outline-offset: 2px; }

/* "Padrão do tema" não tem cor própria: metade clara, metade escura, para
   dizer sem texto que ele acompanha o claro ou o escuro do sistema. */
.color-opt.tom-auto {
  background: linear-gradient(135deg, #f4f5f7 0 50%, #16181d 50% 100%);
}

.key-input {
  font-family: var(--font-mono);
  font-size: .95rem;
  letter-spacing: .05em;
  text-align: center;
  text-transform: uppercase;
}
@media (max-width: 400px) {
  .key-input { font-size: .82rem; letter-spacing: .01em; }
}

/* ------------------------------------------------------------------ rotear */

.route-panel { text-align: center; }
.route-url {
  font-family: var(--font-mono);
  font-size: .9rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: .6rem .8rem;
  border-radius: var(--r-sm);
  word-break: break-all;
  user-select: all;
}
.qr-box {
  background: #fff;
  padding: .8rem;
  border-radius: var(--r);
  border: 1px solid var(--border);
  display: inline-block;
  margin: .8rem 0;
}
.qr-box svg { display: block; width: 170px; height: 170px; }

.dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok);
  display: inline-block;
  margin-right: .3rem;
  vertical-align: middle;
}

/* Nota explicativa — informa uma limitação, sem alarmar como um aviso. */
.note {
  display: flex; gap: .6rem;
  text-align: left;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: .7rem .8rem;
  font-size: .8rem;
  color: var(--text-dim);
  line-height: 1.5;
}
.note .ico { color: var(--text-faint); margin-top: .1rem; }
.note strong { color: var(--text); font-weight: 600; }

/* Botão com aparência de link, para ações secundárias dentro de um texto. */
.linkish {
  border: none;
  background: none;
  padding: 0;
  min-height: 0;
  font: inherit;
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  display: inline;
}
.linkish:hover { background: none; filter: brightness(1.15); }

/* ------------------------------------------------------------ config modal */

/* Altura limitada com rolagem interna: o menu cresceu além da tela e o
   conteúdo do fim ficava inalcançável, sem barra de rolagem na janela. */
.cfg-modal {
  display: flex;
  flex-direction: column;
  max-height: min(84vh, 640px);
  padding: 1rem 0 0;
}
.cfg-modal > h2 { padding: 0 1rem .8rem; }

/* Escolha de tipo (investimento). Botões em linha que quebram sozinhos: um
   <select> escondia as opções, e aqui a pessoa vê tudo que existe de uma vez. */
.pick-grid { display: flex; flex-wrap: wrap; gap: .35rem; }
.pick {
  font-size: .82rem;
  padding: .4rem .7rem;
  min-height: 34px;
  border-radius: var(--r-pill);
  color: var(--text-dim);
}
.pick:hover { color: var(--text); }
.pick.active {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: var(--accent);
  color: var(--accent-text);
  font-weight: 600;
}

/* Gráfico de entradas x saídas.
   SVG, não divs com altura em porcentagem: a versão anterior media contra um
   flex sem altura resolvida e as barras viravam linhas de 1px. */
/* Gráfico de entradas x saídas.
   Altura em PX, calculada no JS: a primeira versão usava % dentro de um flex
   sem altura resolvida e as barras viravam linhas de 1px. */
/* Data em três caixas: dia/mês/ano nunca troca de ordem, ao contrário do
   <input type="date">, que segue o idioma do navegador do cliente. */
/* Critério de ordenação em uso. */
.sort-on {
  color: var(--accent-text);
  font-weight: 600;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* Campo com sugestões que abrem no PRIMEIRO clique. O <datalist> nativo só
   abre no segundo, e a pessoa conclui que não há sugestão nenhuma. */
.combo { position: relative; }
.combo-list {
  position: absolute;
  z-index: 20;
  top: calc(100% + 2px);
  left: 0; right: 0;
  max-height: 190px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: 0 6px 18px rgb(0 0 0 / 12%);
  padding: .2rem;
}
.combo-item {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  padding: .4rem .5rem;
  min-height: 32px;
  font-size: .85rem;
  border-radius: var(--r-xs);
}
.combo-item:hover { background: var(--surface-2); }

/* Categoria na lista, com o X de tirar das sugestões. O X só aparece quando o
   ponteiro passa pela linha, para a lista não virar uma parede de ícones. */
.combo-linha { display: flex; align-items: center; gap: .2rem; }
.combo-linha .combo-item { flex: 1; min-width: 0; }
.combo-x {
  flex-shrink: 0;
  border: none;
  background: none;
  color: var(--text-faint);
  padding: .25rem;
  min-height: 26px;
  border-radius: var(--r-xs);
  /* Discreto, mas nunca invisível: no toque não existe hover, e um X que só
     aparece com o ponteiro em cima é um recurso que ninguém encontra. */
  opacity: .45;
  cursor: pointer;
}
.combo-linha:hover .combo-x, .combo-x:focus-visible { opacity: 1; }
.combo-x:hover { color: var(--err-text); background: var(--surface-2); }

/* Aba sendo arrastada: fica translúcida para a pessoa ver onde vai cair. */
.tab.dragging { opacity: .4; cursor: grabbing; }
nav.tabs [data-tab] { cursor: grab; }
nav.tabs [data-tab]:active { cursor: grabbing; }

.date-field {
  /* inline-flex, não flex: como bloco a caixa esticava até a largura da
     coluna, e "07/08/2026" ficava perdido num campo enorme. */
  display: inline-flex;
  align-items: center;
  gap: .15rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  padding: 0 .4rem;
  background: var(--surface);
  min-height: 38px;
}
.date-field:focus-within { border-color: var(--accent); box-shadow: var(--ring); }
.date-field input {
  border: none;
  background: none;
  padding: .3rem 0;
  min-height: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.date-field input:focus { box-shadow: none; }
.date-field .d-day, .date-field .d-mon { width: 2.1rem; }
.date-field .d-year { width: 3.1rem; }
/* Horário: um campo só, com atalhos embaixo. Dois campos (hora e minuto)
   obrigavam a pular de caixa para escrever um horário simples. */
/* Os horários abrem ao clicar no campo, como a lista de categorias. Sempre à
   vista, a fila era mais larga que a caixa de "--:--" e escorria por baixo
   dos campos vizinhos — um bloco solto no meio do formulário, sem dono. */
.time-wrap { position: relative; display: inline-block; }
.time-field {
  display: inline-flex;
  gap: .35rem;
  padding-right: .55rem;
  color: var(--text-faint);
}
.time-field .t-input {
  width: 4.2rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

/* Flutua sobre o formulário, como a lista de categorias: ocupando espaço no
   fluxo, ela empurraria o calendário para baixo toda vez que alguém clicasse
   no campo. */
.time-quick {
  position: absolute;
  z-index: 20;
  top: calc(100% + 3px);
  left: 0;
  /* Grade de colunas iguais, não `flex-wrap`: com 18 horários o wrap deixava
     a última fila pela metade e as caixas de larguras diferentes. */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .25rem;
  width: max-content;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: 0 6px 18px rgb(0 0 0 / 12%);
  padding: .3rem;
}
.time-chip {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  border-radius: var(--r-sm);
  padding: .15rem .4rem;
  font-size: .72rem;
  min-height: 24px;
  font-variant-numeric: tabular-nums;
}
.time-chip:hover { border-color: var(--border-strong); color: var(--text); }
.time-chip.active {
  border-color: var(--accent);
  color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.date-field span { color: var(--text-faint); }

.sort-arrow { margin-left: .2rem; font-size: .9em; }

/* Ação destrutiva: vermelho só onde algo se perde de verdade. */
.btn-danger {
  background: var(--err);
  border-color: var(--err);
  color: #fff;
}
/* Precisa repetir o fundo: `button:hover` vem antes no arquivo, tem a mesma
   especificidade e por isso vencia — o vermelho virava cinza-claro com o
   texto branco por cima, e o botão ficava ilegível sob o cursor. */
.btn-danger:hover {
  background: var(--err);
  filter: brightness(1.08);
}

/* -------------------------------------------------------------- academia */

/* Nome do treino editável no próprio título: um botão "Nomear" só para isso
   era o que mais destoava da tela. */
/* A SEMANA como barra de navegacao, antes do treino: ela vinha DEPOIS do
   nome, entao se lia o nome antes de saber de que dia ele era.
   Os sete dias ocupam a linha inteira -- o contador "N dias na semana", que
   dividia espaco com eles, saiu: cada dia com treino ja tem o seu ponto, e
   contar sete e mais rapido que ler a frase. */
.gym-semana { margin-bottom: .8rem; }

/* O cabecalho do treino do dia: o nome, e as acoes que mexem NELE. */
.gym-cabeca {
  gap: .6rem;
  margin-bottom: .6rem;
  flex-wrap: wrap;
}
.gym-titulo {
  border: 1px solid transparent;
  background: transparent;
  font-size: .82rem;
  font-weight: 500;
  padding: .15rem .4rem;
  min-height: 26px;
  width: 12rem;
  border-radius: var(--r-sm);
  color: var(--text);
}
.gym-titulo::placeholder { color: var(--text-faint); font-weight: 400; }
.gym-titulo:hover { border-color: var(--border); }
.gym-titulo:focus {
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: var(--ring);
}

/* Biblioteca de exercícios: rola por dentro para o botão de salvar continuar
   visível no modal. */
.ex-lista {
  max-height: 34vh;
  overflow-y: auto;
  margin-top: .3rem;
  padding-right: .2rem;
}
.ex-grupo { margin-bottom: .6rem; }
.ex-grupo-nome {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  margin-bottom: .3rem;
}
.ex-chip {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  border-radius: var(--r-pill);
  padding: .25rem .6rem;
  font-size: .78rem;
  min-height: 30px;
}
.ex-chip:hover {
  border-color: var(--accent);
  color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* Campo numérico com − e +: no celular, mirar a setinha nativa é sofrível. */
.passo-num { display: flex; align-items: stretch; gap: .3rem; }
.passo-num .btn {
  flex: none;
  width: 38px;
  padding: 0;
  font-size: 1.05rem;
  line-height: 1;
}
.passo-num input {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}
/* As setinhas nativas competem com os botões. */
.passo-num input::-webkit-outer-spin-button,
.passo-num input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.passo-num input { -moz-appearance: textfield; }

/* ------------------------------------------------ escolher os widgets */

/* Cartões em vez de uma coluna de checkboxes: com quinze opções, a lista
   obrigava a adivinhar o que cada uma mostra. Ícone, nome e uma linha de
   explicação resolvem sem abrir nada. */
.wpick { max-height: 60vh; overflow-y: auto; margin: 0 -.2rem; padding: 0 .2rem; }

.wpick-grupo {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  margin: .9rem 0 .4rem;
}
.wpick-grupo:first-child { margin-top: 0; }

.wpick-grade {
  display: grid;
  grid-template-columns: 1fr;
  gap: .3rem;
}
@media (min-width: 560px) {
  .wpick-grade { grid-template-columns: repeat(2, 1fr); }
}

.wpick-item {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .5rem .6rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.wpick-item:hover { border-color: var(--border-strong); }
.wpick-item input { display: none; }

.wpick-item.on {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

.wpick-ico {
  flex: none;
  display: grid; place-items: center;
  width: 30px; height: 30px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-dim);
}
.wpick-item.on .wpick-ico { background: var(--accent); color: var(--sobre-accent, #fff); }

.wpick-nome { display: block; font-size: .85rem; font-weight: 500; }
.wpick-desc {
  display: block;
  font-size: .72rem;
  color: var(--text-faint);
  line-height: 1.25;
}

/* O tique só aparece no que está escolhido. */
.wpick-check { flex: none; color: var(--accent-text); opacity: 0; }
.wpick-item.on .wpick-check { opacity: 1; }

/* Paleta de cores do evento. */
.ev-color {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 2px solid transparent;
  padding: 0;
  min-height: 0;
  cursor: pointer;
}
.ev-color:hover { transform: scale(1.1); }

/* O título do evento na lista do dia é um botão, mas não deve parecer um:
   quem lê a agenda está lendo texto, e só descobre que dá para clicar ao
   passar o mouse. */
.ev-abrir {
  padding: 0;
  min-height: 0;
  font: inherit;
  color: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ev-abrir:hover { text-decoration: underline; }
.ev-color.selected {
  border-color: var(--text);
  box-shadow: 0 0 0 2px var(--surface) inset;
}

/* Botão que revela saúde e placar: precisa parecer clicável, não texto solto
   no meio do painel. */
.day-more {
  margin-top: .6rem;
  font-size: .78rem;
  min-height: 32px;
  color: var(--text-dim);
  gap: .3rem;
}
.day-more:hover { color: var(--text); }

/* ------------------------------------------------- calendário grande (mês) */

.mc-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.mc-head {
  border-bottom: none;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  margin-bottom: 1px;
}
.mc-head span {
  background: var(--surface-2);
  padding: .3rem;
  text-align: center;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-faint);
}

.mc-day {
  background: var(--surface);
  min-height: 82px;
  padding: .25rem;
  display: flex;
  flex-direction: column;
  gap: 2px;
  cursor: pointer;
  text-align: left;
}
.mc-day:hover { background: var(--surface-2); }

/* Semana e dia: a mesma grade, com as celulas altas. O mes precisa caber
   inteiro na tela; aqui sobra espaco, e e onde a pessoa le os compromissos
   um por um. */
.mc-semana .mc-day { min-height: 200px; }
.mc-um-dia { grid-template-columns: 1fr; }
.mc-um-dia .mc-day { min-height: 260px; cursor: default; }
.mc-day.other { opacity: .35; cursor: default; }
.mc-day.other:hover { background: var(--surface); }
.mc-num {
  font-size: .78rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  padding: 0 .1rem;
}
.mc-day.today .mc-num {
  background: var(--accent);
  color: var(--sobre-accent, #fff);
  border-radius: 50%;
  width: 20px; height: 20px;
  display: grid; place-items: center;
}

/* Mesma convenção do Google Agenda: evento COM hora é um ponto colorido com o
   texto ao lado; evento de dia todo é uma faixa preenchida. A cor vem do
   evento quando ele tem uma, senão do calendário de origem — é assim que se
   distingue feriado de aniversário de compromisso, sem legenda. */
.mc-ev {
  --ev: var(--accent);
  display: flex;
  align-items: center;
  gap: .2rem;
  font-size: .72rem;
  line-height: 1.3;
  padding: 1px .2rem;
  border-radius: 3px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* O ponto: `flex:none` para ele não achatar quando o título é longo. */
.mc-ev::before {
  content: '';
  flex: none;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ev);
}
.mc-ev:hover { background: color-mix(in srgb, var(--ev) 14%, transparent); }

/* Arrastar para outro dia. O cursor anuncia que o bloco se move, e o dia sob
   o ponteiro se acende: sem isso nao da para saber onde ele vai cair. */
.mc-ev[draggable="true"] { cursor: grab; }
.mc-ev.arrastando { opacity: .4; cursor: grabbing; }
.mc-day.alvo {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.mc-ev.all-day {
  background: var(--ev);
  color: #fff;
  font-weight: 500;
  padding: 1px .3rem;
}
.mc-ev.all-day::before { display: none; }
.mc-ev.all-day:hover { filter: brightness(1.08); }

.mc-hora { color: var(--text-faint); }
.mc-ev.all-day .mc-hora { color: inherit; }
.mc-mais { font-size: .72rem; color: var(--text-faint); padding-left: .25rem; }

/* No celular a grade não cabe com texto; vira ponto colorido. */
@media (max-width: 640px) {
  .mc-day { min-height: 54px; }
  .mc-ev {
    height: 4px; padding: 0;
    background: var(--ev); border-radius: 2px;
    font-size: 0; color: transparent;
  }
  .mc-ev::before { display: none; }
  .mc-mais { font-size: .72rem; }
}

/* Linha "de onde vem": rótulo à esquerda, escolha à direita. */
.src-row { padding: .4rem 0; border-bottom: 1px solid var(--border); }
.src-row:last-of-type { border-bottom: none; }
.pick.small {
  padding: .2rem .5rem;
  font-size: .78rem;
  min-height: 28px;
  border-radius: var(--r-sm);
}

/* --------------------------------------------------------------- academia */

/* Séries e repetições são o que se lê primeiro num treino, então ganham peso
   tipográfico próprio em vez de virar mais uma linha de texto miúdo. */
.gym-list { list-style: none; display: flex; flex-direction: column; gap: .1rem; }
.gym-item {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--border);
}
.gym-item:last-child { border-bottom: none; }

.gym-num {
  flex: none;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-faint);
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
}
.gym-name { font-weight: 500; }

.gym-sets {
  display: inline-flex;
  align-items: baseline;
  gap: .25rem;
  font-variant-numeric: tabular-nums;
}
.gym-figure {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text);
}
.gym-x { color: var(--text-faint); font-size: .8rem; }

.gym-cardio-ico {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--step) 14%, transparent);
  color: var(--step-text);
}

/* Ponto sob o dia que tem treino: a semana inteira se lê de relance. */
.daypick-btn.has-dot { position: relative; }
.daypick-btn.has-dot::after {
  content: '';
  position: absolute;
  left: 50%; bottom: 5px;
  transform: translateX(-50%);
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
}
.daypick-btn.active.has-dot::after { background: currentColor; }

/* Coroa de quem lidera: pequena e alinhada ao texto, sem puxar a atenção
   para si mais que o próprio nome. */
.crown {
  display: inline-flex;
  margin-right: .25rem;
  /* A coroa era um emoji, que vinha amarelo em qualquer tema. Agora e um
     icone no traco: herda a cor de quem a contem, e no placar isso e o
     acento do perfil. */
  color: var(--accent-text);
  vertical-align: -.1em;
}


/* Barra do placar: comprimento relativo ao líder do dia. */
.score-bar {
  display: block;
  height: 5px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}
.score-bar > span {
  display: block;
  height: 100%;
  border-radius: 3px;
  transition: width .25s ease;
}


/* Convite da aba Vagas: visível o bastante para ser notado uma vez, discreto
   o bastante para não competir com os dados do dia. Some ao ser dispensado. */
.jobs-hint {
  margin-bottom: .75rem;
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
  background: color-mix(in srgb, var(--accent) 4%, var(--surface));
}
.jobs-hint svg { color: var(--accent-text); flex: none; }

/* Aviso de versão nova. Verde, não azul: é notícia boa e não disputa atenção
   com o banner de vagas, que usa a cor do tema. */
.update-hint {
  border-color: color-mix(in srgb, var(--ok) 35%, var(--border));
  background: color-mix(in srgb, var(--ok) 5%, var(--surface));
}
.update-hint svg { color: var(--ok-text); flex: none; }

/* Aviso de investimento vencido, no topo de Finanças. */
.venc-hint {
  border-color: color-mix(in srgb, var(--warn) 40%, var(--border));
  background: color-mix(in srgb, var(--warn) 5%, var(--surface));
}

/* Passo a passo numerado (conectar o LinkedIn). NÃO se chama .steps: esse
   nome já é dos pontinhos de progresso do onboarding, que são flex em linha —
   reusá-lo punha as instruções em colunas lado a lado, ilegíveis. */
.howto {
  margin: 0;
  padding-left: 1.4rem;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--text-dim);
}
.howto li { margin-bottom: .45rem; }
.howto strong { color: var(--text); font-weight: 600; }
.howto kbd {
  font-family: var(--font-mono);
  font-size: .8em;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  padding: .1rem .3rem;
  color: var(--text);
}

/* Vaga ainda não vista. Um ponto basta: um selo "NOVO" em cada linha vira
   ruído quando a busca traz vinte de uma vez. */
.dot-new {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: middle;
  margin-right: .35rem;
}

/* Alternador dentro de uma aba (Vagas: encontradas / salvas). Mesma linguagem
   das abas da configuração, mas em página, sobre o fundo do conteúdo. */
.subtabs {
  display: flex;
  gap: .1rem;
  border-bottom: 1px solid var(--border);
  /* A linha para no fim das ABAS, e nao atravessa a tela.
     Solta numa linha propria, a barra esticava ate a borda e a borda de
     baixo virava um risco de ponta a ponta sob tres botoes -- sublinhando
     sobretudo o vazio a direita deles. `width: fit-content` faz a barra ter
     a largura do que ela contem; `max-width: 100%` a mantem rolavel quando
     as abas nao cabem. */
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  /* O esmaecido das pontas, para dizer que ha subaba fora da vista. Tarefas
     tem CINCO (Lista do dia, Habitos, Quadro, Caderno, Bilhetes), e numa
     janela estreita as ultimas saiam sem nada indicar que existiam.

     Feito por MASCARA, e nao por um degrade pintado por cima.

     Pintar exige saber a cor do fundo, e a barra de subabas aparece em dois
     fundos diferentes: na pagina (sobre `--bg`) e dentro de um modal (sobre
     `--surface`). Com `--surface` fixo, no tema escuro as pontas viravam uma
     mancha CLARA sobre a pagina - #14171d sobre #0b0d11 -, e a barra parecia
     descolada do resto, com brilho nas duas bordas.

     A mascara nao pinta nada: ela apaga o que passa das bordas, seja qual
     for o fundo. `mask-composite` e o que faz os dois lados conviverem - sem
     ele, o segundo gradiente substituiria o primeiro em vez de somar. */
}
/* O esmaecido das pontas so aparece quando ha subaba FORA da vista, e some
   de cada lado que ja chegou ao fim. Quem liga e desliga as classes e
   `marcaPontasDaBarra`, no JavaScript.

   Por MASCARA, e nao por um degrade pintado por cima: pintar exige saber a
   cor do fundo, e esta barra aparece em dois - na pagina (`--bg`) e dentro
   de um modal (`--surface`). Com a cor fixa que havia aqui, no tema escuro
   as pontas viravam uma mancha CLARA sobre a pagina (#14171d sobre #0b0d11),
   e a barra parecia descolada do resto, com brilho nas duas bordas. A
   mascara nao pinta nada: ela apaga, seja qual for o fundo. */
.subtabs.fade-esq {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 1.5rem);
  mask-image: linear-gradient(to right, transparent, #000 1.5rem);
}
.subtabs.fade-dir {
  -webkit-mask-image: linear-gradient(to left, transparent, #000 1.5rem);
  mask-image: linear-gradient(to left, transparent, #000 1.5rem);
}
.subtabs.fade-esq.fade-dir {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 1.5rem,
                        #000 calc(100% - 1.5rem), transparent);
  mask-image: linear-gradient(to right, transparent, #000 1.5rem,
                #000 calc(100% - 1.5rem), transparent);
}
.subtabs::-webkit-scrollbar { display: none; }
.subtab {
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: .82rem;
  padding: .45rem .7rem;
  min-height: 38px;
  border-bottom: 2px solid transparent;
  display: flex;
  align-items: center;
  gap: .35rem;
  white-space: nowrap;
  cursor: pointer;
}
.subtab:hover { color: var(--text); }
.subtab.active { color: var(--accent-text); border-bottom-color: var(--accent-text); }

.cfg-tabs {
  display: flex;
  gap: .1rem;
  padding: 0 1rem;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
  flex-shrink: 0;
}
.cfg-tabs::-webkit-scrollbar { display: none; }
.cfg-tab {
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: .82rem;
  padding: .4rem .6rem;
  min-height: 34px;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  white-space: nowrap;
}
.cfg-tab:hover { background: none; color: var(--text); }
.cfg-tab.active {
  color: var(--text);
  border-bottom-color: var(--accent-text);
  font-weight: 500;
}

.cfg-body {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
  min-height: 0;   /* sem isto o flex não deixa o filho rolar */
}

.cfg-foot {
  display: flex;
  gap: .5rem;
  padding: .8rem 1rem;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.cfg-foot > :last-child { flex: 1; }

/* Painel de ajustes que abre dentro do card, sem virar modal. */
.fold-panel { margin-top: .2rem; }
.fold-panel hr { margin: .8rem 0; }

.src-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: .2rem;
}
.src-item {
  display: flex; align-items: center; gap: .45rem;
  font-size: .82rem; font-weight: 400;
  color: var(--text);
  margin: 0; padding: .25rem 0;
  cursor: pointer;
  min-width: 0;
}
.src-item span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.src-item input {
  width: 15px; height: 15px; min-height: 15px;
  flex-shrink: 0; accent-color: var(--accent); cursor: pointer;
}

.fold { margin-top: .7rem; text-align: left; }
.fold > summary {
  cursor: pointer;
  font-size: .8rem;
  color: var(--text-dim);
  padding: .3rem 0;
  list-style: none;
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::before { content: "▸ "; color: var(--text-faint); }
.fold[open] > summary::before { content: "▾ "; }
.fold > summary:hover { color: var(--text); }

/* ---------------------------------------------------------- água / listas */

.water-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: .4rem; }
.water-btn {
  font-size: .85rem;
  font-weight: 500;
  padding: .7rem .2rem;
  min-height: 46px;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 400px) {
  .water-row { grid-template-columns: repeat(2, 1fr); }
}

.list { list-style: none; }
.list li {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem 0;
  border-bottom: 1px solid var(--border);
  font-size: .85rem;
}
.list li:last-child { border-bottom: none; }
.list input[type="checkbox"] {
  width: 16px; height: 16px; min-height: 16px;
  flex-shrink: 0; accent-color: var(--accent); cursor: pointer;
}
.done-text { text-decoration: line-through; color: var(--text-faint); }

/* ------------------------------------------------------- dieta / compras */

.daypick { display: grid; grid-template-columns: repeat(7, 1fr); gap: .2rem; }
/* TODO dia tem a sua caixa, e nao so o escolhido.
   Sem moldura, os outros seis nao pareciam clicaveis -- eram texto solto ao
   lado de um botao. Com a caixa, a fila le como o que e: sete opcoes, uma
   marcada. */
.daypick-btn {
  padding: .4rem .1rem;
  font-size: .78rem;
  min-height: 34px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-dim);
  transition: background .12s, color .12s, transform .06s;
}
.daypick-btn:hover { background: var(--surface-2); color: var(--text); }
/* O clique AFUNDA o botao. E o unico retorno imediato do gesto: a troca de
   dia repinta a tela, e sem isto nao havia nada entre o dedo e o resultado. */
.daypick-btn:active { transform: scale(.96); }
.daypick-btn.active {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
  border-color: var(--accent);
}

.meal-form input[type="time"] { width: auto; min-width: 7rem; }
.meal-form button { padding: .5rem .75rem; }

.meal-time {
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--text-dim);
  background: var(--surface-2);
  padding: .1rem .4rem;
  border-radius: var(--r-xs);
  flex-shrink: 0;
}

.icon-btn {
  min-height: 28px;
  width: 28px;
  padding: 0;
  flex-shrink: 0;
  color: var(--text-faint);
  border-color: transparent;
  background: transparent;
}
.icon-btn:hover { color: var(--err-text); background: var(--surface-2); }

.chip {
  display: inline-flex; align-items: center; gap: .25rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  padding: .2rem .35rem .2rem .55rem;
  font-size: .8rem;
}
.chip-x {
  border: none; background: transparent; cursor: pointer;
  color: var(--text-faint); padding: 0 .1rem;
  min-height: auto; line-height: 1;
}
.chip-x:hover { color: var(--err-text); background: transparent; }

/* O comando de terminal que o Linux precisa: monoespaçado e selecionável,
   porque copiar à mão é o caminho reserva quando a área de transferência
   não está disponível. */
.cmd-linha {
  flex: 1; min-width: 0;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .78rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  padding: .4rem .5rem;
  overflow-x: auto;
  white-space: nowrap;
  user-select: all;
}

/* Os filtros da lista de vagas. Em coluna no celular, onde três selects
   lado a lado ficariam estreitos demais para ler o nome da cidade. */
.vagas-filtros { gap: .4rem; flex-wrap: wrap; }
.vagas-filtros select { width: auto; min-width: 0; flex: 1 1 8rem; }

/* ------------------------------------------------------------------ notas

   A mesma paleta do perfil, em duas versões: um tom claro para o tema claro
   (papel colorido) e um escuro para o tema escuro. Guardar o hex na nota
   congelaria um pastel claro sobre fundo preto.

   `neutro` acompanha o tema: papel branco no claro, quase preto no escuro. */
:root {
  /* Três intensidades, escolhidas em Configurações e guardadas em
     `data-notas` no <html>. Não é um controle contínuo de propósito: cada
     nível foi calibrado para o texto manter pelo menos 4,5:1 de contraste, e
     um cursor livre deixaria escolher combinações ilegíveis.

     `medio` é o padrão e mora no :root sem atributo — quem nunca abriu as
     configurações não pode depender de um valor que só o JS põe. */
  --nota-azul:     #acc8ec;  --nota-azul-b:     #3b82f6;
  --nota-rosa:     #ecaccc;  --nota-rosa-b:     #ec4899;
  --nota-verde:    #acecd7;  --nota-verde-b:    #10b981;
  --nota-ambar:    #ecdcac;  --nota-ambar-b:    #f59e0b;
  --nota-laranja:  #eccaac;  --nota-laranja-b:  #f97316;
  --nota-roxo:     #bcacec;  --nota-roxo-b:     #8b5cf6;
  --nota-vermelho: #ecacac;  --nota-vermelho-b: #ef4444;
  --nota-ciano:    #ace4ec;  --nota-ciano-b:    #06b6d4;
  --nota-limao:    #d7ecac;  --nota-limao-b:    #84cc16;
  --nota-neutro:   #1c1c1c;  --nota-neutro-b:   #000000;
  --nota-texto:    #1f2937;
}
:root[data-notas="suave"] {
  --nota-azul:     #d0def1;  --nota-azul-b:     #3b82f6;
  --nota-rosa:     #f1d0e0;  --nota-rosa-b:     #ec4899;
  --nota-verde:    #d0f1e6;  --nota-verde-b:    #10b981;
  --nota-ambar:    #f1e9d0;  --nota-ambar-b:    #f59e0b;
  --nota-laranja:  #f1dfd0;  --nota-laranja-b:  #f97316;
  --nota-roxo:     #d8d0f1;  --nota-roxo-b:     #8b5cf6;
  --nota-vermelho: #f1d0d0;  --nota-vermelho-b: #ef4444;
  --nota-ciano:    #d0edf1;  --nota-ciano-b:    #06b6d4;
  --nota-limao:    #e6f1d0;  --nota-limao-b:    #84cc16;
  --nota-neutro:   #2b2b2b;  --nota-neutro-b:   #000000;
  --nota-texto:    #1f2937;
}
:root[data-notas="forte"] {
  --nota-azul:     #79abec;  --nota-azul-b:     #3b82f6;
  --nota-rosa:     #ec79b3;  --nota-rosa-b:     #ec4899;
  --nota-verde:    #79ecc6;  --nota-verde-b:    #10b981;
  --nota-ambar:    #eccf79;  --nota-ambar-b:    #f59e0b;
  --nota-laranja:  #ecaf79;  --nota-laranja-b:  #f97316;
  --nota-roxo:     #9b80ed;  --nota-roxo-b:     #8b5cf6;
  --nota-vermelho: #ec7979;  --nota-vermelho-b: #ef4444;
  --nota-ciano:    #79deec;  --nota-ciano-b:    #06b6d4;
  --nota-limao:    #c6ec79;  --nota-limao-b:    #84cc16;
  --nota-neutro:   #000000;  --nota-neutro-b:   #000000;
  --nota-texto:    #1f2937;
}

/* No escuro o sentido inverte: mais forte é mais luminoso, porque o fundo é
   preto. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --nota-azul:     #1560c1;  --nota-azul-b:     #3b82f6;
    --nota-rosa:     #c1156b;  --nota-rosa-b:     #ec4899;
    --nota-verde:    #0e7e59;  --nota-verde-b:    #10b981;
    --nota-ambar:    #87690f;  --nota-ambar-b:    #f59e0b;
    --nota-laranja:  #aa5913;  --nota-laranja-b:  #f97316;
    --nota-roxo:     #4015c1;  --nota-roxo-b:     #8b5cf6;
    --nota-vermelho: #c11515;  --nota-vermelho-b: #ef4444;
    --nota-ciano:    #0f7987;  --nota-ciano-b:    #06b6d4;
    --nota-limao:    #54770d;  --nota-limao-b:    #84cc16;
    --nota-neutro:   #f8fafc;  --nota-neutro-b:   #ffffff;
    --nota-texto:    #f3f4f6;
  }
  :root:not([data-theme="light"])[data-notas="suave"] {
    --nota-azul:     #193457;  --nota-azul-b:     #3b82f6;
    --nota-rosa:     #571938;  --nota-rosa-b:     #ec4899;
    --nota-verde:    #195742;  --nota-verde-b:    #10b981;
    --nota-ambar:    #574819;  --nota-ambar-b:    #f59e0b;
    --nota-laranja:  #573619;  --nota-laranja-b:  #f97316;
    --nota-roxo:     #291957;  --nota-roxo-b:     #8b5cf6;
    --nota-vermelho: #571919;  --nota-vermelho-b: #ef4444;
    --nota-ciano:    #195057;  --nota-ciano-b:    #06b6d4;
    --nota-limao:    #425719;  --nota-limao-b:    #84cc16;
    --nota-neutro:   #eef1f5;  --nota-neutro-b:   #ffffff;
    --nota-texto:    #f3f4f6;
  }
  :root:not([data-theme="light"])[data-notas="forte"] {
    --nota-azul:     #0668e7;  --nota-azul-b:     #3b82f6;
    --nota-rosa:     #d6056e;  --nota-rosa-b:     #ec4899;
    --nota-verde:    #037c54;  --nota-verde-b:    #10b981;
    --nota-ambar:    #8b6904;  --nota-ambar-b:    #f59e0b;
    --nota-laranja:  #ae5404;  --nota-laranja-b:  #f97316;
    --nota-roxo:     #561ff9;  --nota-roxo-b:     #8b5cf6;
    --nota-vermelho: #dd0606;  --nota-vermelho-b: #ef4444;
    --nota-ciano:    #047989;  --nota-ciano-b:    #06b6d4;
    --nota-limao:    #527a03;  --nota-limao-b:    #84cc16;
    --nota-neutro:   #ffffff;  --nota-neutro-b:   #ffffff;
    --nota-texto:    #f3f4f6;
  }
}
:root[data-theme="dark"] {
  --nota-azul:     #1560c1;  --nota-azul-b:     #3b82f6;
  --nota-rosa:     #c1156b;  --nota-rosa-b:     #ec4899;
  --nota-verde:    #0e7e59;  --nota-verde-b:    #10b981;
  --nota-ambar:    #87690f;  --nota-ambar-b:    #f59e0b;
  --nota-laranja:  #aa5913;  --nota-laranja-b:  #f97316;
  --nota-roxo:     #4015c1;  --nota-roxo-b:     #8b5cf6;
  --nota-vermelho: #c11515;  --nota-vermelho-b: #ef4444;
  --nota-ciano:    #0f7987;  --nota-ciano-b:    #06b6d4;
  --nota-limao:    #54770d;  --nota-limao-b:    #84cc16;
  --nota-neutro:   #f8fafc;  --nota-neutro-b:   #ffffff;
  --nota-texto:    #f3f4f6;
}
:root[data-theme="dark"][data-notas="suave"] {
  --nota-azul:     #193457;  --nota-azul-b:     #3b82f6;
  --nota-rosa:     #571938;  --nota-rosa-b:     #ec4899;
  --nota-verde:    #195742;  --nota-verde-b:    #10b981;
  --nota-ambar:    #574819;  --nota-ambar-b:    #f59e0b;
  --nota-laranja:  #573619;  --nota-laranja-b:  #f97316;
  --nota-roxo:     #291957;  --nota-roxo-b:     #8b5cf6;
  --nota-vermelho: #571919;  --nota-vermelho-b: #ef4444;
  --nota-ciano:    #195057;  --nota-ciano-b:    #06b6d4;
  --nota-limao:    #425719;  --nota-limao-b:    #84cc16;
  --nota-neutro:   #eef1f5;  --nota-neutro-b:   #ffffff;
  --nota-texto:    #f3f4f6;
}
:root[data-theme="dark"][data-notas="forte"] {
  --nota-azul:     #0668e7;  --nota-azul-b:     #3b82f6;
  --nota-rosa:     #d6056e;  --nota-rosa-b:     #ec4899;
  --nota-verde:    #037c54;  --nota-verde-b:    #10b981;
  --nota-ambar:    #8b6904;  --nota-ambar-b:    #f59e0b;
  --nota-laranja:  #ae5404;  --nota-laranja-b:  #f97316;
  --nota-roxo:     #561ff9;  --nota-roxo-b:     #8b5cf6;
  --nota-vermelho: #dd0606;  --nota-vermelho-b: #ef4444;
  --nota-ciano:    #047989;  --nota-ciano-b:    #06b6d4;
  --nota-limao:    #527a03;  --nota-limao-b:    #84cc16;
  --nota-neutro:   #ffffff;  --nota-neutro-b:   #ffffff;
  --nota-texto:    #f3f4f6;
}

.nota-azul     { background: var(--nota-azul);     border-color: var(--nota-azul-b); }
.nota-rosa     { background: var(--nota-rosa);     border-color: var(--nota-rosa-b); }
.nota-verde    { background: var(--nota-verde);    border-color: var(--nota-verde-b); }
.nota-ambar    { background: var(--nota-ambar);    border-color: var(--nota-ambar-b); }
.nota-laranja  { background: var(--nota-laranja);  border-color: var(--nota-laranja-b); }
.nota-roxo     { background: var(--nota-roxo);     border-color: var(--nota-roxo-b); }
.nota-vermelho { background: var(--nota-vermelho); border-color: var(--nota-vermelho-b); }
.nota-ciano    { background: var(--nota-ciano);    border-color: var(--nota-ciano-b); }
.nota-limao    { background: var(--nota-limao);    border-color: var(--nota-limao-b); }
/* O neutro é o único que inverte: papel preto no tema claro, branco no
   escuro. Por isso o TEXTO dele também inverte — senão some no fundo. */
.nota-neutro   { background: var(--nota-neutro);   border-color: var(--nota-neutro-b); }
.nota-neutro, .nota-flut.nota-neutro { --nota-texto: #f3f4f6; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .nota-neutro,
  :root:not([data-theme="light"]) .nota-flut.nota-neutro { --nota-texto: #1f2937; }
}
:root[data-theme="dark"] .nota-neutro,
:root[data-theme="dark"] .nota-flut.nota-neutro { --nota-texto: #1f2937; }

/* "de Fulano": quem deixou o recado. Sem isso a pessoa acha que escreveu e
   esqueceu, e o bilhete perde a graça de ser uma mensagem. */
.nota-de {
  font-size: .72rem;
  font-weight: 600;
  color: var(--nota-texto);
  opacity: .6;
  margin-bottom: .15rem;
}
.nota-de-flut { padding: 0 .1rem; }

/* Mural da aba: cartões que se acomodam na largura disponível. */
.notas-mural {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: .7rem;
}
.nota {
  display: flex; flex-direction: column;
  border: 1px solid; border-radius: var(--r-sm);
  padding: .5rem .6rem .6rem;
  /* Altura FIXA: o mural é uma grade, e um cartão que cresce com o texto
     deixava buracos ao lado dos vizinhos baixos. O texto que não couber é
     cortado, com reticências avisando que continua. */
  height: 200px;
  overflow: hidden;
  min-width: 0;
}
/* Os controles quebram para a linha de baixo quando não couberem. Numa linha
   só, seis círculos mais o rótulo e dois botões vazavam para fora do cartão
   nas colunas estreitas. */
.nota-topo {
  display: flex; align-items: center; justify-content: space-between;
  gap: .3rem; margin-bottom: .35rem; min-height: 22px;
  flex-wrap: wrap;
}
.nota-cores { display: flex; gap: .2rem; }
/* Empurra os botões para a direita: as cores saíram daqui e viraram menu. */
.nota-espaco { flex: 1; }

/* Mesma regra do bilhete flutuante: em repouso o cartão mostra só o texto.
   Os controles voltam com o mouse ou com o foco. */
.nota .nota-topo .btn-ghost,
.nota .nota-barra {
  opacity: 0; visibility: hidden; transition: opacity .12s;
}
.nota:hover .nota-topo .btn-ghost,
.nota:focus-within .nota-topo .btn-ghost { opacity: .7; visibility: visible; }
.nota:hover .nota-topo .btn-ghost:hover { opacity: 1; }
.nota:hover .nota-barra,
.nota:focus-within .nota-barra { opacity: 1; visibility: visible; }
/* O menu aberto fica: ele fecha por clique, não por perder o mouse. */
.nota .nota-menu:not(.hidden) { opacity: 1; visibility: visible; }
/* O círculo usa a cor da BORDA como preenchimento: o fundo do bilhete é
   claro de propósito, e em 16px ele não se distinguia do branco. */
.nota-cor {
  width: 16px; height: 16px; padding: 0;
  border: none; border-radius: 50%; cursor: pointer;
  min-height: auto;
}
.nota-cor.nota-azul     { background: var(--nota-azul-b); }
.nota-cor.nota-rosa     { background: var(--nota-rosa-b); }
.nota-cor.nota-verde    { background: var(--nota-verde-b); }
.nota-cor.nota-ambar    { background: var(--nota-ambar-b); }
.nota-cor.nota-laranja  { background: var(--nota-laranja-b); }
.nota-cor.nota-roxo     { background: var(--nota-roxo-b); }
.nota-cor.nota-vermelho { background: var(--nota-vermelho-b); }
.nota-cor.nota-ciano    { background: var(--nota-ciano-b); }
.nota-cor.nota-limao    { background: var(--nota-limao-b); }
.nota-cor.nota-neutro   { background: var(--nota-neutro-b); }
.nota-cor.ativa { outline: 2px solid var(--nota-texto); outline-offset: 2px; }
/* O texto herda a cor do bilhete, não a do tema: sobre um amarelo claro o
   branco do modo escuro seria ilegível. */
.nota .nota-texto { overflow: hidden; position: relative; }
/* As reticências: aparecem só quando o texto passa da altura do cartão.
   `data-mais` é posto pelo JS, que é quem sabe medir. */
.nota[data-mais="1"]::after {
  content: '…';
  position: absolute; right: .6rem; bottom: 2.1rem;
  padding-left: 1.2rem;
  color: var(--nota-texto);
  background: linear-gradient(to right, transparent, var(--nota-fundo) 45%);
  pointer-events: none;
}
.nota { position: relative; }
.nota.nota-azul     { --nota-fundo: var(--nota-azul); }
.nota.nota-rosa     { --nota-fundo: var(--nota-rosa); }
.nota.nota-verde    { --nota-fundo: var(--nota-verde); }
.nota.nota-ambar    { --nota-fundo: var(--nota-ambar); }
.nota.nota-laranja  { --nota-fundo: var(--nota-laranja); }
.nota.nota-roxo     { --nota-fundo: var(--nota-roxo); }
.nota.nota-vermelho { --nota-fundo: var(--nota-vermelho); }
.nota.nota-ciano    { --nota-fundo: var(--nota-ciano); }
.nota.nota-limao    { --nota-fundo: var(--nota-limao); }
.nota.nota-neutro   { --nota-fundo: var(--nota-neutro); }
.nota-texto, .nota-flut-texto {
  flex: 1; width: 100%; resize: none;
  border: none; background: transparent; padding: 0;
  color: var(--nota-texto);
  font-family: inherit; font-size: .85rem; line-height: 1.45;
  /* Uma sequência longa sem espaço (uma URL, um "aaaa...") atravessava a
     tela inteira. `anywhere` quebra em qualquer ponto quando não há outro
     lugar por onde quebrar. */
  overflow-wrap: anywhere;
  min-width: 0;
}
.nota-texto:focus, .nota-flut-texto:focus { outline: none; }
/* Campo editável não tem placeholder: o texto de ajuda vem do atributo, e
   some assim que houver qualquer conteúdo. */
.nota-texto:empty::before, .nota-flut-texto:empty::before {
  content: attr(data-vazio);
  opacity: .45;
}
.nota-texto ul, .nota-flut-texto ul,
.nota-texto ol, .nota-flut-texto ol { margin: .2rem 0 .2rem 1.1rem; padding: 0; }

/* A barra de formatação, no rodapé do bilhete como no Sticky Notes. */
.nota-barra {
  display: flex; gap: .1rem; align-items: center;
  margin-top: .3rem; padding-top: .3rem;
  border-top: 1px solid currentColor;
  color: var(--nota-texto);
  opacity: .55;
}
.nota-barra:hover { opacity: 1; }

/* Na nota flutuante os controles somem quando ela não está em uso: fica só o
   texto e a faixa de cor no topo, como no Sticky Notes. Volta ao passar o
   mouse ou ao clicar dentro.
   `visibility` e não `display`: escondendo de vez, a nota mudaria de altura
   ao ganhar foco e o texto pularia sob o cursor. */
.nota-flut .nota-barra { opacity: 0; visibility: hidden; transition: opacity .12s; }
.nota-flut:hover .nota-barra,
.nota-flut:focus-within .nota-barra { opacity: 1; visibility: visible; }
.nota-fmt {
  width: 24px; height: 22px; min-height: 22px; padding: 0;
  border: none; background: transparent; cursor: pointer;
  color: var(--nota-texto);
  font-family: inherit; font-size: .8rem; line-height: 1;
  border-radius: var(--r-xs);
}
.nota-fmt:hover { background: rgba(127, 127, 127, .25); }


.nota .btn-ghost, .nota-flut .btn-ghost { color: var(--nota-texto); opacity: .7; }
.nota .btn-ghost:hover, .nota-flut .btn-ghost:hover { opacity: 1; }
.nota .btn-ghost.ativa { opacity: 1; color: var(--ok-text); }

/* As notas soltas sobre a tela inicial. `position: fixed` para acompanharem a
   rolagem: no fluxo elas subiriam junto com o conteúdo e sumiriam. */
/* `absolute` com altura zero: o container não empurra nada e não cria barra
   de rolagem própria; só serve de referência para as notas. */
#notasFixadas {
  position: absolute; top: 0; left: 0; width: 100%; height: 0;
  /* Abaixo do cabeçalho (30) e da barra de abas: rolando a página, a nota
     passa POR BAIXO deles, em vez de cobrir o menu. Ainda acima do conteúdo,
     que é o ponto de um bilhete colado na tela. */
  pointer-events: none; z-index: 25;
}
/* MONITOR LARGO: a nota deixada perto da borda esquerda ficava sozinha lá,
   a centenas de pixels do painel -- em 2560px o conteúdo começa em x=620 e
   uma nota em x=30 não parecia colada em nada.

   O empurrão é só até a margem do conteúdo, e só onde SOBRA margem: a coluna
   tem no máximo 1320px e a nota 240, então abaixo de ~1840px de janela não há
   faixa livre nenhuma, e mexer na posição faria a nota tapar os cards -- que
   é pior que deixá-la na margem. Acima disso ela encosta na coluna e continua
   ao lado do painel, sem cobrir nada.

   `max()` e não `left` fixo: o x guardado é respeitado quando já está dentro
   da área boa, e só o que ficou para trás é trazido junto. */
@media (min-width: 1840px) {
  /* `left` no CONTAINER, e nao `padding`: a nota e `position: absolute`, e
     filho absoluto ignora o padding do pai -- so a origem do container o
     desloca. A largura encolhe o mesmo tanto, para a borda direita nao sair
     da tela. */
  #notasFixadas {
    left: calc((100vw - 1320px) / 2 - 282px);
    width: calc(100% - ((100vw - 1320px) / 2 - 282px));
  }
}

.nota-flut {
  /* `absolute` e não `fixed`: a nota acompanha a rolagem da página, como um
     post-it colado no papel. Com `fixed` ela ficava parada na tela enquanto o
     conteúdo passava por baixo, e parecia grudada no monitor. */
  position: absolute;
  width: 240px;
  /* Cresce com o texto, até o limite. Altura fixa cortava a nota longa: o
     texto vazava para fora do bilhete e a barra ficava solta embaixo. */
  min-height: 150px;
  max-height: 70vh;
  display: flex; flex-direction: column;
  border: 1px solid; border-radius: var(--r-sm);
  padding: .5rem .55rem .55rem;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
  pointer-events: auto;      /* o container ignora cliques; a nota, não */
}
/* "Fica parada": o bilhete acompanha a tela em vez do conteúdo, como era
   antes. Fica a escolha de quem quer a nota sempre à vista. */
#notasFixadas.presa { position: fixed; }
#notasFixadas.presa .nota-flut { position: fixed; }

/* Passando do teto, o texto rola DENTRO do bilhete em vez de vazar. */
.nota-flut-texto { overflow-y: auto; min-height: 0; }
/* O bilhete do outro é para ler. Sem cursor de arrastar e sem seleção de
   texto: os dois prometeriam uma interação que não existe ali. */
.nota-flut.somente-ler { cursor: default; }
.nota-flut.somente-ler .nota-flut-topo { cursor: default; }
.nota-flut.somente-ler .nota-flut-texto { cursor: default; user-select: text; }

.nota-flut.arrastando,
.nota-flut.redimensionando { opacity: .92; box-shadow: 0 10px 26px rgba(0, 0, 0, .28); }

/* As alças de redimensionar: faixas invisíveis nas bordas e nos cantos. O
   cursor é que anuncia a direção, como numa janela do sistema. Os cantos vêm
   depois dos lados no CSS para ganharem a sobreposição. */
.nota-rz { position: absolute; z-index: 2; }
.nota-rz-n { top: -3px; left: 8px; right: 8px; height: 8px; cursor: ns-resize; }
.nota-rz-s { bottom: -3px; left: 8px; right: 8px; height: 8px; cursor: ns-resize; }
.nota-rz-w { left: -3px; top: 8px; bottom: 8px; width: 8px; cursor: ew-resize; }
.nota-rz-e { right: -3px; top: 8px; bottom: 8px; width: 8px; cursor: ew-resize; }
.nota-rz-nw { top: -3px; left: -3px; width: 12px; height: 12px; cursor: nwse-resize; }
.nota-rz-se { bottom: -3px; right: -3px; width: 12px; height: 12px; cursor: nwse-resize; }
.nota-rz-ne { top: -3px; right: -3px; width: 12px; height: 12px; cursor: nesw-resize; }
.nota-rz-sw { bottom: -3px; left: -3px; width: 12px; height: 12px; cursor: nesw-resize; }
.nota-flut-topo {
  display: flex; align-items: center; justify-content: space-between;
  cursor: grab; user-select: none; margin-bottom: .2rem;
  /* Altura própria: com os botões escondidos a barra encolhia para quase
     zero e não sobrava por onde pegar o bilhete. Ela continua sendo a área
     de arrasto mesmo vazia. */
  min-height: 22px;
  position: relative;
}
.nota-flut.arrastando .nota-flut-topo { cursor: grabbing; }
/* O bilhete inteiro é área de arrasto, menos o texto e os botões: com os
   controles escondidos não sobrava por onde pegá-lo. O cursor anuncia isso. */
.nota-flut { cursor: grab; }
.nota-flut.arrastando { cursor: grabbing; }
.nota-flut-texto { cursor: text; }
.nota-flut .btn-ghost, .nota-flut .nota-fmt,
.nota-flut .nota-menu { cursor: pointer; }
.nota-flut-alca { color: var(--nota-texto); opacity: .45; font-size: .8rem; }

/* A alça e os botões acompanham a barra: some tudo, sobra o bilhete. O menu
   aberto é a exceção — ele fecha por clique, não por perder o mouse. */
.nota-flut .nota-flut-alca,
.nota-flut .nota-flut-topo .btn-ghost {
  opacity: 0; visibility: hidden; transition: opacity .12s;
}
.nota-flut:hover .nota-flut-alca,
.nota-flut:hover .nota-flut-topo .btn-ghost,
.nota-flut:focus-within .nota-flut-alca,
.nota-flut:focus-within .nota-flut-topo .btn-ghost {
  opacity: .7; visibility: visible;
}
.nota-flut:hover .nota-flut-topo .btn-ghost:hover { opacity: 1; }

/* A faixa de cor no topo é o que identifica o bilhete quando o resto some.
   `border-color` e não `currentColor`: currentColor é a cor do TEXTO, e a
   faixa ficaria da cor da letra em vez da cor da nota. */
.nota-flut::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 6px;
  background: var(--nota-faixa, transparent);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  pointer-events: none;
}
.nota-flut.nota-azul     { --nota-faixa: var(--nota-azul-b); }
.nota-flut.nota-rosa     { --nota-faixa: var(--nota-rosa-b); }
.nota-flut.nota-verde    { --nota-faixa: var(--nota-verde-b); }
.nota-flut.nota-ambar    { --nota-faixa: var(--nota-ambar-b); }
.nota-flut.nota-laranja  { --nota-faixa: var(--nota-laranja-b); }
.nota-flut.nota-roxo     { --nota-faixa: var(--nota-roxo-b); }
.nota-flut.nota-vermelho { --nota-faixa: var(--nota-vermelho-b); }
.nota-flut.nota-ciano    { --nota-faixa: var(--nota-ciano-b); }
.nota-flut.nota-limao    { --nota-faixa: var(--nota-limao-b); }
.nota-flut.nota-neutro   { --nota-faixa: var(--nota-neutro-b); }

/* O menu de três pontos, ancorado no canto do bilhete. Fundo do tema, e não
   da nota: sobre o amarelo os itens sumiriam. */
.nota-topo { position: relative; }
.nota-menu {
  position: absolute; top: 100%; right: 0;
  min-width: 0;
  /* Ancorado à direita do botão: numa nota encostada na borda da tela, um
     menu alinhado à esquerda sairia da janela. */
  max-width: max-content;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
  padding: .3rem;
  z-index: 3;
  color: var(--text);
}
/* Duas fileiras de cinco: dez círculos numa linha só passavam da largura do
   bilhete e as últimas cores ficavam fora da tela. */
.nota-menu-cores {
  display: grid;
  grid-template-columns: repeat(5, auto);
  gap: .35rem;
  padding: .3rem;
  justify-content: center;
}
.nota-menu .nota-cor { width: 20px; height: 20px; }
.nota-menu-item {
  display: flex; align-items: center; gap: .45rem;
  width: 100%; padding: .4rem .5rem;
  border: none; background: transparent; cursor: pointer;
  color: var(--text); text-align: left;
  font-family: inherit; font-size: .82rem;
  border-radius: 5px;
}
.nota-menu-item:hover { background: var(--surface-2); }
.nota-menu-item.perigo { color: var(--err-text); }

/* Os itens de uma lista salva, enquanto ela é montada. */
.chip-lista {
  display: flex; flex-wrap: wrap; gap: .3rem;
  max-height: 9rem; overflow-y: auto;
}

/* As listas salvas, no estilo "pedir de novo": cartões lado a lado que cabem
   quantos couberem, e viram coluna única no celular. */
.lista-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: .6rem;
}
.lista-card {
  display: flex; flex-direction: column; gap: .4rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: .7rem .7rem;
  background: var(--surface-2);
}
.lista-nome { font-size: .9rem; min-width: 0; overflow-wrap: anywhere; }
/* Duas linhas de itens e para: o cartão existe para reconhecer a lista, não
   para ler o conteúdo inteiro. */
.lista-itens {
  flex: 1; margin: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Lista de refeições, com ingredientes. */
.meal-list { display: flex; flex-direction: column; }
.meal-item {
  display: flex; align-items: flex-start; gap: .6rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--border);
}
.meal-item:last-child { border-bottom: none; }
/* Editar e remover ficam sempre à vista, discretos: escondidos até o hover,
   a refeição parecia não ter como ser corrigida — e no toque não há hover. */
.meal-item .icon-btn { opacity: .65; transition: opacity .12s; }
.meal-item:hover .icon-btn, .meal-item:focus-within .icon-btn { opacity: 1; }

/* ------------------------------------------------------------------ quadro */

.kanban {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(240px, 1fr);
  gap: .6rem;
  overflow-x: auto;
  padding-bottom: .4rem;
  scroll-snap-type: x proximity;
  align-items: start;
}
.kanban::-webkit-scrollbar { height: 6px; }
.kanban::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-pill); }

/* Estreito, as colunas UMA EMBAIXO DA OUTRA em vez de uma fileira que rola.
   Com `grid-auto-flow: column` e 240px de largura minima, duas colunas ja
   nao cabiam em 480px: a segunda ficava cortada na borda e a terceira fora
   da tela, e so uma barra de rolagem fininha avisava que existiam. Empilhado
   se ve o quadro inteiro rolando a pagina, que e o gesto que ja se usa.

   O limite e 620px porque abaixo disso nem duas colunas de 240 mais o gap
   entram na coluna de conteudo. */
@media (max-width: 900px) {
  .kanban {
    grid-auto-flow: row;
    /* O `auto-fit` faz a conta sozinho: cabem tres colunas de 240, ficam
       tres; cabem duas, ficam duas; nao cabe nenhuma ao lado da outra,
       empilham. Sem largura de janela chutada, e um quadro de duas ou de
       seis colunas se acomoda igual. */
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    grid-auto-columns: auto;
    overflow-x: visible;
    scroll-snap-type: none;
  }
}

/* O quadro era um bloco cinza uniforme. Uma faixa da cor do tema no topo de
   cada coluna dá o mesmo sinal de vida das outras telas, sem tingir o fundo
   e prejudicar a leitura dos cartões. */
.kcol {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  border-radius: var(--r);
  padding: .6rem;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}

.kcol-head {
  display: flex;
  align-items: center;
  gap: .3rem;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  padding-bottom: .35rem;
}
/* Nome editável no lugar: campo sem moldura até receber o cursor, para não
   virar um formulário no meio do quadro. */
.kcol-title {
  flex: 1;
  min-width: 0;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-faint);
  background: none;
  border: 1px solid transparent;
  padding: .2rem .3rem;
  min-height: 26px;
  border-radius: var(--r-xs);
}
input.kcol-title:hover { border-color: var(--border); }
input.kcol-title:focus {
  border-color: var(--accent);
  background: var(--surface);
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
  font-size: .82rem;
}

.kcol-body {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  min-height: 52px;
  border-radius: var(--r-sm);
  transition: background .12s, box-shadow .12s;
}
/* Realce do destino durante o arrasto. */
.kcol-body.kover,
.kcol-body.ktarget {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
}

.kempty {
  font-size: .72rem;
  color: var(--text-faint);
  text-align: center;
  padding: .8rem .3rem;
  border: 1px dashed var(--border);
  border-radius: var(--r-sm);
}

.kcard {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: var(--r-sm);
  padding: .5rem .55rem;
  display: flex;
  align-items: flex-start;
  gap: .35rem;
  font-size: .85rem;
  line-height: 1.4;
  cursor: grab;
}
.kcard:active { cursor: grabbing; }
.kcard-text {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: .85rem;
}
/* Campo sem moldura até receber o cursor: editar no lugar sem o cartão
   parecer um formulário. */
input.kcard-text {
  background: none;
  border: 1px solid transparent;
  padding: 0 .2rem;
  min-height: 22px;
  border-radius: var(--r-xs);
  cursor: text;
}
input.kcard-text:hover { border-color: var(--border-strong); }
input.kcard-text:focus {
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: none;
}
.kcard .icon-btn { opacity: 0; transition: opacity .12s; }
.kcard:hover .icon-btn, .kcard:focus-within .icon-btn { opacity: 1; }
/* No celular não há hover: o botão precisa estar sempre visível. */
@media (pointer: coarse) {
  .kcard .icon-btn { opacity: 1; }
}

/* Os sete rostos numa fileira so, em QUALQUER largura.
   A regra vivia em `@media (pointer: coarse)`: numa janela de PC -- mouse,
   portanto `fine` -- ela nao pegava e os rostos quebravam em duas fileiras
   desencontradas, inflando o card e arrastando o vizinho de linha.

   E nem trocar por uma largura de janela resolve: o que aperta nao e a
   janela, e a COLUNA da grade. Medido, os sete pedem 187px e a fileira
   recebia 132px em 900px de janela, 152 em 1000, 172 em 1100 -- so passava
   dos 187 perto de 1200. Cada card ligado a mais empurra esse limite.

   Entao a condicao e a que importa de verdade: o card do Humor nunca fica
   mais estreito que o controle que ele carrega. O `auto-fit` da grade ve
   esse minimo e da a ele uma coluna maior ou o joga para a linha de baixo
   inteira, sem media query nenhuma. */
/* O minimo vai na FILEIRA, e o card cresce em consequencia (o padding dele
   entra por cima). Posto no card, sobravam 169px de 200 para um controle que
   pede 187 mais os gaps, e a quebra continuava. */
.mood-row { min-width: 200px; }
.grid-4 > .card.stat:has(.mood-row) { min-width: 0; }
/* Sozinho na linha (quando estica), o card do Humor nao herda a altura de
   uma fileira que nao existe: `.mood-row` tem `margin-top: auto` e empurrava
   os rostos para o pe de um card alto e quase vazio. */
.grid-4 > .card.stat:has(.mood-row) { align-self: start; }

@media (max-width: 820px) {
  /* O card do Humor ocupa a LINHA INTEIRA. Ele mora num `.grid-4`, que em
     360px resolve para duas colunas de 163px -- e dentro dele a fileira
     sobra com 139px. Os sete emoji precisam de 189px (180 de emoji mais os
     gaps), entao nao entram: quebravam em duas linhas e faziam o card
     crescer, arrastando o de Sono junto, porque os dois dividem a mesma
     linha da grade.

     Com a largura inteira os sete cabem numa fileira so, que e como o
     controle foi desenhado, e o card volta a ter a altura dos vizinhos.

     O `nth-last-child(2)` devolve o PAR de baixo: com o Humor esticado, o
     card anterior (Sono) ficava sozinho numa fileira com metade vazia, e o
     seguinte (Peso) sozinho na outra -- dois buracos onde antes havia um.
     Puxando o ultimo para o lado do antepenultimo, a fileira fecha. */
  .grid-4 > .card.stat:has(.mood-row) { grid-column: 1 / -1; }

  /* `dense` deixa um card MENOR subir para o buraco que o Humor esticado
     deixou. Sem isto a grade preenche em ordem estrita: o Humor tomava a
     linha inteira, o Sono ficava sozinho com metade vazia acima dele e o
     Peso sozinho embaixo -- dois buracos onde antes havia um. Com `dense`,
     o Peso sobe e faz par com o Sono, e a fileira fecha.

     O reordenamento visual e aceitavel aqui porque cada card se identifica
     pelo proprio rotulo e icone: nao ha sequencia a seguir, e a ordem de
     leitura nao carrega significado (diferente de uma lista ou tabela). */
  .grid-4 { grid-auto-flow: row dense; }
}

.kdragging { opacity: .4; }
.kpicked {
  box-shadow: 0 0 0 2px var(--accent);
  background: var(--surface);
}

/* Botão discreto no lugar do campo "Novo cartão" sempre visível. */
.kadd-btn {
  width: 100%;
  min-height: 30px;
  border-style: dashed;
  border-color: transparent;
  color: var(--text-faint);
}
.kcol:hover .kadd-btn { border-color: var(--border); }
.kadd-btn:hover { color: var(--text); border-color: var(--border-strong); }

.kadd { display: flex; gap: .25rem; margin-top: .1rem; }
.kadd input {
  font-size: .82rem;
  min-height: 32px;
  padding: .3rem .5rem;
  border-color: transparent;
  background: transparent;
}
.kadd input:hover { border-color: var(--border); }
.kadd input:focus { background: var(--surface); border-color: var(--accent); }

.kcol-new:hover { color: var(--text); border-color: var(--text-faint); }

/* Cabeçalho da tela inicial: compacto, é só um rótulo e dois botões. */
/* Margem menor desde que o rotulo "Inicio" saiu: o painel encosta mais
   no cabecalho, sem uma faixa vazia entre os dois. */
.home-bar { margin-bottom: .3rem; min-height: 28px; }
.home-bar .btn-ghost { min-height: 28px; padding: .2rem .5rem; }
.home-bar .icon-only { width: 28px; }

/* O tamanho do ícone escolhido, em Configurações. Mesmo desenho dos filtros
   de período, que a pessoa já conhece das outras abas. */
.tam-opt.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
  font-weight: 500;
}

/* Avatar com foto. */
/* O recorte vai na IMAGEM, não no avatar: `overflow: hidden` aqui cortava a
   medalha, que fica pendurada fora do círculo. */
.avatar.has-photo { padding: 0; }
.avatar.has-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
}

/* Humor: opções em linha dentro do card. */
.mood-row {
  display: flex;
  justify-content: space-between;
  gap: .1rem;
  margin-top: auto;
  padding-top: .5rem;
  /* Sete rostos não cabem na largura de um celular. Sem isto o último era
     cortado e o card empurrava a página inteira para a direita. */
  flex-wrap: wrap;
}
/* Os rostos eram emoji, que não aceitam cor: o não-escolhido só podia ser
   apagado com `opacity`, e o escolhido não tinha como seguir o acento do
   perfil. Sendo SVG, os dois estados viram cor de verdade -- e o escolhido
   fica na cor do perfil, como o resto do Hub. */
.mood-opt {
  border: none;
  background: none;
  padding: .15rem;
  min-height: 26px;
  min-width: 0;
  line-height: 0;
  border-radius: var(--r-xs);
  color: var(--text-dim);
  transition: color .12s, background .12s;
}
.mood-opt:hover { color: var(--text); background: var(--surface-2); }
.mood-opt.selected { color: var(--accent-text); background: var(--surface-2); }
/* O rosto acompanha a linha de texto que ele encabeça (o valor do card, o
   resumo do dia): sem isto o SVG assenta na base e fica alto demais. */
.mood-face { display: inline-flex; align-items: center; gap: .35rem; }
.mood-face .ico { vertical-align: middle; }

/* O valor do card de Humor na MESMA faixa dos numeros dos vizinhos.
   Medindo a tinta desenhada, os quatro numeros comecavam no pixel 187 e o
   rosto do Humor em 179: um SVG de 24px e mais alto que a altura-x de um
   numero de 1.5rem, entao assentado na mesma base ele ultrapassava por
   cima -- e o Humor era o unico dos cinco fora da linha.

   O rosto encolhe para a altura do numero e se alinha pelo CENTRO da
   mancha dele, nao pela base: um circulo nao tem linha de base, e assenta-lo
   como se tivesse e o que o punha alto demais. */
.stat-value-humor .mood-face { align-items: baseline; }
/* O rosto assenta na base como os numeros dos vizinhos.
   Um circulo nao tem linha de base propria, entao ele e empurrado para
   BAIXO ate o pe da linha: sem isso, a caixa do SVG e que se apoiava na
   base, e o desenho inteiro subia acima dela. O deslocamento e a folga
   entre o pe do circulo e o pe do texto. */
.stat-value-humor .mood-face .ico {
  width: 21px;
  height: 21px;
  position: relative;
  top: 3px;
}

/* Recorte de foto: a máscara mostra o que vai virar avatar. */
.crop-stage {
  position: relative;
  width: 256px;
  max-width: 100%;
  aspect-ratio: 1;
  margin: 0 auto;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface-2);
  cursor: grab;
  touch-action: none;
}
.crop-stage:active { cursor: grabbing; }
.crop-stage canvas { width: 100%; height: 100%; display: block; }
.crop-mask {
  position: absolute; inset: 0;
  pointer-events: none;
  border-radius: 50%;
  box-shadow: 0 0 0 999px color-mix(in srgb, var(--bg) 72%, transparent);
}

/* ------------------------------------------------------- mini calendário */

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  text-align: center;
}
/* A grade ocupa a altura que sobrar no card, e as semanas se dividem por
   ela. O widget precisa caber no pior caso (seis semanas, como agosto de
   2026), e nos meses de cinco isso deixava uma faixa vazia embaixo: agora
   as linhas crescem para preencher. */
.wgrid .wcell .cal-grid:not(.cal-head) { flex: 1; align-content: stretch; }
.wgrid .wcell .wbody > .card:has(.cal-grid) {
  display: flex;
  flex-direction: column;
  /* O mes CABE, sem barra de rolagem.
     Num widget de cinco linhas o conteudo dava 292px numa caixa de 286: seis
     pixels de sobra, invisiveis na tela, bastavam para a barra aparecer ao
     lado de um calendario que ja se via inteiro. `min-height: 0` deixa a
     grade encolher ate o espaco disponivel -- por padrao um item flex nao
     encolhe abaixo do proprio conteudo, e era isso que gerava a sobra. */
  overflow: hidden;
}
.wgrid .wcell .cal-grid { min-height: 0; }
.cal-head span {
  font-size: .72rem;
  font-weight: 600;
  color: var(--text-faint);
  padding-bottom: .25rem;
}
/* Dia clicável: vira botão sem parecer um. */
.cal-day {
  font-size: .78rem;
  padding: .35rem 0;
  min-height: 0;
  border: none;
  background: none;
  border-radius: var(--r-xs);
  color: var(--text-dim);
  position: relative;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  display: block;
  width: 100%;
}
.cal-day:hover { background: var(--surface-2); color: var(--text); }
.cal-day.today:hover { background: var(--accent); filter: brightness(1.1); }
.cal-day.today {
  background: var(--accent);
  color: var(--sobre-accent, #fff);
  font-weight: 600;
}
/* Ponto marcando dia com compromisso — discreto para não competir com o
   destaque de hoje. */
.cal-day.busy::after {
  content: "";
  position: absolute;
  bottom: 2px; left: 50%;
  transform: translateX(-50%);
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--accent);
}
.cal-day.today.busy::after { background: var(--sobre-accent, #fff); }
/* Dia aberto no painel de resumo. */
.cal-day.picked {
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--text);
}
/* Hoje já tem o fundo do acento: manter o --text aqui deixava o número da
   mesma cor do fundo com o tema preto no claro (ou branco no escuro), e o
   dia sumia ao ser clicado. */
.cal-day.today.picked { color: var(--sobre-accent, #fff); }

/* Resumo do dia, dentro do próprio widget. */
.day-panel {
  margin-top: .7rem;
  padding-top: .7rem;
  border-top: 1px solid var(--border);
}
.day-panel .list li { padding: .35rem 0; font-size: .82rem; }

/* ----------------------------------------------------- seletor de widgets */

.widget-item:hover { background: var(--surface-2); }
.widget-item input {
  width: 16px; height: 16px; min-height: 16px;
  flex-shrink: 0; accent-color: var(--accent); cursor: pointer;
}

/* ------------------------------------------------------ gráficos e placar */

/* Dois por linha: com quatro colunas cada gráfico ficava estreito demais
   para ler a tendência. */
/* Sempre 2 por linha no desktop: auto-fit deixava 3 em cima e 1 sozinho
   embaixo, dependendo da largura. */
/* `minmax(0, 1fr)`, e não `1fr`: o padrão de um item de grade é
   `min-width: auto`, que o impede de encolher abaixo do conteúdo. Um número
   comprido dentro do card esticava a coluna para 358px numa grade de 334, e
   a aba inteira ganhava 12px de rolagem horizontal em 360px de tela. */
.chart-grid { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 760px) {
  .chart-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* O card que sobra sozinho na última fileira ocupa a linha inteira.
     As colunas são fixas, então sem isto ele fica com metade da largura e
     deixa um buraco do tamanho de outro card ao lado — foi o que apareceu
     ao desligar o Rendimento, e aconteceria igual ao desligar o Patrimônio
     ou qualquer outro bloco que deixe um número ímpar na tela.
     A conta é sobre a POSIÇÃO, não sobre qual bloco saiu: quem escolhe os
     blocos é a pessoa, e listar as combinações seria um caso novo a cada
     bloco criado. `:last-child:nth-child(odd)` é exatamente "é o último e
     está em coluna ímpar", isto é, ninguém veio ao lado. */
  .chart-grid > .card:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
/* "Novo lançamento": continua sendo a ação primária e continua laranja, mas
   com a largura do próprio texto. Em `btn-block` ele virava uma faixa de
   1280px numa tela de 1920 e pesava mais que os valores em dinheiro logo
   acima -- a ação gritava mais alto que a informação. No celular volta a
   ocupar a linha toda, onde largura cheia é o padrão de toque. */
.fin-novo {
  /* A margem de baixo saiu: o botao agora vive dentro de `.fin-acoes`, que
     ja tem a folga da linha inteira.
     
     O padding encolheu junto com o seletor de mes: os dois formam um
     conjunto, e ele precisa caber sob a barra de subabas. */
  padding-inline: .85rem;
}
@media (max-width: 560px) {
  /* Empilhado no celular, o botao ocupa a linha e o seletor de mes fica
     acima dele. */
  .fin-acoes { flex-direction: column; align-items: stretch; }
  .fin-mes { justify-content: center; }
  .fin-novo { width: 100%; }
}

.chart-line { width: 100%; height: 170px; display: block; overflow: visible; }

/* Linhas de apoio bem discretas: dão referência de altura sem disputar
   atenção com o dado. (`chart-grid` já é o container de duas colunas.) */
.chart-rule { stroke: var(--border); stroke-width: 1; opacity: .5; }

.chart-goal {
  /* Acompanha a cor do perfil, como o resto do Hub. */
  stroke: var(--accent);
  stroke-width: 1.2;
  stroke-dasharray: 5 4;
  opacity: .6;
}
.chart-goal-tag {
  fill: var(--accent);
  font-size: 11px;
  font-weight: 500;
  opacity: .85;
}

/* Datas dentro do próprio SVG: fora dele, desalinhavam do início e do fim
   da linha conforme a largura do card. */
.chart-axis {
  fill: var(--text-faint);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* O valor escrito ao lado de cada ponto. Menor que o eixo: ele acompanha o
   dado, não compete com ele. */
.chart-dot-tag {
  fill: var(--text-faint);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}

/* Último ponto em destaque: é onde a linha chegou. */
.chart-last { stroke: var(--surface); stroke-width: 2.5; }

.period-btn.active {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 500;
}

/* Card de quem está na frente hoje. */
.card.winner {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* Interrogação no canto do gráfico: o texto aparece no hover, pelo title. */
.grafico-ajuda {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px; height: 15px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  color: var(--text-faint);
  font-size: .72rem;
  font-weight: 600;
  margin-right: .35rem;
  cursor: help;
  vertical-align: middle;
}
.grafico-ajuda:hover { color: var(--accent-text); border-color: var(--accent); }

/* Quadrado de cor do ativo, clicável para trocar a cor da linha dele. */
/* O quadrado é pequeno por desenho, mas a área clicável não pode ser: no
   toque, 11px é menor que a ponta de um dedo. O ::after estende o alvo além
   do desenho, sem pintar nada a mais. */
.cor-troca {
  position: relative;
  width: 11px; height: 11px;
  border-radius: 3px;
  border: none;
  padding: 0;
  min-height: 0;
  flex-shrink: 0;
  cursor: pointer;
}
.cor-troca::after {
  content: "";
  position: absolute;
  inset: -10px;
}
.cor-troca:hover { outline: 2px solid var(--border-strong); outline-offset: 1px; }

/* Nome do ativo na legenda: leva para a análise só dele. */
.ativo-nome {
  flex: 1;
  min-width: 0;
  text-align: left;
  border: none;
  background: none;
  /* Altura de alvo de toque: o nome é a porta para a análise do ativo, e
     precisa ser acertado com o dedo. */
  padding: .4rem 0;
  min-height: 30px;
  font-size: .85rem;
  color: var(--text);
  cursor: pointer;
}
.ativo-nome:hover { color: var(--accent-text); }

/* A capa de uma fileira que rola, com as setas nas pontas.
   As setas ficam FORA da fileira: dentro, elas rolariam junto com o
   conteudo e sairiam da tela justamente quando fossem necessarias. */
.rola-capa { position: relative; min-width: 0; }
.rola-seta {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  min-height: 0;
}
.rola-seta:hover { color: var(--text); border-color: var(--border-strong); }
.rola-seta[hidden] { display: none; }
.rola-seta-esq { left: -6px; }
.rola-seta-dir { right: -6px; }

/* A BARRA DE ASSUNTOS das Noticias.
   Um assunto pode ter ate 40 caracteres, e nada impedia um nome desses de
   tomar a linha inteira: com dois ou tres deles a barra estourava, os
   controles da direita eram empurrados para uma segunda linha e a aba
   parecia quebrada. Cada botao para num teto e abrevia com reticencias --
   o nome inteiro fica no `title`. */
.noticias-barra .subtab {
  /* `vw` no teto: 14rem e quase metade de uma tela de 360px, e um assunto
     longo sozinho ja empurrava a barra alem da largura da janela. */
  max-width: min(14rem, 45vw);
  /* PISO: o botao nao encolhe abaixo do que da para ler. Sem ele, a barra
     apertada espremia todos por igual e "Gremio" virava "G" ao lado de
     quatro nomes longos abreviados -- o assunto curto, que caberia
     inteiro, sumia por causa dos outros. Chegando no piso, quem nao cabe
     sai para a rolagem, que e o comportamento da barra de abas. */
  /* PISO: o botao nao encolhe abaixo do que da para ler. Sem ele, a barra
     apertada espremia todos por igual e "Gremio" virava "G" ao lado de
     quatro nomes longos abreviados -- o assunto curto, que caberia
     inteiro, sumia por causa dos outros.

     `min(8rem, max-content)` porque o piso vale so para quem PRECISA dele:
     "IA" fica do tamanho de "IA", e nao ocupa 8rem porque um vizinho e
     longo. 8rem cabe "Tecnologia" com o contador ao lado. */
  min-width: min(8rem, max-content);
  flex: 0 1 auto;
}
.noticias-barra .subtab > .nome {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Os controles NAO descem: eles ficam na linha, e quem rola e a barra.
   `min-width: 0` sozinho nao bastava -- num container `row-between` o
   `.subtabs` ainda crescia com o conteudo, chegava a 1192px e nao sobrava
   espaco para os 380px das acoes, que caiam para uma segunda linha. Com
   `flex: 1 1 0` ele parte de largura ZERO e so cresce com o que sobra
   depois das acoes, entao ele e sempre quem cede. */
.noticias-barra > .subtabs,
.noticias-barra > .rola-capa {
  flex: 1 1 0;
  min-width: 0;
}
.noticias-barra > .subtabs-acoes { flex: 0 0 auto; }
/* A seta da esquerda nao pode cobrir a primeira subaba: dentro da barra,
   ela mora na margem que o `padding` abre. */
.noticias-barra > .rola-capa { padding: 0 4px; }

/* No CELULAR a linha de controles nao cabe: "hoje semana tudo", mais tres
   icones e "Atualizar" somam mais que 360px, e ela transbordava a janela.
   Ela ganha rolagem propria, como a barra de assuntos acima dela. */
@media (max-width: 640px) {
  /* No celular as setas saem: nao ha espaco para elas ao lado das subabas,
     e ali o dedo arrasta a fileira, que e o gesto natural do toque. */
  .rola-seta { display: none; }

  /* As duas fileiras EMPILHAM: os assuntos em cima, os controles embaixo.

     Lado a lado elas nao cabem. "hoje semana tudo" mais tres icones e
     "Atualizar" ja passam de 360px, e como os assuntos tem `flex: 1 1 0` --
     que parte de largura ZERO e so cresce com o que sobra --, eram eles que
     cediam TUDO: os quatro assuntos ficavam com 0px cada, presentes no DOM e
     invisiveis na tela. A pessoa via os controles e nenhuma forma de trocar
     de assunto, nem de editar a lista.

     Empilhados, cada fileira rola por conta e as duas cabem. */
  .noticias-barra {
    flex-direction: column;
    align-items: stretch;
    gap: .4rem;
  }

  /* Volta a crescer com o conteudo: a razao do `flex: 1 1 0` era disputar a
     linha com as acoes, e agora elas nao dividem mais linha nenhuma.

     `.subtabs` mora DENTRO de `.rola-capa` (a capa das setas de rolagem),
     entao o seletor precisa alcancar os dois niveis -- so o filho direto da
     barra deixava a fileira interna com largura zero do mesmo jeito. */
  .noticias-barra > .rola-capa,
  .noticias-barra .subtabs {
    flex: none;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  /* A regra que manda `.subtabs` para a gaveta no celular nao vale aqui: os
     assuntos de Noticias nao sao subabas, e a gaveta nao os conhece (ver a
     excecao acima). Numa fileira SO, rolando -- quebrar em duas come a
     altura que aquela regra foi escrita para poupar. */
  .noticias-barra .subtabs {
    display: flex;
    flex-wrap: nowrap;
  }
  .noticias-barra .subtabs::-webkit-scrollbar { display: none; }

  .noticias-barra > .subtabs-acoes {
    overflow-x: auto;
    scrollbar-width: none;
    max-width: 100%;
  }
  .noticias-barra > .subtabs-acoes::-webkit-scrollbar { display: none; }
  .noticias-barra > .subtabs-acoes > * { flex: none; }
}

/* A marca da empresa numa linha de vaga: a inicial num quadrado colorido.
   A cor vem do nome (`--tom`), entao a mesma empresa tem sempre a mesma, e
   o olho reencontra as linhas dela ao percorrer a lista. Saturacao e
   claridade sao fixas: so o matiz varia, para nenhuma marca gritar mais que
   as outras nem competir com o titulo da vaga. */
.vaga-marca {
  flex: none;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
  font-size: .82rem; font-weight: 600;
  background: hsl(var(--tom) 42% 88%);
  color: hsl(var(--tom) 55% 28%);
  margin-top: .1rem;
}
:root:not([data-theme="light"]) .vaga-marca {
  background: hsl(var(--tom) 26% 22%);
  color: hsl(var(--tom) 55% 76%);
}
:root[data-theme="dark"] .vaga-marca {
  background: hsl(var(--tom) 26% 22%);
  color: hsl(var(--tom) 55% 76%);
}
/* Vaga sem empresa informada ("Confidencial" vem vazio em alguns
   anuncios): fica um espaco da mesma largura, para os titulos nao
   desalinharem entre uma linha e outra. */
.vaga-marca-vazia { background: var(--surface-2); }

/* A subaba sendo ARRASTADA para mudar a ordem da barra.
   O gesto e o mesmo da barra de abas de cima; aqui ele substituiu um botao
   "Ordem" que abria uma janela de setas para subir e descer. */
.subtab-arrasta {
  opacity: .6;
  cursor: grabbing;
}
/* Enquanto arrasta, o texto nao pode ser selecionado: puxar a subaba pela
   palavra marcaria o rotulo em azul no meio do gesto. */
.subtabs-arrastando { user-select: none; }
.subtabs-arrastando .subtab { cursor: grabbing; }

/* --------------------------------------------------------------- diversos */

.empty {
  text-align: center;
  padding: 2rem 1rem;
  color: var(--text-dim);
}
.empty .ico { color: var(--text-faint); opacity: .5; margin-bottom: .5rem; }
.empty p { font-size: .85rem; }

.toast-area {
  position: fixed;
  bottom: 1rem; left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  display: flex; flex-direction: column; gap: .4rem;
  width: min(380px, calc(100vw - 2rem));
}
.toast {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-left: 2px solid var(--accent);
  border-radius: var(--r-sm);
  padding: .6rem .8rem;
  font-size: .85rem;
  box-shadow: 0 4px 12px rgb(0 0 0 / 10%);
  animation: rise .18s ease;
}
.toast.err { border-left-color: var(--err-text); }
.toast.ok { border-left-color: var(--ok-text); }
/* O aviso com "Desfazer": o texto ocupa o que sobra e o botão fica à
   direita, sem encolher. */
.toast-undo {
  display: flex;
  align-items: center;
  gap: .6rem;
}
.toast-undo span { flex: 1; min-width: 0; }
.toast-undo button {
  flex: none;
  color: var(--accent-text);
  font-weight: 600;
  padding: .2rem .5rem;
  min-height: 32px;
}
.toast-undo button:hover { background: var(--surface-2); }

@keyframes rise { from { opacity: 0; transform: translateY(6px); } }

.check-row {
  display: flex; align-items: center; gap: .6rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--border);
  font-size: .85rem;
}
.check-row:last-child { border-bottom: none; }
.check-icon { width: 18px; text-align: center; flex-shrink: 0; }
.check-icon.ok { color: var(--ok-text); }
.check-icon.warn { color: var(--warn); }
/* Não configurado: nem sucesso nem falha. Um check verde aqui dava a entender
   que a integração estava ativa quando ela nem foi ligada. */
.check-icon.off { color: var(--text-faint); }

.chart { width: 100%; height: 140px; display: block; }

/* A linha do tempo estica na largura do card, ao contrário do gráfico de
   barras: ela é uma tendência, não uma comparação de tamanhos, e sobrar
   espaço dos lados só encolhe o que se quer ler. `vector-effect` no traço
   mantém a espessura mesmo com o eixo esticado. */
.chart-linha { width: 100%; height: 52px; display: block; }
.chart-linha path { vector-effect: non-scaling-stroke; }

.banner {
  background: color-mix(in srgb, var(--warn) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warn) 28%, var(--border));
  border-radius: var(--r-sm);
  padding: .7rem .8rem;
  font-size: .82rem;
  line-height: 1.5;
  text-align: left;
}

/* Convite para deixar o Hub na tela inicial do celular.

   No meio da tela, e não numa faixa no rodapé: o convite aparece UMA VEZ na
   vida do aparelho, e uma tarja embaixo é fácil de não ver — ela compete com
   a barra do navegador e sai da atenção. Aparecendo uma vez só, precisa ser
   vista nessa vez.

   Espera alguns segundos antes de abrir, para não competir com o que a
   pessoa veio fazer.

   Abaixo dos toasts (100), que são efêmeros e precisam passar por cima. */
.instalar-capa {
  position: fixed; inset: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  /* A margem de segurança do aparelho entra como padding: sem ela, num
     iPhone o cartão alto encosta na barra de gestos. */
  padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  background: rgb(0 0 0 / 55%);
  animation: instalar-surge .2s ease-out;
}
.instalar-cartao {
  width: min(400px, 100%);
  /* Numa tela baixa (paisagem, teclado aberto) o cartão rola por dentro em
     vez de vazar para fora do alcance. */
  max-height: 100%; overflow-y: auto;
  text-align: center;
  padding: 1.4rem 1.2rem 1.1rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: 0 12px 32px rgb(0 0 0 / 26%);
  animation: instalar-sobe .22s ease-out;
}
.instalar-cartao h2 { margin: .5rem 0 .3rem; font-size: 1.05rem; }
.instalar-cartao p { margin: 0 0 1.1rem; }
.instalar-icone .ico { color: var(--accent-text); }
/* Os botões empilham; só o segundo precisa de um respiro para não colar. */
.instalar-cartao .btn-ghost { margin-top: .4rem; }

@keyframes instalar-surge {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes instalar-sobe {
  from { opacity: 0; transform: translateY(10px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .instalar-capa, .instalar-cartao { animation: none; }
}

/* As linhas do painel de lembretes: rótulo à esquerda, liga/desliga à
   direita. Compactas de propósito — com o espaçamento padrão de `.field`,
   as oito linhas somavam mais de uma tela de celular. */
.lemb-linha { margin-bottom: .55rem; }
.lemb-linha + hr { margin: .8rem 0; }
/* `align-items: center` para o rótulo e os botões ficarem na mesma linha
   de base: sem isto o texto subia e os botões desciam, e cada linha do
   painel parecia desalinhada da anterior. */
.lemb-linha .row-between { align-items: center; }

/* As fontes do alarme: três botões que são o próprio estado. Grade de três
   colunas, e não flex: com larguras diferentes ("Agenda" é menor que
   "Hábitos"), o wrap deixava a fileira irregular. */
/* As antecedências: cinco colunas iguais, com o texto numa linha só. */
.antes-lista {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: .3rem;
}
.antes-lista .tam-opt { padding-left: .2rem; padding-right: .2rem; white-space: nowrap; }

.alarme-fontes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .35rem;
}
.fonte-opt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .3rem;
  font: inherit;
  font-size: .85rem;
  cursor: pointer;
  padding: .5rem .4rem;
  border-radius: var(--r-sm);
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.fonte-opt:hover { color: var(--text); border-color: var(--border-strong); }
.fonte-opt.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
  font-weight: 500;
}
.fonte-opt .ico { opacity: .8; }

/* Dois tipos de aviso, e nao tres fontes de alarme: numa grade de tres
   sobrava uma celula vazia a direita. */
.lembdia-tipos { grid-template-columns: repeat(2, 1fr); }

/* Os horarios do lembrete. O campo nativo de hora desenha estreito demais
   sozinho; sem o flex ele encolhe ate cortar o "21:00". */
.lembdia-hora {
  flex: 1;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

.fonte-opt.active .ico { color: currentColor; opacity: 1; }

/* ------------------------------------------- anotar a saude, no Inicio

   Compacto de proposito: com o rotulo ACIMA de cada campo o widget gastava
   duas linhas por numero e precisava de cinco linhas de grade para mostrar
   quatro. O rotulo virou uma etiqueta pequena colada no campo. */
.saude-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: .4rem;
}
.saude-campo {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  min-width: 0;
}
.saude-rot {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-faint);
}
.saude-campo input {
  width: 100%;
  min-height: 32px;
  padding: .25rem .45rem;
  font-size: .85rem;
}
.saude-humor {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  margin-top: .45rem;
}
/* A fileira de humor encolhe junto: sete emojis no tamanho da aba nao
   caberiam ao lado do rotulo num widget de seis colunas. */
.saude-humor .mood-row { flex: 1; min-width: 0; gap: .15rem; margin: 0; }
.saude-humor .mood-opt { padding: .15rem; min-width: 0; }
.saude-salva { margin-top: .5rem; min-height: 34px; }

/* ------------------------------------------- o que ja preenchi hoje

   Uma caixinha por area, com o visto quando ela ja tem registro do dia.
   A grade se ajusta sozinha: o widget vai de 3 a 12 colunas conforme a
   pessoa o arrasta, e um numero fixo de colunas cortaria numa largura ou
   deixaria uma faixa vazia na outra. */
.usadas-grade {
  display: grid;
  /* `auto-fit` com `1fr`: as colunas que couberem, e o que sobra é dividido
     entre elas -- as caixinhas esticam para ocupar a largura inteira em vez
     de ficarem apertadas à esquerda com um vão à direita, que é o que
     `auto-fill` faria ao reservar colunas vazias.

     6.5rem é o que cabe "Finanças" e "Notícias" inteiros com o ícone e o
     visto. Tentei 5.5 para fechar mais caixinhas por fileira, e os dois
     rótulos passaram a cortar em reticências -- e um visto ao lado de
     "Hábit…" não diz o que foi preenchido, que é a única coisa que este
     widget existe para dizer. A fileira incompleta é o preço, e é o menor
     dos dois. */
  grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: .3rem;
  /* Cada caixinha tem a altura de uma linha, e não a da fileira: esticada,
     três viravam três barras altas. */
  align-items: start;
}
/* A grade ocupa a largura, mas NÃO estica na altura: esticada, três
   caixinhas viravam três barras altas e a fileira incompleta deixava um vão
   ainda maior. Uma caixinha de aba tem a altura de uma linha de texto, e é
   assim que ela se lê. O que sobra fica embaixo, junto. */
.wbody > .card > .usadas-grade {
  align-content: start;
}
.usada {
  display: flex;
  align-items: center;
  gap: .35rem;
  min-height: 30px;
  padding: .3rem .4rem;
  font: inherit;
  font-size: .8rem;
  cursor: pointer;
  text-align: left;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.usada:hover { border-color: var(--accent); }
.usada-ico { display: flex; flex-shrink: 0; opacity: .8; }
.usada-nome {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* O visto ocupa lugar mesmo vazio: sem isto o nome escorregaria para a
   direita ao ser marcado, e a fileira inteira dancaria durante o dia. */
.usada-marca {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  flex-shrink: 0;
  color: var(--ok-text);
}

/* As duas naturezas, separadas no painel de escolha. */
.vistos-sec + .vistos-sec { margin-top: .9rem; }
.vistos-sec-tit {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-dim);
  font-weight: 600;
}
/* Preenchida: a borda e o icone ganham a cor do PERFIL, nao um verde fixo.
   Verde no Hub quer dizer dinheiro que entrou; aqui e so "ja preenchi hoje",
   que e estado -- e estado destacado segue o acento. Com o acento ambar ou
   azul, o verde aparecia como cor de fora do tema.

   O fundo usa `color-mix` para nao virar um bloco chapado ao lado dos
   pendentes. */
.usada.on {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface-2));
}
.usada.on .usada-ico { color: var(--accent-text); opacity: 1; }
.usada.on .usada-marca { color: var(--accent-text); }

/* ------------------------------------------- atalhos do caderno

   A linha inteira e o botao, como nos habitos: o alvo grande e o que faz
   o atalho valer a pena no celular. */
.cad-atalho {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  border: 0;
  background: transparent;
  padding: 0;
  min-height: 0;
  font: inherit;
  cursor: pointer;
  color: var(--text);
}
.list li:has(> .cad-atalho) { padding: .5rem 0; }
.cad-atalho:hover { color: var(--accent-text); }
.cad-atalho-ico { flex-shrink: 0; font-size: 1rem; line-height: 1; }
.cad-atalho span:not(.cad-atalho-ico) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ------------------------------------------- cardapio do dia, no Inicio */
.cardapio-linha {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  border: 0;
  background: transparent;
  padding: 0;
  min-height: 0;
  font: inherit;
  cursor: pointer;
  color: var(--text);
  text-align: left;
}
.list li:has(> .cardapio-linha) { padding: .55rem 0; }
.cardapio-linha:hover .hab-ponto { border-color: var(--accent); }
.cardapio-linha:disabled { cursor: default; opacity: .7; }

/* ------------------------------------------------------------ busca */

/* A busca abre no ALTO, não no centro: a lista cresce para baixo enquanto
   se digita, e um painel centralizado ficaria pulando a cada tecla. */
.busca-capa {
  position: fixed; inset: 0; z-index: 60;
  display: flex; justify-content: center;
  padding: 8vh 1rem 1rem;
  background: rgb(0 0 0 / 45%);
}
.busca-caixa {
  width: min(560px, 100%);
  /* `max-height` e não `height`: a caixa cresce com os resultados e para no
     teto. Com altura fixa, três resultados deixavam metade da tela em
     branco embaixo, parecendo que faltou carregar alguma coisa. */
  max-height: 78vh;
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: 0 16px 44px rgb(0 0 0 / 28%);
  overflow: hidden;
}
.busca-topo {
  display: flex; align-items: center; gap: .6rem;
  padding: .7rem .9rem;
  border-bottom: 1px solid var(--border);
}
.busca-topo .ico { color: var(--text-faint); flex: none; }
#buscaCampo {
  flex: 1; min-width: 0;
  font: inherit;
  /* Sem moldura própria: a caixa inteira já é o campo, e a borda do `input`
     do CSS base desenhava um retângulo dentro de outro. */
  padding: 0;
  /* Sem moldura própria: a caixa inteira já é o campo, e a borda do `input`
     do CSS base desenhava um retângulo dentro de outro. */
  padding: 0;
  /* 16px: abaixo disso o iOS dá zoom sozinho ao focar o campo. */
  font-size: 1rem;
  color: var(--text);
  background: none;
  border: none;
}
#buscaCampo:focus { outline: none; }

.busca-sugestoes { display: flex; flex-wrap: wrap; gap: .3rem; padding: .6rem .9rem 0; }
.busca-sugestoes:empty { display: none; }
.busca-sug {
  font: inherit; font-size: .8rem;
  cursor: pointer;
  padding: .25rem .6rem;
  border-radius: var(--r-pill);
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.busca-sug:hover { color: var(--text); border-color: var(--border-strong); }

.busca-resultados { overflow-y: auto; padding: .4rem; }
.busca-vazio { text-align: center; padding: 1.4rem 0; margin: 0; }

.busca-item {
  display: flex; align-items: center; gap: .8rem;
  width: 100%;
  font: inherit;
  cursor: pointer;
  text-align: left;
  padding: .6rem .7rem;
  border: none;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text);
}
.busca-item:hover { background: var(--surface-2); }
.busca-txt {
  flex: 1; min-width: 0;
  font-size: .9rem;
  /* Uma linha só: um texto de nota com três parágrafos empurraria os
     resultados seguintes para fora da tela. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.busca-meta { flex: none; font-size: .78rem; color: var(--text-faint); }

@media (max-width: 560px) {
  .busca-capa { padding: 4vh .6rem .6rem; }
  .busca-caixa { max-height: 88vh; }
}

/* ------------------------------------------------ orçamento por categoria */

/* A engrenagem do limite fica junto do valor, e SEMPRE visível.

   Escondê-la até o mouse passar parecia mais limpo e escondeu o recurso:
   quem não sabe que o limite existe nunca leva o cursor até lá para
   descobrir. Apagada já basta para não competir com os números. */
.orc-btn {
  min-height: 22px;
  padding: 0 .25rem;
  margin-left: .3rem;
  vertical-align: middle;
  color: var(--text-faint);
  opacity: .55;
  transition: opacity .12s, color .12s;
}
.orc-btn:hover, .orc-btn:focus-visible { opacity: 1; color: var(--text); }

/* O aviso vem depois da barra, curto. Cor só nos dois casos que pedem
   atenção: passou do limite, ou está perto. */
.orc-aviso, .orc-perto { margin-top: .25rem; }
.orc-aviso { color: var(--err-text); }
.orc-perto { color: var(--warn); }

/* ------------------------------------------ prioridade e subtarefas */

/* A linha da tarefa virou duas: o topo (que já existia) e as etapas.

   `.list li` é flex e alinha tudo numa fileira; sem `display: block` aqui,
   as subtarefas iam para a DIREITA do texto em vez de ficarem embaixo.
   O seletor cita as duas classes para vencer `.list li` por especificidade. */
.list li.tarefa-linha { display: block; }
.tarefa-topo { display: flex; align-items: center; gap: .5rem; }

/* A marca de prioridade: um caractere, não uma etiqueta com a palavra.
   "Alta" escrito por extenso em cada linha vira uma coluna de texto que
   compete com o nome da tarefa, que é o que a pessoa lê. */
.prio {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 1.15rem; height: 1.15rem;
  border-radius: 5px;
  font-size: .78rem;
  font-weight: 700;
  line-height: 1;
}
.prio-alta { background: color-mix(in srgb, var(--err) 16%, transparent); color: var(--err-text); }
.prio-baixa { background: var(--surface-2); color: var(--text-faint); }

/* O contador de etapas, que também abre e fecha a lista. */
.sub-conta, .sub-add {
  flex: none;
  min-height: 26px;
  padding: .1rem .45rem;
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}
.sub-conta:hover, .sub-add:hover { color: var(--text); }
/* O "+" fica SEMPRE visível, só apagado.

   Escondê-lo até o mouse passar teve o mesmo problema da engrenagem do
   orçamento: quem não sabe que dá para dividir a tarefa em etapas nunca
   leva o cursor até lá para descobrir. E no celular não existe hover. */
.sub-add { opacity: .5; transition: opacity .12s, color .12s; }
.sub-add:hover, .sub-add:focus-visible { opacity: 1; color: var(--text); }

.sublista {
  list-style: none;
  margin: .35rem 0 .2rem 1.7rem;
  padding-left: .8rem;
  border-left: 2px solid var(--border);
}
.sublista li {
  display: flex; align-items: center; gap: .5rem;
  padding: .25rem 0;
  font-size: .9rem;
}
.sublista .sub-input {
  width: 100%;
  font: inherit;
  font-size: .9rem;
  padding: .3rem .1rem;
  color: var(--text);
  background: none;
  border: none;
  border-bottom: 1px dashed var(--border-strong);
}
.sublista .sub-input:focus { outline: none; border-bottom-color: var(--accent-text); }

/* A lista de sons: etiquetas que tocam ao serem escolhidas.

   Grade de três colunas, e não `flex-wrap`: com o wrap a quebra dependia do
   comprimento de cada nome, e os seis saíam 4 + 2, com a última fila pela
   metade. Em três colunas ficam 3 + 3, e todas as etiquetas com a mesma
   largura — o olho compara nomes, não retângulos de tamanhos diferentes. */
.sons-lista {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .35rem;
}
.som-opt {
  display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
  font: inherit; font-size: .85rem;
  cursor: pointer;
  padding: .45rem .8rem;
  border-radius: var(--r-pill);
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.som-opt:hover { color: var(--text); border-color: var(--border-strong); }
/* "O meu" enquanto não há arquivo: visível para dizer que a opção existe,
   travado porque não há o que tocar. Tracejado em vez de sólido — a borda
   diz "falta preencher", e não "quebrou". */
.som-opt[disabled] {
  opacity: .45;
  cursor: default;
  border-style: dashed;
}
.som-opt[disabled]:hover { color: var(--text-dim); border-color: var(--border); }
.som-opt.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
  font-weight: 500;
}
.som-opt.active .ico { color: currentColor; }

/* O seletor de arquivo do navegador é feio e varia por sistema; encolher a
   fonte e dar borda ao menos o encaixa no resto do painel. */
.arq-som {
  width: 100%;
  font-size: .82rem;
  padding: .5rem;
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-dim);
}

/* O aviso do alarme: um cartão fixo no alto, com o botão de parar.

   Não é um toast: toast some sozinho em segundos, e o alarme precisa ficar
   até alguém dispensá-lo — é o que separa "avisei" de "você viu".

   Acima dos toasts (100) porque é o único aviso que exige ação. */
.alarme-aviso {
  position: fixed;
  z-index: 110;
  /* Abaixo do cabeçalho (62px), e não colado no topo da janela: ali ele
     cobria o título de qualquer modal aberto — inclusive o painel de
     lembretes, que é justamente onde a pessoa vai depois de ouvir o alarme. */
  top: calc(4.6rem + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  width: min(420px, calc(100vw - 1.6rem));
  display: flex; align-items: center; gap: .7rem;
  padding: .8rem .9rem;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  box-shadow: 0 10px 30px rgb(0 0 0 / 24%);
  animation: alarme-desce .22s ease-out;
}
.alarme-ico { flex: none; }
.alarme-ico .ico { color: var(--accent-text); }
.alarme-txt { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.alarme-txt strong { font-size: .9rem; line-height: 1.3; }
/* `flex: none` para o botão não encolher: com um título longo o flex o
   espremia até virar duas letras por linha, e é justamente o alvo do dedo. */
.alarme-aviso .btn { flex: none; }

@keyframes alarme-desce {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .alarme-aviso { animation: none; }
}

/* O resumo do dia: a lista de compromissos dentro do modal.

   Grade de três colunas em vez de flex: a hora tem largura fixa e os títulos
   alinham entre si. Com flex, um título longo empurrava a hora do vizinho e
   a coluna ficava serrilhada. */
.resumo-lista { text-align: left; }
.resumo-item {
  display: grid;
  grid-template-columns: 3.2rem 1.1rem 1fr;
  align-items: baseline;
  gap: .5rem;
  padding: .55rem 0;
  border-bottom: 1px solid var(--border);
}
.resumo-item:last-child { border-bottom: none; }
.resumo-hora {
  font-family: var(--font-mono);
  font-size: .85rem;
  font-weight: 600;
  color: var(--accent-text);
}
.resumo-ico .ico { color: var(--text-faint); }
.resumo-txt { font-size: .9rem; line-height: 1.35; }
.resumo-txt .muted { display: block; font-size: .72rem; }

/* O que já passou continua na lista, apenas mais apagado: sumir faria a pessoa
   achar que esqueceu de marcar, e a hora que passou ainda informa onde ela
   está no dia.

   SEM riscar. O risco diz "concluído", e o Hub não sabe disso — só sabe que o
   relógio passou. Pior: abrindo o Hub à noite, a lista inteira apareceria
   riscada e o resumo pareceria defeito, que foi o que a captura mostrou. */
.resumo-item.passou { opacity: .55; }

.viewing-banner {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: var(--r-sm);
  padding: .6rem .8rem;
  font-size: .82rem;
  margin-bottom: .9rem;
  display: flex; align-items: center; gap: .5rem;
}
.viewing-banner .ico { color: var(--accent-text); }

hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1rem 0;
}

@media (max-width: 640px) {
  .wrap { padding: .8rem; }
  h1 { font-size: 1.2rem; }
  .stat-value { font-size: 1.4rem; }
  .card { padding: .8rem; }

  /* Os cards de número são resumo, não conteúdo: em duas colunas altas eles
     tomavam quase a tela inteira antes de a pessoa ver qualquer coisa. Aqui
     ficam compactos, e o que ela abriu a aba para ver aparece de cara. */
  .grid-4 { gap: .5rem; }

  /* O card que sobra sozinho na ultima fileira ocupa a linha inteira.
     Em 360px o `auto-fit` com minimo de 150px resolve para DUAS colunas, e
     cinco indicadores caem em 2+2+1: o ultimo ficava com metade da largura
     e um buraco do tamanho de outro card ao lado.

     Mesma solucao ja usada no `.chart-grid`, e pela mesma razao: a conta e
     sobre a POSICAO, nao sobre quantos cards existem. Quem escolhe os
     indicadores e a pessoa, em Organizar, entao o numero varia -- e
     `:last-child:nth-child(odd)` cobre todos os casos sem listar nenhum. */
  .grid-4 > .card:last-child:nth-child(odd) { grid-column: 1 / -1; }

  /* ...MENOS quando o Humor ja esticou antes dele. Nesse caso a paridade
     mente: o Humor conta como UM filho mas ocupa DOIS lugares, entao o
     ultimo card e par na grade mesmo sendo impar no DOM. Deixado esticado,
     ele descia sozinho e sobrava meia fileira vazia acima -- exatamente o
     buraco ao lado do Sono. Voltando a uma coluna, ele sobe e fecha a
     fileira (o `dense` acima e quem o traz). */
  .grid-4 > .card.stat:has(.mood-row) ~ .card:last-child:nth-child(odd) {
    grid-column: auto;
  }
  .grid-4 > .card.stat { padding: .6rem .7rem; }
  .grid-4 > .card.stat .stat-value { font-size: 1.05rem; }
  .grid-4 > .card.stat .stat-head { margin-bottom: .15rem; }
  .grid-4 > .card.stat .stat-label { font-size: .72rem; }
  .grid-4 > .card.stat .stat-goal { font-size: .72rem; }
}


/* ------------------------------------------------------------------ tour */

.tour-capa {
  position: fixed;
  inset: 0;
  /* Acima do cabeçalho (30), que tem backdrop-filter e por isso repinta o
     próprio fundo por cima de qualquer sombra vinda de baixo. Ainda abaixo
     dos modais (50): se um abrir durante o tour, precisa ficar por cima. */
  z-index: 45;
}

/* O escurecido são QUATRO faixas ao redor do alvo, não uma sombra gigante:
   `box-shadow: 0 0 0 9999px` some quando algum ancestral cria contexto de
   empilhamento — foi o que aconteceu com o cabeçalho, que usa
   backdrop-filter. Faixas são elementos de verdade e sempre pintam. */
.tour-sombra {
  position: absolute;
  background: rgb(0 0 0 / 62%);
  transition: all .2s;
}

.tour-furo {
  position: absolute;
  border-radius: var(--r-sm);
  border: 2px solid var(--accent);
  /* Curva com leve desaceleração no fim: o retângulo "pousa" no alvo em vez
     de parar seco, e o olho acompanha o caminho. */
  transition: top .34s cubic-bezier(.34, 1.2, .5, 1),
              left .34s cubic-bezier(.34, 1.2, .5, 1),
              width .34s cubic-bezier(.34, 1.2, .5, 1),
              height .34s cubic-bezier(.34, 1.2, .5, 1);
  pointer-events: none;
}

/* Pulso que sai da borda destacada: chama a atenção para onde o furo parou,
   sem piscar nem exigir que a pessoa procure. */
.tour-furo::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  border: 2px solid var(--accent);
  animation: tour-pulso 1.6s ease-out infinite;
}

@keyframes tour-pulso {
  0%   { transform: scale(1);    opacity: .7; }
  70%  { transform: scale(1.14); opacity: 0; }
  100% { transform: scale(1.14); opacity: 0; }
}

.tour-balao {
  position: absolute;
  width: min(320px, calc(100vw - 28px));
  transition: top .34s cubic-bezier(.34, 1.2, .5, 1),
              left .34s cubic-bezier(.34, 1.2, .5, 1);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  box-shadow: 0 12px 32px rgb(0 0 0 / 28%);
  padding: .9rem 1rem;
}
/* O conteúdo entra deslizando a cada passo, para ficar claro que mudou —
   o balão em si desliza até o alvo, e sem isso o texto trocaria sem aviso. */
.tour-balao .tour-conteudo {
  animation: tour-entra .26s ease-out;
}

@keyframes tour-entra {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.tour-balao h3 { font-size: .95rem; margin-bottom: .35rem; }
.tour-balao p { font-size: .85rem; color: var(--text-dim); line-height: 1.5; }

.tour-pe {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin-top: .9rem;
}

/* Barra fina mostrando o quanto falta. Substitui contar "3 de 9" na cabeça. */
.tour-barra {
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--border);
  overflow: hidden;
  margin-bottom: .8rem;
}
.tour-barra > i {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: var(--r-pill);
  transition: width .34s ease;
}

/* Quem pediu menos movimento recebe as posições sem o caminho até elas. */
@media (prefers-reduced-motion: reduce) {
  .tour-furo,
  .tour-balao,
  .tour-sombra { transition: none; }
  .tour-furo::after { animation: none; }
  .tour-balao .tour-conteudo { animation: none; }
}


.mc-titulo {
  min-width: 9.5rem;
  font-weight: 600;
  gap: .3rem;
}

.mc-meses {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .3rem;
}
.mc-meses .active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
}

/* Rosca dos macros: gráfico e legenda lado a lado, empilhando no estreito. */
.pizza-wrap {
  display: flex;
  align-items: center;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}
.pizza-leg { list-style: none; display: grid; gap: .3rem; min-width: 150px; }
.pizza-leg li { display: flex; align-items: center; gap: .45rem; font-size: .82rem; }
.pizza-cor { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }

/* Bolinha com a cor do evento, para reconhecer o compromisso de relance —
   as cores só existiam no calendário do mês. */
.ev-cor {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

/* A linha inteira do hábito é o botão, no widget do Início. */
.hab-linha {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  border: 0;
  background: transparent;
  padding: 0;
  min-height: 0;
  font-size: inherit;
}
/* O <li> já dá o respiro da linha. Antes o botão somava o padding dele com o
   do <li> e uma linha de hábito ficava 4px mais alta que uma de tarefa: no
   mesmo tamanho de widget, os hábitos cortavam e as tarefas cabiam.
   A área de toque continua a mesma, porque o botão ocupa o <li> inteiro. */
.list li:has(> .hab-linha) { padding: .55rem 0; }
.hab-linha:hover { background: transparent; }
.hab-linha:hover .hab-ponto { border-color: var(--accent); }

/* Marcador de hábito no widget: cheio quando feito. */
.hab-ponto {
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  flex-shrink: 0;
}
.hab-ponto.on { background: var(--accent); border-color: var(--accent); }

/* Refeição marcada como comida: fica verde e preenchida, para dar de
   relance a leitura do que já foi comido no dia. */
/* Marcar em cima, alinhado à direita; editar e remover embaixo. */
.meal-acoes {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .3rem;
  flex-shrink: 0;
}

/* Largura fixa nos dois estados: o botao alterna entre "Marcar" (6 letras)
   e "Comi" (4), e sem isso ele encolhia ao ser clicado -- a linha inteira
   se remexia a cada refeicao marcada, e numa lista de quatro refeicoes os
   botoes ficavam desalinhados entre si. O `min-width` cabe a palavra maior
   mais o icone. */
.comi-btn {
  white-space: nowrap;
  min-width: 6.6rem;
  justify-content: center;
}
.comi-btn.comi-on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
}
.comi-btn.comi-on:hover { background: var(--accent); filter: brightness(1.08); }

/* ------------------------------------------------------------- hábitos */

.hab-lista { display: grid; gap: .35rem; }

.hab-item {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem .6rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.hab-item.feito { border-color: var(--accent); }

/*
 * Arrastar para mudar a ordem. A alça é o único ponto que pega: arrastar pelo
 * corpo do item roubaria o toque de quem só quer marcar o hábito, e no celular
 * não há como distinguir a intenção antes do gesto começar.
 */
.hab-grip {
  cursor: grab;
  color: var(--text-faint);
  user-select: none;
  flex-shrink: 0;
  padding: .2rem .1rem;
  line-height: 1;
  /* Sem isto o Android rola a página em vez de arrastar o item. */
  touch-action: none;
}
.hab-item.arrastando {
  opacity: .5;
  cursor: grabbing;
  border-color: var(--accent);
}
/* Para onde o item vai cair. */
.hab-item.alvo-acima { box-shadow: 0 -2px 0 0 var(--accent); }
.hab-item.alvo-abaixo { box-shadow: 0 2px 0 0 var(--accent); }

/* A alça das tarefas sem horário, com o mesmo gesto dos hábitos. Discreta
   por padrão: ela é uma saída para quem quer reordenar, não um convite
   permanente numa lista que a maioria só lê. */
.tarefa-grip {
  cursor: grab;
  color: var(--text-faint);
  user-select: none;
  flex-shrink: 0;
  padding: .2rem .1rem;
  line-height: 1;
  opacity: .45;
  /* Sem isto o Android rola a página em vez de arrastar o item. */
  touch-action: none;
}
.tarefa-linha:hover .tarefa-grip { opacity: 1; }
.tarefa-linha.arrastando { opacity: .5; }
.tarefa-linha.alvo-acima { box-shadow: 0 -2px 0 0 var(--accent); }
.tarefa-linha.alvo-abaixo { box-shadow: 0 2px 0 0 var(--accent); }

.hab-check {
  width: 24px; height: 24px;
  min-height: 24px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  background: transparent;
  padding: 0;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.hab-item.feito .hab-check {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
}

.hab-nome { flex: 1; min-width: 0; font-size: .9rem; }
.hab-item.feito .hab-nome { color: var(--text-dim); }

/* A sequência é o que faz alguém não querer quebrar o hábito. */
.hab-seq {
  color: var(--accent-text);
  font-weight: 500;
  white-space: nowrap;
}

/* Quando o hábito se repete, quando não é todo dia. Discreto: é contexto,
   não a informação principal da linha. */
.hab-quando {
  color: var(--text-faint);
  white-space: nowrap;
}

/* Os sete dias da semana no seletor de repetição. */
.hab-dia {
  flex: 1;
  min-width: 0;
  padding: .4rem .1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-dim);
  font-size: .72rem;
  font-family: inherit;
  cursor: pointer;
}
.hab-dia:hover { border-color: var(--accent); }
.hab-dia.ativo {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--sobre-accent, #fff);
  font-weight: 500;
}
.hab-preset { white-space: nowrap; }

/* Pontuação da competição: rótulo à esquerda, campo curto à direita. */
.pt-grid { display: grid; gap: .4rem; }
.pt-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
  padding: .4rem .6rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.pt-rot { font-size: .85rem; line-height: 1.3; }
.pt-item input { width: 68px; text-align: center; }

/* Sub-abas dentro de um painel de configurações. Menores que as de cima,
   para ficar claro que são um nível abaixo. */
.cfg-subtabs {
  display: flex;
  gap: .2rem;
  margin-bottom: .9rem;
  padding: .2rem;
  background: var(--surface-2);
  border-radius: var(--r-sm);
}
.cfg-subtab {
  flex: 1;
  border: 0;
  background: transparent;
  border-radius: calc(var(--r-sm) - 2px);
  padding: .35rem .5rem;
  font-size: .82rem;
  color: var(--text-dim);
  min-height: 30px;
}
.cfg-subtab:hover { background: var(--surface); }
.cfg-subtab.active {
  background: var(--surface);
  color: var(--text);
  font-weight: 500;
  box-shadow: var(--shadow);
}

/* --------------------------------------------------------------- dieta */

/* Quantidade e alimento em campos separados. Juntos num texto só, "200g de
   frango" virava adivinhação: sem unidade o valor era chutado, e um engano
   de digitação devolvia calorias de outro alimento. */
.mf-add {
  display: grid;
  grid-template-columns: 120px 1fr auto;
  gap: .4rem;
  align-items: start;
}
.mf-qtd { display: flex; gap: .2rem; }
.mf-qtd input { min-width: 0; }
.mf-qtd select { width: 62px; padding-right: .3rem; }

.mf-busca { position: relative; min-width: 0; }

.mf-sug {
  position: absolute;
  top: calc(100% + 2px);
  left: 0; right: 0;
  z-index: 5;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow);
  max-height: 210px;
  overflow-y: auto;
}
.mf-sug-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: .6rem;
  width: 100%;
  border: 0;
  border-radius: 0;
  background: transparent;
  text-align: left;
  padding: .4rem .6rem;
  min-height: 34px;
  font-size: .85rem;
}
.mf-sug-item:hover { background: var(--surface-2); }

@media (max-width: 560px) {
  /* Numa tela estreita o alimento precisa da linha inteira. */
  .mf-add { grid-template-columns: 1fr auto; }
  .mf-qtd { grid-column: 1 / -1; }
}

/* Ingrediente com os valores ao lado. A linha inteira é clicável: conferir
   o que a tabela calculou é o caso comum, não a exceção. */
.mf-ing {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .45rem .6rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  margin-bottom: .3rem;
  cursor: pointer;
  background: var(--surface);
}
.mf-ing:hover { border-color: var(--border-strong); background: var(--surface-2); }

.mf-ing-nome { flex: 1; min-width: 0; font-size: .85rem; }
.mf-ing-vals { white-space: nowrap; }

/* Sem valores: tracejado, para a pessoa ver de longe o que falta medir. */
.mf-ing.sem-valor { border-style: dashed; }

.mf-total {
  margin-top: .6rem;
  padding: .55rem .7rem;
  border-radius: var(--r-sm);
  background: var(--surface-2);
}


/* Rendimento agrupado: o tipo é clicável e abre os papéis dele. */
.rend-tipo { cursor: pointer; }
.rend-tipo:hover { background: var(--surface-2); }

.rend-seta {
  display: inline-flex;
  vertical-align: middle;
  margin-left: .2rem;
  color: var(--text-faint);
  transition: transform .2s;
}
.rend-seta.aberta { transform: rotate(180deg); }

/* Os papéis do tipo aberto: recuados, para ficar claro que pertencem a ele. */
.rend-filhos {
  display: block;
  padding: 0 0 .2rem 1.1rem;
  border-left: 2px solid var(--border);
  margin-left: .3rem;
}
.rend-filhos .list li { border: 0; padding: .3rem 0; }


/* Sub-abas à esquerda, ações da aba à direita. Numa tela estreita as ações
   descem para a linha de baixo em vez de espremer as abas. */
.subtabs-linha { flex-wrap: wrap; gap: .5rem; }
.subtabs-acoes { flex-wrap: wrap; }

/* Placar compacto do widget: nome, barra e pontos na mesma linha. */
.comp-linhas { display: grid; gap: .45rem; }

.comp-linha {
  display: grid;
  grid-template-columns: minmax(60px, auto) 1fr auto;
  align-items: center;
  gap: .6rem;
}
.comp-nome {
  font-size: .85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.comp-nome.lider { font-weight: 600; }
.comp-linha .score-bar { margin: 0; }

/* Empurrado para o rodapé do card: o placar fica em cima, os dias embaixo,
   e o widget não estica além do tamanho da célula. */
.comp-dias { margin-top: auto; padding-top: .5rem; }

/* ---------------------------------------------------------- competição */

/* Medalha sobre o avatar. Pequena de propósito: marca quem está na frente
   sem virar o elemento principal do cabeçalho. */
.avatar[data-medalha]:not([data-medalha=""])::after {
  /* A medalha e DESENHADA, nao escrita. Antes `content: attr(...)` imprimia
     o emoji guardado no atributo; com o emoji fora, o atributo passou a
     guardar so o estado (`ouro`/`prata`) e o desenho vem daqui.

     `mask` com o mesmo caminho do icone `medalha`: um retangulo colorido
     recortado no formato da medalha. E o jeito de por SVG num pseudo-
     elemento, que nao aceita marcacao. */
  content: '';
  position: absolute;
  top: -6px;
  right: -4px;
  width: 13px;
  height: 13px;
  background: currentColor;
  -webkit-mask: var(--medalha-svg) center / contain no-repeat;
  mask: var(--medalha-svg) center / contain no-repeat;
  filter: drop-shadow(0 1px 1px rgb(0 0 0 / 35%));
  pointer-events: none;
}
.avatar[data-medalha="ouro"]::after  { color: #c9a227; }
.avatar[data-medalha="prata"]::after { color: #9aa0a6; }
.avatar { position: relative; }

/* A corrida: cada um numa pista, à distância dos próprios pontos. */
.corrida { display: grid; gap: .9rem; }
.corrida-pista { display: grid; gap: .25rem; }

.corrida-linha {
  position: relative;
  height: 46px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  /* Espaço para o corredor não sair da pista nas pontas. */
  margin: 0 30px;
}

/* Faixa preenchida até onde a pessoa chegou: a pista vazia não dava a
   noção de percurso. */
.corrida-linha::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--ate, 0%);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  transition: width .45s cubic-bezier(.34, 1.1, .5, 1);
}

.corrida-corredor {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  /* Anda até a posição em vez de saltar: é o movimento que dá a sensação
     de perseguição. */
  transition: left .45s cubic-bezier(.34, 1.1, .5, 1);
}

/* Quem lidera ganha um anel, não uma medalha: a medalha já está no avatar
   do cabeçalho, e repeti-la aqui poluía a pista. */
.corrida-avatar.lidera {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
}

.corrida-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  background: var(--surface);
  display: grid;
  place-items: center;
  font-size: .9rem;
  overflow: hidden;
}
.corrida-avatar .avatar,
.corrida-avatar img {
  width: 100%; height: 100%;
  border: 0;
  font-size: .9rem;
}

.corrida-pts {
  font-size: .72rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-top: -2px;
}

.corrida-nome { color: var(--text-dim); padding-left: 26px; }


/* Legenda do humor: emoji sobre o nome, do melhor ao pior. */
.mood-legenda {
  display: flex;
  justify-content: center;
  gap: .9rem;
  flex-wrap: wrap;
  margin-top: .6rem;
}
.mood-legenda > span {
  display: grid;
  justify-items: center;
  gap: .1rem;
}
/* O nome ficou: a legenda continua sendo a fila de rostos do gráfico, e
   renomear a classe mudaria o CSS de dois arquivos sem ganho nenhum. */
.mood-emoji { line-height: 0; color: var(--text-dim); }

/* Gráfico que ocupa a largura toda, abaixo da grade de dois. */

/* Escolha do que exportar: uma fila de caixas de seleção.
   O checkbox precisa de tamanho fixo porque num container flex ele encolhe e
   vira um retângulo esticado; o nowrap impede que "Resumo por mês" quebre em
   duas linhas e desalinhe a fila inteira. */
.exp-areas {
  display: flex; flex-wrap: wrap; gap: .45rem;
  margin-bottom: .9rem;
}
.exp-areas label {
  display: inline-flex; align-items: center; gap: .4rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  padding: .3rem .6rem;
  font-size: .82rem;
  white-space: nowrap;
  cursor: pointer;
}
.exp-areas label:hover { border-color: var(--accent); }
.exp-areas input {
  flex: 0 0 auto;
  width: .9rem; height: .9rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Setas para reordenar o exercício, coladas uma na outra.
   Ficam discretas até o mouse passar pela linha: são úteis mas não são a
   ação principal, e três pares de setas sempre visíveis competiriam com o
   nome do exercício, que é o que a pessoa lê primeiro. */
.gym-mover {
  display: inline-flex; flex: none;
  gap: 0;
  opacity: .6;
  transition: opacity .15s;
}
.gym-item:hover .gym-mover,
.gym-mover:focus-within { opacity: 1; }
.gym-mover button { padding: .1rem .15rem; min-height: auto; }
.gym-mover button[disabled] { opacity: .3; cursor: default; }

/* No toque não há hover, e uma seta invisível é uma seta que não existe. */
@media (hover: none) {
  .gym-mover { opacity: .8; }
}

/* ---------------------------------------------------------------------------
   Cartão de crédito ilustrado.

   Desenhado em CSS, sem imagem: uma figura de cartão em PNG teria fundo fixo
   e ficaria com uma moldura clara boiando no tema escuro. Aqui as cores saem
   das variáveis do tema, então o cartão acompanha o modo claro e o escuro
   sozinho, e também a cor de destaque que a pessoa escolher.
--------------------------------------------------------------------------- */

.cc {
  position: relative;
  width: 100%;
  max-width: 20rem;
  aspect-ratio: 1.586;          /* proporção de um cartão de verdade */
  border-radius: .85rem;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  color: #fff;
  background:
    linear-gradient(135deg,
      color-mix(in srgb, var(--cc-cor, var(--accent)) 92%, #000) 0%,
      color-mix(in srgb, var(--cc-cor, var(--accent)) 62%, #000) 55%,
      color-mix(in srgb, var(--cc-cor, var(--accent)) 78%, #000) 100%);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
  overflow: hidden;
}

/* O brilho diagonal que todo cartão tem. Fica atrás do conteúdo. */
.cc::after {
  content: '';
  position: absolute;
  inset: -40% -10% auto -10%;
  height: 120%;
  background: linear-gradient(105deg,
    rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, 0) 42%);
  pointer-events: none;
}

.cc > * { position: relative; z-index: 1; }

.cc-topo { display: flex; justify-content: space-between; align-items: flex-start; }
.cc-nome { font-weight: 600; font-size: .95rem; letter-spacing: .01em; }
.cc-band { font-size: .72rem; opacity: .75; text-transform: uppercase;
           letter-spacing: .08em; }

/* O chip dourado. Duas linhas bastam para o olho reconhecer o desenho. */
.cc-chip {
  width: 2.1rem; height: 1.6rem;
  border-radius: .28rem;
  background: linear-gradient(145deg, #e6cd6a 0%, #c9a227 45%, #f2dd92 100%);
  position: relative;
  flex: none;
}
.cc-chip::before, .cc-chip::after {
  content: '';
  position: absolute;
  left: 12%; right: 12%;
  height: 1px;
  background: rgba(0, 0, 0, .28);
}
.cc-chip::before { top: 34%; }
.cc-chip::after  { top: 62%; }

.cc-valor { font-size: 1.5rem; font-weight: 600; line-height: 1.1;
            font-variant-numeric: tabular-nums; }
.cc-rot { font-size: .72rem; opacity: .8; text-transform: uppercase;
          letter-spacing: .07em; margin-bottom: .15rem; }
.cc-pe { display: flex; justify-content: space-between; align-items: flex-end;
         gap: .5rem; }
.cc-pe-item { font-size: .72rem; opacity: .88; }

/* Barra de limite dentro do cartão. */
.cc-limite { height: 4px; border-radius: 2px; margin-top: .45rem;
             background: rgba(255, 255, 255, .25); overflow: hidden; }
.cc-limite > span { display: block; height: 100%; background: #fff;
                    border-radius: 2px; }

/* Grade de cartões, um do lado do outro quando cabe. */
.cc-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
  gap: .9rem;
}
.cc-bloco { display: flex; flex-direction: column; gap: .7rem; }

/* Fatura ao lado do cartão. */
.cc-fatura { border: 1px solid var(--border); border-radius: var(--r-sm);
             padding: .7rem .8rem; background: var(--surface-2); }
.cc-fatura + .cc-fatura { margin-top: .5rem; }
.cc-fatura.vencendo { border-color: var(--patrimonio); }
.cc-fatura.paga { opacity: .75; }

/* Seções dentro de uma subaba (Extrato / Contas fixas / Cartões).
   Visual diferente das subabas de propósito: são um nível abaixo, e repetir
   o mesmo desenho faria parecer que há duas barras de navegação irmãs. */
/* A ALIMENTACAO com a rosca DENTRO, e nao ao lado.
   Como cartao separado, a rosca ficava com o dobro da altura do vizinho e
   sobrava um vazio do tamanho de meio cartao embaixo do total. */
/* A ALIMENTACAO e a AGUA dividem a linha: cada uma era uma faixa de
   1282px para o que cabe em 400. Em tela estreita empilham, que e quando
   meia largura nao serve para nenhuma das duas. */
.saude-dupla {
  display: flex;
  gap: .75rem;
  margin-bottom: .75rem;
  /* Os dois com a MESMA altura, ate certo ponto. Alturas diferentes lado a
     lado deixavam a Agua baixinha ao lado da Alimentacao alta, e o degrau
     entre elas era mais visivel que o vazio que ele evitava; com o conteudo
     centrado (ver `.nutri-corpo` e `.water-row`), a sobra se reparte em cima
     e embaixo em vez de virar um bloco vazio no pe.

     Mas isso so vale enquanto a diferenca e pequena. Com seis refeicoes na
     lista a Alimentacao passa de 340px e a Agua -- que tem tres botoes --
     era esticada junto, ficando com 132px de vazio medidos abaixo deles.
     O `align-items` cuida do caso comum; quem poe o teto e o
     `max-height` da Agua, mais abaixo. */
  align-items: stretch;
}
.saude-dupla > .card {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
  /* Coluna, para o conteudo poder ocupar a altura que o vizinho mais alto
     impoe: os botoes de agua se centram no espaco em vez de ficarem
     colados no topo com um vazio embaixo. */
  display: flex;
  flex-direction: column;
}
.agua-card > .water-row { flex: 1; align-content: center; }
/* A Agua para de crescer junto com a vizinha. Ela tem tres botoes e um
   rotulo: esticada ate a altura de uma Alimentacao com seis refeicoes,
   sobravam 132px de vazio embaixo deles.
   O teto e generoso para nao brigar com o caso comum (as duas na mesma
   altura, que e o desejado quando a diferenca e pequena); ele so entra
   quando a lista de refeicoes ja cresceu o bastante para o vazio saltar aos
   olhos. `align-self` desfaz o `stretch` da linha. */
.saude-dupla > .agua-card { max-height: 11.5rem; }
@media (max-width: 900px) {
  .saude-dupla { flex-wrap: wrap; }
  .saude-dupla > .card { flex: 1 0 100%; }
}
/* Sozinho na linha, o cartao ocupa tudo -- a alternativa seria meia linha
   vazia ao lado dele. */
.saude-dupla > .card:only-child { flex: 1 0 100%; }
/* A rosca encosta a ESQUERDA, e nao no meio do cartao.
   A regra base centra, o que serve no widget estreito da tela inicial; num
   cartao de largura cheia isso punha o desenho no meio com espaco morto dos
   dois lados. Aqui ele comeca junto com o titulo, e a legenda segue ao
   lado. */
.nutri-card .pizza-wrap {
  margin: 0;
  justify-content: flex-start;
  gap: 1.4rem;
  flex: none;
}
/* A rosca a esquerda, a lista do que se comeu a direita: o cartao dizia o
   total sem dizer de onde ele vinha, e sobrava um vazio do lado do desenho.
   Em tela estreita a lista desce, que e quando as duas lado a lado
   ficariam com uma coluna cada. */
/* O conteudo vive no CENTRO do cartao, e nao encostado a esquerda.
   O cartao tem a largura que tem -- ele divide a linha com a Agua, e sozinho
   (quando a Agua vem do Google e nao e desenhada) ocupa tudo. Encostado na
   borda esquerda, o desenho ficava num canto com metade do cartao vazia a
   direita; centrado, o vazio se reparte nos dois lados e deixa de ser um
   buraco.

   SEM refeicao marcada, a rosca ocupa o centro sozinha. COM refeicoes, as
   duas dividem esse centro: e a mesma ideia dos cartoes na linha -- o que
   existe ocupa o espaco, e o que nao existe nao deixa buraco. */
.nutri-corpo {
  display: flex;
  gap: 1rem 2.4rem;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}
/* A rosca sozinha nao estica: ela tem o tamanho do desenho mais a legenda,
   e centrada isso basta. */
.nutri-um > * { flex: 0 1 auto; }
/* A lista ocupa a ALTURA da rosca, distribuindo as refeicoes nela.
   Com `align-content: start` elas se amontoavam no topo e sobrava um vazio
   do tamanho de duas linhas embaixo -- justamente ao lado do desenho que
   define a altura do cartao. Espalhadas, o vazio vira o respiro entre uma
   refeicao e outra. */
/* A lista divide o centro com a rosca: `flex: 0 1 auto` para ela ter a
   largura do que carrega, e nao esticar ate a borda -- era isso que punha o
   "215 kcal" de uma refeicao a 900px do nome dela. */
.nutri-comidas {
  list-style: none;
  flex: 0 1 auto;
  min-width: 0;
  /* Um nome comprido esticava a lista ate estes 26rem, e como as kcal ficam
     na outra ponta da linha, abria um vao de dedo entre o nome e o numero --
     com "AAAA..." a lista media 416px de 635 do cartao. Cabendo o que cabe
     na largura de um nome normal, o nome longo passa a ser cortado com
     reticencias (`.nutri-nome` ja faz isso) em vez de empurrar a coluna. */
  max-width: 19rem;
  display: grid;
  gap: .45rem;
  align-content: center;
}
.nutri-comidas li {
  display: flex;
  align-items: baseline;
  /* A coluna das kcal recua da do nome por um espaco FIXO, e nao pelo que
     sobrar da largura do cartao -- era isso que jogava o "215 kcal" para a
     outra ponta. */
  gap: 1rem;
  font-size: .82rem;
  /* Sem isto a linha nao encolhe abaixo do conteudo dela: um filho flex tem
     `min-width: auto`, que e o tamanho do que carrega. O nome comprido
     inflava a linha inteira, e como a lista e `flex: 0 1 auto` a largura
     dela vinha da linha mais larga -- as kcal saiam do cartao e apareciam em
     cima da Agua. O `max-width` da lista nao segurava porque quem estourava
     era a linha, por dentro.
     Com o minimo em zero, a linha cabe na lista e sobra o corte do nome. */
  min-width: 0;
}
.nutri-hora {
  font-family: var(--font-mono);
  font-size: .74rem;
  color: var(--text-faint);
  flex: none;
}
.nutri-nome {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nutri-kcal { color: var(--text-dim); flex: none; }

/* A SUBABA COM SECOES: clicar nela abre os caminhos dela.
   As secoes eram botoes numa linha propria embaixo das subabas -- duas
   fileiras de navegacao empilhadas, e a de baixo mostrando o tempo todo os
   dois caminhos que a pessoa NAO escolheu. Agora saem da propria subaba:
   uma fileira, e o caminho inteiro num gesto. */
.subtab-menu { position: relative; display: inline-block; }
.subtab-menu > .subtab {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
}
.subtab-menu > .subtab::-webkit-details-marker { display: none; }
.subtab-menu > .subtab::marker { content: ''; }
/* A seta so aparece na subaba ABERTA e no hover: nas outras ela seria um
   enfeite ao lado de um rotulo que ja e clicavel. */
.subtab-menu > .subtab .ico {
  opacity: 0;
  transition: opacity .12s, transform .15s;
  color: var(--text-faint);
}
.subtab-menu > .subtab.active .ico,
.subtab-menu:hover > .subtab .ico { opacity: 1; }
.subtab-menu[open] > .subtab .ico { transform: rotate(180deg); }
/* A secao que esta valendo, ao lado do nome da subaba: sem isto a barra
   perderia a informacao que a linha de baixo dava. */
.subtab-secao {
  font-size: .74rem;
  font-weight: 400;
  color: var(--text-faint);
  padding-left: .35rem;
  border-left: 1px solid var(--border);
  margin-left: .15rem;
}

/* A barra de subabas tem `overflow-x: auto` para rolar, e isso RECORTA
   qualquer filho que saia dela -- a lista abria com 117px de altura e
   ficava invisivel, atras do card seguinte. Com o menu aberto o recorte
   sai: a barra so precisa dele para rolar, e um menu aberto nao rola.

   `overflow: visible` nos dois eixos, senao o navegador ignora o `visible`
   de um lado quando o outro e `auto`. */
.subtabs:has(.subtab-menu[open]) { overflow: visible; }

/* A lista FLUTUA sobre o conteudo, e nao empurra a pagina: abrir um menu
   nao pode mexer no que esta embaixo dele. */
.secao-lista {
  position: absolute;
  top: calc(100% + .35rem);
  left: 0;
  z-index: 20;
  min-width: max-content;
  display: flex;
  flex-direction: column;
  gap: .1rem;
  padding: .3rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  box-shadow: 0 8px 24px rgb(0 0 0 / 30%);
}
.secao-op {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .4rem .7rem;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-dim);
  font-size: .85rem;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  min-height: 34px;
}
.secao-op:hover { background: var(--surface-2); color: var(--text); }
.secao-op.active { color: var(--accent-text); }

.seg-linha {
  display: flex; flex-wrap: wrap; gap: .35rem;
  margin-bottom: .8rem;
}
.seg {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .35rem .75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-dim);
  font-size: .85rem;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.seg:hover { color: var(--text); border-color: var(--border-strong); }
.seg.active {
  color: var(--accent-text);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.seg-n {
  font-size: .72rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.seg.active .seg-n { color: var(--accent-text); }

/* "Repete todo mês" no lançamento: caixa grande e clicável, com a explicação
   junto. Um checkbox solto com rótulo de uma palavra faria a pessoa decidir
   sem saber o que muda. */
.lanc-repete {
  display: flex; align-items: flex-start; gap: .6rem;
  margin-top: .9rem;
  padding: .7rem .8rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  cursor: pointer;
}
.lanc-repete:hover { border-color: var(--accent); }
.lanc-repete input {
  flex: 0 0 auto;
  width: 1rem; height: 1rem;
  margin-top: .15rem;
  accent-color: var(--accent);
  cursor: pointer;
}

/* O cartão vira botão: a lista inteira é clicável, não só um link pequeno.
   Sem borda nem fundo próprios, porque o cartão já tem os seus. */
.cc-botao {
  display: block; width: 100%;
  padding: 0; border: none; background: none;
  cursor: pointer;
  border-radius: .85rem;
  transition: transform .12s;
}
.cc-botao:hover { transform: translateY(-2px); }
.cc-botao:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Página de um cartão: o cartão à esquerda, as faturas à direita. Empilha
   quando não cabe, para o cartão não encolher a ponto de ficar ilegível. */
.cc-pagina {
  display: grid;
  gap: 1rem;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  align-items: start;
}
/* ------------------------------------------------------- aba do produto
   Só existe na cópia pessoal do código: é a tela que acompanha o negócio. */

/* O estado de cada pedido de teste: pediu, instalou, comprou. A cor faz o
   trabalho que o texto sozinho não faz — quem só pediu some no cinza, e é
   justamente quem precisa de um e-mail. */
.selo-ok, .selo-err {
  display: inline-block;
  font-size: .72rem; font-weight: 600;
  padding: .1rem .4rem; border-radius: var(--r-xs);
  white-space: nowrap;
}
.selo-ok  { color: var(--ok-text);  background: color-mix(in srgb, var(--ok) 12%, transparent); }
.selo-err { color: var(--err-text); background: color-mix(in srgb, var(--err) 12%, transparent); }

/* O filtro da tabela de ativações. `.chip` já existe para as etiquetas de
   busca; aqui ele vira botão, e precisa do estado escolhido. */
button.chip {
  cursor: pointer; font-family: inherit;
  color: var(--text-dim); min-height: auto;
  padding: .2rem .55rem;
}
button.chip:hover { color: var(--text); border-color: var(--text-faint); }
button.chip.ativo {
  color: var(--accent-text); border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
button.chip.ativo .muted { color: var(--accent-text); }

.tabela-produto { font-size: .9rem; }
.linha-produto {
  display: grid;
  /* Só o e-mail estica: as outras colunas têm tamanho previsível, e em `fr`
     elas ganhavam largura sobrando com o texto solto na ponta esquerda —
     "Trocas" chegava a ficar mais perto dos botões que do próprio número.

     `minmax(0, 1fr)` e não `1fr` na primeira: sem o mínimo zero, um e-mail
     longo empurra a grade inteira em vez de ser cortado. */
  /* Larguras FIXAS, e não `auto`: cada `.linha-produto` é uma grade
     independente, então `auto` faz cada linha medir o próprio conteúdo e as
     colunas param de se alinhar entre si — o cabeçalho vai para um lado e os
     dados para outro.

     Os valores são o mínimo que cabe o maior conteúdo real de cada coluna:
     "Individual · cortesia", um hash de 8 caracteres, uma data ISO. Sobra
     vira vão, e vão demais o olho lê como desalinhamento. */
  grid-template-columns:
    minmax(0, 1fr)   /* quem     */
    9.5rem           /* edição: "Individual · cortesia" */
    5.5rem           /* máquina: 8 caracteres           */
    5.5rem           /* desde: 2026-08-14               */
    3rem             /* trocas: um digito               */
    10.5rem;         /* ações: dois botões              */
  gap: .45rem .9rem;
  gap: .6rem;
  padding: .45rem 0;
  border-top: 1px solid var(--border);
  align-items: center;
}
.linha-produto.cabeca {
  border-top: none;
  color: var(--text-faint);
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.linha-produto code { font-size: .82rem; }

/* Números alinham à direita, como número: à esquerda de uma coluna estreita
   eles pareciam soltos no meio da linha. O cabeçalho acompanha. */
.linha-produto > :nth-child(5) { text-align: right; padding-right: .4rem; }

/* O e-mail é o único texto que pode não caber. Cortado com reticências, em
   vez de empurrar as outras colunas para fora da tela. */
.linha-produto > :nth-child(1) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* No celular a grade de cinco colunas espreme tudo. Duas linhas por
   ativação: a chave e a máquina em cima, as datas embaixo. */


/* Os botões de cada linha. Ficam apagados até o ponteiro passar: são ações
   raras, e destacá-las convidaria ao clique errado numa lista que se lê
   todo dia. */
.acoes-produto { display: flex; gap: .3rem; justify-content: flex-end; }
.acoes-produto button { opacity: .5; transition: opacity .12s; }
.linha-produto:hover .acoes-produto button { opacity: 1; }
.acoes-produto button:disabled { opacity: .2; cursor: not-allowed; }
.acoes-produto .perigo:hover { color: var(--err-text); border-color: var(--err); }

/* Chave cancelada: fica na lista, apagada. Sumir esconderia que ela existiu,
   e é justamente o histórico que interessa depois. */
.linha-produto.revogada { opacity: .45; }
.linha-produto.revogada code,
.linha-produto.revogada span { text-decoration: line-through; }

/* No celular a grade de seis colunas não cabe, e dividir em duas embaralhava
   os campos: sem cabeçalho, "9f8e7d6c" e "2026-08-10" viravam dois textos
   soltos sem dizer o que são.

   Vira uma pilha: o e-mail em cima, o resto numa linha de rótulos separados
   por ponto, e os botões embaixo. Cada dado carrega o próprio contexto. */
@media (max-width: 640px) {
  .linha-produto {
    display: block;
    padding: .8rem 0;
  }
  .linha-produto.cabeca { display: none; }

  /* Quem: destacado, é o que identifica a linha. */
  .linha-produto > :nth-child(1) {
    display: block;
    font-weight: 600;
    margin-bottom: .15rem;
  }

  /* Edição, máquina, data e trocas em fluxo, separados por ponto. */
  .linha-produto > :nth-child(2),
  .linha-produto > :nth-child(3),
  .linha-produto > :nth-child(4),
  .linha-produto > :nth-child(5) {
    display: inline;
    text-align: left;
    padding: 0;
    font-size: .82rem;
  }
  .linha-produto > :nth-child(3)::before,
  .linha-produto > :nth-child(4)::before { content: " · "; }
  .linha-produto > :nth-child(5)::before { content: " · trocas: "; }

  .acoes-produto {
    justify-content: flex-start;
    margin-top: .5rem;
  }
  /* No celular não há "passar o ponteiro": os botões ficam sempre visíveis. */
  .acoes-produto button { opacity: 1; }
}

/* ------------------------------------------------ competição configurável */

.comp-cartao { margin-bottom: .75rem; }

.comp-periodo { margin-bottom: .9rem; }

/* Quem está ganhando, em uma frase. Antes de qualquer número: "você está
   ganhando" se lê num relance, e "12 x 8" obriga a comparar. */
.comp-chamada {
  text-align: center; font-size: 1.2rem; font-weight: 700;
  margin: .2rem 0 .9rem;
}
/* Quem esta na frente usa o ACENTO, nao o verde.
   Verde e vermelho no Hub querem dizer dinheiro que entrou e dinheiro que
   saiu. Aqui nao ha nada de financeiro: e so "voce esta ganhando", que e um
   estado de destaque -- e destaque no Hub e a cor do perfil. Com o acento
   ambar ou azul, um verde fixo aparecia como cor de fora do tema. */
.comp-chamada.comp-frente { color: var(--accent-text); }
.comp-chamada.comp-atras { color: var(--err-text); }

/* O GRAFICO DA DISPUTA.
   O desenho tinha medidas fixas e o `preserveAspectRatio` esticava tudo
   junto -- inclusive o TEXTO, que saia achatado e parecendo de baixa
   resolucao. Agora nao ha texto dentro do SVG: os numeros e as datas sao
   HTML por cima, e so as linhas se deformam. */
.disputa { margin: .1rem 0 .9rem; }
.disputa-tela {
  position: relative;
  height: 132px;
  /* Espaco a direita para o numero do fim de cada linha, que fica FORA do
     desenho: dentro, ele seria cortado pela borda do SVG. */
  margin-right: 3rem;
}
.disputa-svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* A espessura do traco nao acompanha a deformacao do eixo: sem isto a linha
   engrossaria na horizontal e afinaria na vertical. */
.disputa-svg path,
.disputa-svg line { vector-effect: non-scaling-stroke; }
.disputa-regua { stroke: var(--border); stroke-width: 1; opacity: .45; }

/* A ponta de cada linha: a bolinha e o total, em HTML posicionado por
   porcentagem -- assim ficam na escala certa em qualquer largura. */
.disputa-ponta {
  position: absolute;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: .35rem;
  white-space: nowrap;
}
.disputa-bola {
  width: 7px; height: 7px;
  border-radius: 50%;
  margin-left: -3.5px;
}
.disputa-num {
  font-size: .78rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.disputa-datas {
  display: flex;
  justify-content: space-between;
  margin: .35rem 3rem 0 0;
  font-size: .72rem;
  color: var(--text-faint);
}

.comp-linhas { display: grid; gap: .5rem; }
.comp-linha {
  display: grid; align-items: center; gap: .6rem;
  /* A coluna da BARRA saiu -- ela virou o grafico de linha acima. Sobrou a
     marca de cor (que amarra o nome a sua linha no grafico), o nome, os
     dias e os pontos. */
  grid-template-columns: auto 1fr auto auto;
  text-align: left;
}
/* A marca da cor do perfil: e ela que diz qual linha do grafico e de quem,
   sem precisar de uma legenda a parte. */
.comp-cor {
  width: 10px; height: 10px;
  border-radius: 50%;
  display: inline-block;
}
.comp-nome { font-size: .9rem; font-weight: 600; }
.comp-barra {
  height: 8px; border-radius: var(--r-pill); background: var(--surface-2);
  overflow: hidden;
}
.comp-barra > span {
  display: block; height: 100%; background: var(--accent);
  /* A barra ANDA quando alguém vence um dia, em vez de saltar. É a única
     animação daqui que carrega informação. */
  transition: width .4s cubic-bezier(.4, 0, .2, 1);
}
.comp-num { font-weight: 700; font-variant-numeric: tabular-nums; }
.comp-pts { min-width: 4.5ch; text-align: right; }

/* A prenda combinada, no rodapé do cartão. */
.comp-prenda {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; flex-wrap: wrap;
  margin-top: .9rem; padding-top: .8rem;
  border-top: 1px solid var(--border);
}
.comp-prenda-txt {
  display: flex; align-items: center; gap: .45rem;
  font-size: .9rem; color: var(--text-dim);
}

/* Quanto falta para o ciclo fechar. Nos ultimos tres dias muda de cor: e
   quando a virada ainda e possivel, e quando o aviso precisa saltar. */
.comp-restam { margin-left: auto; font-size: .82rem; color: var(--text-dim); }
.comp-restam.comp-reta { color: var(--err-text); font-weight: 600; }

/* Os titulos por tipo de ciclo, no historico. */
.comp-titulos { display: flex; gap: .8rem; flex-wrap: wrap; margin-top: .3rem; }
.comp-titulo { font-size: .8rem; color: var(--text-dim); }
.comp-titulo b { color: var(--text); font-size: .95rem; }

/* Os eventos do dia: alvos grandes, porque marcar é gesto de todo dia. */
.comp-eventos { display: flex; flex-wrap: wrap; gap: .45rem; }
.comp-evento {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .55rem .8rem; min-height: 42px;
  border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface); cursor: pointer; font-size: .9rem;
  transition: border-color .15s ease, background .15s ease, transform .12s ease;
}
.comp-evento:hover { border-color: var(--accent); }
.comp-evento:active { transform: scale(.97); }
.comp-evento.comp-feito {
  border-color: var(--ok);
  background: color-mix(in srgb, var(--ok) 12%, transparent);
  color: var(--ok-text);
}
.comp-evento.comp-feito .badge { background: var(--ok); color: #fff; }

/* ---------------------------------------------------------- configuração */

/* A janela do placar, em texto: o ciclo é configuração, não escolha aqui. */
.comp-janela {
  display: flex; align-items: baseline; gap: .5rem;
  margin-bottom: .9rem; flex-wrap: wrap;
}
.comp-ciclo { font-weight: 600; font-size: .95rem; }

/* O ciclo, na configuração: três opções com a explicação embaixo. Um seletor
   nu ("dia / semana / mês") não diz o que muda no placar. */
.cfg-ciclo { display: grid; gap: .4rem; }
.cfg-opt {
  display: block; text-align: left; width: 100%;
  padding: .7rem .8rem; border-radius: var(--r);
  border: 1px solid var(--border); background: var(--surface);
  cursor: pointer; transition: border-color .15s ease;
}
.cfg-opt:hover { border-color: var(--accent); }
.cfg-opt.active { border-color: var(--accent);
                  background: color-mix(in srgb, var(--accent) 8%, transparent); }
.cfg-opt-rot { display: block; font-weight: 600; font-size: .9rem; }
.cfg-opt-nota { display: block; font-size: .8rem; color: var(--text-dim);
                margin-top: .1rem; }

/* Cada critério em UMA LINHA legível: "Passos [1] a cada 1.000 passos, até
   [10] no dia". O slider dizia um número sem dizer de quê. */
.cfg-linha {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding: .6rem 0; border-bottom: 1px solid var(--border);
  transition: opacity .2s ease;
}
.cfg-linha:last-of-type { border-bottom: 0; }
/* Zerado é o mesmo que desligado, e a linha apaga para dizer isso sem
   precisar de um interruptor repetindo a informação. */
.cfg-linha.cfg-off { opacity: .45; }
/* O nome com largura FIXA, e nao esticando: com `flex:1` ele comia toda a
   sobra da linha, e cada caixa comecava onde o nome dela acabava. Fixo, as
   caixas caem todas na mesma vertical. */
.cfg-linha-nome { width: 9rem; flex: none; font-weight: 600; font-size: .9rem; }

/* A UNIDADE com largura fixa e alinhada a esquerda: e ela que varia de
   tamanho ("por item concluido" contra "ao bater a meta"), e era isso que
   empurrava cada campo para um lugar diferente. Fixando a coluna do texto,
   as caixas caem todas na mesma vertical. */
.cfg-linha-campos { display: flex; align-items: center; gap: .4rem; }
/* A unidade da PRIMEIRA caixa com largura fixa: e a unica que precisa, para
   que o par do teto ("ate 30 no dia") comece sempre no mesmo ponto em vez de
   depender do tamanho de "a cada 1.000 passos". */
.cfg-linha-campos > .small:first-of-type { width: 9.5rem; }

/* Os textos livres da aposta. */
.cfg-aposta { margin-bottom: .7rem; }
.cfg-aposta label {
  display: block; font-size: .9rem; font-weight: 600; margin-bottom: .25rem;
}
.cfg-aposta input { width: 100%; }

/* O campo numérico, estreito: é sempre um número de um ou dois dígitos. */
.cfg-n {
  width: 3.4rem; text-align: center; font-variant-numeric: tabular-nums;
}

/* A lista de coisas que o casal inventou. */
.cfg-evento {
  display: flex; align-items: center; gap: .4rem; margin-bottom: .4rem;
}
.cfg-ev-nome { flex: 1; min-width: 0; }

/* O aviso de tarefas que ficaram para tras, na lista de hoje. Discreto: e
   uma oferta, nao um erro, e quem nao quiser trazer segue sem ele atrapalhar
   a leitura da lista. */
.pend-aviso {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; flex-wrap: wrap;
  margin-bottom: .8rem; padding: .6rem .75rem;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2);
}
.pend-txt {
  display: flex; align-items: center; gap: .45rem;
  font-size: .9rem; color: var(--text-dim);
}

/* ==========================================================================
   CADERNO
   ========================================================================== */

/* Árvore à esquerda, página à direita. No celular vira uma coluna: uma barra
   lateral fixa numa tela de 360px não deixa largura para o texto, que é o
   conteúdo. */
.cad-wrap {
  display: grid;
  grid-template-columns: minmax(190px, 240px) 1fr;
  gap: 1rem;
  align-items: start;
  position: relative;
}

/* A lista recolhida: a coluna vai a zero e a pagina ocupa tudo. Some por
   `grid-template-columns`, e nao por `display:none`, para a transicao ter o
   que animar e o conteudo nao ser remontado a cada abre-e-fecha. */
.cad-wrap.recolhida { grid-template-columns: 0 1fr; gap: 0; }
.cad-wrap.recolhida .cad-arvore {
  opacity: 0; pointer-events: none; overflow: hidden;
  padding-left: 0; padding-right: 0; border-width: 0;
}
.cad-arvore { transition: opacity .14s; }

/* O puxador fica DENTRO da area do Caderno, e nao acima dela.
   Com `top` negativo ele subia para a faixa das subabas e cobria a primeira
   ("Lista do dia"), roubando o clique dela - a barra de subabas nao e area
   do Caderno para ele ocupar. */
.cad-puxador {
  position: absolute; top: .3rem; left: .3rem; z-index: 2;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-dim); border-radius: var(--r-xs);
  width: 30px; height: 28px; display: grid; place-items: center;
  cursor: pointer;
}
/* Com a lista ABERTA o puxador cairia em cima do campo de busca. Em vez de
   calcular a largura da coluna (que muda com a tela), a propria lista abre
   espaco no topo e o puxador ocupa esse espaco. */
/* Com a lista ABERTA o puxador cairia em cima do campo de busca. Quem abre
   espaco e a propria BUSCA, e nao a `.cad-arvore`: a arvore ja tem uma regra
   de padding mais abaixo no arquivo, que venceria esta por ordem. */
.cad-wrap:not(.recolhida) .cad-busca { margin-top: 2.1rem; }
.cad-puxador:hover { color: var(--accent-text); border-color: var(--accent); }

/* O + e o X de cada linha: escondidos ate o ponteiro passar, senao a arvore
   vira uma parede de botoes. No toque nao ha hover, entao aparecem sempre. */
.cad-linha-acoes { display: flex; gap: .1rem; margin-left: auto; opacity: 0; }
.cad-item:hover .cad-linha-acoes,
.cad-item:focus-within .cad-linha-acoes { opacity: 1; }
@media (hover: none) { .cad-linha-acoes { opacity: 1; } }

.cad-linha-btn {
  border: none; background: none; color: var(--text-faint);
  width: 20px; height: 20px; display: grid; place-items: center;
  border-radius: var(--r-xs); cursor: pointer; flex: none;
}
.cad-linha-btn:hover { background: var(--surface-2); color: var(--accent-text); }

.cad-arvore {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: .6rem;
  position: sticky;
  top: .75rem;
  max-height: calc(100vh - 6rem);
  overflow-y: auto;
}

.cad-busca { margin-bottom: .5rem; }
.cad-busca input {
  width: 100%;
  font-size: .82rem;
  padding: .4rem .55rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text);
}

.cad-lista { display: grid; gap: 1px; }
.cad-vazio { padding: .5rem .35rem; }

/* A linha que liga o pai aos filhos.
   `--guia` vem do ramo e cai na vertical do icone do pai, entao a linha
   nasce embaixo dele. E o que salva a hierarquia depois do terceiro nivel,
   onde o recuo trava e pai, filho e neto sairiam alinhados. */
.cad-filhos { position: relative; }
.cad-filhos::before {
  content: "";
  position: absolute;
  left: var(--guia, .8rem);
  top: 0; bottom: .1rem;
  width: 1px;
  background: var(--border);
}
/* Com o ponteiro no ramo, a linha daquele ramo se destaca: e o que responde
   "o que exatamente esta dentro desta pasta?" sem precisar contar recuos. */
.cad-ramo:hover > .cad-filhos::before { background: var(--border-strong); }

.cad-item {
  display: flex;
  align-items: center;
  gap: .3rem;
  padding: .3rem .35rem;
  border-radius: var(--r-xs);
  cursor: pointer;
  font-size: .85rem;
  color: var(--text-dim);
  min-height: 30px;
}
.cad-item:hover { background: var(--surface-2); color: var(--text); }
.cad-item.ativo {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--text);
  font-weight: 500;
}

.cad-titulo {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cad-seta {
  border: none;
  background: none;
  color: var(--text-faint);
  padding: 0;
  width: 14px;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform .12s;
}
.cad-seta.aberta { transform: rotate(90deg); }
.cad-seta-vazia { width: 14px; }
.cad-icone { display: grid; place-items: center; width: 16px; font-size: .9rem; }

/* Marcas de onde a página vai cair ao soltar: a linha embaixo é "depois
   deste", a moldura preenchida é "dentro deste". Sem as duas, arrastar é
   adivinhação.

   A linha e a moldura sao `inset` para nao empurrar nada de lugar: uma borda
   de verdade mudaria a altura do item e faria a lista inteira tremer durante
   o arrasto, que e justamente quando a pessoa precisa de um alvo parado.

   `alvo-dentro` ganha FUNDO alem da moldura: so o contorno de 2px se perdia
   no meio de uma lista ja cheia de linhas-guia, e "dentro desta" e a acao que
   muda a arvore - precisa ser inconfundivel. */
/* A linha comeca onde o NOME comeca, e nao na borda da lista.
   Atravessando a largura toda, ela nao dizia em que nivel a pagina ia cair -
   um solto no primeiro nivel e um no quarto desenhavam a mesma linha.
   `background` com `padding-box` respeita o recuo do item; `box-shadow` nao,
   e era por isso que ela vazava para a esquerda. */
.cad-item.alvo {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 100% 2px;
  background-position: left bottom;
  background-repeat: no-repeat;
  background-origin: padding-box;
  background-clip: padding-box;
}
/* "Antes deste": a linha vai no TOPO, e nao embaixo. */
.cad-item.alvo-antes {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 100% 2px;
  background-position: left top;
  background-repeat: no-repeat;
  background-origin: padding-box;
  background-clip: padding-box;
}
.cad-item.alvo-dentro {
  box-shadow: inset 0 0 0 2px var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-radius: var(--r-xs);
}

.cad-achado {
  padding: .4rem .35rem;
  border-radius: var(--r-xs);
  cursor: pointer;
  font-size: .82rem;
}
.cad-achado:hover { background: var(--surface-2); }
.cad-achado-titulo {
  display: flex; align-items: center; gap: .3rem; color: var(--text);
}
.cad-achado-onde { color: var(--text-faint); font-size: .72rem; margin-top: .1rem; }
.cad-achado-trecho {
  color: var(--text-dim); font-size: .78rem; margin-top: .15rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.cad-nova { width: 100%; margin-top: .5rem; justify-content: center; }

/* -------------------------------------------------------------- a página */

.cad-pagina {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  overflow: hidden;
  min-height: 320px;
}

.cad-capa {
  /* Mais alta: a 130px a foto virava uma tira e nada dela se reconhecia. Esta
     altura mostra a imagem e ainda deixa o texto comecar acima da dobra. */
  --cad-capa-h: 200px;
  height: var(--cad-capa-h);
  background-size: cover;
  background-position: center;
  position: relative;
}
/* A barra de navegacao mora DENTRO da capa, sobreposta ao alto dela. Fora,
   ela empurrava o titulo para baixo e criava uma faixa vazia entre a imagem e
   o nome da pagina - o oposto do que se ve num caderno de verdade. */
/* A barra comeca DEPOIS do puxador da lista, que fica no canto de cima da
   esquerda com 30px de largura. Em `.9rem` as setas encostavam nele. */
.cad-capa .cad-topo {
  position: absolute; left: 2.8rem; right: .9rem; top: .5rem;
  margin: 0; z-index: 2;
}
/* Sobre foto, cinza escuro em cinza escuro nao se le - e um texto branco com
   sombra some numa capa clara. Cada peca ganha a propria pastilha escura,
   translucida: ela acompanha o desenho do botao em vez de por uma tarja
   sobre a imagem, e da o mesmo contraste em capa clara e escura. */
.cad-capa .cad-topo .cad-seta-nav,
.cad-capa .cad-topo .cad-trilha-item {
  color: #fff;
  background: rgba(0, 0, 0, .42);
  backdrop-filter: blur(3px);
  border-radius: var(--r-xs);
}
.cad-capa .cad-topo .cad-trilha-item {
  padding: .15rem .4rem;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}
.cad-capa .cad-topo .cad-trilha-sep {
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .85);
}
.cad-capa .cad-topo .cad-seta-nav {
  /* Traco mais grosso: a 14px, 1.6 de espessura sobre foto vira um risco
     cinza que se perde no meio do desenho da imagem. */
  stroke-width: 2.1;
}
.cad-capa .cad-topo .cad-seta-nav svg { stroke-width: 2.1; }
/* Desabilitada continua visivel, so mais apagada: em `.3` ela sumia por
   completo sobre a foto, e a barra parecia ter uma seta so. */
.cad-capa .cad-topo .cad-seta-nav:disabled { opacity: .45; }
.cad-capa .cad-topo .cad-seta-nav:hover:not(:disabled),
.cad-capa .cad-topo .cad-trilha-item:hover {
  background: rgba(0, 0, 0, .68); color: #fff;
}
/* A capa e clicavel: o cursor e a dica dizem isso sem precisar de um botao
   "Capa" numa barra separada. */
.cad-capa[role="button"] { cursor: pointer; }
.cad-capa.padrao { opacity: .55; }
.cad-capa[role="button"]:hover { opacity: 1; }
.cad-capa-dica {
  position: absolute; right: .6rem; bottom: .6rem;
  background: var(--surface); color: var(--text-dim);
  border: 1px solid var(--border); border-radius: var(--r-xs);
  padding: .2rem .5rem; font-size: .72rem;
  opacity: 0; transition: opacity .12s;
}
.cad-capa:hover .cad-capa-dica,
.cad-capa:focus-visible .cad-capa-dica { opacity: 1; }

/* Reposicionar. O botao fica ao lado da dica de trocar, e so aparece quando a
   capa e IMAGEM: um degrade nao tem o que reposicionar. */
.cad-capa-mover {
  position: absolute; right: .6rem; bottom: 2.3rem;
  background: var(--surface); color: var(--text-dim);
  border: 1px solid var(--border); border-radius: var(--r-xs);
  padding: .2rem .5rem; font-size: .72rem; cursor: pointer;
  opacity: 0; transition: opacity .12s;
}
.cad-capa:hover .cad-capa-mover,
.cad-capa:focus-within .cad-capa-mover { opacity: 1; }
.cad-capa-mover:hover { color: var(--accent-text); border-color: var(--accent); }

/* No modo de mover, o cursor diz o que fazer e a faixa nao vira botao. */
.cad-capa.movendo { cursor: grab; }
.cad-capa.movendo:active { cursor: grabbing; }
.cad-capa.movendo .cad-capa-dica,
.cad-capa.movendo .cad-capa-mover { display: none; }

/* A barra cobre a capa inteira para escurece-la, mas NAO recebe o ponteiro:
   senao ela comia o `pointerdown` do arrasto e a imagem nao se movia. Os
   botoes dentro dela reativam o ponteiro para si. */
.cad-capa-barra {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  background: color-mix(in srgb, #000 35%, transparent);
  pointer-events: none;
}
.cad-capa-barra button { pointer-events: auto; }
.cad-capa-ajuda {
  color: #fff; font-size: .78rem;
  background: color-mix(in srgb, #000 45%, transparent);
  padding: .25rem .6rem; border-radius: var(--r-xs);
  pointer-events: none;
}

/* O cabecalho SOBE por cima da capa: e o que faz o icone montar nela, como
   num caderno com etiqueta colada na lombada. O recuo negativo e a metade do
   icone - assim ele fica com metade dentro da imagem e metade fora. */
.cad-cabecalho {
  padding: 0 1.2rem .35rem;
  margin-top: -1.7rem;
  position: relative; z-index: 3;
}

/* A linha de cima da pagina: as setas e o caminho, lado a lado. */
.cad-topo {
  display: flex; align-items: center; gap: .5rem;
  margin-bottom: .4rem; min-height: 24px;
}
.cad-setas { display: flex; gap: .15rem; flex: none; }
.cad-seta-nav {
  border: none; background: none; color: var(--text-faint);
  width: 22px; height: 22px; display: grid; place-items: center;
  border-radius: var(--r-xs); cursor: pointer;
}
.cad-seta-nav:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
/* Desabilitada continua ocupando o lugar, e nao some: uma barra onde os
   botoes aparecem e desaparecem faz o resto da linha pular. */
.cad-seta-nav:disabled { opacity: .3; cursor: default; }

.cad-trilha {
  display: flex; flex-wrap: wrap; align-items: center; gap: .25rem;
  font-size: .78rem; min-width: 0;
}
.cad-trilha-ic { font-size: .8rem; }
.cad-trilha-item {
  display: inline-flex; align-items: center; gap: .25rem;
  border: none; background: none; padding: .1rem .2rem;
  border-radius: var(--r-xs);
  color: var(--text-faint); cursor: pointer; font-size: .78rem;
  max-width: 14rem; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.cad-trilha-item:hover { background: var(--surface-2); }
.cad-trilha-item:hover { color: var(--accent-text); text-decoration: underline; }
.cad-trilha-sep { color: var(--text-faint); }

/* O icone em cima e o titulo embaixo, como no Notion: com os dois na mesma
   linha, o icone montado na capa arrastava o titulo para dentro dela junto. */
.cad-titulo-linha {
  display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
}

/* O icone da PAGINA e grande de proposito: ele identifica a pagina inteira, e
   nao um item de lista. No tamanho antigo competia de igual para igual com os
   icones das subpaginas dentro do texto, e a hierarquia sumia. */
.cad-emoji {
  border: none; background: none; cursor: pointer;
  font-size: 3.2rem; line-height: 1; padding: 0;
  display: grid; place-items: center; color: var(--text-dim);
  width: 4.2rem; height: 4.2rem;
  /* O emoji fica SOLTO sobre a capa, sem quadrado atras. O fundo opaco que
     havia aqui recortava um retangulo escuro no meio da foto, e era ele que
     aparecia, e nao o icone. A sombra sozinha ja o separa da imagem: ela
     acompanha o desenho do emoji em vez de desenhar uma caixa. */
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .45));
}
/* A imagem como icone continua com cantos arredondados e fundo proprio: uma
   foto quadrada solta sobre a capa ficaria com a borda dura. */
.cad-emoji .cad-icone-img {
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .3);
}
.cad-emoji:disabled { cursor: default; }

.cad-titulo-campo {
  flex: 1; min-width: 0;
  font-size: 1.5rem; font-weight: 600; margin: 0;
  outline: none; color: var(--text);
}
.cad-titulo-campo:empty::before {
  content: attr(data-vazio); color: var(--text-faint); font-weight: 400;
}

.cad-acoes {
  display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .6rem;
}

/* Exportar e acao da PAGINA, e nao conteudo dela: solto embaixo do titulo,
   parecia a primeira linha do texto. Vai para a ponta da linha de cima, do
   lado oposto das setas. */
.cad-exportar { margin-left: auto; flex: none; }

.cad-nenhuma { padding: 3rem 1rem; }

/* --------------------------------------------------------------- blocos */

/* A margem esquerda maior abre espaco para a MAO (o `+` e a alca), que fica
   a -2.5rem do bloco. Com o padding antigo de 1.15rem ela caia fora da area
   dos blocos, e o `#cadWrap` por cima roubava o clique - o botao aparecia mas
   nao respondia. */
.cad-blocos { padding: .35rem 1.2rem 1.4rem 3rem; }

.cad-bloco { position: relative; }
.cad-corpo { padding: .1rem 0; }

/* A alça só aparece ao passar o mouse: visível o tempo todo, ela vira ruído
   ao lado de cada linha da página. */
/* A mao da margem: o `+` e a alca, lado a lado, fora do fluxo do texto. */
/* A mao alinhada com a PRIMEIRA LINHA do texto ao lado.
   `top` fixo desalinhava conforme o bloco: num titulo, que tem a linha mais
   alta, o `+` e o `⠿` ficavam acima do texto; num paragrafo de duas linhas,
   pareciam colados no topo. A altura da mao e a mesma de uma linha do corpo
   (1.6em), entao centralizar dentro dela poe os dois no meio da primeira. */
.cad-mao {
  position: absolute;
  left: -2.5rem; top: .08rem;
  height: 1.6em;
  display: flex; align-items: center; gap: .1rem;
}
/* Nos titulos a linha e maior, e a mao acompanha.
   As medidas sao em REM, e nao em `em`: a mao e filha do `.cad-bloco`, que
   tem o tamanho de fonte do corpo - um `em` ali media a fonte do CORPO, e nao
   a do titulo, deixando a mao 16px acima da palavra. */
/* O `top` soma a MARGEM do titulo (`.cad-h1` e irmaos): ela empurra o texto
   para baixo, mas nao a mao, que e `absolute` e ignora o fluxo. Sem somar,
   o `+` e o `⠿` ficavam dez pixels acima da palavra. */
.cad-tipo-titulo1 > .cad-mao { height: 2.1rem; top: calc(.08rem + .7rem); }
.cad-tipo-titulo2 > .cad-mao { height: 1.8rem; top: calc(.08rem + .6rem); }
.cad-tipo-titulo3 > .cad-mao { height: 1.6rem; top: calc(.08rem + .5rem); }
/* A citacao tambem tem margem propria (.25rem), pelo mesmo motivo. */
.cad-tipo-citacao > .cad-mao { top: calc(.08rem + .25rem); }
.cad-mais {
  border: none; background: none; color: var(--text-faint);
  width: 18px; height: 20px; display: grid; place-items: center;
  border-radius: var(--r-xs); cursor: pointer;
  font-size: 1rem; line-height: 1;
  opacity: 0; transition: opacity .12s;
}
.cad-mais:hover { background: var(--surface-2); color: var(--accent-text); }
/* So o bloco sob o ponteiro mostra a mao - nao os pais dele.
   Uma lista aninhada poe bloco dentro de bloco, e `:hover` vale para toda a
   cadeia: passar o mouse no item de terceiro nivel acendia o `+` dele E os
   dos dois blocos acima, tres botoes de uma vez na margem.
   `:not(:has(.cad-bloco:hover))` tira o pai da conta: ele so acende quando o
   ponteiro NAO esta num filho. */
.cad-bloco:hover:not(:has(.cad-bloco:hover)) > .cad-mao .cad-mais,
.cad-bloco:focus-within:not(:has(.cad-bloco:focus-within)) > .cad-mao .cad-mais {
  opacity: 1;
}

.cad-alca {
  position: static;
  color: var(--text-faint);
  cursor: grab;
  opacity: 0;
  transition: opacity .12s;
  font-size: .8rem;
  line-height: 1.4;
  user-select: none;
}
/* A alca segue a mesma regra do `+`: so o bloco sob o ponteiro. */
.cad-bloco:hover:not(:has(.cad-bloco:hover)) .cad-alca { opacity: 1; }
.cad-bloco.arrastando { opacity: .45; }
.cad-bloco.alvo > .cad-corpo { box-shadow: 0 2px 0 var(--accent); }
/* "Antes deste": a linha vai no TOPO. Sem ela nao havia como soltar um bloco
   ACIMA de outro - mover algo para a primeira posicao era impossivel, e
   trocar dois vizinhos exigia arrastar o de cima para baixo. */
.cad-bloco.alvo-antes > .cad-corpo { box-shadow: 0 -2px 0 var(--accent); }

/* Soltar na BORDA cria duas colunas: a barra vertical mostra de que lado o
   bloco vai cair. Vertical, e nao horizontal, porque o resultado e lado a
   lado - a marca precisa parecer com o que vai acontecer. */
.cad-bloco.alvo-col-esq > .cad-corpo { box-shadow: -3px 0 0 var(--accent); }
.cad-bloco.alvo-col-dir > .cad-corpo { box-shadow: 3px 0 0 var(--accent); }
.cad-bloco.alvo-dentro > .cad-corpo {
  box-shadow: inset 0 0 0 2px var(--accent); border-radius: var(--r-xs);
}

.cad-txt {
  outline: none;
  min-height: 1.5em;
  line-height: 1.6;
  word-break: break-word;
  /* O campo ocupa a linha inteira, mesmo VAZIO.
     Dentro de `.cad-item-lista`, que e flex, um campo sem texto colapsava
     para largura zero: um item de lista vazio ficava impossivel de clicar de
     volta - a linha existia, mas nao havia onde pegar nela. Com `flex: 1` e
     `min-width: 0` ele toma a largura que sobra e continua encolhendo quando
     o texto e longo. */
  flex: 1;
  min-width: 0;
}
.cad-txt:empty::before {
  content: 'Escreva, ou tecle / para escolher o tipo';
  color: var(--text-faint);
}
/* Só o bloco em foco mostra a dica: em todos, a página vazia viraria uma
   parede de texto cinza repetido. */
.cad-txt:empty:not(:focus)::before { content: ''; }

.cad-p { font-size: .9rem; }
.cad-h1 { font-size: 1.5rem; font-weight: 600; margin: .7rem 0 .2rem; }
.cad-h2 { font-size: 1.2rem; font-weight: 600; margin: .6rem 0 .15rem; }
.cad-h3 { font-size: 1.05rem; font-weight: 600; margin: .5rem 0 .1rem; }

.cad-item-lista {
  display: flex; align-items: flex-start; gap: .45rem; font-size: .9rem;
}
.cad-marca { color: var(--text-dim); line-height: 1.6; user-select: none; }

/* O marcador muda a cada nivel, como num sumario impresso: bolinha cheia,
   depois vazada, depois quadrada. Sem isso, tres niveis de lista aninhada
   ficam com o mesmo ponto e so o recuo os separa - e o recuo e pequeno. */
.cad-bloco[data-nivel="2"] > .cad-corpo > .cad-item-lista > .cad-marca::after,
.cad-bloco[data-nivel="3"] > .cad-corpo > .cad-item-lista > .cad-marca::after {
  content: "";
}
.cad-bloco[data-nivel="2"] > .cad-corpo > .cad-item-lista > .cad-marca:not(.cad-num) {
  font-size: 0;
}
.cad-bloco[data-nivel="2"] > .cad-corpo > .cad-item-lista > .cad-marca:not(.cad-num)::before {
  content: "◦"; font-size: 1rem;
}
.cad-bloco[data-nivel="3"] > .cad-corpo > .cad-item-lista > .cad-marca:not(.cad-num) {
  font-size: 0;
}
.cad-bloco[data-nivel="3"] > .cad-corpo > .cad-item-lista > .cad-marca:not(.cad-num)::before {
  content: "▪"; font-size: .72rem;
}
/* Largura e altura EXPLICITAS. `flex: none` sozinho nao bastava: sem uma
   largura definida, o `flex-basis: auto` de um `input` dentro de um pai flex
   deixa o navegador estica-lo para o espaco que sobra - a caixa de marcar
   aparecia como um quadrado gigante no meio da pagina. */
.cad-check {
  /* A margem alinha a caixa com a PRIMEIRA linha do texto ao lado. Ela nasce
     do topo (`align-items: flex-start` no pai), e sem o empurrao ficava um
     degrau acima da linha; com o empurrao antigo, de .38rem sobre uma altura
     que o navegador esticava, caia abaixo dela. */
  margin-top: .2rem; flex: none;
  /* A regra geral de `input` (campo de texto: 100% de largura, 38px de altura
     minima, moldura e respiro) atinge o checkbox tambem: era ela que fazia a
     caixa de marcar virar um quadrado gigante no meio da pagina. Aqui ela e
     desfeita item por item. */
  width: 15px; height: 15px; min-height: 0;
  padding: 0; border: none; background: none; border-radius: 0;
  accent-color: var(--accent);
}
.cad-txt[data-feito="1"] { text-decoration: line-through; color: var(--text-faint); }

/* A numeração vem do CSS: guardar o número no bloco obrigaria a renumerar
   tudo a cada Enter, e um item removido deixaria buraco na conta. */
.cad-blocos { counter-reset: cadnum; }
.cad-tipo-numerada { counter-increment: cadnum; }
.cad-tipo-numerada .cad-num::before { content: counter(cadnum) "."; }
/* Cada aninhamento recomeça do 1, como em qualquer lista. */
.cad-filhos-bloco { counter-reset: cadnum; margin-left: 1.4rem; }

.cad-cita {
  border-left: 3px solid var(--border-strong);
  padding-left: .7rem; margin: .25rem 0;
  color: var(--text-dim); font-size: .9rem;
}

.cad-codigo {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  margin: .3rem 0;
  overflow: hidden;
}
.cad-lingua {
  width: 100%; border: none; border-bottom: 1px solid var(--border);
  background: transparent; color: var(--text-faint);
  font-size: .72rem; padding: .25rem .6rem; font-family: var(--font-mono);
}
.cad-pre {
  margin: 0; padding: .55rem .7rem;
  font-family: var(--font-mono); font-size: .82rem;
  white-space: pre-wrap; word-break: break-word; outline: none;
}

.cad-hr { border: none; border-top: 1px solid var(--border); margin: .8rem 0; }

.cad-destaque {
  display: flex; align-items: flex-start; gap: .5rem;
  border-radius: var(--r-sm); padding: .55rem .7rem; margin: .3rem 0;
  border-left: 3px solid var(--tom, var(--accent));
  background: color-mix(in srgb, var(--tom, var(--accent)) 9%, transparent);
  font-size: .9rem;
}
.cad-tom-nota    { --tom: #2563eb; }
.cad-tom-aviso   { --tom: #d97706; }
.cad-tom-cuidado { --tom: #dc2626; }
.cad-tom-ok      { --tom: #059669; }
.cad-tom-btn {
  border: none; background: none; color: var(--tom); cursor: pointer;
  padding: 0; line-height: 1.6; font-size: .72rem;
}

.cad-indice, .cad-indice ul {
  list-style: none; padding: 0; margin: .2rem 0; display: grid; gap: 1px;
}
/* As sublistas nao ganham margem propria: o recuo vem do `padding-left` de
   cada botao, que para no terceiro nivel. Somar os dois faria a quarta
   pagina comecar no meio da largura. */
.cad-indice ul { margin: 0; }
.cad-indice button {
  display: flex; align-items: center; gap: .4rem; width: 100%;
  border: none; background: none; cursor: pointer; text-align: left;
  padding: .3rem .35rem; border-radius: var(--r-xs);
  color: var(--text); font-size: .9rem;
}
.cad-indice button:hover { background: var(--surface-2); color: var(--accent-text); }
.cad-indice-vazio { padding: .3rem 0; }

.cad-figura { margin: .45rem 0; }
.cad-figura img {
  max-width: 100%; height: auto; border-radius: var(--r-sm); display: block;
}
.cad-por-imagem {
  border: 1px dashed var(--border-strong); background: var(--surface-2);
  color: var(--text-dim); border-radius: var(--r-sm);
  padding: 1.1rem; width: 100%; cursor: pointer; font-size: .85rem;
}
.cad-legenda {
  font-size: .78rem; color: var(--text-faint); outline: none; margin-top: .25rem;
}
.cad-legenda:empty::before { content: attr(data-vazio); }

/* A escolha das paginas do widget: UMA coluna, com recuo por nivel.
   Em duas colunas a ordem de profundidade era lida de lado a lado, e a
   hierarquia sumia -- uma subpagina aparecia ao lado da tia como se fossem
   irmas. */
.fix-arvore { grid-template-columns: 1fr; }
.fix-nome {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ------------------------------------------- link no texto do bloco

   O icone do site vem ANTES do texto, dentro do proprio <a>: assim ele
   acompanha o link se a linha quebrar, e sublinhar o link nao sublinha o
   icone. */
/* A cor do link vem de uma VARIAVEL, e nao direto da propriedade.
   Assim o `<span style="color: ...">` que a barra de formatacao escreve
   ganha do estilo do link: com `color: var(--accent-text)` na propria regra, a
   cor escolhida ficava por baixo e o link era o unico texto do Caderno que
   nao aceitava cor. A sublinha acompanha, senao um link vermelho ficaria
   com risco laranja embaixo. */
.cad-txt a {
  --cor-link: var(--accent);
  color: var(--cor-link);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--cor-link) 35%, transparent);
}
/* O `<span>` colorido POR DENTRO do link: a barra envolve a selecao, e o
   texto do link vira filho dele. `currentColor` na sublinha faz a linha
   seguir a cor que o span pintou. */
.cad-txt a span[style*="color"] { color: inherit; }
.cad-txt a:has(span[style*="color"]) {
  color: inherit;
  border-bottom-color: color-mix(in srgb, currentColor 35%, transparent);
}
/* E o `<span>` colorido POR FORA, quando a selecao pegou o link inteiro
   junto com o texto ao redor. */
.cad-txt span[style*="color"] > a,
.cad-txt span[style*="color"] a {
  color: inherit;
  border-bottom-color: color-mix(in srgb, currentColor 35%, transparent);
}
.cad-txt a:hover { border-bottom-color: currentColor; }
.cad-ico-site {
  /* Largura fixa desde antes de o icone chegar: sem ela o link pularia de
     lugar quando a busca respondesse, no meio da digitacao. */
  width: 14px;
  height: 14px;
  object-fit: contain;
  vertical-align: -2px;
  margin-right: .3rem;
  border-radius: 2px;
}

/* ------------------------------------------- arquivo anexado a pagina

   Uma linha so, como no Notion: icone, nome, tamanho. Ela ocupa a largura
   do texto e nao um bloco alto, porque um anexo e uma REFERENCIA dentro da
   pagina, e nao o conteudo dela. */
.cad-anexo {
  display: flex;
  align-items: center;
  gap: .2rem;
  margin: .3rem 0;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  padding: .2rem .3rem .2rem .1rem;
}
.cad-anexo.vazio { border: 0; background: none; padding: 0; }
.cad-anexo-abre {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex: 1;
  min-width: 0;
  padding: .35rem .45rem;
  border-radius: var(--r-xs);
  color: var(--text);
  text-decoration: none;
}
.cad-anexo-abre:hover { background: var(--surface); color: var(--accent-text); }
.cad-anexo-ico { display: flex; flex-shrink: 0; opacity: .75; }
.cad-anexo-abre:hover .cad-anexo-ico { opacity: 1; }
.cad-anexo-nome {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: .85rem;
}
/* O tamanho e informacao de apoio, e nao parte do nome: menor e apagado,
   para o olho pegar o nome primeiro. */
.cad-anexo-tam {
  flex-shrink: 0;
  font-size: .72rem;
  color: var(--text-faint);
}
.cad-anexo-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  background: none;
  border-radius: var(--r-xs);
  color: var(--text-faint);
  cursor: pointer;
  text-decoration: none;
}
.cad-anexo-btn:hover { color: var(--text); background: var(--surface); }
.cad-por-anexo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  border: 1px dashed var(--border-strong);
  background: var(--surface-2);
  color: var(--text-dim);
  border-radius: var(--r-sm);
  padding: .8rem;
  width: 100%;
  cursor: pointer;
  font: inherit;
  font-size: .85rem;
}
.cad-por-anexo:hover { border-color: var(--accent); color: var(--accent-text); }

/* Duas colunas no computador; empilhadas no celular, onde lado a lado daria
   170px por coluna e cortaria toda palavra comprida. */
.cad-colunas { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; }
.cad-coluna { min-width: 0; }

.cad-adicionar {
  display: flex; align-items: center; gap: .35rem;
  border: none; background: none; color: var(--text-faint);
  cursor: pointer; padding: .4rem 0; font-size: .85rem; width: 100%;
}
.cad-adicionar:hover { color: var(--accent-text); }
.cad-adicionar.pequeno { justify-content: center; padding: .2rem 0; }

/* ------------------------------------------------------- menu de barra */

.cad-menu {
  position: fixed;
  z-index: 60;
  width: 230px;
  max-height: 280px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
  padding: .25rem;
}
/* "Nenhum tipo com X": o menu fica na tela dizendo que nao achou, em vez de
   sumir. Sumindo, apagar a letra errada nao trazia a lista de volta. */
.cad-menu-vazio {
  margin: 0; padding: .5rem .6rem;
  color: var(--text-faint); font-size: .8rem;
}
.cad-menu-item {
  display: flex; flex-direction: column; align-items: flex-start;
  width: 100%; border: none; background: none; cursor: pointer;
  padding: .35rem .5rem; border-radius: var(--r-xs); text-align: left;
}
.cad-menu-item.ativo, .cad-menu-item:hover { background: var(--surface-2); }
.cad-menu-rotulo { font-size: .85rem; color: var(--text); }
.cad-menu-dica { font-size: .72rem; color: var(--text-faint); }

/* ---------------------------------------------------------- capa e ícone */

/* Quatro colunas para as 12 capas: tres fileiras cheias. Com tres colunas, a
   decima segunda ficava sozinha na quarta fileira. */
.cad-capas { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
@media (max-width: 480px) {
  .cad-capas { grid-template-columns: repeat(3, 1fr); }
}
.cad-capa-opt {
  height: 52px; border: 1px solid var(--border); border-radius: var(--r-sm);
  cursor: pointer;
}
.cad-capa-opt:hover { outline: 2px solid var(--accent); }

/* Oito colunas FIXAS, para as 32 opcoes cairem em quatro fileiras cheias.
   Com `auto-fill` a grade mudava de forma conforme a largura do modal, e a
   ultima fileira quase sempre sobrava pela metade. */
.cad-emojis {
  display: grid; grid-template-columns: repeat(8, 1fr);
  gap: .3rem;
}
/* No celular oito colunas dariam menos de 30px por icone: la sao quatro, e
   as 32 viram oito fileiras. */
@media (max-width: 480px) {
  .cad-emojis { grid-template-columns: repeat(4, 1fr); }
}
.cad-emoji-opt {
  border: 1px solid var(--border); background: var(--surface-2);
  border-radius: var(--r-xs); cursor: pointer;
  font-size: 1.2rem; padding: .35rem; line-height: 1;
}
.cad-emoji-opt:hover { outline: 2px solid var(--accent); }

/* ------------------------------------------------------------- celular */

@media (max-width: 760px) {
  /* As duas colunas da pagina do Caderno empilham. */
  .cc-pagina { grid-template-columns: 1fr; }

  /* No celular a lista de paginas e uma GAVETA que desliza por cima, e nao
     uma coluna empilhada acima do texto.
     
     Empilhada, ela empurrava a pagina para baixo: a capa e o titulo ficavam
     fora da tela, e era preciso rolar por uma lista de 260px para chegar ao
     que se veio ler. Como gaveta, a pagina ocupa a tela inteira e a lista
     aparece so quando pedida - que e como o Notion no celular se comporta. */
  .cad-wrap { display: block; position: relative; }

  .cad-arvore {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: min(82vw, 320px);
    max-height: none;
    z-index: 60;
    overflow-y: auto;
    border-radius: 0;
    transform: translateX(-102%);
    transition: transform .18s ease-out;
    padding-top: 3.2rem;
  }
  .cad-wrap:not(.recolhida) .cad-arvore { transform: translateX(0); }
  /* Aberta, ela some pelo lado; nao ha o que esconder com opacidade. */
  .cad-wrap.recolhida .cad-arvore { opacity: 1; display: block; }

  /* O veu atras da gaveta: escurece a pagina e fecha a lista ao ser tocado.
     Sem ele, tocar "fora" nao faria nada e a unica saida seria achar o
     puxador de novo. */
  .cad-veu {
    position: fixed; inset: 0; z-index: 55;
    background: color-mix(in srgb, #000 45%, transparent);
    border: none;
  }

  /* O puxador fica no topo da area do Caderno, e nao flutuando na tela.
     `position: fixed` sem `top` o deixava cair no rodape, longe da lista que
     ele controla; `absolute` no `.cad-wrap` (que e `relative`) o prende ao
     canto de cima do conteudo, que e onde a mao vai procurar. */
  .cad-puxador {
    position: absolute; top: .4rem; left: .4rem; z-index: 61;
  }
  /* Com a gaveta ABERTA ele acompanha a borda dela, para continuar sendo o
     mesmo botao de fechar - e nao sumir atras do painel. */
  .cad-wrap:not(.recolhida) .cad-puxador {
    position: fixed; top: .5rem; left: min(82vw, 320px);
    margin-left: .4rem;
  }
  /* A pagina abre espaco para o puxador nao cair em cima da capa. */
  .cad-pagina { padding-top: 2.6rem; }

  /* A pagina ocupa a largura toda: no celular ela E a tela. */
  .cad-pagina { width: 100%; }

  /* Empilha, e é o que a regra do produto pede: no celular as duas colunas
     lado a lado dariam menos de 170px cada, cortando o conteúdo. */
  .cad-colunas { grid-template-columns: 1fr; }
  /* A alça sai do caminho: no toque não há arrasto de bloco, e ela só comeria
     a margem esquerda do texto. O `+` FICA: e o unico jeito de inserir bloco
     sem teclado fisico para digitar a barra. */
  .cad-alca { display: none; }
  .cad-mao { left: -1.6rem; }
  .cad-blocos { padding-left: 2.2rem; padding-right: .9rem; }
  .cad-cabecalho { padding-left: .9rem; padding-right: .9rem; }
  .cad-capa { --cad-capa-h: 130px; }
  .cad-emoji { width: 3.4rem; height: 3.4rem; font-size: 2.6rem; }
  .cad-emoji .cad-icone-img { width: 2.6rem; height: 2.6rem; }

  /* O toque nao tem hover: as acoes de linha e as da tabela ficam sempre
     visiveis, senao nao ha como chegar nelas com o dedo. */
  .cad-linha-acoes,
  .cad-tab-alca,
  .cad-img-acoes { opacity: 1; }
}


/* O link de subpagina, do `/pagina`. Parece uma linha de texto clicavel, e
   nao um botao: ele vive DENTRO do texto, e um botao ali quebraria a leitura. */
/* O link de subpagina e uma LINHA DE TEXTO, e nao uma faixa.
   Com `width: 100%` ele esticava de ponta a ponta e o nome aparecia
   centralizado no meio da pagina, longe da margem onde o resto do texto
   comeca - parecia um botao solto, e nao uma pagina dentro da pagina.
   `fit-content` faz o link medir o proprio nome e ficar na margem. */
.cad-link-pagina {
  display: inline-flex; align-items: center; gap: .4rem;
  border: none; background: none; cursor: pointer; text-align: left;
  padding: .25rem .3rem; border-radius: var(--r-xs);
  color: var(--text); font-size: .9rem;
  width: fit-content; max-width: 100%;
}
/* O icone dentro do link e um alvo proprio: clicar nele troca o icone, e nao
   abre a pagina. O quadrado em volta no hover diz que ele e clicavel. */
.cad-link-ic { padding: .1rem; border-radius: var(--r-xs); }
.cad-link-ic:hover { background: var(--surface-2); outline: 1px solid var(--border); }
.cad-link-pagina .cad-renomeia { font-size: .9rem; }
.cad-link-pagina:hover { background: var(--surface-2); }
.cad-link-titulo { border-bottom: 1px solid var(--border-strong); }
.cad-link-perdido {
  display: inline-flex; align-items: center; gap: .35rem;
  color: var(--text-faint); font-size: .9rem; font-style: italic;
}

/* Renomear na arvore: o campo ocupa o lugar exato do nome, para a linha nao
   pular de altura enquanto se digita. */
.cad-renomeia {
  flex: 1; min-width: 0;
  font-size: .85rem; font-family: inherit;
  padding: .1rem .25rem;
  border: 1px solid var(--accent); border-radius: var(--r-xs);
  background: var(--surface); color: var(--text);
}

/* O icone quando e imagem, e nao emoji. */
.cad-icone-img {
  width: 1.05em; height: 1.05em;
  object-fit: cover; border-radius: 3px; display: block;
}
.cad-emoji .cad-icone-img { width: 3.2rem; height: 3.2rem; border-radius: 6px; }

/* O icone de quem nao escolheu: um pouco apagado, para nao competir com os
   que a pessoa escolheu de proposito. Ele ganha cor ao passar o mouse, que e
   quando ela pode querer troca-lo. */
.cad-icone-auto { opacity: .75; }
.cad-item:hover .cad-icone-auto,
.cad-emoji:hover .cad-icone-auto { opacity: 1; }

/* A area clicavel abaixo do ultimo bloco: e o que substituiu o botao
   "Escrever". Ocupa o resto da pagina, entao clicar no vazio continua o
   texto, como num documento. */
.cad-fim { min-height: 120px; cursor: text; }

/* As acoes da imagem so aparecem com o ponteiro em cima ou com a figura em
   foco: sempre visiveis, elas competiriam com a propria imagem. */
/* A figura encolhe ate o tamanho da imagem (`width: fit-content`), e nao
   ocupa a largura toda da pagina. Sem isto, a caixa de acoes - que e
   `absolute` no canto da FIGURA - aparecia longe de uma imagem pequena, e
   chegava a cobrir o bloco seguinte.

   `max-width: 100%` mantem a imagem grande dentro da coluna. */
.cad-figura {
  position: relative; outline: none;
  width: fit-content; max-width: 100%;
  /* Largura E altura minimas do tamanho da caixa de acoes. Elas sao
     `absolute` no canto da figura: numa imagem pequena - um icone de 16px,
     um recorte fino - transbordavam para fora e ficavam por cima do bloco
     seguinte, roubando o clique de quem ia escrever ali. */
  min-width: 120px;
  min-height: 46px;
}
.cad-figura:focus-visible { outline: 2px solid var(--accent); border-radius: var(--r-sm); }
.cad-img-acoes {
  position: absolute; top: .4rem; right: .4rem;
  display: flex; gap: .2rem; opacity: 0; transition: opacity .12s;
}
.cad-figura:hover .cad-img-acoes,
.cad-figura:focus-within .cad-img-acoes { opacity: 1; }
.cad-img-acoes button {
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-dim); border-radius: var(--r-xs);
  width: 26px; height: 26px; display: grid; place-items: center;
  cursor: pointer; font-size: .78rem;
}
.cad-img-acoes button:hover { color: var(--accent-text); border-color: var(--accent); }

/* A tabela. Rola de lado dentro da propria caixa, e nunca empurra a pagina:
   uma tabela de nove colunas colada de uma planilha e mais larga que o texto,
   e deixar a PAGINA rolar de lado quebraria a leitura de tudo o mais. */
/* `position: relative` para as alcas de redimensionar se prenderem as bordas.
   O `overflow-x` fica numa camada de DENTRO: com ele aqui, as alcas - que
   ficam fora da moldura da tabela - seriam cortadas pela rolagem. */
.cad-tabela-caixa { margin: .5rem 0; position: relative; padding-right: 1.6rem; }
.cad-tabela-rola { overflow-x: auto; }

/* As alcas: uma na direita (colunas) e uma embaixo (linhas). Clique acrescenta
   uma; arrasto acrescenta ou tira varias. */
.cad-tab-puxa {
  position: absolute;
  border: 1px dashed var(--border); background: var(--surface);
  color: var(--text-faint); border-radius: var(--r-xs);
  display: grid; place-items: center;
  cursor: pointer; font-size: .8rem; line-height: 1;
  opacity: 0; transition: opacity .12s;
  touch-action: none;   /* o arrasto e nosso, e nao rolagem da pagina */
}
.cad-tabela-caixa:hover .cad-tab-puxa,
.cad-tabela-caixa:focus-within .cad-tab-puxa { opacity: .7; }
.cad-tab-puxa:hover { opacity: 1; color: var(--accent-text); border-color: var(--accent); }

/* O `+` das colunas fica FORA da tabela, no espaco que a caixa reserva a
   direita. Ele encostava na borda da area de rolagem e, numa tabela estreita,
   cobria a alca da linha - a alca existia mas o clique nao chegava nela. */
.cad-tab-puxa-col {
  top: 1.6rem; right: 0; bottom: .6rem; width: .9rem;
  cursor: ew-resize;
}
/* O `+` das linhas mora num PE, embaixo da area que rola, e nao flutuando
   sobre ela. Antes ele ficava a 1.4rem do fundo, bem em cima da barra de
   rolagem horizontal: a barra existia, mas o botao comia o clique e nao dava
   para arrastar a tabela de lado. */
.cad-tab-pe { padding-right: 1.6rem; margin-top: .15rem; }
.cad-tab-puxa-lin {
  position: static; width: 100%; height: .9rem;
  cursor: ns-resize;
}

.cad-tabela {
  border-collapse: collapse;
  width: max-content;
  min-width: 100%;
  font-size: .9rem;
}
.cad-celula {
  border: 1px solid var(--border);
  padding: .4rem .55rem;
  vertical-align: top;
  min-width: 7rem;
  max-width: 22rem;
  text-align: left;
  /* A pega mora aqui dentro, encostada na divisa direita. */
  position: relative;
}
/* Assim que UMA coluna ganha largura escolhida a mao, o min e o max saem de
   cena na tabela toda: eles existem para a tabela sem largura definida ficar
   legivel sozinha, e nao para discutir com quem arrastou a divisa ate onde
   queria. `table-layout: fixed` e o que faz o `<col>` mandar de verdade -
   sem ele o navegador reparte pelo conteudo e ignora a largura pedida. */
.cad-tabela:has(col[style]) { table-layout: fixed; }
.cad-tabela:has(col[style]) .cad-celula { min-width: 0; max-width: none; }

/* A divisa entre duas colunas, para arrastar. Larga o bastante para o mouse
   acertar (8px), mas invisivel ate a tabela receber o ponteiro - uma linha
   marcada em toda divisa competiria com as bordas da propria tabela. */
.cad-tab-pega {
  position: absolute; top: 0; right: -4px; bottom: 0;
  width: 8px; cursor: col-resize;
  z-index: 2;
  user-select: none;
}
.cad-tab-pega::after {
  content: ''; position: absolute;
  top: 0; bottom: 0; left: 3px; width: 2px;
  background: var(--accent); opacity: 0;
  transition: opacity .12s;
}
.cad-tabela-caixa:hover .cad-tab-pega:hover::after { opacity: 1; }
/* Enquanto arrasta, o cursor e o mesmo em toda a tela e nada seleciona -
   senao o texto das celulas ia sendo marcado atras do gesto. */
body.cad-redimensionando { cursor: col-resize; user-select: none; }
body.cad-redimensionando .cad-tab-pega::after { opacity: 1; }
.cad-tabela th.cad-celula {
  background: var(--surface-2);
  font-weight: 600;
}
.cad-celula:focus { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Espacamento apertado: cabe mais coluna na tela sem rolar. */
.cad-tabela-caixa.apertada .cad-celula {
  padding: .2rem .35rem;
  min-width: 4.5rem;
  font-size: .82rem;
}

/* Os X de apagar linha e coluna. Ficam fora da moldura da tabela, e so
   aparecem com o ponteiro nela. */
/* A linha das alcas de coluna: e uma `<tr>` da tabela, entao cada celula ja
   tem a largura da coluna que representa. A altura e pequena porque a linha
   nao guarda conteudo - so a alca. */
/* A linha das alcas: a celula guarda so a alca. Ela continua sendo uma
   celula de tabela de verdade - qualquer outro `display` a tiraria do
   `<colgroup>`, e todas as alcas ficariam do mesmo tamanho em vez de
   acompanhar a largura da coluna.

   A alca vai como `inline-block` centrado pelo `text-align`: com o botao em
   `display: block` o `vertical-align: middle` da celula o esticava ate a
   altura dela, e era dai que vinham 38px de alca no lugar de 4. */
/* A linha das alcas: a celula guarda so a alca, e a `<tr>` inteira e uma
   faixa fina. `line-height: 0` na celula e o que faz a linha encolher - sem
   ele o navegador reserva a altura de uma linha de texto, e a alca (que e um
   `<button>` vazio, esticado pelo `vertical-align: middle` da celula lateral)
   ficava com 38px em vez de 4. */
.cad-tab-alcas-linha td {
  height: 1rem; padding: 0 0 .15rem;
  text-align: center; vertical-align: middle;
  line-height: 0;
}
.cad-tab-alcas-linha .cad-tab-alca-col {
  display: inline-block;
  vertical-align: middle;
}

/* A alca de uma linha ou coluna: uma barra fina, cinza, que so aparece com o
   ponteiro na tabela. Clicar nela abre o menu daquela linha ou coluna. */
/* As duas alcas sao a MESMA peca, girada: uma barra fina, cinza, que so
   aparece com o ponteiro na tabela. A de coluna deita sobre a coluna, a de
   linha fica em pe ao lado dela - e as duas ficam centradas na celula. */
.cad-tab-alca {
  border: none; background: var(--text-faint);
  border-radius: 2px; padding: 0;
  cursor: pointer;
  opacity: 0; transition: opacity .12s, background .12s;
}
.cad-tab-alca-col { width: 70%; max-width: 4rem; height: 4px; }
/* `height` em porcentagem dentro de uma celula de tabela nao tem contra o
   que medir e o navegador arredonda por conta propria - dai a alca ficava
   uns pixels fora do centro. `display: block` com margem automatica centra
   pelo modelo de caixa, sem depender disso. */
.cad-tab-alca-lin {
  width: 4px; height: 1.1rem;
  display: block; margin: 0 auto;
}
.cad-tabela-caixa:hover .cad-tab-alca,
.cad-tabela-caixa:focus-within .cad-tab-alca { opacity: .3; }
.cad-tab-alca:hover,
.cad-tab-alca:focus-visible { opacity: 1; background: var(--accent); }

/* O menu de linha e coluna. Ancorado na alca por `posicionarMenuFlutuante`,
   que e o mesmo posicionador do menu do `/` - ele ja resolve caber na
   janela e abrir para cima quando nao ha espaco embaixo. */
.cad-tab-menu {
  position: fixed; z-index: 60;
  min-width: 12rem; padding: .3rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .32);
  display: flex; flex-direction: column; gap: .1rem;
  overflow-y: auto;
}
.cad-tab-menu button {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; width: 100%;
  padding: .35rem .5rem; text-align: left;
  background: none; border: 0; cursor: pointer;
  color: var(--text); font-size: .82rem; border-radius: var(--r-xs);
}
.cad-tab-menu button:hover,
.cad-tab-menu button:focus-visible { background: var(--surface-2, var(--border)); }
/* Excluir em vermelho, e depois de um risco: e a unica do menu que nao tem
   volta obvia, e precisa parecer diferente das outras. */
.cad-tab-menu button.perigo { color: var(--erro, #e5484d); }
.cad-tab-menu-risco {
  height: 1px; margin: .2rem .1rem;
  background: var(--border);
}

/* A chavinha de "primeira linha e titulo" e "espacamento apertado": elas sao
   estados que ficam ligados, e nao acoes que acontecem uma vez. */
.cad-tab-chave {
  width: 1.6rem; height: .9rem; border-radius: .45rem;
  background: var(--border); position: relative; flex: none;
  transition: background .12s;
}
.cad-tab-chave::after {
  content: ''; position: absolute;
  top: 2px; left: 2px; width: .5rem; height: .5rem;
  border-radius: 50%; background: var(--surface);
  transition: transform .12s;
}
.cad-tab-chave.ligada { background: var(--accent); }
.cad-tab-chave.ligada::after { transform: translateX(.7rem); }

/* A celula da lateral nao tem moldura: ela nao faz parte da tabela, e a alca
   dela ficaria parecendo mais uma coluna. */
td.cad-tab-lado {
  border: none; background: none; padding: 0 .15rem;
  vertical-align: middle;
  text-align: center;
}
/* A faixa lateral fica na ESQUERDA e tem largura fixa: e so o lugar da alca,
   e sem largura declarada o navegador a esticaria como se fosse conteudo. */
col.cad-tab-col-lado { width: 1.4rem; }

/* O menu de irmas da trilha. Fica no `<body>` para nao ser cortado pelo
   `overflow` do cabecalho, e por isso e posicionado por JavaScript. */
/* A coluna VAZIA convida a escrever; a coluna com conteudo nao mostra nada.
   Antes cada coluna carregava um `+` fixo no fim, e uma pagina com duas
   colunas ficava com dois botoes soltos no meio do texto - o `+` da margem,
   que ja aparece em cada bloco, faz o mesmo trabalho sem sujar a leitura. */
.cad-coluna-vazia {
  width: 100%; text-align: left;
  border: none; background: none; cursor: text;
  color: var(--text-faint); font-size: .9rem;
  padding: .3rem .1rem;
}
.cad-coluna-vazia:hover { color: var(--text-dim); }

.cad-irmas {
  position: fixed; z-index: 70;
  min-width: 12rem; max-width: 16rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  box-shadow: var(--sombra-alta, 0 8px 24px rgba(0,0,0,.35));
  padding: .25rem;
  display: flex; flex-direction: column; gap: .1rem;
}
.cad-irma {
  display: flex; align-items: center; gap: .45rem;
  border: none; background: none; cursor: pointer; text-align: left;
  padding: .35rem .45rem; border-radius: var(--r-xs);
  color: var(--text); font-size: .85rem; width: 100%;
}
.cad-irma:hover { background: var(--surface-2); }
.cad-irma-nome {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cad-irma-seta { color: var(--text-faint); display: grid; place-items: center; }
/* "Mais N" e informacao, e nao botao: quem quer ver o resto abre a arvore,
   que e o lugar que mostra a lista inteira sem limite. */
.cad-irma-resto {
  color: var(--text-faint); font-size: .78rem;
  padding: .3rem .45rem;
}

/* O rodape da arvore: dois botoes so de icone, lado a lado. Sem rotulo: o
   rodape fica embaixo de uma lista de paginas com nome, e duas frases ali
   competiam com os nomes que a pessoa esta procurando. A lixeira SOME quando
   esta vazia - um botao de lixeira vazia so lembraria de um lugar sem nada. */
.cad-rodape {
  display: flex; align-items: center; justify-content: center;
  gap: .35rem; padding: .35rem .1rem 0;
}
.cad-pe-btn {
  width: 2rem; height: 2rem; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-faint); border-radius: var(--r-sm);
}
.cad-pe-btn:hover { color: var(--text); background: var(--surface-2, var(--border)); }

/* Uma linha da lixeira: nome, quanto falta, e o que fazer com ela. */
.lix-item {
  display: flex; align-items: center; gap: .45rem;
  padding: .35rem .1rem;
  border-bottom: 1px solid var(--border);
}
.lix-item:last-child { border-bottom: none; }
.lix-nome {
  flex: 1; min-width: 0; font-size: .9rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* O PRAZO e o ponto da lixeira: "apagada" sem data nao diz se ainda da tempo
   de voltar atras. */
.lix-prazo {
  font-size: .72rem; color: var(--text-faint); flex: none;
  padding: .1rem .35rem; border: 1px solid var(--border);
  border-radius: var(--r-xs);
}
.perigo { color: var(--erro, #e5484d) !important; }

/* O laco da selecao: arrastar no vazio marca o que ele toca. */
.cad-laco {
  position: fixed; z-index: 65; pointer-events: none;
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 3px;
}
/* Bloco marcado. O fundo cobre o bloco inteiro, e nao so o texto: e preciso
   ver de relance QUANTOS estao no grupo antes de apertar Backspace. */
.cad-bloco.escolhido > .cad-corpo {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border-radius: var(--r-xs);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
}

/* O seletor de icone: abas em cima, busca, e a grade por assunto.
   Antes era uma grade solta com um botao "escolher imagem" embaixo, que
   misturava duas coisas diferentes - escolher um simbolo e subir um arquivo. */
.ico-topo {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; margin-bottom: .6rem;
}
.ico-abas { display: flex; gap: .15rem; }
.ico-aba {
  border: none; background: none; color: var(--text-dim);
  padding: .3rem .6rem; border-radius: var(--r-xs);
  font-size: .85rem; cursor: pointer;
}
.ico-aba:hover { color: var(--text); }
.ico-aba.active { background: var(--surface-2); color: var(--text); }

.ico-busca { display: flex; gap: .3rem; margin-bottom: .5rem; }
.ico-busca input { flex: 1; }

/* Altura fixa com rolagem: a grade cresce com o catalogo, e sem teto o modal
   passaria da tela e os ultimos assuntos ficariam fora. */
.ico-grade { max-height: 260px; overflow-y: auto; }
.ico-secao { margin-bottom: .5rem; }
.ico-secao h4 {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-faint); margin: .3rem .1rem;
}
/* `minmax(0, 1fr)`, e nao `1fr`.
   O `1fr` puro nunca encolhe abaixo do conteudo (`min-width: auto` e o
   padrao), entao oito botoes de emoji somavam 481px numa caixa de 386 e a
   grade rolava de LADO - a pior rolagem possivel numa grade de escolha, onde
   metade das opcoes fica escondida sem nada indicar. Com `minmax(0, ...)` as
   colunas cedem e tudo cabe na largura. */
.ico-itens {
  display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: .25rem;
}
@media (max-width: 480px) {
  .ico-itens { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
.ico-opt {
  border: 1px solid transparent; background: none;
  border-radius: var(--r-xs); cursor: pointer;
  font-size: 1.2rem; line-height: 1;
  min-width: 0;   /* deixa a coluna encolher; ver `.ico-itens` */
  aspect-ratio: 1; display: grid; place-items: center;
}
.ico-opt:hover { background: var(--surface-2); }
/* O que ja esta em uso fica marcado: sem isso, quem abre para TROCAR nao sabe
   qual dos trinta e o atual. */
.ico-opt.ativo { border-color: var(--accent); background: var(--surface-2); }

/* A barra de assuntos do seletor de icone, embaixo da grade.
   Cada botao mostra o PRIMEIRO icone do grupo: um desenho diz o assunto mais
   rapido que um rotulo escrito em corpo 8. */
.ico-atalhos {
  display: flex; gap: .15rem; margin-top: .5rem;
  padding-top: .45rem; border-top: 1px solid var(--border);
}
.ico-atalho {
  flex: 1; min-width: 0;
  border: none; background: none; cursor: pointer;
  font-size: 1.05rem; line-height: 1;
  padding: .3rem 0; border-radius: var(--r-xs);
  opacity: .65;
}
.ico-atalho:hover { opacity: 1; background: var(--surface-2); }

/* O quadro do vídeo. `aspect-ratio` mantém o 16:9 sem JavaScript, e o vídeo
   acompanha a largura do texto em vez de ter um tamanho fixo que ficaria
   pequeno no monitor e cortado no celular. */
.cad-video {
  position: relative; margin: .5rem 0;
  aspect-ratio: 16 / 9; max-width: 100%;
  border-radius: var(--r-sm); overflow: hidden;
  background: #000;
}
.cad-video iframe { width: 100%; height: 100%; border: none; display: block; }

.cad-video-vazio {
  margin: .4rem 0; padding: .5rem;
  border: 1px dashed var(--border-strong); border-radius: var(--r-sm);
}
.cad-video-url { width: 100%; }

/* A REFERÊNCIA se distingue da subpágina pela seta e pelo caminho: as duas
   abrem a mesma página, mas uma diz "mora aqui" e a outra "veja também". Sem
   a marca, apagar uma pensando que era a outra apagaria a página. */
.cad-link-pagina.referencia { color: var(--text-dim); }
.cad-link-seta { color: var(--text-faint); font-size: .8rem; flex: none; }
.cad-link-onde {
  color: var(--text-faint); font-size: .72rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}

/* A lista de páginas do `/link`: nome em cima, caminho embaixo. O caminho é o
   que separa duas páginas de mesmo título. */
.lk-lista { max-height: 300px; overflow-y: auto; }
.lk-item {
  display: flex; align-items: center; gap: .45rem; width: 100%;
  border: none; background: none; cursor: pointer; text-align: left;
  padding: .4rem .45rem; border-radius: var(--r-xs);
  color: var(--text); font-size: .9rem;
}
.lk-item:hover { background: var(--surface-2); }
.lk-nome { flex: none; max-width: 55%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lk-onde {
  color: var(--text-faint); font-size: .78rem; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* A barra que aparece sobre o texto escolhido, e as gavetas dela.

   `position: fixed`: ela e posicionada pelo retangulo da SELECAO, que ja vem
   em coordenadas de janela. Com `absolute` seria preciso descontar a rolagem
   da pagina a cada abertura, e a barra escorregaria do trecho ao rolar. */
.cad-barra-texto {
  position: fixed; z-index: 60;
  display: flex; align-items: center; gap: .1rem;
  padding: .25rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
}
.cad-barra-texto button {
  min-width: 1.8rem; height: 1.8rem; padding: 0 .35rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer;
  color: var(--text); font-size: .85rem; line-height: 1;
  border-radius: var(--r-xs);
}
.cad-barra-texto button:hover { background: var(--surface-2, var(--border)); }
.cad-barra-sep {
  width: 1px; height: 1.1rem; margin: 0 .2rem;
  background: var(--border);
}

/* A bolinha do botao de cor: um degrade, porque ele abre as DUAS paletas
   (texto e fundo) e nenhuma cor sozinha representaria as duas. */
.cad-bolinha {
  width: .9rem; height: .9rem; border-radius: 50%;
  background: linear-gradient(135deg,
    var(--nota-vermelho-b), var(--nota-azul-b));
}

.cad-gaveta {
  position: fixed; z-index: 61;
  padding: .3rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
  display: flex; flex-direction: column; gap: .1rem;
  max-height: 60vh; overflow-y: auto;
}
.cad-gaveta button {
  padding: .3rem .6rem; text-align: left;
  background: none; border: 0; cursor: pointer;
  color: var(--text); font-size: .85rem; border-radius: var(--r-xs);
  white-space: nowrap;
}
.cad-gaveta button:hover { background: var(--surface-2, var(--border)); }

/* As cores em LISTA com previa, e nao em grade de bolinhas: a bolinha diz a
   cor mas nao diz como o texto vai ficar nela, e a de fundo e a de texto sao
   a mesma bolinha. Aqui cada linha mostra um "A" ja pintado (ou ja sobre o
   fundo) e diz por extenso o que faz - e o que o Notion faz. */
.cad-gaveta.cores { min-width: 12rem; gap: 0; }
.cad-gaveta.cores button {
  display: flex; align-items: center; gap: .55rem;
  padding: .3rem .45rem;
}
.cad-cor-amostra {
  width: 1.35rem; height: 1.35rem; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--border); border-radius: var(--r-xs);
  font-size: .82rem; font-weight: 600; line-height: 1;
}
/* O "Padrao" e o unico sem cor: um risco diagonal diz que ele TIRA a cor, em
   vez de parecer um botao branco que pinta de branco. */
.cad-cor-amostra.sem-cor {
  background: linear-gradient(135deg,
    transparent 44%, var(--text-faint) 44%, var(--text-faint) 56%,
    transparent 56%);
}
.cad-gaveta-titulo {
  padding: .35rem .45rem .2rem;
  font-size: .72rem; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .04em;
}
.cad-gaveta-titulo:not(:first-child) {
  margin-top: .2rem; border-top: 1px solid var(--border);
}

/* Os tamanhos em duas colunas: dez numeros empilhados dariam uma lista mais
   alta que a gaveta, e numero se compara melhor lado a lado. */
.cad-gaveta.tamanhos {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: .1rem;
}
.cad-gaveta.tamanhos button {
  text-align: center; padding: .3rem .4rem;
  /* A previa cresce ate 36: sem um teto de altura, a linha do "36" faria a
     gaveta pular de tamanho conforme a lista. */
  line-height: 1.1; max-height: 2.2rem; overflow: hidden;
}


/* Os interruptores de Sistema. Nome a esquerda, chave a direita, explicacao
   embaixo em uma linha - a mesma medida para todos, para a coluna nao ficar
   torta quando dois deles aparecem juntos. */
.cfg-chave-linha {
  display: flex; align-items: center; gap: .6rem;
  cursor: pointer; position: relative;
}
.cfg-chave-nome { flex: 1; min-width: 0; }
.cfg-chave-dica {
  margin: .25rem 0 0;
  /* Alinhada com o NOME, e nao com a borda da caixa: o olho segue a coluna
     do texto, e a dica pendurada mais a esquerda parecia de outro campo. */
  padding-right: 3.4rem;
}
.cfg-recado { margin: .2rem 0 .6rem; }

/* A caixa de marcar nativa vira uma chave deslizante: a nativa e desenhada
   pelo sistema, muda de tamanho entre Windows e Linux e nao aceita cor - dois
   deles na mesma tela ficavam de tamanhos diferentes. */
.cfg-switch {
  position: absolute; right: 0;
  width: 2.4rem; height: 1.35rem;
  margin: 0; opacity: 0; cursor: pointer;
  z-index: 1;
}
.cfg-switch-trilho {
  flex: none;
  width: 2.4rem; height: 1.35rem; border-radius: .7rem;
  background: var(--border);
  position: relative; transition: background .15s;
}
.cfg-switch-trilho::after {
  content: ''; position: absolute;
  top: 2px; left: 2px; width: 1.05rem; height: 1.05rem;
  border-radius: 50%; background: var(--surface);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .3);
  transition: transform .15s;
}
.cfg-switch:checked + .cfg-switch-trilho { background: var(--accent); }
.cfg-switch:checked + .cfg-switch-trilho::after { transform: translateX(1.05rem); }
/* O foco do teclado precisa aparecer: a caixa de verdade e invisivel, entao
   quem marca o contorno e o trilho. */
.cfg-switch:focus-visible + .cfg-switch-trilho {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* Arrastar BLOCOS ate uma pagina - na arvore ou na trilha - marca o destino
   com a mesma moldura do arrasto de pagina: a promessa e a mesma, o que for
   solto vai para dentro dela. */
.cad-trilha-item.alvo-dentro {
  outline: 2px solid var(--accent); outline-offset: 1px;
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: #fff;
}

/* Um item de configuracao que nao pode ser marcado agora: o limite de abas
   promovidas ja foi atingido. Apagado, e nao escondido - some-lo faria a
   lista mudar de tamanho a cada clique. */
.src-item.src-cheio {
  opacity: .45;
  cursor: not-allowed;
}

/* Aviso de que o Caderno rende mais no computador. So aparece no celular,
   e uma vez so: a margem de baixo o separa da area de escrita, que comeca
   logo abaixo. */
.cad-aviso-celular { margin-bottom: .75rem; }

/* ------------------------------------------- modelos da tela inicial

   Um slot por modelo: nome a esquerda, acoes a direita. Os slots vazios
   ficam visiveis, e nao escondidos: e assim que se ve que ha tres, e nao
   apenas os que ja foram usados. */
.modelo-slot {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
  padding: .7rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.modelo-slot + .modelo-slot { margin-top: .5rem; }
.modelo-slot:not(.cheio) { border-style: dashed; }
.modelo-info {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  flex: 1;
  min-width: 8rem;
}
.modelo-acoes {
  display: flex;
  align-items: center;
  gap: .35rem;
  flex-wrap: wrap;
}
.modelo-nome {
  width: 100%;
  font: inherit;
  font-weight: 600;
  padding: .25rem .4rem;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
}


/* Editar e remover na linha da tarefa. A altura vinha inline do app.js e
   ganhava de qualquer folha de estilo -- virou classe para o toque poder
   crescer no celular (ver o bloco de alvos de toque no fim do arquivo). */
.acao-linha { padding: .2rem .5rem; min-height: 32px; }

/* ---------------------------------------------------------------------------
   ALVOS DE TOQUE

   Fica no FIM do arquivo de propósito. A regra vivia lá em cima, perto dos
   estilos de formulário, e de lá não valia nada: `.mood-opt` (26px),
   `.cal-day` (min-height: 0), `.icon-btn` (28px) e `.cor-troca` (11px) vêm
   centenas de linhas depois e reescreviam a altura. Medido em 360px, 44 de
   47 alvos da aba Tarefas ficavam abaixo do mínimo.

   Onde o desenho não comporta um quadrado de 44px -- o dia do calendário
   numa grade de sete colunas, a bolinha de trocar a cor -- a área cresce por
   pseudo-elemento, que aumenta o que o dedo acerta sem mexer no que o olho
   vê. O `content: ''` com position absoluta não ocupa espaço no fluxo.
   --------------------------------------------------------------------------- */
@media (pointer: coarse) {
  button, .btn, input, select, textarea, [role="button"] { min-height: 44px; }

  /* Os que traziam altura menor escrita à mão. */
  .mood-opt, .icon-btn, .orc-btn, .sub-add, .subtab, .cad-pe-btn,
  .cad-linha-btn, .cal-day { min-height: 44px; }
  .icon-btn, .cad-pe-btn, .cad-linha-btn { min-width: 44px; }

  /* O HUMOR fica de fora do `min-width`. Sao SETE emoji numa fileira que,
     espremida ao lado do rotulo, mede 139px: sete vezes 44 pedem 308, entao
     eles quebravam em 3+3+1 e o card inflava de 85 para 209px -- arrastando
     o card de Sono junto, porque os dois dividem a linha da grade.

     A largura fica com o que couber (`min-width: 0`, como era), e o alvo
     cresce em ALTURA, que e a dimensao em que sobra espaco. Numa fileira
     horizontal encostada, altura de 44px ja evita o toque errado: o dedo
     erra para cima e para baixo, e os vizinhos laterais sao emoji do mesmo
     controle, nao acoes diferentes. */
  .mood-opt { min-width: 0; }


  /* O AVATAR continua redondo.

     Ele e um `button` no cabecalho, e a regra de 44px acima o esticava para
     32x44: um circulo com altura maior que a largura vira um ovo. O desenho
     volta ao quadrado (`min-height: 0`) e o alvo cresce por pseudo-elemento,
     como nas caixas de marcar logo abaixo -- o dedo continua acertando 44px
     sem que o olho veja um avatar deformado.

     `.avatar-login` fica de fora: la ele ja tem 52px, maior que o minimo. */
  .avatar { min-height: 0; position: relative; }
  .avatar::before {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }
  /* O `::after` do avatar ja desenha a medalha da competicao; o alvo usa o
     `::before` para nao disputar com ela. */

  /* Caixa de marcar: o quadrado continua pequeno, a área de toque não. */
  input[type="checkbox"], input[type="radio"] {
    min-height: 0;
    position: relative;
  }
  input[type="checkbox"]::after, input[type="radio"]::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }

  /* Grade de sete colunas: 44px de largura não cabe em 360px, então cresce
     só o que dá, e a altura vai ao mínimo inteiro. */
  .cal-day { position: relative; }
  .cal-day::after {
    content: '';
    position: absolute;
    top: 50%; left: 0; right: 0;
    height: 44px;
    transform: translateY(-50%);
  }

  /* Bolinha de 11px: o alvo cresce por baixo, o ponto colorido fica. */
  .cor-troca { position: relative; }
  .cor-troca::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }

  /* Botão fantasma solto (editar, remover numa linha de lista): não tinha
     altura mínima nenhuma e ficava em 31x32. */
  .btn-ghost { min-height: 44px; }

  /* Ícone de largura fixa: 34px no cabeçalho, 28px na barra do Início.
     Cinco deles somam 145px de uma tela de 360 -- a 44px cada seriam 220 e
     o título não caberia. A área cresce por baixo, sobrepondo a margem entre
     eles, que é espaço morto de qualquer forma. */
  .icon-only, .sub-add, .icon-btn { position: relative; }
  .icon-only::after, .sub-add::after, .icon-btn::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }

  /* A aba parava em 38px de `min-height` e desenhava 40 com o padding. É o
     controle mais usado do celular: quem erra a aba troca de tela inteira. */
  .tab { min-height: 44px; }

  /* Sobraram os que não têm altura escrita e vivem de padding: o botão
     pequeno de uma linha de lista, o campo de hora da tarefa, o nome do
     ativo. O seletor precisa ser mais específico que a regra de componente
     que os desenha, daí o `button.` e o `input.` na frente. */
  button.btn-ghost.small, button.btn-ghost, button.ativo-nome,
  input.t-input, .acao-linha { min-height: 44px; }

  /* A manchete de Noticias e um link de duas linhas que parava em 42px --
     dois pixels do minimo, e e o alvo que a pessoa mais toca na aba.
     `inline-flex` porque `min-height` nao vale em elemento `inline`: a regra
     estava la e nao fazia nada. `align-items: center` mantem o texto no meio
     quando a linha unica ocupa menos que os 44. */
  .list a, ul a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Campos compostos de data e hora: cada pedaço é um input estreito. A
     largura fica (dd não precisa de 44px), a altura sobe. */
  .date-field input, .time-field input { min-height: 44px; }

  /* Escolher a cor do compromisso e o dia da semana na Dieta: quadradinhos
     numa fileira. `.daypick-btn.has-dot` já usa `::after` para o pontinho,
     então aqui a área cresce pelo `::before`, que está livre. */
  .ev-color, .daypick-btn { position: relative; }
  .ev-color::before, .daypick-btn::before {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* ---------------------------------------------------------------------------
   O TOPO DE FINANCAS

   Eram cinco cartoes identicos: mesma moldura, mesmo peso, sem hierarquia.
   Cinco caixas iguais nao dizem o que importa mais, e e o que faz a tela
   parecer montada por gerador.

   Agora o saldo fica SOLTO sobre o fundo, no corpo grande, e o resto vira
   uma linha de apoio. Quatro molduras a menos.
   --------------------------------------------------------------------------- */
.fin-topo { margin-bottom: 1.2rem; }

/* O saldo divide a linha com "Como usar" e "Organizar". Os botoes ficam no
   ALTO dessa linha, na altura do rotulo, e nao centrados ao lado de um
   numero de 2.6rem -- ali eles pareceriam parte do valor. */
.fin-cabeca { align-items: flex-start; margin-bottom: .6rem; }
.fin-cabeca > .subtabs-acoes { flex: none; }
/* No celular os dois nao dividem a linha: ao lado de "SALDO DO MES" eles
   encostavam no rotulo, e a leitura do numero ficava espremida entre um
   texto de um lado e dois botoes do outro. Empilhados, o saldo fica com a
   largura inteira, que e o que ele merece na primeira dobra. */
@media (max-width: 560px) {
  .fin-cabeca { flex-wrap: wrap; }
  .fin-cabeca > .fin-saldo { flex: 1 0 100%; order: 1; }
  .fin-cabeca > .subtabs-acoes { order: 0; margin-left: auto; }
}

.fin-saldo { min-width: 0; }
.fin-saldo-val {
  font-size: 2.6rem;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin-top: .1rem;
}
.fin-saldo-nota {
  font-size: .82rem;
  color: var(--text-faint);
  margin-top: .2rem;
}

/* A linha de apoio: os outros indicadores, separados por espaco em vez de
   moldura. `flex-wrap` porque o numero deles varia com o que esta ligado em
   Organizar, e numa tela estreita eles quebram sozinhos. */
/* A linha de valores divide a linha das SUBABAS, a direita delas.

   O que separa as duas e a COR, e nao um traco: os rotulos aqui puxam para
   o acento do perfil, e as subabas ficam no cinza de sempre. Uma barra
   vertical entre eles era mais um risco na tela para dizer o que a cor diz
   sozinha.

   O texto ENCOLHE antes de esconder qualquer coisa -- o espaco entre os
   itens primeiro, depois o corpo da fonte. Passando do piso, a linha ROLA
   SOZINHA, como um painel de bolsa: e o unico jeito de caber "R$ 1.234.567"
   em quatro valores sem cortar nenhum. */
.fin-apoio {
  display: flex;
  flex-wrap: nowrap;
  gap: .3rem clamp(.55rem, 1.6vw, 2rem);
  min-width: 0;
  /* O tamanho acompanha a largura da janela, com piso e teto: em 1920px
     fica no corpo normal, e apertando ele desce ate .78rem, que ainda se
     le sem esforco. */
  font-size: clamp(.78rem, .62vw + .34rem, .9rem);
  padding-left: clamp(.55rem, 1.6vw, 1.4rem);
  overflow: hidden;
}
/* O ROTULO puxa para o acento do perfil. E o que diz, sem traco nenhum,
   que estes textos sao outra coisa que as subabas ao lado. Levemente: o
   acento cheio competiria com a subaba ativa, que usa a mesma cor para
   dizer onde a pessoa esta. */
.fin-apoio-rot { color: color-mix(in srgb, var(--accent-text) 45%, var(--text-dim)); }

/* As SUBABAS nao encolhem: elas sao a navegacao da aba, e "Metas" cortado
   pela metade e pior que um valor fora da vista -- o valor se alcanca
   rolando a linha, a subaba cortada a pessoa pode nem reconhecer. */
.fin-subabas > .subtabs { flex: none; }
/* A `.subtabs-linha` traz `flex-wrap: wrap`, e era ELE que empurrava a
   linha de valores para baixo -- nao a largura dela. Aqui ela nao quebra:
   quem cede e a linha de valores, encolhendo o texto. */
.fin-subabas { flex-wrap: nowrap; }
.fin-subabas > .fin-apoio { flex: 0 1 auto; min-width: 0; }

/* Em tela ESTREITA a linha desce, e ai sim ocupa a largura inteira.
   Espremida ao lado das subabas ela sobrava so um terco da tela, e dois dos
   quatro valores ficavam sempre fora da vista. */
@media (max-width: 1180px) {
  .fin-subabas { flex-wrap: wrap; }
  .fin-subabas > .fin-apoio { flex: 1 0 100%; }
}

/* A fita e a linha de itens: um flex que nao quebra.
   Ela existe como elemento proprio porque o `overflow: hidden` da linha
   precisa de algo por dentro para recortar -- e e o que segura os quatro
   valores lado a lado quando o espaco aperta. */
.fin-apoio-fita {
  display: flex;
  flex-wrap: nowrap;
  gap: inherit;
  min-width: max-content;
}

/* A segunda copia da lista serve so a fita que ANDA, no celular. No
   computador a linha cabe inteira e parada, e repetir os valores ali seria
   dizer duas vezes a mesma coisa. */
.fin-apoio-copia { display: none; }

.fin-apoio-item {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  /* HERDA o tamanho da linha, que encolhe com a janela: com `.9rem` fixo
     aqui, o `clamp` do pai nao valia de nada e os valores voltavam a nao
     caber. */
  font-size: inherit;
  /* Cada item tem a largura do seu conteudo: sem isto o flex os espremeria
     na horizontal e "R$ 33.501,38" sairia quebrado no meio. */
  flex: none;
  white-space: nowrap;
}
.fin-apoio-val {
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
/* A nota acompanha o valor que ela explica: em `em`, ela encolhe junto com
   a linha em vez de ficar do mesmo tamanho do numero numa tela apertada. */
.fin-apoio-nota { color: var(--text-faint); font-size: .92em; }

@media (max-width: 560px) {
  .fin-saldo-val { font-size: 2rem; }
  /* Empilhado, com o rotulo em cima: lado a lado em 360px os quatro itens
     quebravam no meio do numero. */
  .fin-apoio { gap: .5rem 1.2rem; }
}

/* O SELETOR DE MES deixa de ser um card de largura inteira.
   Ele era uma faixa de 1280px so para dizer "agosto de 2026" com duas setas
   -- mais peso visual que os valores em dinheiro logo acima. Agora e um
   controle do tamanho do proprio texto, na mesma linha do botao de lancar. */
.fin-mes {
  display: inline-flex;
  align-items: center;
  gap: .2rem;
  padding: .2rem .3rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
}
/* O mes e o botao juntos cabem DENTRO da menor barra de subabas.
   
   Medido: as subabas variam de 361px (Resumo, Metas) a 447 (Patrimonio,
   que abre secoes). O conjunto media 419 -- maior que duas delas e menor
   que a outra, e essa quase-igualdade e o que incomodava: duas bordas a
   57px uma da outra parecem erro, enquanto uma diferenca clara parece
   escolha.
   
   O alvo e caber abaixo de 361 com folga, e o botao segue ESTATICO: amarra-
   lo a barra o faria mudar de tamanho a cada subaba clicada.
   
   O nome do mes larga 7rem em vez de 9.5. Ele so precisa de largura fixa
   para as setas nao dancarem ao trocar de mes, e 7rem ainda segura
   "setembro de 2026". */
.fin-mes .fin-mes-nome {
  min-width: 6.2rem;
  text-align: center;
  font-weight: 600;
  font-size: .85rem;
}
.fin-acoes {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
  margin-bottom: .9rem;
}

/* A escala de temperatura, em Configuracoes -> Perfil -> Cor. Sete quadrados
   na ordem frio -> neutro -> quente, cada um pintado com o proprio valor:
   a amostra E a escolha, sem precisar de rotulo em cada uma. */
.temp-escala { display: flex; }
.temp-opt {
  flex: 1;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  cursor: pointer;
  padding: 0;
}
.temp-opt[data-temp="frio-forte"]   { background: #0b0d10; }
.temp-opt[data-temp="frio-medio"]   { background: #0c0d0f; }
.temp-opt[data-temp="frio-leve"]    { background: #0d0d0e; }
.temp-opt[data-temp="neutro"]       { background: #0e0e0e; }
.temp-opt[data-temp="quente-leve"]  { background: #0e0d0d; }
.temp-opt[data-temp="quente-medio"] { background: #0f0d0c; }
.temp-opt[data-temp="quente-forte"] { background: #100d0b; }

/* No tema claro a amostra tem de ser a do tema claro: os tons escuros ali
   seriam sete quadrados pretos indistinguiveis. */
:root[data-theme="light"] .temp-opt[data-temp="frio-forte"]   { background: #e3e6eb; }
:root[data-theme="light"] .temp-opt[data-temp="frio-medio"]   { background: #e5e6ea; }
:root[data-theme="light"] .temp-opt[data-temp="frio-leve"]    { background: #e6e7e8; }
:root[data-theme="light"] .temp-opt[data-temp="neutro"]       { background: #e7e7e7; }
:root[data-theme="light"] .temp-opt[data-temp="quente-leve"]  { background: #e8e7e6; }
:root[data-theme="light"] .temp-opt[data-temp="quente-medio"] { background: #eae6e5; }
:root[data-theme="light"] .temp-opt[data-temp="quente-forte"] { background: #ebe6e3; }

.temp-opt:hover { border-color: var(--text-faint); }
.temp-opt.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
}

/* Os dois botoes do painel visitado ("Recado" e "Voltar") dividem a largura
   que sobra ao lado do avatar. `min-width: 0` autoriza o encolhimento -- sem
   ele o flex respeita a largura do texto e o segundo botao vaza do card. */
.visita-acoes { min-width: 0; flex-shrink: 1; }
.visita-acoes .btn,
.visita-acoes .btn-primary {
  min-width: 0;
  padding-inline: .55rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A linha de acoes de uma aba ("Como usar", "Organizar"), sem rotulo a
   esquerda. O nome da aba saiu: a barra de cima ja mostra qual esta ativa, e
   repeti-lo gastava uma linha inteira sem informar nada.

   `flex-end` no lugar de `row-between` porque sobrou um filho so -- com
   `space-between` ele iria para a esquerda. */
.row-fim {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .6rem;
}
/* Margem menor que a do `row-between` que estava aqui: sem o rotulo, o
   conteudo pode encostar mais no cabecalho. */
.acoes-da-aba { margin-bottom: .3rem; }

/* Os filtros de uma busca salva, um por etiqueta, numa LINHA SO.
   Quebrando, a quarta etiqueta descia e esticava o card: numa grade, um
   card mais alto que os vizinhos desalinha a fileira inteira, e a busca com
   mais filtros passava a ocupar o dobro do espaco das outras.

   O que nao cabe vira "+N" (ver `chipsDaBusca`), e nao um corte na borda:
   meia palavra -- "Junio", "7 dia" -- le como erro de desenho, e nao como
   "tem mais". Sem corte, tambem nao ha mascara de esmaecido nem rolagem
   escondida. */
.busca-chips {
  display: flex;
  flex-wrap: nowrap;
  gap: .25rem;
  margin-top: .3rem;
  min-width: 0;
}
/* A etiqueta encolhe se faltar espaco, com reticencias no fim. Assim o
   "+N" nunca e empurrado para fora, que era o que fazia o contador sumir
   justamente nos cards que mais precisavam dele.

   As reticencias vao no SPAN de dentro, e nao no chip: `.chip` e
   `inline-flex`, e `text-overflow` nao vale em container flex -- a palavra
   era cortada em seco na borda, que e o que parecia defeito. */
.busca-chips .chip {
  font-size: .72rem;
  /* Cada etiqueta tem o tamanho do seu texto; quem cede espaco e so a
     PRIMEIRA, que carrega as palavras da busca e e sempre a mais longa.
     Deixando todas encolherem por igual, "Junior" virava "Jun..." junto com
     ela -- tres etiquetas ilegiveis em vez de uma abreviada. */
  flex: none;
  overflow: hidden;
}
.busca-chips .chip:first-child { flex: 0 1 auto; min-width: 4rem; }
.busca-chips .chip > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chip-mais {
  flex: none;
  color: var(--text-dim);
  cursor: default;
}

/* O topo de Vagas: "Nova busca", "Atualizar" e o ajuste do LinkedIn numa
   linha so, sem card em volta -- como o "+ Novo evento" da Agenda. */
.vagas-topo {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .4rem;
  margin-bottom: .75rem;
}
.vagas-nova {
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: .5rem .9rem;
  font-weight: 600;
  min-height: 36px;
}
/* O ajuste do LinkedIn vai para a direita: ele e configuracao, e nao a
   acao principal da tela. Abre em janela propria (`abrirAjusteLinkedin`);
   como painel que se desdobrava aqui, ele empurrava os botoes vizinhos. */
.vagas-li { margin-left: auto; }
/* O ponto de aviso quando a conexao expirou: um circulo, sem texto, para
   nao alongar o botao. O motivo fica no `title`. */
.ponto-aviso {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--warn);
  display: inline-block;
  margin-left: .1rem;
}

/* A opcao do LinkedIn numa linha so: a caixa e o botao. */
.li-linha {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .3rem .8rem;
  margin-top: .1rem;
}
.li-linha > .src-item { flex: none; }
.li-linha > button { margin-left: auto; }

/* O TEXTO da primeira e da ultima aba encosta na margem do conteudo.
   `.tab` tem .7rem de padding lateral: a caixa da aba ja coincide com a
   coluna, mas o texto dentro dela comeca 11px depois -- o "Inicio" nascia
   recuado em relacao a borda dos cards, e a ultima aba terminava antes da
   direita.

   O padding sai so nas PONTAS. Ele NAO volta como margem: o espacamento
   entre as abas e do `gap` da barra, e devolver .7rem aqui somava a ele --
   o vao antes de "Inicio" e depois de "Produto" saia 11px maior que os do
   meio, que e o espaco sobrando ao lado da ultima aba.
   A area de clique perde 11px numa borda, o que e aceitavel: e a borda da
   janela, onde nao ha o que clicar por engano.

   Tirar o padding, porem, nao bastava: quem passou a encostar na coluna foi
   o ICONE, e o texto continuou 22px adentro (os 14px do icone mais o `gap`
   de .4rem que o separa da palavra). Medido, `difIcone` dava 0 e `difTexto`
   dava 22 em toda largura -- e e o TEXTO que o olho usa para julgar o
   alinhamento, porque o icone e leve e cinza ao lado da borda do card.

   Na ULTIMA aba o problema nao existe: la o texto e o ultimo elemento, e
   tirar o padding ja o encosta na coluna (`ultimaTxtDir` medido em 0). E a
   ordem dentro da aba que desequilibra as duas pontas.

   Para o texto cair na coluna, os 22px do icone tem de ir para FORA dela --
   e a margem da pagina nem sempre os tem: medida, ela da 19px ate 1200 de
   janela (a barra e a coluna partilham o mesmo `padding: 1.2rem`) e so abre
   depois disso -- 59px a 1400, 319 a 1920.

   Entao a regra vale onde ha espaco. Ate 1200 fica o icone encostado na
   coluna, que e o que cabe: a `.ico` e cinza e leve, e serve de margem
   optica entre a borda e a palavra. Tentar mesmo assim poe o icone em -3px,
   cortado ao meio na borda da barra. */
nav.tabs > .tab:first-child { padding-left: 0; }
nav.tabs > .tab:last-child { padding-right: 0; }

/* As buscas salvas numa FILEIRA que rola, e nao uma por linha nem uma
   grade que quebra.
   Cada busca e um nome curto e tres ou quatro etiquetas -- numa linha de
   1300px sobravam dois tercos vazios, e comparar duas exigia percorrer a
   tela inteira.

   Em grade, a quarta busca descia para uma segunda fileira e abria uma
   faixa com tres buracos ao lado dela; com oito buscas eram tres fileiras
   empurrando a lista de vagas -- que e o assunto da tela -- para fora da
   primeira dobra. Na fileira que rola, as buscas ficam sempre na mesma
   altura e a lista comeca logo abaixo, tenha a pessoa duas buscas ou oito.

   Como a barra de abas: `mask-image` avisa que ha mais a direita, e a
   barra de rolagem some porque o esmaecido ja diz o que ela diria. */
.buscas-grade {
  display: flex;
  gap: .6rem;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: .1rem;
}
.buscas-grade::-webkit-scrollbar { display: none; }
/* O esmaecido da ponta direita, e so quando ha busca fora da vista: com
   duas ou tres a fileira nao rola, e apagar a ponta de um cartao inteiro
   sem motivo pareceria defeito. `data-rola` e ligado pelo JS ao medir. */
.buscas-grade[data-rola="1"] {
  mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent);
}
.buscas-grade .search-card {
  margin: 0;
  /* Largura fixa: sem ela, `flex` espremeria oito cards na tela em vez de
     deixar os que nao cabem para a rolagem. */
  flex: 0 0 clamp(17rem, 26vw, 22rem);
  /* Cada card com a SUA altura. Numa fileira flex os itens esticam ate a
     altura do mais alto, entao abrir os filtros de uma busca deixava as
     vizinhas com um vao vazio do tamanho do formulario. */
  align-self: flex-start;
}
/* A busca ABERTA e uma JANELA sobre a tela, e nao um painel que se
   desdobra dentro da fileira.

   Desdobrada ali, a fileira -- uma linha de cartoes de 85px -- passava a
   ter a altura do formulario, com as vizinhas ao lado de um vao vazio, e os
   campos ficavam espremidos na largura de um cartao. E a fileira tem
   `overflow-x: auto` para rolar, o que PRENDE qualquer filho `fixed` dentro
   dela: a janela so funciona fora. */
.busca-janela-fundo {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgb(0 0 0 / 55%);
  display: grid;
  place-items: center;
  padding: 1.2rem;
}
.busca-janela {
  width: min(34rem, 100%);
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
  box-shadow: 0 12px 40px rgb(0 0 0 / 45%);
}
/* O painel perde a moldura de "bloco que se abriu": dentro da janela ele
   E o conteudo, e a linha de cima so repetiria a borda do cartao. */
.busca-janela .fold-panel { border: 0; padding: 0; margin: 0; }
.busca-janela .fold-panel > hr:last-child { display: none; }

/* "Novo evento" fechado: um botao do tamanho do texto, nao uma faixa.
   Aberto sempre, o formulario tomava a primeira dobra e empurrava o
   calendario -- que e o motivo de abrir a Agenda -- para fora da tela.
   Fechado, o card perde fundo e borda: sobra so o gatilho, e o calendario
   sobe. Aberto, o card volta a existir em volta do formulario. */
.ev-novo {
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  width: fit-content;
}
.ev-novo[open] {
  background: var(--surface);
  border: 1px solid var(--border);
  width: auto;
}
.ev-novo-abre {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .9rem;
  cursor: pointer;
  font-size: .85rem;
  font-weight: 600;
  color: var(--text-dim);
  list-style: none;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  min-height: 36px;
}
/* O triangulo padrao do elemento details sai: o mais e o rotulo ja dizem
   que abre, e o marcador nativo tem desenho diferente em cada sistema. */
.ev-novo-abre::-webkit-details-marker { display: none; }
.ev-novo-abre::marker { content: ''; }
.ev-novo-abre:hover { color: var(--text); background: var(--surface-2); }
.ev-novo[open] .ev-novo-abre {
  display: flex;
  color: var(--text);
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: var(--r) var(--r) 0 0;
  margin-bottom: .2rem;
  padding: .7rem 1rem;
}
/* O conteudo do formulario ganha o padding que o card perdeu. */
.ev-novo > *:not(.ev-novo-abre) { margin-inline: 1rem; }
/* O botao tem o tamanho do texto: uma faixa azul de ponta a ponta e o
   que da ao formulario cara de gerado, e ele nao e a acao principal da
   Agenda -- ver o mes e. */
.ev-novo > .btn-primary { margin-bottom: 1rem; width: fit-content; }

/* ═══════════════════════════════════ navegacao do celular (barra inferior) */

/* O corte e 860px, o mesmo que o resto do arquivo ja usa para "isto e uma
   tela estreita". Nao e `pointer: coarse`: um notebook com tela sensivel
   continua sendo um PC com a barra de cima funcionando, e uma janela
   estreita no monitor precisa da barra de baixo tanto quanto um telefone.

   Por padrao a barra nao existe. Ela nasce dentro do @media, e assim o
   desktop segue exatamente como estava. */
.bottomnav { display: none; }
.folha-veu { display: none; }

@media (max-width: 859px) {

  /* -- o cabecalho encolhe ---------------------------------------------- */

  /* As abas saem do topo: quem navega agora e a barra de baixo, e manter as
     duas seria navegacao em dois lugares ao mesmo tempo. O cabecalho fica,
     fino, com avatar, saudacao e a busca -- ela atravessa as abas e nao
     pertence a nenhuma, entao seguir no topo e onde ela ja era procurada. */
  header.topbar nav.tabs { display: none; }

  /* Os quatro icones que viraram itens da folha somem do cabecalho. Sair,
     Tema, Configuracoes e Acesso remoto sao destinos secundarios, e o
     lugar deles e dentro do "Mais". */
  header.topbar #btnRoute,
  header.topbar #btnTheme,
  header.topbar #btnMenu,
  header.topbar #btnLogout { display: none; }

  header.topbar .topbar-inner { padding: .5rem .9rem; }

  /* O conteudo termina ACIMA da barra, senao o ultimo card fica embaixo
     dela para sempre -- nao ha como rolar alem do fim da pagina.
     3.5rem e a altura da barra; o `env()` cobre o risco do iPhone. */
  main.wrap {
    padding-bottom: calc(3.5rem + 1rem + env(safe-area-inset-bottom, 0px));
  }

  /* -- a barra ----------------------------------------------------------- */

  .bottomnav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* Acima do conteudo e das notas fixadas (25), abaixo dos modais (50):
       uma janela de confirmacao precisa cobrir a barra, senao o botao de
       navegar continua clicavel por cima do dialogo. */
    z-index: 30;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: blur(12px);
    /* A borda de 1px separando do conteudo. A sombra vai junto e para
       CIMA, porque a barra esta na base: sem ela, um card claro rolando
       por tras encostava na barra clara e as duas viravam uma coisa so. */
    border-top: 1px solid var(--border);
    box-shadow: 0 -1px 8px rgb(0 0 0 / 4%);
    /* O respiro acima do risco do iPhone. Sem ele o rotulo "Inicio" cai
       debaixo do indicador de inicio, e o toque vira gesto do sistema. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  .bottomnav-item {
    /* Os cinco slots repartem a largura em partes iguais: cada alvo fica
       com ~20% da tela, muito acima dos 44px que um polegar acerta, e a
       posicao de cada item nao muda quando o rotulo e mais comprido. */
    flex: 1 1 0;
    min-width: 0;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .15rem;
    /* 44px de altura minima, o piso de area de toque. Com o padding a
       barra fica em ~56px, que e onde o dedo nao erra e a tela nao perde
       conteudo demais. */
    min-height: 44px;
    padding: .45rem .2rem .5rem;
    border: 0;
    background: transparent;
    color: var(--text-dim);
    font-size: .65rem;
    font-weight: 500;
    letter-spacing: .01em;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    /* A cor troca em 160ms em vez de piscar. E so a cor: animar tamanho
       ou posicao aqui faria a barra tremer a cada toque. */
    transition: color .16s ease;
  }

  /* O icone nao herda a opacidade de .7 das abas do topo: aqui o inativo
     ja e --text-dim, e escurecer duas vezes derrubava o contraste abaixo
     do minimo legivel no tema claro. */
  .bottomnav-item .ico { opacity: 1; }

  .bottomnav-rotulo {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* O estado ativo diz o mesmo TRES vezes: cor de destaque, peso do texto
     e o tracinho em cima. Cor sozinha nao serve para quem nao a distingue,
     e o tracinho repete no rodape a marca que o topo ja usava. */
  .bottomnav-item.active {
    color: var(--accent-text);
    font-weight: 600;
  }
  .bottomnav-item.active .ico { color: var(--accent-text); }
  .bottomnav-item.active::before {
    content: "";
    position: absolute;
    top: 0;
    width: 1.6rem;
    height: 2px;
    border-radius: 0 0 2px 2px;
    background: var(--accent-text);
  }

  /* O feedback do toque: o fundo acende enquanto o dedo esta em cima e
     apaga ao soltar. `:active` e nao `:hover` -- no toque o hover gruda e
     o item ficaria aceso depois de solto. */
  .bottomnav-item:hover { background: transparent; }
  .bottomnav-item:active { background: var(--surface-2); }

  .bottomnav-item:focus-visible {
    outline: 2px solid var(--accent-text);
    outline-offset: -3px;
  }

  /* -- a folha do "Mais" ------------------------------------------------- */

  .folha-veu {
    display: block;
    position: fixed;
    inset: 0;
    background: rgb(0 0 0 / 45%);
    /* Acima da barra, que ela cobre; abaixo dos modais que ela abre --
       tocar "Configuracoes" na folha abre uma janela que precisa vir por
       cima. */
    z-index: 40;
    animation: folha-veu-entra .18s ease;
  }
  .folha-veu.hidden { display: none !important; }

  .folha {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    max-height: 82vh;
    overflow-y: auto;
    background: var(--surface);
    border-top: 1px solid var(--border);
    border-radius: var(--r) var(--r) 0 0;
    padding: .5rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
    animation: folha-sobe .2s ease;
  }

  /* A alcinha cinza no topo: e o que diz "isto subiu de baixo e desce de
     novo", sem precisar de um botao escrito "fechar". */
  .folha-alca {
    width: 2.2rem;
    height: 4px;
    margin: .3rem auto .8rem;
    border-radius: var(--r-pill);
    background: var(--border);
  }

  .folha-titulo {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin: .9rem .2rem .5rem;
  }
  .folha-titulo:first-child { margin-top: .2rem; }

  /* As abas restantes em grade de tres colunas: uma lista de sete linhas
     empurraria as acoes para fora da vista, e a grade cabe tudo numa
     olhada so. */
  .folha-grade {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .4rem;
  }

  .folha-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    min-height: 4.2rem;
    padding: .6rem .3rem;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--text);
    font-size: .72rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  /* Mesmo motivo do `.folha-acao`: o hover global gruda depois do toque. */
  .folha-item:hover { background: var(--surface); }
  .folha-item:active { background: var(--surface-2); }
  .folha-item.active {
    border-color: var(--accent-text);
    color: var(--accent-text);
  }
  .folha-item .ico { opacity: .8; }
  .folha-item.active .ico { opacity: 1; color: var(--accent-text); }
  .folha-item span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* As acoes sao LINHAS, nao cartoes: elas nao sao destinos, e dar a elas
     a mesma forma das abas seria dizer que sao. */
  .folha-acao {
    display: flex;
    align-items: center;
    /* A regra global de `button` centra o conteudo, e centrada a linha
       vira um botao: o icone descola do texto e a lista perde a coluna
       que o olho segue de cima a baixo. */
    justify-content: flex-start;
    gap: .7rem;
    width: 100%;
    min-height: 44px;
    padding: .7rem .3rem;
    /* `border: 0` sozinho nao basta: a regra global desenha borda nos
       quatro lados, e o `border-bottom` abaixo tem de vir DEPOIS dela
       para o risco separador sobreviver. */
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    background: transparent;
    color: var(--text);
    font-size: .88rem;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .folha-acao:last-child { border-bottom: 0; }
  /* O hover global pinta o fundo de qualquer `button`, e num telefone ele
     GRUDA depois do toque: a ultima linha tocada ficava acesa. Aqui o
     realce e so do `:active`, enquanto o dedo esta em cima. */
  .folha-acao:hover { background: transparent; }
  .folha-acao:active { background: var(--surface-2); }
  .folha-acao .ico { opacity: .7; flex: none; }

  /* Mesma historia da gaveta: subindo de baixo, os itens viajam junto e
     quem toca rapido acerta onde o botao VAI estar. Aqui ela nasce no
     lugar e so aparece, com um passo curto de 14px. */
  @keyframes folha-sobe {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  @keyframes folha-veu-entra {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
}

/* Quem pediu menos movimento no sistema recebe a folha sem o deslize. Ela
   continua aparecendo -- o que sai e a animacao, nao a funcao. */
@media (prefers-reduced-motion: reduce) {
  .folha, .folha-veu { animation: none; }
  .bottomnav-item { transition: none; }
}

/* -- ajustes do celular, medidos na tela ------------------------------- */

@media (max-width: 859px) {

  /* O painel dos modais era 420px numa janela de 390: com `place-items:
     center` o grid NAO encolhe o filho, entao o cartao passava da tela e
     ficava com as bordas cortadas dos dois lados -- medido em 430px de
     caixa numa janela de 390.

     `min()` em vez de `100%`: o `padding` do `.screen-center` nao entra na
     conta de `100%` num item de grid centrado, e o cartao voltava a
     encostar nas bordas. Descontar o padding dos dois lados (2.4rem) e o
     que deixa a margem aparecer.

     O `#login` tem regra propria de 460px, mais especifica, e por isso vem
     junto aqui -- senao a tela de entrada continuaria estourando. */
  .panel,
  #login .panel { max-width: min(420px, calc(100vw - 2.4rem)); }

  /* O respiro lateral do modal encolhe junto: 1.2rem de cada lado numa tela
     de 390 e um terco do que sobra para o cartao. */
  .screen-center { padding: 1rem .8rem; }

  /* Os 16 avatares em 8 colunas pedem 330px so de grade, e com o padding do
     cartao a fileira saia pela direita.

     QUATRO colunas, e nao seis: 16 dividido por 4 da quatro fileiras
     CHEIAS, e nenhuma linha fica pela metade. Com seis sairia 6+6+4, e a
     ultima, mais curta, ficava desalinhada das outras -- foi o que apareceu
     na tela. O numero de colunas tem de DIVIDIR o total, senao sobra
     sempre uma fileira torta.

     As celulas crescem para 40px, que sobra do espaco das duas colunas que
     sairam: alvo maior para o dedo, sem custo nenhum. */
  .emoji-picker {
    grid-template-columns: repeat(4, 40px);
    justify-content: center;
  }
  .emoji-opt { width: 40px; height: 40px; min-height: 40px; }

  /* As bolinhas de cor tem o MESMO problema, e a mesma causa: sao 10 (nove
     cores mais o neutro do tema), cabem 9 numa fileira de 390px, e a
     decima ficava sozinha embaixo -- foi o que apareceu na tela, nas cores
     e nos tons de texto.

     Grade de CINCO colunas: 10 divide por 5 e saem duas fileiras cheias,
     uma sobre a outra. `flex-wrap` nao resolveria: ele quebra por onde
     couber, e "onde couber" muda com a largura do aparelho. */
  .color-picker {
    display: grid;
    grid-template-columns: repeat(5, 28px);
    justify-content: center;
    gap: .5rem;
  }

  /* Configuracoes e o modal mais alto do Hub, e com a barra de baixo em
     cena ele terminava POR TRAS dela. A altura desconta a barra e o risco
     do iPhone. */
  .cfg-modal {
    max-height: calc(100vh - 3.5rem - 2rem - env(safe-area-inset-bottom, 0px));
  }

  /* As subabas QUEBRAM em vez de rolar.

     Medido em Tarefas: 473px de conteudo numa barra de 364. "Caderno" e
     "Bilhetes" ficavam fora da vista, e a rolagem lateral so as encontrava
     para quem descobrisse o gesto -- num lugar onde nada mais rola de lado.

     Em duas linhas elas aparecem todas de uma vez, e o custo e ~30px de
     altura. `width: auto` porque o `fit-content` do desktop, com a barra
     quebrada, encolhe a caixa ate a palavra mais larga. */
  .subtabs {
    flex-wrap: wrap;
    width: auto;
    overflow-x: visible;
    row-gap: .1rem;
  }

  /* Sem rolagem nao ha o que esmaecer, e a mascara das pontas apagaria a
     primeira e a ultima subaba de cada linha -- justamente as que a quebra
     acabou de trazer para a vista. */
  .subtabs.fade-esq,
  .subtabs.fade-dir,
  .subtabs.fade-esq.fade-dir {
    -webkit-mask-image: none;
    mask-image: none;
  }

  /* -- o botao de acao no meio da barra --------------------------------- */

  /* Ele NAO e uma aba: e a acao da tela em que a pessoa esta. Por isso sai
     da fileira de rotulos e vira um circulo cheio, com a cor da marca --
     um item de navegacao a mais no meio confundiria "ir para" com "criar". */
  .bottomnav-acao {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin: 0 .35rem;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--accent);
    color: #fff;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    box-shadow: 0 2px 8px rgb(0 0 0 / 18%);
    transition: transform .12s ease;
  }

  /* O `+` tambem nao herda o hover de `button`.

     Mesmo caso da alca: `button:hover` pinta `--surface-2` e tem
     especificidade maior, e no Android o hover gruda depois do toque. O
     botao que cria ficava cinza ate a pessoa tocar noutro lugar --
     medido, rgb(30,28,27) no lugar da cor do perfil. */
  .bottomnav-acao:hover { background: var(--accent); }
  .bottomnav-acao:hover { background: var(--accent); }
  /* Afunda um triz ao ser tocado. E o unico movimento da barra, e cabe
     aqui: o botao de acao e o que responde a um gesto, nao a uma escolha. */
  .bottomnav-acao:active { transform: scale(.92); }
  .bottomnav-acao .ico { opacity: 1; }
  .bottomnav-acao:focus-visible {
    outline: 2px solid var(--accent-text);
    outline-offset: 2px;
  }

  /* -- a linha "Abas da barra", dentro do Mais -------------------------- */

  /* Ela abre a escolha do que fica na barra de baixo. Fica separada da
     grade de abas por um titulo proprio: "quais abas EXISTEM" e coisa de
     Configuracoes, e "quais delas ficam na barra" e desta tela. */
  /* `.folha-escolher` virou `.escolha-lista`, em coluna: ver acima. */

  .escolha-item {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 44px;
    padding: .55rem .6rem;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--text);
    font-size: .8rem;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .escolha-item:hover { background: var(--surface); }
  .escolha-item:active { background: var(--surface-2); }
  .escolha-item span {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* -- o desenho da barra, ao vivo ------------------------------------ */

  /* "2o lugar" nao diz nada; o que a pessoa quer saber e como a barra vai
     ficar. Aqui ela ve, com a mesma divisao do rodape de verdade -- duas
     abas, o "+", duas abas. */
  .previa-barra {
    display: grid;
    grid-template-columns: 1fr 1fr auto 1fr 1fr;
    align-items: center;
    gap: .2rem;
    padding: .5rem .3rem;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
  }
  .previa-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .12rem;
    min-width: 0;
    font-size: .58rem;
    color: var(--text-dim);
  }
  .previa-item span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .previa-mais {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--r-pill);
    background: var(--accent);
    color: #fff;
  }

  /* -- as duas listas -------------------------------------------------- */

  /* Uma COLUNA, e nao a grade de duas que havia: arrastar para reordenar
     pede uma ordem de leitura sem ambiguidade, e numa grade "antes" e
     "depois" dependem de saber que ela se le em zigue-zague. */
  .escolha-lista {
    display: flex;
    flex-direction: column;
    gap: .3rem;
  }

  .escolha-punho {
    flex: none;
    color: var(--text-faint);
    font-size: 1rem;
    line-height: 1;
    cursor: grab;
  }

  /* A linha sendo arrastada: some do lugar sem sumir da lista, para as
     outras poderem passar por baixo dela. */
  .escolha-item.arrastando {
    opacity: .5;
    border-color: var(--accent-text);
    cursor: grabbing;
  }

  /* Sem isto o navegador entende o arrasto como rolagem e rouba o gesto no
     meio do caminho. */
  #escolhaNaBarra .escolha-item { touch-action: none; }

  /* Na barra: borda e texto no acento, e o numero do slot a direita. O
     numero importa porque a ordem da barra e a mesma da esquerda para a
     direita, e sem ele "trocar a 2a pela 4a" viraria tentativa e erro. */
  .escolha-item.na-barra {
    border-color: var(--accent-text);
    color: var(--accent-text);
  }
  .escolha-item.na-barra .ico { color: var(--accent-text); }
  .escolha-slot {
    flex: none;
    font-size: .68rem;
    font-weight: 600;
    opacity: .75;
  }
}

/* -- a barra simetrica, com o botao grande no meio -------------------- */

/* O "Mais" do cabecalho so existe no telefone: no PC as abas todas estao na
   barra de cima, entao nao ha o que a folha oferecesse. */
.so-no-cel { display: none; }

@media (max-width: 859px) {

  .so-no-cel { display: inline-flex; }
  .so-no-cel.hidden { display: none !important; }

  /* Tres colunas: duas abas | botao | duas abas. Os lados tem a MESMA
     largura (`1fr`), e e isso que poe o botao no centro exato da tela --
     com o "Mais" na ponta direita, como estava, o lado de la tinha uma
     coluna a mais e o "+" ficava sempre um pouco a esquerda. */
  .bottomnav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
  }

  .bottomnav-lado {
    display: flex;
    /* As duas abas de cada lado repartem a metade em partes iguais, e ficam
       no mesmo lugar independente do tamanho do rotulo. */
    justify-content: space-around;
    min-width: 0;
  }

  /* O botao de acao, agora GRANDE: 56px contra os 44 de antes. Ele e a
     acao principal da tela e o unico elemento colorido da barra -- no
     tamanho anterior competia de igual para igual com os icones de traco
     ao lado, e nao se lia como o centro de nada.

     Sobe 10px acima da barra e transborda: e o que o separa da fileira de
     abas e diz que ele nao e mais uma delas. A barra ganha `overflow:
     visible` para ele poder sair. */
  .bottomnav-acao {
    width: 56px;
    height: 56px;
    margin: 0 .5rem;
    transform: translateY(-10px);
    box-shadow: 0 4px 14px rgb(0 0 0 / 22%);
  }
  .bottomnav-acao:active { transform: translateY(-10px) scale(.93); }

  /* A barra deixa o botao transbordar por cima. */
  .bottomnav { overflow: visible; }

  /* A tela sem nada a criar mantem o botao no lugar -- some-lo faria as
     abas dancarem a cada troca de subaba --, mas apagado, e o toque diz por
     que. Cinza em vez de laranja: a cor da marca prometendo uma acao que
     nao existe e pior que um botao visivelmente inerte. */
  .bottomnav-acao.sem-acao {
    background: var(--surface-2);
    color: var(--text-faint);
    box-shadow: none;
  }
  .bottomnav-acao.sem-acao:hover { background: var(--surface-2); }

  /* Dentro do "Organizar" o botao vira o CONCLUIR. Verde, e nao laranja: o
     laranja e a cor de criar, e aqui ele encerra um modo. */
  .bottomnav-acao.concluindo { background: var(--ok, #16a34a); }
  .bottomnav-acao.concluindo:hover { background: var(--ok, #16a34a); }

  /* O conteudo termina acima da barra. O botao sobe 10px, entao a folga
     cresce junto: sem isto o ultimo card passava por baixo dele. */
  main.wrap {
    padding-bottom: calc(3.5rem + 1.6rem + env(safe-area-inset-bottom, 0px));
  }

  /* -- os botoes de criar somem da tela ------------------------------- */

  /* Eles viraram o "+" da barra. Ficam ESCONDIDOS, e nao removidos:
     `display: none` continua clicavel por script, e e assim que o botao da
     barra aciona o mesmo caminho de criacao que o desktop usa -- uma
     segunda implementacao por aba seria uma segunda para consertar depois.

     O Caderno (`#cadNovaRaiz`) fica de FORA da lista: ele mora no rodape da
     propria gaveta de paginas, junto das outras acoes dali, e escondendo-o
     a gaveta perderia a unica forma de criar a primeira pagina quando o
     Caderno nem esta aberto. */
  #habNovo,
  #kAddCol,
  #notaNova,
  #finNovo,
  #addTopicAbre,
  #addTerm,
  #mealNew,
  /* O "Organizar" da tela inicial e o "Concluir" que o substitui: os dois
     viraram o "+" da barra, que alterna entre eles. */
  #homeEdit,
  #homeDone { display: none !important; }

  /* Com os botoes fora, a faixa deles fica VAZIA -- e ela tem altura
     minima e margem, entao sobrava um vao entre o cabecalho e o primeiro
     card sem nada dentro. Fora do "Organizar" ela nao tem mais o que
     mostrar, e some.

     `:has()` em vez de esconder sempre: DENTRO do modo organizar a faixa
     ainda traz "Escolher o que aparece", "Modelos" e "Restaurar padrao",
     que nao tem outro lugar no celular. */
  .home-bar:not(:has(#homeConfig)) {
    display: none;
  }

  /* O formulario da Agenda vive na JANELA do "+", e some da tela. Ele
     continua no HTML porque e ele quem grava: a janela preenche os campos
     daqui e aciona o "Criar evento". Escondido com `position: absolute`
     fora da vista, e nao `display: none` -- campo nao pintado nao aceita
     valor em todo navegador, e a copia sairia vazia.

     `aria-hidden` porque ele nao e mais navegavel: quem le a tela por voz
     encontraria um formulario duplicado sem saber qual dos dois usar. */
  .ev-novo {
    position: absolute !important;
    left: -9999px !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
  }

  /* O campo de tarefa e o horario: mesma historia, mesma solucao. A janela
     escreve neles e clica no "Adicionar". */
  .tarefa-campos-cel {
    position: absolute !important;
    left: -9999px !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
  }

  /* -- a gaveta das subabas ------------------------------------------- */

  /* As subabas saem do topo do conteudo: em duas linhas elas cabiam, mas
     comiam 60px de altura em TODA tela, e altura e o que falta num
     telefone. Agora vivem na gaveta, e o cabecalho fica com uma coisa so. */
  .subtabs { display: none; }

  /* A EXCECAO sao os assuntos de Noticias.

     A regra acima manda as subabas para a gaveta, e a gaveta lista
     `SUBABAS[aba]` -- um catalogo fixo, com Saude, Tarefas e Financas.
     Noticias nao esta la, porque os assuntos nao sao subabas: sao dados do
     perfil, criados e apagados pela pessoa. O resultado e que eles sumiam da
     barra e nao apareciam na gaveta: no celular nao havia como trocar de
     assunto, nem chegar na engrenagem que edita cada um.

     Aqui eles voltam, na propria barra, rolando na horizontal. */
  .noticias-barra .subtab { flex: 0 0 auto; }
  /* A linha que sobrava com as subabas fora dela: sem as abas, `.subtabs-
     acoes` deixava uma faixa vazia com borda embaixo. */
  .subtabs-linha:empty,
  .subtabs-acoes:empty { display: none; }

  /* A MARGEM da barra escondida continuava contando.
     
     `display: none` tira a caixa, mas a `.subtabs-linha` que a envolve tem
     margem propria -- em Tarefas ela deixava 25px de folga contra os 13 das
     outras abas, um degrau visivel ao trocar de aba. `:has()` acha a linha
     que so tinha as subabas dentro e a apaga inteira. */
  .subtabs-linha:has(> .subtabs):not(:has(> :not(.subtabs):not(:empty))) {
    display: none;
  }

  /* -- o cabecalho de Financas ---------------------------------------- */

  /* "Como usar" e "Organizar" saem da linha nobre do topo.
     
     Eles ocupavam a primeira linha da aba inteira -- acima do saldo, que e
     o numero pelo qual a pessoa abriu Financas. "Como usar" e um tour que
     se ve uma vez; "Organizar" tem o "+" da barra em Inicio e nao pertence
     aqui. Some os dois, e o saldo sobe para o topo. */
  .fin-cabeca > .subtabs-acoes { display: none; }

  /* O seletor de mes encosta a ESQUERDA.
     
     Ele parecia centrado porque o "Novo lancamento" ao lado sumiu no
     celular (virou o "+"), e sem ele o `gap` do flex deixava o mes
     boiando. `justify-content` explicito prende a linha na margem, onde
     comeca todo o resto do conteudo -- e `margin` zerada no proprio mes,
     porque a regra de tela estreita o centrava com `margin: 0 auto`. */
  .fin-acoes {
    justify-content: flex-start;
    margin-bottom: .6rem;
  }
  /* O cartao do mes tinha a LARGURA DA TELA e centrava o conteudo por
     dentro: `.fin-acoes` vira coluna com `align-items: stretch` abaixo de
     560px, e `.fin-mes` ganhava `justify-content: center`. Era isso que
     fazia o mes parecer centrado, e nao margem nenhuma.
     
     Aquilo servia quando o "Novo lancamento" dividia a linha logo abaixo:
     os dois esticados ficavam alinhados. O botao virou o "+" da barra e a
     coluna ficou com um item so, entao o cartao volta a ter o tamanho do
     proprio texto, encostado na margem. */
  .fin-acoes {
    flex-direction: row;
    align-items: center;
  }
  .fin-acoes > .fin-mes {
    flex: 0 0 auto;
    justify-content: flex-start;
  }
  /* O nome largava 9.5rem de minimo para as setas nao dancarem ao trocar de
     mes. 6.5rem ainda segura "setembro de 2026", e economiza 48px. */
  .fin-mes .fin-mes-nome { min-width: 6.5rem; font-size: .85rem; }

  /* -- a bolinha do mini calendario -------------------------------------- */

  /* O ponto que marca "tem algo na agenda" ficava DEBAIXO do numero.
     
     Ele mora em `bottom: 2px`, e no computador a celula tem altura de
     sobra: o numero fica em cima, o ponto embaixo. No celular a grade
     aperta e a celula encolhe ate o numero -- os dois passam a disputar a
     mesma faixa de pixels, e o ponto sai por tras do algarismo.
     
     A celula ganha uma tira embaixo so para o ponto: `padding-bottom` abre
     o espaco, e o numero -- que e o conteudo -- fica acima dela. */
  .cal-day {
    padding-top: .2rem;
    padding-bottom: .95rem;
  }
  .cal-day.busy::after { bottom: 4px; width: 4px; height: 4px; }

  /* A linha Entrou/Saiu/Patrimonio ANDA SOZINHA, como um painel de cotacoes.
     
     Ela nao cabe em 390px -- sao quatro valores em dinheiro -- e antes o
     ultimo sumia pela borda. Rolar de lado resolvia, mas so para quem
     descobrisse o gesto; andando, os quatro passam pela vista sem pedir
     nada.
     
     A fita e DUPLICADA no HTML e a animacao corre metade da largura: ao
     terminar, a segunda copia esta exatamente onde a primeira comecou, e o
     salto de volta ao inicio nao se ve. E o jeito de fazer um ciclo
     infinito sem JavaScript medindo largura a cada quadro.
     
     `mask` nas duas pontas para os itens nascerem e sumirem esmaecidos, em
     vez de aparecerem cortados na borda. */
  .fin-apoio {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 1.2rem,
                          #000 calc(100% - 1.2rem), transparent);
    mask-image: linear-gradient(to right, transparent, #000 1.2rem,
                  #000 calc(100% - 1.2rem), transparent);
  }

  .fin-apoio-fita {
    /* 28s para a fita inteira: devagar o bastante para ler um numero de
       dinheiro sem correr atras dele com os olhos. */
    animation: fin-fita 28s linear infinite;
    will-change: transform;
  }

  /* A copia entra na fita como se fosse a continuacao da lista: mesma
     direcao, mesmo vao entre os itens. `gap: inherit` puxa o vao da
     `.fin-apoio`, que e quem o define. */
  /* A copia nao e uma caixa a parte: ela some como elemento (`display:
     contents`) e os itens dela entram na fita como se fossem irmaos dos
     primeiros. E o que faz o `gap` da fita valer igual entre as duas
     voltas -- com uma caixa no meio, o vao interno e o externo seriam
     medidas diferentes e o ciclo emendaria com um salto visivel. */
  .fin-apoio-copia { display: contents; }

  /* Parar com o dedo em cima: quem quer conferir um valor encosta e ele
     fica. */
  .fin-apoio:active .fin-apoio-fita { animation-play-state: paused; }

  /* O vao entre os itens vira um valor FIXO no celular.
     
     Ele era um `clamp(.55rem, 1.6vw, 2rem)`, e um vao que muda com a
     largura da tela nao da para somar na conta da animacao: `calc()` nao
     le a propriedade de um irmao, e repetir o `clamp()` no `keyframes` dava
     um numero diferente do que o navegador usou de fato -- medido, sobravam
     9px de salto a cada volta.
     
     Com 1.2rem fixo, o deslocamento e exatamente `-50% - .6rem`. */
  .fin-apoio { gap: .5rem 1.2rem; }

  /* O ciclo anda meia fita MAIS meio vao.
     
     `-50%` sozinho nao emenda: entre a ultima copia da primeira volta e a
     primeira da segunda ha um `gap`, e ele conta na largura total mas nao
     na metade percorrida -- o salto e de meio vao a cada volta. */
  @keyframes fin-fita {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(-50% - .6rem)); }
  }

  .gaveta-veu {
    position: fixed;
    inset: 0;
    background: rgb(0 0 0 / 45%);
    /* Acima da barra de baixo (30), abaixo dos modais (50). */
    z-index: 40;
    animation: folha-veu-entra .18s ease;
  }
  .gaveta-veu.hidden { display: none !important; }

  /* Entra pela ESQUERDA, e nao de baixo: a folha do "Mais" ja vem de baixo,
     e as duas sao coisas diferentes -- uma troca a tela DENTRO da aba, a
     outra troca de aba. Lados diferentes e o que as distingue sem rotulo. */
  /* O painel entra com OPACIDADE, e nao deslizando.
     
     Deslizando, os itens viajam junto com a caixa: quem abre e toca rapido
     acerta o lugar onde o botao VAI estar, e nao onde ele esta -- medido,
     no primeiro quadro "Dieta" estava em x=466 numa tela de 390, ou seja,
     fora dela. O toque caia no vazio e parecia bloqueio de tempo.
     
     Com o painel parado no lugar final desde o primeiro quadro, o alvo nao
     se move: o que muda e so o quanto ele aparece. O movimento continua --
     um deslize curto de 12px, longe do bastante do dedo para nao roubar
     nenhum toque. */
  .gaveta {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    /* A largura do TEXTO, e nao uma fatia da tela.
       
       78vw dava 304px numa tela de 390 -- quase toda ela -- para mostrar
       "Movimentacao", que ocupa uns 130. O painel cobria o conteudo sem
       precisar, e a mao tinha de atravessar a tela inteira para fecha-lo.
       
       `fit-content` mede o item mais largo e para ali. O teto de 62vw
       impede que um rotulo comprido estique o painel de volta ao tamanho
       de antes, e o piso de 11rem evita uma faixa fina demais numa aba de
       nomes curtos. `clamp()` nao serve aqui: ele nao aceita palavra-chave
       de tamanho intrinseco no meio. */
    width: fit-content;
    min-width: 11rem;
    max-width: 62vw;
    overflow-y: auto;
    background: var(--surface);
    border-right: 1px solid var(--border);
    box-shadow: 4px 0 20px rgb(0 0 0 / 18%);
    padding: 1rem .8rem calc(1rem + env(safe-area-inset-bottom, 0px));
    animation: gaveta-entra .16s ease;
  }

  .gaveta-sub {
    display: flex;
    align-items: center;
    gap: .7rem;
    width: 100%;
    min-height: 44px;
    padding: .7rem .6rem;
    margin-bottom: .2rem;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--text-dim);
    font-size: .9rem;
    text-align: left;
    justify-content: flex-start;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .gaveta-sub:hover { background: transparent; }
  .gaveta-sub:active { background: var(--surface-2); }
  .gaveta-sub .ico { flex: none; opacity: .8; }

  /* A subaba aberta: fundo, cor e peso. Tres sinais, como na barra de
     baixo -- cor sozinha nao serve para quem nao a distingue. */
  .gaveta-sub.active {
    background: var(--surface-2);
    color: var(--accent-text);
    font-weight: 600;
  }
  .gaveta-sub.active .ico { opacity: 1; color: var(--accent-text); }

  /* O avatar agora e um botao: leva para o Inicio. */
  .topbar .avatar { cursor: pointer; }
  .topbar .avatar:active { opacity: .75; }

  /* -- as duas metades da gaveta -------------------------------------- */

  /* "nesta aba" ao lado do nome da aba, e "Outras abas" mais abaixo: a
     gaveta leva DUAS coisas, e sem essa marca a lista pareceria uma so --
     "Placar, Historico, Configurar, Dieta, Compras" se lê como cinco telas
     do mesmo lugar. */
  .gaveta-nota {
    margin-left: .4rem;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    opacity: .6;
  }

  /* A segunda secao vem separada por um risco e mais respiro: e outro
     nivel de navegacao, e nao a continuacao da lista de cima. */
  .folha-titulo.gaveta-outras {
    margin-top: 1rem;
    padding-top: .8rem;
    border-top: 1px solid var(--border);
  }

  /* As abas de fora vem em texto normal, e nao no cinza das subabas: elas
     nao sao "a tela ao lado", sao um destino inteiro. */
  .gaveta-aba { color: var(--text); }

  /* As secoes de uma subaba de Financas, recuadas sob ela. O recuo e o
     risco a esquerda dizem "isto e parte da linha de cima" sem precisar de
     um titulo repetindo o nome dela. */
  .gaveta-secoes {
    margin: 0 0 .3rem .95rem;
    padding-left: .7rem;
    border-left: 1px solid var(--border);
  }

  .gaveta-secao {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    min-height: 40px;
    padding: .5rem .6rem;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--text-dim);
    font-size: .84rem;
    text-align: left;
    justify-content: flex-start;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .gaveta-secao:hover { background: transparent; }
  .gaveta-secao:active { background: var(--surface-2); }
  .gaveta-secao > span:first-child { flex: 1; min-width: 0; }
  .gaveta-secao.active { color: var(--accent-text); font-weight: 600; }

  /* A contagem ao lado do nome: quantos lancamentos, quantas dividas. */
  .gaveta-secao .seg-n {
    flex: none;
    font-size: .72rem;
    opacity: .7;
  }

  /* As 11 cores do evento, na janela.
     
     Onze e PRIMO: nenhuma grade as divide em fileiras iguais, e forcar uma
     deixaria a ultima com um buraco de lado. Aqui a sobra fica CENTRADA --
     seis em cima, cinco embaixo, e a fileira curta alinhada no meio da
     outra, que e como o olho espera ver uma paleta terminar. */
  .ev-cores-janela {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .45rem;
    max-width: 15rem;
    margin: 0 auto;
  }

  /* O `@keyframes` foi para fora deste `@media`: o computador usa a mesma
     animacao no modo gaveta, e aqui dentro ele nao a enxergava. */
}

@media (prefers-reduced-motion: reduce) {
  .gaveta, .gaveta-veu { animation: none; }
}

/* -- a alca do painel lateral (estilo Edge Panel) ---------------------- */

.alca-sub { display: none; }

@media (max-width: 859px) {

  /* Uma faixa fina colada na borda. Estreita de proposito: ela fica sobre o
     conteudo o tempo todo, e larga demais viraria uma tarja permanente
     tapando o texto. 20px e o bastante para o polegar acertar na borda,
     onde ele ja encosta naturalmente. */
  .alca-sub {
    display: block;
    position: fixed;
    /* Fina e ALTA: 5px de largura por 128px de altura.

       Parece contra-intuitivo -- alvo menor deveria ser mais dificil --,
       mas o que se acerta aqui e a BORDA, nao um ponto: o polegar desliza
       de lado ate encostar, e o que importa e o quanto da borda responde.
       Dobrando a altura, a faixa que responde ao dedo mais que dobra; e
       estreitando, ela deixa de tapar o conteudo e para de ser confundida
       com uma barra de rolagem que a pessoa tenta arrastar.

       A area de TOQUE nao encolhe junto: o `::before` abaixo estende o
       alvo para 24px de largura, invisivel, para o dedo nao precisar
       acertar os 10px pintados. */
    width: 5px;
    height: 128px;
    padding: 0;
    border: 0;
    /* Abaixo dos modais e da propria gaveta, acima do conteudo. */
    z-index: 28;
    /* A cor do perfil, CHEIA, sem misturar com o fundo.

       Ela ja foi `--text-dim`, depois `--border-strong`, depois um
       `color-mix` a 55% e a 80%. Todas as versoes misturadas tinham o
       mesmo defeito: misturar o acento com `--surface` so mexe no BRILHO.
       No tema escuro o laranja a 80% dava rgb(193,88,33) contra os
       rgb(236,105,37) do toque -- 42 de diferenca no vermelho e 3 no
       azul, ou seja, a mesma cor duas vezes.

       E um laranja escuro sobre fundo escuro nao le como laranja: le como
       CINZA amarronzado. Era esse o "fica cinza" que sobreviveu a cada
       tentativa de ajustar o contraste entre os dois estados -- o
       problema nunca foi a distancia entre eles, foi a mistura.

       Cheia, a alca e a cor do perfil em qualquer tema. O que separa o
       toque agora e a LARGURA e a sombra: forma, e nao tom, que e o que
       se enxerga numa faixa de 5px com o dedo em cima. */
    background: var(--accent);
    cursor: grab;
    -webkit-tap-highlight-color: transparent;
    /* Sem isto o navegador entende o arrasto como rolagem da pagina e
       rouba o gesto no meio do caminho. */
    touch-action: none;
    /* Anima LARGURA e sombra, nao a cor.

       O `background` entrou e saiu daqui tres vezes, sempre pelo motivo
       errado, porque o estado de toque era uma troca de cor. Agora nao e
       mais: a cor e a mesma sempre, e o que muda de estado e a forma. */
    transition: width .12s ease, height .15s ease, box-shadow .12s ease;
    /* Camada propria no compositor, para a alca acompanhar a rolagem sem
       esperar o layout da pagina.

       ISTO NAO FOI O QUE CONSERTOU o salto ao rolar -- a explicacao que
       estava aqui antes culpava a repintura, e estava errada. A causa era
       o `top` em PORCENTAGEM contra uma viewport que muda de tamanho
       quando a barra do navegador recolhe; quem resolve e o `svh` em
       `aplicaPosicaoDaAlca`. Fica registrado para ninguem tentar de novo
       por este caminho.

       O `translateZ(0)` fica porque ajuda de verdade num `fixed` sobre
       conteudo que rola, e nao custa nada aqui: e um elemento de 5px. */
    transform: translateZ(0);
    will-change: transform;
  }
  /* O HOVER de `button` nao vale aqui.

     A alca e um `<button>`, e a regra geral `button:hover` pinta
     `--surface-2` -- um cinza quase preto no tema escuro. No computador
     isso nunca apareceu porque o ponteiro passa e sai; no Android o hover
     GRUDA depois de um toque simples e so sai ao tocar noutro lugar.

     Era exatamente esta a diferenca entre "pegar para arrastar" e
     "segurar como se fosse clicar": arrastando, o dedo se move e o sistema
     descarta o hover; segurando parado, ele fica -- e a alca virava
     rgb(30,28,27), medido.

     `button:hover` tem especificidade 0-1-1 contra os 0-1-0 de
     `.alca-sub`, entao ganhava mesmo estando 8.900 linhas antes. Repetir
     a cor aqui, com a pseudo-classe, empata a especificidade e o que vem
     depois no arquivo vence. */
  .alca-sub:hover { background: var(--accent); }

  .alca-sub.hidden { display: none !important; }

  /* Com a gaveta ABERTA a alca sai do caminho de qualquer toque.
     
     Ela fica embaixo do veu (z-index 28 contra 40), entao nao recebe
     clique -- mas o Android guarda o alvo do gesto que COMECOU nela, e o
     toque seguinte podia voltar para la em vez de ir para a lista.
     `pointer-events: none` corta isso na raiz: enquanto o painel esta em
     cena, a alca simplesmente nao existe para o dedo. */
  body:has(#subVeu:not(.hidden)) .alca-sub { pointer-events: none; }

  /* Cantos arredondados so para DENTRO da tela: encostada na borda, a alca
     e meia pilula. */
  /* 6px longe da borda, e nao colada nela.
     
     A borda e onde o Android desenha a faixa de gesto do "voltar": um
     toque que comeca ali vira navegacao do SISTEMA, e o Hub nunca chega a
     receber. Afastando esses poucos pixels, o dedo encosta na alca antes
     de entrar na faixa do sistema -- e ela continua visivelmente na
     borda, porque 6px nao se leem como um botao solto no meio da tela. */
  .alca-sub.alca-dir {
    right: 10px;
    border-radius: var(--r-pill);
  }
  .alca-sub.alca-esq {
    left: 10px;
    border-radius: var(--r-pill);
  }

  /* O alvo invisivel em volta.
     
     A conta anterior estava errada: 14px para cada lado numa faixa colada
     na borda joga METADE do alvo para fora da tela, entao do lado de
     dentro -- o unico que existe -- sobravam 14px. Some-se a isso a faixa
     de gesto do Android, que fica justamente na borda e rouba o toque para
     o "voltar" do sistema, e a alca ficava mesmo dificil de pegar.
     
     O que cresce e o ALVO, nunca a faixa pintada: ela e fina de proposito
     -- fica sobre o conteudo o tempo todo, e engordar seria uma tarja
     permanente tapando o texto. O alvo, sendo invisivel, nao paga esse
     preco.

     80x188 de area que responde, para 5x128 de alca desenhada. E muito
     acima do piso de 44, e deve ser: aqui o dedo chega de lado, sem ver
     onde encosta, e o gesto e um PUXAO que comeca antes de a pessoa mirar
     em coisa alguma. */
  .alca-sub::before {
    content: "";
    position: absolute;
    /* Alto tambem, e nao so largo: o dedo erra no eixo vertical tanto
       quanto no horizontal, e 128px de faixa pintada viram 188 de faixa
       que responde. */
    top: -30px;
    bottom: -30px;
  }
  /* Para DENTRO e um pouco para fora: os 10px de folga ate a borda tambem
     valem como alvo, mas o gesto do sistema mora la -- por isso o grosso
     do alvo cresce para o lado de dentro, que e onde o dedo chega. */
  .alca-sub.alca-dir::before { left: -65px; right: -10px; }
  .alca-sub.alca-esq::before { right: -65px; left: -10px; }

  /* `.tocada`, e nao `:active`.

     No Android o `:active` de um `<button>` GRUDA depois do toque: ele so
     sai quando se encosta em outro lugar da tela. A alca ficava com a cor
     cheia depois de segurar e largar, e parecia que ela tinha trocado de
     cor sozinha -- e o proximo toque, em qualquer canto, a "consertava",
     o que tornava o defeito dificil de descrever.

     Uma classe some quando o codigo manda, e o codigo ja mandava: `solta()`
     limpa no fim de todo gesto. */
  /* O toque ENGORDA a alca, em vez de mudar a cor dela.

     A cor e a mesma nos dois estados agora, e tinha de ser: qualquer par
     de tons do mesmo acento fica indistinguivel numa faixa de 5px. A
     largura dobrada e a sombra aparecem mesmo com o dedo em cima. */
  .alca-sub.tocada {
    width: 10px;
    box-shadow: 0 2px 10px rgb(0 0 0 / 28%);
  }

  /* Segurando, ela CRESCE e ganha a cor da marca: e o aviso de que soltou
     do lugar e agora acompanha o dedo. O dedo esta em cima dela, entao o
     que muda tem de ser grande o bastante para aparecer em volta dele. */
  .alca-sub.arrastando {
    /* Sem `background`: a alca ja E a cor do perfil em repouso, e
       repetir aqui so criaria uma segunda fonte de verdade para a cor --
       foi assim que o "fica cinza" durou tanto. Arrastando ela cresce
       nos DOIS eixos, que e o que diz "soltou do lugar". */
    width: 10px;
    height: 140px;
    cursor: grabbing;
    box-shadow: 0 2px 14px rgb(0 0 0 / 30%);
  }

  /* A alca PISCANDO, enquanto o aviso de boas-vindas esta aberto.
     
     O texto diz "aquela faixa fina na borda", e sem apontar qual a pessoa
     procura algo que quase nao se ve. Ela cresce e ganha a cor da marca em
     pulsos -- o mesmo estado do arrasto, so que sozinho.
     
     `z-index` acima do veu do modal (50): piscando ATRAS do escuro, o
     aviso apontaria para uma sombra. */
  .alca-sub.alca-piscando {
    z-index: 51;
    animation: alca-pulsa 1.4s ease-in-out infinite;
  }
  @keyframes alca-pulsa {
    0%, 100% { width: 5px; }
    50%      { width: 14px; }
  }
  @media (prefers-reduced-motion: reduce) {
    /* Sem pulso, mas ainda visivel: quem pediu menos movimento continua
       precisando achar a alca. */
    .alca-sub.alca-piscando {
      animation: none;
      width: 14px;
      background: var(--accent);
    }
  }

  .alca-sub:focus-visible {
    outline: 2px solid var(--accent-text);
    outline-offset: 2px;
  }

  /* -- a gaveta abre do lado da alca ---------------------------------- */

  /* O padrao (esquerda) ja esta definido acima; aqui so o espelho, para
     quando a alca esta na direita. `right: 0` com `left: auto` porque a
     regra de cima fixa `left`, e as duas conviveriam empurrando a gaveta
     para a largura inteira da tela. */
  .gaveta.gaveta-dir {
    left: auto;
    right: 0;
    border-right: 0;
    border-left: 1px solid var(--border);
    box-shadow: -4px 0 20px rgb(0 0 0 / 18%);
    animation: gaveta-entra-dir .16s ease;
  }

}

/* A SAIDA da gaveta: a animacao inversa da entrada.
   
   Ela entrava com transicao e sumia num quadro so -- a ida tinha peso, a
   volta parecia um corte. `forwards` segura o ultimo quadro ate o
   JavaScript por o `hidden`, senao ela reapareceria por um instante entre
   o fim da animacao e a classe. */
/* Saindo, o veu deixa de receber clique NA HORA -- e nao ao fim da
   animacao. Ele cobre a tela inteira, e nos 200ms da saida engolia o
   primeiro clique de quem ja tinha ido mexer noutra coisa: a gaveta
   fechava sozinha e o toque seguinte "nao contava". */
.gaveta-veu.saindo { animation: veu-sai .18s ease forwards; pointer-events: none; }
.gaveta-veu.saindo .gaveta { animation: gaveta-sai .18s ease forwards; }
.gaveta-veu.saindo .gaveta.gaveta-dir {
  animation: gaveta-sai-dir .18s ease forwards;
}

@keyframes veu-sai {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes gaveta-sai {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(-12px); }
}
@keyframes gaveta-sai-dir {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(12px); }
}

/* Quem pediu menos movimento recebe a gaveta sem o deslize -- ela continua
   fechando, o que sai e a animacao. */
@media (prefers-reduced-motion: reduce) {
  .gaveta-veu.saindo,
  .gaveta-veu.saindo .gaveta,
  .gaveta-veu.saindo .gaveta.gaveta-dir { animation: none; opacity: 0; }
}

/* FORA do `@media` do celular: o computador usa as mesmas animacoes no
   modo gaveta, e dentro dele o desktop ficava sem os `@keyframes` -- a
   gaveta aparecia sem transicao nenhuma. */
@keyframes gaveta-entra {
  from { opacity: 0; transform: translateX(-12px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes gaveta-entra-dir {
  from { opacity: 0; transform: translateX(12px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* ═══════════════════════════════════ os modos de navegacao (computador) */

/* Tudo aqui vale ACIMA de 860px. No celular a barra e sempre embaixo, e
   `aplicaModoDeNavegacao` forca `data-nav="topo"` para nenhuma destas
   regras pegar. */
@media (min-width: 860px) {

  /* -- as abas no RODAPE ------------------------------------------------ */

  /* A mesma `nav.tabs` do topo, presa no pe da janela. Nao e um segundo
     elemento: duas barras com a mesma funcao seriam dois lugares para
     consertar, e a de cima ja sabe desenhar aba ativa, promovida e
     arrastavel. */
  /* Sem `header.topbar` no seletor: neste modo a barra foi movida para
     fora dele (o `backdrop-filter` do cabecalho prendia o `fixed`). */
  /* A BARRA DE BAIXO e outro sistema, e nao a de cima virada.
     
     Em cima ela e uma fita fina abaixo do cabecalho, com icone e texto
     lado a lado -- ali ela e secundaria, presa a um cabecalho que ja tem
     avatar e acoes. Embaixo ela e a UNICA coisa naquela faixa, e a faixa
     e a mais alcancavel da tela: ganha o peso do cabecalho (61px), icone
     ACIMA do rotulo e alvos que ocupam a altura inteira.
     
     Empilhado, e nao lado a lado: em pe o conjunto icone+texto fica
     centrado no alvo e a fileira ganha ritmo -- doze abas lado a lado
     viravam uma linha de texto corrida com simbolos no meio. */
  :root[data-nav="rodape"] nav.tabs {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    max-width: none;
    margin: 0;
    padding: 0 1rem;
    /* A altura do cabecalho, medida: 61px. */
    min-height: 61px;
    align-items: stretch;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: blur(12px);
    border-top: 1px solid var(--border);
    border-bottom: 0;
    /* A sombra vai para CIMA: a barra esta na base, e sem ela um card
       claro rolando por tras encostava nela e as duas viravam uma coisa
       so. */
    box-shadow: 0 -1px 8px rgb(0 0 0 / 4%);
    /* `safe center`, e nao `center` puro: com todas as abas ligadas o
       conteudo passa da largura da barra, e o `center` corta pelos DOIS
       lados -- a primeira aba nasce fora da vista com a rolagem ja em
       zero, inalcancavel. O `safe` desiste de centrar nesse caso e alinha
       pelo comeco, que e o que se pode rolar. */
    /* O espalhamento segue a escolha, como na barra de cima. `safe center`
       nos dois casos que centram: com todas as abas ligadas o conteudo
       passa da largura, e o `center` puro corta pelos DOIS lados -- a
       primeira aba nasce fora do alcance da rolagem. */
    justify-content: safe center;
    gap: .2rem;
  }

  /* ESPALHAR: as abas das pontas encostam nas bordas da coluna de
     conteudo, como em cima. A largura e a mesma do `.wrap`, e nao a da
     janela: alinhar com a borda da tela deixaria as abas fora do prumo dos
     cards. */
  :root[data-espaco="espalhar"][data-nav="rodape"] nav.tabs {
    justify-content: space-between;
    gap: .4rem;
    padding-inline: max(1.2rem, calc((100vw - 1320px) / 2 + 1.2rem));
  }

  /* O conteudo termina acima dela, senao o ultimo card fica embaixo para
     sempre -- nao ha como rolar alem do fim da pagina. */
  :root[data-nav="rodape"] main.wrap { padding-bottom: 4.6rem; }

  /* Cada aba: uma coluna, com o icone em cima. O alvo ocupa a altura
     inteira da barra -- o mouse acerta a faixa, nao o texto. */
  :root[data-nav="rodape"] .tab {
    flex-direction: column;
    justify-content: center;
    gap: .2rem;
    padding: .3rem .7rem;
    min-width: 4.4rem;
    min-height: 100%;
    border-bottom: 0;
    /* A marca da aba ativa vai para CIMA: embaixo o sublinhado encostaria
       na borda da janela e sumiria. */
    border-top: 2px solid transparent;
    font-size: .72rem;
  }
  :root[data-nav="rodape"] .tab.active { border-top-color: var(--accent-text); }

  /* Icones MAIORES: 16px na fita de cima, 20 aqui. O `svg` vem com
     `width`/`height` no atributo, entao a regra precisa vencer os dois. */
  :root[data-nav="rodape"] .tab .ico {
    width: 20px;
    height: 20px;
    opacity: .75;
  }
  :root[data-nav="rodape"] .tab.active .ico { opacity: 1; }

  /* O fundo acende na aba sob o cursor: numa faixa alta, o sublinhado
     sozinho e um sinal fraco demais para dizer onde o mouse esta. */
  :root[data-nav="rodape"] .tab:hover {
    background: var(--surface-2);
    color: var(--text);
  }

  /* -- a GAVETA lateral -------------------------------------------------- */

  /* "Sem barra": as abas somem e quem navega e a gaveta. E uma escolha
     separada da gaveta em si -- da para ter as duas, ou so uma. */
  :root[data-nav="nenhuma"] nav.tabs { display: none; }

  /* A faixa que acorda a gaveta.

     Invisivel e estreita: ela fica sobre o conteudo o tempo todo, e larga
     demais roubaria o clique de quem so quer alcancar a margem esquerda
     dos cards. 8px e o bastante para o mouse encostar sem mirar -- a
     borda da tela para o cursor, entao acerta-la e o gesto mais facil que
     existe num computador.

     Abaixo do cabecalho (30) para nao cobrir o avatar e a busca. */
  /* A faixa que acorda a gaveta.
     
     `z-index: 41` -- ACIMA do cabecalho (30) e da barra do rodape (30), e
     acima do proprio veu (40) para continuar respondendo com a gaveta
     aberta. Em 26 ela ficava ATRAS dos dois: a borda so funcionava no
     trecho do meio da tela, entre o fim do cabecalho e o comeco da barra,
     e passar disso nao abria nada.
     
     20px, e nao 8: o mouse vai a borda em diagonal e chega com velocidade,
     e uma faixa fina exige que ele PARE exatamente nela. Ela e invisivel,
     entao o custo de ser mais larga e so nao poder cobrir nada clicavel --
     e na borda da janela nao ha nada. */
  .nav-borda {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    /* 40px, o dobro dos 20 de antes. O mouse chega a borda em diagonal e
       com velocidade, e uma faixa estreita exige que ele PARE exatamente
       nela -- alargando, basta ir na direcao certa.

       Ela e invisivel, entao o custo e so nao poder cobrir nada clicavel.
       Na borda da janela nao ha nada: o conteudo tem margem, e a faixa
       morre antes do primeiro card. */
    /* 80px: o dobro dos 40. A faixa e invisivel e nao cobre nada clicavel
       -- conferido, zero botoes ficam debaixo dela --, entao o unico custo
       de alarga-la e nenhum, e o ganho e o mouse acertar sem mirar. */
    width: 80px;
    z-index: 41;
  }
  /* Na borda que a gaveta usa. O padrao e a DIREITA: navegadores como o
     Zen ocupam a esquerda, e duas gavetas na mesma borda fariam uma abrir
     quando a pessoa quisesse a outra. */
  .nav-borda.nav-borda-dir { left: auto; right: 0; }
  .nav-borda.hidden { display: none !important; }

  /* A gaveta, no computador, vive dela mesma: as regras dela sao do
     `@media (max-width: 859px)` e aqui precisam ser repetidas. */
  :root[data-gaveta="on"] .gaveta-veu {
    /* `display: block` explicito: a regra base, fora do `@media` do
       celular, deixa o veu em `none` -- sem isto ele existia mas nao
       pintava, e a gaveta abria sobre a pagina em cor cheia. */
    display: block;
    position: fixed;
    inset: 0;
    /* Mais leve que os 45% do celular: no PC a gaveta e um menu de
       passagem, e escurecer a tela inteira para consultar uma lista faria
       o gesto parecer mais grave do que e. */
    background: rgb(0 0 0 / 32%);
    z-index: 40;
  }
  :root[data-gaveta="on"] .gaveta-veu.hidden { display: none !important; }

  :root[data-gaveta="on"] .gaveta {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: fit-content;
    min-width: 13rem;
    max-width: 22rem;
    overflow-y: auto;
    background: var(--surface);
    border-right: 1px solid var(--border);
    box-shadow: 4px 0 24px rgb(0 0 0 / 22%);
    padding: 1rem .8rem;
    animation: gaveta-entra .16s ease;
  }

  /* Pela DIREITA. A regra do celular (`.gaveta-dir`) vive no `@media`
     estreito e nao chega aqui: `left: auto` e obrigatorio, senao as duas
     ancoras valeriam ao mesmo tempo e a gaveta esticaria pela tela toda. */
  :root[data-gaveta="on"] .gaveta.gaveta-dir {
    left: auto;
    right: 0;
    border-right: 0;
    border-left: 1px solid var(--border);
    box-shadow: -4px 0 24px rgb(0 0 0 / 22%);
    animation: gaveta-entra-dir .16s ease;
  }

  /* Os itens e os titulos: as mesmas regras do celular, que vivem no
     `@media` estreito. Repetidas aqui em vez de movidas para fora porque
     as MEDIDAS diferem -- no PC nao ha piso de 44px de toque, e a lista
     cabe mais compacta. */
  /* As linhas ficam ALTAS, e nao largas.
     
     Elas foram desenhadas apertadas, com medo de a lista nao caber -- mas
     no caso mais CHEIO que existe (Financas, com as quatro subabas e as
     seis secoes) ainda sobra mais de meia gaveta vazia. Aperto so faz
     sentido quando falta espaco, e aqui sobra.
     
     O que cresce e a ALTURA, o icone e a fonte: e disso que o clique
     precisa. Largura extra so afastaria o texto da borda -- a linha ja
     ocupa a gaveta inteira, e mirar nela nunca foi o problema. */
  :root[data-gaveta="on"] .gaveta-sub {
    display: flex;
    align-items: center;
    gap: .75rem;
    width: 100%;
    min-height: 52px;
    padding: .8rem .75rem;
    margin-bottom: .25rem;
    font-size: .95rem;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--text-dim);
    font-size: .85rem;
    text-align: left;
    justify-content: flex-start;
    cursor: pointer;
  }
  :root[data-gaveta="on"] .gaveta-sub:hover {
    background: var(--surface-2);
    color: var(--text);
  }
  /* 21px contra os 18 do HTML: o `svg` traz `width` e `height` no atributo,
     entao a regra precisa vencer os dois. */
  :root[data-gaveta="on"] .gaveta-sub .ico {
    flex: none;
    width: 21px;
    height: 21px;
    opacity: .8;
  }
  :root[data-gaveta="on"] .gaveta-sub.active {
    background: var(--surface-2);
    color: var(--accent-text);
    font-weight: 600;
  }
  :root[data-gaveta="on"] .gaveta-sub.active .ico {
    opacity: 1;
    color: var(--accent-text);
  }
  :root[data-gaveta="on"] .gaveta-aba { color: var(--text); }

  :root[data-gaveta="on"] .gaveta-secoes {
    margin: 0 0 .25rem .85rem;
    padding-left: .6rem;
    border-left: 1px solid var(--border);
  }
  :root[data-gaveta="on"] .gaveta-secao {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    min-height: 44px;
    padding: .65rem .7rem;
    margin-bottom: .15rem;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--text-dim);
    font-size: .88rem;
    text-align: left;
    justify-content: flex-start;
    cursor: pointer;
  }
  :root[data-gaveta="on"] .gaveta-secao:hover {
    background: var(--surface-2);
    color: var(--text);
  }
  :root[data-gaveta="on"] .gaveta-secao > span:first-child {
    flex: 1;
    min-width: 0;
  }
  :root[data-gaveta="on"] .gaveta-secao.active {
    color: var(--accent-text);
    font-weight: 600;
  }
  :root[data-gaveta="on"] .gaveta-secao .seg-n {
    flex: none;
    font-size: .72rem;
    opacity: .7;
  }
  :root[data-gaveta="on"] .gaveta-nota {
    margin-left: .4rem;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    opacity: .6;
  }
  :root[data-gaveta="on"] .folha-titulo.gaveta-outras {
    margin-top: .9rem;
    padding-top: .7rem;
    border-top: 1px solid var(--border);
  }
  :root[data-gaveta="on"] .folha-titulo {
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin: .9rem .3rem .5rem;
  }
  :root[data-gaveta="on"] .folha-titulo:first-child { margin-top: .1rem; }
}

/* -- a escolha, em Configuracoes -------------------------------------- */

.nav-modos {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.nav-modo {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: .7rem .8rem;
  border: 1px solid var(--border);
  border-radius: var(--r);
  cursor: pointer;
}
.nav-modo:hover { background: var(--surface-2); }
.nav-modo:has(input:checked) {
  border-color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
/* O radio volta ao tamanho de um radio.
   
   A regra global de `input` da `width: 100%` e `min-height: 38px` -- feita
   para campos de texto --, e o radio herdava: medido, ele ocupava 358x38 e
   engolia a linha inteira, deixando so uma bola gigante e nenhum texto.
   `width`/`height` explicitos, e `flex: none` para o flex nao o esticar de
   volta. */
.nav-modo input[type="radio"] {
  flex: none;
  width: 16px;
  height: 16px;
  min-height: 0;
  padding: 0;
  margin: 0;
}

.nav-modo-txt { display: flex; flex-direction: column; gap: .1rem; }

/* ------------------------------------------- objetivos do onboarding
   A marca do Hub abrindo o passo, com a pergunta ao lado.

   Nao e um mascote: e o mesmo simbolo do instalador e da aba do navegador,
   no unico passo do wizard que pergunta em vez de configurar. */
.ob-marca {
  display: flex;
  align-items: flex-start;
  gap: .8rem;
  margin-bottom: 1.1rem;
}

.ob-marca-ico {
  flex: none;
  color: var(--accent-text);
  line-height: 0;
  margin-top: .1rem;
}

/* Os cartoes de "o que voce quer organizar", um por linha.

   Largura inteira, e nao a grade de dois: a descricao e o que faz a pessoa
   entender o que marcou, e em duas colunas ela quebrava em cinco palavras
   por linha. Uma coluna tambem poe o icone sempre no mesmo eixo, e a fileira
   vira uma lista que se le de cima a baixo. */
.objetivos {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

/* `button`, e nao `label` com checkbox escondido: o cartao inteiro e o alvo,
   o teclado o alcanca com Tab e Espaco, e `aria-pressed` diz se esta marcado.
   Um checkbox visivel ficava com dois alvos na mesma caixa. */
.objetivo {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  width: 100%;
  padding: .75rem .85rem;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
/* Os cartoes entram em escada quando o passo abre.
   
   `--i` vem do inline, com a posicao de cada um: sem o atraso os seis
   aparecem juntos e o efeito e um piscar, nao uma chegada. 40ms e curto o
   bastante para o ultimo nao fazer esperar (240ms no total) e longo o
   bastante para a ordem se ler. */
.objetivo {
  animation: rise .26s ease-out both;
  animation-delay: calc(var(--i, 0) * 40ms);
}

.objetivo:hover { background: var(--surface-2); }
.objetivo.ativo {
  border-color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
.objetivo:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* O icone e o MESMO da aba que o objetivo liga: quem marca "cuidar do
   dinheiro" ja viu o simbolo que vai procurar na barra depois. Apagado
   enquanto nao escolhido, na cor da marca quando escolhido -- e o que faz o
   toque virar uma mudanca visivel sem animacao nenhuma. */
.objetivo-ico {
  flex: none;
  /* `flex`, e nao `grid` com `place-items`: a grade dimensionava a coluna
     pelo conteudo, e o icone de Noticias -- que usa a largura toda do
     viewBox -- empurrava a propria caixa 24px para a direita. Um deles saia
     do eixo da fileira, e so na tela dava para ver. */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-dim);
  transition: background .15s, color .15s;
}
/* O SVG ocupa a celula inteira em vez de ser centrado como caixa.

   Os icones nao usam o viewBox todo, e cada um sobra de um lado diferente:
   `tarefas` e um V estreito no meio, `noticias` e `vagas` vao quase de borda
   a borda. Centrado como CAIXA, o desenho de cada um caia num ponto
   diferente, e a fileira de seis ficava com dois icones fora do eixo. */
.objetivo-ico .ico {
  width: 20px;
  height: 20px;
  display: block;
}
.objetivo.ativo .objetivo-ico {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent-text);
}

/* `flex: 1` e o que prende o icone na borda esquerda.

   Sem ele o texto so ocupa a largura de que precisa, e num cartao de
   descricao curta sobrava espaco na linha: o flex distribuia a sobra e o
   icone descolava do canto. Quem tinha texto longo ficava no lugar, quem
   tinha texto de uma linha saia -- e a fileira parecia desalinhada sem
   motivo visivel. `min-width: 0` deixa o texto quebrar em vez de esticar o
   cartao. */
.objetivo-txt {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: .15rem;
}

/* As abas que o objetivo liga. Menor e mais apagado que a descricao: e a
   letra miuda da promessa, nao a promessa. */
.objetivo-abas {
  font-size: .74rem;
  color: var(--text-faint);
  margin-top: .1rem;
}

/* ------------------------------------------- fichas de assunto
   Os assuntos de Noticias e as buscas de Vaga, no passo que so aparece para
   quem ligou aquelas abas.

   Pilulas, e nao os cartoes dos objetivos: aqui sao vinte e duas escolhas de
   uma palavra, e um cartao por assunto daria uma coluna de vinte e duas
   linhas. A escolha tambem e mais leve -- "Economia" nao pede explicacao como
   "Cuidar do dinheiro" pedia. */
.fichas {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
}

.ficha {
  padding: .4rem .75rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-dim);
  font: inherit;
  font-size: .86rem;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.ficha:hover { color: var(--text); border-color: var(--text-faint); }
.ficha.ativa {
  border-color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent-text);
  font-weight: 600;
}
.ficha:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* O rotulo que separa Noticias de Vagas, quando os dois aparecem juntos. */
.ob-grupo {
  display: block;
  font-size: .74rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: .45rem;
}

/* ------------------------------------------- a previa da tela inicial
   O que a escolha monta, mostrado em vez de escrito. */
/* A previa e um HUB EM MINIATURA, nao uma caixa de exemplo ao lado.

   Antes era tracejada e solta, e lia como "amostra": a barra de abas ficava
   dentro de um quadro pontilhado, desligada do que ela representa. Agora tem
   a moldura de uma janela -- borda cheia, o mesmo raio dos cards --, com a
   barra colada na grade como no Hub de verdade. A continuidade e o ponto: o
   que a pessoa ve aqui e a tela que ela vai abrir. */
.previa {
  margin-top: 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface-2);
  overflow: hidden;
}

.previa-rot {
  padding: .5rem .8rem .45rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

/* A barra e a grade dividem o mesmo corpo, sem respiro entre elas: e assim
   que o Hub desenha, a barra encostada no conteudo. */
.previa-corpo { padding: 0 .7rem .7rem; }

.previa-rot {
  display: block;
  font-size: .72rem;
  font-weight: 600;
  color: var(--text-dim);
}

/* Rola na horizontal como a barra do Hub: com nove abas a fileira nao cabe
   em 375px, e quebrar em duas linhas mentiria sobre como a barra de verdade
   se comporta. */
.previa-barra {
  display: flex;
  gap: .1rem;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--border);
  margin-bottom: .5rem;
}
.previa-barra::-webkit-scrollbar { display: none; }

.previa-aba {
  flex: 0 0 auto;
  padding: .2rem .45rem .3rem;
  font-size: .74rem;
  color: var(--text-dim);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}
/* A primeira e o Inicio, que e onde o Hub abre. Marcada como a barra de
   verdade marca a aba ativa. */
.previa-aba.ativa {
  color: var(--accent-text);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

/* A barra no PE da previa, quando a pessoa escolhe a navegacao embaixo.
   A borda troca de lado: em cima ela separa a barra do conteudo, embaixo ela
   precisa separar o conteudo da barra. */
.previa-barra-pe {
  border-bottom: 0;
  border-top: 1px solid var(--border);
  margin-bottom: 0;
  margin-top: .5rem;
}

/* A gaveta lateral: uma faixa fina encostada na borda, que e como ela se
   anuncia no Hub antes de ser puxada. Desenhada com `border-left` para nao
   precisar de mais um elemento so para isso. */
.previa-corpo.com-gaveta {
  border-left: 3px solid color-mix(in srgb, var(--accent) 55%, transparent);
  padding-left: .5rem;
}

/* Os blocos da tela inicial, nas MESMAS 12 colunas da grade de verdade.

   Altura por linha fixa e pequena (7px): a previa e um selo, e o que importa
   nela e o ARRANJO -- quantos blocos, de que tamanho, em que ordem --, nao o
   conteudo, que nesta escala nao se leria de qualquer forma. */
.previa-grade {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  /* 10px por linha, e nao 7: com o nome dentro, um bloco de 2 linhas precisa
     de altura para uma palavra caber sem cortar no meio da letra. */
  grid-auto-rows: 10px;
  gap: 3px;
  /* `--linhas` vem do inline, calculado pelo maior bloco: sem teto a grade
     cresceria com o layout e a previa empurraria os botoes para fora da tela. */
  max-height: calc(var(--linhas, 14) * 10px);
  overflow: hidden;
  /* Esmaece embaixo: a tela inicial nao termina ali, e um corte reto pareceria
     que o Hub tem so aquilo. */
  mask-image: linear-gradient(to bottom, #000 70%, transparent);
}

/* ------------------------------------------- o passo no celular
   Seis cartoes com descricao, mais a previa, davam 1119px numa tela de 844:
   o "Continuar" nascia 262px abaixo da dobra, e quem entrasse pelo telefone
   nao via como seguir. O segundo perfil e justamente quem tende a entrar pelo
   celular, entao esta nao e a tela rara -- e uma das principais.

   O que encolhe: o respiro dos cartoes, o tamanho da descricao, a altura da
   previa. O que NAO encolhe: a lista de abas de cada objetivo, que e o que
   torna a promessa conferivel. */
@media (max-width: 560px) {
  .objetivos { gap: .4rem; }

  .objetivo {
    padding: .5rem .65rem;
    gap: .55rem;
  }

  /* As tres linhas do cartao coladas: titulo, descricao e abas continuam
     legiveis, e cada 2px aqui vale 12px na coluna de seis. */
  .objetivo-txt { gap: .05rem; }
  .objetivo-abas { margin-top: 0; font-size: .72rem; }

  .objetivo-ico {
    width: 30px;
    height: 30px;
  }

  .objetivo-txt .muted {
    font-size: .78rem;
    line-height: 1.35;
  }

  .ob-marca { margin-bottom: .8rem; }

  .previa { margin-top: .7rem; }

  /* Marcar duas areas abre duas listas de especialidade, e o passo passa de
     1100px: o "Continuar" ficava longe do polegar depois de cada escolha.
     A linha dos botoes gruda no pe da tela, sobre um fundo solido, e a
     pessoa segue sem precisar rolar de volta.

     So no passo dos assuntos (`#stepBody .ob-acoes`): os outros passos cabem
     na tela, e uma barra fixa neles seria peso sem motivo. */
  #stepBody .ob-acoes {
    position: sticky;
    bottom: 0;
    background: var(--surface);
    padding: .7rem 0 .2rem;
    margin-top: .8rem;
    box-shadow: 0 -8px 12px -6px rgb(0 0 0 / 35%);
  }

  /* O rotulo e o corpo mais justos: 19px separavam o "Continuar" da dobra no
     iPhone, e eles saem daqui sem custo de leitura. */
  .previa-rot { padding: .4rem .65rem .35rem; }
  .previa-corpo { padding: 0 .55rem .55rem; }

  /* A previa vira uma FITA: no computador ela mostra a tela inteira, e no
     celular o que cabe sao as primeiras linhas -- o bastante para a pessoa
     ver os blocos mudarem, que e o que ela faz aqui. */
  /* Linhas menores que no computador, mas nao tao curtas quanto antes: com o
     NOME dentro, um bloco de 2 linhas precisa caber uma palavra. 8px por
     linha deixa a primeira faixa inteira legivel, que e o que importa aqui. */
  .previa-grade {
    grid-auto-rows: 8px;
    max-height: 56px;
  }

  .previa-rot { margin-bottom: .35rem; }
  .previa-barra { margin-bottom: .35rem; }
}

.previa-bloco {
  border-radius: 3px;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  /* O nome dentro, centrado e cortado sem reticencias: numa miniatura, "..."
     rouba dois caracteres do pouco que cabe. O bloco pequeno mostra o comeco
     da palavra, e isso basta para reconhece-la. */
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 0 .2rem;
  font-size: .62rem;
  font-style: normal;
  line-height: 1.15;
  text-align: center;
  color: var(--text-dim);
  /* Os blocos ENTRAM, em vez de aparecerem prontos.
     
     A previa e redesenhada inteira a cada toque, entao a animacao roda de
     novo em todos: o efeito e a tela se remontando, que e exatamente o que
     acabou de acontecer. Curta (.18s) porque ela repete a cada clique, e uma
     animacao que se ve dez vezes tem de ser mais rapida que uma que se ve uma.
     
     A regra global de `prefers-reduced-motion` (no topo do arquivo) ja zera
     isto para quem pediu menos movimento. */
  animation: previa-bloco-entra .18s ease-out both;
}

@keyframes previa-bloco-entra {
  from { opacity: 0; transform: scale(.92); }
}

/* O icone do cartao reage ao toque com um pulso curto.
   
   `transition` sozinha ja troca a cor, mas a troca de cor e um estado, nao um
   gesto -- e a queixa de "so marquei checks" e justamente a falta do gesto. O
   pulso dura o suficiente para o olho registrar e some antes de cansar. */
.objetivo.ativo .objetivo-ico {
  animation: objetivo-pulso .22s ease-out;
}

@keyframes objetivo-pulso {
  50% { transform: scale(1.12); }
}

/* O rotulo de cada grupo dentro da aba. */
.cfg-rot {
  display: block;
  font-size: .78rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: .45rem;
}

/* O lado da gaveta apagado enquanto ela esta desligada: a escolha continua
   ali, dizendo que existe, mas sem fingir que vale agora. */
.nav-lado-off {
  opacity: .45;
  pointer-events: none;
}

/* O desenho de cada modo: um retangulo com a barra no lugar.
   "Em cima" e "embaixo" so se distinguem por ONDE ela esta, e tres linhas
   de texto pediriam que a pessoa imaginasse cada uma. */
/* `inline-block`, e nao o `inline` que um `<span>` e por padrao: em
   `inline` o navegador ignora `width` e `height`, e o desenho saia com 2px
   de largura -- invisivel. */
.nav-modo-desenho { display: inline-flex; flex: none; }
.nm-tela {
  display: block;
  position: relative;
  flex: none;
  width: 42px;
  height: 30px;
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  background: var(--surface-2);
}
.nm-barra { position: absolute; background: var(--accent); }
.nm-topo { left: 0; right: 0; top: 0; height: 6px; }
.nm-baixo { left: 0; right: 0; bottom: 0; height: 6px; }
.nm-lado { left: 0; top: 0; bottom: 0; width: 8px; }
