/* ─────────────────────────────────────────────────────────────────────────
   METRICUT — componentes da pele interna

   Uma classe por peça, lendo SÓ tokens (publico/tokens.css). ⛔ Nenhum hex aqui:
   `grep -nE "#[0-9a-fA-F]{3,8}\b" publico/componentes.css` tem de voltar vazio.
   Exemplo vivo de cada peça, nas duas peles e nos dois temas, com o nome da classe: /sistema.html

   O que carrega confiança aqui são regras, não enfeite:
   · dinheiro é sempre DM Mono, à direita, com centavos        (.tabela__num, .destaque__valor)
   · número agregado traz a RÉGUA escrita embaixo              (.destaque__regua)
   · ação destrutiva pede confirmação dizendo o que se perde   (.dialogo, via confirmar())
   · toda gravação responde na tela, toda falha diz o que fazer (.aviso, .nota, .erro-bloco)
   · lista vazia diz POR QUE está vazia                        (.vazio)

   Cor tem orçamento: a próxima ação (.btn--primario), onde eu estou
   ([aria-current], [aria-selected]) e o que exige ação (.selo--ruim, --atencao).
   ───────────────────────────────────────────────────────────────────────── */

/* ── base ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
body {
  background: var(--fundo); color: var(--texto);
  font: 400 var(--corpo)/1.5 var(--f-corpo);
  min-height: 100dvh; -webkit-font-smoothing: antialiased;
  overflow-wrap: anywhere;   /* nome de 60 letras sem espaço não pode empurrar a página */
}
button, input, select, textarea { font: inherit; color: inherit; }
/* ⚠️ `hidden` perde para qualquer `display:` de classe (.btn é inline-flex). Sem isto, o que
   o JS escondeu continua na tela e no leitor de tela. */
[hidden] { display: none !important; }
a { color: var(--acento-texto); }

/* Foco visível em TUDO que é clicável. Uma regra só, para ninguém esquecer de repetir. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--acento-texto); outline-offset: 2px;
}

.so-leitor {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ── a marca do Metricut ──────────────────────────────────────────────────
   <span class="marca [marca--solta]"><span class="marca__selo" aria-hidden="true">
     <svg viewBox="0 0 32 32"><use href="/marca.svg#tesoura"/></svg></span>
     <span class="marca__nome">Metricut</span></span>
   O DESENHO mora num lugar só, publico/marca.svg (a tesoura de lâminas em M), e ele não escreve cor:
   cada lâmina pinta com uma variável (--marca-l1, --marca-l2) que cai em currentColor. Aqui fica a roupa.
   · O SELO (padrão): quadrado BRANCO com as duas lâminas nas cores do poste de barbeiro — a 1ª vermelha,
     a 2ª azul, a azul por cima no pino. O fio de contorno por dentro é o limite do selo: branco sobre o
     papel branco não teria borda nenhuma.
     ⚠️ O selo é branco em TODO tema e sobre QUALQUER fundo: é um selo, não uma superfície. E não leva
     --acento: o azul dele é o do poste, escrito em tokens.css — não acompanha a cor de casa nenhuma.
   · .marca--solta: a versão de UMA cor — sem selo, as duas lâminas na cor do texto em volta. Para fundo
     que já é cor (o acento, uma foto) e para impressão em uma tinta. ⚠️ As duas variáveis são REDEFINIDAS
     para currentColor, não apenas "não definidas": variável herda, e sem isto a regra do selo (que casa
     no mesmo elemento) continuaria pintando de vermelho e azul.
   ⛔ As cores do poste (--poste-*) só existem aqui e na fita (.pub-fita); o auditor conta os usos.
   ⛔ Não trocar as cores das lâminas entre si, não colorir o selo, não pintar a tesoura com --ruim.
   O nome é a única Archivo Black da pele interna. O tamanho inteiro sai de --marca-t (o lado do selo):
   26 no menu, 30 no site. Mínimo: 16 px de selo (conferido com as duas cores); abaixo de 20 o nome não
   acompanha (use só o selo).
   ⛔ Só nas telas do Metricut. A página do cliente leva a marca da BARBEARIA (.pub-casa__marca). */
.marca { --marca-t: 26px; display: inline-flex; align-items: center; gap: calc(var(--marca-t) * .38); color: var(--texto); text-decoration: none; }
.marca__selo {
  display: grid; place-items: center; width: var(--marca-t); height: var(--marca-t); flex: none;
  border-radius: calc(var(--marca-t) * .27); background: var(--poste-branco); box-shadow: inset 0 0 0 1px var(--borda);
  --marca-l1: var(--poste-vermelho); --marca-l2: var(--poste-azul);
}
.marca__selo > svg { display: block; width: 100%; height: 100%; }
.marca__nome { font: calc(var(--marca-t) * .62)/1 var(--f-marca); text-transform: uppercase; letter-spacing: -.02em; }
.marca--solta .marca__selo {
  background: none; box-shadow: none; border-radius: 0; color: inherit;
  --marca-l1: currentColor; --marca-l2: currentColor;
}

/* ── botão ────────────────────────────────────────────────────────────────
   Um primário por tela: se dois são coloridos, nenhum é a próxima ação.
   A altura vem de --h-controle (36 no ponteiro, 44 no dedo — tokens.css). */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e-2);
  min-height: var(--h-controle); padding: 0 14px; flex: none;
  border: 1px solid transparent; border-radius: var(--r-campo);
  background: none; color: var(--texto);
  font-size: var(--corpo); font-weight: 600; line-height: 1.2; white-space: nowrap;
  text-decoration: none; cursor: pointer;
  transition: background var(--t), border-color var(--t), color var(--t);
}
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

/* ⚠️ a tinta por cima do acento é CALCULADA (--acento-tinta), nunca --fundo:
   com acento claro o texto do botão sumia. */
.btn--primario { background: var(--acento); color: var(--acento-tinta); font-weight: 700; }
.btn--primario:hover:not(:disabled) { filter: brightness(1.08); }

.btn--secundario { background: var(--sup); border-color: var(--borda-controle); }
.btn--secundario:hover:not(:disabled) { background: var(--sup-2); }

.btn--perigo { background: var(--sup); border-color: var(--borda-controle); color: var(--ruim); }
.btn--perigo:hover:not(:disabled) {
  /* 7%, não 9%: a 9% o texto --ruim caía para 4,49:1 sobre o cartão cinza da pele pública
     (medido por design/conferir.mjs). A primeira declaração é a reserva de quem não tem
     color-mix (Safari < 16.2), que sem ela ficava sem fundo nenhum no hover. */
  border-color: var(--ruim); background: var(--sup-2); background: color-mix(in srgb, var(--ruim) 7%, var(--sup));
}

.btn--fantasma { color: var(--texto-2); }
.btn--fantasma:hover:not(:disabled) { background: var(--sup-2); color: var(--texto); }

.btn--bloco { display: flex; width: 100%; }
/* só ícone (ex.: ‹ › da troca de dia): quadrado, e o nome vai em aria-label */
.btn--icone { width: var(--h-controle); padding: 0; font-family: var(--f-dado); font-size: 16px; }

/* ── campo: rótulo + controle + erro ──────────────────────────────────────
   <div class="campo"><label for="x">Nome</label><input id="x">
     <p class="campo__ajuda">…</p><p class="campo__erro">…</p></div>
   Com erro: acrescente .campo--erro e aria-invalid="true" no controle.
   ⚠️ A validação da TELA aceita exatamente o que o servidor aceita. Mais restrita
   que o banco cria registro que existe e não pode ser salvo (o "quinto buraco"). */
.campo { display: flex; flex-direction: column; gap: 6px; margin-bottom: 13px; min-width: 0; }
.campo > label, .campo__rotulo {
  font-size: var(--t-coluna); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texto-3);
}
.campo > input:not([type="checkbox"], [type="radio"]),
.campo > select, .campo > textarea, .entrada, .seletor {
  width: 100%; min-width: 0; height: var(--h-controle); padding: 0 11px;
  background: var(--sup); color: var(--texto);
  border: 1px solid var(--borda-controle); border-radius: var(--r-campo);
  font: 400 var(--campo)/1.2 var(--f-corpo);
}
.campo > textarea { height: auto; min-height: 84px; padding: 9px 11px; line-height: 1.45; resize: vertical; }
.campo > input::placeholder, .campo > textarea::placeholder, .entrada::placeholder { color: var(--texto-3); }
/* ⚠️ RESERVA para quem não conhece :focus-visible (Safari < 15.4, iPhone parado no iOS 15):
   lá um seletor desconhecido derruba a REGRA INTEIRA — a de baixo e a geral do topo —, e o
   campo em uso ficava sem o anel do produto. Esta regra usa só :focus, que todos entendem.
   Campo de digitar sempre mostra foco, então nos navegadores atuais ela diz o mesmo que a de
   baixo; o <select> fica fora de propósito (nele :focus vale também para o clique do mouse). */
.campo > input:not([type="checkbox"], [type="radio"]):focus, .campo > textarea:focus, .entrada:focus {
  outline: 2px solid var(--acento-texto); outline-offset: -1px; border-color: var(--acento);
}
.campo > input:focus-visible, .campo > select:focus-visible,
.campo > textarea:focus-visible, .entrada:focus-visible, .seletor:focus-visible {
  outline-offset: -1px; border-color: var(--acento);
}
.campo__ajuda { font-size: var(--apoio); color: var(--texto-3); line-height: 1.45; }
.campo__erro { font-size: var(--apoio); font-weight: 600; color: var(--ruim); line-height: 1.45; }
.campo__erro:empty { display: none; }
/* dinheiro digitado: o que a tela ENTENDEU fica escrito embaixo do campo, antes de enviar ("= R$ 1.250,50").
   <p class="campo__lido" aria-live="polite"></p> — enquanto o texto ainda não é um valor, .campo__lido--espera
   diz isso sem gritar. Vazio não ocupa lugar (nem a ajuda vazia): um parágrafo sem texto abria um vão no formulário. */
.campo__lido { font-family: var(--f-dado); font-variant-numeric: tabular-nums; font-size: var(--t-dado); color: var(--texto); }
.campo__lido--espera { font-family: var(--f-corpo); color: var(--texto-3); }
.campo__lido:empty, .campo__ajuda:empty { display: none; }
/* um botão que age SOBRE o campo ("Mostrar a senha"), logo abaixo dele: fica do tamanho do texto, não da coluna
   <button type="button" class="btn btn--fantasma campo__acao" aria-controls="id-do-campo" aria-pressed="false">… */
.campo__acao { align-self: flex-start; }
/* ⚠️ Esta regra tem de VENCER duas outras, e por isso os seletores são pesados de propósito:
   · a do controle (.campo > input:not(…)): sem o :not(…) aqui a borda vermelha não pintava em
     <input> e o erro ficava só no texto de baixo;
   · as de foco logo acima (a mais pesada é .campo > input:not(…):focus): a classe aparece
     DOBRADA (.campo--erro.campo--erro) para que ela sozinha, sem aria-invalid, continue vermelha
     com o campo em foco — em <input>, <select> e <textarea>.
   Vale nas duas peles. O anel de foco (outline) continua aparecendo por fora da borda. */
.campo--erro.campo--erro > input:not([type="checkbox"], [type="radio"]),
.campo > input[aria-invalid="true"]:not([type="checkbox"], [type="radio"]),
.campo > select[aria-invalid="true"], .campo > textarea[aria-invalid="true"],
.campo--erro.campo--erro > select, .campo--erro.campo--erro > textarea,
.campo [aria-invalid="true"] { border-color: var(--ruim); }

/* dois campos lado a lado; em tela estreita cada um ganha a própria linha */
.campo-par { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 0 11px; }

/* ── seletor ──────────────────────────────────────────────────────────────
   <select class="seletor">. Dentro de .campo o <select> já sai assim.
   A seta é desenhada com gradiente para ler a cor do tema (um SVG embutido
   levaria um hex fixo, que não troca no escuro). */
.campo > select, .seletor {
  appearance: none; padding-right: 30px; cursor: pointer; text-overflow: ellipsis;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--texto-2) 50%),
    linear-gradient(135deg, var(--texto-2) 50%, transparent 50%);
  background-position: right 15px center, right 10px center;
  background-size: 5px 5px; background-repeat: no-repeat;
}
.seletor--justo { width: auto; max-width: 100%; }

/* caixa de marcar em linha inteira — o alvo é a linha, não o quadradinho de 16px */
.marcavel {
  display: flex; align-items: center; gap: 10px;
  min-height: var(--h-controle); padding: 0 11px;
  border: 1px solid var(--borda); border-radius: var(--r-campo);
  font-size: var(--corpo); font-weight: 600; cursor: pointer;
}
.marcavel:hover { border-color: var(--borda-controle); }
.marcavel > input { width: 16px; height: 16px; flex: none; accent-color: var(--acento); }
.marcavel:has(input:focus-visible) { outline: 2px solid var(--acento-texto); outline-offset: 2px; }
.marcaveis { display: flex; flex-direction: column; gap: 6px; }
/* várias opções curtas (os dias da semana): em grade, duas ou mais por linha, em vez de sete linhas inteiras */
.marcaveis--grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); }

/* rodapé de formulário: cancelar à esquerda do que grava, o que grava por último */
.acoes {
  display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--e-2);
  margin-top: var(--e-4); padding-top: 14px; border-top: 1px solid var(--borda);
}

/* a ação que DESTRÓI (Apagar, Remover) fica sozinha à esquerda, longe do que grava */
.acoes__esq { margin-right: auto; }
/* título de um formulário dentro do cartão ("Editar unidade", "Vender plano") */
.secao-titulo { font-size: var(--t-secao); font-weight: 700; line-height: 1.3; margin-bottom: 11px; }

/* ── cartão: o papel sobre a mesa ─────────────────────────────────────────
   A sombra é a menor das três (--sombra-1): não é enfeite, é o que diz que o papel está POUSADO
   na mesa e não impresso nela. O que flutua de verdade (gaveta, diálogo, aviso) usa --sup-alta e --sombra. */
.cartao {
  background: var(--sup); border: 1px solid var(--borda);
  border-radius: var(--r-cartao); min-width: 0; overflow: hidden; box-shadow: var(--sombra-1);
}
.cartao__cab {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  min-height: 46px; padding: 5px var(--pad-cartao); border-bottom: 1px solid var(--borda);
}
.cartao__titulo { flex: 1; min-width: 0; font-size: var(--t-secao); font-weight: 700; letter-spacing: -.005em; line-height: 1.3; }
.cartao__corpo { padding: var(--pad-cartao); }

/* ── linha de lista (dentro de .cartao) ───────────────────────────────────
   <button class="linha" aria-current="true"> quando seleciona; <div class="linha">
   quando só mostra. Os dados da direita são .dado (DM Mono). */
.linha {
  display: flex; align-items: center; gap: 4px 12px; flex-wrap: wrap;
  width: 100%; min-height: var(--h-linha); padding: 6px var(--pad-cartao);
  background: none; border: 0; border-bottom: 1px solid var(--borda);
  text-align: left; font-size: var(--corpo);
}
.linha:last-child { border-bottom: 0; }
button.linha { cursor: pointer; }
/* ⚠️ :not([aria-current]) — sem ele o hover vencia a seleção e a linha aberta perdia o fundo
   justamente com o mouse em cima dela */
button.linha:not([aria-current="true"]):hover { background: var(--sup-2); }
button.linha:focus-visible { outline-offset: -2px; }
.linha[aria-current="true"] { background: var(--acento-sel); }
.linha[aria-current="true"] .linha__nome { color: var(--acento-texto); font-weight: 700; }
.linha__nome { flex: 1 1 120px; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.linha__apoio { font-weight: 400; color: var(--texto-3); }
.linha .dado { flex: none; font-size: var(--t-dado); color: var(--texto-2); }
/* fora do ar / inativo: recua para o cinza de apoio — por COR, nunca por opacidade (a .55 o
   dado caía para ~2,6:1). O selo ao lado é que explica o motivo, e ele não recua. */
.linha--apagada .linha__nome { color: var(--texto-2); font-weight: 500; }
.linha--apagada .dado { color: var(--texto-3); }

/* ── tabela ───────────────────────────────────────────────────────────────
   <div class="tabela-rolagem"><table class="tabela">…</table></div>
   .tabela__num  → dinheiro e contagem: DM Mono, tabular, à DIREITA (no th e no td)
   .tabela--empilha + data-rotulo="…" em cada <td> → abaixo de 640px cada linha vira
   um cartão, em vez de a tabela rolar de lado. */
.tabela-rolagem { overflow-x: auto; }
.tabela { width: 100%; border-collapse: collapse; font-size: var(--corpo); }
.tabela th {
  height: 32px; padding: 0 var(--pad-cartao); background: var(--sup-2);
  border-bottom: 1px solid var(--borda); text-align: left; white-space: nowrap;
  font-size: var(--t-coluna); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texto-3);
}
.tabela td {
  height: var(--h-linha); padding: 6px var(--pad-cartao);
  border-bottom: 1px solid var(--borda); vertical-align: middle;
}
.tabela tbody tr:last-child td { border-bottom: 0; }
.tabela tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--sup-2) 45%, transparent); }
.tabela th.tabela__num, .tabela td.tabela__num {
  text-align: right; white-space: nowrap;
  font-family: var(--f-dado); font-variant-numeric: tabular-nums;
}
.tabela td.tabela__num { font-size: var(--t-dado); }
.tabela__apoio { display: block; font-size: var(--apoio); color: var(--texto-3); }
/* linha que abre alguma coisa: <tr tabindex="0" data-abre> */
.tabela tr[data-abre] { cursor: pointer; }
.tabela tr[data-abre]:hover td { background: var(--sup-2); }
.tabela tr[data-abre]:focus-visible { outline-offset: -2px; }
.tabela tfoot td { border-top: 1px solid var(--borda-controle); border-bottom: 0; font-weight: 700; }
/* DM Mono só vem em 400 e 500: pedir 700 faria o navegador engrossar a letra na marra */
.tabela tfoot td.tabela__num { font-weight: 500; }

@media (max-width: 640px) {
  .tabela--empilha thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .tabela--empilha, .tabela--empilha tbody, .tabela--empilha tfoot, .tabela--empilha tr, .tabela--empilha td { display: block; }
  .tabela--empilha tr { padding: 10px var(--pad-cartao); border-bottom: 1px solid var(--borda); }
  .tabela--empilha tbody tr:last-child { border-bottom: 0; }
  .tabela--empilha tfoot tr { border-bottom: 0; border-top: 1px solid var(--borda-controle); }
  .tabela--empilha td:empty { display: none; }
  .tabela--empilha td, .tabela--empilha tfoot td, .tabela--empilha tbody tr:nth-child(even) td {
    display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
    height: auto; padding: 3px 0; border: 0; background: none; text-align: right;
  }
  .tabela--empilha td::before {
    content: attr(data-rotulo); flex: none; text-align: left;
    font: 700 var(--t-coluna)/1.6 var(--f-corpo); letter-spacing: .14em;
    text-transform: uppercase; color: var(--texto-3);
  }
  /* a primeira célula é o "título" do cartão: sem rótulo, à esquerda, com peso */
  .tabela--empilha td:first-child, .tabela--empilha tbody tr:nth-child(even) td:first-child { display: block; text-align: left; font-weight: 700; padding-bottom: 5px; }
  .tabela--empilha td:first-child .tabela__apoio { font-weight: 400; }
  .tabela--empilha td:first-child::before { content: none; }
}

/* ── número-destaque: rótulo + valor + RÉGUA ──────────────────────────────
   <div class="grade"><div class="destaque">
     <div class="destaque__rotulo">No caixa</div>
     <div class="destaque__valor">R$ 1.234,50</div>
     <div class="destaque__regua">só o que já foi atendido</div>
     <div class="destaque__variacao destaque__variacao--sobe">12% sobre ontem</div>
   </div></div>
   ⚠️ A régua não é opcional em número agregado: é ela que diz o que entrou na conta.
   ⚠️ O valor ENCOLHE com a caixa (container query) em vez de estourar — foi assim que
   "R$ 585,00" vazou do cartão do caixa num celular de 320px. */
/* 148px: num celular de 360 cabem DOIS por linha (328 úteis). Com 160 cada número ocupava a
   largura toda e a agenda só aparecia depois de rolar três cartões. */
.grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 14px; container: grade / inline-size; }
/* Em DUAS colunas (310 a 472px de grade: 2×148+14 até 3×148+28), o último ímpar ocupa a
   linha inteira em vez de deixar um buraco ao lado. É container query e não media query
   porque quem decide o número de colunas é a largura da GRADE, não a da tela. */
@container grade (min-width: 310px) and (max-width: 471.98px) {
  .grade > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}
.destaque {
  container-type: inline-size; min-width: 0;
  background: var(--sup); border: 1px solid var(--borda);
  border-radius: var(--r-cartao); padding: 14px var(--pad-cartao); box-shadow: var(--sombra-1);
}
.destaque__rotulo {
  font-size: var(--t-coluna); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texto-3);
}
.destaque__valor {
  margin-top: var(--e-2); white-space: nowrap; line-height: 1.15;
  font-family: var(--f-dado); font-weight: 500; font-variant-numeric: tabular-nums;
  font-size: var(--t-numero); font-size: clamp(16px, 12.5cqi, var(--t-numero));
  letter-spacing: -.02em;
}
.destaque__regua { margin-top: var(--e-1); font-size: var(--apoio); color: var(--texto-3); line-height: 1.4; }
.destaque__variacao { margin-top: 6px; font-size: var(--apoio); font-weight: 700; }
/* a seta diz a direção sem depender da cor (quem não distingue verde de vermelho lê igual) */
.destaque__variacao--sobe { color: var(--bom); }
.destaque__variacao--sobe::before { content: "▲ "; font-size: .8em; }
.destaque__variacao--desce { color: var(--ruim); }
.destaque__variacao--desce::before { content: "▼ "; font-size: .8em; }
/* o próprio número carrega estado só quando ele É o estado (atendidos, faltaram) */
.destaque--bom .destaque__valor { color: var(--bom); }
.destaque--ruim .destaque__valor { color: var(--ruim); }

/* ── selo de estado ───────────────────────────────────────────────────────
   Quadradinho + palavra. A cor é do TEXTO e do quadradinho; o fundo fica quieto —
   quarenta selos de fundo colorido numa lista viram confete.
   --bom atendido/pago · --atencao precisa de olho · --ruim faltou/recusado
   --neutro só informa · --acento "é daqui" (assinante, a tela aberta) */
.selo {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  padding: 2px 8px; border: 1px solid var(--borda); border-radius: var(--r-selo);
  font-size: var(--t-selo); font-weight: 700; letter-spacing: .04em; line-height: 1.5;
  text-transform: uppercase; white-space: nowrap; color: var(--texto-2);
}
.selo::before { content: ""; width: 7px; height: 7px; border-radius: 2px; background: currentColor; flex: none; }
.selo--bom { color: var(--bom); }
/* a primeira border-color é a reserva de quem não tem color-mix (Safari < 16.2): sem ela a
   declaração inteira cai e o selo de atenção fica com a borda de um selo qualquer */
.selo--atencao { color: var(--atencao); border-color: var(--atencao); border-color: color-mix(in srgb, var(--atencao) 55%, var(--borda)); }
.selo--ruim { color: var(--ruim); border-color: var(--ruim); border-color: color-mix(in srgb, var(--ruim) 55%, var(--borda)); }
.selo--neutro { color: var(--texto-2); }
.selo--acento { color: var(--acento-texto); background: var(--acento-sel); border-color: transparent; }
.selo--acento::before { content: none; }

/* ── abas ─────────────────────────────────────────────────────────────────
   Duas formas, a mesma cara — o que muda é o que a aba FAZ:
   · troca um painel na mesma tela (filtro):
       <div class="abas" role="tablist"><button class="aba" role="tab" aria-selected="true">…
   · leva a outro endereço (seção, #): são LINKS, sem role de tab —
       <nav class="abas" aria-label="…"><a class="aba" href="#x" aria-current="page">…
   Em tela estreita a fileira QUEBRA de linha. Ela já rolou de lado, e a quarta aba ficava
   cortada sem nenhum indício de que existia: o que não se vê não se clica. */
.abas { display: flex; flex-wrap: wrap; gap: 6px; }
.aba {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--h-controle); padding: 0 13px;
  background: none; border: 1px solid var(--borda); border-radius: var(--r-pilula);
  color: var(--texto-2); font-size: var(--corpo); font-weight: 600; white-space: nowrap;
  text-decoration: none; cursor: pointer;
  transition: background var(--t), border-color var(--t), color var(--t);
}
.aba:hover { border-color: var(--borda-controle); color: var(--texto); }
/* aria-pressed: a aba que é um BOTÃO de escolher um entre vários (a hora sugerida no "Marcar horário") */
.aba[aria-selected="true"], .aba[aria-current="page"], .aba[aria-pressed="true"] { background: var(--acento-sel); border-color: transparent; color: var(--acento-texto); font-weight: 700; }

/* ── os três estados que toda lista tem ───────────────────────────────── */
/* vazio: diz POR QUE está vazio e, se houver, o que fazer */
.vazio { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 30px var(--pad-cartao); text-align: center; }
.vazio__titulo { font-size: var(--t-secao); font-weight: 700; }
.vazio__texto { max-width: 46ch; color: var(--texto-2); line-height: 1.55; }
.vazio .btn { margin-top: 10px; }

/* passos: o que fazer, NA ORDEM — cada um diz se já está feito e leva ao lugar de fazer.
   <ol class="passos"><li class="passos__item passos__item--feito|--agora">
     <span class="passos__marca">1</span><span class="passos__texto"><b>Passo</b><span>por quê</span></span>
     <a class="btn btn--primario">Fazer agora</a></li></ol>
   Só o passo "--agora" (o primeiro que falta) leva o acento: é a próxima ação. */
.passos { list-style: none; display: flex; flex-direction: column; margin-top: 10px; border: 1px solid var(--borda); border-radius: var(--r-campo); text-align: left; }
.passos__item { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; min-height: var(--h-linha); padding: 9px 12px; border-bottom: 1px solid var(--borda); }
.passos__item:last-child { border-bottom: 0; }
.passos__marca {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none; border-radius: 50%;
  border: 1px solid var(--borda-controle); font: 12px/1 var(--f-dado); color: var(--texto-2);
}
.passos__texto { flex: 1 1 200px; min-width: 0; line-height: 1.4; }
.passos__texto > b { display: block; }
.passos__texto > span { font-size: var(--apoio); color: var(--texto-2); }
.passos__item--feito .passos__marca { border-color: var(--bom); color: var(--bom); }
.passos__item--feito .passos__texto > b { font-weight: 600; color: var(--texto-2); }
.passos__item--agora .passos__marca { border-color: transparent; background: var(--acento); color: var(--acento-tinta); }
.vazio .passos .btn { margin-top: 0; }

/* carregando: o esqueleto tem a altura da linha, então nada pula quando o dado chega */
.esqueleto { display: flex; flex-direction: column; }
.esqueleto__linha { display: flex; align-items: center; min-height: var(--h-linha); padding: 0 var(--pad-cartao); border-bottom: 1px solid var(--borda); }
.esqueleto__linha:last-child { border-bottom: 0; }
.esqueleto__linha::before {
  content: ""; height: 10px; width: var(--larg, 60%); border-radius: var(--r-pilula);
  background: linear-gradient(90deg, var(--sup-2) 25%, var(--borda) 50%, var(--sup-2) 75%);
  background-size: 200% 100%; animation: esqueleto 1.3s linear infinite;
}
@keyframes esqueleto { from { background-position: 200% 0; } to { background-position: 0 0; } }

/* erro: o que houve + o botão que resolve. Nunca só "erro". */
.erro-bloco {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 28px var(--pad-cartao); text-align: center;
}
.erro-bloco__texto { max-width: 46ch; color: var(--texto); line-height: 1.55; }
.erro-bloco__texto::before {
  content: ""; display: block; width: 8px; height: 8px; margin: 0 auto 10px;
  border-radius: 50%; background: var(--ruim);
}

/* ── nota: explicação que fica na tela ────────────────────────────────────
   <div class="nota"><b>Regra.</b> Por quê.</div>  — a barra da esquerda é o estado.
   --ruim é onde mora a falha de gravação: ela NÃO some sozinha como o toast. */
.nota {
  padding: 11px 12px 11px 14px; border: 1px solid var(--borda); border-left: 3px solid var(--borda-controle);
  border-radius: var(--r-campo); background: var(--fundo);
  font-size: var(--apoio); color: var(--texto-2); line-height: 1.55;
}
.nota b { color: var(--texto); }
.nota--bom { border-left-color: var(--bom); }
.nota--atencao { border-left-color: var(--atencao); }
.nota--ruim { border-left-color: var(--ruim); color: var(--texto); font-size: var(--corpo); }
.nota + .nota, .nota + form, form + .nota { margin-top: 13px; }

/* ── aviso (toast) ────────────────────────────────────────────────────────
   Não se escreve na mão: aviso("Salvo") de central.js. Sobe do rodapé, some sozinho. */
.avisos {
  position: fixed; z-index: 60; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--e-4) + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; align-items: center; gap: var(--e-2);
  width: min(420px, calc(100vw - 2 * var(--e-4))); pointer-events: none;
}
.aviso {
  pointer-events: auto; display: flex; align-items: flex-start; gap: 10px;
  max-width: 100%; padding: 11px 14px; cursor: pointer; text-align: left;
  background: var(--sup-alta); color: var(--texto);
  border: 1px solid var(--borda-controle); border-radius: var(--r-cartao);
  box-shadow: var(--sombra); font-size: var(--corpo); font-weight: 600; line-height: 1.45;
  animation: aviso-entra var(--t);
}
.aviso::before { content: ""; flex: none; width: 8px; height: 8px; margin-top: .45em; border-radius: 50%; background: var(--texto-2); }
.aviso--bom::before { background: var(--bom); }
.aviso--atencao::before { background: var(--atencao); }
.aviso--ruim::before { background: var(--ruim); }
@keyframes aviso-entra { from { opacity: 0; transform: translateY(8px); } }

/* ── diálogo de confirmação ───────────────────────────────────────────────
   Não se escreve na mão: await confirmar({ titulo, texto, rotulo }) de central.js.
   É <dialog> nativo: o foco fica preso e o Esc fecha sem uma linha de código nossa. */
.dialogo {
  margin: auto; width: min(420px, calc(100vw - 2 * var(--e-4))); padding: 0;
  background: var(--sup-alta); color: var(--texto);
  border: 1px solid var(--borda); border-radius: var(--r-cartao); box-shadow: var(--sombra);
}
.dialogo::backdrop { background: color-mix(in srgb, var(--texto) 45%, transparent); }
:root[data-tema="escuro"] .dialogo::backdrop { background: color-mix(in srgb, var(--fundo) 70%, transparent); }
/* o respiro fica na CAIXA, não no <dialog>: clique no respiro não pode contar como clique no véu */
.dialogo__caixa { padding: 20px; }
.dialogo__titulo { font-size: var(--t-secao); font-weight: 700; line-height: 1.3; }
.dialogo__texto { margin-top: var(--e-2); color: var(--texto-2); line-height: 1.55; }
.dialogo .acoes { border-top: 0; padding-top: 0; margin-top: 20px; }
/* diálogo que pergunta com campos (entrar de novo, trocar a senha): os campos entre o texto e os botões */
.dialogo__campos { margin-top: 14px; }
.dialogo__campos .campo:last-child { margin-bottom: 0; }
.dialogo__campos .nota { margin-bottom: 13px; }

/* ── gaveta: a ficha que abre por cima da lista ───────────────────────────
   <dialog class="ficha" aria-labelledby="…"><div class="ficha__caixa">
     <header class="ficha__cab"><div class="ficha__cab-quem">
         <span class="ficha__disco">MA</span>
         <div class="ficha__quem"><h2 class="ficha__nome">…</h2><div class="ficha__fone dado">…</div></div></div>
       <button class="ficha__fechar" aria-label="Fechar">×</button></header>
     <div class="ficha__corpo">…</div></div></dialog>
   À direita no desktop, tela cheia no celular. É <dialog> nativo aberto com showModal(): o
   foco fica preso, o Esc fecha e a página por baixo fica inerte, sem código nosso. O VOLTAR
   do navegador também fecha — quem cuida disso é a tela (clientes.js, whatsapp.js). */
.ficha {
  margin: 0 0 0 auto; padding: 0; border: 0; border-left: 1px solid var(--borda);
  width: min(420px, 100vw); max-width: 100vw; height: 100dvh; max-height: 100dvh;
  background: var(--sup-alta); color: var(--texto); box-shadow: var(--sombra); overflow: hidden;
}
.ficha[open] { animation: ficha-entra var(--t); }
@keyframes ficha-entra { from { transform: translateX(28px); opacity: 0; } }
.ficha::backdrop { background: color-mix(in srgb, var(--texto) 45%, transparent); }
:root[data-tema="escuro"] .ficha::backdrop { background: color-mix(in srgb, var(--fundo) 70%, transparent); }
/* o conteúdo ocupa a caixa inteira: clique que acerta o <dialog> em si só pode ser no véu */
.ficha__caixa { display: flex; flex-direction: column; height: 100%; }
.ficha__cab {
  flex: none; display: flex; align-items: center; gap: 11px;
  padding: 12px 8px 12px var(--pad-cartao); border-bottom: 1px solid var(--borda);
}
.ficha__cab-quem { flex: 1; min-width: 0; display: flex; align-items: center; gap: 11px; }
.ficha__disco {
  display: grid; place-items: center; width: 40px; height: 40px; flex: none; border-radius: 50%;
  background: var(--sup-2); border: 1px solid var(--borda);
  font: 13px/1 var(--f-dado); color: var(--texto-2);
}
.ficha__quem { flex: 1; min-width: 0; }
.ficha__nome { font-size: var(--t-secao); font-weight: 700; line-height: 1.3; }
.ficha__fone { font-size: var(--apoio); color: var(--texto-3); }
.ficha__fechar {
  display: grid; place-items: center; width: 44px; height: 44px; flex: none;
  background: none; border: 0; border-radius: var(--r-campo); color: var(--texto); cursor: pointer;
}
.ficha__fechar:hover { background: var(--sup-2); }
.ficha__corpo { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-bottom: env(safe-area-inset-bottom); }
.ficha__bloco { padding: 14px var(--pad-cartao); border-bottom: 1px solid var(--borda); }
.ficha__bloco:last-child { border-bottom: 0; }
@media (max-width: 640px) { .ficha { width: 100vw; border-left: 0; } }

/* ── movimento: quem pediu menos, recebe nenhum ───────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ── dedo ─────────────────────────────────────────────────────────────────
   --h-controle e --h-linha já viram 44/48 em tokens.css. Aqui entra só o que
   não é medido por eles. */
@media (pointer: coarse), (max-width: 899.98px) {
  .btn--icone { width: 44px; }
  .selo { padding-block: 3px; }
  .marcavel > input { width: 20px; height: 20px; }
}

/* ═════════════════════════════════════════════════════════════════════════
   PEÇAS COMPOSTAS — as que carregam a cara do produto

   Nasceram dentro das telas (num <style> de cada página) e vieram para cá porque são usadas por mais de uma
   tela ou porque são a identidade da gestão: quem abre /sistema.html precisa VER a linha da agenda, e não só o
   botão e o selo de que ela é feita. Cada uma tem exemplo vivo lá, com dado de mentira.
   ⚠️ Ficam DEPOIS das peças simples de propósito: várias ajustam .btn e .selo (mesma especificidade — vence a
   ordem). O que é só de UMA tela (o placar de comissão, o QR, o resultado do mês) continua na tela.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── linha da agenda (.ag) — Hoje ─────────────────────────────────────────
   <article class="ag ag--marcado|confirmado|atendido|faltou|cancelado [ag--fechado]">
     <div class="ag__hora dado">09:30<span class="ag__dur">45 min</span></div>
     <div class="ag__corpo"><p class="ag__cliente">…</p><p class="ag__servico">…</p><p class="ag__plano">…</p></div>
     <div class="ag__lado"><span class="selo">…</span><span class="ag__valor dado">R$ 50,00</span></div>
     <div class="ag__acoes">…botões…</div></article> */
/* A barra da esquerda é o que se lê de relance; o que já se resolveu esmaece, e o que
   sobra em pé é o que ainda pede ação. */
.ag {
  display: grid; grid-template-columns: 54px minmax(0, 1fr) auto; gap: 4px 14px; align-items: start;
  padding: 12px var(--pad-cartao) 12px calc(var(--pad-cartao) - 3px);
  border-left: 3px solid var(--borda-controle); border-bottom: 1px solid var(--borda);
}
.ag:last-child { border-bottom: 0; }
.ag--confirmado { border-left-color: var(--acento); }
.ag--atendido { border-left-color: var(--bom); }
.ag--faltou, .ag--cancelado { border-left-color: var(--ruim); }
.ag__hora { font-size: 15px; line-height: 1.35; }
.ag__dur { display: block; font-size: 11px; color: var(--texto-3); }
.ag__cliente { font-size: 14.5px; font-weight: 700; line-height: 1.35; }
.ag__cliente .selo { margin-left: 4px; vertical-align: 1px; }
.ag__servico { color: var(--texto-2); }
.ag__plano { margin-top: 3px; font-size: var(--apoio); color: var(--texto-2); }
.ag__plano b { color: var(--texto); }
.ag__plano--sem { color: var(--atencao); font-weight: 600; }
.ag__lado { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
/* o dinheiro do atendido por extenso: o que foi ao caixa, a comissão, quem definiu a forma;
   e o rastro (só para quem gerencia): quem marcou pelo painel, quem registrou o status, quando */
.ag__dinheiro, .ag__rastro { margin-top: 3px; font-size: var(--apoio); color: var(--texto-2); line-height: 1.5; }
.ag__dinheiro b, .ag__rastro b { color: var(--texto); font-weight: 600; }
/* o selo da forma é um BOTÃO quando dá para corrigir: a seta diz isso, e o alvo de toque é
   maior que o desenho (o ::after estica a área sem mexer na linha) */
.ag__forma-selo { position: relative; background: none; font-family: inherit; cursor: pointer; }
.ag__forma-selo::after { content: ""; position: absolute; inset: -11px -6px; }
.ag__forma-selo:hover { border-color: var(--borda-controle); color: var(--texto); }
.ag__forma-selo.selo--atencao:hover { border-color: var(--atencao); color: var(--atencao); }
.ag__forma-selo > span { font-size: 1.25em; line-height: 1; margin-left: -2px; }
/* ⚠️ no dedo o selo-botão tem 44px DE VERDADE. A área invisível acima (::after) dava o alvo
   só a quem acertasse o entorno, e a régua de toque do projeto mede a caixa do controle.
   No ponteiro de desktop nada muda: continua um selo de 24px. */
@media (pointer: coarse), (max-width: 899.98px) {
  .ag__forma-selo { min-height: 44px; padding-inline: 12px; }
  .ag__forma-selo::after { inset: 0; }
}
/* a escolha da forma: botões de 44px em qualquer tela — é tocada com o cliente na frente */
.ag__forma { grid-column: 2 / -1; margin-top: 8px; padding: 12px; border: 1px solid var(--borda-controle); border-radius: var(--r-campo); background: var(--fundo); }
.ag__forma-pergunta { font-weight: 700; margin-bottom: 10px; }
.ag__forma-opcoes { display: flex; flex-wrap: wrap; gap: 8px; }
.ag__forma-btn { min-height: 44px; min-width: 92px; padding: 0 16px; }
.ag__forma-btn[aria-pressed="true"] { opacity: 1; background: var(--acento-sel); border-color: transparent; color: var(--acento-texto); }
.ag__forma-regua { margin-top: 10px; font-size: var(--apoio); color: var(--texto-2); line-height: 1.5; }
.ag__valor { font-size: var(--t-dado); color: var(--texto-2); white-space: nowrap; }
.ag__acoes { grid-column: 2 / -1; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ag__acoes .btn { padding: 0 11px; }
.ag__zap { margin-left: auto; }
/* desfazer um desfecho marcado por engano: discreto, no fim da linha — não é a próxima ação */
.ag__acoes--desfazer { margin-top: 4px; justify-content: flex-end; }
.ag__desfazer { font-size: var(--apoio); font-weight: 600; }
/* a falha de gravação mora na própria linha, embaixo dos botões que a pessoa vai tocar de novo */
.ag__falha { grid-column: 1 / -1; margin-top: 10px; }
.ag__falha--solta { margin: 12px var(--pad-cartao); }
/* resolvido recua para o cinza de apoio — por COR, não por opacidade: a .6 o texto de apoio
   caía para ~2,5:1, e registro também precisa ser lido */
.ag--fechado .ag__hora { color: var(--texto-2); }
.ag--fechado .ag__cliente { color: var(--texto-2); font-weight: 600; }

@media (max-width: 520px) {
  .ag { grid-template-columns: 48px minmax(0, 1fr); }
  /* selo à esquerda, PREÇO à direita: dinheiro alinha à direita também quando a linha empilha */
  .ag__lado { grid-column: 2; flex-direction: row; flex-wrap: wrap; justify-content: flex-start; align-items: center; gap: 8px 10px; margin-top: 4px; }
  .ag__lado .ag__valor { margin-left: auto; }
  .ag__forma { grid-column: 1 / -1; }
  .ag__forma-btn { flex: 1 1 calc(50% - 4px); }
  .ag__acoes { grid-column: 1 / -1; }
  .ag__zap { margin-left: 0; }
}

/* ── barra de ocupação (.barb) — um profissional, o percentual e a barra ───
   <div class="barb [barb--folga]"><span class="barb__nome">João</span><span class="barb__pct dado">62%</span>
     <span class="barb__conta">5 marcados · 3 atendidos</span>
     <span class="barb__trilho"><span class="barb__barra" style="width:62%"></span></span></div> */
/* um barbeiro: nome + percentual, contagem, e a barra. ⚠️ A barra é UMA cor só
   (--acento-marca, a que passa de 3:1 contra o cartão): o comprimento já é a medida. */
.barb {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; align-items: center;
  padding: 11px var(--pad-cartao); border-bottom: 1px solid var(--borda);
}
.barb__nome { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barb__pct { font-size: var(--t-dado); }
.barb__conta { grid-column: 1 / -1; font-size: var(--apoio); color: var(--texto-2); }
.barb__trilho { grid-column: 1 / -1; height: 6px; margin-top: 6px; border-radius: var(--r-pilula); background: var(--sup-2); overflow: hidden; }
.barb__barra { display: block; height: 100%; border-radius: inherit; background: var(--acento-marca, var(--acento)); }
.barb--folga .barb__nome { color: var(--texto-2); font-weight: 500; }
.barb--folga .barb__conta { color: var(--texto-3); }
.barb__regua { padding: 10px var(--pad-cartao) 12px; font-size: var(--apoio); color: var(--texto-3); line-height: 1.45; }

/* ── gráfico de barras (.fat-grafico) — o SVG é desenhado por faturamento.js ─
   <div class="fat-grafico"><div class="fat-grafico__area" tabindex="0" role="group" aria-label="…">
     <svg>… .fat-grade .fat-base .fat-eixo .fat-barra .fat-pico .fat-faixa …</svg>
     <div class="fat-dica">…</div></div></div>
   Série única = UMA cor. O destaque é tipografia (.fat-eixo--forte, .fat-pico), nunca um segundo tom. */
.fat-grafico { position: relative; padding: 14px var(--pad-cartao) 12px; }
.fat-grafico__area { position: relative; outline-offset: 4px; border-radius: 4px; touch-action: pan-y; }
.fat-grafico svg { display: block; width: 100%; overflow: visible; }
/* marca gráfica: --acento-marca é a versão do acento que passa de 3:1 contra o cartão */
.fat-barra { fill: var(--acento-marca, var(--acento)); }
.fat-grade { stroke: var(--borda); stroke-width: 1; shape-rendering: crispEdges; }
.fat-base { stroke: var(--borda-controle); stroke-width: 1; shape-rendering: crispEdges; }
.fat-eixo { fill: var(--texto-3); font: 10px var(--f-dado); }
.fat-eixo--dia { font: 10.5px var(--f-corpo); fill: var(--texto-2); }
/* o destaque é TIPOGRAFIA: sábado em negrito no eixo, o pico com o valor escrito. Nunca um segundo tom. */
.fat-eixo--forte { font-weight: 700; fill: var(--texto); }
.fat-pico { fill: var(--texto); font: 500 10.5px var(--f-dado); }
.fat-faixa { fill: var(--sup-2); }
.fat-dica {
  position: absolute; z-index: 2; top: 0; pointer-events: none; transform: translateX(-50%);
  padding: 7px 10px; background: var(--sup-alta); border: 1px solid var(--borda-controle);
  border-radius: var(--r-campo); box-shadow: var(--sombra); white-space: nowrap; line-height: 1.4;
}
.fat-dica__dia { font-size: var(--apoio); color: var(--texto-2); }
.fat-dica__valor { font-size: 14px; font-weight: 500; }
.fat-dica__n { font-size: var(--apoio); color: var(--texto-3); }

/* ── a conta por unidade (.fin-res / .fin-cols) — tabela no desktop, um cartão por coluna no celular ──
   <section class="cartao fin-res-larga"><table class="tabela fin-res">… .fin-res__empresa na coluna do total …</table></section>
   <section class="fin-cols"><article class="cartao fin-col [fin-col--empresa]">…</article></section>
   .fin-neg — resultado negativo: vermelho E com o sinal escrito (a cor não é o único aviso). */
.fin-neg { color: var(--ruim); }
/* a conta por unidade: tabela no desktop (compara-se na horizontal), um cartão por coluna no celular */
.fin-res th:first-child, .fin-res td:first-child { width: 28%; }
.fin-res td:first-child { font-weight: 600; }
.fin-res .fin-res__empresa { background: var(--sup-2); }
.fin-res tbody tr:nth-child(even) td.fin-res__empresa { background: var(--sup-2); }
.fin-res tfoot td { height: 48px; font-size: var(--corpo); }
.fin-res tfoot td.tabela__num { font-size: 14.5px; }
.fin-res__vazio { color: var(--texto-3); }
.fin-cols { display: none; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.fin-col { padding: 14px var(--pad-cartao) 12px; }
.fin-col--empresa { border-color: var(--borda-controle); }
.fin-col__cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fin-col__nome { font-size: var(--t-secao); font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fin-col__linhas { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
.fin-col__linha { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.fin-col__linha dt { color: var(--texto-2); }
.fin-col__linha dd { font-size: var(--t-dado); white-space: nowrap; }
.fin-col__linha--total { margin-top: 4px; padding-top: 9px; border-top: 1px solid var(--borda-controle); }
.fin-col__linha--total dt { color: var(--texto); font-weight: 700; }
.fin-col__linha--total dd { font-size: 15px; font-weight: 500; }
@media (max-width: 719.98px) {
  .fin-res-larga { display: none; }
  .fin-cols { display: grid; }
}

/* ── chave liga/desliga (.wpp-chave) ──────────────────────────────────────
   <button class="wpp-chave" role="switch" aria-checked="true|false">
     <span class="wpp-chave__trilho" aria-hidden="true"></span>
     <span class="wpp-chave__texto">O que liga<span class="wpp-chave__estado">Ligado</span></span></button> */
/* a chave do atendente: role="switch" — o alvo é a linha inteira */
.wpp-chave {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 6px 0;
  background: none; border: 0; text-align: left; cursor: pointer; color: var(--texto);
}
.wpp-chave:disabled { cursor: not-allowed; }
.wpp-chave__trilho {
  position: relative; flex: none; width: 40px; height: 24px; border-radius: var(--r-pilula);
  background: var(--sup-2); box-shadow: inset 0 0 0 1.5px var(--borda-controle); transition: background var(--t);
}
.wpp-chave__trilho::after {
  content: ""; position: absolute; top: 4px; left: 4px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--texto-2); transition: transform var(--t), background var(--t);
}
.wpp-chave[aria-checked="true"] .wpp-chave__trilho { background: var(--acento); box-shadow: none; }
.wpp-chave[aria-checked="true"] .wpp-chave__trilho::after { transform: translateX(16px); background: var(--acento-tinta); }
.wpp-chave:disabled .wpp-chave__trilho::after { background: var(--texto-3); }
.wpp-chave__texto { flex: 1; min-width: 0; font-size: var(--corpo); font-weight: 700; line-height: 1.35; }
.wpp-chave__estado { display: block; font-size: var(--apoio); font-weight: 400; color: var(--texto-3); }
@media (prefers-reduced-motion: reduce) { .wpp-chave__trilho, .wpp-chave__trilho::after { transition: none; } }

/* ── conversa (.wpp-fio / .wpp-msg) — a bolha diz QUEM falou pela forma e pelo lado ──
   <ol class="wpp-fio"><li class="wpp-msg wpp-msg--cliente|robo|humano [wpp-msg--nossa]">
     <div class="wpp-msg__balao">texto</div><div class="wpp-msg__meta"><span class="wpp-msg__quem">Robô</span>…</div></li></ol>
   ⚠️ O texto vem de TERCEIRO: entra por esc(), quebra em qualquer ponto e NUNCA vira link. */
.wpp-fio { list-style: none; display: flex; flex-direction: column; gap: 12px; padding: 14px var(--pad-cartao) 18px; }
.wpp-fio__regua { font-size: var(--apoio); color: var(--texto-3); text-align: center; line-height: 1.45; }
.wpp-msg { display: flex; flex-direction: column; align-items: flex-start; max-width: 100%; }
.wpp-msg--nossa { align-items: flex-end; }
/* ⚠️ o texto vem de TERCEIRO: entra por textContent/esc(), quebra em qualquer ponto (palavra de
   500 letras não alarga a gaveta) e NUNCA vira link — endereço em mensagem de cliente é só texto */
.wpp-msg__balao {
  max-width: 86%; padding: 8px 11px; border-radius: var(--r-cartao); border: 1px solid var(--borda);
  background: var(--sup-2); font-size: var(--corpo); line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
}
.wpp-msg--robo .wpp-msg__balao { background: var(--acento-sel); border-color: transparent; }
.wpp-msg--humano .wpp-msg__balao { background: var(--fundo); border-color: var(--borda-controle); }
.wpp-msg__balao--mudo { font-style: italic; color: var(--texto-2); }
.wpp-msg__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 7px; margin-top: 4px; font-size: var(--apoio); color: var(--texto-3); }
.wpp-msg__meta .dado { font-size: var(--t-dado); }
.wpp-msg__quem { font-weight: 600; color: var(--texto-2); }

/* ── faixa de jornada (.faixa) — dia · UNIDADE · horário · remover ────────
   <div class="faixa"><span class="faixa__dia">Segunda</span><span class="faixa__uni">Centro</span>
     <span class="faixa__hh dado">09:00–12:00</span><button class="faixa__x" aria-label="Remover…">×</button></div>
   ⚠️ A unidade aparece em TODA faixa: a jornada é profissional × unidade × dia. */
/* jornada: uma faixa por linha, porque o almoço são DUAS faixas no mesmo dia */
.faixa { display: flex; align-items: center; gap: 10px; min-height: 34px; border-bottom: 1px solid var(--borda); }
.faixa:last-child { border-bottom: 0; }
.faixa__dia { width: 72px; flex: none; font-size: 12.5px; font-weight: 700; }
.faixa__uni { flex: 1; min-width: 0; font-size: var(--apoio); color: var(--texto-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.faixa__hh { flex: none; font-size: 12.5px; }
.faixa__fechado { color: var(--texto-3); }
/* ⚠️ o × é inline numa linha de texto: com a altura de controle (36px) ele estoura
   a linha e joga o horário para baixo. No dedo, o alvo de 44 vem da própria faixa. */
.faixa__x {
  display: grid; place-items: center; width: 26px; height: 26px; flex: none;
  background: none; border: 1px solid transparent; border-radius: 6px;
  color: var(--texto-3); font-size: 16px; line-height: 1; cursor: pointer;
}
.faixa__x:hover { border-color: var(--ruim); color: var(--ruim); }
@media (pointer: coarse), (max-width: 899.98px) { .faixa { min-height: 48px; } .faixa__x { width: 44px; height: 44px; } }


/* ═════════════════════════════════════════════════════════════════════════
   PELE PÚBLICA — o que o cliente da barbearia vê (/?b=<slug> e /a/<token>)

   ⚠️ Tudo daqui para baixo ou é classe `pub-*`, ou está preso a
   `:root:not([data-pele="interna"])`. Nenhuma regra desta seção alcança as telas de
   gestão — é assim que se mexe na pele pública sem reabrir a revisão da interna.

   As superfícies são as mesmas da gestão (papel claro pousado na mesa tingida — tokens.css). O que
   muda de uma pele para a outra: aqui há espaço, o título grita em Archivo Black e o acento é o da
   BARBEARIA.
   ═════════════════════════════════════════════════════════════════════════ */

/* Antes de a barbearia chegar pela rede (e quando ela não existe), a página é PRETO E BRANCO — não o azul do Metricut.
   Uma casa de cor lima não pode piscar azul por meio segundo. acento.js escreve os valores
   de verdade no próprio <html>, e estilo no elemento vence esta regra.
   (A tinta aqui é --fundo porque o "acento" provisório é o cinza --texto-2, que tokens.css já
   garante legível contra o fundo nos dois temas. Com cor de barbearia a tinta é sempre CALCULADA.) */
:root:not([data-pele="interna"]) {
  --acento: var(--texto-2); --acento-tinta: var(--fundo); --acento-texto: var(--texto);
  --acento-marca: var(--texto-2); --acento-sel: var(--sup-2);
}

/* O primário grita, como o título. E ganha BORDA na cor de marca gráfica (≥ 3:1 contra a
   superfície): a barbearia pode escolher branco no tema claro ou preto no escuro, e sem a
   borda o botão vira texto solto — legível, mas sem cara de botão. Com cor comum a borda
   é a própria cor e não aparece. */
:root:not([data-pele="interna"]) .btn--primario {
  border-color: var(--acento-marca);
  font-family: var(--f-display); font-weight: 400; font-size: 13.5px;
  letter-spacing: .07em; text-transform: uppercase;
}
/* ⚠️ Botão TRABALHANDO ("Confirmando…", "Cancelando…") não apaga: a .45 de opacidade o texto
   caía para 1,6–2,0:1, justamente na hora em que a pessoa mais olha para ele. Aqui ele mantém
   a tinta inteira e mostra que está ocupado por FORMA — o texto muda e um anel gira ao lado
   (com movimento reduzido o anel fica parado; o texto continua dizendo). Liga com aria-busy. */
:root:not([data-pele="interna"]) .btn:disabled,
:root:not([data-pele="interna"]) .btn[aria-busy="true"] { opacity: 1; cursor: progress; }
:root:not([data-pele="interna"]) .btn[aria-busy="true"]::before {
  content: ""; flex: none; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: pub-ocupado .7s linear infinite;
}
@keyframes pub-ocupado { to { transform: rotate(1turn); } }
:root:not([data-pele="interna"]) .campo > input:not([type="checkbox"], [type="radio"]) { padding: 0 14px; }

/* Os três estados alinham à ESQUERDA: a página pública é uma coluna encostada na fita,
   e um bloco centralizado no meio dela parece ter caído de outra tela. */
:root:not([data-pele="interna"]) .vazio,
:root:not([data-pele="interna"]) .erro-bloco { align-items: flex-start; padding: var(--e-2) 0; text-align: left; }
:root:not([data-pele="interna"]) .erro-bloco__texto::before { margin-left: 0; }
:root:not([data-pele="interna"]) .vazio__titulo { font-size: 18px; line-height: 1.3; }
/* o esqueleto tem a forma do que vem: cartões de opção, não linhas de tabela
   (--h-linha é `auto` nesta pele; sem isto cada linha teria 10px) */
:root:not([data-pele="interna"]) .esqueleto { gap: 10px; }
:root:not([data-pele="interna"]) .esqueleto__linha {
  min-height: 66px; padding: 0 var(--e-4);
  border: 1px solid var(--borda); border-radius: var(--r-cartao);
}
:root:not([data-pele="interna"]) .esqueleto--horas { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: var(--e-2); }
:root:not([data-pele="interna"]) .esqueleto--horas .esqueleto__linha { min-height: var(--h-controle); border-radius: var(--r-campo); padding: 0 var(--e-3); }

/* ── a página ─────────────────────────────────────────────────────────── */
.pub-pagina { display: flex; }
.pub-miolo {
  flex: 1; min-width: 0; width: 100%; max-width: 560px; margin-left: 14px;
  padding: 24px 20px calc(28px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
}
@media (min-width: 640px) { .pub-miolo { margin-left: calc(14px + 6vw); padding: 44px 32px 40px; } }
/* em tela larga a coluna vai para o MEIO: encostada na fita, ela usava só a metade esquerda de um monitor */
@media (min-width: 900px) { .pub-miolo { margin-inline: auto; } }

/* ── A FITA: o poste de barbeiro como barra de progresso — a assinatura do produto.
   <div class="pub-fita" aria-hidden="true"><i style="--avanco:62%"></i></div>
   Tem as cores REAIS do poste: listras a 135°, branco · vermelho · branco · azul, cada uma com 7,071 px
   (o período na vertical dá 40 px exatos, e é ele o tamanho do ladrilho — por isso a emenda não aparece).
   O trilho vazio é o tubo (--poste-tubo, com um filete por dentro); por cima de tudo, PARADO, o brilho
   de vidro (::after) — quem gira são as listras, não a luz.
   ⚠️ A REGRA (11/10/2026 — desfaz de propósito a de 12/09, que proibia o vermelho aqui):
   O VERMELHO DO POSTE NÃO É COR DE INTERFACE. Ele existe na fita e no selo da marca, e em nenhum outro
   lugar; --ruim continua sendo o único vermelho que significa algo. O que impede a confusão é o LUGAR:
   uma faixa decorativa na borda, sempre junto de branco e azul, não se lê como erro.
   ⛔ A fita NÃO leva a cor da barbearia nem --acento nenhum: é igual em toda página, tema e pele. (O azul
   é --poste-azul, valor escrito — se apontasse para --acento, a cor da casa voltaria por acento.js.) Não
   existe variante "fita da casa"; a cor da casa mora no selo dela, nos botões e no que foi escolhido.
   O que NÃO mudou: o avanço. Na página do cliente a altura é --avanco (enche a cada passo); no site e na
   página viva o avanço é recorte (site.css / sistema.js). O giro é o mesmo de sempre, com outras cores —
   e quem pede menos movimento recebe a fita parada (a regra geral, acima). */
.pub-fita {
  position: fixed; z-index: 10; left: 0; top: 0; bottom: 0; width: 14px; overflow: hidden;
  background: var(--poste-tubo); box-shadow: inset 0 0 0 1px var(--poste-filete);
}
.pub-fita > i {
  position: absolute; left: 0; right: 0; top: 0; height: var(--avanco, 0%);
  background: repeating-linear-gradient(135deg,
    var(--poste-branco) 0 7.071px, var(--poste-vermelho) 7.071px 14.142px,
    var(--poste-branco) 14.142px 21.213px, var(--poste-azul) 21.213px 28.284px);
  background-size: 100% 40px; animation: pub-gira 1.8s linear infinite;
  transition: height .5s cubic-bezier(.3, .8, .3, 1);
}
/* o vidro: sombra nas duas bordas e um fio de luz a 38% — por cima das listras e do trilho, sem girar */
.pub-fita::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, var(--poste-vidro-sombra), var(--poste-vidro-luz) 38%, transparent 58%, var(--poste-vidro-sombra));
}
@keyframes pub-gira { to { background-position: 0 -40px; } }

/* ── a casa: quem o cliente veio procurar. O Metricut só assina no rodapé. */
.pub-cab { padding-bottom: var(--e-4); border-bottom: 1px solid var(--borda); }
.pub-casa { display: flex; align-items: center; gap: var(--e-3); }
.pub-casa__marca {
  flex: none; width: 40px; height: 40px; display: grid; place-items: center;
  background: var(--acento); color: var(--acento-tinta);
  border: 1px solid var(--acento-marca); border-radius: 10px;
  font: 13px/1 var(--f-display); letter-spacing: .02em; text-transform: uppercase;
}
/* enquanto a barbearia não chegou, a marca é um quadrado quieto — não um botão cinza */
.pub-casa__marca:empty { background: var(--sup-2); border-color: var(--borda); }
.pub-casa__nome { font: 14px/1.15 var(--f-display); letter-spacing: .1em; text-transform: uppercase; }
.pub-casa__local { margin-top: 3px; font-size: 12.5px; color: var(--texto-2); line-height: 1.35; }
.pub-casa__local:empty { display: none; }
/* o que já foi escolhido — cresce a cada passo, some enquanto está vazio */
.pub-trilha { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--e-3); }
.pub-trilha:empty { display: none; }
.pub-trilha .selo { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }

.pub-passo { padding-top: var(--e-5); animation: pub-entra .32s cubic-bezier(.2, .7, .3, 1); }
@keyframes pub-entra { from { opacity: 0; transform: translateY(9px); } }
/* o topo do passo: no DOM vem o título e depois o Voltar (ordem do foco); na tela o Voltar sobe */
.pub-topo { display: flex; flex-direction: column; align-items: flex-start; }
.pub-topo > .pub-voltar { order: -1; }
.pub-voltar { margin: -10px 0 var(--e-2) -14px; }
.pub-titulo {
  font: clamp(29px, 8.6vw, 44px)/.96 var(--f-display); letter-spacing: -.015em;
  text-transform: uppercase; text-wrap: balance; overflow-wrap: break-word;
}
.pub-titulo:focus { outline: none; }   /* recebe o foco só para o leitor de tela anunciar o passo */
.pub-titulo--menor { font-size: clamp(25px, 7.2vw, 36px); }
.pub-sub { margin: var(--e-3) 0 var(--e-5); max-width: 46ch; color: var(--texto-2); line-height: 1.5; }
.pub-passo > .selo { margin-bottom: var(--e-3); }
.pub-passo > .nota { margin-bottom: var(--e-4); }
.pub-passo > .cartao + .nota { margin-top: var(--e-4); margin-bottom: 0; }
.pub-acoes { display: flex; flex-direction: column; gap: var(--e-2); margin-top: var(--e-4); }

/* ── opção: unidade, profissional, serviço. A linha inteira é o alvo. ──── */
.pub-lista { display: grid; gap: 10px; list-style: none; }
.pub-opcao {
  display: flex; align-items: center; gap: 14px; width: 100%; min-height: 66px;
  padding: 12px var(--e-4); text-align: left; cursor: pointer;
  background: var(--sup); border: 1px solid var(--borda-controle); border-radius: var(--r-cartao);
  transition: border-color var(--t), background var(--t), transform var(--t);
}
.pub-opcao:hover { background: var(--sup-2); border-color: var(--texto); }
.pub-opcao:active { transform: scale(.988); }
.pub-opcao__disco {
  flex: none; width: 40px; height: 40px; display: grid; place-items: center; border-radius: 50%;
  background: var(--fundo); border: 1px solid var(--borda-controle);
  font: 14px/1 var(--f-display); text-transform: uppercase;
}
.pub-opcao__texto { flex: 1; min-width: 0; }
.pub-opcao__nome { display: block; font-size: 16px; font-weight: 700; line-height: 1.3; }
.pub-opcao__apoio { display: block; margin-top: 2px; font-size: var(--apoio); color: var(--texto-2); line-height: 1.4; }
.pub-opcao__preco { flex: none; font-family: var(--f-dado); font-variant-numeric: tabular-nums; font-size: var(--t-dado); white-space: nowrap; }
.pub-opcao::after { content: "›"; content: "›" / ""; flex: none; font: 18px/1 var(--f-dado); color: var(--texto-3); }

/* ── dia e hora ───────────────────────────────────────────────────────────
   A faixa de dias rola DENTRO dela; a página nunca rola de lado. O último dia aparece
   cortado de propósito: é o indício de que tem mais para o lado. */
.pub-dias { display: flex; gap: var(--e-2); overflow-x: auto; margin: 0 -20px var(--e-4); padding: 8px 20px; scrollbar-width: none; }
.pub-dias::-webkit-scrollbar { display: none; }
/* com mouse não há como arrastar uma faixa sem barra de rolagem: em tela larga os 14 dias
   QUEBRAM em duas linhas, todos à vista (a mesma lição das abas da gestão) */
@media (min-width: 640px) { .pub-dias { flex-wrap: wrap; overflow: visible; margin-inline: 0; padding-inline: 0; } }
.pub-dia {
  flex: none; min-width: 60px; min-height: 62px; padding: 8px 6px; text-align: center; cursor: pointer;
  background: var(--sup); border: 1px solid var(--borda-controle); border-radius: var(--r-campo);
  transition: background var(--t), border-color var(--t), color var(--t);
}
.pub-dia__semana { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--texto-2); }
.pub-dia__num { display: block; margin-top: 3px; font: 19px/1.1 var(--f-display); }
.pub-dia:hover { border-color: var(--texto); }
/* ⚠️ O dia escolhido NÃO depende só do preenchimento: com a barbearia no branco (tema claro)
   ou no preto (tema escuro) o acento tem a cor da página, e o dia marcado ficava igual aos
   outros. O anel em volta é forma, não cor — e usa a cor de marca gráfica (≥ 3:1). */
.pub-dia[aria-pressed="true"] {
  background: var(--acento); border-color: var(--acento-marca); color: var(--acento-tinta);
  box-shadow: 0 0 0 2px var(--fundo), 0 0 0 4px var(--acento-marca);
}
.pub-dia:focus-visible { outline-offset: 5px; }
.pub-dia[aria-pressed="true"] .pub-dia__semana { color: inherit; }

.pub-horas { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: var(--e-2); list-style: none; }
.pub-hora {
  width: 100%; min-height: var(--h-controle); cursor: pointer;
  background: var(--sup); border: 1px solid var(--borda-controle); border-radius: var(--r-campo);
  font-family: var(--f-dado); font-variant-numeric: tabular-nums; font-size: var(--t-dado);
  transition: background var(--t), border-color var(--t);
}
.pub-hora:hover { background: var(--sup-2); border-color: var(--texto); }

/* ── recibo: o que ficou combinado, em pares rótulo → valor ───────────── */
.pub-recibo { padding: 6px var(--e-4); }
.pub-recibo__linha { display: flex; justify-content: space-between; gap: var(--e-4); padding: 11px 0; border-bottom: 1px solid var(--borda); }
.pub-recibo__linha:last-child { border-bottom: 0; }
/* o RÓTULO cede (quebra de linha) antes do valor: "Aviso no WhatsApp" + telefone não cabem lado a lado em 360px,
   e quem quebrava era o telefone, no meio do número */
.pub-recibo dt { flex: 0 1 auto; min-width: 4.5em; color: var(--texto-2); }
.pub-recibo dd { min-width: 0; text-align: right; font-weight: 700; }
.pub-recibo dd .dado { white-space: nowrap; }
.pub-recibo dd small { display: block; font-size: var(--apoio); font-weight: 400; color: var(--texto-2); line-height: 1.4; }
.pub-recibo dd.dado { font-weight: 500; }

/* o link do próprio horário, inteiro e selecionável: é por ele que o cliente desmarca */
.pub-link {
  display: block; padding: 12px 14px; background: var(--sup);
  border: 1px dashed var(--borda-controle); border-radius: var(--r-campo);
  font: 12.5px/1.5 var(--f-dado); color: var(--texto); overflow-wrap: anywhere; user-select: all;
}
.pub-rotulo { margin: var(--e-5) 0 var(--e-2); font-size: var(--t-coluna); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--texto-3); }
.pub-miudo { margin-top: var(--e-3); font-size: var(--apoio); color: var(--texto-2); line-height: 1.55; }
.pub-miudo b { color: var(--texto); }

/* o Metricut aparece uma vez, do tamanho de um crédito */
.pub-credito { margin-top: auto; padding-top: var(--e-7); font-size: var(--t-coluna); letter-spacing: .14em; text-transform: uppercase; color: var(--texto-3); }
.pub-credito b { margin-left: 4px; font: 400 10.5px/1 var(--f-marca); letter-spacing: .12em; color: var(--texto-2); }
