@layer base, components, views;

@layer base {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }

  html { -webkit-text-size-adjust: 100%; }

  body {
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    color: var(--text);
    background: var(--bg);
    min-height: 100dvh;
    -webkit-font-smoothing: antialiased;
    /* O WebView pinta um retângulo cinza no toque; ele aparece por cima do
       nosso estado :active e faz o app parecer página. */
    -webkit-tap-highlight-color: transparent;
  }

  ::selection { background: var(--selection); }

  /* Componentes definem display:grid/flex, que sobrescreveria o atributo
     hidden e deixaria botões visíveis antes da hora. */
  [hidden] { display: none !important; }

  button, input, textarea { font: inherit; color: inherit; }
  fieldset { border: none; padding: 0; margin: 0; min-width: 0; }
  legend { padding: 0; }
  button { cursor: pointer; border: none; background: none; }
  :focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; border-radius: 4px; }

  /* Título que quebra em duas linhas com uma palavra órfã na segunda lê como
     descuido; `balance` reparte as linhas. Onde não houver suporte, nada
     acontece — a regra é só uma preferência de quebra. */
  h1, h2, h3 { line-height: var(--leading-tight); font-weight: 600; text-wrap: balance; }
  .numeric { font-variant-numeric: tabular-nums; }
  .mono { font-family: var(--font-mono); font-size: 0.95em; }

  .sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  /* Troca de tela. O roteador já usava View Transitions quando o WebView
     oferece; sem estas regras, a troca padrão é um fade longo de 250ms que
     parece lentidão. Curta e com 6px de subida: parece app trocando de aba. */
  ::view-transition-old(root) { animation: screen-out var(--dur-fast) var(--ease-out) both; }
  ::view-transition-new(root) { animation: screen-in var(--dur-base) var(--ease-out) both; }
  @keyframes screen-out { to { opacity: 0; } }
  @keyframes screen-in { from { opacity: 0; transform: translateY(6px); } }

  @media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
  }
}

@layer components {
  /* ── app shell ───────────────────────────────────────────────────── */
  /* `isolation` prende o halo (.app::before) neste contexto: ele fica acima
     do fundo da página e abaixo de todo conteúdo, sem z-index negativo
     global nem position: fixed — que no Android se comporta mal. */
  .app {
    position: relative; isolation: isolate;
    display: flex; flex-direction: column; min-height: 100dvh;
  }
  .app::before {
    content: ""; position: absolute; inset: 0 0 auto; height: 26rem;
    z-index: -1; pointer-events: none;
    background: radial-gradient(64% 72% at 50% 0%, var(--aura), transparent 72%);
  }

  /* Ícones (SVG). O traço herda a cor do texto, então o mesmo desenho serve
     ao item ativo, ao botão desabilitado e aos dois temas — coisa que emoji
     não faz. */
  .icon {
    width: 1.25em; height: 1.25em; flex: none;
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round;
  }

  /* O <main> precisa esticar, senão `flex: 1` do chat e da voz não tem contra
     o que crescer: o campo de escrever ficava logo abaixo da última mensagem,
     no meio da tela, com um vazio embaixo. `min-height: 0` deixa o filho
     rolar em vez de empurrar a página. */
  #outlet { flex: 1; min-height: 0; display: flex; flex-direction: column; }

  /* Dentro do app Android a janela JÁ é recuada pelas barras do sistema (o
     contêiner recebe os insets como padding em MainActivity). Sem isto, o CSS
     somava env(safe-area-inset-bottom) por cima e sobrava uma faixa vazia
     abaixo dos rótulos do menu. O marcador é posto pelo app; no navegador ele
     não existe e env() continua valendo, que é o certo lá. */
  :root[data-app] { --safe-bottom: 0px; --safe-top: 0px; }

  .topbar {
    display: flex; align-items: center; gap: var(--space-3);
    padding: calc(var(--space-3) + var(--safe-top, env(safe-area-inset-top, 0px))) var(--space-4) var(--space-3);
    border-bottom: 1px solid var(--border);
    background: color-mix(in oklch, var(--bg) 85%, transparent);
    backdrop-filter: blur(8px);
    position: sticky; top: 0; z-index: 10;
  }
  .topbar__brand {
    font-weight: 600; letter-spacing: -0.02em;
    display: flex; align-items: center; gap: var(--space-2);
  }
  .topbar__dot {
    width: 10px; height: 10px; border-radius: var(--radius-full);
    background: linear-gradient(140deg, var(--brand-300), var(--brand-600));
    box-shadow: 0 0 12px var(--brand-line);
  }
  .topbar__spacer { flex: 1; }

  .nav {
    display: flex; gap: var(--space-1);
    overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav__item { white-space: nowrap; }
  .nav__item {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: var(--space-2) var(--space-3); border-radius: var(--radius-md);
    color: var(--text-muted); font-size: var(--text-sm); font-weight: 500;
    transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast);
  }
  .nav__item:hover { background: var(--surface-hover); color: var(--text); }
  /* O item ativo é o único que usa a cor da marca: é ela que responde "onde
     eu estou" sem precisar de sublinhado, caixa alta nem negrito. */
  .nav__item[aria-current="page"] {
    background: var(--brand-soft); color: var(--brand-text); font-weight: 600;
  }
  .nav__icon { width: 1.15rem; height: 1.15rem; }

  /* Celular estreito: marca + saldo + idioma + tema não cabiam em 360px por
     7px — e 7px de sobra viram scroll lateral, que faz a página inteira
     "passear" quando o dedo arrasta de lado. Aperto espaços e alvos em vez
     de esconder informação. */
  @media (max-width: 400px) {
    .topbar { gap: var(--space-2); padding-inline: var(--space-3); }
    .topbar__brand { gap: var(--space-1); }
    .balance { padding-inline: var(--space-2); }
    .lang-switch button { padding-inline: var(--space-1); }
    .btn--icon { width: 2rem; height: 2rem; }
  }

  /* Até 360px o que sobra é o nome da marca — o item menos informativo da
     barra (o app já se chama learn2talk no ícone, e o ponto É a marca do
     favicon). Tentei segurar o nome apertando espaços, e o resultado foi uma
     barra espremida que ainda passava 3px; melhor perder o nome do que a
     barra. Daí para cima, o aperto logo acima faz tudo caber. */
  @media (max-width: 360px) {
    .topbar__nome { display: none; }
  }

  /* Entre a barra de baixo (≤640px) e o desktop largo, a barra de cima não
     tem largura para marca + cinco rótulos + saldo + idioma: o último item
     ficava cortado pelo scroll. Nesta faixa o ícone fica e o rótulo sai —
     o aria-label do link mantém o nome para leitor de tela. */
  @media (min-width: 641px) and (max-width: 980px) {
    .nav__label { display: none; }
    .nav__item { padding: var(--space-2) var(--space-3); }
  }

  /* ── botões ──────────────────────────────────────────────────────── */
  .btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: var(--space-2);
    /* Vários botões são <a> — sem isto o navegador sublinha, e o "Voz" ao
       lado de "Encerrar e analisar" parecia um link no meio de dois botões.
       Fica na regra base, não em cada variante, porque a variante seguinte
       repetiria o mesmo esquecimento. */
    text-decoration: none;
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-md);
    font-size: var(--text-sm); font-weight: 550;
    transition: transform var(--dur-fast) var(--ease-out),
                background var(--dur-fast), box-shadow var(--dur-fast),
                opacity var(--dur-fast);
  }
  .btn:active:not(:disabled) { transform: scale(0.98); }
  .btn:disabled { opacity: 0.5; cursor: not-allowed; }

  /* A sombra separa a ação principal do fundo; sem ela o violeta é só mais
     uma forma chapada na tela. Puxa para o violeta, não para o preto. */
  .btn--primary {
    background: var(--brand-500); color: var(--text-on-brand);
    box-shadow: var(--shadow-sm);
  }
  .btn--primary:hover:not(:disabled) {
    background: var(--brand-600); box-shadow: var(--shadow-md);
  }

  .btn--ghost { color: var(--text-muted); }
  .btn--ghost:hover:not(:disabled) { background: var(--surface-hover); color: var(--text); }

  .btn--sm { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }

  /* Botão só de ícone (o do tema). Alvo de 2.25rem: o mesmo do chip de nível,
     que é o menor que o polegar acerta sem mirar. */
  .btn--icon {
    display: grid; place-items: center;
    width: 2.25rem; height: 2.25rem; padding: 0;
    border-radius: var(--radius-full); font-size: var(--text-base);
  }

  /* Encerrar e analisar: é a ação que entrega o valor do produto, então tem
     peso de ação, não de link. */
  .btn--accent {
    background: color-mix(in oklch, var(--brand-500) 18%, transparent);
    color: var(--brand-500); font-weight: 600;
    border: 1px solid color-mix(in oklch, var(--brand-500) 40%, transparent);
  }
  .btn--accent:hover:not(:disabled) {
    background: color-mix(in oklch, var(--brand-500) 26%, transparent);
  }

  .btn--outline { border: 1px solid var(--border-strong); color: var(--text); }
  .btn--outline:hover:not(:disabled) { background: var(--surface-hover); }

  /* Entrar com o Google. Antes vinha pronto do SDK; agora é nosso, porque o
     SDK saiu do caminho (ver ADR-0010). Mantém a forma que a pessoa
     reconhece: marca à esquerda, rótulo centrado, alvo de toque cheio. */
  .btn--google {
    width: 100%;
    justify-content: center;
    position: relative;
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-pill, 999px);
  }
  .btn--google svg {
    position: absolute; left: var(--space-4);
    width: 1.25rem; height: 1.25rem;
    background: #fff; border-radius: 50%; padding: 2px;
  }

  /* ── chat ────────────────────────────────────────────────────────── */
  .chat { flex: 1; display: flex; flex-direction: column; min-height: 0; }

  .chat__targets {
    max-width: var(--container-chat); margin: 0 auto; width: 100%;
    padding: var(--space-3) var(--space-4) 0;
    font-size: var(--text-xs); color: var(--text-subtle);
    display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  }
  .chat__targets b { font-weight: 550; color: var(--text-muted); }

  .chat__scroll { flex: 1; overflow-y: auto; padding: var(--space-4) var(--space-4) var(--space-6); }
  .chat__list {
    max-width: var(--container-chat); margin: 0 auto;
    display: flex; flex-direction: column; gap: var(--space-4);
  }

  .bubble {
    max-width: 85%; padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-lg); line-height: var(--leading-relaxed);
    animation: bubble-in var(--dur-base) var(--ease-out);
    overflow-wrap: anywhere;
  }
  .bubble--assistant {
    align-self: flex-start; background: var(--bg-elevated);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-sm), inset 0 1px 0 var(--edge);
  }
  .bubble--user {
    align-self: flex-end; background: var(--brand-500); color: var(--text-on-brand);
    border-bottom-right-radius: var(--radius-sm);
  }
  .bubble--pending { opacity: 0.6; }
  .bubble--error {
    align-self: center; background: color-mix(in oklch, var(--danger-500) 12%, var(--bg));
    color: var(--text); font-size: var(--text-sm); max-width: 100%;
  }

  @keyframes bubble-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
  }

  .typing { display: inline-flex; gap: 4px; padding: var(--space-1) 0; }
  .typing span {
    width: 6px; height: 6px; border-radius: var(--radius-full);
    background: var(--text-subtle); animation: blink 1.4s infinite;
  }
  .typing span:nth-child(2) { animation-delay: 0.2s; }
  .typing span:nth-child(3) { animation-delay: 0.4s; }
  @keyframes blink { 0%, 60%, 100% { opacity: 0.25; } 30% { opacity: 1; } }

  .composer {
    border-top: 1px solid var(--border);
    background: var(--bg);
    padding: var(--space-3) var(--space-4) calc(var(--space-4) + var(--safe-bottom, env(safe-area-inset-bottom, 0px)));
  }
  .composer__actions {
    max-width: var(--container-chat); margin: var(--space-3) auto 0; width: 100%;
    display: flex; align-items: center; gap: var(--space-2);
  }
  .composer__actions .btn--accent { margin-left: auto; }

  .composer__inner {
    max-width: var(--container-chat); margin: 0 auto;
    display: flex; gap: var(--space-2); align-items: flex-end;
  }
  .composer__input {
    flex: 1; resize: none; max-height: 9rem;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
    background: var(--bg-elevated); line-height: var(--leading-normal);
    transition: border-color var(--dur-fast);
  }
  .composer__input:focus { outline: none; border-color: var(--brand-500); }
  .composer__hint {
    max-width: var(--container-chat); margin: var(--space-2) auto 0;
    font-size: var(--text-xs); color: var(--text-subtle);
    display: flex; justify-content: space-between; gap: var(--space-3);
  }

  /* ── cartões e listas ────────────────────────────────────────────── */
  .card {
    background: var(--bg-elevated); border: 1px solid var(--border);
    border-radius: var(--radius-lg); padding: var(--space-5);
    /* Fio de luz no topo: no escuro é o que dá relevo ao cartão sem clarear
       a borda inteira, que deixaria o contorno visível demais. */
    box-shadow: inset 0 1px 0 var(--edge);
  }
  .card--flat { background: transparent; border: none; padding: 0; box-shadow: none; }

  .chip {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: var(--space-1) var(--space-3); border-radius: var(--radius-full);
    font-size: var(--text-xs); font-weight: 500;
    background: var(--surface-hover); color: var(--text-muted);
  }
  /* Dois chips com significado próprio: resumo pronto (positivo) e conversa
     em andamento (presente). No cinza padrão os dois seriam o mesmo cinza. */
  .chip--win {
    background: color-mix(in oklch, var(--win-500) 18%, transparent);
    color: color-mix(in oklch, var(--win-500) 60%, var(--text));
  }
  .chip--brand { background: var(--brand-soft); color: var(--brand-text); }

  .overline {
    font-size: var(--text-xs); font-weight: 550; letter-spacing: 0.06em;
    text-transform: uppercase; color: var(--text-subtle);
  }

  /* ── correção ────────────────────────────────────────────────────── */
  .correction { display: grid; gap: var(--space-2); }
  .correction__before {
    font-family: var(--font-mono); font-size: var(--text-sm);
    text-decoration: underline wavy var(--focus-500); text-underline-offset: 4px;
    color: var(--text-muted);
  }
  .correction__after {
    font-family: var(--font-mono); font-size: var(--text-sm); color: var(--win-500);
    font-weight: 500;
  }
  .correction__why { font-size: var(--text-sm); color: var(--text-muted); }

  .meter {
    height: 6px; border-radius: var(--radius-full);
    background: var(--surface-hover); overflow: hidden;
  }
  .meter__fill {
    height: 100%; border-radius: inherit;
    background: linear-gradient(90deg, var(--brand-400), var(--brand-600));
    transition: width var(--dur-slow) var(--ease-out);
  }

  .toast {
    position: fixed; left: 50%; bottom: var(--space-6); translate: -50% 0;
    background: var(--gray-900); color: var(--gray-50);
    padding: var(--space-3) var(--space-5); border-radius: var(--radius-full);
    font-size: var(--text-sm); box-shadow: var(--shadow-lg); z-index: 50;
    animation: bubble-in var(--dur-base) var(--ease-out);
  }
}

@layer views {
  /* ── tela inicial ─────────────────────────────────────────────────── */
  .home__hero { display: grid; gap: var(--space-2); padding-block: var(--space-5) var(--space-2); }
  .home__hero h1 { font-size: var(--text-2xl); letter-spacing: -0.03em; }
  .home__hero p { color: var(--text-muted); }

  .home__actions { display: grid; gap: var(--space-3); }

  .action {
    display: flex; align-items: center; gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
    background: var(--bg-elevated); text-decoration: none; color: var(--text);
    transition: background var(--dur-fast), border-color var(--dur-fast),
                transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast);
  }
  .action:active { transform: scale(0.99); }
  .action--primary {
    border-color: var(--brand-line);
    background: var(--brand-tint);
  }
  /* O ícone ganha um tijolo próprio. Solto, ele fica do tamanho do texto e as
     duas ações viram dois links um do lado do outro. */
  .action__icon {
    display: grid; place-items: center; flex: none;
    width: 2.75rem; height: 2.75rem; border-radius: var(--radius-md);
    background: var(--surface-hover); color: var(--text-muted);
    font-size: var(--text-lg);
  }
  .action--primary .action__icon { background: var(--brand-tint); color: var(--brand-text); }
  .action__text { display: grid; gap: 2px; min-width: 0; flex: 1; }
  .action__text b { font-size: var(--text-base); font-weight: 600; }
  .action__text small { font-size: var(--text-xs); color: var(--text-subtle); }
  /* A seta é o convite: diz que a linha inteira é tocável — coisa que uma
     borda sozinha não diz. Só com mouse: no toque, ela pisca sem motivo. */
  .action__go {
    color: var(--text-subtle);
    transition: translate var(--dur-base) var(--ease-out), color var(--dur-base);
  }
  @media (hover: hover) {
    .action:hover { background: var(--surface-hover); box-shadow: var(--shadow-md); }
    .action--primary:hover {
      background: color-mix(in oklch, var(--brand-500) 24%, transparent);
    }
    .action:hover .action__go { translate: 3px 0; color: var(--text); }
  }

  .home__meta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
  .home__pill {
    display: inline-flex; align-items: center; gap: var(--space-1);
    min-height: 2.25rem; padding: var(--space-1) var(--space-3);
    border: 1px solid var(--border-strong); border-radius: var(--radius-full);
    background: var(--bg-elevated); color: var(--text-muted);
    font-size: var(--text-xs); text-decoration: none;
  }
  .home__pill b { color: var(--text); font-weight: 600; }
  .home__pill:hover { background: var(--surface-hover); }

  .home__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
  .home__link { color: var(--brand-500); font-size: var(--text-xs); text-decoration: none; }
  .home__link:hover { text-decoration: underline; }

  .steps { display: grid; gap: var(--space-3); list-style: none; }
  .step { display: flex; gap: var(--space-3); align-items: flex-start; }
  /* O emoji em cima de um tijolo cinza para de parecer enfeite de texto e
     passa a ser o marcador do passo. */
  .step__icon {
    display: grid; place-items: center; flex: none;
    width: 1.9rem; height: 1.9rem; border-radius: var(--radius-sm);
    background: var(--surface-hover); font-size: 1rem; line-height: 1;
  }
  .step__text { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-relaxed); }
  .step__text b { color: var(--text); font-weight: 600; }

  .recent {
    display: flex; align-items: center; gap: var(--space-3);
    padding-block: var(--space-2); text-decoration: none; color: var(--text);
  }
  .recent + .recent { border-top: 1px solid var(--border); }
  .recent__text { display: grid; gap: 2px; min-width: 0; flex: 1; }
  .recent__text b { font-weight: 550; }
  .recent__text small { font-size: var(--text-xs); color: var(--text-subtle); }
  .recent__tag { font-size: var(--text-xs); color: var(--brand-500); flex: none; }

  .view { max-width: var(--container-wide); margin: 0 auto; padding: var(--space-6) var(--space-4); width: 100%; }
  .view--narrow { max-width: var(--container-chat); }

  .stack { display: grid; gap: var(--space-5); }
  .stack--tight { gap: var(--space-3); }

  .hero { display: grid; gap: var(--space-4); padding-block: var(--space-7); }
  .hero h1 { font-size: var(--text-3xl); letter-spacing: -0.03em; }
  .hero p { color: var(--text-muted); max-width: 34rem; }

  .grid-2 { display: grid; gap: var(--space-4); grid-template-columns: 1fr; }
  @media (min-width: 720px) { .grid-2 { grid-template-columns: 1fr 1fr; } }

  .debrief__headline { font-size: var(--text-2xl); letter-spacing: -0.02em; }
  .debrief__section { display: grid; gap: var(--space-3); }

  .win { display: grid; gap: var(--space-1); padding-left: var(--space-4); position: relative; }
  .win::before {
    content: "✓"; position: absolute; left: 0; color: var(--win-500); font-weight: 600;
  }
  .win__quote { font-family: var(--font-mono); font-size: var(--text-sm); }
  .win__note { font-size: var(--text-sm); color: var(--text-muted); }

  .skill-row {
    display: grid; gap: var(--space-2);
    padding: var(--space-4); border: 1px solid var(--border);
    border-radius: var(--radius-md); background: var(--bg-elevated);
    box-shadow: inset 0 1px 0 var(--edge);
  }
  .skill-row__head { display: flex; align-items: baseline; gap: var(--space-3); }
  .skill-row__label { font-weight: 550; }
  .skill-row__meta { margin-left: auto; font-size: var(--text-xs); color: var(--text-subtle); }

  /* Linha do histórico: duas linhas, uma frase cada — o título trunca em vez
     de quebrar, e os números dividem a segunda linha com o estado.

     Antes era um cartão de três linhas de texto corrido (título, data, e a
     pílula caindo sozinha embaixo): com tópico em inglês longo, meia tela
     virava sopa. O que importa — de que foi a conversa e quando — fica nas
     duas linhas; o resto saiu abreviado ("obs.") para caber sem quebrar. */
  .conversa {
    display: grid; grid-template-columns: 1fr auto;
    align-items: center; gap: var(--space-2) var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border); border-radius: var(--radius-md);
    background: var(--bg-elevated); box-shadow: inset 0 1px 0 var(--edge);
    text-decoration: none; color: inherit;
    transition: border-color var(--dur-fast), background var(--dur-fast),
                transform var(--dur-fast) var(--ease-out);
  }
  .conversa__titulo {
    grid-area: 1 / 1; font-weight: 600; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .conversa__meta {
    grid-area: 2 / 1; min-width: 0;
    display: flex; align-items: center; gap: var(--space-3);
    font-size: var(--text-xs); color: var(--text-muted);
  }
  .conversa__info {
    min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* O estado encosta na direita, alinhado com a seta do canto — e mais fino
     que o chip padrão, para não esticar a altura da linha. */
  .conversa__meta .chip {
    flex: none; margin-left: auto;
    padding: 1px var(--space-2); font-size: 0.6875rem;
  }
  .conversa__seta {
    grid-area: 1 / 2 / 3 / 3; align-self: center;
    color: var(--text-subtle);
    transition: translate var(--dur-base) var(--ease-out), color var(--dur-base);
  }
  .conversa:active { transform: scale(0.995); }
  @media (hover: hover) {
    .conversa:hover { border-color: var(--border-strong); background: var(--surface-hover); }
    .conversa:hover .conversa__seta { translate: 3px 0; color: var(--text); }
  }

  /* Extrato de créditos: o que foi em cima, de onde veio e quando embaixo.
     O valor alinha à direita, e só entrada ganha cor — débito é o normal. */
  .ledger-row {
    display: flex; align-items: center; gap: var(--space-3);
    padding-block: var(--space-2);
  }
  .ledger-row + .ledger-row { border-top: 1px solid var(--border); }
  .ledger-row__text { display: grid; gap: 2px; min-width: 0; flex: 1; }
  .ledger-row__kind { font-weight: 550; }
  .ledger-row__note { font-size: var(--text-xs); color: var(--text-subtle); }
  .ledger-row__note:empty { display: none; }
  .ledger-row__delta { color: var(--text-muted); font-weight: 550; }
  .ledger-row__delta--in { color: var(--win-500); }

  .cat-row { display: grid; grid-template-columns: 10rem 1fr 3rem; gap: var(--space-3); align-items: center; }
  .cat-row__name { font-size: var(--text-sm); color: var(--text-muted); }
  .cat-row__value { font-size: var(--text-sm); text-align: right; }
  @media (max-width: 520px) { .cat-row { grid-template-columns: 7rem 1fr 2.5rem; } }

  .empty {
    text-align: center; padding: var(--space-8) var(--space-4);
    color: var(--text-muted);
    /* Linha de leitura curta: centralizado, texto largo perde o começo da
       linha seguinte e a pessoa relê o parágrafo. */
    max-width: 32rem; margin-inline: auto;
  }
  .empty h2 { font-size: var(--text-lg); margin-bottom: var(--space-2); color: var(--text); }

  .progress-line {
    display: flex; align-items: center; gap: var(--space-3);
    font-size: var(--text-sm); color: var(--text-muted);
  }
}

@layer components {
  /* ── voz ─────────────────────────────────────────────────────────── */
  .voice {
    flex: 1; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: var(--space-6);
    padding: var(--space-6) var(--space-4)
             calc(var(--space-6) + var(--safe-bottom, env(safe-area-inset-bottom, 0px)));
    /* Luz no centro, onde o orbe vive: a tela de voz é quase vazia e o vazio
       chapado parece inacabado — o gradiente dá o palco sem desenhar nada. */
    background: radial-gradient(70% 55% at 50% 44%, var(--bg-elevated), var(--bg-sunken) 72%);
    min-height: 0;
  }

  /* Faixa do topo da tela de voz: cronômetro à esquerda, nível à direita.
     Fica fora do fluxo para não desalinhar o orbe, que é centralizado; o
     padding-top da .voice reserva o espaço dela. */
  .voice { position: relative; padding-top: calc(var(--space-6) + 2.75rem); }
  .voice__top {
    position: absolute; inset: var(--space-4) var(--space-4) auto;
    display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3);
  }
  .voice__timer {
    margin-right: auto;
    font-size: var(--text-sm); color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
  }

  .orb {
    --orb-level: 0;
    position: relative;
    width: clamp(160px, 34vw, 260px); aspect-ratio: 1;
    border-radius: var(--radius-full);
    background: radial-gradient(circle at 35% 30%,
                var(--brand-300), var(--brand-500) 55%, var(--brand-700));
    box-shadow: 0 0 60px oklch(62% 0.19 275 / 0.35);
    transform: scale(calc(1 + var(--orb-level) * 0.12));
    transition: transform 80ms linear, opacity var(--dur-base) var(--ease-out),
                filter var(--dur-base) var(--ease-out);
    will-change: transform;
  }
  /* Anel externo: dá contorno à esfera e preenche o vazio em volta sem
     participar das animações de estado — quem pulsa é o orbe. */
  .orb::after {
    content: ""; position: absolute; inset: -9%; border-radius: inherit;
    border: 1px solid var(--brand-line); opacity: 0.55;
  }
  .orb[data-state="connecting"] {
    background: none; border: 3px solid var(--gray-400);
    border-top-color: transparent; box-shadow: none;
    animation: orb-spin 1s linear infinite;
  }
  .orb[data-state="listening"] { animation: orb-breathe 3s ease-in-out infinite; }
  .orb[data-state="thinking"]  { filter: saturate(0.6); opacity: 0.75; }
  .orb[data-state="speaking"] {
    box-shadow: 0 0 90px oklch(62% 0.19 275 / 0.55);
    background: radial-gradient(circle at 35% 30%,
                var(--brand-300), var(--brand-400) 60%, var(--brand-600));
  }
  .orb[data-state="ended"] { filter: grayscale(1); opacity: 0.4; }

  @keyframes orb-spin { to { transform: rotate(360deg); } }
  @keyframes orb-breathe {
    50% { transform: scale(calc(1.04 + var(--orb-level) * 0.12)); }
  }

  @media (prefers-reduced-motion: reduce) {
    .orb { animation: none !important; transform: none !important; }
    .orb[data-state="listening"] { outline: 3px solid var(--brand-400); outline-offset: 8px; }
    .orb[data-state="speaking"]  { outline: 6px solid var(--brand-300); outline-offset: 8px; }
  }

  .voice__status {
    font-size: var(--text-lg); font-weight: 500; text-align: center;
    min-height: 1.6em;
  }
  .voice__hint { font-size: var(--text-sm); color: var(--text-muted); text-align: center; }

  .captions {
    width: min(100%, 34rem); min-height: 4.5rem;
    padding: var(--space-4); border-radius: var(--radius-lg);
    background: var(--bg-elevated); border: 1px solid var(--border);
    font-size: var(--text-base); line-height: var(--leading-relaxed);
    display: grid; gap: var(--space-2);
  }
  .captions[hidden] { display: none; }
  .captions__line--user { color: var(--text); }
  .captions__line--assistant { color: var(--text-muted); }
  .captions__label {
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text-subtle); margin-right: var(--space-2);
  }

  .voice__controls { display: flex; gap: var(--space-3); align-items: center; }
  .voice__btn {
    display: grid; place-items: center; width: 56px; height: 56px;
    border-radius: var(--radius-full); border: 1px solid var(--border-strong);
    background: var(--bg-elevated); font-size: 1.25rem;
    transition: background var(--dur-fast), transform var(--dur-fast) var(--ease-out);
  }
  .voice__btn:hover:not(:disabled) { background: var(--surface-hover); }
  .voice__btn:active:not(:disabled) { transform: scale(0.94); }
  .voice__btn .icon { width: 1.5rem; height: 1.5rem; }
  /* O vermelho é do microfone no mudo — é o único estado "cuidado" da tela.
     O CC desligado é só ausência de legenda: fica neutro. */
  .voice__btn[aria-pressed="true"] {
    background: color-mix(in oklch, var(--danger-500) 18%, var(--bg-elevated));
    border-color: var(--danger-500);
  }
  .voice__btn--cc { font-size: var(--text-sm); font-weight: 600; letter-spacing: 0.04em; }
  .voice__btn--cc[aria-pressed="true"] {
    background: var(--brand-soft); border-color: var(--brand-line);
    color: var(--brand-text);
  }
  .voice__btn--cc[aria-pressed="false"] { color: var(--text-subtle); }
  .voice__btn--end {
    width: auto; padding-inline: var(--space-5); border-radius: var(--radius-full);
    font-size: var(--text-sm); font-weight: 550;
    background: var(--brand-500); color: var(--text-on-brand); border: none;
  }
  .voice__btn--end:hover:not(:disabled) { background: var(--brand-600); }
}

@layer views {
  /* a trajetória da conversa: o que mudou do começo para o fim */
  .debrief__progress {
    padding: var(--space-4) var(--space-5);
    border-left: 3px solid var(--brand-500);
    background: var(--bg-sunken);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    color: var(--text-muted); line-height: var(--leading-relaxed);
  }
}

@layer components {
  .lang-picker { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
  .lang-option {
    display: grid; gap: var(--space-1); cursor: pointer;
    padding: var(--space-4); border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg); background: var(--bg-elevated);
    transition: border-color var(--dur-fast), background var(--dur-fast);
  }
  .lang-option input { position: absolute; opacity: 0; pointer-events: none; }
  .lang-option:hover { background: var(--surface-hover); }
  .lang-option:has(input:checked) {
    border-color: var(--brand-500);
    background: var(--brand-tint);
  }
  .lang-option:has(input:focus-visible) { outline: 2px solid var(--brand-500); outline-offset: 2px; }
  .lang-option__name { font-size: var(--text-lg); font-weight: 600; }
  .lang-option__pt { font-size: var(--text-xs); color: var(--text-subtle); }

  /* ── nível da conversa ──────────────────────────────────────────── */

  /* Cinco barrinhas: lê-se "quão difícil" sem saber o que é CEFR. */
  .level-meter { display: inline-flex; align-items: flex-end; gap: 2px; height: 0.75rem; }
  .level-meter__bar {
    width: 3px; border-radius: 1px; background: var(--border-strong);
  }
  .level-meter__bar:nth-child(1) { height: 30%; }
  .level-meter__bar:nth-child(2) { height: 47%; }
  .level-meter__bar:nth-child(3) { height: 64%; }
  .level-meter__bar:nth-child(4) { height: 82%; }
  .level-meter__bar:nth-child(5) { height: 100%; }
  .level-meter__bar.is-on { background: var(--brand-500); }

  .level-chip {
    display: inline-flex; align-items: center; gap: var(--space-2);
    min-height: 2.25rem; /* alvo de toque confortável */
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--border-strong); border-radius: var(--radius-full);
    background: var(--bg-elevated); color: var(--text);
    font-size: var(--text-xs); font-weight: 550; white-space: nowrap;
    transition: background var(--dur-fast), border-color var(--dur-fast);
  }
  .level-chip:hover { background: var(--surface-hover); }
  .level-chip__caret { color: var(--text-subtle); font-size: 0.7em; }

  .level-list { display: grid; gap: var(--space-3); }
  .level-option {
    position: relative; display: grid; gap: var(--space-1); cursor: pointer;
    padding: var(--space-4); border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg); background: var(--bg-elevated);
    transition: border-color var(--dur-fast), background var(--dur-fast);
  }
  .level-option input { position: absolute; opacity: 0; pointer-events: none; }
  .level-option:hover { background: var(--surface-hover); }
  .level-option:has(input:checked) {
    border-color: var(--brand-500);
    background: var(--brand-tint);
  }
  .level-option:has(input:focus-visible) { outline: 2px solid var(--brand-500); outline-offset: 2px; }
  .level-option:has(input:disabled) { cursor: progress; opacity: 0.7; }
  .level-option__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
  .level-option__name { font-weight: 600; }
  .level-option__desc { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-normal); }
  .level-option__sample {
    margin-top: var(--space-1);
    font-size: var(--text-sm); font-style: italic; color: var(--text);
    padding-left: var(--space-3); border-left: 2px solid var(--border-strong);
  }
  .level-option:has(input:checked) .level-option__sample { border-left-color: var(--brand-500); }

  /* ── folha (dialog) ─────────────────────────────────────────────────
     <dialog> nativo: foco preso dentro, Esc fecha, leitor de tela entende
     como modal — nada disso precisa ser reimplementado. */
  .sheet {
    border: none; padding: 0; margin: auto;
    width: min(34rem, calc(100% - 2 * var(--space-4)));
    max-height: min(85dvh, 44rem);
    background: var(--bg); color: var(--text);
    border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
    display: flex; flex-direction: column; overflow: hidden;
  }
  .sheet:not([open]) { display: none; }
  .sheet[open] { animation: sheet-pop var(--dur-base) var(--ease-out); }
  .sheet::backdrop { background: oklch(10% 0.01 275 / 0.55); }
  .sheet__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: var(--space-3); padding: var(--space-5) var(--space-5) var(--space-3);
  }
  .sheet__title { font-size: var(--text-lg); }
  .sheet__sub { font-size: var(--text-sm); color: var(--text-muted); margin-top: var(--space-1); }
  .sheet__close {
    display: grid; place-items: center; flex: none;
    width: 2.5rem; height: 2.5rem; border-radius: var(--radius-full);
    color: var(--text-muted);
  }
  .sheet__close:hover { background: var(--surface-hover); color: var(--text); }
  .sheet__body {
    overflow-y: auto; overscroll-behavior: contain;
    padding: var(--space-2) var(--space-5) var(--space-5);
    display: grid; gap: var(--space-4);
  }
  .sheet__note { font-size: var(--text-xs); color: var(--text-subtle); }

  /* ── apresentação guiada ──────────────────────────────────────────── */
  .tour { position: fixed; inset: 0; z-index: 80; }

  /* O "buraco" é um retângulo transparente com uma sombra enorme em volta:
     escurece tudo menos o alvo, sem precisar recortar nada. */
  .tour__hole {
    position: absolute; border-radius: var(--radius-md);
    box-shadow: 0 0 0 100vmax oklch(10% 0.01 275 / 0.72);
    outline: 2px solid var(--brand-500); outline-offset: 0;
    transition: all var(--dur-base) var(--ease-out);
    pointer-events: none;
  }

  .tour__bubble {
    position: absolute; width: min(20rem, calc(100vw - 24px));
    /* Alvo mais alto que a tela pode produzir um balão mais alto que ela
       também; melhor rolar por dentro do que sair da área visível. */
    max-height: calc(100dvh - 24px); overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-4) var(--space-5);
    background: var(--bg-elevated); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    display: grid; gap: var(--space-2);
    animation: bubble-in var(--dur-base) var(--ease-out);
  }
  .tour__step { font-size: var(--text-xs); color: var(--text-subtle); }
  .tour__title { font-size: var(--text-base); font-weight: 600; }
  .tour__text { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-relaxed); }
  .tour__actions { display: flex; gap: var(--space-2); justify-content: flex-end; margin-top: var(--space-1); }

  /* Setinha apontando para o alvo. */
  .tour__bubble::after {
    content: ""; position: absolute; left: 50%; translate: -50% 0;
    border: 8px solid transparent;
  }
  .tour__bubble:not(.tour__bubble--below)::after {
    top: 100%; border-top-color: var(--bg-elevated);
  }
  .tour__bubble--below::after {
    bottom: 100%; border-bottom-color: var(--bg-elevated);
  }
  /* Sem seta quando o balão fica POR CIMA do alvo (alvo mais alto que a tela):
     ela apontaria para o próprio balão. */
  .tour__bubble--over::after { display: none; }

  @keyframes sheet-pop {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
  }

  /* No celular vira folha que sobe do rodapé: fica onde o polegar está. */
  @media (max-width: 640px) {
    .sheet {
      width: 100%; max-width: none; margin: auto 0 0;
      max-height: 88dvh;
      border-radius: var(--radius-xl) var(--radius-xl) 0 0;
      padding-bottom: env(safe-area-inset-bottom, 0px);
    }
    .sheet[open] { animation: sheet-up var(--dur-base) var(--ease-out); }
  }
  @keyframes sheet-up {
    from { transform: translateY(100%); }
    to   { transform: none; }
  }

  /* Faixa do topo do chat: o que está sendo trabalhado à esquerda, o nível
     à direita. */
  .chat__bar {
    max-width: var(--container-chat); margin: 0 auto; width: 100%;
    padding: var(--space-3) var(--space-4) 0;
    display: flex; align-items: center; gap: var(--space-3);
  }
  .chat__bar .chat__targets { padding: 0; margin: 0; flex: 1; min-width: 0; }
  .chat__bar .level-chip { margin-left: auto; flex: none; }

  /* No celular o nível desce para a própria linha: lado a lado com os alvos
     da conversa, ele espremia os chips em três linhas de duas palavras. */
  @media (max-width: 640px) {
    .chat__bar { display: grid; gap: var(--space-3); }
    .chat__bar .level-chip { margin-left: 0; justify-self: start; }
  }

  .lang-switch {
    display: flex; gap: var(--space-1); padding: 2px; flex: none;
    background: var(--surface-hover); border-radius: var(--radius-full);
  }
  .lang-switch button {
    padding: var(--space-1) var(--space-3); border-radius: var(--radius-full);
    font-size: var(--text-xs); font-weight: 550; color: var(--text-muted);
    /* 日本語 quebra em três linhas dentro do botão se o flex apertar — a
       barra de cima inteira cresce por causa disso. */
    white-space: nowrap;
    transition: background var(--dur-fast), color var(--dur-fast);
  }
  .lang-switch button[aria-pressed="true"] {
    background: var(--bg-elevated); color: var(--text); box-shadow: var(--shadow-sm);
  }
}

@layer components {
  /* Em celular a navegação vai para baixo, onde o polegar alcança — e para de
     disputar espaço com a marca e o seletor de idioma na barra de cima. */
  @media (max-width: 640px) {
    .topbar {
      gap: var(--space-3); padding-inline: var(--space-4);
      /* backdrop-filter cria bloco de contenção para descendentes fixed — com
         ele, a nav de baixo fica presa DENTRO da topbar e cobre a marca. */
      backdrop-filter: none;
      background: var(--bg);
    }

    .nav {
      position: fixed; inset: auto 0 0 0; z-index: 20;
      justify-content: space-around; gap: var(--space-1);
      padding: var(--space-2) var(--space-2)
               calc(var(--space-2) + var(--safe-bottom, env(safe-area-inset-bottom, 0px)));
      background: color-mix(in oklch, var(--bg) 92%, transparent);
      backdrop-filter: blur(12px);
      border-top: 1px solid var(--border);
      overflow: visible;
    }

    /* Cada item é um alvo com forma: ícone em cima, nome embaixo, fundo
       próprio quando ativo. Só o sublinhado não dizia onde começava e
       terminava o que dava para tocar. */
    .nav__item {
      flex: 1; min-width: 0;
      display: grid; justify-items: center; gap: 3px;
      padding: var(--space-2) var(--space-1);
      border-radius: var(--radius-md);
      font-size: 0.6875rem; line-height: 1.1; text-align: center;
      text-decoration: none;
    }
    .nav__icon { width: 1.3rem; height: 1.3rem; }

    /* A barra é fixa e flutua sobre o conteúdo, então o conteúdo precisa
       abrir mão da altura dela. Esse número é MEDIDO em JavaScript e chega
       aqui como --nav-space (ver main.js).
       Três tentativas de escrevê-lo à mão falharam: a área segura vale 0 num
       aparelho e 48px em outro, e o valor fixo de 4rem sobrava por 1rem. O
       6rem abaixo é só a rede de segurança para o instante antes de a medição
       acontecer — generoso de propósito, porque sobrar espaço é invisível e
       faltar esconde um botão. */
    .composer { padding-bottom: calc(var(--nav-space, 6rem) + var(--space-3)); }
    .voice    { padding-bottom: calc(var(--nav-space, 6rem) + var(--space-6)); }
  }
}

@layer views {
  /* Esta regra PRECISA estar na camada `views`.
     `.view { padding }` é declarada em @layer views; a ordem no topo do
     arquivo é `base, components, views`, e camada vence camada — antes de
     especificidade, antes de media query, antes de tudo. A mesma regra
     escrita em `components` é simplesmente ignorada, sem erro e sem aviso.
     Foi o que manteve o botão de "Começar a conversar" debaixo da barra por
     três correções seguidas: a regra que eu ajustava nunca chegava a valer. */
  @media (max-width: 640px) {
    .view { padding-bottom: calc(var(--nav-space, 6rem) + var(--space-6)); }
  }
}

@layer components {
  /* Saldo sempre à vista: crédito que some sem o usuário perceber vira
     surpresa no meio de uma conversa. */
  .balance {
    display: inline-flex; align-items: center; gap: var(--space-1);
    padding: var(--space-1) var(--space-3); border-radius: var(--radius-full);
    background: var(--surface-hover); color: var(--text-muted);
    font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums;
    text-decoration: none; transition: background var(--dur-fast);
  }
  .balance::before { content: "◈"; color: var(--brand-400); }
  .balance:hover { background: var(--border); color: var(--text); }
  .balance--empty {
    background: color-mix(in oklch, var(--focus-500) 18%, transparent);
    color: var(--focus-500);
  }
  .balance--empty::before { color: var(--focus-500); }
}
