/* allSwap v21 — sistema "pôster preto" (ver DESIGN.md + PLANO-V21.md) */
@font-face{
  font-family:"Anton";
  src:url('/v22/fonts/anton.woff2') format('woff2');
  font-weight:400;font-style:normal;font-display:swap;
}
:root{
  /* v22 — escada malva (ART2-2): as superfícies acima do preto ganham um fio
     do matiz da marca, mesma luminância da escada cinza antiga. --ink e o
     theme-color do index.html NÃO mudam. */
  --ink:#050505; --ink-2:#0E0C0F; --ink-3:#161318; --ink-4:#1F1B21;
  --pink:#FF2D8F; --pink-2:#ED1E79; --pink-deep:#B60C57; --pink-dim:rgba(255,45,143,.13);
  --white:#FFFFFF; --mute:#A79BA3; --mute-2:#8F8494; --press:#170A10;
  --hair:rgba(255,255,255,.12); --hair-2:rgba(255,255,255,.06);
  --teal:#2FD3A5; --gold:#F5C24B; --violet:#9B8CFF;
  /* F5 (rodada 1): erro é VERMELHO, não o rosa da marca — erro cor de marca
     vira decoração e ninguém lê como problema. Formulários usam este token. */
  --danger:#FF5C5C;
  /* F4 (rodada 1): verde de acerto legível nos 2 temas (deck .yes, checks) */
  --green:#4ADE80;
  /* v22 — chrome (UX2-1): header e tabbar OPACOS de propósito — a .97 o card
     fantasma do deck aparecia através do header no arremesso do swipe.
     --glass é o translúcido legítimo: vive SOBRE O MAPA do radar, onde ver
     através é o ponto. */
  --chrome:#050505; --chrome-2:#050505; --glass:rgba(5,5,5,.92);
  --display:"Anton",Impact,system-ui,sans-serif;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Inter,"Helvetica Neue",sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --safe-b:env(safe-area-inset-bottom,0px);
  /* Reforma Baygon (19/ago): barra um pouco maior e com folga garantida
     embaixo — em celular de gesto a barrinha do sistema caía EM CIMA dos
     ícones quando o env() vinha 0 (Android web/WebView). */
  --tabh:68px;
  --tab-safe:max(var(--safe-b),16px);
  /* v22 — corpo de texto por token (UX2-6, escopo restrito): consumido SÓ por
     ui.css, mod-otto e mod-conversas nesta rodada; html.txt-lg re-declara os
     tokens. Demais módulos migram na v23. */
  --fs-body:14.5px; --fs-sub:13px; --fs-hint:12.5px; --fs-k:10.5px;
  /* v22 — sombras compostas num token só (UX2-8 + ART2-4): o tema claro troca
     o highlight interno por sombra de papel redefinindo só os tokens. */
  --shadow-card:inset 0 1px 0 rgba(255,255,255,.05);
  --shadow-sheet:inset 0 1px 0 rgba(255,255,255,.05),0 -18px 48px rgba(0,0,0,.5);
  --shadow-mdl:inset 0 1px 0 rgba(255,255,255,.05),0 24px 64px rgba(0,0,0,.55);
  /* Geometria por PAPEL, não por gosto: o raio passa a dizer o que a coisa é.
     sm = controle pequeno e caixa de aviso; md = bloco de conteúdo curto;
     lg = card; xl = superfície que cobre a tela (folha e modal); pill = trilho.
     Quem escrever componente novo escolhe o papel, não um número. */
  --r-sm:10px; --r-md:14px; --r-lg:18px; --r-xl:20px; --r-pill:99px;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
/* F2 (rodada 1): o arrasto horizontal do deck NUNCA pode virar a navegação
   "voltar" do navegador (testador saiu do app no meio do swipe). O gesto de
   swipe-nav do Chrome/Edge nasce do overscroll no eixo X — cortado na raiz. */
html,body{overscroll-behavior-x:none}
/* 21/ago — o CARD EM VOO nao pode inchar a viewport do WebView.
   `overflow-x:hidden` estava so no body, e no Android o que manda no viewport
   e o ROOT: o card que sai (`.dk-card.out-r`, translate 126%) transbordava a
   largura, o WebView entrava em "shrink to fit" e dava zoom-out. Medido no
   moto g15: `innerHeight` saltava 901 -> 1314 -> 1389 CSS px no meio do gesto.
   `fitStack()` remedia a barra de decisao nessa viewport falsa e escrevia
   `--dkh` de 838px (era 422), a pilha dobrava, a tabbar caia para fora da tela
   e por ~500ms sobrava um retangulo chapado com o gradiente da capa do proximo
   anuncio ocupando quase tudo — o "a tela toda fica azul" que o dono viu (azul
   quando a capa seguinte era azul; a cor era sempre a do proximo card).
   `clip` e nao `hidden`: no root, `hidden` propaga para o viewport e cria
   container de rolagem; `clip` corta o transbordo lateral e deixa o eixo Y
   `visible`, entao o scroll vertical das telas longas continua igual. */
html{overflow-x:clip}
html{background:var(--ink)}
body{background:var(--ink);color:var(--white);font-family:var(--sans);font-size:var(--fs-body);line-height:1.45;
  overflow-x:hidden;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;border:none;background:none}
a{color:inherit;text-decoration:none}
::selection{background:var(--pink);color:#fff}
.hidden{display:none!important}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.wrap{width:100%;max-width:440px;margin:0 auto;padding:0 16px}

/* ---------- tipografia ---------- */
.disp{font-family:var(--display);text-transform:uppercase;letter-spacing:0;line-height:1.1;font-weight:400}
h1.disp{font-size:34px}
.disp-xl{font-size:40px}
.disp-lg{font-size:30px}
/* v22 (UX2-6): display pequeno (≤22px) respira com .015em; ≥30px mantém 0 —
   tracking relativo ao corpo, não ao pôster. */
.disp-md{font-size:22px;letter-spacing:.015em}
.lbl{font-size:var(--fs-k);font-weight:800;letter-spacing:.11em;text-transform:uppercase;color:var(--mute-2)}
.sub{color:var(--mute);font-size:var(--fs-sub)}
.hint{color:var(--mute);font-size:var(--fs-hint)}
.pink{color:var(--pink)}
.tealc{color:var(--teal)}
.goldc{color:var(--gold)}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:700}

/* ---------- marca ---------- */
.wm{display:inline-flex;align-items:baseline;font-weight:900;letter-spacing:-1px;line-height:1}
/* v22 (UX2-1): o "all" acompanha o chrome — em chrome claro, tinta escura. */
.wm .a{color:var(--white)}
.wm .s{color:var(--pink)}
.mark{width:30px;height:30px;flex:none;object-fit:contain}
.mark-fb{width:30px;height:30px;flex:none;border-radius:9px;display:grid;place-items:center;font-weight:900;
  font-size:16px;background:var(--pink);color:#0A0006}
.tagline{font-size:11px;font-weight:700;letter-spacing:.24em;text-transform:uppercase;color:var(--mute)}
.tagline b{color:var(--pink);font-weight:800}

/* ---------- estrutura ---------- */
.rule{height:1px;background:var(--hair);border:0;margin:14px 0}
.rule.glow{background:linear-gradient(90deg,transparent,rgba(255,45,143,.75),transparent);height:1px}
.rule.tight{margin:10px 0}
.sec{margin:22px 0 10px;display:flex;align-items:baseline;gap:10px}
.sec h2{font-family:var(--display);text-transform:uppercase;font-size:19px;letter-spacing:.015em;font-weight:400;line-height:1.1}
.sec .more{margin-left:auto;font-size:11.5px;font-weight:800;color:var(--pink);letter-spacing:.3px}
.card{background:var(--ink-2);border:1px solid var(--hair);border-radius:var(--r-lg);padding:16px;
  box-shadow:var(--shadow-card)}
.card + .card{margin-top:10px}
.card.flat{background:none;border-color:var(--hair-2)}
.card.pink-edge{border-color:rgba(255,45,143,.45)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.grid2 > *{min-width:0}
.stack{display:grid;gap:10px}

/* ---------- ícones desenhados (AS.icon) ---------- */
.ic{width:1em;height:1em;flex:none;display:inline-block;vertical-align:-.14em}

/* ---------- ícone de linha em círculo (do anúncio) ---------- */
.ico{width:40px;height:40px;flex:none;border-radius:50%;border:1.5px solid var(--pink);color:var(--pink);
  display:grid;place-items:center;font-size:17px;line-height:1}
.ico .ic{width:1.2em;height:1.2em;vertical-align:0}
.ico.sm{width:30px;height:30px;font-size:13px;border-width:1.5px}
.ico.lg{width:56px;height:56px;font-size:24px}
.ico.mutec{border-color:var(--hair);color:var(--mute)}
.ico.tealc{border-color:rgba(47,211,165,.6);color:var(--teal)}
.ico.goldc{border-color:rgba(245,194,75,.6);color:var(--gold)}
.ico.solid{background:var(--pink);color:#0A0006;border-color:transparent}
/* v22 (ART1-3): violeta é autoria — o círculo do Otto quando ele assina. */
.ico.vio{border-color:rgba(155,140,255,.6);color:var(--violet)}

/* ---------- KPI ---------- */
.kpi{display:grid;gap:2px}
.kpi .v{font-family:var(--display);font-size:30px;line-height:.95;letter-spacing:0;font-weight:400}
.kpi .v.mono{font-family:var(--mono);font-size:22px;font-weight:700;letter-spacing:-.5px}
.kpi .d{font-size:11px;font-weight:800;font-family:var(--mono)}
.kpi .d.up{color:var(--teal)}
.kpi .d.dn{color:var(--pink)}
.kpi-row{display:grid;grid-template-columns:1fr 1fr;gap:16px 12px}

/* ---------- linha de lista ---------- */
.row{display:flex;align-items:center;gap:12px;padding:13px 0;border-bottom:1px solid var(--hair-2);
  width:100%;text-align:left}
.row:last-child{border-bottom:0}
.row .body{flex:1;min-width:0}
.row .t{font-size:14.5px;font-weight:700;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row .s{font-size:12.5px;color:var(--mute);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:1px}
.row .r{margin-left:auto;text-align:right;flex:none}
.row .r .v{font-family:var(--mono);font-weight:700;font-size:13.5px}
.row .r .k{font-size:10px;color:var(--mute-2);letter-spacing:.6px;text-transform:uppercase}
.row .chev{color:var(--mute-2);font-size:16px;flex:none}
.row.press:active{background:var(--press)}
.av{width:40px;height:40px;flex:none;border-radius:12px;display:grid;place-items:center;font-weight:800;font-size:13px;
  background:var(--ink-4);border:1px solid var(--hair);font-family:var(--sans);overflow:hidden}
.av img{width:100%;height:100%;object-fit:cover}
.av.dot::after{content:"";position:absolute}

/* ---------- revelação progressiva ----------
   O <details class="dk-disc"> nasceu no deck (rodada 1) e virou componente do
   sistema: o que fala de dinheiro, custódia, taxa ou responsabilidade nunca é
   apagado — sai do CAMINHO de quem está decidindo e fica a um toque. Na frente
   ficam o número e a consequência; o parágrafo mora dentro.
   <details> é bloco: não pode ser aberto dentro de um <p>. */
.disc{margin-top:10px}
.disc > summary{display:flex;align-items:center;gap:8px;min-height:36px;cursor:pointer;list-style:none;
  font-size:12px;font-weight:700;letter-spacing:.2px;color:var(--mute)}
.disc > summary::-webkit-details-marker{display:none}
.disc > summary::after{content:"+";margin-left:auto;flex:none;width:20px;height:20px;border-radius:50%;
  border:1px solid var(--hair);display:grid;place-items:center;font-size:13px;line-height:1;color:var(--mute-2)}
.disc > summary:hover{color:var(--white)}
.disc[open] > summary{color:var(--white)}
.disc[open] > summary::after{content:"\2212";border-color:var(--pink);color:var(--pink)}
.disc > summary + *{margin-top:0}
/* Resposta ao toque: o que estava escondido ENTRA, em vez de piscar no lugar.
   <details> não anima sozinho — 120 ms de subida bastam para o olho seguir de
   onde o texto veio e não reler a tela inteira. É o único movimento do
   componente: nada pulsa, nada se repete. */
.disc[open] > summary + *{animation:discIn .12s cubic-bezier(.2,.9,.25,1)}
@keyframes discIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}

/* ---------- a leitura do Otto na superfície da decisão ----------
   O servidor (api/app/services/otto_mesa.py) já escreve o que o Otto viu na
   conta quando uma proposta entra. Isso vivia SÓ como mensagem no fio da
   conversa — rolava para cima e sumia justamente quando a pessoa ia decidir.
   Este bloco é o mesmo violeta do moderador (o da mesa a três e o da bolha
   `.cv-ottoline`), agora onde estão aceitar, recusar e contrapor: duas telas
   (folha da proposta em mod-conversas.js e folha da Mesa em mod-mesa.js) usam
   o MESMO componente, então ele mora aqui, como o `.disc`.
   Só entra: 160 ms de subida, uma vez, para o olho achar quem falou. */
.otto-read{margin-top:11px;border:1px solid rgba(155,140,255,.3);background:rgba(155,140,255,.07);
  border-radius:var(--r-md);padding:10px 13px;font-size:13px;line-height:1.5;text-align:left;
  animation:ottoRead .16s cubic-bezier(.2,.9,.25,1)}
.otto-read .who{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:10px;
  font-weight:800;letter-spacing:1px;text-transform:uppercase;color:var(--violet);margin-bottom:5px}
.otto-read .who .ic,.otto-read .who svg{width:13px;height:13px;vertical-align:0}
/* a voz do cérebro por cima do parecer (20/ago): leitura verificada em cima da
   conta que já está na folha — negrito para se distinguir do texto do parecer */
.otto-read .voz,.bf-juizo .voz{display:block;margin:0 0 7px;font-weight:600;line-height:1.45;
  animation:ottoRead .16s cubic-bezier(.2,.9,.25,1)}
.bf-juizo .voz{margin:6px 0 0;font-size:12.5px}
@keyframes ottoRead{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}

/* ---------- tag ---------- */
/* v22 (UX2-5): piso tipográfico — nada lido abaixo de 10px (9.5→10.5). */
.tag{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:800;letter-spacing:.085em;
  text-transform:uppercase;border:1px solid var(--hair);border-radius:6px;padding:3px 7px;color:var(--mute);
  white-space:nowrap}
/* Rosa é cor de FUNDO, não de texto branco em cima: #fff sobre --pink dá
   3,49:1 e reprova AA. A tinta escura da marca dá 5,93:1 — é a mesma decisão
   já tomada na landing (site/index.html › .btn.solid). */
.tag.pink{color:#0A0006;border-color:transparent;background:var(--pink)}
.tag.pinkline{color:var(--pink);border-color:rgba(255,45,143,.5)}
.tag.teal{color:var(--teal);border-color:rgba(47,211,165,.45)}
.tag.gold{color:var(--gold);border-color:rgba(245,194,75,.45)}
.tag.violet{color:var(--violet);border-color:rgba(155,140,255,.45)}
.vf{display:inline-grid;place-items:center;width:14px;height:14px;border-radius:50%;background:var(--teal);
  color:#04231a;font-size:9px;font-weight:900;vertical-align:1px}

/* ---------- botões ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 18px;
  border-radius:12px;font-size:14.5px;font-weight:800;letter-spacing:.2px;transition:opacity .15s,
  background .15s,border-color .15s}
.btn:active{background:var(--press)}
/* mesma razão da .tag.pink: 3,49:1 → 5,93:1, sem trocar o rosa da marca */
.btn.solid{background:var(--pink);color:#0A0006}
.btn.solid:hover{background:var(--pink-2)}
.btn.solid:active{background:var(--pink-2)}
/* F4 (rodada 1): tokens no lugar de branco literal — o tema claro troca os
   tokens e estes botões ficavam invisíveis (branco sobre branco). */
.btn.line{border:1px solid var(--hair);color:var(--white)}
.btn.line:hover{border-color:var(--pink);color:var(--white)}
.btn.ghost{color:var(--pink);padding:0 6px;min-height:40px}
.btn.block{width:100%}
.btn.sm{min-height:38px;font-size:13px;padding:0 13px;border-radius:var(--r-sm)}
.btn.xs{min-height:32px;font-size:12px;padding:0 10px;border-radius:9px;font-weight:800}
.btn[disabled]{opacity:.4;cursor:default}
/* v22 (ART2-5): o CTA principal emite luz — mas com contenção: dentro do corpo
   de modal tudo é FOSCO (só o CTA do rodapé acende) e, quando há dois solids
   lado a lado, só o ÚLTIMO carrega o halo. Um glow por tela, sempre no botão
   que fecha a decisão. */
.btn.solid:not(.sm):not(.xs){box-shadow:0 8px 22px rgba(255,45,143,.20)}
.btn.solid:not(.sm):not(.xs):active{box-shadow:0 4px 12px rgba(255,45,143,.14)}
.mdl-body .btn.solid{box-shadow:none}
.mdl-foot .btn.solid:not(:last-of-type),
.btn-row .btn.solid:not(:last-of-type){box-shadow:none}
html[data-tema="claro"] .btn.solid:not(.sm):not(.xs){box-shadow:0 6px 16px rgba(237,30,121,.16)}
html[data-tema="claro"] .mdl-body .btn.solid{box-shadow:none}
.btn-row{display:flex;gap:9px}
.btn-row > .btn{flex:1}
.spin{width:15px;height:15px;border-radius:50%;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;
  display:inline-block;animation:sp .7s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}

/* ---------- campos ---------- */
.field{margin-bottom:13px}
.field > label{display:block;margin-bottom:6px}
.input{width:100%;background:var(--ink-3);border:1px solid var(--hair);border-radius:12px;padding:13px 14px;
  font-size:15px;outline:none;transition:border-color .15s}
.input:focus{border-color:var(--pink)}
/* O exemplo dentro do campo é instrução, não decoração: em #4B4B55 ele dava
   2,13:1 sobre --ink-3 e sumia no sol. --mute-2 é o mesmo cinza do resto do
   texto secundário do sistema (5,16:1) — continua claramente "ainda vazio". */
.input::placeholder{color:var(--mute-2)}
textarea.input{min-height:70px;resize:vertical}
select.input{appearance:none}
.err{border:1px solid rgba(255,45,143,.5);background:rgba(255,45,143,.1);color:#FFC2DC;border-radius:var(--r-sm);
  padding:10px 12px;font-size:13px;margin-bottom:12px}

/* ---------- medidor ---------- */
/* medidor: .meter (alias .bar para markup ja escrito; :not(header) evita colidir com <header class="bar">) */
.meter,.bar:not(header){height:5px;border-radius:var(--r-pill);background:var(--ink-4);overflow:hidden}
.meter > i,.bar:not(header) > i{display:block;height:100%;background:var(--pink);border-radius:var(--r-pill)}
.meter.teal > i,.bar:not(header).teal > i{background:var(--teal)}
.steps{display:flex;gap:4px}
.steps i{flex:1;height:4px;border-radius:var(--r-pill);background:var(--ink-4)}
.steps i.on{background:var(--pink)}
.steps.teal i.on{background:var(--teal)}

/* ---------- login ---------- */
#login{min-height:100dvh;display:grid;place-items:center;padding:30px 18px;
  /* v22 (ART2-7): vinheta — dois respiros de cor nos cantos opostos, abaixo do
     limiar de banding; o claro dispensa (papel não emite luz). */
  background:
    radial-gradient(110% 70% at 14% 6%,rgba(255,45,143,.06),transparent 50%),
    radial-gradient(90% 60% at 88% 96%,rgba(155,140,255,.04),transparent 55%),
    var(--ink)}
html[data-tema="claro"] #login{background:var(--ink)}
.login-box{width:100%;max-width:400px}
.poster{text-align:left;margin-bottom:26px}
.poster h1{font-family:var(--display);text-transform:uppercase;font-size:clamp(34px,10vw,48px);line-height:1.1;
  letter-spacing:0;font-weight:400}
.poster h1 .pk{color:var(--pink)}
.poster .lead{margin-top:16px;display:grid;gap:12px}
.poster .lead div{display:flex;align-items:center;gap:12px;font-size:14.5px;font-weight:600;line-height:1.25}
.poster .lead b{color:var(--pink);font-weight:800}
.brandline{display:flex;align-items:center;gap:10px;margin:20px 0 8px}
.brandline .wm{font-size:34px}
.top-hub{position:fixed;top:12px;right:14px;font-size:11.5px;font-weight:700;color:var(--mute-2);padding:6px 10px;
  border-radius:8px;z-index:60}
.top-hub:hover{color:var(--white)}
/* R2 (G2h): alternador de tema no canto do login — 36px de caixa, 44px de mira
   (mesmo truque do .btn.sm), antes de existir qualquer sessão. */
.top-tema{position:fixed;top:8px;left:14px;z-index:60;width:36px;height:36px;border-radius:99px;
  border:1px solid var(--hair);color:var(--mute);display:grid;place-items:center;background:none}
.top-tema svg{width:18px;height:18px}
.top-tema:hover{color:var(--white);border-color:var(--hair)}
.top-tema::after{content:'';position:absolute;inset:-4px}
/* R2 (G16): "Esqueci a senha" tem 26px de caixa — a MIRA cresce até 44px. */
#forgotBtn{position:relative}
#forgotBtn::after{content:'';position:absolute;inset:calc((44px - 100%) / -2) 0}

/* ---------- shell ---------- */
#app{min-height:100dvh;display:flex;flex-direction:column}
/* O header e a tabbar tinham backdrop-filter LIGADO O TEMPO TODO. Sob 92%/96%
   de preto o borrão não aparecia — mas obrigava o compositor a reprocessar duas
   faixas de largura total a cada quadro em que qualquer coisa se mexia (arrasto
   do card, saída do swipe, giro do Swapou!, rolagem). Trocado por um preto um
   fio mais fechado: mesmo desenho, sem o imposto por quadro. */
header.bar{position:sticky;top:0;z-index:40;background:var(--chrome);
  padding-top:env(safe-area-inset-top,0px);
  border-bottom:1px solid transparent;transition:border-color .2s}
/* v22 (UX2-3): o traço do header só existe quando há conteúdo passando por
   baixo — acende com scrollY>8 (core.js › boot) e apaga no topo. Threshold
   único, sem histerese. */
header.bar.lift{border-bottom-color:var(--hair-2)}
header.bar .row-h{display:flex;align-items:center;gap:8px;padding:10px 0;flex-wrap:nowrap}
header .wm{font-size:19px}
.hpill{position:relative;display:inline-flex;align-items:center;gap:5px;border:1px solid var(--hair);border-radius:var(--r-pill);
  padding:5px 10px;font-size:11px;font-weight:800;white-space:nowrap;flex:none;font-family:var(--mono)}
.hpill[role="button"]::after{content:'';position:absolute;inset:-9px 0}
.hpill .ic{width:13px;height:13px;vertical-align:0}
.hpill [data-icon]{display:inline-flex;align-items:center}
.hpill .k{font-size:10px;letter-spacing:.7px;text-transform:uppercase;color:var(--mute-2);font-family:var(--sans)}
.hpill.plan-premium{color:var(--gold);border-color:rgba(245,194,75,.5)}
.hpill.plan-business{color:var(--teal);border-color:rgba(47,211,165,.5)}
.hpill.plan-basic{color:var(--mute)}
.spacer{flex:1}
main{flex:1;padding:12px 0 calc(var(--tabh) + 30px + var(--tab-safe))}
nav.tabbar{position:fixed;left:0;right:0;bottom:0;z-index:45;background:var(--chrome-2);
  border-top:1px solid var(--hair-2);padding-bottom:var(--tab-safe)}
nav.tabbar .row-t{display:grid;padding:0}
nav.tabbar button{position:relative;height:var(--tabh);display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:4px;font-size:10px;font-weight:800;letter-spacing:.3px;color:var(--mute-2);
  min-width:0;max-width:100%;overflow:hidden;white-space:nowrap}
nav.tabbar button .g{font-size:20px;line-height:1;display:grid;place-items:center}
nav.tabbar button.on{color:var(--pink)}
nav.tabbar .tb-ind{position:absolute;top:0;left:0;height:2px;background:var(--pink);pointer-events:none;
  width:calc(56% / var(--n,5));transform:translateX(calc((var(--i,0) + .22) * 100% / .56));
  transition:transform .18s ease-out}
nav.tabbar .tb-ind.off{opacity:0}
/* O numeral aqui é o texto mais hostil do sistema: 9px, peso 800, dentro de um
   selo de 15px. Em branco sobre --pink dava 3,49:1 — a mesma tinta escura das
   .btn.solid/.tag.pink leva a 5,93:1 e é o que decide se "3" ou "8" some. */
nav.tabbar .bdg{position:absolute;top:9px;right:calc(50% - 20px);min-width:16px;height:16px;border-radius:var(--r-pill);
  background:var(--pink);color:#0A0006;font-size:10px;font-weight:800;display:grid;place-items:center;padding:0 4px;
  font-family:var(--mono)}
/* O selo só se mexe quando a CONTAGEM SOBE — chegou coisa nova esperando por
   você. A barra é reescrita a cada troca de tela, e animar em toda reescrita
   transformaria o aviso em enfeite (o core guarda a última contagem por aba
   justamente para saber a diferença). */
@keyframes bdgUp{
  0%{transform:scale(.6);opacity:0}
  55%{transform:scale(1.18);opacity:1}
  100%{transform:scale(1);opacity:1}
}
nav.tabbar .bdg.up{animation:bdgUp .26s cubic-bezier(.2,.9,.25,1) both}

/* ---------- segmento de superfície ----------
   Duas telas que respondem à mesma pergunta viradas para lados opostos — o
   Radar mostra o que a rede OFERECE, o Reverso o que ela PROCURA. Uma delas
   deixou a barra para a aba de Swaps entrar; este segmento é o preço disso:
   um toque, sempre no mesmo lugar, no topo das duas. */
.nav-seg{display:flex;gap:4px;padding:3px;margin:0 0 12px;border:1px solid var(--hair);
  border-radius:var(--r-pill);background:var(--ink-2)}
.nav-seg > *{flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center;gap:6px;
  height:34px;border-radius:var(--r-pill);font-size:12px;font-weight:800;letter-spacing:.3px;color:var(--mute);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:background .16s ease,color .16s ease}
.nav-seg > .on{background:var(--ink-4);color:var(--white)}
.nav-seg .ic{width:15px;height:15px;flex:none}
@media (max-width:340px){.nav-seg .ic{display:none}}
@media (prefers-reduced-motion:reduce){.nav-seg > *{transition:none}}
html.no-anim nav.tabbar .bdg.up{animation:none}
.view-head{margin:4px 0 12px}
.view-head h1{font-family:var(--display);text-transform:uppercase;font-size:30px;letter-spacing:0;line-height:1.1;
  font-weight:400}
.view-head p{color:var(--mute);font-size:13px;margin-top:5px}
.back{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:800;color:var(--mute);
  letter-spacing:.6px;text-transform:uppercase;margin-bottom:10px}

/* ---------- estados ---------- */
.empty{text-align:center;padding:38px 20px}
.empty .ico{margin:0 auto 14px}
.empty h3{font-family:var(--display);text-transform:uppercase;font-size:22px;line-height:1.1;letter-spacing:.015em;
  font-weight:400;margin-bottom:7px}
/* v22 (UX2-9): vazio compacto para superfícies pequenas (dropdown do sino). */
.empty.tight{padding:22px 16px}
.empty p{color:var(--mute);font-size:13.5px;max-width:300px;margin:0 auto}
.empty .btn{margin-top:16px}
/* Mercado abrindo (Deslizar, Radar, Comunidade, Reverso): o vazio de um país
   que ainda não tem empresa nenhuma, que é o oposto do vazio por filtro. O
   único movimento é a ENTRADA do estado — 180 ms de subida para o olho pousar
   no que mudou. Não pulsa, não repete: é notícia de mercado começando, não
   festa. */
.mkt-open{animation:mktIn .18s cubic-bezier(.2,.9,.25,1) both}
@keyframes mktIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion:reduce){.mkt-open{animation:none}}
html.no-anim .mkt-open{animation:none!important}
.skel{border-radius:var(--r-md);background:linear-gradient(100deg,rgba(255,255,255,.05) 30%,rgba(255,255,255,.1) 50%,
  rgba(255,255,255,.05) 70%);background-size:220% 100%;animation:sh 1.3s linear infinite}
@keyframes sh{from{background-position:120% 0}to{background-position:-20% 0}}

/* ---------- folha / modal ---------- */
#modalRoot{position:fixed;inset:0;z-index:70;pointer-events:none}
#modalRoot.on{pointer-events:auto}
.ovl{position:absolute;inset:0;background:rgba(0,0,0,.72);backdrop-filter:blur(3px);opacity:0;transition:opacity .2s}
#modalRoot.on .ovl{opacity:1}
.sheet{position:absolute;left:0;right:0;bottom:0;display:flex;flex-direction:column;max-height:92dvh;
  background:var(--ink-2);border-top:1px solid var(--hair);border-radius:var(--r-xl) var(--r-xl) 0 0;
  box-shadow:var(--shadow-sheet);
  /* v22 (UX1-5): a folha ENTRA de baixo de verdade — min(100%,60vh) em vez de
     um empurrão de 18px; folha alta pede ~300ms para o olho acompanhar. */
  transform:translateY(min(100%,60vh));opacity:0;transition:transform .3s cubic-bezier(.2,.9,.25,1),opacity .2s}
#modalRoot.on .sheet{transform:translateY(0);opacity:1}
.mdl{position:absolute;left:50%;top:50%;width:min(94vw,430px);max-height:88dvh;display:flex;flex-direction:column;
  /* v22 (UX1-5): entrada por translateY(28px) — mesmo vocabulário da folha. */
  transform:translate(-50%,-50%) translateY(28px) scale(.97);opacity:0;background:var(--ink-2);border:1px solid var(--hair);
  box-shadow:var(--shadow-mdl);
  border-radius:var(--r-xl);transition:transform .22s cubic-bezier(.2,.9,.25,1),opacity .2s}
#modalRoot.on .mdl{transform:translate(-50%,-50%) scale(1);opacity:1}
.grab{width:36px;height:4px;border-radius:var(--r-pill);background:var(--hair);margin:9px auto 2px;flex:none}
.sheet .grab,.sheet .mdl-head{touch-action:none}
.mdl-head{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid var(--hair-2);flex:none}
.mdl-head h3{font-family:var(--display);text-transform:uppercase;font-size:20px;letter-spacing:.015em;line-height:1.1;
  font-weight:400}
.mdl-head .x{margin:-6px -6px -6px auto;width:44px;height:44px;border-radius:12px;border:1px solid var(--hair);
  color:var(--mute);display:flex;align-items:center;justify-content:center;flex:none}
.mdl-head .x:active{background:var(--press)}
.mdl-head .x .ic{width:18px;height:18px;vertical-align:0}
.mdl-body{padding:16px;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;flex:1}
.mdl-foot{padding:12px 16px calc(12px + var(--safe-b));border-top:1px solid var(--hair-2);flex:none;
  background:var(--ink-2)}

/* ---------- toasts ---------- */
.toasts{position:fixed;left:0;right:0;bottom:calc(var(--tabh) + 14px + var(--safe-b));z-index:80;display:flex;
  flex-direction:column;align-items:center;gap:8px;pointer-events:none;padding:0 16px}
/* Modal aberto: o toast sobe para o topo. Ancorado no rodapé ele pousava exatamente
   sobre o CTA do .mdl-foot (toasts z-80 fica ACIMA do #modalRoot z-70) — o aviso de
   boas-vindas cobria o botão do modal pós-cadastro. #modalRoot precede .toasts no
   index.html, então o irmão-geral (~) enxerga o estado .on. */
/* F10 (rodada 1): no topo o toast desce para DEBAIXO do header (~54px) — em
   cima dele cobria sino/plano/saldo e ficava ilegível sobre o chrome. */
#modalRoot.on ~ .toasts{bottom:auto;top:calc(62px + env(safe-area-inset-top,0px))}
/* No deck a âncora de rodapé pousava exatamente sobre a barra Passar/Tenho
   interesse — o toast confirmava a decisão COBRINDO os botões dela. Com o deck
   aberto (body[data-view], core.js go()) o aviso sobe para o topo. */
body[data-view="dossie"] .toasts{bottom:auto;top:calc(62px + env(safe-area-inset-top,0px))}
/* R3 (H13): na conversa a âncora de rodapé pousava sobre o campo "Escreva…" —
   o toast sobe para debaixo do header, como no deck. */
body[data-view="chat"] .toasts{bottom:auto;top:calc(62px + env(safe-area-inset-top,0px))}
/* O #131316 era um cinza órfão — não existia em lugar nenhum do sistema e não
   acompanhava troca de tema. --ink-3 é o mesmo degrau de superfície elevada
   usado pelos campos, e o raio passa a ser o do papel (bloco curto). */
.toast{max-width:420px;background:var(--ink-3);border:1px solid var(--hair);border-radius:var(--r-md);padding:11px 14px;
  font-size:13px;font-weight:600;animation:tin .2s cubic-bezier(.2,.9,.25,1);display:flex;align-items:flex-start;
  gap:9px}
.toast .ic{width:16px;height:16px;margin-top:1px;vertical-align:0}
.toast.ok{border-color:rgba(47,211,165,.5);color:#BFF3E5}
.toast.err{border-color:rgba(255,45,143,.55);color:#FFC2DC}
.toast.ai{border-color:rgba(155,140,255,.55);color:#DCD6FF}
@keyframes tin{from{transform:translateY(8px);opacity:0}to{transform:translateY(0);opacity:1}}

/* ---------- planos ---------- */
.plan-lock{display:flex;align-items:flex-start;gap:11px;border:1px solid rgba(245,194,75,.35);border-radius:var(--r-md);
  padding:12px 13px;font-size:12.5px;color:var(--mute)}
.plan-lock b{color:var(--white)}
.plan-card{border:1px solid var(--hair);border-radius:16px;padding:14px}
.plan-card.on{border-color:rgba(245,194,75,.55)}
.plan-card .top{display:flex;align-items:baseline;gap:8px}
.plan-card .top .nm{font-family:var(--display);text-transform:uppercase;font-size:22px;line-height:1.1;
  letter-spacing:.015em;font-weight:400}
.plan-card .top .pr{margin-left:auto;font-family:var(--mono);font-size:12.5px;color:var(--mute)}
.plan-perks{list-style:none;display:grid;gap:6px;margin:10px 0}
.plan-perks li{position:relative;padding-left:17px;font-size:12.5px;color:var(--mute)}
.plan-perks li::before{content:"→";position:absolute;left:0;color:var(--pink);font-weight:800}
.trial{border:1px dashed var(--hair);border-radius:12px;padding:11px 12px;font-size:12.5px;color:var(--mute)}
.trial b{color:var(--white)}

@media (max-width:400px){
  header .wm{display:none}
  .view-head h1{font-size:28px}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001s!important;animation-iteration-count:1!important;transition-duration:.05s!important}
  /* v22 (UX1-9): superfícies que ENTRAM não teleportam — trocam o deslize por
     um cross-fade de 160ms. Opacity-só: transform congelado. */
  .ovl,.sheet,.mdl,.toast,.dk-scrim,.dk-sheet{transition-duration:.16s!important;
    transition-property:opacity!important;transform:none!important}
  nav.tabbar .tb-ind{transition:none}
  .disc[open] > summary + *{animation:none}
  .otto-read{animation:none}
}
/* v22 (UX2-4b): GÊMEO de html.hi-con abaixo — quem pede mais contraste ao
   SISTEMA recebe o mesmo tratamento sem abrir Configurações. EDITAR JUNTO. */
/* R2 (G2g): o boot agora carimba data-tema="escuro" como padrão explícito —
   o seletor deixou de ser "sem atributo" e passou a ser "não-claro", senão
   este bloco nunca mais valeria para ninguém. */
@media (prefers-contrast:more){
  html:not([data-tema="claro"]):not([data-tema="auto"]){
    --hair:rgba(255,255,255,.32);
    --hair-2:rgba(255,255,255,.2);
    --mute:#D8D0D6;
    --mute-2:#BDB3BC;
  }
  html:not([data-tema="claro"]):not([data-tema="auto"]) .card,
  html:not([data-tema="claro"]):not([data-tema="auto"]) .cf-list,
  html:not([data-tema="claro"]):not([data-tema="auto"]) .cm-post{border-width:1.5px}
}
/* v22 (UX2-4b): sem transparência quando o sistema pede opacidade. */
@media (prefers-reduced-transparency:reduce){
  .ovl{backdrop-filter:none;background:rgba(0,0,0,.85)}
}

/* ==========================================================================
   v21 — preferências de aparência com efeito real
   O que a tela de Configurações grava em /api/me/settings vira atributo e
   classe no <html> (mod-perfil.js › aplicaAparencia). Daqui para baixo é o
   que cada opção MUDA de verdade — nenhuma delas é enfeite.
   ========================================================================== */

/* Texto maior: a base sobe e tudo que é medido em rem/em acompanha; o que é
   px fixo (números monoespaçados, selos) fica, para a grade não estourar. */
html.txt-lg body{font-size:16.5px}
html.txt-lg .hint,html.txt-lg .sub{font-size:14px}
html.txt-lg .lbl{font-size:11.5px}
/* v22 (UX2-6): quem consome os tokens de corpo (ui.css, mod-otto,
   mod-conversas) escala junto re-declarando só os tokens. */
html.txt-lg{--fs-body:16.5px;--fs-sub:14px;--fs-hint:14px;--fs-k:11.5px}
/* R2 (G9): os tamanhos PINADOS dos módulos entram na régua do texto maior —
   inclusive todo valor em R$, que estava fora dela. A migração completa por
   token fica para a v23; aqui sobem os textos informativos de 9,5–13px que a
   auditoria mediu fora da escala. */
html.txt-lg .tag{font-size:11.5px}
html.txt-lg .row .s{font-size:14px}
html.txt-lg .row .t{font-size:16px}
html.txt-lg .row .r .v{font-size:15px}
html.txt-lg .row .r .k{font-size:11px}
html.txt-lg .pay-amt{font-size:22px}
html.txt-lg .pay-line{font-size:14px}
html.txt-lg .plan-note{font-size:13.5px}
html.txt-lg .plan-perks li,html.txt-lg .plan-card .why{font-size:14px}
/* deck: rótulos e o par que decide o swipe */
html.txt-lg .dk-nm b,html.txt-lg .dk-nm i{font-size:14px}
html.txt-lg .dk-sb{font-size:14.5px}
html.txt-lg .dk-deal .w{font-size:14px}
html.txt-lg .dk-deal .v{font-size:18px}
html.txt-lg .dk-sub{font-size:13px}
html.txt-lg .dk-shead .vl b{font-size:17px}
html.txt-lg .dk-shead .vl span{font-size:11.5px}
html.txt-lg .dk-act .lb{font-size:14px}
/* mesa/mesa3/reverso/radar: linhas informativas pequenas */
html.txt-lg .m3-leg,html.txt-lg .m3-legs summary{font-size:14px}
html.txt-lg .m3-sys{font-size:13px}
html.txt-lg .m3-bub{font-size:15px}
html.txt-lg .cv-kv{font-size:14px}
html.txt-lg .cv-note{font-size:13.5px}
html.txt-lg .rd-meta{font-size:13.5px}
html.txt-lg .kpi .v.mono{font-size:24px}

/* Alto contraste: as hairlines saem da transparência e o texto secundário
   deixa de ser cinza-sobre-preto.
   v22 (UX2-4b): GÊMEO do bloco @media (prefers-contrast:more) acima — quem
   editar um, edita o outro. */
html.hi-con{
  --hair:rgba(255,255,255,.32);
  --hair-2:rgba(255,255,255,.2);
  --mute:#D8D0D6;
  --mute-2:#BDB3BC;
}
html.hi-con .card,html.hi-con .cf-list,html.hi-con .cm-post{border-width:1.5px}

/* Menos animações: o mesmo corte de prefers-reduced-motion, mas por escolha
   explícita do usuário — inclusive o carimbo do swipe e o giro do Swapou!. */
html.no-anim *{
  animation-duration:.001s!important;
  animation-iteration-count:1!important;
  transition-duration:.05s!important;
}
html.no-anim .dk-stamp .mk,html.no-anim .cv-rig,html.no-anim .cv-mc,
html.no-anim .cv-mark{transition:none!important}
/* v22 (UX1-9): espelho do cross-fade do prefers-reduced-motion — superfícies
   entram por opacidade, 160ms, transform congelado. */
html.no-anim .ovl,html.no-anim .sheet,html.no-anim .mdl,html.no-anim .toast,
html.no-anim .dk-scrim,html.no-anim .dk-sheet{transition-duration:.16s!important;
  transition-property:opacity!important;transform:none!important}
/* Mesma regra vale para o retorno ao dedo que a rodada de limpeza acrescentou:
   a lavagem de cor na borda do card e o card de trás subindo com `--f` são
   movimento, e movimento aqui está desligado por escolha do usuário. A mola do
   snap-back já cai no corte de transition acima. */
html.no-anim .dk-card[data-i="0"][data-dir]::after{display:none!important}
html.no-anim .dk-card[data-i="1"]{transform:translateY(10px) scale(.968)!important;opacity:.46!important}
/* A celebração do fechamento da permuta é movimento com propósito, mas continua
   sendo movimento: com "menos animações" a faixa aparece pronta e o anel some. */
html.no-anim .mesa-cel{animation:none!important}
html.no-anim .mesa-cel .cel-ring{display:none!important}
/* a revelação progressiva continua funcionando sem o movimento de entrada */
html.no-anim .disc[open] > summary + *{animation:none!important}
/* a leitura do Otto aparece pronta: o bloco é conteúdo, a subida é só o rastro */
html.no-anim .otto-read{animation:none!important}
/* sem movimento não há o que compositar: nenhuma camada de GPU fica reservada */
html.no-anim .cv-cel.hot .cv-rig,html.no-anim .cv-cel.hot .cv-mc,
html.no-anim .cv-cel.hot .cv-mark,html.no-anim .dk-card .dk-stamp,
html.no-anim .dk-card .dk-stamp .mk{will-change:auto!important}

/* Tema claro: o sistema é todo feito de tokens, então trocar o tema é trocar
   os tokens — nenhuma regra de componente precisa saber que existe tema. */
html[data-tema="claro"]{
  --ink:#F6F4F6; --ink-2:#FFFFFF; --ink-3:#F0EDF1; --ink-4:#E4DFE6;
  --white:#141116; --mute:#5C5360; --mute-2:#6E6474;
  --hair:rgba(20,17,22,.14); --hair-2:rgba(20,17,22,.07);
  --press:#FCE7F1; --pink-dim:rgba(255,45,143,.1);
  /* v22: chrome claro de verdade (UX2-1), violeta que passa AA sobre #F6F4F6
     (ART1-3: #5B4BC4 dá 5,7:1) e sombras de papel no lugar do highlight. */
  --chrome:#F6F4F6; --chrome-2:#F6F4F6; --glass:rgba(246,244,246,.92);
  --violet:#5B4BC4;
  --danger:#C62E38;   /* F5: vermelho AA sobre superfícies claras */
  --green:#17803D;    /* F4: verde AA sobre superfícies claras */
  /* R2 (G2b): teal e âmbar ESCUROS no claro — os originais davam 1,9:1 e
     1,65:1 sobre papel. #0B6B54 = 5,6:1 e #7A5D10 = 5,3:1 sobre --ink-3;
     todo selo/estimado/ok que fala por token herda a correção. */
  --teal:#0B6B54; --gold:#7A5D10;
  --shadow-card:0 1px 2px rgba(20,17,22,.05);
  --shadow-sheet:0 -12px 36px rgba(20,17,22,.18);
  --shadow-mdl:0 18px 48px rgba(20,17,22,.2);
}
html[data-tema="claro"] body{background:var(--ink);color:var(--white)}
html[data-tema="claro"] .cm-post,html[data-tema="claro"] .card,
html[data-tema="claro"] .cf-list,html[data-tema="claro"] .pf-head{box-shadow:var(--shadow-card)}
html[data-tema="claro"] ::selection{background:var(--pink);color:#fff}
/* R2 (G2b): o visto de verificada usa --teal de FUNDO com tinta escura — com o
   teal escurecido no claro, a tinta vira branca para o check não sumir. */
html[data-tema="claro"] .vf{color:#fff}
/* R2 (G2c): tinta dos toasts no claro — os tons pastel do escuro (#BFF3E5,
   #FFC2DC, #DCD6FF) somem sobre --ink-3 claro. Valores AA medidos. */
html[data-tema="claro"] .toast.ok{color:#0B5C41}
html[data-tema="claro"] .toast.err{color:#A3213B}
html[data-tema="claro"] .toast.ai{color:var(--violet)}
/* R2 (G2f): aviso âmbar (folha de pagamento/proposta) legível no claro. */
html[data-tema="claro"] .pay-box.warn{color:#6B5310}
html[data-tema="claro"] .pay-box.warn b{color:#6B5310}
html[data-tema="claro"] .pay-st.bad{color:#A3213B}
/* R2 (G2a): dezenas de frases do i18n carregam color:#EDEDF2 INLINE (a cor faz
   parte da chave de tradução e não pode mudar sem órfão). No claro esse quase
   branco dá 1,17:1 — o seletor de atributo devolve a tinta do tema por cima
   do estilo inline. */
html[data-tema="claro"] [style*="#EDEDF2"]{color:var(--white)!important}
@media (prefers-color-scheme:light){
  html[data-tema="auto"]{
    --ink:#F6F4F6; --ink-2:#FFFFFF; --ink-3:#F0EDF1; --ink-4:#E4DFE6;
    --white:#141116; --mute:#5C5360; --mute-2:#6E6474;
    --hair:rgba(20,17,22,.14); --hair-2:rgba(20,17,22,.07);
    --press:#FCE7F1; --pink-dim:rgba(255,45,143,.1);
    /* v22: espelho do bloco claro explícito acima — editar junto. */
    --chrome:#F6F4F6; --chrome-2:#F6F4F6; --glass:rgba(246,244,246,.92);
    --violet:#5B4BC4;
    --danger:#C62E38;   /* F5: espelho do claro explícito */
    --green:#17803D;    /* F4: espelho do claro explícito */
    --teal:#0B6B54; --gold:#7A5D10;   /* R2 (G2b): espelho do claro */
    --shadow-card:0 1px 2px rgba(20,17,22,.05);
    --shadow-sheet:0 -12px 36px rgba(20,17,22,.18);
    --shadow-mdl:0 18px 48px rgba(20,17,22,.2);
  }
  html[data-tema="auto"] body{background:var(--ink);color:var(--white)}
  /* R2 (G2a–f): espelho das correções de tinta do claro explícito. */
  html[data-tema="auto"] .vf{color:#fff}
  html[data-tema="auto"] .toast.ok{color:#0B5C41}
  html[data-tema="auto"] .toast.err{color:#A3213B}
  html[data-tema="auto"] .toast.ai{color:var(--violet)}
  html[data-tema="auto"] .pay-box.warn{color:#6B5310}
  html[data-tema="auto"] .pay-box.warn b{color:#6B5310}
  html[data-tema="auto"] .pay-st.bad{color:#A3213B}
  html[data-tema="auto"] [style*="#EDEDF2"]{color:var(--white)!important}
}

/* ------------------------------------------------- bandeiras de idioma ----
   O seletor da primeira interação (login e 1º passo do cadastro): um botão
   com a bandeira da porta atual; clicar desce o dropdown com os mercados. */
.lang-dd{position:relative;display:inline-block;margin:0 0 14px}
.ldd-btn{display:flex;align-items:center;gap:6px;padding:4px 8px;border-radius:6px;
  border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.05);
  color:var(--mute-2,#9a9aa2);cursor:pointer;line-height:0}
.ldd-btn:hover{border-color:rgba(255,255,255,.45)}
.ldd-flag svg{width:24px;height:16px;border-radius:2px;display:block}
.ldd-car{width:10px;height:6px;flex:none}
.ldd-menu{position:absolute;top:calc(100% + 6px);left:0;z-index:80;min-width:216px;
  padding:6px;border-radius:var(--r-sm);border:1px solid rgba(255,255,255,.12);
  background:var(--ink-3);box-shadow:0 14px 36px rgba(0,0,0,.55)}
.ldd-l{display:block;font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--mute-2,#9a9aa2);padding:4px 8px 6px}
.ldd-i{display:flex;align-items:center;gap:9px;width:100%;padding:7px 8px;border:0;
  border-radius:6px;background:none;color:var(--white,#fff);cursor:pointer;
  font:inherit;font-size:13.5px;text-align:left}
.ldd-i svg{width:22px;height:15px;border-radius:2px;flex:none}
.ldd-i:hover{background:rgba(255,255,255,.07)}
.ldd-i.on{background:var(--pink-dim,rgba(255,45,143,.13))}

/* ==========================================================================
   Foco visível — quem navega por teclado precisa saber ONDE está
   O app inteiro rodava sem um único :focus-visible: com o outline nativo
   apagado pelo reset, a tecla Tab movia um cursor invisível. É a mesma regra
   já em pé na landing (site/index.html), agora no app, para os dois lados da
   porta responderem igual.
   :where() zera a especificidade: qualquer componente pode redesenhar o próprio
   foco sem precisar de !important, e nada aqui vence uma regra de módulo.
   O par :focus:not(:focus-visible) existe para o anel NÃO vazar no toque — o
   dedo não precisa de mira, e sem isso todo botão tocado ficaria contornado. */
:where(button,a,summary,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--pink);outline-offset:3px;border-radius:inherit}
:focus:not(:focus-visible){outline:none}

/* ==========================================================================
   Alvo de toque de 44px sem mexer no desenho
   .btn.sm (38px), .btn.xs (32px) e o resumo do .disc (36px) são pequenos DE
   PROPÓSITO — são ações secundárias e devem parecer secundárias. O que não pode
   ser pequeno é a área que o dedo acerta. O sistema já resolve isso na .hpill
   do cabeçalho com um pseudo transparente que estica a área além da caixa; aqui
   a mesma ideia vira regra geral: a caixa continua com o tamanho desenhado, a
   MIRA cresce até 44px. Nada muda de aparência, nada muda de posição.
   inset:calc((44px - 100%) / -2) 0 — a porcentagem vertical mede a altura do
   próprio elemento, então a sobra é dividida igualmente para cima e para baixo.
   O ::before no summary (e não ::after) é obrigatório: o ::after dele já é o
   +/− da revelação progressiva. */
.btn.xs,.btn.sm,.disc > summary{position:relative}
.btn.xs::after,.btn.sm::after,.disc > summary::before{
  content:'';position:absolute;inset:calc((44px - 100%) / -2) 0}
