/* ==========================================================================
   Garagem — folha de estilo base
   Identidade visual da seção 3 do spec.

   Direção: instrumento, não brochura. Tons frios, superfícies quietas,
   estrutura por espaço e tonalidade — bordas discretas, sem sombras
   dramáticas. O único elemento escuro do app é o mostrador de hodômetro,
   que é a assinatura visual do produto.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* --- Paleta oficial (seção 3 do spec) --------------------------------- */
  --azul-aco: #2B6CA8;
  --grafite: #2D3748;
  --cinza-claro: #F1F4F7;
  --laranja-sinal: #E8752C;

  /* Derivadas da paleta — mesma matiz, só a luminosidade muda.
     Nunca introduzir uma quinta matiz. */
  --azul-aco-escuro: #235887;
  --azul-aco-claro: #E7EFF7;
  --grafite-claro: #3C4859;
  --laranja-sinal-fraco: #FCEFE5;

  /* --- Superfícies ------------------------------------------------------- */
  --canvas: var(--cinza-claro);      /* fundo da aplicação */
  --painel: #FFFFFF;                 /* cartões, listas, barras */
  --painel-elevado: #FFFFFF;         /* popovers e sheets (sobem por sombra) */
  --instrumento: var(--grafite);     /* mostrador escuro — assinatura */
  --campo: #FBFCFD;                  /* inputs: levemente recuados */
  /* Recuo que funciona sobre QUALQUER fundo: tinta grafite em opacidade baixa,
     mesma receita de `--borda`. `--campo` é um valor opaco calibrado contra o
     branco do `.cartao`, e por isso ele falha sobre `--canvas` — lá ele fica
     mais CLARO que o fundo e o trilho recuado vira um degrau para cima. Achado
     na Sessão 13b, com o `.alternador` do Financeiro, que é o primeiro controle
     do projeto a viver fora de um cartão. */
  --recuo: rgba(45, 55, 72, 0.05);

  /* --- Texto: quatro níveis ---------------------------------------------- */
  --texto: var(--grafite);
  --texto-secundario: #55617A;
  --texto-terciario: #7B8698;
  --texto-mudo: #A3ABBA;
  --texto-invertido: #F4F7FA;
  --texto-invertido-fraco: #9FAEC2;

  /* --- Bordas: baixa opacidade, some quando não se procura por ela ------- */
  --borda: rgba(45, 55, 72, 0.10);
  --borda-suave: rgba(45, 55, 72, 0.06);
  --borda-forte: rgba(45, 55, 72, 0.18);
  /* Sobre grafite a borda tem de vir da luz, não da tinta: rgba branca de baixa
     opacidade, o espelho de `--borda`. Usada na faixa escura da landing. */
  --borda-invertida: rgba(255, 255, 255, 0.12);
  --anel-foco: rgba(43, 108, 168, 0.35);

  /* --- Semânticas — cor só quando comunica estado ------------------------ */
  --alerta: var(--laranja-sinal);      /* vencido / vencendo */
  --alerta-fundo: var(--laranja-sinal-fraco);
  --ok: #2E7D5B;
  --ok-fundo: #E6F2EC;
  --erro: #C0392B;
  --erro-fundo: #FBEAE7;

  /* --- Tipografia (seção 3 do spec) -------------------------------------- */
  --fonte-titulo: 'Space Grotesk', 'Segoe UI', system-ui, sans-serif;
  --fonte-corpo: 'Inter', 'Segoe UI', system-ui, sans-serif;

  /* Escala 1.25 sobre base 15px, arredondada ao pixel */
  --t-legenda: 0.6875rem; /* 11px — labels de instrumento, em caixa alta */
  --t-mini: 0.8125rem;    /* 13px — metadados */
  --t-corpo: 0.9375rem;   /* 15px */
  --t-h4: 1.0625rem;      /* 17px */
  --t-h3: 1.25rem;        /* 20px */
  --t-h2: 1.5rem;         /* 24px */
  --t-h1: 1.875rem;       /* 30px */
  /* Passo seguinte da MESMA razão 1.25 (30 × 1.25 = 37,5 → 38). Existe para
     um lugar só: o herói de uma página de leitura, onde o título é a peça e
     não o rótulo de uma lista. Dentro do app nada usa isto — lá o que precisa
     de destaque é o dado, não o cabeçalho. */
  --t-display: 2.375rem;  /* 38px */

  /* --- Espaçamento: base 4px --------------------------------------------- */
  --e-1: 4px;
  --e-2: 8px;
  --e-3: 12px;
  --e-4: 16px;
  --e-5: 20px;
  --e-6: 24px;
  --e-8: 32px;
  --e-10: 40px;
  --e-12: 48px;
  /* A escala continua acima de 48px porque a landing precisa separar FAIXAS,
     não blocos: 48px era o maior respiro do app e virou o respiro médio de uma
     página que se lê rolando. Mesma base 4/8, sem valor solto. */
  --e-16: 64px;
  --e-20: 80px;
  --e-24: 96px;

  /* Densidade: oficina, não brochura. Cartão respira em 16px, não 24. */
  --pad-cartao: var(--e-4);
  --pad-secao: var(--e-6);

  /* --- Raio: escala, não valor único ------------------------------------- */
  --r-pequeno: 6px;   /* inputs, botões, chips */
  --r-medio: 10px;    /* cartões, mostradores */
  --r-grande: 16px;   /* sheets, modais */
  --r-total: 999px;   /* pílulas */

  /* --- Elevação: 1px ring + duas camadas suaves -------------------------- */
  --elev-0: 0 0 0 1px var(--borda);
  --elev-1: 0 0 0 1px rgba(45, 55, 72, 0.06),
            0 1px 2px -1px rgba(45, 55, 72, 0.08),
            0 2px 4px rgba(45, 55, 72, 0.04);
  --elev-2: 0 0 0 1px rgba(45, 55, 72, 0.06),
            0 4px 12px -4px rgba(45, 55, 72, 0.14),
            0 8px 24px -8px rgba(45, 55, 72, 0.10);
  /* Terceiro degrau, e o último. Existe para as duas peças da landing que
     precisam ficar ACIMA de uma faixa de cor (o painel do herói e o cartão de
     preço) — sobre `--canvas`, `--elev-2` some. Continua sendo ring + duas
     camadas: o que muda é a distância, não a dureza. */
  --elev-3: 0 0 0 1px rgba(45, 55, 72, 0.05),
            0 12px 28px -12px rgba(45, 55, 72, 0.18),
            0 28px 56px -24px rgba(45, 55, 72, 0.16);

  /* --- Movimento: sentido, não assistido --------------------------------- */
  --saida: cubic-bezier(0.23, 1, 0.32, 1);
  --entre-tela: cubic-bezier(0.77, 0, 0.175, 1);
  --dur-toque: 120ms;
  --dur-popover: 180ms;
  --dur-sheet: 260ms;

  /* --- Layout ------------------------------------------------------------ */
  --largura-max: 640px;   /* PWA mobile-first: conteúdo não vira planilha */
  --altura-header: 68px;
  --altura-nav: 60px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-top: env(safe-area-inset-top, 0px);
}

/* --------------------------------------------------------------------------
   2. Reset e base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100dvh;
  background: var(--canvas);
  color: var(--texto);
  font-family: var(--fonte-corpo);
  font-size: var(--t-corpo);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: var(--fonte-titulo);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.015em; /* títulos apertam opticamente */
  text-wrap: balance;
}

h1 { font-size: var(--t-h1); letter-spacing: -0.02em; }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); }
h4 { font-size: var(--t-h4); letter-spacing: -0.01em; }

p, li {
  text-wrap: pretty;
}

a {
  color: var(--azul-aco);
  text-decoration-color: rgba(43, 108, 168, 0.3);
  text-underline-offset: 2px;
}

a:hover {
  text-decoration-color: currentColor;
}

img, svg {
  display: block;
  max-width: 100%;
}

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

fieldset {
  min-width: 0;
  padding: 0;
  border: 0;
}

legend {
  padding: 0;
}

/* `hidden` tem de vencer qualquer `display` declarado depois dele — vários
   componentes deste projeto alternam visibilidade pelo atributo. */
[hidden] {
  display: none !important;
}

/* Foco visível e consistente em tudo que recebe teclado. */
:focus-visible {
  outline: 2px solid var(--anel-foco);
  outline-offset: 2px;
  border-radius: var(--r-pequeno);
}

/* Qualquer número dinâmico usa largura fixa — nada de layout dançando. */
.num,
.mostrador__valor,
.instrumento__valor {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   3. Utilitários de texto
   -------------------------------------------------------------------------- */

.legenda {
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.mini { font-size: var(--t-mini); color: var(--texto-secundario); }
.mudo { color: var(--texto-mudo); }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   4. Casca do app
   -------------------------------------------------------------------------- */

.app {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100dvh;
}

.app__conteudo {
  width: 100%;
  max-width: var(--largura-max);
  margin-inline: auto;
  padding: var(--e-5) var(--e-4) var(--e-10);
  /* `.app` é grid, e item de grid nasce com `min-width: auto` — ou seja, ele se
     recusa a ficar menor que o min-content do conteúdo. Bastava uma fila de
     chips mais larga que a tela para o <main> inteiro esticar e a PÁGINA ganhar
     scroll horizontal em 375px, com o `overflow-x: auto` do `.filtro` sem
     efeito nenhum: quem deveria rolar era o trilho de chips, e quem rolava era
     o documento. Encontrado na Sessão 7, com os dois filtros de Gastos; valia
     igual para o filtro de Manutenção, só não tinha aparecido ainda. */
  min-width: 0;
}

/* --- Header: mesma cor do canvas. Não fragmentar a tela em dois mundos. -- */
.header {
  position: sticky;
  top: 0;
  z-index: 20;
  padding-top: var(--safe-top);
  background: var(--canvas);
  border-bottom: 1px solid var(--borda-suave);
}

/* A barra passou a ter um ocupante só (Sessão 18a), e o lockup vai CENTRADO.

   Alinhado à esquerda, ele deixaria dois terços da barra vazios sem que nada
   ali significasse ausência de alguma coisa — o vão só existia antes porque o
   mostrador o preenchia. Centrado, a barra volta a ser uma peça inteira, e o
   que ela diz é exatamente o que ela faz: identidade, sem função. */
.header__interno {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: var(--largura-max);
  min-height: var(--altura-header);
  margin-inline: auto;
  padding: var(--e-2) var(--e-4);
}

/* Lockup, não palavra solta — mesma peça da landing e das telas de Auth,
   um degrau menor. Era a última superfície do produto que se apresentava só
   por escrito, e é a que a pessoa vê todo dia. */
.header__marca {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  flex-shrink: 0;
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 700;
  letter-spacing: -0.02em;
  /* `--texto`, e não `--grafite` cru: os dois valem #2D3748 hoje, e a landing
     (`.landing__marca`) já escrevia o do meio. Duas superfícies que exibem o
     MESMO lockup não podem estar presas a tokens diferentes — quem trocar o
     tom do texto um dia trocaria em uma e não na outra, e o desencontro
     apareceria no lugar em que as duas telas se prometem uma à outra. */
  color: var(--texto);
}

/* Sem `border-radius`: o `<rect rx="14">` do símbolo já desenha o canto, e em
   26px ele cai em 5,7px — os 6px que a regra recortava por fora eram um
   segundo canto por cima do primeiro. A landing nunca teve essa linha, e é a
   mesma peça nas duas. */
.header__simbolo {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
}

/* A palavra ficava escondida abaixo de 420px porque disputava a barra com o
   mostrador, e a leitura de hodômetro ganhava a disputa. Sem o mostrador não
   há disputa — e um lockup pela metade justamente na largura em que o app é
   usado esconderia a marca de quem a vê todo dia. A regra saiu na Sessão 18a;
   a `.aparelho` da landing continua escondendo a palavra por conta própria,
   porque lá a medida é a da JANELA de quem lê a landing, não a da tela
   desenhada dentro da moldura. */

/* --------------------------------------------------------------------------
   5. O mostrador — a leitura de hodômetro de um veículo (assinatura)

   Placa grafite com o km em dígitos tabulares, e o único bloco escuro do app.

   Ele morou no topo da casca da Sessão 1 à 17, onde era leitura E seletor de
   veículo ativo. A Sessão 18a tirou as duas funções de lá — a de seletor
   porque veículo ativo virou consequência de navegação, e a de leitura porque
   ela não tinha por que atravessar telas que falam de outra coisa. A peça não
   foi descartada: ela é o cabeçalho de `#/veiculo`, onde a placa grafite diz
   o km DAQUELE veículo, que é o que ela sempre quis dizer.

   O que saiu junto foi só o que era botão — cursor, hover, `:active` e a seta
   do popover. Medidas, tipografia e hierarquia (apelido demovido, valor
   liderando, unidade inline) são as da Sessão 13b, intactas.
   -------------------------------------------------------------------------- */

.mostrador {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  width: 100%;
  min-width: 0;
  padding: var(--e-3);
  background: var(--instrumento);
  color: var(--texto-invertido);
  border-radius: var(--r-medio);
  text-align: left;
}

.mostrador__identificacao {
  flex: 1;
  min-width: 0;
}

/* Identificação, não leitura. Estava em 15/600 contra um valor de 20/600 na
   mesma cor — duas vozes fortes lado a lado, e o olho não sabia qual era o
   instrumento. Desce um degrau para que o km lidere sem ambiguidade. */
.mostrador__apelido {
  display: block;
  font-family: var(--fonte-titulo);
  font-size: var(--t-mini);
  font-weight: 600;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mostrador__placa {
  display: block;
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--texto-invertido-fraco);
  font-variant-numeric: tabular-nums;
}

.mostrador__leitura {
  display: flex;
  align-items: baseline;
  text-align: right;
  flex-shrink: 0;
}

.mostrador__valor {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

/* Unidade INLINE, como em todo o resto do app (`.instrumento__unidade`).
   Empilhada, ela ocupava uma segunda linha para dizer o que já se lê do
   contexto e obrigava o mostrador a crescer; ao lado, "75.810 km" volta a
   ser uma leitura só — que é o que a mesma peça faz na Garagem, na previsão
   e no Financeiro. */
.mostrador__unidade {
  margin-left: 0.28em;
  font-size: var(--t-mini);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texto-invertido-fraco);
}

/* --------------------------------------------------------------------------
   6. Navegação inferior

   Tab bar, não sidebar: o uso real é em pé, no posto ou na oficina, com uma
   mão. Quatro destinos, e desde a Sessão 18a não há um quinto item "Mais":
   tudo que não está aqui trabalha sobre UM veículo e se alcança de dentro da
   tela dele.

   `.nav__link--destaque` saiu junto (a caixa de `--azul-aco-claro` atrás do
   ícone de Abastecer, Sessão 16). Ele existia porque a barra misturava
   frequências muito diferentes — Abastecer toda semana ao lado de Manutenção
   duas vezes por ano — e realçava o item que se usava mais. A barra nova não
   mistura frequência nenhuma: os quatro itens respondem a assuntos distintos,
   e nenhum é o "mais usado" dos outros. Realce sem hierarquia para marcar é
   enfeite, e CSS órfão não fica inerte — continua casando.
   -------------------------------------------------------------------------- */

.nav {
  position: sticky;
  bottom: 0;
  z-index: 20;
  padding-bottom: var(--safe-bottom);
  background: var(--painel);
  border-top: 1px solid var(--borda);
}

.nav__lista {
  display: flex;
  width: 100%;
  max-width: var(--largura-max);
  margin-inline: auto;
  list-style: none;
  padding: 0;
}

.nav__item { flex: 1; }

.nav__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: var(--altura-nav); /* alvo de toque acima de 44px */
  padding: var(--e-2) var(--e-1);
  color: var(--texto-terciario);
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: color var(--dur-toque) var(--saida);
}

.nav__link:hover { color: var(--texto-secundario); }
.nav__link:active { transform: scale(0.96); }

.nav__link[aria-current='page'] {
  color: var(--azul-aco);
}

.nav__icone {
  width: 22px;
  height: 22px;
  stroke: currentColor;
  stroke-width: 1.75;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --------------------------------------------------------------------------
   7. Cartões e placas de instrumento
   -------------------------------------------------------------------------- */

.cartao {
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-1);
  padding: var(--pad-cartao);
}

/* Raio concêntrico: filho = pai − padding. */
.cartao > .cartao__interno {
  border-radius: calc(var(--r-medio) - var(--pad-cartao) / 2);
}

.cartao__cabecalho {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
  margin-bottom: var(--e-3);
}

/* Placa de instrumento: label demovido em caixa alta, valor lidera. */
.instrumento {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
}

.instrumento__rotulo {
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.instrumento__valor {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--texto);
}

.instrumento__nota {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* Unidade acompanha o valor, meia altura e demovida: "45.000 km" tem de ler
   como uma leitura só, não como duas informações. */
.instrumento__unidade {
  margin-left: 0.28em;
  font-size: var(--t-mini);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.instrumento--alerta .instrumento__valor { color: var(--alerta); }

/* Duas leituras lado a lado num cartão estreito (km previsto + data prevista).
   24px em duas colunas quebraria a data em telas de 360px; 20px continua sendo
   leitura de instrumento e cabe. Só o tamanho muda — fonte, peso e tabular
   permanecem, senão deixa de ser a mesma peça. */
.instrumento--compacto .instrumento__valor {
  font-size: var(--t-h3);
  letter-spacing: -0.015em;
}

/* Ficha: rótulo à esquerda, valor à direita, uma linha por campo — Sessão 16,
   para os dados básicos no resumo do veículo.

   Parece `.sem-previsao__item`, e não é a mesma peça: lá o PESO está à
   esquerda (o tipo de manutenção, em Space Grotesk 600) e a direita é apoio
   (`--texto-terciario`); aqui é o contrário — "Tipo", "Marca" e "Ano" são
   rótulos de instrumento, e o dado é o que se veio ler. Mesma medida, ênfase
   trocada: agrupar os dois seletores faria o próximo ajuste de um estragar o
   outro.

   `<dl>` e não `<ul>` porque é literalmente uma lista de definições — rótulo e
   valor, pareados. */
.ficha {
  list-style: none;
  padding: 0;
  margin: 0;
}

.instrumento + .ficha { margin-top: var(--e-3); }

.ficha__linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-2) 0;
}

.ficha__linha + .ficha__linha {
  border-top: 1px solid var(--borda-suave);
}

.ficha__rotulo {
  flex-shrink: 0;
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.ficha__valor {
  margin: 0;
  min-width: 0;
  font-size: var(--t-corpo);
  font-weight: 500;
  text-align: right;
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   8. Botões
   -------------------------------------------------------------------------- */

.botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e-2);
  min-height: 44px;
  padding: 0 var(--e-4);
  border: 1px solid transparent;
  border-radius: var(--r-pequeno);
  font-family: var(--fonte-corpo);
  font-size: var(--t-corpo);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  /* `.botao` também veste `<a>` (a landing e as telas de Auth usam os dois), e
     o sublinhado do reset de link atravessava o rótulo do botão. Achado na
     Sessão 13a olhando a página renderizada pela primeira vez — em CSS
     computado o valor está lá desde a Sessão 1 e não chamava atenção. */
  text-decoration: none;
  transition: background-color var(--dur-toque) var(--saida),
              border-color var(--dur-toque) var(--saida),
              transform var(--dur-toque) var(--saida);
}

.botao:active { transform: scale(0.97); }

.botao:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.botao--primario {
  background: var(--azul-aco);
  color: #FFFFFF;
}
.botao--primario:hover:not(:disabled) { background: var(--azul-aco-escuro); }

.botao--secundario {
  background: var(--painel);
  color: var(--texto);
  border-color: var(--borda-forte);
}
.botao--secundario:hover:not(:disabled) { background: var(--cinza-claro); }

.botao--fantasma {
  background: transparent;
  color: var(--azul-aco);
}
.botao--fantasma:hover:not(:disabled) { background: var(--azul-aco-claro); }

/* Ação destrutiva: vermelho de `--erro`, nunca o laranja. Laranja neste
   projeto é vencimento de manutenção e só — usá-lo aqui apagaria a única
   coisa que ele significa. */
.botao--destrutivo {
  background: var(--erro);
  color: #FFFFFF;
}
.botao--destrutivo:hover:not(:disabled) { background: #A5322A; }

/* Variante fantasma da mesma ideia, para a linha de ações de um cartão. */
.botao--perigo { color: var(--erro); }
.botao--perigo:hover:not(:disabled) { background: var(--erro-fundo); }

/* Ação secundária dentro de cartão: rótulo e recuo menores, mas os 44px de
   altura ficam — a regra de alvo de toque não abre exceção por hierarquia. */
.botao--pequeno {
  padding: 0 var(--e-3);
  font-size: var(--t-mini);
  gap: var(--e-1);
}

/* O outro extremo da mesma escala, e a contrapartida de `.botao--pequeno`:
   aqui a altura SOBE junto, porque este botão não é ação secundária dentro de
   um cartão — é o foco de uma tela inteira, e numa página de leitura o CTA
   precisa liderar por tamanho, não só por cor. Só o herói, o preço e o fecho
   da landing o usam. */
.botao--grande {
  min-height: 52px;
  padding: 0 var(--e-6);
  font-size: var(--t-h4);
  font-weight: 600;
}

/* Sobre a faixa grafite o azul de ação some (#2B6CA8 sobre #2D3748 é contraste
   de tinta sobre tinta). Quem lidera num fundo escuro é a luz: o botão inverte
   e o grafite volta como texto. Não entra cor nova — é a mesma dupla, trocada
   de lado. */
.botao--invertido {
  background: var(--texto-invertido);
  color: var(--grafite);
}
.botao--invertido:hover:not(:disabled) { background: #FFFFFF; }

/* Par secundário da inversão: contorno de luz sobre o escuro, sem preencher. */
.botao--contorno {
  background: transparent;
  color: var(--texto-invertido);
  border-color: var(--borda-invertida);
}
.botao--contorno:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.24);
}

.botao--bloco { width: 100%; }

.botao__icone {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  stroke: currentColor;
  stroke-width: 1.9;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Botão só de ícone — fechar sheet. Quadrado, alvo de 44px mantido. */
.botao-icone {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-right: calc(var(--e-2) * -1);
  background: transparent;
  border: 0;
  border-radius: var(--r-pequeno);
  color: var(--texto-terciario);
  cursor: pointer;
  transition: background-color var(--dur-toque) var(--saida),
              color var(--dur-toque) var(--saida);
}

.botao-icone:hover {
  background: var(--cinza-claro);
  color: var(--texto);
}

.botao-icone svg { stroke: currentColor; fill: none; }

/* `.botao-icone--acento` saiu na Sessão 18b, junto com o último consumidor.

   Ele nasceu na 16 para o botão de resumo no cartão do Dashboard e passou na
   18a para a engrenagem no cabeçalho de `#/veiculo`: nos dois casos, um ícone
   SEM RÓTULO que precisava ser achado, e o azul era a tentativa de fazê-lo
   ser achado. Nos dois casos a resposta certa acabou sendo a mesma, e não era
   cor — foi dar um nome à ação ("Administrar" na 18a, "Editar ou excluir" na
   18b). O realce existia para compensar a falta do rótulo; com o rótulo, não
   há o que compensar.

   Removido e não guardado, pela regra que a `.vitrine` deixou na Sessão 15:
   CSS órfão não fica inerte, continua casando. */

/* --------------------------------------------------------------------------
   9. Campos de formulário

   Inputs são recuados: fundo levemente mais escuro que a superfície,
   sinalizando "escreva aqui" sem borda pesada.
   -------------------------------------------------------------------------- */

.campo {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
}

.campo__rotulo {
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-secundario);
}

.campo__controle {
  width: 100%;
  min-height: 44px;
  padding: var(--e-2) var(--e-3);
  background: var(--campo);
  border: 1px solid var(--borda-forte);
  border-radius: var(--r-pequeno);
  transition: border-color var(--dur-toque) var(--saida),
              box-shadow var(--dur-toque) var(--saida);
}

.campo__controle::placeholder { color: var(--texto-mudo); }

/* Campo de texto longo — Sessão 16, para as observações de Manutenção.

   Só o que um <textarea> precisa a mais que um <input>: altura mínima de três
   linhas, entrelinha de leitura e o `resize` limitado ao eixo vertical.
   Redimensionar na horizontal dentro de um sheet de largura fixa só produziria
   um campo maior que o formulário que o contém.

   Nada mais muda: fundo `--campo`, borda e anel de foco continuam sendo os do
   `.campo__controle`, porque é o mesmo componente. */
.campo__controle--texto {
  min-height: 88px;
  line-height: 1.5;
  resize: vertical;
}

.campo__controle:focus {
  outline: none;
  border-color: var(--azul-aco);
  box-shadow: 0 0 0 3px var(--anel-foco);
}

.campo__controle:disabled {
  background: var(--cinza-claro);
  color: var(--texto-mudo);
  cursor: not-allowed;
}

.campo__ajuda { font-size: var(--t-mini); color: var(--texto-terciario); }
.campo__erro { font-size: var(--t-mini); color: var(--erro); }

/* Aviso que NÃO bloqueia o envio — hoje, km de manutenção lançado fora de
   ordem cronológica.

   Fica um degrau acima de `.campo__ajuda` e um abaixo de `.campo__erro`: ganha
   peso e o texto principal, mas nenhuma cor semântica. Vermelho seria mentira
   (não impede nada) e laranja gastaria a única coisa que o laranja significa
   neste app, que é vencimento de manutenção. Hierarquia por peso, não por
   matiz. */
.campo__nota {
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-secundario);
}

.campo--invalido .campo__controle {
  border-color: var(--erro);
}

.campo__obrigatorio {
  color: var(--erro);
  font-weight: 600;
}

/* Dois campos curtos na mesma linha (marca/modelo, ano/km). Em telas muito
   estreitas volta a empilhar: 44px de alvo importa mais que a linha. */
.campo-par {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--e-3);
}

@media (max-width: 360px) {
  .campo-par { grid-template-columns: 1fr; }
}

/* Placa lê como placa: caixa alta, espaçada, na fonte de instrumento. */
.campo__controle--placa {
  font-family: var(--fonte-titulo);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* --- Segmentado: escolha de tipo de veículo --------------------------------

   Quatro opções fixas e mutuamente exclusivas, todas visíveis: um <select>
   esconderia a lista atrás de um toque e perderia o ícone, que é o que faz a
   escolha ser reconhecida sem ler.
   -------------------------------------------------------------------------- */

.segmentado__opcoes {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--e-1);
  margin-top: var(--e-1);
}

.segmentado__opcao {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--e-1);
  min-height: 68px;
  padding: var(--e-2) var(--e-1);
  background: var(--campo);
  border: 1px solid var(--borda-forte);
  border-radius: var(--r-pequeno);
  font-size: var(--t-legenda);
  font-weight: 500;
  color: var(--texto-secundario);
  text-align: center;
  cursor: pointer;
  transition: background-color var(--dur-toque) var(--saida),
              border-color var(--dur-toque) var(--saida),
              color var(--dur-toque) var(--saida);
}

/* O radio continua no DOM e recebe teclado; só não é desenhado. */
.segmentado__opcao input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.segmentado__icone {
  width: 24px;
  height: 24px;
  stroke: currentColor;
  stroke-width: 1.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.segmentado__opcao:hover { background: var(--painel); }

.segmentado__opcao:has(input:checked) {
  background: var(--azul-aco-claro);
  border-color: var(--azul-aco);
  color: var(--azul-aco-escuro);
}

.segmentado__opcao:has(input:focus-visible) {
  outline: 2px solid var(--anel-foco);
  outline-offset: 2px;
}

/* --- Escolha de foto ------------------------------------------------------- */

.foto-escolha {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  margin-top: var(--e-1);
}

.foto-escolha__previa {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 72px;
  height: 72px;
  overflow: hidden;
  background: var(--campo);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-0);
  color: var(--texto-mudo);
}

.foto-escolha__previa--cheia { background: var(--grafite); }

/* A miniatura do comprovante já gravado é botão: abre o arquivo em aba nova
   pela signed URL. Herda a mesma caixa de 72px — o que muda é só o affordance
   de que dá para tocar. Desabilitada enquanto o arquivo é só uma escolha ainda
   não enviada. */
.foto-escolha__previa--acionavel {
  padding: 0;
  border: 0;
  background: var(--grafite);
  cursor: pointer;
}

.foto-escolha__previa--acionavel:disabled { cursor: default; }

.foto-escolha__previa img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.foto-escolha__icone {
  width: 24px;
  height: 24px;
  stroke: currentColor;
  stroke-width: 1.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.foto-escolha__acoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

.foto-escolha__acoes .campo__ajuda { flex-basis: 100%; }

/* --------------------------------------------------------------------------
   10. Selos de estado — laranja é vencimento, nunca decoração
   -------------------------------------------------------------------------- */

.selo {
  display: inline-flex;
  align-items: center;
  gap: var(--e-1);
  padding: 3px var(--e-2);
  border-radius: var(--r-total);
  font-size: var(--t-legenda);
  font-weight: 600;
  letter-spacing: 0.02em;
}

.selo--alerta { background: var(--alerta-fundo); color: #A5501A; }
.selo--ok     { background: var(--ok-fundo);     color: var(--ok); }
.selo--erro   { background: var(--erro-fundo);   color: var(--erro); }
.selo--neutro { background: var(--cinza-claro);  color: var(--texto-secundario); }

/* --------------------------------------------------------------------------
   11. Estados de dados — vazio, carregando, erro
   -------------------------------------------------------------------------- */

/* Peso calibrado na Sessão 13b, ao ver o estado renderizado: 48px de recuo
   em cima e embaixo faziam um cartão de 340px de altura para dizer uma frase
   e oferecer um botão — nem desanimador nem discreto, só grande. 32px dá
   presença sem transformar "ainda não há nada" no assunto principal da tela. */
.estado {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e-2);
  padding: var(--e-8) var(--e-5);
  text-align: center;
}

/* Dentro de um cartão que já tem outro conteúdo (a explicação do gráfico sem
   pontos suficientes), o estado é um recado, não a tela inteira. */
.estado--embutido {
  padding: var(--e-5) var(--e-2);
}

.estado__titulo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 600;
  color: var(--texto);
  /* "Nenhuma manutenção registrada" cabe em uma linha em 375px; a medida
     existe para o título mais longo, e `balance` reparte as duas linhas
     quando ela é atingida em vez de deixar uma palavra órfã embaixo. */
  text-wrap: balance;
  max-width: 30ch;
}

.estado__texto {
  font-size: var(--t-mini);
  color: var(--texto-terciario);
  max-width: 34ch;
}

.estado__acao { margin-top: var(--e-3); }

/* Ícone de estado vazio: ganha CAIXA, como `.recurso__marca` na landing e
   `.autenticacao__selo` nas telas de Auth. Solto sobre o branco ele era o
   único ícone do produto sem apoio nenhum — lia como desenho esquecido no
   meio de um cartão vazio, que é justamente a impressão que um estado vazio
   não pode dar. O tom continua baixo: é sinal de categoria, não ilustração. */
.estado__marca {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-bottom: var(--e-2);
  background: var(--cinza-claro);
  border-radius: var(--r-medio);
}

.estado__icone {
  width: 24px;
  height: 24px;
  stroke: var(--texto-terciario);
  stroke-width: 1.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Esqueleto de leitura: usado enquanto a primeira carga da garagem não voltou.
   "Ainda não sei" não pode aparecer como "não tem nada". */
.carga {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding: var(--e-2) 0;
}

.carga__linha { height: 14px; }
.carga__linha--curta { width: 40%; }
.carga__linha--media { width: 68%; }

/* Esqueleto de carregamento */
.esqueleto {
  background: linear-gradient(
    90deg,
    rgba(45, 55, 72, 0.05) 25%,
    rgba(45, 55, 72, 0.09) 37%,
    rgba(45, 55, 72, 0.05) 63%
  );
  background-size: 400% 100%;
  border-radius: var(--r-pequeno);
  animation: esqueleto 1.4s ease-in-out infinite;
}

@keyframes esqueleto {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* --------------------------------------------------------------------------
   11b. Lista do menu "Mais"

   Cartão único com linhas divididas, não cartões soltos: são destinos de
   navegação, não conteúdo — devem ler como um índice.
   -------------------------------------------------------------------------- */

.lista-mais {
  list-style: none;
  padding: 0;
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-1);
  overflow: hidden;
}

.lista-mais li + li .item-mais {
  border-top: 1px solid var(--borda-suave);
}

.item-mais {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  min-height: 60px;
  padding: var(--e-3) var(--e-4);
  color: inherit;
  text-decoration: none;
  transition: background-color var(--dur-toque) var(--saida);
}

/* O mesmo índice serve a destino de navegação (<a>, no menu "Mais") e a ação
   que abre um sheet (<button>, em Configurações desde a Sessão 11). O elemento
   muda porque a natureza muda — link navega, botão age —, e o desenho não:
   são a mesma linha de índice, e inventar um segundo componente para ela só
   criaria duas versões da mesma coisa para divergirem. */
button.item-mais {
  width: 100%;
  font: inherit;
  text-align: left;
  background: transparent;
  border: 0;
  cursor: pointer;
}

.item-mais:hover { background: var(--cinza-claro); }
.item-mais:active { background: var(--azul-aco-claro); }

/* Alinhado ao TÍTULO, não ao centro do bloco. Com descrição de duas linhas o
   ícone caía entre o título e a descrição, apontando para o vão — em "Mais",
   onde metade dos itens tem descrição longa, era a fila inteira desalinhada.
   O deslocamento de 2px é ótico: o traço do ícone tem menos massa em cima que
   a caixa da letra. */
.item-mais__icone {
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 2px;
  width: 20px;
  height: 20px;
  stroke: var(--azul-aco);
  stroke-width: 1.75;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.item-mais__texto {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.item-mais__titulo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-corpo);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.item-mais__descricao {
  font-size: var(--t-mini);
  color: var(--texto-terciario);
}

.item-mais__seta {
  flex-shrink: 0;
  color: var(--texto-mudo);
  stroke: currentColor;
}

/* --------------------------------------------------------------------------
   Interruptor — Sessão 17

   O PRIMEIRO controle de liga/desliga do projeto, e ele nasce dentro do
   `.item-mais` em vez de virar componente próprio: a linha de índice de 60px
   já existe, já tem título, descrição e alvo de toque de largura inteira. O
   que muda é o que ocupa a ponta direita — no índice é a seta (`vai levar você
   a algum lugar`), aqui é o interruptor (`isto está ligado`).

   O ELEMENTO É O `<button role="switch">` DA LINHA INTEIRA, não um `<input
   type="checkbox">` escondido. `role="switch"` é lido como "ligado/desligado"
   em vez de "marcado", que é a diferença entre um estado e uma escolha de
   formulário — e o botão já é a semântica certa de "isto age agora", sem
   Salvar. O desenho abaixo é puramente visual: quem manda no estado é
   `aria-checked`, então leitor de tela e olho nunca podem divergir.

   Cor: `--azul-aco` quando ligado, `--borda-forte` quando desligado. Nada de
   verde: a paleta do projeto tem quatro matizes e ligado não é "sucesso" —
   é só ligado.
   -------------------------------------------------------------------------- */

.interruptor {
  flex-shrink: 0;
  position: relative;
  width: 44px;
  height: 26px;
  border-radius: 999px;
  background: var(--borda-forte);
  transition: background-color var(--dur-toque) var(--saida);
}

.interruptor::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--painel);
  box-shadow: 0 1px 2px rgba(45, 55, 72, 0.25);
  transition: transform var(--dur-toque) var(--saida);
}

[aria-checked='true'] .interruptor { background: var(--azul-aco); }
[aria-checked='true'] .interruptor::after { transform: translateX(18px); }

/* Enquanto a permissão do navegador está sendo pedida ou a linha está sendo
   gravada, a linha inteira fica inerte — sem isso, dois toques rápidos
   abririam duas caixas de permissão. O tom vem da opacidade, não de uma cor
   nova de "desabilitado": o controle continua sendo o mesmo, só está ocupado. */
.item-mais[aria-busy='true'] {
  opacity: 0.55;
  pointer-events: none;
}

code {
  font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
  font-size: 0.9em;
  padding: 1px 5px;
  background: var(--cinza-claro);
  border-radius: 4px;
  color: var(--texto-secundario);
}

/* --------------------------------------------------------------------------
   12. Entrada de vista

   Nunca de scale(0) — nada aparece do nada.
   -------------------------------------------------------------------------- */

/* 32px ENTRE seções contra 12px DENTRO delas (`.secao`), fixado na Sessão 13b.
   Era 20 contra 12, e uma razão de 1,7 não separa nada: o título de uma seção
   ficava tão perto do cartão da seção anterior quanto do próprio corpo, e a
   vista lia como uma pilha de cartões em vez de três blocos com assunto
   próprio. É o mesmo raciocínio que a 13a aplicou às faixas da landing —
   respiro desigual é o que produz agrupamento —, na régua do app. */
.vista {
  display: flex;
  flex-direction: column;
  gap: var(--e-8);
  animation: entrada var(--dur-popover) var(--saida) both;
}

@keyframes entrada {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.vista__cabecalho {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--e-3);
}

/* Voltar + título, do lado esquerdo do cabeçalho — Sessão 18a, a tela de um
   veículo. É o único lugar do app com um passo para trás: todas as outras
   vistas são destino de tab bar, e tab bar não tem "de onde vim".

   `align-items: flex-end` alinha a base do botão com a base do <h1>, que é o
   que o cabeçalho já faz com a ação da direita. `min-width: 0` porque o
   apelido pode ser longo e é ele quem tem de truncar, não o botão. */
.vista__identidade {
  display: flex;
  align-items: flex-end;
  gap: var(--e-2);
  min-width: 0;
}

.vista__identidade-texto { min-width: 0; }

/* `.botao-icone` nasceu com `margin-right` negativo para o canto DIREITO de um
   cabeçalho de sheet — é o que faz o alvo de 44px sangrar até a borda sem
   afastar o conteúdo. Aqui ele está no canto esquerdo, então o recuo troca de
   lado: sem isso, o ícone fica 8px para dentro da margem que o título respeita
   e as duas bordas do cabeçalho deixam de se corresponder.

   E ele sobe um nível de texto (Sessão 18b). O terciário é o tom certo para o
   "fechar" de um cabeçalho de sheet, onde o Esc e o backdrop fazem o mesmo
   trabalho; aqui ele é a única saída desenhada da tela, ao lado de um título
   de 30px. No mesmo cinza claro de um rótulo de apoio, um traço de 2px lia
   como pontuação e não como controle. */
.vista__identidade .botao-icone {
  margin-right: 0;
  margin-left: calc(var(--e-2) * -1);
  color: var(--texto-secundario);
}

/* --------------------------------------------------------------------------
   12b. Aviso de resultado

   Confirmação curta acima da lista, não toast flutuante: o retorno pertence ao
   contexto da ação e não deve tapar conteúdo nem exigir pressa para ler.
   -------------------------------------------------------------------------- */

.aviso {
  padding: var(--e-2) var(--e-3);
  border-radius: var(--r-pequeno);
  font-size: var(--t-mini);
  font-weight: 500;
  background: var(--cinza-claro);
  color: var(--texto-secundario);
  box-shadow: var(--elev-0);
}

.aviso--ok     { background: var(--ok-fundo);     color: var(--ok); }
.aviso--alerta { background: var(--alerta-fundo);  color: #A5501A; }
.aviso--erro   { background: var(--erro-fundo);   color: var(--erro); }

/* --------------------------------------------------------------------------
   12c. Cartão de veículo

   Um cartão por veículo, não linha de lista: cada um carrega identificação,
   uma leitura de instrumento (km) e três ações. Linha de tabela não sustenta
   isso em tela de celular.

   O veículo ativo se distingue por anel azul, não por fundo escuro — o fundo
   grafite é exclusividade do mostrador do topo (ver "Assinatura" no
   system.md); replicá-lo aqui esvaziaria o sentido dele.
   -------------------------------------------------------------------------- */

.lista-veiculos {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  list-style: none;
  padding: 0;
}

.cartao-veiculo {
  display: grid;
  gap: var(--e-3);
}

.cartao-veiculo--ativo {
  box-shadow: 0 0 0 1.5px var(--azul-aco),
              0 2px 8px -2px rgba(43, 108, 168, 0.18);
}

.cartao-veiculo__topo {
  display: flex;
  align-items: flex-start;
  gap: var(--e-3);
}

.avatar-veiculo {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  overflow: hidden;
  background: var(--azul-aco-claro);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-0);
  color: var(--azul-aco);
}

/* Com foto, o fundo azul-claro sai: a imagem cobre o quadrado inteiro. */
.avatar-veiculo--foto { background: var(--grafite); }

.avatar-veiculo__icone {
  width: 26px;
  height: 26px;
  stroke: currentColor;
  stroke-width: 1.5;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.avatar-veiculo__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cartao-veiculo__identificacao {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.cartao-veiculo__nome {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 600;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

.cartao-veiculo__meta {
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.cartao-veiculo__ficha {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

.cartao-veiculo__leitura { gap: 0; }

/* Canto superior direito do cartão: o selo "Ativo" e, desde a Sessão 16, o
   botão de resumo.

   EMPILHADOS, não lado a lado. Em 375px o cartão tem ~343px: tirando o avatar
   (52) e os dois gaps (24), sobram 267 para identificação + canto. Com selo
   (~50) e botão (44) na horizontal o canto come 102px, e "Hilux do trabalho"
   quebra em duas linhas — justamente no aparelho em que o app é usado. Na
   vertical o canto custa a largura do mais largo dos dois (~50px) e o cartão
   cresce em altura, que é a dimensão que ele tem de sobra.

   O `margin-right` negativo que o `.botao-icone` traz de nascença fica: ele
   alinha OPTICAMENTE o traço do ícone com a borda do texto — sem ele, os 12px
   de folga interna do botão de 44px somariam ao padding do cartão e o ícone
   pareceria solto no meio do nada. É a mesma razão pela qual ele existe no
   cabeçalho do sheet. */
.cartao-veiculo__canto {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex-shrink: 0;
  gap: var(--e-1);
}

/* Ações separadas do conteúdo por um divisor, não por espaço solto: fica claro
   que a linha inteira pertence àquele veículo. */
/* Linha de ações no pé de um cartão, atrás de um divisor. Nasceu no cartão de
   veículo (Sessão 2) e virou seletor agrupado na Sessão 11, quando o cartão de
   exclusão de conta em Configurações pediu exatamente o mesmo arranjo — mesma
   regra num lugar só, como `.origem` fez com `.previsao__origem`. O nome antigo
   continua valendo: duas cópias divergiriam na primeira correção. */
.cartao__acoes,
.cartao-veiculo__acoes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2);
  padding-top: var(--e-3);
  border-top: 1px solid var(--borda-suave);
}

/* O cartão traz `padding` do próprio token; o divisor precisa nascer colado no
   texto que ele separa. */
.cartao__acoes { margin-top: var(--e-3); }

/* O CTA do cartão de veículo ocupa a linha inteira — Sessão 18a.

   Eram três botões aqui (usar, editar, excluir), e o primeiro empurrava os
   outros para a direita com `margin-right: auto`. Agora é um, e ele é a porta
   do veículo: dar-lhe a largura do cartão é o que o faz parecer o destino da
   peça em vez de mais um controle no rodapé dela. */
.cartao-veiculo__acoes .botao--bloco { flex: 1 1 100%; }

/* O botão de cadastrar não é do último cartão: respira mais que o vão entre
   cartões (12px) e menos que o corte entre seções (32px) — ele ainda pertence
   à lista, só não é um item dela. */
.garagem__adicionar { margin-top: var(--e-4); }

/* --------------------------------------------------------------------------
   12d. Sheet — cadastro e edição de veículo

   <dialog> nativo: foco preso, Esc e backdrop sem JS de acessibilidade
   reinventado. Sobe pela base porque o formulário é longo e o polegar fica
   embaixo — os tokens --r-grande, --dur-sheet e --entre-tela foram reservados
   na Sessão 1 exatamente para esta camada.
   -------------------------------------------------------------------------- */

.sheet {
  position: fixed;
  /* `width: auto` de propósito: com left/right em 0, é o par que resolve a
     largura, e só então `max-width` a limita e `margin-inline: auto` centra.
     Com `width: 100%` as margens automáticas ficam sem folga para distribuir e
     o sheet gruda na esquerda em tela larga. */
  inset: auto 0 0 0;
  width: auto;
  max-width: var(--largura-max);
  max-height: min(90dvh, 760px);
  margin-inline: auto;
  margin-block: 0;
  padding: 0;
  overflow: hidden;
  background: var(--painel-elevado);
  border: 0;
  border-radius: var(--r-grande) var(--r-grande) 0 0;
  box-shadow: var(--elev-2);
  color: var(--texto);
}

.sheet[open] {
  animation: sheet-sobe var(--dur-sheet) var(--entre-tela);
}

.sheet::backdrop {
  background: rgba(45, 55, 72, 0.45);
  animation: veu var(--dur-sheet) var(--saida);
}

@keyframes sheet-sobe {
  from { transform: translateY(100%); }
  to   { transform: none; }
}

@keyframes veu {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.sheet__forma {
  display: flex;
  flex-direction: column;
  max-height: inherit;
}

.sheet__cabecalho {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-4) var(--pad-secao);
  border-bottom: 1px solid var(--borda-suave);
}

.sheet__titulo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h3);
  font-weight: 600;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}

.sheet__corpo {
  display: flex;
  flex-direction: column;
  /* flex: 1 1 auto + min-height: 0 — sem isso, item de flex column nasce com
     min-height: auto (não fico menor que o meu conteúdo) e o overflow-y:auto
     não tem o que fazer: o corpo cresce até caber tudo, empurrando
     .sheet__rodape para fora do max-height do .sheet (Salvar inalcançável em
     formulário longo). Mesma armadilha do min-width: 0 documentada em
     system.md § "min-width: 0 em quem contém coisa rolável", achada na
     Sessão 8 ao testar o sheet de Garagem contra o banco real. */
  flex: 1 1 auto;
  min-height: 0;
  gap: var(--e-4);
  padding: var(--pad-secao);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.sheet__rodape {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding: var(--e-3) var(--pad-secao);
  padding-bottom: calc(var(--e-3) + var(--safe-bottom));
  background: var(--painel-elevado);
  border-top: 1px solid var(--borda-suave);
}

.sheet__botoes {
  display: flex;
  gap: var(--e-2);
}

/* Salvar é a ação esperada: ocupa o dobro do Cancelar. */
.sheet__botoes .botao { flex: 1; }
.sheet__botoes .botao--primario { flex: 2; }

.sheet__erro {
  font-size: var(--t-mini);
  color: var(--erro);
}

/* --------------------------------------------------------------------------
   12e. Modal de confirmação destrutiva

   Centralizado e estreito, ao contrário do sheet: não é formulário, é uma
   pergunta que precisa parar o fluxo. Vermelho de --erro, nunca laranja.
   -------------------------------------------------------------------------- */

.modal {
  width: calc(100% - var(--e-8));
  max-width: 420px;
  padding: var(--pad-secao);
  margin: auto;
  background: var(--painel-elevado);
  border: 0;
  border-radius: var(--r-grande);
  box-shadow: var(--elev-2);
  color: var(--texto);
}

.modal[open] {
  animation: modal-entra var(--dur-popover) var(--saida);
}

.modal::backdrop {
  background: rgba(45, 55, 72, 0.45);
  animation: veu var(--dur-popover) var(--saida);
}

/* De 0.96, não de 0: nada aparece do nada. */
@keyframes modal-entra {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: none; }
}

.modal__interno {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.modal__marca {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  background: var(--erro-fundo);
  border-radius: var(--r-total);
  color: var(--erro);
}

.modal__marca svg {
  stroke: currentColor;
  stroke-width: 1.8;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.modal__titulo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h3);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.modal__texto {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* O aviso de cascata é o motivo da caixa existir: destacado, não escondido no
   meio do parágrafo. */
.modal__cascata {
  padding: var(--e-2) var(--e-3);
  background: var(--erro-fundo);
  border-radius: var(--r-pequeno);
  color: #8E2C21;
}

.modal__promocao {
  color: var(--texto-terciario);
}

.modal__erro {
  margin-top: var(--e-2);
  font-size: var(--t-mini);
  color: var(--erro);
}

.modal__acoes {
  display: flex;
  gap: var(--e-2);
  margin-top: var(--e-4);
}

.modal__acoes .botao { flex: 1; }

/* --------------------------------------------------------------------------
   12f. Bloco de seção dentro de uma vista

   Chega na Sessão 5, quando a primeira vista passou a ter dois blocos
   (previsões e histórico). O título de bloco é h4, não h2 visual: a <h1> da
   vista continua sendo a única voz forte da tela — dois títulos grandes
   competindo transformariam a vista em duas páginas coladas.
   -------------------------------------------------------------------------- */

.secao {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.secao__cabecalho {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-2);
}

.secao__titulo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Contagem de itens: informação de apoio, no nível mais baixo de texto. */
.secao__contagem {
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-terciario);
}

/* Legenda de uma linha logo abaixo do título — sobe contra o gap da seção
   para ficar colada no título a que pertence, não no conteúdo. */
.secao__nota {
  margin-top: calc(var(--e-2) * -1);
  font-size: var(--t-mini);
  color: var(--texto-terciario);
}

/* --------------------------------------------------------------------------
   12g. Filtro por tipo — chips de escolha exclusiva

   `role="radiogroup"` de verdade: a escolha é única e sempre há uma marcada.
   Altura de 40px, igual à do `.alternador__opcao` — os dois são a mesma
   categoria de controle (escolha exclusiva, rótulo de uma palavra, sem ícone),
   e um terceiro tamanho para a mesma função só criaria ruído.

   Rola na horizontal em vez de quebrar linha: com sete tipos, duas ou três
   linhas de chip empurrariam o histórico para fora da primeira tela.
   -------------------------------------------------------------------------- */

.filtro {
  display: flex;
  gap: var(--e-2);
  overflow-x: auto;
  /* O par padding/margin devolve o espaço que o `overflow` recortaria do anel
     de foco. Sem ele, o foco no chip aparece cortado nos quatro lados. */
  padding: var(--e-1);
  margin: calc(var(--e-1) * -1);
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}

.filtro::-webkit-scrollbar { display: none; }

.filtro__opcao {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  flex: 0 0 auto;
  min-height: 40px;
  padding: 0 var(--e-3);
  background: var(--painel);
  border: 1px solid var(--borda-forte);
  border-radius: var(--r-total);
  font-family: var(--fonte-corpo);
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-secundario);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur-toque) var(--saida),
              border-color var(--dur-toque) var(--saida),
              color var(--dur-toque) var(--saida);
}

.filtro__opcao:hover[aria-checked='false'] { color: var(--texto); }

.filtro__opcao[aria-checked='true'] {
  background: var(--azul-aco-claro);
  border-color: var(--azul-aco);
  color: var(--azul-aco-escuro);
  font-weight: 600;
}

/* Contagem demovida dentro do chip: é apoio, não o rótulo. */
.filtro__contagem {
  font-size: var(--t-legenda);
  font-weight: 500;
  color: var(--texto-terciario);
}

.filtro__opcao[aria-checked='true'] .filtro__contagem { color: var(--azul-aco); }

/* Dois filtros na mesma vista (Sessão 7: categoria e período). Empilhados, não
   lado a lado: cada um rola sozinho na horizontal, e dois trilhos roláveis
   dividindo a largura de um celular não caberiam. O gap é o menor da escala —
   os dois grupos são o mesmo controle recortando a mesma lista, não duas
   seções. */
.filtros {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  /* Item de flex/grid não encolhe abaixo do min-content sem isto, e o trilho
     de chips só rola sozinho se o invólucro puder ser mais estreito que ele.
     A mesma razão do `min-width: 0` em `.app__conteudo`. */
  min-width: 0;
}

/* --------------------------------------------------------------------------
   12h. Previsão de próxima manutenção

   Um cartão por tipo, com a previsão do último registro daquele tipo.

   SEM cor de alerta, sem selo de urgência e sem ordenação por vencimento: a
   Sessão 5 entrega exibição neutra, e o laranja de `--alerta` só entra quando
   a Edge Function agendada de Web Push existir. Um cartão que já pintasse de
   laranja aqui criaria um segundo lugar onde a regra de vencimento vive.
   -------------------------------------------------------------------------- */

.previsoes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--e-3);
  list-style: none;
  padding: 0;
}

.previsao {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.previsao__tipo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Km previsto e data prevista dividem a linha: são a mesma previsão lida por
   duas unidades, e "o que vier primeiro" só se entende se as duas estiverem
   visíveis ao mesmo tempo. */
.previsao__leituras {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-4);
}

.previsao__leituras .instrumento { flex: 1 1 auto; min-width: 0; }

/* Tipos sem intervalo cadastrado ('outro' inteiro, 'bateria' sem km): a
   trigger deixa a previsão nula de propósito, e a tela diz isso em palavras
   em vez de mostrar um travessão órfão.

   Até a Sessão 13a cada um desses tipos ganhava um CARTÃO de previsão inteiro
   para repetir a mesma frase — com sete tipos lançados, quatro cartões
   idênticos empurravam o histórico para depois de mil pixels de nada. Agora
   são linhas de uma lista só, com a explicação dita uma vez no pé.

   Não é `.lancamento`: nada aqui é clicável e a lista não cresce sem limite —
   ela tem no máximo o número de tipos de manutenção que existem. */
.previsoes + .sem-previsao {
  margin-top: var(--e-3);
}

.sem-previsao {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

.sem-previsao__lista {
  list-style: none;
  padding: 0;
  margin: 0;
}

.sem-previsao__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-2) 0;
}

.sem-previsao__item + .sem-previsao__item {
  border-top: 1px solid var(--borda-suave);
}

.sem-previsao__tipo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-corpo);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.sem-previsao__origem {
  font-size: var(--t-mini);
  color: var(--texto-terciario);
  text-align: right;
}

/* Continua declarado: `previsao__sem` some do markup de Manutenção, mas o
   PDF e qualquer vista futura que precise da frase solta ainda a acham. */
.previsao__sem {
  font-size: var(--t-mini);
  color: var(--texto-terciario);
}

/* De onde a leitura veio — é o que a torna conferível a olho. Em Manutenção:
   "a previsão vem do último registro que você lançou". No Financeiro: quantos
   abastecimentos entraram na conta e entre que datas.

   `.origem` é a forma genérica, aberta na Sessão 9 quando o segundo consumidor
   apareceu; `.previsao__origem` continua existindo como o nome que a Sessão 5
   já usa no markup de Manutenção. Mesma regra, um seletor só — duas cópias
   divergiriam na primeira correção. */
.previsao__origem,
.origem {
  padding-top: var(--e-3);
  border-top: 1px solid var(--borda-suave);
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
}

/* Passo a passo numerado — Sessão 16, para as instruções de instalação do PWA
   em Configurações.

   `<ol>` de verdade, com o marcador NATIVO: "toque em compartilhar, depois em
   adicionar" é uma sequência, e desenhar os números à mão (num `<ul>`, ou em
   `::before`) tiraria do leitor de tela a única coisa que faz esta lista ser
   diferente das outras — que ela tem ordem.

   `padding-left` em `em`, não em token de espaçamento: o recuo tem de
   acompanhar o corpo do número, e o número é 13px aqui. Fora da escala de 4px
   por essa razão, e só por ela.

   `<strong>` sobe para `--texto` e 600: dentro de um parágrafo de apoio em
   `--texto-secundario`, o nome do botão que a pessoa tem de procurar na tela é
   a única palavra que ela vai varrer. */
.passos {
  margin: 0;
  padding-left: 1.4em;
  font-size: var(--t-mini);
  line-height: 1.55;
  color: var(--texto-secundario);
}

.passos li + li { margin-top: var(--e-2); }

.passos li::marker {
  color: var(--texto-terciario);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.passos strong {
  font-weight: 600;
  color: var(--texto);
}

/* --------------------------------------------------------------------------
   12h-bis. Financeiro — Sessão 9

   O módulo não trouxe componente novo de interação: filtro é `.filtro`, a
   escolha entre os dois modos de custo é `.alternador`, e cada leitura é o
   `.instrumento` de sempre dentro de um `.cartao`. O que faltava eram duas
   peças de EXIBIÇÃO, e só elas entram aqui.
   -------------------------------------------------------------------------- */

/* Corpo de uma seção: o que o filtro daquela seção recorta. Existe porque uma
   vista com três seções precisa repintar cada uma sozinha (repintar as três
   destruiria o chip que acabou de receber o foco), e para isso cada uma precisa
   de um contêiner próprio. Herda o ritmo de `.secao`.

   `min-width: 0` pela mesma razão de `.filtros` e de `.app__conteudo`: item de
   flex nasce com `min-width: auto` e o trilho de chips lá dentro nunca rolaria
   sozinho — a página inteira ganharia scroll horizontal em 375px. */
.secao__corpo {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  min-width: 0;
}

/* Leitura que não pôde ser calculada, no lugar onde o valor iria.

   Segue o padrão neutro que o projeto já usa para nulo — o "km/l — sem dado
   suficiente" da lista de Abastecimento —, e é deliberadamente SEM cor de
   alerta: `--laranja-sinal` continua significando vencimento de manutenção e
   só, e dado insuficiente não é erro do usuário nem urgência. Peso e tamanho
   fazem a hierarquia, como no `.campo__nota`.

   Ocupa o lugar do `.instrumento__valor`, não o de uma mensagem embaixo dele:
   a ausência do número É a informação, e empurrá-la para uma nota de rodapé
   deixaria um travessão órfão no lugar de destaque. */
.instrumento__sem {
  font-size: var(--t-h4);
  font-weight: 500;
  line-height: 1.2;
  color: var(--texto-terciario);
}

/* Composição de um total: de onde ele veio, linha a linha.

   É o que separa "R$ 3.480 no ano" de uma informação acionável — o usuário
   precisa ver que R$ 2.100 disso foi combustível. Sem isto, a visão
   consolidada seria um número grande sem resposta nenhuma.

   Não é `.lancamento`: aquilo é linha de lista, com alvo de toque de 60px e a
   linha inteira sendo botão. Aqui nada é clicável e nada cresce sem limite —
   são de duas a seis linhas de leitura. */
.composicao {
  display: flex;
  flex-direction: column;
  margin: 0;
}

.composicao__linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-2) 0;
  border-top: 1px solid var(--borda-suave);
}

.composicao__linha:first-child { border-top: 0; }

.composicao__rotulo {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

.composicao__valor {
  font-family: var(--fonte-titulo);
  font-size: var(--t-corpo);
  font-weight: 600;
  color: var(--texto);
  white-space: nowrap;
}

/* A linha do total ganha peso e um divisor mais firme — é a soma das de cima,
   não mais uma parcela. */
.composicao__linha--total {
  border-top-color: var(--borda);
}

.composicao__linha--total .composicao__rotulo {
  font-weight: 600;
  color: var(--texto);
}

.composicao__linha--total .composicao__valor { font-size: var(--t-h4); }

/* Parcela que não é gasto: o divisor da conta de custo por km. Fica no mesmo
   bloco para a divisão ser lida como uma frase — "R$ 1.240 ÷ 1.850 km" —, e em
   tom terciário para não competir com os valores em dinheiro. */
.composicao__linha--divisor .composicao__rotulo,
.composicao__linha--divisor .composicao__valor {
  color: var(--texto-terciario);
  font-weight: 500;
}

.composicao__linha--divisor .composicao__valor { font-size: var(--t-corpo); }

/* --------------------------------------------------------------------------
   12i. Lançamento — linha de histórico

   Linha, não cartão, ao contrário do veículo: um registro de manutenção é um
   fato de cinco campos numa lista que cresce sem limite, e cartão por registro
   viraria uma pilha de caixas em duas semanas de uso.

   A linha inteira é o botão de edição — e a exclusão mora dentro do sheet de
   edição. Assim a lista não carrega dois botões por registro competindo com a
   leitura, que é o que ela existe para dar.
   -------------------------------------------------------------------------- */

.lista-lancamentos {
  list-style: none;
  padding: 0;
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-1);
  overflow: hidden;
}

.lista-lancamentos li + li .lancamento {
  border-top: 1px solid var(--borda-suave);
}

.lancamento {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  width: 100%;
  min-height: 60px;
  padding: var(--e-3) var(--e-4);
  background: transparent;
  border: 0;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--dur-toque) var(--saida);
}

.lancamento:hover { background: var(--cinza-claro); }
.lancamento:active { background: var(--azul-aco-claro); }

.lancamento__texto {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.lancamento__topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
}

.lancamento__tipo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-corpo);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* O custo alinha à direita e fica na fonte de instrumento: é o número que o
   módulo Financeiro vai somar, não um detalhe do texto. */
.lancamento__custo {
  flex-shrink: 0;
  font-family: var(--fonte-titulo);
  font-size: var(--t-corpo);
  font-weight: 600;
}

.lancamento__meta {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
  overflow-wrap: anywhere;
}

.lancamento__previsao {
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
}

/* Observação da manutenção na linha do histórico — Sessão 16.

   RECORTADA EM DUAS LINHAS, e é isso que a mantém compatível com a decisão da
   Sessão 5 de que lançamento é linha e não cartão. O campo aceita 500
   caracteres; solto aqui, um registro comentado ocuparia sete linhas e
   empurraria os outros lançamentos para fora da primeira tela — a lista
   deixaria de ser uma lista. Duas linhas dão o suficiente para reconhecer o
   recado, e a linha inteira abre a edição, onde ele aparece por completo.

   `-webkit-line-clamp` é a única forma com suporte real hoje; `line-clamp` sem
   prefixo vai junto para quando ela chegar. Onde nenhuma das duas pega, o
   `max-height` de duas linhas segura o layout do mesmo jeito — o texto só
   corta em vez de reticenciar, que é degradação aceitável.

   O FIO à esquerda é o que a distingue de `.lancamento__previsao`, que mora na
   mesma linha visual (11px `--texto-terciario`). Sem ele, "Próxima: 55.000 km"
   e o recado do mecânico ficariam indistinguíveis — e são coisas de naturezas
   opostas: uma o app calculou, a outra a pessoa escreveu. A distinção não pode
   ser cor (a quarta cor de texto é a última) nem itálico (o projeto inteiro
   não tem um `font-style` sequer, e abrir a exceção aqui criaria um quinto
   canal de hierarquia por causa de uma linha). Fio neutro de 2px é a mesma
   jogada de `.instrucao`, um degrau mais baixo: lá o fio é azul e grosso
   porque o bloco é instrução; aqui é `--borda` porque é citação. */
.lancamento__observacoes {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  max-height: calc(var(--t-legenda) * 1.45 * 2);
  margin-top: 3px;
  padding-left: var(--e-2);
  border-left: 2px solid var(--borda);
  font-size: var(--t-legenda);
  line-height: 1.45;
  color: var(--texto-terciario);
  overflow-wrap: anywhere;
}

/* Indicador de anexo (Sessão 7) — ícone MAIS palavra, no nível mais baixo de
   texto. Só o ícone obrigaria o usuário a aprender um símbolo; e cor nova está
   fora de questão, porque neste app o laranja é vencimento e o vermelho é
   exclusão. Um anexo não é nenhum dos dois: é um fato, e fato se escreve. */
.lancamento__anexo {
  display: inline-flex;
  align-items: center;
  gap: var(--e-1);
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
}

.lancamento__anexo-icone {
  width: 13px;
  height: 13px;
  stroke: currentColor;
  stroke-width: 1.8;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lancamento__seta {
  flex-shrink: 0;
  color: var(--texto-mudo);
  stroke: currentColor;
}

/* Ação destrutiva no pé do corpo do sheet, atrás de um divisor — nunca ao lado
   de "Salvar". A linha de botões do rodapé é da ação esperada; misturar
   exclusão ali poria a ação irreversível a um deslize de distância. */
.sheet__destrutivo {
  padding-top: var(--e-4);
  border-top: 1px solid var(--borda-suave);
}

/* --------------------------------------------------------------------------
   12a-bis. Item de lista dentro de formulário — Sessão 8b

   Padrão novo: o formulário de Abastecimento precisa de 1..N itens de
   combustível (tipo + litros + valor), repetíveis. Não é `.campo-par`
   sozinho (three coisas por item, mais um botão de remover) nem merece um
   componente próprio pesado — é um `.campo-par` de sempre, com um cabeçalho
   de seletor+remover em cima, dentro de um contêiner com borda própria para
   os itens não se confundirem visualmente na rolagem do sheet. Primeiro
   caso do projeto de "lista editável dentro de formulário"; módulo futuro
   com necessidade parecida reusa esta classe antes de inventar outra.
   -------------------------------------------------------------------------- */

.itens-abastecimento {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.item-abastecimento {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding: var(--e-3);
  border: 1px solid var(--borda-suave);
  border-radius: var(--r-pequeno);
}

.item-abastecimento__cabecalho {
  display: flex;
  align-items: center;
  gap: var(--e-2);
}

.item-abastecimento__cabecalho .campo__controle {
  flex: 1;
  min-width: 0;
}

/* --------------------------------------------------------------------------
   12a-ter. Gráfico de evolução de consumo — Sessão 8b

   SVG puro, sem biblioteca: o histórico de um veículo é pequeno (uso
   pessoal), e uma dependência de gráfico pesaria mais do que o problema
   exige. Cores e tipografia vêm dos tokens de sempre — nenhuma paleta nova.
   -------------------------------------------------------------------------- */

/* O viewBox vem em pixels reais (`grafico.montar` mede o contêiner), então o
   SVG já nasce do tamanho certo e nada aqui reescala. `max-width` é só a
   trava para o instante entre uma medida e a seguinte. */
.grafico-consumo {
  display: block;
  max-width: 100%;
}

/* Leitura e curva no MESMO cartão — a média é a resposta, o gráfico é a
   mesma resposta ao longo do tempo.

   O desenho recua até a borda do cartão, e SEM padding lateral: quem desenha
   (`grafico.montar`) usa a largura do contêiner, então padding aqui faria o
   SVG nascer mais largo que a caixa e vazar pelas bordas. A folga de que o
   traçado precisa já é a margem interna do próprio gráfico (`MARGEM_TELA`),
   onde moram os rótulos dos eixos — recuar duas vezes deixaria a grade
   flutuando num quadro dentro de outro quadro. */
.leitura-grafico__desenho {
  margin: var(--e-3) calc(var(--pad-cartao) * -1) calc(var(--pad-cartao) * -1);
  padding-bottom: var(--e-2);
  min-width: 0;
}

.grafico-consumo__linha {
  fill: none;
  stroke: var(--azul-aco);
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Área sob a série. Mesmo azul, opacidade no gradiente do próprio markup —
   nenhum token novo. Ver a razão em `js/grafico.js`. */
.grafico-consumo__area {
  fill: url(#grafico-consumo-area);
  stroke: none;
}

.grafico-consumo__ponto {
  fill: var(--painel-elevado);
  stroke: var(--azul-aco);
  stroke-width: 2.5;
}

.grafico-consumo__grade {
  stroke: var(--borda-suave);
  stroke-width: 1;
}

/* Unidade do eixo, no canto de cima da régua. O gráfico dizia km/l em lugar
   nenhum — quem chegasse nele sem ler o cartão inteiro via uma linha subindo
   e nenhuma grandeza. */
.grafico-consumo__unidade {
  font-family: var(--fonte-corpo);
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  fill: var(--texto-mudo);
}

.grafico-consumo__rotulo {
  font-family: var(--fonte-corpo);
  font-size: var(--t-legenda);
  font-variant-numeric: tabular-nums;
  fill: var(--texto-terciario);
}

/* --------------------------------------------------------------------------
   12j. Exportação em PDF — Sessão 10

   Bloco no PÉ da vista, depois da lista, e não um segundo botão no cabeçalho
   ao lado do "Novo". Duas razões, nesta ordem:

   1. O que se exporta é o que está ACIMA. A ação lê a lista já filtrada, e
      colada ao fim dela essa relação é visível sem precisar de explicação.
   2. Em 375px o cabeçalho não comporta dois botões de 44px ao lado de um h1 de
      30px. O segundo viraria ícone sem rótulo — e "exportar" não é ação que se
      reconheça por desenho, ao contrário de "adicionar".

   Nenhum componente novo: o botão é `.botao--secundario` + `.botao--bloco`, já
   fixados na Sessão 1. O que entra aqui é só o arranjo e a nota.
   -------------------------------------------------------------------------- */

.exportacao {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

/* A nota não é decoração: ela diz, ANTES do clique, o que vai sair no PDF —
   quantos lançamentos e sob qual recorte. É o que torna visível a regra de que
   o documento respeita o filtro da tela; sem ela, o usuário só descobriria o
   recorte depois de abrir o arquivo. Tom terciário e 13px, como `.secao__nota`:
   é legenda de uma ação, não um aviso. */
/* Alinhada à ESQUERDA desde a Sessão 13b. Estava centrada, e centrada ela era
   a única linha de texto centrada de uma tela inteira alinhada à esquerda —
   o tipo de detalhe que denuncia duas mãos diferentes. Legenda acompanha o
   fluxo de leitura do que ela legenda. */
.exportacao__nota {
  font-size: var(--t-mini);
  color: var(--texto-terciario);
  text-wrap: pretty;
}

/* A falha de geração (tipicamente a CDN do jsPDF fora do ar) aparece no lugar
   da nota, e não num toast: é onde o olho já está, e o texto que ela substitui
   é exatamente o que deixou de valer. `--erro`, não `--laranja-sinal` — laranja
   continua sendo vencimento de manutenção e só. */
.exportacao__nota--erro {
  font-weight: 500;
  color: var(--erro);
}

/* --------------------------------------------------------------------------
   12b. Portão de sessão

   O que aparece enquanto a sessão persistida está sendo lida, em app.html e
   em entrar.html. Existe para não piscar tela de login na cara de quem já
   está logado — nem pintar o shell antes de saber de quem é a garagem.

   Deliberadamente quase vazio: é um intervalo de milissegundos no caso normal.
   Marca + um pulso. Spinner girando aqui daria ao instante mais peso do que
   ele tem.
   -------------------------------------------------------------------------- */

.portao {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--e-4);
  min-height: 100dvh;
  padding: var(--e-6);
  text-align: center;
}

.portao__marca {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h3);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--texto);
}

/* Barra de progresso indeterminada, mesma linguagem do .esqueleto: tonalidade
   em movimento, não spinner. */
.portao__pulso {
  width: 96px;
  height: 3px;
  overflow: hidden;
  background: var(--borda);
  border-radius: var(--r-total);
}

.portao__pulso::after {
  content: '';
  display: block;
  width: 40%;
  height: 100%;
  background: var(--azul-aco);
  border-radius: var(--r-total);
  animation: portao-pulso 1.1s var(--saida) infinite;
}

@keyframes portao-pulso {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}

/* Falha antes de haver sessão: o import do supabase-js pela CDN não voltou.
   Precisa de saída, senão o pulso vira spinner eterno. */
.portao__erro {
  max-width: 32ch;
  font-size: var(--t-mini);
  color: var(--erro);
}

/* --------------------------------------------------------------------------
   12c. Autenticação — entrar.html

   Não é uma vista do shell: não tem mostrador, nem tab bar, nem veículo ativo.
   Centrada na altura da tela, coluna estreita, cartão único.

   Os tokens são os mesmos do resto do app. Nenhum valor novo entra aqui — o
   formulário reusa .campo, .botao e .aviso da Sessão 1/2.
   -------------------------------------------------------------------------- */

.autenticacao {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--e-8);
  width: 100%;
  max-width: 420px;   /* mais estreito que --largura-max: são dois campos */
  min-height: 100dvh;
  margin-inline: auto;
  padding: var(--e-10) var(--e-4);
}

.autenticacao__topo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e-2);
  text-align: center;
}

/* Lockup: símbolo e palavra na mesma linha de base óptica. O `gap` é `--e-3`
   e não `--e-2` porque o símbolo é uma caixa cheia e a palavra é traço — colar
   os dois faria o "G" encostar na borda do quadrado. */
.autenticacao__marca {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  font-size: var(--t-h1);
  letter-spacing: -0.02em;
}

.autenticacao__simbolo {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
}

.autenticacao__linha {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* O cartão sobe um degrau em relação ao `.cartao` padrão: ele é a única peça
   da tela, repousando sobre `--canvas`, e com `--elev-1` ficava rente ao fundo
   em vez de ser o objeto que a tela inteira existe para apresentar. O raio
   acompanha — `--r-grande` é o raio das peças que ocupam a tela (sheet, modal),
   e este cartão é uma delas na prática. */
.autenticacao__cartao {
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
  padding: var(--pad-secao);
  border-radius: var(--r-grande);
  box-shadow: var(--elev-2);
}

.autenticacao__rodape {
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
  text-align: center;
}

@media (min-width: 480px) {
  .autenticacao__cartao { padding: var(--e-8); }
}

/* --- Alternador entrar / criar conta -------------------------------------
   Duas opções mutuamente exclusivas que trocam o MESMO formulário, então é
   tablist, não navegação. Vive sobre o fundo recuado de --campo pelo mesmo
   motivo dos inputs: o que está por baixo é trilho, o que sobe é a escolha.

   Não é .segmentado: aquele é escolha de conteúdo do formulário (tipo de
   veículo), com ícone e alvo de 68px. Aqui a escolha é de modalidade da tela.
   ------------------------------------------------------------------------ */

/* O trilho usa `--recuo`, não `--campo`: em `entrar.html` ele vive dentro do
   cartão branco e os dois davam no mesmo, mas no Financeiro ele repousa sobre
   `--canvas` — e ali `--campo` (#FBFCFD) é mais claro que o fundo, o que
   fazia a peça inteira ler como um cartão branco com dois botões brancos
   dentro, sem escolha visível. Tinta em opacidade baixa recua sobre os dois. */
.alternador {
  display: flex;
  gap: var(--e-1);
  padding: var(--e-1);
  background: var(--recuo);
  border: 1px solid var(--borda);
  border-radius: var(--r-pequeno);
}

.alternador__opcao {
  flex: 1;
  min-height: 40px;
  padding: 0 var(--e-3);
  font-family: var(--fonte-corpo);
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-secundario);
  background: transparent;
  border: 0;
  border-radius: calc(var(--r-pequeno) - 2px);
  cursor: pointer;
  transition: background var(--dur-toque) var(--saida),
              color var(--dur-toque) var(--saida);
}

.alternador__opcao:hover:not([aria-selected='true']) { color: var(--texto); }

/* A opção marcada SOBE do trilho — `--elev-1` e não `--elev-0`. Com o anel de
   1px sozinho ela lia como "mais uma caixa dentro de uma caixa"; com a sombra,
   lê como a peça escolhida, que é o que ela é. */
.alternador__opcao[aria-selected='true'] {
  color: var(--azul-aco);
  font-weight: 600;
  background: var(--painel);
  box-shadow: var(--elev-1);
}

.alternador__opcao:disabled { cursor: default; opacity: 0.6; }

/* --- Formulário ---------------------------------------------------------- */

.forma-auth {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

.forma-auth__erro { margin-bottom: calc(var(--e-1) * -1); }

/* Boa notícia vinda da tela anterior (e-mail confirmado, senha alterada).
   Mesmo recuo negativo do erro: os dois ocupam o mesmo lugar na coluna, nunca
   ao mesmo tempo. */
.forma-auth__sucesso { margin-bottom: calc(var(--e-1) * -1); }

.forma-auth__nota {
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
  text-align: center;
}

/* --- Saídas em texto (Sessão 4) -------------------------------------------
   "Esqueci minha senha" e "Voltar para o login" são links, não botões: levam
   a outra página e nada acontece ao tocá-los além disso. Botão aqui
   competiria com a ação primária do cartão, que é entrar.

   Os 44px de alvo de toque continuam valendo — a regra não abre exceção por
   o elemento ser <a>. `min-height` + `inline-flex` em vez de padding chutado:
   padding depende da altura de linha da fonte e erra por alguns pixels quando
   a escala tipográfica muda.
   -------------------------------------------------------------------------- */

.forma-auth__esqueci,
.forma-auth__voltar {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-mini);
  font-weight: 500;
  text-decoration: none;
}

.forma-auth__esqueci {
  align-self: flex-start;
  color: var(--azul-aco);
}

.forma-auth__esqueci:hover { text-decoration: underline; }

.forma-auth__voltar {
  align-self: center;
  padding-inline: var(--e-3);
  color: var(--texto-secundario);
}

.forma-auth__voltar:hover { color: var(--texto); text-decoration: underline; }

/* Campo com botão embutido — hoje só o "mostrar senha". O botão flutua sobre
   o input em vez de dividir a linha: dividir encurtaria o campo de senha, que
   é onde o texto precisa de espaço. */
.campo__com-acao {
  position: relative;
  display: flex;
}

.campo__com-acao .campo__controle {
  flex: 1;
  padding-right: 48px;
}

.campo__acao {
  position: absolute;
  top: 50%;
  right: 0;
  /* `.botao-icone` traz margin-right negativa para encostar na borda do sheet;
     aqui ele mora dentro do campo e essa margem o jogaria para fora. */
  margin-right: 0;
  transform: translateY(-50%);
  color: var(--texto-terciario);
  background: transparent;
}

.campo__acao:hover { background: transparent; color: var(--texto-secundario); }
.campo__acao[aria-pressed='true'] { color: var(--azul-aco); }

/* --- Telas de instrução ---------------------------------------------------
   Um recado que ocupa o cartão inteiro, em vez de um `.aviso` de uma linha:
   confirme seu e-mail, verifique sua caixa de entrada, link inválido. Nos
   três a próxima ação da pessoa está FORA do navegador, e isso precisa de
   espaço para ser lido.
   -------------------------------------------------------------------------- */

.autenticacao__confirme {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e-3);
  text-align: center;
}

/* Disco de 44px com um ícone de traço fino, no topo de uma tela que dá uma
   notícia — "confirme seu e-mail", "link inválido", "veículo cadastrado". O
   onboarding da Sessão 11 pediu exatamente a mesma peça, então o seletor
   virou agrupado em vez de ganhar uma cópia: só a cor semântica muda. */
.autenticacao__selo,
.boas-vindas__selo {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  color: var(--azul-aco);
  background: var(--azul-aco-claro);
  border-radius: var(--r-total);
}

.autenticacao__selo svg,
.boas-vindas__selo svg { stroke: currentColor; fill: none; }

/* Link morto não é vencimento de manutenção: `--erro`, nunca o laranja. */
.autenticacao__selo--erro {
  color: var(--erro);
  background: var(--erro-fundo);
}

.autenticacao__titulo {
  font-size: var(--t-h4);
  letter-spacing: -0.01em;
}

/* Recebe foco por script ao trocar de estado — sem contorno de foco visível,
   porque o alvo é o leitor de tela, não o ponteiro. */
.autenticacao__titulo:focus { outline: none; }

.autenticacao__texto {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* Cabeçalho do formulário quando ele tem um assunto próprio (recuperar
   senha, definir nova senha) e não o alternador entrar/criar conta. */
.autenticacao__intro {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
}

/* `>` de propósito: quando as ações estão agrupadas em `.autenticacao__acoes`,
   quem controla o espaçamento entre elas é o grupo. */
.autenticacao__confirme > .botao { margin-top: var(--e-2); }

.autenticacao__acoes {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  width: 100%;
  margin-top: var(--e-2);
}

/* Resposta ao "Reenviar e-mail": sucesso ou falha, no mesmo lugar. */
.autenticacao__retorno {
  width: 100%;
  text-align: left;
}

/* --------------------------------------------------------------------------
   Instrução que carrega um DADO a conferir — Sessão 13b

   Nasce em `assinar.html`, para o e-mail com que o pagamento tem de ser
   feito. É o terceiro registro de mensagem do projeto, e o que faltava:

     `.aviso`         resultado de uma ação que acabou de acontecer
     `.campo__nota`   ressalva que não impede o envio
     `.instrucao`     o que fazer AGORA, com o dado a conferir em destaque

   Estrutura de `.instrumento` — rótulo demovido, valor liderando, nota
   embaixo —, porque é a mesma leitura: um rótulo diz o que é, e o dado é o
   que a pessoa precisa levar consigo. O que muda é a caixa: fundo
   `--azul-aco-claro` e um fio azul à esquerda, marcando que a instrução vem
   do produto e não é mais uma linha de texto do cartão.

   Deliberadamente NÃO usa `--laranja-sinal`. A versão anterior era
   `.aviso--alerta`, e laranja continua sendo vencimento de manutenção e só —
   ver "Ação destrutiva" e "Exibição neutra da previsão" no system.md. Fora
   de alerta, laranja é bug de design, inclusive numa tela de conversão.
   -------------------------------------------------------------------------- */

.instrucao {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
  width: 100%;
  padding: var(--e-3) var(--e-4);
  background: var(--azul-aco-claro);
  border-left: 3px solid var(--azul-aco);
  border-radius: var(--r-pequeno);
  text-align: left;
}

.instrucao__rotulo {
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--azul-aco-escuro);
}

/* Fonte de título e quebra em qualquer ponto: e-mail longo não pode estourar
   a coluna de 420px nem virar reticências — é o dado que precisa ser LIDO e
   copiado. */
.instrucao__valor {
  font-family: var(--fonte-titulo);
  font-size: var(--t-corpo);
  font-weight: 600;
  line-height: 1.3;
  color: var(--texto);
  overflow-wrap: anywhere;
}

.instrucao__nota {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* --------------------------------------------------------------------------
   12d. Bloco de conta — pé do menu "Mais"

   Identificação de quem está logado e a saída. Fora da tab bar de propósito:
   sair é raro e não deveria ficar sob o polegar.
   -------------------------------------------------------------------------- */

.conta {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  margin-top: var(--e-6);
  padding: var(--e-3) var(--pad-cartao);
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-1);
}

.conta__avatar {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  color: var(--texto-terciario);
  background: var(--cinza-claro);
  border-radius: var(--r-total);
}

.conta__avatar svg { stroke: currentColor; fill: none; stroke-width: 1.9; }

.conta__texto {
  display: flex;
  flex-direction: column;
  min-width: 0;   /* deixa o e-mail longo truncar em vez de esticar a linha */
  margin-right: auto;
}

.conta__rotulo {
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.conta__valor {
  overflow: hidden;
  font-size: var(--t-mini);
  color: var(--texto);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   12k. Onboarding — primeiro uso (Sessão 11)

   Rota `#/boas-vindas`, dentro do shell: tem mostrador e tab bar como qualquer
   outra vista, e é de propósito — a pessoa está no app, não numa antessala.

   O que muda em relação a uma vista comum é o eixo: coluna centrada, sem
   `.vista__cabecalho` e sem a legenda "Módulo". Esta é a única tela do app
   sem cabeçalho de vista, e a razão é que ela não é um módulo — é o estado de
   quem ainda não tem o que listar.

   Nenhum token novo. O que entra é o arranjo, e ele é mais generoso que o do
   resto do app (título de 30px, texto de 15px, respiro de 24px) porque aqui
   não há dado competindo por espaço: é a única tela em que o conteúdo é a
   explicação.
   -------------------------------------------------------------------------- */

.boas-vindas {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e-4);
  padding-top: var(--e-6);
  text-align: center;
}

/* Azul, e não terciário como as outras legendas: é a primeira linha que a
   pessoa lê no app, e ela dá as boas-vindas em vez de rotular um módulo. */
.boas-vindas__legenda { color: var(--azul-aco); }

.boas-vindas__titulo {
  max-width: 20ch;   /* quebra em duas linhas por composição, não por acaso */
  font-size: var(--t-h1);
  letter-spacing: -0.02em;
}

/* Recebe foco por script quando a tela 2 substitui a 1 — sem contorno visível,
   porque o alvo é o leitor de tela e não o ponteiro. Mesma decisão de
   `.autenticacao__titulo`. */
.boas-vindas__titulo:focus { outline: none; }

.boas-vindas__texto {
  max-width: 42ch;
  color: var(--texto-secundario);
}

/* O CTA se afasta do texto mais do que o texto se afasta do título: o respiro
   uniforme de 16px entre TUDO era o que deixava a tela com cara de lista de
   parágrafos em vez de uma tela com uma ação. */
.boas-vindas__acao { margin-top: var(--e-3); }

/* A coluna é centrada, então o esqueleto de carga (um `.cartao`) encolheria
   até o tamanho do conteúdo e ficaria com cara de erro em vez de espera. */
.boas-vindas > .cartao { width: 100%; }

/* O que o app faz, em três linhas. Cartão com o texto à ESQUERDA dentro de uma
   coluna centrada: frase de duas linhas centralizada é desconfortável de ler,
   e aqui elas são de duas linhas. */
.boas-vindas__lista {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: var(--pad-cartao);
  list-style: none;
  text-align: left;
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-1);
}

.boas-vindas__item {
  display: flex;
  gap: var(--e-3);
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* Divisor entre as promessas, e não só um vão de 16px: são TRÊS coisas que o
   app faz, e empilhadas sem corte elas liam como um parágrafo de três frases
   com ícones no meio. Mesma peça de `.lancamento` e `.item-mais` — divisor
   `--borda-suave` entre linhas de uma lista, que é o que isto é. */
.boas-vindas__item + .boas-vindas__item {
  margin-top: var(--e-4);
  padding-top: var(--e-4);
  border-top: 1px solid var(--borda-suave);
}

.boas-vindas__item strong {
  display: block;
  font-weight: 600;
  color: var(--texto);
}

.boas-vindas__icone {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 2px;   /* alinha com a maiúscula, não com a caixa da linha */
  stroke: var(--azul-aco);
  stroke-width: 1.75;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.boas-vindas__nota {
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
}

/* Cadastro concluído: o disco herda a forma de `.autenticacao__selo` e troca a
   cor para `--ok`. Verde aqui é confirmação de que algo deu certo, que é o que
   `--ok` já significa em `.selo--ok` e `.aviso--ok`. */
/* Verde de `--ok` — confirmação de que algo deu certo, que é o que `--ok` já
   significa em `.selo--ok` e `.aviso--ok`.

   E 56px, não os 44px de `.autenticacao__selo`: lá o disco acompanha um título
   de 17px dando uma instrução; aqui ele abre uma tela de 30px que existe para
   marcar a chegada do primeiro veículo. É o único momento de chegada do
   produto, e o selo precisa do peso do título que vem abaixo dele. */
.boas-vindas__selo {
  width: 56px;
  height: 56px;
  margin-bottom: var(--e-1);
  color: var(--ok);
  background: var(--ok-fundo);
}

.boas-vindas__selo svg { width: 26px; height: 26px; }

.boas-vindas__saidas {
  width: 100%;
  text-align: left;
}

/* Saída em texto, não botão: competir com as três ações acima transformaria a
   tela em quatro opções de mesmo peso. Alvo de 44px mantido. */
.boas-vindas__depois {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-secundario);
  text-decoration: none;
}

.boas-vindas__depois:hover { color: var(--texto); text-decoration: underline; }

/* --------------------------------------------------------------------------
   13. Acessibilidade e telas maiores
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* A regra acima congelaria o pulso do portão fora da tela
     (translateX(-100%)), deixando quem pediu menos movimento sem nenhum sinal
     de que algo está acontecendo. Vira barra estática. */
  .portao__pulso::after {
    width: 100%;
    transform: none;
    opacity: 0.45;
  }
}

/* Acima do tablet o conteúdo permanece em coluna única e centrado: este é um
   app de campo, alargar transformaria a leitura de lançamentos em planilha. */
@media (min-width: 768px) {
  :root {
    --pad-cartao: var(--e-5);
  }

  .app__conteudo {
    padding-inline: var(--e-6);
  }
}

/* --------------------------------------------------------------------------
   14. Landing pública — index.html (Sessão 11, recomposta na Sessão 13a)

   A única página do projeto que não é app nem tela de Auth, e a primeira peça
   pública de marketing. O que ela pode fazer diferente, e o que não pode:

   PODE respirar mais, e desde a Sessão 13a pode respirar DIFERENTE em cada
   trecho. A página não é mais uma pilha de blocos iguais separados por fio de
   1px: ela alterna FAIXAS de fundo (`--canvas` → `--painel` → `--canvas` →
   grafite) e três medidas de coluna, e é essa alternância que dá o ritmo. Lá
   dentro do app o conteúdo é dado competindo por espaço numa tela segurada com
   uma mão; aqui é uma leitura que acontece rolando, e leitura sem ritmo é
   leitura sem hierarquia.

   NÃO PODE inventar identidade. Nenhuma cor, fonte ou raio nova entra por causa
   desta página — o mostrador do herói é literalmente o `.mostrador` do shell,
   com as mesmas classes, e os botões e cartões são os de sempre. Uma landing
   que parece outro produto quebra a promessa dela mesma no primeiro clique,
   que é justamente o clique que leva ao app.

   O que a Sessão 13a acrescentou ao `:root` — `--t-display`, `--e-16/20/24`,
   `--elev-3`, `--borda-invertida` — são CONTINUAÇÕES das escalas que já
   existiam (mesma razão tipográfica, mesma base 4px, mesma receita de ring +
   duas camadas), não uma segunda linguagem. Nenhum valor solto mora aqui.
   -------------------------------------------------------------------------- */

.pagina-landing {
  /* Duas margens de leitura, e não mais que duas — cada troca de recuo é um
     degrau que o olho tem de subir, e uma página com três recuos diferentes
     parece três páginas coladas:

       padrão   880px  corpo da página: títulos de seção, grade de recursos e
                       prosa (o parágrafo se limita sozinho em 62ch, então a
                       linha nunca fica longa demais)
       ampla   1040px  o herói, a única composição de duas colunas

     `--estreito` (560px) não é uma terceira margem: é a largura de uma PEÇA
     centrada — o cartão de preço e o fecho —, e peça centrada não cria recuo.

     Uma medida só para tudo era o que fazia a página parecer o app esticado. */
  --largura-landing: 880px;
  --largura-landing-ampla: 1040px;

  background: var(--painel);
}

/* Rolagem suave, e SÓ na landing (Sessão 19).

   `scroll-behavior` governa o viewport, e quem responde por ele é o elemento
   raiz — declarar em `.pagina-landing` (que veste o `<body>`) não faz efeito
   nenhum no Chrome. Daí o `:has()`: a regra alcança o `<html>` a partir da
   classe que só a landing tem.

   Ela NÃO pode valer para o app. `app.html` navega por hash (`#/garagem`,
   `#/veiculo`…), e rolagem animada em troca de rota seria a tela deslizando
   inteira a cada toque na tab bar.

   Quem pediu menos movimento recebe `scroll-behavior: auto !important` da
   regra global da § 13, e volta ao salto seco. */
html:has(.pagina-landing) { scroll-behavior: smooth; }

/* Salto para o conteúdo: fica fora da tela até receber foco por teclado. */
.pular {
  position: absolute;
  top: var(--e-2);
  left: var(--e-2);
  z-index: 50;
  padding: var(--e-2) var(--e-3);
  background: var(--azul-aco);
  color: #FFFFFF;
  border-radius: var(--r-pequeno);
  font-size: var(--t-mini);
  font-weight: 500;
  text-decoration: none;
  transform: translateY(-200%);
}

.pular:focus { transform: none; }

/* --- Topo ----------------------------------------------------------------
   Marca à esquerda, "Entrar" à direita, e nada mais. Um menu de navegação
   numa página de uma coluna só seria um índice de si mesma.
   ------------------------------------------------------------------------ */

.landing__topo {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--borda-suave);
}

.landing__topo-interno {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-3);
  width: 100%;
  max-width: var(--largura-landing-ampla);
  min-height: var(--altura-header);
  margin-inline: auto;
  padding: var(--e-2) var(--e-4);
}

/* A marca virou lockup: símbolo + palavra. O símbolo é o que faz a página se
   apresentar como um produto e não como um documento — e é onde o laranja da
   identidade aparece, dentro da marca, que é o único lugar em que ele não
   significa vencimento. */
.landing__marca {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--texto);
}

.landing__marca-simbolo {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
}

/* --- Faixas ---------------------------------------------------------------
   A unidade de composição da página. Cada faixa é largura total (é ela que
   pinta o fundo de ponta a ponta) e centra um `.faixa__interno` com a medida
   que aquele trecho pede.

   Os fios de 1px que separavam as seções saíram: separação agora é tom e
   respiro. Fio entre blocos é o que se usa quando não se decidiu a hierarquia
   — e a página tinha sete deles, todos iguais.
   ------------------------------------------------------------------------ */

.faixa {
  padding-block: var(--e-16);
}

.faixa__interno {
  width: 100%;
  max-width: var(--largura-landing);
  margin-inline: auto;
  padding-inline: var(--e-4);
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
}

.faixa__interno--estreito { max-width: 560px; }

/* Abertura e preço sobem sobre o cinza do app; o fecho fecha no grafite. */
.faixa--abertura  { background: var(--canvas); padding-block: var(--e-12) var(--e-16); }
.faixa--claro     { background: var(--painel); }
.faixa--recuada   { background: var(--canvas); }
.faixa--instrumento {
  background: var(--grafite);
  color: var(--texto-invertido);
}

/* Duas faixas de mesmo tom encostadas não precisam somar 128px de respiro:
   o assunto muda, o fundo não, e o corte é a mudança de assunto. */
.faixa--claro + .faixa--claro { padding-top: 0; }

/* --- Herói ----------------------------------------------------------------
   Uma coluna abaixo de 1024px, duas acima. A figura não é ilustração de
   apoio: é a prova da promessa que o texto acabou de fazer, e lado a lado as
   duas chegam no mesmo golpe de vista.
   ------------------------------------------------------------------------ */

.heroi {
  gap: var(--e-10);
}

.heroi__texto {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

.heroi__legenda { color: var(--azul-aco); }

/* O maior tipo da página, e o único uso de `--t-display`. `text-wrap: balance`
   vem do reset; o que muda aqui é o aperto óptico, que cresce com o corpo. */
.heroi__titulo {
  max-width: 16ch;
  font-size: var(--t-display);
  line-height: 1.08;
  letter-spacing: -0.03em;
}

.heroi__linha {
  max-width: 46ch;
  font-size: var(--t-h4);
  line-height: 1.55;
  color: var(--texto-secundario);
}

.heroi__acoes {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--e-3);
  margin-top: var(--e-2);
}

/* O segundo CTA do herói, a partir da Sessão 19: link, não botão.

   Ele era `.botao--secundario.botao--grande.botao--bloco` — mesma altura,
   mesma largura e mesma massa do CTA azul, separado dele só pela cor. Dois
   alvos do mesmo tamanho na primeira dobra não são hierarquia: são uma
   pergunta ("qual dos dois?"), e a resposta barata é sempre a que não
   converte.

   Sublinhado, e não `.botao--fantasma`: fantasma ainda é caixa de botão com
   fundo no hover, e o que se quer aqui é a aparência de TEXTO clicável. O
   sublinhado vem apagado (`--borda-forte`) e acende no hover — o mesmo
   movimento do link do rodapé sobre grafite, na paleta clara.

   Os 44px de alvo ficam: a regra de toque do projeto não abre exceção por
   hierarquia, e este link é a segunda coisa mais clicada da página. */
.heroi__secundario {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-corpo);
  font-weight: 500;
  color: var(--texto-secundario);
  text-decoration: underline;
  text-decoration-color: var(--borda-forte);
  text-underline-offset: 4px;
  transition: color var(--dur-toque) var(--saida),
              text-decoration-color var(--dur-toque) var(--saida);
}

.heroi__secundario:hover {
  color: var(--texto);
  text-decoration-color: currentColor;
}

/* O preço aparece colado ao CTA porque é o que a pessoa procura no instante em
   que decide clicar — e porque escondê-lo mais para baixo seria a versão
   educada de não dizer. */
.heroi__nota {
  font-size: var(--t-mini);
  color: var(--texto-terciario);
}

/* A linha do formato (PWA), um degrau ABAIXO da nota de preço. Ela não
   argumenta nada: desarma a busca por uma loja de aplicativos que não existe.
   Se subisse para `--t-mini` ficaria empatada com o preço, e a primeira dobra
   passaria a ter duas notas de rodapé com o mesmo peso. */
.heroi__formato {
  max-width: 42ch;
  font-size: var(--t-legenda);
  line-height: 1.6;
  color: var(--texto-terciario);
}

.heroi__figura {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e-3);
  margin: 0;
}

.heroi__legenda-figura {
  font-size: var(--t-legenda);
  color: var(--texto-mudo);
  text-align: center;
}

/* A `.vitrine` — o mostrador solto sobre um cartão — morava aqui e foi
   REMOVIDA junto com a chegada do `.aparelho`. Nada mais no projeto a usa
   (conferido em .html, .js e .css), e o serviço que ela prestava passou
   inteiro para `.aparelho`: mostrar a peça real e neutralizar o que nela é
   botão. As duas leituras que ela carregava viraram `.aparelho__flutuante`.

   Ela não foi deixada "por precaução": regra de estilo órfã continua casando
   com seletores, e uma delas (`.heroi__figura .instrumento + .instrumento`,
   no bloco de 1024px) chegou a aplicar divisórias na peça flutuante nova,
   mudando a altura dela só acima de 1024px. Isso é o que CSS morto faz.

   --- Títulos de seção ---------------------------------------------------- */

.landing__secao-titulo {
  font-size: var(--t-h2);
  letter-spacing: -0.02em;
}

.landing__secao-titulo--centrado { text-align: center; }

.landing__texto {
  max-width: 62ch;
  color: var(--texto-secundario);
}

/* O único parágrafo longo da página — o que explica para quem o produto é.
   Ele sobe de corpo porque é leitura, não legenda de bloco. */
.landing__texto--maior {
  font-size: var(--t-h4);
  line-height: 1.6;
}

/* --- Recursos ------------------------------------------------------------
   Duas colunas a partir de 640px, uma abaixo disso. Cartão por recurso, o
   mesmo `--elev-1` e `--r-medio` do app.

   Sem hover: estes cartões não são clicáveis, e realce de ponteiro em coisa
   que não responde é a mesma promessa falsa que `.aparelho` desfaz na tela do
   app (a regra era da `.vitrine`, e passou junto com o serviço).
   ------------------------------------------------------------------------ */

.recursos {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--e-4);
  list-style: none;
  padding: 0;
}

.recurso {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding: var(--pad-cartao);
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-1);
}

/* Chip azul-claro sob o ícone: dá ao recurso um ponto de entrada visual em vez
   de um traço solto de 22px, e é a mesma peça de `.avatar-veiculo` sem foto
   (fundo `--azul-aco-claro` + ícone de traço). */
.recurso__marca {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: var(--e-1);
  background: var(--azul-aco-claro);
  border-radius: var(--r-pequeno);
}

.recurso__icone {
  width: 22px;
  height: 22px;
  stroke: var(--azul-aco);
  stroke-width: 1.75;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.recurso__titulo {
  font-size: var(--t-h4);
  letter-spacing: -0.01em;
}

.recurso__texto {
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* --- Reforço de marca -----------------------------------------------------
   Uma frase, e a única da página escrita para ser LEMBRADA em vez de
   entendida. Fecha "O que você registra" dizendo em voz alta o que dois dos
   quatro cartões dizem de lado ("não estimado por tabela", "em vez de
   inventar um número").

   Nenhuma peça nova: é o fio azul de `.beneficio` virado de lado — mesma
   régua de 2px, à esquerda em vez de em cima. Não é `<blockquote>` porque não
   é citação de ninguém, e não é `.destaque` porque não tem ícone nem bloco:
   um cartão a mais aqui faria a página bater o mesmo compasso pela quinta vez
   seguida.
   ------------------------------------------------------------------------ */

.reforco {
  max-width: 34ch;
  margin-top: var(--e-2);
  padding-left: var(--e-4);
  border-left: 2px solid var(--azul-aco);
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.01em;
}

/* --- Destaque de exportação ---------------------------------------------- */

.destaque {
  display: flex;
  gap: var(--e-5);
  padding: var(--e-8);
  background: var(--azul-aco-claro);
  border-radius: var(--r-grande);
}

.destaque__corpo {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

/* Mesma peça do `.recurso__marca`, um degrau maior — este bloco é um só e
   carrega o argumento de revenda sozinho. */
.destaque__marca {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  background: var(--painel);
  border-radius: var(--r-medio);
}

.destaque__icone {
  width: 26px;
  height: 26px;
  stroke: var(--azul-aco);
  stroke-width: 1.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* A ponte entre o uso de hoje e o valor de daqui a três anos. Sobe de corpo
   porque é a frase que a seção quer que fique — mas fica abaixo do `<h2>`, e
   não no lugar dele: é reforço do título, não um segundo título. */
.destaque__ponte {
  /* Sem `max-width`: em 34ch ela quebrava em "…Agora ele pode ter / prova
     disso.", partindo a frase no meio da segunda oração. O bloco já tem
     medida própria, e `balance` cuida da quebra onde ela precisa acontecer. */
  text-wrap: balance;
  font-family: var(--fonte-titulo);
  font-size: var(--t-h4);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--azul-aco-escuro);
}

/* Os quatro documentos, contáveis com o dedo. Chips de contorno sobre o azul
   claro do bloco — o mesmo `--painel` da marca do ícone, que é o que já
   estabelece "peça branca sobre o fundo azul-claro" aqui dentro.

   `list-style: none` sem `role="list"`: o Safari tira a lista da árvore de
   acessibilidade quando o marcador some, e para uma enumeração de quatro
   palavras isso é o comportamento desejado — quem lê com leitor de tela já
   recebeu os quatro nomes no parágrafo acima. */
.destaque__documentos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.destaque__documentos li {
  padding: var(--e-1) var(--e-3);
  background: var(--painel);
  border-radius: var(--r-pequeno);
  font-size: var(--t-mini);
  font-weight: 500;
  color: var(--texto-secundario);
}

/* --- Preço ----------------------------------------------------------------
   Um número, uma vez. Não existe valor riscado, "de/por", contagem regressiva
   nem plano fantasma ao lado para comparação — regra fixada no spec e nas
   memórias do projeto, e nenhuma reescrita desta página deve reintroduzi-los.

   O destaque vem da COMPOSIÇÃO: faixa cinza, cartão branco elevado em cima
   dela e o valor no maior corpo da página depois do herói. Nenhum selo, nenhum
   laço, nenhuma cor de urgência.
   -------------------------------------------------------------------------- */

.preco {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  padding: var(--e-8);
  background: var(--painel);
  border-radius: var(--r-grande);
  box-shadow: var(--elev-3);
}

.preco__rotulo {
  font-size: var(--t-legenda);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--texto-terciario);
}

.preco__valor {
  display: flex;
  align-items: baseline;
  gap: var(--e-2);
  font-family: var(--fonte-titulo);
  font-size: var(--t-display);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.preco__periodo {
  font-family: var(--fonte-corpo);
  font-size: var(--t-mini);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--texto-terciario);
}

/* A divisão por mês, colada no valor anual — não é um segundo preço, é o
   mesmo número em outra escala. Fica em `--t-mini` e no cinza de apoio de
   propósito: se subisse de corpo passaria a disputar com o R$ 49,90, e a
   página voltaria a ter dois preços na mesma peça, que é exatamente o que a
   regra do projeto não quer. */
.preco__equivalencia {
  margin-top: calc(var(--e-2) * -1);
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

.preco__equivalencia strong {
  font-weight: 600;
  color: var(--texto);
}

/* "Um preço só" — de nota de rodapé a faixa, na Sessão 19.

   Era `.preco__linha`, em `--t-mini` e no cinza de apoio, e ficava entre a
   equivalência mensal e a lista de inclusos: o argumento que mais separa este
   produto de quem cobra por veículo, com o peso tipográfico de um asterisco.

   A regra do bloco de preço continua inteira — não há valor riscado, plano
   fantasma nem selo de oferta. O que esta faixa destaca não é o preço; é a
   UNIDADE de cobrança, que é outra informação.

   Nenhuma cor nova: `--azul-aco-claro` sobre `--azul-aco-escuro` é o par que
   `.recurso__marca` e `.destaque` já usam. Laranja continua sendo vencimento.
   `.preco__linha` saiu junto — nada mais no projeto a usava. */
.preco__ilimitado {
  padding: var(--e-3) var(--e-4);
  background: var(--azul-aco-claro);
  border-radius: var(--r-pequeno);
  font-size: var(--t-mini);
  font-weight: 600;
  color: var(--azul-aco-escuro);
}

.preco__lista {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  margin: 0;
  padding: var(--e-4) 0 var(--e-1);
  list-style: none;
  border-top: 1px solid var(--borda-suave);
  font-size: var(--t-mini);
  color: var(--texto-secundario);
}

/* Marcador desenhado em CSS: um traço azul curto. Um ícone de "check" por
   linha daria cinco marcas de sucesso numa lista que só enumera o que está
   incluído. */
.preco__lista li {
  position: relative;
  padding-left: var(--e-5);
}

.preco__lista li::before {
  content: '';
  position: absolute;
  top: 0.62em;
  left: 0;
  width: 12px;
  height: 2px;
  background: var(--azul-aco);
  border-radius: 2px;
}

.preco__acao { margin-top: var(--e-1); }

.preco__nota {
  font-size: var(--t-legenda);
  line-height: 1.6;
  color: var(--texto-terciario);
}

/* --- Perguntas ------------------------------------------------------------
   Pergunta e resposta abertas, não sanfona: são três, e esconder três
   respostas atrás de um toque cada é atrito sem economia de espaço.
   -------------------------------------------------------------------------- */

.perguntas {
  display: flex;
  flex-direction: column;
  gap: var(--e-6);
}

.pergunta {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding-bottom: var(--e-6);
  border-bottom: 1px solid var(--borda-suave);
}

.pergunta:last-of-type { padding-bottom: 0; border-bottom: 0; }

.pergunta__titulo {
  font-size: var(--t-h3);
  letter-spacing: -0.015em;
}

/* Subiu de 13px para o corpo de leitura: eram metadados quando a seção era
   mais um bloco na pilha, e são resposta a uma dúvida de compra agora. */
.pergunta__texto {
  max-width: 66ch;
  color: var(--texto-secundario);
}

/* --- Fechamento e rodapé -------------------------------------------------
   Faixa grafite, e o rodapé continua ela sem costura. É o pé da página: a
   última coisa que a pessoa vê é o material do instrumento.
   ------------------------------------------------------------------------ */

.fecho {
  align-items: center;
  gap: var(--e-4);
  text-align: center;
}

.fecho__titulo {
  max-width: 18ch;
  font-size: var(--t-h1);
  letter-spacing: -0.025em;
}

.fecho__texto {
  max-width: 48ch;
  color: var(--texto-invertido-fraco);
}

.fecho__acoes {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  width: 100%;
  max-width: 340px;
  margin-top: var(--e-2);
}

.landing__rodape {
  padding: 0 var(--e-4) var(--e-16);
  background: var(--grafite);
}

.landing__rodape-interno {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
  width: 100%;
  max-width: var(--largura-landing-ampla);
  margin-inline: auto;
  padding-top: var(--e-8);
  border-top: 1px solid var(--borda-invertida);
  text-align: center;
}

.landing__rodape-marca {
  font-family: var(--fonte-titulo);
  font-size: var(--t-mini);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--texto-invertido);
}

.landing__rodape-texto {
  font-size: var(--t-legenda);
  color: var(--texto-invertido-fraco);
}

/* Link sobre grafite: o azul de ação é ilegível aqui. Vira sublinhado de luz,
   que é o que um link é quando não pode ser cor. */
.landing__rodape a {
  color: var(--texto-invertido);
  text-decoration-color: rgba(255, 255, 255, 0.35);
}

.landing__rodape a:hover { text-decoration-color: currentColor; }

/* --- Microinterações ------------------------------------------------------
   Só onde existe ação de verdade. O botão primário ganha uma sombra que
   acende no hover — 120ms, `--saida`, nada além de cor e sombra (transform
   fica reservado ao `:active`, que já existe globalmente).
   ------------------------------------------------------------------------ */

.pagina-landing .botao--primario {
  box-shadow: 0 1px 2px rgba(43, 108, 168, 0.24);
  transition: background-color var(--dur-toque) var(--saida),
              box-shadow var(--dur-popover) var(--saida),
              transform var(--dur-toque) var(--saida);
}

.pagina-landing .botao--primario:hover:not(:disabled) {
  box-shadow: 0 2px 4px rgba(43, 108, 168, 0.22),
              0 8px 20px -6px rgba(43, 108, 168, 0.38);
}

/* --- Benefícios -----------------------------------------------------------
   O contraponto de `.recursos`, e é por isso que NÃO é cartão: aquela grade
   já usa cartão, chip e sombra, e repetir a mesma peça logo abaixo faria a
   página bater o mesmo compasso oito vezes seguidas.

   Aqui o agrupamento vem de um fio azul curto no topo de cada bloco — o mesmo
   marcador de `.preco__lista li::before`, na régua de um título. Sem sombra,
   sem fundo próprio: o bloco repousa direto sobre `--canvas`.
   ------------------------------------------------------------------------ */

.beneficios {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--e-8);
  margin-top: var(--e-2);
  list-style: none;
  padding: 0;
}

.beneficio {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding-top: var(--e-4);
  border-top: 2px solid var(--azul-aco);
}

.beneficio__titulo {
  font-size: var(--t-h4);
  letter-spacing: -0.01em;
}

.beneficio__texto {
  font-size: var(--t-mini);
  line-height: 1.65;
  color: var(--texto-secundario);
}

/* --- Chamada do meio da página --------------------------------------------
   O CTA que fica entre o entendimento e o preço. Centrado e solto na faixa —
   não é cartão, não compete com o de `.preco`, e existe só para não obrigar
   quem já decidiu a rolar mais três seções até achar um botão.
   ------------------------------------------------------------------------ */

.chamada-meio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e-2);
  margin-top: var(--e-4);
  text-align: center;
}

.chamada-meio .botao { width: 100%; max-width: 320px; }

.chamada-meio__nota {
  font-size: var(--t-legenda);
  color: var(--texto-terciario);
}

/* --- Garantia -------------------------------------------------------------
   Fica FORA do cartão de preço, e de propósito: dentro dele viraria mais um
   item da lista de inclusos, e o que ela diz não é "o que vem junto" — é "o
   que acontece se você se arrepender". É a última objeção da página, e merece
   o próprio bloco.

   Sem cor de alerta e sem selo: `--ok-fundo` é o verde de confirmação que o
   app já usa, e o laranja continua reservado a vencimento.
   ------------------------------------------------------------------------ */

.garantia {
  display: flex;
  gap: var(--e-4);
  align-items: flex-start;
  padding: var(--e-5);
  background: var(--ok-fundo);
  border-radius: var(--r-medio);
}

.garantia__marca {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  background: var(--painel);
  border-radius: var(--r-pequeno);
}

.garantia__icone {
  width: 22px;
  height: 22px;
  stroke: var(--ok);
  stroke-width: 1.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.garantia__corpo {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
}

.garantia__titulo {
  font-size: var(--t-h4);
  letter-spacing: -0.01em;
  color: var(--ok);
}

.garantia__texto {
  font-size: var(--t-mini);
  line-height: 1.65;
  color: var(--texto-secundario);
}

.garantia__texto strong { color: var(--texto); font-weight: 600; }

/* --- Perguntas: agora sanfona --------------------------------------------
   Eram três abertas. São oito, e oito respostas abertas empurram o fecho da
   página para muito longe de quem só queria conferir duas dúvidas.

   `<details>`/`<summary>` nativos: teclado, foco e leitor de tela já vêm
   prontos, e a página segue sem uma linha de JS por causa desta seção. O
   marcador padrão sai e entra um sinal de "+" desenhado em CSS, que gira 45°
   e vira "×" quando aberto — 180ms, `--saida`, a mesma régua do popover.
   ------------------------------------------------------------------------ */

.perguntas { gap: 0; }

.pergunta {
  padding-bottom: 0;
  border-bottom: 1px solid var(--borda-suave);
}

.pergunta:last-of-type { border-bottom: 1px solid var(--borda-suave); }

.pergunta__titulo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--e-4);
  padding: var(--e-5) 0;
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-toque) var(--saida);
}

/* A pergunta é um `<h3>` DENTRO do `<summary>`, e não o próprio summary.

   Trocar o h3 por summary tirou as oito perguntas do índice de títulos do
   documento — e numa seção de FAQ o título é justamente o que é lido, indexado
   e citado. O h3 devolve a hierarquia sem tirar do summary o que é dele: o
   clique, o foco e o estado aberto/fechado continuam no elemento nativo. */
.pergunta__pergunta {
  flex: 1;
  min-width: 0;
  font-size: var(--t-h3);
  letter-spacing: -0.015em;
  color: inherit;   /* herda o azul do :hover do summary */
}

/* O triângulo padrão do Safari/iOS sai por aqui; o do Chrome/Firefox, pelo
   `list-style: none` acima. Os dois são necessários. */
.pergunta__titulo::-webkit-details-marker { display: none; }

.pergunta__titulo:hover { color: var(--azul-aco); }

.pergunta__titulo:focus-visible {
  outline: 2px solid var(--azul-aco);
  outline-offset: 3px;
  border-radius: var(--r-pequeno);
}

/* O "+" — dois traços cruzados, girados juntos. Desenhado, e não ícone, para
   que o giro seja de uma peça só. */
.pergunta__titulo::after {
  content: '';
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  margin-top: 0.3em;
  background:
    linear-gradient(var(--azul-aco), var(--azul-aco)) center / 100% 2px no-repeat,
    linear-gradient(var(--azul-aco), var(--azul-aco)) center / 2px 100% no-repeat;
  transition: transform var(--dur-popover) var(--saida);
}

.pergunta[open] .pergunta__titulo::after { transform: rotate(135deg); }

.pergunta__texto {
  padding-bottom: var(--e-5);
  animation: pergunta-abre var(--dur-popover) var(--saida) both;
}

@keyframes pergunta-abre {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* --- O aparelho: o app de verdade, num celular ----------------------------
   A moldura é grafite porque grafite é o material do instrumento no produto —
   o mesmo do mostrador e da faixa de fecho. Um celular prateado ou preto
   genérico traria uma terceira cor de casca para a página.

   Dentro dela não há nada inventado: são as classes do shell (`.header`,
   `.vista`, `.cartao-veiculo`, `.nav`). O que este bloco faz é (1) dar altura
   e recorte de aparelho, e (2) NEUTRALIZAR o que ali dentro é controle —
   mesmo serviço que a antiga `.vitrine` prestava ao mostrador, agora para uma
   tela inteira.
   ------------------------------------------------------------------------ */

.aparelho {
  position: relative;
  width: min(320px, 100%);
  height: 660px;
  padding: 10px;
  overflow: hidden;   /* rede para viewports abaixo de 340px */
  background: var(--grafite);
  border-radius: 42px;
  /* Fio de luz na borda superior + a sombra funda de `--elev-3`: é o que faz
     a peça parecer um objeto pousado, e não um retângulo escuro. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14),
              0 0 0 1px rgba(45, 55, 72, 0.28),
              0 24px 48px -16px rgba(45, 55, 72, 0.42),
              0 8px 16px -8px rgba(45, 55, 72, 0.24);
}

/* A tela é desenhada na largura de um CELULAR DE VERDADE (366px) e reduzida
   para caber na moldura de 300px — não desenhada direto em 300px.

   A diferença não é estética, é de conteúdo: em 300px o texto quebra mais, a
   pilha cresce e o SEGUNDO veículo saía inteiro do quadro. E ele é o ponto da
   peça — é o que mostra que a licença vale para a garagem toda. Renderizando
   em 366px e escalando, entra a mesma tela que a pessoa vê no aparelho dela,
   com os dois cartões.

   Os números: 300 / 366 = 0.8197, e 640 / 0.8197 = 781. O raio sobe na mesma
   proporção (32 / 0.8197 = 39) para chegar em 32px depois da escala. */
.aparelho__tela {
  display: flex;
  flex-direction: column;
  width: 366px;
  height: 781px;
  overflow: hidden;
  background: var(--canvas);
  border-radius: 39px;
  transform: scale(0.8197);
  transform-origin: top left;
}

/* O conteúdo rola no app; aqui ele é uma fotografia. `overflow: hidden` faz o
   corte na altura do aparelho, e o corte é honesto: no celular real a lista
   continua abaixo da dobra exatamente assim. */
.aparelho .app__conteudo {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: var(--e-5) var(--e-4) var(--e-4);
}

.aparelho .header,
.aparelho .nav { position: static; }

.aparelho .header { padding-top: 0; }
.aparelho .nav { padding-bottom: 0; }

/* A palavra da marca APARECE, como no app.

   A regra aqui era o oposto até a Sessão 18a — `display: none`, escrito
   explicitamente porque o media query de 420px do app mede a JANELA (a de
   quem lê a landing no desktop) e não a tela desenhada dentro da moldura. Ela
   existia porque o app escondia a palavra em 366px: lá ela disputava a barra
   com o mostrador, e com as duas visíveis o apelido do veículo truncava.

   Sem o mostrador não há disputa, o app mostra a palavra em qualquer largura,
   e o fiel do mockup passou a ser mostrá-la também. A regra some, e some por
   inteiro — deixá-la aqui como `display: block` seria manter uma exceção que
   não corrige mais nada. */

/* `<p>` no lugar do `<h1>` da vista real: a figura é `aria-hidden`, e um
   título de nível 1 dentro dela seria um segundo h1 no documento. O tamanho é
   o mesmo. */
.aparelho__titulo {
  font-family: var(--fonte-titulo);
  font-size: var(--t-h1);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

/* --- Neutralização: nada aqui dentro responde ao ponteiro ----------------
   As duas regras de `.mostrador` saíram na Sessão 18a: a peça deixou de ser
   botão no app (ela não tem mais cursor nem hover para neutralizar) e deixou
   de aparecer neste mockup, que agora mostra a tela da Garagem. */
.aparelho .nav__link:hover { color: var(--texto-terciario); }
.aparelho .nav__link[data-atual='sim'] { color: var(--azul-aco); }
.aparelho .botao { cursor: default; }

/* --- A peça que flutua ----------------------------------------------------
   As duas leituras que o app calcula sozinho — o argumento do produto — ditas
   fora da moldura, onde não disputam espaço com a tela.

   Abaixo de 480px ela desce para o fluxo normal: sobreposta numa tela de
   360px, ela taparia justamente o cartão do veículo que veio provar.
   ------------------------------------------------------------------------ */

.aparelho__flutuante {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--e-4);
  width: min(320px, 100%);
  padding: var(--e-3) var(--e-4);
  background: var(--painel);
  border-radius: var(--r-medio);
  box-shadow: var(--elev-3);
}

/* --- Movimento ------------------------------------------------------------
   A página era estática de ponta a ponta, e uma página de venda que não se
   move lê como documento impresso. O movimento aqui obedece a três regras:

   1. **Entra uma vez, e para.** Nada pisca, pulsa ou repete — exceto a peça
      flutuante, num deslocamento de 6px que existe para dizer "isto está
      solto sobre aquilo", não para chamar atenção.
   2. **A régua é a que já existe.** `--saida` e as durações do sistema; o que
      entra de novo é `--dur-entrada` (520ms), porque 180ms de popover num
      bloco de página inteira lê como um susto, não como uma entrada.
   3. **Sem JS, a página aparece inteira.** O estado escondido só existe sob
      `[data-revelar='armado']`, e quem arma é o script. JS desligado, script
      quebrado ou `prefers-reduced-motion` ligado: nada some.
   ------------------------------------------------------------------------ */

.pagina-landing { --dur-entrada: 520ms; }

@keyframes sobe {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

/* O herói não espera rolagem: ele já está na tela quando a página abre, e é
   animado por CSS puro — se dependesse do observador, a primeira dobra ficaria
   à mercê de um script. Os degraus de atraso são o que faz a leitura acontecer
   na ordem em que foi escrita. */
.heroi__texto > *,
.heroi__figura {
  animation: sobe var(--dur-entrada) var(--saida) both;
}

.heroi__legenda      { animation-delay: 40ms; }
.heroi__titulo       { animation-delay: 100ms; }
.heroi__linha        { animation-delay: 180ms; }
.heroi__acoes        { animation-delay: 260ms; }
.heroi__nota         { animation-delay: 320ms; }
.heroi__formato      { animation-delay: 360ms; }
.heroi__figura       { animation-delay: 200ms; }

@keyframes flutua {
  0%   { transform: translateY(0); }
  50%  { transform: translateY(-6px); }
  100% { transform: translateY(0); }
}

/* --- Revelação por rolagem ------------------------------------------------
   `[data-revela]` marca o alvo; o observador troca o valor para `visivel`.
   O estado escondido exige `[data-revelar='armado']` no <html> — ver regra 3
   acima.
   ------------------------------------------------------------------------ */

[data-revelar='armado'] [data-revela] {
  opacity: 0;
  transform: translateY(20px);
}

[data-revelar='armado'] [data-revela='visivel'] {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-entrada) var(--saida),
              transform var(--dur-entrada) var(--saida);
}

/* Escalonamento dentro de uma grade: os cartões chegam em sequência, não em
   bloco. `--i` é escrito no HTML, um índice por item. */
[data-revelar='armado'] [data-revela='visivel'] { transition-delay: calc(var(--i, 0) * 70ms); }

/* Quem pediu menos movimento não recebe nem a entrada do herói. A regra
   global da § 13 já zera durações; esta desliga a animação inteira, para que
   nem o `both` deixe rastro de estado inicial. */
@media (prefers-reduced-motion: reduce) {
  .heroi__texto > *,
  .heroi__figura,
  .aparelho__flutuante,
  .pergunta__texto {
    animation: none !important;
  }

  [data-revelar='armado'] [data-revela] {
    opacity: 1;
    transform: none;
  }
}

/* --- Acima de 480px: a peça flutua de verdade ---------------------------- */

@media (min-width: 480px) {
  .heroi__figura { position: relative; }

  /* A peça flutuante começa em 602px e tem 152px de altura, então termina 94px
     ABAIXO da moldura de 660px. O `gap` de 12px da figura não dá conta disso e
     a legenda ficava por baixo dela. 96px é a folga medida contra essa base —
     não um respiro escolhido no olho. */
  .heroi__legenda-figura { margin-top: var(--e-24); }

  /* Ancorada ao CENTRO da figura, não à borda dela: o aparelho é centrado na
     coluna, então `left: 0` prendia a peça na margem da página, a meia tela de
     distância do celular — solta, sem parecer estar sobre nada.

     `right: calc(50% + 74px)` põe a borda direita da peça 74px à esquerda do
     centro, ou seja 86px DENTRO do aparelho (que tem 320px, logo 160 de meia
     largura). A conta não depende da largura da peça, então o texto pode mudar
     sem soltar a âncora.

     Eram 100px até a Sessão 18b, e o que mudou foi o que está por baixo. A
     peça cruza a tab bar do mockup, e a barra passou de cinco itens para
     quatro na 18a — as células foram de 60px para 75px. Com a borda em 100 ela
     caía NO MEIO do rótulo "Garagem", e meia palavra recortada lê como falha
     de renderização, não como profundidade. Em 74 a borda cai no limite entre
     a primeira célula e a segunda: o primeiro item some inteiro e os outros
     três aparecem completos. A conta é `160 − 75 − 11` — meia largura do
     aparelho, menos uma célula, menos a moldura de cada lado.

     A altura é ancorada pelo TOPO, e isso não é preferência: `bottom` conta a
     partir da `.heroi__figura`, que inclui a legenda — mexer no respiro da
     legenda arrastava a peça junto, e ela voltava a cobrir a tela. Pelo topo a
     referência é o aparelho, que tem altura fixa (660px), e a peça não se move
     mais quando o que está embaixo muda.

     602px = 660 − 58, e o 58 foi medido: qualquer valor menor faz a peça
     encostar no cartão da MOTO — o segundo veículo, que é exatamente o que
     este herói veio provar. Aqui ela cruza só a tab bar e desce para fora da
     moldura, que é o que a faz parecer solta SOBRE o aparelho, não colada. */
  .aparelho__flutuante {
    position: absolute;
    right: calc(50% + 74px);
    left: auto;
    top: 602px;
    z-index: 2;
    width: auto;
    grid-template-columns: 1fr;
    gap: var(--e-3);
    animation: flutua 6s var(--saida) infinite;
  }
}

/* --- Acima de 640px ------------------------------------------------------- */

@media (min-width: 640px) {
  .beneficios { grid-template-columns: 1fr 1fr; gap: var(--e-6) var(--e-8); }

  .chamada-meio .botao { width: auto; min-width: 260px; }

  .recursos { grid-template-columns: 1fr 1fr; }

  .faixa { padding-block: var(--e-20); }
  .faixa--abertura { padding-block: var(--e-16) var(--e-20); }
  .faixa--claro + .faixa--claro { padding-top: 0; }

  .heroi__titulo {
    font-size: 2.875rem;   /* 46px — passo seguinte da mesma razão 1.25 */
    max-width: 15ch;
  }

  /* Com o herói em 46px, um título de seção em 24px não abria degrau nenhum:
     a página inteira lia como um só nível de voz depois da primeira dobra. */
  .landing__secao-titulo { font-size: var(--t-h1); }

  .fecho__acoes {
    flex-direction: row;
    justify-content: center;
    max-width: none;
  }

  .fecho__acoes .botao { width: auto; min-width: 200px; }
}

/* --- Acima de 1024px: o herói vira duas colunas --------------------------- */

@media (min-width: 1024px) {
  .heroi {
    display: grid;
    /* 1,15fr / 1fr: a coluna de texto é a que fala, a figura é a que prova.
       Proporções iguais fariam as duas parecerem alternativas uma da outra. */
    grid-template-columns: 1.15fr 1fr;
    align-items: center;
    gap: var(--e-16);
    max-width: var(--largura-landing-ampla);
  }

  .heroi__titulo { max-width: 14ch; }

  .heroi__acoes {
    flex-direction: row;
    align-items: center;
    gap: var(--e-5);
  }

  /* `.botao--bloco` (width: 100%) fazia sentido quando os dois CTAs eram
     botões e dividiam a linha meio a meio. Com um botão e um link ao lado, o
     100% do botão come a linha inteira e espreme o link contra a borda. Aqui
     ele volta a ser do tamanho do próprio rótulo. */
  .heroi__acoes .botao--bloco { width: auto; }

  /* As três regras da `.vitrine` que moravam aqui saíram com ela. A última
     delas alcançava `.heroi__figura .instrumento + .instrumento` — genérica
     demais — e passou a mexer na `.aparelho__flutuante` assim que a peça nova
     entrou, engordando-a 33px só acima de 1024px. O aparelho já nasce em
     retrato e não precisa de ajuste de proporção neste breakpoint. */

  .faixa--abertura { padding-block: var(--e-20) var(--e-24); }
  .faixa--instrumento { padding-block: var(--e-24); }
}

/* Abaixo de 400px o bloco de destaque empilha ícone e texto. */
@media (max-width: 400px) {
  .destaque {
    flex-direction: column;
    gap: var(--e-4);
    padding: var(--e-6);
  }

  .preco { padding: var(--e-6); }
}
